conditional.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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-2022, 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. * Possible states of a single level of \if block.
  27. */
  28. typedef enum ifState
  29. {
  30. IFSTATE_NONE = 0, /* not currently in an \if block */
  31. IFSTATE_TRUE, /* currently in an \if or \elif that is true
  32. * and all parent branches (if any) are true */
  33. IFSTATE_FALSE, /* currently in an \if or \elif that is false
  34. * but no true branch has yet been seen, and
  35. * all parent branches (if any) are true */
  36. IFSTATE_IGNORED, /* currently in an \elif that follows a true
  37. * branch, or the whole \if is a child of a
  38. * false parent branch */
  39. IFSTATE_ELSE_TRUE, /* currently in an \else that is true and all
  40. * parent branches (if any) are true */
  41. IFSTATE_ELSE_FALSE /* currently in an \else that is false or
  42. * ignored */
  43. } ifState;
  44. /*
  45. * The state of nested \ifs is stored in a stack.
  46. *
  47. * query_len is used to determine what accumulated text to throw away at the
  48. * end of an inactive branch. (We could, perhaps, teach the lexer to not add
  49. * stuff to the query buffer in the first place when inside an inactive branch;
  50. * but that would be very invasive.) We also need to save and restore the
  51. * lexer's parenthesis nesting depth when throwing away text. (We don't need
  52. * to save and restore any of its other state, such as comment nesting depth,
  53. * because a backslash command could never appear inside a comment or SQL
  54. * literal.)
  55. */
  56. typedef struct IfStackElem
  57. {
  58. ifState if_state; /* current state, see enum above */
  59. int query_len; /* length of query_buf at last branch start */
  60. int paren_depth; /* parenthesis depth at last branch start */
  61. struct IfStackElem *next; /* next surrounding \if, if any */
  62. } IfStackElem;
  63. typedef struct ConditionalStackData
  64. {
  65. IfStackElem *head;
  66. } ConditionalStackData;
  67. typedef struct ConditionalStackData *ConditionalStack;
  68. extern ConditionalStack conditional_stack_create(void);
  69. extern void conditional_stack_reset(ConditionalStack cstack);
  70. extern void conditional_stack_destroy(ConditionalStack cstack);
  71. extern int conditional_stack_depth(ConditionalStack cstack);
  72. extern void conditional_stack_push(ConditionalStack cstack, ifState new_state);
  73. extern bool conditional_stack_pop(ConditionalStack cstack);
  74. extern ifState conditional_stack_peek(ConditionalStack cstack);
  75. extern bool conditional_stack_poke(ConditionalStack cstack, ifState new_state);
  76. extern bool conditional_stack_empty(ConditionalStack cstack);
  77. extern bool conditional_active(ConditionalStack cstack);
  78. extern void conditional_stack_set_query_len(ConditionalStack cstack, int len);
  79. extern int conditional_stack_get_query_len(ConditionalStack cstack);
  80. extern void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth);
  81. extern int conditional_stack_get_paren_depth(ConditionalStack cstack);
  82. #endif /* CONDITIONAL_H */