LCOV - code coverage report
Current view: top level - src/tools/pg_bsd_indent - parse.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 88 122 72.1 %
Date: 2024-03-29 12:13:04 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 1985 Sun Microsystems, Inc.
       3             :  * Copyright (c) 1980, 1993
       4             :  *  The Regents of the University of California.  All rights reserved.
       5             :  * All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  * 3. Neither the name of the University nor the names of its contributors
      16             :  *    may be used to endorse or promote products derived from this software
      17             :  *    without specific prior written permission.
      18             :  *
      19             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      20             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      21             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      22             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      23             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      24             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      25             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      26             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      27             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      28             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      29             :  * SUCH DAMAGE.
      30             :  */
      31             : 
      32             : #if 0
      33             : #ifndef lint
      34             : static char sccsid[] = "@(#)parse.c    8.1 (Berkeley) 6/6/93";
      35             : #endif /* not lint */
      36             : #endif
      37             : 
      38             : #include "c.h"
      39             : 
      40             : #include <err.h>
      41             : #include <stdio.h>
      42             : #include "indent_globs.h"
      43             : #include "indent_codes.h"
      44             : #include "indent.h"
      45             : 
      46             : static void reduce(void);
      47             : 
      48             : void
      49         606 : parse(int tk) /* tk: the code for the construct scanned */
      50             : {
      51             :     int         i;
      52             : 
      53             : #ifdef debug
      54             :     printf("%2d - %s\n", tk, token);
      55             : #endif
      56             : 
      57         616 :     while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
      58             :     /* true if we have an if without an else */
      59          10 :     ps.p_stack[ps.tos] = stmt;  /* apply the if(..) stmt ::= stmt
      60             :                      * reduction */
      61          10 :     reduce();       /* see if this allows any reduction */
      62             :     }
      63             : 
      64             : 
      65         606 :     switch (tk) {       /* go on and figure out what to do with the
      66             :                  * input */
      67             : 
      68         174 :     case decl:          /* scanned a declaration word */
      69         174 :     ps.search_brace = btype_2;
      70             :     /* indicate that following brace should be on same line */
      71         174 :     if (ps.p_stack[ps.tos] != decl) {   /* only put one declaration
      72             :                          * onto stack */
      73         154 :         break_comma = true; /* while in declaration, newline should be
      74             :                  * forced after comma */
      75         154 :         ps.p_stack[++ps.tos] = decl;
      76         154 :         ps.il[ps.tos] = ps.i_l_follow;
      77             : 
      78         154 :         if (ps.ljust_decl) {/* only do if we want left justified
      79             :                  * declarations */
      80           0 :         ps.ind_level = 0;
      81           0 :         for (i = ps.tos - 1; i > 0; --i)
      82           0 :             if (ps.p_stack[i] == decl)
      83           0 :             ++ps.ind_level; /* indentation is number of
      84             :                      * declaration levels deep we are */
      85           0 :         ps.i_l_follow = ps.ind_level;
      86             :         }
      87             :     }
      88         174 :     break;
      89             : 
      90          20 :     case ifstmt:        /* scanned if (...) */
      91          20 :     if (ps.p_stack[ps.tos] == elsehead && ps.else_if)   /* "else if ..." */
      92             :         /*
      93             :          * Note that the stack pointer here is decremented, effectively
      94             :          * reducing "else if" to "if". This saves a lot of stack space
      95             :          * in case of a long "if-else-if ... else-if" sequence.
      96             :          */
      97           2 :         ps.i_l_follow = ps.il[ps.tos--];
      98             :     /* the rest is the same as for dolit and forstmt */
      99             :     /* FALLTHROUGH */
     100             :     case dolit:     /* 'do' */
     101             :     case forstmt:       /* for (...) */
     102          20 :     ps.p_stack[++ps.tos] = tk;
     103          20 :     ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
     104          20 :     ++ps.i_l_follow;    /* subsequent statements should be indented 1 */
     105          20 :     ps.search_brace = btype_2;
     106          20 :     break;
     107             : 
     108          82 :     case lbrace:        /* scanned { */
     109          82 :     break_comma = false;    /* don't break comma in an initial list */
     110          82 :     if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
     111          62 :         || ps.p_stack[ps.tos] == stmtl)
     112          68 :         ++ps.i_l_follow;    /* it is a random, isolated stmt group or a
     113             :                  * declaration */
     114             :     else {
     115          14 :         if (s_code == e_code) {
     116             :         /*
     117             :          * only do this if there is nothing on the line
     118             :          */
     119           8 :         --ps.ind_level;
     120             :         /*
     121             :          * it is a group as part of a while, for, etc.
     122             :          */
     123           8 :         if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
     124           0 :             --ps.ind_level;
     125             :         /*
     126             :          * for a switch, brace should be two levels out from the code
     127             :          */
     128             :         }
     129             :     }
     130             : 
     131          82 :     ps.p_stack[++ps.tos] = lbrace;
     132          82 :     ps.il[ps.tos] = ps.ind_level;
     133          82 :     ps.p_stack[++ps.tos] = stmt;
     134             :     /* allow null stmt between braces */
     135          82 :     ps.il[ps.tos] = ps.i_l_follow;
     136          82 :     break;
     137             : 
     138           0 :     case whilestmt:     /* scanned while (...) */
     139           0 :     if (ps.p_stack[ps.tos] == dohead) {
     140             :         /* it is matched with do stmt */
     141           0 :         ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
     142           0 :         ps.p_stack[++ps.tos] = whilestmt;
     143           0 :         ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
     144             :     }
     145             :     else {          /* it is a while loop */
     146           0 :         ps.p_stack[++ps.tos] = whilestmt;
     147           0 :         ps.il[ps.tos] = ps.i_l_follow;
     148           0 :         ++ps.i_l_follow;
     149           0 :         ps.search_brace = btype_2;
     150             :     }
     151             : 
     152           0 :     break;
     153             : 
     154          10 :     case elselit:       /* scanned an else */
     155             : 
     156          10 :     if (ps.p_stack[ps.tos] != ifhead)
     157           0 :         diag2(1, "Unmatched 'else'");
     158             :     else {
     159          10 :         ps.ind_level = ps.il[ps.tos];   /* indentation for else should
     160             :                          * be same as for if */
     161          10 :         ps.i_l_follow = ps.ind_level + 1;   /* everything following should
     162             :                          * be in 1 level */
     163          10 :         ps.p_stack[ps.tos] = elsehead;
     164             :         /* remember if with else */
     165          10 :         ps.search_brace = btype_2 | ps.else_if;
     166             :     }
     167          10 :     break;
     168             : 
     169          82 :     case rbrace:        /* scanned a } */
     170             :     /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
     171          82 :     if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) {
     172          82 :         ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
     173          82 :         ps.p_stack[ps.tos] = stmt;
     174             :     }
     175             :     else
     176           0 :         diag2(1, "Statement nesting error");
     177          82 :     break;
     178             : 
     179           2 :     case swstmt:        /* had switch (...) */
     180           2 :     ps.p_stack[++ps.tos] = swstmt;
     181           2 :     ps.cstk[ps.tos] = case_ind;
     182             :     /* save current case indent level */
     183           2 :     ps.il[ps.tos] = ps.i_l_follow;
     184           2 :     case_ind = ps.i_l_follow + ps.case_indent;  /* cases should be one
     185             :                              * level down from
     186             :                              * switch */
     187           2 :     ps.i_l_follow += ps.case_indent + 1;    /* statements should be two
     188             :                          * levels in */
     189           2 :     ps.search_brace = btype_2;
     190           2 :     break;
     191             : 
     192         236 :     case semicolon:     /* this indicates a simple stmt */
     193         236 :     break_comma = false;    /* turn off flag to break after commas in a
     194             :                  * declaration */
     195         236 :     ps.p_stack[++ps.tos] = stmt;
     196         236 :     ps.il[ps.tos] = ps.ind_level;
     197         236 :     break;
     198             : 
     199           0 :     default:            /* this is an error */
     200           0 :     diag2(1, "Unknown code to parser");
     201           0 :     return;
     202             : 
     203             : 
     204             :     }               /* end of switch */
     205             : 
     206         606 :     if (ps.tos >= nitems(ps.p_stack) - 1)
     207           0 :     errx(1, "Parser stack overflow");
     208             : 
     209         606 :     reduce();           /* see if any reduction can be done */
     210             : 
     211             : #ifdef debug
     212             :     for (i = 1; i <= ps.tos; ++i)
     213             :     printf("(%d %d)", ps.p_stack[i], ps.il[i]);
     214             :     printf("\n");
     215             : #endif
     216             : 
     217         606 :     return;
     218             : }
     219             : 
     220             : /*
     221             :  * NAME: reduce
     222             :  *
     223             :  * FUNCTION: Implements the reduce part of the parsing algorithm
     224             :  *
     225             :  * ALGORITHM: The following reductions are done.  Reductions are repeated
     226             :  *  until no more are possible.
     227             :  *
     228             :  * Old TOS      New TOS
     229             :  * <stmt> <stmt>    <stmtl>
     230             :  * <stmtl> <stmt>   <stmtl>
     231             :  * do <stmt>      "dostmt"
     232             :  * if <stmt>      "ifstmt"
     233             :  * switch <stmt>  <stmt>
     234             :  * decl <stmt>        <stmt>
     235             :  * "ifelse" <stmt>  <stmt>
     236             :  * for <stmt>     <stmt>
     237             :  * while <stmt>       <stmt>
     238             :  * "dostmt" while <stmt>
     239             :  *
     240             :  * On each reduction, ps.i_l_follow (the indentation for the following line)
     241             :  * is set to the indentation level associated with the old TOS.
     242             :  *
     243             :  * PARAMETERS: None
     244             :  *
     245             :  * RETURNS: Nothing
     246             :  *
     247             :  * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
     248             :  *
     249             :  * CALLS: None
     250             :  *
     251             :  * CALLED BY: parse
     252             :  *
     253             :  * HISTORY: initial coding  November 1976   D A Willcox of CAC
     254             :  *
     255             :  */
     256             : /*----------------------------------------------*\
     257             : |   REDUCTION PHASE                 |
     258             : \*----------------------------------------------*/
     259             : static void
     260        1108 : reduce(void)
     261             : {
     262             :     int i;
     263             : 
     264             :     for (;;) {          /* keep looping until there is nothing left to
     265             :                  * reduce */
     266             : 
     267        1108 :     switch (ps.p_stack[ps.tos]) {
     268             : 
     269         574 :     case stmt:
     270         574 :         switch (ps.p_stack[ps.tos - 1]) {
     271             : 
     272         308 :         case stmt:
     273             :         case stmtl:
     274             :         /* stmtl stmt or stmt stmt */
     275         308 :         ps.p_stack[--ps.tos] = stmtl;
     276         308 :         break;
     277             : 
     278           0 :         case dolit: /* <do> <stmt> */
     279           0 :         ps.p_stack[--ps.tos] = dohead;
     280           0 :         ps.i_l_follow = ps.il[ps.tos];
     281           0 :         break;
     282             : 
     283          20 :         case ifstmt:
     284             :         /* <if> <stmt> */
     285          20 :         ps.p_stack[--ps.tos] = ifhead;
     286          20 :         for (i = ps.tos - 1;
     287             :             (
     288          20 :              ps.p_stack[i] != stmt
     289          16 :              &&
     290          16 :              ps.p_stack[i] != stmtl
     291           0 :              &&
     292           0 :              ps.p_stack[i] != lbrace
     293             :              );
     294           0 :             --i);
     295          20 :         ps.i_l_follow = ps.il[i];
     296             :         /*
     297             :          * for the time being, we will assume that there is no else on
     298             :          * this if, and set the indentation level accordingly. If an
     299             :          * else is scanned, it will be fixed up later
     300             :          */
     301          20 :         break;
     302             : 
     303           2 :         case swstmt:
     304             :         /* <switch> <stmt> */
     305           2 :         case_ind = ps.cstk[ps.tos - 1];
     306             :         /* FALLTHROUGH */
     307         164 :         case decl:      /* finish of a declaration */
     308             :         case elsehead:
     309             :         /* <<if> <stmt> else> <stmt> */
     310             :         case forstmt:
     311             :         /* <for> <stmt> */
     312             :         case whilestmt:
     313             :         /* <while> <stmt> */
     314         164 :         ps.p_stack[--ps.tos] = stmt;
     315         164 :         ps.i_l_follow = ps.il[ps.tos];
     316         164 :         break;
     317             : 
     318          82 :         default:        /* <anything else> <stmt> */
     319          82 :         return;
     320             : 
     321             :         }           /* end of section for <stmt> on top of stack */
     322         492 :         break;
     323             : 
     324           0 :     case whilestmt: /* while (...) on top */
     325           0 :         if (ps.p_stack[ps.tos - 1] == dohead) {
     326             :         /* it is termination of a do while */
     327           0 :         ps.tos -= 2;
     328           0 :         break;
     329             :         }
     330             :         else
     331           0 :         return;
     332             : 
     333         534 :     default:        /* anything else on top */
     334         534 :         return;
     335             : 
     336             :     }
     337             :     }
     338             : }

Generated by: LCOV version 1.14