[BACK]Return to indent.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / indent

Annotation of src/usr.bin/indent/indent.c, Revision 1.51

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

CVSweb <webmaster@jp.NetBSD.org>