blob: 1f12e48e78c6f7058b874912ecfa6780e808290b [file] [log] [blame]
#line 2 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
#include "common.h"
#include "smtp.h"
#include <ctype.h>
char *yylp; /* next character to be lex'd */
int yydone; /* tell yylex to give up */
char *yybuffer; /* first parsed character */
char *yyend; /* end of buffer to be parsed */
Node *root;
Field *firstfield;
Field *lastfield;
Node *usender;
Node *usys;
Node *udate;
char *startfield, *endfield;
int originator;
int destination;
int date;
int received;
int messageid;
extern int yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
#ifndef YYSTYPE
#define YYSTYPE int
#endif
YYSTYPE yylval;
YYSTYPE yyval;
#define WORD 57346
#define DATE 57347
#define RESENT_DATE 57348
#define RETURN_PATH 57349
#define FROM 57350
#define SENDER 57351
#define REPLY_TO 57352
#define RESENT_FROM 57353
#define RESENT_SENDER 57354
#define RESENT_REPLY_TO 57355
#define SUBJECT 57356
#define TO 57357
#define CC 57358
#define BCC 57359
#define RESENT_TO 57360
#define RESENT_CC 57361
#define RESENT_BCC 57362
#define REMOTE 57363
#define PRECEDENCE 57364
#define MIMEVERSION 57365
#define CONTENTTYPE 57366
#define MESSAGEID 57367
#define RECEIVED 57368
#define MAILER 57369
#define BADTOKEN 57370
#define YYEOFCODE 1
#define YYERRCODE 2
#line 246 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
/*
* Initialize the parsing. Done once for each header field.
*/
void
yyinit(char *p, int len)
{
yybuffer = p;
yylp = p;
yyend = p + len;
firstfield = lastfield = 0;
received = 0;
}
/*
* keywords identifying header fields we care about
*/
typedef struct Keyword Keyword;
struct Keyword {
char *rep;
int val;
};
/* field names that we need to recognize */
Keyword key[] = {
{ "date", DATE },
{ "resent-date", RESENT_DATE },
{ "return_path", RETURN_PATH },
{ "from", FROM },
{ "sender", SENDER },
{ "reply-to", REPLY_TO },
{ "resent-from", RESENT_FROM },
{ "resent-sender", RESENT_SENDER },
{ "resent-reply-to", RESENT_REPLY_TO },
{ "to", TO },
{ "cc", CC },
{ "bcc", BCC },
{ "resent-to", RESENT_TO },
{ "resent-cc", RESENT_CC },
{ "resent-bcc", RESENT_BCC },
{ "remote", REMOTE },
{ "subject", SUBJECT },
{ "precedence", PRECEDENCE },
{ "mime-version", MIMEVERSION },
{ "content-type", CONTENTTYPE },
{ "message-id", MESSAGEID },
{ "received", RECEIVED },
{ "mailer", MAILER },
{ "who-the-hell-cares", WORD }
};
/*
* Lexical analysis for an rfc822 header field. Continuation lines
* are handled in yywhite() when skipping over white space.
*
*/
int
yylex(void)
{
String *t;
int quoting;
int escaping;
char *start;
Keyword *kp;
int c, d;
/* print("lexing\n"); /**/
if(yylp >= yyend)
return 0;
if(yydone)
return 0;
quoting = escaping = 0;
start = yylp;
yylval = malloc(sizeof(Node));
yylval->white = yylval->s = 0;
yylval->next = 0;
yylval->addr = 0;
yylval->start = yylp;
for(t = 0; yylp < yyend; yylp++){
c = *yylp & 0xff;
/* dump nulls, they can't be in header */
if(c == 0)
continue;
if(escaping) {
escaping = 0;
} else if(quoting) {
switch(c){
case '\\':
escaping = 1;
break;
case '\n':
d = (*(yylp+1))&0xff;
if(d != ' ' && d != '\t'){
quoting = 0;
yylp--;
continue;
}
break;
case '"':
quoting = 0;
break;
}
} else {
switch(c){
case '\\':
escaping = 1;
break;
case '(':
case ' ':
case '\t':
case '\r':
goto out;
case '\n':
if(yylp == start){
yylp++;
/* print("lex(c %c)\n", c); /**/
yylval->end = yylp;
return yylval->c = c;
}
goto out;
case '@':
case '>':
case '<':
case ':':
case ',':
case ';':
if(yylp == start){
yylp++;
yylval->white = yywhite();
/* print("lex(c %c)\n", c); /**/
yylval->end = yylp;
return yylval->c = c;
}
goto out;
case '"':
quoting = 1;
break;
default:
break;
}
}
if(t == 0)
t = s_new();
s_putc(t, c);
}
out:
yylval->white = yywhite();
if(t) {
s_terminate(t);
} else /* message begins with white-space! */
return yylval->c = '\n';
yylval->s = t;
for(kp = key; kp->val != WORD; kp++)
if(cistrcmp(s_to_c(t), kp->rep)==0)
break;
/* print("lex(%d) %s\n", kp->val-WORD, s_to_c(t)); /**/
yylval->end = yylp;
return yylval->c = kp->val;
}
void
yyerror(char *x)
{
USED(x);
/*fprint(2, "parse err: %s\n", x);/**/
}
/*
* parse white space and comments
*/
String *
yywhite(void)
{
String *w;
int clevel;
int c;
int escaping;
escaping = clevel = 0;
for(w = 0; yylp < yyend; yylp++){
c = *yylp & 0xff;
/* dump nulls, they can't be in header */
if(c == 0)
continue;
if(escaping){
escaping = 0;
} else if(clevel) {
switch(c){
case '\n':
/*
* look for multiline fields
*/
if(*(yylp+1)==' ' || *(yylp+1)=='\t')
break;
else
goto out;
case '\\':
escaping = 1;
break;
case '(':
clevel++;
break;
case ')':
clevel--;
break;
}
} else {
switch(c){
case '\\':
escaping = 1;
break;
case '(':
clevel++;
break;
case ' ':
case '\t':
case '\r':
break;
case '\n':
/*
* look for multiline fields
*/
if(*(yylp+1)==' ' || *(yylp+1)=='\t')
break;
else
goto out;
default:
goto out;
}
}
if(w == 0)
w = s_new();
s_putc(w, c);
}
out:
if(w)
s_terminate(w);
return w;
}
/*
* link two parsed entries together
*/
Node*
link2(Node *p1, Node *p2)
{
Node *p;
for(p = p1; p->next; p = p->next)
;
p->next = p2;
return p1;
}
/*
* link three parsed entries together
*/
Node*
link3(Node *p1, Node *p2, Node *p3)
{
Node *p;
for(p = p2; p->next; p = p->next)
;
p->next = p3;
for(p = p1; p->next; p = p->next)
;
p->next = p2;
return p1;
}
/*
* make a:b, move all white space after both
*/
Node*
colon(Node *p1, Node *p2)
{
if(p1->white){
if(p2->white)
s_append(p1->white, s_to_c(p2->white));
} else {
p1->white = p2->white;
p2->white = 0;
}
s_append(p1->s, ":");
if(p2->s)
s_append(p1->s, s_to_c(p2->s));
if(p1->end < p2->end)
p1->end = p2->end;
freenode(p2);
return p1;
}
/*
* concatenate two fields, move all white space after both
*/
Node*
concat(Node *p1, Node *p2)
{
char buf[2];
if(p1->white){
if(p2->white)
s_append(p1->white, s_to_c(p2->white));
} else {
p1->white = p2->white;
p2->white = 0;
}
if(p1->s == nil){
buf[0] = p1->c;
buf[1] = 0;
p1->s = s_new();
s_append(p1->s, buf);
}
if(p2->s)
s_append(p1->s, s_to_c(p2->s));
else {
buf[0] = p2->c;
buf[1] = 0;
s_append(p1->s, buf);
}
if(p1->end < p2->end)
p1->end = p2->end;
freenode(p2);
return p1;
}
/*
* look for disallowed chars in the field name
*/
int
badfieldname(Node *p)
{
for(; p; p = p->next){
/* field name can't contain white space */
if(p->white && p->next)
return 1;
}
return 0;
}
/*
* mark as an address
*/
Node *
address(Node *p)
{
p->addr = 1;
return p;
}
/*
* case independent string compare
*/
int
cistrcmp(char *s1, char *s2)
{
int c1, c2;
for(; *s1; s1++, s2++){
c1 = isupper(*s1) ? tolower(*s1) : *s1;
c2 = isupper(*s2) ? tolower(*s2) : *s2;
if (c1 != c2)
return -1;
}
return *s2;
}
/*
* free a node
*/
void
freenode(Node *p)
{
Node *tp;
while(p){
tp = p->next;
if(p->s)
s_free(p->s);
if(p->white)
s_free(p->white);
free(p);
p = tp;
}
}
/*
* an anonymous user
*/
Node*
nobody(Node *p)
{
if(p->s)
s_free(p->s);
p->s = s_copy("pOsTmAsTeR");
p->addr = 1;
return p;
}
/*
* add anything that was dropped because of a parse error
*/
void
missing(Node *p)
{
Node *np;
char *start, *end;
Field *f;
String *s;
start = yybuffer;
if(lastfield != nil){
for(np = lastfield->node; np; np = np->next)
start = np->end+1;
}
end = p->start-1;
if(end <= start)
return;
if(strncmp(start, "From ", 5) == 0)
return;
np = malloc(sizeof(Node));
np->start = start;
np->end = end;
np->white = nil;
s = s_copy("BadHeader: ");
np->s = s_nappend(s, start, end-start);
np->next = nil;
f = malloc(sizeof(Field));
f->next = 0;
f->node = np;
f->source = 0;
if(firstfield)
lastfield->next = f;
else
firstfield = f;
lastfield = f;
}
/*
* create a new field
*/
void
newfield(Node *p, int source)
{
Field *f;
missing(p);
f = malloc(sizeof(Field));
f->next = 0;
f->node = p;
f->source = source;
if(firstfield)
lastfield->next = f;
else
firstfield = f;
lastfield = f;
endfield = startfield;
startfield = yylp;
}
/*
* fee a list of fields
*/
void
freefield(Field *f)
{
Field *tf;
while(f){
tf = f->next;
freenode(f->node);
free(f);
f = tf;
}
}
/*
* add some white space to a node
*/
Node*
whiten(Node *p)
{
Node *tp;
for(tp = p; tp->next; tp = tp->next)
;
if(tp->white == 0)
tp->white = s_copy(" ");
return p;
}
void
yycleanup(void)
{
Field *f, *fnext;
Node *np, *next;
for(f = firstfield; f; f = fnext){
for(np = f->node; np; np = next){
if(np->s)
s_free(np->s);
if(np->white)
s_free(np->white);
next = np->next;
free(np);
}
fnext = f->next;
free(f);
}
firstfield = lastfield = 0;
}
static const short yyexca[] =
{-1, 1,
1, -1,
-2, 0,
-1, 47,
1, 4,
-2, 0,
-1, 112,
29, 72,
31, 72,
32, 72,
35, 72,
-2, 74,
};
#define YYNPROD 122
#define YYPRIVATE 57344
#define YYLAST 608
static const short yyact[] =
{
112, 133, 136, 53, 121, 111, 134, 55, 109, 118,
119, 116, 162, 171, 35, 48, 166, 54, 5, 166,
179, 114, 115, 155, 49, 101, 100, 99, 95, 94,
93, 92, 98, 91, 132, 90, 123, 89, 122, 88,
87, 86, 85, 84, 83, 82, 97, 81, 80, 106,
47, 46, 110, 117, 153, 168, 108, 2, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65, 73, 66,
67, 68, 69, 70, 71, 72, 74, 75, 76, 77,
78, 79, 124, 124, 49, 55, 177, 131, 110, 52,
110, 110, 138, 137, 140, 141, 124, 124, 51, 120,
124, 124, 124, 50, 102, 104, 135, 154, 31, 32,
107, 157, 105, 14, 55, 55, 156, 13, 161, 117,
117, 139, 158, 124, 142, 143, 144, 145, 146, 147,
163, 164, 160, 12, 148, 149, 11, 157, 150, 151,
152, 10, 156, 9, 8, 7, 3, 1, 0, 124,
124, 124, 124, 124, 0, 169, 0, 0, 110, 165,
0, 0, 170, 117, 0, 0, 0, 0, 173, 176,
178, 0, 0, 0, 172, 0, 0, 0, 180, 0,
0, 182, 183, 0, 0, 165, 165, 165, 165, 165,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 174, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 73, 66, 67, 68, 69, 70, 71,
72, 74, 75, 76, 77, 78, 79, 0, 0, 128,
130, 129, 125, 126, 127, 15, 0, 36, 16, 17,
19, 103, 20, 18, 23, 22, 21, 30, 24, 26,
28, 25, 27, 29, 0, 34, 37, 38, 39, 33,
40, 0, 4, 0, 45, 44, 41, 42, 43, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 73,
66, 67, 68, 69, 70, 71, 72, 74, 75, 76,
77, 78, 79, 0, 0, 96, 45, 44, 41, 42,
43, 15, 0, 36, 16, 17, 19, 6, 20, 18,
23, 22, 21, 30, 24, 26, 28, 25, 27, 29,
0, 34, 37, 38, 39, 33, 40, 0, 4, 0,
45, 44, 41, 42, 43, 15, 0, 36, 16, 17,
19, 103, 20, 18, 23, 22, 21, 30, 24, 26,
28, 25, 27, 29, 0, 34, 37, 38, 39, 33,
40, 0, 0, 0, 45, 44, 41, 42, 43, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 73,
66, 67, 68, 69, 70, 71, 72, 74, 75, 76,
77, 78, 79, 0, 0, 0, 0, 175, 113, 0,
52, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 73, 66, 67, 68, 69, 70, 71, 72, 74,
75, 76, 77, 78, 79, 0, 0, 0, 0, 0,
113, 0, 52, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 73, 66, 67, 68, 69, 70, 71,
72, 74, 75, 76, 77, 78, 79, 0, 0, 0,
0, 0, 0, 159, 52, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 73, 66, 67, 68, 69,
70, 71, 72, 74, 75, 76, 77, 78, 79, 0,
0, 0, 0, 0, 0, 0, 52, 56, 57, 58,
59, 60, 61, 62, 63, 64, 65, 73, 66, 67,
68, 69, 70, 71, 72, 74, 75, 76, 77, 78,
79, 0, 0, 167, 0, 0, 113, 56, 57, 58,
59, 60, 61, 62, 63, 64, 65, 73, 66, 67,
68, 69, 70, 71, 72, 74, 75, 76, 77, 78,
79, 0, 0, 0, 0, 0, 113, 56, 57, 58,
59, 60, 61, 62, 63, 64, 65, 73, 66, 67,
68, 69, 70, 71, 72, 74, 75, 76, 77, 78,
79, 0, 0, 181, 56, 57, 58, 59, 60, 61,
62, 63, 64, 65, 73, 66, 67, 68, 69, 70,
71, 72, 74, 75, 76, 77, 78, 79
};
static const short yypact[] =
{
299,-1000,-1000, 22,-1000, 21, 54,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000, 19, 17, 15, 14, 13,
12, 11, 10, 9, 7, 5, 3, 1, 0, -1,
-2, 265, -3, -4, -5,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000, 233, 233, 580, 397,
-9,-1000, 580, -26, -25,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
333, 199, 199, 397, 461, 397, 397, 397, 397, 397,
397, 397, 397, 397, 397, 199, 199,-1000,-1000, 199,
199, 199,-1000, -6,-1000, 33, 580, -8,-1000,-1000,
523,-1000,-1000, 429, 580, -23,-1000,-1000, 580, 580,
-1000,-1000, 199,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000, -15,-1000,-1000,-1000, 493,-1000,-1000, -15,
-1000,-1000, -15, -15, -15, -15, -15, -15, 199, 199,
199, 199, 199, 47, 580, 397,-1000,-1000, -21,-1000,
-25, -26, 580,-1000,-1000,-1000, 397, 365, 580, 580,
-1000,-1000,-1000,-1000, -12,-1000,-1000, 553,-1000,-1000,
580, 580,-1000,-1000
};
static const short yypgo[] =
{
0, 147, 57, 146, 18, 145, 144, 143, 141, 136,
133, 117, 113, 8, 112, 0, 34, 110, 6, 4,
38, 109, 108, 1, 106, 2, 5, 103, 17, 98,
11, 3, 36, 86, 14
};
static const short yyr1[] =
{
0, 1, 1, 2, 2, 2, 4, 4, 4, 4,
4, 4, 4, 4, 4, 3, 6, 6, 6, 6,
6, 6, 6, 5, 5, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 8, 8, 11,
11, 12, 12, 10, 10, 21, 21, 21, 21, 9,
9, 16, 16, 23, 23, 24, 24, 17, 17, 18,
18, 18, 26, 26, 13, 13, 27, 27, 29, 29,
28, 28, 31, 30, 25, 25, 20, 20, 32, 32,
32, 32, 32, 32, 32, 19, 14, 33, 33, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 22, 22, 22, 22, 34, 34, 34,
34, 34
};
static const short yyr2[] =
{
0, 1, 3, 1, 2, 3, 1, 1, 1, 1,
1, 1, 1, 1, 3, 6, 3, 3, 3, 3,
3, 3, 3, 3, 3, 2, 3, 2, 3, 2,
3, 2, 3, 2, 3, 2, 3, 3, 2, 3,
2, 3, 2, 3, 2, 1, 1, 1, 1, 3,
2, 1, 3, 1, 1, 4, 3, 1, 3, 1,
2, 1, 3, 2, 3, 1, 2, 4, 1, 1,
3, 3, 1, 1, 1, 2, 1, 2, 1, 1,
1, 1, 1, 1, 1, 1, 6, 1, 3, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 2, 2, 1, 1, 1,
1, 1
};
static const short yychk[] =
{
-1000, -1, -2, -3, 29, -4, 8, -5, -6, -7,
-8, -9, -10, -11, -12, 2, 5, 6, 10, 7,
9, 13, 12, 11, 15, 18, 16, 19, 17, 20,
14, -22, -21, 26, 22, -34, 4, 23, 24, 25,
27, 33, 34, 35, 32, 31, 29, 29, -13, 30,
-27, -29, 35, -31, -28, -15, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 15, 16, 17, 18,
19, 20, 21, 14, 22, 23, 24, 25, 26, 27,
29, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, -34, -15, 30,
30, 30, -2, 8, -2, -14, -15, -17, -18, -13,
-25, -26, -15, 33, 30, 31, -30, -15, 35, 35,
-4, -19, -20, -32, -15, 33, 34, 35, 30, 32,
31, -19, -16, -23, -18, -24, -25, -13, -18, -16,
-18, -18, -16, -16, -16, -16, -16, -16, -20, -20,
-20, -20, -20, 21, -15, 31, -26, -15, -13, 34,
-28, -31, 35, -30, -30, -32, 31, 30, 8, -15,
-18, 34, -30, -23, -16, 32, -15, -33, -15, 32,
-15, 30, -15, -15
};
static const short yydef[] =
{
0, -2, 1, 0, 3, 0, 0, 6, 7, 8,
9, 10, 11, 12, 13, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 113, 114, 45, 46, 47,
48, 117, 118, 119, 120, 121, 0, -2, 0, 0,
0, 65, 0, 68, 69, 72, 89, 90, 91, 92,
93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
27, 29, 31, 33, 35, 38, 50, 115, 116, 44,
40, 42, 2, 0, 5, 0, 0, 18, 57, 59,
0, 61, -2, 0, 0, 0, 66, 73, 0, 0,
14, 23, 85, 76, 78, 79, 80, 81, 82, 83,
84, 24, 16, 51, 53, 54, 0, 17, 19, 20,
21, 22, 26, 28, 30, 32, 34, 36, 37, 49,
43, 39, 41, 0, 0, 0, 60, 75, 0, 63,
64, 0, 0, 70, 71, 77, 0, 0, 0, 0,
58, 62, 67, 52, 0, 56, 15, 0, 87, 55,
0, 0, 86, 88
};
static const short yytok1[] =
{
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 30, 32,
33, 0, 34, 0, 35
};
static const short yytok2[] =
{
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28
};
static const long yytok3[] =
{
0
};
#define YYFLAG -1000
#define YYERROR goto yyerrlab
#define YYACCEPT return(0)
#define YYABORT return(1)
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
#ifdef yydebug
#include "y.debug"
#else
#define yydebug 0
static const char* yytoknames[1]; /* for debugging */
static const char* yystates[1]; /* for debugging */
#endif
/* parser for yacc output */
#ifdef YYARG
#define yynerrs yyarg->yynerrs
#define yyerrflag yyarg->yyerrflag
#define yyval yyarg->yyval
#define yylval yyarg->yylval
#else
int yynerrs = 0; /* number of errors */
int yyerrflag = 0; /* error recovery flag */
#endif
extern int fprint(int, char*, ...);
extern int sprint(char*, char*, ...);
static const char*
yytokname(int yyc)
{
static char x[10];
if(yyc > 0 && yyc <= sizeof(yytoknames)/sizeof(yytoknames[0]))
if(yytoknames[yyc-1])
return yytoknames[yyc-1];
sprint(x, "<%d>", yyc);
return x;
}
static const char*
yystatname(int yys)
{
static char x[10];
if(yys >= 0 && yys < sizeof(yystates)/sizeof(yystates[0]))
if(yystates[yys])
return yystates[yys];
sprint(x, "<%d>\n", yys);
return x;
}
static long
#ifdef YYARG
yylex1(struct Yyarg *yyarg)
#else
yylex1(void)
#endif
{
long yychar;
const long *t3p;
int c;
#ifdef YYARG
yychar = yylex(yyarg);
#else
yychar = yylex();
#endif
if(yychar <= 0) {
c = yytok1[0];
goto out;
}
if(yychar < sizeof(yytok1)/sizeof(yytok1[0])) {
c = yytok1[yychar];
goto out;
}
if(yychar >= YYPRIVATE)
if(yychar < YYPRIVATE+sizeof(yytok2)/sizeof(yytok2[0])) {
c = yytok2[yychar-YYPRIVATE];
goto out;
}
for(t3p=yytok3;; t3p+=2) {
c = t3p[0];
if(c == yychar) {
c = t3p[1];
goto out;
}
if(c == 0)
break;
}
c = 0;
out:
if(c == 0)
c = yytok2[1]; /* unknown char */
if(yydebug >= 3)
fprint(2, "lex %.4lux %s\n", yychar, yytokname(c));
return c;
}
int
#ifdef YYARG
yyparse(struct Yyarg *yyarg)
#else
yyparse(void)
#endif
{
struct
{
YYSTYPE yyv;
int yys;
} yys[YYMAXDEPTH], *yyp, *yypt;
const short *yyxi;
int yyj, yym, yystate, yyn, yyg;
long yychar;
#ifndef YYARG
YYSTYPE save1, save2;
int save3, save4;
save1 = yylval;
save2 = yyval;
save3 = yynerrs;
save4 = yyerrflag;
#endif
yystate = 0;
yychar = -1;
yynerrs = 0;
yyerrflag = 0;
yyp = &yys[-1];
goto yystack;
ret0:
yyn = 0;
goto ret;
ret1:
yyn = 1;
goto ret;
ret:
#ifndef YYARG
yylval = save1;
yyval = save2;
yynerrs = save3;
yyerrflag = save4;
#endif
return yyn;
yystack:
/* put a state and value onto the stack */
if(yydebug >= 4)
fprint(2, "char %s in %s", yytokname(yychar), yystatname(yystate));
yyp++;
if(yyp >= &yys[YYMAXDEPTH]) {
yyerror("yacc stack overflow");
goto ret1;
}
yyp->yys = yystate;
yyp->yyv = yyval;
yynewstate:
yyn = yypact[yystate];
if(yyn <= YYFLAG)
goto yydefault; /* simple state */
if(yychar < 0)
#ifdef YYARG
yychar = yylex1(yyarg);
#else
yychar = yylex1();
#endif
yyn += yychar;
if(yyn < 0 || yyn >= YYLAST)
goto yydefault;
yyn = yyact[yyn];
if(yychk[yyn] == yychar) { /* valid shift */
yychar = -1;
yyval = yylval;
yystate = yyn;
if(yyerrflag > 0)
yyerrflag--;
goto yystack;
}
yydefault:
/* default state action */
yyn = yydef[yystate];
if(yyn == -2) {
if(yychar < 0)
#ifdef YYARG
yychar = yylex1(yyarg);
#else
yychar = yylex1();
#endif
/* look through exception table */
for(yyxi=yyexca;; yyxi+=2)
if(yyxi[0] == -1 && yyxi[1] == yystate)
break;
for(yyxi += 2;; yyxi += 2) {
yyn = yyxi[0];
if(yyn < 0 || yyn == yychar)
break;
}
yyn = yyxi[1];
if(yyn < 0)
goto ret0;
}
if(yyn == 0) {
/* error ... attempt to resume parsing */
switch(yyerrflag) {
case 0: /* brand new error */
yyerror("syntax error");
if(yydebug >= 1) {
fprint(2, "%s", yystatname(yystate));
fprint(2, "saw %s\n", yytokname(yychar));
}
goto yyerrlab;
yyerrlab:
yynerrs++;
case 1:
case 2: /* incompletely recovered error ... try again */
yyerrflag = 3;
/* find a state where "error" is a legal shift action */
while(yyp >= yys) {
yyn = yypact[yyp->yys] + YYERRCODE;
if(yyn >= 0 && yyn < YYLAST) {
yystate = yyact[yyn]; /* simulate a shift of "error" */
if(yychk[yystate] == YYERRCODE)
goto yystack;
}
/* the current yyp has no shift onn "error", pop stack */
if(yydebug >= 2)
fprint(2, "error recovery pops state %d, uncovers %d\n",
yyp->yys, (yyp-1)->yys );
yyp--;
}
/* there is no state on the stack with an error shift ... abort */
goto ret1;
case 3: /* no shift yet; clobber input char */
if(yydebug >= 2)
fprint(2, "error recovery discards %s\n", yytokname(yychar));
if(yychar == YYEOFCODE)
goto ret1;
yychar = -1;
goto yynewstate; /* try again in the same state */
}
}
/* reduction by production yyn */
if(yydebug >= 2)
fprint(2, "reduce %d in:\n\t%s", yyn, yystatname(yystate));
yypt = yyp;
yyp -= yyr2[yyn];
yyval = (yyp+1)->yyv;
yym = yyn;
/* consult goto table to find next state */
yyn = yyr1[yyn];
yyg = yypgo[yyn];
yyj = yyg + yyp->yys + 1;
if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn)
yystate = yyact[yyg];
switch(yym) {
case 3:
#line 56 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yydone = 1; } break;
case 6:
#line 61 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ date = 1; } break;
case 7:
#line 63 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ originator = 1; } break;
case 8:
#line 65 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ destination = 1; } break;
case 15:
#line 74 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ freenode(yypt[-5].yyv); freenode(yypt[-2].yyv); freenode(yypt[-1].yyv);
usender = yypt[-4].yyv; udate = yypt[-3].yyv; usys = yypt[-0].yyv;
} break;
case 16:
#line 79 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
case 17:
#line 81 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
case 18:
#line 83 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
case 19:
#line 85 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
case 20:
#line 87 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
case 21:
#line 89 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
case 22:
#line 91 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 1); } break;
case 23:
#line 94 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 24:
#line 96 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 25:
#line 99 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 26:
#line 101 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 27:
#line 103 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 28:
#line 105 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 29:
#line 107 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 30:
#line 109 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 31:
#line 111 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 32:
#line 113 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 33:
#line 115 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 34:
#line 117 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 35:
#line 119 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 36:
#line 121 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 37:
#line 124 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 38:
#line 126 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 39:
#line 129 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); received++; } break;
case 40:
#line 131 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); received++; } break;
case 41:
#line 134 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 42:
#line 136 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 43:
#line 139 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 44:
#line 141 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0); } break;
case 47:
#line 143 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ messageid = 1; } break;
case 49:
#line 146 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ /* hack to allow same lex for field names and the rest */
if(badfieldname(yypt[-2].yyv)){
freenode(yypt[-2].yyv);
freenode(yypt[-1].yyv);
freenode(yypt[-0].yyv);
return 1;
}
newfield(link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv), 0);
} break;
case 50:
#line 156 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ /* hack to allow same lex for field names and the rest */
if(badfieldname(yypt[-1].yyv)){
freenode(yypt[-1].yyv);
freenode(yypt[-0].yyv);
return 1;
}
newfield(link2(yypt[-1].yyv, yypt[-0].yyv), 0);
} break;
case 52:
#line 167 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
case 55:
#line 173 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link2(yypt[-3].yyv, link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv)); } break;
case 56:
#line 175 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
case 58:
#line 179 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
case 60:
#line 183 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
case 62:
#line 187 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
case 63:
#line 189 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = nobody(yypt[-0].yyv); freenode(yypt[-1].yyv); } break;
case 64:
#line 192 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = address(concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv))); } break;
case 66:
#line 196 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = concat(yypt[-1].yyv, yypt[-0].yyv); } break;
case 67:
#line 198 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = concat(yypt[-3].yyv, concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv))); } break;
case 68:
#line 201 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = address(yypt[-0].yyv); } break;
case 70:
#line 205 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = address(concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv)));} break;
case 71:
#line 207 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = address(concat(yypt[-2].yyv, concat(yypt[-1].yyv, yypt[-0].yyv)));} break;
case 75:
#line 215 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
case 77:
#line 219 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
case 86:
#line 226 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link3(yypt[-5].yyv, yypt[-3].yyv, link3(yypt[-4].yyv, yypt[-0].yyv, link2(yypt[-2].yyv, yypt[-1].yyv))); } break;
case 88:
#line 230 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link3(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break;
case 115:
#line 240 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
case 116:
#line 242 "/usr/local/plan9/src/cmd/upas/smtp/rfc822.y"
{ yyval = link2(yypt[-1].yyv, yypt[-0].yyv); } break;
}
goto yystack; /* stack new state and value */
}