PostgreSQL Source Code  git master
conditional.c
Go to the documentation of this file.
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  */
19 {
21 
22  cstack->head = NULL;
23  return cstack;
24 }
25 
26 /*
27  * Destroy all the elements from the stack. The stack itself is not freed.
28  */
29 void
31 {
32  if (!cstack)
33  return; /* nothing to do here */
34 
35  while (conditional_stack_pop(cstack))
36  continue;
37 }
38 
39 /*
40  * destroy stack
41  */
42 void
44 {
46  free(cstack);
47 }
48 
49 /*
50  * Create a new conditional branch.
51  */
52 void
54 {
55  IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
56 
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;
62 }
63 
64 /*
65  * Destroy the topmost conditional branch.
66  * Returns false if there was no branch to end.
67  */
68 bool
70 {
71  IfStackElem *p = cstack->head;
72 
73  if (!p)
74  return false;
75  cstack->head = cstack->head->next;
76  free(p);
77  return true;
78 }
79 
80 /*
81  * Returns current stack depth, for debugging purposes.
82  */
83 int
85 {
86  if (cstack == NULL)
87  return -1;
88  else
89  {
90  IfStackElem *p = cstack->head;
91  int depth = 0;
92 
93  while (p != NULL)
94  {
95  depth++;
96  p = p->next;
97  }
98  return depth;
99  }
100 }
101 
102 /*
103  * Fetch the current state of the top of the stack.
104  */
105 ifState
107 {
108  if (conditional_stack_empty(cstack))
109  return IFSTATE_NONE;
110  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
119 {
120  if (conditional_stack_empty(cstack))
121  return false;
122  cstack->head->if_state = new_state;
123  return true;
124 }
125 
126 /*
127  * True if there are no active \if-blocks.
128  */
129 bool
131 {
132  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
141 {
142  ifState s = conditional_stack_peek(cstack);
143 
144  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
152 {
154  cstack->head->query_len = len;
155 }
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
163 {
164  if (conditional_stack_empty(cstack))
165  return -1;
166  return cstack->head->query_len;
167 }
168 
169 /*
170  * Save current parenthesis nesting depth in topmost stack entry.
171  */
172 void
174 {
176  cstack->head->paren_depth = depth;
177 }
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
185 {
186  if (conditional_stack_empty(cstack))
187  return -1;
188  return cstack->head->paren_depth;
189 }
void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
Definition: conditional.c:173
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:106
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:53
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
int conditional_stack_depth(ConditionalStack cstack)
Definition: conditional.c:84
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:69
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:43
void conditional_stack_set_query_len(ConditionalStack cstack, int len)
Definition: conditional.c:151
int conditional_stack_get_query_len(ConditionalStack cstack)
Definition: conditional.c:162
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:140
void conditional_stack_reset(ConditionalStack cstack)
Definition: conditional.c:30
int conditional_stack_get_paren_depth(ConditionalStack cstack)
Definition: conditional.c:184
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:118
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:130
ifState
Definition: conditional.h:30
@ IFSTATE_ELSE_TRUE
Definition: conditional.h:40
@ IFSTATE_TRUE
Definition: conditional.h:32
@ IFSTATE_NONE
Definition: conditional.h:31
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define free(a)
Definition: header.h:65
Assert(fmt[strlen(fmt) - 1] !='\n')
const void size_t len
IfStackElem * head
Definition: conditional.h:68
struct IfStackElem * next
Definition: conditional.h:63
int paren_depth
Definition: conditional.h:62
ifState if_state
Definition: conditional.h:60