1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

jsonpath scanner: reentrant scanner

Use the flex %option reentrant to make the generated scanner
reentrant and thread-safe.  Note: The parser was already pure.

Simplify flex scan buffer management: Instead of constructing the
buffer from pieces and then using yy_scan_buffer(), we can just use
yy_scan_string(), which does the same thing internally.  (Actually, we
use yy_scan_bytes() here because we already have the length.)

Use flex yyextra to handle context information, instead of global
variables.  This complements the other changes to make the scanner
reentrant.

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
This commit is contained in:
Peter Eisentraut
2024-12-24 23:42:41 +01:00
parent 9b254895c3
commit 2a7425d7ee
4 changed files with 145 additions and 154 deletions

View File

@ -7,7 +7,7 @@ GETTEXT_TRIGGERS = $(BACKEND_COMMON_GETTEXT_TRIGGERS) \
GUC_check_errhint \ GUC_check_errhint \
write_stderr \ write_stderr \
yyerror \ yyerror \
jsonpath_yyerror:3 \ jsonpath_yyerror:4 \
parser_yyerror \ parser_yyerror \
replication_yyerror:2 \ replication_yyerror:2 \
scanner_yyerror \ scanner_yyerror \

View File

@ -60,8 +60,10 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr,
%name-prefix="jsonpath_yy" %name-prefix="jsonpath_yy"
%parse-param {JsonPathParseResult **result} %parse-param {JsonPathParseResult **result}
%parse-param {struct Node *escontext} %parse-param {struct Node *escontext}
%parse-param {yyscan_t yyscanner}
%lex-param {JsonPathParseResult **result} %lex-param {JsonPathParseResult **result}
%lex-param {struct Node *escontext} %lex-param {struct Node *escontext}
%lex-param {yyscan_t yyscanner}
%union %union
{ {

View File

@ -22,17 +22,25 @@ typedef struct JsonPathString
int total; int total;
} JsonPathString; } JsonPathString;
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void *yyscan_t;
#endif
#include "utils/jsonpath.h" #include "utils/jsonpath.h"
#include "jsonpath_gram.h" #include "jsonpath_gram.h"
#define YY_DECL extern int jsonpath_yylex(YYSTYPE *yylval_param, \ #define YY_DECL extern int jsonpath_yylex(YYSTYPE *yylval_param, \
JsonPathParseResult **result, \ JsonPathParseResult **result, \
struct Node *escontext) struct Node *escontext, \
yyscan_t yyscanner)
YY_DECL; YY_DECL;
extern int jsonpath_yyparse(JsonPathParseResult **result, extern int jsonpath_yyparse(JsonPathParseResult **result,
struct Node *escontext); struct Node *escontext,
yyscan_t yyscanner);
extern void jsonpath_yyerror(JsonPathParseResult **result, extern void jsonpath_yyerror(JsonPathParseResult **result,
struct Node *escontext, struct Node *escontext,
yyscan_t yyscanner,
const char *message); const char *message);
#endif /* JSONPATH_INTERNAL_H */ #endif /* JSONPATH_INTERNAL_H */

View File

@ -30,18 +30,17 @@
} }
%{ %{
static JsonPathString scanstring; struct jsonpath_yy_extra_type
{
JsonPathString scanstring;
};
#define YY_EXTRA_TYPE struct jsonpath_yy_extra_type *
/* Handles to the buffer that the lexer uses internally */ static void addstring(bool init, char *s, int l, yyscan_t yyscanner);
static YY_BUFFER_STATE scanbufhandle; static void addchar(bool init, char c, yyscan_t yyscanner);
static char *scanbuf; static enum yytokentype checkKeyword(yyscan_t yyscanner);
static int scanbuflen; static bool parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner);
static bool parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner);
static void addstring(bool init, char *s, int l);
static void addchar(bool init, char c);
static enum yytokentype checkKeyword(void);
static bool parseUnicode(char *s, int l, struct Node *escontext);
static bool parseHexChar(char *s, struct Node *escontext);
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
#undef fprintf #undef fprintf
@ -65,6 +64,7 @@ fprintf_to_ereport(const char *fmt, const char *msg)
%option noyywrap %option noyywrap
%option warn %option warn
%option prefix="jsonpath_yy" %option prefix="jsonpath_yy"
%option reentrant
%option bison-bridge %option bison-bridge
%option noyyalloc %option noyyalloc
%option noyyrealloc %option noyyrealloc
@ -120,63 +120,63 @@ hex_fail \\x{hexdigit}{0,1}
%% %%
<xnq>{other}+ { <xnq>{other}+ {
addstring(false, yytext, yyleng); addstring(false, yytext, yyleng, yyscanner);
} }
<xnq>{blank}+ { <xnq>{blank}+ {
yylval->str = scanstring; yylval->str = yyextra->scanstring;
BEGIN INITIAL; BEGIN INITIAL;
return checkKeyword(); return checkKeyword(yyscanner);
} }
<xnq>\/\* { <xnq>\/\* {
yylval->str = scanstring; yylval->str = yyextra->scanstring;
BEGIN xc; BEGIN xc;
} }
<xnq>({special}|\") { <xnq>({special}|\") {
yylval->str = scanstring; yylval->str = yyextra->scanstring;
yyless(0); yyless(0);
BEGIN INITIAL; BEGIN INITIAL;
return checkKeyword(); return checkKeyword(yyscanner);
} }
<xnq><<EOF>> { <xnq><<EOF>> {
yylval->str = scanstring; yylval->str = yyextra->scanstring;
BEGIN INITIAL; BEGIN INITIAL;
return checkKeyword(); return checkKeyword(yyscanner);
} }
<xnq,xq,xvq>\\b { addchar(false, '\b'); } <xnq,xq,xvq>\\b { addchar(false, '\b', yyscanner); }
<xnq,xq,xvq>\\f { addchar(false, '\f'); } <xnq,xq,xvq>\\f { addchar(false, '\f', yyscanner); }
<xnq,xq,xvq>\\n { addchar(false, '\n'); } <xnq,xq,xvq>\\n { addchar(false, '\n', yyscanner); }
<xnq,xq,xvq>\\r { addchar(false, '\r'); } <xnq,xq,xvq>\\r { addchar(false, '\r', yyscanner); }
<xnq,xq,xvq>\\t { addchar(false, '\t'); } <xnq,xq,xvq>\\t { addchar(false, '\t', yyscanner); }
<xnq,xq,xvq>\\v { addchar(false, '\v'); } <xnq,xq,xvq>\\v { addchar(false, '\v', yyscanner); }
<xnq,xq,xvq>{unicode}+ { <xnq,xq,xvq>{unicode}+ {
if (!parseUnicode(yytext, yyleng, escontext)) if (!parseUnicode(yytext, yyleng, escontext, yyscanner))
yyterminate(); yyterminate();
} }
<xnq,xq,xvq>{hex_char} { <xnq,xq,xvq>{hex_char} {
if (!parseHexChar(yytext, escontext)) if (!parseHexChar(yytext, escontext, yyscanner))
yyterminate(); yyterminate();
} }
<xnq,xq,xvq>{unicode}*{unicodefail} { <xnq,xq,xvq>{unicode}*{unicodefail} {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"invalid Unicode escape sequence"); "invalid Unicode escape sequence");
yyterminate(); yyterminate();
} }
<xnq,xq,xvq>{hex_fail} { <xnq,xq,xvq>{hex_fail} {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"invalid hexadecimal character sequence"); "invalid hexadecimal character sequence");
yyterminate(); yyterminate();
} }
@ -184,37 +184,37 @@ hex_fail \\x{hexdigit}{0,1}
<xnq,xq,xvq>{unicode}+\\ { <xnq,xq,xvq>{unicode}+\\ {
/* throw back the \\, and treat as unicode */ /* throw back the \\, and treat as unicode */
yyless(yyleng - 1); yyless(yyleng - 1);
if (!parseUnicode(yytext, yyleng, escontext)) if (!parseUnicode(yytext, yyleng, escontext, yyscanner))
yyterminate(); yyterminate();
} }
<xnq,xq,xvq>\\. { addchar(false, yytext[1]); } <xnq,xq,xvq>\\. { addchar(false, yytext[1], yyscanner); }
<xnq,xq,xvq>\\ { <xnq,xq,xvq>\\ {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"unexpected end after backslash"); "unexpected end after backslash");
yyterminate(); yyterminate();
} }
<xq,xvq><<EOF>> { <xq,xvq><<EOF>> {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"unterminated quoted string"); "unterminated quoted string");
yyterminate(); yyterminate();
} }
<xq>\" { <xq>\" {
yylval->str = scanstring; yylval->str = yyextra->scanstring;
BEGIN INITIAL; BEGIN INITIAL;
return STRING_P; return STRING_P;
} }
<xvq>\" { <xvq>\" {
yylval->str = scanstring; yylval->str = yyextra->scanstring;
BEGIN INITIAL; BEGIN INITIAL;
return VARIABLE_P; return VARIABLE_P;
} }
<xq,xvq>[^\\\"]+ { addstring(false, yytext, yyleng); } <xq,xvq>[^\\\"]+ { addstring(false, yytext, yyleng, yyscanner); }
<xc>\*\/ { BEGIN INITIAL; } <xc>\*\/ { BEGIN INITIAL; }
@ -223,7 +223,7 @@ hex_fail \\x{hexdigit}{0,1}
<xc>\* { } <xc>\* { }
<xc><<EOF>> { <xc><<EOF>> {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"unexpected end of comment"); "unexpected end of comment");
yyterminate(); yyterminate();
} }
@ -250,14 +250,14 @@ hex_fail \\x{hexdigit}{0,1}
\> { return GREATER_P; } \> { return GREATER_P; }
\${other}+ { \${other}+ {
addstring(true, yytext + 1, yyleng - 1); addstring(true, yytext + 1, yyleng - 1, yyscanner);
addchar(false, '\0'); addchar(false, '\0', yyscanner);
yylval->str = scanstring; yylval->str = yyextra->scanstring;
return VARIABLE_P; return VARIABLE_P;
} }
\$\" { \$\" {
addchar(true, '\0'); addchar(true, '\0', yyscanner);
BEGIN xvq; BEGIN xvq;
} }
@ -266,85 +266,85 @@ hex_fail \\x{hexdigit}{0,1}
{blank}+ { /* ignore */ } {blank}+ { /* ignore */ }
\/\* { \/\* {
addchar(true, '\0'); addchar(true, '\0', yyscanner);
BEGIN xc; BEGIN xc;
} }
{real} { {real} {
addstring(true, yytext, yyleng); addstring(true, yytext, yyleng, yyscanner);
addchar(false, '\0'); addchar(false, '\0', yyscanner);
yylval->str = scanstring; yylval->str = yyextra->scanstring;
return NUMERIC_P; return NUMERIC_P;
} }
{decimal} { {decimal} {
addstring(true, yytext, yyleng); addstring(true, yytext, yyleng, yyscanner);
addchar(false, '\0'); addchar(false, '\0', yyscanner);
yylval->str = scanstring; yylval->str = yyextra->scanstring;
return NUMERIC_P; return NUMERIC_P;
} }
{decinteger} { {decinteger} {
addstring(true, yytext, yyleng); addstring(true, yytext, yyleng, yyscanner);
addchar(false, '\0'); addchar(false, '\0', yyscanner);
yylval->str = scanstring; yylval->str = yyextra->scanstring;
return INT_P; return INT_P;
} }
{hexinteger} { {hexinteger} {
addstring(true, yytext, yyleng); addstring(true, yytext, yyleng, yyscanner);
addchar(false, '\0'); addchar(false, '\0', yyscanner);
yylval->str = scanstring; yylval->str = yyextra->scanstring;
return INT_P; return INT_P;
} }
{octinteger} { {octinteger} {
addstring(true, yytext, yyleng); addstring(true, yytext, yyleng, yyscanner);
addchar(false, '\0'); addchar(false, '\0', yyscanner);
yylval->str = scanstring; yylval->str = yyextra->scanstring;
return INT_P; return INT_P;
} }
{bininteger} { {bininteger} {
addstring(true, yytext, yyleng); addstring(true, yytext, yyleng, yyscanner);
addchar(false, '\0'); addchar(false, '\0', yyscanner);
yylval->str = scanstring; yylval->str = yyextra->scanstring;
return INT_P; return INT_P;
} }
{realfail} { {realfail} {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"invalid numeric literal"); "invalid numeric literal");
yyterminate(); yyterminate();
} }
{decinteger_junk} { {decinteger_junk} {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"trailing junk after numeric literal"); "trailing junk after numeric literal");
yyterminate(); yyterminate();
} }
{decimal_junk} { {decimal_junk} {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"trailing junk after numeric literal"); "trailing junk after numeric literal");
yyterminate(); yyterminate();
} }
{real_junk} { {real_junk} {
jsonpath_yyerror(NULL, escontext, jsonpath_yyerror(NULL, escontext, yyscanner,
"trailing junk after numeric literal"); "trailing junk after numeric literal");
yyterminate(); yyterminate();
} }
\" { \" {
addchar(true, '\0'); addchar(true, '\0', yyscanner);
BEGIN xq; BEGIN xq;
} }
\\ { \\ {
yyless(0); yyless(0);
addchar(true, '\0'); addchar(true, '\0', yyscanner);
BEGIN xnq; BEGIN xnq;
} }
{other}+ { {other}+ {
addstring(true, yytext, yyleng); addstring(true, yytext, yyleng, yyscanner);
BEGIN xnq; BEGIN xnq;
} }
@ -354,10 +354,17 @@ hex_fail \\x{hexdigit}{0,1}
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
/* see scan.l */
#undef yyextra
#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
void void
jsonpath_yyerror(JsonPathParseResult **result, struct Node *escontext, jsonpath_yyerror(JsonPathParseResult **result, struct Node *escontext,
yyscan_t yyscanner,
const char *message) const char *message)
{ {
struct yyguts_t * yyg = (struct yyguts_t *) yyscanner; /* needed for yytext macro */
/* don't overwrite escontext if it's already been set */ /* don't overwrite escontext if it's already been set */
if (SOFT_ERROR_OCCURRED(escontext)) if (SOFT_ERROR_OCCURRED(escontext))
return; return;
@ -427,9 +434,11 @@ static const JsonPathKeyword keywords[] = {
{ 12,false, TIMESTAMP_TZ_P, "timestamp_tz"}, { 12,false, TIMESTAMP_TZ_P, "timestamp_tz"},
}; };
/* Check if current scanstring value is a keyword */ /*
* Check if current scanstring value is a keyword
*/
static enum yytokentype static enum yytokentype
checkKeyword() checkKeyword(yyscan_t yyscanner)
{ {
int res = IDENT_P; int res = IDENT_P;
int diff; int diff;
@ -437,18 +446,18 @@ checkKeyword()
*StopHigh = keywords + lengthof(keywords), *StopHigh = keywords + lengthof(keywords),
*StopMiddle; *StopMiddle;
if (scanstring.len > keywords[lengthof(keywords) - 1].len) if (yyextra->scanstring.len > keywords[lengthof(keywords) - 1].len)
return res; return res;
while (StopLow < StopHigh) while (StopLow < StopHigh)
{ {
StopMiddle = StopLow + ((StopHigh - StopLow) >> 1); StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
if (StopMiddle->len == scanstring.len) if (StopMiddle->len == yyextra->scanstring.len)
diff = pg_strncasecmp(StopMiddle->keyword, scanstring.val, diff = pg_strncasecmp(StopMiddle->keyword, yyextra->scanstring.val,
scanstring.len); yyextra->scanstring.len);
else else
diff = StopMiddle->len - scanstring.len; diff = StopMiddle->len - yyextra->scanstring.len;
if (diff < 0) if (diff < 0)
StopLow = StopMiddle + 1; StopLow = StopMiddle + 1;
@ -457,8 +466,8 @@ checkKeyword()
else else
{ {
if (StopMiddle->lowercase) if (StopMiddle->lowercase)
diff = strncmp(StopMiddle->keyword, scanstring.val, diff = strncmp(StopMiddle->keyword, yyextra->scanstring.val,
scanstring.len); yyextra->scanstring.len);
if (diff == 0) if (diff == 0)
res = StopMiddle->val; res = StopMiddle->val;
@ -470,85 +479,47 @@ checkKeyword()
return res; return res;
} }
/*
* Called before any actual parsing is done
*/
static void
jsonpath_scanner_init(const char *str, int slen)
{
if (slen <= 0)
slen = strlen(str);
/*
* Might be left over after ereport()
*/
yy_init_globals();
/*
* Make a scan buffer with special termination needed by flex.
*/
scanbuflen = slen;
scanbuf = palloc(slen + 2);
memcpy(scanbuf, str, slen);
scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
BEGIN(INITIAL);
}
/*
* Called after parsing is done to clean up after jsonpath_scanner_init()
*/
static void
jsonpath_scanner_finish(void)
{
yy_delete_buffer(scanbufhandle);
pfree(scanbuf);
}
/* /*
* Resize scanstring so that it can append string of given length. * Resize scanstring so that it can append string of given length.
* Reinitialize if required. * Reinitialize if required.
*/ */
static void static void
resizeString(bool init, int appendLen) resizeString(bool init, int appendLen, yyscan_t yyscanner)
{ {
if (init) if (init)
{ {
scanstring.total = Max(32, appendLen); yyextra->scanstring.total = Max(32, appendLen);
scanstring.val = (char *) palloc(scanstring.total); yyextra->scanstring.val = (char *) palloc(yyextra->scanstring.total);
scanstring.len = 0; yyextra->scanstring.len = 0;
} }
else else
{ {
if (scanstring.len + appendLen >= scanstring.total) if (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total)
{ {
while (scanstring.len + appendLen >= scanstring.total) while (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total)
scanstring.total *= 2; yyextra->scanstring.total *= 2;
scanstring.val = repalloc(scanstring.val, scanstring.total); yyextra->scanstring.val = repalloc(yyextra->scanstring.val, yyextra->scanstring.total);
} }
} }
} }
/* Add set of bytes at "s" of length "l" to scanstring */ /* Add set of bytes at "s" of length "l" to scanstring */
static void static void
addstring(bool init, char *s, int l) addstring(bool init, char *s, int l, yyscan_t yyscanner)
{ {
resizeString(init, l + 1); resizeString(init, l + 1, yyscanner);
memcpy(scanstring.val + scanstring.len, s, l); memcpy(yyextra->scanstring.val + yyextra->scanstring.len, s, l);
scanstring.len += l; yyextra->scanstring.len += l;
} }
/* Add single byte "c" to scanstring */ /* Add single byte "c" to scanstring */
static void static void
addchar(bool init, char c) addchar(bool init, char c, yyscan_t yyscanner)
{ {
resizeString(init, 1); resizeString(init, 1, yyscanner);
scanstring.val[scanstring.len] = c; yyextra->scanstring.val[yyextra->scanstring.len] = c;
if (c != '\0') if (c != '\0')
scanstring.len++; yyextra->scanstring.len++;
} }
/* Interface to jsonpath parser */ /* Interface to jsonpath parser */
@ -556,20 +527,30 @@ JsonPathParseResult *
parsejsonpath(const char *str, int len, struct Node *escontext) parsejsonpath(const char *str, int len, struct Node *escontext)
{ {
JsonPathParseResult *parseresult; JsonPathParseResult *parseresult;
yyscan_t scanner;
struct jsonpath_yy_extra_type yyext;
jsonpath_scanner_init(str, len); if (jsonpath_yylex_init(&scanner) != 0)
elog(ERROR, "yylex_init() failed: %m");
if (jsonpath_yyparse(&parseresult, escontext) != 0) yyset_extra(&yyext, scanner);
jsonpath_yyerror(NULL, escontext, "invalid input"); /* shouldn't happen */
jsonpath_scanner_finish(); if (len <= 0)
len = strlen(str);
jsonpath_yy_scan_bytes(str, len, scanner);
if (jsonpath_yyparse(&parseresult, escontext, scanner) != 0)
jsonpath_yyerror(NULL, escontext, scanner, "invalid input"); /* shouldn't happen */
jsonpath_yylex_destroy(scanner);
return parseresult; return parseresult;
} }
/* Turn hex character into integer */ /* Turn hex character into integer */
static bool static bool
hexval(char c, int *result, struct Node *escontext) hexval(char c, int *result, struct Node *escontext, yyscan_t yyscanner)
{ {
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9')
{ {
@ -586,13 +567,13 @@ hexval(char c, int *result, struct Node *escontext)
*result = c - 'A' + 0xA; *result = c - 'A' + 0xA;
return true; return true;
} }
jsonpath_yyerror(NULL, escontext, "invalid hexadecimal digit"); jsonpath_yyerror(NULL, escontext, yyscanner, "invalid hexadecimal digit");
return false; return false;
} }
/* Add given unicode character to scanstring */ /* Add given unicode character to scanstring */
static bool static bool
addUnicodeChar(int ch, struct Node *escontext) addUnicodeChar(int ch, struct Node *escontext, yyscan_t yyscanner)
{ {
if (ch == 0) if (ch == 0)
{ {
@ -618,14 +599,14 @@ addUnicodeChar(int ch, struct Node *escontext)
ereturn(escontext, false, ereturn(escontext, false,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("could not convert Unicode to server encoding"))); errmsg("could not convert Unicode to server encoding")));
addstring(false, cbuf, strlen(cbuf)); addstring(false, cbuf, strlen(cbuf), yyscanner);
} }
return true; return true;
} }
/* Add unicode character, processing any surrogate pairs */ /* Add unicode character, processing any surrogate pairs */
static bool static bool
addUnicode(int ch, int *hi_surrogate, struct Node *escontext) addUnicode(int ch, int *hi_surrogate, struct Node *escontext, yyscan_t yyscanner)
{ {
if (is_utf16_surrogate_first(ch)) if (is_utf16_surrogate_first(ch))
{ {
@ -658,7 +639,7 @@ addUnicode(int ch, int *hi_surrogate, struct Node *escontext)
"surrogate."))); "surrogate.")));
} }
return addUnicodeChar(ch, escontext); return addUnicodeChar(ch, escontext, yyscanner);
} }
/* /*
@ -666,7 +647,7 @@ addUnicode(int ch, int *hi_surrogate, struct Node *escontext)
* src/backend/utils/adt/json.c * src/backend/utils/adt/json.c
*/ */
static bool static bool
parseUnicode(char *s, int l, struct Node *escontext) parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner)
{ {
int i = 2; int i = 2;
int hi_surrogate = -1; int hi_surrogate = -1;
@ -680,7 +661,7 @@ parseUnicode(char *s, int l, struct Node *escontext)
{ {
while (s[++i] != '}' && i < l) while (s[++i] != '}' && i < l)
{ {
if (!hexval(s[i], &si, escontext)) if (!hexval(s[i], &si, escontext, yyscanner))
return false; return false;
ch = (ch << 4) | si; ch = (ch << 4) | si;
} }
@ -690,13 +671,13 @@ parseUnicode(char *s, int l, struct Node *escontext)
{ {
for (j = 0; j < 4 && i < l; j++) for (j = 0; j < 4 && i < l; j++)
{ {
if (!hexval(s[i++], &si, escontext)) if (!hexval(s[i++], &si, escontext, yyscanner))
return false; return false;
ch = (ch << 4) | si; ch = (ch << 4) | si;
} }
} }
if (! addUnicode(ch, &hi_surrogate, escontext)) if (! addUnicode(ch, &hi_surrogate, escontext, yyscanner))
return false; return false;
} }
@ -714,17 +695,17 @@ parseUnicode(char *s, int l, struct Node *escontext)
/* Parse sequence of hex-encoded characters */ /* Parse sequence of hex-encoded characters */
static bool static bool
parseHexChar(char *s, struct Node *escontext) parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner)
{ {
int s2, s3, ch; int s2, s3, ch;
if (!hexval(s[2], &s2, escontext)) if (!hexval(s[2], &s2, escontext, yyscanner))
return false; return false;
if (!hexval(s[3], &s3, escontext)) if (!hexval(s[3], &s3, escontext, yyscanner))
return false; return false;
ch = (s2 << 4) | s3; ch = (s2 << 4) | s3;
return addUnicodeChar(ch, escontext); return addUnicodeChar(ch, escontext, yyscanner);
} }
/* /*
@ -733,13 +714,13 @@ parseHexChar(char *s, struct Node *escontext)
*/ */
void * void *
jsonpath_yyalloc(yy_size_t bytes) jsonpath_yyalloc(yy_size_t bytes, yyscan_t yyscanner)
{ {
return palloc(bytes); return palloc(bytes);
} }
void * void *
jsonpath_yyrealloc(void *ptr, yy_size_t bytes) jsonpath_yyrealloc(void *ptr, yy_size_t bytes, yyscan_t yyscanner)
{ {
if (ptr) if (ptr)
return repalloc(ptr, bytes); return repalloc(ptr, bytes);
@ -748,7 +729,7 @@ jsonpath_yyrealloc(void *ptr, yy_size_t bytes)
} }
void void
jsonpath_yyfree(void *ptr) jsonpath_yyfree(void *ptr, yyscan_t yyscanner)
{ {
if (ptr) if (ptr)
pfree(ptr); pfree(ptr);