Merged the FsmCodeGen, TabCodeGen and JavaTabCodeGen classes. Updated the
[external/ragel.git] / test / mailbox1.rl
1 /*
2  * @LANG: c++
3  * @CFLAGS: -I../aapl
4  * @ALLOW_GENFLAGS: -T0 -T1 -F0 -F1 -G0 -G1 -G2 -P
5  */
6
7 /*
8  * Parses unix mail boxes into headers and bodies.
9  */
10
11 #include "mailbox1.h"
12
13 %%{
14         machine MBox;
15
16         # Buffer the header names.
17         action bufHeadName { fsm->headName.append(fc); }
18
19         # Buffer the header content.
20         action bufHeadContent { fsm->headContent.append(fc); }
21
22         # Terminate a header. If it is an interesting header then prints it.
23         action finBufHeadContent {
24                 /* Terminate the buffers. */
25                 fsm->headName.append(0);
26                 fsm->headContent.append(0);
27
28                 /* Print the header. Interesting headers. */
29                 printf("%s:%s\n", fsm->headName.data, fsm->headContent.data);
30                 
31                 /* Clear for the next time we use them. */
32                 fsm->headName.empty();
33                 fsm->headContent.empty();
34         }
35
36         action msgstart{
37                 printf("NEW MESSAGE\n");
38         }
39
40         # Prints a blank line after the end of the headers of each message.
41         action blankLine {
42                 printf("\n");
43         }
44         
45         # Helpers we will use in matching the date section of the from line.
46         day = /[A-Z][a-z][a-z]/;
47         month = /[A-Z][a-z][a-z]/;
48         year = /[0-9][0-9][0-9][0-9]/;
49         time = /[0-9][0-9]:[0-9][0-9]/ . ( /:[0-9][0-9]/ | '' );
50         letterZone = /[A-Z][A-Z][A-Z]/;
51         numZone = /[+\-][0-9][0-9][0-9][0-9]/;
52         zone = letterZone | numZone;
53         dayNum = /[0-9 ][0-9]/;
54
55         # These are the different formats of the date minus an obscure
56         # type that has a funny string 'remote from xxx' on the end. Taken
57         # from c-client in the imap-2000 distribution.
58         date = day . ' ' . month . ' ' . dayNum . ' ' . time . ' ' .
59                 ( year | year . ' ' . zone | zone . ' ' . year );
60
61         # Note the priority assignment on the end of the from line. While we
62         # matching the body of a message we may enter into this machine. We will
63         # not leave the body of the previous message until this entire from line is
64         # matched. 
65         fromLine = 'From ' . /[^\n]/* . ' ' . date . '\n' @(new_msg,1) @msgstart;
66
67         # The types of characters that can be used as a header name.
68         hchar = print - [ :];
69
70         header =
71                 # The name of the header.
72                 hchar+ $bufHeadName . ':' 
73                 # The content of the header. Look out for continuations.
74                 . ( (extend - '\n') $bufHeadContent | '\n'. [ \t] @bufHeadContent )*
75                 # Buffer must end with a newline that does not continue.
76                 . '\n' %finBufHeadContent;
77
78         messageLine = ( extend - '\n' )* . '\n' @(new_msg, 0);
79
80         # When we get to the last newline we are still matching messageLine
81         # so on the last newline it will think we are still in the message.
82         # We need this because we can't assume that every newline means
83         # the end of the current message, whereas at the same time we requre
84         # that there be a newline before the fromLine of the next message.
85         message = ( fromLine .  header* .  '\n' @blankLine .  messageLine* . '\n' );
86
87         # Its important that the priority in the fromLine gets bumped up
88         # so that we are able to move to new messages. Otherwise we
89         # will always stay in the message body of the first message.
90         main := message*;
91 }%%
92
93 %% write data;
94
95 void MBox::init( )
96 {
97         MBox *fsm = this;
98         %% write init;
99 }
100
101 void MBox::execute( char *data, int len )
102 {
103         MBox *fsm = this;
104         char *p = data;
105         char *pe = data + len;
106         %%{
107                 access fsm->;
108                 write exec;
109         }%%
110 }
111
112 int MBox::finish( )
113 {
114         if ( cs == MBox_error )
115                 return -1;
116         if ( cs >= MBox_first_final )
117                 return 1;
118         return 0;
119 }
120
121 MBox mbox;
122
123 void test( char *buf )
124 {
125         int len = strlen( buf );
126         mbox.init();
127         mbox.execute( buf, len );
128         if ( mbox.finish() > 0 )
129                 printf("ACCEPT\n");
130         else
131                 printf("FAIL\n");
132 }
133
134
135 int main()
136 {
137         test(
138                 "From email address goes here Wed Nov 28 13:30:05 2001 -0500\n"
139                 "Header1: this is the header contents\n"
140                 " there is more on the second line\n"
141                 "       and more on the third line.\n"
142                 "Header2: slkdj\n"
143                 "\n"
144                 "This is the message data\n"
145                 "\n"
146                 "From email Wed Nov 28 13:30:05 2001 -0500\n"
147                 "Header: \n"
148                 "\n"
149                 "mail message\n"
150                 "\n"
151         );
152
153         test(
154                 "From user@host.dom Wed Nov 28 13:30:05 2001\n"
155                 "\n"
156                 "There are no headers. \n"
157                 "\n"
158                 "From email Wed Nov 28 13:30:05 EST 2000\n"
159                 "\n"
160                 "There are no headers.\n"
161                 "\n"
162         );
163
164         test(
165                 "From user@host.dom Wed Nov 28 13:30:05 2001\n"
166                 "Header:alsdj\n"
167                 "\n"
168                 "Header:\n"
169                 "salkfj\n"
170                 "\n"
171                 "There are no headers. \n"
172                 "\n"
173         );
174
175         test(
176                 "From user@host.dom Wed Nov 28 13:30:05 2001\n"
177                 "Header:alsdj\n"
178                 "\n"
179                 "Header:\n"
180                 "salkfj\n"
181                 "\n"
182                 "There are no headers. \n"
183                 "\n"
184                 ">From user@host.dom Wed Nov 28 13:30:05 2001\n"
185                 "\n"
186         );
187
188         test(
189                 "From user@host.dom Wed Nov 28 13:30:05 2001\n"
190                 "Header:alsdj\n"
191                 "\n"
192                 "Header:\n"
193                 "salkfj\n"
194                 "\n"
195                 "There are no headers. \n"
196                 "\n"
197                 "From user@host.dom Wed Nov 28 13:30:05 2001\n"
198                 "\n"
199         );
200
201         test(
202                 "From user@host.dom Wed Nov 28 13:30:05 2001\n"
203                 "Header:alsdj\n"
204                 "\n"
205                 "Header:\n"
206                 "salkfj\n"
207                 "\n"
208                 "There are no headers. \n"
209                 "\n"
210                 "From user@host.dom Wed Nov 28 13:30:05 2001\n"
211                 "\n"
212                 "\n"
213         );
214
215         return 0;
216 }
217
218 #ifdef _____OUTPUT_____
219 NEW MESSAGE
220 Header1: this is the header contents there is more on the second line   and more on the third line.
221 Header2: slkdj
222
223 NEW MESSAGE
224 Header: 
225
226 ACCEPT
227 NEW MESSAGE
228
229 NEW MESSAGE
230
231 ACCEPT
232 NEW MESSAGE
233 Header:alsdj
234
235 ACCEPT
236 NEW MESSAGE
237 Header:alsdj
238
239 ACCEPT
240 NEW MESSAGE
241 Header:alsdj
242
243 NEW MESSAGE
244
245 FAIL
246 NEW MESSAGE
247 Header:alsdj
248
249 NEW MESSAGE
250
251 ACCEPT
252 #endif