=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/lex/scan.l,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- src/usr.bin/lex/scan.l 2006/12/06 05:03:29 1.9 +++ src/usr.bin/lex/scan.l 2015/11/19 19:43:40 1.10 @@ -1,43 +1,44 @@ -/* $OpenBSD: scan.l,v 1.9 2006/12/06 05:03:29 ray Exp $ */ +/* $OpenBSD: scan.l,v 1.10 2015/11/19 19:43:40 tedu Exp $ */ -/* scan.l - scanner for flex input */ +/* 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. - * - * 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. - */ +/* Copyright (c) 1990 The Regents of the University of California. */ +/* All rights reserved. */ -/* $Header: /cvsrepo/anoncvs/cvs/src/usr.bin/lex/scan.l,v 1.9 2006/12/06 05:03:29 ray Exp $ */ +/* 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 ACTION_ECHO add_action( yytext ) #define ACTION_IFDEF(def, should_define) \ @@ -46,6 +47,17 @@ 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 \ @@ -56,7 +68,15 @@ return CHAR; #define RETURNNAME \ - strlcpy( nmstr, yytext, sizeof nmstr); \ + if(yyleng < MAXLINE) \ + { \ + strlcpy( nmstr, yytext, sizeof nmstr ); \ + } \ + else \ + { \ + synerr(_("Input line too long\n")); \ + FLEX_EXIT(EXIT_FAILURE); \ + } \ return NAME; #define PUT_BACK_STRING(str, start) \ @@ -70,18 +90,27 @@ #define CHECK_YYMORE(str) \ if ( all_lower( str ) ) \ yymore_used = true; + +#define YY_USER_INIT \ + if ( getenv("POSIXLY_CORRECT") ) \ + posix_compat = true; + %} -%option caseless nodefault outfile="scan.c" stack noyy_top_state +%option caseless nodefault 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 +%x OPTION LINEDIR CODEBLOCK_MATCH_BRACE +%x GROUP_WITH_PARAMS +%x GROUP_MINUS_PARAMS +%x EXTENDED_COMMENT +%x COMMENT_DISCARD WS [[:blank:]]+ OPTWS [[:blank:]]* -NOT_WS [^[:blank:]\n] +NOT_WS [^[:blank:]\r\n] NL \r?\n @@ -94,18 +123,21 @@ FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ}) CCL_CHAR ([^\\\n\]]|{ESCSEQ}) -CCL_EXPR ("[:"[[:alpha:]]+":]") +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 i; - Char nmdef[MAXLINE], myesc(); + int i, brace_depth=0, brace_start_line=0; + Char nmdef[MAXLINE]; { @@ -120,7 +152,16 @@ indented_code = false; BEGIN(CODEBLOCK); } + ^"%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 */ ^"%%".* { @@ -140,10 +181,20 @@ ^"%"{LEXOPT}{OPTWS}[[:digit:]]*{OPTWS}{NL} ++linenum; /* ignore */ ^"%"{LEXOPT}{WS}.*{NL} ++linenum; /* ignore */ + /* xgettext: no-c-format */ ^"%"[^sxaceknopr{}].* synerr( _( "unrecognized '%' directive" ) ); ^{NAME} { + if(yyleng < MAXLINE) + { strlcpy( nmstr, yytext, sizeof nmstr ); + } + else + { + synerr( _("Definition name too long\n")); + FLEX_EXIT(EXIT_FAILURE); + } + didadef = false; BEGIN(PICKUPDEF); } @@ -157,10 +208,26 @@ { "*/" ACTION_ECHO; yy_pop_state(); "*" ACTION_ECHO; - [^*\n]+ ACTION_ECHO; - [^*\n]*{NL} ++linenum; ACTION_ECHO; + {M4QSTART} ACTION_ECHO_QSTART; + {M4QEND} ACTION_ECHO_QEND; + [^*\n] ACTION_ECHO; + {NL} ++linenum; ACTION_ECHO; } +{ + /* 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 ); @@ -176,7 +243,9 @@ { ^"%}".*{NL} ++linenum; BEGIN(INITIAL); - {NAME}|{NOT_NAME}|. ACTION_ECHO; + {M4QSTART} ACTION_ECHO_QSTART; + {M4QEND} ACTION_ECHO_QEND; + . ACTION_ECHO; {NL} { ++linenum; @@ -186,13 +255,53 @@ } } +{ + "}" { + 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, strlen(escaped_qstart)); + {M4QEND} buf_strnappend(&top_buf, escaped_qend, strlen(escaped_qend)); + + [^{}\r\n] { + buf_strnappend(&top_buf, yytext, yyleng); + } + + <> { + linenum = brace_start_line; + synerr(_("Unmatched '{'")); + yyterminate(); + } +} + + { {WS} /* separates name and definition */ - {NOT_WS}.* { - strlcpy( (char *) nmdef, yytext, sizeof nmdef); - + {NOT_WS}[^\r\n]* { + if(yyleng < MAXLINE) + { + strlcpy( (char *) nmdef, yytext, sizeof nmdef ); + } + else + { + format_synerr( _("Definition value for {%s} too long\n"), nmstr); + FLEX_EXIT(EXIT_FAILURE); + } /* Skip trailing whitespace. */ for ( i = strlen( (char *) nmdef ) - 1; i >= 0 && (nmdef[i] == ' ' || nmdef[i] == '\t'); @@ -227,14 +336,21 @@ align long_align = option_sense; always-interactive { - action_define( "YY_ALWAYS_INTERACTIVE", option_sense ); + ACTION_M4_IFDEF( "M4""_YY_ALWAYS_INTERACTIVE", option_sense ); + interactive = option_sense; } array yytext_is_array = option_sense; + ansi-definitions ansi_func_defs = option_sense; + ansi-prototypes ansi_func_protos = option_sense; backup backing_up_report = option_sense; batch interactive = ! option_sense; + bison-bridge bison_bridge_lval = option_sense; + bison-locations { if((bison_bridge_lloc = option_sense)) + bison_bridge_lval = true; + } "c++" C_plus_plus = option_sense; - caseful|case-sensitive caseins = ! option_sense; - caseless|case-insensitive caseins = option_sense; + caseful|case-sensitive sf_set_case_ins(!option_sense); + caseless|case-insensitive sf_set_case_ins(option_sense); debug ddebug = option_sense; default spprdflt = ! option_sense; ecs useecs = option_sense; @@ -249,44 +365,88 @@ input ACTION_IFDEF("YY_NO_INPUT", ! option_sense); interactive interactive = option_sense; lex-compat lex_compat = option_sense; + posix-compat posix_compat = option_sense; main { - action_define( "YY_MAIN", option_sense ); - do_yywrap = ! option_sense; + ACTION_M4_IFDEF( "M4""_YY_MAIN", option_sense); + /* Override yywrap */ + if( option_sense == true ) + do_yywrap = false; } meta-ecs usemecs = option_sense; never-interactive { - action_define( "YY_NEVER_INTERACTIVE", option_sense ); + ACTION_M4_IFDEF( "M4""_YY_NEVER_INTERACTIVE", option_sense ); + interactive = !option_sense; } perf-report performance_report += option_sense ? 1 : -1; pointer yytext_is_array = ! option_sense; read use_read = option_sense; + reentrant reentrant = option_sense; reject reject_really_used = option_sense; - stack action_define( "YY_STACK_USED", option_sense ); + stack ACTION_M4_IFDEF( "M4""_YY_STACK_USED", option_sense ); stdinit do_stdinit = option_sense; stdout use_stdout = option_sense; - unput ACTION_IFDEF("YY_NO_UNPUT", ! option_sense); + unistd ACTION_IFDEF("YY_NO_UNISTD_H", ! option_sense); + unput ACTION_M4_IFDEF("M4""_YY_NO_UNPUT", ! option_sense); verbose printstats = option_sense; warn nowarn = ! option_sense; - yylineno do_yylineno = option_sense; + yylineno do_yylineno = option_sense; ACTION_M4_IFDEF("M4""_YY_USE_LINENO", option_sense); yymore yymore_really_used = option_sense; - yywrap do_yywrap = option_sense; + yywrap do_yywrap = option_sense; - yy_push_state ACTION_IFDEF("YY_NO_PUSH_STATE", ! option_sense); - yy_pop_state ACTION_IFDEF("YY_NO_POP_STATE", ! option_sense); - yy_top_state ACTION_IFDEF("YY_NO_TOP_STATE", ! option_sense); + yy_push_state ACTION_M4_IFDEF("M4""_YY_NO_PUSH_STATE", ! option_sense); + yy_pop_state ACTION_M4_IFDEF("M4""_YY_NO_POP_STATE", ! option_sense); + yy_top_state ACTION_M4_IFDEF("M4""_YY_NO_TOP_STATE", ! option_sense); - yy_scan_buffer ACTION_IFDEF("YY_NO_SCAN_BUFFER", ! option_sense); - yy_scan_bytes ACTION_IFDEF("YY_NO_SCAN_BYTES", ! option_sense); - yy_scan_string ACTION_IFDEF("YY_NO_SCAN_STRING", ! option_sense); + yy_scan_buffer ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BUFFER", ! option_sense); + yy_scan_bytes ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BYTES", ! option_sense); + yy_scan_string ACTION_M4_IFDEF("M4""_YY_NO_SCAN_STRING", ! option_sense); + yyalloc ACTION_M4_IFDEF("M4""_YY_NO_FLEX_ALLOC", ! option_sense); + yyrealloc ACTION_M4_IFDEF("M4""_YY_NO_FLEX_REALLOC", ! option_sense); + yyfree ACTION_M4_IFDEF("M4""_YY_NO_FLEX_FREE", ! option_sense); + + yyget_debug ACTION_M4_IFDEF("M4""_YY_NO_GET_DEBUG", ! option_sense); + yyset_debug ACTION_M4_IFDEF("M4""_YY_NO_SET_DEBUG", ! option_sense); + yyget_extra ACTION_M4_IFDEF("M4""_YY_NO_GET_EXTRA", ! option_sense); + yyset_extra ACTION_M4_IFDEF("M4""_YY_NO_SET_EXTRA", ! option_sense); + yyget_leng ACTION_M4_IFDEF("M4""_YY_NO_GET_LENG", ! option_sense); + yyget_text ACTION_M4_IFDEF("M4""_YY_NO_GET_TEXT", ! option_sense); + yyget_lineno ACTION_M4_IFDEF("M4""_YY_NO_GET_LINENO", ! option_sense); + yyset_lineno ACTION_M4_IFDEF("M4""_YY_NO_SET_LINENO", ! option_sense); + yyget_in ACTION_M4_IFDEF("M4""_YY_NO_GET_IN", ! option_sense); + yyset_in ACTION_M4_IFDEF("M4""_YY_NO_SET_IN", ! option_sense); + yyget_out ACTION_M4_IFDEF("M4""_YY_NO_GET_OUT", ! option_sense); + yyset_out ACTION_M4_IFDEF("M4""_YY_NO_SET_OUT", ! option_sense); + yyget_lval ACTION_M4_IFDEF("M4""_YY_NO_GET_LVAL", ! option_sense); + yyset_lval ACTION_M4_IFDEF("M4""_YY_NO_SET_LVAL", ! option_sense); + yyget_lloc ACTION_M4_IFDEF("M4""_YY_NO_GET_LLOC", ! option_sense); + yyset_lloc ACTION_M4_IFDEF("M4""_YY_NO_SET_LLOC", ! option_sense); + + extra-type return OPT_EXTRA_TYPE; outfile return OPT_OUTFILE; prefix return OPT_PREFIX; yyclass return OPT_YYCLASS; + header(-file)? return OPT_HEADER; + tables-file return OPT_TABLES; + tables-verify { + tablesverify = option_sense; + if(!tablesext && option_sense) + tablesext = true; + } + \"[^"\n]*\" { - strlcpy( nmstr, yytext + 1, sizeof nmstr); - if (nmstr[strlen(nmstr) - 1] == '"') - nmstr[strlen(nmstr) - 1] = '\0'; + if(yyleng-1 < MAXLINE) + { + strlcpy( nmstr, yytext + 1, sizeof nmstr ); + } + else + { + synerr( _("Option line too long\n")); + FLEX_EXIT(EXIT_FAILURE); + } + if (nmstr[strlen( nmstr ) - 1] == '"') + nmstr[strlen( nmstr ) - 1] = '\0'; return NAME; } @@ -318,7 +478,7 @@ ACTION_ECHO; } - .* ACTION_ECHO; + . ACTION_ECHO; {NL} ++linenum; ACTION_ECHO; <> { @@ -338,10 +498,21 @@ BEGIN(PERCENT_BRACE_ACTION); } - ^{OPTWS}"<" BEGIN(SC); return '<'; + ^{OPTWS}"<" { + /* Allow "<" to appear in (?x) patterns. */ + if (!sf_skip_ws()) + BEGIN(SC); + return '<'; + } ^{OPTWS}"^" return '^'; \" BEGIN(QUOTE); return '"'; - "{"/[[:digit:]] BEGIN(NUM); return '{'; + "{"/[[:digit:]] { + BEGIN(NUM); + if ( lex_compat || posix_compat ) + return BEGIN_REPEAT_POSIX; + else + return BEGIN_REPEAT_FLEX; + } "$"/([[:blank:]]|{NL}) return '$'; {WS}"%{" { @@ -355,46 +526,77 @@ return '\n'; } } - {WS}"|".*{NL} continued_action = true; ++linenum; return '\n'; + {WS}"|".*{NL} { + if (sf_skip_ws()){ + /* We're in the middle of a (?x: ) pattern. */ + /* Push back everything starting at the "|" */ + size_t amt; + amt = strchr (yytext, '|') - yytext; + yyless(amt); + } + else { + continued_action = true; + ++linenum; + return '\n'; + } + } ^{WS}"/*" { - yyless( yyleng - 2 ); /* put back '/', '*' */ - bracelevel = 0; - continued_action = false; - BEGIN(ACTION); + + if (sf_skip_ws()){ + /* We're in the middle of a (?x: ) pattern. */ + yy_push_state(COMMENT_DISCARD); + } + else{ + yyless( yyleng - 2 ); /* put back '/', '*' */ + bracelevel = 0; + continued_action = false; + BEGIN(ACTION); + } } - ^{WS} /* allow indented rules */ + ^{WS} /* allow indented rules */ ; {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); + if (sf_skip_ws()){ + /* We're in the middle of a (?x: ) pattern. */ + } + else{ + /* 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); - if ( in_rule ) - { - doing_rule_action = true; - in_rule = false; - return '\n'; - } + if ( in_rule ) + { + doing_rule_action = true; + in_rule = false; + return '\n'; + } + } } {OPTWS}{NL} { - bracelevel = 0; - continued_action = false; - BEGIN(ACTION); - unput( '\n' ); /* so sees it */ + if (sf_skip_ws()){ + /* We're in the middle of a (?x: ) pattern. */ + ++linenum; + } + else{ + bracelevel = 0; + continued_action = false; + BEGIN(ACTION); + unput( '\n' ); /* so sees it */ - if ( in_rule ) - { - doing_rule_action = true; - in_rule = false; - return '\n'; - } + if ( in_rule ) + { + doing_rule_action = true; + in_rule = false; + return '\n'; + } + } } ^{OPTWS}"<>" | @@ -403,18 +605,32 @@ ^"%%".* { sectnum = 3; BEGIN(SECT3); + outn("/* Begin user sect3 */"); yyterminate(); /* to stop the parser */ } "["({FIRST_CCL_CHAR}|{CCL_EXPR})({CCL_CHAR}|{CCL_EXPR})* { int cclval; - strlcpy( nmstr, yytext, sizeof nmstr); + if(yyleng < MAXLINE) + { + strlcpy( nmstr, yytext, sizeof nmstr ); + } + else + { + synerr( _("Input line too long\n")); + FLEX_EXIT(EXIT_FAILURE); + } /* Check to see if we've already encountered this * ccl. */ - if ( (cclval = ccllookup( (Char *) nmstr )) != 0 ) + if (0 /* <--- This "0" effectively disables the reuse of a + * character class (purely based on its source text). + * The reason it was disabled is so yacc/bison can parse + * ccl operations, such as ccl difference and union. + */ + && (cclval = ccllookup( (Char *) nmstr )) != 0 ) { if ( input() != ']' ) synerr( _( "bad character class" ) ); @@ -439,13 +655,31 @@ return '['; } } + "{-}" return CCL_OP_DIFF; + "{+}" return CCL_OP_UNION; - "{"{NAME}"}" { - register Char *nmdefptr; - Char *ndlookup(); + /* Check for :space: at the end of the rule so we don't + * wrap the expanded regex in '(' ')' -- breaking trailing + * context. + */ + "{"{NAME}"}"[[:space:]]? { + Char *nmdefptr; + int end_is_ws, end_ch; + + end_ch = yytext[yyleng-1]; + end_is_ws = end_ch != '}' ? 1 : 0; + + if(yyleng-1 < MAXLINE) + { strlcpy( nmstr, yytext + 1, sizeof nmstr ); - nmstr[yyleng - 2] = '\0'; /* chop trailing brace */ + } + else + { + synerr( _("Input line too long\n")); + FLEX_EXIT(EXIT_FAILURE); + } +nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */ if ( (nmdefptr = ndlookup( nmstr )) == 0 ) format_synerr( @@ -455,9 +689,12 @@ else { /* push back name surrounded by ()'s */ int len = strlen( (char *) nmdefptr ); + if (end_is_ws) + unput(end_ch); if ( lex_compat || nmdefptr[0] == '^' || - (len > 0 && nmdefptr[len - 1] == '$') ) + (len > 0 && nmdefptr[len - 1] == '$') + || (end_is_ws && trlcontxt && !sf_skip_ws())) { /* don't use ()'s after all */ PUT_BACK_STRING((char *) nmdefptr, 0); @@ -474,12 +711,45 @@ } } + "/*" { + if (sf_skip_ws()) + yy_push_state(COMMENT_DISCARD); + else{ + /* Push back the "*" and return "/" as usual. */ + yyless(1); + return '/'; + } + } + + "(?#" { + if (lex_compat || posix_compat){ + /* Push back the "?#" and treat it like a normal parens. */ + yyless(1); + sf_push(); + return '('; + } + else + yy_push_state(EXTENDED_COMMENT); + } + "(?" { + sf_push(); + if (lex_compat || posix_compat) + /* Push back the "?" and treat it like a normal parens. */ + yyless(1); + else + BEGIN(GROUP_WITH_PARAMS); + return '('; + } + "(" sf_push(); return '('; + ")" sf_pop(); return ')'; + [/|*+?.(){}] return (unsigned char) yytext[0]; . RETURNCHAR; } { + {OPTWS}{NL}{OPTWS} ++linenum; /* Allow blank lines & continuations */ [,*] return (unsigned char) yytext[0]; ">" BEGIN(SECT2); return '>'; ">"/^ BEGIN(CARETISBOL); return '>'; @@ -505,6 +775,19 @@ } } +{ + ":" BEGIN(SECT2); + "-" BEGIN(GROUP_MINUS_PARAMS); + i sf_set_case_ins(1); + s sf_set_dot_all(1); + x sf_set_skip_ws(1); +} +{ + ":" BEGIN(SECT2); + i sf_set_case_ins(0); + s sf_set_dot_all(0); + x sf_set_skip_ws(0); +} { "^"/[^-\]\n] BEGIN(CCL); return '^'; @@ -536,6 +819,19 @@ "[:space:]" BEGIN(CCL); return CCE_SPACE; "[:upper:]" BEGIN(CCL); return CCE_UPPER; "[:xdigit:]" BEGIN(CCL); return CCE_XDIGIT; + + "[:^alnum:]" BEGIN(CCL); return CCE_NEG_ALNUM; + "[:^alpha:]" BEGIN(CCL); return CCE_NEG_ALPHA; + "[:^blank:]" BEGIN(CCL); return CCE_NEG_BLANK; + "[:^cntrl:]" BEGIN(CCL); return CCE_NEG_CNTRL; + "[:^digit:]" BEGIN(CCL); return CCE_NEG_DIGIT; + "[:^graph:]" BEGIN(CCL); return CCE_NEG_GRAPH; + "[:^lower:]" BEGIN(CCL); return CCE_NEG_LOWER; + "[:^print:]" BEGIN(CCL); return CCE_NEG_PRINT; + "[:^punct:]" BEGIN(CCL); return CCE_NEG_PUNCT; + "[:^space:]" BEGIN(CCL); return CCE_NEG_SPACE; + "[:^upper:]" BEGIN(CCL); return CCE_NEG_UPPER; + "[:^xdigit:]" BEGIN(CCL); return CCE_NEG_XDIGIT; {CCL_EXPR} { format_synerr( _( "bad character class expression: %s" ), @@ -551,7 +847,13 @@ } "," return ','; - "}" BEGIN(SECT2); return '}'; + "}" { + BEGIN(SECT2); + if ( lex_compat || posix_compat ) + return END_REPEAT_POSIX; + else + return END_REPEAT_FLEX; + } . { synerr( _( "bad character inside {}'s" ) ); @@ -584,7 +886,9 @@ } } - {NAME}|{NOT_NAME}|. ACTION_ECHO; + {M4QSTART} ACTION_ECHO_QSTART; + {M4QEND} ACTION_ECHO_QEND; + . ACTION_ECHO; {NL} { ++linenum; ACTION_ECHO; @@ -605,7 +909,10 @@ { "{" ACTION_ECHO; ++bracelevel; "}" ACTION_ECHO; --bracelevel; - [^[:alpha:]_{}"'/\n]+ ACTION_ECHO; + {M4QSTART} ACTION_ECHO_QSTART; + {M4QEND} ACTION_ECHO_QEND; + [^[:alpha:]_{}"'/\n\[\]]+ ACTION_ECHO; + [\[\]] ACTION_ECHO; {NAME} ACTION_ECHO; "'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */ \" ACTION_ECHO; BEGIN(ACTION_STRING); @@ -627,16 +934,20 @@ { [^"\\\n]+ ACTION_ECHO; \\. ACTION_ECHO; - {NL} ++linenum; ACTION_ECHO; + {NL} ++linenum; ACTION_ECHO; BEGIN(ACTION); \" ACTION_ECHO; BEGIN(ACTION); . ACTION_ECHO; } -<> { +<> { synerr( _( "EOF encountered inside an action" ) ); yyterminate(); } +<> { + synerr( _( "EOF encountered inside pattern" ) ); + yyterminate(); + } {ESCSEQ} { yylval = myesc( (Char *) yytext ); @@ -649,7 +960,10 @@ { - .*(\n?) ECHO; + {M4QSTART} fwrite (escaped_qstart, 1, strlen(escaped_qstart), yyout); + {M4QEND} fwrite (escaped_qend, 1, strlen(escaped_qend), yyout); + [^\[\]\n]*(\n?) ECHO; + (.|\n) ECHO; <> sectnum = 0; yyterminate(); }