git clone https://orangeshoelaces.net/git/tttm.git
Author: Vasily Kolobkov on 05/03/2016
Committer: Vasily Kolobkov on 05/03/2016
Add parser shades - parser testbed
Plus next round of refinement and cleanup
parse.c | 917 ++++++--
parse.h | 117 +-
pshades.c | 129 +
3 files changed, 926 insertions(+), 237 deletions(-)
diff --git a/parse.c b/parse.c
index abc1ac6..801ff23 100644
--- a/parse.c
+++ b/parse.c
@@ -4,52 +4,131 @@
specific error code or 0 is dispensed to the parse context.
*/
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
#include <strings.h>
#include "parse.h"
+#define LEN(a) (sizeof(a) / sizeof(a)[0])
+
static struct literal {
- enum { OK, NO, BAD, SP } kind;
- char *val;
- size_t len;
+ int val;
+ char *srep;
+ size_t slen;
} literals[] = {
- { ALERT, "ALERT", 5 },
- { ANSWERED, "\\Answered", 9 },
- { ANYFL, "\\*", 2 },
- { ASTERISK, "*", 1 },
- { AUTHEQ, "AUTH=", 5 },
- { BAD, "BAD", 3 },
- { BADCS, "BADCHARSET", 10 },
- { CAP, "CAPABILITY", 10 },
- { CBRACK, "]", 1 },
- { CPAR, ")", 1 },
- { DELETED, "\\Deleted", 8 },
- { DQUOTE, "\"", 1 },
- { DRAFT, "\\Draft", 6 },
- { EOL, "\r\n", 2 },
- { FLAGGED, "\\Flagged", 8 },
- { FLAGS, "FLAGS", 5 },
- { LIST, "LIST", 4 },
- { NIL, "NIL", 3 },
- { NO, "NO", 2 },
- { OBRACK, "[", 1 },
- { OK, "OK", 2 },
- { OPAR, "(", 1 },
- { PARSE, "PARSE", 5 },
- { PERMFL, "PERMANENTFLAGS", 14 },
- { PLUS, "+", 1 },
- { RO, "READ-ONLY", 9 },
- { RW, "READ-WRITE", 10 },
- { SEEN, "\\Seen", 5 },
- { SP, " ", 1 },
- { TRYC, "TRYCREATE", 9 },
- { UIDNEXT, "UIDNEXT", 7 },
- { UIDVAL, "UIDVALIDITY", 11 },
- { UNSEEN, "UNSEEN", 6 },
+ { IL_7BIT, "7BIT", 4 },
+ { IL_8BIT, "8BIT", 4 },
+ { IL_ALERT, "ALERT", 5 },
+ { IL_APP, "APPLICATION", 11 },
+ { IL_APR, "Apr", 3 },
+ { IL_ASTERISK, "*", 1 },
+ { IL_AUDIO, "AUDIO", 5 },
+ { IL_AUG, "Aug", 3 },
+ { IL_AUTHEQ, "AUTH=", 5 },
+ { IL_B64, "BASE64", 6 },
+ { IL_BAD, "BAD", 3 },
+ { IL_BADCS, "BADCHARSET", 10 },
+ { IL_BIN, "BINARY", 6 },
+ { IL_BODY, "BODY", 4 },
+ { IL_BSLASH, "\\", 1 },
+ { IL_BYE, "BYE", 3 },
+ { IL_CAP, "CAPABILITY", 10 },
+ { IL_CBRACE, "}", 1 },
+ { IL_CBRACK, "]", 1 },
+ { IL_COLON, ":", 1 },
+ { IL_CPAR, ")", 1 },
+ { IL_DEC, "Dec", 3 },
+ { IL_DHDR, ".HEADER", 7 },
+ { IL_DNOT, ".NOT", 4 },
+ { IL_DOT, ".", 1 },
+ { IL_DQUOTE, "\"", 1 },
+ { IL_DTXT, ".TEXT", 5 },
+ { IL_ENVELOPE, "ENVELOPE", 8 },
+ { IL_EOL, "\r\n", 2 },
+ { IL_EXISTS, "EXISTS", 6 },
+ { IL_EXPUNGE, "EXPUNGE", 7 },
+ { IL_FEB, "Feb", 3 },
+ { IL_FETCH, "FETCH", 5 },
+ { IL_FLAGS, "FLAGS", 5 },
+ { IL_FLANSWERED, "\\Answered", 9 },
+ { IL_FLANY, "\\*", 2 },
+ { IL_FLDELETED, "\\Deleted", 8 },
+ { IL_FLDRAFT, "\\Draft", 6 },
+ { IL_FLFLAGGED, "\\Flagged", 8 },
+ { IL_FLMARKED, "\\Marked", 7 },
+ { IL_FLNOINFERIORS, "\\Noinferiors", 12 },
+ { IL_FLNOSEL, "\\Noselect", 9 },
+ { IL_FLRECENT, "\\Recent", 7 },
+ { IL_FLSEEN, "\\Seen", 5 },
+ { IL_FLUNMARKED, "\\Unmarked", 9 },
+ { IL_GT, ">", 1 },
+ { IL_HDR, "HEADER", 6 },
+ { IL_HDRFIELDS, "HEADER.FIELDS", 13 },
+ { IL_IMG, "IMAGE", 5 },
+ { IL_INBOX, "INBOX", 5 },
+ { IL_INTDATE, "INTERNALDATE", 12 },
+ { IL_JAN, "Jan", 3 },
+ { IL_JUL, "Jul", 3 },
+ { IL_JUN, "Jun", 3 },
+ { IL_LIST, "LIST", 4 },
+ { IL_LSUB, "LSUB", 4 },
+ { IL_LT, "<", 1 },
+ { IL_MAR, "Mar", 3 },
+ { IL_MAY, "May", 3 },
+ { IL_MIME, "MIME", 4 },
+ { IL_MINUS, "-", 1 },
+ { IL_MSG, "MESSAGE", 7 },
+ { IL_MSGS, "MESSAGES", 8 },
+ { IL_NIL, "NIL", 3 },
+ { IL_NO, "NO", 2 },
+ { IL_NOV, "Nov", 3 },
+ { IL_OBRACE, "{", 1 },
+ { IL_OBRACK, "[", 1 },
+ { IL_OCT, "Oct", 3 },
+ { IL_OK, "OK", 2 },
+ { IL_OPAR, "(", 1 },
+ { IL_PARSE, "PARSE", 5 },
+ { IL_PERMFL, "PERMANENTFLAGS", 14 },
+ { IL_PLUS, "+", 1 },
+ { IL_QPRN, "QUOTED-PRINTABLE", 16 },
+ { IL_RECENT, "RECENT", 6 },
+ { IL_RFC822, "RFC822", 6 },
+ { IL_RFC822SIZE, "RFC822.SIZE", 11 },
+ { IL_RO, "READ-ONLY", 9 },
+ { IL_RW, "READ-WRITE", 10 },
+ { IL_SEARCH, "SEARCH", 6 },
+ { IL_SEP, "Sep", 3 },
+ { IL_SP, " ", 1 },
+ { IL_STATUS, "STATUS", 6 },
+ { IL_STRUCT, "STRUCTURE", 9 },
+ { IL_TRYC, "TRYCREATE", 9 },
+ { IL_TXT, "TEXT", 4 },
+ { IL_UID, "UID", 3 },
+ { IL_UIDNEXT, "UIDNEXT", 7 },
+ { IL_UIDVAL, "UIDVALIDITY", 11 },
+ { IL_UNSEEN, "UNSEEN", 6 },
+ { IL_VIDEO, "VIDEO", 5 },
};
+static const char astr_specials[] = ""
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ " \"%()*\\{\x7f";
+
+static const char atom_specials[] = ""
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ " \"%()*\\]{\x7f";
+
+static const char tag_specials[] = ""
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ " \"%()*+\\{\x7f";
+
struct parse_cur {
- const char *tok;
+ const char *tok;
union parse_node *pt;
};
@@ -67,14 +146,177 @@ struct parse_ctx {
typedef int parsefn(struct parse_ctx *);
+int parse_respln(const char *, size_t, union parse_node *, size_t, size_t);
+
+static int cmpchr(const void *, const void *);
+static int contains(const char *, size_t, char);
+
+static int p_chk(struct parse_ctx *, struct parse_cur *);
+static int p_insint(struct parse_ctx *, int, size_t);
+static int p_inslit(struct parse_ctx *, int);
+static int p_insnum(struct parse_ctx *, uint32_t);
+static int p_insoblstr(struct parse_ctx *, uint32_t);
+static int p_insstr(struct parse_ctx *, int, const char *, uint32_t);
+static int p_beg(struct parse_ctx *, struct parse_cur *, int);
+static int p_end(struct parse_ctx *, struct parse_cur *);
+static int p_rwd(struct parse_ctx *, struct parse_cur *);
+static int p_opt(struct parse_ctx *);
+static int p_list(struct parse_ctx *, parsefn *);
+static int p_listsep(struct parse_ctx *, parsefn *, int);
+static int p_rep(struct parse_ctx *, parsefn *);
+static int p_repchr(struct parse_ctx *, const char *, size_t, int);
+static int p_2xcombo(struct parse_ctx *, int, parsefn *);
+static int p_3xcombo(struct parse_ctx *, int, int, parsefn *);
+static int p_r3xcombo(struct parse_ctx *, parsefn *, int, int);
+static int p_sss(struct parse_ctx *);
+
+static int p_addr(struct parse_ctx *);
+static int p_astr(struct parse_ctx *);
+static int p_atom(struct parse_ctx *);
+static int p_authtype(struct parse_ctx *);
+static int p_badcscode(struct parse_ctx *);
+static int p_badcsopt(struct parse_ctx *);
+static int p_base64(struct parse_ctx *);
+static int p_body(struct parse_ctx *);
+static int p_body1pt(struct parse_ctx *);
+static int p_bodybas(struct parse_ctx *);
+static int p_bodyext(struct parse_ctx *);
+static int p_bodyf(struct parse_ctx *);
+static int p_bodyfdes(struct parse_ctx *);
+static int p_bodyfdsp(struct parse_ctx *);
+static int p_bodyfenc(struct parse_ctx *);
+static int p_bodyfid(struct parse_ctx *);
+static int p_bodyflan(struct parse_ctx *);
+static int p_bodyflin(struct parse_ctx *);
+static int p_bodyfloc(struct parse_ctx *);
+static int p_bodyfmd5(struct parse_ctx *);
+static int p_bodyfoct(struct parse_ctx *);
+static int p_bodyfpar(struct parse_ctx *);
+static int p_bodympt(struct parse_ctx *);
+static int p_bodymsg(struct parse_ctx *);
+static int p_bodytxt(struct parse_ctx *);
+static int p_bodyx1pt(struct parse_ctx *);
+static int p_bodyxcmn(struct parse_ctx *);
+static int p_bodyxmpt(struct parse_ctx *);
+static int p_cap(struct parse_ctx *);
+static int p_capdata(struct parse_ctx *);
+static int p_contreq(struct parse_ctx *);
+static int p_datetime(struct parse_ctx *);
+static int p_dayfix(struct parse_ctx *);
+static int p_dig(struct parse_ctx *, size_t);
+static int p_dquotedchar(struct parse_ctx *);
+static int p_env(struct parse_ctx *);
+static int p_envaddr(struct parse_ctx *, int);
+static int p_envbcc(struct parse_ctx *);
+static int p_envcc(struct parse_ctx *);
+static int p_envdate(struct parse_ctx *);
+static int p_envfrom(struct parse_ctx *);
+static int p_envinrepto(struct parse_ctx *);
+static int p_envmsgid(struct parse_ctx *);
+static int p_envrepto(struct parse_ctx *);
+static int p_envsender(struct parse_ctx *);
+static int p_envsubj(struct parse_ctx *);
+static int p_envto(struct parse_ctx *);
+static int p_fetchrec(struct parse_ctx *);
+static int p_flag(struct parse_ctx *);
+static int p_flext(struct parse_ctx *);
+static int p_flfetch(struct parse_ctx *);
+static int p_flkeyword(struct parse_ctx *);
+static int p_gencode(struct parse_ctx *);
+static int p_genctext(struct parse_ctx *);
+static int p_hdrfname(struct parse_ctx *);
+static int p_hdrlist(struct parse_ctx *);
+static int p_lit(struct parse_ctx *, int);
+static int p_lstr(struct parse_ctx *);
+static int p_mailbox(struct parse_ctx *);
+static int p_matbody(struct parse_ctx *);
+static int p_matbsect(struct parse_ctx *);
+static int p_matenv(struct parse_ctx *);
+static int p_mathdrotxt(struct parse_ctx *);
+static int p_matintdate(struct parse_ctx *);
+static int p_matsize(struct parse_ctx *);
+static int p_matuid(struct parse_ctx *);
+static int p_mbdata(struct parse_ctx *);
+static int p_mbexists(struct parse_ctx *);
+static int p_mbflags(struct parse_ctx *);
+static int p_mblist(struct parse_ctx *);
+static int p_mblistdata(struct parse_ctx *);
+static int p_mblistfl(struct parse_ctx *);
+static int p_mblistofl(struct parse_ctx *);
+static int p_mblistosfl(struct parse_ctx *);
+static int p_mblistsfl(struct parse_ctx *);
+static int p_mblsub(struct parse_ctx *);
+static int p_mbrecent(struct parse_ctx *);
+static int p_mbsearch(struct parse_ctx *);
+static int p_mbstatus(struct parse_ctx *);
+static int p_medbas(struct parse_ctx *);
+static int p_medmsg(struct parse_ctx *);
+static int p_medsubt(struct parse_ctx *);
+static int p_medtxt(struct parse_ctx *);
+static int p_month(struct parse_ctx *);
+static int p_msgdata(struct parse_ctx *);
+static int p_msgatt(struct parse_ctx *);
+static int p_msgattdyn(struct parse_ctx *);
+static int p_msgattstat(struct parse_ctx *);
+static int p_nstr(struct parse_ctx *);
+static int p_num(struct parse_ctx *);
+static int p_nznum(struct parse_ctx *);
+static int p_permfl(struct parse_ctx *);
+static int p_permflcode(struct parse_ctx *);
+static int p_qchar(struct parse_ctx *);
+static int p_qchars(struct parse_ctx *);
+static int p_qstr(struct parse_ctx *);
+static int p_respbye(struct parse_ctx *);
+static int p_respdata(struct parse_ctx *);
+static int p_respln(struct parse_ctx *);
+static int p_respstate(struct parse_ctx *);
+static int p_resptext(struct parse_ctx *);
+static int p_resptextcode(struct parse_ctx *);
+static int p_secmsgtxt(struct parse_ctx *);
+static int p_secpt(struct parse_ctx *);
+static int p_secspec(struct parse_ctx *);
+static int p_section(struct parse_ctx *);
+static int p_sectxt(struct parse_ctx *);
+static int p_statt(struct parse_ctx *);
+static int p_stattrec(struct parse_ctx *);
+static int p_str(struct parse_ctx *);
+static int p_tag(struct parse_ctx *);
+static int p_taggedresp(struct parse_ctx *);
+static int p_text(struct parse_ctx *);
+static int p_time(struct parse_ctx *);
+static int p_uid(struct parse_ctx *);
+static int p_uidncode(struct parse_ctx *);
+static int p_uidvcode(struct parse_ctx *);
+static int p_unseencode(struct parse_ctx *);
+static int p_year(struct parse_ctx *);
+static int p_zone(struct parse_ctx *);
+
+static int p_cpar(struct parse_ctx *);
+static int p_dquote(struct parse_ctx *);
+static int p_opar(struct parse_ctx *);
+static int p_sp(struct parse_ctx *);
+
int
parse_respln(const char *tok, size_t toklen, union parse_node *pt,
size_t ptlen, size_t oblth)
{
- struct parse_ctx p = { tok, tok + toklen, toklen, pt,
- pt + ptlen, ptlen, { tok, pt }, oblth, 0 };
+ struct parse_ctx p = { { tok, pt}, tok, tok + toklen, toklen,
+ pt, pt + ptlen, ptlen, 0, oblth };
+
p_respln(&p);
- return p->e;
+ return p.e;
+}
+
+int
+cmpchr(const void *a, const void *b)
+{
+ return *(char *)a - *(char *)b;
+}
+
+int
+contains(const char *s, size_t slen, char c)
+{
+ return bsearch(&c, s, slen, sizeof(char), cmpchr) != 0;
}
/*
@@ -101,6 +343,77 @@ p_insint(struct parse_ctx *p, int prod, size_t len)
cur->inter.type = PN_INTER;
cur->inter.prod = prod;
cur->inter.len = len;
+ p->e = PE_OK;
+ p->cur.pt++;
+ return 1;
+}
+
+int
+p_inslit(struct parse_ctx *p, int val)
+{
+ union parse_node *cur;
+
+ cur = p->cur.pt;
+ if (cur == p->ptend) {
+ p->e = PE_NOTENNODES;
+ return 0;
+ }
+ cur->lit.type = PN_LIT;
+ cur->lit.val = val;
+ p->e = PE_OK;
+ p->cur.pt++;
+ return 1;
+}
+
+int
+p_insnum(struct parse_ctx *p, uint32_t val)
+{
+ union parse_node *cur;
+
+ cur = p->cur.pt;
+ if (cur == p->ptend) {
+ p->e = PE_NOTENNODES;
+ return 0;
+ }
+ cur->lit.type = PN_NUM;
+ cur->lit.val = val;
+ p->e = PE_OK;
+ p->cur.pt++;
+ return 1;
+}
+
+int
+p_insoblstr(struct parse_ctx *p, uint32_t len)
+{
+ union parse_node *cur;
+
+ cur = p->cur.pt;
+ if (cur == p->ptend) {
+ p->e = PE_NOTENNODES;
+ return 0;
+ }
+ cur->str.type = PN_OBLSTR;
+ cur->str.len = len;
+ cur->str.iob = 0;
+ p->e = PE_OK;
+ p->cur.pt++;
+ return 1;
+}
+
+int
+p_insstr(struct parse_ctx *p, int type, const char *tok, uint32_t len)
+{
+ union parse_node *cur;
+
+ cur = p->cur.pt;
+ if (cur == p->ptend) {
+ p->e = PE_NOTENNODES;
+ return 0;
+ }
+ cur->str.type = type;
+ cur->str.len = len;
+ cur->str.tok = tok;
+ p->e = PE_OK;
p->cur.pt++;
return 1;
}
@@ -108,13 +421,13 @@ p_insint(struct parse_ctx *p, int prod, size_t len)
int
p_beg(struct parse_ctx *p, struct parse_cur *beg, int prod)
{
- return p_chk(p, beg) && p_insint(p, type, 0);
+ return p_chk(p, beg) && p_insint(p, prod, 0);
}
int
p_end(struct parse_ctx *p, struct parse_cur *beg)
{
- beg->pt->inter.len = p->cur.mark - beg->mark;
+ beg->pt->inter.len = p->cur.pt - beg->pt - 1;
p->e = PE_OK;
return 1;
}
@@ -144,7 +457,7 @@ p_list(struct parse_ctx *p, parsefn *prod)
{
int res;
- for (res = prod(p); res && p_2xcombo(p, SP, prod);)
+ for (res = prod(p); res && p_2xcombo(p, IL_SP, prod);)
;
return res && p_opt(p);
}
@@ -172,22 +485,24 @@ p_rep(struct parse_ctx *p, parsefn *prod)
/* 1*<any char but those in `except'> */
int
-p_repchr(struct parse_ctx *p, const char *except, int strtype)
+p_repchr(struct parse_ctx *p, const char *except, size_t elen, int strtype)
{
- char *t;
+ const char *t;
size_t len;
t = p->cur.tok;
-
- while (t != p->tokend && binsearch(except, *t) == -1)
+ while (t != p->tokend && !contains(except, elen, *t))
t++;
len = t - p->cur.tok;
if (len == 0) {
p->e = PE_PARSE;
goto exit;
+ } else if (len > UINT32_MAX) {
+ p->e = PE_STRTOOBIG;
+ goto exit;
}
- if (!p_insstr(p, strtype, p->cur.tok, len))
+ if (!p_insstr(p, strtype, p->cur.tok, (uint32_t)len))
goto exit;
p->cur.tok = t;
@@ -251,16 +566,18 @@ p_astr(struct parse_ctx *p)
{
struct parse_cur b;
- return p_beg(p, &b, PR_ASTRING) &&
- (p_repchr(p, astr_specials, PN_STR) || p_str(p)) &&
- p_end(p, &b) || p_rwd(p, &b);
+ return p_beg(p, &b, IP_ASTR) &&
+ (p_repchr(p, astr_specials, LEN(astr_specials), PN_STR) ||
+ p_str(p)) && p_end(p, &b) || p_rwd(p, &b);
}
int
p_atom(struct parse_ctx *p)
{
- return p_beg(p, &b, PR_ATOM) &&
- p_repchr(p, atom_specials, PN_STR) &&
+ struct parse_cur b;
+
+ return p_beg(p, &b, IP_ATOM) &&
+ p_repchr(p, atom_specials, LEN(atom_specials), PN_STR) &&
p_end(p, &b) || p_rwd(p, &b);
}
@@ -275,7 +592,7 @@ p_badcscode(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, BADCS) &&
+ return p_chk(p, &b) && p_lit(p, IL_BADCS) &&
(p_badcsopt(p) || p_opt(p)) || p_rwd(p, &b);
}
@@ -285,7 +602,7 @@ p_badcsopt(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) && p_sp(p) && p_opar(p) &&
- p_list(p, parse_astr) && p_cpar(p) || p_rwd(p, &b);
+ p_list(p, p_astr) && p_cpar(p) || p_rwd(p, &b);
}
int
@@ -336,6 +653,8 @@ p_bodyext(struct parse_ctx *p)
int
p_bodyf(struct parse_ctx *p)
{
+ struct parse_cur b;
+
return p_chk(p, &b) && p_bodyfpar(p) && p_sp(p) &&
p_bodyfid(p) && p_sp(p) && p_bodyfdes(p) && p_sp(p) &&
p_bodyfenc(p) && p_sp(p) && p_bodyfoct(p) || p_rwd(p, &b);
@@ -353,7 +672,7 @@ p_bodyfdsp(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) && (p_opar(p) && p_str(p) && p_sp(p) &&
- p_bodyfpar(p) && p_cpar(p) || p_rwd(p, &b)) || p_lit(p, NIL);
+ p_bodyfpar(p) && p_cpar(p) || p_rwd(p, &b)) || p_lit(p, IL_NIL);
}
int
@@ -361,9 +680,9 @@ p_bodyfenc(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && (p_dquote(p) && (p_lit(p, 7BIT) ||
- p_lit(p, 8BIT) || p_lit(p, BIN) || p_lit(p, B64) ||
- p_lit(p, QPRN)) && p_dquote(p) || p_rwd(p, &b)) ||
+ return p_chk(p, &b) && (p_dquote(p) && (p_lit(p, IL_7BIT) ||
+ p_lit(p, IL_8BIT) || p_lit(p, IL_BIN) || p_lit(p, IL_B64) ||
+ p_lit(p, IL_QPRN)) && p_dquote(p) || p_rwd(p, &b)) ||
p_str(p);
}
@@ -412,7 +731,7 @@ p_bodyfpar(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) && (p_opar(p) && p_list(p, p_sss) &&
- p_cpar(p) || p_rwd(p, &b)) || p_lit(p, NIL);
+ p_cpar(p) || p_rwd(p, &b)) || p_lit(p, IL_NIL);
}
int
@@ -483,8 +802,8 @@ p_cap(struct parse_ctx *p)
{
struct parse_cur b;
- return p_beg(p, &b, PR_CAP) && p_sp(p) &&
- (p_2xcombo(p, AUTHEQ, parse_authtype) || p_atom(p)) &&
+ return p_beg(p, &b, IP_CAP) && p_sp(p) &&
+ (p_2xcombo(p, IL_AUTHEQ, p_authtype) || p_atom(p)) &&
p_end(p, &b) || p_rwd(p, &b);
}
@@ -493,8 +812,8 @@ p_capdata(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, CAP) &&
- p_rep(p, parse_cap) || p_rwd(p, &b);
+ return p_chk(p, &b) && p_lit(p, IL_CAP) &&
+ p_rep(p, p_cap) || p_rwd(p, &b);
}
int
@@ -503,9 +822,9 @@ p_contreq(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) &&
- p_lit(p, PLUS) && p_sp(p) &&
+ p_lit(p, IL_PLUS) && p_sp(p) &&
(p_resptext(p) || p_base64(p)) &&
- p_lit(p, EOL) || p_rwd(p, &b);
+ p_lit(p, IL_EOL) || p_rwd(p, &b);
}
int
@@ -514,7 +833,7 @@ p_datetime(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) && p_dquote(p) && p_dayfix(p) &&
- p_lit(p, MINUS) && p_month(p) && p_lit(p, MINUS) &&
+ p_lit(p, IL_MINUS) && p_month(p) && p_lit(p, IL_MINUS) &&
p_year(p) && p_sp(p) && p_time(p) && p_sp(p) && p_zone(p) &&
p_dquote(p) || p_rwd(p, &b);
}
@@ -528,13 +847,41 @@ p_dayfix(struct parse_ctx *p)
p_rwd(p, &b) || p_dig(p, 2);
}
+int
+p_dig(struct parse_ctx *p, size_t count)
+{
+ uint32_t n, prev;
+ const char *t;
+
+ prev = n = 0;
+ t = p->cur.tok;
+
+ while (t != p->tokend && count && *t >= '0' && *t <= '9') {
+ prev = n;
+ n = UINT32_MAX & (10 * n + (*t - 48));
+ if (prev > n) {
+ p->e = PE_PARSE;
+ goto exit;
+ }
+ t++;
+ count--;
+ }
+ if (t == p->cur.tok || count != 0) {
+ p->e = PE_PARSE;
+ } else if (p_insnum(p, n)) {
+ p->cur.tok = t;
+ p->e = PE_OK;
+ }
+ exit:
+ return !p->e;
+}
+
int
p_dquotedchar(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_dquote(p) &&
- p_quotedchar(p) && p_dquote(p) ||
+ return p_chk(p, &b) && p_dquote(p) && p_qchar(p) && p_dquote(p) ||
p_rwd(p, &b);
}
@@ -556,20 +903,21 @@ p_envaddr(struct parse_ctx *p, int prod)
{
struct parse_cur b;
- return p_chk(p, &b) && p_opar(p) && p_rep(p, p_addr) && p_cpar(p) ||
- p_rwd(p, &b) || p_lit(p, NIL);
+ return p_beg(p, &b, prod) &&
+ (p_opar(p) && p_rep(p, p_addr) && p_cpar(p) ||
+ p_rwd(p, &b) || p_lit(p, IL_NIL)) && p_end(p, &b);
}
int
p_envbcc(struct parse_ctx *p)
{
- return p_envaddr(p, PR_ENVBCC);
+ return p_envaddr(p, IP_ENVBCC);
}
int
p_envcc(struct parse_ctx *p)
{
- return p_envaddr(p, cc);
+ return p_envaddr(p, IP_ENVCC);
}
int
@@ -581,7 +929,7 @@ p_envdate(struct parse_ctx *p)
int
p_envfrom(struct parse_ctx *p)
{
- return p_envaddr(p, PR_ENVFROM)
+ return p_envaddr(p, IP_ENVFROM);
}
int
@@ -599,13 +947,13 @@ p_envmsgid(struct parse_ctx *p)
int
p_envrepto(struct parse_ctx *p)
{
- return p_envaddr(p, PR_ENVREPTO)
+ return p_envaddr(p, IP_ENVREPTO);
}
int
p_envsender(struct parse_ctx *p)
{
- return p_envaddr(p, PR_ENVSENDER)
+ return p_envaddr(p, IP_ENVSENDER);
}
int
@@ -617,17 +965,7 @@ p_envsubj(struct parse_ctx *p)
int
p_envto(struct parse_ctx *p)
{
- return p_envaddr(p, PR_ENVTO)
-}
-
-int
-p_escqspec(struct parse_ctx *p)
-{
- struct parse_cur b;
-
- return p_chk(p, &b) && p_lit(p, BSLASH) &&
- (p_dquote(p) || p_lit(p, BSLASH)) ||
- p_rwd(p, &b);
+ return p_envaddr(p, IP_ENVTO);
}
int
@@ -635,16 +973,16 @@ p_fetchrec(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, FETCH) && p_sp(p) &&
+ return p_chk(p, &b) && p_lit(p, IL_FETCH) && p_sp(p) &&
p_opar(p) && p_list(p, p_msgatt) && p_cpar(p) || p_rwd(p, &b);
}
int
p_flag(struct parse_ctx *p)
{
- return p_lit(p, ANSWERED) || p_lit(p, FLAGGED) ||
- p_lit(p, DELETED) || p_lit(p, SEEN) ||
- p_lit(p, DRAFT) || p_flkeyword(p) ||
+ return p_lit(p, IL_FLANSWERED) || p_lit(p, IL_FLFLAGGED) ||
+ p_lit(p, IL_FLDELETED) || p_lit(p, IL_FLSEEN) ||
+ p_lit(p, IL_FLDRAFT) || p_flkeyword(p) ||
p_flext(p);
}
@@ -653,14 +991,14 @@ p_flext(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, BSLASH) &&
+ return p_chk(p, &b) && p_lit(p, IL_BSLASH) &&
p_atom(p) || p_rwd(p, &b);
}
int
p_flfetch(struct parse_ctx *p)
{
- return p_flag(p) || p_lit(p, FLRECENT);
+ return p_flag(p) || p_lit(p, IL_FLRECENT);
}
int
@@ -683,17 +1021,17 @@ int
p_genctext(struct parse_ctx *p)
{
int res;
- char *t;
+ const char *t;
- t = p->cur.ntok;
+ t = p->cur.tok;
while (t != p->tokend && *t >= '\1' && *t <= '\x7f' &&
*t != ']' && *t != '\r' && *t != '\n')
t++;
- res = t > p->cur.ntok;
+ res = t > p->cur.tok;
if (res)
- p->cur.ntok = t;
+ p->cur.tok = t;
p->e = !res;
return res;
@@ -715,46 +1053,53 @@ p_hdrlist(struct parse_ctx *p)
}
int
-p_lit(struct parse_ctx *p, int lit)
+p_lit(struct parse_ctx *p, int val)
{
size_t left;
+ struct literal *lit;
- left = p->toklen - (p->cur.ntok - p->tokens);
- if (left < literals[lit].len) {
- p->e = 1;
+ left = p->tokend - p->cur.tok;
+ lit = literals + val;
+
+ if (left < lit->slen) {
+ p->e = PE_PARSE;
goto exit;
}
- if (strncasecmp(p->cur.tok, literals[lit].val, literals[lit].len) == 0) {
- if (p->cur.nact == p->actend)) {
- p->e = 2;
- goto exit;
+ if (strncasecmp(p->cur.tok, lit->srep, lit->slen) == 0) {
+ if (p_inslit(p, val)) {
+ p->cur.tok += lit->slen;
+ p->e = PE_OK;
}
- *p->cur.nact++ = { ... };
- p->cur.ntok += literals[lit].len;
- p->e = 0;
} else {
- p->e = 1;
- goto exit;
+ p->e = PE_PARSE;
}
exit:
return !p->e;
}
int
-p_litstr(struct parse_ctx *p)
+p_lstr(struct parse_ctx *p)
{
int res;
size_t len;
- struct parse_cur b;
+ struct parse_cur b, n;
- res = p_beg(p, MK_LITSTR, &b) && p_lit(p, OBRACE) &&
- p_number(p) && p_lit(p, CBRACE) && p_lit(p, EOL) &&
- p_end(p, &b) || p_rwd(p, &b);
+ res = p_chk(p, &b) && p_lit(p, IL_OBRACE) &&
+ p_chk(p, &n) && p_num(p) && p_lit(p, IL_CBRACE) &&
+ p_lit(p, IL_EOL) || p_rwd(p, &b);
if (res) {
- len = b.pt[4].num.val;
- if (len < p->oblth)
- p->cur.tok += len;
+ len = n.pt->num.val;
+ if (len > UINT32_MAX) {
+ p->e = PE_STRTOOBIG;
+ res = 0;
+ } else if (len < p->oblth) {
+ res = p_insstr(p, PN_LSTR, p->cur.tok, (uint32_t)len);
+ if (res)
+ p->cur.tok += len;
+ } else {
+ res = p_insoblstr(p, (uint32_t)len);
+ }
}
return res;
}
@@ -762,7 +1107,7 @@ p_litstr(struct parse_ctx *p)
int
p_mailbox(struct parse_ctx *p)
{
- return p_lit(p, INBOX) || p_astr(p);
+ return p_lit(p, IL_INBOX) || p_astr(p);
}
int
@@ -770,8 +1115,8 @@ p_matbody(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, BODY) &&
- (p_lit(p, STRUCT) || p_opt(p)) && p_sp(p) &&
+ return p_chk(p, &b) && p_lit(p, IL_BODY) &&
+ (p_lit(p, IL_STRUCT) || p_opt(p)) && p_sp(p) &&
p_body(p) || p_rwd(p, &b);
}
@@ -780,15 +1125,15 @@ p_matbsect(struct parse_ctx *p)
{
struct parse_cur b, o;
- return p_chk(p, &b) && p_lit(p, BODY) && p_section(p) &&
- (p_chk(p, &o) && p_lit(p, LT) && p_num(p) && p_lit(p, GT) ||
+ return p_chk(p, &b) && p_lit(p, IL_BODY) && p_section(p) &&
+ (p_chk(p, &o) && p_lit(p, IL_LT) && p_num(p) && p_lit(p, IL_GT) ||
p_rwd(p, &o) || p_opt(p)) && p_sp(p) && p_nstr(p) || p_rwd(p, &b);
}
int
p_matenv(struct parse_ctx *p)
{
- return p_3xcombo(p, EVELOPE, SP, p_env);
+ return p_3xcombo(p, IL_ENVELOPE, IL_SP, p_env);
}
int
@@ -796,8 +1141,8 @@ p_mathdrotxt(struct parse_ctx *p)
{
struct parse_cur b, o;
- return p_chk(p, &b) && p_lit(p, RFC822) &&
- (p_chk(p, &o) && p_lit(p, DHDR) || p_lit(p, DTXT) ||
+ return p_chk(p, &b) && p_lit(p, IL_RFC822) &&
+ (p_chk(p, &o) && p_lit(p, IL_DHDR) || p_lit(p, IL_DTXT) ||
p_rwd(p, &o) || p_opt(p)) && p_sp(p) && p_nstr(p) ||
p_rwd(p, &b);
}
@@ -805,19 +1150,19 @@ p_mathdrotxt(struct parse_ctx *p)
int
p_matintdate(struct parse_ctx *p)
{
- return p_3xcombo(p, INTDATE, SP, p_datetime);
+ return p_3xcombo(p, IL_INTDATE, IL_SP, p_datetime);
}
int
p_matsize(struct parse_ctx *p)
{
- return p_3xcombo(p, RFC822SIZE, SP, p_num);
+ return p_3xcombo(p, IL_RFC822SIZE, IL_SP, p_num);
}
int
p_matuid(struct parse_ctx *p)
{
- return p_3xcombo(p, UID, SP, p_uid);
+ return p_3xcombo(p, IL_UID, IL_SP, p_uid);
}
int
@@ -832,7 +1177,7 @@ p_mbdata(struct parse_ctx *p)
int
p_mbexists(struct parse_ctx *p)
{
- return p_r3xcombo(p, parse_number, SP, EXISTS);
+ return p_r3xcombo(p, p_num, IL_SP, IL_EXISTS);
}
int
@@ -840,9 +1185,9 @@ p_mbflags(struct parse_ctx *p)
{
struct parse_cur b;
- rerurn p_chk(p, &b) && p_lit(p, FLAGS) &&
+ return p_chk(p, &b) && p_lit(p, IL_FLAGS) &&
p_sp(p) && p_opar(p) &&
- (p_list(p, parse_flag) || p_opt(p)) &&
+ (p_list(p, p_flag) || p_opt(p)) &&
p_cpar(p) || p_rwd(p, &b);
}
@@ -851,7 +1196,7 @@ p_mblist(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, LIST) &&
+ return p_chk(p, &b) && p_lit(p, IL_LIST) &&
p_sp(p) && p_mblistdata(p) ||
p_rwd(p, &b);
}
@@ -862,9 +1207,9 @@ p_mblistdata(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) && p_opar(p) &&
- (p_list(p, parse_mblistfl) || p_opt(p)) &&
+ (p_list(p, p_mblistfl) || p_opt(p)) &&
p_cpar(p) && p_sp(p) &&
- (p_dquotedchar(p) || p_lit(NIL)) &&
+ (p_dquotedchar(p) || p_lit(p, IL_NIL)) &&
p_sp(p) && p_mailbox(p) || p_rwd(p, &b);
}
@@ -875,30 +1220,30 @@ p_mblistdata(struct parse_ctx *p)
int
p_mblistfl(struct parse_ctx *p)
{
- return p_mblistosfl(p) || p_list(p, parse_mblistofl);
+ return p_mblistosfl(p) || p_list(p, p_mblistofl);
}
int
p_mblistofl(struct parse_ctx *p)
{
- return p_lit(p, NOINFERIORS) || p_flext(p);
+ return p_lit(p, IL_FLNOINFERIORS) || p_flext(p);
}
int
-p_mblistosfl(struc parse_ctx *p)
+p_mblistosfl(struct parse_ctx *p)
{
int res;
struct parse_cur b;
- checkpoint(p, &b);
+ p_chk(p, &b);
- res = p_list(p, parse_mblistofl) &&
+ res = p_list(p, p_mblistofl) &&
p_sp(p) || p_rwd(p, &b) || p_opt(p);
res = res && p_mblistsfl(p);
- res = res && p_chk(p, &s) && p_sp(p) &&
- p_list(p, parse_mblistofl) || p_rwd(p, &s) || p_opt(p);
+ res = res && p_chk(p, &b) && p_sp(p) &&
+ p_list(p, p_mblistofl) || p_rwd(p, &b) || p_opt(p);
return res || p_rwd(p, &b);
}
@@ -906,8 +1251,8 @@ p_mblistosfl(struc parse_ctx *p)
int
p_mblistsfl(struct parse_ctx *p)
{
- return p_lit(p, NOSEL) || p_lit(p, MARKED) ||
- p_lit(p, UNMARKED);
+ return p_lit(p, IL_FLNOSEL) || p_lit(p, IL_FLMARKED) ||
+ p_lit(p, IL_FLUNMARKED);
}
int
@@ -915,7 +1260,7 @@ p_mblsub(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, LSUB) &&
+ return p_chk(p, &b) && p_lit(p, IL_LSUB) &&
p_sp(p) && p_mblistdata(p) ||
p_rwd(p, &b);
}
@@ -923,7 +1268,7 @@ p_mblsub(struct parse_ctx *p)
int
p_mbrecent(struct parse_ctx *p)
{
- return p_r3xcombo(p, parse_number, SP, RECENT);
+ return p_r3xcombo(p, p_num, IL_SP, IL_RECENT);
}
int
@@ -931,9 +1276,9 @@ p_mbsearch(struct parse_ctx *p)
{
struct parse_cur b, o;
- return p_chk(p, &b) && p_lit(p, SEARCH) &&
+ return p_chk(p, &b) && p_lit(p, IL_SEARCH) &&
(p_chk(p, &o) && p_sp(p) &&
- p_list(p, parse_nznumber) || p_rwd(p, &o) || p_opt(p)) ||
+ p_list(p, p_nznum) || p_rwd(p, &o) || p_opt(p)) ||
p_rwd(p, &b);
}
@@ -942,18 +1287,20 @@ p_mbstatus(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, STATUS) && p_sp(p) &&
+ return p_chk(p, &b) && p_lit(p, IL_STATUS) && p_sp(p) &&
p_mailbox(p) && p_sp(p) && p_opar(p) &&
- (p_list(p, parse_stattrec) || p_opt(p)) && p_cpar(p) ||
+ (p_list(p, p_stattrec) || p_opt(p)) && p_cpar(p) ||
p_rwd(p, &b);
}
int
p_medbas(struct parse_ctx *p)
{
+ struct parse_cur b;
+
return p_chk(p, &b) && (p_dquote(p) &&
- (p_lit(p, APP) || p_lit(p, AUDIO) || p_lit(p, IMG) ||
- p_lit(p, MSG) || p_lit(p, VIDEO)) && p_dquote(p) ||
+ (p_lit(p, IL_APP) || p_lit(p, IL_AUDIO) || p_lit(p, IL_IMG) ||
+ p_lit(p, IL_MSG) || p_lit(p, IL_VIDEO)) && p_dquote(p) ||
(p_rwd(p, &b) || p_str(p))) &&
p_sp(p) && p_medsubt(p) || p_rwd(p, &b);
}
@@ -964,8 +1311,8 @@ p_medmsg(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) &&
- p_dquote(p) && p_lit(p, MSG) && p_dquote(p) && p_sp(p) &&
- p_dquote(p) && p_lit(p, RFC822) && p_dquote(p) || p_rwd(p, &b);
+ p_dquote(p) && p_lit(p, IL_MSG) && p_dquote(p) && p_sp(p) &&
+ p_dquote(p) && p_lit(p, IL_RFC822) && p_dquote(p) || p_rwd(p, &b);
}
int
@@ -979,17 +1326,17 @@ p_medtxt(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_dquote(p) && p_lit(p, TXT) && p_dquote(p) &&
+ return p_chk(p, &b) && p_dquote(p) && p_lit(p, IL_TXT) && p_dquote(p) &&
p_sp(p) && p_medsubt(p) || p_rwd(p, &b);
}
int
p_month(struct parse_ctx *p)
{
- return p_lit(p, JAN) || p_lit(p, FEB) || p_lit(p, MAR) ||
- p_lit(p, APR) || p_lit(p, MAY) || p_lit(p, JUN) ||
- p_lit(p, JUL) || p_lit(p, AUG) || p_lit(p, SEP) ||
- p_lit(p, OCT) || p_lit(p, NOV) || p_lit(p, DEC);
+ return p_lit(p, IL_JAN) || p_lit(p, IL_FEB) || p_lit(p, IL_MAR) ||
+ p_lit(p, IL_APR) || p_lit(p, IL_MAY) || p_lit(p, IL_JUN) ||
+ p_lit(p, IL_JUL) || p_lit(p, IL_AUG) || p_lit(p, IL_SEP) ||
+ p_lit(p, IL_OCT) || p_lit(p, IL_NOV) || p_lit(p, IL_DEC);
}
int
@@ -998,7 +1345,7 @@ p_msgdata(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) && p_nznum(p) && p_sp(p) &&
- (p_lit(p, EXPUNGE) || p_fetchrec(p)) || p_rwd(p, &b);
+ (p_lit(p, IL_EXPUNGE) || p_fetchrec(p)) || p_rwd(p, &b);
}
int
@@ -1012,7 +1359,7 @@ p_msgattdyn(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, FLAGS) && p_sp(p) && p_opar(p) &&
+ return p_chk(p, &b) && p_lit(p, IL_FLAGS) && p_sp(p) && p_opar(p) &&
(p_list(p, p_flfetch) || p_opt(p)) && p_cpar(p) || p_rwd(p, &b);
}
@@ -1026,42 +1373,57 @@ p_msgattstat(struct parse_ctx *p)
int
p_nstr(struct parse_ctx *p)
{
- return p_str(p) || p_lit(p, NIL);
+ return p_str(p) || p_lit(p, IL_NIL);
}
int
-p_number(struct parse_ctx *p)
+p_num(struct parse_ctx *p)
{
- /* DO ME */
+ uint32_t n, prev;
+ const char *t;
+
+ prev = n = 0;
+ t = p->cur.tok;
+
+ while (t != p->tokend && *t >= '0' && *t <= '9') {
+ prev = n;
+ n = UINT32_MAX & (10 * n + (*t - 48));
+ if (prev > n) {
+ p->e = PE_PARSE;
+ goto exit;
+ }
+ t++;
+ }
+ if (t == p->cur.tok) {
+ p->e = PE_PARSE;
+ } else if (p_insnum(p, n)) {
+ p->cur.tok = t;
+ p->e = PE_OK;
+ }
+ exit:
+ return !p->e;
}
int
-p_nznumber(struct parse_ctx *p)
+p_nznum(struct parse_ctx *p)
{
- int res;
- char *t;
+ const char *t;
- t = p->cur.ntok;
+ t = p->cur.tok;
- if (t == p->tokend || *t < '1' || *t > '9')
+ if (t == p->tokend || *t < '1' || *t > '9') {
+ p->e = PE_PARSE;
goto exit;
-
- while (t != p->tokend && *t >= '0' && *t <= '9')
- t++;
-
+ }
+ p_num(p);
exit:
- res = t > p->cur.ntok;
- if (res)
- p->cur.ntok = t;
-
- p->e = !res;
- return res;
+ return !p->e;
}
int
p_permfl(struct parse_ctx *p)
{
- return p_flag(p) || p_lit(p, ANYFL);
+ return p_flag(p) || p_lit(p, IL_FLANY);
}
int
@@ -1069,38 +1431,100 @@ p_permflcode(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, PERMFL) &&
+ return p_chk(p, &b) && p_lit(p, IL_PERMFL) &&
p_sp(p) && p_opar(p) &&
- (p_list(p, parse_permfl) || p_opt(p)) &&
+ (p_list(p, p_permfl) || p_opt(p)) &&
p_cpar(p) || p_rwd(p, &b);
}
int
-p_quotedchar(struct parse_ctx *p)
+p_qchar(struct parse_ctx *p)
{
- return p_quotedcharclean(p) || p_escqspec(p);
+ const char *t;
+ int len;
+ size_t left;
+
+ t = p->cur.tok;
+ left = p->tokend - p->cur.tok;
+
+ if (t == p->tokend) {
+ p->e = PE_PARSE;
+ goto exit;
+ }
+ if (*t >= '\1' && *t <= '\x7f' && *t != '\r' &&
+ *t != '\n' && *t != '"' && *t != '\\') {
+ len = 1;
+ } else if (left >= 2 &&
+ (strncmp(t, "\\\"", 2) == 0 || strncmp(t, "\\\\", 2) == 0)) {
+ len = 2;
+ } else {
+ p->e = PE_PARSE;
+ goto exit;
+ }
+
+ if (!p_insstr(p, PN_QSTR, p->cur.tok, len)) {
+ p->e = PE_PARSE;
+ goto exit;
+ }
+ p->cur.tok += len;
+ p->e = PE_OK;
+
+ exit:
+ return !p->e;
}
int
-p_quotedcharclean(struct parse_ctx *p)
+p_qchars(struct parse_ctx *p)
{
- if (p->cur.ntok != p->tokend &&
- binsearch(quotedclean, *p->cur.ntok) == -1) {
- p->cur.ntok++;
- p->e = 0;
- } else {
- p->e = 1;
+ const char *t;
+ size_t len;
+ int esc;
+
+ t = p->cur.tok;
+ esc = 0;
+ while (t != p->tokend) {
+ if (esc) {
+ if (*t == '"' || *t == '\\') {
+ t++;
+ esc = 0;
+ } else {
+ p->e = PE_PARSE;
+ goto exit;
+ }
+ } else if (*t == '\\') {
+ t++;
+ esc = 1;
+ } else if (*t >= '\1' && *t <= '\x7f' && *t != '\r' &&
+ *t != '\n' && *t != '"' && *t != '\\') {
+ t++;
+ } else {
+ p->e = PE_PARSE;
+ goto exit;
+ }
}
+ len = t - p->cur.tok;
+ if (len == 0) {
+ p->e = PE_PARSE;
+ goto exit;
+ } else if (len > UINT32_MAX) {
+ p->e = PE_STRTOOBIG;
+ goto exit;
+ } else if (!p_insstr(p, PN_QSTR, p->cur.tok, (uint32_t)len))
+ goto exit;
+
+ p->cur.tok = t;
+ p->e = PE_OK;
+
+ exit:
return !p->e;
}
int
-p_quotstr(struct parse_ctx *p)
+p_qstr(struct parse_ctx *p)
{
struct parse_cur b;
- return p_beg(p, &b, MK_QUOTSTR) && p_dquote(p) &&
- (p_rep(p, parse_quotedchar) || p_opt(p)) &&
+ return p_chk(p, &b) && p_dquote(p) && (p_qchars(p) || p_opt(p)) &&
p_dquote(p) || p_rwd(p, &b);
}
@@ -1109,7 +1533,7 @@ p_respbye(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, BYE) && p_sp(p) &&
+ return p_chk(p, &b) && p_lit(p, IL_BYE) && p_sp(p) &&
p_resptext(p) || p_rwd(p, &b);
}
@@ -1118,10 +1542,10 @@ p_respdata(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, ASTERISK) &&
+ return p_chk(p, &b) && p_lit(p, IL_ASTERISK) &&
p_sp(p) && (p_respstate(p) ||
p_respbye(p) || p_mbdata(p) || p_msgdata(p) ||
- p_capdata(p)) && p_eol(p) || p_rwd(p &s);
+ p_capdata(p)) && p_lit(p, IL_EOL) || p_rwd(p, &b);
}
int
@@ -1136,7 +1560,7 @@ p_respstate(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) &&
- (p_lit(p, OK) || p_lit(p, NO) || p_lit(p, BAD)) &&
+ (p_lit(p, IL_OK) || p_lit(p, IL_NO) || p_lit(p, IL_BAD)) &&
p_sp(p) && p_resptext(p) || p_rwd(p, &b);
}
@@ -1146,8 +1570,8 @@ p_resptext(struct parse_ctx *p)
int res;
struct parse_cur b;
- res = p_chk(p, &b) && p_lit(p, OBRACK) &&
- p_resptextcode(p) && p_lit(p, CBRACK) &&
+ res = p_chk(p, &b) && p_lit(p, IL_OBRACK) &&
+ p_resptextcode(p) && p_lit(p, IL_CBRACK) &&
p_sp(p) || p_rwd(p, &b) || p_opt(p);
return res && p_text(p);
@@ -1156,10 +1580,10 @@ p_resptext(struct parse_ctx *p)
int
p_resptextcode(struct parse_ctx *p)
{
- return p_lit(p, ALERT) || p_badcscode(p) ||
- p_capdata(p) || p_lit(p, PARSE) ||
- p_permflcode(p) || p_lit(p, RO) ||
- p_lit(p, RW) || p_lit(p, TRYC) ||
+ return p_lit(p, IL_ALERT) || p_badcscode(p) ||
+ p_capdata(p) || p_lit(p, IL_PARSE) ||
+ p_permflcode(p) || p_lit(p, IL_RO) ||
+ p_lit(p, IL_RW) || p_lit(p, IL_TRYC) ||
p_uidncode(p) || p_uidvcode(p) ||
p_unseencode(p) || p_gencode(p);
}
@@ -1169,15 +1593,15 @@ p_secmsgtxt(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, HEADER) ||
- (p_lit(p, HDRFLDS) && (p_lit(p, DNOT) || p_opt(p)) &&
- p_sp(p) && p_hdrlist(p) || p_rwd(p, &b)) || p_lit(p, TXT);
+ return p_chk(p, &b) && p_lit(p, IL_HDR) ||
+ (p_lit(p, IL_HDRFIELDS) && (p_lit(p, IL_DNOT) || p_opt(p)) &&
+ p_sp(p) && p_hdrlist(p) || p_rwd(p, &b)) || p_lit(p, IL_TXT);
}
int
p_secpt(struct parse_ctx *p)
{
- return p_listsep(p, p_nznum, DOT);
+ return p_listsep(p, p_nznum, IL_DOT);
}
int
@@ -1186,7 +1610,7 @@ p_secspec(struct parse_ctx *p)
struct parse_cur b, o;
return p_chk(p, &b) && p_secmsgtxt(p) || (p_secpt(p) &&
- (p_chk(p, &o) && p_lit(p, DOT) && p_sectxt(p) ||
+ (p_chk(p, &o) && p_lit(p, IL_DOT) && p_sectxt(p) ||
p_rwd(p, &o) || p_opt(p))) || p_rwd(p, &b);
}
@@ -1195,23 +1619,23 @@ p_section(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_lit(p, OBRACK) &&
+ return p_chk(p, &b) && p_lit(p, IL_OBRACK) &&
(p_secspec(p) || p_opt(p)) &&
- p_lit(p, CBRACK) || p_rwd(p, &b);
+ p_lit(p, IL_CBRACK) || p_rwd(p, &b);
}
int
p_sectxt(struct parse_ctx *p)
{
- return p_secmsgtxt(p) || p_lit(p, MIME);
+ return p_secmsgtxt(p) || p_lit(p, IL_MIME);
}
int
p_statt(struct parse_ctx *p)
{
- return p_lit(p, MESSAGES) || p_lit(p, RECENT) ||
- p_lit(p, UIDNEXT) || p_lit(p, UIDVAL) ||
- p_lit(p, UNSEEN);
+ return p_lit(p, IL_MSGS) || p_lit(p, IL_RECENT) ||
+ p_lit(p, IL_UIDNEXT) || p_lit(p, IL_UIDVAL) ||
+ p_lit(p, IL_UNSEEN);
}
int
@@ -1220,19 +1644,19 @@ p_stattrec(struct parse_ctx *p)
struct parse_cur b;
return p_chk(p, &b) && p_statt(p) && p_sp(p) &&
- p_number(p) || p_rwd(p, &b);
+ p_num(p) || p_rwd(p, &b);
}
int
p_str(struct parse_ctx *p)
{
- return p_qoutstr(p) || p_litstr(p);
+ return p_qstr(p) || p_lstr(p);
}
int
p_tag(struct parse_ctx *p)
{
- return p_repchr(p, tag_specials);
+ return p_repchr(p, tag_specials, LEN(tag_specials), PN_STR);
}
int
@@ -1240,8 +1664,38 @@ p_taggedresp(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_tag(p) && p_sp(p) &&
- p_respstate(p) && p_eol(p) || p_rwd(p, &b);
+ return p_beg(p, &b, IP_TAGGEDRESP) && (p_tag(p) && p_sp(p) &&
+ p_respstate(p) && p_lit(p, IL_EOL) || p_rwd(p, &b)) &&
+ p_end(p, &b);
+}
+
+int
+p_text(struct parse_ctx *p)
+{
+ const char *t;
+ size_t len;
+
+ t = p->cur.tok;
+ while (t != p->tokend && *t >= '\1' && *t <= '\x7f' &&
+ *t != '\r' && *t != '\n')
+ t++;
+
+ len = t - p->cur.tok;
+ if (len == 0) {
+ p->e = PE_PARSE;
+ goto exit;
+ } else if (len > UINT32_MAX) {
+ p->e = PE_STRTOOBIG;
+ goto exit;
+ }
+ if (!p_insstr(p, PN_STR, p->cur.tok, (uint32_t)len))
+ goto exit;
+
+ p->cur.tok = t;
+ p->e = PE_OK;
+
+ exit:
+ return !p->e;
}
int
@@ -1249,32 +1703,32 @@ p_time(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && p_dig(p, 2) && p_lit(p, COLON) &&
- p_dig(p, 2) && p_lit(p, COLON) && p_dig(p, 2) || p_rwd(p, &b);
+ return p_chk(p, &b) && p_dig(p, 2) && p_lit(p, IL_COLON) &&
+ p_dig(p, 2) && p_lit(p, IL_COLON) && p_dig(p, 2) || p_rwd(p, &b);
}
int
p_uid(struct parse_ctx *p)
{
- return p_nznumber(p);
+ return p_nznum(p);
}
int
p_uidncode(struct parse_ctx *p)
{
- return p_3xcombo(UIDNEXT, SP, parse_nznumber);
+ return p_3xcombo(p, IL_UIDNEXT, IL_SP, p_nznum);
}
int
p_uidvcode(struct parse_ctx *p)
{
- return p_3xcombo(UIDVAL, SP, parse_nznumber);
+ return p_3xcombo(p, IL_UIDVAL, IL_SP, p_nznum);
}
int
p_unseencode(struct parse_ctx *p)
{
- return p_3xcombo(UNSEEN, SP, parse_nznumber);
+ return p_3xcombo(p, IL_UNSEEN, IL_SP, p_nznum);
}
int
@@ -1288,7 +1742,8 @@ p_zone(struct parse_ctx *p)
{
struct parse_cur b;
- return p_chk(p, &b) && (p_lit(p, PLUS) || p_lit(p, MINUS)) &&
+ return p_chk(p, &b) &&
+ (p_lit(p, IL_PLUS) || p_lit(p, IL_MINUS)) &&
p_dig(p, 4) || p_rwd(p, &b);
}
@@ -1298,23 +1753,23 @@ p_zone(struct parse_ctx *p)
int
p_cpar(struct parse_ctx *p)
{
- return p_lit(p, CPAR);
+ return p_lit(p, IL_CPAR);
}
int
p_dquote(struct parse_ctx *p)
{
- return p_lit(p, DQUOTE);
+ return p_lit(p, IL_DQUOTE);
}
int
p_opar(struct parse_ctx *p)
{
- return p_lit(p, OPAR);
+ return p_lit(p, IL_OPAR);
}
int
p_sp(struct parse_ctx *p)
{
- return p_lit(p, SP);
+ return p_lit(p, IL_SP);
}
diff --git a/parse.h b/parse.h
index 9ab51dd..c83ee61 100644
--- a/parse.h
+++ b/parse.h
@@ -1,9 +1,114 @@
-enum parse_lit { };
-enum parse_prod { };
+enum {
+ IL_7BIT,
+ IL_8BIT,
+ IL_ALERT,
+ IL_APP,
+ IL_APR,
+ IL_ASTERISK,
+ IL_AUDIO,
+ IL_AUG,
+ IL_AUTHEQ,
+ IL_B64,
+ IL_BAD,
+ IL_BADCS,
+ IL_BIN,
+ IL_BODY,
+ IL_BSLASH,
+ IL_BYE,
+ IL_CAP,
+ IL_CBRACE,
+ IL_CBRACK,
+ IL_COLON,
+ IL_CPAR,
+ IL_DEC,
+ IL_DHDR,
+ IL_DNOT,
+ IL_DOT,
+ IL_DQUOTE,
+ IL_DTXT,
+ IL_ENVELOPE,
+ IL_EOL,
+ IL_EXISTS,
+ IL_EXPUNGE,
+ IL_FEB,
+ IL_FETCH,
+ IL_FLAGS,
+ IL_FLANSWERED,
+ IL_FLANY,
+ IL_FLDELETED,
+ IL_FLDRAFT,
+ IL_FLFLAGGED,
+ IL_FLMARKED,
+ IL_FLNOINFERIORS,
+ IL_FLNOSEL,
+ IL_FLRECENT,
+ IL_FLSEEN,
+ IL_FLUNMARKED,
+ IL_GT,
+ IL_HDR,
+ IL_HDRFIELDS,
+ IL_IMG,
+ IL_INBOX,
+ IL_INTDATE,
+ IL_JAN,
+ IL_JUL,
+ IL_JUN,
+ IL_LIST,
+ IL_LSUB,
+ IL_LT,
+ IL_MAR,
+ IL_MAY,
+ IL_MIME,
+ IL_MINUS,
+ IL_MSG,
+ IL_MSGS,
+ IL_NIL,
+ IL_NO,
+ IL_NOV,
+ IL_OBRACE,
+ IL_OBRACK,
+ IL_OCT,
+ IL_OK,
+ IL_OPAR,
+ IL_PARSE,
+ IL_PERMFL,
+ IL_PLUS,
+ IL_QPRN,
+ IL_RECENT,
+ IL_RFC822,
+ IL_RFC822SIZE,
+ IL_RO,
+ IL_RW,
+ IL_SEARCH,
+ IL_SEP,
+ IL_SP,
+ IL_STATUS,
+ IL_STRUCT,
+ IL_TRYC,
+ IL_TXT,
+ IL_UID,
+ IL_UIDNEXT,
+ IL_UIDVAL,
+ IL_UNSEEN,
+ IL_VIDEO,
+};
+
+enum {
+ IP_ASTR,
+ IP_ATOM,
+ IP_CAP,
+ IP_ENVBCC,
+ IP_ENVCC,
+ IP_ENVFROM,
+ IP_ENVREPTO,
+ IP_ENVSENDER,
+ IP_ENVTO,
+ IP_TAGGEDRESP,
+};
enum { PN_INTER, PN_LIT, PN_NUM, PN_STR, PN_QSTR, PN_LSTR, PN_OBLSTR };
-enum { PE_OK, PE_PARSE, PE_NOTENNODES };
+enum { PE_OK, PE_PARSE, PE_NOTENNODES, PE_STRTOOBIG };
union parse_node {
int type;
@@ -18,17 +123,17 @@ union parse_node {
} lit;
struct {
int type;
- size_t val;
+ uint32_t val;
} num;
struct {
int type;
uint32_t len;
union {
- char *tok;
+ const char *tok;
size_t iob;
};
} str;
};
int parse_respln(const char *tok, size_t toklen, union parse_node *pt,
- size_t ptlen, size_t oblth)
+ size_t ptlen, size_t oblth);
diff --git a/pshades.c b/pshades.c
new file mode 100644
index 0000000..c5854c3
--- /dev/null
+++ b/pshades.c
@@ -0,0 +1,129 @@
+#include <err.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+#define LEN(a) (sizeof(a) / sizeof(a)[0])
+
+char *perr[] = {
+ [PE_PARSE] = "input not recognized",
+ [PE_NOTENNODES] = "cannot fit parse tree within supplied space",
+ [PE_STRTOOBIG] = "stalled upon a string longer than 2^32 - 1",
+};
+
+char *prod[] = {
+ "ASTR",
+ "ATOM",
+ "CAP",
+ "ENVBCC",
+ "ENVCC",
+ "ENVFROM",
+ "ENVREPTO",
+ "ENVSENDER",
+ "ENVTO",
+ "TAGGEDRESP",
+};
+
+char *literals[] = {
+ "7BIT", "8BIT", "ALERT", "APP", "APR", "ASTERISK", "AUDIO", "AUG",
+ "AUTHEQ", "B64", "BAD", "BADCS", "BIN", "BODY", "BSLASH", "BYE",
+ "CAP", "CBRACE", "CBRACK", "COLON", "CPAR", "DEC", "DHDR", "DNOT",
+ "DOT", "DQUOTE", "DTXT", "ENVELOPE", "EOL", "EXISTS", "EXPUNGE",
+ "FEB", "FETCH", "FLAGS", "FLANSWERED", "FLANY", "FLDELETED",
+ "FLDRAFT", "FLFLAGGED", "FLRECENT", "FLSEEN", "GT", "HDR",
+ "HDRFIELDS", "IMG", "INBOX", "INTDATE", "JAN", "JUL", "JUN", "LIST",
+ "LSUB", "LT", "MAR", "MARKED", "MAY", "MIME", "MINUS", "MSG", "MSGS",
+ "NIL", "NO", "NOINFERIORS", "NOSEL", "NOV", "OBRACE", "OBRACK",
+ "OCT", "OK", "OPAR", "PARSE", "PERMFL", "PLUS", "QPRN", "RECENT",
+ "RFC822", "RFC822SIZE", "RO", "RW", "SEARCH", "SEP", "SP", "STATUS",
+ "STRUCT", "TRYC", "TXT", "UID", "UIDNEXT", "UIDVAL", "UNMARKED",
+ "UNSEEN", "VIDEO",
+};
+
+void ptprint(union parse_node *, size_t);
+union parse_node *ptnext(union parse_node *);
+
+int
+main(int argc, char **argv)
+{
+ size_t l, inlen;
+ ssize_t n;
+ char input[1024], *p;
+ union parse_node pt[1024];
+ int e;
+
+ p = input;
+ l = LEN(input);
+
+ while (l > 0 && (n = read(STDIN_FILENO, p, l))) {
+ if (n < 0) {
+ if (errno == EINTR) continue;
+ else break;
+ }
+ p += n;
+ l -= n;
+ }
+
+ if (n < 0)
+ err(1, "error reading input");
+ else if (l == 0 && n > 0)
+ errx(1, "input is too big (%zu is max accepted)", LEN(input));
+
+ inlen = p - input;
+
+ if ((e = parse_respln(input, inlen, pt, LEN(pt), 1024)))
+ errx(1, "error parsing input: %s", perr[e]);
+
+ ptprint(pt, 0);
+ return 0;
+}
+
+union parse_node *
+ptnext(union parse_node *n)
+{
+ if (n->type == PN_INTER)
+ n += n->inter.len;
+
+ return n + 1;
+}
+
+void
+ptprint(union parse_node *n, size_t depth)
+{
+ static char *prefix = " >";
+ size_t l;
+
+ printf("%.*s", (int)depth, prefix);
+
+ switch (n->type) {
+ case PN_INTER:
+ printf("%s\n", prod[n->inter.prod]);
+ for (l = n->inter.len, n++; l > 0; l--, n = ptnext(n))
+ ptprint(n, depth + 1);
+ break;
+ case PN_LIT:
+ printf("%s\n", literals[n->lit.val]);
+ break;
+ case PN_NUM:
+ /* acting a tad careless here... */
+ printf("%zu\n", (size_t)n->num.val);
+ break;
+ case PN_STR:
+ printf("%.*s\n", (int)n->str.len, n->str.tok);
+ break;
+ case PN_QSTR:
+ printf("\"%.*s\"\n", (int)n->str.len, n->str.tok);
+ break;
+ case PN_LSTR:
+ printf("%.*s\n", (int)n->str.len, n->str.tok);
+ break;
+ case PN_OBLSTR:
+ printf("OBLSTR #%zu\n", n->str.iob);
+ break;
+ default:
+ errx(1, "cannot grok parse node of type %d\n", n->type);
+ }
+}