/
githubmirror
/
postgres
Обзор
Документация
Войти
/
githubmirror
/
postgres
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/fe_utils/conditional.c
197 строк
4 KB
Tom Lane
Save/restore more lexer state when skipping text due to \if.
10 авг 2026, 16:37
10 авг 2026, 16:37
cf754f7
Код
Авторство
О чём код?
/*------------------------------------------------------------------------- * A stack of automaton states to handle nested conditionals. * * Copyright (c) 2000-2026, PostgreSQL Global Development Group * * src/fe_utils/conditional.c * *------------------------------------------------------------------------- */ #include "postgres_fe.h" #include "fe_utils/conditional.h" /* * create stack */ ConditionalStack conditional_stack_create(void) { ConditionalStack cstack = pg_malloc_object(ConditionalStackData); cstack->head = NULL; return cstack; } /* * Destroy all the elements from the stack. The stack itself is not freed. */ void conditional_stack_reset(ConditionalStack cstack) { if (!cstack) return; /* nothing to do here */ while (conditional_stack_pop(cstack)) continue; } /* * destroy stack */ void conditional_stack_destroy(ConditionalStack cstack) { conditional_stack_reset(cstack); free(cstack); } /* * Create a new conditional branch. */ void conditional_stack_push(ConditionalStack cstack, ifState new_state) { IfStackElem *p = pg_malloc_object(IfStackElem); p->if_state = new_state; p->query_len = -1; p->lex_state = NULL; p->next = cstack->head; cstack->head = p; } /* * Destroy the topmost conditional branch. * Returns false if there was no branch to end. */ bool conditional_stack_pop(ConditionalStack cstack) { IfStackElem *p = cstack->head; if (!p) return false; cstack->head = cstack->head->next; if (p->lex_state) free(p->lex_state); free(p); return true; } /* * Returns current stack depth, for debugging purposes. */ int conditional_stack_depth(ConditionalStack cstack) { if (cstack == NULL) return -1; else { IfStackElem *p = cstack->head; int depth = 0; while (p != NULL) { depth++; p = p->next; } return depth; } } /* * Fetch the current state of the top of the stack. */ ifState conditional_stack_peek(ConditionalStack cstack) { if (conditional_stack_empty(cstack)) return IFSTATE_NONE; return cstack->head->if_state; } /* * Change the state of the topmost branch. * Returns false if there was no branch state to set. */ bool conditional_stack_poke(ConditionalStack cstack, ifState new_state) { if (conditional_stack_empty(cstack)) return false; cstack->head->if_state = new_state; return true; } /* * True if there are no active \if-blocks. */ bool conditional_stack_empty(ConditionalStack cstack) { return cstack->head == NULL; } /* * True if we should execute commands normally; that is, the current * conditional branch is active, or there is no open \if block. */ bool conditional_active(ConditionalStack cstack) { ifState s = conditional_stack_peek(cstack); return s == IFSTATE_NONE || s == IFSTATE_TRUE || s == IFSTATE_ELSE_TRUE; } /* * Save current query buffer length in topmost stack entry. */ void conditional_stack_set_query_len(ConditionalStack cstack, int len) { Assert(!conditional_stack_empty(cstack)); cstack->head->query_len = len; } /* * Fetch last-recorded query buffer length from topmost stack entry. * Will return -1 if no stack or it was never saved. */ int conditional_stack_get_query_len(ConditionalStack cstack) { if (conditional_stack_empty(cstack)) return -1; return cstack->head->query_len; } /* * Save current lexer state in topmost stack entry. * * The lexer state is presumed to be a single pg_malloc'd chunk. * It will be freed automatically when the stack entry is popped. */ void conditional_stack_set_lex_state(ConditionalStack cstack, PsqlScanStateSave *lex_state) { Assert(!conditional_stack_empty(cstack)); if (cstack->head->lex_state) /* free old state, if any */ free(cstack->head->lex_state); cstack->head->lex_state = lex_state; } /* * Fetch last-recorded lexer state from topmost stack entry. * Will return NULL if no stack or it was never saved. */ PsqlScanStateSave * conditional_stack_get_lex_state(ConditionalStack cstack) { if (conditional_stack_empty(cstack)) return NULL; return cstack->head->lex_state; }