LCOV - code coverage report
Current view: top level - src/tools/pg_bsd_indent - indent.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 565 733 77.1 %
Date: 2024-04-19 08:11:23 Functions: 2 3 66.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14