/* scan.l - scanner for flex input -*-C-*- */ %{ /* 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. */ /* This file is part of flex. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* 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. */ #include "flexdef.h" #include "parse.h" extern bool tablesverify, tablesext; extern int trlcontxt; /* Set in parse.y for each rule. */ extern const char *escaped_qstart, *escaped_qend; #define M4QSTART "[""[" #define M4QEND "]""]" #define ESCAPED_QSTART "[" M4QEND M4QSTART "[" M4QEND M4QSTART #define ESCAPED_QEND M4QEND "]" M4QSTART M4QEND "]" M4QSTART #define ACTION_ECHO add_action( yytext ) #define ACTION_IFDEF(def, should_define) \ { \ if ( should_define ) \ action_define( def, 1 ); \ } #define ACTION_ECHO_QSTART add_action (ESCAPED_QSTART) #define ACTION_ECHO_QEND add_action (ESCAPED_QEND) #define ACTION_M4_IFDEF(def, should_define) \ do{ \ if ( should_define ) \ buf_m4_define( &m4defs_buf, def, NULL);\ else \ buf_m4_undefine( &m4defs_buf, def);\ } while(0) #define MARK_END_OF_PROLOG mark_prolog(); #define YY_DECL \ int flexscan(void) #define RETURNCHAR \ yylval = (unsigned char) yytext[0]; \ return CHAR; #define RETURNNAME \ if(yyleng < MAXLINE) \ { \ strncpy( nmstr, yytext, sizeof(nmstr) ); \ return NAME; \ } \ else \ do { \ synerr(_("Input line too long\n")); \ FLEX_EXIT(EXIT_FAILURE); \ } while (0) #define PUT_BACK_STRING(str, start) \ { size_t i = strlen( str ); \ while ( i > start ) \ unput((str)[--i]); \ } #define CHECK_REJECT(str) \ if ( all_upper( str ) ) \ reject = true; #define CHECK_YYMORE(str) \ if ( all_lower( str ) ) \ yymore_used = true; #define YY_USER_INIT \ if ( getenv("POSIXLY_CORRECT") ) \ posix_compat = true; #define START_CODEBLOCK(x) do { \ /* Emit the needed line directive... */\ if (indented_code == false) { \ linenum++; \ line_directive_out(NULL, 1); \ } \ add_action(M4QSTART); \ yy_push_state(CODEBLOCK); \ if ((indented_code = x)) ACTION_ECHO; \ } while(0) #define END_CODEBLOCK do { \ yy_pop_state();\ add_action(M4QEND); \ if (!indented_code) line_directive_out(NULL, 0);\ } while (0) %} %option caseless nodefault noreject stack noyy_top_state %option nostdinit %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE %x FIRSTCCL CCL ACTION RECOVER COMMENT ACTION_STRING PERCENT_BRACE_ACTION %x OPTION LINEDIR CODEBLOCK_MATCH_BRACE %x GROUP_WITH_PARAMS %x GROUP_MINUS_PARAMS %x EXTENDED_COMMENT %x COMMENT_DISCARD CODE_COMMENT %x SECT3_NOESCAPE %x CHARACTER_CONSTANT WS [[:blank:]]+ OPTWS [[:blank:]]* NOT_WS [^[:blank:]\r\n] NL \r?\n NAME ([[:alpha:]_][[:alnum:]_-]*) NOT_NAME [^[:alpha:]_*\n]+ SCNAME {NAME} ESCSEQ (\\([^\n]|[0-7]{1,3}|x[[:xdigit:]]{1,2})) FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ}) CCL_CHAR ([^\\\n\]]|{ESCSEQ}) CCL_EXPR ("[:"^?[[:alpha:]]+":]") LEXOPT [aceknopr] M4QSTART "[""[" M4QEND "]""]" %% static int bracelevel, didadef, indented_code; static int doing_rule_action = false; static int option_sense; int doing_codeblock = false; int brace_depth=0, brace_start_line=0; char nmdef[MAXLINE]; { ^{WS} START_CODEBLOCK(true); ^"/*" add_action("/*[""["); yy_push_state( COMMENT ); ^#{OPTWS}line{WS} yy_push_state( LINEDIR ); ^"%s"{NAME}? return SCDECL; ^"%x"{NAME}? return XSCDECL; ^"%{".*{NL} START_CODEBLOCK(false); ^"%top"[[:blank:]]*"{"[[:blank:]]*{NL} { brace_start_line = linenum; ++linenum; buf_linedir( &top_buf, infilename?infilename:"", linenum); brace_depth = 1; yy_push_state(CODEBLOCK_MATCH_BRACE); } ^"%top".* synerr( _("malformed '%top' directive") ); {WS} /* discard */ ^"%%".* { sectnum = 2; bracelevel = 0; mark_defs1(); line_directive_out(NULL, 1); BEGIN(SECT2PROLOG); return SECTEND; } ^"%pointer".*{NL} yytext_is_array = false; ++linenum; ^"%array".*{NL} yytext_is_array = true; ++linenum; ^"%option" BEGIN(OPTION); return TOK_OPTION; ^"%"{LEXOPT}{OPTWS}[[:digit:]]*{OPTWS}{NL} ++linenum; /* ignore */ ^"%"{LEXOPT}{WS}.*{NL} ++linenum; /* ignore */ /* xgettext: no-c-format */ ^"%"[^sxaceknopr{}].* synerr( _( "unrecognized '%' directive" ) ); ^{NAME} { if(yyleng < MAXLINE) { strncpy( nmstr, yytext, sizeof(nmstr) ); } else { synerr( _("Definition name too long\n")); FLEX_EXIT(EXIT_FAILURE); } didadef = false; BEGIN(PICKUPDEF); } {SCNAME} RETURNNAME; ^{OPTWS}{NL} ++linenum; /* allows blank lines in section 1 */ {OPTWS}{NL} ACTION_ECHO; ++linenum; /* maybe end of comment line */ } { /* */ [^\[\]\*\n]* ACTION_ECHO; . ACTION_ECHO; {NL} ++linenum; ACTION_ECHO; } { "*/" add_action("*/]""]"); yy_pop_state(); } { "*/" ACTION_ECHO; yy_pop_state(); } { /* This is the same as COMMENT, but is discarded rather than output. */ "*/" yy_pop_state(); "*" ; [^*\n] ; {NL} ++linenum; } { ")" yy_pop_state(); [^\n\)]+ ; {NL} ++linenum; } { \n yy_pop_state(); [[:digit:]]+ linenum = myctoi( yytext ); \"[^"\n]*\" { free(infilename); infilename = xstrdup(yytext + 1); infilename[strlen( infilename ) - 1] = '\0'; } . /* ignore spurious characters */ } { {M4QSTART} ACTION_ECHO_QSTART; {M4QEND} ACTION_ECHO_QEND; } { ^"%}".*{NL} ++linenum; END_CODEBLOCK; [^\n%\[\]]* ACTION_ECHO; . ACTION_ECHO; {NL} { ++linenum; ACTION_ECHO; if ( indented_code ) END_CODEBLOCK; } } { "}" { if( --brace_depth == 0){ /* TODO: Matched. */ yy_pop_state(); }else buf_strnappend(&top_buf, yytext, yyleng); } "{" { brace_depth++; buf_strnappend(&top_buf, yytext, yyleng); } {NL} { ++linenum; buf_strnappend(&top_buf, yytext, yyleng); } {M4QSTART} buf_strnappend(&top_buf, escaped_qstart, (int) strlen(escaped_qstart)); {M4QEND} buf_strnappend(&top_buf, escaped_qend, (int) strlen(escaped_qend)); ([^{}\r\n\[\]]+)|[^{}\r\n] { buf_strnappend(&top_buf, yytext, yyleng); } <> { linenum = brace_start_line; synerr(_("Unmatched '{'")); yyterminate(); } } { {WS} /* separates name and definition */ {NOT_WS}[^\r\n]* { if(yyleng < MAXLINE) { strncpy( nmdef, yytext, sizeof(nmdef) ); } else { format_synerr( _("Definition value for {%s} too long\n"), nmstr); FLEX_EXIT(EXIT_FAILURE); } /* Skip trailing whitespace. */ { size_t i = strlen( nmdef ); while (i > 0 && (nmdef[i-1] == ' ' || nmdef[i-1] == '\t')) --i; nmdef[i] = '\0'; } ndinstal( nmstr, nmdef ); didadef = true; } {NL} { if ( ! didadef ) synerr( _( "incomplete name definition" ) ); BEGIN(INITIAL); ++linenum; } }