diff options
author | Demi Obenour <demiobenour@gmail.com> | 2016-09-27 10:54:16 -0400 |
---|---|---|
committer | Will Estes <westes575@gmail.com> | 2016-10-05 19:25:56 -0400 |
commit | 9d3ddf572e3744e4cf5e9788b676f423fe69aee8 (patch) | |
tree | 1a9ae51e2be904714c0afdae5dbad00c81ccf300 /src | |
parent | 735ffb6a653552831321acaa0e7d0a834a210a84 (diff) |
Fix M4 quoting of section 3.
This fixes M4 quoting of section 3 of the input file, including escape
sequences and character constants.
Tests were added to verify the behavior in section 3 with respect to
quoting. Both escaping of quotes and quoting of potential macro-start
characters are tested. Existing tests were also fixed to account for the new -- and now correct -- behavior. Many tests relied on the old behavior of expanding M4 macros
in section 3. They needed to be updated for the new behavior.
Diffstat (limited to 'src')
-rw-r--r-- | src/filter.c | 2 | ||||
-rw-r--r-- | src/flexdef.h | 3 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/misc.c | 7 | ||||
-rw-r--r-- | src/options.c | 3 | ||||
-rw-r--r-- | src/options.h | 3 | ||||
-rw-r--r-- | src/scan.l | 41 | ||||
-rw-r--r-- | src/yylex.c | 9 |
8 files changed, 49 insertions, 23 deletions
diff --git a/src/filter.c b/src/filter.c index 1ac199f..9d0ace5 100644 --- a/src/filter.c +++ b/src/filter.c @@ -390,7 +390,7 @@ int filter_fix_linedirs (struct filter *chain) /* Adjust the line directives. */ in_gen = true; snprintf (buf, readsz, "#line %d \"%s\"\n", - lineno + 1, filename); + lineno, filename); } else { /* it's a #line directive for code we didn't write */ diff --git a/src/flexdef.h b/src/flexdef.h index a727ede..a4d1896 100644 --- a/src/flexdef.h +++ b/src/flexdef.h @@ -1063,9 +1063,10 @@ extern struct Buf defs_buf; /* a char* buffer to save #define'd some symbols extern struct Buf yydmap_buf; /* a string buffer to hold yydmap elements */ extern struct Buf m4defs_buf; /* Holds m4 definitions. */ extern struct Buf top_buf; /* contains %top code. String buffer. */ +extern bool no_section3_escape; /* True if the undocumented option --unsafe-no-m4-sect3-escape was passed */ /* For blocking out code from the header file. */ -#define OUT_BEGIN_CODE() outn("m4_ifdef( [[M4_YY_IN_HEADER]],,[[") +#define OUT_BEGIN_CODE() outn("m4_ifdef( [[M4_YY_IN_HEADER]],,[[m4_dnl") #define OUT_END_CODE() outn("]])") /* For setjmp/longjmp (instead of calling exit(2)). Linkage in main.c */ @@ -1427,6 +1427,10 @@ void flexinit (int argc, char **argv) break; case OPT_HEX: trace_hex = 1; + break; + case OPT_NO_SECT3_ESCAPE: + no_section3_escape = true; + break; } /* switch */ } /* while scanopt() */ @@ -362,8 +362,8 @@ void line_directive_out (FILE *output_file, int do_infile) s3 = &filename[sizeof (filename) - 2]; while (s2 < s3 && *s1) { - if (*s1 == '\\') - /* Escape the '\' */ + if (*s1 == '\\' || *s1 == '"') + /* Escape the '\' or '"' */ *s2++ = '\\'; *s2++ = *s1++; @@ -512,7 +512,8 @@ unsigned char myesc (unsigned char array[]) { /* \<octal> */ int sptr = 1; - while (isascii (array[sptr]) && + while (sptr <= 3 && + isascii (array[sptr]) && isdigit (array[sptr])) /* Don't increment inside loop control * because if isdigit() is a macro it might diff --git a/src/options.c b/src/options.c index 3f3a39f..366bc2e 100644 --- a/src/options.c +++ b/src/options.c @@ -271,7 +271,8 @@ optspec_t flexopts[] = { , {"--noyyset_lloc", OPT_NO_YYSET_LLOC, 0} , - + {"--unsafe-no-m4-sect3-escape", OPT_NO_SECT3_ESCAPE, 0} + , {0, 0, 0} /* required final NULL entry. */ }; diff --git a/src/options.h b/src/options.h index 8555343..5b51c23 100644 --- a/src/options.h +++ b/src/options.h @@ -125,7 +125,8 @@ enum flexopt_flag_t { OPT_YYCLASS, OPT_YYLINENO, OPT_YYMORE, - OPT_YYWRAP + OPT_YYWRAP, + OPT_NO_SECT3_ESCAPE, }; #endif @@ -41,6 +41,9 @@ extern const char *escaped_qstart, *escaped_qend; #define M4QSTART "[[" #define M4QEND "]]" +#define SECT3_ESCAPED_QSTART "[" M4QEND M4QSTART "[" M4QEND M4QSTART +#define SECT3_ESCAPED_QEND M4QEND "]" M4QSTART M4QEND "]" M4QSTART + #define ACTION_ECHO add_action( yytext ) #define ACTION_IFDEF(def, should_define) \ { \ @@ -110,6 +113,8 @@ extern const char *escaped_qstart, *escaped_qend; %x GROUP_MINUS_PARAMS %x EXTENDED_COMMENT %x COMMENT_DISCARD +%x SECT3_NOESCAPE +%x CHARACTER_CONSTANT WS [[:blank:]]+ OPTWS [[:blank:]]* @@ -240,8 +245,8 @@ M4QEND "]]" } . /* ignore spurious characters */ } -<ACTION,CODEBLOCK,ACTION_STRING,PERCENT_BRACE_ACTION,COMMENT>{ - "M4"|"YY"|"m4" add_action(M4QSTART); ACTION_ECHO; add_action(M4QEND); +<ACTION,CODEBLOCK,ACTION_STRING,PERCENT_BRACE_ACTION,COMMENT,CHARACTER_CONSTANT>{ + M4|YY|m4 add_action(M4QSTART); ACTION_ECHO; add_action(M4QEND); {M4QSTART} ACTION_ECHO_QSTART; {M4QEND} ACTION_ECHO_QEND; } @@ -285,9 +290,9 @@ M4QEND "]]" buf_strnappend(&top_buf, M4QEND, 2); } - [^{}\r\n] { - buf_strnappend(&top_buf, yytext, yyleng); - } + ([^{}\r\nmMY\[\]]+)|[^{}\r\n] { + buf_strnappend(&top_buf, yytext, yyleng); + } <<EOF>> { linenum = brace_start_line; @@ -920,10 +925,11 @@ nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */ <ACTION>{ "{" ACTION_ECHO; ++bracelevel; "}" ACTION_ECHO; --bracelevel; - [^[:alpha:]_{}"'/\n\[\]]+ ACTION_ECHO; + [^[:alpha:]_{}\"'/\n\[\]]+ ACTION_ECHO; [\[\]] ACTION_ECHO; {NAME} ACTION_ECHO; - "'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */ + "'"([^\'\\\n]|\\.)"'" ACTION_ECHO; /* character constant */ + "'" ACTION_ECHO; yy_push_state(CHARACTER_CONSTANT); \" ACTION_ECHO; BEGIN(ACTION_STRING); {NL} { ++linenum; @@ -941,14 +947,20 @@ nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */ } <ACTION_STRING>{ - [^]"\\\n[]+ ACTION_ECHO; + [^\]\"\\\n\[MmY]+ ACTION_ECHO; + \" ACTION_ECHO; BEGIN(ACTION); +} +<CHARACTER_CONSTANT>{ + [^\[\]\'\\\nMmY]+ ACTION_ECHO; + \' ACTION_ECHO; yy_pop_state(); +} +<ACTION_STRING,CHARACTER_CONSTANT>{ \\. ACTION_ECHO; {NL} ++linenum; ACTION_ECHO; - \" ACTION_ECHO; BEGIN(ACTION); . ACTION_ECHO; } -<COMMENT,COMMENT_DISCARD,ACTION,ACTION_STRING><<EOF>> { +<COMMENT,COMMENT_DISCARD,ACTION,ACTION_STRING,CHARACTER_CONSTANT><<EOF>> { synerr( _( "EOF encountered inside an action" ) ); yyterminate(); } @@ -969,10 +981,15 @@ nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */ <SECT3>{ - /* "M4"|"m4"|"YY" fprintf (yyout, "[[%s]]", yytext); */ + "M4"|"m4"|"YY" { + if (no_section3_escape) { + ECHO; + } else + fprintf (yyout, "[[%s]]", yytext); + } {M4QSTART} fwrite (escaped_qstart, 1, strlen(escaped_qstart) - 0, yyout); {M4QEND} fwrite (escaped_qend, 1, strlen(escaped_qend) - 0, yyout); - [^\[\]\n]*(\n?) ECHO; + [^\[\]MmY\n]*(\n?) ECHO; (.|\n) ECHO; <<EOF>> { //fwrite(M4QEND, 1, strlen(M4QEND), yyout); diff --git a/src/yylex.c b/src/yylex.c index c3de1d5..521db7f 100644 --- a/src/yylex.c +++ b/src/yylex.c @@ -37,18 +37,19 @@ /* yylex - scan for a regular expression token */ - extern char *yytext; +extern FILE *yyout; +bool no_section3_escape = false; int yylex (void) { int toktype; static int beglin = false; - if (eofseen) + if (eofseen) { toktype = EOF; - else + } else { toktype = flexscan (); - + } if (toktype == EOF || toktype == 0) { eofseen = 1; |