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>