Commit | Line | Data |
---|---|---|
7d684d5e NW |
1 | |
2 | /* scan.l - scanner for flex input */ | |
3 | ||
4 | %{ | |
15637ed4 RG |
5 | /*- |
6 | * Copyright (c) 1990 The Regents of the University of California. | |
7 | * All rights reserved. | |
8 | * | |
9 | * This code is derived from software contributed to Berkeley by | |
7d684d5e | 10 | * Vern Paxson. |
15637ed4 | 11 | * |
7d684d5e | 12 | * The United States Government has rights in this work pursuant |
15637ed4 RG |
13 | * to contract no. DE-AC03-76SF00098 between the United States |
14 | * Department of Energy and the University of California. | |
15 | * | |
7d684d5e NW |
16 | * Redistribution and use in source and binary forms are permitted provided |
17 | * that: (1) source distributions retain this entire copyright notice and | |
18 | * comment, and (2) distributions including binaries display the following | |
19 | * acknowledgement: ``This product includes software developed by the | |
20 | * University of California, Berkeley and its contributors'' in the | |
21 | * documentation or other materials provided with the distribution and in | |
22 | * all advertising materials mentioning features or use of this software. | |
23 | * Neither the name of the University nor the names of its contributors may | |
24 | * be used to endorse or promote products derived from this software without | |
25 | * specific prior written permission. | |
26 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED | |
27 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | |
28 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
15637ed4 RG |
29 | */ |
30 | ||
7d684d5e NW |
31 | #ifndef lint |
32 | static char rcsid[] = | |
33 | "@(#) $Header: /usr/fsys/odin/a/vern/flex/RCS/scan.l,v 2.9 90/06/27 23:48:34 vern Exp $ (LBL)"; | |
34 | #endif | |
15637ed4 | 35 | |
15637ed4 RG |
36 | #undef yywrap |
37 | ||
38 | #include "flexdef.h" | |
39 | #include "parse.h" | |
40 | ||
15637ed4 RG |
41 | #define ACTION_ECHO fprintf( temp_action_file, "%s", yytext ) |
42 | #define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" ); | |
43 | ||
44 | #undef YY_DECL | |
45 | #define YY_DECL \ | |
46 | int flexscan() | |
47 | ||
48 | #define RETURNCHAR \ | |
49 | yylval = yytext[0]; \ | |
50 | return ( CHAR ); | |
51 | ||
52 | #define RETURNNAME \ | |
53 | (void) strcpy( nmstr, (char *) yytext ); \ | |
54 | return ( NAME ); | |
55 | ||
56 | #define PUT_BACK_STRING(str, start) \ | |
57 | for ( i = strlen( (char *) (str) ) - 1; i >= start; --i ) \ | |
58 | unput((str)[i]) | |
59 | ||
60 | #define CHECK_REJECT(str) \ | |
61 | if ( all_upper( str ) ) \ | |
62 | reject = true; | |
63 | ||
64 | #define CHECK_YYMORE(str) \ | |
65 | if ( all_lower( str ) ) \ | |
66 | yymore_used = true; | |
67 | %} | |
68 | ||
69 | %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE | |
70 | %x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT ACTION_COMMENT | |
71 | %x ACTION_STRING PERCENT_BRACE_ACTION USED_LIST CODEBLOCK_2 XLATION | |
72 | ||
73 | WS [ \t\f]+ | |
74 | OPTWS [ \t\f]* | |
75 | NOT_WS [^ \t\f\n] | |
76 | ||
77 | NAME [a-z_][a-z_0-9-]* | |
78 | NOT_NAME [^a-z_\n]+ | |
79 | ||
80 | SCNAME {NAME} | |
81 | ||
82 | ESCSEQ \\([^\n]|[0-9]{1,3}|x[0-9a-f]{1,2}) | |
83 | ||
84 | %% | |
85 | static int bracelevel, didadef; | |
86 | int i, indented_code, checking_used, new_xlation; | |
87 | int doing_codeblock = false; | |
88 | Char nmdef[MAXLINE], myesc(); | |
89 | ||
90 | ^{WS} indented_code = true; BEGIN(CODEBLOCK); | |
91 | ^#.*\n ++linenum; /* treat as a comment */ | |
92 | ^"/*" ECHO; BEGIN(C_COMMENT); | |
93 | ^"%s"{NAME}? return ( SCDECL ); | |
94 | ^"%x"{NAME}? return ( XSCDECL ); | |
95 | ^"%{".*\n { | |
96 | ++linenum; | |
97 | line_directive_out( stdout ); | |
98 | indented_code = false; | |
99 | BEGIN(CODEBLOCK); | |
100 | } | |
101 | ||
102 | {WS} return ( WHITESPACE ); | |
103 | ||
104 | ^"%%".* { | |
105 | sectnum = 2; | |
106 | line_directive_out( stdout ); | |
107 | BEGIN(SECT2PROLOG); | |
108 | return ( SECTEND ); | |
109 | } | |
110 | ||
111 | ^"%used" { | |
112 | pinpoint_message( "warning - %%used/%%unused have been deprecated" ); | |
113 | checking_used = REALLY_USED; BEGIN(USED_LIST); | |
114 | } | |
115 | ^"%unused" { | |
116 | checking_used = REALLY_NOT_USED; BEGIN(USED_LIST); | |
117 | pinpoint_message( "warning - %%used/%%unused have been deprecated" ); | |
118 | checking_used = REALLY_NOT_USED; BEGIN(USED_LIST); | |
119 | } | |
120 | ||
121 | ||
7d684d5e | 122 | ^"%"[aeknopt]{WS}.*\n { |
15637ed4 RG |
123 | #ifdef NOTDEF |
124 | fprintf( stderr, | |
125 | "old-style lex command at line %d ignored:\n\t%s", | |
126 | linenum, yytext ); | |
127 | #endif | |
128 | ++linenum; | |
129 | } | |
130 | ||
131 | ^"%"[cr]{OPTWS} /* ignore old lex directive */ | |
132 | ||
133 | %t{OPTWS}\n { | |
134 | ++linenum; | |
135 | xlation = | |
136 | (int *) malloc( sizeof( int ) * (unsigned) csize ); | |
137 | ||
138 | if ( ! xlation ) | |
139 | flexfatal( | |
140 | "dynamic memory failure building %t table" ); | |
141 | ||
142 | for ( i = 0; i < csize; ++i ) | |
143 | xlation[i] = 0; | |
144 | ||
145 | num_xlations = 0; | |
146 | ||
147 | BEGIN(XLATION); | |
148 | } | |
149 | ||
150 | ^"%"[^sxanpekotcru{}]{OPTWS} synerr( "unrecognized '%' directive" ); | |
151 | ||
152 | ^{NAME} { | |
153 | (void) strcpy( nmstr, (char *) yytext ); | |
154 | didadef = false; | |
155 | BEGIN(PICKUPDEF); | |
156 | } | |
157 | ||
158 | {SCNAME} RETURNNAME; | |
159 | ^{OPTWS}\n ++linenum; /* allows blank lines in section 1 */ | |
160 | {OPTWS}\n ++linenum; return ( '\n' ); | |
161 | . synerr( "illegal character" ); BEGIN(RECOVER); | |
162 | ||
163 | ||
164 | <C_COMMENT>"*/" ECHO; BEGIN(INITIAL); | |
165 | <C_COMMENT>"*/".*\n ++linenum; ECHO; BEGIN(INITIAL); | |
166 | <C_COMMENT>[^*\n]+ ECHO; | |
167 | <C_COMMENT>"*" ECHO; | |
168 | <C_COMMENT>\n ++linenum; ECHO; | |
169 | ||
170 | ||
171 | <CODEBLOCK>^"%}".*\n ++linenum; BEGIN(INITIAL); | |
172 | <CODEBLOCK>"reject" ECHO; CHECK_REJECT(yytext); | |
173 | <CODEBLOCK>"yymore" ECHO; CHECK_YYMORE(yytext); | |
174 | <CODEBLOCK>{NAME}|{NOT_NAME}|. ECHO; | |
175 | <CODEBLOCK>\n { | |
176 | ++linenum; | |
177 | ECHO; | |
178 | if ( indented_code ) | |
179 | BEGIN(INITIAL); | |
180 | } | |
181 | ||
182 | ||
183 | <PICKUPDEF>{WS} /* separates name and definition */ | |
184 | ||
185 | <PICKUPDEF>{NOT_WS}.* { | |
186 | (void) strcpy( (char *) nmdef, (char *) yytext ); | |
187 | ||
188 | for ( i = strlen( (char *) nmdef ) - 1; | |
189 | i >= 0 && | |
190 | nmdef[i] == ' ' || nmdef[i] == '\t'; | |
191 | --i ) | |
192 | ; | |
193 | ||
194 | nmdef[i + 1] = '\0'; | |
195 | ||
196 | ndinstal( nmstr, nmdef ); | |
197 | didadef = true; | |
198 | } | |
199 | ||
200 | <PICKUPDEF>\n { | |
201 | if ( ! didadef ) | |
202 | synerr( "incomplete name definition" ); | |
203 | BEGIN(INITIAL); | |
204 | ++linenum; | |
205 | } | |
206 | ||
207 | <RECOVER>.*\n ++linenum; BEGIN(INITIAL); RETURNNAME; | |
208 | ||
209 | ||
210 | <USED_LIST>\n ++linenum; BEGIN(INITIAL); | |
211 | <USED_LIST>{WS} | |
212 | <USED_LIST>"reject" { | |
213 | if ( all_upper( yytext ) ) | |
214 | reject_really_used = checking_used; | |
215 | else | |
216 | synerr( "unrecognized %used/%unused construct" ); | |
217 | } | |
218 | <USED_LIST>"yymore" { | |
219 | if ( all_lower( yytext ) ) | |
220 | yymore_really_used = checking_used; | |
221 | else | |
222 | synerr( "unrecognized %used/%unused construct" ); | |
223 | } | |
224 | <USED_LIST>{NOT_WS}+ synerr( "unrecognized %used/%unused construct" ); | |
225 | ||
226 | ||
227 | <XLATION>"%t"{OPTWS}\n ++linenum; BEGIN(INITIAL); | |
228 | <XLATION>^{OPTWS}[0-9]+ ++num_xlations; new_xlation = true; | |
229 | <XLATION>^. synerr( "bad row in translation table" ); | |
230 | <XLATION>{WS} /* ignore whitespace */ | |
231 | ||
232 | <XLATION>{ESCSEQ} { | |
233 | xlation[myesc( yytext )] = | |
234 | (new_xlation ? num_xlations : -num_xlations); | |
235 | new_xlation = false; | |
236 | } | |
237 | <XLATION>. { | |
238 | xlation[yytext[0]] = | |
239 | (new_xlation ? num_xlations : -num_xlations); | |
240 | new_xlation = false; | |
241 | } | |
242 | ||
243 | <XLATION>\n ++linenum; | |
244 | ||
245 | ||
246 | <SECT2PROLOG>.*\n/{NOT_WS} { | |
247 | ++linenum; | |
248 | ACTION_ECHO; | |
249 | MARK_END_OF_PROLOG; | |
250 | BEGIN(SECT2); | |
251 | } | |
252 | ||
253 | <SECT2PROLOG>.*\n ++linenum; ACTION_ECHO; | |
254 | ||
255 | <SECT2PROLOG><<EOF>> MARK_END_OF_PROLOG; yyterminate(); | |
256 | ||
257 | <SECT2>^{OPTWS}\n ++linenum; /* allow blank lines in section 2 */ | |
258 | ||
259 | <SECT2>^({WS}|"%{") { | |
260 | indented_code = (yytext[0] != '%'); | |
261 | doing_codeblock = true; | |
262 | bracelevel = 1; | |
263 | ||
264 | if ( indented_code ) | |
265 | ACTION_ECHO; | |
266 | ||
267 | BEGIN(CODEBLOCK_2); | |
268 | } | |
269 | ||
270 | <SECT2>"<" BEGIN(SC); return ( '<' ); | |
271 | <SECT2>^"^" return ( '^' ); | |
272 | <SECT2>\" BEGIN(QUOTE); return ( '"' ); | |
273 | <SECT2>"{"/[0-9] BEGIN(NUM); return ( '{' ); | |
274 | <SECT2>"{"[^0-9\n][^}\n]* BEGIN(BRACEERROR); | |
275 | <SECT2>"$"/[ \t\n] return ( '$' ); | |
276 | ||
277 | <SECT2>{WS}"%{" { | |
278 | bracelevel = 1; | |
279 | BEGIN(PERCENT_BRACE_ACTION); | |
280 | return ( '\n' ); | |
281 | } | |
282 | <SECT2>{WS}"|".*\n continued_action = true; ++linenum; return ( '\n' ); | |
283 | ||
284 | <SECT2>{WS} { | |
285 | /* this rule is separate from the one below because | |
286 | * otherwise we get variable trailing context, so | |
287 | * we can't build the scanner using -{f,F} | |
288 | */ | |
289 | bracelevel = 0; | |
290 | continued_action = false; | |
291 | BEGIN(ACTION); | |
292 | return ( '\n' ); | |
293 | } | |
294 | ||
295 | <SECT2>{OPTWS}/\n { | |
296 | bracelevel = 0; | |
297 | continued_action = false; | |
298 | BEGIN(ACTION); | |
299 | return ( '\n' ); | |
300 | } | |
301 | ||
302 | <SECT2>^{OPTWS}\n ++linenum; return ( '\n' ); | |
303 | ||
304 | <SECT2>"<<EOF>>" return ( EOF_OP ); | |
305 | ||
306 | <SECT2>^"%%".* { | |
307 | sectnum = 3; | |
308 | BEGIN(SECT3); | |
309 | return ( EOF ); /* to stop the parser */ | |
310 | } | |
311 | ||
312 | <SECT2>"["([^\\\]\n]|{ESCSEQ})+"]" { | |
313 | int cclval; | |
314 | ||
315 | (void) strcpy( nmstr, (char *) yytext ); | |
316 | ||
317 | /* check to see if we've already encountered this ccl */ | |
318 | if ( (cclval = ccllookup( (Char *) nmstr )) ) | |
319 | { | |
320 | yylval = cclval; | |
321 | ++cclreuse; | |
322 | return ( PREVCCL ); | |
323 | } | |
324 | else | |
325 | { | |
326 | /* we fudge a bit. We know that this ccl will | |
327 | * soon be numbered as lastccl + 1 by cclinit | |
328 | */ | |
329 | cclinstal( (Char *) nmstr, lastccl + 1 ); | |
330 | ||
331 | /* push back everything but the leading bracket | |
332 | * so the ccl can be rescanned | |
333 | */ | |
334 | PUT_BACK_STRING((Char *) nmstr, 1); | |
335 | ||
336 | BEGIN(FIRSTCCL); | |
337 | return ( '[' ); | |
338 | } | |
339 | } | |
340 | ||
341 | <SECT2>"{"{NAME}"}" { | |
342 | register Char *nmdefptr; | |
343 | Char *ndlookup(); | |
344 | ||
345 | (void) strcpy( nmstr, (char *) yytext ); | |
346 | nmstr[yyleng - 1] = '\0'; /* chop trailing brace */ | |
347 | ||
348 | /* lookup from "nmstr + 1" to chop leading brace */ | |
349 | if ( ! (nmdefptr = ndlookup( nmstr + 1 )) ) | |
350 | synerr( "undefined {name}" ); | |
351 | ||
352 | else | |
353 | { /* push back name surrounded by ()'s */ | |
354 | unput(')'); | |
355 | PUT_BACK_STRING(nmdefptr, 0); | |
356 | unput('('); | |
357 | } | |
358 | } | |
359 | ||
360 | <SECT2>[/|*+?.()] return ( yytext[0] ); | |
361 | <SECT2>. RETURNCHAR; | |
362 | <SECT2>\n ++linenum; return ( '\n' ); | |
363 | ||
364 | ||
365 | <SC>"," return ( ',' ); | |
366 | <SC>">" BEGIN(SECT2); return ( '>' ); | |
367 | <SC>">"/"^" BEGIN(CARETISBOL); return ( '>' ); | |
368 | <SC>{SCNAME} RETURNNAME; | |
369 | <SC>. synerr( "bad start condition name" ); | |
370 | ||
371 | <CARETISBOL>"^" BEGIN(SECT2); return ( '^' ); | |
372 | ||
373 | ||
374 | <QUOTE>[^"\n] RETURNCHAR; | |
375 | <QUOTE>\" BEGIN(SECT2); return ( '"' ); | |
376 | ||
377 | <QUOTE>\n { | |
378 | synerr( "missing quote" ); | |
379 | BEGIN(SECT2); | |
380 | ++linenum; | |
381 | return ( '"' ); | |
382 | } | |
383 | ||
384 | ||
385 | <FIRSTCCL>"^"/[^-\n] BEGIN(CCL); return ( '^' ); | |
386 | <FIRSTCCL>"^"/- return ( '^' ); | |
387 | <FIRSTCCL>- BEGIN(CCL); yylval = '-'; return ( CHAR ); | |
388 | <FIRSTCCL>. BEGIN(CCL); RETURNCHAR; | |
389 | ||
390 | <CCL>-/[^\]\n] return ( '-' ); | |
391 | <CCL>[^\]\n] RETURNCHAR; | |
392 | <CCL>"]" BEGIN(SECT2); return ( ']' ); | |
393 | ||
394 | ||
395 | <NUM>[0-9]+ { | |
396 | yylval = myctoi( yytext ); | |
397 | return ( NUMBER ); | |
398 | } | |
399 | ||
400 | <NUM>"," return ( ',' ); | |
401 | <NUM>"}" BEGIN(SECT2); return ( '}' ); | |
402 | ||
403 | <NUM>. { | |
404 | synerr( "bad character inside {}'s" ); | |
405 | BEGIN(SECT2); | |
406 | return ( '}' ); | |
407 | } | |
408 | ||
409 | <NUM>\n { | |
410 | synerr( "missing }" ); | |
411 | BEGIN(SECT2); | |
412 | ++linenum; | |
413 | return ( '}' ); | |
414 | } | |
415 | ||
416 | ||
417 | <BRACEERROR>"}" synerr( "bad name in {}'s" ); BEGIN(SECT2); | |
418 | <BRACEERROR>\n synerr( "missing }" ); ++linenum; BEGIN(SECT2); | |
419 | ||
420 | ||
421 | <PERCENT_BRACE_ACTION,CODEBLOCK_2>{OPTWS}"%}".* bracelevel = 0; | |
422 | <PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"reject" { | |
423 | ACTION_ECHO; | |
424 | CHECK_REJECT(yytext); | |
425 | } | |
426 | <PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"yymore" { | |
427 | ACTION_ECHO; | |
428 | CHECK_YYMORE(yytext); | |
429 | } | |
430 | <PERCENT_BRACE_ACTION,CODEBLOCK_2>{NAME}|{NOT_NAME}|. ACTION_ECHO; | |
431 | <PERCENT_BRACE_ACTION,CODEBLOCK_2>\n { | |
432 | ++linenum; | |
433 | ACTION_ECHO; | |
434 | if ( bracelevel == 0 || | |
435 | (doing_codeblock && indented_code) ) | |
436 | { | |
437 | if ( ! doing_codeblock ) | |
438 | fputs( "\tYY_BREAK\n", temp_action_file ); | |
439 | ||
440 | doing_codeblock = false; | |
441 | BEGIN(SECT2); | |
442 | } | |
443 | } | |
444 | ||
445 | ||
446 | /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */ | |
447 | <ACTION>"{" ACTION_ECHO; ++bracelevel; | |
448 | <ACTION>"}" ACTION_ECHO; --bracelevel; | |
449 | <ACTION>[^a-z_{}"'/\n]+ ACTION_ECHO; | |
450 | <ACTION>{NAME} ACTION_ECHO; | |
451 | <ACTION>"/*" ACTION_ECHO; BEGIN(ACTION_COMMENT); | |
452 | <ACTION>"'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */ | |
453 | <ACTION>\" ACTION_ECHO; BEGIN(ACTION_STRING); | |
454 | <ACTION>\n { | |
455 | ++linenum; | |
456 | ACTION_ECHO; | |
457 | if ( bracelevel == 0 ) | |
458 | { | |
459 | fputs( "\tYY_BREAK\n", temp_action_file ); | |
460 | BEGIN(SECT2); | |
461 | } | |
462 | } | |
463 | <ACTION>. ACTION_ECHO; | |
464 | ||
465 | <ACTION_COMMENT>"*/" ACTION_ECHO; BEGIN(ACTION); | |
466 | <ACTION_COMMENT>[^*\n]+ ACTION_ECHO; | |
467 | <ACTION_COMMENT>"*" ACTION_ECHO; | |
468 | <ACTION_COMMENT>\n ++linenum; ACTION_ECHO; | |
469 | <ACTION_COMMENT>. ACTION_ECHO; | |
470 | ||
471 | <ACTION_STRING>[^"\\\n]+ ACTION_ECHO; | |
472 | <ACTION_STRING>\\. ACTION_ECHO; | |
473 | <ACTION_STRING>\n ++linenum; ACTION_ECHO; | |
474 | <ACTION_STRING>\" ACTION_ECHO; BEGIN(ACTION); | |
475 | <ACTION_STRING>. ACTION_ECHO; | |
476 | ||
477 | <ACTION,ACTION_COMMENT,ACTION_STRING><<EOF>> { | |
478 | synerr( "EOF encountered inside an action" ); | |
479 | yyterminate(); | |
480 | } | |
481 | ||
482 | ||
483 | <SECT2,QUOTE,CCL>{ESCSEQ} { | |
484 | yylval = myesc( yytext ); | |
485 | return ( CHAR ); | |
486 | } | |
487 | ||
488 | <FIRSTCCL>{ESCSEQ} { | |
489 | yylval = myesc( yytext ); | |
490 | BEGIN(CCL); | |
491 | return ( CHAR ); | |
492 | } | |
493 | ||
494 | ||
495 | <SECT3>.*(\n?) ECHO; | |
496 | %% | |
497 | ||
498 | ||
499 | int yywrap() | |
500 | ||
501 | { | |
502 | if ( --num_input_files > 0 ) | |
503 | { | |
504 | set_input_file( *++input_files ); | |
505 | return ( 0 ); | |
506 | } | |
507 | ||
508 | else | |
509 | return ( 1 ); | |
510 | } | |
511 | ||
512 | ||
513 | /* set_input_file - open the given file (if NULL, stdin) for scanning */ | |
514 | ||
515 | void set_input_file( file ) | |
516 | char *file; | |
517 | ||
518 | { | |
519 | if ( file ) | |
520 | { | |
521 | infilename = file; | |
522 | yyin = fopen( infilename, "r" ); | |
523 | ||
524 | if ( yyin == NULL ) | |
525 | lerrsf( "can't open %s", file ); | |
526 | } | |
527 | ||
528 | else | |
529 | { | |
530 | yyin = stdin; | |
531 | infilename = "<stdin>"; | |
532 | } | |
533 | } |