Line data Source code
1 : /*-
2 : * Copyright (c) 1985 Sun Microsystems, Inc.
3 : * Copyright (c) 1980, 1993
4 : * The Regents of the University of California. All rights reserved.
5 : * 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 : #if 0
33 : #ifndef lint
34 : static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93";
35 : #endif /* not lint */
36 : #endif
37 :
38 : #include "c.h"
39 :
40 : /*
41 : * Argument scanning and profile reading code. Default parameters are set
42 : * here as well.
43 : */
44 :
45 : #include <ctype.h>
46 : #include <err.h>
47 : #include <limits.h>
48 : #include <stdio.h>
49 : #include <stdlib.h>
50 : #include <string.h>
51 : #include "indent_globs.h"
52 : #include "indent.h"
53 :
54 : #define INDENT_VERSION "2.1.2"
55 :
56 : /* profile types */
57 : #define PRO_SPECIAL 1 /* special case */
58 : #define PRO_BOOL 2 /* boolean */
59 : #define PRO_INT 3 /* integer */
60 :
61 : /* profile specials for booleans */
62 : #define ON 1 /* turn it on */
63 : #define OFF 0 /* turn it off */
64 :
65 : /* profile specials for specials */
66 : #define IGN 1 /* ignore it */
67 : #define CLI 2 /* case label indent (float) */
68 : #define STDIN 3 /* use stdin */
69 : #define KEY 4 /* type (keyword) */
70 :
71 : static void scan_profile(FILE *f);
72 :
73 : #define KEY_FILE 5 /* only used for args */
74 : #define VERSION 6 /* only used for args */
75 :
76 : const char *option_source = "?";
77 :
78 : void add_typedefs_from_file(const char *str);
79 :
80 : /*
81 : * N.B.: because of the way the table here is scanned, options whose names are
82 : * substrings of other options must occur later; that is, with -lp vs -l, -lp
83 : * must be first. Also, while (most) booleans occur more than once, the last
84 : * default value is the one actually assigned.
85 : */
86 : struct pro {
87 : const char *p_name; /* name, e.g. -bl, -cli */
88 : int p_type; /* type (int, bool, special) */
89 : int p_default; /* the default value (if int) */
90 : int p_special; /* depends on type */
91 : int *p_obj; /* the associated variable */
92 : } pro[] = {
93 :
94 : {"T", PRO_SPECIAL, 0, KEY, 0},
95 : {"U", PRO_SPECIAL, 0, KEY_FILE, 0},
96 : {"-version", PRO_SPECIAL, 0, VERSION, 0},
97 : {"P", PRO_SPECIAL, 0, IGN, 0},
98 : {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation},
99 : {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop},
100 : {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations},
101 : {"bap", PRO_BOOL, false, ON, &blanklines_after_procs},
102 : {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments},
103 : {"bc", PRO_BOOL, true, OFF, &ps.leave_comma},
104 : {"bl", PRO_BOOL, true, OFF, &btype_2},
105 : {"br", PRO_BOOL, true, ON, &btype_2},
106 : {"bs", PRO_BOOL, false, ON, &Bill_Shannon},
107 : {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline},
108 : {"cd", PRO_INT, 0, 0, &ps.decl_com_ind},
109 : {"ce", PRO_BOOL, true, ON, &cuddle_else},
110 : {"ci", PRO_INT, 0, 0, &continuation_indent},
111 : {"cli", PRO_SPECIAL, 0, CLI, 0},
112 : {"cp", PRO_INT, 0, 0, &else_endif_com_ind},
113 : {"c", PRO_INT, 33, 0, &ps.com_ind},
114 : {"di", PRO_INT, 16, 0, &ps.decl_indent},
115 : {"dj", PRO_BOOL, false, ON, &ps.ljust_decl},
116 : {"d", PRO_INT, 0, 0, &ps.unindent_displace},
117 : {"eei", PRO_BOOL, false, ON, &extra_expression_indent},
118 : {"ei", PRO_BOOL, true, ON, &ps.else_if},
119 : {"fbs", PRO_BOOL, true, ON, &function_brace_split},
120 : {"fc1", PRO_BOOL, true, ON, &format_col1_comments},
121 : {"fcb", PRO_BOOL, true, ON, &format_block_comments},
122 : {"ip", PRO_BOOL, true, ON, &ps.indent_parameters},
123 : {"i", PRO_INT, 8, 0, &ps.ind_size},
124 : {"lc", PRO_INT, 0, 0, &block_comment_max_col},
125 : {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent},
126 : {"lpl", PRO_BOOL, false, ON, &lineup_to_parens_always},
127 : {"lp", PRO_BOOL, true, ON, &lineup_to_parens},
128 : {"l", PRO_INT, 78, 0, &max_col},
129 : {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation},
130 : {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop},
131 : {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations},
132 : {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs},
133 : {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments},
134 : {"nbc", PRO_BOOL, true, ON, &ps.leave_comma},
135 : {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon},
136 : {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline},
137 : {"nce", PRO_BOOL, true, OFF, &cuddle_else},
138 : {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl},
139 : {"neei", PRO_BOOL, false, OFF, &extra_expression_indent},
140 : {"nei", PRO_BOOL, true, OFF, &ps.else_if},
141 : {"nfbs", PRO_BOOL, true, OFF, &function_brace_split},
142 : {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments},
143 : {"nfcb", PRO_BOOL, true, OFF, &format_block_comments},
144 : {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters},
145 : {"nlpl", PRO_BOOL, false, OFF, &lineup_to_parens_always},
146 : {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens},
147 : {"npcs", PRO_BOOL, false, OFF, &proc_calls_space},
148 : {"npro", PRO_SPECIAL, 0, IGN, 0},
149 : {"npsl", PRO_BOOL, true, OFF, &procnames_start_line},
150 : {"nsac", PRO_BOOL, false, OFF, &space_after_cast},
151 : {"nsc", PRO_BOOL, true, OFF, &star_comment_cont},
152 : {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines},
153 : {"ntpg", PRO_BOOL, false, OFF, &postgres_tab_rules},
154 : {"nut", PRO_BOOL, true, OFF, &use_tabs},
155 : {"nv", PRO_BOOL, false, OFF, &verbose},
156 : {"pcs", PRO_BOOL, false, ON, &proc_calls_space},
157 : {"psl", PRO_BOOL, true, ON, &procnames_start_line},
158 : {"sac", PRO_BOOL, false, ON, &space_after_cast},
159 : {"sc", PRO_BOOL, true, ON, &star_comment_cont},
160 : {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines},
161 : {"st", PRO_SPECIAL, 0, STDIN, 0},
162 : {"ta", PRO_BOOL, false, ON, &auto_typedefs},
163 : {"tpg", PRO_BOOL, false, ON, &postgres_tab_rules},
164 : {"ts", PRO_INT, 8, 0, &tabsize},
165 : {"ut", PRO_BOOL, true, ON, &use_tabs},
166 : {"v", PRO_BOOL, false, ON, &verbose},
167 : /* whew! */
168 : {0, 0, 0, 0, 0}
169 : };
170 :
171 : /*
172 : * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
173 : * given in these files.
174 : */
175 : void
176 38 : set_profile(const char *profile_name)
177 : {
178 : FILE *f;
179 : char fname[MAXPGPATH];
180 : static char prof[] = ".indent.pro";
181 :
182 38 : if (profile_name == NULL)
183 2 : snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof);
184 : else
185 36 : snprintf(fname, sizeof(fname), "%s", profile_name + 2);
186 38 : if ((f = fopen(option_source = fname, "r")) != NULL) {
187 16 : scan_profile(f);
188 16 : (void) fclose(f);
189 : }
190 38 : if ((f = fopen(option_source = prof, "r")) != NULL) {
191 0 : scan_profile(f);
192 0 : (void) fclose(f);
193 : }
194 38 : option_source = "Command line";
195 38 : }
196 :
197 : static void
198 38 : scan_profile(FILE *f)
199 : {
200 : int comment, i;
201 : char *p;
202 : char buf[BUFSIZ];
203 :
204 : while (1) {
205 38 : p = buf;
206 38 : comment = 0;
207 176 : while ((i = getc(f)) != EOF) {
208 160 : if (i == '*' && !comment && p > buf && p[-1] == '/') {
209 0 : comment = p - buf;
210 0 : *p++ = i;
211 160 : } else if (i == '/' && comment && p > buf && p[-1] == '*') {
212 0 : p = buf + comment - 1;
213 0 : comment = 0;
214 160 : } else if (isspace((unsigned char)i)) {
215 22 : if (p > buf && !comment)
216 22 : break;
217 : } else {
218 138 : *p++ = i;
219 : }
220 : }
221 38 : if (p != buf) {
222 22 : *p++ = 0;
223 22 : if (verbose)
224 0 : printf("profile: %s\n", buf);
225 22 : set_option(buf);
226 : }
227 16 : else if (i == EOF)
228 16 : return;
229 : }
230 : }
231 :
232 : static const char *
233 182 : eqin(const char *s1, const char *s2)
234 : {
235 412 : while (*s1) {
236 352 : if (*s1++ != *s2++)
237 122 : return (NULL);
238 : }
239 60 : return (s2);
240 : }
241 :
242 : /*
243 : * Set the defaults.
244 : */
245 : void
246 38 : set_defaults(void)
247 : {
248 : struct pro *p;
249 :
250 : /*
251 : * Because ps.case_indent is a float, we can't initialize it from the
252 : * table:
253 : */
254 38 : ps.case_indent = 0.0; /* -cli0.0 */
255 2812 : for (p = pro; p->p_name; p++)
256 2774 : if (p->p_type != PRO_SPECIAL)
257 2508 : *p->p_obj = p->p_default;
258 38 : }
259 :
260 : void
261 60 : set_option(char *arg)
262 : {
263 : struct pro *p;
264 : const char *param_start;
265 :
266 60 : arg++; /* ignore leading "-" */
267 820 : for (p = pro; p->p_name; p++)
268 820 : if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL)
269 60 : goto found;
270 0 : errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
271 60 : found:
272 60 : switch (p->p_type) {
273 :
274 42 : case PRO_SPECIAL:
275 42 : switch (p->p_special) {
276 :
277 36 : case IGN:
278 36 : break;
279 :
280 0 : case CLI:
281 0 : if (*param_start == 0)
282 0 : goto need_param;
283 0 : ps.case_indent = atof(param_start);
284 0 : break;
285 :
286 0 : case STDIN:
287 0 : if (input == NULL)
288 0 : input = stdin;
289 0 : if (output == NULL)
290 0 : output = stdout;
291 0 : break;
292 :
293 2 : case KEY:
294 2 : if (*param_start == 0)
295 0 : goto need_param;
296 2 : add_typename(param_start);
297 2 : break;
298 :
299 2 : case KEY_FILE:
300 2 : if (*param_start == 0)
301 0 : goto need_param;
302 2 : add_typedefs_from_file(param_start);
303 2 : break;
304 :
305 2 : case VERSION:
306 2 : printf("pg_bsd_indent %s (based on FreeBSD indent)\n", INDENT_VERSION);
307 2 : exit(0);
308 :
309 0 : default:
310 0 : errx(1, "set_option: internal error: p_special %d", p->p_special);
311 : }
312 40 : break;
313 :
314 12 : case PRO_BOOL:
315 12 : if (p->p_special == OFF)
316 6 : *p->p_obj = false;
317 : else
318 6 : *p->p_obj = true;
319 12 : break;
320 :
321 6 : case PRO_INT:
322 6 : if (!isdigit((unsigned char)*param_start)) {
323 0 : need_param:
324 0 : errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name);
325 : }
326 6 : *p->p_obj = atoi(param_start);
327 6 : break;
328 :
329 0 : default:
330 0 : errx(1, "set_option: internal error: p_type %d", p->p_type);
331 : }
332 58 : }
333 :
334 : void
335 2 : add_typedefs_from_file(const char *str)
336 : {
337 : FILE *file;
338 : char line[BUFSIZ];
339 :
340 2 : if ((file = fopen(str, "r")) == NULL) {
341 0 : fprintf(stderr, "indent: cannot open file %s\n", str);
342 0 : exit(1);
343 : }
344 6 : while ((fgets(line, BUFSIZ, file)) != NULL) {
345 : /* Remove trailing whitespace */
346 4 : line[strcspn(line, " \t\n\r")] = '\0';
347 4 : add_typename(line);
348 : }
349 2 : fclose(file);
350 2 : }
|