Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit429ee5a

Browse files
committed
Make pgbench's expression lexer reentrant.
This is a necessary preliminary step for making it play with psqlscan.lgiven the way I set up the lexer input-buffer sharing mechanism in commit0ea9efb.I've not tried to make it *actually* reentrant; there's still some staticvariables laying about. But flex thinks it's reentrant, and that's whatcounts.In support of that, fix exprparse.y to pass through the yyscan_t from thecaller. Also do some minor code beautification, like not casting awayconst.
1 parent1038bc9 commit429ee5a

File tree

4 files changed

+117
-64
lines changed

4 files changed

+117
-64
lines changed

‎src/bin/pgbench/exprparse.y

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10+
* src/bin/pgbench/exprparse.y
11+
*
1012
*-------------------------------------------------------------------------
1113
*/
1214

@@ -19,16 +21,19 @@ PgBenchExpr *expr_parse_result;
1921
static PgBenchExprList *make_elist(PgBenchExpr *exp, PgBenchExprList *list);
2022
static PgBenchExpr *make_integer_constant(int64 ival);
2123
static PgBenchExpr *make_variable(char *varname);
22-
static PgBenchExpr *make_op(constchar *operator, PgBenchExpr *lexpr,
23-
PgBenchExpr *rexpr);
24-
staticintfind_func(constchar *fname);
25-
static PgBenchExpr *make_func(constint fnumber, PgBenchExprList *args);
24+
static PgBenchExpr *make_op(yyscan_t yyscanner,constchar *operator,
25+
PgBenchExpr *lexpr,PgBenchExpr *rexpr);
26+
staticintfind_func(yyscan_t yyscanner,constchar *fname);
27+
static PgBenchExpr *make_func(yyscan_t yyscanner,int fnumber, PgBenchExprList *args);
2628

2729
%}
2830

2931
%expect0
3032
%name-prefix="expr_yy"
3133

34+
%parse-param {yyscan_t yyscanner}
35+
%lex-param {yyscan_t yyscanner}
36+
3237
%union
3338
{
3439
int64ival;
@@ -43,7 +48,6 @@ static PgBenchExpr *make_func(const int fnumber, PgBenchExprList *args);
4348
%type<str>VARIABLEFUNCTION
4449

4550
%tokenINTEGERVARIABLEFUNCTION
46-
%tokenCHAR_ERROR/* never used, will raise a syntax error*/
4751

4852
/* Precedence: lowest to highest*/
4953
%left'+''-'
@@ -61,18 +65,19 @@ elist: { $$ = NULL; }
6165

6266
expr:'('expr')'{$$ =$2; }
6367
|'+'expr %precUMINUS{$$ =$2; }
64-
|'-'expr %precUMINUS{$$ = make_op("-", make_integer_constant(0),$2); }
65-
|expr'+'expr{$$ = make_op("+",$1,$3); }
66-
|expr'-'expr{$$ = make_op("-",$1,$3); }
67-
|expr'*'expr{$$ = make_op("*",$1,$3); }
68-
|expr'/'expr{$$ = make_op("/",$1,$3); }
69-
|expr'%'expr{$$ = make_op("%",$1,$3); }
68+
|'-'expr %precUMINUS{$$ = make_op(yyscanner,"-",
69+
make_integer_constant(0), $2); }
70+
|expr'+'expr{$$ = make_op(yyscanner,"+",$1,$3); }
71+
|expr'-'expr{$$ = make_op(yyscanner,"-",$1,$3); }
72+
|expr'*'expr{$$ = make_op(yyscanner,"*",$1,$3); }
73+
|expr'/'expr{$$ = make_op(yyscanner,"/",$1,$3); }
74+
|expr'%'expr{$$ = make_op(yyscanner,"%",$1,$3); }
7075
|INTEGER{$$ = make_integer_constant($1); }
7176
|VARIABLE {$$ = make_variable($1); }
72-
|function'('elist')'{$$ = make_func($1,$3); }
77+
|function'('elist')'{$$ = make_func(yyscanner,$1,$3); }
7378
;
7479

75-
function:FUNCTION{$$ = find_func($1); pg_free($1); }
80+
function:FUNCTION{$$ = find_func(yyscanner,$1); pg_free($1); }
7681
;
7782

7883
%%
@@ -98,9 +103,10 @@ make_variable(char *varname)
98103
}
99104

100105
static PgBenchExpr *
101-
make_op(constchar *operator, PgBenchExpr *lexpr, PgBenchExpr *rexpr)
106+
make_op(yyscan_t yyscanner,constchar *operator,
107+
PgBenchExpr *lexpr, PgBenchExpr *rexpr)
102108
{
103-
returnmake_func(find_func(operator),
109+
returnmake_func(yyscanner,find_func(yyscanner,operator),
104110
make_elist(rexpr,make_elist(lexpr,NULL)));
105111
}
106112

@@ -139,7 +145,7 @@ static struct
139145
* or fail if the function is unknown.
140146
*/
141147
staticint
142-
find_func(constchar *fname)
148+
find_func(yyscan_t yyscanner,constchar *fname)
143149
{
144150
int i =0;
145151

@@ -150,7 +156,7 @@ find_func(const char * fname)
150156
i++;
151157
}
152158

153-
expr_yyerror_more("unexpected function name", fname);
159+
expr_yyerror_more(yyscanner,"unexpected function name", fname);
154160

155161
/* not reached*/
156162
return -1;
@@ -198,21 +204,21 @@ elist_length(PgBenchExprList *list)
198204

199205
/* Build function call expression*/
200206
static PgBenchExpr *
201-
make_func(constint fnumber, PgBenchExprList *args)
207+
make_func(yyscan_t yyscanner,int fnumber, PgBenchExprList *args)
202208
{
203209
PgBenchExpr *expr =pg_malloc(sizeof(PgBenchExpr));
204210

205211
Assert(fnumber >=0);
206212

207213
if (PGBENCH_FUNCTIONS[fnumber].nargs >=0 &&
208214
PGBENCH_FUNCTIONS[fnumber].nargs !=elist_length(args))
209-
expr_yyerror_more("unexpected number of arguments",
215+
expr_yyerror_more(yyscanner,"unexpected number of arguments",
210216
PGBENCH_FUNCTIONS[fnumber].fname);
211217

212218
/* check at least one arg for min & max*/
213219
if (PGBENCH_FUNCTIONS[fnumber].nargs == -1 &&
214220
elist_length(args) ==0)
215-
expr_yyerror_more("at least one argument expected",
221+
expr_yyerror_more(yyscanner,"at least one argument expected",
216222
PGBENCH_FUNCTIONS[fnumber].fname);
217223

218224
expr->etype = ENODE_FUNCTION;
@@ -226,4 +232,15 @@ make_func(const int fnumber, PgBenchExprList *args)
226232
return expr;
227233
}
228234

235+
/*
236+
* exprscan.l is compiled as part of exprparse.y. Currently, this is
237+
* unavoidable because exprparse does not create a .h file to export
238+
* its token symbols. If these files ever grow large enough to be
239+
* worth compiling separately, that could be fixed; but for now it
240+
* seems like useless complication.
241+
*/
242+
243+
/* First, get rid of "#define yyscan_t" from pgbench.h*/
244+
#undef yyscan_t
245+
229246
#include"exprscan.c"

‎src/bin/pgbench/exprscan.l

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10+
* src/bin/pgbench/exprscan.l
11+
*
1012
*-------------------------------------------------------------------------
1113
*/
1214

@@ -16,16 +18,27 @@ static intyyline = 0, yycol = 0;
1618
/* Handles to the buffer that the lexer uses internally*/
1719
static YY_BUFFER_STATE scanbufhandle;
1820
staticchar *scanbuf;
19-
staticintscanbuflen;
2021

2122
/* context information for error reporting*/
22-
staticchar *expr_source =NULL;
23+
staticconstchar *expr_source =NULL;
2324
staticint expr_lineno =0;
24-
staticchar *expr_full_line =NULL;
25-
staticchar *expr_command =NULL;
25+
staticconstchar *expr_full_line =NULL;
26+
staticconstchar *expr_command =NULL;
2627
staticint expr_col =0;
28+
29+
/*
30+
* Work around a bug in flex 2.5.35: it emits a couple of functions that
31+
* it forgets to emit declarations for. Since we use -Wmissing-prototypes,
32+
* this would cause warnings. Providing our own declarations should be
33+
* harmless even when the bug gets fixed.
34+
*/
35+
externintexpr_yyget_column(yyscan_t yyscanner);
36+
externvoidexpr_yyset_column(int column_no,yyscan_t yyscanner);
37+
2738
%}
2839

40+
/* Except for the prefix, these options should match psqlscan.l */
41+
%optionreentrant
2942
%option8bit
3043
%optionnever-interactive
3144
%optionnodefault
@@ -42,6 +55,15 @@ space[ \t\r\f]
4255

4356
%%
4457

58+
%{
59+
/*
60+
* Force flex into the appropriate start state ... which, for this
61+
* case, is always INITIAL. This ensures that we can transition
62+
* between different lexers sharing the same yyscan_t.
63+
*/
64+
BEGIN(INITIAL);
65+
%}
66+
4567
"+"{ yycol += yyleng;return'+'; }
4668
"-"{ yycol += yyleng;return'-'; }
4769
"*"{ yycol += yyleng;return'*'; }
@@ -69,77 +91,76 @@ space[ \t\r\f]
6991

7092
[\n]{ yycol =0; yyline++; }
7193

72-
{space}+{ yycol += yyleng;/* ignore */ }
94+
{space}+{ yycol += yyleng;/*otherwiseignore */ }
7395

7496
.{
7597
yycol += yyleng;
7698
syntax_error(expr_source, expr_lineno, expr_full_line, expr_command,
7799
"unexpected character", yytext, expr_col + yycol);
78-
/*dead code, exit is called from syntax_error */
79-
returnCHAR_ERROR;
100+
/*NOTREACHED, exit is called from syntax_error */
101+
return0;
80102
}
81103
%%
82104

83105
void
84-
expr_yyerror_more(constchar *message,constchar *more)
106+
expr_yyerror_more(yyscan_t yyscanner,constchar *message,constchar *more)
85107
{
86108
syntax_error(expr_source, expr_lineno, expr_full_line, expr_command,
87109
message, more, expr_col + yycol);
88110
}
89111

90112
void
91-
yyerror(constchar *message)
113+
yyerror(yyscan_t yyscanner,constchar *message)
92114
{
93-
expr_yyerror_more(message,NULL);
115+
expr_yyerror_more(yyscanner,message,NULL);
94116
}
95117

96118
/*
97119
* Called before any actual parsing is done
98120
*/
99-
void
121+
yyscan_t
100122
expr_scanner_init(constchar *str,constchar *source,
101-
constint lineno,constchar *line,
102-
constchar *cmd,constint ecol)
123+
int lineno,constchar *line,
124+
constchar *cmd,int ecol)
103125
{
126+
yyscan_t yyscanner;
104127
Sizeslen =strlen(str);
105128

106-
/* save context informations for error messages */
107-
expr_source = (char *) source;
108-
expr_lineno = (int) lineno;
109-
expr_full_line = (char *) line;
110-
expr_command = (char *) cmd;
111-
expr_col = (int) ecol;
129+
/* Set up yyscan_t */
130+
yylex_init(&yyscanner);
131+
132+
/* save context information for error messages */
133+
expr_source = source;
134+
expr_lineno = lineno;
135+
expr_full_line = line;
136+
expr_command = cmd;
137+
expr_col = ecol;
112138

113139
/* reset error pointers for this scan */
114140
yycol = yyline =0;
115141

116-
/*
117-
* Might be left over after error
118-
*/
119-
if (YY_CURRENT_BUFFER)
120-
yy_delete_buffer(YY_CURRENT_BUFFER);
121-
122142
/*
123143
* Make a scan buffer with special termination needed by flex.
124144
*/
125-
scanbuflen = slen;
126145
scanbuf =pg_malloc(slen +2);
127146
memcpy(scanbuf, str, slen);
128147
scanbuf[slen] = scanbuf[slen +1] = YY_END_OF_BUFFER_CHAR;
129-
scanbufhandle =yy_scan_buffer(scanbuf, slen +2);
148+
scanbufhandle =yy_scan_buffer(scanbuf, slen +2, yyscanner);
130149

131-
BEGIN(INITIAL);
150+
return yyscanner;
132151
}
133152

134153

135154
/*
136-
* Called after parsing is done to clean up afterseg_scanner_init()
155+
* Called after parsing is done to clean up afterexpr_scanner_init()
137156
*/
138157
void
139-
expr_scanner_finish(void)
158+
expr_scanner_finish(yyscan_t yyscanner)
140159
{
141-
yy_delete_buffer(scanbufhandle);
160+
yy_delete_buffer(scanbufhandle, yyscanner);
142161
pg_free(scanbuf);
162+
yylex_destroy(yyscanner);
163+
143164
expr_source =NULL;
144165
expr_lineno =0;
145166
expr_full_line =NULL;

‎src/bin/pgbench/pgbench.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,25 +2495,30 @@ process_commands(char *buf, const char *source, const int lineno)
24952495
}
24962496
elseif (pg_strcasecmp(my_commands->argv[0],"set")==0)
24972497
{
2498+
yyscan_tyyscanner;
2499+
24982500
if (my_commands->argc<3)
24992501
{
25002502
syntax_error(source,lineno,my_commands->line,my_commands->argv[0],
25012503
"missing argument",NULL,-1);
25022504
}
25032505

2504-
expr_scanner_init(my_commands->argv[2],source,lineno,
2505-
my_commands->line,my_commands->argv[0],
2506-
my_commands->cols[2]-1);
2506+
yyscanner=expr_scanner_init(my_commands->argv[2],
2507+
source,
2508+
lineno,
2509+
my_commands->line,
2510+
my_commands->argv[0],
2511+
my_commands->cols[2]-1);
25072512

2508-
if (expr_yyparse()!=0)
2513+
if (expr_yyparse(yyscanner)!=0)
25092514
{
25102515
/* dead code: exit done from syntax_error called by yyerror */
25112516
exit(1);
25122517
}
25132518

25142519
my_commands->expr=expr_parse_result;
25152520

2516-
expr_scanner_finish();
2521+
expr_scanner_finish(yyscanner);
25172522
}
25182523
elseif (pg_strcasecmp(my_commands->argv[0],"sleep")==0)
25192524
{

‎src/bin/pgbench/pgbench.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111
#ifndefPGBENCH_H
1212
#definePGBENCH_H
1313

14+
/*
15+
* This file is included outside exprscan.l, in places where we can't see
16+
* flex's definition of typedef yyscan_t. Fortunately, it's documented as
17+
* being "void *", so we can use a macro to keep the function declarations
18+
* here looking like the definitions in exprscan.l. exprparse.y also
19+
* uses this to be able to declare things as "yyscan_t".
20+
*/
21+
#defineyyscan_t void *
22+
1423
/* Types of expression nodes */
1524
typedefenumPgBenchExprType
1625
{
@@ -73,17 +82,18 @@ struct PgBenchExprList
7382

7483
externPgBenchExpr*expr_parse_result;
7584

76-
externintexpr_yyparse(void);
77-
externintexpr_yylex(void);
78-
externvoidexpr_yyerror(constchar*str);
79-
externvoidexpr_yyerror_more(constchar*str,constchar*more);
80-
externvoidexpr_scanner_init(constchar*str,constchar*source,
81-
constintlineno,constchar*line,
82-
constchar*cmd,constintecol);
85+
externintexpr_yyparse(yyscan_tyyscanner);
86+
externintexpr_yylex(yyscan_tyyscanner);
87+
externvoidexpr_yyerror(yyscan_tyyscanner,constchar*str);
88+
externvoidexpr_yyerror_more(yyscan_tyyscanner,constchar*str,
89+
constchar*more);
90+
externyyscan_texpr_scanner_init(constchar*str,constchar*source,
91+
intlineno,constchar*line,
92+
constchar*cmd,intecol);
8393
externvoidsyntax_error(constchar*source,constintlineno,constchar*line,
8494
constchar*cmd,constchar*msg,constchar*more,
8595
constintcol);
86-
externvoidexpr_scanner_finish(void);
96+
externvoidexpr_scanner_finish(yyscan_tyyscanner);
8797

8898
externint64strtoint64(constchar*str);
8999

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp