summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO6
-rw-r--r--doc/flex.texi94
-rw-r--r--flex.skl269
-rw-r--r--gen.c8
-rw-r--r--main.c6
5 files changed, 296 insertions, 87 deletions
diff --git a/TODO b/TODO
index f470999..1fef06c 100644
--- a/TODO
+++ b/TODO
@@ -52,15 +52,13 @@
** make test suite more complete
+** add a test for yypush_buffer_state/yypop_buffer_state
+
* generic coding
** move as much skeleton code as possible out of gen.c and into
flex.skl
-** Automatic management of the input buffer stack. (currently does
- this for the start condition stack, but not for the input
- buffer stack.)
-
** figure out whether we want to add the capability to have
auto-generated backout rules
diff --git a/doc/flex.texi b/doc/flex.texi
index 9a0d057..cd3ecad 100644
--- a/doc/flex.texi
+++ b/doc/flex.texi
@@ -1928,12 +1928,14 @@ using:
@deftypefun void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer )
@end deftypefun
-The above switches the scanner's input buffer so subsequent tokens will
-come from @code{new_buffer}. Note that @code{yy_switch_to_buffer()} may
-be used by @code{yywrap()} to set things up for continued scanning,
-instead of opening a new file and pointing @file{yyin} at it. Note also
-that switching input sources via either @code{yy_switch_to_buffer()} or
-@code{yywrap()} does @emph{not} change the start condition.
+The above function switches the scanner's input buffer so subsequent tokens
+will come from @code{new_buffer}. Note that @code{yy_switch_to_buffer()} may
+be used by @code{yywrap()} to set things up for continued scanning, instead of
+opening a new file and pointing @file{yyin} at it. If you are looking for a
+stack of input buffers, then you want to use @code{yypush_buffer_state()}
+instead of this function. Note also that switching input sources via either
+@code{yy_switch_to_buffer()} or @code{yywrap()} does @emph{not} change the
+start condition.
@cindex memory, deleting input buffers
@deftypefun void yy_delete_buffer ( YY_BUFFER_STATE buffer )
@@ -1943,6 +1945,26 @@ is used to reclaim the storage associated with a buffer. (@code{buffer}
can be NULL, in which case the routine does nothing.) You can also clear
the current contents of a buffer using:
+@cindex pushing an input buffer
+@cindex stack, input buffer push
+@deftypefun void yypush_buffer_state ( YY_BUFFER_STATE buffer )
+@end deftypefun
+
+This function pushes the new buffer state onto an internal stack. The pushed
+state becomes the new current state. The stack is maintained by flex and will
+grow as required. This function is intended to be used instead of
+@code{yy_switch_to_buffer}, when you want to change states, but preserve the
+current state for later use.
+
+@cindex popping an input buffer
+@cindex stack, input buffer pop
+@deftypefun void yypop_buffer_state ( )
+@end deftypefun
+
+This function removes the current state from the top of the stack, and deletes
+it by calling @code{yy_delete_buffer}. The next state on the stack, if any,
+becomes the new current state.
+
@cindex clearing an input buffer
@cindex flushing an input buffer
@deftypefun void yy_flush_buffer ( YY_BUFFER_STATE buffer )
@@ -1960,15 +1982,57 @@ is an alias for @code{yy_create_buffer()},
provided for compatibility with the C++ use of @code{new} and
@code{delete} for creating and destroying dynamic objects.
-@cindex YY_CURRENT_BUFFER, and multiple buffers
-Finally, the macro @code{YY_CURRENT_BUFFER} macro returns a
-@code{YY_BUFFER_STATE} handle to the current buffer.
+@cindex YY_CURRENT_BUFFER, and multiple buffers Finally, the macro
+@code{YY_CURRENT_BUFFER} macro returns a @code{YY_BUFFER_STATE} handle to the
+current buffer. It should not be used as an lvalue.
@cindex EOF, example using multiple input buffers
-Here is an example of using these features for writing a scanner
+Here are two examples of using these features for writing a scanner
which expands include files (the
@code{<<EOF>>}
-feature is discussed below):
+feature is discussed below).
+
+This first example uses yypush_buffer_state and yypop_buffer_state. Flex
+maintains the stack internally.
+
+@cindex handling include files with multiple input buffers
+@example
+@verbatim
+ /* the "incl" state is used for picking up the name
+ * of an include file
+ */
+ %x incl
+ %%
+ include BEGIN(incl);
+
+ [a-z]+ ECHO;
+ [^a-z\n]*\n? ECHO;
+
+ <incl>[ \t]* /* eat the whitespace */
+ <incl>[^ \t\n]+ { /* got the include file name */
+ yyin = fopen( yytext, "r" );
+
+ if ( ! yyin )
+ error( ... );
+
+ yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
+
+ BEGIN(INITIAL);
+ }
+
+ <<EOF>> {
+ yypop_buffer_state();
+
+ if ( !YY_CURRENT_BUFFER )
+ {
+ yyterminate();
+ }
+ }
+@end verbatim
+@end example
+
+The second example, below, does the same thing as the previous example did, but
+manages its own input buffer stack manually (instead of letting flex do it).
@cindex handling include files with multiple input buffers
@example
@@ -5882,7 +5946,7 @@ you might try this:
@example
@verbatim
/* For non-reentrant C scanner only. */
-yy_delete_buffer(yy_current_buffer);
+yy_delete_buffer(YY_CURRENT_BUFFER);
yy_init = 1;
@end verbatim
@end example
@@ -5898,7 +5962,7 @@ situation. It is possible that some other globals may need resetting as well.
> We thought that it would be possible to have this number through the
> evaluation of the following expression:
>
-> seek_position = (no_buffers)*YY_READ_BUF_SIZE + yy_c_buf_p - yy_current_buffer->yy_ch_buf
+> seek_position = (no_buffers)*YY_READ_BUF_SIZE + yy_c_buf_p - YY_CURRENT_BUFFER->yy_ch_buf
@end verbatim
@end example
@@ -5909,7 +5973,7 @@ even though @code{YY_READ_BUF_SIZE} bytes were requested). The second problem
is that when refilling its internal buffer, @code{flex} keeps some characters
from the previous buffer (because usually it's in the middle of a match,
and needs those characters to construct @code{yytext} for the match once it's
-done). Because of this, @code{yy_c_buf_p - yy_current_buffer->yy_ch_buf} won't
+done). Because of this, @code{yy_c_buf_p - YY_CURRENT_BUFFER->yy_ch_buf} won't
be exactly the number of characters already read from the current buffer.
An alternative solution is to count the number of characters you've matched
@@ -6267,7 +6331,7 @@ Date: Wed, 13 Nov 1996 19:51:54 PST
From: Vern Paxson <vern>
> "unput()" them to input flow, question occurs. If I do this after I scan
-> a carriage, the variable "yy_current_buffer->yy_at_bol" is changed. That
+> a carriage, the variable "YY_CURRENT_BUFFER->yy_at_bol" is changed. That
> means the carriage flag has gone.
You can control this by calling yy_set_bol(). It's described in the manual.
diff --git a/flex.skl b/flex.skl
index c3c1fc9..c4d70d1 100644
--- a/flex.skl
+++ b/flex.skl
@@ -393,16 +393,28 @@ struct yy_buffer_state
%c-only Standard (non-C++) definition
%not-for-header
%if-not-reentrant
-static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /*<< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /*<< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /*<< Stack as an array. */
%endif
%ok-for-header
%pop
-
/* We provide macros for accessing buffer states in case in the
* future we want to put the buffer states in a more general
* "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( YY_G(yy_buffer_stack) \
+ ? YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
*/
-#define YY_CURRENT_BUFFER yy_current_buffer
+#define YY_CURRENT_BUFFER_FAST YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)]
%push
%c-only Standard (non-C++) definition
@@ -438,8 +450,11 @@ YY_BUFFER_STATE yy_create_buffer YY_PARAMS(( FILE *file, int size YY_PROTO_LAST_
void yy_delete_buffer YY_PARAMS(( YY_BUFFER_STATE b YY_PROTO_LAST_ARG ));
void yy_init_buffer YY_PARAMS(( YY_BUFFER_STATE b, FILE *file YY_PROTO_LAST_ARG ));
void yy_flush_buffer YY_PARAMS(( YY_BUFFER_STATE b YY_PROTO_LAST_ARG ));
+void yypush_buffer_state YY_PARAMS(( YY_BUFFER_STATE new_buffer YY_PROTO_LAST_ARG ));
+void yypop_buffer_state YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+void yyensure_buffer_stack YY_PARAMS(( YY_PROTO_ONLY_ARG ));
-#define YY_FLUSH_BUFFER yy_flush_buffer( YY_G(yy_current_buffer) YY_CALL_LAST_ARG)
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER YY_CALL_LAST_ARG)
YY_BUFFER_STATE yy_scan_buffer YY_PARAMS(( char *base, yy_size_t size YY_PROTO_LAST_ARG ));
YY_BUFFER_STATE yy_scan_string YY_PARAMS(( yyconst char *yy_str YY_PROTO_LAST_ARG ));
@@ -455,21 +470,25 @@ void yyfree YY_PARAMS(( void * YY_PROTO_LAST_ARG ));
#define yy_set_interactive(is_interactive) \
{ \
- if ( ! YY_G(yy_current_buffer) ) \
- YY_G(yy_current_buffer) = \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (YY_CALL_ONLY_ARG); \
+ YY_CURRENT_BUFFER_FAST = \
yy_create_buffer( yyin, YY_BUF_SIZE YY_CALL_LAST_ARG); \
- YY_G(yy_current_buffer)->yy_is_interactive = is_interactive; \
+ } \
+ YY_CURRENT_BUFFER_FAST->yy_is_interactive = is_interactive; \
}
#define yy_set_bol(at_bol) \
{ \
- if ( ! YY_G(yy_current_buffer) ) \
- YY_G(yy_current_buffer) = \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (YY_CALL_ONLY_ARG); \
+ YY_CURRENT_BUFFER_FAST = \
yy_create_buffer( yyin, YY_BUF_SIZE YY_CALL_LAST_ARG); \
- YY_G(yy_current_buffer)->yy_at_bol = at_bol; \
+ } \
+ YY_CURRENT_BUFFER_FAST->yy_at_bol = at_bol; \
}
-#define YY_AT_BOL() (YY_G(yy_current_buffer)->yy_at_bol)
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_FAST->yy_at_bol)
%% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here
@@ -531,7 +550,9 @@ struct yyguts_t
/* The rest are the same as the globals declared in the non-reentrant scanner. */
FILE *yyin_r, *yyout_r;
- YY_BUFFER_STATE yy_current_buffer;
+ size_t yy_buffer_stack_top; /*<< index of top of stack. */
+ size_t yy_buffer_stack_max; /*<< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /*<< Stack as an array. */
char yy_hold_char;
int yy_n_chars;
int yyleng_r;
@@ -934,9 +955,11 @@ YY_DECL
yyout = & std::cout;
%pop
- if ( ! YY_G(yy_current_buffer) )
- YY_G(yy_current_buffer) =
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack (YY_CALL_ONLY_ARG);
+ YY_CURRENT_BUFFER_FAST =
yy_create_buffer( yyin, YY_BUF_SIZE YY_CALL_LAST_ARG);
+ }
yy_load_buffer_state( YY_CALL_ONLY_ARG );
}
@@ -980,20 +1003,20 @@ do_action: /* This label is used only to access EOF actions. */
*yy_cp = YY_G(yy_hold_char);
YY_RESTORE_YY_MORE_OFFSET
- if ( YY_G(yy_current_buffer)->yy_buffer_status == YY_BUFFER_NEW )
+ if ( YY_CURRENT_BUFFER_FAST->yy_buffer_status == YY_BUFFER_NEW )
{
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
* yylex(). If so, then we have to assure
- * consistency between yy_current_buffer and our
+ * consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
* back-up) that will match for the new input source.
*/
- YY_G(yy_n_chars) = YY_G(yy_current_buffer)->yy_n_chars;
- YY_G(yy_current_buffer)->yy_input_file = yyin;
- YY_G(yy_current_buffer)->yy_buffer_status = YY_BUFFER_NORMAL;
+ YY_G(yy_n_chars) = YY_CURRENT_BUFFER_FAST->yy_n_chars;
+ YY_CURRENT_BUFFER_FAST->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_FAST->yy_buffer_status = YY_BUFFER_NORMAL;
}
/* Note that here we test for yy_c_buf_p "<=" to the position
@@ -1003,7 +1026,7 @@ do_action: /* This label is used only to access EOF actions. */
* end-of-buffer state). Contrast this with the test
* in input().
*/
- if ( YY_G(yy_c_buf_p) <= &YY_G(yy_current_buffer)->yy_ch_buf[YY_G(yy_n_chars)] )
+ if ( YY_G(yy_c_buf_p) <= &YY_CURRENT_BUFFER_FAST->yy_ch_buf[YY_G(yy_n_chars)] )
{ /* This was really a NUL. */
yy_state_type yy_next_state;
@@ -1082,7 +1105,7 @@ do_action: /* This label is used only to access EOF actions. */
case EOB_ACT_LAST_MATCH:
YY_G(yy_c_buf_p) =
- &YY_G(yy_current_buffer)->yy_ch_buf[YY_G(yy_n_chars)];
+ &YY_CURRENT_BUFFER_FAST->yy_ch_buf[YY_G(yy_n_chars)];
yy_current_state = yy_get_previous_state( YY_CALL_ONLY_ARG );
@@ -1205,16 +1228,16 @@ static int yy_get_next_buffer YYFARGS0(void)
int yyFlexLexer::yy_get_next_buffer()
%pop
{
- register char *dest = YY_G(yy_current_buffer)->yy_ch_buf;
+ register char *dest = YY_CURRENT_BUFFER_FAST->yy_ch_buf;
register char *source = YY_G(yytext_ptr);
register int number_to_move, i;
int ret_val;
- if ( YY_G(yy_c_buf_p) > &YY_G(yy_current_buffer)->yy_ch_buf[YY_G(yy_n_chars) + 1] )
+ if ( YY_G(yy_c_buf_p) > &YY_CURRENT_BUFFER_FAST->yy_ch_buf[YY_G(yy_n_chars) + 1] )
YY_FATAL_ERROR(
"fatal flex scanner internal error--end of buffer missed" );
- if ( YY_G(yy_current_buffer)->yy_fill_buffer == 0 )
+ if ( YY_CURRENT_BUFFER_FAST->yy_fill_buffer == 0 )
{ /* Don't try to fill the buffer, so this is an EOF. */
if ( YY_G(yy_c_buf_p) - YY_G(yytext_ptr) - YY_MORE_ADJ == 1 )
{
@@ -1241,16 +1264,16 @@ int yyFlexLexer::yy_get_next_buffer()
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
- if ( YY_G(yy_current_buffer)->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ if ( YY_CURRENT_BUFFER_FAST->yy_buffer_status == YY_BUFFER_EOF_PENDING )
/* don't do the read, it's not guaranteed to return an EOF,
* just force an EOF
*/
- YY_G(yy_current_buffer)->yy_n_chars = YY_G(yy_n_chars) = 0;
+ YY_CURRENT_BUFFER_FAST->yy_n_chars = YY_G(yy_n_chars) = 0;
else
{
size_t num_to_read =
- YY_G(yy_current_buffer)->yy_buf_size - number_to_move - 1;
+ YY_CURRENT_BUFFER_FAST->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */
@@ -1260,7 +1283,7 @@ int yyFlexLexer::yy_get_next_buffer()
#else
/* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = YY_G(yy_current_buffer);
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
int yy_c_buf_p_offset =
(int) (YY_G(yy_c_buf_p) - b->yy_ch_buf);
@@ -1289,7 +1312,7 @@ int yyFlexLexer::yy_get_next_buffer()
YY_G(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
- num_to_read = YY_G(yy_current_buffer)->yy_buf_size -
+ num_to_read = YY_CURRENT_BUFFER_FAST->yy_buf_size -
number_to_move - 1;
#endif
}
@@ -1298,10 +1321,10 @@ int yyFlexLexer::yy_get_next_buffer()
num_to_read = YY_READ_BUF_SIZE;
/* Read in more data. */
- YY_INPUT( (&YY_G(yy_current_buffer)->yy_ch_buf[number_to_move]),
+ YY_INPUT( (&YY_CURRENT_BUFFER_FAST->yy_ch_buf[number_to_move]),
YY_G(yy_n_chars), num_to_read );
- YY_G(yy_current_buffer)->yy_n_chars = YY_G(yy_n_chars);
+ YY_CURRENT_BUFFER_FAST->yy_n_chars = YY_G(yy_n_chars);
}
if ( YY_G(yy_n_chars) == 0 )
@@ -1315,7 +1338,7 @@ int yyFlexLexer::yy_get_next_buffer()
else
{
ret_val = EOB_ACT_LAST_MATCH;
- YY_G(yy_current_buffer)->yy_buffer_status =
+ YY_CURRENT_BUFFER_FAST->yy_buffer_status =
YY_BUFFER_EOF_PENDING;
}
}
@@ -1324,10 +1347,10 @@ int yyFlexLexer::yy_get_next_buffer()
ret_val = EOB_ACT_CONTINUE_SCAN;
YY_G(yy_n_chars) += number_to_move;
- YY_G(yy_current_buffer)->yy_ch_buf[YY_G(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
- YY_G(yy_current_buffer)->yy_ch_buf[YY_G(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_FAST->yy_ch_buf[YY_G(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_FAST->yy_ch_buf[YY_G(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
- YY_G(yytext_ptr) = &YY_G(yy_current_buffer)->yy_ch_buf[0];
+ YY_G(yytext_ptr) = &YY_CURRENT_BUFFER_FAST->yy_ch_buf[0];
return ret_val;
}
@@ -1389,24 +1412,24 @@ int yyFlexLexer::yy_get_next_buffer()
/* undo effects of setting up yytext */
*yy_cp = YY_G(yy_hold_char);
- if ( yy_cp < YY_G(yy_current_buffer)->yy_ch_buf + 2 )
+ if ( yy_cp < YY_CURRENT_BUFFER_FAST->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
register int number_to_move = YY_G(yy_n_chars) + 2;
- register char *dest = &YY_G(yy_current_buffer)->yy_ch_buf[
- YY_G(yy_current_buffer)->yy_buf_size + 2];
+ register char *dest = &YY_CURRENT_BUFFER_FAST->yy_ch_buf[
+ YY_CURRENT_BUFFER_FAST->yy_buf_size + 2];
register char *source =
- &YY_G(yy_current_buffer)->yy_ch_buf[number_to_move];
+ &YY_CURRENT_BUFFER_FAST->yy_ch_buf[number_to_move];
- while ( source > YY_G(yy_current_buffer)->yy_ch_buf )
+ while ( source > YY_CURRENT_BUFFER_FAST->yy_ch_buf )
*--dest = *--source;
yy_cp += (int) (dest - source);
yy_bp += (int) (dest - source);
- YY_G(yy_current_buffer)->yy_n_chars =
- YY_G(yy_n_chars) = YY_G(yy_current_buffer)->yy_buf_size;
+ YY_CURRENT_BUFFER_FAST->yy_n_chars =
+ YY_G(yy_n_chars) = YY_CURRENT_BUFFER_FAST->yy_buf_size;
- if ( yy_cp < YY_G(yy_current_buffer)->yy_ch_buf + 2 )
+ if ( yy_cp < YY_CURRENT_BUFFER_FAST->yy_ch_buf + 2 )
YY_FATAL_ERROR( "flex scanner push-back overflow" );
}
@@ -1450,7 +1473,7 @@ int yyFlexLexer::yy_get_next_buffer()
* If this occurs *before* the EOB characters, then it's a
* valid NUL; if not, then we've hit the end of the buffer.
*/
- if ( YY_G(yy_c_buf_p) < &YY_G(yy_current_buffer)->yy_ch_buf[YY_G(yy_n_chars)] )
+ if ( YY_G(yy_c_buf_p) < &YY_CURRENT_BUFFER_FAST->yy_ch_buf[YY_G(yy_n_chars)] )
/* This was really a NUL. */
*YY_G(yy_c_buf_p) = '\0';
@@ -1518,11 +1541,13 @@ int yyFlexLexer::yy_get_next_buffer()
void yyFlexLexer::yyrestart( std::istream* input_file )
%pop
{
- if ( ! YY_G(yy_current_buffer) )
- YY_G(yy_current_buffer) =
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack (YY_CALL_ONLY_ARG);
+ YY_CURRENT_BUFFER_FAST =
yy_create_buffer( yyin, YY_BUF_SIZE YY_CALL_LAST_ARG);
+ }
- yy_init_buffer( YY_G(yy_current_buffer), input_file YY_CALL_LAST_ARG);
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file YY_CALL_LAST_ARG);
yy_load_buffer_state( YY_CALL_ONLY_ARG );
}
@@ -1533,18 +1558,24 @@ int yyFlexLexer::yy_get_next_buffer()
void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
%pop
{
- if ( YY_G(yy_current_buffer) == new_buffer )
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack (YY_CALL_ONLY_ARG);
+ if ( YY_CURRENT_BUFFER == new_buffer )
return;
- if ( YY_G(yy_current_buffer) )
+ if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
*YY_G(yy_c_buf_p) = YY_G(yy_hold_char);
- YY_G(yy_current_buffer)->yy_buf_pos = YY_G(yy_c_buf_p);
- YY_G(yy_current_buffer)->yy_n_chars = YY_G(yy_n_chars);
+ YY_CURRENT_BUFFER_FAST->yy_buf_pos = YY_G(yy_c_buf_p);
+ YY_CURRENT_BUFFER_FAST->yy_n_chars = YY_G(yy_n_chars);
}
- YY_G(yy_current_buffer) = new_buffer;
+ YY_CURRENT_BUFFER_FAST = new_buffer;
yy_load_buffer_state( YY_CALL_ONLY_ARG );
/* We don't actually know whether we did this switch during
@@ -1563,9 +1594,9 @@ int yyFlexLexer::yy_get_next_buffer()
void yyFlexLexer::yy_load_buffer_state()
%pop
{
- YY_G(yy_n_chars) = YY_G(yy_current_buffer)->yy_n_chars;
- YY_G(yytext_ptr) = YY_G(yy_c_buf_p) = YY_G(yy_current_buffer)->yy_buf_pos;
- yyin = YY_G(yy_current_buffer)->yy_input_file;
+ YY_G(yy_n_chars) = YY_CURRENT_BUFFER_FAST->yy_n_chars;
+ YY_G(yytext_ptr) = YY_G(yy_c_buf_p) = YY_CURRENT_BUFFER_FAST->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_FAST->yy_input_file;
YY_G(yy_hold_char) = *YY_G(yy_c_buf_p);
}
@@ -1608,8 +1639,8 @@ int yyFlexLexer::yy_get_next_buffer()
if ( ! b )
return;
- if ( b == YY_G(yy_current_buffer) )
- YY_G(yy_current_buffer) = (YY_BUFFER_STATE) 0;
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_FAST = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
yyfree( (void *) b->yy_ch_buf YY_CALL_LAST_ARG );
@@ -1688,10 +1719,111 @@ void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file )
b->yy_at_bol = 1;
b->yy_buffer_status = YY_BUFFER_NEW;
- if ( b == YY_G(yy_current_buffer) )
+ if ( b == YY_CURRENT_BUFFER )
yy_load_buffer_state( YY_CALL_ONLY_ARG );
}
+%push
+%c-only
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ */
+void yypush_buffer_state YYFARGS1(YY_BUFFER_STATE,new_buffer)
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack(YY_CALL_ONLY_ARG);
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *YY_G(yy_c_buf_p) = YY_G(yy_hold_char);
+ YY_CURRENT_BUFFER_FAST->yy_buf_pos = YY_G(yy_c_buf_p);
+ YY_CURRENT_BUFFER_FAST->yy_n_chars = YY_G(yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ YY_G(yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_FAST = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( YY_CALL_ONLY_ARG );
+ YY_G(yy_did_buffer_switch_on_eof) = 1;
+}
+%pop
+
+%push
+%c-only
+/** Removes and DELETES the top of the stack, if present.
+ * The next element becomes the new top, if present.
+ */
+void yypop_buffer_state YYFARGS0(void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER YY_CALL_LAST_ARG);
+ YY_CURRENT_BUFFER_FAST = NULL;
+ if (YY_G(yy_buffer_stack_top) > 0)
+ --YY_G(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( YY_CALL_ONLY_ARG );
+ YY_G(yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+%pop
+
+%push
+%c-only
+/** Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+void yyensure_buffer_stack YYFARGS0(void)
+{
+ int num_to_alloc;
+
+ if (!YY_G(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ YY_CALL_LAST_ARG);
+
+ memset(YY_G(yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ YY_G(yy_buffer_stack_max) = num_to_alloc;
+ YY_G(yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if (YY_G(yy_buffer_stack_top) >= (YY_G(yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = YY_G(yy_buffer_stack_max) + grow_size;
+ YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ (YY_G(yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ YY_CALL_LAST_ARG);
+
+ /* zero only the new slots.*/
+ memset(YY_G(yy_buffer_stack) + YY_G(yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ YY_G(yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+%pop
+
+
#ifndef YY_NO_SCAN_BUFFER
%push
@@ -2020,7 +2152,9 @@ static int yy_init_globals YYFARGS0(void)
#ifdef YY_USE_LINENO
yylineno = 1;
#endif
- YY_G(yy_current_buffer) = 0;
+ YY_G(yy_buffer_stack) = 0;
+ YY_G(yy_buffer_stack_top) = 0;
+ YY_G(yy_buffer_stack_max) = 0;
YY_G(yy_c_buf_p) = (char *) 0;
YY_G(yy_init) = 1;
YY_G(yy_start) = 0;
@@ -2093,16 +2227,23 @@ int yylex_init( ptr_yy_globals )
/* yylex_destroy is for both reentrant and non-reentrant scanners. */
int yylex_destroy YYFARGS0(void)
{
- /* Destroy the current (main) buffer. */
- yy_delete_buffer( YY_G(yy_current_buffer) YY_CALL_LAST_ARG );
- YY_G(yy_current_buffer) = NULL;
+ int i;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer( YY_CURRENT_BUFFER YY_CALL_LAST_ARG );
+ YY_CURRENT_BUFFER_FAST = NULL;
+ yypop_buffer_state(YY_CALL_ONLY_ARG);
+ }
+
+ /* Destroy the stack itself. */
+ yyfree(YY_G(yy_buffer_stack) YY_CALL_LAST_ARG);
+ YY_G(yy_buffer_stack) = NULL;
#if defined(YY_STACK_USED) || defined(YY_REENTRANT)
/* Destroy the start condition stack. */
- if (YY_G(yy_start_stack) ){
yyfree( YY_G(yy_start_stack) YY_CALL_LAST_ARG );
YY_G(yy_start_stack) = NULL;
- }
#endif
#ifdef YY_USES_REJECT
diff --git a/gen.c b/gen.c
index 3532af2..eb9acd8 100644
--- a/gen.c
+++ b/gen.c
@@ -1898,7 +1898,7 @@ void make_tables ()
}
else {
- outn ("\tif ( YY_G(yy_current_buffer)->yy_is_interactive ) \\");
+ outn ("\tif ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \\");
outn ("\t\t{ \\");
outn ("\t\tint c = '*'; \\");
outn ("\t\tsize_t n; \\");
@@ -1935,7 +1935,7 @@ void make_tables ()
if (bol_needed) {
indent_puts ("if ( yyleng > 0 ) \\");
indent_up ();
- indent_puts ("YY_G(yy_current_buffer)->yy_at_bol = \\");
+ indent_puts ("YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \\");
indent_puts ("\t\t(yytext[yyleng - 1] == '\\n'); \\");
indent_down ();
}
@@ -2149,10 +2149,10 @@ void make_tables ()
/* Update BOL and yylineno inside of input(). */
if (bol_needed) {
indent_puts
- ("YY_G(yy_current_buffer)->yy_at_bol = (c == '\\n');");
+ ("YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\\n');");
if (do_yylineno) {
indent_puts
- ("if ( YY_G(yy_current_buffer)->yy_at_bol )");
+ ("if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol )");
indent_up ();
indent_puts ("++yylineno;");
indent_down ();
diff --git a/main.c b/main.c
index 8ae5b83..9df7269 100644
--- a/main.c
+++ b/main.c
@@ -405,6 +405,9 @@ void check_options ()
GEN_PREFIX ("_flush_buffer");
GEN_PREFIX ("_load_buffer_state");
GEN_PREFIX ("_switch_to_buffer");
+ GEN_PREFIX ("push_buffer_state");
+ GEN_PREFIX ("pop_buffer_state");
+ GEN_PREFIX ("ensure_buffer_stack");
GEN_PREFIX ("lex");
GEN_PREFIX ("restart");
GEN_PREFIX ("lex_init");
@@ -753,6 +756,9 @@ void flexend (exit_status)
"yy_set_bol",
"yy_set_interactive",
"yy_switch_to_buffer",
+ "yypush_buffer_state",
+ "yypop_buffer_state",
+ "yyensure_buffer_stack",
"yyalloc",
"yyconst",
"yyextra",