summaryrefslogtreecommitdiff
path: root/src/scan.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/scan.l')
-rw-r--r--src/scan.l281
1 files changed, 159 insertions, 122 deletions
diff --git a/src/scan.l b/src/scan.l
index cfc832d..66db864 100644
--- a/src/scan.l
+++ b/src/scan.l
@@ -38,6 +38,12 @@ 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) \
{ \
@@ -45,8 +51,8 @@ extern const char *escaped_qstart, *escaped_qend;
action_define( def, 1 ); \
}
-#define ACTION_ECHO_QSTART add_action (escaped_qstart)
-#define ACTION_ECHO_QEND add_action (escaped_qend)
+#define ACTION_ECHO_QSTART add_action (ESCAPED_QSTART)
+#define ACTION_ECHO_QEND add_action (ESCAPED_QEND)
#define ACTION_M4_IFDEF(def, should_define) \
do{ \
@@ -68,18 +74,20 @@ extern const char *escaped_qstart, *escaped_qend;
#define RETURNNAME \
if(yyleng < MAXLINE) \
{ \
- strcpy( nmstr, yytext ); \
+ strncpy( nmstr, yytext, sizeof(nmstr) ); \
+ return NAME; \
} \
else \
- { \
+ do { \
synerr(_("Input line too long\n")); \
FLEX_EXIT(EXIT_FAILURE); \
- } \
- return NAME;
+ } while (0)
#define PUT_BACK_STRING(str, start) \
- for ( i = strlen( str ) - 1; i >= start; --i ) \
- unput((str)[i])
+ { size_t i = strlen( str ); \
+ while ( i > start ) \
+ unput((str)[--i]); \
+ }
#define CHECK_REJECT(str) \
if ( all_upper( str ) ) \
@@ -93,6 +101,23 @@ extern const char *escaped_qstart, *escaped_qend;
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
@@ -104,7 +129,9 @@ extern const char *escaped_qstart, *escaped_qend;
%x GROUP_WITH_PARAMS
%x GROUP_MINUS_PARAMS
%x EXTENDED_COMMENT
-%x COMMENT_DISCARD
+%x COMMENT_DISCARD CODE_COMMENT
+%x SECT3_NOESCAPE
+%x CHARACTER_CONSTANT
WS [[:blank:]]+
OPTWS [[:blank:]]*
@@ -125,8 +152,8 @@ CCL_EXPR ("[:"^?[[:alpha:]]+":]")
LEXOPT [aceknopr]
-M4QSTART "[["
-M4QEND "]]"
+M4QSTART "[""["
+M4QEND "]""]"
%%
static int bracelevel, didadef, indented_code;
@@ -134,22 +161,17 @@ M4QEND "]]"
static int option_sense;
int doing_codeblock = false;
- int i, brace_depth=0, brace_start_line=0;
+ int brace_depth=0, brace_start_line=0;
char nmdef[MAXLINE];
<INITIAL>{
- ^{WS} indented_code = true; BEGIN(CODEBLOCK);
- ^"/*" ACTION_ECHO; yy_push_state( COMMENT );
+ ^{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} {
- ++linenum;
- line_directive_out(NULL, 1);
- indented_code = false;
- BEGIN(CODEBLOCK);
- }
+ ^"%{".*{NL} START_CODEBLOCK(false);
^"%top"[[:blank:]]*"{"[[:blank:]]*{NL} {
brace_start_line = linenum;
++linenum;
@@ -185,7 +207,7 @@ M4QEND "]]"
^{NAME} {
if(yyleng < MAXLINE)
{
- strcpy( nmstr, yytext );
+ strncpy( nmstr, yytext, sizeof(nmstr) );
}
else
{
@@ -203,14 +225,18 @@ M4QEND "]]"
}
-<COMMENT>{
- "*/" ACTION_ECHO; yy_pop_state();
- "*" ACTION_ECHO;
- {M4QSTART} ACTION_ECHO_QSTART;
- {M4QEND} ACTION_ECHO_QEND;
- [^*\n] ACTION_ECHO;
+<COMMENT,CODE_COMMENT>{ /* */
+ [^\[\]\*\n]* ACTION_ECHO;
+ . ACTION_ECHO;
+
{NL} ++linenum; ACTION_ECHO;
}
+<COMMENT>{
+ "*/" add_action("*/]""]"); yy_pop_state();
+}
+<CODE_COMMENT>{
+ "*/" ACTION_ECHO; yy_pop_state();
+}
<COMMENT_DISCARD>{
/* This is the same as COMMENT, but is discarded rather than output. */
@@ -223,7 +249,7 @@ M4QEND "]]"
<EXTENDED_COMMENT>{
")" yy_pop_state();
[^\n\)]+ ;
- {NL} ++linenum;
+ {NL} ++linenum;
}
<LINEDIR>{
@@ -237,19 +263,19 @@ M4QEND "]]"
}
. /* ignore spurious characters */
}
+<ACTION,CODEBLOCK,ACTION_STRING,PERCENT_BRACE_ACTION,CHARACTER_CONSTANT,COMMENT,CODE_COMMENT>{
+ {M4QSTART} ACTION_ECHO_QSTART;
+ {M4QEND} ACTION_ECHO_QEND;
+}
<CODEBLOCK>{
- ^"%}".*{NL} ++linenum; BEGIN(INITIAL);
-
- {M4QSTART} ACTION_ECHO_QSTART;
- {M4QEND} ACTION_ECHO_QEND;
- . ACTION_ECHO;
-
+ ^"%}".*{NL} ++linenum; END_CODEBLOCK;
+ [^\n%\[\]]* ACTION_ECHO;
+ . ACTION_ECHO;
{NL} {
++linenum;
ACTION_ECHO;
- if ( indented_code )
- BEGIN(INITIAL);
+ if ( indented_code ) END_CODEBLOCK;
}
}
@@ -274,10 +300,9 @@ M4QEND "]]"
{M4QSTART} buf_strnappend(&top_buf, escaped_qstart, (int) strlen(escaped_qstart));
{M4QEND} buf_strnappend(&top_buf, escaped_qend, (int) strlen(escaped_qend));
-
- [^{}\r\n] {
- buf_strnappend(&top_buf, yytext, yyleng);
- }
+ ([^{}\r\n\[\]]+)|[^{}\r\n] {
+ buf_strnappend(&top_buf, yytext, yyleng);
+ }
<<EOF>> {
linenum = brace_start_line;
@@ -293,7 +318,7 @@ M4QEND "]]"
{NOT_WS}[^\r\n]* {
if(yyleng < MAXLINE)
{
- strcpy( nmdef, yytext );
+ strncpy( nmdef, yytext, sizeof(nmdef) );
}
else
{
@@ -301,12 +326,12 @@ M4QEND "]]"
FLEX_EXIT(EXIT_FAILURE);
}
/* Skip trailing whitespace. */
- for ( i = strlen( nmdef ) - 1;
- i >= 0 && (nmdef[i] == ' ' || nmdef[i] == '\t');
- --i )
- ;
-
- nmdef[i + 1] = '\0';
+ {
+ size_t i = strlen( nmdef );
+ while (i > 0 && (nmdef[i-1] == ' ' || nmdef[i-1] == '\t'))
+ --i;
+ nmdef[i] = '\0';
+ }
ndinstal( nmstr, nmdef );
didadef = true;
@@ -338,8 +363,6 @@ M4QEND "]]"
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;
@@ -437,7 +460,7 @@ M4QEND "]]"
\"[^"\n]*\" {
if(yyleng-1 < MAXLINE)
{
- strcpy( nmstr, yytext + 1 );
+ strncpy( nmstr, yytext + 1, sizeof(nmstr) );
}
else
{
@@ -462,19 +485,20 @@ M4QEND "]]"
^"%{".* ++bracelevel; yyless( 2 ); /* eat only %{ */
^"%}".* --bracelevel; yyless( 2 ); /* eat only %} */
- ^{WS}.* ACTION_ECHO; /* indented code in prolog */
-
- ^{NOT_WS}.* { /* non-indented code */
- if ( bracelevel <= 0 )
- { /* not in %{ ... %} */
- yyless( 0 ); /* put it all back */
- yy_set_bol( 1 );
- mark_prolog();
- BEGIN(SECT2);
- }
- else
- ACTION_ECHO;
- }
+ ^{WS} START_CODEBLOCK(true); /* indented code in prolog */
+
+ ^{NOT_WS}.* {
+ /* non-indented code */
+ if ( bracelevel <= 0 ) {
+ /* not in %{ ... %} */
+ yyless( 0 ); /* put it all back */
+ yy_set_bol( 1 );
+ mark_prolog();
+ BEGIN(SECT2);
+ } else {
+ START_CODEBLOCK(true);
+ }
+ }
. ACTION_ECHO;
{NL} ++linenum; ACTION_ECHO;
@@ -532,6 +556,7 @@ M4QEND "]]"
yyless(amt);
}
else {
+ add_action("]""]");
continued_action = true;
++linenum;
return '\n';
@@ -601,9 +626,10 @@ M4QEND "]]"
^"%%".* {
sectnum = 3;
- BEGIN(SECT3);
+ BEGIN(no_section3_escape ? SECT3_NOESCAPE : SECT3);
outn("/* Begin user sect3 */");
yyterminate(); /* to stop the parser */
+
}
"["({FIRST_CCL_CHAR}|{CCL_EXPR})({CCL_CHAR}|{CCL_EXPR})* {
@@ -611,7 +637,7 @@ M4QEND "]]"
if(yyleng < MAXLINE)
{
- strcpy( nmstr, yytext );
+ strncpy( nmstr, yytext, sizeof(nmstr) );
}
else
{
@@ -669,7 +695,7 @@ M4QEND "]]"
if(yyleng-1 < MAXLINE)
{
- strcpy( nmstr, yytext + 1 );
+ strncpy( nmstr, yytext + 1, sizeof(nmstr) );
}
else
{
@@ -685,7 +711,7 @@ nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */
else
{ /* push back name surrounded by ()'s */
- int len = strlen( nmdefptr );
+ size_t len = strlen( nmdefptr );
if (end_is_ws)
unput(end_ch);
@@ -876,35 +902,31 @@ nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */
<PERCENT_BRACE_ACTION>{
{OPTWS}"%}".* bracelevel = 0;
- <ACTION>"/*" ACTION_ECHO; yy_push_state( COMMENT );
+ <ACTION>"/*" ACTION_ECHO; yy_push_state( CODE_COMMENT );
<CODEBLOCK,ACTION>{
- "reject" {
- ACTION_ECHO;
- CHECK_REJECT(yytext);
- }
- "yymore" {
- ACTION_ECHO;
- CHECK_YYMORE(yytext);
- }
+ "reject" {
+ ACTION_ECHO;
+ CHECK_REJECT(yytext);
+ }
+ "yymore" {
+ ACTION_ECHO;
+ CHECK_YYMORE(yytext);
+ }
}
- {M4QSTART} ACTION_ECHO_QSTART;
- {M4QEND} ACTION_ECHO_QEND;
- . ACTION_ECHO;
- {NL} {
- ++linenum;
- ACTION_ECHO;
- if ( bracelevel == 0 ||
- (doing_codeblock && indented_code) )
- {
- if ( doing_rule_action )
- add_action( "\tYY_BREAK\n" );
-
- doing_rule_action = doing_codeblock = false;
- BEGIN(SECT2);
- }
- }
+ . ACTION_ECHO;
+ {NL} {
+ ++linenum;
+ ACTION_ECHO;
+ if (bracelevel <= 0 || (doing_codeblock && indented_code)) {
+ if ( doing_rule_action )
+ add_action( "\tYY_BREAK]""]\n" );
+
+ doing_rule_action = doing_codeblock = false;
+ BEGIN(SECT2);
+ }
+ }
}
@@ -912,37 +934,41 @@ nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */
<ACTION>{
"{" ACTION_ECHO; ++bracelevel;
"}" ACTION_ECHO; --bracelevel;
- {M4QSTART} ACTION_ECHO_QSTART;
- {M4QEND} ACTION_ECHO_QEND;
- [^[:alpha:]_{}"'/\n\[\]]+ ACTION_ECHO;
- [\[\]] ACTION_ECHO;
- {NAME} ACTION_ECHO;
- "'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */
+ [^[:alpha:]_{}\"'/\n\[\]]+ ACTION_ECHO;
+ {NAME} ACTION_ECHO;
+ "'"([^\'\\\n]|\\.)"'" ACTION_ECHO; /* character constant */
+ "'" ACTION_ECHO; BEGIN(CHARACTER_CONSTANT);
\" ACTION_ECHO; BEGIN(ACTION_STRING);
- {NL} {
- ++linenum;
- ACTION_ECHO;
- if ( bracelevel == 0 )
- {
- if ( doing_rule_action )
- add_action( "\tYY_BREAK\n" );
+ {NL} {
+ ++linenum;
+ ACTION_ECHO;
+ if (bracelevel <= 0) {
+ if ( doing_rule_action )
+ add_action( "\tYY_BREAK]""]\n" );
- doing_rule_action = false;
- BEGIN(SECT2);
- }
- }
- . ACTION_ECHO;
+ doing_rule_action = false;
+ BEGIN(SECT2);
+ }
+ }
+ . ACTION_ECHO;
}
<ACTION_STRING>{
- [^"\\\n]+ ACTION_ECHO;
- \\. ACTION_ECHO;
- {NL} ++linenum; ACTION_ECHO; BEGIN(ACTION);
+ [^\[\]\"\\\n]+ ACTION_ECHO;
\" ACTION_ECHO; BEGIN(ACTION);
- . ACTION_ECHO;
+}
+<CHARACTER_CONSTANT>{
+ [^\[\]\'\\\n]+ ACTION_ECHO;
+ \' ACTION_ECHO; BEGIN(ACTION);
+}
+<ACTION_STRING,CHARACTER_CONSTANT>{
+ (\\\n)* ACTION_ECHO;
+ \\(\\\n)*. ACTION_ECHO;
+ {NL} ++linenum; ACTION_ECHO; if (bracelevel <= 0) { BEGIN(SECT2); } else { BEGIN(ACTION); }
+ . ACTION_ECHO;
}
-<COMMENT,COMMENT_DISCARD,ACTION,ACTION_STRING><<EOF>> {
+<COMMENT,CODE_COMMENT,COMMENT_DISCARD,ACTION,ACTION_STRING,CHARACTER_CONSTANT><<EOF>> {
synerr( _( "EOF encountered inside an action" ) );
yyterminate();
}
@@ -961,15 +987,26 @@ nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */
return CHAR;
}
-
<SECT3>{
- {M4QSTART} fwrite (escaped_qstart, 1, strlen(escaped_qstart), yyout);
- {M4QEND} fwrite (escaped_qend, 1, strlen(escaped_qend), yyout);
- [^\[\]\n]*(\n?) ECHO;
- (.|\n) ECHO;
- <<EOF>> sectnum = 0; yyterminate();
+ {M4QSTART} fputs(escaped_qstart, yyout);
+ {M4QEND} fputs(escaped_qend, yyout);
+ [^\[\]]* ECHO;
+ [][] ECHO;
+ <<EOF>> {
+ sectnum = 0;
+ yyterminate();
+ }
+}
+<SECT3_NOESCAPE>{
+ {M4QSTART} fprintf(yyout, "[""[%s]""]", escaped_qstart);
+ {M4QEND} fprintf(yyout, "[""[%s]""]", escaped_qend);
+ [^][]* ECHO;
+ [][] ECHO;
+ <<EOF>> {
+ sectnum = 0;
+ yyterminate();
+ }
}
-
<*>.|\n format_synerr( _( "bad character: %s" ), yytext );
%%