/* scan.l - scanner for flex input */ %{ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Vern Paxson. * * The United States Government has rights in this work pursuant * to contract no. DE-AC03-76SF00098 between the United States * Department of Energy and the University of California. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static char rcsid[] = "@(#) $Id$ (LBL)"; #endif #undef yywrap #include "flexdef.h" #include "parse.h" #define ACTION_ECHO fprintf( temp_action_file, "%s", yytext ) #define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" ); #undef YY_DECL #define YY_DECL \ int flexscan() #define RETURNCHAR \ yylval = yytext[0]; \ return ( CHAR ); #define RETURNNAME \ (void) strcpy( nmstr, (char *) yytext ); \ return ( NAME ); #define PUT_BACK_STRING(str, start) \ for ( i = strlen( (char *) (str) ) - 1; i >= start; --i ) \ unput((str)[i]) #define CHECK_REJECT(str) \ if ( all_upper( str ) ) \ reject = true; #define CHECK_YYMORE(str) \ if ( all_lower( str ) ) \ yymore_used = true; %} %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE %x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT ACTION_COMMENT %x ACTION_STRING PERCENT_BRACE_ACTION USED_LIST CODEBLOCK_2 XLATION WS [ \t\f]+ OPTWS [ \t\f]* NOT_WS [^ \t\f\n] NAME [a-z_][a-z_0-9-]* NOT_NAME [^a-z_\n]+ SCNAME {NAME} ESCSEQ \\([^\n]|[0-9]{1,3}|x[0-9a-f]{1,2}) %% static int bracelevel, didadef; int i, indented_code, checking_used, new_xlation; int doing_codeblock = false; Char nmdef[MAXLINE], myesc(); ^{WS} indented_code = true; BEGIN(CODEBLOCK); ^#.*\n ++linenum; /* treat as a comment */ ^"/*" ECHO; BEGIN(C_COMMENT); ^"%s"{NAME}? return ( SCDECL ); ^"%x"{NAME}? return ( XSCDECL ); ^"%{".*\n { ++linenum; line_directive_out( stdout ); indented_code = false; BEGIN(CODEBLOCK); } {WS} return ( WHITESPACE ); ^"%%".* { sectnum = 2; line_directive_out( stdout ); BEGIN(SECT2PROLOG); return ( SECTEND ); } ^"%used" { pinpoint_message( "warning - %%used/%%unused have been deprecated" ); checking_used = REALLY_USED; BEGIN(USED_LIST); } ^"%unused" { checking_used = REALLY_NOT_USED; BEGIN(USED_LIST); pinpoint_message( "warning - %%used/%%unused have been deprecated" ); checking_used = REALLY_NOT_USED; BEGIN(USED_LIST); } ^"%"[aeknopt]" ".*\n { #ifdef NOTDEF fprintf( stderr, "old-style lex command at line %d ignored:\n\t%s", linenum, yytext ); #endif ++linenum; } ^"%"[cr]{OPTWS} /* ignore old lex directive */ %t{OPTWS}\n { ++linenum; xlation = (int *) malloc( sizeof( int ) * (unsigned) csize ); if ( ! xlation ) flexfatal( "dynamic memory failure building %t table" ); for ( i = 0; i < csize; ++i ) xlation[i] = 0; num_xlations = 0; BEGIN(XLATION); } ^"%"[^sxanpekotcru{}]{OPTWS} synerr( "unrecognized '%' directive" ); ^{NAME} { (void) strcpy( nmstr, (char *) yytext ); didadef = false; BEGIN(PICKUPDEF); } {SCNAME} RETURNNAME; ^{OPTWS}\n ++linenum; /* allows blank lines in section 1 */ {OPTWS}\n ++linenum; return ( '\n' ); . synerr( "illegal character" ); BEGIN(RECOVER); "*/" ECHO; BEGIN(INITIAL); "*/".*\n ++linenum; ECHO; BEGIN(INITIAL); [^*\n]+ ECHO; "*" ECHO; \n ++linenum; ECHO; ^"%}".*\n ++linenum; BEGIN(INITIAL); "reject" ECHO; CHECK_REJECT(yytext); "yymore" ECHO; CHECK_YYMORE(yytext); {NAME}|{NOT_NAME}|. ECHO; \n { ++linenum; ECHO; if ( indented_code ) BEGIN(INITIAL); } {WS} /* separates name and definition */ {NOT_WS}.* { (void) strcpy( (char *) nmdef, (char *) yytext ); for ( i = strlen( (char *) nmdef ) - 1; i >= 0 && nmdef[i] == ' ' || nmdef[i] == '\t'; --i ) ; nmdef[i + 1] = '\0'; ndinstal( nmstr, nmdef ); didadef = true; } \n { if ( ! didadef ) synerr( "incomplete name definition" ); BEGIN(INITIAL); ++linenum; } .*\n ++linenum; BEGIN(INITIAL); RETURNNAME; \n ++linenum; BEGIN(INITIAL); {WS} "reject" { if ( all_upper( yytext ) ) reject_really_used = checking_used; else synerr( "unrecognized %used/%unused construct" ); } "yymore" { if ( all_lower( yytext ) ) yymore_really_used = checking_used; else synerr( "unrecognized %used/%unused construct" ); } {NOT_WS}+ synerr( "unrecognized %used/%unused construct" ); "%t"{OPTWS}\n ++linenum; BEGIN(INITIAL); ^{OPTWS}[0-9]+ ++num_xlations; new_xlation = true; ^. synerr( "bad row in translation table" ); {WS} /* ignore whitespace */ {ESCSEQ} { xlation[myesc( yytext )] = (new_xlation ? num_xlations : -num_xlations); new_xlation = false; } . { xlation[yytext[0]] = (new_xlation ? num_xlations : -num_xlations); new_xlation = false; } \n ++linenum; .*\n/{NOT_WS} { ++linenum; ACTION_ECHO; MARK_END_OF_PROLOG; BEGIN(SECT2); } .*\n ++linenum; ACTION_ECHO; <> MARK_END_OF_PROLOG; yyterminate(); ^{OPTWS}\n ++linenum; /* allow blank lines in section 2 */ ^({WS}|"%{") { indented_code = (yytext[0] != '%'); doing_codeblock = true; bracelevel = 1; if ( indented_code ) ACTION_ECHO; BEGIN(CODEBLOCK_2); } "<" BEGIN(SC); return ( '<' ); ^"^" return ( '^' ); \" BEGIN(QUOTE); return ( '"' ); "{"/[0-9] BEGIN(NUM); return ( '{' ); "{"[^0-9\n][^}\n]* BEGIN(BRACEERROR); "$"/[ \t\n] return ( '$' ); {WS}"%{" { bracelevel = 1; BEGIN(PERCENT_BRACE_ACTION); return ( '\n' ); } {WS}"|".*\n continued_action = true; ++linenum; return ( '\n' ); {WS} { /* this rule is separate from the one below because * otherwise we get variable trailing context, so * we can't build the scanner using -{f,F} */ bracelevel = 0; continued_action = false; BEGIN(ACTION); return ( '\n' ); } {OPTWS}/\n { bracelevel = 0; continued_action = false; BEGIN(ACTION); return ( '\n' ); } ^{OPTWS}\n ++linenum; return ( '\n' ); "<>" return ( EOF_OP ); ^"%%".* { sectnum = 3; BEGIN(SECT3); return ( EOF ); /* to stop the parser */ } "["([^\\\]\n]|{ESCSEQ})+"]" { int cclval; (void) strcpy( nmstr, (char *) yytext ); /* check to see if we've already encountered this ccl */ if ( (cclval = ccllookup( (Char *) nmstr )) ) { yylval = cclval; ++cclreuse; return ( PREVCCL ); } else { /* we fudge a bit. We know that this ccl will * soon be numbered as lastccl + 1 by cclinit */ cclinstal( (Char *) nmstr, lastccl + 1 ); /* push back everything but the leading bracket * so the ccl can be rescanned */ PUT_BACK_STRING((Char *) nmstr, 1); BEGIN(FIRSTCCL); return ( '[' ); } } "{"{NAME}"}" { register Char *nmdefptr; Char *ndlookup(); (void) strcpy( nmstr, (char *) yytext ); nmstr[yyleng - 1] = '\0'; /* chop trailing brace */ /* lookup from "nmstr + 1" to chop leading brace */ if ( ! (nmdefptr = ndlookup( nmstr + 1 )) ) synerr( "undefined {name}" ); else { /* push back name surrounded by ()'s */ unput(')'); PUT_BACK_STRING(nmdefptr, 0); unput('('); } } [/|*+?.()] return ( yytext[0] ); . RETURNCHAR; \n ++linenum; return ( '\n' ); "," return ( ',' ); ">" BEGIN(SECT2); return ( '>' ); ">"/"^" BEGIN(CARETISBOL); return ( '>' ); {SCNAME} RETURNNAME; . synerr( "bad start condition name" ); "^" BEGIN(SECT2); return ( '^' ); [^"\n] RETURNCHAR; \" BEGIN(SECT2); return ( '"' ); \n { synerr( "missing quote" ); BEGIN(SECT2); ++linenum; return ( '"' ); } "^"/[^-\n] BEGIN(CCL); return ( '^' ); "^"/- return ( '^' ); - BEGIN(CCL); yylval = '-'; return ( CHAR ); . BEGIN(CCL); RETURNCHAR; -/[^\]\n] return ( '-' ); [^\]\n] RETURNCHAR; "]" BEGIN(SECT2); return ( ']' ); [0-9]+ { yylval = myctoi( yytext ); return ( NUMBER ); } "," return ( ',' ); "}" BEGIN(SECT2); return ( '}' ); . { synerr( "bad character inside {}'s" ); BEGIN(SECT2); return ( '}' ); } \n { synerr( "missing }" ); BEGIN(SECT2); ++linenum; return ( '}' ); } "}" synerr( "bad name in {}'s" ); BEGIN(SECT2); \n synerr( "missing }" ); ++linenum; BEGIN(SECT2); {OPTWS}"%}".* bracelevel = 0; "reject" { ACTION_ECHO; CHECK_REJECT(yytext); } "yymore" { ACTION_ECHO; CHECK_YYMORE(yytext); } {NAME}|{NOT_NAME}|. ACTION_ECHO; \n { ++linenum; ACTION_ECHO; if ( bracelevel == 0 || (doing_codeblock && indented_code) ) { if ( ! doing_codeblock ) fputs( "\tYY_BREAK\n", temp_action_file ); doing_codeblock = false; BEGIN(SECT2); } } /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */ "{" ACTION_ECHO; ++bracelevel; "}" ACTION_ECHO; --bracelevel; [^a-z_{}"'/\n]+ ACTION_ECHO; {NAME} ACTION_ECHO; "/*" ACTION_ECHO; BEGIN(ACTION_COMMENT); "'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */ \" ACTION_ECHO; BEGIN(ACTION_STRING); \n { ++linenum; ACTION_ECHO; if ( bracelevel == 0 ) { fputs( "\tYY_BREAK\n", temp_action_file ); BEGIN(SECT2); } } . ACTION_ECHO; "*/" ACTION_ECHO; BEGIN(ACTION); [^*\n]+ ACTION_ECHO; "*" ACTION_ECHO; \n ++linenum; ACTION_ECHO; . ACTION_ECHO; [^"\\\n]+ ACTION_ECHO; \\. ACTION_ECHO; \n ++linenum; ACTION_ECHO; \" ACTION_ECHO; BEGIN(ACTION); . ACTION_ECHO; <> { synerr( "EOF encountered inside an action" ); yyterminate(); } {ESCSEQ} { yylval = myesc( yytext ); return ( CHAR ); } {ESCSEQ} { yylval = myesc( yytext ); BEGIN(CCL); return ( CHAR ); } .*(\n?) ECHO; %% int yywrap() { if ( --num_input_files > 0 ) { set_input_file( *++input_files ); return ( 0 ); } else return ( 1 ); } /* set_input_file - open the given file (if NULL, stdin) for scanning */ void set_input_file( file ) char *file; { if ( file ) { infilename = file; yyin = fopen( infilename, "r" ); if ( yyin == NULL ) lerrsf( "can't open %s", file ); } else { yyin = stdin; infilename = ""; } }