blob: 8039f80c63f77db71eb879d5f4cff7e7c10f5ed1 (
plain)
1
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
/*
* @LANG: c++
* @CFLAGS: -I../aapl
*/
#include <iostream>
#include <string.h>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
%%{
machine mailbox;
action prn_char { cout << *p; }
action prn_space { cout << ' '; }
action prn_word { cout.write(ws, p-ws); cout << ' '; }
action prn_addr1 { cout << "| "; cout.write(ws+1, p-ws-2); }
action prn_addr2 { cout << "| "; cout.write(ws, p-ws); }
action prn_tab { cout << '\t'; }
action prn_nl { cout << '\n'; }
action prn_separator { cout << "------\n"; }
action prn_from { cout << "FROM\n"; }
action prn_to { cout << "TO\n"; }
action prn_subj { cout << "SUBJECT\n"; }
action start_word { ws = p; }
action start_headers { preserve = p; }
action end_headers {preserve = 0;}
day = upper lower{2};
month = upper lower{2};
year = digit{4};
time = digit{2} ':' digit{2}
( ':' digit{2} )?;
letterZone = upper{3};
numZone = [+\-] digit{4};
zone = letterZone | numZone;
dayNum = ( digit | ' ' ) digit;
date = day ' ' month ' '
dayNum ' ' time ' '
(
year |
year ' ' zone |
zone ' ' year
);
fromLine = 'From ' [^\n]* ' '
date '\n' @start_headers;
headerChar = print - [ :];
headersToPrint = 'From' |
'To' | 'Subject';
headersToConsume =
headerChar+ - headersToPrint;
action init_hlen {hlen = 0;}
action hlen {hlen++ < 50}
consumeHeaderBody =
':' @init_hlen
(
[^\n] |
( '\n' [ \t] )
)* when hlen
'\n';
consumeHeader =
headersToConsume consumeHeaderBody;
addrWS = ( [ \t]+ | '\n' [ \t]+ );
addrComment = '(' [^)]* ')';
addrWord = [^"'@,<>() \t\n]+;
addrAddr1 = '<' [^>]* '>';
addrAddr2 = addrWord '@' addrWord;
addrString =
'"' [^"]* '"' |
"'" [^']* "'";
addrItem = (
addrAddr1 %prn_addr1 |
addrAddr2 %prn_addr2 |
addrWord %prn_word |
addrString %prn_word
) >start_word;
address = (
addrWS |
addrComment |
addrItem
)** >prn_tab;
addrHeader = (
'From' %prn_from |
'To' %prn_to
) ':' @init_hlen
( address ( ',' @prn_nl address )* ) when hlen
'\n' %prn_nl;
subjectHeader =
'Subject:' @prn_subj @prn_tab @init_hlen
(
' '* <:
(
[^\n] @prn_char |
( '\n' [ \t]+ ) %prn_space
)**
) when hlen
'\n' %prn_nl;
header = consumeHeader |
addrHeader | subjectHeader;
messageLine =
( [^\n]* when hlen '\n' @init_hlen ) - fromLine;
main := (
fromLine %prn_separator
header*
'\n' @end_headers @init_hlen
messageLine*
)*;
}%%
%% write data;
#define BUFSIZE 8192
void test( const char *buf )
{
int cs, len = strlen( buf );
const char *preserve = 0, *ws = 0;
int hlen = 0;
%% write init;
const char *p = buf;
const char *pe = p + len;
%% write exec;
if ( cs < mailbox_first_final ) {
cout << endl << endl;
cout << "DID NOT FINISH IN A FINAL STATE" << endl;
}
}
int main()
{
test(
"From user@host.com Wed Nov 28 13:30:05 2001\n"
"From: \"Adrian D. Thurston\" <thurston@complang.org>\n"
"Subject: the squirrel has landed\n"
"\n"
"Message goes here. \n"
"From (trick from line).\n"
"From: not really a header\n"
"\n"
"From user2@host2.com Wed Nov 28 13:30:05 2001\n"
"To: \"(kill 1)\" Edgar Allen Poe <ep@net.com> (da man)\n"
"Subject: (no subject) this is a really long subject which should fail the length constraint \n"
"Other: 0123456789\n"
"\n"
"Message goes here. \n"
"\n"
);
test(
"From user@host.com Wed Nov 28 13:30:05 2001\n"
"To: \"(kill 2)\" some guy <sg@net.com>\n"
"From: \"Adrian D. Thurston this name is far too long\" <thurston@complang.org>\n"
"Subject: the squirrel has landed\n"
"\n"
"From user2@host2.com Wed Nov 28 13:30:05 2001\n"
"To: Edgar Allen Poe <ep@net.com> (da man)\n"
"Subject: (no subject) \n"
"\n"
);
test(
"From user@host.com Wed Nov 28 13:30:05 2001\n"
"To: \"(kill 3)\" some guy <sg@net.com>\n"
"From: \"Adrian D. Thurston This name is fore sure absolutely too long\" <t@cs.ca>\n"
"Subject: the squirrel has landed\n"
"\n"
);
test(
"From user@host.com Wed Nov 28 13:30:05 2001\n"
"From: \"Adrian D. Thurston \" <t@cs.ca>\n"
"Subject: (kill 4) the squirrel has landed\n"
"Other: This is another header field, not interpreted, that is too long\n"
"\n"
);
test(
"From user@host.com Wed Nov 28 13:30:05 2001\n"
"From: \"Adrian D. Thurston \" <t@cs.ca>\n"
"Subject: (kill 5)the squirrel has landed\n"
"\n"
"This message line is okay.\n"
"But this message line is far too long and will cause an error.\n"
);
return 0;
}
#ifdef _____OUTPUT_____
------
FROM
"Adrian D. Thurston" | thurston@complang.org
SUBJECT
the squirrel has landed
------
TO
"(kill 1)" Edgar Allen Poe | ep@net.com
SUBJECT
(no subject) this is a really long subject whic
DID NOT FINISH IN A FINAL STATE
------
TO
"(kill 2)" some guy | sg@net.com
FROM
"Adrian D. Thurston this name is far too long"
DID NOT FINISH IN A FINAL STATE
------
TO
"(kill 3)" some guy | sg@net.com
FROM
DID NOT FINISH IN A FINAL STATE
------
FROM
"Adrian D. Thurston " | t@cs.ca
SUBJECT
(kill 4) the squirrel has landed
DID NOT FINISH IN A FINAL STATE
------
FROM
"Adrian D. Thurston " | t@cs.ca
SUBJECT
(kill 5)the squirrel has landed
DID NOT FINISH IN A FINAL STATE
#endif
|