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