00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "plpgsql.h"
00017
00018 #include "mb/pg_wchar.h"
00019 #include "parser/scanner.h"
00020
00021 #include "pl_gram.h"
00022
00023 #define PG_KEYWORD(a,b,c) {a,b,c},
00024
00025
00026
00027 IdentifierLookup plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 static const ScanKeyword reserved_keywords[] = {
00062 PG_KEYWORD("all", K_ALL, RESERVED_KEYWORD)
00063 PG_KEYWORD("begin", K_BEGIN, RESERVED_KEYWORD)
00064 PG_KEYWORD("by", K_BY, RESERVED_KEYWORD)
00065 PG_KEYWORD("case", K_CASE, RESERVED_KEYWORD)
00066 PG_KEYWORD("close", K_CLOSE, RESERVED_KEYWORD)
00067 PG_KEYWORD("collate", K_COLLATE, RESERVED_KEYWORD)
00068 PG_KEYWORD("continue", K_CONTINUE, RESERVED_KEYWORD)
00069 PG_KEYWORD("declare", K_DECLARE, RESERVED_KEYWORD)
00070 PG_KEYWORD("default", K_DEFAULT, RESERVED_KEYWORD)
00071 PG_KEYWORD("diagnostics", K_DIAGNOSTICS, RESERVED_KEYWORD)
00072 PG_KEYWORD("else", K_ELSE, RESERVED_KEYWORD)
00073 PG_KEYWORD("elseif", K_ELSIF, RESERVED_KEYWORD)
00074 PG_KEYWORD("elsif", K_ELSIF, RESERVED_KEYWORD)
00075 PG_KEYWORD("end", K_END, RESERVED_KEYWORD)
00076 PG_KEYWORD("exception", K_EXCEPTION, RESERVED_KEYWORD)
00077 PG_KEYWORD("execute", K_EXECUTE, RESERVED_KEYWORD)
00078 PG_KEYWORD("exit", K_EXIT, RESERVED_KEYWORD)
00079 PG_KEYWORD("fetch", K_FETCH, RESERVED_KEYWORD)
00080 PG_KEYWORD("for", K_FOR, RESERVED_KEYWORD)
00081 PG_KEYWORD("foreach", K_FOREACH, RESERVED_KEYWORD)
00082 PG_KEYWORD("from", K_FROM, RESERVED_KEYWORD)
00083 PG_KEYWORD("get", K_GET, RESERVED_KEYWORD)
00084 PG_KEYWORD("if", K_IF, RESERVED_KEYWORD)
00085 PG_KEYWORD("in", K_IN, RESERVED_KEYWORD)
00086 PG_KEYWORD("insert", K_INSERT, RESERVED_KEYWORD)
00087 PG_KEYWORD("into", K_INTO, RESERVED_KEYWORD)
00088 PG_KEYWORD("loop", K_LOOP, RESERVED_KEYWORD)
00089 PG_KEYWORD("move", K_MOVE, RESERVED_KEYWORD)
00090 PG_KEYWORD("not", K_NOT, RESERVED_KEYWORD)
00091 PG_KEYWORD("null", K_NULL, RESERVED_KEYWORD)
00092 PG_KEYWORD("open", K_OPEN, RESERVED_KEYWORD)
00093 PG_KEYWORD("or", K_OR, RESERVED_KEYWORD)
00094 PG_KEYWORD("perform", K_PERFORM, RESERVED_KEYWORD)
00095 PG_KEYWORD("raise", K_RAISE, RESERVED_KEYWORD)
00096 PG_KEYWORD("return", K_RETURN, RESERVED_KEYWORD)
00097 PG_KEYWORD("strict", K_STRICT, RESERVED_KEYWORD)
00098 PG_KEYWORD("then", K_THEN, RESERVED_KEYWORD)
00099 PG_KEYWORD("to", K_TO, RESERVED_KEYWORD)
00100 PG_KEYWORD("using", K_USING, RESERVED_KEYWORD)
00101 PG_KEYWORD("when", K_WHEN, RESERVED_KEYWORD)
00102 PG_KEYWORD("while", K_WHILE, RESERVED_KEYWORD)
00103 };
00104
00105 static const int num_reserved_keywords = lengthof(reserved_keywords);
00106
00107 static const ScanKeyword unreserved_keywords[] = {
00108 PG_KEYWORD("absolute", K_ABSOLUTE, UNRESERVED_KEYWORD)
00109 PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)
00110 PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)
00111 PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)
00112 PG_KEYWORD("constant", K_CONSTANT, UNRESERVED_KEYWORD)
00113 PG_KEYWORD("current", K_CURRENT, UNRESERVED_KEYWORD)
00114 PG_KEYWORD("cursor", K_CURSOR, UNRESERVED_KEYWORD)
00115 PG_KEYWORD("debug", K_DEBUG, UNRESERVED_KEYWORD)
00116 PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD)
00117 PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD)
00118 PG_KEYWORD("errcode", K_ERRCODE, UNRESERVED_KEYWORD)
00119 PG_KEYWORD("error", K_ERROR, UNRESERVED_KEYWORD)
00120 PG_KEYWORD("first", K_FIRST, UNRESERVED_KEYWORD)
00121 PG_KEYWORD("forward", K_FORWARD, UNRESERVED_KEYWORD)
00122 PG_KEYWORD("hint", K_HINT, UNRESERVED_KEYWORD)
00123 PG_KEYWORD("info", K_INFO, UNRESERVED_KEYWORD)
00124 PG_KEYWORD("is", K_IS, UNRESERVED_KEYWORD)
00125 PG_KEYWORD("last", K_LAST, UNRESERVED_KEYWORD)
00126 PG_KEYWORD("log", K_LOG, UNRESERVED_KEYWORD)
00127 PG_KEYWORD("message", K_MESSAGE, UNRESERVED_KEYWORD)
00128 PG_KEYWORD("message_text", K_MESSAGE_TEXT, UNRESERVED_KEYWORD)
00129 PG_KEYWORD("next", K_NEXT, UNRESERVED_KEYWORD)
00130 PG_KEYWORD("no", K_NO, UNRESERVED_KEYWORD)
00131 PG_KEYWORD("notice", K_NOTICE, UNRESERVED_KEYWORD)
00132 PG_KEYWORD("option", K_OPTION, UNRESERVED_KEYWORD)
00133 PG_KEYWORD("pg_exception_context", K_PG_EXCEPTION_CONTEXT, UNRESERVED_KEYWORD)
00134 PG_KEYWORD("pg_exception_detail", K_PG_EXCEPTION_DETAIL, UNRESERVED_KEYWORD)
00135 PG_KEYWORD("pg_exception_hint", K_PG_EXCEPTION_HINT, UNRESERVED_KEYWORD)
00136 PG_KEYWORD("prior", K_PRIOR, UNRESERVED_KEYWORD)
00137 PG_KEYWORD("query", K_QUERY, UNRESERVED_KEYWORD)
00138 PG_KEYWORD("relative", K_RELATIVE, UNRESERVED_KEYWORD)
00139 PG_KEYWORD("result_oid", K_RESULT_OID, UNRESERVED_KEYWORD)
00140 PG_KEYWORD("returned_sqlstate", K_RETURNED_SQLSTATE, UNRESERVED_KEYWORD)
00141 PG_KEYWORD("reverse", K_REVERSE, UNRESERVED_KEYWORD)
00142 PG_KEYWORD("row_count", K_ROW_COUNT, UNRESERVED_KEYWORD)
00143 PG_KEYWORD("rowtype", K_ROWTYPE, UNRESERVED_KEYWORD)
00144 PG_KEYWORD("scroll", K_SCROLL, UNRESERVED_KEYWORD)
00145 PG_KEYWORD("slice", K_SLICE, UNRESERVED_KEYWORD)
00146 PG_KEYWORD("sqlstate", K_SQLSTATE, UNRESERVED_KEYWORD)
00147 PG_KEYWORD("stacked", K_STACKED, UNRESERVED_KEYWORD)
00148 PG_KEYWORD("type", K_TYPE, UNRESERVED_KEYWORD)
00149 PG_KEYWORD("use_column", K_USE_COLUMN, UNRESERVED_KEYWORD)
00150 PG_KEYWORD("use_variable", K_USE_VARIABLE, UNRESERVED_KEYWORD)
00151 PG_KEYWORD("variable_conflict", K_VARIABLE_CONFLICT, UNRESERVED_KEYWORD)
00152 PG_KEYWORD("warning", K_WARNING, UNRESERVED_KEYWORD)
00153 };
00154
00155 static const int num_unreserved_keywords = lengthof(unreserved_keywords);
00156
00157
00158
00159 typedef struct
00160 {
00161 YYSTYPE lval;
00162 YYLTYPE lloc;
00163 int leng;
00164 } TokenAuxData;
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 static core_yyscan_t yyscanner = NULL;
00175 static core_yy_extra_type core_yy;
00176
00177
00178 static const char *scanorig;
00179
00180
00181 static int plpgsql_yyleng;
00182
00183
00184 #define MAX_PUSHBACKS 4
00185
00186 static int num_pushbacks;
00187 static int pushback_token[MAX_PUSHBACKS];
00188 static TokenAuxData pushback_auxdata[MAX_PUSHBACKS];
00189
00190
00191 static const char *cur_line_start;
00192 static const char *cur_line_end;
00193 static int cur_line_num;
00194
00195
00196 static int internal_yylex(TokenAuxData *auxdata);
00197 static void push_back_token(int token, TokenAuxData *auxdata);
00198 static void location_lineno_init(void);
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 int
00211 plpgsql_yylex(void)
00212 {
00213 int tok1;
00214 TokenAuxData aux1;
00215 const ScanKeyword *kw;
00216
00217 tok1 = internal_yylex(&aux1);
00218 if (tok1 == IDENT || tok1 == PARAM)
00219 {
00220 int tok2;
00221 TokenAuxData aux2;
00222
00223 tok2 = internal_yylex(&aux2);
00224 if (tok2 == '.')
00225 {
00226 int tok3;
00227 TokenAuxData aux3;
00228
00229 tok3 = internal_yylex(&aux3);
00230 if (tok3 == IDENT)
00231 {
00232 int tok4;
00233 TokenAuxData aux4;
00234
00235 tok4 = internal_yylex(&aux4);
00236 if (tok4 == '.')
00237 {
00238 int tok5;
00239 TokenAuxData aux5;
00240
00241 tok5 = internal_yylex(&aux5);
00242 if (tok5 == IDENT)
00243 {
00244 if (plpgsql_parse_tripword(aux1.lval.str,
00245 aux3.lval.str,
00246 aux5.lval.str,
00247 &aux1.lval.wdatum,
00248 &aux1.lval.cword))
00249 tok1 = T_DATUM;
00250 else
00251 tok1 = T_CWORD;
00252 }
00253 else
00254 {
00255
00256 push_back_token(tok5, &aux5);
00257 push_back_token(tok4, &aux4);
00258 if (plpgsql_parse_dblword(aux1.lval.str,
00259 aux3.lval.str,
00260 &aux1.lval.wdatum,
00261 &aux1.lval.cword))
00262 tok1 = T_DATUM;
00263 else
00264 tok1 = T_CWORD;
00265 }
00266 }
00267 else
00268 {
00269
00270 push_back_token(tok4, &aux4);
00271 if (plpgsql_parse_dblword(aux1.lval.str,
00272 aux3.lval.str,
00273 &aux1.lval.wdatum,
00274 &aux1.lval.cword))
00275 tok1 = T_DATUM;
00276 else
00277 tok1 = T_CWORD;
00278 }
00279 }
00280 else
00281 {
00282
00283 push_back_token(tok3, &aux3);
00284 push_back_token(tok2, &aux2);
00285 if (plpgsql_parse_word(aux1.lval.str,
00286 core_yy.scanbuf + aux1.lloc,
00287 &aux1.lval.wdatum,
00288 &aux1.lval.word))
00289 tok1 = T_DATUM;
00290 else if (!aux1.lval.word.quoted &&
00291 (kw = ScanKeywordLookup(aux1.lval.word.ident,
00292 unreserved_keywords,
00293 num_unreserved_keywords)))
00294 {
00295 aux1.lval.keyword = kw->name;
00296 tok1 = kw->value;
00297 }
00298 else
00299 tok1 = T_WORD;
00300 }
00301 }
00302 else
00303 {
00304
00305 push_back_token(tok2, &aux2);
00306 if (plpgsql_parse_word(aux1.lval.str,
00307 core_yy.scanbuf + aux1.lloc,
00308 &aux1.lval.wdatum,
00309 &aux1.lval.word))
00310 tok1 = T_DATUM;
00311 else if (!aux1.lval.word.quoted &&
00312 (kw = ScanKeywordLookup(aux1.lval.word.ident,
00313 unreserved_keywords,
00314 num_unreserved_keywords)))
00315 {
00316 aux1.lval.keyword = kw->name;
00317 tok1 = kw->value;
00318 }
00319 else
00320 tok1 = T_WORD;
00321 }
00322 }
00323 else
00324 {
00325
00326 }
00327
00328 plpgsql_yylval = aux1.lval;
00329 plpgsql_yylloc = aux1.lloc;
00330 plpgsql_yyleng = aux1.leng;
00331 return tok1;
00332 }
00333
00334
00335
00336
00337
00338
00339
00340 static int
00341 internal_yylex(TokenAuxData *auxdata)
00342 {
00343 int token;
00344 const char *yytext;
00345
00346 if (num_pushbacks > 0)
00347 {
00348 num_pushbacks--;
00349 token = pushback_token[num_pushbacks];
00350 *auxdata = pushback_auxdata[num_pushbacks];
00351 }
00352 else
00353 {
00354 token = core_yylex(&auxdata->lval.core_yystype,
00355 &auxdata->lloc,
00356 yyscanner);
00357
00358
00359 yytext = core_yy.scanbuf + auxdata->lloc;
00360 auxdata->leng = strlen(yytext);
00361
00362
00363 if (token == Op)
00364 {
00365 if (strcmp(auxdata->lval.str, "<<") == 0)
00366 token = LESS_LESS;
00367 else if (strcmp(auxdata->lval.str, ">>") == 0)
00368 token = GREATER_GREATER;
00369 else if (strcmp(auxdata->lval.str, "#") == 0)
00370 token = '#';
00371 }
00372
00373
00374 else if (token == PARAM)
00375 {
00376 auxdata->lval.str = pstrdup(yytext);
00377 }
00378 }
00379
00380 return token;
00381 }
00382
00383
00384
00385
00386 static void
00387 push_back_token(int token, TokenAuxData *auxdata)
00388 {
00389 if (num_pushbacks >= MAX_PUSHBACKS)
00390 elog(ERROR, "too many tokens pushed back");
00391 pushback_token[num_pushbacks] = token;
00392 pushback_auxdata[num_pushbacks] = *auxdata;
00393 num_pushbacks++;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402 void
00403 plpgsql_push_back_token(int token)
00404 {
00405 TokenAuxData auxdata;
00406
00407 auxdata.lval = plpgsql_yylval;
00408 auxdata.lloc = plpgsql_yylloc;
00409 auxdata.leng = plpgsql_yyleng;
00410 push_back_token(token, &auxdata);
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 bool
00420 plpgsql_token_is_unreserved_keyword(int token)
00421 {
00422 int i;
00423
00424 for (i = 0; i < num_unreserved_keywords; i++)
00425 {
00426 if (unreserved_keywords[i].value == token)
00427 return true;
00428 }
00429 return false;
00430 }
00431
00432
00433
00434
00435
00436 void
00437 plpgsql_append_source_text(StringInfo buf,
00438 int startlocation, int endlocation)
00439 {
00440 Assert(startlocation <= endlocation);
00441 appendBinaryStringInfo(buf, scanorig + startlocation,
00442 endlocation - startlocation);
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452 int
00453 plpgsql_peek(void)
00454 {
00455 int tok1;
00456 TokenAuxData aux1;
00457
00458 tok1 = internal_yylex(&aux1);
00459 push_back_token(tok1, &aux1);
00460 return tok1;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 void
00472 plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc)
00473 {
00474 int tok1,
00475 tok2;
00476 TokenAuxData aux1,
00477 aux2;
00478
00479 tok1 = internal_yylex(&aux1);
00480 tok2 = internal_yylex(&aux2);
00481
00482 *tok1_p = tok1;
00483 if (tok1_loc)
00484 *tok1_loc = aux1.lloc;
00485 *tok2_p = tok2;
00486 if (tok2_loc)
00487 *tok2_loc = aux2.lloc;
00488
00489 push_back_token(tok2, &aux2);
00490 push_back_token(tok1, &aux1);
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 int
00505 plpgsql_scanner_errposition(int location)
00506 {
00507 int pos;
00508
00509 if (location < 0 || scanorig == NULL)
00510 return 0;
00511
00512
00513 pos = pg_mbstrlen_with_len(scanorig, location) + 1;
00514
00515 (void) internalerrposition(pos);
00516
00517 return internalerrquery(scanorig);
00518 }
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 void __attribute__((noreturn))
00532 plpgsql_yyerror(const char *message)
00533 {
00534 char *yytext = core_yy.scanbuf + plpgsql_yylloc;
00535
00536 if (*yytext == '\0')
00537 {
00538 ereport(ERROR,
00539 (errcode(ERRCODE_SYNTAX_ERROR),
00540
00541 errmsg("%s at end of input", _(message)),
00542 plpgsql_scanner_errposition(plpgsql_yylloc)));
00543 }
00544 else
00545 {
00546
00547
00548
00549
00550
00551
00552 yytext[plpgsql_yyleng] = '\0';
00553
00554 ereport(ERROR,
00555 (errcode(ERRCODE_SYNTAX_ERROR),
00556
00557 errmsg("%s at or near \"%s\"", _(message), yytext),
00558 plpgsql_scanner_errposition(plpgsql_yylloc)));
00559 }
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 int
00571 plpgsql_location_to_lineno(int location)
00572 {
00573 const char *loc;
00574
00575 if (location < 0 || scanorig == NULL)
00576 return 0;
00577 loc = scanorig + location;
00578
00579
00580 if (loc < cur_line_start)
00581 location_lineno_init();
00582
00583 while (cur_line_end != NULL && loc > cur_line_end)
00584 {
00585 cur_line_start = cur_line_end + 1;
00586 cur_line_num++;
00587 cur_line_end = strchr(cur_line_start, '\n');
00588 }
00589
00590 return cur_line_num;
00591 }
00592
00593
00594 static void
00595 location_lineno_init(void)
00596 {
00597 cur_line_start = scanorig;
00598 cur_line_num = 1;
00599
00600 cur_line_end = strchr(cur_line_start, '\n');
00601 }
00602
00603
00604 int
00605 plpgsql_latest_lineno(void)
00606 {
00607 return cur_line_num;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 void
00619 plpgsql_scanner_init(const char *str)
00620 {
00621
00622 yyscanner = scanner_init(str, &core_yy,
00623 reserved_keywords, num_reserved_keywords);
00624
00625
00626
00627
00628
00629
00630
00631 scanorig = str;
00632
00633
00634 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
00635
00636 num_pushbacks = 0;
00637
00638 location_lineno_init();
00639 }
00640
00641
00642
00643
00644 void
00645 plpgsql_scanner_finish(void)
00646 {
00647
00648 scanner_finish(yyscanner);
00649
00650 yyscanner = NULL;
00651 scanorig = NULL;
00652 }