LCOV - code coverage report
Current view: top level - src/tools/pg_bsd_indent - indent.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 76.9 % 735 565
Test Date: 2026-07-03 19:57:34 Functions: 66.7 % 3 2
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 64.4 % 671 432

             Branch data     Line data    Source code
       1                 :             : /*-
       2                 :             :  * Copyright (c) 1985 Sun Microsystems, Inc.
       3                 :             :  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
       4                 :             :  * Copyright (c) 1980, 1993
       5                 :             :  *  The Regents of the University of California.  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[] = "@(#)indent.c   5.17 (Berkeley) 6/7/93";
      35                 :             : #endif /* not lint */
      36                 :             : #endif
      37                 :             : 
      38                 :             : #include "c.h"
      39                 :             : 
      40                 :             : #include <sys/param.h>
      41                 :             : #include <err.h>
      42                 :             : #include <fcntl.h>
      43                 :             : #include <unistd.h>
      44                 :             : #include <stdio.h>
      45                 :             : #include <stdlib.h>
      46                 :             : #include <string.h>
      47                 :             : #include <ctype.h>
      48                 :             : 
      49                 :             : /* Tell indent_globs.h to define our global variables here */
      50                 :             : #define DECLARE_INDENT_GLOBALS 1
      51                 :             : 
      52                 :             : #include "indent_globs.h"
      53                 :             : #include "indent_codes.h"
      54                 :             : #include "indent.h"
      55                 :             : 
      56                 :             : static void bakcopy(void);
      57                 :             : static void indent_declaration(int cur_dec_ind, int tabs_to_var);
      58                 :             : 
      59                 :             : const char *in_name = "Standard Input";   /* will always point to name of input
      60                 :             :                      * file */
      61                 :             : const char *out_name = "Standard Output"; /* will always point to name
      62                 :             :                          * of output file */
      63                 :             : char        bakfile[MAXPGPATH] = "";
      64                 :             : 
      65                 :             : int
      66                 :          19 : main(int argc, char **argv)
      67                 :             : {
      68                 :             :     int         dec_ind;    /* current indentation for declarations */
      69                 :             :     int         di_stack[20];   /* a stack of structure indentation levels */
      70                 :             :     int         force_nl;   /* when true, code must be broken */
      71                 :          19 :     int         hd_type = 0;    /* used to store type of stmt for if (...),
      72                 :             :                  * for (...), etc */
      73                 :             :     int     i;      /* local loop counter */
      74                 :             :     int         scase;      /* set to true when we see a case, so we will
      75                 :             :                  * know what to do with the following colon */
      76                 :             :     int         sp_sw;      /* when true, we are in the expression of
      77                 :             :                  * if(...), while(...), etc. */
      78                 :             :     int         squest;     /* when this is positive, we have seen a ?
      79                 :             :                  * without the matching : in a <c>?<s>:<s>
      80                 :             :                  * construct */
      81                 :             :     const char *t_ptr;      /* used for copying tokens */
      82                 :             :     int     tabs_to_var;    /* true if using tabs to indent to var name */
      83                 :             :     int         type_code;  /* the type of token, returned by lexi */
      84                 :             : 
      85                 :          19 :     int         last_else = 0;  /* true iff last keyword was an else */
      86                 :          19 :     const char *profile_name = NULL;
      87                 :             :     struct parser_state transient_state; /* a copy for lookup */
      88                 :             : 
      89                 :             : 
      90                 :             :     /*-----------------------------------------------*\
      91                 :             :     |             INITIALIZATION              |
      92                 :             :     \*-----------------------------------------------*/
      93                 :             : 
      94                 :          19 :     found_err = 0;
      95                 :             : 
      96                 :          19 :     ps.p_stack[0] = stmt;   /* this is the parser's stack */
      97                 :          19 :     ps.last_nl = true;      /* this is true if the last thing scanned was
      98                 :             :                  * a newline */
      99                 :          19 :     ps.last_token = semicolon;
     100                 :          19 :     combuf = (char *) malloc(bufsize);
     101         [ -  + ]:          19 :     if (combuf == NULL)
     102                 :           0 :     err(1, NULL);
     103                 :          19 :     labbuf = (char *) malloc(bufsize);
     104         [ -  + ]:          19 :     if (labbuf == NULL)
     105                 :           0 :     err(1, NULL);
     106                 :          19 :     codebuf = (char *) malloc(bufsize);
     107         [ -  + ]:          19 :     if (codebuf == NULL)
     108                 :           0 :     err(1, NULL);
     109                 :          19 :     tokenbuf = (char *) malloc(bufsize);
     110         [ -  + ]:          19 :     if (tokenbuf == NULL)
     111                 :           0 :     err(1, NULL);
     112                 :          19 :     alloc_typenames();
     113                 :          19 :     l_com = combuf + bufsize - 5;
     114                 :          19 :     l_lab = labbuf + bufsize - 5;
     115                 :          19 :     l_code = codebuf + bufsize - 5;
     116                 :          19 :     l_token = tokenbuf + bufsize - 5;
     117                 :          19 :     combuf[0] = codebuf[0] = labbuf[0] = ' ';   /* set up code, label, and
     118                 :             :                          * comment buffers */
     119                 :          19 :     combuf[1] = codebuf[1] = labbuf[1] = '\0';
     120                 :          19 :     ps.else_if = 1;     /* Default else-if special processing to on */
     121                 :          19 :     s_lab = e_lab = labbuf + 1;
     122                 :          19 :     s_code = e_code = codebuf + 1;
     123                 :          19 :     s_com = e_com = combuf + 1;
     124                 :          19 :     s_token = e_token = tokenbuf + 1;
     125                 :             : 
     126                 :          19 :     in_buffer = (char *) malloc(10);
     127         [ -  + ]:          19 :     if (in_buffer == NULL)
     128                 :           0 :     err(1, NULL);
     129                 :          19 :     in_buffer_limit = in_buffer + 8;
     130                 :          19 :     buf_ptr = buf_end = in_buffer;
     131                 :          19 :     line_no = 1;
     132                 :          19 :     had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
     133                 :          19 :     sp_sw = force_nl = false;
     134                 :          19 :     ps.in_or_st = false;
     135                 :          19 :     ps.bl_line = true;
     136                 :          19 :     dec_ind = 0;
     137                 :          19 :     di_stack[ps.dec_nest = 0] = 0;
     138                 :          19 :     ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
     139                 :             : 
     140                 :          19 :     scase = ps.pcase = false;
     141                 :          19 :     squest = 0;
     142                 :          19 :     sc_end = NULL;
     143                 :          19 :     bp_save = NULL;
     144                 :          19 :     be_save = NULL;
     145                 :             : 
     146                 :          19 :     output = NULL;
     147                 :          19 :     tabs_to_var = 0;
     148                 :             : 
     149                 :             :     /*--------------------------------------------------*\
     150                 :             :     |           COMMAND LINE SCAN        |
     151                 :             :     \*--------------------------------------------------*/
     152                 :             : 
     153                 :             : #ifdef undef
     154                 :             :     max_col = 78;       /* -l78 */
     155                 :             :     lineup_to_parens = 1;   /* -lp */
     156                 :             :     lineup_to_parens_always = 0;    /* -nlpl */
     157                 :             :     ps.ljust_decl = 0;      /* -ndj */
     158                 :             :     ps.com_ind = 33;        /* -c33 */
     159                 :             :     star_comment_cont = 1;  /* -sc */
     160                 :             :     ps.ind_size = 8;        /* -i8 */
     161                 :             :     verbose = 0;
     162                 :             :     ps.decl_indent = 16;    /* -di16 */
     163                 :             :     ps.local_decl_indent = -1;  /* if this is not set to some nonnegative value
     164                 :             :                  * by an arg, we will set this equal to
     165                 :             :                  * ps.decl_ind */
     166                 :             :     ps.indent_parameters = 1;   /* -ip */
     167                 :             :     ps.decl_com_ind = 0;    /* if this is not set to some positive value
     168                 :             :                  * by an arg, we will set this equal to
     169                 :             :                  * ps.com_ind */
     170                 :             :     btype_2 = 1;        /* -br */
     171                 :             :     cuddle_else = 1;        /* -ce */
     172                 :             :     ps.unindent_displace = 0;   /* -d0 */
     173                 :             :     ps.case_indent = 0;     /* -cli0 */
     174                 :             :     format_block_comments = 1;  /* -fcb */
     175                 :             :     format_col1_comments = 1;   /* -fc1 */
     176                 :             :     procnames_start_line = 1;   /* -psl */
     177                 :             :     proc_calls_space = 0;   /* -npcs */
     178                 :             :     comment_delimiter_on_blankline = 1; /* -cdb */
     179                 :             :     ps.leave_comma = 1;     /* -nbc */
     180                 :             : #endif
     181                 :             : 
     182         [ +  + ]:          74 :     for (i = 1; i < argc; ++i)
     183         [ -  + ]:          55 :     if (strcmp(argv[i], "-npro") == 0)
     184                 :           0 :         break;
     185   [ +  +  +  +  :          55 :     else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0')
                   +  - ]
     186                 :          18 :         profile_name = argv[i]; /* non-empty -P (set profile) */
     187                 :          19 :     set_defaults();
     188         [ +  - ]:          19 :     if (i >= argc)
     189                 :          19 :     set_profile(profile_name);
     190                 :             : 
     191         [ +  + ]:          73 :     for (i = 1; i < argc; ++i) {
     192                 :             : 
     193                 :             :     /*
     194                 :             :      * look thru args (if any) for changes to defaults
     195                 :             :      */
     196         [ +  + ]:          55 :     if (argv[i][0] != '-') {/* no flag on parameter */
     197         [ +  + ]:          36 :         if (input == NULL) {    /* we must have the input file */
     198                 :          18 :         in_name = argv[i];  /* remember name of input file */
     199                 :          18 :         input = fopen(in_name, "r");
     200         [ -  + ]:          18 :         if (input == NULL)  /* check for open error */
     201                 :           0 :             err(1, "%s", in_name);
     202                 :          18 :         continue;
     203                 :             :         }
     204         [ +  - ]:          18 :         else if (output == NULL) {  /* we have the output file */
     205                 :          18 :         out_name = argv[i]; /* remember name of output file */
     206         [ -  + ]:          18 :         if (strcmp(in_name, out_name) == 0) {   /* attempt to overwrite
     207                 :             :                              * the file */
     208                 :           0 :             errx(1, "input and output files must be different");
     209                 :             :         }
     210                 :          18 :         output = fopen(out_name, "wb");
     211         [ -  + ]:          18 :         if (output == NULL) /* check for create error */
     212                 :           0 :             err(1, "%s", out_name);
     213                 :          18 :         continue;
     214                 :             :         }
     215                 :           0 :         errx(1, "unknown parameter: %s", argv[i]);
     216                 :             :     }
     217                 :             :     else
     218                 :          19 :         set_option(argv[i]);
     219                 :             :     }               /* end of for */
     220         [ -  + ]:          18 :     if (input == NULL)
     221                 :           0 :     input = stdin;
     222         [ -  + ]:          18 :     if (output == NULL) {
     223         [ #  # ]:           0 :     if (input == stdin)
     224                 :           0 :         output = stdout;
     225                 :             :     else {
     226                 :           0 :         out_name = in_name;
     227                 :           0 :         bakcopy();
     228                 :             :     }
     229                 :             :     }
     230                 :             : 
     231         [ -  + ]:          18 :     if (ps.com_ind <= 1)
     232                 :           0 :     ps.com_ind = 2;     /* don't put normal comments before column 2 */
     233         [ +  - ]:          18 :     if (block_comment_max_col <= 0)
     234                 :          18 :     block_comment_max_col = max_col;
     235         [ +  - ]:          18 :     if (ps.local_decl_indent < 0)    /* if not specified by user, set this */
     236                 :          18 :     ps.local_decl_indent = ps.decl_indent;
     237         [ +  - ]:          18 :     if (ps.decl_com_ind <= 0)    /* if not specified by user, set this */
     238         [ -  + ]:          18 :     ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
     239         [ +  - ]:          18 :     if (continuation_indent == 0)
     240                 :          18 :     continuation_indent = ps.ind_size;
     241                 :          18 :     fill_buffer();      /* get first batch of stuff into input buffer */
     242                 :             : 
     243                 :          18 :     parse(semicolon);
     244                 :             :     {
     245                 :          18 :     char *p = buf_ptr;
     246                 :          18 :     int col = 1;
     247                 :             : 
     248                 :             :     while (1) {
     249         [ -  + ]:          18 :         if (*p == ' ')
     250                 :           0 :         col++;
     251         [ -  + ]:          18 :         else if (*p == '\t')
     252                 :           0 :         col = tabsize * (1 + (col - 1) / tabsize) + 1;
     253                 :             :         else
     254                 :          18 :         break;
     255                 :           0 :         p++;
     256                 :             :     }
     257         [ -  + ]:          18 :     if (col > ps.ind_size)
     258                 :           0 :         ps.ind_level = ps.i_l_follow = col / ps.ind_size;
     259                 :             :     }
     260                 :             : 
     261                 :             :     /*
     262                 :             :      * START OF MAIN LOOP
     263                 :             :      */
     264                 :             : 
     265                 :        1233 :     while (1) {         /* this is the main loop.  it will go until we
     266                 :             :                  * reach eof */
     267                 :        1251 :     int comment_buffered = false;
     268                 :             : 
     269                 :        1251 :     type_code = lexi(&ps);  /* lexi reads one token.  The actual
     270                 :             :                  * characters read are stored in "token". lexi
     271                 :             :                  * returns a code indicating the type of token */
     272                 :             : 
     273                 :             :     /*
     274                 :             :      * The following code moves newlines and comments following an if (),
     275                 :             :      * while (), else, etc. up to the start of the following stmt to
     276                 :             :      * a buffer. This allows proper handling of both kinds of brace
     277                 :             :      * placement (-br, -bl) and cuddling "else" (-ce).
     278                 :             :      */
     279                 :             : 
     280         [ +  + ]:        1340 :     while (ps.search_brace) {
     281   [ +  -  +  +  :         218 :         switch (type_code) {
                      + ]
     282                 :          46 :         case newline:
     283         [ +  + ]:          46 :         if (sc_end == NULL) {
     284                 :          30 :             save_com = sc_buf;
     285                 :          30 :             save_com[0] = save_com[1] = ' ';
     286                 :          30 :             sc_end = &save_com[2];
     287                 :             :         }
     288                 :          46 :         *sc_end++ = '\n';
     289                 :             :         /*
     290                 :             :          * We may have inherited a force_nl == true from the previous
     291                 :             :          * token (like a semicolon). But once we know that a newline
     292                 :             :          * has been scanned in this loop, force_nl should be false.
     293                 :             :          *
     294                 :             :          * However, the force_nl == true must be preserved if newline
     295                 :             :          * is never scanned in this loop, so this assignment cannot be
     296                 :             :          * done earlier.
     297                 :             :          */
     298                 :          46 :         force_nl = false;
     299                 :          46 :         break;
     300                 :           0 :         case form_feed:
     301                 :           0 :         break;
     302                 :           9 :         case comment:
     303         [ +  + ]:           9 :         if (sc_end == NULL) {
     304                 :             :             /*
     305                 :             :              * Copy everything from the start of the line, because
     306                 :             :              * pr_comment() will use that to calculate original
     307                 :             :              * indentation of a boxed comment.
     308                 :             :              */
     309                 :           4 :             memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4);
     310                 :           4 :             save_com = sc_buf + (buf_ptr - in_buffer - 4);
     311                 :           4 :             save_com[0] = save_com[1] = ' ';
     312                 :           4 :             sc_end = &save_com[2];
     313                 :             :         }
     314                 :           9 :         comment_buffered = true;
     315                 :           9 :         *sc_end++ = '/';    /* copy in start of comment */
     316                 :           9 :         *sc_end++ = '*';
     317                 :             :         for (;;) {  /* loop until we get to the end of the comment */
     318                 :         293 :             *sc_end = *buf_ptr++;
     319         [ +  + ]:         293 :             if (buf_ptr >= buf_end)
     320                 :           4 :             fill_buffer();
     321   [ +  +  +  + ]:         293 :             if (*sc_end++ == '*' && *buf_ptr == '/')
     322                 :           9 :             break;  /* we are at end of comment */
     323         [ -  + ]:         284 :             if (sc_end >= &save_com[sc_size]) {  /* check for temp buffer
     324                 :             :                              * overflow */
     325                 :           0 :             diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
     326                 :           0 :             fflush(output);
     327                 :           0 :             exit(1);
     328                 :             :             }
     329                 :             :         }
     330                 :           9 :         *sc_end++ = '/';    /* add ending slash */
     331         [ -  + ]:           9 :         if (++buf_ptr >= buf_end)    /* get past / in buffer */
     332                 :           0 :             fill_buffer();
     333                 :           9 :         break;
     334                 :          29 :         case lbrace:
     335                 :             :         /*
     336                 :             :          * Put KNF-style lbraces before the buffered up tokens and
     337                 :             :          * jump out of this loop in order to avoid copying the token
     338                 :             :          * again under the default case of the switch below.
     339                 :             :          */
     340   [ +  +  +  + ]:          29 :         if (sc_end != NULL && btype_2) {
     341                 :          15 :             save_com[0] = '{';
     342                 :             :             /*
     343                 :             :              * Originally the lbrace may have been alone on its own
     344                 :             :              * line, but it will be moved into "the else's line", so
     345                 :             :              * if there was a newline resulting from the "{" before,
     346                 :             :              * it must be scanned now and ignored.
     347                 :             :              */
     348         [ +  + ]:          39 :             while (isspace((unsigned char)*buf_ptr)) {
     349         [ +  + ]:          28 :             if (++buf_ptr >= buf_end)
     350                 :          14 :                 fill_buffer();
     351         [ +  + ]:          28 :             if (*buf_ptr == '\n')
     352                 :           4 :                 break;
     353                 :             :             }
     354                 :          15 :             goto sw_buffer;
     355                 :             :         }
     356                 :             :         pg_fallthrough;
     357                 :             :         default:        /* it is the start of a normal statement */
     358                 :             :         {
     359                 :             :             int remove_newlines;
     360                 :             : 
     361                 :         148 :             remove_newlines =
     362                 :             :             /* "} else" */
     363         [ +  - ]:           2 :             (type_code == sp_nparen && *token == 'e' &&
     364   [ +  -  -  + ]:           2 :                 e_code != s_code && e_code[-1] == '}')
     365                 :             :             /* "else if" */
     366   [ +  +  +  +  :         151 :             || (type_code == sp_paren && *token == 'i' &&
             +  -  +  + ]
     367         [ +  - ]:           1 :                 last_else && ps.else_if);
     368         [ +  + ]:         148 :             if (remove_newlines)
     369                 :           3 :             force_nl = false;
     370         [ +  + ]:         148 :             if (sc_end == NULL) {   /* ignore buffering if
     371                 :             :                          * comment wasn't saved up */
     372                 :         129 :             ps.search_brace = false;
     373                 :         129 :             goto check_type;
     374                 :             :             }
     375   [ +  -  +  + ]:          38 :             while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) {
     376                 :          19 :             sc_end--;
     377                 :             :             }
     378   [ +  -  +  + ]:          19 :             if (swallow_optional_blanklines ||
     379         [ +  + ]:          13 :             (!comment_buffered && remove_newlines)) {
     380                 :           1 :             force_nl = !remove_newlines;
     381   [ +  -  +  + ]:           4 :             while (sc_end > save_com && sc_end[-1] == '\n') {
     382                 :           3 :                 sc_end--;
     383                 :             :             }
     384                 :             :             }
     385         [ +  + ]:          19 :             if (force_nl) { /* if we should insert a nl here, put
     386                 :             :                      * it into the buffer */
     387                 :           1 :             force_nl = false;
     388                 :           1 :             --line_no;  /* this will be re-increased when the
     389                 :             :                      * newline is read from the buffer */
     390                 :           1 :             *sc_end++ = '\n';
     391                 :           1 :             *sc_end++ = ' ';
     392         [ -  + ]:           1 :             if (verbose)    /* print error msg if the line was
     393                 :             :                      * not already broken */
     394                 :           0 :                 diag2(0, "Line broken");
     395                 :             :             }
     396         [ +  + ]:          86 :             for (t_ptr = token; *t_ptr; ++t_ptr)
     397                 :          67 :             *sc_end++ = *t_ptr;
     398                 :             : 
     399                 :          19 :         sw_buffer:
     400                 :          34 :             ps.search_brace = false;    /* stop looking for start of
     401                 :             :                          * stmt */
     402                 :          34 :             bp_save = buf_ptr;  /* save current input buffer */
     403                 :          34 :             be_save = buf_end;
     404                 :          34 :             buf_ptr = save_com; /* fix so that subsequent calls to
     405                 :             :                      * lexi will take tokens out of
     406                 :             :                      * save_com */
     407                 :          34 :             *sc_end++ = ' ';/* add trailing blank, just in case */
     408                 :          34 :             buf_end = sc_end;
     409                 :          34 :             sc_end = NULL;
     410                 :          34 :             break;
     411                 :             :         }
     412                 :             :         }           /* end of switch */
     413                 :             :         /*
     414                 :             :          * We must make this check, just in case there was an unexpected
     415                 :             :          * EOF.
     416                 :             :          */
     417         [ +  - ]:          89 :         if (type_code != 0) {
     418                 :             :         /*
     419                 :             :          * The only intended purpose of calling lexi() below is to
     420                 :             :          * categorize the next token in order to decide whether to
     421                 :             :          * continue buffering forthcoming tokens. Once the buffering
     422                 :             :          * is over, lexi() will be called again elsewhere on all of
     423                 :             :          * the tokens - this time for normal processing.
     424                 :             :          *
     425                 :             :          * Calling it for this purpose is a bug, because lexi() also
     426                 :             :          * changes the parser state and discards leading whitespace,
     427                 :             :          * which is needed mostly for comment-related considerations.
     428                 :             :          *
     429                 :             :          * Work around the former problem by giving lexi() a copy of
     430                 :             :          * the current parser state and discard it if the call turned
     431                 :             :          * out to be just a look ahead.
     432                 :             :          *
     433                 :             :          * Work around the latter problem by copying all whitespace
     434                 :             :          * characters into the buffer so that the later lexi() call
     435                 :             :          * will read them.
     436                 :             :          */
     437         [ +  + ]:          89 :         if (sc_end != NULL) {
     438   [ +  +  +  + ]:          86 :             while (*buf_ptr == ' ' || *buf_ptr == '\t') {
     439                 :          31 :             *sc_end++ = *buf_ptr++;
     440         [ -  + ]:          31 :             if (sc_end >= &save_com[sc_size]) {
     441                 :           0 :                 errx(1, "input too long");
     442                 :             :             }
     443                 :             :             }
     444         [ -  + ]:          55 :             if (buf_ptr >= buf_end) {
     445                 :           0 :             fill_buffer();
     446                 :             :             }
     447                 :             :         }
     448                 :          89 :         transient_state = ps;
     449                 :          89 :         type_code = lexi(&transient_state); /* read another token */
     450   [ +  +  +  -  :          89 :         if (type_code != newline && type_code != form_feed &&
                   +  + ]
     451         [ +  + ]:          50 :             type_code != comment && !transient_state.search_brace) {
     452                 :          16 :             ps = transient_state;
     453                 :             :         }
     454                 :             :         }
     455                 :             :     }           /* end of while (search_brace) */
     456                 :        1122 :     last_else = 0;
     457                 :        1251 : check_type:
     458         [ +  + ]:        1251 :     if (type_code == 0) {   /* we got eof */
     459   [ +  +  +  + ]:          18 :         if (s_lab != e_lab || s_code != e_code
     460         [ -  + ]:           1 :             || s_com != e_com)  /* must dump end of line */
     461                 :          17 :         dump_line();
     462         [ -  + ]:          18 :         if (ps.tos > 1)  /* check for balanced braces */
     463                 :           0 :         diag2(1, "Stuff missing from end of file");
     464                 :             : 
     465         [ -  + ]:          18 :         if (verbose) {
     466                 :           0 :         printf("There were %d output lines and %d comments\n",
     467                 :             :                ps.out_lines, ps.out_coms);
     468                 :           0 :         printf("(Lines with comments)/(Lines with code): %6.3f\n",
     469                 :             :                (1.0 * ps.com_lines) / code_lines);
     470                 :             :         }
     471                 :          18 :         fflush(output);
     472                 :          18 :         exit(found_err);
     473                 :             :     }
     474         [ +  + ]:        1233 :     if (
     475         [ +  + ]:        1175 :         (type_code != comment) &&
     476         [ +  + ]:         894 :         (type_code != newline) &&
     477         [ +  - ]:         883 :         (type_code != preesc) &&
     478                 :             :         (type_code != form_feed)) {
     479   [ +  +  +  - ]:         883 :         if (force_nl &&
     480         [ +  + ]:           7 :             (type_code != semicolon) &&
     481         [ +  + ]:           4 :             (type_code != lbrace || !btype_2)) {
     482                 :             :         /* we should force a broken line here */
     483         [ -  + ]:           6 :         if (verbose)
     484                 :           0 :             diag2(0, "Line broken");
     485                 :           6 :         dump_line();
     486                 :           6 :         ps.want_blank = false;  /* don't insert blank at line start */
     487                 :           6 :         force_nl = false;
     488                 :             :         }
     489                 :         883 :         ps.in_stmt = true;  /* turn on flag which causes an extra level of
     490                 :             :                  * indentation. this is turned off by a ; or
     491                 :             :                  * '}' */
     492         [ +  + ]:         883 :         if (s_com != e_com) {   /* the turkey has embedded a comment
     493                 :             :                      * in a line. fix it */
     494                 :           2 :         int len = e_com - s_com;
     495                 :             : 
     496   [ -  +  -  - ]:           2 :         CHECK_SIZE_CODE(len + 3);
     497                 :           2 :         *e_code++ = ' ';
     498                 :           2 :         memcpy(e_code, s_com, len);
     499                 :           2 :         e_code += len;
     500                 :           2 :         *e_code++ = ' ';
     501                 :           2 :         *e_code = '\0'; /* null terminate code sect */
     502                 :           2 :         ps.want_blank = false;
     503                 :           2 :         e_com = s_com;
     504                 :             :         }
     505                 :             :     }
     506         [ +  + ]:         350 :     else if (type_code != comment)  /* preserve force_nl thru a comment */
     507                 :         292 :         force_nl = false;   /* cancel forced newline after newline, form
     508                 :             :                  * feed, etc */
     509                 :             : 
     510                 :             : 
     511                 :             : 
     512                 :             :     /*-----------------------------------------------------*\
     513                 :             :     |      do switch on type of token scanned       |
     514                 :             :     \*-----------------------------------------------------*/
     515   [ -  +  -  - ]:        1233 :     CHECK_SIZE_CODE(3); /* maximum number of increments of e_code
     516                 :             :                  * before the next CHECK_SIZE_CODE or
     517                 :             :                  * dump_line() is 2. After that there's the
     518                 :             :                  * final increment for the null character. */
     519   [ -  +  +  +  :        1233 :     switch (type_code) {    /* now, decide what to do with the token */
          +  +  -  -  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                   +  - ]
     520                 :             : 
     521                 :           0 :     case form_feed: /* found a form feed in line */
     522                 :           0 :         ps.use_ff = true;   /* a form feed is treated much like a newline */
     523                 :           0 :         dump_line();
     524                 :           0 :         ps.want_blank = false;
     525                 :           0 :         break;
     526                 :             : 
     527                 :         281 :     case newline:
     528   [ +  +  +  + ]:         281 :         if (ps.last_token != comma || ps.p_l_follow > 0
     529   [ +  -  +  +  :          16 :             || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
             +  +  -  + ]
     530                 :         273 :         dump_line();
     531                 :         273 :         ps.want_blank = false;
     532                 :             :         }
     533                 :         281 :         ++line_no;      /* keep track of input line number */
     534                 :         281 :         break;
     535                 :             : 
     536                 :          78 :     case lparen:        /* got a '(' or '[' */
     537                 :             :         /* count parens to make Healy happy */
     538         [ -  + ]:          78 :         if (++ps.p_l_follow == nitems(ps.paren_indents)) {
     539                 :           0 :         diag3(0, "Reached internal limit of %zu unclosed parens",
     540                 :             :             nitems(ps.paren_indents));
     541                 :           0 :         ps.p_l_follow--;
     542                 :             :         }
     543         [ +  + ]:          78 :         if (*token == '[')
     544                 :             :         /* not a function pointer declaration or a function call */;
     545   [ +  +  +  +  :          71 :         else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent &&
                   +  + ]
     546   [ +  -  +  - ]:           4 :         ps.procname[0] == '\0' && ps.paren_level == 0) {
     547                 :             :         /* function pointer declarations */
     548                 :           4 :         indent_declaration(dec_ind, tabs_to_var);
     549                 :           4 :         ps.dumped_decl_indent = true;
     550                 :             :         }
     551         [ +  + ]:          67 :         else if (ps.want_blank &&
     552   [ +  +  -  + ]:          43 :             ((ps.last_token != ident && ps.last_token != funcname) ||
     553                 :             :             /* offsetof (1) is never allowed a space; sizeof (2) gets
     554                 :             :              * one iff -bs; all other keywords (>2) always get a space
     555                 :             :              * before lparen */
     556         [ +  + ]:          17 :             ps.keyword + Bill_Shannon > 2))
     557                 :          27 :         *e_code++ = ' ';
     558                 :          78 :         ps.want_blank = false;
     559                 :          78 :         *e_code++ = token[0];
     560                 :          78 :         ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1;
     561   [ +  +  +  -  :          78 :         if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
                   -  + ]
     562         [ #  # ]:           0 :             && ps.paren_indents[0] < 2 * ps.ind_size)
     563                 :           0 :         ps.paren_indents[0] = 2 * ps.ind_size;
     564   [ +  +  +  +  :          78 :         if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
                   +  + ]
     565                 :             :         /*
     566                 :             :          * this is a kluge to make sure that declarations will be
     567                 :             :          * aligned right if proc decl has an explicit type on it, i.e.
     568                 :             :          * "int a(x) {..."
     569                 :             :          */
     570                 :          27 :         parse(semicolon);   /* I said this was a kluge... */
     571                 :          27 :         ps.in_or_st = false;    /* turn off flag for structure decl or
     572                 :             :                      * initialization */
     573                 :             :         }
     574                 :             :         /*
     575                 :             :          * parenthesized type following sizeof or offsetof is not a cast,
     576                 :             :          * and we assume the same for any other non-keyword identifier,
     577                 :             :          * to support macros that take types
     578                 :             :          */
     579         [ +  + ]:          78 :         if (ps.last_token == ident &&
     580   [ +  +  +  +  :          24 :         (ps.keyword == 0 || ps.keyword == 1 || ps.keyword == 2))
                   -  + ]
     581                 :          23 :         ps.not_cast_mask |= 1 << ps.p_l_follow;
     582                 :          78 :         break;
     583                 :             : 
     584                 :          78 :     case rparen:        /* got a ')' or ']' */
     585         [ +  + ]:          78 :         if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) {
     586                 :          31 :         ps.last_u_d = true;
     587                 :          31 :         ps.cast_mask &= (1 << ps.p_l_follow) - 1;
     588                 :          31 :         ps.want_blank = space_after_cast;
     589                 :             :         } else
     590                 :          47 :         ps.want_blank = true;
     591                 :          78 :         ps.not_cast_mask &= (1 << ps.p_l_follow) - 1;
     592         [ -  + ]:          78 :         if (--ps.p_l_follow < 0) {
     593                 :           0 :         ps.p_l_follow = 0;
     594                 :           0 :         diag3(0, "Extra %c", *token);
     595                 :             :         }
     596         [ -  + ]:          78 :         if (e_code == s_code)   /* if the paren starts the line */
     597                 :           0 :         ps.paren_level = ps.p_l_follow; /* then indent it */
     598                 :             : 
     599                 :          78 :         *e_code++ = token[0];
     600                 :             : 
     601   [ +  +  +  - ]:          78 :         if (sp_sw && (ps.p_l_follow == 0)) {    /* check for end of if
     602                 :             :                              * (...), or some such */
     603                 :          11 :         sp_sw = false;
     604                 :          11 :         force_nl = true;/* must force newline after if */
     605                 :          11 :         ps.last_u_d = true; /* inform lexi that a following
     606                 :             :                      * operator is unary */
     607                 :          11 :         ps.in_stmt = false; /* don't use stmt continuation
     608                 :             :                      * indentation */
     609                 :             : 
     610                 :          11 :         parse(hd_type); /* let parser worry about if, or whatever */
     611                 :             :         }
     612                 :          78 :         ps.search_brace = btype_2;  /* this should ensure that constructs
     613                 :             :                      * such as main(){...} and int[]{...}
     614                 :             :                      * have their braces put in the right
     615                 :             :                      * place */
     616                 :          78 :         break;
     617                 :             : 
     618                 :          42 :     case unary_op:      /* this could be any unary operation */
     619   [ +  +  +  +  :          42 :         if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init &&
                   +  - ]
     620   [ +  -  +  + ]:          15 :         ps.procname[0] == '\0' && ps.paren_level == 0) {
     621                 :             :         /* pointer declarations */
     622                 :             : 
     623                 :             :         /*
     624                 :             :          * if this is a unary op in a declaration, we should indent
     625                 :             :          * this token
     626                 :             :          */
     627         [ +  + ]:          27 :         for (i = 0; token[i]; ++i)
     628                 :             :             /* find length of token */;
     629                 :          12 :         indent_declaration(dec_ind - i, tabs_to_var);
     630                 :          12 :         ps.dumped_decl_indent = true;
     631                 :             :         }
     632         [ +  + ]:          30 :         else if (ps.want_blank)
     633                 :          19 :         *e_code++ = ' ';
     634                 :             : 
     635                 :             :         {
     636                 :          42 :         int len = e_token - s_token;
     637                 :             : 
     638   [ -  +  -  - ]:          42 :         CHECK_SIZE_CODE(len);
     639                 :          42 :         memcpy(e_code, token, len);
     640                 :          42 :         e_code += len;
     641                 :             :         }
     642                 :          42 :         ps.want_blank = false;
     643                 :          42 :         break;
     644                 :             : 
     645                 :          42 :     case binary_op: /* any binary operation */
     646                 :             :         {
     647                 :          42 :         int len = e_token - s_token;
     648                 :             : 
     649   [ -  +  -  - ]:          42 :         CHECK_SIZE_CODE(len + 1);
     650         [ +  - ]:          42 :         if (ps.want_blank)
     651                 :          42 :             *e_code++ = ' ';
     652                 :          42 :         memcpy(e_code, token, len);
     653                 :          42 :         e_code += len;
     654                 :             :         }
     655                 :          42 :         ps.want_blank = true;
     656                 :          42 :         break;
     657                 :             : 
     658                 :           0 :     case postop:        /* got a trailing ++ or -- */
     659                 :           0 :         *e_code++ = token[0];
     660                 :           0 :         *e_code++ = token[1];
     661                 :           0 :         ps.want_blank = true;
     662                 :           0 :         break;
     663                 :             : 
     664                 :           0 :     case question:      /* got a ? */
     665                 :           0 :         squest++;       /* this will be used when a later colon
     666                 :             :                  * appears so we can distinguish the
     667                 :             :                  * <c>?<n>:<n> construct */
     668         [ #  # ]:           0 :         if (ps.want_blank)
     669                 :           0 :         *e_code++ = ' ';
     670                 :           0 :         *e_code++ = '?';
     671                 :           0 :         ps.want_blank = true;
     672                 :           0 :         break;
     673                 :             : 
     674                 :           2 :     case casestmt:      /* got word 'case' or 'default' */
     675                 :           2 :         scase = true;   /* so we can process the later colon properly */
     676                 :           2 :         goto copy_id;
     677                 :             : 
     678                 :           5 :     case colon:     /* got a ':' */
     679         [ -  + ]:           5 :         if (squest > 0) {    /* it is part of the <c>?<n>: <n> construct */
     680                 :           0 :         --squest;
     681         [ #  # ]:           0 :         if (ps.want_blank)
     682                 :           0 :             *e_code++ = ' ';
     683                 :           0 :         *e_code++ = ':';
     684                 :           0 :         ps.want_blank = true;
     685                 :           0 :         break;
     686                 :             :         }
     687         [ -  + ]:           5 :         if (ps.in_or_st) {
     688                 :           0 :         *e_code++ = ':';
     689                 :           0 :         ps.want_blank = false;
     690                 :           0 :         break;
     691                 :             :         }
     692                 :           5 :         ps.in_stmt = false; /* seeing a label does not imply we are in a
     693                 :             :                  * stmt */
     694                 :             :         /*
     695                 :             :          * turn everything so far into a label
     696                 :             :          */
     697                 :             :         {
     698                 :           5 :         int len = e_code - s_code;
     699                 :             : 
     700   [ -  +  -  - ]:           5 :         CHECK_SIZE_LAB(len + 3);
     701                 :           5 :         memcpy(e_lab, s_code, len);
     702                 :           5 :         e_lab += len;
     703                 :           5 :         *e_lab++ = ':';
     704                 :           5 :         *e_lab = '\0';
     705                 :           5 :         e_code = s_code;
     706                 :             :         }
     707                 :           5 :         force_nl = ps.pcase = scase;    /* ps.pcase will be used by
     708                 :             :                          * dump_line to decide how to
     709                 :             :                          * indent the label. force_nl
     710                 :             :                          * will force a case n: to be
     711                 :             :                          * on a line by itself */
     712                 :           5 :         scase = false;
     713                 :           5 :         ps.want_blank = false;
     714                 :           5 :         break;
     715                 :             : 
     716                 :          74 :     case semicolon: /* got a ';' */
     717         [ +  + ]:          74 :         if (ps.dec_nest == 0)
     718                 :          68 :         ps.in_or_st = false;/* we are not in an initialization or
     719                 :             :                      * structure declaration */
     720                 :          74 :         scase = false;  /* these will only need resetting in an error */
     721                 :          74 :         squest = 0;
     722         [ +  + ]:          74 :         if (ps.last_token == rparen)
     723                 :          13 :         ps.in_parameter_declaration = 0;
     724                 :          74 :         ps.cast_mask = 0;
     725                 :          74 :         ps.not_cast_mask = 0;
     726                 :          74 :         ps.block_init = 0;
     727                 :          74 :         ps.block_init_level = 0;
     728                 :          74 :         ps.just_saw_decl--;
     729                 :             : 
     730   [ +  +  +  +  :          74 :         if (ps.in_decl && s_code == e_code && !ps.block_init &&
                   +  - ]
     731   [ +  -  +  - ]:           1 :         !ps.dumped_decl_indent && ps.paren_level == 0) {
     732                 :             :         /* indent stray semicolons in declarations */
     733                 :           1 :         indent_declaration(dec_ind - 1, tabs_to_var);
     734                 :           1 :         ps.dumped_decl_indent = true;
     735                 :             :         }
     736                 :             : 
     737                 :          74 :         ps.in_decl = (ps.dec_nest > 0);  /* if we were in a first level
     738                 :             :                          * structure declaration, we
     739                 :             :                          * arent any more */
     740                 :             : 
     741   [ -  +  -  -  :          74 :         if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
                   -  + ]
     742                 :             : 
     743                 :             :         /*
     744                 :             :          * This should be true iff there were unbalanced parens in the
     745                 :             :          * stmt.  It is a bit complicated, because the semicolon might
     746                 :             :          * be in a for stmt
     747                 :             :          */
     748                 :           0 :         diag2(1, "Unbalanced parens");
     749                 :           0 :         ps.p_l_follow = 0;
     750         [ #  # ]:           0 :         if (sp_sw) {    /* this is a check for an if, while, etc. with
     751                 :             :                  * unbalanced parens */
     752                 :           0 :             sp_sw = false;
     753                 :           0 :             parse(hd_type); /* don't lose the if, or whatever */
     754                 :             :         }
     755                 :             :         }
     756                 :          74 :         *e_code++ = ';';
     757                 :          74 :         ps.want_blank = true;
     758                 :          74 :         ps.in_stmt = (ps.p_l_follow > 0);    /* we are no longer in the
     759                 :             :                          * middle of a stmt */
     760                 :             : 
     761         [ +  - ]:          74 :         if (!sp_sw) {   /* if not if for (;;) */
     762                 :          74 :         parse(semicolon);   /* let parser know about end of stmt */
     763                 :          74 :         force_nl = true;/* force newline after an end of stmt */
     764                 :             :         }
     765                 :          74 :         break;
     766                 :             : 
     767                 :          42 :     case lbrace:        /* got a '{' */
     768                 :          42 :         ps.in_stmt = false; /* don't indent the {} */
     769         [ +  + ]:          42 :         if (!ps.block_init)
     770                 :          33 :         force_nl = true;/* force other stuff on same line as '{' onto
     771                 :             :                  * new line */
     772         [ +  + ]:           9 :         else if (ps.block_init_level <= 0)
     773                 :           6 :         ps.block_init_level = 1;
     774                 :             :         else
     775                 :           3 :         ps.block_init_level++;
     776                 :             : 
     777   [ +  +  +  + ]:          42 :         if (s_code != e_code && !ps.block_init) {
     778         [ +  + ]:          29 :         if (!btype_2) {
     779                 :           1 :             dump_line();
     780                 :           1 :             ps.want_blank = false;
     781                 :             :         }
     782   [ +  +  +  - ]:          28 :         else if (ps.in_parameter_declaration && !ps.in_or_st) {
     783                 :          20 :             ps.i_l_follow = 0;
     784         [ +  - ]:          20 :             if (function_brace_split) { /* dump the line prior to the
     785                 :             :                          * brace ... */
     786                 :          20 :             dump_line();
     787                 :          20 :             ps.want_blank = false;
     788                 :             :             } else  /* add a space between the decl and brace */
     789                 :           0 :             ps.want_blank = true;
     790                 :             :         }
     791                 :             :         }
     792         [ +  + ]:          42 :         if (ps.in_parameter_declaration)
     793                 :          21 :         prefix_blankline_requested = 0;
     794                 :             : 
     795         [ -  + ]:          42 :         if (ps.p_l_follow > 0) { /* check for preceding unbalanced
     796                 :             :                      * parens */
     797                 :           0 :         diag2(1, "Unbalanced parens");
     798                 :           0 :         ps.p_l_follow = 0;
     799         [ #  # ]:           0 :         if (sp_sw) {    /* check for unclosed if, for, etc. */
     800                 :           0 :             sp_sw = false;
     801                 :           0 :             parse(hd_type);
     802                 :           0 :             ps.ind_level = ps.i_l_follow;
     803                 :             :         }
     804                 :             :         }
     805         [ +  + ]:          42 :         if (s_code == e_code)
     806                 :          29 :         ps.ind_stmt = false;    /* don't put extra indentation on line
     807                 :             :                      * with '{' */
     808   [ +  +  +  - ]:          42 :         if (ps.in_decl && ps.in_or_st) {    /* this is either a structure
     809                 :             :                          * declaration or an init */
     810                 :          14 :         di_stack[ps.dec_nest] = dec_ind;
     811         [ -  + ]:          14 :         if (++ps.dec_nest == nitems(di_stack)) {
     812                 :           0 :             diag3(0, "Reached internal limit of %zu struct levels",
     813                 :             :             nitems(di_stack));
     814                 :           0 :             ps.dec_nest--;
     815                 :             :         }
     816                 :             :         /* ?        dec_ind = 0; */
     817                 :             :         }
     818                 :             :         else {
     819                 :          28 :         ps.decl_on_line = false;    /* we can't be in the middle of
     820                 :             :                          * a declaration, so don't do
     821                 :             :                          * special indentation of
     822                 :             :                          * comments */
     823         [ -  + ]:          28 :         if (blanklines_after_declarations_at_proctop
     824         [ #  # ]:           0 :             && ps.in_parameter_declaration)
     825                 :           0 :             postfix_blankline_requested = 1;
     826                 :          28 :         ps.in_parameter_declaration = 0;
     827                 :          28 :         ps.in_decl = false;
     828                 :             :         }
     829                 :          42 :         dec_ind = 0;
     830                 :          42 :         parse(lbrace);  /* let parser know about this */
     831         [ +  + ]:          42 :         if (ps.want_blank)  /* put a blank before '{' if '{' is not at
     832                 :             :                  * start of line */
     833                 :          13 :         *e_code++ = ' ';
     834                 :          42 :         ps.want_blank = false;
     835                 :          42 :         *e_code++ = '{';
     836                 :          42 :         ps.just_saw_decl = 0;
     837                 :          42 :         break;
     838                 :             : 
     839                 :          42 :     case rbrace:        /* got a '}' */
     840   [ -  +  -  - ]:          42 :         if (ps.p_stack[ps.tos] == decl && !ps.block_init)   /* semicolons can be
     841                 :             :                                  * omitted in
     842                 :             :                                  * declarations */
     843                 :           0 :         parse(semicolon);
     844         [ -  + ]:          42 :         if (ps.p_l_follow) {/* check for unclosed if, for, else. */
     845                 :           0 :         diag2(1, "Unbalanced parens");
     846                 :           0 :         ps.p_l_follow = 0;
     847                 :           0 :         sp_sw = false;
     848                 :             :         }
     849                 :          42 :         ps.just_saw_decl = 0;
     850                 :          42 :         ps.block_init_level--;
     851   [ +  +  -  + ]:          42 :         if (s_code != e_code && !ps.block_init) {   /* '}' must be first on
     852                 :             :                              * line */
     853         [ #  # ]:           0 :         if (verbose)
     854                 :           0 :             diag2(0, "Line broken");
     855                 :           0 :         dump_line();
     856                 :             :         }
     857                 :          42 :         *e_code++ = '}';
     858                 :          42 :         ps.want_blank = true;
     859                 :          42 :         ps.in_stmt = ps.ind_stmt = false;
     860         [ +  + ]:          42 :         if (ps.dec_nest > 0) {   /* we are in multi-level structure
     861                 :             :                      * declaration */
     862                 :          14 :         dec_ind = di_stack[--ps.dec_nest];
     863   [ +  +  +  - ]:          14 :         if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
     864                 :          11 :             ps.just_saw_decl = 2;
     865                 :          14 :         ps.in_decl = true;
     866                 :             :         }
     867                 :          42 :         prefix_blankline_requested = 0;
     868                 :          42 :         parse(rbrace);  /* let parser know about this */
     869         [ +  + ]:          42 :         ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
     870   [ +  -  +  - ]:          84 :         && ps.il[ps.tos] >= ps.ind_level;
     871   [ +  +  -  +  :          42 :         if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
                   -  - ]
     872                 :           0 :         postfix_blankline_requested = 1;
     873                 :          42 :         break;
     874                 :             : 
     875                 :           1 :     case swstmt:        /* got keyword "switch" */
     876                 :           1 :         sp_sw = true;
     877                 :           1 :         hd_type = swstmt;   /* keep this for when we have seen the
     878                 :             :                  * expression */
     879                 :           1 :         goto copy_id;   /* go move the token into buffer */
     880                 :             : 
     881                 :          10 :     case sp_paren:      /* token is if, while, for */
     882                 :          10 :         sp_sw = true;   /* the interesting stuff is done after the
     883                 :             :                  * expression is scanned */
     884         [ -  + ]:          10 :         hd_type = (*token == 'i' ? ifstmt :
     885         [ #  # ]:           0 :                (*token == 'w' ? whilestmt : forstmt));
     886                 :             : 
     887                 :             :         /*
     888                 :             :          * remember the type of header for later use by parser
     889                 :             :          */
     890                 :          10 :         goto copy_id;   /* copy the token into line */
     891                 :             : 
     892                 :           5 :     case sp_nparen: /* got else, do */
     893                 :           5 :         ps.in_stmt = false;
     894         [ +  - ]:           5 :         if (*token == 'e') {
     895   [ +  +  +  -  :           5 :         if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
                   -  + ]
     896         [ #  # ]:           0 :             if (verbose)
     897                 :           0 :             diag2(0, "Line broken");
     898                 :           0 :             dump_line();/* make sure this starts a line */
     899                 :           0 :             ps.want_blank = false;
     900                 :             :         }
     901                 :           5 :         force_nl = true;/* also, following stuff must go onto new line */
     902                 :           5 :         last_else = 1;
     903                 :           5 :         parse(elselit);
     904                 :             :         }
     905                 :             :         else {
     906         [ #  # ]:           0 :         if (e_code != s_code) { /* make sure this starts a line */
     907         [ #  # ]:           0 :             if (verbose)
     908                 :           0 :             diag2(0, "Line broken");
     909                 :           0 :             dump_line();
     910                 :           0 :             ps.want_blank = false;
     911                 :             :         }
     912                 :           0 :         force_nl = true;/* also, following stuff must go onto new line */
     913                 :           0 :         last_else = 0;
     914                 :           0 :         parse(dolit);
     915                 :             :         }
     916                 :           5 :         goto copy_id;   /* move the token into line */
     917                 :             : 
     918                 :          16 :     case type_def:
     919                 :             :     case storage:
     920                 :          16 :         prefix_blankline_requested = 0;
     921                 :          16 :         goto copy_id;
     922                 :             : 
     923                 :          19 :     case structure:
     924         [ +  + ]:          19 :         if (ps.p_l_follow > 0)
     925                 :          10 :         goto copy_id;
     926                 :             :         pg_fallthrough;
     927                 :             :     case decl:      /* we have a declaration type (int, etc.) */
     928                 :          89 :         parse(decl);    /* let parser worry about indentation */
     929   [ +  +  +  + ]:          89 :         if (ps.last_token == rparen && ps.tos <= 1) {
     930         [ -  + ]:           1 :         if (s_code != e_code) {
     931                 :           0 :             dump_line();
     932                 :           0 :             ps.want_blank = 0;
     933                 :             :         }
     934                 :             :         }
     935   [ -  +  -  -  :          89 :         if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
                   -  - ]
     936                 :           0 :         ps.ind_level = ps.i_l_follow = 1;
     937                 :           0 :         ps.ind_stmt = 0;
     938                 :             :         }
     939                 :          89 :         ps.in_or_st = true; /* this might be a structure or initialization
     940                 :             :                  * declaration */
     941                 :          89 :         ps.in_decl = ps.decl_on_line = true;
     942         [ +  + ]:          89 :         if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
     943                 :          83 :         ps.just_saw_decl = 2;
     944                 :          89 :         prefix_blankline_requested = 0;
     945         [ +  + ]:         461 :         for (i = 0; token[i++];);   /* get length of token */
     946                 :             : 
     947   [ +  +  +  + ]:          89 :         if (ps.ind_level == 0 || ps.dec_nest > 0) {
     948                 :             :         /* global variable or struct member in local variable */
     949         [ +  - ]:          56 :         dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
     950   [ +  +  +  - ]:          56 :         tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0);
     951                 :             :         } else {
     952                 :             :         /* local variable */
     953         [ +  - ]:          33 :         dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i;
     954   [ +  -  +  - ]:          33 :         tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0);
     955                 :             :         }
     956                 :          89 :         goto copy_id;
     957                 :             : 
     958                 :         283 :     case funcname:
     959                 :             :     case ident:     /* got an identifier or constant */
     960         [ +  + ]:         283 :         if (ps.in_decl) {
     961         [ +  + ]:         186 :         if (type_code == funcname) {
     962                 :          21 :             ps.in_decl = false;
     963   [ +  -  +  + ]:          21 :             if (procnames_start_line && s_code != e_code) {
     964                 :          15 :             *e_code = '\0';
     965                 :          15 :             dump_line();
     966                 :             :             }
     967         [ -  + ]:           6 :             else if (ps.want_blank) {
     968                 :           0 :             *e_code++ = ' ';
     969                 :             :             }
     970                 :          21 :             ps.want_blank = false;
     971                 :             :         }
     972   [ +  +  +  + ]:         165 :         else if (!ps.block_init && !ps.dumped_decl_indent &&
     973         [ +  + ]:          59 :             ps.paren_level == 0) { /* if we are in a declaration, we
     974                 :             :                         * must indent identifier */
     975                 :          51 :             indent_declaration(dec_ind, tabs_to_var);
     976                 :          51 :             ps.dumped_decl_indent = true;
     977                 :          51 :             ps.want_blank = false;
     978                 :             :         }
     979                 :             :         }
     980   [ +  +  +  - ]:          97 :         else if (sp_sw && ps.p_l_follow == 0) {
     981                 :           0 :         sp_sw = false;
     982                 :           0 :         force_nl = true;
     983                 :           0 :         ps.last_u_d = true;
     984                 :           0 :         ps.in_stmt = false;
     985                 :           0 :         parse(hd_type);
     986                 :             :         }
     987                 :          97 :     copy_id:
     988                 :             :         {
     989                 :         416 :         int len = e_token - s_token;
     990                 :             : 
     991   [ -  +  -  - ]:         416 :         CHECK_SIZE_CODE(len + 1);
     992         [ +  + ]:         416 :         if (ps.want_blank)
     993                 :         104 :             *e_code++ = ' ';
     994                 :         416 :         memcpy(e_code, s_token, len);
     995                 :         416 :         e_code += len;
     996                 :             :         }
     997         [ +  + ]:         416 :         if (type_code != funcname)
     998                 :         394 :         ps.want_blank = true;
     999                 :         416 :         break;
    1000                 :             : 
    1001                 :           2 :     case strpfx:
    1002                 :             :         {
    1003                 :           2 :         int len = e_token - s_token;
    1004                 :             : 
    1005   [ -  +  -  - ]:           2 :         CHECK_SIZE_CODE(len + 1);
    1006         [ +  - ]:           2 :         if (ps.want_blank)
    1007                 :           2 :             *e_code++ = ' ';
    1008                 :           2 :         memcpy(e_code, token, len);
    1009                 :           2 :         e_code += len;
    1010                 :             :         }
    1011                 :           2 :         ps.want_blank = false;
    1012                 :           2 :         break;
    1013                 :             : 
    1014                 :           6 :     case period:        /* treat a period kind of like a binary
    1015                 :             :                  * operation */
    1016   [ +  +  +  + ]:           6 :         if (ps.want_blank && ps.last_token == comma)
    1017                 :           2 :             *e_code++ = ' ';
    1018                 :           6 :         *e_code++ = '.';    /* move the period into line */
    1019                 :           6 :         ps.want_blank = false;  /* don't put a blank after a period */
    1020                 :           6 :         break;
    1021                 :             : 
    1022                 :          56 :     case comma:
    1023                 :          56 :         ps.want_blank = (s_code != e_code); /* only put blank after comma
    1024                 :             :                          * if comma does not start the
    1025                 :             :                          * line */
    1026   [ +  +  +  -  :          56 :         if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init &&
                   +  + ]
    1027   [ +  +  +  + ]:          24 :         !ps.dumped_decl_indent && ps.paren_level == 0) {
    1028                 :             :         /* indent leading commas and not the actual identifiers */
    1029                 :           2 :         indent_declaration(dec_ind - 1, tabs_to_var);
    1030                 :           2 :         ps.dumped_decl_indent = true;
    1031                 :             :         }
    1032                 :          56 :         *e_code++ = ',';
    1033         [ +  + ]:          56 :         if (ps.p_l_follow == 0) {
    1034         [ +  + ]:          30 :         if (ps.block_init_level <= 0)
    1035                 :          17 :             ps.block_init = 0;
    1036   [ +  +  +  - ]:          30 :         if (break_comma && (!ps.leave_comma ||
    1037                 :          12 :             count_spaces_until(compute_code_target(), s_code, e_code) >
    1038         [ +  + ]:          12 :             max_col - tabsize))
    1039                 :           1 :             force_nl = true;
    1040                 :             :         }
    1041                 :          56 :         break;
    1042                 :             : 
    1043                 :          11 :     case preesc:        /* got the character '#' */
    1044         [ +  - ]:          11 :         if ((s_com != e_com) ||
    1045         [ +  - ]:          11 :             (s_lab != e_lab) ||
    1046         [ -  + ]:          11 :             (s_code != e_code))
    1047                 :           0 :         dump_line();
    1048   [ -  +  -  - ]:          11 :         CHECK_SIZE_LAB(1);
    1049                 :          11 :         *e_lab++ = '#'; /* move whole line to 'label' buffer */
    1050                 :             :         {
    1051                 :          11 :         int         in_comment = 0;
    1052                 :          11 :         int         com_start = 0;
    1053                 :          11 :         char        quote = 0;
    1054                 :          11 :         int         com_end = 0;
    1055                 :             : 
    1056   [ -  +  -  + ]:          22 :         while (*buf_ptr == ' ' || *buf_ptr == '\t') {
    1057                 :           0 :             buf_ptr++;
    1058         [ #  # ]:           0 :             if (buf_ptr >= buf_end)
    1059                 :           0 :             fill_buffer();
    1060                 :             :         }
    1061   [ +  +  -  +  :         181 :         while (*buf_ptr != '\n' || (in_comment && !had_eof)) {
                   -  - ]
    1062   [ -  +  -  - ]:         170 :             CHECK_SIZE_LAB(2);
    1063                 :         170 :             *e_lab = *buf_ptr++;
    1064         [ -  + ]:         170 :             if (buf_ptr >= buf_end)
    1065                 :           0 :             fill_buffer();
    1066   [ -  +  +  -  :         170 :             switch (*e_lab++) {
                   +  + ]
    1067                 :           0 :             case BACKSLASH:
    1068         [ #  # ]:           0 :             if (!in_comment) {
    1069                 :           0 :                 *e_lab++ = *buf_ptr++;
    1070         [ #  # ]:           0 :                 if (buf_ptr >= buf_end)
    1071                 :           0 :                 fill_buffer();
    1072                 :             :             }
    1073                 :           0 :             break;
    1074                 :           4 :             case '/':
    1075   [ +  -  +  -  :           4 :             if (*buf_ptr == '*' && !in_comment && !quote) {
                   +  - ]
    1076                 :           4 :                 in_comment = 1;
    1077                 :           4 :                 *e_lab++ = *buf_ptr++;
    1078                 :           4 :                 com_start = e_lab - s_lab - 2;
    1079                 :             :             }
    1080                 :           4 :             break;
    1081                 :           2 :             case '"':
    1082         [ -  + ]:           2 :             if (quote == '"')
    1083                 :           0 :                 quote = 0;
    1084                 :           2 :             break;
    1085                 :           0 :             case '\'':
    1086         [ #  # ]:           0 :             if (quote == '\'')
    1087                 :           0 :                 quote = 0;
    1088                 :           0 :             break;
    1089                 :           4 :             case '*':
    1090   [ +  -  +  - ]:           4 :             if (*buf_ptr == '/' && in_comment) {
    1091                 :           4 :                 in_comment = 0;
    1092                 :           4 :                 *e_lab++ = *buf_ptr++;
    1093                 :           4 :                 com_end = e_lab - s_lab;
    1094                 :             :             }
    1095                 :           4 :             break;
    1096                 :             :             }
    1097                 :             :         }
    1098                 :             : 
    1099   [ +  -  -  +  :          11 :         while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
                   -  + ]
    1100                 :           0 :             e_lab--;
    1101   [ +  +  +  - ]:          11 :         if (e_lab - s_lab == com_end && bp_save == NULL) {
    1102                 :             :             /* comment on preprocessor line */
    1103         [ +  - ]:           4 :             if (sc_end == NULL) {   /* if this is the first comment,
    1104                 :             :                          * we must set up the buffer */
    1105                 :           4 :             save_com = sc_buf;
    1106                 :           4 :             sc_end = &save_com[0];
    1107                 :             :             }
    1108                 :             :             else {
    1109                 :           0 :             *sc_end++ = '\n';   /* add newline between
    1110                 :             :                          * comments */
    1111                 :           0 :             *sc_end++ = ' ';
    1112                 :           0 :             --line_no;
    1113                 :             :             }
    1114         [ -  + ]:           4 :             if (sc_end - save_com + com_end - com_start > sc_size)
    1115                 :           0 :             errx(1, "input too long");
    1116                 :           4 :             memmove(sc_end, s_lab + com_start, com_end - com_start);
    1117                 :           4 :             sc_end += com_end - com_start;
    1118                 :           4 :             e_lab = s_lab + com_start;
    1119   [ +  -  +  +  :           9 :             while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
                   +  + ]
    1120                 :           5 :             e_lab--;
    1121                 :           4 :             bp_save = buf_ptr;  /* save current input buffer */
    1122                 :           4 :             be_save = buf_end;
    1123                 :           4 :             buf_ptr = save_com; /* fix so that subsequent calls to
    1124                 :             :                      * lexi will take tokens out of
    1125                 :             :                      * save_com */
    1126                 :           4 :             *sc_end++ = ' ';    /* add trailing blank, just in case */
    1127                 :           4 :             buf_end = sc_end;
    1128                 :           4 :             sc_end = NULL;
    1129                 :             :         }
    1130   [ -  +  -  - ]:          11 :         CHECK_SIZE_LAB(1);
    1131                 :          11 :         *e_lab = '\0';  /* null terminate line */
    1132                 :          11 :         ps.pcase = false;
    1133                 :             :         }
    1134                 :             : 
    1135         [ +  + ]:          11 :         if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */
    1136         [ +  - ]:           2 :         if ((size_t)ifdef_level < nitems(state_stack)) {
    1137                 :           2 :             match_state[ifdef_level].tos = -1;
    1138                 :           2 :             state_stack[ifdef_level++] = ps;
    1139                 :             :         }
    1140                 :             :         else
    1141                 :           0 :             diag2(1, "#if stack overflow");
    1142                 :             :         }
    1143         [ +  + ]:           9 :         else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */
    1144         [ -  + ]:           4 :         if (ifdef_level <= 0)
    1145         [ #  # ]:           0 :             diag2(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else");
    1146                 :             :         else {
    1147                 :           4 :             match_state[ifdef_level - 1] = ps;
    1148                 :           4 :             ps = state_stack[ifdef_level - 1];
    1149                 :             :         }
    1150                 :             :         }
    1151         [ +  + ]:           5 :         else if (strncmp(s_lab, "#endif", 6) == 0) {
    1152         [ -  + ]:           2 :         if (ifdef_level <= 0)
    1153                 :           0 :             diag2(1, "Unmatched #endif");
    1154                 :             :         else
    1155                 :           2 :             ifdef_level--;
    1156                 :             :         } else {
    1157                 :             :         struct directives {
    1158                 :             :             int size;
    1159                 :             :             const char *string;
    1160                 :             :         }
    1161                 :           3 :         recognized[] = {
    1162                 :             :             {7, "include"},
    1163                 :             :             {6, "define"},
    1164                 :             :             {5, "undef"},
    1165                 :             :             {4, "line"},
    1166                 :             :             {5, "error"},
    1167                 :             :             {6, "pragma"}
    1168                 :             :         };
    1169                 :           3 :         int d = nitems(recognized);
    1170         [ +  - ]:          13 :         while (--d >= 0)
    1171         [ +  + ]:          13 :             if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0)
    1172                 :           3 :             break;
    1173         [ -  + ]:           3 :         if (d < 0) {
    1174                 :           0 :             diag2(1, "Unrecognized cpp directive");
    1175                 :           0 :             break;
    1176                 :             :         }
    1177                 :             :         }
    1178         [ -  + ]:          11 :         if (blanklines_around_conditional_compilation) {
    1179                 :           0 :         postfix_blankline_requested++;
    1180                 :           0 :         n_real_blanklines = 0;
    1181                 :             :         }
    1182                 :             :         else {
    1183                 :          11 :         postfix_blankline_requested = 0;
    1184                 :          11 :         prefix_blankline_requested = 0;
    1185                 :             :         }
    1186                 :          11 :         break;      /* subsequent processing of the newline
    1187                 :             :                  * character will cause the line to be printed */
    1188                 :             : 
    1189                 :          58 :     case comment:       /* we have gotten a / followed by * this is a biggie */
    1190                 :          58 :         pr_comment();
    1191                 :          58 :         break;
    1192                 :             :     }           /* end of big switch stmt */
    1193                 :             : 
    1194                 :        1233 :     *e_code = '\0';     /* make sure code section is null terminated */
    1195   [ +  +  +  +  :        1233 :     if (type_code != comment && type_code != newline && type_code != preesc)
                   +  + ]
    1196                 :         883 :         ps.last_token = type_code;
    1197                 :             :     }               /* end of main while (1) loop */
    1198                 :             : }
    1199                 :             : 
    1200                 :             : /*
    1201                 :             :  * copy input file to backup file if in_name is /blah/blah/blah/file, then
    1202                 :             :  * backup file will be ".Bfile" then make the backup file the input and
    1203                 :             :  * original input file the output
    1204                 :             :  */
    1205                 :             : static void
    1206                 :           0 : bakcopy(void)
    1207                 :             : {
    1208                 :             :     int         n,
    1209                 :             :                 bakchn;
    1210                 :             :     char        buff[8 * 1024];
    1211                 :             :     const char *p;
    1212                 :             : 
    1213                 :             :     /* construct file name .Bfile */
    1214         [ #  # ]:           0 :     for (p = in_name; *p; p++); /* skip to end of string */
    1215   [ #  #  #  # ]:           0 :     while (p > in_name && *p != '/') /* find last '/' */
    1216                 :           0 :     p--;
    1217         [ #  # ]:           0 :     if (*p == '/')
    1218                 :           0 :     p++;
    1219                 :           0 :     sprintf(bakfile, "%s.BAK", p);
    1220                 :             : 
    1221                 :             :     /* copy in_name to backup file */
    1222                 :           0 :     bakchn = creat(bakfile, 0600);
    1223         [ #  # ]:           0 :     if (bakchn < 0)
    1224                 :           0 :     err(1, "%s", bakfile);
    1225         [ #  # ]:           0 :     while ((n = read(fileno(input), buff, sizeof(buff))) > 0)
    1226         [ #  # ]:           0 :     if (write(bakchn, buff, n) != n)
    1227                 :           0 :         err(1, "%s", bakfile);
    1228         [ #  # ]:           0 :     if (n < 0)
    1229                 :           0 :     err(1, "%s", in_name);
    1230                 :           0 :     close(bakchn);
    1231                 :           0 :     fclose(input);
    1232                 :             : 
    1233                 :             :     /* re-open backup file as the input file */
    1234                 :           0 :     input = fopen(bakfile, "r");
    1235         [ #  # ]:           0 :     if (input == NULL)
    1236                 :           0 :     err(1, "%s", bakfile);
    1237                 :             :     /* now the original input file will be the output */
    1238                 :           0 :     output = fopen(in_name, "wb");
    1239         [ #  # ]:           0 :     if (output == NULL) {
    1240                 :           0 :     unlink(bakfile);
    1241                 :           0 :     err(1, "%s", in_name);
    1242                 :             :     }
    1243                 :           0 : }
    1244                 :             : 
    1245                 :             : static void
    1246                 :          70 : indent_declaration(int cur_dec_ind, int tabs_to_var)
    1247                 :             : {
    1248                 :          70 :     int pos = e_code - s_code;
    1249                 :          70 :     char *startpos = e_code;
    1250                 :             : 
    1251                 :             :     /*
    1252                 :             :      * get the tab math right for indentations that are not multiples of tabsize
    1253                 :             :      */
    1254         [ -  + ]:          70 :     if ((ps.ind_level * ps.ind_size) % tabsize != 0) {
    1255                 :           0 :     pos += (ps.ind_level * ps.ind_size) % tabsize;
    1256                 :           0 :     cur_dec_ind += (ps.ind_level * ps.ind_size) % tabsize;
    1257                 :             :     }
    1258         [ +  - ]:          70 :     if (tabs_to_var) {
    1259                 :             :     int tpos;
    1260                 :             : 
    1261   [ -  +  -  - ]:          70 :     CHECK_SIZE_CODE(cur_dec_ind / tabsize);
    1262         [ +  + ]:         165 :     while ((tpos = tabsize * (1 + pos / tabsize)) <= cur_dec_ind) {
    1263         [ -  + ]:          95 :         *e_code++ = (!postgres_tab_rules ||
    1264         [ #  # ]:           0 :              tpos != pos + 1 ||
    1265         [ #  # ]:           0 :              cur_dec_ind >= tpos + tabsize) ? '\t' : ' ';
    1266                 :          95 :         pos = tpos;
    1267                 :             :     }
    1268                 :             :     }
    1269   [ -  +  -  - ]:          70 :     CHECK_SIZE_CODE(cur_dec_ind - pos + 1);
    1270         [ +  + ]:         158 :     while (pos < cur_dec_ind) {
    1271                 :          88 :     *e_code++ = ' ';
    1272                 :          88 :     pos++;
    1273                 :             :     }
    1274   [ +  +  +  + ]:          70 :     if (e_code == startpos && ps.want_blank) {
    1275                 :           3 :     *e_code++ = ' ';
    1276                 :           3 :     ps.want_blank = false;
    1277                 :             :     }
    1278                 :          70 : }
        

Generated by: LCOV version 2.0-1