diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-19 16:35:41 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-19 16:35:41 -0400 |
commit | 429ee5a822db0e8faf669d77c810f1eeaaff1ab4 (patch) | |
tree | 60b96ede0aed5ad8511e197741060a185894f001 /src/bin/pgbench/exprscan.l | |
parent | 1038bc91ca98865bd60bf63db46fc331f3099998 (diff) |
Make pgbench's expression lexer reentrant.
This is a necessary preliminary step for making it play with psqlscan.l
given the way I set up the lexer input-buffer sharing mechanism in commit
0ea9efbe9ec1bf07.
I've not tried to make it *actually* reentrant; there's still some static
variables laying about. But flex thinks it's reentrant, and that's what
counts.
In support of that, fix exprparse.y to pass through the yyscan_t from the
caller. Also do some minor code beautification, like not casting away
const.
Diffstat (limited to 'src/bin/pgbench/exprscan.l')
-rw-r--r-- | src/bin/pgbench/exprscan.l | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/src/bin/pgbench/exprscan.l b/src/bin/pgbench/exprscan.l index fc7615f5585..00cb74d7dad 100644 --- a/src/bin/pgbench/exprscan.l +++ b/src/bin/pgbench/exprscan.l @@ -7,6 +7,8 @@ * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * + * src/bin/pgbench/exprscan.l + * *------------------------------------------------------------------------- */ @@ -16,16 +18,27 @@ static int yyline = 0, yycol = 0; /* Handles to the buffer that the lexer uses internally */ static YY_BUFFER_STATE scanbufhandle; static char *scanbuf; -static int scanbuflen; /* context information for error reporting */ -static char *expr_source = NULL; +static const char *expr_source = NULL; static int expr_lineno = 0; -static char *expr_full_line = NULL; -static char *expr_command = NULL; +static const char *expr_full_line = NULL; +static const char *expr_command = NULL; static int expr_col = 0; + +/* + * Work around a bug in flex 2.5.35: it emits a couple of functions that + * it forgets to emit declarations for. Since we use -Wmissing-prototypes, + * this would cause warnings. Providing our own declarations should be + * harmless even when the bug gets fixed. + */ +extern int expr_yyget_column(yyscan_t yyscanner); +extern void expr_yyset_column(int column_no, yyscan_t yyscanner); + %} +/* Except for the prefix, these options should match psqlscan.l */ +%option reentrant %option 8bit %option never-interactive %option nodefault @@ -42,6 +55,15 @@ space [ \t\r\f] %% +%{ + /* + * Force flex into the appropriate start state ... which, for this + * case, is always INITIAL. This ensures that we can transition + * between different lexers sharing the same yyscan_t. + */ + BEGIN(INITIAL); +%} + "+" { yycol += yyleng; return '+'; } "-" { yycol += yyleng; return '-'; } "*" { yycol += yyleng; return '*'; } @@ -69,77 +91,76 @@ space [ \t\r\f] [\n] { yycol = 0; yyline++; } -{space}+ { yycol += yyleng; /* ignore */ } +{space}+ { yycol += yyleng; /* otherwise ignore */ } . { yycol += yyleng; syntax_error(expr_source, expr_lineno, expr_full_line, expr_command, "unexpected character", yytext, expr_col + yycol); - /* dead code, exit is called from syntax_error */ - return CHAR_ERROR; + /* NOTREACHED, exit is called from syntax_error */ + return 0; } %% void -expr_yyerror_more(const char *message, const char *more) +expr_yyerror_more(yyscan_t yyscanner, const char *message, const char *more) { syntax_error(expr_source, expr_lineno, expr_full_line, expr_command, message, more, expr_col + yycol); } void -yyerror(const char *message) +yyerror(yyscan_t yyscanner, const char *message) { - expr_yyerror_more(message, NULL); + expr_yyerror_more(yyscanner, message, NULL); } /* * Called before any actual parsing is done */ -void +yyscan_t expr_scanner_init(const char *str, const char *source, - const int lineno, const char *line, - const char *cmd, const int ecol) + int lineno, const char *line, + const char *cmd, int ecol) { + yyscan_t yyscanner; Size slen = strlen(str); - /* save context informations for error messages */ - expr_source = (char *) source; - expr_lineno = (int) lineno; - expr_full_line = (char *) line; - expr_command = (char *) cmd; - expr_col = (int) ecol; + /* Set up yyscan_t */ + yylex_init(&yyscanner); + + /* save context information for error messages */ + expr_source = source; + expr_lineno = lineno; + expr_full_line = line; + expr_command = cmd; + expr_col = ecol; /* reset error pointers for this scan */ yycol = yyline = 0; /* - * Might be left over after error - */ - if (YY_CURRENT_BUFFER) - yy_delete_buffer(YY_CURRENT_BUFFER); - - /* * Make a scan buffer with special termination needed by flex. */ - scanbuflen = slen; scanbuf = pg_malloc(slen + 2); memcpy(scanbuf, str, slen); scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); + scanbufhandle = yy_scan_buffer(scanbuf, slen + 2, yyscanner); - BEGIN(INITIAL); + return yyscanner; } /* - * Called after parsing is done to clean up after seg_scanner_init() + * Called after parsing is done to clean up after expr_scanner_init() */ void -expr_scanner_finish(void) +expr_scanner_finish(yyscan_t yyscanner) { - yy_delete_buffer(scanbufhandle); + yy_delete_buffer(scanbufhandle, yyscanner); pg_free(scanbuf); + yylex_destroy(yyscanner); + expr_source = NULL; expr_lineno = 0; expr_full_line = NULL; |