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

Commit1f0de66

Browse files
committed
seg: pure parser and reentrant scanner
Use the flex %option reentrant and the bison option %pure-parser tomake the generated scanner and parser pure, reentrant, andthread-safe.Make the generated scanner use palloc() etc. instead of malloc() etc.Previously, we only used palloc() for the buffer, but flex would stilluse malloc() for its internal structures. As a result, there could besome small memory leaks in case of uncaught errors. (We do catchnormal syntax errors as soft errors.) Now, all the memory is underpalloc() control, so there are no more such issues.Simplify flex scan buffer management: Instead of constructing thebuffer from pieces and then using yy_scan_buffer(), we can just useyy_scan_string(), which does the same thing internally.The previous code was necessary because we allocated the buffer withpalloc() and the rest of the state was handled by malloc(). But thisis no longer the case; everything is under palloc() now.(We could even get rid of the yylex_destroy() call and just let thememory context cleanup handle everything. But for now, we preservethe existing behavior.)Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>Reviewed-by: Andreas Karlsson <andreas@proxel.se>Discussion:https://www.postgresql.org/message-id/flat/eb6faeac-2a8a-4b69-9189-c33c520e5b7b@eisentraut.org
1 parent802fe92 commit1f0de66

File tree

4 files changed

+72
-49
lines changed

4 files changed

+72
-49
lines changed

‎contrib/seg/seg.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,14 @@ seg_in(PG_FUNCTION_ARGS)
105105
{
106106
char*str=PG_GETARG_CSTRING(0);
107107
SEG*result=palloc(sizeof(SEG));
108+
yyscan_tscanner;
108109

109-
seg_scanner_init(str);
110+
seg_scanner_init(str,&scanner);
110111

111-
if (seg_yyparse(result,fcinfo->context)!=0)
112-
seg_yyerror(result,fcinfo->context,"bogus input");
112+
if (seg_yyparse(result,fcinfo->context,scanner)!=0)
113+
seg_yyerror(result,fcinfo->context,scanner,"bogus input");
113114

114-
seg_scanner_finish();
115+
seg_scanner_finish(scanner);
115116

116117
PG_RETURN_POINTER(result);
117118
}

‎contrib/seg/segdata.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ typedef struct SEG
1414
/* in seg.c */
1515
externintsignificant_digits(constchar*s);
1616

17+
/* for segscan.l and segparse.y */
18+
unionYYSTYPE;
19+
typedefvoid*yyscan_t;
20+
1721
/* in segscan.l */
18-
externintseg_yylex(void);
22+
externintseg_yylex(unionYYSTYPE*yylval_param,yyscan_tyyscanner);
1923
externvoidseg_yyerror(SEG*result,structNode*escontext,
24+
yyscan_tyyscanner,
2025
constchar*message);
21-
externvoidseg_scanner_init(constchar*str);
22-
externvoidseg_scanner_finish(void);
26+
externvoidseg_scanner_init(constchar*str,yyscan_t*yyscannerp);
27+
externvoidseg_scanner_finish(yyscan_tyyscanner);
2328

2429
/* in segparse.y */
25-
externintseg_yyparse(SEG*result,structNode*escontext);
30+
externintseg_yyparse(SEG*result,structNode*escontext,yyscan_tyyscanner);

‎contrib/seg/segparse.y

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
#include"segdata.h"
1515
#include"segparse.h"
1616

17-
/* silence -Wmissing-variable-declarations*/
18-
externint seg_yychar;
19-
externint seg_yynerrs;
20-
2117
/*
2218
* Bison doesn't allocate anything that needs to live across parser calls,
2319
* so we can easily have it use palloc instead of malloc. This prevents
@@ -35,6 +31,9 @@ static int sig_digits(const char *value);
3531
/* BISON Declarations*/
3632
%parse-param {SEG *result}
3733
%parse-param {structNode *escontext}
34+
%parse-param {yyscan_t yyscanner}
35+
%lex-param {yyscan_t yyscanner}
36+
%pure-parser
3837
%expect0
3938
%name-prefix="seg_yy"
4039

@@ -72,6 +71,8 @@ range: boundary PLUMIN deviation
7271
result->u_sigd =Max(sig_digits(strbuf),Max($1.sigd, $3.sigd));
7372
result->l_ext ='\0';
7473
result->u_ext ='\0';
74+
75+
(void) yynerrs;/* suppress compiler warning*/
7576
}
7677

7778
| boundary RANGE boundary

‎contrib/seg/segscan.l

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@
66

77
#include "nodes/miscnodes.h"
88

9-
/*
10-
* NB: include segparse.h only AFTER including segdata.h, because segdata.h
11-
* contains the definition for SEG.
12-
*/
139
#include "segdata.h"
14-
#include "segparse.h"
10+
#include "segparse.h"/* must be after segdata.h for SEG */
1511
}
1612

1713
%{
@@ -29,18 +25,19 @@ fprintf_to_ereport(const char *fmt, const char *msg)
2925
{
3026
ereport(ERROR, (errmsg_internal("%s", msg)));
3127
}
32-
33-
/* Handles to the buffer that the lexer uses internally*/
34-
static YY_BUFFER_STATE scanbufhandle;
35-
staticchar *scanbuf;
3628
%}
3729

30+
%optionreentrant
31+
%optionbison-bridge
3832
%option8bit
3933
%optionnever-interactive
4034
%optionnodefault
4135
%optionnoinput
4236
%optionnounput
4337
%optionnoyywrap
38+
%optionnoyyalloc
39+
%optionnoyyrealloc
40+
%optionnoyyfree
4441
%optionwarn
4542
%optionprefix="seg_yy"
4643

@@ -53,12 +50,12 @@ float ({integer}|{real})([eE]{integer})?
5350

5451
%%
5552

56-
{range}seg_yylval.text = yytext;return RANGE;
57-
{plumin}seg_yylval.text = yytext;return PLUMIN;
58-
{float}seg_yylval.text = yytext;return SEGFLOAT;
59-
\<seg_yylval.text ="<";return EXTENSION;
60-
\>seg_yylval.text =">";return EXTENSION;
61-
\~seg_yylval.text ="~";return EXTENSION;
53+
{range}yylval->text = yytext;return RANGE;
54+
{plumin}yylval->text = yytext;return PLUMIN;
55+
{float}yylval->text = yytext;return SEGFLOAT;
56+
\<yylval->text ="<";return EXTENSION;
57+
\>yylval->text =">";return EXTENSION;
58+
\~yylval->text ="~";return EXTENSION;
6259
[\t\n\r\f\v]+/* discard spaces */
6360
.return yytext[0];/* alert parser of the garbage*/
6461

@@ -67,8 +64,10 @@ float ({integer}|{real})([eE]{integer})?
6764
/* LCOV_EXCL_STOP */
6865

6966
void
70-
seg_yyerror(SEG *result,structNode *escontext,constchar *message)
67+
seg_yyerror(SEG *result,structNode *escontext,yyscan_t yyscanner,constchar *message)
7168
{
69+
structyyguts_t * yyg = (structyyguts_t *) yyscanner;/* needed for yytext macro */
70+
7271
/* if we already reported an error, don't overwrite it */
7372
if (SOFT_ERROR_OCCURRED(escontext))
7473
return;
@@ -96,34 +95,51 @@ seg_yyerror(SEG *result, struct Node *escontext, const char *message)
9695
* Called before any actual parsing is done
9796
*/
9897
void
99-
seg_scanner_init(constchar *str)
98+
seg_scanner_init(constchar *str,yyscan_t *yyscannerp)
10099
{
101-
Sizeslen =strlen(str);
102-
103-
/*
104-
* Might be left over after ereport()
105-
*/
106-
if (YY_CURRENT_BUFFER)
107-
yy_delete_buffer(YY_CURRENT_BUFFER);
108-
109-
/*
110-
* Make a scan buffer with special termination needed by flex.
111-
*/
112-
scanbuf =palloc(slen +2);
113-
memcpy(scanbuf, str, slen);
114-
scanbuf[slen] = scanbuf[slen +1] = YY_END_OF_BUFFER_CHAR;
115-
scanbufhandle =yy_scan_buffer(scanbuf, slen +2);
116-
117-
BEGIN(INITIAL);
100+
yyscan_t yyscanner;
101+
102+
if (yylex_init(yyscannerp) !=0)
103+
elog(ERROR,"yylex_init() failed: %m");
104+
105+
yyscanner = *yyscannerp;
106+
107+
yy_scan_string(str, yyscanner);
118108
}
119109

120110

121111
/*
122112
* Called after parsing is done to clean up after seg_scanner_init()
123113
*/
124114
void
125-
seg_scanner_finish(void)
115+
seg_scanner_finish(yyscan_t yyscanner)
116+
{
117+
yylex_destroy(yyscanner);
118+
}
119+
120+
/*
121+
* Interface functions to make flex use palloc() instead of malloc().
122+
* It'd be better to make these static, but flex insists otherwise.
123+
*/
124+
125+
void *
126+
yyalloc(yy_size_t size,yyscan_t yyscanner)
127+
{
128+
returnpalloc(size);
129+
}
130+
131+
void *
132+
yyrealloc(void *ptr,yy_size_t size,yyscan_t yyscanner)
133+
{
134+
if (ptr)
135+
returnrepalloc(ptr, size);
136+
else
137+
returnpalloc(size);
138+
}
139+
140+
void
141+
yyfree(void *ptr,yyscan_t yyscanner)
126142
{
127-
yy_delete_buffer(scanbufhandle);
128-
pfree(scanbuf);
143+
if (ptr)
144+
pfree(ptr);
129145
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp