Line data Source code
1 : /*
2 : * psql - the PostgreSQL interactive terminal
3 : *
4 : * Copyright (c) 2000-2017, PostgreSQL Global Development Group
5 : *
6 : * src/bin/psql/conditional.c
7 : */
8 : #include "postgres_fe.h"
9 :
10 : #include "conditional.h"
11 :
12 : /*
13 : * create stack
14 : */
15 : ConditionalStack
16 180 : conditional_stack_create(void)
17 : {
18 180 : ConditionalStack cstack = pg_malloc(sizeof(ConditionalStackData));
19 :
20 180 : cstack->head = NULL;
21 180 : return cstack;
22 : }
23 :
24 : /*
25 : * destroy stack
26 : */
27 : void
28 180 : conditional_stack_destroy(ConditionalStack cstack)
29 : {
30 360 : while (conditional_stack_pop(cstack))
31 0 : continue;
32 180 : free(cstack);
33 180 : }
34 :
35 : /*
36 : * Create a new conditional branch.
37 : */
38 : void
39 789 : conditional_stack_push(ConditionalStack cstack, ifState new_state)
40 : {
41 789 : IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
42 :
43 789 : p->if_state = new_state;
44 789 : p->query_len = -1;
45 789 : p->paren_depth = -1;
46 789 : p->next = cstack->head;
47 789 : cstack->head = p;
48 789 : }
49 :
50 : /*
51 : * Destroy the topmost conditional branch.
52 : * Returns false if there was no branch to end.
53 : */
54 : bool
55 969 : conditional_stack_pop(ConditionalStack cstack)
56 : {
57 969 : IfStackElem *p = cstack->head;
58 :
59 969 : if (!p)
60 180 : return false;
61 789 : cstack->head = cstack->head->next;
62 789 : free(p);
63 789 : return true;
64 : }
65 :
66 : /*
67 : * Fetch the current state of the top of the stack.
68 : */
69 : ifState
70 25980 : conditional_stack_peek(ConditionalStack cstack)
71 : {
72 25980 : if (conditional_stack_empty(cstack))
73 25712 : return IFSTATE_NONE;
74 268 : return cstack->head->if_state;
75 : }
76 :
77 : /*
78 : * Change the state of the topmost branch.
79 : * Returns false if there was no branch state to set.
80 : */
81 : bool
82 30 : conditional_stack_poke(ConditionalStack cstack, ifState new_state)
83 : {
84 30 : if (conditional_stack_empty(cstack))
85 0 : return false;
86 30 : cstack->head->if_state = new_state;
87 30 : return true;
88 : }
89 :
90 : /*
91 : * True if there are no active \if-blocks.
92 : */
93 : bool
94 26282 : conditional_stack_empty(ConditionalStack cstack)
95 : {
96 26282 : return cstack->head == NULL;
97 : }
98 :
99 : /*
100 : * True if we should execute commands normally; that is, the current
101 : * conditional branch is active, or there is no open \if block.
102 : */
103 : bool
104 25939 : conditional_active(ConditionalStack cstack)
105 : {
106 25939 : ifState s = conditional_stack_peek(cstack);
107 :
108 25939 : return s == IFSTATE_NONE || s == IFSTATE_TRUE || s == IFSTATE_ELSE_TRUE;
109 : }
110 :
111 : /*
112 : * Save current query buffer length in topmost stack entry.
113 : */
114 : void
115 25 : conditional_stack_set_query_len(ConditionalStack cstack, int len)
116 : {
117 25 : Assert(!conditional_stack_empty(cstack));
118 25 : cstack->head->query_len = len;
119 25 : }
120 :
121 : /*
122 : * Fetch last-recorded query buffer length from topmost stack entry.
123 : * Will return -1 if no stack or it was never saved.
124 : */
125 : int
126 21 : conditional_stack_get_query_len(ConditionalStack cstack)
127 : {
128 21 : if (conditional_stack_empty(cstack))
129 0 : return -1;
130 21 : return cstack->head->query_len;
131 : }
132 :
133 : /*
134 : * Save current parenthesis nesting depth in topmost stack entry.
135 : */
136 : void
137 25 : conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
138 : {
139 25 : Assert(!conditional_stack_empty(cstack));
140 25 : cstack->head->paren_depth = depth;
141 25 : }
142 :
143 : /*
144 : * Fetch last-recorded parenthesis nesting depth from topmost stack entry.
145 : * Will return -1 if no stack or it was never saved.
146 : */
147 : int
148 21 : conditional_stack_get_paren_depth(ConditionalStack cstack)
149 : {
150 21 : if (conditional_stack_empty(cstack))
151 0 : return -1;
152 21 : return cstack->head->paren_depth;
153 : }
|