[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.167

1.167   ! rillig      1: /*     $NetBSD: indent.c,v 1.166 2021/10/28 22:06:23 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
                     41: static char sccsid[] = "@(#)indent.c   5.17 (Berkeley) 6/7/93";
                     42: #endif
1.1       cgd        43:
1.25      kamil      44: #include <sys/cdefs.h>
                     45: #if defined(__NetBSD__)
1.167   ! rillig     46: __RCSID("$NetBSD: indent.c,v 1.166 2021/10/28 22:06:23 rillig Exp $");
1.25      kamil      47: #elif defined(__FreeBSD__)
                     48: __FBSDID("$FreeBSD: head/usr.bin/indent/indent.c 340138 2018-11-04 19:24:49Z oshogbo $");
                     49: #endif
1.1       cgd        50:
                     51: #include <sys/param.h>
1.25      kamil      52: #if HAVE_CAPSICUM
                     53: #include <sys/capsicum.h>
                     54: #include <capsicum_helpers.h>
                     55: #endif
1.82      rillig     56: #include <ctype.h>
1.6       lukem      57: #include <err.h>
                     58: #include <errno.h>
1.1       cgd        59: #include <fcntl.h>
                     60: #include <stdio.h>
                     61: #include <stdlib.h>
                     62: #include <string.h>
1.82      rillig     63: #include <unistd.h>
1.29      rillig     64:
1.25      kamil      65: #include "indent.h"
                     66:
1.71      rillig     67: struct options opt = {
1.122     rillig     68:     .brace_same_line = true,
1.86      rillig     69:     .comment_delimiter_on_blankline = true,
                     70:     .cuddle_else = true,
                     71:     .comment_column = 33,
                     72:     .decl_indent = 16,
                     73:     .else_if = true,
                     74:     .function_brace_split = true,
                     75:     .format_col1_comments = true,
                     76:     .format_block_comments = true,
                     77:     .indent_parameters = true,
                     78:     .indent_size = 8,
                     79:     .local_decl_indent = -1,
                     80:     .lineup_to_parens = true,
                     81:     .procnames_start_line = true,
                     82:     .star_comment_cont = true,
                     83:     .tabsize = 8,
                     84:     .max_line_length = 78,
                     85:     .use_tabs = true,
1.71      rillig     86: };
                     87:
1.27      joerg      88: struct parser_state ps;
                     89:
1.63      rillig     90: struct buffer lab;
1.65      rillig     91: struct buffer code;
1.63      rillig     92: struct buffer com;
1.67      rillig     93: struct buffer token;
1.27      joerg      94:
1.124     rillig     95: struct buffer inp;
1.86      rillig     96:
                     97: char sc_buf[sc_size];
                     98: char *save_com;
1.88      rillig     99: static char *sc_end;           /* pointer into save_com buffer */
1.86      rillig    100:
1.125     rillig    101: char *saved_inp_s;
                    102: char *saved_inp_e;
1.86      rillig    103:
                    104: bool found_err;
1.140     rillig    105: int blank_lines_to_output;
1.142     rillig    106: bool blank_line_before;
                    107: bool blank_line_after;
1.86      rillig    108: bool break_comma;
                    109: float case_ind;
                    110: bool had_eof;
                    111: int line_no;
                    112: bool inhibit_formatting;
1.27      joerg     113:
1.88      rillig    114: static int ifdef_level;
                    115: static struct parser_state state_stack[5];
1.27      joerg     116:
1.86      rillig    117: FILE *input;
                    118: FILE *output;
1.27      joerg     119:
1.88      rillig    120: static const char *in_name = "Standard Input";
                    121: static const char *out_name = "Standard Output";
                    122: static const char *backup_suffix = ".BAK";
                    123: static char bakfile[MAXPATHLEN] = "";
1.1       cgd       124:
1.40      rillig    125: #if HAVE_CAPSICUM
                    126: static void
                    127: init_capsicum(void)
1.1       cgd       128: {
1.25      kamil     129:     cap_rights_t rights;
1.40      rillig    130:
                    131:     /* Restrict input/output descriptors and enter Capsicum sandbox. */
                    132:     cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
                    133:     if (caph_rights_limit(fileno(output), &rights) < 0)
                    134:        err(EXIT_FAILURE, "unable to limit rights for %s", out_name);
                    135:     cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
                    136:     if (caph_rights_limit(fileno(input), &rights) < 0)
                    137:        err(EXIT_FAILURE, "unable to limit rights for %s", in_name);
                    138:     if (caph_enter() < 0)
                    139:        err(EXIT_FAILURE, "unable to enter capability mode");
                    140: }
1.41      rillig    141: #endif
                    142:
1.148     rillig    143: void
                    144: diag(int level, const char *msg, ...)
                    145: {
                    146:     va_list ap;
                    147:
                    148:     if (level != 0)
                    149:        found_err = true;
                    150:
                    151:     va_start(ap, msg);
                    152:     fprintf(stderr, "%s: %s:%d: ",
                    153:        level == 0 ? "warning" : "error", in_name, line_no);
                    154:     vfprintf(stderr, msg, ap);
                    155:     fprintf(stderr, "\n");
                    156:     va_end(ap);
                    157: }
                    158:
1.41      rillig    159: static void
1.158     rillig    160: search_stmt_newline(bool *force_nl)
1.91      rillig    161: {
                    162:     if (sc_end == NULL) {
                    163:        save_com = sc_buf;
                    164:        save_com[0] = save_com[1] = ' ';
                    165:        sc_end = &save_com[2];
                    166:     }
                    167:     *sc_end++ = '\n';
                    168:
1.147     rillig    169:     line_no++;
                    170:
1.91      rillig    171:     /*
1.92      rillig    172:      * We may have inherited a force_nl == true from the previous token (like
                    173:      * a semicolon). But once we know that a newline has been scanned in this
                    174:      * loop, force_nl should be false.
1.91      rillig    175:      *
1.92      rillig    176:      * However, the force_nl == true must be preserved if newline is never
                    177:      * scanned in this loop, so this assignment cannot be done earlier.
1.91      rillig    178:      */
1.104     rillig    179:     *force_nl = false;
1.91      rillig    180: }
                    181:
                    182: static void
1.158     rillig    183: search_stmt_comment(bool *comment_buffered)
1.91      rillig    184: {
                    185:     if (sc_end == NULL) {
                    186:        /*
                    187:         * Copy everything from the start of the line, because
1.92      rillig    188:         * process_comment() will use that to calculate original indentation
                    189:         * of a boxed comment.
1.91      rillig    190:         */
1.124     rillig    191:        memcpy(sc_buf, inp.buf, (size_t)(inp.s - inp.buf) - 4);
                    192:        save_com = sc_buf + (inp.s - inp.buf - 4);
1.91      rillig    193:        save_com[0] = save_com[1] = ' ';
                    194:        sc_end = &save_com[2];
                    195:     }
1.119     rillig    196:
1.104     rillig    197:     *comment_buffered = true;
1.92      rillig    198:     *sc_end++ = '/';           /* copy in start of comment */
1.91      rillig    199:     *sc_end++ = '*';
1.119     rillig    200:
1.92      rillig    201:     for (;;) {                 /* loop until the end of the comment */
1.100     rillig    202:        *sc_end++ = inbuf_next();
1.124     rillig    203:        if (sc_end[-1] == '*' && *inp.s == '/')
1.92      rillig    204:            break;              /* we are at end of comment */
1.91      rillig    205:        if (sc_end >= &save_com[sc_size]) {     /* check for temp buffer
                    206:                                                 * overflow */
                    207:            diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
                    208:            fflush(output);
                    209:            exit(1);
                    210:        }
                    211:     }
1.119     rillig    212:
1.92      rillig    213:     *sc_end++ = '/';           /* add ending slash */
1.99      rillig    214:     inbuf_skip();              /* get past / in buffer */
1.91      rillig    215: }
                    216:
                    217: static bool
1.158     rillig    218: search_stmt_lbrace(void)
1.91      rillig    219: {
                    220:     /*
1.92      rillig    221:      * Put KNF-style lbraces before the buffered up tokens and jump out of
1.117     rillig    222:      * this loop in order to avoid copying the token again.
1.91      rillig    223:      */
1.122     rillig    224:     if (sc_end != NULL && opt.brace_same_line) {
1.91      rillig    225:        save_com[0] = '{';
                    226:        /*
1.92      rillig    227:         * Originally the lbrace may have been alone on its own line, but it
                    228:         * will be moved into "the else's line", so if there was a newline
                    229:         * resulting from the "{" before, it must be scanned now and ignored.
1.91      rillig    230:         */
1.124     rillig    231:        while (isspace((unsigned char)*inp.s)) {
1.99      rillig    232:            inbuf_skip();
1.124     rillig    233:            if (*inp.s == '\n')
1.91      rillig    234:                break;
                    235:        }
                    236:        return true;
                    237:     }
                    238:     return false;
                    239: }
                    240:
                    241: static bool
1.158     rillig    242: search_stmt_other(lexer_symbol lsym, bool *force_nl,
1.91      rillig    243:     bool comment_buffered, bool last_else)
                    244: {
                    245:     bool remove_newlines;
                    246:
                    247:     remove_newlines =
1.160     rillig    248:        /* "} else" */
                    249:        (lsym == lsym_else && code.e != code.s && code.e[-1] == '}')
                    250:        /* "else if" */
                    251:        || (lsym == lsym_if && last_else && opt.else_if);
1.91      rillig    252:     if (remove_newlines)
1.104     rillig    253:        *force_nl = false;
1.119     rillig    254:
1.91      rillig    255:     if (sc_end == NULL) {      /* ignore buffering if comment wasn't saved
                    256:                                 * up */
1.158     rillig    257:        ps.search_stmt = false;
1.91      rillig    258:        return false;
                    259:     }
1.119     rillig    260:
1.120     rillig    261:     while (sc_end > save_com && isblank((unsigned char)sc_end[-1]))
1.91      rillig    262:        sc_end--;
1.119     rillig    263:
1.91      rillig    264:     if (opt.swallow_optional_blanklines ||
                    265:        (!comment_buffered && remove_newlines)) {
1.104     rillig    266:        *force_nl = !remove_newlines;
1.91      rillig    267:        while (sc_end > save_com && sc_end[-1] == '\n') {
                    268:            sc_end--;
                    269:        }
                    270:     }
1.119     rillig    271:
1.117     rillig    272:     if (*force_nl) {           /* if we should insert a nl here, put it into
1.91      rillig    273:                                 * the buffer */
1.104     rillig    274:        *force_nl = false;
1.91      rillig    275:        --line_no;              /* this will be re-increased when the newline
                    276:                                 * is read from the buffer */
                    277:        *sc_end++ = '\n';
                    278:        *sc_end++ = ' ';
1.117     rillig    279:        if (opt.verbose)        /* warn if the line was not already broken */
1.91      rillig    280:            diag(0, "Line broken");
                    281:     }
1.119     rillig    282:
1.135     rillig    283:     /* XXX: buffer overflow? This is essentially a strcpy. */
1.91      rillig    284:     for (const char *t_ptr = token.s; *t_ptr != '\0'; ++t_ptr)
                    285:        *sc_end++ = *t_ptr;
                    286:     return true;
                    287: }
                    288:
                    289: static void
                    290: switch_buffer(void)
                    291: {
1.158     rillig    292:     ps.search_stmt = false;
1.139     rillig    293:     saved_inp_s = inp.s;       /* save current input buffer */
1.125     rillig    294:     saved_inp_e = inp.e;
1.124     rillig    295:     inp.s = save_com;          /* fix so that subsequent calls to lexi will
1.91      rillig    296:                                 * take tokens out of save_com */
                    297:     *sc_end++ = ' ';           /* add trailing blank, just in case */
1.124     rillig    298:     inp.e = sc_end;
1.91      rillig    299:     sc_end = NULL;
1.124     rillig    300:     debug_println("switched inp.s to save_com");
1.91      rillig    301: }
                    302:
                    303: static void
1.158     rillig    304: search_stmt_lookahead(lexer_symbol *lsym)
1.91      rillig    305: {
1.156     rillig    306:     if (*lsym == lsym_eof)
1.115     rillig    307:        return;
                    308:
1.91      rillig    309:     /*
1.149     rillig    310:      * The only intended purpose of calling lexi() below is to categorize the
                    311:      * next token in order to decide whether to continue buffering forthcoming
                    312:      * tokens. Once the buffering is over, lexi() will be called again
                    313:      * elsewhere on all of the tokens - this time for normal processing.
1.115     rillig    314:      *
1.149     rillig    315:      * Calling it for this purpose is a bug, because lexi() also changes the
                    316:      * parser state and discards leading whitespace, which is needed mostly
                    317:      * for comment-related considerations.
1.115     rillig    318:      *
1.149     rillig    319:      * Work around the former problem by giving lexi() a copy of the current
                    320:      * parser state and discard it if the call turned out to be just a
                    321:      * lookahead.
1.115     rillig    322:      *
                    323:      * Work around the latter problem by copying all whitespace characters
                    324:      * into the buffer so that the later lexi() call will read them.
1.91      rillig    325:      */
1.115     rillig    326:     if (sc_end != NULL) {
1.124     rillig    327:        while (is_hspace(*inp.s)) {
                    328:            *sc_end++ = *inp.s++;
1.115     rillig    329:            if (sc_end >= &save_com[sc_size])
                    330:                errx(1, "input too long");
1.91      rillig    331:        }
1.124     rillig    332:        if (inp.s >= inp.e)
1.133     rillig    333:            inbuf_read_line();
1.115     rillig    334:     }
1.91      rillig    335:
1.165     rillig    336:     struct parser_state backup_ps = ps;
                    337:     *lsym = lexi();
                    338:     if (*lsym == lsym_newline || *lsym == lsym_form_feed ||
1.166     rillig    339:        *lsym == lsym_comment || ps.search_stmt) {
1.165     rillig    340:        ps = backup_ps;
1.166     rillig    341:        debug_println("rolled back parser state");
                    342:     }
1.91      rillig    343: }
                    344:
1.164     rillig    345: /*
                    346:  * Move newlines and comments following an 'if (expr)', 'while (expr)',
                    347:  * 'else', etc. up to the start of the following statement to a buffer. This
                    348:  * allows proper handling of both kinds of brace placement (-br, -bl) and
                    349:  * "cuddling else" (-ce).
                    350:  */
1.91      rillig    351: static void
1.158     rillig    352: search_stmt(lexer_symbol *lsym, bool *force_nl,
1.104     rillig    353:     bool *comment_buffered, bool *last_else)
1.41      rillig    354: {
1.158     rillig    355:     while (ps.search_stmt) {
1.156     rillig    356:        switch (*lsym) {
                    357:        case lsym_newline:
1.158     rillig    358:            search_stmt_newline(force_nl);
1.59      rillig    359:            break;
1.156     rillig    360:        case lsym_form_feed:
1.41      rillig    361:            break;
1.156     rillig    362:        case lsym_comment:
1.158     rillig    363:            search_stmt_comment(comment_buffered);
1.41      rillig    364:            break;
1.156     rillig    365:        case lsym_lbrace:
1.158     rillig    366:            if (search_stmt_lbrace())
1.115     rillig    367:                goto switch_buffer;
1.41      rillig    368:            /* FALLTHROUGH */
                    369:        default:                /* it is the start of a normal statement */
1.158     rillig    370:            if (!search_stmt_other(*lsym, force_nl,
1.104     rillig    371:                    *comment_buffered, *last_else))
1.41      rillig    372:                return;
1.149     rillig    373:     switch_buffer:
1.91      rillig    374:            switch_buffer();
1.41      rillig    375:        }
1.158     rillig    376:        search_stmt_lookahead(lsym);
1.41      rillig    377:     }
1.40      rillig    378:
1.104     rillig    379:     *last_else = false;
1.41      rillig    380: }
1.1       cgd       381:
1.53      rillig    382: static void
1.72      rillig    383: buf_init(struct buffer *buf)
                    384: {
1.123     rillig    385:     size_t size = 200;
                    386:     buf->buf = xmalloc(size);
1.86      rillig    387:     buf->buf[0] = ' ';         /* allow accessing buf->e[-1] */
1.72      rillig    388:     buf->buf[1] = '\0';
                    389:     buf->s = buf->buf + 1;
                    390:     buf->e = buf->s;
1.123     rillig    391:     buf->l = buf->buf + size - 5;      /* safety margin */
1.72      rillig    392: }
                    393:
1.110     rillig    394: static size_t
                    395: buf_len(const struct buffer *buf)
                    396: {
                    397:     return (size_t)(buf->e - buf->s);
                    398: }
                    399:
1.81      rillig    400: void
                    401: buf_expand(struct buffer *buf, size_t desired_size)
                    402: {
1.110     rillig    403:     size_t nsize = (size_t)(buf->l - buf->s) + 400 + desired_size;
                    404:     size_t len = buf_len(buf);
1.81      rillig    405:     buf->buf = xrealloc(buf->buf, nsize);
1.110     rillig    406:     buf->e = buf->buf + len + 1;
1.81      rillig    407:     buf->l = buf->buf + nsize - 5;
                    408:     buf->s = buf->buf + 1;
                    409: }
                    410:
1.72      rillig    411: static void
1.112     rillig    412: buf_reserve(struct buffer *buf, size_t n)
                    413: {
                    414:     if (buf->e + n >= buf->l)
                    415:        buf_expand(buf, n);
                    416: }
                    417:
                    418: static void
                    419: buf_add_char(struct buffer *buf, char ch)
                    420: {
                    421:     buf_reserve(buf, 1);
                    422:     *buf->e++ = ch;
                    423: }
                    424:
                    425: static void
                    426: buf_add_buf(struct buffer *buf, const struct buffer *add)
                    427: {
                    428:     size_t len = buf_len(add);
                    429:     buf_reserve(buf, len);
                    430:     memcpy(buf->e, add->s, len);
                    431:     buf->e += len;
                    432: }
                    433:
                    434: static void
                    435: buf_terminate(struct buffer *buf)
                    436: {
                    437:     buf_reserve(buf, 1);
                    438:     *buf->e = '\0';
                    439: }
                    440:
                    441: static void
                    442: buf_reset(struct buffer *buf)
                    443: {
                    444:     buf->e = buf->s;
                    445: }
                    446:
                    447: static void
1.53      rillig    448: main_init_globals(void)
1.40      rillig    449: {
1.83      rillig    450:     found_err = false;
1.1       cgd       451:
1.156     rillig    452:     ps.s_sym[0] = psym_stmt;
1.116     rillig    453:     ps.last_nl = true;
1.156     rillig    454:     ps.last_token = lsym_semicolon;
1.72      rillig    455:     buf_init(&com);
                    456:     buf_init(&lab);
                    457:     buf_init(&code);
                    458:     buf_init(&token);
1.119     rillig    459:
1.73      rillig    460:     opt.else_if = true;                /* XXX: redundant? */
1.25      kamil     461:
1.124     rillig    462:     inp.buf = xmalloc(10);
                    463:     inp.l = inp.buf + 8;
                    464:     inp.s = inp.e = inp.buf;
1.25      kamil     465:     line_no = 1;
1.121     rillig    466:     had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
1.119     rillig    467:
1.134     rillig    468:     ps.init_or_struct = false;
1.25      kamil     469:     ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
1.119     rillig    470:     ps.is_case_label = false;
1.25      kamil     471:
                    472:     sc_end = NULL;
1.125     rillig    473:     saved_inp_s = NULL;
                    474:     saved_inp_e = NULL;
1.25      kamil     475:
                    476:     output = NULL;
                    477:
1.53      rillig    478:     const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX");
                    479:     if (suffix != NULL)
1.88      rillig    480:        backup_suffix = suffix;
1.53      rillig    481: }
                    482:
1.131     rillig    483: /*
                    484:  * Copy the input file to the backup file, then make the backup file the input
                    485:  * and the original input file the output.
                    486:  */
                    487: static void
                    488: bakcopy(void)
                    489: {
                    490:     ssize_t n;
                    491:     int bak_fd;
                    492:     char buff[8 * 1024];
                    493:
                    494:     const char *last_slash = strrchr(in_name, '/');
                    495:     snprintf(bakfile, sizeof(bakfile), "%s%s",
1.149     rillig    496:        last_slash != NULL ? last_slash + 1 : in_name, backup_suffix);
1.131     rillig    497:
                    498:     /* copy in_name to backup file */
                    499:     bak_fd = creat(bakfile, 0600);
                    500:     if (bak_fd < 0)
                    501:        err(1, "%s", bakfile);
                    502:
                    503:     while ((n = read(fileno(input), buff, sizeof(buff))) > 0)
                    504:        if (write(bak_fd, buff, (size_t)n) != n)
                    505:            err(1, "%s", bakfile);
                    506:     if (n < 0)
                    507:        err(1, "%s", in_name);
                    508:
                    509:     close(bak_fd);
                    510:     (void)fclose(input);
                    511:
                    512:     /* re-open backup file as the input file */
                    513:     input = fopen(bakfile, "r");
                    514:     if (input == NULL)
                    515:        err(1, "%s", bakfile);
                    516:     /* now the original input file will be the output */
                    517:     output = fopen(in_name, "w");
                    518:     if (output == NULL) {
                    519:        unlink(bakfile);
                    520:        err(1, "%s", in_name);
                    521:     }
                    522: }
                    523:
1.53      rillig    524: static void
                    525: main_parse_command_line(int argc, char **argv)
                    526: {
                    527:     int i;
                    528:     const char *profile_name = NULL;
1.1       cgd       529:
1.25      kamil     530:     for (i = 1; i < argc; ++i)
                    531:        if (strcmp(argv[i], "-npro") == 0)
                    532:            break;
                    533:        else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0')
1.97      rillig    534:            profile_name = argv[i] + 2; /* non-empty -P (set profile) */
1.25      kamil     535:     if (i >= argc)
1.98      rillig    536:        load_profiles(profile_name);
1.1       cgd       537:
1.25      kamil     538:     for (i = 1; i < argc; ++i) {
1.80      rillig    539:        if (argv[i][0] == '-') {
1.114     rillig    540:            set_option(argv[i], "Command line");
1.80      rillig    541:
                    542:        } else if (input == NULL) {
                    543:            in_name = argv[i];
                    544:            input = fopen(in_name, "r");
                    545:            if (input == NULL)
                    546:                err(1, "%s", in_name);
                    547:
                    548:        } else if (output == NULL) {
                    549:            out_name = argv[i];
                    550:            if (strcmp(in_name, out_name) == 0)
                    551:                errx(1, "input and output files must be different");
                    552:            output = fopen(out_name, "w");
                    553:            if (output == NULL)
                    554:                err(1, "%s", out_name);
1.1       cgd       555:
1.80      rillig    556:        } else
1.163     rillig    557:            errx(1, "too many arguments: %s", argv[i]);
1.80      rillig    558:     }
                    559:
1.25      kamil     560:     if (input == NULL)
                    561:        input = stdin;
                    562:     if (output == NULL) {
                    563:        if (input == stdin)
                    564:            output = stdout;
                    565:        else {
                    566:            out_name = in_name;
                    567:            bakcopy();
1.1       cgd       568:        }
1.25      kamil     569:     }
                    570:
1.57      rillig    571:     if (opt.comment_column <= 1)
                    572:        opt.comment_column = 2; /* don't put normal comments before column 2 */
1.51      rillig    573:     if (opt.block_comment_max_line_length <= 0)
                    574:        opt.block_comment_max_line_length = opt.max_line_length;
1.100     rillig    575:     if (opt.local_decl_indent < 0)     /* if not specified by user, set this */
1.25      kamil     576:        opt.local_decl_indent = opt.decl_indent;
1.57      rillig    577:     if (opt.decl_comment_column <= 0)  /* if not specified by user, set this */
                    578:        opt.decl_comment_column = opt.ljust_decl
                    579:            ? (opt.comment_column <= 10 ? 2 : opt.comment_column - 8)
                    580:            : opt.comment_column;
1.25      kamil     581:     if (opt.continuation_indent == 0)
1.57      rillig    582:        opt.continuation_indent = opt.indent_size;
1.53      rillig    583: }
                    584:
                    585: static void
                    586: main_prepare_parsing(void)
                    587: {
1.133     rillig    588:     inbuf_read_line();
1.25      kamil     589:
1.156     rillig    590:     parse(psym_semicolon);
1.53      rillig    591:
1.106     rillig    592:     int ind = 0;
1.137     rillig    593:     for (const char *p = inp.s;; p++) {
1.53      rillig    594:        if (*p == ' ')
1.106     rillig    595:            ind++;
1.53      rillig    596:        else if (*p == '\t')
1.136     rillig    597:            ind = next_tab(ind);
1.53      rillig    598:        else
                    599:            break;
1.25      kamil     600:     }
1.137     rillig    601:
1.106     rillig    602:     if (ind >= opt.indent_size)
1.107     rillig    603:        ps.ind_level = ps.ind_level_follow = ind / opt.indent_size;
1.53      rillig    604: }
1.25      kamil     605:
1.131     rillig    606: static void
                    607: indent_declaration(int cur_decl_ind, bool tabs_to_var)
                    608: {
1.137     rillig    609:     int ind = (int)buf_len(&code);
1.131     rillig    610:     char *orig_code_e = code.e;
                    611:
                    612:     /*
                    613:      * get the tab math right for indentations that are not multiples of
                    614:      * tabsize
                    615:      */
                    616:     if ((ps.ind_level * opt.indent_size) % opt.tabsize != 0) {
1.137     rillig    617:        ind += (ps.ind_level * opt.indent_size) % opt.tabsize;
1.131     rillig    618:        cur_decl_ind += (ps.ind_level * opt.indent_size) % opt.tabsize;
                    619:     }
                    620:
                    621:     if (tabs_to_var) {
1.137     rillig    622:        for (int next; (next = next_tab(ind)) <= cur_decl_ind; ind = next)
1.131     rillig    623:            buf_add_char(&code, '\t');
                    624:     }
                    625:
1.137     rillig    626:     for (; ind < cur_decl_ind; ind++)
1.131     rillig    627:        buf_add_char(&code, ' ');
                    628:
                    629:     if (code.e == orig_code_e && ps.want_blank) {
                    630:        *code.e++ = ' ';
                    631:        ps.want_blank = false;
                    632:     }
                    633: }
                    634:
1.60      rillig    635: static void __attribute__((__noreturn__))
1.54      rillig    636: process_end_of_file(void)
                    637: {
1.65      rillig    638:     if (lab.s != lab.e || code.s != code.e || com.s != com.e)
1.54      rillig    639:        dump_line();
                    640:
                    641:     if (ps.tos > 1)            /* check for balanced braces */
                    642:        diag(1, "Stuff missing from end of file");
                    643:
                    644:     if (opt.verbose) {
                    645:        printf("There were %d output lines and %d comments\n",
1.86      rillig    646:            ps.stats.lines, ps.stats.comments);
1.54      rillig    647:        printf("(Lines with comments)/(Lines with code): %6.3f\n",
1.86      rillig    648:            (1.0 * ps.stats.comment_lines) / ps.stats.code_lines);
1.54      rillig    649:     }
                    650:
                    651:     fflush(output);
1.83      rillig    652:     exit(found_err ? EXIT_FAILURE : EXIT_SUCCESS);
1.54      rillig    653: }
                    654:
                    655: static void
1.156     rillig    656: process_comment_in_code(lexer_symbol lsym, bool *force_nl)
1.54      rillig    657: {
1.104     rillig    658:     if (*force_nl &&
1.156     rillig    659:        lsym != lsym_semicolon &&
                    660:        (lsym != lsym_lbrace || !opt.brace_same_line)) {
1.54      rillig    661:
                    662:        /* we should force a broken line here */
                    663:        if (opt.verbose)
                    664:            diag(0, "Line broken");
                    665:        dump_line();
1.102     rillig    666:        ps.want_blank = false;  /* don't insert blank at line start */
1.104     rillig    667:        *force_nl = false;
1.54      rillig    668:     }
                    669:
1.118     rillig    670:     /* add an extra level of indentation; turned off again by a ';' or '}' */
                    671:     ps.in_stmt = true;
                    672:
                    673:     if (com.s != com.e) {      /* a comment embedded in a line */
1.112     rillig    674:        buf_add_char(&code, ' ');
                    675:        buf_add_buf(&code, &com);
                    676:        buf_add_char(&code, ' ');
                    677:        buf_terminate(&code);
                    678:        buf_reset(&com);
1.54      rillig    679:        ps.want_blank = false;
                    680:     }
                    681: }
                    682:
                    683: static void
                    684: process_form_feed(void)
                    685: {
1.145     rillig    686:     dump_line_ff();
1.54      rillig    687:     ps.want_blank = false;
                    688: }
                    689:
                    690: static void
                    691: process_newline(void)
                    692: {
1.156     rillig    693:     if (ps.last_token == lsym_comma && ps.p_l_follow == 0 && !ps.block_init &&
1.141     rillig    694:        !opt.break_after_comma && break_comma &&
                    695:        com.s == com.e)
                    696:        goto stay_in_line;
                    697:
                    698:     dump_line();
                    699:     ps.want_blank = false;
                    700:
                    701: stay_in_line:
1.116     rillig    702:     ++line_no;
1.54      rillig    703: }
                    704:
1.94      rillig    705: static bool
                    706: want_blank_before_lparen(void)
                    707: {
1.95      rillig    708:     if (!ps.want_blank)
                    709:        return false;
1.156     rillig    710:     if (ps.last_token == lsym_rparen_or_rbracket)
1.96      rillig    711:        return false;
1.156     rillig    712:     if (ps.last_token != lsym_ident && ps.last_token != lsym_funcname)
1.95      rillig    713:        return true;
                    714:     if (opt.proc_calls_space)
                    715:        return true;
1.161     rillig    716:     if (ps.prev_keyword == kw_sizeof)
1.95      rillig    717:        return opt.blank_after_sizeof;
1.161     rillig    718:     return ps.prev_keyword != kw_0 && ps.prev_keyword != kw_offsetof;
1.94      rillig    719: }
                    720:
1.54      rillig    721: static void
1.157     rillig    722: process_lparen_or_lbracket(int decl_ind, bool tabs_to_var, bool spaced_expr)
1.54      rillig    723: {
1.146     rillig    724:     if (++ps.p_l_follow == array_length(ps.paren_indents)) {
1.54      rillig    725:        diag(0, "Reached internal limit of %zu unclosed parens",
1.146     rillig    726:            array_length(ps.paren_indents));
1.54      rillig    727:        ps.p_l_follow--;
                    728:     }
1.119     rillig    729:
1.93      rillig    730:     if (token.s[0] == '(' && ps.in_decl
                    731:        && !ps.block_init && !ps.dumped_decl_indent &&
1.54      rillig    732:        ps.procname[0] == '\0' && ps.paren_level == 0) {
                    733:        /* function pointer declarations */
1.105     rillig    734:        indent_declaration(decl_ind, tabs_to_var);
1.54      rillig    735:        ps.dumped_decl_indent = true;
1.94      rillig    736:     } else if (want_blank_before_lparen())
1.65      rillig    737:        *code.e++ = ' ';
1.54      rillig    738:     ps.want_blank = false;
1.67      rillig    739:     *code.e++ = token.s[0];
1.58      rillig    740:
1.54      rillig    741:     ps.paren_indents[ps.p_l_follow - 1] =
1.103     rillig    742:        (short)indentation_after_range(0, code.s, code.e);
1.135     rillig    743:     debug_println("paren_indents[%d] is now %d",
1.58      rillig    744:        ps.p_l_follow - 1, ps.paren_indents[ps.p_l_follow - 1]);
                    745:
1.157     rillig    746:     if (spaced_expr && ps.p_l_follow == 1 && opt.extra_expr_indent
1.58      rillig    747:            && ps.paren_indents[0] < 2 * opt.indent_size) {
1.103     rillig    748:        ps.paren_indents[0] = (short)(2 * opt.indent_size);
1.135     rillig    749:        debug_println("paren_indents[0] is now %d", ps.paren_indents[0]);
1.58      rillig    750:     }
1.119     rillig    751:
1.134     rillig    752:     if (ps.init_or_struct && *token.s == '(' && ps.tos <= 2) {
1.54      rillig    753:        /*
1.86      rillig    754:         * this is a kluge to make sure that declarations will be aligned
                    755:         * right if proc decl has an explicit type on it, i.e. "int a(x) {..."
1.54      rillig    756:         */
1.156     rillig    757:        parse(psym_semicolon);  /* I said this was a kluge... */
1.134     rillig    758:        ps.init_or_struct = false;
1.54      rillig    759:     }
1.119     rillig    760:
1.54      rillig    761:     /* parenthesized type following sizeof or offsetof is not a cast */
1.161     rillig    762:     if (ps.prev_keyword == kw_offsetof || ps.prev_keyword == kw_sizeof)
1.54      rillig    763:        ps.not_cast_mask |= 1 << ps.p_l_follow;
                    764: }
                    765:
                    766: static void
1.157     rillig    767: process_rparen_or_rbracket(bool *spaced_expr, bool *force_nl, stmt_head hd)
1.54      rillig    768: {
1.73      rillig    769:     if ((ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) != 0) {
1.144     rillig    770:        ps.next_unary = true;
1.54      rillig    771:        ps.cast_mask &= (1 << ps.p_l_follow) - 1;
                    772:        ps.want_blank = opt.space_after_cast;
                    773:     } else
                    774:        ps.want_blank = true;
                    775:     ps.not_cast_mask &= (1 << ps.p_l_follow) - 1;
                    776:
                    777:     if (--ps.p_l_follow < 0) {
                    778:        ps.p_l_follow = 0;
1.67      rillig    779:        diag(0, "Extra %c", *token.s);
1.54      rillig    780:     }
                    781:
1.65      rillig    782:     if (code.e == code.s)      /* if the paren starts the line */
1.54      rillig    783:        ps.paren_level = ps.p_l_follow; /* then indent it */
                    784:
1.67      rillig    785:     *code.e++ = token.s[0];
1.54      rillig    786:
1.157     rillig    787:     if (*spaced_expr && ps.p_l_follow == 0) {  /* check for end of 'if
                    788:                                                 * (...)', or some such */
                    789:        *spaced_expr = false;
1.104     rillig    790:        *force_nl = true;       /* must force newline after if */
1.144     rillig    791:        ps.next_unary = true;
1.102     rillig    792:        ps.in_stmt = false;     /* don't use stmt continuation indentation */
1.54      rillig    793:
1.167   ! rillig    794:        parse_stmt_head(hd);
1.54      rillig    795:     }
1.122     rillig    796:
                    797:     /*
                    798:      * This should ensure that constructs such as main(){...} and int[]{...}
                    799:      * have their braces put in the right place.
                    800:      */
1.158     rillig    801:     ps.search_stmt = opt.brace_same_line;
1.54      rillig    802: }
                    803:
                    804: static void
1.105     rillig    805: process_unary_op(int decl_ind, bool tabs_to_var)
1.54      rillig    806: {
                    807:     if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init &&
                    808:        ps.procname[0] == '\0' && ps.paren_level == 0) {
                    809:        /* pointer declarations */
1.132     rillig    810:        indent_declaration(decl_ind - (int)buf_len(&token), tabs_to_var);
1.54      rillig    811:        ps.dumped_decl_indent = true;
                    812:     } else if (ps.want_blank)
1.65      rillig    813:        *code.e++ = ' ';
1.54      rillig    814:
1.112     rillig    815:     buf_add_buf(&code, &token);
1.54      rillig    816:     ps.want_blank = false;
                    817: }
                    818:
                    819: static void
                    820: process_binary_op(void)
                    821: {
                    822:     if (ps.want_blank)
1.112     rillig    823:        buf_add_char(&code, ' ');
                    824:     buf_add_buf(&code, &token);
1.54      rillig    825:     ps.want_blank = true;
                    826: }
                    827:
                    828: static void
                    829: process_postfix_op(void)
                    830: {
1.67      rillig    831:     *code.e++ = token.s[0];
                    832:     *code.e++ = token.s[1];
1.54      rillig    833:     ps.want_blank = true;
                    834: }
                    835:
                    836: static void
1.152     rillig    837: process_question(int *quest_level)
1.54      rillig    838: {
1.152     rillig    839:     (*quest_level)++;
1.54      rillig    840:     if (ps.want_blank)
1.65      rillig    841:        *code.e++ = ' ';
                    842:     *code.e++ = '?';
1.54      rillig    843:     ps.want_blank = true;
                    844: }
                    845:
                    846: static void
1.152     rillig    847: process_colon(int *quest_level, bool *force_nl, bool *seen_case)
1.54      rillig    848: {
1.152     rillig    849:     if (*quest_level > 0) {    /* part of a '?:' operator */
                    850:        --*quest_level;
1.54      rillig    851:        if (ps.want_blank)
1.65      rillig    852:            *code.e++ = ' ';
                    853:        *code.e++ = ':';
1.54      rillig    854:        ps.want_blank = true;
                    855:        return;
                    856:     }
1.113     rillig    857:
1.149     rillig    858:     if (ps.init_or_struct) {   /* bit-field */
1.65      rillig    859:        *code.e++ = ':';
1.54      rillig    860:        ps.want_blank = false;
                    861:        return;
                    862:     }
                    863:
1.113     rillig    864:     buf_add_buf(&lab, &code);  /* 'case' or 'default' or named label */
1.112     rillig    865:     buf_add_char(&lab, ':');
                    866:     buf_terminate(&lab);
                    867:     buf_reset(&code);
                    868:
1.113     rillig    869:     ps.in_stmt = false;
                    870:     ps.is_case_label = *seen_case;
                    871:     *force_nl = *seen_case;
1.105     rillig    872:     *seen_case = false;
1.54      rillig    873:     ps.want_blank = false;
                    874: }
                    875:
                    876: static void
1.152     rillig    877: process_semicolon(bool *seen_case, int *quest_level, int decl_ind,
1.157     rillig    878:     bool tabs_to_var, bool *spaced_expr, stmt_head hd, bool *force_nl)
1.54      rillig    879: {
1.79      rillig    880:     if (ps.decl_nest == 0)
1.135     rillig    881:        ps.init_or_struct = false;
1.105     rillig    882:     *seen_case = false;                /* these will only need resetting in an error */
1.152     rillig    883:     *quest_level = 0;
1.156     rillig    884:     if (ps.last_token == lsym_rparen_or_rbracket)
1.73      rillig    885:        ps.in_parameter_declaration = false;
1.54      rillig    886:     ps.cast_mask = 0;
                    887:     ps.not_cast_mask = 0;
1.73      rillig    888:     ps.block_init = false;
1.54      rillig    889:     ps.block_init_level = 0;
                    890:     ps.just_saw_decl--;
                    891:
1.65      rillig    892:     if (ps.in_decl && code.s == code.e && !ps.block_init &&
1.54      rillig    893:        !ps.dumped_decl_indent && ps.paren_level == 0) {
                    894:        /* indent stray semicolons in declarations */
1.105     rillig    895:        indent_declaration(decl_ind - 1, tabs_to_var);
1.54      rillig    896:        ps.dumped_decl_indent = true;
                    897:     }
                    898:
1.135     rillig    899:     ps.in_decl = ps.decl_nest > 0;     /* if we were in a first level
1.102     rillig    900:                                         * structure declaration, we aren't
                    901:                                         * anymore */
1.54      rillig    902:
1.157     rillig    903:     if ((!*spaced_expr || hd != hd_for) && ps.p_l_follow > 0) {
1.54      rillig    904:
                    905:        /*
1.135     rillig    906:         * There were unbalanced parens in the statement. It is a bit
                    907:         * complicated, because the semicolon might be in a for statement.
1.54      rillig    908:         */
                    909:        diag(1, "Unbalanced parens");
                    910:        ps.p_l_follow = 0;
1.167   ! rillig    911:        if (*spaced_expr) {     /* 'if', 'while', etc. */
1.157     rillig    912:            *spaced_expr = false;
1.167   ! rillig    913:            parse_stmt_head(hd);
1.54      rillig    914:        }
                    915:     }
1.65      rillig    916:     *code.e++ = ';';
1.54      rillig    917:     ps.want_blank = true;
1.157     rillig    918:     ps.in_stmt = ps.p_l_follow > 0;    /* we are no longer in the middle of a
1.86      rillig    919:                                         * stmt */
1.54      rillig    920:
1.157     rillig    921:     if (!*spaced_expr) {       /* if not if for (;;) */
1.156     rillig    922:        parse(psym_semicolon);  /* let parser know about end of stmt */
1.104     rillig    923:        *force_nl = true;       /* force newline after an end of stmt */
1.54      rillig    924:     }
                    925: }
                    926:
                    927: static void
1.157     rillig    928: process_lbrace(bool *force_nl, bool *spaced_expr, stmt_head hd,
1.105     rillig    929:     int *di_stack, int di_stack_cap, int *decl_ind)
1.54      rillig    930: {
1.102     rillig    931:     ps.in_stmt = false;                /* don't indent the {} */
1.119     rillig    932:
1.54      rillig    933:     if (!ps.block_init)
1.104     rillig    934:        *force_nl = true;       /* force other stuff on same line as '{' onto
1.54      rillig    935:                                 * new line */
                    936:     else if (ps.block_init_level <= 0)
                    937:        ps.block_init_level = 1;
                    938:     else
                    939:        ps.block_init_level++;
                    940:
1.65      rillig    941:     if (code.s != code.e && !ps.block_init) {
1.122     rillig    942:        if (!opt.brace_same_line) {
1.54      rillig    943:            dump_line();
                    944:            ps.want_blank = false;
1.134     rillig    945:        } else if (ps.in_parameter_declaration && !ps.init_or_struct) {
1.79      rillig    946:            ps.ind_level_follow = 0;
1.86      rillig    947:            if (opt.function_brace_split) {     /* dump the line prior to the
                    948:                                                 * brace ... */
1.54      rillig    949:                dump_line();
                    950:                ps.want_blank = false;
                    951:            } else              /* add a space between the decl and brace */
                    952:                ps.want_blank = true;
                    953:        }
                    954:     }
1.119     rillig    955:
1.54      rillig    956:     if (ps.in_parameter_declaration)
1.142     rillig    957:        blank_line_before = false;
1.54      rillig    958:
1.86      rillig    959:     if (ps.p_l_follow > 0) {   /* check for preceding unbalanced parens */
1.54      rillig    960:        diag(1, "Unbalanced parens");
                    961:        ps.p_l_follow = 0;
1.157     rillig    962:        if (*spaced_expr) {     /* check for unclosed 'if', 'for', etc. */
                    963:            *spaced_expr = false;
1.167   ! rillig    964:            parse_stmt_head(hd);
1.79      rillig    965:            ps.ind_level = ps.ind_level_follow;
1.54      rillig    966:        }
                    967:     }
1.119     rillig    968:
1.65      rillig    969:     if (code.s == code.e)
1.118     rillig    970:        ps.ind_stmt = false;    /* don't indent the '{' itself */
1.134     rillig    971:     if (ps.in_decl && ps.init_or_struct) {
1.105     rillig    972:        di_stack[ps.decl_nest] = *decl_ind;
1.79      rillig    973:        if (++ps.decl_nest == di_stack_cap) {
1.54      rillig    974:            diag(0, "Reached internal limit of %d struct levels",
1.86      rillig    975:                di_stack_cap);
1.79      rillig    976:            ps.decl_nest--;
1.54      rillig    977:        }
                    978:     } else {
1.86      rillig    979:        ps.decl_on_line = false;        /* we can't be in the middle of a
                    980:                                         * declaration, so don't do special
                    981:                                         * indentation of comments */
1.128     rillig    982:        if (opt.blanklines_after_decl_at_top && ps.in_parameter_declaration)
1.142     rillig    983:            blank_line_after = true;
1.73      rillig    984:        ps.in_parameter_declaration = false;
1.54      rillig    985:        ps.in_decl = false;
                    986:     }
1.119     rillig    987:
1.105     rillig    988:     *decl_ind = 0;
1.156     rillig    989:     parse(psym_lbrace);
1.116     rillig    990:     if (ps.want_blank)
1.65      rillig    991:        *code.e++ = ' ';
1.54      rillig    992:     ps.want_blank = false;
1.65      rillig    993:     *code.e++ = '{';
1.54      rillig    994:     ps.just_saw_decl = 0;
                    995: }
                    996:
                    997: static void
1.157     rillig    998: process_rbrace(bool *spaced_expr, int *decl_ind, const int *di_stack)
1.54      rillig    999: {
1.156     rillig   1000:     if (ps.s_sym[ps.tos] == psym_decl && !ps.block_init) {
                   1001:        /* semicolons can be omitted in declarations */
                   1002:        parse(psym_semicolon);
                   1003:     }
1.119     rillig   1004:
1.73      rillig   1005:     if (ps.p_l_follow != 0) {  /* check for unclosed if, for, else. */
1.54      rillig   1006:        diag(1, "Unbalanced parens");
                   1007:        ps.p_l_follow = 0;
1.157     rillig   1008:        *spaced_expr = false;
1.54      rillig   1009:     }
1.119     rillig   1010:
1.54      rillig   1011:     ps.just_saw_decl = 0;
                   1012:     ps.block_init_level--;
1.119     rillig   1013:
1.65      rillig   1014:     if (code.s != code.e && !ps.block_init) {  /* '}' must be first on line */
1.54      rillig   1015:        if (opt.verbose)
                   1016:            diag(0, "Line broken");
                   1017:        dump_line();
                   1018:     }
1.119     rillig   1019:
1.65      rillig   1020:     *code.e++ = '}';
1.54      rillig   1021:     ps.want_blank = true;
                   1022:     ps.in_stmt = ps.ind_stmt = false;
1.119     rillig   1023:
1.79      rillig   1024:     if (ps.decl_nest > 0) { /* we are in multi-level structure declaration */
1.105     rillig   1025:        *decl_ind = di_stack[--ps.decl_nest];
1.151     rillig   1026:        if (ps.decl_nest == 0 && !ps.in_parameter_declaration) {
1.54      rillig   1027:            ps.just_saw_decl = 2;
1.151     rillig   1028:            *decl_ind = ps.ind_level == 0
                   1029:                ? opt.decl_indent : opt.local_decl_indent;
                   1030:        }
1.54      rillig   1031:        ps.in_decl = true;
                   1032:     }
1.119     rillig   1033:
1.142     rillig   1034:     blank_line_before = false;
1.156     rillig   1035:     parse(psym_rbrace);
1.158     rillig   1036:     ps.search_stmt = opt.cuddle_else
1.156     rillig   1037:        && ps.s_sym[ps.tos] == psym_if_expr_stmt
1.143     rillig   1038:        && ps.s_ind_level[ps.tos] >= ps.ind_level;
1.119     rillig   1039:
1.79      rillig   1040:     if (ps.tos <= 1 && opt.blanklines_after_procs && ps.decl_nest <= 0)
1.142     rillig   1041:        blank_line_after = true;
1.54      rillig   1042: }
                   1043:
                   1044: static void
1.127     rillig   1045: process_keyword_do(bool *force_nl, bool *last_else)
1.54      rillig   1046: {
                   1047:     ps.in_stmt = false;
1.119     rillig   1048:
1.127     rillig   1049:     if (code.e != code.s) {    /* make sure this starts a line */
                   1050:        if (opt.verbose)
                   1051:            diag(0, "Line broken");
                   1052:        dump_line();
                   1053:        ps.want_blank = false;
                   1054:     }
1.119     rillig   1055:
1.127     rillig   1056:     *force_nl = true;          /* following stuff must go onto new line */
                   1057:     *last_else = false;
1.156     rillig   1058:     parse(psym_do);
1.127     rillig   1059: }
1.119     rillig   1060:
1.127     rillig   1061: static void
                   1062: process_keyword_else(bool *force_nl, bool *last_else)
                   1063: {
                   1064:     ps.in_stmt = false;
1.119     rillig   1065:
1.127     rillig   1066:     if (code.e != code.s && (!opt.cuddle_else || code.e[-1] != '}')) {
                   1067:        if (opt.verbose)
                   1068:            diag(0, "Line broken");
                   1069:        dump_line();            /* make sure this starts a line */
                   1070:        ps.want_blank = false;
1.54      rillig   1071:     }
1.127     rillig   1072:
                   1073:     *force_nl = true;          /* following stuff must go onto new line */
                   1074:     *last_else = true;
1.156     rillig   1075:     parse(psym_else);
1.54      rillig   1076: }
                   1077:
                   1078: static void
1.164     rillig   1079: process_type(int *decl_ind, bool *tabs_to_var)
1.54      rillig   1080: {
1.156     rillig   1081:     parse(psym_decl);          /* let the parser worry about indentation */
1.119     rillig   1082:
1.156     rillig   1083:     if (ps.last_token == lsym_rparen_or_rbracket && ps.tos <= 1) {
1.65      rillig   1084:        if (code.s != code.e) {
1.54      rillig   1085:            dump_line();
1.73      rillig   1086:            ps.want_blank = false;
1.54      rillig   1087:        }
                   1088:     }
1.119     rillig   1089:
1.79      rillig   1090:     if (ps.in_parameter_declaration && opt.indent_parameters &&
                   1091:        ps.decl_nest == 0) {
                   1092:        ps.ind_level = ps.ind_level_follow = 1;
1.73      rillig   1093:        ps.ind_stmt = false;
1.54      rillig   1094:     }
1.119     rillig   1095:
1.134     rillig   1096:     ps.init_or_struct = /* maybe */ true;
1.156     rillig   1097:     ps.in_decl = ps.decl_on_line = ps.last_token != lsym_typedef;
1.134     rillig   1098:     if (ps.decl_nest <= 0)
1.54      rillig   1099:        ps.just_saw_decl = 2;
1.119     rillig   1100:
1.142     rillig   1101:     blank_line_before = false;
1.54      rillig   1102:
1.132     rillig   1103:     int len = (int)buf_len(&token) + 1;
1.82      rillig   1104:     int ind = ps.ind_level == 0 || ps.decl_nest > 0
1.149     rillig   1105:        ? opt.decl_indent       /* global variable or local member */
                   1106:        : opt.local_decl_indent;        /* local variable */
1.132     rillig   1107:     *decl_ind = ind > 0 ? ind : len;
                   1108:     *tabs_to_var = opt.use_tabs && ind > 0;
1.54      rillig   1109: }
                   1110:
                   1111: static void
1.156     rillig   1112: process_ident(lexer_symbol lsym, int decl_ind, bool tabs_to_var,
1.157     rillig   1113:     bool *spaced_expr, bool *force_nl, stmt_head hd)
1.54      rillig   1114: {
                   1115:     if (ps.in_decl) {
1.156     rillig   1116:        if (lsym == lsym_funcname) {
1.54      rillig   1117:            ps.in_decl = false;
1.65      rillig   1118:            if (opt.procnames_start_line && code.s != code.e) {
                   1119:                *code.e = '\0';
1.54      rillig   1120:                dump_line();
                   1121:            } else if (ps.want_blank) {
1.65      rillig   1122:                *code.e++ = ' ';
1.54      rillig   1123:            }
                   1124:            ps.want_blank = false;
1.119     rillig   1125:
1.54      rillig   1126:        } else if (!ps.block_init && !ps.dumped_decl_indent &&
1.86      rillig   1127:            ps.paren_level == 0) {      /* if we are in a declaration, we must
                   1128:                                         * indent identifier */
1.105     rillig   1129:            indent_declaration(decl_ind, tabs_to_var);
1.54      rillig   1130:            ps.dumped_decl_indent = true;
                   1131:            ps.want_blank = false;
                   1132:        }
1.119     rillig   1133:
1.157     rillig   1134:     } else if (*spaced_expr && ps.p_l_follow == 0) {
                   1135:        *spaced_expr = false;
1.104     rillig   1136:        *force_nl = true;
1.144     rillig   1137:        ps.next_unary = true;
1.54      rillig   1138:        ps.in_stmt = false;
1.167   ! rillig   1139:        parse_stmt_head(hd);
1.54      rillig   1140:     }
                   1141: }
                   1142:
                   1143: static void
1.111     rillig   1144: copy_token(void)
1.54      rillig   1145: {
                   1146:     if (ps.want_blank)
1.112     rillig   1147:        buf_add_char(&code, ' ');
                   1148:     buf_add_buf(&code, &token);
1.54      rillig   1149: }
                   1150:
                   1151: static void
                   1152: process_string_prefix(void)
                   1153: {
1.112     rillig   1154:     copy_token();
1.54      rillig   1155:     ps.want_blank = false;
                   1156: }
                   1157:
                   1158: static void
                   1159: process_period(void)
                   1160: {
1.85      rillig   1161:     if (code.e[-1] == ',')
                   1162:        *code.e++ = ' ';
1.102     rillig   1163:     *code.e++ = '.';
                   1164:     ps.want_blank = false;
1.54      rillig   1165: }
                   1166:
                   1167: static void
1.105     rillig   1168: process_comma(int decl_ind, bool tabs_to_var, bool *force_nl)
1.54      rillig   1169: {
1.135     rillig   1170:     ps.want_blank = code.s != code.e;  /* only put blank after comma if comma
1.86      rillig   1171:                                         * does not start the line */
1.119     rillig   1172:
1.54      rillig   1173:     if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init &&
                   1174:        !ps.dumped_decl_indent && ps.paren_level == 0) {
                   1175:        /* indent leading commas and not the actual identifiers */
1.105     rillig   1176:        indent_declaration(decl_ind - 1, tabs_to_var);
1.54      rillig   1177:        ps.dumped_decl_indent = true;
                   1178:     }
1.119     rillig   1179:
1.65      rillig   1180:     *code.e++ = ',';
1.119     rillig   1181:
1.54      rillig   1182:     if (ps.p_l_follow == 0) {
                   1183:        if (ps.block_init_level <= 0)
1.73      rillig   1184:            ps.block_init = false;
1.87      rillig   1185:        if (break_comma && (opt.break_after_comma ||
1.149     rillig   1186:                indentation_after_range(compute_code_indent(), code.s, code.e)
                   1187:                >= opt.max_line_length - opt.tabsize))
1.104     rillig   1188:            *force_nl = true;
1.54      rillig   1189:     }
                   1190: }
                   1191:
1.112     rillig   1192: /* move the whole line to the 'label' buffer */
1.54      rillig   1193: static void
1.115     rillig   1194: read_preprocessing_line(void)
1.54      rillig   1195: {
1.129     rillig   1196:     enum {
                   1197:        PLAIN, STR, CHR, COMM
                   1198:     } state;
                   1199:
1.112     rillig   1200:     buf_add_char(&lab, '#');
1.54      rillig   1201:
1.129     rillig   1202:     state = PLAIN;
1.115     rillig   1203:     int com_start = 0, com_end = 0;
                   1204:
1.124     rillig   1205:     while (is_hspace(*inp.s))
1.115     rillig   1206:        inbuf_skip();
                   1207:
1.129     rillig   1208:     while (*inp.s != '\n' || (state == COMM && !had_eof)) {
1.115     rillig   1209:        buf_reserve(&lab, 2);
                   1210:        *lab.e++ = inbuf_next();
                   1211:        switch (lab.e[-1]) {
                   1212:        case '\\':
1.129     rillig   1213:            if (state != COMM)
1.115     rillig   1214:                *lab.e++ = inbuf_next();
                   1215:            break;
                   1216:        case '/':
1.129     rillig   1217:            if (*inp.s == '*' && state == PLAIN) {
                   1218:                state = COMM;
1.124     rillig   1219:                *lab.e++ = *inp.s++;
1.115     rillig   1220:                com_start = (int)buf_len(&lab) - 2;
                   1221:            }
                   1222:            break;
                   1223:        case '"':
1.129     rillig   1224:            if (state == STR)
                   1225:                state = PLAIN;
                   1226:            else if (state == PLAIN)
                   1227:                state = STR;
1.115     rillig   1228:            break;
                   1229:        case '\'':
1.129     rillig   1230:            if (state == CHR)
                   1231:                state = PLAIN;
                   1232:            else if (state == PLAIN)
                   1233:                state = CHR;
1.115     rillig   1234:            break;
                   1235:        case '*':
1.129     rillig   1236:            if (*inp.s == '/' && state == COMM) {
                   1237:                state = PLAIN;
1.124     rillig   1238:                *lab.e++ = *inp.s++;
1.115     rillig   1239:                com_end = (int)buf_len(&lab);
1.54      rillig   1240:            }
1.115     rillig   1241:            break;
1.54      rillig   1242:        }
1.115     rillig   1243:     }
1.54      rillig   1244:
1.115     rillig   1245:     while (lab.e > lab.s && is_hspace(lab.e[-1]))
                   1246:        lab.e--;
1.125     rillig   1247:     if (lab.e - lab.s == com_end && saved_inp_s == NULL) {
1.115     rillig   1248:        /* comment on preprocessor line */
                   1249:        if (sc_end == NULL) {   /* if this is the first comment, we must set
                   1250:                                 * up the buffer */
                   1251:            save_com = sc_buf;
                   1252:            sc_end = save_com;
                   1253:        } else {
                   1254:            *sc_end++ = '\n';   /* add newline between comments */
                   1255:            *sc_end++ = ' ';
                   1256:            --line_no;
                   1257:        }
                   1258:        if (sc_end - save_com + com_end - com_start > sc_size)
                   1259:            errx(1, "input too long");
                   1260:        memmove(sc_end, lab.s + com_start, (size_t)(com_end - com_start));
                   1261:        sc_end += com_end - com_start;
                   1262:        lab.e = lab.s + com_start;
1.101     rillig   1263:        while (lab.e > lab.s && is_hspace(lab.e[-1]))
1.63      rillig   1264:            lab.e--;
1.125     rillig   1265:        saved_inp_s = inp.s;    /* save current input buffer */
                   1266:        saved_inp_e = inp.e;
1.124     rillig   1267:        inp.s = save_com;       /* fix so that subsequent calls to lexi will
1.58      rillig   1268:                                 * take tokens out of save_com */
1.115     rillig   1269:        *sc_end++ = ' ';        /* add trailing blank, just in case */
1.124     rillig   1270:        inp.e = sc_end;
1.115     rillig   1271:        sc_end = NULL;
1.124     rillig   1272:        debug_println("switched inp.s to save_com");
1.54      rillig   1273:     }
1.115     rillig   1274:     buf_terminate(&lab);
                   1275: }
                   1276:
                   1277: static void
                   1278: process_preprocessing(void)
                   1279: {
                   1280:     if (com.s != com.e || lab.s != lab.e || code.s != code.e)
                   1281:        dump_line();
                   1282:
                   1283:     read_preprocessing_line();
                   1284:
                   1285:     ps.is_case_label = false;
1.54      rillig   1286:
1.86      rillig   1287:     if (strncmp(lab.s, "#if", 3) == 0) {       /* also ifdef, ifndef */
1.146     rillig   1288:        if ((size_t)ifdef_level < array_length(state_stack))
1.54      rillig   1289:            state_stack[ifdef_level++] = ps;
1.88      rillig   1290:        else
1.54      rillig   1291:            diag(1, "#if stack overflow");
1.119     rillig   1292:
1.86      rillig   1293:     } else if (strncmp(lab.s, "#el", 3) == 0) {        /* else, elif */
1.54      rillig   1294:        if (ifdef_level <= 0)
1.63      rillig   1295:            diag(1, lab.s[3] == 'i' ? "Unmatched #elif" : "Unmatched #else");
1.88      rillig   1296:        else
1.54      rillig   1297:            ps = state_stack[ifdef_level - 1];
1.119     rillig   1298:
1.63      rillig   1299:     } else if (strncmp(lab.s, "#endif", 6) == 0) {
1.54      rillig   1300:        if (ifdef_level <= 0)
                   1301:            diag(1, "Unmatched #endif");
                   1302:        else
                   1303:            ifdef_level--;
1.119     rillig   1304:
1.54      rillig   1305:     } else {
1.63      rillig   1306:        if (strncmp(lab.s + 1, "pragma", 6) != 0 &&
                   1307:            strncmp(lab.s + 1, "error", 5) != 0 &&
                   1308:            strncmp(lab.s + 1, "line", 4) != 0 &&
                   1309:            strncmp(lab.s + 1, "undef", 5) != 0 &&
                   1310:            strncmp(lab.s + 1, "define", 6) != 0 &&
                   1311:            strncmp(lab.s + 1, "include", 7) != 0) {
1.54      rillig   1312:            diag(1, "Unrecognized cpp directive");
                   1313:            return;
                   1314:        }
                   1315:     }
1.119     rillig   1316:
1.54      rillig   1317:     if (opt.blanklines_around_conditional_compilation) {
1.142     rillig   1318:        blank_line_after = true;
1.140     rillig   1319:        blank_lines_to_output = 0;
1.54      rillig   1320:     } else {
1.142     rillig   1321:        blank_line_after = false;
                   1322:        blank_line_before = false;
1.54      rillig   1323:     }
                   1324:
                   1325:     /*
                   1326:      * subsequent processing of the newline character will cause the line to
                   1327:      * be printed
                   1328:      */
                   1329: }
                   1330:
1.60      rillig   1331: static void __attribute__((__noreturn__))
1.53      rillig   1332: main_loop(void)
                   1333: {
1.150     rillig   1334:     bool force_nl = false;     /* when true, code must be broken */
1.75      rillig   1335:     bool last_else = false;    /* true iff last keyword was an else */
1.150     rillig   1336:     int decl_ind = 0;          /* current indentation for declarations */
1.86      rillig   1337:     int di_stack[20];          /* a stack of structure indentation levels */
1.150     rillig   1338:     bool tabs_to_var = false;  /* true if using tabs to indent to var name */
1.157     rillig   1339:     bool spaced_expr = false;  /* whether we are in the expression of
1.53      rillig   1340:                                 * if(...), while(...), etc. */
1.160     rillig   1341:     stmt_head hd = hd_0;       /* the type of statement for 'if (...)', 'for
                   1342:                                 * (...)', etc */
1.152     rillig   1343:     int quest_level = 0;       /* when this is positive, we have seen a '?'
                   1344:                                 * without the matching ':' in a '?:'
                   1345:                                 * expression */
1.150     rillig   1346:     bool seen_case = false;    /* set to true when we see a 'case', so we
1.53      rillig   1347:                                 * know what to do with the following colon */
                   1348:
1.79      rillig   1349:     di_stack[ps.decl_nest = 0] = 0;
1.1       cgd      1350:
1.59      rillig   1351:     for (;;) {                 /* this is the main loop.  it will go until we
1.1       cgd      1352:                                 * reach eof */
1.75      rillig   1353:        bool comment_buffered = false;
1.1       cgd      1354:
1.165     rillig   1355:        lexer_symbol lsym = lexi();     /* Read the next token.  The actual
1.150     rillig   1356:                                         * characters read are stored in
                   1357:                                         * "token". */
1.1       cgd      1358:
1.158     rillig   1359:        search_stmt(&lsym, &force_nl, &comment_buffered, &last_else);
1.25      kamil    1360:
1.156     rillig   1361:        if (lsym == lsym_eof) {
1.54      rillig   1362:            process_end_of_file();
1.60      rillig   1363:            /* NOTREACHED */
1.54      rillig   1364:        }
1.25      kamil    1365:
1.156     rillig   1366:        if (lsym == lsym_newline || lsym == lsym_form_feed ||
                   1367:                lsym == lsym_preprocessing)
1.130     rillig   1368:            force_nl = false;
1.156     rillig   1369:        else if (lsym != lsym_comment)
                   1370:            process_comment_in_code(lsym, &force_nl);
1.25      kamil    1371:
1.112     rillig   1372:        buf_reserve(&code, 3);  /* space for 2 characters plus '\0' */
1.1       cgd      1373:
1.156     rillig   1374:        switch (lsym) {
1.25      kamil    1375:
1.156     rillig   1376:        case lsym_form_feed:
1.54      rillig   1377:            process_form_feed();
1.25      kamil    1378:            break;
                   1379:
1.156     rillig   1380:        case lsym_newline:
1.54      rillig   1381:            process_newline();
1.25      kamil    1382:            break;
                   1383:
1.156     rillig   1384:        case lsym_lparen_or_lbracket:
1.157     rillig   1385:            process_lparen_or_lbracket(decl_ind, tabs_to_var, spaced_expr);
1.25      kamil    1386:            break;
                   1387:
1.156     rillig   1388:        case lsym_rparen_or_rbracket:
1.157     rillig   1389:            process_rparen_or_rbracket(&spaced_expr, &force_nl, hd);
1.25      kamil    1390:            break;
                   1391:
1.156     rillig   1392:        case lsym_unary_op:
1.105     rillig   1393:            process_unary_op(decl_ind, tabs_to_var);
1.25      kamil    1394:            break;
                   1395:
1.156     rillig   1396:        case lsym_binary_op:
1.54      rillig   1397:            process_binary_op();
1.25      kamil    1398:            break;
                   1399:
1.156     rillig   1400:        case lsym_postfix_op:
1.54      rillig   1401:            process_postfix_op();
1.25      kamil    1402:            break;
                   1403:
1.156     rillig   1404:        case lsym_question:
1.152     rillig   1405:            process_question(&quest_level);
1.25      kamil    1406:            break;
                   1407:
1.164     rillig   1408:        case lsym_case_label:
1.116     rillig   1409:            seen_case = true;
1.111     rillig   1410:            goto copy_token;
1.25      kamil    1411:
1.156     rillig   1412:        case lsym_colon:
1.152     rillig   1413:            process_colon(&quest_level, &force_nl, &seen_case);
1.25      kamil    1414:            break;
                   1415:
1.156     rillig   1416:        case lsym_semicolon:
1.152     rillig   1417:            process_semicolon(&seen_case, &quest_level, decl_ind, tabs_to_var,
1.157     rillig   1418:                &spaced_expr, hd, &force_nl);
1.25      kamil    1419:            break;
                   1420:
1.156     rillig   1421:        case lsym_lbrace:
1.157     rillig   1422:            process_lbrace(&force_nl, &spaced_expr, hd, di_stack,
1.146     rillig   1423:                (int)array_length(di_stack), &decl_ind);
1.25      kamil    1424:            break;
                   1425:
1.156     rillig   1426:        case lsym_rbrace:
1.157     rillig   1427:            process_rbrace(&spaced_expr, &decl_ind, di_stack);
1.25      kamil    1428:            break;
                   1429:
1.156     rillig   1430:        case lsym_switch:
1.157     rillig   1431:            spaced_expr = true; /* the interesting stuff is done after the
1.156     rillig   1432:                                 * expressions are scanned */
                   1433:            hd = hd_switch;     /* remember the type of header for later use
1.164     rillig   1434:                                 * by the parser */
1.111     rillig   1435:            goto copy_token;
1.25      kamil    1436:
1.156     rillig   1437:        case lsym_for:
1.157     rillig   1438:            spaced_expr = true;
1.156     rillig   1439:            hd = hd_for;
1.154     rillig   1440:            goto copy_token;
1.25      kamil    1441:
1.156     rillig   1442:        case lsym_if:
1.157     rillig   1443:            spaced_expr = true;
1.156     rillig   1444:            hd = hd_if;
1.154     rillig   1445:            goto copy_token;
                   1446:
1.156     rillig   1447:        case lsym_while:
1.157     rillig   1448:            spaced_expr = true;
1.156     rillig   1449:            hd = hd_while;
1.111     rillig   1450:            goto copy_token;
1.25      kamil    1451:
1.156     rillig   1452:        case lsym_do:
1.153     rillig   1453:            process_keyword_do(&force_nl, &last_else);
                   1454:            goto copy_token;
                   1455:
1.156     rillig   1456:        case lsym_else:
1.153     rillig   1457:            process_keyword_else(&force_nl, &last_else);
1.111     rillig   1458:            goto copy_token;
1.25      kamil    1459:
1.156     rillig   1460:        case lsym_typedef:
                   1461:        case lsym_storage_class:
1.142     rillig   1462:            blank_line_before = false;
1.111     rillig   1463:            goto copy_token;
1.25      kamil    1464:
1.156     rillig   1465:        case lsym_tag:
1.25      kamil    1466:            if (ps.p_l_follow > 0)
1.111     rillig   1467:                goto copy_token;
1.25      kamil    1468:            /* FALLTHROUGH */
1.156     rillig   1469:        case lsym_type:
1.164     rillig   1470:            process_type(&decl_ind, &tabs_to_var);
1.111     rillig   1471:            goto copy_token;
1.25      kamil    1472:
1.156     rillig   1473:        case lsym_funcname:
1.164     rillig   1474:        case lsym_ident:
1.157     rillig   1475:            process_ident(lsym, decl_ind, tabs_to_var, &spaced_expr,
                   1476:                &force_nl, hd);
1.111     rillig   1477:     copy_token:
                   1478:            copy_token();
1.156     rillig   1479:            if (lsym != lsym_funcname)
1.25      kamil    1480:                ps.want_blank = true;
                   1481:            break;
                   1482:
1.156     rillig   1483:        case lsym_string_prefix:
1.54      rillig   1484:            process_string_prefix();
1.25      kamil    1485:            break;
1.1       cgd      1486:
1.156     rillig   1487:        case lsym_period:
1.54      rillig   1488:            process_period();
1.25      kamil    1489:            break;
                   1490:
1.156     rillig   1491:        case lsym_comma:
1.105     rillig   1492:            process_comma(decl_ind, tabs_to_var, &force_nl);
1.25      kamil    1493:            break;
                   1494:
1.164     rillig   1495:        case lsym_preprocessing:
1.54      rillig   1496:            process_preprocessing();
                   1497:            break;
1.119     rillig   1498:
1.164     rillig   1499:        case lsym_comment:
1.56      rillig   1500:            process_comment();
1.25      kamil    1501:            break;
1.30      rillig   1502:
                   1503:        default:
                   1504:            break;
1.64      rillig   1505:        }
1.25      kamil    1506:
1.65      rillig   1507:        *code.e = '\0';
1.156     rillig   1508:        if (lsym != lsym_comment && lsym != lsym_newline &&
                   1509:                lsym != lsym_preprocessing)
                   1510:            ps.last_token = lsym;
1.53      rillig   1511:     }
                   1512: }
                   1513:
                   1514: int
                   1515: main(int argc, char **argv)
                   1516: {
                   1517:     main_init_globals();
                   1518:     main_parse_command_line(argc, argv);
                   1519: #if HAVE_CAPSICUM
                   1520:     init_capsicum();
                   1521: #endif
                   1522:     main_prepare_parsing();
                   1523:     main_loop();
1.25      kamil    1524: }
1.6       lukem    1525:
1.48      rillig   1526: #ifdef debug
                   1527: void
                   1528: debug_printf(const char *fmt, ...)
                   1529: {
                   1530:     FILE *f = output == stdout ? stderr : stdout;
                   1531:     va_list ap;
                   1532:
                   1533:     va_start(ap, fmt);
                   1534:     vfprintf(f, fmt, ap);
                   1535:     va_end(ap);
                   1536: }
                   1537:
                   1538: void
                   1539: debug_println(const char *fmt, ...)
                   1540: {
                   1541:     FILE *f = output == stdout ? stderr : stdout;
                   1542:     va_list ap;
                   1543:
                   1544:     va_start(ap, fmt);
                   1545:     vfprintf(f, fmt, ap);
                   1546:     va_end(ap);
                   1547:     fprintf(f, "\n");
                   1548: }
                   1549:
                   1550: void
                   1551: debug_vis_range(const char *prefix, const char *s, const char *e,
1.86      rillig   1552:     const char *suffix)
1.48      rillig   1553: {
                   1554:     debug_printf("%s", prefix);
                   1555:     for (const char *p = s; p < e; p++) {
1.159     rillig   1556:        if (*p == '\\' || *p == '"')
                   1557:            debug_printf("\\%c", *p);
                   1558:        else if (isprint((unsigned char)*p))
1.48      rillig   1559:            debug_printf("%c", *p);
                   1560:        else if (*p == '\n')
                   1561:            debug_printf("\\n");
                   1562:        else if (*p == '\t')
                   1563:            debug_printf("\\t");
                   1564:        else
1.162     rillig   1565:            debug_printf("\\x%02x", (unsigned char)*p);
1.48      rillig   1566:     }
                   1567:     debug_printf("%s", suffix);
                   1568: }
                   1569: #endif
1.68      rillig   1570:
                   1571: static void *
                   1572: nonnull(void *p)
                   1573: {
                   1574:     if (p == NULL)
                   1575:        err(EXIT_FAILURE, NULL);
                   1576:     return p;
                   1577: }
                   1578:
                   1579: void *
                   1580: xmalloc(size_t size)
                   1581: {
                   1582:     return nonnull(malloc(size));
                   1583: }
                   1584:
                   1585: void *
                   1586: xrealloc(void *p, size_t new_size)
                   1587: {
                   1588:     return nonnull(realloc(p, new_size));
                   1589: }
                   1590:
                   1591: char *
                   1592: xstrdup(const char *s)
                   1593: {
                   1594:     return nonnull(strdup(s));
                   1595: }

CVSweb <webmaster@jp.NetBSD.org>