1 /*
2 * Copyright (c) 1985 Sun Microsystems, Inc.
3 * Copyright (c) 1980 The Regents of the University of California.
4 * Copyright (c) 1976 Board of Trustees of the University of Illinois.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the University of California, Berkeley, the University of Illinois,
13 * Urbana, and Sun Microsystems, Inc. The name of either University
14 * or Sun Microsystems may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 */
20
21 #ifndef lint
22 static char sccsid[] = "@(#)args.c 5.6 (Berkeley) 9/15/88";
23 #endif /* not lint */
24
25 /*
26 * Argument scanning and profile reading code. Default parameters are set
27 * here as well.
28 */
29
30 #include "indent_globs.h"
31 #include <ctype.h>
32 #include "version.h"
33
34 int else_endif_col;
35
36 extern char *in_name;
37
38 char *getenv();
39
40 /* profile types */
41 enum profile {PRO_BOOL, /* boolean */
42 PRO_INT, /* integer */
43 PRO_FONT, /* troff font */
44 PRO_IGN, /* ignore it */
45 PRO_STDIN, /* -st switch */
46 PRO_KEY, /* -T switch */
47 PRO_SETTINGS, /* bundled set of settings */
48 PRO_PRSTRING /* Print string and exit */
49 };
50
51 /* profile specials for booleans */
52 enum on_or_off {OFF,ON};
53
54 /* Explicit flags for each option. */
55 static int exp_T = 0;
56 static int exp_bacc = 0;
57 static int exp_badp = 0;
58 static int exp_bad = 0;
59 static int exp_bap = 0;
60 static int exp_bbb = 0;
61 static int exp_bc = 0;
62 static int exp_bli = 0;
63 static int exp_bl = 0;
64 static int exp_bs = 0;
65 static int exp_cdb = 0;
66 static int exp_cd = 0;
67 static int exp_ce = 0;
68 static int exp_ci = 0;
69 static int exp_cli = 0;
70 static int exp_cp = 0;
71 static int exp_c = 0;
72 static int exp_di = 0;
73 static int exp_dj = 0;
74 static int exp_d = 0;
75 static int exp_eei = 0;
76 static int exp_ei = 0;
77 static int exp_fbc = 0;
78 static int exp_fbx = 0;
79 static int exp_fb = 0;
80 static int exp_fc1 = 0;
81 static int exp_fca = 0;
82 static int exp_fc = 0;
83 static int exp_fk = 0;
84 static int exp_fs = 0;
85 static int exp_gnu = 0;
86 static int exp_ip = 0;
87 static int exp_i = 0;
88 static int exp_lc = 0;
89 static int exp_lp = 0;
90 static int exp_l = 0;
91 static int exp_pcs = 0;
92 static int exp_psl = 0;
93 static int exp_pro = 0;
94 static int exp_ps = 0;
95 static int exp_kr = 0;
96 static int exp_sc = 0;
97 static int exp_sob = 0;
98 static int exp_ss = 0;
99 static int exp_st = 0;
100 static int exp_troff = 0;
101 static int exp_v = 0;
102 static int exp_version = 0;
103 static int exp_lpc = 0;
104
105 /* The following variables are controlled by command line parameters and
106 their meaning is explained in indent_globs.h. */
107 int leave_comma;
108 int decl_com_ind;
109 int case_indent;
110 int com_ind;
111 int decl_indent;
112 int ljust_decl;
113 int unindent_displace;
114 int else_if;
115 int indent_parameters;
116 int ind_size;
117 int blanklines_after_procs;
118 int lpc;
119 int noarrowspace;
120
121 /*
122 * N.B.: because of the way the table here is scanned, options whose names are
123 * substrings of other options must occur later; that is, with -lp vs -l, -lp
124 * must be first. Also, while (most) booleans occur more than once, the last
125 * default value is the one actually assigned.
126 */
127 struct pro {
128 char *p_name; /* name, eg -bl, -cli */
129 enum profile p_type;
130 int p_default; /* the default value (if int) */
131
132 /* If p_type == PRO_BOOL, ON or OFF to tell how this switch affects
133 the variable.
134 Not used for other p_type's. */
135 enum on_or_off p_special;
136
137 /* if p_type == PRO_SETTINGS, a (char *) pointing to a list of the
138 switches to set, separated by NULs, terminated by 2 NULs.
139 if p_type == PRO_BOOL, PRO_INT, or PRO_FONT, address of the
140 variable that gets set by the option.
141 if p_type == PRO_PRSTRING, a (char *) pointing to the string. */
142 int *p_obj;
143
144 /* Points to a nonzero value (allocated statically for all options)
145 if the option has been specified explicitly. This is necessary
146 because for boolean options, the options to set and reset the
147 variable must share the explicit flag. */
148 int* p_explicit;
149 };
150
151 struct pro pro[] = {
152
153 {"T", PRO_KEY, 0, 0, 0, &exp_T},
154 {"bacc", PRO_BOOL, false, ON,
155 &blanklines_around_conditional_compilation, &exp_bacc},
156 {"badp", PRO_BOOL, false, ON,
157 &blanklines_after_declarations_at_proctop, &exp_badp},
158 {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations, &exp_bad},
159 {"bap", PRO_BOOL, false, ON, &blanklines_after_procs, &exp_bap},
160 {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments, &exp_bbb},
161 {"bc", PRO_BOOL, true, OFF, &leave_comma, &exp_bc},
162 {"bli", PRO_INT, 0, 0, &brace_indent, &exp_bli},
163 {"bl", PRO_BOOL, true, OFF, &btype_2, &exp_bl},
164 {"br", PRO_BOOL, true, ON, &btype_2, &exp_bl},
165 {"bs", PRO_BOOL, false, ON, &Bill_Shannon, &exp_bs},
166 {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline, &exp_cdb},
167 {"cd", PRO_INT, 0, 0, &decl_com_ind, &exp_cd},
168 {"ce", PRO_BOOL, true, ON, &cuddle_else, &exp_ce},
169 {"ci", PRO_INT, 0, 0, &continuation_indent, &exp_ci},
170 {"cli", PRO_INT, 0, 0, &case_indent, &exp_cli},
171 {"cp", PRO_INT, 33, 0, &else_endif_col, &exp_cp},
172 {"c", PRO_INT, 33, 0, &com_ind, &exp_c},
173 {"di", PRO_INT, 16, 0, &decl_indent, &exp_di},
174 {"dj", PRO_BOOL, false, ON, &ljust_decl, &exp_dj},
175 {"d", PRO_INT, 0, 0, &unindent_displace, &exp_d},
176 {"eei", PRO_BOOL, false, ON, &extra_expression_indent, &exp_eei},
177 {"ei", PRO_BOOL, true, ON, &else_if, &exp_ei},
178 {"fbc", PRO_FONT, 0, 0, (int *) &blkcomf, &exp_fbc},
179 {"fbx", PRO_FONT, 0, 0, (int *) &boxcomf, &exp_fbx},
180 {"fb", PRO_FONT, 0, 0, (int *) &bodyf, &exp_fb},
181 {"fc1", PRO_BOOL, true, ON, &format_col1_comments, &exp_fc1},
182 {"fca", PRO_BOOL, true, ON, &format_comments, &exp_fca},
183 {"fc", PRO_FONT, 0, 0, (int *) &scomf, &exp_fc},
184 {"fk", PRO_FONT, 0, 0, (int *) &keywordf, &exp_fk},
185 {"fs", PRO_FONT, 0, 0, (int *) &stringf, &exp_fs},
186 {"gnu", PRO_SETTINGS, 0, 0,
187 (int *)"-nbad\0-bap\0-nbbb\0-nbc\0-bl\0-ncdb\0-nce\0-di0\0-ndj\0\
188 -ei\0-nfc1\0-i2\0-ip5\0-lp\0-pcs\0-nps\0-psl\0-nsc\0-nsob\0-bli2\0-ss\0\
189 -cp1\0-nfca\0", &exp_gnu},
190 {"ip", PRO_INT, 4, ON, &indent_parameters, &exp_ip},
191 {"i", PRO_INT, 4, 0, &ind_size, &exp_i},
192 {"kr", PRO_SETTINGS, 0, 0,
193 (int *)"-nbad\0-bap\0-nbbb\0-nbc\0-br\0-c33\0-cd33\0-ncdb\0-ce\0\
194 -ci4\0-cli0\0-d0\0-di1\0-nfc1\0-i4\0-ip0\0-l75\0-lp\0-npcs\0-npsl\0\
195 -nsc\0-nsc\0-nsob\0-nfca\0-cp33\0-nss\0", &exp_kr},
196 {"lpc", PRO_BOOL, false, ON, &lpc, &exp_lpc},
197 {"lc", PRO_INT, 0, 0, &block_comment_max_col, &exp_lc},
198 {"lp", PRO_BOOL, true, ON, &lineup_to_parens, &exp_lp},
199 {"l", PRO_INT, 78, 0, &max_col, &exp_l},
200 {"nbacc", PRO_BOOL, false, ON,
201 &blanklines_around_conditional_compilation, &exp_bacc},
202 {"nbadp", PRO_BOOL, false, OFF,
203 &blanklines_after_declarations_at_proctop, &exp_badp},
204 {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations, &exp_bad},
205 {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs, &exp_bap},
206 {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments, &exp_bbb},
207 {"nbc", PRO_BOOL, true, ON, &leave_comma, &exp_bc},
208 {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon, &exp_bs},
209 {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline, &exp_cdb},
210 {"nce", PRO_BOOL, true, OFF, &cuddle_else, &exp_ce},
211 {"ndj", PRO_BOOL, false, OFF, &ljust_decl, &exp_dj},
212 {"neei", PRO_BOOL, false, OFF, &extra_expression_indent, &exp_eei},
213 {"nei", PRO_BOOL, true, OFF, &else_if, &exp_ei},
214 {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments, &exp_fc1},
215 {"nfca", PRO_BOOL, true, OFF, &format_comments, &exp_fca},
216 {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens, &exp_lp},
217 {"npcs", PRO_BOOL, false, OFF, &proc_calls_space, &exp_pcs},
218 {"npro", PRO_IGN, 0, 0, 0, &exp_pro},
219 {"npsl", PRO_BOOL, true, OFF, &procnames_start_line, &exp_psl},
220 {"nps", PRO_BOOL, false, OFF, &pointer_as_binop, &exp_ps},
221 {"nsc", PRO_BOOL, true, OFF, &star_comment_cont, &exp_sc},
222 {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines, &exp_sob},
223 {"nss", PRO_BOOL, false, OFF, &space_sp_semicolon, &exp_ss},
224 {"nv", PRO_BOOL, false, OFF, &verbose, &exp_v},
225 {"pcs", PRO_BOOL, false, ON, &proc_calls_space, &exp_pcs},
226 {"psl", PRO_BOOL, true, ON, &procnames_start_line, &exp_psl},
227 {"ps", PRO_BOOL, false, ON, &pointer_as_binop, &exp_ps},
228 {"sc", PRO_BOOL, true, ON, &star_comment_cont, &exp_sc},
229 {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines, &exp_sob},
230 {"ss", PRO_BOOL, false, ON, &space_sp_semicolon, &exp_ss},
231 {"st", PRO_STDIN, 0, 0, 0, &exp_st},
232 {"troff", PRO_BOOL, false, ON, &troff, &exp_troff},
233 {"version", PRO_PRSTRING, 0, 0, (int *)VERSION_STRING, &exp_version},
234 {"v", PRO_BOOL, false, ON, &verbose, &exp_v},
235
236 /* Signify end of structure. */
237 {0, 0, 0, 0, 0, 0}
238 };
239
240 /*
241 * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
242 * given in these files.
243 */
set_profile()244 set_profile()
245 {
246 register FILE *f;
247 char *fname;
248 static char prof[] = ".indent.pro";
249
250 char *homedir;
251
252 homedir = getenv("HOME");
253 fname = xmalloc(strlen(homedir) + 10 + sizeof prof);
254 sprintf(fname, "%s/%s", homedir, prof);
255 if ((f = fopen(prof, "r")) != NULL) {
256 scan_profile(f);
257 (void) fclose(f);
258 }
259 if ((f = fopen(fname, "r")) != NULL) {
260 scan_profile(f);
261 (void) fclose(f);
262 }
263 free (fname);
264 }
265
scan_profile(f)266 scan_profile(f)
267 register FILE *f;
268 {
269 register int i;
270 register char *p;
271 char buf[BUFSIZ];
272
273 while (1) {
274 for (p = buf; (i = getc(f)) != EOF && (*p = i) > ' '; ++p);
275 if (p != buf) {
276 *p++ = 0;
277 if (verbose)
278 printf("profile: %s\n", buf);
279 set_option(buf, 1);
280 }
281 else if (i == EOF)
282 return;
283 }
284 }
285
286 /* S1 should be a string. S2 should be a string, perhaps followed by
287 an argument. Compare the two, returning true if they are equal,
288 and if they are equal set *START_PARAM to point to the argument
289 in S2. */
eqin(s1,s2,start_param)290 eqin(s1, s2, start_param)
291 register char *s1;
292 register char *s2;
293 char **start_param;
294 {
295 while (*s1) {
296 if (*s1++ != *s2++)
297 return (false);
298 }
299 *start_param = s2;
300 return (true);
301 }
302
303 /*
304 * Set the defaults.
305 */
set_defaults()306 set_defaults()
307 {
308 register struct pro *p;
309
310 for (p = pro; p->p_name; p++)
311 if (p->p_type == PRO_BOOL || p->p_type == PRO_INT)
312 *p->p_obj = p->p_default;
313 }
314
315 /* Process an option ARG (e.g. "-l60").
316 EXPLICIT should be nonzero iff the argument is being explicitly
317 specified (as opposed to being taken from a PRO_SETTINGS group of
318 settings). */
319
set_option(arg,explicit)320 set_option (arg, explicit)
321 char *arg;
322 int explicit;
323 {
324 struct pro *p;
325 char *param_start;
326
327 arg++; /* ignore leading "-" */
328 for (p = pro; p->p_name; p++)
329 if (*p->p_name == *arg && eqin(p->p_name, arg, ¶m_start))
330 goto found;
331 fprintf(stderr, "indent: unknown parameter \"%s\"\n", arg - 1);
332 exit(1);
333 found:
334 /* If the parameter has been explicitly specified, we don't */
335 /* want a group of bundled settings to override the explicit */
336 /* setting. */
337 if (explicit || !*(p->p_explicit))
338 {
339 if (explicit)
340 *(p->p_explicit) = 1;
341
342 switch (p->p_type) {
343
344 case PRO_PRSTRING:
345 puts ((char *)p->p_obj);
346 exit (0);
347
348 case PRO_SETTINGS:
349 {
350 char *t; /* current position */
351
352 t = (char *)p->p_obj;
353 do
354 {
355 set_option(t, 0);
356 /* advance to character following next NUL */
357 while (*t++) ;
358 }
359 while (*t);
360 }
361
362 case PRO_IGN:
363 break;
364
365 case PRO_STDIN:
366 if (in_name == 0)
367 {
368 read_stdin();
369 /* Let it be known that we have an input file. */
370 in_name = "Standard Input";
371 }
372 if (output == 0)
373 output = stdout;
374 break;
375
376 case PRO_KEY:
377 if (*param_start == 0)
378 goto need_param;
379 {
380 register char *str = (char *) xmalloc(strlen(param_start) + 1);
381 strcpy(str, param_start);
382 addkey(str, 4);
383 }
384 break;
385
386 case PRO_BOOL:
387 if (p->p_special == OFF)
388 *p->p_obj = false;
389 else
390 *p->p_obj = true;
391 break;
392
393 case PRO_INT:
394 if (*param_start == 0) {
395 need_param:
396 fprintf(stderr, "indent: ``%s'' requires a parameter\n",
397 arg - 1);
398 exit(1);
399 }
400 *p->p_obj = atoi(param_start);
401 break;
402
403 case PRO_FONT:
404 parsefont((struct fstate *) p->p_obj, param_start);
405 break;
406
407 default:
408 fprintf(stderr, "indent: set_option: internal error: p_type %d\n",
409 p->p_type);
410 exit(1);
411 }
412 }
413 }
414