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