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

1.27    ! rillig      1: /*     $NetBSD: args.c,v 1.26 2021/09/25 17:20:02 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.27    ! rillig     46: __RCSID("$NetBSD: args.c,v 1.26 2021/09/25 17:20:02 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:
                     51: /*
                     52:  * Argument scanning and profile reading code.  Default parameters are set
                     53:  * here as well.
                     54:  */
                     55:
1.5       lukem      56: #include <ctype.h>
1.12      ginsbach   57: #include <err.h>
1.14      kamil      58: #include <limits.h>
1.1       cgd        59: #include <stdio.h>
                     60: #include <stdlib.h>
                     61: #include <string.h>
1.15      rillig     62:
1.14      kamil      63: #include "indent.h"
                     64:
                     65: #define INDENT_VERSION "2.0"
1.1       cgd        66:
                     67: /* profile types */
                     68: #define        PRO_SPECIAL     1       /* special case */
                     69: #define        PRO_BOOL        2       /* boolean */
                     70: #define        PRO_INT         3       /* integer */
                     71:
                     72: /* profile specials for booleans */
                     73: #define        ON              1       /* turn it on */
                     74: #define        OFF             0       /* turn it off */
                     75:
                     76: /* profile specials for specials */
                     77: #define        IGN             1       /* ignore it */
                     78: #define        CLI             2       /* case label indent (float) */
                     79: #define        STDIN           3       /* use stdin */
                     80: #define        KEY             4       /* type (keyword) */
                     81:
1.14      kamil      82: static void scan_profile(FILE *);
                     83:
1.18      rillig     84: #define        KEY_FILE        5       /* only used for args */
                     85: #define VERSION                6       /* only used for args */
1.14      kamil      86:
1.10      lukem      87: const char *option_source = "?";
1.1       cgd        88:
1.14      kamil      89: void add_typedefs_from_file(const char *str);
                     90:
1.25      rillig     91: #if __STDC_VERSION__ >= 201112L
                     92: #define assert_type(expr, type) _Generic((expr), type : (expr))
                     93: #else
                     94: #define assert_type(expr, type) (expr)
                     95: #endif
                     96: #define bool_option(name, value, var) \
1.26      rillig     97:        {name, PRO_BOOL, value, assert_type(&(var), bool *)}
1.25      rillig     98: #define int_option(name, value, var) \
                     99:        {name, PRO_INT, value, assert_type(&(var), int *)}
                    100: #define special_option(name, value) \
                    101:        {name, PRO_SPECIAL, assert_type(value, int), NULL}
                    102:
1.1       cgd       103: /*
                    104:  * N.B.: because of the way the table here is scanned, options whose names are
                    105:  * substrings of other options must occur later; that is, with -lp vs -l, -lp
1.25      rillig    106:  * must be first.
1.1       cgd       107:  */
1.17      rillig    108: const struct pro {
1.14      kamil     109:     const char *p_name;                /* name, e.g. -bl, -cli */
                    110:     int         p_type;                /* type (int, bool, special) */
                    111:     int         p_special;     /* depends on type */
1.25      rillig    112:     void        *p_obj;                /* the associated variable */
1.14      kamil     113: }           pro[] = {
1.25      rillig    114:     special_option("T", KEY),
                    115:     special_option("U", KEY_FILE),
                    116:     special_option("-version", VERSION),
                    117:     special_option("P", IGN),
                    118:     bool_option("bacc", ON, opt.blanklines_around_conditional_compilation),
                    119:     bool_option("badp", ON, opt.blanklines_after_declarations_at_proctop),
                    120:     bool_option("bad", ON, opt.blanklines_after_declarations),
                    121:     bool_option("bap", ON, opt.blanklines_after_procs),
                    122:     bool_option("bbb", ON, opt.blanklines_before_blockcomments),
                    123:     bool_option("bc", OFF, opt.leave_comma),
                    124:     bool_option("bl", OFF, opt.btype_2),
                    125:     bool_option("br", ON, opt.btype_2),
1.27    ! rillig    126:     bool_option("bs", ON, opt.blank_after_sizeof),
1.25      rillig    127:     bool_option("cdb", ON, opt.comment_delimiter_on_blankline),
                    128:     int_option("cd", 0, opt.decl_comment_column),
                    129:     bool_option("ce", ON, opt.cuddle_else),
                    130:     int_option("ci", 0, opt.continuation_indent),
                    131:     special_option("cli", CLI),
                    132:     bool_option("cs", ON, opt.space_after_cast),
                    133:     int_option("c", 0, opt.comment_column),
                    134:     int_option("di", 0, opt.decl_indent),
                    135:     bool_option("dj", ON, opt.ljust_decl),
                    136:     int_option("d", 0, opt.unindent_displace),
                    137:     bool_option("eei", ON, opt.extra_expression_indent),
                    138:     bool_option("ei", ON, opt.else_if),
                    139:     bool_option("fbs", ON, opt.function_brace_split),
                    140:     bool_option("fc1", ON, opt.format_col1_comments),
                    141:     bool_option("fcb", ON, opt.format_block_comments),
                    142:     bool_option("ip", ON, opt.indent_parameters),
                    143:     int_option("i", 0, opt.indent_size),
                    144:     int_option("lc", 0, opt.block_comment_max_line_length),
                    145:     int_option("ldi", 0, opt.local_decl_indent),
                    146:     bool_option("lpl", ON, opt.lineup_to_parens_always),
                    147:     bool_option("lp", ON, opt.lineup_to_parens),
                    148:     int_option("l", 0, opt.max_line_length),
                    149:     bool_option("nbacc", OFF, opt.blanklines_around_conditional_compilation),
                    150:     bool_option("nbadp", OFF, opt.blanklines_after_declarations_at_proctop),
                    151:     bool_option("nbad", OFF, opt.blanklines_after_declarations),
                    152:     bool_option("nbap", OFF, opt.blanklines_after_procs),
                    153:     bool_option("nbbb", OFF, opt.blanklines_before_blockcomments),
                    154:     bool_option("nbc", ON, opt.leave_comma),
1.27    ! rillig    155:     bool_option("nbs", OFF, opt.blank_after_sizeof),
1.25      rillig    156:     bool_option("ncdb", OFF, opt.comment_delimiter_on_blankline),
                    157:     bool_option("nce", OFF, opt.cuddle_else),
                    158:     bool_option("ncs", OFF, opt.space_after_cast),
                    159:     bool_option("ndj", OFF, opt.ljust_decl),
                    160:     bool_option("neei", OFF, opt.extra_expression_indent),
                    161:     bool_option("nei", OFF, opt.else_if),
                    162:     bool_option("nfbs", OFF, opt.function_brace_split),
                    163:     bool_option("nfc1", OFF, opt.format_col1_comments),
                    164:     bool_option("nfcb", OFF, opt.format_block_comments),
                    165:     bool_option("nip", OFF, opt.indent_parameters),
                    166:     bool_option("nlpl", OFF, opt.lineup_to_parens_always),
                    167:     bool_option("nlp", OFF, opt.lineup_to_parens),
                    168:     bool_option("npcs", OFF, opt.proc_calls_space),
                    169:     special_option("npro", IGN),
                    170:     bool_option("npsl", OFF, opt.procnames_start_line),
                    171:     bool_option("nsc", OFF, opt.star_comment_cont),
                    172:     bool_option("nsob", OFF, opt.swallow_optional_blanklines),
                    173:     bool_option("nut", OFF, opt.use_tabs),
                    174:     bool_option("nv", OFF, opt.verbose),
                    175:     bool_option("pcs", ON, opt.proc_calls_space),
                    176:     bool_option("psl", ON, opt.procnames_start_line),
                    177:     bool_option("sc", ON, opt.star_comment_cont),
                    178:     bool_option("sob", ON, opt.swallow_optional_blanklines),
                    179:     special_option("st", STDIN),
                    180:     bool_option("ta", ON, opt.auto_typedefs),
                    181:     int_option("ts", 0, opt.tabsize),
                    182:     bool_option("ut", ON, opt.use_tabs),
                    183:     bool_option("v", ON, opt.verbose),
1.14      kamil     184:     /* whew! */
1.24      rillig    185:     {0, 0, 0, 0}
1.1       cgd       186: };
1.14      kamil     187:
1.1       cgd       188: /*
                    189:  * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
                    190:  * given in these files.
                    191:  */
1.5       lukem     192: void
1.14      kamil     193: set_profile(const char *profile_name)
1.1       cgd       194: {
1.14      kamil     195:     FILE *f;
                    196:     char fname[PATH_MAX];
                    197:     static char prof[] = ".indent.pro";
1.5       lukem     198:
1.14      kamil     199:     if (profile_name == NULL)
1.8       itojun    200:        snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof);
1.14      kamil     201:     else
                    202:        snprintf(fname, sizeof(fname), "%s", profile_name + 2);
                    203:     if ((f = fopen(option_source = fname, "r")) != NULL) {
                    204:        scan_profile(f);
                    205:        (void) fclose(f);
                    206:     }
                    207:     if ((f = fopen(option_source = prof, "r")) != NULL) {
                    208:        scan_profile(f);
                    209:        (void) fclose(f);
                    210:     }
                    211:     option_source = "Command line";
1.1       cgd       212: }
                    213:
1.14      kamil     214: static void
1.7       wiz       215: scan_profile(FILE *f)
1.1       cgd       216: {
1.15      rillig    217:     int                comment_index, i;
1.14      kamil     218:     char       *p;
                    219:     char        buf[BUFSIZ];
                    220:
1.22      rillig    221:     for (;;) {
1.14      kamil     222:        p = buf;
1.15      rillig    223:        comment_index = 0;
1.14      kamil     224:        while ((i = getc(f)) != EOF) {
1.25      rillig    225:            if (i == '*' && comment_index == 0 && p > buf && p[-1] == '/') {
1.22      rillig    226:                comment_index = (int)(p - buf);
1.14      kamil     227:                *p++ = i;
1.25      rillig    228:            } else if (i == '/' && comment_index != 0 && p > buf && p[-1] == '*') {
1.15      rillig    229:                p = buf + comment_index - 1;
                    230:                comment_index = 0;
1.14      kamil     231:            } else if (isspace((unsigned char)i)) {
1.25      rillig    232:                if (p > buf && comment_index == 0)
1.14      kamil     233:                    break;
                    234:            } else {
                    235:                *p++ = i;
                    236:            }
1.1       cgd       237:        }
1.14      kamil     238:        if (p != buf) {
                    239:            *p++ = 0;
                    240:            if (opt.verbose)
                    241:                printf("profile: %s\n", buf);
                    242:            set_option(buf);
1.19      rillig    243:        } else if (i == EOF)
1.14      kamil     244:            return;
                    245:     }
1.1       cgd       246: }
                    247:
1.14      kamil     248: static const char *
1.10      lukem     249: eqin(const char *s1, const char *s2)
1.1       cgd       250: {
1.25      rillig    251:     while (*s1 != '\0') {
1.14      kamil     252:        if (*s1++ != *s2++)
1.16      rillig    253:            return NULL;
1.14      kamil     254:     }
1.16      rillig    255:     return s2;
1.1       cgd       256: }
1.14      kamil     257:
1.5       lukem     258: void
1.7       wiz       259: set_option(char *arg)
1.1       cgd       260: {
1.17      rillig    261:     const struct pro *p;
1.14      kamil     262:     const char *param_start;
1.1       cgd       263:
1.14      kamil     264:     arg++;                     /* ignore leading "-" */
1.25      rillig    265:     for (p = pro; p->p_name != NULL; p++)
1.14      kamil     266:        if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL)
                    267:            goto found;
                    268:     errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
1.1       cgd       269: found:
1.14      kamil     270:     switch (p->p_type) {
1.1       cgd       271:
1.14      kamil     272:     case PRO_SPECIAL:
                    273:        switch (p->p_special) {
1.1       cgd       274:
1.14      kamil     275:        case IGN:
                    276:            break;
1.1       cgd       277:
1.14      kamil     278:        case CLI:
                    279:            if (*param_start == 0)
                    280:                goto need_param;
                    281:            opt.case_indent = atof(param_start);
                    282:            break;
                    283:
                    284:        case STDIN:
                    285:            if (input == NULL)
                    286:                input = stdin;
                    287:            if (output == NULL)
                    288:                output = stdout;
                    289:            break;
                    290:
                    291:        case KEY:
                    292:            if (*param_start == 0)
                    293:                goto need_param;
                    294:            add_typename(param_start);
                    295:            break;
                    296:
                    297:        case KEY_FILE:
                    298:            if (*param_start == 0)
                    299:                goto need_param;
                    300:            add_typedefs_from_file(param_start);
                    301:            break;
                    302:
                    303:        case VERSION:
                    304:            printf("FreeBSD indent %s\n", INDENT_VERSION);
                    305:            exit(0);
1.22      rillig    306:            /*NOTREACHED*/
1.1       cgd       307:
1.5       lukem     308:        default:
1.14      kamil     309:            errx(1, "set_option: internal error: p_special %d", p->p_special);
                    310:        }
                    311:        break;
                    312:
                    313:     case PRO_BOOL:
                    314:        if (p->p_special == OFF)
1.26      rillig    315:            *(bool *)p->p_obj = false;
1.14      kamil     316:        else
1.26      rillig    317:            *(bool *)p->p_obj = true;
1.14      kamil     318:        break;
                    319:
                    320:     case PRO_INT:
                    321:        if (!isdigit((unsigned char)*param_start)) {
                    322:     need_param:
                    323:            errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name);
1.1       cgd       324:        }
1.25      rillig    325:        *(int *)p->p_obj = atoi(param_start);
1.14      kamil     326:        break;
                    327:
                    328:     default:
                    329:        errx(1, "set_option: internal error: p_type %d", p->p_type);
                    330:     }
                    331: }
                    332:
                    333: void
                    334: add_typedefs_from_file(const char *str)
                    335: {
                    336:     FILE *file;
                    337:     char line[BUFSIZ];
                    338:
                    339:     if ((file = fopen(str, "r")) == NULL) {
                    340:        fprintf(stderr, "indent: cannot open file %s\n", str);
                    341:        exit(1);
                    342:     }
                    343:     while ((fgets(line, BUFSIZ, file)) != NULL) {
                    344:        /* Remove trailing whitespace */
                    345:        line[strcspn(line, " \t\n\r")] = '\0';
                    346:        add_typename(line);
                    347:     }
                    348:     fclose(file);
1.1       cgd       349: }

CVSweb <webmaster@jp.NetBSD.org>