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, &param_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