LCOV - code coverage report
Current view: top level - src/fe_utils - conditional.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 49 61 80.3 %
Date: 2020-05-31 23:07:13 Functions: 12 13 92.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13