/parser.c
1 /*
2 Be warned! p_* functions bear unconventional call semantics
3 returning 1 on success and 0 otherwise. Specific error code
4 is dispensed to the parse context.
5 */
6
7 #include <errno.h>
8 #include <poll.h>
9 #include <stdarg.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <strings.h>
14 #include <unistd.h>
15 #include <sys/mman.h>
16 #include <sys/stat.h>
17
18 #include "errors.h"
19 #include "parser.h"
20
21 #define LEN(x) (sizeof(x) / sizeof((x)[0]))
22 #define MAX(a, b) ((a) >= (b) ? (a) : (b))
23 #define MIN(a, b) ((a) <= (b) ? (a) : (b))
24
25 #define ASCII_CTL \
26 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
27 "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
28
29 static int timeout = 2 * 60 * 1000;
30 static size_t minstrcap = 1 << 13;
31
32 static struct literal {
33 char *srep;
34 size_t slen;
35 } literals[] = {
36 [IL_7BIT] = { "7BIT", 4 },
37 [IL_8BIT] = { "8BIT", 4 },
38 [IL_ALERT] = { "ALERT", 5 },
39 [IL_APP] = { "APPLICATION", 11 },
40 [IL_APR] = { "Apr", 3 },
41 [IL_ASTERISK] = { "*", 1 },
42 [IL_AUDIO] = { "AUDIO", 5 },
43 [IL_AUG] = { "Aug", 3 },
44 [IL_AUTHEQ] = { "AUTH=", 5 },
45 [IL_B64] = { "BASE64", 6 },
46 [IL_BAD] = { "BAD", 3 },
47 [IL_BADCS] = { "BADCHARSET", 10 },
48 [IL_BIN] = { "BINARY", 6 },
49 [IL_BODY] = { "BODY", 4 },
50 [IL_BSLASH] = { "\\", 1 },
51 [IL_BYE] = { "BYE", 3 },
52 [IL_CAP] = { "CAPABILITY", 10 },
53 [IL_CBRACE] = { "}", 1 },
54 [IL_CBRACK] = { "]", 1 },
55 [IL_COLON] = { ":", 1 },
56 [IL_CPAR] = { ")", 1 },
57 [IL_DEC] = { "Dec", 3 },
58 [IL_DHDR] = { ".HEADER", 7 },
59 [IL_DNOT] = { ".NOT", 4 },
60 [IL_DOT] = { ".", 1 },
61 [IL_DQUOTE] = { "\"", 1 },
62 [IL_DTXT] = { ".TEXT", 5 },
63 [IL_ENVELOPE] = { "ENVELOPE", 8 },
64 [IL_EOL] = { "\r\n", 2 },
65 [IL_EXISTS] = { "EXISTS", 6 },
66 [IL_EXPUNGE] = { "EXPUNGE", 7 },
67 [IL_FEB] = { "Feb", 3 },
68 [IL_FETCH] = { "FETCH", 5 },
69 [IL_FLAGS] = { "FLAGS", 5 },
70 [IL_FLANSWERED] = { "\\Answered", 9 },
71 [IL_FLANY] = { "\\*", 2 },
72 [IL_FLDELETED] = { "\\Deleted", 8 },
73 [IL_FLDRAFT] = { "\\Draft", 6 },
74 [IL_FLFLAGGED] = { "\\Flagged", 8 },
75 [IL_FLMARKED] = { "\\Marked", 7 },
76 [IL_FLNOINFERIORS] = { "\\Noinferiors", 12 },
77 [IL_FLNOSEL] = { "\\Noselect", 9 },
78 [IL_FLRECENT] = { "\\Recent", 7 },
79 [IL_FLSEEN] = { "\\Seen", 5 },
80 [IL_FLUNMARKED] = { "\\Unmarked", 9 },
81 [IL_GT] = { ">", 1 },
82 [IL_HDR] = { "HEADER", 6 },
83 [IL_HDRFIELDS] = { "HEADER.FIELDS", 13 },
84 [IL_IMG] = { "IMAGE", 5 },
85 [IL_INBOX] = { "INBOX", 5 },
86 [IL_INTDATE] = { "INTERNALDATE", 12 },
87 [IL_JAN] = { "Jan", 3 },
88 [IL_JUL] = { "Jul", 3 },
89 [IL_JUN] = { "Jun", 3 },
90 [IL_LIST] = { "LIST", 4 },
91 [IL_LSUB] = { "LSUB", 4 },
92 [IL_LT] = { "<", 1 },
93 [IL_MAR] = { "Mar", 3 },
94 [IL_MAY] = { "May", 3 },
95 [IL_MIME] = { "MIME", 4 },
96 [IL_MINUS] = { "-", 1 },
97 [IL_MSG] = { "MESSAGE", 7 },
98 [IL_MSGS] = { "MESSAGES", 8 },
99 [IL_NIL] = { "NIL", 3 },
100 [IL_NO] = { "NO", 2 },
101 [IL_NOV] = { "Nov", 3 },
102 [IL_OBRACE] = { "{", 1 },
103 [IL_OBRACK] = { "[", 1 },
104 [IL_OCT] = { "Oct", 3 },
105 [IL_OK] = { "OK", 2 },
106 [IL_OPAR] = { "(", 1 },
107 [IL_PARSE] = { "PARSE", 5 },
108 [IL_PERMFL] = { "PERMANENTFLAGS", 14 },
109 [IL_PLUS] = { "+", 1 },
110 [IL_PREAUTH] = { "PREAUTH", 7 },
111 [IL_QPRN] = { "QUOTED-PRINTABLE", 16 },
112 [IL_RECENT] = { "RECENT", 6 },
113 [IL_RFC822] = { "RFC822", 6 },
114 [IL_RFC822SIZE] = { "RFC822.SIZE", 11 },
115 [IL_RO] = { "READ-ONLY", 9 },
116 [IL_RW] = { "READ-WRITE", 10 },
117 [IL_SEARCH] = { "SEARCH", 6 },
118 [IL_SEP] = { "Sep", 3 },
119 [IL_SP] = { " ", 1 },
120 [IL_STATUS] = { "STATUS", 6 },
121 [IL_STRUCT] = { "STRUCTURE", 9 },
122 [IL_TRYC] = { "TRYCREATE", 9 },
123 [IL_TXT] = { "TEXT", 4 },
124 [IL_UID] = { "UID", 3 },
125 [IL_UIDNEXT] = { "UIDNEXT", 7 },
126 [IL_UIDVAL] = { "UIDVALIDITY", 11 },
127 [IL_UNSEEN] = { "UNSEEN", 6 },
128 [IL_VIDEO] = { "VIDEO", 5 },
129 };
130
131 static const char astr_specials[] = ASCII_CTL " \"%()*\\{\x7f";
132
133 static const char atom_specials[] = ASCII_CTL " \"%()*\\]{\x7f";
134
135 static const char tag_specials[] = ASCII_CTL " \"%()*+\\{\x7f";
136
137 struct parcur {
138 size_t off;
139 union parnode *pt;
140 };
141
142 struct parctx {
143 int e;
144 int src;
145 char *str;
146 size_t strcap;
147 size_t strlen;
148 size_t stroff;
149 struct parcur cur;
150 union parnode *pt;
151 union parnode *ptend;
152 size_t ptlen;
153 };
154
155 typedef int parfn(struct parctx *);
156
157 static union parnode * par_vseld(union parnode *, va_list);
158 static int cmpchr(const void *, const void *);
159 static int contains(const char *, size_t, char);
160
161 static void par_init(struct parctx *, int,
162 char *, size_t, size_t, size_t, union parnode *, size_t);
163 static int par_fillstr(struct parctx *, size_t);
164
165 static int p_chk(struct parctx *, struct parcur *);
166 static int p_insint(struct parctx *, int, size_t);
167 static int p_inslit(struct parctx *, int);
168 static int p_insnum(struct parctx *, uint32_t);
169 static int p_insstr(struct parctx *, int, size_t, uint32_t);
170 static int p_beg(struct parctx *, struct parcur *, int);
171 static int p_end(struct parctx *, struct parcur *);
172 static int p_rwd(struct parctx *, struct parcur *);
173 static int p_opt(struct parctx *);
174 static int p_list(struct parctx *, parfn *);
175 static int p_listsep(struct parctx *, parfn *, int);
176 static int p_rep(struct parctx *, parfn *);
177 static int p_repchr(struct parctx *, const char *, size_t, int);
178 static int p_2xcombo(struct parctx *, int, parfn *);
179 static int p_3xcombo(struct parctx *, int, int, parfn *);
180 static int p_r3xcombo(struct parctx *, parfn *, int, int);
181 static int p_sss(struct parctx *);
182
183 static int p_addr(struct parctx *);
184 static int p_astr(struct parctx *);
185 static int p_atom(struct parctx *);
186 static int p_authtype(struct parctx *);
187 static int p_badcscode(struct parctx *);
188 static int p_badcsopt(struct parctx *);
189 static int p_base64(struct parctx *);
190 static int p_body(struct parctx *);
191 static int p_body1pt(struct parctx *);
192 static int p_bodybas(struct parctx *);
193 static int p_bodyext(struct parctx *);
194 static int p_bodyf(struct parctx *);
195 static int p_bodyfdes(struct parctx *);
196 static int p_bodyfdsp(struct parctx *);
197 static int p_bodyfenc(struct parctx *);
198 static int p_bodyfid(struct parctx *);
199 static int p_bodyflan(struct parctx *);
200 static int p_bodyflin(struct parctx *);
201 static int p_bodyfloc(struct parctx *);
202 static int p_bodyfmd5(struct parctx *);
203 static int p_bodyfoct(struct parctx *);
204 static int p_bodyfpar(struct parctx *);
205 static int p_bodympt(struct parctx *);
206 static int p_bodymsg(struct parctx *);
207 static int p_bodytxt(struct parctx *);
208 static int p_bodyx1pt(struct parctx *);
209 static int p_bodyxcmn(struct parctx *);
210 static int p_bodyxmpt(struct parctx *);
211 static int p_cap(struct parctx *);
212 static int p_capdata(struct parctx *);
213 static int p_contreq(struct parctx *);
214 static int p_datetime(struct parctx *);
215 static int p_dayfix(struct parctx *);
216 static int p_dig(struct parctx *, size_t);
217 static int p_dquotedchar(struct parctx *);
218 static int p_env(struct parctx *);
219 static int p_envaddr(struct parctx *);
220 static int p_expunge(struct parctx *);
221 static int p_fetch(struct parctx *);
222 static int p_flag(struct parctx *);
223 static int p_flext(struct parctx *);
224 static int p_flfetch(struct parctx *);
225 static int p_flkeyword(struct parctx *);
226 static int p_gencode(struct parctx *);
227 static int p_genctext(struct parctx *);
228 static int p_hdrfname(struct parctx *);
229 static int p_hdrlist(struct parctx *);
230 static int p_lit(struct parctx *, int);
231 static int p_lstr(struct parctx *);
232 static int p_mailbox(struct parctx *);
233 static int p_mat822body(struct parctx *);
234 static int p_matbody(struct parctx *);
235 static int p_matbsect(struct parctx *);
236 static int p_matenv(struct parctx *);
237 static int p_mathdrotxt(struct parctx *);
238 static int p_matintdate(struct parctx *);
239 static int p_matsize(struct parctx *);
240 static int p_matuid(struct parctx *);
241 static int p_mbdata(struct parctx *);
242 static int p_mbexists(struct parctx *);
243 static int p_mbflags(struct parctx *);
244 static int p_mblist(struct parctx *);
245 static int p_mblistdata(struct parctx *);
246 static int p_mblistfl(struct parctx *);
247 static int p_mblistofl(struct parctx *);
248 static int p_mblistosfl(struct parctx *);
249 static int p_mblistsfl(struct parctx *);
250 static int p_mblsub(struct parctx *);
251 static int p_mbrecent(struct parctx *);
252 static int p_mbsearch(struct parctx *);
253 static int p_mbstatus(struct parctx *);
254 static int p_medbas(struct parctx *);
255 static int p_medmsg(struct parctx *);
256 static int p_medsubt(struct parctx *);
257 static int p_medtxt(struct parctx *);
258 static int p_month(struct parctx *);
259 static int p_msgdata(struct parctx *);
260 static int p_msgatt(struct parctx *);
261 static int p_msgattdyn(struct parctx *);
262 static int p_msgattstat(struct parctx *);
263 static int p_nstr(struct parctx *);
264 static int p_num(struct parctx *);
265 static int p_nznum(struct parctx *);
266 static int p_permfl(struct parctx *);
267 static int p_permflcode(struct parctx *);
268 static int p_qchar(struct parctx *);
269 static int p_qchars(struct parctx *);
270 static int p_qstr(struct parctx *);
271 static int p_respauth(struct parctx *);
272 static int p_respbye(struct parctx *);
273 static int p_respdata(struct parctx *);
274 static int p_respln(struct parctx *);
275 static int p_respstate(struct parctx *);
276 static int p_resptext(struct parctx *);
277 static int p_resptextcode(struct parctx *);
278 static int p_secmsgtxt(struct parctx *);
279 static int p_secpt(struct parctx *);
280 static int p_secspec(struct parctx *);
281 static int p_section(struct parctx *);
282 static int p_sectxt(struct parctx *);
283 static int p_statt(struct parctx *);
284 static int p_stattrec(struct parctx *);
285 static int p_str(struct parctx *);
286 static int p_tag(struct parctx *);
287 static int p_taggedresp(struct parctx *);
288 static int p_text(struct parctx *);
289 static int p_time(struct parctx *);
290 static int p_uid(struct parctx *);
291 static int p_uidncode(struct parctx *);
292 static int p_uidvcode(struct parctx *);
293 static int p_unseencode(struct parctx *);
294 static int p_year(struct parctx *);
295 static int p_zone(struct parctx *);
296
297 static int p_cpar(struct parctx *);
298 static int p_dquote(struct parctx *);
299 static int p_opar(struct parctx *);
300 static int p_sp(struct parctx *);
301
302 int
303 par_parseln(int src, char **str, size_t *strcap, size_t *strlen, size_t *stroff,
304 union parnode *pt, size_t ptlen)
305 {
306 struct parctx p;
307
308 par_init(&p, src, *str, *strcap, *strlen, *stroff, pt, ptlen);
309 p_respln(&p);
310 *str = p.str;
311 *strcap = p.strcap;
312 *strlen = p.strlen;
313 *stroff = p.cur.off;
314 return p.e;
315 }
316
317 union parnode *
318 par_nn(union parnode *n)
319 {
320 if (n->type == PN_INTER)
321 n += n->inter.len;
322
323 return n + 1;
324 }
325
326 union parnode *
327 par_sel(union parnode *n, ...)
328 {
329 int prod;
330 va_list ap;
331
332 va_start(ap, n);
333 prod = va_arg(ap, int);
334 if (prod != -1 && n->type == PN_INTER && n->inter.prod == prod) {
335 n = par_vseld(n, ap);
336 } else {
337 n = 0;
338 }
339 va_end(ap);
340 return n;
341 }
342
343 union parnode *
344 par_seld(union parnode *n, ...)
345 {
346 va_list ap;
347
348 va_start(ap, n);
349 n = par_vseld(n, ap);
350 va_end(ap);
351 return n;
352 }
353
354 union parnode *
355 par_vseld(union parnode *n, va_list ap)
356 {
357 int prod;
358 union parnode *end;
359
360 if (n->type == PN_INTER) {
361 end = n + n->inter.len + 1;
362 } else {
363 n = 0;
364 goto exit;
365 }
366
367 while ((prod = va_arg(ap, int)) != -1) {
368 for (n++; n < end; n = par_nn(n)) {
369 if (n->type == PN_INTER && n->inter.prod == prod)
370 break;
371 }
372 if (n == end) {
373 n = 0;
374 break;
375 }
376 }
377 exit:
378 return n;
379 }
380
381 int
382 cmpchr(const void *a, const void *b)
383 {
384 return *(char *)a - *(char *)b;
385 }
386
387 int
388 contains(const char *s, size_t slen, char c)
389 {
390 return bsearch(&c, s, slen, sizeof(char), cmpchr) != 0;
391 }
392
393 void
394 par_init(struct parctx *p, int src, char *str, size_t strcap, size_t strlen,
395 size_t stroff, union parnode *pt, size_t ptlen)
396 {
397 bzero(p, sizeof(*p));
398 p->src = src;
399 p->str = str;
400 p->strcap = strcap;
401 p->strlen = strlen;
402 p->stroff = stroff;
403 p->cur.off = stroff;
404 p->cur.pt = pt;
405 p->pt = pt;
406 p->ptend = pt + ptlen;
407 p->ptlen = ptlen;
408 }
409
410 int
411 par_fillstr(struct parctx *p, size_t len)
412 {
413 char *newstr;
414 struct pollfd pd;
415 int ready;
416 ssize_t n;
417
418 if (len <= p->strlen) {
419 p->e = TE_OK;
420 goto exit;
421 }
422 if (len > p->strcap) {
423 p->strcap = MAX(minstrcap, p->strcap);
424 do {
425 p->strcap *= 2;
426 } while (len > p->strcap);
427 newstr = realloc(p->str, p->strcap);
428 if (newstr == 0) {
429 goto emem;
430 }
431 p->str = newstr;
432 }
433
434 pd.fd = p->src;
435 pd.events = POLLIN | POLLHUP;
436
437 while (len > p->strlen) {
438 ready = poll(&pd, 1, timeout);
439
440 if (ready == -1) goto ein;
441 if (ready == 0) goto eto;
442
443 if (pd.revents & (POLLIN | POLLHUP)) {
444 n = read(pd.fd, p->str + p->strlen, p->strcap - p->strlen);
445 if (n == 0) {
446 goto eof;
447 } else if (n == -1) {
448 if (errno == EINTR || errno == EAGAIN)
449 continue;
450 else goto ein;
451 }
452 p->strlen += n;
453 }
454 }
455
456 exit:
457 return p->e;
458 emem:
459 p->e = TE_NOMEM;
460 goto exit;
461 ein:
462 p->e = TE_IN;
463 goto exit;
464 eto:
465 p->e = TE_TIMEOUT;
466 goto exit;
467 eof:
468 p->e = TE_EOF;
469 goto exit;
470 }
471
472 /*
473 Combinators and misc meta critters
474 */
475
476 int
477 p_chk(struct parctx *p, struct parcur *cp)
478 {
479 *cp = p->cur;
480 return p->e <= TE_PARSE;
481 }
482
483 int
484 p_insint(struct parctx *p, int prod, size_t len)
485 {
486 union parnode *cur;
487
488 cur = p->cur.pt;
489 if (cur == p->ptend) {
490 p->e = TE_PTOFLOW;
491 return 0;
492 }
493 cur->inter.type = PN_INTER;
494 cur->inter.prod = prod;
495 cur->inter.len = len;
496 p->cur.pt++;
497 return 1;
498 }
499
500 int
501 p_inslit(struct parctx *p, int val)
502 {
503 union parnode *cur;
504
505 cur = p->cur.pt;
506 if (cur == p->ptend) {
507 p->e = TE_PTOFLOW;
508 return 0;
509 }
510 cur->lit.type = PN_LIT;
511 cur->lit.val = val;
512 p->cur.pt++;
513 return 1;
514 }
515
516 int
517 p_insnum(struct parctx *p, uint32_t val)
518 {
519 union parnode *cur;
520
521 cur = p->cur.pt;
522 if (cur == p->ptend) {
523 p->e = TE_PTOFLOW;
524 return 0;
525 }
526 cur->lit.type = PN_NUM;
527 cur->lit.val = val;
528 p->cur.pt++;
529 return 1;
530 }
531
532 int
533 p_insstr(struct parctx *p, int type, size_t off, uint32_t len)
534 {
535 union parnode *cur;
536
537 cur = p->cur.pt;
538 if (cur == p->ptend) {
539 p->e = TE_PTOFLOW;
540 return 0;
541 }
542 cur->str.type = type;
543 cur->str.off = off;
544 cur->str.len = len;
545 p->cur.pt++;
546 return 1;
547 }
548
549 int
550 p_beg(struct parctx *p, struct parcur *beg, int prod)
551 {
552 return p_chk(p, beg) && p_insint(p, prod, 0);
553 }
554
555 int
556 p_end(struct parctx *p, struct parcur *beg)
557 {
558 beg->pt->inter.len = p->cur.pt - beg->pt - 1;
559 return 1;
560 }
561
562 int
563 p_rwd(struct parctx *p, struct parcur *cp)
564 {
565 p->cur = *cp;
566 if (!p->e)
567 p->e = TE_PARSE;
568 return 0;
569 }
570
571 int
572 p_opt(struct parctx *p)
573 {
574 if (p->e == TE_PARSE)
575 p->e = TE_OK;
576 return !p->e;
577 }
578
579 /* prod *(SP prod) */
580 int
581 p_list(struct parctx *p, parfn *prod)
582 {
583 int res;
584
585 res = (p->e <= TE_PARSE) && prod(p);
586 while (res && p_2xcombo(p, IL_SP, prod))
587 ;
588 return res && p_opt(p);
589 }
590
591 int
592 p_listsep(struct parctx *p, parfn *prod, int sep)
593 {
594 int res;
595
596 res = (p->e <= TE_PARSE) && prod(p);
597 while (res && p_2xcombo(p, sep, prod))
598 ;
599 return res && p_opt(p);
600 }
601
602 /* 1*prod */
603 int
604 p_rep(struct parctx *p, parfn *prod)
605 {
606 int res;
607
608 res = (p->e <= TE_PARSE) && prod(p);
609 while (res && prod(p))
610 ;
611 return res && p_opt(p);
612 }
613
614 /* 1*<any char but those in `except'> */
615 int
616 p_repchr(struct parctx *p, const char *except, size_t elen, int strtype)
617 {
618 size_t pr;
619 char *prp;
620 size_t len;
621
622 if (p->e > TE_PARSE)
623 goto exit;
624
625 p->e = TE_OK;
626 pr = p->cur.off;
627
628 while (par_fillstr(p, pr + 1) == TE_OK) {
629 for (prp = p->str + pr; pr < p->strlen; ++pr, ++prp) {
630 if (contains(except, elen, *prp))
631 goto stop;
632 }
633 }
634 stop:
635 len = pr - p->cur.off;
636 if (p->e == TE_EOF && len)
637 p->e = TE_OK;
638
639 if (p->e) goto exit;
640 if (!len) goto eparse;
641 if (len > UINT32_MAX) goto exl;
642 if (!p_insstr(p, strtype, p->cur.off, len)) goto exit;
643
644 p->cur.off = pr;
645 exit:
646 return p->e == TE_OK;
647 eparse:
648 p->e = TE_PARSE;
649 goto exit;
650 exl:
651 p->e = TE_XLSTR;
652 goto exit;
653 }
654
655 int
656 p_2xcombo(struct parctx *p, int lit, parfn *prod)
657 {
658 struct parcur b;
659
660 return p_chk(p, &b) && p_lit(p, lit) && prod(p) || p_rwd(p, &b);
661 }
662
663 int
664 p_3xcombo(struct parctx *p, int lit1, int lit2, parfn *prod)
665 {
666 struct parcur b;
667
668 return p_chk(p, &b) && p_lit(p, lit1) &&
669 p_lit(p, lit2) && prod(p) || p_rwd(p, &b);
670 }
671
672 int
673 p_r3xcombo(struct parctx *p, parfn *prod, int lit1, int lit2)
674 {
675 struct parcur b;
676
677 return p_chk(p, &b) && prod(p) && p_lit(p, lit1) &&
678 p_lit(p, lit2) || p_rwd(p, &b);
679 }
680
681 int
682 p_sss(struct parctx *p)
683 {
684 struct parcur b;
685
686 return p_chk(p, &b) && p_str(p) && p_sp(p) && p_str(p) ||
687 p_rwd(p, &b);
688 }
689
690 /*
691 IMAP parsers
692 */
693
694 int
695 p_addr(struct parctx *p)
696 {
697 struct parcur b;
698
699 return p_chk(p, &b) && p_opar(p) && p_nstr(p) && p_sp(p) &&
700 p_nstr(p) && p_sp(p) && p_nstr(p) && p_sp(p) &&
701 p_nstr(p) && p_cpar(p) || p_rwd(p, &b);
702 }
703
704 int
705 p_astr(struct parctx *p)
706 {
707 struct parcur b;
708
709 return p_chk(p, &b) &&
710 (p_repchr(p, astr_specials, LEN(astr_specials), PN_STR) ||
711 p_str(p)) || p_rwd(p, &b);
712 }
713
714 int
715 p_atom(struct parctx *p)
716 {
717 struct parcur b;
718
719 return p_beg(p, &b, IP_ATOM) &&
720 p_repchr(p, atom_specials, LEN(atom_specials), PN_STR) &&
721 p_end(p, &b) || p_rwd(p, &b);
722 }
723
724 int
725 p_authtype(struct parctx *p)
726 {
727 return p_atom(p);
728 }
729
730 int
731 p_badcscode(struct parctx *p)
732 {
733 struct parcur b;
734
735 return p_chk(p, &b) && p_lit(p, IL_BADCS) &&
736 (p_badcsopt(p) || p_opt(p)) || p_rwd(p, &b);
737 }
738
739 int
740 p_badcsopt(struct parctx *p)
741 {
742 struct parcur b;
743
744 return p_chk(p, &b) && p_sp(p) && p_opar(p) &&
745 p_list(p, p_astr) && p_cpar(p) || p_rwd(p, &b);
746 }
747
748 int
749 p_base64(struct parctx *p)
750 {
751 /* brush 6 bit encoding off yet */
752 if (!p->e)
753 p->e = TE_PARSE;
754 return 0;
755 }
756
757 int
758 p_body(struct parctx *p)
759 {
760 struct parcur b;
761
762 return p_chk(p, &b) && p_opar(p) && (p_body1pt(p) ||
763 p_bodympt(p)) && p_cpar(p) || p_rwd(p, &b);
764 }
765
766 int
767 p_body1pt(struct parctx *p)
768 {
769 struct parcur b, o;
770
771 return p_chk(p, &b) &&
772 (p_bodybas(p) || p_bodymsg(p) || p_bodytxt(p)) &&
773 (p_chk(p, &o) && p_sp(p) && p_bodyx1pt(p) ||
774 p_rwd(p, &o) || p_opt(p)) || p_rwd(p, &b);
775 }
776
777 int
778 p_bodybas(struct parctx *p)
779 {
780 struct parcur b;
781
782 return p_chk(p, &b) && p_medbas(p) && p_sp(p) &&
783 p_bodyf(p) || p_rwd(p, &b);
784 }
785
786 int
787 p_bodyext(struct parctx *p)
788 {
789 struct parcur b;
790
791 return p_chk(p, &b) && p_nstr(p) || p_num(p) ||
792 (p_opar(p) && p_list(p, p_bodyext) && p_cpar(p)) ||
793 p_rwd(p, &b);
794 }
795
796 int
797 p_bodyf(struct parctx *p)
798 {
799 struct parcur b;
800
801 return p_chk(p, &b) && p_bodyfpar(p) && p_sp(p) &&
802 p_bodyfid(p) && p_sp(p) && p_bodyfdes(p) && p_sp(p) &&
803 p_bodyfenc(p) && p_sp(p) && p_bodyfoct(p) || p_rwd(p, &b);
804 }
805
806 int
807 p_bodyfdes(struct parctx *p)
808 {
809 return p_nstr(p);
810 }
811
812 int
813 p_bodyfdsp(struct parctx *p)
814 {
815 struct parcur b;
816
817 return p_chk(p, &b) && (p_opar(p) && p_str(p) && p_sp(p) &&
818 p_bodyfpar(p) && p_cpar(p) || p_rwd(p, &b)) || p_lit(p, IL_NIL);
819 }
820
821 int
822 p_bodyfenc(struct parctx *p)
823 {
824 struct parcur b;
825
826 return p_chk(p, &b) && (p_dquote(p) && (p_lit(p, IL_7BIT) ||
827 p_lit(p, IL_8BIT) || p_lit(p, IL_BIN) || p_lit(p, IL_B64) ||
828 p_lit(p, IL_QPRN)) && p_dquote(p) || p_rwd(p, &b)) ||
829 p_str(p);
830 }
831
832 int
833 p_bodyfid(struct parctx *p)
834 {
835 return p_nstr(p);
836 }
837
838 int
839 p_bodyflan(struct parctx *p)
840 {
841 struct parcur b;
842
843 return p_chk(p, &b) && p_nstr(p) || (p_opar(p) &&
844 p_list(p, p_str) && p_cpar(p) || p_rwd(p, &b));
845 }
846
847 int
848 p_bodyflin(struct parctx *p)
849 {
850 return p_num(p);
851 }
852
853 int
854 p_bodyfloc(struct parctx *p)
855 {
856 return p_nstr(p);
857 }
858
859 int
860 p_bodyfmd5(struct parctx *p)
861 {
862 return p_nstr(p);
863 }
864
865 int
866 p_bodyfoct(struct parctx *p)
867 {
868 return p_num(p);
869 }
870
871 int
872 p_bodyfpar(struct parctx *p)
873 {
874 struct parcur b;
875
876 return p_chk(p, &b) && (p_opar(p) && p_list(p, p_sss) &&
877 p_cpar(p) || p_rwd(p, &b)) || p_lit(p, IL_NIL);
878 }
879
880 int
881 p_bodympt(struct parctx *p)
882 {
883 struct parcur b, o;
884
885 return p_chk(p, &b) && p_rep(p, p_body) && p_sp(p) &&
886 p_medsubt(p) && (p_chk(p, &o) && p_sp(p) && p_bodyxmpt(p) ||
887 p_rwd(p, &o) || p_opt(p)) || p_rwd(p, &b);
888 }
889
890 int
891 p_bodymsg(struct parctx *p)
892 {
893 struct parcur b;
894
895 return p_chk(p, &b) && p_medmsg(p) && p_sp(p) && p_bodyf(p) &&
896 p_sp(p) && p_env(p) && p_sp(p) && p_body(p) && p_sp(p) &&
897 p_bodyflin(p) || p_rwd(p, &b);
898 }
899
900 int
901 p_bodytxt(struct parctx *p)
902 {
903 struct parcur b;
904
905 return p_chk(p, &b) && p_medtxt(p) && p_sp(p) && p_bodyf(p) &&
906 p_sp(p) && p_bodyflin(p) || p_rwd(p, &b);
907 }
908
909 int
910 p_bodyx1pt(struct parctx *p)
911 {
912 struct parcur b;
913
914 return p_chk(p, &b) && p_bodyfmd5(p) &&
915 p_bodyxcmn(p) || p_rwd(p, &b);
916 }
917
918 /* TODO: this one's extra gross, prob needs a good factoring */
919 int
920 p_bodyxcmn(struct parctx *p)
921 {
922 struct parcur o1, o2, o3, o4;
923
924 return p_chk(p, &o1) && p_sp(p) && p_bodyfdsp(p) &&
925 (p_chk(p, &o2) && p_sp(p) && p_bodyflan(p) &&
926 (p_chk(p, &o3) && p_sp(p) && p_bodyfloc(p) &&
927 (p_chk(p, &o4) && p_sp(p) && p_list(p, p_bodyext) ||
928 p_rwd(p, &o4) || p_opt(p)) ||
929 p_rwd(p, &o3) || p_opt(p)) ||
930 p_rwd(p, &o2) || p_opt(p)) ||
931 p_rwd(p, &o1) || p_opt(p);
932 }
933
934 int
935 p_bodyxmpt(struct parctx *p)
936 {
937 struct parcur b;
938
939 return p_chk(p, &b) && p_bodyfpar(p) &&
940 p_bodyxcmn(p) || p_rwd(p, &b);
941 }
942
943 int
944 p_cap(struct parctx *p)
945 {
946 struct parcur b, c;
947
948 return p_chk(p, &b) && p_sp(p) && p_beg(p, &c, IP_CAP) &&
949 (p_2xcombo(p, IL_AUTHEQ, p_authtype) || p_atom(p)) &&
950 p_end(p, &c) || p_rwd(p, &b);
951 }
952
953 int
954 p_capdata(struct parctx *p)
955 {
956 struct parcur b;
957
958 return p_beg(p, &b, IP_CAPDATA) && (p_lit(p, IL_CAP) &&
959 p_rep(p, p_cap) || p_rwd(p, &b)) && p_end(p, &b);
960 }
961
962 int
963 p_contreq(struct parctx *p)
964 {
965 struct parcur b;
966
967 return p_beg(p, &b, IP_CONTREQ) && (p_lit(p, IL_PLUS) && p_sp(p) &&
968 (p_resptext(p) || p_base64(p)) && p_lit(p, IL_EOL) ||
969 p_rwd(p, &b)) && p_end(p, &b);
970 }
971
972 int
973 p_datetime(struct parctx *p)
974 {
975 struct parcur b;
976
977 return p_chk(p, &b) && p_dquote(p) && p_dayfix(p) &&
978 p_lit(p, IL_MINUS) && p_month(p) && p_lit(p, IL_MINUS) &&
979 p_year(p) && p_sp(p) && p_time(p) && p_sp(p) && p_zone(p) &&
980 p_dquote(p) || p_rwd(p, &b);
981 }
982
983 int
984 p_dayfix(struct parctx *p)
985 {
986 struct parcur b;
987
988 return p_chk(p, &b) && p_sp(p) && p_dig(p, 1) ||
989 p_rwd(p, &b) || p_dig(p, 2);
990 }
991
992 int
993 p_dig(struct parctx *p, size_t count)
994 {
995 size_t pr;
996 char *prp;
997 size_t len;
998 uint32_t n, prev;
999 size_t d;
1000
1001 if (p->e > TE_PARSE)
1002 goto exit;
1003
1004 p->e = TE_OK;
1005 pr = p->cur.off;
1006 n = prev = 0;
1007 d = count == SIZE_MAX ? 0 : 1;
1008
1009 while (par_fillstr(p, pr + 1) == TE_OK) {
1010 for (prp = p->str + pr; pr < p->strlen; ++pr, ++prp) {
1011 if (count == 0 || *prp < '0' || *prp > '9')
1012 goto stop;
1013 prev = n;
1014 n = UINT32_MAX & (10 * n + (*prp - '0'));
1015 if (prev > n) {
1016 p->e = TE_PARSE;
1017 goto stop;
1018 }
1019 count -= d;
1020 }
1021 }
1022 stop:
1023 len = pr - p->cur.off;
1024 if (p->e == TE_EOF && len)
1025 p->e = TE_OK;
1026
1027 if (p->e) goto exit;
1028 if (!len) goto eparse;
1029 if (!p_insnum(p, n)) goto exit;
1030
1031 p->cur.off = pr;
1032 exit:
1033 return p->e == TE_OK;
1034 eparse:
1035 p->e = TE_PARSE;
1036 goto exit;
1037 }
1038
1039 int
1040 p_dquotedchar(struct parctx *p)
1041 {
1042 struct parcur b;
1043
1044 return p_chk(p, &b) && p_dquote(p) && p_qchar(p) && p_dquote(p) ||
1045 p_rwd(p, &b);
1046 }
1047
1048 int
1049 p_env(struct parctx *p)
1050 {
1051 struct parcur b;
1052
1053 return p_chk(p, &b) && p_opar(p) && p_nstr(p) && p_sp(p) &&
1054 p_nstr(p) && p_sp(p) && p_envaddr(p) && p_sp(p) &&
1055 p_envaddr(p) && p_sp(p) && p_envaddr(p) && p_sp(p) &&
1056 p_envaddr(p) && p_sp(p) && p_envaddr(p) && p_sp(p) &&
1057 p_envaddr(p) && p_sp(p) && p_nstr(p) && p_sp(p) &&
1058 p_nstr(p) && p_cpar(p) || p_rwd(p, &b);
1059 }
1060
1061 int
1062 p_envaddr(struct parctx *p)
1063 {
1064 struct parcur b;
1065
1066 return p_chk(p, &b) && p_opar(p) && p_rep(p, p_addr) && p_cpar(p) ||
1067 p_rwd(p, &b) || p_lit(p, IL_NIL);
1068 }
1069
1070 int
1071 p_expunge(struct parctx *p)
1072 {
1073 struct parcur b;
1074
1075 return p_beg(p, &b, IP_EXPUNGE) && p_nznum(p) && p_sp(p) &&
1076 p_lit(p, IL_EXPUNGE) && p_end(p, &b) || p_rwd(p, &b);
1077 }
1078
1079 int
1080 p_fetch(struct parctx *p)
1081 {
1082 struct parcur b;
1083
1084 return p_beg(p, &b, IP_FETCH) && p_nznum(p) && p_sp(p) &&
1085 p_lit(p, IL_FETCH) && p_sp(p) && p_opar(p) &&
1086 p_list(p, p_msgatt) && p_cpar(p) && p_end(p, &b) ||
1087 p_rwd(p, &b);
1088 }
1089
1090 int
1091 p_flag(struct parctx *p)
1092 {
1093 return p_lit(p, IL_FLANSWERED) || p_lit(p, IL_FLFLAGGED) ||
1094 p_lit(p, IL_FLDELETED) || p_lit(p, IL_FLSEEN) ||
1095 p_lit(p, IL_FLDRAFT) || p_flkeyword(p) ||
1096 p_flext(p);
1097 }
1098
1099 int
1100 p_flext(struct parctx *p)
1101 {
1102 struct parcur b;
1103
1104 return p_chk(p, &b) && p_lit(p, IL_BSLASH) &&
1105 p_atom(p) || p_rwd(p, &b);
1106 }
1107
1108 int
1109 p_flfetch(struct parctx *p)
1110 {
1111 return p_flag(p) || p_lit(p, IL_FLRECENT);
1112 }
1113
1114 int
1115 p_flkeyword(struct parctx *p)
1116 {
1117 return p_atom(p);
1118 }
1119
1120 int
1121 p_gencode(struct parctx *p)
1122 {
1123 struct parcur opt;
1124
1125 return p_atom(p) && (p_chk(p, &opt) &&
1126 p_sp(p) && p_genctext(p) ||
1127 p_rwd(p, &opt) || p_opt(p));
1128 }
1129
1130 int
1131 p_genctext(struct parctx *p)
1132 {
1133 size_t pr;
1134 char *prp;
1135 size_t len;
1136
1137 if (p->e > TE_PARSE)
1138 goto exit;
1139
1140 p->e = TE_OK;
1141 pr = p->cur.off;
1142
1143 while (par_fillstr(p, pr + 1) == TE_OK) {
1144 for (prp = p->str + pr; pr < p->strlen; ++pr, ++prp) {
1145 if (*prp == 0 || *prp > '\x7f' || *prp == ']' ||
1146 *prp == '\r' || *prp == '\n')
1147 goto stop;
1148 }
1149 }
1150 stop:
1151 len = pr - p->cur.off;
1152 if (p->e == TE_EOF && len)
1153 p->e = TE_OK;
1154
1155 if (p->e) goto exit;
1156 if (!len) goto eparse;
1157 if (len > UINT32_MAX) goto exl;
1158 if (!p_insstr(p, PN_STR, p->cur.off, len)) goto exit;
1159
1160 p->cur.off = pr;
1161 exit:
1162 return p->e == TE_OK;
1163 eparse:
1164 p->e = TE_PARSE;
1165 goto exit;
1166 exl:
1167 p->e = TE_XLSTR;
1168 goto exit;
1169 }
1170
1171 int
1172 p_hdrfname(struct parctx *p)
1173 {
1174 return p_astr(p);
1175 }
1176
1177 int
1178 p_hdrlist(struct parctx *p)
1179 {
1180 struct parcur b;
1181
1182 return p_chk(p, &b) && p_opar(p) && p_list(p, p_hdrfname) &&
1183 p_cpar(p) || p_rwd(p, &b);
1184 }
1185
1186 int
1187 p_lit(struct parctx *p, int val)
1188 {
1189 struct literal *lit;
1190
1191 if (p->e > TE_PARSE)
1192 goto exit;
1193
1194 p->e = TE_OK;
1195 lit = literals + val;
1196
1197 if (par_fillstr(p, p->cur.off + lit->slen) != TE_OK)
1198 goto exit;
1199 if (strncasecmp(p->str + p->cur.off, lit->srep, lit->slen) != 0)
1200 goto eparse;
1201
1202 if (p_inslit(p, val))
1203 p->cur.off += lit->slen;
1204 exit:
1205 return p->e == TE_OK;
1206 eparse:
1207 p->e = TE_PARSE;
1208 goto exit;
1209 }
1210
1211 int
1212 p_lstr(struct parctx *p)
1213 {
1214 int prefix;
1215 size_t len;
1216 struct parcur b, n;
1217
1218 prefix = p_chk(p, &b) && p_lit(p, IL_OBRACE) &&
1219 p_chk(p, &n) && p_num(p) && p_lit(p, IL_CBRACE) &&
1220 p_lit(p, IL_EOL) || p_rwd(p, &b);
1221
1222 if (!prefix)
1223 goto exit;
1224
1225 p->e = TE_OK;
1226 len = n.pt->num.val;
1227 p->cur.pt = b.pt;
1228
1229 if (len > UINT32_MAX) goto exl;
1230 if (par_fillstr(p, p->cur.off + len) != TE_OK)
1231 goto exit;
1232 if (!p_insstr(p, PN_LSTR, p->cur.off, len))
1233 goto exit;
1234
1235 p->cur.off += len;
1236 exit:
1237 return p->e == TE_OK;
1238 exl:
1239 p->e = TE_XLSTR;
1240 goto exit;
1241 }
1242
1243 int
1244 p_mailbox(struct parctx *p)
1245 {
1246 return p_lit(p, IL_INBOX) || p_astr(p);
1247 }
1248
1249 int
1250 p_mat822body(struct parctx *p)
1251 {
1252 struct parcur b;
1253
1254 return p_beg(p, &b, IP_822BODY) && p_lit(p, IL_RFC822) &&
1255 p_sp(p) && p_nstr(p) && p_end(p, &b) || p_rwd(p, &b);
1256 }
1257
1258 int
1259 p_matbody(struct parctx *p)
1260 {
1261 struct parcur b;
1262
1263 return p_chk(p, &b) && p_lit(p, IL_BODY) &&
1264 (p_lit(p, IL_STRUCT) || p_opt(p)) && p_sp(p) &&
1265 p_body(p) || p_rwd(p, &b);
1266 }
1267
1268 int
1269 p_matbsect(struct parctx *p)
1270 {
1271 struct parcur b, o;
1272
1273 return p_chk(p, &b) && p_lit(p, IL_BODY) && p_section(p) &&
1274 (p_chk(p, &o) && p_lit(p, IL_LT) && p_num(p) && p_lit(p, IL_GT) ||
1275 p_rwd(p, &o) || p_opt(p)) && p_sp(p) && p_nstr(p) || p_rwd(p, &b);
1276 }
1277
1278 int
1279 p_matenv(struct parctx *p)
1280 {
1281 return p_3xcombo(p, IL_ENVELOPE, IL_SP, p_env);
1282 }
1283
1284 int
1285 p_mathdrotxt(struct parctx *p)
1286 {
1287 struct parcur b;
1288
1289 return p_chk(p, &b) && p_lit(p, IL_RFC822) &&
1290 (p_lit(p, IL_DHDR) || p_lit(p, IL_DTXT)) && p_sp(p) &&
1291 p_nstr(p) || p_rwd(p, &b);
1292 }
1293
1294 int
1295 p_matintdate(struct parctx *p)
1296 {
1297 return p_3xcombo(p, IL_INTDATE, IL_SP, p_datetime);
1298 }
1299
1300 int
1301 p_matsize(struct parctx *p)
1302 {
1303 return p_3xcombo(p, IL_RFC822SIZE, IL_SP, p_num);
1304 }
1305
1306 int
1307 p_matuid(struct parctx *p)
1308 {
1309 return p_3xcombo(p, IL_UID, IL_SP, p_uid);
1310 }
1311
1312 int
1313 p_mbdata(struct parctx *p)
1314 {
1315 return p_mbflags(p) || p_mblist(p) ||
1316 p_mblsub(p) || p_mbsearch(p) ||
1317 p_mbstatus(p) || p_mbexists(p) ||
1318 p_mbrecent(p);
1319 }
1320
1321 int
1322 p_mbexists(struct parctx *p)
1323 {
1324 struct parcur b;
1325
1326 return p_beg(p, &b, IP_EXISTS) &&
1327 p_r3xcombo(p, p_num, IL_SP, IL_EXISTS) &&
1328 p_end(p, &b) || p_rwd(p, &b);
1329 }
1330
1331 int
1332 p_mbflags(struct parctx *p)
1333 {
1334 struct parcur b;
1335
1336 return p_chk(p, &b) && p_lit(p, IL_FLAGS) &&
1337 p_sp(p) && p_opar(p) &&
1338 (p_list(p, p_flag) || p_opt(p)) &&
1339 p_cpar(p) || p_rwd(p, &b);
1340 }
1341
1342 int
1343 p_mblist(struct parctx *p)
1344 {
1345 struct parcur b;
1346
1347 return p_chk(p, &b) && p_lit(p, IL_LIST) &&
1348 p_sp(p) && p_mblistdata(p) ||
1349 p_rwd(p, &b);
1350 }
1351
1352 int
1353 p_mblistdata(struct parctx *p)
1354 {
1355 struct parcur b;
1356
1357 return p_chk(p, &b) && p_opar(p) &&
1358 (p_list(p, p_mblistfl) || p_opt(p)) &&
1359 p_cpar(p) && p_sp(p) &&
1360 (p_dquotedchar(p) || p_lit(p, IL_NIL)) &&
1361 p_sp(p) && p_mailbox(p) || p_rwd(p, &b);
1362 }
1363
1364 /*
1365 TODO: will 1*(SFL|OFL) with a soundness check afterwards
1366 be simpler and more readable?
1367 */
1368 int
1369 p_mblistfl(struct parctx *p)
1370 {
1371 return p_mblistosfl(p) || p_list(p, p_mblistofl);
1372 }
1373
1374 int
1375 p_mblistofl(struct parctx *p)
1376 {
1377 return p_lit(p, IL_FLNOINFERIORS) || p_flext(p);
1378 }
1379
1380 int
1381 p_mblistosfl(struct parctx *p)
1382 {
1383 int res;
1384 struct parcur b;
1385
1386 res = p_chk(p, &b) && p_list(p, p_mblistofl) &&
1387 p_sp(p) || p_rwd(p, &b) || p_opt(p);
1388
1389 res = res && p_mblistsfl(p);
1390
1391 res = res && (p_chk(p, &b) && p_sp(p) &&
1392 p_list(p, p_mblistofl) || p_rwd(p, &b) || p_opt(p));
1393
1394 return res;
1395 }
1396
1397 int
1398 p_mblistsfl(struct parctx *p)
1399 {
1400 return p_lit(p, IL_FLNOSEL) || p_lit(p, IL_FLMARKED) ||
1401 p_lit(p, IL_FLUNMARKED);
1402 }
1403
1404 int
1405 p_mblsub(struct parctx *p)
1406 {
1407 struct parcur b;
1408
1409 return p_chk(p, &b) && p_lit(p, IL_LSUB) &&
1410 p_sp(p) && p_mblistdata(p) ||
1411 p_rwd(p, &b);
1412 }
1413
1414 int
1415 p_mbrecent(struct parctx *p)
1416 {
1417 return p_r3xcombo(p, p_num, IL_SP, IL_RECENT);
1418 }
1419
1420 int
1421 p_mbsearch(struct parctx *p)
1422 {
1423 struct parcur b, o;
1424
1425 return p_chk(p, &b) && p_lit(p, IL_SEARCH) &&
1426 (p_chk(p, &o) && p_sp(p) &&
1427 p_list(p, p_nznum) || p_rwd(p, &o) || p_opt(p)) ||
1428 p_rwd(p, &b);
1429 }
1430
1431 int
1432 p_mbstatus(struct parctx *p)
1433 {
1434 struct parcur b;
1435
1436 return p_chk(p, &b) && p_lit(p, IL_STATUS) && p_sp(p) &&
1437 p_mailbox(p) && p_sp(p) && p_opar(p) &&
1438 (p_list(p, p_stattrec) || p_opt(p)) && p_cpar(p) ||
1439 p_rwd(p, &b);
1440 }
1441
1442 int
1443 p_medbas(struct parctx *p)
1444 {
1445 struct parcur b;
1446
1447 return p_chk(p, &b) && (p_dquote(p) &&
1448 (p_lit(p, IL_APP) || p_lit(p, IL_AUDIO) || p_lit(p, IL_IMG) ||
1449 p_lit(p, IL_MSG) || p_lit(p, IL_VIDEO)) && p_dquote(p) ||
1450 (p_rwd(p, &b) || p_str(p))) &&
1451 p_sp(p) && p_medsubt(p) || p_rwd(p, &b);
1452 }
1453
1454 int
1455 p_medmsg(struct parctx *p)
1456 {
1457 struct parcur b;
1458
1459 return p_chk(p, &b) &&
1460 p_dquote(p) && p_lit(p, IL_MSG) && p_dquote(p) && p_sp(p) &&
1461 p_dquote(p) && p_lit(p, IL_RFC822) && p_dquote(p) || p_rwd(p, &b);
1462 }
1463
1464 int
1465 p_medsubt(struct parctx *p)
1466 {
1467 return p_str(p);
1468 }
1469
1470 int
1471 p_medtxt(struct parctx *p)
1472 {
1473 struct parcur b;
1474
1475 return p_chk(p, &b) && p_dquote(p) && p_lit(p, IL_TXT) && p_dquote(p) &&
1476 p_sp(p) && p_medsubt(p) || p_rwd(p, &b);
1477 }
1478
1479 int
1480 p_month(struct parctx *p)
1481 {
1482 return p_lit(p, IL_JAN) || p_lit(p, IL_FEB) || p_lit(p, IL_MAR) ||
1483 p_lit(p, IL_APR) || p_lit(p, IL_MAY) || p_lit(p, IL_JUN) ||
1484 p_lit(p, IL_JUL) || p_lit(p, IL_AUG) || p_lit(p, IL_SEP) ||
1485 p_lit(p, IL_OCT) || p_lit(p, IL_NOV) || p_lit(p, IL_DEC);
1486 }
1487
1488 int
1489 p_msgdata(struct parctx *p)
1490 {
1491 return p_expunge(p) || p_fetch(p);
1492 }
1493
1494 int
1495 p_msgatt(struct parctx *p)
1496 {
1497 return p_msgattstat(p) || p_msgattdyn(p);
1498 }
1499
1500 int
1501 p_msgattdyn(struct parctx *p)
1502 {
1503 struct parcur b;
1504
1505 return p_chk(p, &b) && p_lit(p, IL_FLAGS) && p_sp(p) && p_opar(p) &&
1506 (p_list(p, p_flfetch) || p_opt(p)) && p_cpar(p) || p_rwd(p, &b);
1507 }
1508
1509 int
1510 p_msgattstat(struct parctx *p)
1511 {
1512 return p_matenv(p) || p_matintdate(p) || p_mat822body(p) ||
1513 p_mathdrotxt(p) || p_matsize(p) || p_matbody(p) ||
1514 p_matbsect(p) || p_matuid(p);
1515 }
1516
1517 int
1518 p_nstr(struct parctx *p)
1519 {
1520 return p_str(p) || p_lit(p, IL_NIL);
1521 }
1522
1523 int
1524 p_num(struct parctx *p)
1525 {
1526 return p_dig(p, SIZE_MAX);
1527 }
1528
1529 int
1530 p_nznum(struct parctx *p)
1531 {
1532 const char *prp;
1533
1534 if (p->e > TE_PARSE)
1535 goto exit;
1536
1537 p->e = TE_OK;
1538
1539 if (par_fillstr(p, p->cur.off + 1) != TE_OK)
1540 goto exit;
1541
1542 prp = p->str + p->cur.off;
1543 if (*prp < '1' || *prp > '9')
1544 goto eparse;
1545
1546 p_num(p);
1547 exit:
1548 return p->e == TE_OK;
1549 eparse:
1550 p->e = TE_PARSE;
1551 goto exit;
1552 }
1553
1554 int
1555 p_permfl(struct parctx *p)
1556 {
1557 return p_flag(p) || p_lit(p, IL_FLANY);
1558 }
1559
1560 int
1561 p_permflcode(struct parctx *p)
1562 {
1563 struct parcur b;
1564
1565 return p_chk(p, &b) && p_lit(p, IL_PERMFL) &&
1566 p_sp(p) && p_opar(p) &&
1567 (p_list(p, p_permfl) || p_opt(p)) &&
1568 p_cpar(p) || p_rwd(p, &b);
1569 }
1570
1571 int
1572 p_qchar(struct parctx *p)
1573 {
1574 char x, y;
1575 int len;
1576
1577 if (p->e > TE_PARSE)
1578 goto exit;
1579
1580 p->e = TE_OK;
1581
1582 if (par_fillstr(p, p->cur.off + 1) != TE_OK)
1583 goto exit;
1584 x = p->str[p->cur.off];
1585 if (x >= '\1' && x <= '\x7f' && x != '\r' &&
1586 x != '\n' && x != '"' && x != '\\') {
1587 len = 1;
1588 goto ins;
1589 }
1590 if (par_fillstr(p, p->cur.off + 2) != TE_OK)
1591 goto exit;
1592 y = p->str[p->cur.off + 1];
1593 if (x == '\\' && (y == '"' || y == '\\')) {
1594 len = 2;
1595 goto ins;
1596 }
1597 goto eparse;
1598
1599 ins:
1600 if (!p_insstr(p, PN_QSTR, p->cur.off, len))
1601 goto exit;
1602
1603 p->cur.off += len;
1604 exit:
1605 return p->e == TE_OK;
1606 eparse:
1607 p->e = TE_PARSE;
1608 goto exit;
1609 }
1610
1611 int
1612 p_qchars(struct parctx *p)
1613 {
1614 size_t pr;
1615 char *prp;
1616 size_t len;
1617 int esc;
1618
1619 if (p->e > TE_PARSE)
1620 goto exit;
1621
1622 p->e = TE_OK;
1623 pr = p->cur.off;
1624 esc = 0;
1625
1626 while (par_fillstr(p, pr + 1) == TE_OK) {
1627 for (prp = p->str + pr; pr < p->strlen; ++pr, ++prp) {
1628 if (esc) {
1629 if (*prp == '"' || *prp == '\\') {
1630 esc = 0;
1631 } else {
1632 goto eparse;
1633 }
1634 } else if (*prp == '\\') {
1635 esc = 1;
1636 } else if (*prp == 0 || *prp > '\x7f' ||
1637 *prp == '\r' || *prp == '\n' || *prp == '"') {
1638 goto stop;
1639 }
1640 }
1641 }
1642 stop:
1643 len = pr - p->cur.off;
1644 if (p->e == TE_EOF && len)
1645 p->e = TE_OK;
1646
1647 if (p->e) goto exit;
1648 if (!len) goto eparse;
1649 if (len > UINT32_MAX) goto exl;
1650 if (!p_insstr(p, PN_QSTR, p->cur.off, len)) goto exit;
1651
1652 p->cur.off = pr;
1653 exit:
1654 return p->e == TE_OK;
1655 eparse:
1656 p->e = TE_PARSE;
1657 goto exit;
1658 exl:
1659 p->e = TE_XLSTR;
1660 goto exit;
1661 }
1662
1663 int
1664 p_qstr(struct parctx *p)
1665 {
1666 struct parcur b;
1667
1668 return p_chk(p, &b) && p_dquote(p) && (p_qchars(p) || p_opt(p)) &&
1669 p_dquote(p) || p_rwd(p, &b);
1670 }
1671
1672 int
1673 p_respauth(struct parctx *p)
1674 {
1675 struct parcur b;
1676
1677 return p_beg(p, &b, IP_RESPAUTH) && (p_lit(p, IL_PREAUTH) && p_sp(p) &&
1678 p_resptext(p) || p_rwd(p, &b)) && p_end(p, &b);
1679 }
1680
1681 int
1682 p_respbye(struct parctx *p)
1683 {
1684 struct parcur b;
1685
1686 return p_beg(p, &b, IP_RESPBYE) && (p_lit(p, IL_BYE) && p_sp(p) &&
1687 p_resptext(p) || p_rwd(p, &b)) && p_end(p, &b);
1688 }
1689
1690 int
1691 p_respdata(struct parctx *p)
1692 {
1693 struct parcur b;
1694
1695 return p_beg(p, &b, IP_RESPDATA) && (p_lit(p, IL_ASTERISK) && p_sp(p) &&
1696 (p_respauth(p) || p_respstate(p) || p_respbye(p) ||
1697 p_mbdata(p) || p_msgdata(p) || p_capdata(p)) &&
1698 p_lit(p, IL_EOL) || p_rwd(p, &b)) && p_end(p, &b);
1699 }
1700
1701 int
1702 p_respln(struct parctx *p)
1703 {
1704 return p_contreq(p) || p_respdata(p) || p_taggedresp(p);
1705 }
1706
1707 int
1708 p_respstate(struct parctx *p)
1709 {
1710 struct parcur b;
1711
1712 return p_beg(p, &b, IP_RESPSTATE) &&
1713 ((p_lit(p, IL_OK) || p_lit(p, IL_NO) || p_lit(p, IL_BAD)) &&
1714 p_sp(p) && p_resptext(p) || p_rwd(p, &b)) && p_end(p, &b);
1715 }
1716
1717 int
1718 p_resptext(struct parctx *p)
1719 {
1720 int res;
1721 struct parcur b;
1722
1723 res = p_chk(p, &b) && p_lit(p, IL_OBRACK) &&
1724 p_resptextcode(p) && p_lit(p, IL_CBRACK) &&
1725 p_sp(p) || p_rwd(p, &b) || p_opt(p);
1726
1727 return res && p_text(p);
1728 }
1729
1730 int
1731 p_resptextcode(struct parctx *p)
1732 {
1733 struct parcur b;
1734
1735 return p_beg(p, &b, IP_RESPTXTCODE) &&
1736 (p_lit(p, IL_ALERT) || p_badcscode(p) || p_capdata(p) ||
1737 p_lit(p, IL_PARSE) || p_permflcode(p) || p_lit(p, IL_RO) ||
1738 p_lit(p, IL_RW) || p_lit(p, IL_TRYC) || p_uidncode(p) ||
1739 p_uidvcode(p) || p_unseencode(p) || p_gencode(p) ||
1740 p_rwd(p, &b)) && p_end(p, &b);
1741 }
1742
1743 int
1744 p_secmsgtxt(struct parctx *p)
1745 {
1746 struct parcur b;
1747
1748 return p_chk(p, &b) && p_lit(p, IL_HDR) ||
1749 (p_lit(p, IL_HDRFIELDS) && (p_lit(p, IL_DNOT) || p_opt(p)) &&
1750 p_sp(p) && p_hdrlist(p) || p_rwd(p, &b)) || p_lit(p, IL_TXT);
1751 }
1752
1753 int
1754 p_secpt(struct parctx *p)
1755 {
1756 return p_listsep(p, p_nznum, IL_DOT);
1757 }
1758
1759 int
1760 p_secspec(struct parctx *p)
1761 {
1762 struct parcur b, o;
1763
1764 return p_chk(p, &b) && p_secmsgtxt(p) || (p_secpt(p) &&
1765 (p_chk(p, &o) && p_lit(p, IL_DOT) && p_sectxt(p) ||
1766 p_rwd(p, &o) || p_opt(p))) || p_rwd(p, &b);
1767 }
1768
1769 int
1770 p_section(struct parctx *p)
1771 {
1772 struct parcur b;
1773
1774 return p_chk(p, &b) && p_lit(p, IL_OBRACK) &&
1775 (p_secspec(p) || p_opt(p)) &&
1776 p_lit(p, IL_CBRACK) || p_rwd(p, &b);
1777 }
1778
1779 int
1780 p_sectxt(struct parctx *p)
1781 {
1782 return p_secmsgtxt(p) || p_lit(p, IL_MIME);
1783 }
1784
1785 int
1786 p_statt(struct parctx *p)
1787 {
1788 return p_lit(p, IL_MSGS) || p_lit(p, IL_RECENT) ||
1789 p_lit(p, IL_UIDNEXT) || p_lit(p, IL_UIDVAL) ||
1790 p_lit(p, IL_UNSEEN);
1791 }
1792
1793 int
1794 p_stattrec(struct parctx *p)
1795 {
1796 struct parcur b;
1797
1798 return p_chk(p, &b) && p_statt(p) && p_sp(p) &&
1799 p_num(p) || p_rwd(p, &b);
1800 }
1801
1802 int
1803 p_str(struct parctx *p)
1804 {
1805 return p_qstr(p) || p_lstr(p);
1806 }
1807
1808 int
1809 p_tag(struct parctx *p)
1810 {
1811 return p_repchr(p, tag_specials, LEN(tag_specials), PN_STR);
1812 }
1813
1814 int
1815 p_taggedresp(struct parctx *p)
1816 {
1817 struct parcur b;
1818
1819 return p_beg(p, &b, IP_TAGGEDRESP) && (p_tag(p) && p_sp(p) &&
1820 p_respstate(p) && p_lit(p, IL_EOL) || p_rwd(p, &b)) &&
1821 p_end(p, &b);
1822 }
1823
1824 int
1825 p_text(struct parctx *p)
1826 {
1827 size_t pr;
1828 char *prp;
1829 size_t len;
1830
1831 if (p->e > TE_PARSE)
1832 goto exit;
1833
1834 p->e = TE_OK;
1835 pr = p->cur.off;
1836
1837 while (par_fillstr(p, pr + 1) == TE_OK) {
1838 for (prp = p->str + pr; pr < p->strlen; ++pr, ++prp) {
1839 if (*prp == 0 || *prp > '\x7f' ||
1840 *prp == '\r' || *prp == '\n')
1841 goto stop;
1842 }
1843 }
1844 stop:
1845 len = pr - p->cur.off;
1846 if (p->e == TE_EOF && len)
1847 p->e = TE_OK;
1848
1849 if (p->e) goto exit;
1850 if (!len) goto eparse;
1851 if (len > UINT32_MAX) goto exl;
1852 if (!p_insstr(p, PN_STR, p->cur.off, len)) goto exit;
1853
1854 p->cur.off = pr;
1855 exit:
1856 return p->e == TE_OK;
1857 eparse:
1858 p->e = TE_PARSE;
1859 goto exit;
1860 exl:
1861 p->e = TE_XLSTR;
1862 goto exit;
1863 }
1864
1865 int
1866 p_time(struct parctx *p)
1867 {
1868 struct parcur b;
1869
1870 return p_chk(p, &b) && p_dig(p, 2) && p_lit(p, IL_COLON) &&
1871 p_dig(p, 2) && p_lit(p, IL_COLON) && p_dig(p, 2) || p_rwd(p, &b);
1872 }
1873
1874 int
1875 p_uid(struct parctx *p)
1876 {
1877 return p_nznum(p);
1878 }
1879
1880 int
1881 p_uidncode(struct parctx *p)
1882 {
1883 return p_3xcombo(p, IL_UIDNEXT, IL_SP, p_nznum);
1884 }
1885
1886 int
1887 p_uidvcode(struct parctx *p)
1888 {
1889 return p_3xcombo(p, IL_UIDVAL, IL_SP, p_nznum);
1890 }
1891
1892 int
1893 p_unseencode(struct parctx *p)
1894 {
1895 return p_3xcombo(p, IL_UNSEEN, IL_SP, p_nznum);
1896 }
1897
1898 int
1899 p_year(struct parctx *p)
1900 {
1901 return p_dig(p, 4);
1902 }
1903
1904 int
1905 p_zone(struct parctx *p)
1906 {
1907 struct parcur b;
1908
1909 return p_chk(p, &b) &&
1910 (p_lit(p, IL_PLUS) || p_lit(p, IL_MINUS)) &&
1911 p_dig(p, 4) || p_rwd(p, &b);
1912 }
1913
1914 /* shortcuts for some common literals and means
1915 of imrpoving legibility of bulky productions */
1916
1917 int
1918 p_cpar(struct parctx *p)
1919 {
1920 return p_lit(p, IL_CPAR);
1921 }
1922
1923 int
1924 p_dquote(struct parctx *p)
1925 {
1926 return p_lit(p, IL_DQUOTE);
1927 }
1928
1929 int
1930 p_opar(struct parctx *p)
1931 {
1932 return p_lit(p, IL_OPAR);
1933 }
1934
1935 int
1936 p_sp(struct parctx *p)
1937 {
1938 return p_lit(p, IL_SP);
1939 }