args.c revision 1.17 1 1.17 rillig /* $NetBSD: args.c,v 1.17 2021/03/07 20:52:11 rillig Exp $ */
2 1.3 tls
3 1.14 kamil /*-
4 1.14 kamil * SPDX-License-Identifier: BSD-4-Clause
5 1.14 kamil *
6 1.14 kamil * Copyright (c) 1985 Sun Microsystems, Inc.
7 1.4 mrg * Copyright (c) 1980, 1993
8 1.4 mrg * The Regents of the University of California. All rights reserved.
9 1.1 cgd * All rights reserved.
10 1.1 cgd *
11 1.1 cgd * Redistribution and use in source and binary forms, with or without
12 1.1 cgd * modification, are permitted provided that the following conditions
13 1.1 cgd * are met:
14 1.1 cgd * 1. Redistributions of source code must retain the above copyright
15 1.1 cgd * notice, this list of conditions and the following disclaimer.
16 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 cgd * notice, this list of conditions and the following disclaimer in the
18 1.1 cgd * documentation and/or other materials provided with the distribution.
19 1.1 cgd * 3. All advertising materials mentioning features or use of this software
20 1.1 cgd * must display the following acknowledgement:
21 1.1 cgd * This product includes software developed by the University of
22 1.1 cgd * California, Berkeley and its contributors.
23 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
24 1.1 cgd * may be used to endorse or promote products derived from this software
25 1.1 cgd * without specific prior written permission.
26 1.1 cgd *
27 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 1.1 cgd * SUCH DAMAGE.
38 1.1 cgd */
39 1.1 cgd
40 1.14 kamil #if 0
41 1.14 kamil #ifndef lint
42 1.14 kamil static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93";
43 1.14 kamil #endif /* not lint */
44 1.14 kamil #endif
45 1.14 kamil
46 1.5 lukem #include <sys/cdefs.h>
47 1.1 cgd #ifndef lint
48 1.14 kamil #if defined(__NetBSD__)
49 1.17 rillig __RCSID("$NetBSD: args.c,v 1.17 2021/03/07 20:52:11 rillig Exp $");
50 1.14 kamil #elif defined(__FreeBSD__)
51 1.14 kamil __FBSDID("$FreeBSD: head/usr.bin/indent/args.c 336318 2018-07-15 21:04:21Z pstef $");
52 1.14 kamil #endif
53 1.4 mrg #endif
54 1.1 cgd
55 1.1 cgd /*
56 1.1 cgd * Argument scanning and profile reading code. Default parameters are set
57 1.1 cgd * here as well.
58 1.1 cgd */
59 1.1 cgd
60 1.5 lukem #include <ctype.h>
61 1.12 ginsbach #include <err.h>
62 1.14 kamil #include <limits.h>
63 1.1 cgd #include <stdio.h>
64 1.1 cgd #include <stdlib.h>
65 1.1 cgd #include <string.h>
66 1.15 rillig
67 1.14 kamil #include "indent.h"
68 1.14 kamil
69 1.14 kamil #define INDENT_VERSION "2.0"
70 1.1 cgd
71 1.1 cgd /* profile types */
72 1.1 cgd #define PRO_SPECIAL 1 /* special case */
73 1.1 cgd #define PRO_BOOL 2 /* boolean */
74 1.1 cgd #define PRO_INT 3 /* integer */
75 1.1 cgd
76 1.1 cgd /* profile specials for booleans */
77 1.1 cgd #define ON 1 /* turn it on */
78 1.1 cgd #define OFF 0 /* turn it off */
79 1.1 cgd
80 1.1 cgd /* profile specials for specials */
81 1.1 cgd #define IGN 1 /* ignore it */
82 1.1 cgd #define CLI 2 /* case label indent (float) */
83 1.1 cgd #define STDIN 3 /* use stdin */
84 1.1 cgd #define KEY 4 /* type (keyword) */
85 1.1 cgd
86 1.14 kamil static void scan_profile(FILE *);
87 1.14 kamil
88 1.14 kamil #define KEY_FILE 5 /* only used for args */
89 1.14 kamil #define VERSION 6 /* only used for args */
90 1.14 kamil
91 1.10 lukem const char *option_source = "?";
92 1.1 cgd
93 1.14 kamil void add_typedefs_from_file(const char *str);
94 1.14 kamil
95 1.1 cgd /*
96 1.1 cgd * N.B.: because of the way the table here is scanned, options whose names are
97 1.1 cgd * substrings of other options must occur later; that is, with -lp vs -l, -lp
98 1.1 cgd * must be first. Also, while (most) booleans occur more than once, the last
99 1.1 cgd * default value is the one actually assigned.
100 1.1 cgd */
101 1.17 rillig const struct pro {
102 1.14 kamil const char *p_name; /* name, e.g. -bl, -cli */
103 1.14 kamil int p_type; /* type (int, bool, special) */
104 1.14 kamil int p_default; /* the default value (if int) */
105 1.14 kamil int p_special; /* depends on type */
106 1.14 kamil int *p_obj; /* the associated variable */
107 1.14 kamil } pro[] = {
108 1.14 kamil {"T", PRO_SPECIAL, 0, KEY, 0},
109 1.14 kamil {"U", PRO_SPECIAL, 0, KEY_FILE, 0},
110 1.14 kamil {"-version", PRO_SPECIAL, 0, VERSION, 0},
111 1.14 kamil {"P", PRO_SPECIAL, 0, IGN, 0},
112 1.14 kamil {"bacc", PRO_BOOL, false, ON, &opt.blanklines_around_conditional_compilation},
113 1.14 kamil {"badp", PRO_BOOL, false, ON, &opt.blanklines_after_declarations_at_proctop},
114 1.14 kamil {"bad", PRO_BOOL, false, ON, &opt.blanklines_after_declarations},
115 1.14 kamil {"bap", PRO_BOOL, false, ON, &opt.blanklines_after_procs},
116 1.14 kamil {"bbb", PRO_BOOL, false, ON, &opt.blanklines_before_blockcomments},
117 1.14 kamil {"bc", PRO_BOOL, true, OFF, &opt.leave_comma},
118 1.14 kamil {"bl", PRO_BOOL, true, OFF, &opt.btype_2},
119 1.14 kamil {"br", PRO_BOOL, true, ON, &opt.btype_2},
120 1.14 kamil {"bs", PRO_BOOL, false, ON, &opt.Bill_Shannon},
121 1.14 kamil {"cdb", PRO_BOOL, true, ON, &opt.comment_delimiter_on_blankline},
122 1.14 kamil {"cd", PRO_INT, 0, 0, &opt.decl_com_ind},
123 1.14 kamil {"ce", PRO_BOOL, true, ON, &opt.cuddle_else},
124 1.14 kamil {"ci", PRO_INT, 0, 0, &opt.continuation_indent},
125 1.14 kamil {"cli", PRO_SPECIAL, 0, CLI, 0},
126 1.14 kamil {"cs", PRO_BOOL, false, ON, &opt.space_after_cast},
127 1.14 kamil {"c", PRO_INT, 33, 0, &opt.com_ind},
128 1.14 kamil {"di", PRO_INT, 16, 0, &opt.decl_indent},
129 1.14 kamil {"dj", PRO_BOOL, false, ON, &opt.ljust_decl},
130 1.14 kamil {"d", PRO_INT, 0, 0, &opt.unindent_displace},
131 1.14 kamil {"eei", PRO_BOOL, false, ON, &opt.extra_expression_indent},
132 1.14 kamil {"ei", PRO_BOOL, true, ON, &opt.else_if},
133 1.14 kamil {"fbs", PRO_BOOL, true, ON, &opt.function_brace_split},
134 1.14 kamil {"fc1", PRO_BOOL, true, ON, &opt.format_col1_comments},
135 1.14 kamil {"fcb", PRO_BOOL, true, ON, &opt.format_block_comments},
136 1.14 kamil {"ip", PRO_BOOL, true, ON, &opt.indent_parameters},
137 1.14 kamil {"i", PRO_INT, 8, 0, &opt.ind_size},
138 1.14 kamil {"lc", PRO_INT, 0, 0, &opt.block_comment_max_col},
139 1.14 kamil {"ldi", PRO_INT, -1, 0, &opt.local_decl_indent},
140 1.14 kamil {"lpl", PRO_BOOL, false, ON, &opt.lineup_to_parens_always},
141 1.14 kamil {"lp", PRO_BOOL, true, ON, &opt.lineup_to_parens},
142 1.14 kamil {"l", PRO_INT, 78, 0, &opt.max_col},
143 1.14 kamil {"nbacc", PRO_BOOL, false, OFF, &opt.blanklines_around_conditional_compilation},
144 1.14 kamil {"nbadp", PRO_BOOL, false, OFF, &opt.blanklines_after_declarations_at_proctop},
145 1.14 kamil {"nbad", PRO_BOOL, false, OFF, &opt.blanklines_after_declarations},
146 1.14 kamil {"nbap", PRO_BOOL, false, OFF, &opt.blanklines_after_procs},
147 1.14 kamil {"nbbb", PRO_BOOL, false, OFF, &opt.blanklines_before_blockcomments},
148 1.14 kamil {"nbc", PRO_BOOL, true, ON, &opt.leave_comma},
149 1.14 kamil {"nbs", PRO_BOOL, false, OFF, &opt.Bill_Shannon},
150 1.14 kamil {"ncdb", PRO_BOOL, true, OFF, &opt.comment_delimiter_on_blankline},
151 1.14 kamil {"nce", PRO_BOOL, true, OFF, &opt.cuddle_else},
152 1.14 kamil {"ncs", PRO_BOOL, false, OFF, &opt.space_after_cast},
153 1.14 kamil {"ndj", PRO_BOOL, false, OFF, &opt.ljust_decl},
154 1.14 kamil {"neei", PRO_BOOL, false, OFF, &opt.extra_expression_indent},
155 1.14 kamil {"nei", PRO_BOOL, true, OFF, &opt.else_if},
156 1.14 kamil {"nfbs", PRO_BOOL, true, OFF, &opt.function_brace_split},
157 1.14 kamil {"nfc1", PRO_BOOL, true, OFF, &opt.format_col1_comments},
158 1.14 kamil {"nfcb", PRO_BOOL, true, OFF, &opt.format_block_comments},
159 1.14 kamil {"nip", PRO_BOOL, true, OFF, &opt.indent_parameters},
160 1.14 kamil {"nlpl", PRO_BOOL, false, OFF, &opt.lineup_to_parens_always},
161 1.14 kamil {"nlp", PRO_BOOL, true, OFF, &opt.lineup_to_parens},
162 1.14 kamil {"npcs", PRO_BOOL, false, OFF, &opt.proc_calls_space},
163 1.14 kamil {"npro", PRO_SPECIAL, 0, IGN, 0},
164 1.14 kamil {"npsl", PRO_BOOL, true, OFF, &opt.procnames_start_line},
165 1.14 kamil {"nsc", PRO_BOOL, true, OFF, &opt.star_comment_cont},
166 1.14 kamil {"nsob", PRO_BOOL, false, OFF, &opt.swallow_optional_blanklines},
167 1.14 kamil {"nut", PRO_BOOL, true, OFF, &opt.use_tabs},
168 1.14 kamil {"nv", PRO_BOOL, false, OFF, &opt.verbose},
169 1.14 kamil {"pcs", PRO_BOOL, false, ON, &opt.proc_calls_space},
170 1.14 kamil {"psl", PRO_BOOL, true, ON, &opt.procnames_start_line},
171 1.14 kamil {"sc", PRO_BOOL, true, ON, &opt.star_comment_cont},
172 1.14 kamil {"sob", PRO_BOOL, false, ON, &opt.swallow_optional_blanklines},
173 1.14 kamil {"st", PRO_SPECIAL, 0, STDIN, 0},
174 1.14 kamil {"ta", PRO_BOOL, false, ON, &opt.auto_typedefs},
175 1.14 kamil {"ts", PRO_INT, 8, 0, &opt.tabsize},
176 1.14 kamil {"ut", PRO_BOOL, true, ON, &opt.use_tabs},
177 1.14 kamil {"v", PRO_BOOL, false, ON, &opt.verbose},
178 1.14 kamil /* whew! */
179 1.14 kamil {0, 0, 0, 0, 0}
180 1.1 cgd };
181 1.14 kamil
182 1.1 cgd /*
183 1.1 cgd * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
184 1.1 cgd * given in these files.
185 1.1 cgd */
186 1.5 lukem void
187 1.14 kamil set_profile(const char *profile_name)
188 1.1 cgd {
189 1.14 kamil FILE *f;
190 1.14 kamil char fname[PATH_MAX];
191 1.14 kamil static char prof[] = ".indent.pro";
192 1.5 lukem
193 1.14 kamil if (profile_name == NULL)
194 1.8 itojun snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof);
195 1.14 kamil else
196 1.14 kamil snprintf(fname, sizeof(fname), "%s", profile_name + 2);
197 1.14 kamil if ((f = fopen(option_source = fname, "r")) != NULL) {
198 1.14 kamil scan_profile(f);
199 1.14 kamil (void) fclose(f);
200 1.14 kamil }
201 1.14 kamil if ((f = fopen(option_source = prof, "r")) != NULL) {
202 1.14 kamil scan_profile(f);
203 1.14 kamil (void) fclose(f);
204 1.14 kamil }
205 1.14 kamil option_source = "Command line";
206 1.1 cgd }
207 1.1 cgd
208 1.14 kamil static void
209 1.7 wiz scan_profile(FILE *f)
210 1.1 cgd {
211 1.15 rillig int comment_index, i;
212 1.14 kamil char *p;
213 1.14 kamil char buf[BUFSIZ];
214 1.14 kamil
215 1.14 kamil while (1) {
216 1.14 kamil p = buf;
217 1.15 rillig comment_index = 0;
218 1.14 kamil while ((i = getc(f)) != EOF) {
219 1.15 rillig if (i == '*' && !comment_index && p > buf && p[-1] == '/') {
220 1.15 rillig comment_index = p - buf;
221 1.14 kamil *p++ = i;
222 1.15 rillig } else if (i == '/' && comment_index && p > buf && p[-1] == '*') {
223 1.15 rillig p = buf + comment_index - 1;
224 1.15 rillig comment_index = 0;
225 1.14 kamil } else if (isspace((unsigned char)i)) {
226 1.15 rillig if (p > buf && !comment_index)
227 1.14 kamil break;
228 1.14 kamil } else {
229 1.14 kamil *p++ = i;
230 1.14 kamil }
231 1.1 cgd }
232 1.14 kamil if (p != buf) {
233 1.14 kamil *p++ = 0;
234 1.14 kamil if (opt.verbose)
235 1.14 kamil printf("profile: %s\n", buf);
236 1.14 kamil set_option(buf);
237 1.14 kamil }
238 1.14 kamil else if (i == EOF)
239 1.14 kamil return;
240 1.14 kamil }
241 1.1 cgd }
242 1.1 cgd
243 1.14 kamil static const char *
244 1.10 lukem eqin(const char *s1, const char *s2)
245 1.1 cgd {
246 1.14 kamil while (*s1) {
247 1.14 kamil if (*s1++ != *s2++)
248 1.16 rillig return NULL;
249 1.14 kamil }
250 1.16 rillig return s2;
251 1.1 cgd }
252 1.14 kamil
253 1.1 cgd /*
254 1.1 cgd * Set the defaults.
255 1.1 cgd */
256 1.5 lukem void
257 1.7 wiz set_defaults(void)
258 1.1 cgd {
259 1.14 kamil /*
260 1.14 kamil * Because ps.case_indent is a float, we can't initialize it from the
261 1.14 kamil * table:
262 1.14 kamil */
263 1.17 rillig opt.case_indent = 0.0F; /* -cli0.0 */
264 1.17 rillig
265 1.17 rillig for (const struct pro *p = pro; p->p_name; p++)
266 1.14 kamil if (p->p_type != PRO_SPECIAL)
267 1.14 kamil *p->p_obj = p->p_default;
268 1.1 cgd }
269 1.1 cgd
270 1.5 lukem void
271 1.7 wiz set_option(char *arg)
272 1.1 cgd {
273 1.17 rillig const struct pro *p;
274 1.14 kamil const char *param_start;
275 1.1 cgd
276 1.14 kamil arg++; /* ignore leading "-" */
277 1.14 kamil for (p = pro; p->p_name; p++)
278 1.14 kamil if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL)
279 1.14 kamil goto found;
280 1.14 kamil errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
281 1.1 cgd found:
282 1.14 kamil switch (p->p_type) {
283 1.1 cgd
284 1.14 kamil case PRO_SPECIAL:
285 1.14 kamil switch (p->p_special) {
286 1.1 cgd
287 1.14 kamil case IGN:
288 1.14 kamil break;
289 1.1 cgd
290 1.14 kamil case CLI:
291 1.14 kamil if (*param_start == 0)
292 1.14 kamil goto need_param;
293 1.14 kamil opt.case_indent = atof(param_start);
294 1.14 kamil break;
295 1.14 kamil
296 1.14 kamil case STDIN:
297 1.14 kamil if (input == NULL)
298 1.14 kamil input = stdin;
299 1.14 kamil if (output == NULL)
300 1.14 kamil output = stdout;
301 1.14 kamil break;
302 1.14 kamil
303 1.14 kamil case KEY:
304 1.14 kamil if (*param_start == 0)
305 1.14 kamil goto need_param;
306 1.14 kamil add_typename(param_start);
307 1.14 kamil break;
308 1.14 kamil
309 1.14 kamil case KEY_FILE:
310 1.14 kamil if (*param_start == 0)
311 1.14 kamil goto need_param;
312 1.14 kamil add_typedefs_from_file(param_start);
313 1.14 kamil break;
314 1.14 kamil
315 1.14 kamil case VERSION:
316 1.14 kamil printf("FreeBSD indent %s\n", INDENT_VERSION);
317 1.14 kamil exit(0);
318 1.1 cgd
319 1.5 lukem default:
320 1.14 kamil errx(1, "set_option: internal error: p_special %d", p->p_special);
321 1.14 kamil }
322 1.14 kamil break;
323 1.14 kamil
324 1.14 kamil case PRO_BOOL:
325 1.14 kamil if (p->p_special == OFF)
326 1.14 kamil *p->p_obj = false;
327 1.14 kamil else
328 1.14 kamil *p->p_obj = true;
329 1.14 kamil break;
330 1.14 kamil
331 1.14 kamil case PRO_INT:
332 1.14 kamil if (!isdigit((unsigned char)*param_start)) {
333 1.14 kamil need_param:
334 1.14 kamil errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name);
335 1.1 cgd }
336 1.14 kamil *p->p_obj = atoi(param_start);
337 1.14 kamil break;
338 1.14 kamil
339 1.14 kamil default:
340 1.14 kamil errx(1, "set_option: internal error: p_type %d", p->p_type);
341 1.14 kamil }
342 1.14 kamil }
343 1.14 kamil
344 1.14 kamil void
345 1.14 kamil add_typedefs_from_file(const char *str)
346 1.14 kamil {
347 1.14 kamil FILE *file;
348 1.14 kamil char line[BUFSIZ];
349 1.14 kamil
350 1.14 kamil if ((file = fopen(str, "r")) == NULL) {
351 1.14 kamil fprintf(stderr, "indent: cannot open file %s\n", str);
352 1.14 kamil exit(1);
353 1.14 kamil }
354 1.14 kamil while ((fgets(line, BUFSIZ, file)) != NULL) {
355 1.14 kamil /* Remove trailing whitespace */
356 1.14 kamil line[strcspn(line, " \t\n\r")] = '\0';
357 1.14 kamil add_typename(line);
358 1.14 kamil }
359 1.14 kamil fclose(file);
360 1.1 cgd }
361