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

Annotation of src/usr.bin/indent/args.c, Revision 1.52

1.52    ! rillig      1: /*     $NetBSD: args.c,v 1.51 2021/10/07 22:56:49 rillig Exp $ */
1.3       tls         2:
1.14      kamil       3: /*-
                      4:  * SPDX-License-Identifier: BSD-4-Clause
                      5:  *
                      6:  * Copyright (c) 1985 Sun Microsystems, Inc.
1.4       mrg         7:  * Copyright (c) 1980, 1993
                      8:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         9:  * All rights reserved.
                     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.
                     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.14      kamil      40: #if 0
                     41: static char sccsid[] = "@(#)args.c     8.1 (Berkeley) 6/6/93";
                     42: #endif
                     43:
1.5       lukem      44: #include <sys/cdefs.h>
1.14      kamil      45: #if defined(__NetBSD__)
1.52    ! rillig     46: __RCSID("$NetBSD: args.c,v 1.51 2021/10/07 22:56:49 rillig Exp $");
1.14      kamil      47: #elif defined(__FreeBSD__)
                     48: __FBSDID("$FreeBSD: head/usr.bin/indent/args.c 336318 2018-07-15 21:04:21Z pstef $");
                     49: #endif
1.1       cgd        50:
1.50      rillig     51: /* Read options from profile files and from the command line. */
1.1       cgd        52:
1.5       lukem      53: #include <ctype.h>
1.12      ginsbach   54: #include <err.h>
1.14      kamil      55: #include <limits.h>
1.1       cgd        56: #include <stdio.h>
                     57: #include <stdlib.h>
                     58: #include <string.h>
1.15      rillig     59:
1.14      kamil      60: #include "indent.h"
                     61:
                     62: #define INDENT_VERSION "2.0"
1.1       cgd        63:
1.32      rillig     64: void add_typedefs_from_file(const char *);
1.14      kamil      65:
1.25      rillig     66: #if __STDC_VERSION__ >= 201112L
                     67: #define assert_type(expr, type) _Generic((expr), type : (expr))
                     68: #else
                     69: #define assert_type(expr, type) (expr)
                     70: #endif
                     71: #define bool_option(name, value, var) \
1.38      rillig     72:        {name, true, value, false, assert_type(&(opt.var), bool *)}
1.31      rillig     73: #define int_option(name, var) \
1.38      rillig     74:        {name, false, false, false, assert_type(&(opt.var), int *)}
1.35      rillig     75: #define bool_options(name, var) \
1.38      rillig     76:        {name, true, false, true, assert_type(&(opt.var), bool *)}
1.25      rillig     77:
1.1       cgd        78: /*
1.36      rillig     79:  * N.B.: an option whose name is a prefix of another option must come earlier;
                     80:  * for example, "l" must come before "lp".
1.32      rillig     81:  *
1.36      rillig     82:  * See set_special_option for special options.
1.1       cgd        83:  */
1.29      rillig     84: static const struct pro {
1.37      rillig     85:     const char p_name[5];      /* name, e.g. "bl", "cli" */
1.33      rillig     86:     bool p_is_bool;
                     87:     bool p_bool_value;
1.37      rillig     88:     bool p_may_negate;
1.39      rillig     89:     void *p_var;               /* the associated variable */
1.33      rillig     90: }   pro[] = {
1.38      rillig     91:     bool_options("bacc", blanklines_around_conditional_compilation),
1.52    ! rillig     92:     bool_options("bad", blanklines_after_decl),
        !            93:     bool_options("badp", blanklines_after_decl_at_top),
1.38      rillig     94:     bool_options("bap", blanklines_after_procs),
1.52    ! rillig     95:     bool_options("bbb", blanklines_before_block_comments),
1.38      rillig     96:     bool_options("bc", break_after_comma),
1.51      rillig     97:     bool_option("bl", false, brace_same_line),
                     98:     bool_option("br", true, brace_same_line),
1.38      rillig     99:     bool_options("bs", blank_after_sizeof),
                    100:     int_option("c", comment_column),
                    101:     int_option("cd", decl_comment_column),
                    102:     bool_options("cdb", comment_delimiter_on_blankline),
                    103:     bool_options("ce", cuddle_else),
                    104:     int_option("ci", continuation_indent),
1.36      rillig    105:     /* "cli" is special */
1.38      rillig    106:     bool_options("cs", space_after_cast),
                    107:     int_option("d", unindent_displace),
                    108:     int_option("di", decl_indent),
                    109:     bool_options("dj", ljust_decl),
1.52    ! rillig    110:     bool_options("eei", extra_expr_indent),
1.38      rillig    111:     bool_options("ei", else_if),
                    112:     bool_options("fbs", function_brace_split),
                    113:     bool_options("fc1", format_col1_comments),
                    114:     bool_options("fcb", format_block_comments),
                    115:     int_option("i", indent_size),
                    116:     bool_options("ip", indent_parameters),
                    117:     int_option("l", max_line_length),
                    118:     int_option("lc", block_comment_max_line_length),
                    119:     int_option("ldi", local_decl_indent),
                    120:     bool_options("lp", lineup_to_parens),
                    121:     bool_options("lpl", lineup_to_parens_always),
1.36      rillig    122:     /* "npro" is special */
                    123:     /* "P" is special */
1.38      rillig    124:     bool_options("pcs", proc_calls_space),
                    125:     bool_options("psl", procnames_start_line),
                    126:     bool_options("sc", star_comment_cont),
                    127:     bool_options("sob", swallow_optional_blanklines),
1.36      rillig    128:     /* "st" is special */
1.38      rillig    129:     bool_option("ta", true, auto_typedefs),
1.36      rillig    130:     /* "T" is special */
1.38      rillig    131:     int_option("ts", tabsize),
1.36      rillig    132:     /* "U" is special */
1.38      rillig    133:     bool_options("ut", use_tabs),
                    134:     bool_options("v", verbose),
1.1       cgd       135: };
1.14      kamil     136:
                    137: static void
1.46      rillig    138: load_profile(const char *fname, bool must_exist)
1.1       cgd       139: {
1.42      rillig    140:     FILE *f;
1.14      kamil     141:
1.46      rillig    142:     if ((f = fopen(fname, "r")) == NULL) {
                    143:        if (must_exist)
                    144:            err(EXIT_FAILURE, "profile %s", fname);
1.42      rillig    145:        return;
1.46      rillig    146:     }
1.42      rillig    147:
1.22      rillig    148:     for (;;) {
1.45      rillig    149:        char buf[BUFSIZ];
                    150:        size_t n = 0;
                    151:        int ch, comment_ch = -1;
                    152:
1.43      rillig    153:        while ((ch = getc(f)) != EOF) {
1.45      rillig    154:            if (ch == '*' && comment_ch < 0 && n > 0 && buf[n - 1] == '/') {
                    155:                n--;
                    156:                comment_ch = ch;
                    157:            } else if (comment_ch >= 0) {
                    158:                comment_ch = ch == '/' && comment_ch == '*' ? -1 : ch;
1.43      rillig    159:            } else if (isspace((unsigned char)ch)) {
1.45      rillig    160:                break;
                    161:            } else if (n >= nitems(buf) - 5) {
1.44      rillig    162:                diag(1, "buffer overflow in %s, starting with '%.10s'",
1.49      rillig    163:                     fname, buf);
1.44      rillig    164:                exit(1);
1.45      rillig    165:            } else
                    166:                buf[n++] = (char)ch;
1.1       cgd       167:        }
1.45      rillig    168:
                    169:        if (n > 0) {
                    170:            buf[n] = '\0';
1.14      kamil     171:            if (opt.verbose)
                    172:                printf("profile: %s\n", buf);
1.49      rillig    173:            set_option(buf, fname);
1.45      rillig    174:        } else if (ch == EOF)
                    175:            break;
1.14      kamil     176:     }
1.45      rillig    177:     (void)fclose(f);
1.1       cgd       178: }
                    179:
1.41      rillig    180: void
                    181: load_profiles(const char *profile_name)
                    182: {
                    183:     char fname[PATH_MAX];
                    184:
1.42      rillig    185:     if (profile_name != NULL)
1.46      rillig    186:        load_profile(profile_name, true);
1.42      rillig    187:     else {
                    188:        snprintf(fname, sizeof(fname), "%s/.indent.pro", getenv("HOME"));
1.46      rillig    189:        load_profile(fname, false);
1.41      rillig    190:     }
1.46      rillig    191:     load_profile(".indent.pro", false);
1.41      rillig    192: }
                    193:
1.14      kamil     194: static const char *
1.37      rillig    195: skip_over(const char *s, bool may_negate, const char *prefix)
1.1       cgd       196: {
1.37      rillig    197:     if (may_negate && s[0] == 'n')
                    198:        s++;
1.30      rillig    199:     while (*prefix != '\0') {
                    200:        if (*prefix++ != *s++)
1.16      rillig    201:            return NULL;
1.14      kamil     202:     }
1.30      rillig    203:     return s;
1.1       cgd       204: }
1.14      kamil     205:
1.32      rillig    206: static bool
1.49      rillig    207: set_special_option(const char *arg, const char *option_source)
1.32      rillig    208: {
                    209:     const char *arg_end;
                    210:
                    211:     if (strncmp(arg, "-version", 8) == 0) {
                    212:        printf("FreeBSD indent %s\n", INDENT_VERSION);
                    213:        exit(0);
1.33      rillig    214:        /* NOTREACHED */
1.32      rillig    215:     }
                    216:
                    217:     if (arg[0] == 'P' || strncmp(arg, "npro", 4) == 0)
                    218:        return true;
                    219:
                    220:     if (strncmp(arg, "cli", 3) == 0) {
                    221:        arg_end = arg + 3;
                    222:        if (arg_end[0] == '\0')
                    223:            goto need_param;
1.48      rillig    224:        opt.case_indent = (float)atof(arg_end);
1.32      rillig    225:        return true;
                    226:     }
                    227:
                    228:     if (strncmp(arg, "st", 2) == 0) {
                    229:        if (input == NULL)
                    230:            input = stdin;
                    231:        if (output == NULL)
                    232:            output = stdout;
                    233:        return true;
                    234:     }
                    235:
                    236:     if (arg[0] == 'T') {
                    237:        arg_end = arg + 1;
                    238:        if (arg_end[0] == '\0')
                    239:            goto need_param;
                    240:        add_typename(arg_end);
                    241:        return true;
                    242:     }
                    243:
                    244:     if (arg[0] == 'U') {
                    245:        arg_end = arg + 1;
                    246:        if (arg_end[0] == '\0')
                    247:            goto need_param;
                    248:        add_typedefs_from_file(arg_end);
                    249:        return true;
                    250:     }
                    251:
                    252:     return false;
                    253:
                    254: need_param:
                    255:     errx(1, "%s: ``%.*s'' requires a parameter",
                    256:        option_source, (int)(arg_end - arg), arg);
                    257:     /* NOTREACHED */
                    258: }
                    259:
1.5       lukem     260: void
1.49      rillig    261: set_option(const char *arg, const char *option_source)
1.1       cgd       262: {
1.17      rillig    263:     const struct pro *p;
1.33      rillig    264:     const char *param_start;
1.1       cgd       265:
1.46      rillig    266:     arg++;                     /* skip leading '-' */
1.49      rillig    267:     if (set_special_option(arg, option_source))
1.32      rillig    268:        return;
                    269:
1.37      rillig    270:     for (p = pro + nitems(pro); p-- != pro;) {
                    271:        param_start = skip_over(arg, p->p_may_negate, p->p_name);
                    272:        if (param_start != NULL)
                    273:            goto found;
                    274:     }
1.14      kamil     275:     errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
1.30      rillig    276:
1.1       cgd       277: found:
1.47      rillig    278:     if (p->p_is_bool) {
                    279:        /* XXX: Trailing garbage in param_start is silently ignored. */
1.39      rillig    280:        *(bool *)p->p_var = p->p_may_negate ? arg[0] != 'n' : p->p_bool_value;
1.47      rillig    281:     } else {
1.32      rillig    282:        if (!isdigit((unsigned char)*param_start))
                    283:            errx(1, "%s: ``%s'' requires a parameter",
                    284:                option_source, p->p_name);
1.39      rillig    285:        *(int *)p->p_var = atoi(param_start);
1.14      kamil     286:     }
                    287: }
                    288:
                    289: void
1.30      rillig    290: add_typedefs_from_file(const char *fname)
1.14      kamil     291: {
                    292:     FILE *file;
                    293:     char line[BUFSIZ];
                    294:
1.30      rillig    295:     if ((file = fopen(fname, "r")) == NULL) {
                    296:        fprintf(stderr, "indent: cannot open file %s\n", fname);
1.14      kamil     297:        exit(1);
                    298:     }
                    299:     while ((fgets(line, BUFSIZ, file)) != NULL) {
                    300:        /* Remove trailing whitespace */
                    301:        line[strcspn(line, " \t\n\r")] = '\0';
                    302:        add_typename(line);
                    303:     }
                    304:     fclose(file);
1.1       cgd       305: }

CVSweb <webmaster@jp.NetBSD.org>