1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2017, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/conditional.h
7  */
8 #ifndef CONDITIONAL_H
9 #define CONDITIONAL_H
10 
11 /*
12  * Possible states of a single level of \if block.
13  */
14 typedef enum ifState
15 {
16 	IFSTATE_NONE = 0,			/* not currently in an \if block */
17 	IFSTATE_TRUE,				/* currently in an \if or \elif that is true
18 								 * and all parent branches (if any) are true */
19 	IFSTATE_FALSE,				/* currently in an \if or \elif that is false
20 								 * but no true branch has yet been seen, and
21 								 * all parent branches (if any) are true */
22 	IFSTATE_IGNORED,			/* currently in an \elif that follows a true
23 								 * branch, or the whole \if is a child of a
24 								 * false parent branch */
25 	IFSTATE_ELSE_TRUE,			/* currently in an \else that is true and all
26 								 * parent branches (if any) are true */
27 	IFSTATE_ELSE_FALSE			/* currently in an \else that is false or
28 								 * ignored */
29 } ifState;
30 
31 /*
32  * The state of nested \ifs is stored in a stack.
33  *
34  * query_len is used to determine what accumulated text to throw away at the
35  * end of an inactive branch.  (We could, perhaps, teach the lexer to not add
36  * stuff to the query buffer in the first place when inside an inactive branch;
37  * but that would be very invasive.)  We also need to save and restore the
38  * lexer's parenthesis nesting depth when throwing away text.  (We don't need
39  * to save and restore any of its other state, such as comment nesting depth,
40  * because a backslash command could never appear inside a comment or SQL
41  * literal.)
42  */
43 typedef struct IfStackElem
44 {
45 	ifState		if_state;		/* current state, see enum above */
46 	int			query_len;		/* length of query_buf at last branch start */
47 	int			paren_depth;	/* parenthesis depth at last branch start */
48 	struct IfStackElem *next;	/* next surrounding \if, if any */
49 } IfStackElem;
50 
51 typedef struct ConditionalStackData
52 {
53 	IfStackElem *head;
54 }			ConditionalStackData;
55 
56 typedef struct ConditionalStackData *ConditionalStack;
57 
58 
59 extern ConditionalStack conditional_stack_create(void);
60 
61 extern void conditional_stack_destroy(ConditionalStack cstack);
62 
63 extern void conditional_stack_push(ConditionalStack cstack, ifState new_state);
64 
65 extern bool conditional_stack_pop(ConditionalStack cstack);
66 
67 extern ifState conditional_stack_peek(ConditionalStack cstack);
68 
69 extern bool conditional_stack_poke(ConditionalStack cstack, ifState new_state);
70 
71 extern bool conditional_stack_empty(ConditionalStack cstack);
72 
73 extern bool conditional_active(ConditionalStack cstack);
74 
75 extern void conditional_stack_set_query_len(ConditionalStack cstack, int len);
76 
77 extern int	conditional_stack_get_query_len(ConditionalStack cstack);
78 
79 extern void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth);
80 
81 extern int	conditional_stack_get_paren_depth(ConditionalStack cstack);
82 
83 #endif							/* CONDITIONAL_H */
84