387 {
388 /* Declare some local variables inside yylex(), for convenience */
391
392 /*
393 * Force flex into the state indicated by start_state. This has a
394 * couple of purposes: it lets some of the functions below set a new
395 * starting state without ugly direct access to flex variables, and it
396 * allows us to transition from one flex lexer to another so that we
397 * can lex different parts of the source string using separate lexers.
398 */
400%}
401
402{whitespace} {
403 /*
404 * Note that the whitespace rule includes both true
405 * whitespace and single-line ("--" style) comments.
406 * We suppress whitespace until we have collected some
407 * non-whitespace data. (This interacts with some
408 * decisions in MainLoop(); see there for details.)
409 */
410 if (output_buf->
len > 0)
412 }
413
414{xcstart} {
416 BEGIN(xc);
417 /* Put back any characters past slash-star; see above */
418 yyless(2);
420 }
421
422<xc>{
423{xcstart} {
424 cur_state->xcdepth++;
425 /* Put back any characters past slash-star; see above */
426 yyless(2);
428 }
429
430{xcstop} {
431 if (cur_state->xcdepth <= 0)
432 BEGIN(INITIAL);
433 else
434 cur_state->xcdepth--;
436 }
437
438{xcinside} {
440 }
441
442{op_chars} {
444 }
445
446\*+ {
448 }
449} /* <xc> */
450
451{xbstart} {
452 BEGIN(xb);
454 }
455<xh>{xhinside} |
456<xb>{xbinside} {
458 }
459
460{xhstart} {
461 /* Hexadecimal bit type.
462 * At some point we should simply pass the string
463 * forward to the parser and label it there.
464 * In the meantime, place a leading "x" on the string
465 * to mark it for the input routine as a hex string.
466 */
467 BEGIN(xh);
469 }
470
471{xnstart} {
472 yyless(1); /* eat only 'n' this time */
474 }
475
476{xqstart} {
477 if (cur_state->std_strings)
478 BEGIN(xq);
479 else
480 BEGIN(xe);
482 }
483{xestart} {
484 BEGIN(xe);
486 }
487{xusstart} {
488 BEGIN(xus);
490 }
491
492<xb,xh,xq,xe,xus>{quote} {
493 /*
494 * When we are scanning a quoted string and see an end
495 * quote, we must look ahead for a possible continuation.
496 * If we don't see one, we know the end quote was in fact
497 * the end of the string. To reduce the lexer table size,
498 * we use a single "xqs" state to do the lookahead for all
499 * types of strings.
500 */
501 cur_state->state_before_str_stop = YYSTATE;
502 BEGIN(xqs);
504 }
505<xqs>{quotecontinue} {
506 /*
507 * Found a quote continuation, so return to the in-quote
508 * state and continue scanning the literal. Nothing is
509 * added to the literal's contents.
510 */
511 BEGIN(cur_state->state_before_str_stop);
513 }
514<xqs>{quotecontinuefail} |
515<xqs>{other} {
516 /*
517 * Failed to see a quote continuation. Throw back
518 * everything after the end quote, and handle the string
519 * according to the state we were in previously.
520 */
521 yyless(0);
522 BEGIN(INITIAL);
523 /* There's nothing to echo ... */
524 }
525
526<xq,xe,xus>{xqdouble} {
528 }
529<xq,xus>{xqinside} {
531 }
532<xe>{xeinside} {
534 }
535<xe>{xeunicode} {
537 }
538<xe>{xeunicodefail} {
540 }
541<xe>{xeescape} {
543 }
544<xe>{xeoctesc} {
546 }
547<xe>{xehexesc} {
549 }
550<xe>. {
551 /* This is only needed for \ just before EOF */
553 }
554
555{dolqdelim} {
556 cur_state->dolqstart =
pg_strdup(yytext);
557 BEGIN(xdolq);
559 }
560{dolqfailed} {
561 /* throw back all but the initial "$" */
562 yyless(1);
564 }
565<xdolq>{dolqdelim} {
566 if (strcmp(yytext, cur_state->dolqstart) == 0)
567 {
568 free(cur_state->dolqstart);
569 cur_state->dolqstart = NULL;
570 BEGIN(INITIAL);
571 }
572 else
573 {
574 /*
575 * When we fail to match $...$ to dolqstart, transfer
576 * the $... part to the output, but put back the final
577 * $ for rescanning. Consider $delim$...$junk$delim$
578 */
580 }
582 }
583<xdolq>{dolqinside} {
585 }
586<xdolq>{dolqfailed} {
588 }
589<xdolq>. {
590 /* This is only needed for $ inside the quoted text */
592 }
593
594{xdstart} {
595 BEGIN(xd);
597 }
598{xuistart} {
599 BEGIN(xui);
601 }
602<xd>{xdstop} {
603 BEGIN(INITIAL);
605 }
606<xui>{dquote} {
607 BEGIN(INITIAL);
609 }
610<xd,xui>{xddouble} {
612 }
613<xd,xui>{xdinside} {
615 }
616
617{xufailed} {
618 /* throw back all but the initial u/U */
619 yyless(1);
621 }
622
623{typecast} {
625 }
626
627{dot_dot} {
629 }
630
631{colon_equals} {
633 }
634
635{equals_greater} {
637 }
638
639{less_equals} {
641 }
642
643{greater_equals} {
645 }
646
647{less_greater} {
649 }
650
651{not_equals} {
653 }
654
655 /*
656 * These rules are specific to psql --- they implement parenthesis
657 * counting and detection of command-ending semicolon. These must
658 * appear before the {self} rule so that they take precedence over it.
659 */
660
661"(" {
662 cur_state->paren_depth++;
664 }
665
666")" {
667 if (cur_state->paren_depth > 0)
668 cur_state->paren_depth--;
670 }
671
672";" {
674 if (cur_state->paren_depth == 0 && cur_state->begin_depth == 0)
675 {
676 /* Terminate lexing temporarily */
677 cur_state->start_state = YY_START;
678 cur_state->identifier_count = 0;
680 }
681 }
682
683 /*
684 * psql-specific rules to handle backslash commands and variable
685 * substitution. We want these before {self}, also.
686 */
687
688"\\"[;:] {
689 /* Force a semi-colon or colon into the query buffer */
691 if (yytext[1] == ';')
692 cur_state->identifier_count = 0;
693 }
694
695"\\" {
696 /* Terminate lexing temporarily */
697 cur_state->start_state = YY_START;
699 }
700
701:{variable_char}+ {
702 /* Possible psql variable substitution */
703 char *varname;
705
707 yytext + 1,
709 if (cur_state->callbacks->get_variable)
710 value = cur_state->callbacks->get_variable(varname,
712 cur_state->cb_passthrough);
713 else
715
717 {
718 /* It is a variable, check for recursion */
720 {
721 /* Recursive expansion --- don't go there */
723 varname);
724 /* Instead copy the string as is */
726 }
727 else
728 {
729 /* OK, perform substitution */
731 /* yy_scan_string already made buffer active */
732 }
734 }
735 else
736 {
737 /*
738 * if the variable doesn't exist we'll copy the string
739 * as is
740 */
742 }
#define pg_log_warning(...)
void psqlscan_push_new_buffer(PsqlScanState state, const char *newstr, const char *varname)
bool psqlscan_var_is_current_source(PsqlScanState state, const char *varname)
743
745 }
746
747:'{variable_char}+' {
750 }
void psqlscan_escape_variable(PsqlScanState state, const char *txt, int len, PsqlScanQuoteType quote)
751
752:\"{variable_char}+\" {
755 }
756
757:\{\?{variable_char}+\} {
759 }
void psqlscan_test_variable(PsqlScanState state, const char *txt, int len)
760
761 /*
762 * These rules just avoid the need for scanner backup if one of the
763 * three rules above fails to match completely.
764 */
765
766:'{variable_char}* {
767 /* Throw back everything but the colon */
768 yyless(1);
770 }
771
772:\"{variable_char}* {
773 /* Throw back everything but the colon */
774 yyless(1);
776 }
777
778:\{\?{variable_char}* {
779 /* Throw back everything but the colon */
780 yyless(1);
782 }
783:\{ {
784 /* Throw back everything but the colon */
785 yyless(1);
787 }
788
789 /*
790 * Back to backend-compatible rules.
791 */
792
793{self} {
795 }
796
797{operator} {
798 /*
799 * Check for embedded slash-star or dash-dash; those
800 * are comment starts, so operator must stop there.
801 * Note that slash-star or dash-dash at the first
802 * character will match a prior rule, not this one.
803 */
805 char *slashstar = strstr(yytext, "/*");
806 char *dashdash = strstr(yytext, "--");
807
808 if (slashstar && dashdash)
809 {
810 /* if both appear, take the first one */
811 if (slashstar > dashdash)
812 slashstar = dashdash;
813 }
814 else if (!slashstar)
815 slashstar = dashdash;
816 if (slashstar)
817 nchars = slashstar - yytext;
818
819 /*
820 * For SQL compatibility, '+' and '-' cannot be the
821 * last char of a multi-char operator unless the operator
822 * contains chars that are not in SQL operators.
823 * The idea is to lex '=-' as two operators, but not
824 * to forbid operator names like '?-' that could not be
825 * sequences of SQL operators.
826 */
827 if (nchars > 1 &&
828 (yytext[nchars - 1] == '+' ||
829 yytext[nchars - 1] == '-'))
830 {
831 int ic;
832
833 for (ic = nchars - 2; ic >= 0; ic--)
834 {
836 if (
c ==
'~' ||
c ==
'!' ||
c ==
'@' ||
837 c ==
'#' ||
c ==
'^' ||
c ==
'&' ||
838 c ==
'|' ||
c ==
'`' ||
c ==
'?' ||
840 break;
841 }
842 if (ic < 0)
843 {
844 /*
845 * didn't find a qualifying character, so remove
846 * all trailing [+-]
847 */
848 do {
849 nchars--;
850 } while (nchars > 1 &&
851 (yytext[nchars - 1] == '+' ||
852 yytext[nchars - 1] == '-'));
853 }
854 }
855
857 {
858 /* Strip the unwanted chars from the token */
859 yyless(nchars);
860 }
862 }
863
864{param} {
866 }
867{param_junk} {
869 }
870
871{decinteger} {
873 }
874{hexinteger} {
876 }
877{octinteger} {
879 }
880{bininteger} {
882 }
883{hexfail} {
885 }
886{octfail} {
888 }
889{binfail} {
891 }
892{numeric} {
894 }
895{numericfail} {
896 /* throw back the .., and treat as integer */
899 }
900{real} {
902 }
903{realfail} {
905 }
906{integer_junk} {
908 }
909{numeric_junk} {
911 }
912{real_junk} {
914 }
915
916
917{identifier} {
918 /*
919 * We need to track if we are inside a BEGIN .. END block
920 * in a function definition, so that semicolons contained
921 * therein don't terminate the whole statement. Short of
922 * writing a full parser here, the following heuristic
923 * should work. First, we track whether the beginning of
924 * the statement matches CREATE [OR REPLACE]
925 * {FUNCTION|PROCEDURE}
926 */
927
928 if (cur_state->identifier_count == 0)
929 memset(cur_state->identifiers, 0, sizeof(cur_state->identifiers));
930
936 {
937 if (cur_state->identifier_count < sizeof(cur_state->identifiers))
938 cur_state->identifiers[cur_state->identifier_count] =
pg_tolower((
unsigned char) yytext[0]);
939 }
int pg_strcasecmp(const char *s1, const char *s2)
unsigned char pg_tolower(unsigned char ch)
940
941 cur_state->identifier_count++;
942
943 if (cur_state->identifiers[0] == 'c' &&
944 (cur_state->identifiers[1] == 'f' || cur_state->identifiers[1] == 'p' ||
945 (cur_state->identifiers[1] == 'o' && cur_state->identifiers[2] == 'r' &&
946 (cur_state->identifiers[3] == 'f' || cur_state->identifiers[3] == 'p'))) &&
947 cur_state->paren_depth == 0)
948 {
950 cur_state->begin_depth++;
952 {
953 /*
954 * CASE also ends with END. We only need to track
955 * this if we are already inside a BEGIN.
956 */
957 if (cur_state->begin_depth >= 1)
958 cur_state->begin_depth++;
959 }
961 {
962 if (cur_state->begin_depth > 0)
963 cur_state->begin_depth--;
964 }
965 }
966
968 }
969
970{other} {
972 }
973
974<<EOF>> {
975 if (cur_state->buffer_stack == NULL)
976 {
977 cur_state->start_state = YY_START;
979 }
980
981 /*
982 * We were expanding a variable, so pop the inclusion
983 * stack and keep lexing
984 */
987 }
void psqlscan_select_top_buffer(PsqlScanState state)
988
989%%