]> granicus.if.org Git - flex/commitdiff
2.0.1 beta
authorVern Paxson <vern@ee.lbl.gov>
Tue, 20 Jun 1989 15:38:27 +0000 (15:38 +0000)
committerVern Paxson <vern@ee.lbl.gov>
Tue, 20 Jun 1989 15:38:27 +0000 (15:38 +0000)
flex.skl
flexdef.h
gen.c
misc.c
nfa.c
parse.y
scan.l
sym.c

index 1ccbdff4355beaae73ca13d8d7d770be8baf0cfa..54e9dedf558d619e4256bb61d577b940766fc840 100644 (file)
--- a/flex.skl
+++ b/flex.skl
@@ -8,18 +8,17 @@
 
 #define FLEX_SCANNER
 
-/* returned upon end-of-file */
-#define YY_END_TOK 0
-
 /* amount of stuff to slurp up with each read */
+#ifndef YY_READ_BUF_SIZE
 #define YY_READ_BUF_SIZE 8192
+#endif
 
+#ifndef YY_BUF_SIZE
 #define YY_BUF_SIZE (YY_READ_BUF_SIZE * 2) /* size of input buffer */
+#endif
 
-/* number of characters one rule can match.  One less than YY_BUF_SIZE to make
- * sure we never access beyond the end of an array
- */
-#define YY_BUF_MAX (YY_BUF_SIZE - 1)
+/* returned upon end-of-file */
+#define YY_END_TOK 0
 
 /* copy whatever the last rule matched to the standard output */
 
@@ -32,6 +31,7 @@
        if ( (result = read( fileno(yyin), buf, max_size )) < 0 ) \
            YY_FATAL_ERROR( "read() in flex scanner failed" );
 #define YY_NULL 0
+#define yyterminate() return ( YY_NULL )
 
 /* report a fatal error */
 #define YY_FATAL_ERROR(msg) \
 #define yywrap() 1
 
 /* enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way that old Unix-lex does it
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN
  */
-#define BEGIN yy_start = 1 +
+#define BEGIN yy_start = 1 + 2 *
+
+/* action number for EOF rule of a given start state */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* special action meaning "start processing a new file" */
+#define YY_NEW_FILE goto new_file
 
 /* default declaration of generated scanner - a define so the user can
  * easily add parameters
  */
+#ifdef __STDC__
+#define YY_DECL int yylex( void )
+#else
 #define YY_DECL int yylex()
+#endif
 
 /* code executed at the end of each rule */
 #define YY_BREAK break;
 
 #define YY_USER_ACTION
 
-%% section 1 code and the data tables for the DFA go here
-
 FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+char *yytext;
+
+#ifndef __STDC__
+#define const
+#endif
+
+%% section 1 code and the data tables for the DFA go here
 
 /* these variables are all declared out here so that section 3 code can
  * manipulate them
@@ -111,16 +127,23 @@ static char yy_ch_buf[YY_BUF_SIZE + 2];
 
 /* yy_hold_char holds the character lost when yytext is formed */
 static char yy_hold_char;
-char *yytext;
 
 static yy_state_type yy_last_accepting_state;
 static char *yy_last_accepting_cpos;
 
+#ifdef __STDC__
+static yy_state_type yy_get_previous_state( void );
+static int yy_get_next_buffer( void );
+static void yyunput( int c, char *buf_ptr );
+static int input( void );
+static void yyrestart( FILE *input_file );
+#else
 static yy_state_type yy_get_previous_state();
 static int yy_get_next_buffer();
-
 static void yyunput();
 static int input();
+static void yyrestart();
+#endif
 
 YY_DECL
     {
@@ -177,13 +200,13 @@ new_file:
        /* yy_bp points to the position in yy_ch_buf of the start of the
         * current run.
         */
-       yy_bp = yy_cp;
+%% yymore()-related code goes here
 
 %% code to set up and find next match goes here
 
-       /* bogus while loop to let YY_BACK_TRACK and EOB_ACT_LAST_MATCH
-        * actions branch here without introducing an optimizer-daunting
-        * goto
+       /* bogus while loop to let YY_BACK_TRACK, EOB_ACT_LAST_MATCH,
+        * and EOF actions branch here without introducing an optimizer-
+        * daunting goto
         */
        while ( 1 )
            {
@@ -196,6 +219,8 @@ new_file:
            fprintf( stderr, "--accepting rule #%d (\"%s\")\n",
                     yy_act, yytext );
 #endif
+
+do_action:     /* this label is used only to access EOF actions */
            switch ( yy_act )
                {
 %% actions go here
@@ -221,11 +246,13 @@ new_file:
                                 * will get returned.
                                 */
                                yy_c_buf_p = yytext;
-                               return ( YY_NULL );
+
+                               yy_act = YY_STATE_EOF((yy_start - 1) / 2);
+                               goto do_action;
                                }
 
                            else
-                               goto new_file;
+                               YY_NEW_FILE;
                            }
                            break;
 
@@ -270,65 +297,70 @@ new_file:
 static int yy_get_next_buffer()
 
     {
+    register char *dest = yy_ch_buf;
+    register char *source = yytext - 1; /* copy prev. char, too */
+    register int number_to_move, i;
+    int ret_val;
+    
     if ( yy_c_buf_p != &yy_ch_buf[yy_n_chars + 1] )
        {
        YY_FATAL_ERROR( "NULL in input" );
        /*NOTREACHED*/
        }
 
-    else
-       { /* try to read more data */
-       register char *dest = yy_ch_buf;
-       register char *source = yytext - 1; /* copy prev. char, too */
-       register int number_to_move, i;
-       int ret_val;
-       
-       /* first move last chars to start of buffer */
-       number_to_move = yy_c_buf_p - yytext;
-
-       for ( i = 0; i < number_to_move; ++i )
-           *(dest++) = *(source++);
-
-       if ( yy_eof_has_been_seen )
-           /* don't do the read, it's not guaranteed to return an EOF,
-            * just force an EOF
-            */
-           yy_n_chars = 0;
+    /* try to read more data */
 
-       else
-           /* read in more data */
-           YY_INPUT( (&yy_ch_buf[number_to_move]), yy_n_chars,
-                     YY_BUF_SIZE - number_to_move - 1 );
+    /* first move last chars to start of buffer */
+    number_to_move = yy_c_buf_p - yytext;
 
-       if ( yy_n_chars == 0 )
-           {
-           if ( number_to_move == 1 )
-               ret_val = EOB_ACT_END_OF_FILE;
-           else
-               ret_val = EOB_ACT_LAST_MATCH;
+    for ( i = 0; i < number_to_move; ++i )
+       *(dest++) = *(source++);
 
-           yy_eof_has_been_seen = 1;
-           }
+    if ( yy_eof_has_been_seen )
+       /* don't do the read, it's not guaranteed to return an EOF,
+        * just force an EOF
+        */
+       yy_n_chars = 0;
 
-       else
-           ret_val = EOB_ACT_RESTART_SCAN;
+    else
+       {
+       int num_to_read = YY_BUF_SIZE - number_to_move - 1;
 
-       yy_n_chars += number_to_move;
-       yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-       yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+       if ( num_to_read > YY_READ_BUF_SIZE )
+           num_to_read = YY_READ_BUF_SIZE;
 
-       /* yytext begins at the second character in
-        * yy_ch_buf; the first character is the one which
-        * preceded it before reading in the latest buffer;
-        * it needs to be kept around in case it's a
-        * newline, so yy_get_previous_state() will have
-        * with '^' rules active
-        */
+       /* read in more data */
+       YY_INPUT( (&yy_ch_buf[number_to_move]), yy_n_chars, num_to_read );
+       }
 
-       yytext = &yy_ch_buf[1];
+    if ( yy_n_chars == 0 )
+       {
+       if ( number_to_move == 1 )
+           ret_val = EOB_ACT_END_OF_FILE;
+       else
+           ret_val = EOB_ACT_LAST_MATCH;
 
-       return ( ret_val );
+       yy_eof_has_been_seen = 1;
        }
+
+    else
+       ret_val = EOB_ACT_RESTART_SCAN;
+
+    yy_n_chars += number_to_move;
+    yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+    yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+    /* yytext begins at the second character in
+     * yy_ch_buf; the first character is the one which
+     * preceded it before reading in the latest buffer;
+     * it needs to be kept around in case it's a
+     * newline, so yy_get_previous_state() will have
+     * with '^' rules active
+     */
+
+    yytext = &yy_ch_buf[1];
+
+    return ( ret_val );
     }
 
 
@@ -355,9 +387,13 @@ static yy_state_type yy_get_previous_state()
     }
 
 
+#ifdef __STDC__
+static void yyunput( int c, register char *yy_bp )
+#else
 static void yyunput( c, yy_bp )
 int c;
 register char *yy_bp;
+#endif
 
     {
     register char *yy_cp = yy_c_buf_p;
@@ -441,3 +477,19 @@ static int input()
 
     return ( c );
     }
+
+
+#ifdef __STDC__
+static void yyrestart( FILE *input_file )
+#else
+static void yyrestart( input_file )
+FILE *input_file;
+#endif
+
+    {
+    if ( yyin != stdin )
+       fclose( yyin );
+
+    yyin = input_file;
+    yy_init = 1;
+    }
index 379a2faadb5ed2ad90ac6e13bc223e40810bcd88..85272fd5a7891ff817b04da699ab93aed85230e3 100644 (file)
--- a/flexdef.h
+++ b/flexdef.h
 #include <stdio.h>
 #endif
 
-#ifdef SV
+#ifdef SYS_V
 #include <string.h>
+
+#ifdef AMIGA
+#define bzero(s, n) setmem((char *)(s), (unsigned)(n), '\0')
+#define abs(x) ((x) < 0 ? -(x) : (x))
+#else
 #define bzero(s, n) memset((char *)(s), '\0', (unsigned)(n))
+#endif
+
 #ifndef VMS
 char *memset();
 #else
@@ -49,7 +56,7 @@ char *memset();
 #endif
 #endif
 
-#ifndef SV
+#ifndef SYS_V
 #include <strings.h>
 #ifdef lint
 char *sprintf(); /* keep lint happy */
@@ -331,6 +338,8 @@ extern struct hash_entry *ccltab[CCL_HASH_SIZE];
  * reject - if true, generate backtracking tables for REJECT macro
  * real_reject - if true, scanner really uses REJECT (as opposed to just
  *               having "reject" set for variable trailing context)
+ * continued_action - true if this rule's action is to "fall through" to
+ *                    the next rule's action (i.e., the '|' action)
  * yymore_really_used - has a REALLY_xxx value indicating whether a
  *                      %used or %notused was used with yymore()
  * reject_really_used - same for REJECT
@@ -339,7 +348,7 @@ extern struct hash_entry *ccltab[CCL_HASH_SIZE];
 extern int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
 extern int interactive, caseins, useecs, fulltbl, usemecs;
 extern int fullspd, gen_line_dirs, performance_report, backtrack_report;
-extern int yymore_used, reject, real_reject;
+extern int yymore_used, reject, real_reject, continued_action;
 
 #define REALLY_NOT_DETERMINED 0
 #define REALLY_USED 1
@@ -464,10 +473,13 @@ extern int tecfwd[CSIZE + 1], tecbck[CSIZE + 1];
  * scset - set of rules active in start condition
  * scbol - set of rules active only at the beginning of line in a s.c.
  * scxclu - true if start condition is exclusive
+ * sceof - true if start condition has EOF rule
+ * scname - start condition name
  * actvsc - stack of active start conditions for the current rule
  */
 
-extern int lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
+extern int lastsc, current_max_scs, *scset, *scbol, *scxclu, *sceof, *actvsc;
+extern char **scname;
 
 
 /* variables for dfa machine data:
@@ -566,6 +578,9 @@ char *allocate_array(), *reallocate_array();
 #define allocate_int_ptr_array(size) \
        (int **) allocate_array( size, sizeof( int * ) )
 
+#define allocate_char_ptr_array(size) \
+       (char **) allocate_array( size, sizeof( char * ) )
+
 #define allocate_dfaacc_union(size) \
        (union dfaacc_union *) \
                allocate_array( size, sizeof( union dfaacc_union ) )
@@ -573,6 +588,9 @@ char *allocate_array(), *reallocate_array();
 #define reallocate_int_ptr_array(array,size) \
        (int **) reallocate_array( (char *) array, size, sizeof( int * ) )
 
+#define reallocate_char_ptr_array(array,size) \
+       (char **) reallocate_array( (char *) array, size, sizeof( char * ) )
+
 #define reallocate_dfaacc_union(array, size) \
        (union dfaacc_union *)  reallocate_array( (char *) array, size, sizeof( union dfaacc_union ) )
 
diff --git a/gen.c b/gen.c
index 87e705844321d8afd1b2adb593d13dee86c18d5c..f39600d21c8995dc41107a9ee201ea3d1103599f 100644 (file)
--- a/gen.c
+++ b/gen.c
@@ -132,7 +132,7 @@ genctbl()
     int end_of_buffer_action = num_rules + 1;
 
     /* table of verify for transition and offset to next state */
-    printf( "static struct yy_trans_info yy_transition[%d] =\n",
+    printf( "static const struct yy_trans_info yy_transition[%d] =\n",
            tblend + numecs + 1 );
     printf( "    {\n" );
     
@@ -197,7 +197,7 @@ genctbl()
     printf( "\n" );
 
     /* table of pointers to start states */
-    printf( "static struct yy_trans_info *yy_start_state_list[%d] =\n",
+    printf( "static const struct yy_trans_info *yy_start_state_list[%d] =\n",
        lastsc * 2 + 1 );
     printf( "    {\n" );
 
@@ -217,7 +217,7 @@ genecs()
 
     {
     register int i, j;
-    static char C_char_decl[] = "static char %s[%d] =\n    {   0,\n";
+    static char C_char_decl[] = "static const char %s[%d] =\n    {   0,\n";
     int numrows;
     char clower();
 
@@ -390,7 +390,8 @@ genftbl()
     /* *everything* is done in terms of arrays starting at 1, so provide
      * a null entry for the zero element of all C arrays
      */
-    static char C_short_decl[] = "static short int %s[%d] =\n    {   0,\n";
+    static char C_short_decl[] =
+       "static const short int %s[%d] =\n    {   0,\n";
 
     printf( C_short_decl, ALIST, lastdfa + 1 );
 
@@ -611,8 +612,11 @@ gen_start_state()
            }
 
        if ( reject )
+           {
            /* set up for storing up states */
            indent_puts( "yy_state_ptr = yy_state_buf;" );
+           indent_puts( "*yy_state_ptr++ = yy_current_state;" );
+           }
        }
     }
 
@@ -632,9 +636,12 @@ gentabs()
     /* *everything* is done in terms of arrays starting at 1, so provide
      * a null entry for the zero element of all C arrays
      */
-    static char C_long_decl[] = "static long int %s[%d] =\n    {   0,\n";
-    static char C_short_decl[] = "static short int %s[%d] =\n    {   0,\n";
-    static char C_char_decl[] = "static char %s[%d] =\n    {   0,\n";
+    static char C_long_decl[] =
+       "static const long int %s[%d] =\n    {   0,\n";
+    static char C_short_decl[] =
+       "static const short int %s[%d] =\n    {   0,\n";
+    static char C_char_decl[] =
+       "static const char %s[%d] =\n    {   0,\n";
 
     acc_array = allocate_integer_array( current_max_dfas );
     nummt = 0;
@@ -684,7 +691,9 @@ gentabs()
 
                    ++j;
 
-                   if ( variable_trailing_context_rules && accnum > 0 &&
+                   if ( variable_trailing_context_rules &&
+                        ! (accnum & YY_TRAILING_HEAD_MASK) &&
+                        accnum > 0 &&
                         rule_type[accnum] == RULE_VARIABLE )
                        {
                        /* special hack to flag accepting number as part
@@ -895,6 +904,9 @@ char str[];
 make_tables()
 
     {
+    register int i;
+    int did_eof_rule = false;
+
     printf( "#define YY_END_OF_BUFFER %d\n", num_rules + 1 );
 
     if ( fullspd )
@@ -940,7 +952,7 @@ make_tables()
     if ( reject )
        {
        /* declare state buffer variables */
-       puts( "yy_trans_info yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;" );
+       puts( "yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;" );
        puts( "char *yy_full_match;" );
        puts( "int yy_lp;" );
 
@@ -982,6 +994,15 @@ make_tables()
        puts( " */" );
        puts( "#define REJECT reject_used_but_not_detected" );
        }
+    
+    if ( yymore_used )
+       {
+       indent_puts( "static char *yy_more_pos = (char *) 0;" );
+       indent_puts( "#define yymore() (yy_more_pos = yy_bp)" );
+       }
+    
+    else
+       indent_puts( "#define yymore() yymore_used_but_not_detected" );
 
 
     skelout();
@@ -996,6 +1017,26 @@ make_tables()
 
     set_indent( 2 );
 
+    if ( yymore_used )
+       {
+       indent_puts( "if ( yy_more_pos )" );
+       indent_up();
+       indent_puts( "{" );
+       indent_puts( "yy_bp = yy_more_pos;" );
+       indent_puts( "yy_more_pos = (char *) 0;" );
+       indent_puts( "}" );
+       indent_down();
+       indent_puts( "else" );
+       indent_up();
+       indent_puts( "yy_bp = yy_cp;" );
+       indent_down();
+       }
+
+    else
+       indent_puts( "yy_bp = yy_cp;" );
+
+    skelout();
+
     gen_start_state();
     gen_next_match();
 
@@ -1009,6 +1050,23 @@ make_tables()
     gen_bt_action();
     action_out();
 
+    /* generate cases for any missing EOF rules */
+    for ( i = 1; i <= lastsc; ++i )
+       if ( ! sceof[i] )
+           {
+           do_indent();
+           printf( "case YY_STATE_EOF(%s):\n", scname[i] );
+           did_eof_rule = true;
+           }
+    
+    if ( did_eof_rule )
+       {
+       indent_up();
+       indent_puts( "yyterminate();" );
+       indent_down();
+       }
+
+
     /* generate code for yy_get_previous_state() */
     set_indent( 1 );
     skelout();
diff --git a/misc.c b/misc.c
index 08ebf2daed5fba53286def365747fa10c2ed71f2..004e267c9dbdc5e749b8c21b6ba147c49d12fa60 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -289,11 +289,15 @@ dataflush()
     datapos = 0;
     }
 
-/* gettime - return current time
+/* flex_gettime - return current time
  *
  * synopsis
- *    char *gettime(), *time_str;
- *    time_str = gettime();
+ *    char *flex_gettime(), *time_str;
+ *    time_str = flex_gettime();
+ *
+ * note
+ *    the routine name has the "flex_" prefix because of name clashes
+ *    with Turbo-C
  */
 
 /* include sys/types.h to use time_t and make lint happy */
@@ -311,7 +315,7 @@ dataflush()
 typedef long time_t;
 #endif
 
-char *gettime()
+char *flex_gettime()
 
     {
     time_t t, time();
@@ -377,6 +381,7 @@ char msg[];
 
     {
     fprintf( stderr, "flex: %s\n", msg );
+
     flexend( 1 );
     }
 
@@ -506,48 +511,53 @@ char array[];
     {
     switch ( array[1] )
        {
-       case 'n': return ( '\n' );
-       case 't': return ( '\t' );
+       case 'a': return ( '\a' );
+       case 'b': return ( '\b' );
        case 'f': return ( '\f' );
+       case 'n': return ( '\n' );
        case 'r': return ( '\r' );
-       case 'b': return ( '\b' );
+       case 't': return ( '\t' );
+       case 'v': return ( '\v' );
 
        case '0':
-           if ( isdigit(array[2]) )
-               { /* \0<octal> */
-               char c, esc_char;
-               register int sptr = 2;
-
-               while ( isdigit(array[sptr]) )
-                   /* don't increment inside loop control because the
-                    * macro will expand it to two increments!  (Not a
-                    * problem with the C version of the macro)
-                    */
-                   ++sptr;
-
-               c = array[sptr];
-               array[sptr] = '\0';
-
-               esc_char = otoi( array + 2 );
-               array[sptr] = c;
-
-               if ( esc_char == '\0' )
-                   {
-                   synerr( "escape sequence for null not allowed" );
-                   return ( 1 );
-                   }
-
-               return ( esc_char );
-               }
-
-           else
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+           { /* \<octal> */
+           char c, esc_char;
+           register int sptr = 1;
+
+           while ( isdigit(array[sptr]) )
+               /* don't increment inside loop control because if
+                * isdigit() is a macro it will expand it to two
+                * increments ...
+                */
+               ++sptr;
+
+           c = array[sptr];
+           array[sptr] = '\0';
+
+           esc_char = otoi( array + 1 );
+           array[sptr] = c;
+
+           if ( esc_char == '\0' )
                {
                synerr( "escape sequence for null not allowed" );
                return ( 1 );
                }
+
+           return ( esc_char );
+           }
+
+       default:
+           return ( array[1] );
        }
-    
-    return ( array[1] );
     }
 
 
diff --git a/nfa.c b/nfa.c
index d386037ebb7f1b1ad6e3b4fe89c387f4fa2e3c57..53fdd013ef984b5ff000e4a00a0099fdc549eb26 100644 (file)
--- a/nfa.c
+++ b/nfa.c
@@ -216,7 +216,7 @@ int mach, variable_trail_rule, headcnt, trailcnt;
     /* we did this in new_rule(), but it often gets the wrong
      * number because we do it before we start parsing the current rule
      */
-    rule_type[num_rules] = linenum;
+    rule_linenum[num_rules] = linenum;
 
     fprintf( temp_action_file, "case %d:\n", num_rules );
 
diff --git a/parse.y b/parse.y
index 6f742dcd468d300fcee5f80e6a375bde7f081393..f11f738ec4b4fd6371cb9edbf95a6005097a60de 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -24,7 +24,7 @@
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-%token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL
+%token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL EOF_OP
 
 %{
 
@@ -46,6 +46,7 @@ int trlcontxt, xcluflg, cclsorted, varlength, variable_trail_rule;
 char clower();
 
 static int madeany = false;  /* whether we've made the '.' character class */
+int previous_continued_action; /* whether the previous rule's action was '|' */
 
 %}
 
@@ -59,7 +60,7 @@ goal            :  initlex sect1 sect1end sect2 initforrule
 
                        def_rule = mkstate( -pat );
 
-                       finish_rule( def_rule, variable_trail_rule, 0, 0 );
+                       finish_rule( def_rule, false, 0, 0 );
 
                        for ( i = 1; i <= lastsc; ++i )
                            scset[i] = mkbranch( scset[i], def_rule );
@@ -126,6 +127,7 @@ initforrule     :
                        trlcontxt = variable_trail_rule = varlength = false;
                        trailcnt = headcnt = rulelen = 0;
                        current_state_type = STATE_NORMAL;
+                       previous_continued_action = continued_action;
                        new_rule();
                        }
                ;
@@ -196,6 +198,16 @@ flexrule        :  scon '^' re eol
                                scset[i] = mkbranch( scset[i], pat );
                        }
 
+                |  scon EOF_OP
+                       { build_eof_action(); }
+
+                |  EOF_OP
+                       {
+                       /* this EOF applies only to the INITIAL start cond. */
+                       actvsc[actvp = 1] = 1;
+                       build_eof_action();
+                       }
+
                 |  error
                        { synerr( "unrecognized rule" ); }
                ;
@@ -206,7 +218,7 @@ scon            :  '<' namelist2 '>'
 namelist2       :  namelist2 ',' NAME
                         {
                        if ( (scnum = sclookup( nmstr )) == 0 )
-                           synerr( "undeclared start condition" );
+                           lerrsf( "undeclared start condition %s", nmstr );
 
                        else
                            actvsc[++actvp] = scnum;
@@ -215,7 +227,7 @@ namelist2       :  namelist2 ',' NAME
                |  NAME
                        {
                        if ( (scnum = sclookup( nmstr )) == 0 )
-                           synerr( "undeclared start condition" );
+                           lerrsf( "undeclared start condition %s", nmstr );
                        else
                            actvsc[actvp = 1] = scnum;
                        }
@@ -280,6 +292,28 @@ re              :  re '|' series
                        mark_beginning_as_normal( $2 );
                        current_state_type = STATE_NORMAL;
 
+                       if ( previous_continued_action )
+                           {
+                           /* we need to treat this as variable trailing
+                            * context so that the backup does not happen
+                            * in the action but before the action switch
+                            * statement.  If the backup happens in the
+                            * action, then the rules "falling into" this
+                            * one's action will *also* do the backup,
+                            * erroneously.
+                            */
+                           if ( ! varlength || headcnt != 0 )
+                               {
+                               if ( performance_report )
+                                   fprintf( stderr,
+    "trailing context rule made variable because of preceding '|' action\n" );
+                               }
+
+                           /* mark as variable */
+                           varlength = true;
+                           headcnt = 0;
+                           }
+
                        if ( varlength && headcnt == 0 )
                            { /* variable trailing context rule */
                            /* mark the first part of the rule as the accepting
@@ -558,6 +592,34 @@ string             :  string CHAR
 
 %%
 
+
+/* build_eof_action - build the "<<EOF>>" action for the active start
+ *                    conditions
+ */
+
+build_eof_action()
+
+    {
+    register int i;
+
+    for ( i = 1; i <= actvp; ++i )
+       {
+       if ( sceof[actvsc[i]] )
+           lerrsf( "multiple <<EOF>> rules for start condition %s",
+                   scname[actvsc[i]] );
+
+       else
+           {
+           sceof[actvsc[i]] = true;
+           fprintf( temp_action_file, "case YY_STATE_EOF(%s):\n",
+                    scname[actvsc[i]] );
+           }
+       }
+
+    line_directive_out( temp_action_file );
+    }
+
+
 /* synerr - report a syntax error
  *
  * synopsis
diff --git a/scan.l b/scan.l
index 6c9f0c011ca32778a588b9c9c62b7ff0e52ac9d1..092c02821bd1be72804b2c1e77acf7a163466b48 100644 (file)
--- a/scan.l
+++ b/scan.l
@@ -78,7 +78,7 @@ NOT_NAME      [^a-z_\n]+
 
 SCNAME         {NAME}
 
-ESCSEQ         \\([^\n]|0[0-9]{1,3})
+ESCSEQ         \\([^\n]|[0-9]{1,3})
 
 %%
     static int bracelevel, didadef;
@@ -107,7 +107,7 @@ ESCSEQ              \\([^\n]|0[0-9]{1,3})
                        }
 
 ^"%used"               checking_used = REALLY_USED; BEGIN(USED_LIST);
-^"%not"{OPTWS}"used"   checking_used = REALLY_NOT_USED; BEGIN(USED_LIST);
+^"%unused"             checking_used = REALLY_NOT_USED; BEGIN(USED_LIST);
 
 
 ^"%"[^sx]" ".*\n               {
@@ -181,15 +181,15 @@ ESCSEQ            \\([^\n]|0[0-9]{1,3})
                        if ( all_upper( yytext ) )
                            reject_really_used = checking_used;
                        else
-                           synerr( "unrecognized %used/%notused construct" );
+                           synerr( "unrecognized %used/%unused construct" );
                        }
 <USED_LIST>"yymore"    {
                        if ( all_lower( yytext ) )
                            yymore_really_used = checking_used;
                        else
-                           synerr( "unrecognized %used/%notused construct" );
+                           synerr( "unrecognized %used/%unused construct" );
                        }
-<USED_LIST>{NOT_WS}+   synerr( "unrecognized %used/%notused construct" );
+<USED_LIST>{NOT_WS}+   synerr( "unrecognized %used/%unused construct" );
 
 
 <SECT2PROLOG>.*\n/{NOT_WS}     {
@@ -201,6 +201,8 @@ ESCSEQ              \\([^\n]|0[0-9]{1,3})
 
 <SECT2PROLOG>.*\n      ++linenum; ACTION_ECHO;
 
+<SECT2PROLOG><<EOF>>   MARK_END_OF_PROLOG; yyterminate();
+
 <SECT2>^{OPTWS}\n      ++linenum; /* allow blank lines in section 2 */
 
        /* this horrible mess of a rule matches indented lines which
@@ -225,26 +227,22 @@ ESCSEQ            \\([^\n]|0[0-9]{1,3})
                        BEGIN(PERCENT_BRACE_ACTION);
                        return ( '\n' );
                        }
-<SECT2>{WS}"|".*\n     ++linenum; return ( '\n' );
+<SECT2>{WS}"|".*\n     continued_action = true; ++linenum; return ( '\n' );
 
 <SECT2>^{OPTWS}"/*"    ACTION_ECHO; BEGIN(C_COMMENT_2);
 
-<SECT2>{WS}            { /* needs to be separate from following rule due to
-                          * bug with trailing context
-                          */
-                       bracelevel = 0;
-                       BEGIN(ACTION);
-                       return ( '\n' );
-                       }
-
+<SECT2>{WS}            |
 <SECT2>{OPTWS}/\n      {
                        bracelevel = 0;
+                       continued_action = false;
                        BEGIN(ACTION);
                        return ( '\n' );
                        }
 
 <SECT2>^{OPTWS}\n      ++linenum; return ( '\n' );
 
+<SECT2>"<<EOF>>"       return ( EOF_OP );
+
 <SECT2>^"%%".*         {
                        sectnum = 3;
                        BEGIN(SECT3);
diff --git a/sym.c b/sym.c
index 3cccd8df2795c674f6dda931883188f9ac4de4b1..48aaee01ca5913ab53a88694ffd271ffc43ae12b 100644 (file)
--- a/sym.c
+++ b/sym.c
@@ -266,7 +266,7 @@ int xcluflg;
      */
 
     if ( strcmp( str, "0" ) )
-       printf( "#define %s %d\n", str, lastsc * 2 );
+       printf( "#define %s %d\n", str, lastsc );
 
     if ( ++lastsc >= current_max_scs )
        {
@@ -277,16 +277,21 @@ int xcluflg;
        scset = reallocate_integer_array( scset, current_max_scs );
        scbol = reallocate_integer_array( scbol, current_max_scs );
        scxclu = reallocate_integer_array( scxclu, current_max_scs );
+       sceof = reallocate_integer_array( sceof, current_max_scs );
+       scname = reallocate_char_ptr_array( scname, current_max_scs );
        actvsc = reallocate_integer_array( actvsc, current_max_scs );
        }
 
-    if ( addsym( copy_string( str ), (char *) 0, lastsc,
-                sctbl, START_COND_HASH_SIZE ) )
+    scname[lastsc] = copy_string( str );
+
+    if ( addsym( scname[lastsc], (char *) 0, lastsc,
+                sctbl, START_COND_HASH_SIZE ) )
        lerrsf( "start condition %s declared twice", str );
 
     scset[lastsc] = mkstate( SYM_EPSILON );
     scbol[lastsc] = mkstate( SYM_EPSILON );
     scxclu[lastsc] = xcluflg;
+    sceof[lastsc] = false;
     }