#include "plpgsql.h"#include "mb/pg_wchar.h"#include "parser/scanner.h"#include "pl_gram.h"
Go to the source code of this file.
Data Structures | |
| struct | TokenAuxData |
Defines | |
| #define | PG_KEYWORD(a, b, c) {a,b,c}, |
| #define | MAX_PUSHBACKS 4 |
Functions | |
| static int | internal_yylex (TokenAuxData *auxdata) |
| static void | push_back_token (int token, TokenAuxData *auxdata) |
| static void | location_lineno_init (void) |
| int | plpgsql_yylex (void) |
| void | plpgsql_push_back_token (int token) |
| bool | plpgsql_token_is_unreserved_keyword (int token) |
| void | plpgsql_append_source_text (StringInfo buf, int startlocation, int endlocation) |
| int | plpgsql_peek (void) |
| void | plpgsql_peek2 (int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc) |
| int | plpgsql_scanner_errposition (int location) |
| void | __attribute__ ((noreturn)) |
| int | plpgsql_location_to_lineno (int location) |
| int | plpgsql_latest_lineno (void) |
| void | plpgsql_scanner_init (const char *str) |
| void | plpgsql_scanner_finish (void) |
Variables | |
| IdentifierLookup | plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL |
| static const ScanKeyword | reserved_keywords [] |
| static const int | num_reserved_keywords = lengthof(reserved_keywords) |
| static const ScanKeyword | unreserved_keywords [] |
| static const int | num_unreserved_keywords = lengthof(unreserved_keywords) |
| static core_yyscan_t | yyscanner = NULL |
| static core_yy_extra_type | core_yy |
| static const char * | scanorig |
| static int | plpgsql_yyleng |
| static int | num_pushbacks |
| static int | pushback_token [MAX_PUSHBACKS] |
| static TokenAuxData | pushback_auxdata [MAX_PUSHBACKS] |
| static const char * | cur_line_start |
| static const char * | cur_line_end |
| static int | cur_line_num |
| #define MAX_PUSHBACKS 4 |
Definition at line 184 of file pl_scanner.c.
Referenced by push_back_token().
Definition at line 23 of file pl_scanner.c.
| void __attribute__ | ( | (noreturn) | ) |
Definition at line 531 of file pl_scanner.c.
References _, ereport, errcode(), errmsg(), ERROR, plpgsql_scanner_errposition(), plpgsql_yyleng, core_yy_extra_type::scanbuf, and yytext.
{
char *yytext = core_yy.scanbuf + plpgsql_yylloc;
if (*yytext == '\0')
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
/* translator: %s is typically the translation of "syntax error" */
errmsg("%s at end of input", _(message)),
plpgsql_scanner_errposition(plpgsql_yylloc)));
}
else
{
/*
* If we have done any lookahead then flex will have restored the
* character after the end-of-token. Zap it again so that we report
* only the single token here. This modifies scanbuf but we no longer
* care about that.
*/
yytext[plpgsql_yyleng] = '\0';
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
/* translator: first %s is typically the translation of "syntax error" */
errmsg("%s at or near \"%s\"", _(message), yytext),
plpgsql_scanner_errposition(plpgsql_yylloc)));
}
}
| static int internal_yylex | ( | TokenAuxData * | auxdata | ) | [static] |
Definition at line 341 of file pl_scanner.c.
References core_yylex(), TokenAuxData::leng, TokenAuxData::lloc, TokenAuxData::lval, num_pushbacks, pstrdup(), pushback_token, core_yy_extra_type::scanbuf, yyscanner, and yytext.
Referenced by plpgsql_peek(), plpgsql_peek2(), and plpgsql_yylex().
{
int token;
const char *yytext;
if (num_pushbacks > 0)
{
num_pushbacks--;
token = pushback_token[num_pushbacks];
*auxdata = pushback_auxdata[num_pushbacks];
}
else
{
token = core_yylex(&auxdata->lval.core_yystype,
&auxdata->lloc,
yyscanner);
/* remember the length of yytext before it gets changed */
yytext = core_yy.scanbuf + auxdata->lloc;
auxdata->leng = strlen(yytext);
/* Check for << >> and #, which the core considers operators */
if (token == Op)
{
if (strcmp(auxdata->lval.str, "<<") == 0)
token = LESS_LESS;
else if (strcmp(auxdata->lval.str, ">>") == 0)
token = GREATER_GREATER;
else if (strcmp(auxdata->lval.str, "#") == 0)
token = '#';
}
/* The core returns PARAM as ival, but we treat it like IDENT */
else if (token == PARAM)
{
auxdata->lval.str = pstrdup(yytext);
}
}
return token;
}
| static void location_lineno_init | ( | void | ) | [static] |
Definition at line 595 of file pl_scanner.c.
References cur_line_end, cur_line_num, cur_line_start, and scanorig.
Referenced by plpgsql_location_to_lineno(), and plpgsql_scanner_init().
{
cur_line_start = scanorig;
cur_line_num = 1;
cur_line_end = strchr(cur_line_start, '\n');
}
| void plpgsql_append_source_text | ( | StringInfo | buf, | |
| int | startlocation, | |||
| int | endlocation | |||
| ) |
Definition at line 437 of file pl_scanner.c.
References appendBinaryStringInfo(), Assert, and scanorig.
{
Assert(startlocation <= endlocation);
appendBinaryStringInfo(buf, scanorig + startlocation,
endlocation - startlocation);
}
| int plpgsql_latest_lineno | ( | void | ) |
Definition at line 605 of file pl_scanner.c.
References cur_line_num.
Referenced by plpgsql_compile_error_callback().
{
return cur_line_num;
}
| int plpgsql_location_to_lineno | ( | int | location | ) |
Definition at line 571 of file pl_scanner.c.
References cur_line_end, cur_line_num, cur_line_start, location_lineno_init(), NULL, and scanorig.
{
const char *loc;
if (location < 0 || scanorig == NULL)
return 0; /* garbage in, garbage out */
loc = scanorig + location;
/* be correct, but not fast, if input location goes backwards */
if (loc < cur_line_start)
location_lineno_init();
while (cur_line_end != NULL && loc > cur_line_end)
{
cur_line_start = cur_line_end + 1;
cur_line_num++;
cur_line_end = strchr(cur_line_start, '\n');
}
return cur_line_num;
}
| int plpgsql_peek | ( | void | ) |
Definition at line 453 of file pl_scanner.c.
References internal_yylex(), and push_back_token().
{
int tok1;
TokenAuxData aux1;
tok1 = internal_yylex(&aux1);
push_back_token(tok1, &aux1);
return tok1;
}
| void plpgsql_peek2 | ( | int * | tok1_p, | |
| int * | tok2_p, | |||
| int * | tok1_loc, | |||
| int * | tok2_loc | |||
| ) |
Definition at line 472 of file pl_scanner.c.
References internal_yylex(), TokenAuxData::lloc, and push_back_token().
{
int tok1,
tok2;
TokenAuxData aux1,
aux2;
tok1 = internal_yylex(&aux1);
tok2 = internal_yylex(&aux2);
*tok1_p = tok1;
if (tok1_loc)
*tok1_loc = aux1.lloc;
*tok2_p = tok2;
if (tok2_loc)
*tok2_loc = aux2.lloc;
push_back_token(tok2, &aux2);
push_back_token(tok1, &aux1);
}
| void plpgsql_push_back_token | ( | int | token | ) |
Definition at line 403 of file pl_scanner.c.
References TokenAuxData::leng, TokenAuxData::lloc, TokenAuxData::lval, plpgsql_yyleng, and push_back_token().
{
TokenAuxData auxdata;
auxdata.lval = plpgsql_yylval;
auxdata.lloc = plpgsql_yylloc;
auxdata.leng = plpgsql_yyleng;
push_back_token(token, &auxdata);
}
| int plpgsql_scanner_errposition | ( | int | location | ) |
Definition at line 505 of file pl_scanner.c.
References internalerrposition(), internalerrquery(), NULL, pg_mbstrlen_with_len(), and scanorig.
Referenced by __attribute__().
{
int pos;
if (location < 0 || scanorig == NULL)
return 0; /* no-op if location is unknown */
/* Convert byte offset to character number */
pos = pg_mbstrlen_with_len(scanorig, location) + 1;
/* And pass it to the ereport mechanism */
(void) internalerrposition(pos);
/* Also pass the function body string */
return internalerrquery(scanorig);
}
| void plpgsql_scanner_finish | ( | void | ) |
Definition at line 645 of file pl_scanner.c.
References scanner_finish(), scanorig, and yyscanner.
Referenced by do_compile(), and plpgsql_compile_inline().
{
/* release storage */
scanner_finish(yyscanner);
/* avoid leaving any dangling pointers */
yyscanner = NULL;
scanorig = NULL;
}
| void plpgsql_scanner_init | ( | const char * | str | ) |
Definition at line 619 of file pl_scanner.c.
References location_lineno_init(), num_pushbacks, num_reserved_keywords, plpgsql_IdentifierLookup, scanner_init(), scanorig, and yyscanner.
Referenced by do_compile(), and plpgsql_compile_inline().
{
/* Start up the core scanner */
yyscanner = scanner_init(str, &core_yy,
reserved_keywords, num_reserved_keywords);
/*
* scanorig points to the original string, which unlike the scanner's
* scanbuf won't be modified on-the-fly by flex. Notice that although
* yytext points into scanbuf, we rely on being able to apply locations
* (offsets from string start) to scanorig as well.
*/
scanorig = str;
/* Other setup */
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
num_pushbacks = 0;
location_lineno_init();
}
| bool plpgsql_token_is_unreserved_keyword | ( | int | token | ) |
Definition at line 420 of file pl_scanner.c.
References i, num_unreserved_keywords, and value.
{
int i;
for (i = 0; i < num_unreserved_keywords; i++)
{
if (unreserved_keywords[i].value == token)
return true;
}
return false;
}
| int plpgsql_yylex | ( | void | ) |
Definition at line 211 of file pl_scanner.c.
References internal_yylex(), TokenAuxData::leng, TokenAuxData::lloc, TokenAuxData::lval, ScanKeyword::name, num_unreserved_keywords, plpgsql_parse_dblword(), plpgsql_parse_tripword(), plpgsql_parse_word(), plpgsql_yyleng, push_back_token(), core_yy_extra_type::scanbuf, ScanKeywordLookup(), and ScanKeyword::value.
{
int tok1;
TokenAuxData aux1;
const ScanKeyword *kw;
tok1 = internal_yylex(&aux1);
if (tok1 == IDENT || tok1 == PARAM)
{
int tok2;
TokenAuxData aux2;
tok2 = internal_yylex(&aux2);
if (tok2 == '.')
{
int tok3;
TokenAuxData aux3;
tok3 = internal_yylex(&aux3);
if (tok3 == IDENT)
{
int tok4;
TokenAuxData aux4;
tok4 = internal_yylex(&aux4);
if (tok4 == '.')
{
int tok5;
TokenAuxData aux5;
tok5 = internal_yylex(&aux5);
if (tok5 == IDENT)
{
if (plpgsql_parse_tripword(aux1.lval.str,
aux3.lval.str,
aux5.lval.str,
&aux1.lval.wdatum,
&aux1.lval.cword))
tok1 = T_DATUM;
else
tok1 = T_CWORD;
}
else
{
/* not A.B.C, so just process A.B */
push_back_token(tok5, &aux5);
push_back_token(tok4, &aux4);
if (plpgsql_parse_dblword(aux1.lval.str,
aux3.lval.str,
&aux1.lval.wdatum,
&aux1.lval.cword))
tok1 = T_DATUM;
else
tok1 = T_CWORD;
}
}
else
{
/* not A.B.C, so just process A.B */
push_back_token(tok4, &aux4);
if (plpgsql_parse_dblword(aux1.lval.str,
aux3.lval.str,
&aux1.lval.wdatum,
&aux1.lval.cword))
tok1 = T_DATUM;
else
tok1 = T_CWORD;
}
}
else
{
/* not A.B, so just process A */
push_back_token(tok3, &aux3);
push_back_token(tok2, &aux2);
if (plpgsql_parse_word(aux1.lval.str,
core_yy.scanbuf + aux1.lloc,
&aux1.lval.wdatum,
&aux1.lval.word))
tok1 = T_DATUM;
else if (!aux1.lval.word.quoted &&
(kw = ScanKeywordLookup(aux1.lval.word.ident,
unreserved_keywords,
num_unreserved_keywords)))
{
aux1.lval.keyword = kw->name;
tok1 = kw->value;
}
else
tok1 = T_WORD;
}
}
else
{
/* not A.B, so just process A */
push_back_token(tok2, &aux2);
if (plpgsql_parse_word(aux1.lval.str,
core_yy.scanbuf + aux1.lloc,
&aux1.lval.wdatum,
&aux1.lval.word))
tok1 = T_DATUM;
else if (!aux1.lval.word.quoted &&
(kw = ScanKeywordLookup(aux1.lval.word.ident,
unreserved_keywords,
num_unreserved_keywords)))
{
aux1.lval.keyword = kw->name;
tok1 = kw->value;
}
else
tok1 = T_WORD;
}
}
else
{
/* Not a potential plpgsql variable name, just return the data */
}
plpgsql_yylval = aux1.lval;
plpgsql_yylloc = aux1.lloc;
plpgsql_yyleng = aux1.leng;
return tok1;
}
| static void push_back_token | ( | int | token, | |
| TokenAuxData * | auxdata | |||
| ) | [static] |
Definition at line 387 of file pl_scanner.c.
References elog, ERROR, MAX_PUSHBACKS, num_pushbacks, and pushback_token.
Referenced by plpgsql_peek(), plpgsql_peek2(), plpgsql_push_back_token(), and plpgsql_yylex().
{
if (num_pushbacks >= MAX_PUSHBACKS)
elog(ERROR, "too many tokens pushed back");
pushback_token[num_pushbacks] = token;
pushback_auxdata[num_pushbacks] = *auxdata;
num_pushbacks++;
}
core_yy_extra_type core_yy [static] |
Definition at line 175 of file pl_scanner.c.
const char* cur_line_end [static] |
Definition at line 192 of file pl_scanner.c.
Referenced by location_lineno_init(), and plpgsql_location_to_lineno().
int cur_line_num [static] |
Definition at line 193 of file pl_scanner.c.
Referenced by location_lineno_init(), plpgsql_latest_lineno(), and plpgsql_location_to_lineno().
const char* cur_line_start [static] |
Definition at line 191 of file pl_scanner.c.
Referenced by location_lineno_init(), and plpgsql_location_to_lineno().
int num_pushbacks [static] |
Definition at line 186 of file pl_scanner.c.
Referenced by internal_yylex(), plpgsql_scanner_init(), and push_back_token().
const int num_reserved_keywords = lengthof(reserved_keywords) [static] |
Definition at line 105 of file pl_scanner.c.
Referenced by plpgsql_scanner_init().
const int num_unreserved_keywords = lengthof(unreserved_keywords) [static] |
Definition at line 155 of file pl_scanner.c.
Referenced by plpgsql_token_is_unreserved_keyword(), and plpgsql_yylex().
| IdentifierLookup plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL |
Definition at line 27 of file pl_scanner.c.
Referenced by plpgsql_parse_dblword(), plpgsql_parse_tripword(), plpgsql_parse_word(), and plpgsql_scanner_init().
int plpgsql_yyleng [static] |
Definition at line 181 of file pl_scanner.c.
Referenced by __attribute__(), plpgsql_push_back_token(), and plpgsql_yylex().
TokenAuxData pushback_auxdata[MAX_PUSHBACKS] [static] |
Definition at line 188 of file pl_scanner.c.
int pushback_token[MAX_PUSHBACKS] [static] |
Definition at line 187 of file pl_scanner.c.
Referenced by internal_yylex(), and push_back_token().
const ScanKeyword reserved_keywords[] [static] |
Definition at line 61 of file pl_scanner.c.
const char* scanorig [static] |
Definition at line 178 of file pl_scanner.c.
Referenced by location_lineno_init(), plpgsql_append_source_text(), plpgsql_location_to_lineno(), plpgsql_scanner_errposition(), plpgsql_scanner_finish(), and plpgsql_scanner_init().
const ScanKeyword unreserved_keywords[] [static] |
Definition at line 107 of file pl_scanner.c.
core_yyscan_t yyscanner = NULL [static] |
Definition at line 174 of file pl_scanner.c.
Referenced by fill_in_constant_lengths(), internal_yylex(), plpgsql_scanner_finish(), plpgsql_scanner_init(), and raw_parser().
1.7.1