PostgreSQL Source Code  git master
conditional.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  * A stack of automaton states to handle nested conditionals.
3  *
4  * This file describes a stack of automaton states which
5  * allow a manage nested conditionals.
6  *
7  * It is used by:
8  * - "psql" interpreter for handling \if ... \endif
9  * - "pgbench" interpreter for handling \if ... \endif
10  * - "pgbench" syntax checker to test for proper nesting
11  *
12  * The stack holds the state of enclosing conditionals (are we in
13  * a true branch? in a false branch? have we already encountered
14  * a true branch?) so that the interpreter knows whether to execute
15  * code and whether to evaluate conditions.
16  *
17  * Copyright (c) 2000-2019, PostgreSQL Global Development Group
18  *
19  * src/include/fe_utils/conditional.h
20  *
21  *-------------------------------------------------------------------------
22  */
23 #ifndef CONDITIONAL_H
24 #define CONDITIONAL_H
25 
26 /*
27  * Possible states of a single level of \if block.
28  */
29 typedef enum ifState
30 {
31  IFSTATE_NONE = 0, /* not currently in an \if block */
32  IFSTATE_TRUE, /* currently in an \if or \elif that is true
33  * and all parent branches (if any) are true */
34  IFSTATE_FALSE, /* currently in an \if or \elif that is false
35  * but no true branch has yet been seen, and
36  * all parent branches (if any) are true */
37  IFSTATE_IGNORED, /* currently in an \elif that follows a true
38  * branch, or the whole \if is a child of a
39  * false parent branch */
40  IFSTATE_ELSE_TRUE, /* currently in an \else that is true and all
41  * parent branches (if any) are true */
42  IFSTATE_ELSE_FALSE /* currently in an \else that is false or
43  * ignored */
44 } ifState;
45 
46 /*
47  * The state of nested \ifs is stored in a stack.
48  *
49  * query_len is used to determine what accumulated text to throw away at the
50  * end of an inactive branch. (We could, perhaps, teach the lexer to not add
51  * stuff to the query buffer in the first place when inside an inactive branch;
52  * but that would be very invasive.) We also need to save and restore the
53  * lexer's parenthesis nesting depth when throwing away text. (We don't need
54  * to save and restore any of its other state, such as comment nesting depth,
55  * because a backslash command could never appear inside a comment or SQL
56  * literal.)
57  */
58 typedef struct IfStackElem
59 {
60  ifState if_state; /* current state, see enum above */
61  int query_len; /* length of query_buf at last branch start */
62  int paren_depth; /* parenthesis depth at last branch start */
63  struct IfStackElem *next; /* next surrounding \if, if any */
64 } IfStackElem;
65 
66 typedef struct ConditionalStackData
67 {
70 
72 
73 
74 extern ConditionalStack conditional_stack_create(void);
75 
76 extern void conditional_stack_destroy(ConditionalStack cstack);
77 
78 extern int conditional_stack_depth(ConditionalStack cstack);
79 
80 extern void conditional_stack_push(ConditionalStack cstack, ifState new_state);
81 
82 extern bool conditional_stack_pop(ConditionalStack cstack);
83 
84 extern ifState conditional_stack_peek(ConditionalStack cstack);
85 
86 extern bool conditional_stack_poke(ConditionalStack cstack, ifState new_state);
87 
88 extern bool conditional_stack_empty(ConditionalStack cstack);
89 
90 extern bool conditional_active(ConditionalStack cstack);
91 
92 extern void conditional_stack_set_query_len(ConditionalStack cstack, int len);
93 
94 extern int conditional_stack_get_query_len(ConditionalStack cstack);
95 
96 extern void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth);
97 
98 extern int conditional_stack_get_paren_depth(ConditionalStack cstack);
99 
100 #endif /* CONDITIONAL_H */
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:106
int conditional_stack_depth(ConditionalStack cstack)
Definition: conditional.c:72
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:57
ifState
Definition: conditional.h:29
IfStackElem * head
Definition: conditional.h:68
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:30
struct IfStackElem IfStackElem
int conditional_stack_get_paren_depth(ConditionalStack cstack)
Definition: conditional.c:172
void conditional_stack_set_query_len(ConditionalStack cstack, int len)
Definition: conditional.c:139
void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
Definition: conditional.c:161
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:94
int paren_depth
Definition: conditional.h:62
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
ifState if_state
Definition: conditional.h:60
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:41
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:118
struct ConditionalStackData * ConditionalStack
Definition: conditional.h:71
struct ConditionalStackData ConditionalStackData
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:128
struct IfStackElem * next
Definition: conditional.h:63
int conditional_stack_get_query_len(ConditionalStack cstack)
Definition: conditional.c:150