xref: /netbsd-src/usr.bin/indent/args.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: args.c,v 1.13 2016/02/22 21:20:29 ginsbach Exp $	*/
2 
3 /*
4  * Copyright (c) 1980, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
34  * Copyright (c) 1985 Sun Microsystems, Inc.
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *	This product includes software developed by the University of
48  *	California, Berkeley and its contributors.
49  * 4. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  */
65 
66 #include <sys/cdefs.h>
67 #ifndef lint
68 #if 0
69 static char sccsid[] = "@(#)args.c	8.1 (Berkeley) 6/6/93";
70 #else
71 __RCSID("$NetBSD: args.c,v 1.13 2016/02/22 21:20:29 ginsbach Exp $");
72 #endif
73 #endif				/* not lint */
74 
75 /*
76  * Argument scanning and profile reading code.  Default parameters are set
77  * here as well.
78  */
79 
80 #include <ctype.h>
81 #include <err.h>
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
85 #include "indent_globs.h"
86 
87 /* profile types */
88 #define	PRO_SPECIAL	1	/* special case */
89 #define	PRO_BOOL	2	/* boolean */
90 #define	PRO_INT		3	/* integer */
91 #define PRO_FONT	4	/* troff font */
92 
93 /* profile specials for booleans */
94 #define	ON		1	/* turn it on */
95 #define	OFF		0	/* turn it off */
96 
97 /* profile specials for specials */
98 #define	IGN		1	/* ignore it */
99 #define	CLI		2	/* case label indent (float) */
100 #define	STDIN		3	/* use stdin */
101 #define	KEY		4	/* type (keyword) */
102 
103 const char *option_source = "?";
104 
105 /*
106  * N.B.: because of the way the table here is scanned, options whose names are
107  * substrings of other options must occur later; that is, with -lp vs -l, -lp
108  * must be first.  Also, while (most) booleans occur more than once, the last
109  * default value is the one actually assigned.
110  */
111 struct pro {
112 	const char *p_name;	/* name, eg -bl, -cli */
113 	int     p_type;		/* type (int, bool, special) */
114 	int     p_default;	/* the default value (if int) */
115 	int     p_special;	/* depends on type */
116 	int    *p_obj;		/* the associated variable */
117 }       pro[] = {
118 	{
119 		"T", PRO_SPECIAL, 0, KEY, 0
120 	},
121 	{
122 		"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation
123 	},
124 	{
125 		"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop
126 	},
127 	{
128 		"bad", PRO_BOOL, false, ON, &blanklines_after_declarations
129 	},
130 	{
131 		"bap", PRO_BOOL, false, ON, &blanklines_after_procs
132 	},
133 	{
134 		"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments
135 	},
136 	{
137 		"bc", PRO_BOOL, true, OFF, &ps.leave_comma
138 	},
139 	{
140 		"bl", PRO_BOOL, true, OFF, &btype_2
141 	},
142 	{
143 		"br", PRO_BOOL, true, ON, &btype_2
144 	},
145 	{
146 		"bs", PRO_BOOL, false, ON, &Bill_Shannon
147 	},
148 	{
149 		"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline
150 	},
151 	{
152 		"cd", PRO_INT, 0, 0, &ps.decl_com_ind
153 	},
154 	{
155 		"ce", PRO_BOOL, true, ON, &cuddle_else
156 	},
157 	{
158 		"ci", PRO_INT, 0, 0, &continuation_indent
159 	},
160 	{
161 		"cli", PRO_SPECIAL, 0, CLI, 0
162 	},
163 	{
164 		"c", PRO_INT, 33, 0, &ps.com_ind
165 	},
166 	{
167 		"di", PRO_INT, 16, 0, &ps.decl_indent
168 	},
169 	{
170 		"dj", PRO_BOOL, false, ON, &ps.ljust_decl
171 	},
172 	{
173 		"d", PRO_INT, 0, 0, &ps.unindent_displace
174 	},
175 	{
176 		"eei", PRO_BOOL, false, ON, &extra_expression_indent
177 	},
178 	{
179 		"ei", PRO_BOOL, true, ON, &ps.else_if
180 	},
181 	{
182 		"fbc", PRO_FONT, 0, 0, (int *) &blkcomf
183 	},
184 	{
185 		"fbx", PRO_FONT, 0, 0, (int *) &boxcomf
186 	},
187 	{
188 		"fb", PRO_FONT, 0, 0, (int *) &bodyf
189 	},
190 	{
191 		"fc1", PRO_BOOL, true, ON, &format_col1_comments
192 	},
193 	{
194 		"fc", PRO_FONT, 0, 0, (int *) &scomf
195 	},
196 	{
197 		"fk", PRO_FONT, 0, 0, (int *) &keywordf
198 	},
199 	{
200 		"fs", PRO_FONT, 0, 0, (int *) &stringf
201 	},
202 	{
203 		"ip", PRO_BOOL, true, ON, &ps.indent_parameters
204 	},
205 	{
206 		"i", PRO_INT, 8, 0, &ps.ind_size
207 	},
208 	{
209 		"lc", PRO_INT, 0, 0, &block_comment_max_col
210 	},
211 	{
212 		"lp", PRO_BOOL, true, ON, &lineup_to_parens
213 	},
214 	{
215 		"l", PRO_INT, 78, 0, &max_col
216 	},
217 	{
218 		"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation
219 	},
220 	{
221 		"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop
222 	},
223 	{
224 		"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations
225 	},
226 	{
227 		"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs
228 	},
229 	{
230 		"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments
231 	},
232 	{
233 		"nbc", PRO_BOOL, true, ON, &ps.leave_comma
234 	},
235 	{
236 		"nbs", PRO_BOOL, false, OFF, &Bill_Shannon
237 	},
238 	{
239 		"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline
240 	},
241 	{
242 		"nce", PRO_BOOL, true, OFF, &cuddle_else
243 	},
244 	{
245 		"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl
246 	},
247 	{
248 		"neei", PRO_BOOL, false, OFF, &extra_expression_indent
249 	},
250 	{
251 		"nei", PRO_BOOL, true, OFF, &ps.else_if
252 	},
253 	{
254 		"nfc1", PRO_BOOL, true, OFF, &format_col1_comments
255 	},
256 	{
257 		"nip", PRO_BOOL, true, OFF, &ps.indent_parameters
258 	},
259 	{
260 		"nlp", PRO_BOOL, true, OFF, &lineup_to_parens
261 	},
262 	{
263 		"npcs", PRO_BOOL, false, OFF, &proc_calls_space
264 	},
265 	{
266 		"npro", PRO_SPECIAL, 0, IGN, 0
267 	},
268 	{
269 		"npsl", PRO_BOOL, true, OFF, &procnames_start_line
270 	},
271 	{
272 		"nps", PRO_BOOL, false, OFF, &pointer_as_binop
273 	},
274 	{
275 		"nsc", PRO_BOOL, true, OFF, &star_comment_cont
276 	},
277 	{
278 		"nut", PRO_BOOL, true, OFF, &use_tabs
279 	},
280 	{
281 		"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines
282 	},
283 	{
284 		"nv", PRO_BOOL, false, OFF, &verbose
285 	},
286 	{
287 		"pcs", PRO_BOOL, false, ON, &proc_calls_space
288 	},
289 	{
290 		"psl", PRO_BOOL, true, ON, &procnames_start_line
291 	},
292 	{
293 		"ps", PRO_BOOL, false, ON, &pointer_as_binop
294 	},
295 	{
296 		"sc", PRO_BOOL, true, ON, &star_comment_cont
297 	},
298 	{
299 		"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines
300 	},
301 	{
302 		"st", PRO_SPECIAL, 0, STDIN, 0
303 	},
304 	{
305 		"troff", PRO_BOOL, false, ON, &troff
306 	},
307 	{
308 		"ut", PRO_BOOL, true, ON, &use_tabs
309 	},
310 	{
311 		"v", PRO_BOOL, false, ON, &verbose
312 	},
313 	/* whew! */
314 	{
315 		0, 0, 0, 0, 0
316 	}
317 };
318 /*
319  * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
320  * given in these files.
321  */
322 void
323 set_profile(void)
324 {
325 	FILE   *f;
326 	char    fname[BUFSIZ];
327 	static char prof[] = ".indent.pro";
328 
329 	snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof);
330 	if ((f = fopen(option_source = fname, "r")) != NULL) {
331 		scan_profile(f);
332 		(void) fclose(f);
333 	}
334 	if ((f = fopen(option_source = prof, "r")) != NULL) {
335 		scan_profile(f);
336 		(void) fclose(f);
337 	}
338 	option_source = "Command line";
339 }
340 
341 void
342 scan_profile(FILE *f)
343 {
344 	int     i;
345 	char   *p;
346 	char    buf[BUFSIZ];
347 
348 	while (1) {
349 		for (p = buf; (i = getc(f)) != EOF && (*p = i) > ' '; ++p);
350 		if (p != buf) {
351 			*p++ = 0;
352 			if (verbose)
353 				printf("profile: %s\n", buf);
354 			set_option(buf);
355 		} else
356 			if (i == EOF)
357 				return;
358 	}
359 }
360 
361 const char *param_start;
362 
363 int
364 eqin(const char *s1, const char *s2)
365 {
366 	while (*s1) {
367 		if (*s1++ != *s2++)
368 			return (false);
369 	}
370 	param_start = s2;
371 	return (true);
372 }
373 /*
374  * Set the defaults.
375  */
376 void
377 set_defaults(void)
378 {
379 	struct pro *p;
380 
381 	/*
382          * Because ps.case_indent is a float, we can't initialize it from the
383          * table:
384          */
385 	ps.case_indent = 0.0;	/* -cli0.0 */
386 	for (p = pro; p->p_name; p++)
387 		if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT)
388 			*p->p_obj = p->p_default;
389 }
390 
391 void
392 set_option(char *arg)
393 {
394 	struct pro *p;
395 
396 	arg++;			/* ignore leading "-" */
397 	for (p = pro; p->p_name; p++)
398 		if (*p->p_name == *arg && eqin(p->p_name, arg))
399 			goto found;
400 	errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
401 found:
402 	switch (p->p_type) {
403 
404 	case PRO_SPECIAL:
405 		switch (p->p_special) {
406 
407 		case IGN:
408 			break;
409 
410 		case CLI:
411 			if (*param_start == 0)
412 				goto need_param;
413 			ps.case_indent = atof(param_start);
414 			break;
415 
416 		case STDIN:
417 			if (input == 0)
418 				input = stdin;
419 			if (output == 0)
420 				output = stdout;
421 			break;
422 
423 		case KEY:
424 			if (*param_start == 0)
425 				goto need_param;
426 			{
427 				char   *str;
428 
429 				str = strdup(param_start);
430 				addkey(str, 4);
431 			}
432 			break;
433 
434 		default:
435 			errx(1, "set_option: internal error: p_special %d",
436 			     p->p_special);
437 		}
438 		break;
439 
440 	case PRO_BOOL:
441 		if (p->p_special == OFF)
442 			*p->p_obj = false;
443 		else
444 			*p->p_obj = true;
445 		break;
446 
447 	case PRO_INT:
448 		if (!isdigit((unsigned char)*param_start)) {
449 	need_param:
450 			errx(1, "%s: ``%s'' requires a parameter",
451 			     option_source, arg - 1);
452 		}
453 		*p->p_obj = atoi(param_start);
454 		break;
455 
456 	case PRO_FONT:
457 		parsefont((struct fstate *) p->p_obj, param_start);
458 		break;
459 
460 	default:
461 		errx(1, "set_option: internal error: p_type %d", p->p_type);
462 	}
463 }
464