2 /* scan.l - scanner for flex input */
6 * Copyright (c) 1990 The Regents of the University of California.
9 * This code is derived from software contributed to Berkeley by
12 * The United States Government has rights in this work pursuant
13 * to contract no. DE-AC03-76SF00098 between the United States
14 * Department of Energy and the University of California.
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.
33 "@(#) $Id: scan.l,v 1.2 1994/06/24 10:57:25 ceriel Exp $ (LBL)";
41 #define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
42 #define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
53 (void) strcpy( nmstr, (char *) yytext ); \
56 #define PUT_BACK_STRING(str, start) \
57 for ( i = strlen( (char *) (str) ) - 1; i >= start; --i ) \
60 #define CHECK_REJECT(str) \
61 if ( all_upper( str ) ) \
64 #define CHECK_YYMORE(str) \
65 if ( all_lower( str ) ) \
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
77 NAME [a-z_][a-z_0-9-]*
82 ESCSEQ \\([^\n]|[0-9]{1,3}|x[0-9a-f]{1,2})
85 static int bracelevel, didadef;
86 int i, indented_code, checking_used, new_xlation;
87 int doing_codeblock = false;
88 Char nmdef[MAXLINE], myesc();
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 );
97 line_directive_out( stdout );
98 indented_code = false;
102 {WS} return ( WHITESPACE );
106 line_directive_out( stdout );
112 pinpoint_message( "warning - %%used/%%unused have been deprecated" );
113 checking_used = REALLY_USED; BEGIN(USED_LIST);
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);
122 ^"%"[aeknopt]" ".*\n {
125 "old-style lex command at line %d ignored:\n\t%s",
131 ^"%"[cr]{OPTWS} /* ignore old lex directive */
136 (int *) malloc( sizeof( int ) * (unsigned) csize );
140 "dynamic memory failure building %t table" );
142 for ( i = 0; i < csize; ++i )
150 ^"%"[^sxanpekotcru{}]{OPTWS} synerr( "unrecognized '%' directive" );
153 (void) strcpy( nmstr, (char *) yytext );
159 ^{OPTWS}\n ++linenum; /* allows blank lines in section 1 */
160 {OPTWS}\n ++linenum; return ( '\n' );
161 . synerr( "illegal character" ); BEGIN(RECOVER);
164 <C_COMMENT>"*/" ECHO; BEGIN(INITIAL);
165 <C_COMMENT>"*/".*\n ++linenum; ECHO; BEGIN(INITIAL);
166 <C_COMMENT>[^*\n]+ ECHO;
168 <C_COMMENT>\n ++linenum; ECHO;
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;
183 <PICKUPDEF>{WS} /* separates name and definition */
185 <PICKUPDEF>{NOT_WS}.* {
186 (void) strcpy( (char *) nmdef, (char *) yytext );
188 for ( i = strlen( (char *) nmdef ) - 1;
190 nmdef[i] == ' ' || nmdef[i] == '\t';
196 ndinstal( nmstr, nmdef );
202 synerr( "incomplete name definition" );
207 <RECOVER>.*\n ++linenum; BEGIN(INITIAL); RETURNNAME;
210 <USED_LIST>\n ++linenum; BEGIN(INITIAL);
212 <USED_LIST>"reject" {
213 if ( all_upper( yytext ) )
214 reject_really_used = checking_used;
216 synerr( "unrecognized %used/%unused construct" );
218 <USED_LIST>"yymore" {
219 if ( all_lower( yytext ) )
220 yymore_really_used = checking_used;
222 synerr( "unrecognized %used/%unused construct" );
224 <USED_LIST>{NOT_WS}+ synerr( "unrecognized %used/%unused construct" );
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 */
233 xlation[myesc( yytext )] =
234 (new_xlation ? num_xlations : -num_xlations);
239 (new_xlation ? num_xlations : -num_xlations);
243 <XLATION>\n ++linenum;
246 <SECT2PROLOG>.*\n/{NOT_WS} {
253 <SECT2PROLOG>.*\n ++linenum; ACTION_ECHO;
255 <SECT2PROLOG><<EOF>> MARK_END_OF_PROLOG; yyterminate();
257 <SECT2>^{OPTWS}\n ++linenum; /* allow blank lines in section 2 */
259 <SECT2>^({WS}|"%{") {
260 indented_code = (yytext[0] != '%');
261 doing_codeblock = true;
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 ( '$' );
279 BEGIN(PERCENT_BRACE_ACTION);
282 <SECT2>{WS}"|".*\n continued_action = true; ++linenum; return ( '\n' );
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}
290 continued_action = false;
297 continued_action = false;
302 <SECT2>^{OPTWS}\n ++linenum; return ( '\n' );
304 <SECT2>"<<EOF>>" return ( EOF_OP );
309 return ( EOF ); /* to stop the parser */
312 <SECT2>"["([^\\\]\n]|{ESCSEQ})+"]" {
315 (void) strcpy( nmstr, (char *) yytext );
317 /* check to see if we've already encountered this ccl */
318 if ( (cclval = ccllookup( (Char *) nmstr )) )
326 /* we fudge a bit. We know that this ccl will
327 * soon be numbered as lastccl + 1 by cclinit
329 cclinstal( (Char *) nmstr, lastccl + 1 );
331 /* push back everything but the leading bracket
332 * so the ccl can be rescanned
334 PUT_BACK_STRING((Char *) nmstr, 1);
341 <SECT2>"{"{NAME}"}" {
342 register Char *nmdefptr;
345 (void) strcpy( nmstr, (char *) yytext );
346 nmstr[yyleng - 1] = '\0'; /* chop trailing brace */
348 /* lookup from "nmstr + 1" to chop leading brace */
349 if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
350 synerr( "undefined {name}" );
353 { /* push back name surrounded by ()'s */
355 PUT_BACK_STRING(nmdefptr, 0);
360 <SECT2>[/|*+?.()] return ( yytext[0] );
362 <SECT2>\n ++linenum; return ( '\n' );
365 <SC>"," return ( ',' );
366 <SC>">" BEGIN(SECT2); return ( '>' );
367 <SC>">"/"^" BEGIN(CARETISBOL); return ( '>' );
368 <SC>{SCNAME} RETURNNAME;
369 <SC>. synerr( "bad start condition name" );
371 <CARETISBOL>"^" BEGIN(SECT2); return ( '^' );
374 <QUOTE>[^"\n] RETURNCHAR;
375 <QUOTE>\" BEGIN(SECT2); return ( '"' );
378 synerr( "missing quote" );
385 <FIRSTCCL>"^"/[^-\n] BEGIN(CCL); return ( '^' );
386 <FIRSTCCL>"^"/- return ( '^' );
387 <FIRSTCCL>- BEGIN(CCL); yylval = '-'; return ( CHAR );
388 <FIRSTCCL>. BEGIN(CCL); RETURNCHAR;
390 <CCL>-/[^\]\n] return ( '-' );
391 <CCL>[^\]\n] RETURNCHAR;
392 <CCL>"]" BEGIN(SECT2); return ( ']' );
396 yylval = myctoi( yytext );
400 <NUM>"," return ( ',' );
401 <NUM>"}" BEGIN(SECT2); return ( '}' );
404 synerr( "bad character inside {}'s" );
410 synerr( "missing }" );
417 <BRACEERROR>"}" synerr( "bad name in {}'s" ); BEGIN(SECT2);
418 <BRACEERROR>\n synerr( "missing }" ); ++linenum; BEGIN(SECT2);
421 <PERCENT_BRACE_ACTION,CODEBLOCK_2>{OPTWS}"%}".* bracelevel = 0;
422 <PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"reject" {
424 CHECK_REJECT(yytext);
426 <PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"yymore" {
428 CHECK_YYMORE(yytext);
430 <PERCENT_BRACE_ACTION,CODEBLOCK_2>{NAME}|{NOT_NAME}|. ACTION_ECHO;
431 <PERCENT_BRACE_ACTION,CODEBLOCK_2>\n {
434 if ( bracelevel == 0 ||
435 (doing_codeblock && indented_code) )
437 if ( ! doing_codeblock )
438 fputs( "\tYY_BREAK\n", temp_action_file );
440 doing_codeblock = false;
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);
457 if ( bracelevel == 0 )
459 fputs( "\tYY_BREAK\n", temp_action_file );
463 <ACTION>. ACTION_ECHO;
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;
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;
477 <ACTION,ACTION_COMMENT,ACTION_STRING><<EOF>> {
478 synerr( "EOF encountered inside an action" );
483 <SECT2,QUOTE,CCL>{ESCSEQ} {
484 yylval = myesc( yytext );
489 yylval = myesc( yytext );
502 if ( --num_input_files > 0 )
504 set_input_file( *++input_files );
513 /* set_input_file - open the given file (if NULL, stdin) for scanning */
515 void set_input_file( file )
522 yyin = fopen( infilename, "r" );
525 lerrsf( "can't open %s", file );
531 infilename = "<stdin>";