doc: clarify that pg_global can _only_ be used for system tabs.
[pgsql.git] / src / fe_utils / conditional.c
blobe67fb0dbe8cc211aeb210c7c5c38f591e93e3dfe
1 /*-------------------------------------------------------------------------
2 * A stack of automaton states to handle nested conditionals.
4 * Copyright (c) 2000-2023, PostgreSQL Global Development Group
6 * src/fe_utils/conditional.c
8 *-------------------------------------------------------------------------
9 */
10 #include "postgres_fe.h"
12 #include "fe_utils/conditional.h"
15 * create stack
17 ConditionalStack
18 conditional_stack_create(void)
20 ConditionalStack cstack = pg_malloc(sizeof(ConditionalStackData));
22 cstack->head = NULL;
23 return cstack;
27 * Destroy all the elements from the stack. The stack itself is not freed.
29 void
30 conditional_stack_reset(ConditionalStack cstack)
32 if (!cstack)
33 return; /* nothing to do here */
35 while (conditional_stack_pop(cstack))
36 continue;
40 * destroy stack
42 void
43 conditional_stack_destroy(ConditionalStack cstack)
45 conditional_stack_reset(cstack);
46 free(cstack);
50 * Create a new conditional branch.
52 void
53 conditional_stack_push(ConditionalStack cstack, ifState new_state)
55 IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
57 p->if_state = new_state;
58 p->query_len = -1;
59 p->paren_depth = -1;
60 p->next = cstack->head;
61 cstack->head = p;
65 * Destroy the topmost conditional branch.
66 * Returns false if there was no branch to end.
68 bool
69 conditional_stack_pop(ConditionalStack cstack)
71 IfStackElem *p = cstack->head;
73 if (!p)
74 return false;
75 cstack->head = cstack->head->next;
76 free(p);
77 return true;
81 * Returns current stack depth, for debugging purposes.
83 int
84 conditional_stack_depth(ConditionalStack cstack)
86 if (cstack == NULL)
87 return -1;
88 else
90 IfStackElem *p = cstack->head;
91 int depth = 0;
93 while (p != NULL)
95 depth++;
96 p = p->next;
98 return depth;
103 * Fetch the current state of the top of the stack.
105 ifState
106 conditional_stack_peek(ConditionalStack cstack)
108 if (conditional_stack_empty(cstack))
109 return IFSTATE_NONE;
110 return cstack->head->if_state;
114 * Change the state of the topmost branch.
115 * Returns false if there was no branch state to set.
117 bool
118 conditional_stack_poke(ConditionalStack cstack, ifState new_state)
120 if (conditional_stack_empty(cstack))
121 return false;
122 cstack->head->if_state = new_state;
123 return true;
127 * True if there are no active \if-blocks.
129 bool
130 conditional_stack_empty(ConditionalStack cstack)
132 return cstack->head == NULL;
136 * True if we should execute commands normally; that is, the current
137 * conditional branch is active, or there is no open \if block.
139 bool
140 conditional_active(ConditionalStack cstack)
142 ifState s = conditional_stack_peek(cstack);
144 return s == IFSTATE_NONE || s == IFSTATE_TRUE || s == IFSTATE_ELSE_TRUE;
148 * Save current query buffer length in topmost stack entry.
150 void
151 conditional_stack_set_query_len(ConditionalStack cstack, int len)
153 Assert(!conditional_stack_empty(cstack));
154 cstack->head->query_len = len;
158 * Fetch last-recorded query buffer length from topmost stack entry.
159 * Will return -1 if no stack or it was never saved.
162 conditional_stack_get_query_len(ConditionalStack cstack)
164 if (conditional_stack_empty(cstack))
165 return -1;
166 return cstack->head->query_len;
170 * Save current parenthesis nesting depth in topmost stack entry.
172 void
173 conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
175 Assert(!conditional_stack_empty(cstack));
176 cstack->head->paren_depth = depth;
180 * Fetch last-recorded parenthesis nesting depth from topmost stack entry.
181 * Will return -1 if no stack or it was never saved.
184 conditional_stack_get_paren_depth(ConditionalStack cstack)
186 if (conditional_stack_empty(cstack))
187 return -1;
188 return cstack->head->paren_depth;