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