Annotation of src/usr.bin/indent/args.c, Revision 1.37
1.37 ! rillig 1: /* $NetBSD: args.c,v 1.36 2021/09/26 20:21:47 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.37 ! rillig 46: __RCSID("$NetBSD: args.c,v 1.36 2021/09/26 20:21:47 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:
1.14 kamil 67: static void scan_profile(FILE *);
1.32 rillig 68: void add_typedefs_from_file(const char *);
1.14 kamil 69:
1.32 rillig 70: static const char *option_source = "?";
1.14 kamil 71:
1.25 rillig 72: #if __STDC_VERSION__ >= 201112L
73: #define assert_type(expr, type) _Generic((expr), type : (expr))
74: #else
75: #define assert_type(expr, type) (expr)
76: #endif
77: #define bool_option(name, value, var) \
1.37 ! rillig 78: {name, true, value, false, assert_type(&(var), bool *)}
1.31 rillig 79: #define int_option(name, var) \
1.37 ! rillig 80: {name, false, false, false, assert_type(&(var), int *)}
1.35 rillig 81: #define bool_options(name, var) \
1.37 ! rillig 82: {name, true, false, true, assert_type(&(var), bool *)}
1.25 rillig 83:
1.1 cgd 84: /*
1.36 rillig 85: * N.B.: an option whose name is a prefix of another option must come earlier;
86: * for example, "l" must come before "lp".
1.32 rillig 87: *
1.36 rillig 88: * See set_special_option for special options.
1.1 cgd 89: */
1.29 rillig 90: static const struct pro {
1.37 ! rillig 91: const char p_name[5]; /* name, e.g. "bl", "cli" */
1.33 rillig 92: bool p_is_bool;
93: bool p_bool_value;
1.37 ! rillig 94: bool p_may_negate;
1.33 rillig 95: void *p_obj; /* the associated variable (bool, int) */
96: } pro[] = {
1.35 rillig 97: bool_options("bacc", opt.blanklines_around_conditional_compilation),
1.36 rillig 98: bool_options("bad", opt.blanklines_after_declarations),
1.35 rillig 99: bool_options("badp", opt.blanklines_after_declarations_at_proctop),
100: bool_options("bap", opt.blanklines_after_procs),
101: bool_options("bbb", opt.blanklines_before_blockcomments),
102: bool_options("bc", opt.break_after_comma),
1.31 rillig 103: bool_option("bl", false, opt.btype_2),
104: bool_option("br", true, opt.btype_2),
1.35 rillig 105: bool_options("bs", opt.blank_after_sizeof),
1.36 rillig 106: int_option("c", opt.comment_column),
107: int_option("cd", opt.decl_comment_column),
1.35 rillig 108: bool_options("cdb", opt.comment_delimiter_on_blankline),
109: bool_options("ce", opt.cuddle_else),
1.31 rillig 110: int_option("ci", opt.continuation_indent),
1.36 rillig 111: /* "cli" is special */
1.35 rillig 112: bool_options("cs", opt.space_after_cast),
1.36 rillig 113: int_option("d", opt.unindent_displace),
1.31 rillig 114: int_option("di", opt.decl_indent),
1.35 rillig 115: bool_options("dj", opt.ljust_decl),
116: bool_options("eei", opt.extra_expression_indent),
117: bool_options("ei", opt.else_if),
118: bool_options("fbs", opt.function_brace_split),
119: bool_options("fc1", opt.format_col1_comments),
120: bool_options("fcb", opt.format_block_comments),
1.36 rillig 121: int_option("i", opt.indent_size),
1.35 rillig 122: bool_options("ip", opt.indent_parameters),
1.36 rillig 123: int_option("l", opt.max_line_length),
1.31 rillig 124: int_option("lc", opt.block_comment_max_line_length),
125: int_option("ldi", opt.local_decl_indent),
1.36 rillig 126: bool_options("lp", opt.lineup_to_parens),
1.35 rillig 127: bool_options("lpl", opt.lineup_to_parens_always),
1.36 rillig 128: /* "npro" is special */
129: /* "P" is special */
1.35 rillig 130: bool_options("pcs", opt.proc_calls_space),
131: bool_options("psl", opt.procnames_start_line),
132: bool_options("sc", opt.star_comment_cont),
133: bool_options("sob", opt.swallow_optional_blanklines),
1.36 rillig 134: /* "st" is special */
1.31 rillig 135: bool_option("ta", true, opt.auto_typedefs),
1.36 rillig 136: /* "T" is special */
1.31 rillig 137: int_option("ts", opt.tabsize),
1.36 rillig 138: /* "U" is special */
1.35 rillig 139: bool_options("ut", opt.use_tabs),
140: bool_options("v", opt.verbose),
1.1 cgd 141: };
1.14 kamil 142:
1.1 cgd 143: /*
144: * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
145: * given in these files.
146: */
1.5 lukem 147: void
1.14 kamil 148: set_profile(const char *profile_name)
1.1 cgd 149: {
1.14 kamil 150: FILE *f;
151: char fname[PATH_MAX];
152: static char prof[] = ".indent.pro";
1.5 lukem 153:
1.14 kamil 154: if (profile_name == NULL)
1.8 itojun 155: snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof);
1.14 kamil 156: else
157: snprintf(fname, sizeof(fname), "%s", profile_name + 2);
158: if ((f = fopen(option_source = fname, "r")) != NULL) {
159: scan_profile(f);
1.33 rillig 160: (void)fclose(f);
1.14 kamil 161: }
162: if ((f = fopen(option_source = prof, "r")) != NULL) {
163: scan_profile(f);
1.33 rillig 164: (void)fclose(f);
1.14 kamil 165: }
166: option_source = "Command line";
1.1 cgd 167: }
168:
1.14 kamil 169: static void
1.7 wiz 170: scan_profile(FILE *f)
1.1 cgd 171: {
1.33 rillig 172: int comment_index, i;
173: char *p;
174: char buf[BUFSIZ];
1.14 kamil 175:
1.22 rillig 176: for (;;) {
1.14 kamil 177: p = buf;
1.15 rillig 178: comment_index = 0;
1.14 kamil 179: while ((i = getc(f)) != EOF) {
1.25 rillig 180: if (i == '*' && comment_index == 0 && p > buf && p[-1] == '/') {
1.22 rillig 181: comment_index = (int)(p - buf);
1.14 kamil 182: *p++ = i;
1.25 rillig 183: } else if (i == '/' && comment_index != 0 && p > buf && p[-1] == '*') {
1.15 rillig 184: p = buf + comment_index - 1;
185: comment_index = 0;
1.14 kamil 186: } else if (isspace((unsigned char)i)) {
1.25 rillig 187: if (p > buf && comment_index == 0)
1.14 kamil 188: break;
189: } else {
190: *p++ = i;
191: }
1.1 cgd 192: }
1.14 kamil 193: if (p != buf) {
194: *p++ = 0;
195: if (opt.verbose)
196: printf("profile: %s\n", buf);
197: set_option(buf);
1.19 rillig 198: } else if (i == EOF)
1.14 kamil 199: return;
200: }
1.1 cgd 201: }
202:
1.14 kamil 203: static const char *
1.37 ! rillig 204: skip_over(const char *s, bool may_negate, const char *prefix)
1.1 cgd 205: {
1.37 ! rillig 206: if (may_negate && s[0] == 'n')
! 207: s++;
1.30 rillig 208: while (*prefix != '\0') {
209: if (*prefix++ != *s++)
1.16 rillig 210: return NULL;
1.14 kamil 211: }
1.30 rillig 212: return s;
1.1 cgd 213: }
1.14 kamil 214:
1.32 rillig 215: static bool
216: set_special_option(const char *arg)
217: {
218: const char *arg_end;
219:
220: if (strncmp(arg, "-version", 8) == 0) {
221: printf("FreeBSD indent %s\n", INDENT_VERSION);
222: exit(0);
1.33 rillig 223: /* NOTREACHED */
1.32 rillig 224: }
225:
226: if (arg[0] == 'P' || strncmp(arg, "npro", 4) == 0)
227: return true;
228:
229: if (strncmp(arg, "cli", 3) == 0) {
230: arg_end = arg + 3;
231: if (arg_end[0] == '\0')
232: goto need_param;
233: opt.case_indent = atof(arg_end);
234: return true;
235: }
236:
237: if (strncmp(arg, "st", 2) == 0) {
238: if (input == NULL)
239: input = stdin;
240: if (output == NULL)
241: output = stdout;
242: return true;
243: }
244:
245: if (arg[0] == 'T') {
246: arg_end = arg + 1;
247: if (arg_end[0] == '\0')
248: goto need_param;
249: add_typename(arg_end);
250: return true;
251: }
252:
253: if (arg[0] == 'U') {
254: arg_end = arg + 1;
255: if (arg_end[0] == '\0')
256: goto need_param;
257: add_typedefs_from_file(arg_end);
258: return true;
259: }
260:
261: return false;
262:
263: need_param:
264: errx(1, "%s: ``%.*s'' requires a parameter",
265: option_source, (int)(arg_end - arg), arg);
266: /* NOTREACHED */
267: }
268:
1.5 lukem 269: void
1.29 rillig 270: set_option(const char *arg)
1.1 cgd 271: {
1.17 rillig 272: const struct pro *p;
1.33 rillig 273: const char *param_start;
1.1 cgd 274:
1.14 kamil 275: arg++; /* ignore leading "-" */
1.32 rillig 276: if (set_special_option(arg))
277: return;
278:
1.37 ! rillig 279: for (p = pro + nitems(pro); p-- != pro;) {
! 280: param_start = skip_over(arg, p->p_may_negate, p->p_name);
! 281: if (param_start != NULL)
! 282: goto found;
! 283: }
1.14 kamil 284: errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
1.30 rillig 285:
1.1 cgd 286: found:
1.32 rillig 287: if (p->p_is_bool)
1.37 ! rillig 288: *(bool *)p->p_obj = p->p_may_negate ? arg[0] != 'n' : p->p_bool_value;
1.32 rillig 289: else {
290: if (!isdigit((unsigned char)*param_start))
291: errx(1, "%s: ``%s'' requires a parameter",
292: option_source, p->p_name);
1.25 rillig 293: *(int *)p->p_obj = atoi(param_start);
1.14 kamil 294: }
295: }
296:
297: void
1.30 rillig 298: add_typedefs_from_file(const char *fname)
1.14 kamil 299: {
300: FILE *file;
301: char line[BUFSIZ];
302:
1.30 rillig 303: if ((file = fopen(fname, "r")) == NULL) {
304: fprintf(stderr, "indent: cannot open file %s\n", fname);
1.14 kamil 305: exit(1);
306: }
307: while ((fgets(line, BUFSIZ, file)) != NULL) {
308: /* Remove trailing whitespace */
309: line[strcspn(line, " \t\n\r")] = '\0';
310: add_typename(line);
311: }
312: fclose(file);
1.1 cgd 313: }
CVSweb <webmaster@jp.NetBSD.org>