Blob


2 #line 2 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
3 #include "common.h"
4 #include "smtp.h"
5 #include <ctype.h>
7 char *yylp; /* next character to be lex'd */
8 int yydone; /* tell yylex to give up */
9 char *yybuffer; /* first parsed character */
10 char *yyend; /* end of buffer to be parsed */
11 Node *root;
12 Field *firstfield;
13 Field *lastfield;
14 Node *usender;
15 Node *usys;
16 Node *udate;
17 char *startfield, *endfield;
18 int originator;
19 int destination;
20 int date;
21 int received;
22 int messageid;
23 extern int yyerrflag;
24 #ifndef YYMAXDEPTH
25 #define YYMAXDEPTH 150
26 #endif
27 #ifndef YYSTYPE
28 #define YYSTYPE int
29 #endif
30 YYSTYPE yylval;
31 YYSTYPE yyval;
32 #define WORD 57346
33 #define DATE 57347
34 #define RESENT_DATE 57348
35 #define RETURN_PATH 57349
36 #define FROM 57350
37 #define SENDER 57351
38 #define REPLY_TO 57352
39 #define RESENT_FROM 57353
40 #define RESENT_SENDER 57354
41 #define RESENT_REPLY_TO 57355
42 #define SUBJECT 57356
43 #define TO 57357
44 #define CC 57358
45 #define BCC 57359
46 #define RESENT_TO 57360
47 #define RESENT_CC 57361
48 #define RESENT_BCC 57362
49 #define REMOTE 57363
50 #define PRECEDENCE 57364
51 #define MIMEVERSION 57365
52 #define CONTENTTYPE 57366
53 #define MESSAGEID 57367
54 #define RECEIVED 57368
55 #define MAILER 57369
56 #define BADTOKEN 57370
57 #define YYEOFCODE 1
58 #define YYERRCODE 2
60 #line 246 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
63 /*
64 * Initialize the parsing. Done once for each header field.
65 */
66 void
67 yyinit(char *p, int len)
68 {
69 yybuffer = p;
70 yylp = p;
71 yyend = p + len;
72 firstfield = lastfield = 0;
73 received = 0;
74 }
76 /*
77 * keywords identifying header fields we care about
78 */
79 typedef struct Keyword Keyword;
80 struct Keyword {
81 char *rep;
82 int val;
83 };
85 /* field names that we need to recognize */
86 Keyword key[] = {
87 { "date", DATE },
88 { "resent-date", RESENT_DATE },
89 { "return_path", RETURN_PATH },
90 { "from", FROM },
91 { "sender", SENDER },
92 { "reply-to", REPLY_TO },
93 { "resent-from", RESENT_FROM },
94 { "resent-sender", RESENT_SENDER },
95 { "resent-reply-to", RESENT_REPLY_TO },
96 { "to", TO },
97 { "cc", CC },
98 { "bcc", BCC },
99 { "resent-to", RESENT_TO },
100 { "resent-cc", RESENT_CC },
101 { "resent-bcc", RESENT_BCC },
102 { "remote", REMOTE },
103 { "subject", SUBJECT },
104 { "precedence", PRECEDENCE },
105 { "mime-version", MIMEVERSION },
106 { "content-type", CONTENTTYPE },
107 { "message-id", MESSAGEID },
108 { "received", RECEIVED },
109 { "mailer", MAILER },
110 { "who-the-hell-cares", WORD }
111 };
113 /*
114 * Lexical analysis for an rfc822 header field. Continuation lines
115 * are handled in yywhite() when skipping over white space.
117 */
118 int
119 yylex(void)
121 String *t;
122 int quoting;
123 int escaping;
124 char *start;
125 Keyword *kp;
126 int c, d;
128 /* print("lexing\n"); /**/
129 if(yylp >= yyend)
130 return 0;
131 if(yydone)
132 return 0;
134 quoting = escaping = 0;
135 start = yylp;
136 yylval = malloc(sizeof(Node));
137 yylval->white = yylval->s = 0;
138 yylval->next = 0;
139 yylval->addr = 0;
140 yylval->start = yylp;
141 for(t = 0; yylp < yyend; yylp++){
142 c = *yylp & 0xff;
144 /* dump nulls, they can't be in header */
145 if(c == 0)
146 continue;
148 if(escaping) {
149 escaping = 0;
150 } else if(quoting) {
151 switch(c){
152 case '\\':
153 escaping = 1;
154 break;
155 case '\n':
156 d = (*(yylp+1))&0xff;
157 if(d != ' ' && d != '\t'){
158 quoting = 0;
159 yylp--;
160 continue;
162 break;
163 case '"':
164 quoting = 0;
165 break;
167 } else {
168 switch(c){
169 case '\\':
170 escaping = 1;
171 break;
172 case '(':
173 case ' ':
174 case '\t':
175 case '\r':
176 goto out;
177 case '\n':
178 if(yylp == start){
179 yylp++;
180 /* print("lex(c %c)\n", c); /**/
181 yylval->end = yylp;
182 return yylval->c = c;
184 goto out;
185 case '@':
186 case '>':
187 case '<':
188 case ':':
189 case ',':
190 case ';':
191 if(yylp == start){
192 yylp++;
193 yylval->white = yywhite();
194 /* print("lex(c %c)\n", c); /**/
195 yylval->end = yylp;
196 return yylval->c = c;
198 goto out;
199 case '"':
200 quoting = 1;
201 break;
202 default:
203 break;
206 if(t == 0)
207 t = s_new();
208 s_putc(t, c);
210 out:
211 yylval->white = yywhite();
212 if(t) {
213 s_terminate(t);
214 } else /* message begins with white-space! */
215 return yylval->c = '\n';
216 yylval->s = t;
217 for(kp = key; kp->val != WORD; kp++)
218 if(cistrcmp(s_to_c(t), kp->rep)==0)
219 break;
220 /* print("lex(%d) %s\n", kp->val-WORD, s_to_c(t)); /**/
221 yylval->end = yylp;
222 return yylval->c = kp->val;
225 void
226 yyerror(char *x)
228 USED(x);
230 /*fprint(2, "parse err: %s\n", x);/**/
233 /*
234 * parse white space and comments
235 */
236 String *
237 yywhite(void)
239 String *w;
240 int clevel;
241 int c;
242 int escaping;
244 escaping = clevel = 0;
245 for(w = 0; yylp < yyend; yylp++){
246 c = *yylp & 0xff;
248 /* dump nulls, they can't be in header */
249 if(c == 0)
250 continue;
252 if(escaping){
253 escaping = 0;
254 } else if(clevel) {
255 switch(c){
256 case '\n':
257 /*
258 * look for multiline fields
259 */
260 if(*(yylp+1)==' ' || *(yylp+1)=='\t')
261 break;
262 else
263 goto out;
264 case '\\':
265 escaping = 1;
266 break;
267 case '(':
268 clevel++;
269 break;
270 case ')':
271 clevel--;
272 break;
274 } else {
275 switch(c){
276 case '\\':
277 escaping = 1;
278 break;
279 case '(':
280 clevel++;
281 break;
282 case ' ':
283 case '\t':
284 case '\r':
285 break;
286 case '\n':
287 /*
288 * look for multiline fields
289 */
290 if(*(yylp+1)==' ' || *(yylp+1)=='\t')
291 break;
292 else
293 goto out;
294 default:
295 goto out;
298 if(w == 0)
299 w = s_new();
300 s_putc(w, c);
302 out:
303 if(w)
304 s_terminate(w);
305 return w;
308 /*
309 * link two parsed entries together
310 */
311 Node*
312 link2(Node *p1, Node *p2)
314 Node *p;
316 for(p = p1; p->next; p = p->next)
318 p->next = p2;
319 return p1;
322 /*
323 * link three parsed entries together
324 */
325 Node*
326 link3(Node *p1, Node *p2, Node *p3)
328 Node *p;
330 for(p = p2; p->next; p = p->next)
332 p->next = p3;
334 for(p = p1; p->next; p = p->next)
336 p->next = p2;
338 return p1;
341 /*
342 * make a:b, move all white space after both
343 */
344 Node*
345 colon(Node *p1, Node *p2)
347 if(p1->white){
348 if(p2->white)
349 s_append(p1->white, s_to_c(p2->white));
350 } else {
351 p1->white = p2->white;
352 p2->white = 0;
355 s_append(p1->s, ":");
356 if(p2->s)
357 s_append(p1->s, s_to_c(p2->s));
359 if(p1->end < p2->end)
360 p1->end = p2->end;
361 freenode(p2);
362 return p1;
365 /*
366 * concatenate two fields, move all white space after both
367 */
368 Node*
369 concat(Node *p1, Node *p2)
371 char buf[2];
373 if(p1->white){
374 if(p2->white)
375 s_append(p1->white, s_to_c(p2->white));
376 } else {
377 p1->white = p2->white;
378 p2->white = 0;
381 if(p1->s == nil){
382 buf[0] = p1->c;
383 buf[1] = 0;
384 p1->s = s_new();
385 s_append(p1->s, buf);
388 if(p2->s)
389 s_append(p1->s, s_to_c(p2->s));
390 else {
391 buf[0] = p2->c;
392 buf[1] = 0;
393 s_append(p1->s, buf);
396 if(p1->end < p2->end)
397 p1->end = p2->end;
398 freenode(p2);
399 return p1;
402 /*
403 * look for disallowed chars in the field name
404 */
405 int
406 badfieldname(Node *p)
408 for(; p; p = p->next){
409 /* field name can't contain white space */
410 if(p->white && p->next)
411 return 1;
413 return 0;
416 /*
417 * mark as an address
418 */
419 Node *
420 address(Node *p)
422 p->addr = 1;
423 return p;
426 /*
427 * case independent string compare
428 */
429 int
430 cistrcmp(char *s1, char *s2)
432 int c1, c2;
434 for(; *s1; s1++, s2++){
435 c1 = isupper(*s1) ? tolower(*s1) : *s1;
436 c2 = isupper(*s2) ? tolower(*s2) : *s2;
437 if (c1 != c2)
438 return -1;
440 return *s2;
443 /*
444 * free a node
445 */
446 void
447 freenode(Node *p)
449 Node *tp;
451 while(p){
452 tp = p->next;
453 if(p->s)
454 s_free(p->s);
455 if(p->white)
456 s_free(p->white);
457 free(p);
458 p = tp;
463 /*
464 * an anonymous user
465 */
466 Node*
467 nobody(Node *p)
469 if(p->s)
470 s_free(p->s);
471 p->s = s_copy("pOsTmAsTeR");
472 p->addr = 1;
473 return p;
476 /*
477 * add anything that was dropped because of a parse error
478 */
479 void
480 missing(Node *p)
482 Node *np;
483 char *start, *end;
484 Field *f;
485 String *s;
487 start = yybuffer;
488 if(lastfield != nil){
489 for(np = lastfield->node; np; np = np->next)
490 start = np->end+1;
493 end = p->start-1;
495 if(end <= start)
496 return;
498 if(strncmp(start, "From ", 5) == 0)
499 return;
501 np = malloc(sizeof(Node));
502 np->start = start;
503 np->end = end;
504 np->white = nil;
505 s = s_copy("BadHeader: ");
506 np->s = s_nappend(s, start, end-start);
507 np->next = nil;
509 f = malloc(sizeof(Field));
510 f->next = 0;
511 f->node = np;
512 f->source = 0;
513 if(firstfield)
514 lastfield->next = f;
515 else
516 firstfield = f;
517 lastfield = f;
520 /*
521 * create a new field
522 */
523 void
524 newfield(Node *p, int source)
526 Field *f;
528 missing(p);
530 f = malloc(sizeof(Field));
531 f->next = 0;
532 f->node = p;
533 f->source = source;
534 if(firstfield)
535 lastfield->next = f;
536 else
537 firstfield = f;
538 lastfield = f;
539 endfield = startfield;
540 startfield = yylp;
543 /*
544 * fee a list of fields
545 */
546 void
547 freefield(Field *f)
549 Field *tf;
551 while(f){
552 tf = f->next;
553 freenode(f->node);
554 free(f);
555 f = tf;
559 /*
560 * add some white space to a node
561 */
562 Node*
563 whiten(Node *p)
565 Node *tp;
567 for(tp = p; tp->next; tp = tp->next)
569 if(tp->white == 0)
570 tp->white = s_copy(" ");
571 return p;
574 void
575 yycleanup(void)
577 Field *f, *fnext;
578 Node *np, *next;
580 for(f = firstfield; f; f = fnext){
581 for(np = f->node; np; np = next){
582 if(np->s)
583 s_free(np->s);
584 if(np->white)
585 s_free(np->white);
586 next = np->next;
587 free(np);
589 fnext = f->next;
590 free(f);
592 firstfield = lastfield = 0;
594 static const short yyexca[] =
595 {-1, 1,
596 1, -1,
597 -2, 0,
598 -1, 47,
599 1, 4,
600 -2, 0,
601 -1, 112,
602 29, 72,
603 31, 72,
604 32, 72,
605 35, 72,
606 -2, 74
607 };
608 #define YYNPROD 122
609 #define YYPRIVATE 57344
610 #define YYLAST 608
611 static const short yyact[] =
613 112, 133, 136, 53, 121, 111, 134, 55, 109, 118,
614 119, 116, 162, 171, 35, 48, 166, 54, 5, 166,
615 179, 114, 115, 155, 49, 101, 100, 99, 95, 94,
616 93, 92, 98, 91, 132, 90, 123, 89, 122, 88,
617 87, 86, 85, 84, 83, 82, 97, 81, 80, 106,
618 47, 46, 110, 117, 153, 168, 108, 2, 56, 57,
619 58, 59, 60, 61, 62, 63, 64, 65, 73, 66,
620 67, 68, 69, 70, 71, 72, 74, 75, 76, 77,
621 78, 79, 124, 124, 49, 55, 177, 131, 110, 52,
622 110, 110, 138, 137, 140, 141, 124, 124, 51, 120,
623 124, 124, 124, 50, 102, 104, 135, 154, 31, 32,
624 107, 157, 105, 14, 55, 55, 156, 13, 161, 117,
625 117, 139, 158, 124, 142, 143, 144, 145, 146, 147,
626 163, 164, 160, 12, 148, 149, 11, 157, 150, 151,
627 152, 10, 156, 9, 8, 7, 3, 1, 0, 124,
628 124, 124, 124, 124, 0, 169, 0, 0, 110, 165,
629 0, 0, 170, 117, 0, 0, 0, 0, 173, 176,
630 178, 0, 0, 0, 172, 0, 0, 0, 180, 0,
631 0, 182, 183, 0, 0, 165, 165, 165, 165, 165,
632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
633 0, 0, 174, 56, 57, 58, 59, 60, 61, 62,
634 63, 64, 65, 73, 66, 67, 68, 69, 70, 71,
635 72, 74, 75, 76, 77, 78, 79, 0, 0, 128,
636 130, 129, 125, 126, 127, 15, 0, 36, 16, 17,
637 19, 103, 20, 18, 23, 22, 21, 30, 24, 26,
638 28, 25, 27, 29, 0, 34, 37, 38, 39, 33,
639 40, 0, 4, 0, 45, 44, 41, 42, 43, 56,
640 57, 58, 59, 60, 61, 62, 63, 64, 65, 73,
641 66, 67, 68, 69, 70, 71, 72, 74, 75, 76,
642 77, 78, 79, 0, 0, 96, 45, 44, 41, 42,
643 43, 15, 0, 36, 16, 17, 19, 6, 20, 18,
644 23, 22, 21, 30, 24, 26, 28, 25, 27, 29,
645 0, 34, 37, 38, 39, 33, 40, 0, 4, 0,
646 45, 44, 41, 42, 43, 15, 0, 36, 16, 17,
647 19, 103, 20, 18, 23, 22, 21, 30, 24, 26,
648 28, 25, 27, 29, 0, 34, 37, 38, 39, 33,
649 40, 0, 0, 0, 45, 44, 41, 42, 43, 56,
650 57, 58, 59, 60, 61, 62, 63, 64, 65, 73,
651 66, 67, 68, 69, 70, 71, 72, 74, 75, 76,
652 77, 78, 79, 0, 0, 0, 0, 175, 113, 0,
653 52, 56, 57, 58, 59, 60, 61, 62, 63, 64,
654 65, 73, 66, 67, 68, 69, 70, 71, 72, 74,
655 75, 76, 77, 78, 79, 0, 0, 0, 0, 0,
656 113, 0, 52, 56, 57, 58, 59, 60, 61, 62,
657 63, 64, 65, 73, 66, 67, 68, 69, 70, 71,
658 72, 74, 75, 76, 77, 78, 79, 0, 0, 0,
659 0, 0, 0, 159, 52, 56, 57, 58, 59, 60,
660 61, 62, 63, 64, 65, 73, 66, 67, 68, 69,
661 70, 71, 72, 74, 75, 76, 77, 78, 79, 0,
662 0, 0, 0, 0, 0, 0, 52, 56, 57, 58,
663 59, 60, 61, 62, 63, 64, 65, 73, 66, 67,
664 68, 69, 70, 71, 72, 74, 75, 76, 77, 78,
665 79, 0, 0, 167, 0, 0, 113, 56, 57, 58,
666 59, 60, 61, 62, 63, 64, 65, 73, 66, 67,
667 68, 69, 70, 71, 72, 74, 75, 76, 77, 78,
668 79, 0, 0, 0, 0, 0, 113, 56, 57, 58,
669 59, 60, 61, 62, 63, 64, 65, 73, 66, 67,
670 68, 69, 70, 71, 72, 74, 75, 76, 77, 78,
671 79, 0, 0, 181, 56, 57, 58, 59, 60, 61,
672 62, 63, 64, 65, 73, 66, 67, 68, 69, 70,
673 71, 72, 74, 75, 76, 77, 78, 79
674 };
675 static const short yypact[] =
677 299,-1000,-1000, 22,-1000, 21, 54,-1000,-1000,-1000,
678 -1000,-1000,-1000,-1000,-1000, 19, 17, 15, 14, 13,
679 12, 11, 10, 9, 7, 5, 3, 1, 0, -1,
680 -2, 265, -3, -4, -5,-1000,-1000,-1000,-1000,-1000,
681 -1000,-1000,-1000,-1000,-1000,-1000, 233, 233, 580, 397,
682 -9,-1000, 580, -26, -25,-1000,-1000,-1000,-1000,-1000,
683 -1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
684 -1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
685 333, 199, 199, 397, 461, 397, 397, 397, 397, 397,
686 397, 397, 397, 397, 397, 199, 199,-1000,-1000, 199,
687 199, 199,-1000, -6,-1000, 33, 580, -8,-1000,-1000,
688 523,-1000,-1000, 429, 580, -23,-1000,-1000, 580, 580,
689 -1000,-1000, 199,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
690 -1000,-1000, -15,-1000,-1000,-1000, 493,-1000,-1000, -15,
691 -1000,-1000, -15, -15, -15, -15, -15, -15, 199, 199,
692 199, 199, 199, 47, 580, 397,-1000,-1000, -21,-1000,
693 -25, -26, 580,-1000,-1000,-1000, 397, 365, 580, 580,
694 -1000,-1000,-1000,-1000, -12,-1000,-1000, 553,-1000,-1000,
695 580, 580,-1000,-1000
696 };
697 static const short yypgo[] =
699 0, 147, 57, 146, 18, 145, 144, 143, 141, 136,
700 133, 117, 113, 8, 112, 0, 34, 110, 6, 4,
701 38, 109, 108, 1, 106, 2, 5, 103, 17, 98,
702 11, 3, 36, 86, 14
703 };
704 static const short yyr1[] =
706 0, 1, 1, 2, 2, 2, 4, 4, 4, 4,
707 4, 4, 4, 4, 4, 3, 6, 6, 6, 6,
708 6, 6, 6, 5, 5, 7, 7, 7, 7, 7,
709 7, 7, 7, 7, 7, 7, 7, 8, 8, 11,
710 11, 12, 12, 10, 10, 21, 21, 21, 21, 9,
711 9, 16, 16, 23, 23, 24, 24, 17, 17, 18,
712 18, 18, 26, 26, 13, 13, 27, 27, 29, 29,
713 28, 28, 31, 30, 25, 25, 20, 20, 32, 32,
714 32, 32, 32, 32, 32, 19, 14, 33, 33, 15,
715 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
716 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
717 15, 15, 15, 22, 22, 22, 22, 34, 34, 34,
718 34, 34
719 };
720 static const short yyr2[] =
722 0, 1, 3, 1, 2, 3, 1, 1, 1, 1,
723 1, 1, 1, 1, 3, 6, 3, 3, 3, 3,
724 3, 3, 3, 3, 3, 2, 3, 2, 3, 2,
725 3, 2, 3, 2, 3, 2, 3, 3, 2, 3,
726 2, 3, 2, 3, 2, 1, 1, 1, 1, 3,
727 2, 1, 3, 1, 1, 4, 3, 1, 3, 1,
728 2, 1, 3, 2, 3, 1, 2, 4, 1, 1,
729 3, 3, 1, 1, 1, 2, 1, 2, 1, 1,
730 1, 1, 1, 1, 1, 1, 6, 1, 3, 1,
731 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
732 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
733 1, 1, 1, 1, 1, 2, 2, 1, 1, 1,
734 1, 1
735 };
736 static const short yychk[] =
738 -1000, -1, -2, -3, 29, -4, 8, -5, -6, -7,
739 -8, -9, -10, -11, -12, 2, 5, 6, 10, 7,
740 9, 13, 12, 11, 15, 18, 16, 19, 17, 20,
741 14, -22, -21, 26, 22, -34, 4, 23, 24, 25,
742 27, 33, 34, 35, 32, 31, 29, 29, -13, 30,
743 -27, -29, 35, -31, -28, -15, 4, 5, 6, 7,
744 8, 9, 10, 11, 12, 13, 15, 16, 17, 18,
745 19, 20, 21, 14, 22, 23, 24, 25, 26, 27,
746 29, 30, 30, 30, 30, 30, 30, 30, 30, 30,
747 30, 30, 30, 30, 30, 30, 30, -34, -15, 30,
748 30, 30, -2, 8, -2, -14, -15, -17, -18, -13,
749 -25, -26, -15, 33, 30, 31, -30, -15, 35, 35,
750 -4, -19, -20, -32, -15, 33, 34, 35, 30, 32,
751 31, -19, -16, -23, -18, -24, -25, -13, -18, -16,
752 -18, -18, -16, -16, -16, -16, -16, -16, -20, -20,
753 -20, -20, -20, 21, -15, 31, -26, -15, -13, 34,
754 -28, -31, 35, -30, -30, -32, 31, 30, 8, -15,
755 -18, 34, -30, -23, -16, 32, -15, -33, -15, 32,
756 -15, 30, -15, -15
757 };
758 static const short yydef[] =
760 0, -2, 1, 0, 3, 0, 0, 6, 7, 8,
761 9, 10, 11, 12, 13, 0, 0, 0, 0, 0,
762 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
763 0, 0, 0, 0, 0, 113, 114, 45, 46, 47,
764 48, 117, 118, 119, 120, 121, 0, -2, 0, 0,
765 0, 65, 0, 68, 69, 72, 89, 90, 91, 92,
766 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
767 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
768 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
769 27, 29, 31, 33, 35, 38, 50, 115, 116, 44,
770 40, 42, 2, 0, 5, 0, 0, 18, 57, 59,
771 0, 61, -2, 0, 0, 0, 66, 73, 0, 0,
772 14, 23, 85, 76, 78, 79, 80, 81, 82, 83,
773 84, 24, 16, 51, 53, 54, 0, 17, 19, 20,
774 21, 22, 26, 28, 30, 32, 34, 36, 37, 49,
775 43, 39, 41, 0, 0, 0, 60, 75, 0, 63,
776 64, 0, 0, 70, 71, 77, 0, 0, 0, 0,
777 58, 62, 67, 52, 0, 56, 15, 0, 87, 55,
778 0, 0, 86, 88
779 };
780 static const short yytok1[] =
782 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
783 29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
784 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
785 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
786 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
787 0, 0, 0, 0, 0, 0, 0, 0, 30, 32,
788 33, 0, 34, 0, 35
789 };
790 static const short yytok2[] =
792 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
793 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
794 22, 23, 24, 25, 26, 27, 28
795 };
796 static const long yytok3[] =
799 };
800 #define YYFLAG -1000
801 #define YYERROR goto yyerrlab
802 #define YYACCEPT return(0)
803 #define YYABORT return(1)
804 #define yyclearin yychar = -1
805 #define yyerrok yyerrflag = 0
807 #ifdef yydebug
808 #include "y.debug"
809 #else
810 #define yydebug 0
811 static const char* yytoknames[1]; /* for debugging */
812 static const char* yystates[1]; /* for debugging */
813 #endif
815 /* parser for yacc output */
816 #ifdef YYARG
817 #define yynerrs yyarg->yynerrs
818 #define yyerrflag yyarg->yyerrflag
819 #define yyval yyarg->yyval
820 #define yylval yyarg->yylval
821 #else
822 int yynerrs = 0; /* number of errors */
823 int yyerrflag = 0; /* error recovery flag */
824 #endif
826 extern int fprint(int, char*, ...);
827 extern int sprint(char*, char*, ...);
829 static const char*
830 yytokname(int yyc)
832 static char x[10];
834 if(yyc > 0 && yyc <= sizeof(yytoknames)/sizeof(yytoknames[0]))
835 if(yytoknames[yyc-1])
836 return yytoknames[yyc-1];
837 sprint(x, "<%d>", yyc);
838 return x;
841 static const char*
842 yystatname(int yys)
844 static char x[10];
846 if(yys >= 0 && yys < sizeof(yystates)/sizeof(yystates[0]))
847 if(yystates[yys])
848 return yystates[yys];
849 sprint(x, "<%d>\n", yys);
850 return x;
853 static long
854 #ifdef YYARG
855 yylex1(struct Yyarg *yyarg)
856 #else
857 yylex1(void)
858 #endif
860 long yychar;
861 const long *t3p;
862 int c;
864 #ifdef YYARG
865 yychar = yylex(yyarg);
866 #else
867 yychar = yylex();
868 #endif
869 if(yychar <= 0) {
870 c = yytok1[0];
871 goto out;
873 if(yychar < sizeof(yytok1)/sizeof(yytok1[0])) {
874 c = yytok1[yychar];
875 goto out;
877 if(yychar >= YYPRIVATE)
878 if(yychar < YYPRIVATE+sizeof(yytok2)/sizeof(yytok2[0])) {
879 c = yytok2[yychar-YYPRIVATE];
880 goto out;
882 for(t3p=yytok3;; t3p+=2) {
883 c = t3p[0];
884 if(c == yychar) {
885 c = t3p[1];
886 goto out;
888 if(c == 0)
889 break;
891 c = 0;
893 out:
894 if(c == 0)
895 c = yytok2[1]; /* unknown char */
896 if(yydebug >= 3)
897 fprint(2, "lex %.4lux %s\n", yychar, yytokname(c));
898 return c;
901 int
902 #ifdef YYARG
903 yyparse(struct Yyarg *yyarg)
904 #else
905 yyparse(void)
906 #endif
908 struct
910 YYSTYPE yyv;
911 int yys;
912 } yys[YYMAXDEPTH], *yyp, *yypt;
913 const short *yyxi;
914 int yyj, yym, yystate, yyn, yyg;
915 long yychar;
916 #ifndef YYARG
917 YYSTYPE save1, save2;
918 int save3, save4;
920 save1 = yylval;
921 save2 = yyval;
922 save3 = yynerrs;
923 save4 = yyerrflag;
924 #endif
926 yystate = 0;
927 yychar = -1;
928 yynerrs = 0;
929 yyerrflag = 0;
930 yyp = &yys[-1];
931 goto yystack;
933 ret0:
934 yyn = 0;
935 goto ret;
937 ret1:
938 yyn = 1;
939 goto ret;
941 ret:
942 #ifndef YYARG
943 yylval = save1;
944 yyval = save2;
945 yynerrs = save3;
946 yyerrflag = save4;
947 #endif
948 return yyn;
950 yystack:
951 /* put a state and value onto the stack */
952 if(yydebug >= 4)
953 fprint(2, "char %s in %s", yytokname(yychar), yystatname(yystate));
955 yyp++;
956 if(yyp >= &yys[YYMAXDEPTH]) {
957 yyerror("yacc stack overflow");
958 goto ret1;
960 yyp->yys = yystate;
961 yyp->yyv = yyval;
963 yynewstate:
964 yyn = yypact[yystate];
965 if(yyn <= YYFLAG)
966 goto yydefault; /* simple state */
967 if(yychar < 0)
968 #ifdef YYARG
969 yychar = yylex1(yyarg);
970 #else
971 yychar = yylex1();
972 #endif
973 yyn += yychar;
974 if(yyn < 0 || yyn >= YYLAST)
975 goto yydefault;
976 yyn = yyact[yyn];
977 if(yychk[yyn] == yychar) { /* valid shift */
978 yychar = -1;
979 yyval = yylval;
980 yystate = yyn;
981 if(yyerrflag > 0)
982 yyerrflag--;
983 goto yystack;
986 yydefault:
987 /* default state action */
988 yyn = yydef[yystate];
989 if(yyn == -2) {
990 if(yychar < 0)
991 #ifdef YYARG
992 yychar = yylex1(yyarg);
993 #else
994 yychar = yylex1();
995 #endif
997 /* look through exception table */
998 for(yyxi=yyexca;; yyxi+=2)
999 if(yyxi[0] == -1 && yyxi[1] == yystate)
1000 break;
1001 for(yyxi += 2;; yyxi += 2) {
1002 yyn = yyxi[0];
1003 if(yyn < 0 || yyn == yychar)
1004 break;
1006 yyn = yyxi[1];
1007 if(yyn < 0)
1008 goto ret0;
1010 if(yyn == 0) {
1011 /* error ... attempt to resume parsing */
1012 switch(yyerrflag) {
1013 case 0: /* brand new error */
1014 yyerror("syntax error");
1015 if(yydebug >= 1) {
1016 fprint(2, "%s", yystatname(yystate));
1017 fprint(2, "saw %s\n", yytokname(yychar));
1019 goto yyerrlab;
1020 yyerrlab:
1021 yynerrs++;
1023 case 1:
1024 case 2: /* incompletely recovered error ... try again */
1025 yyerrflag = 3;
1027 /* find a state where "error" is a legal shift action */
1028 while(yyp >= yys) {
1029 yyn = yypact[yyp->yys] + YYERRCODE;
1030 if(yyn >= 0 && yyn < YYLAST) {
1031 yystate = yyact[yyn]; /* simulate a shift of "error" */
1032 if(yychk[yystate] == YYERRCODE)
1033 goto yystack;
1036 /* the current yyp has no shift onn "error", pop stack */
1037 if(yydebug >= 2)
1038 fprint(2, "error recovery pops state %d, uncovers %d\n",
1039 yyp->yys, (yyp-1)->yys );
1040 yyp--;
1042 /* there is no state on the stack with an error shift ... abort */
1043 goto ret1;
1045 case 3: /* no shift yet; clobber input char */
1046 if(yydebug >= 2)
1047 fprint(2, "error recovery discards %s\n", yytokname(yychar));
1048 if(yychar == YYEOFCODE)
1049 goto ret1;
1050 yychar = -1;
1051 goto yynewstate; /* try again in the same state */
1055 /* reduction by production yyn */
1056 if(yydebug >= 2)
1057 fprint(2, "reduce %d in:\n\t%s", yyn, yystatname(yystate));
1059 yypt = yyp;
1060 yyp -= yyr2[yyn];
1061 yyval = (yyp+1)->yyv;
1062 yym = yyn;
1064 /* consult goto table to find next state */
1065 yyn = yyr1[yyn];
1066 yyg = yypgo[yyn];
1067 yyj = yyg + yyp->yys + 1;
1069 if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn)
1070 yystate = yyact[yyg];
1071 switch(yym) {
1073 case 3:
1074 #line 56 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1075 { yydone = 1; } break;
1076 case 6:
1077 #line 61 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1078 { date = 1; } break;
1079 case 7:
1080 #line 63 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1081 { originator = 1; } break;
1082 case 8:
1083 #line 65 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1084 { destination = 1; } break;
1085 case 15:
1086 #line 74 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1087 { freenode(yypt[-5].yyv); freenode(yypt[-2].yyv); freenode(yypt[-1].yyv);
1088 usender = yypt[-4].yyv; udate = yypt[-3].yyv; usys = yypt[-0].yyv;
1089 } break;
1090 case 16:
1091 #line 79 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1092 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
1093 case 17:
1094 #line 81 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1095 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
1096 case 18:
1097 #line 83 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1098 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
1099 case 19:
1100 #line 85 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1101 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
1102 case 20:
1103 #line 87 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1104 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
1105 case 21:
1106 #line 89 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1107 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
1108 case 22:
1109 #line 91 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1110 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
1111 case 23:
1112 #line 94 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1113 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1114 case 24:
1115 #line 96 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1116 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1117 case 25:
1118 #line 99 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1119 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1120 case 26:
1121 #line 101 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1122 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1123 case 27:
1124 #line 103 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1125 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1126 case 28:
1127 #line 105 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1128 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1129 case 29:
1130 #line 107 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1131 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1132 case 30:
1133 #line 109 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1134 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1135 case 31:
1136 #line 111 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1137 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1138 case 32:
1139 #line 113 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1140 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1141 case 33:
1142 #line 115 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1143 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1144 case 34:
1145 #line 117 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1146 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1147 case 35:
1148 #line 119 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1149 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1150 case 36:
1151 #line 121 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1152 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1153 case 37:
1154 #line 124 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1155 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1156 case 38:
1157 #line 126 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1158 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1159 case 39:
1160 #line 129 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1161 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); received++; } break;
1162 case 40:
1163 #line 131 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1164 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); received++; } break;
1165 case 41:
1166 #line 134 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1167 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1168 case 42:
1169 #line 136 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1170 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1171 case 43:
1172 #line 139 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1173 { newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1174 case 44:
1175 #line 141 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1176 { newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
1177 case 47:
1178 #line 143 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1179 { messageid = 1; } break;
1180 case 49:
1181 #line 146 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1182 { /* hack to allow same lex for field names and the rest */
1183 if(badfieldname(yypt[-2].yyv)){
1184 freenode(yypt[-2].yyv);
1185 freenode(yypt[-1].yyv);
1186 freenode(yypt[-0].yyv);
1187 return 1;
1189 newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0);
1190 } break;
1191 case 50:
1192 #line 156 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1193 { /* hack to allow same lex for field names and the rest */
1194 if(badfieldname(yypt[-1].yyv)){
1195 freenode(yypt[-1].yyv);
1196 freenode(yypt[-0].yyv);
1197 return 1;
1199 newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0);
1200 } break;
1201 case 52:
1202 #line 167 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1203 { yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
1204 case 55:
1205 #line 173 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1206 { yyval = link2(yypt[-3].yyv, link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv)); } break;
1207 case 56:
1208 #line 175 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1209 { yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
1210 case 58:
1211 #line 179 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1212 { yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
1213 case 60:
1214 #line 183 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1215 { yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
1216 case 62:
1217 #line 187 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1218 { yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
1219 case 63:
1220 #line 189 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1221 { yyval = nobody(yypt[-0].yyv); freenode(yypt[-1].yyv); } break;
1222 case 64:
1223 #line 192 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1224 { yyval = address(concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv))); } break;
1225 case 66:
1226 #line 196 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1227 { yyval = concat(yypt[-1].yyv, yypt[-0].yyv); } break;
1228 case 67:
1229 #line 198 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1230 { yyval = concat(yypt[-3].yyv, concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv))); } break;
1231 case 68:
1232 #line 201 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1233 { yyval = address(yypt[-0].yyv); } break;
1234 case 70:
1235 #line 205 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1236 { yyval = address(concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv)));} break;
1237 case 71:
1238 #line 207 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1239 { yyval = address(concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv)));} break;
1240 case 75:
1241 #line 215 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1242 { yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
1243 case 77:
1244 #line 219 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1245 { yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
1246 case 86:
1247 #line 226 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1248 { yyval = link3(yypt[-5].yyv, yypt[-3].yyv, link3(yypt[-4].yyv, yypt[-0].yyv, link2(yypt[-2].yyv, yypt[-1].yyv))); } break;
1249 case 88:
1250 #line 230 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1251 { yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
1252 case 115:
1253 #line 240 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1254 { yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
1255 case 116:
1256 #line 242 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
1257 { yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
1259 goto yystack; /* stack new state and value */