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-2019, 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 stack
28  */
29 void
31 {
32  while (conditional_stack_pop(cstack))
33  continue;
34  free(cstack);
35 }
36 
37 /*
38  * Create a new conditional branch.
39  */
40 void
42 {
43  IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
44 
45  p->if_state = new_state;
46  p->query_len = -1;
47  p->paren_depth = -1;
48  p->next = cstack->head;
49  cstack->head = p;
50 }
51 
52 /*
53  * Destroy the topmost conditional branch.
54  * Returns false if there was no branch to end.
55  */
56 bool
58 {
59  IfStackElem *p = cstack->head;
60 
61  if (!p)
62  return false;
63  cstack->head = cstack->head->next;
64  free(p);
65  return true;
66 }
67 
68 /*
69  * Returns current stack depth, for debugging purposes.
70  */
71 int
73 {
74  if (cstack == NULL)
75  return -1;
76  else
77  {
78  IfStackElem *p = cstack->head;
79  int depth = 0;
80 
81  while (p != NULL)
82  {
83  depth++;
84  p = p->next;
85  }
86  return depth;
87  }
88 }
89 
90 /*
91  * Fetch the current state of the top of the stack.
92  */
93 ifState
95 {
96  if (conditional_stack_empty(cstack))
97  return IFSTATE_NONE;
98  return cstack->head->if_state;
99 }
100 
101 /*
102  * Change the state of the topmost branch.
103  * Returns false if there was no branch state to set.
104  */
105 bool
107 {
108  if (conditional_stack_empty(cstack))
109  return false;
110  cstack->head->if_state = new_state;
111  return true;
112 }
113 
114 /*
115  * True if there are no active \if-blocks.
116  */
117 bool
119 {
120  return cstack->head == NULL;
121 }
122 
123 /*
124  * True if we should execute commands normally; that is, the current
125  * conditional branch is active, or there is no open \if block.
126  */
127 bool
129 {
130  ifState s = conditional_stack_peek(cstack);
131 
132  return s == IFSTATE_NONE || s == IFSTATE_TRUE || s == IFSTATE_ELSE_TRUE;
133 }
134 
135 /*
136  * Save current query buffer length in topmost stack entry.
137  */
138 void
140 {
142  cstack->head->query_len = len;
143 }
144 
145 /*
146  * Fetch last-recorded query buffer length from topmost stack entry.
147  * Will return -1 if no stack or it was never saved.
148  */
149 int
151 {
152  if (conditional_stack_empty(cstack))
153  return -1;
154  return cstack->head->query_len;
155 }
156 
157 /*
158  * Save current parenthesis nesting depth in topmost stack entry.
159  */
160 void
162 {
164  cstack->head->paren_depth = depth;
165 }
166 
167 /*
168  * Fetch last-recorded parenthesis nesting depth from topmost stack entry.
169  * Will return -1 if no stack or it was never saved.
170  */
171 int
173 {
174  if (conditional_stack_empty(cstack))
175  return -1;
176  return cstack->head->paren_depth;
177 }
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:128
void conditional_stack_set_query_len(ConditionalStack cstack, int len)
Definition: conditional.c:139
int conditional_stack_depth(ConditionalStack cstack)
Definition: conditional.c:72
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:57
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:41
int conditional_stack_get_query_len(ConditionalStack cstack)
Definition: conditional.c:150
void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
Definition: conditional.c:161
ifState
Definition: conditional.h:29
IfStackElem * head
Definition: conditional.h:68
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:94
#define free(a)
Definition: header.h:65
#define Assert(condition)
Definition: c.h:733
int paren_depth
Definition: conditional.h:62
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:106
ifState if_state
Definition: conditional.h:60
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:30
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:118
int conditional_stack_get_paren_depth(ConditionalStack cstack)
Definition: conditional.c:172
struct IfStackElem * next
Definition: conditional.h:63