LCOV - code coverage report
Current view: top level - src/fe_utils - conditional.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 49 61 80.3 %
Date: 2019-11-13 22:07:24 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-2019, 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        3356 : conditional_stack_create(void)
      19             : {
      20        3356 :     ConditionalStack cstack = pg_malloc(sizeof(ConditionalStackData));
      21             : 
      22        3356 :     cstack->head = NULL;
      23        3356 :     return cstack;
      24             : }
      25             : 
      26             : /*
      27             :  * destroy stack
      28             :  */
      29             : void
      30        3204 : conditional_stack_destroy(ConditionalStack cstack)
      31             : {
      32        6416 :     while (conditional_stack_pop(cstack))
      33           8 :         continue;
      34        3204 :     free(cstack);
      35        3204 : }
      36             : 
      37             : /*
      38             :  * Create a new conditional branch.
      39             :  */
      40             : void
      41        5068 : conditional_stack_push(ConditionalStack cstack, ifState new_state)
      42             : {
      43        5068 :     IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
      44             : 
      45        5068 :     p->if_state = new_state;
      46        5068 :     p->query_len = -1;
      47        5068 :     p->paren_depth = -1;
      48        5068 :     p->next = cstack->head;
      49        5068 :     cstack->head = p;
      50        5068 : }
      51             : 
      52             : /*
      53             :  * Destroy the topmost conditional branch.
      54             :  * Returns false if there was no branch to end.
      55             :  */
      56             : bool
      57        8268 : conditional_stack_pop(ConditionalStack cstack)
      58             : {
      59        8268 :     IfStackElem *p = cstack->head;
      60             : 
      61        8268 :     if (!p)
      62        3206 :         return false;
      63        5062 :     cstack->head = cstack->head->next;
      64        5062 :     free(p);
      65        5062 :     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      166440 : conditional_stack_peek(ConditionalStack cstack)
      95             : {
      96      166440 :     if (conditional_stack_empty(cstack))
      97      165000 :         return IFSTATE_NONE;
      98        1440 :     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         164 : conditional_stack_poke(ConditionalStack cstack, ifState new_state)
     107             : {
     108         164 :     if (conditional_stack_empty(cstack))
     109           0 :         return false;
     110         164 :     cstack->head->if_state = new_state;
     111         164 :     return true;
     112             : }
     113             : 
     114             : /*
     115             :  * True if there are no active \if-blocks.
     116             :  */
     117             : bool
     118      170012 : conditional_stack_empty(ConditionalStack cstack)
     119             : {
     120      170012 :     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      166192 : conditional_active(ConditionalStack cstack)
     129             : {
     130      166192 :     ifState     s = conditional_stack_peek(cstack);
     131             : 
     132      166192 :     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         128 : conditional_stack_set_query_len(ConditionalStack cstack, int len)
     140             : {
     141             :     Assert(!conditional_stack_empty(cstack));
     142         128 :     cstack->head->query_len = len;
     143         128 : }
     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         104 : conditional_stack_get_query_len(ConditionalStack cstack)
     151             : {
     152         104 :     if (conditional_stack_empty(cstack))
     153           0 :         return -1;
     154         104 :     return cstack->head->query_len;
     155             : }
     156             : 
     157             : /*
     158             :  * Save current parenthesis nesting depth in topmost stack entry.
     159             :  */
     160             : void
     161         128 : conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
     162             : {
     163             :     Assert(!conditional_stack_empty(cstack));
     164         128 :     cstack->head->paren_depth = depth;
     165         128 : }
     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         104 : conditional_stack_get_paren_depth(ConditionalStack cstack)
     173             : {
     174         104 :     if (conditional_stack_empty(cstack))
     175           0 :         return -1;
     176         104 :     return cstack->head->paren_depth;
     177             : }

Generated by: LCOV version 1.13