Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : * A stack of automaton states to handle nested conditionals.
3 : : *
4 : : * Copyright (c) 2000-2024, PostgreSQL Global Development Group
5 : : *
6 : : * src/fe_utils/conditional.c
7 : : *
8 : : *-------------------------------------------------------------------------
9 : : */
10 : : #include "postgres_fe.h"
11 : :
12 : : #include "fe_utils/conditional.h"
13 : :
14 : : /*
15 : : * create stack
16 : : */
17 : : ConditionalStack
2572 tgl@sss.pgh.pa.us 18 :CBC 8073 : conditional_stack_create(void)
19 : : {
20 : 8073 : ConditionalStack cstack = pg_malloc(sizeof(ConditionalStackData));
21 : :
22 : 8073 : cstack->head = NULL;
23 : 8073 : return cstack;
24 : : }
25 : :
26 : : /*
27 : : * Destroy all the elements from the stack. The stack itself is not freed.
28 : : */
29 : : void
753 ishii@postgresql.org 30 : 7945 : conditional_stack_reset(ConditionalStack cstack)
2572 tgl@sss.pgh.pa.us 31 : 6 : {
753 ishii@postgresql.org 32 [ - + ]: 7945 : if (!cstack)
753 ishii@postgresql.org 33 :UBC 0 : return; /* nothing to do here */
34 : :
2572 tgl@sss.pgh.pa.us 35 [ + + ]:CBC 7951 : while (conditional_stack_pop(cstack))
36 : 6 : continue;
37 : : }
38 : :
39 : : /*
40 : : * destroy stack
41 : : */
42 : : void
753 ishii@postgresql.org 43 : 7943 : conditional_stack_destroy(ConditionalStack cstack)
44 : : {
45 : 7943 : conditional_stack_reset(cstack);
2572 tgl@sss.pgh.pa.us 46 : 7943 : free(cstack);
47 : 7943 : }
48 : :
49 : : /*
50 : : * Create a new conditional branch.
51 : : */
52 : : void
53 : 6589 : conditional_stack_push(ConditionalStack cstack, ifState new_state)
54 : : {
55 : 6589 : IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
56 : :
57 : 6589 : p->if_state = new_state;
58 : 6589 : p->query_len = -1;
59 : 6589 : p->paren_depth = -1;
60 : 6589 : p->next = cstack->head;
61 : 6589 : cstack->head = p;
62 : 6589 : }
63 : :
64 : : /*
65 : : * Destroy the topmost conditional branch.
66 : : * Returns false if there was no branch to end.
67 : : */
68 : : bool
69 : 14531 : conditional_stack_pop(ConditionalStack cstack)
70 : : {
71 : 14531 : IfStackElem *p = cstack->head;
72 : :
73 [ + + ]: 14531 : if (!p)
74 : 7946 : return false;
75 : 6585 : cstack->head = cstack->head->next;
76 : 6585 : free(p);
77 : 6585 : return true;
78 : : }
79 : :
80 : : /*
81 : : * Returns current stack depth, for debugging purposes.
82 : : */
83 : : int
2215 teodor@sigaev.ru 84 :UBC 0 : conditional_stack_depth(ConditionalStack cstack)
85 : : {
86 [ # # ]: 0 : if (cstack == NULL)
87 : 0 : return -1;
88 : : else
89 : : {
2180 tgl@sss.pgh.pa.us 90 : 0 : IfStackElem *p = cstack->head;
2215 teodor@sigaev.ru 91 : 0 : int depth = 0;
92 : :
93 [ # # ]: 0 : while (p != NULL)
94 : : {
95 : 0 : depth++;
96 : 0 : p = p->next;
97 : : }
98 : 0 : return depth;
99 : : }
100 : : }
101 : :
102 : : /*
103 : : * Fetch the current state of the top of the stack.
104 : : */
105 : : ifState
2572 tgl@sss.pgh.pa.us 106 :CBC 187931 : conditional_stack_peek(ConditionalStack cstack)
107 : : {
108 [ + + ]: 187931 : if (conditional_stack_empty(cstack))
109 : 185361 : return IFSTATE_NONE;
110 : 2570 : return cstack->head->if_state;
111 : : }
112 : :
113 : : /*
114 : : * Change the state of the topmost branch.
115 : : * Returns false if there was no branch state to set.
116 : : */
117 : : bool
118 : 146 : conditional_stack_poke(ConditionalStack cstack, ifState new_state)
119 : : {
120 [ - + ]: 146 : if (conditional_stack_empty(cstack))
2572 tgl@sss.pgh.pa.us 121 :UBC 0 : return false;
2572 tgl@sss.pgh.pa.us 122 :CBC 146 : cstack->head->if_state = new_state;
123 : 146 : return true;
124 : : }
125 : :
126 : : /*
127 : : * True if there are no active \if-blocks.
128 : : */
129 : : bool
130 : 211728 : conditional_stack_empty(ConditionalStack cstack)
131 : : {
132 : 211728 : return cstack->head == NULL;
133 : : }
134 : :
135 : : /*
136 : : * True if we should execute commands normally; that is, the current
137 : : * conditional branch is active, or there is no open \if block.
138 : : */
139 : : bool
140 : 187349 : conditional_active(ConditionalStack cstack)
141 : : {
142 : 187349 : ifState s = conditional_stack_peek(cstack);
143 : :
144 [ + + + + : 187349 : return s == IFSTATE_NONE || s == IFSTATE_TRUE || s == IFSTATE_ELSE_TRUE;
+ + ]
145 : : }
146 : :
147 : : /*
148 : : * Save current query buffer length in topmost stack entry.
149 : : */
150 : : void
151 : 122 : conditional_stack_set_query_len(ConditionalStack cstack, int len)
152 : : {
153 [ - + ]: 122 : Assert(!conditional_stack_empty(cstack));
154 : 122 : cstack->head->query_len = len;
155 : 122 : }
156 : :
157 : : /*
158 : : * Fetch last-recorded query buffer length from topmost stack entry.
159 : : * Will return -1 if no stack or it was never saved.
160 : : */
161 : : int
162 : 104 : conditional_stack_get_query_len(ConditionalStack cstack)
163 : : {
164 [ - + ]: 104 : if (conditional_stack_empty(cstack))
2572 tgl@sss.pgh.pa.us 165 :UBC 0 : return -1;
2572 tgl@sss.pgh.pa.us 166 :CBC 104 : return cstack->head->query_len;
167 : : }
168 : :
169 : : /*
170 : : * Save current parenthesis nesting depth in topmost stack entry.
171 : : */
172 : : void
173 : 122 : conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
174 : : {
175 [ - + ]: 122 : Assert(!conditional_stack_empty(cstack));
176 : 122 : cstack->head->paren_depth = depth;
177 : 122 : }
178 : :
179 : : /*
180 : : * Fetch last-recorded parenthesis nesting depth from topmost stack entry.
181 : : * Will return -1 if no stack or it was never saved.
182 : : */
183 : : int
184 : 104 : conditional_stack_get_paren_depth(ConditionalStack cstack)
185 : : {
186 [ - + ]: 104 : if (conditional_stack_empty(cstack))
2572 tgl@sss.pgh.pa.us 187 :UBC 0 : return -1;
2572 tgl@sss.pgh.pa.us 188 :CBC 104 : return cstack->head->paren_depth;
189 : : }
|