1 |
|
|
/* $OpenBSD: args.c,v 1.18 2014/05/20 01:25:23 guenther Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 1980, 1993 |
5 |
|
|
* The Regents of the University of California. |
6 |
|
|
* Copyright (c) 1976 Board of Trustees of the University of Illinois. |
7 |
|
|
* Copyright (c) 1985 Sun Microsystems, Inc. |
8 |
|
|
* All rights reserved. |
9 |
|
|
* |
10 |
|
|
* Redistribution and use in source and binary forms, with or without |
11 |
|
|
* modification, are permitted provided that the following conditions |
12 |
|
|
* are met: |
13 |
|
|
* 1. Redistributions of source code must retain the above copyright |
14 |
|
|
* notice, this list of conditions and the following disclaimer. |
15 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
16 |
|
|
* notice, this list of conditions and the following disclaimer in the |
17 |
|
|
* documentation and/or other materials provided with the distribution. |
18 |
|
|
* 3. Neither the name of the University nor the names of its contributors |
19 |
|
|
* may be used to endorse or promote products derived from this software |
20 |
|
|
* without specific prior written permission. |
21 |
|
|
* |
22 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
23 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 |
|
|
* SUCH DAMAGE. |
33 |
|
|
*/ |
34 |
|
|
|
35 |
|
|
/* |
36 |
|
|
* Argument scanning and profile reading code. Default parameters are set |
37 |
|
|
* here as well. |
38 |
|
|
*/ |
39 |
|
|
|
40 |
|
|
#include <stdio.h> |
41 |
|
|
#include <ctype.h> |
42 |
|
|
#include <stdlib.h> |
43 |
|
|
#include <string.h> |
44 |
|
|
#include <errno.h> |
45 |
|
|
#include "indent_globs.h" |
46 |
|
|
#include <err.h> |
47 |
|
|
|
48 |
|
|
/* profile types */ |
49 |
|
|
#define PRO_SPECIAL 1 /* special case */ |
50 |
|
|
#define PRO_BOOL 2 /* boolean */ |
51 |
|
|
#define PRO_INT 3 /* integer */ |
52 |
|
|
#define PRO_FONT 4 /* troff font */ |
53 |
|
|
|
54 |
|
|
/* profile specials for booleans */ |
55 |
|
|
#define ON 1 /* turn it on */ |
56 |
|
|
#define OFF 0 /* turn it off */ |
57 |
|
|
|
58 |
|
|
/* profile specials for specials */ |
59 |
|
|
#define IGN 1 /* ignore it */ |
60 |
|
|
#define CLI 2 /* case label indent (float) */ |
61 |
|
|
#define STDIN 3 /* use stdin */ |
62 |
|
|
#define KEY 4 /* type (keyword) */ |
63 |
|
|
|
64 |
|
|
char *option_source = "?"; |
65 |
|
|
|
66 |
|
|
/* |
67 |
|
|
* N.B.: because of the way the table here is scanned, options whose names are |
68 |
|
|
* substrings of other options must occur later; that is, with -lp vs -l, -lp |
69 |
|
|
* must be first. Also, while (most) booleans occur more than once, the last |
70 |
|
|
* default value is the one actually assigned. |
71 |
|
|
*/ |
72 |
|
|
struct pro { |
73 |
|
|
char *p_name; /* name, eg -bl, -cli */ |
74 |
|
|
int p_type; /* type (int, bool, special) */ |
75 |
|
|
int p_default; /* the default value (if int) */ |
76 |
|
|
int p_special; /* depends on type */ |
77 |
|
|
int *p_obj; /* the associated variable */ |
78 |
|
|
} pro[] = { |
79 |
|
|
|
80 |
|
|
{ "T", PRO_SPECIAL, 0, KEY, 0 }, |
81 |
|
|
{"bacc", PRO_BOOL, false, ON, |
82 |
|
|
&blanklines_around_conditional_compilation }, |
83 |
|
|
{"badp", PRO_BOOL, false, ON, |
84 |
|
|
&blanklines_after_declarations_at_proctop }, |
85 |
|
|
{"bad", PRO_BOOL, false, ON, &blanklines_after_declarations }, |
86 |
|
|
{"bap", PRO_BOOL, false, ON, &blanklines_after_procs }, |
87 |
|
|
{"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments }, |
88 |
|
|
{"bc", PRO_BOOL, true, OFF, &ps.leave_comma }, |
89 |
|
|
{"bl", PRO_BOOL, true, OFF, &btype_2 }, |
90 |
|
|
{"br", PRO_BOOL, true, ON, &btype_2 }, |
91 |
|
|
{"bs", PRO_BOOL, false, ON, &Bill_Shannon }, |
92 |
|
|
{"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline }, |
93 |
|
|
{"cd", PRO_INT, 0, 0, &ps.decl_com_ind }, |
94 |
|
|
{"ce", PRO_BOOL, true, ON, &cuddle_else }, |
95 |
|
|
{"ci", PRO_INT, 0, 0, &continuation_indent }, |
96 |
|
|
{"cli", PRO_SPECIAL, 0, CLI, 0 }, |
97 |
|
|
{"c", PRO_INT, 33, 0, &ps.com_ind }, |
98 |
|
|
{"di", PRO_INT, 16, 0, &ps.decl_indent }, |
99 |
|
|
{"dj", PRO_BOOL, false, ON, &ps.ljust_decl }, |
100 |
|
|
{"d", PRO_INT, 0, 0, &ps.unindent_displace }, |
101 |
|
|
{"eei", PRO_BOOL, false, ON, &extra_expression_indent }, |
102 |
|
|
{"ei", PRO_BOOL, true, ON, &ps.else_if }, |
103 |
|
|
{"fbc", PRO_FONT, 0, 0, (int *) &blkcomf }, |
104 |
|
|
{"fbx", PRO_FONT, 0, 0, (int *) &boxcomf }, |
105 |
|
|
{"fb", PRO_FONT, 0, 0, (int *) &bodyf }, |
106 |
|
|
{"fc1", PRO_BOOL, true, ON, &format_col1_comments }, |
107 |
|
|
{"fc", PRO_FONT, 0, 0, (int *) &scomf }, |
108 |
|
|
{"fk", PRO_FONT, 0, 0, (int *) &keywordf }, |
109 |
|
|
{"fs", PRO_FONT, 0, 0, (int *) &stringf }, |
110 |
|
|
{"ip", PRO_BOOL, true, ON, &ps.indent_parameters }, |
111 |
|
|
{"i", PRO_INT, 8, 0, &ps.ind_size }, |
112 |
|
|
{"lc", PRO_INT, 0, 0, &block_comment_max_col }, |
113 |
|
|
{"lp", PRO_BOOL, true, ON, &lineup_to_parens }, |
114 |
|
|
{"l", PRO_INT, 78, 0, &max_col }, |
115 |
|
|
{"nbacc", PRO_BOOL, false, OFF, |
116 |
|
|
&blanklines_around_conditional_compilation }, |
117 |
|
|
{"nbadp", PRO_BOOL, false, OFF, |
118 |
|
|
&blanklines_after_declarations_at_proctop }, |
119 |
|
|
{"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations }, |
120 |
|
|
{"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs }, |
121 |
|
|
{"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments }, |
122 |
|
|
{"nbc", PRO_BOOL, true, ON, &ps.leave_comma }, |
123 |
|
|
{"nbs", PRO_BOOL, false, OFF, &Bill_Shannon }, |
124 |
|
|
{"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline }, |
125 |
|
|
{"nce", PRO_BOOL, true, OFF, &cuddle_else }, |
126 |
|
|
{"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl }, |
127 |
|
|
{"neei", PRO_BOOL, false, OFF, &extra_expression_indent }, |
128 |
|
|
{"nei", PRO_BOOL, true, OFF, &ps.else_if }, |
129 |
|
|
{"nfc1", PRO_BOOL, true, OFF, &format_col1_comments }, |
130 |
|
|
{"nip", PRO_BOOL, true, OFF, &ps.indent_parameters }, |
131 |
|
|
{"nlp", PRO_BOOL, true, OFF, &lineup_to_parens }, |
132 |
|
|
{"npcs", PRO_BOOL, false, OFF, &proc_calls_space }, |
133 |
|
|
{"npro", PRO_SPECIAL, 0, IGN, 0 }, |
134 |
|
|
{"npsl", PRO_BOOL, true, OFF, &procnames_start_line }, |
135 |
|
|
{"nps", PRO_BOOL, false, OFF, &pointer_as_binop }, |
136 |
|
|
{"nsc", PRO_BOOL, true, OFF, &star_comment_cont }, |
137 |
|
|
{"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines }, |
138 |
|
|
{"nut", PRO_BOOL, true, OFF, &use_tabs}, |
139 |
|
|
{"nv", PRO_BOOL, false, OFF, &verbose }, |
140 |
|
|
{"pcs", PRO_BOOL, false, ON, &proc_calls_space }, |
141 |
|
|
{"psl", PRO_BOOL, true, ON, &procnames_start_line }, |
142 |
|
|
{"ps", PRO_BOOL, false, ON, &pointer_as_binop }, |
143 |
|
|
{"sc", PRO_BOOL, true, ON, &star_comment_cont }, |
144 |
|
|
{"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines }, |
145 |
|
|
{"st", PRO_SPECIAL, 0, STDIN, 0 }, |
146 |
|
|
{"troff", PRO_BOOL, false, ON, &troff }, |
147 |
|
|
{"ut", PRO_BOOL, true, ON, &use_tabs}, |
148 |
|
|
{"v", PRO_BOOL, false, ON, &verbose }, |
149 |
|
|
/* whew! */ |
150 |
|
|
{ 0, 0, 0, 0, 0 } |
151 |
|
|
}; |
152 |
|
|
|
153 |
|
|
void scan_profile(FILE *); |
154 |
|
|
void set_option(char *); |
155 |
|
|
|
156 |
|
|
/* |
157 |
|
|
* set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments |
158 |
|
|
* given in these files. |
159 |
|
|
*/ |
160 |
|
|
void |
161 |
|
|
set_profile(void) |
162 |
|
|
{ |
163 |
|
|
FILE *f; |
164 |
|
|
char fname[BUFSIZ]; |
165 |
|
|
char *home; |
166 |
|
|
static char prof[] = ".indent.pro"; |
167 |
|
|
|
168 |
|
|
home = getenv("HOME"); |
169 |
|
|
if (home != NULL && *home != '\0') { |
170 |
|
|
if (snprintf(fname, sizeof fname, "%s/%s", home, prof) >= sizeof fname) { |
171 |
|
|
warnc(ENAMETOOLONG, "%s/%s", home, prof); |
172 |
|
|
return; |
173 |
|
|
} |
174 |
|
|
if ((f = fopen(option_source = fname, "r")) != NULL) { |
175 |
|
|
scan_profile(f); |
176 |
|
|
(void) fclose(f); |
177 |
|
|
} |
178 |
|
|
} |
179 |
|
|
if ((f = fopen(option_source = prof, "r")) != NULL) { |
180 |
|
|
scan_profile(f); |
181 |
|
|
(void) fclose(f); |
182 |
|
|
} |
183 |
|
|
option_source = "Command line"; |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
void |
187 |
|
|
scan_profile(FILE *f) |
188 |
|
|
{ |
189 |
|
|
int i; |
190 |
|
|
char *p; |
191 |
|
|
char buf[BUFSIZ]; |
192 |
|
|
|
193 |
|
|
while (1) { |
194 |
|
|
for (p = buf; |
195 |
|
|
(i = getc(f)) != EOF && (*p = i) > ' ' && p + 1 - buf < BUFSIZ; |
196 |
|
|
++p) |
197 |
|
|
; |
198 |
|
|
if (p != buf) { |
199 |
|
|
*p = 0; |
200 |
|
|
if (verbose) |
201 |
|
|
printf("profile: %s\n", buf); |
202 |
|
|
set_option(buf); |
203 |
|
|
} |
204 |
|
|
else if (i == EOF) |
205 |
|
|
return; |
206 |
|
|
} |
207 |
|
|
} |
208 |
|
|
|
209 |
|
|
char *param_start; |
210 |
|
|
|
211 |
|
|
int |
212 |
|
|
eqin(char *s1, char *s2) |
213 |
|
|
{ |
214 |
|
|
while (*s1) { |
215 |
|
|
if (*s1++ != *s2++) |
216 |
|
|
return (false); |
217 |
|
|
} |
218 |
|
|
param_start = s2; |
219 |
|
|
return (true); |
220 |
|
|
} |
221 |
|
|
|
222 |
|
|
/* |
223 |
|
|
* Set the defaults. |
224 |
|
|
*/ |
225 |
|
|
void |
226 |
|
|
set_defaults(void) |
227 |
|
|
{ |
228 |
|
|
struct pro *p; |
229 |
|
|
|
230 |
|
|
/* |
231 |
|
|
* Because ps.case_indent is a float, we can't initialize it from the |
232 |
|
|
* table: |
233 |
|
|
*/ |
234 |
|
|
ps.case_indent = 0.0; /* -cli0.0 */ |
235 |
|
|
for (p = pro; p->p_name; p++) |
236 |
|
|
if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT) |
237 |
|
|
*p->p_obj = p->p_default; |
238 |
|
|
} |
239 |
|
|
|
240 |
|
|
void |
241 |
|
|
set_option(char *arg) |
242 |
|
|
{ |
243 |
|
|
struct pro *p; |
244 |
|
|
|
245 |
|
|
arg++; /* ignore leading "-" */ |
246 |
|
|
for (p = pro; p->p_name; p++) |
247 |
|
|
if (*p->p_name == *arg && eqin(p->p_name, arg)) |
248 |
|
|
goto found; |
249 |
|
|
errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1); |
250 |
|
|
found: |
251 |
|
|
switch (p->p_type) { |
252 |
|
|
|
253 |
|
|
case PRO_SPECIAL: |
254 |
|
|
switch (p->p_special) { |
255 |
|
|
|
256 |
|
|
case IGN: |
257 |
|
|
break; |
258 |
|
|
|
259 |
|
|
case CLI: |
260 |
|
|
if (*param_start == 0) |
261 |
|
|
goto need_param; |
262 |
|
|
ps.case_indent = atof(param_start); |
263 |
|
|
break; |
264 |
|
|
|
265 |
|
|
case STDIN: |
266 |
|
|
if (input == 0) |
267 |
|
|
input = stdin; |
268 |
|
|
if (output == 0) |
269 |
|
|
output = stdout; |
270 |
|
|
break; |
271 |
|
|
|
272 |
|
|
case KEY: |
273 |
|
|
if (*param_start == 0) |
274 |
|
|
goto need_param; |
275 |
|
|
{ |
276 |
|
|
char *str; |
277 |
|
|
if ((str = strdup(param_start)) == NULL) |
278 |
|
|
err(1, NULL); |
279 |
|
|
addkey(str, 4); |
280 |
|
|
} |
281 |
|
|
break; |
282 |
|
|
|
283 |
|
|
default: |
284 |
|
|
errx(1, "set_option: internal error: p_special %d", p->p_special); |
285 |
|
|
} |
286 |
|
|
break; |
287 |
|
|
|
288 |
|
|
case PRO_BOOL: |
289 |
|
|
if (p->p_special == OFF) |
290 |
|
|
*p->p_obj = false; |
291 |
|
|
else |
292 |
|
|
*p->p_obj = true; |
293 |
|
|
break; |
294 |
|
|
|
295 |
|
|
case PRO_INT: |
296 |
|
|
if (!isdigit((unsigned char)*param_start)) { |
297 |
|
|
need_param: |
298 |
|
|
errx(1, "%s: ``%s'' requires a parameter", option_source, arg - 1); |
299 |
|
|
} |
300 |
|
|
*p->p_obj = atoi(param_start); |
301 |
|
|
if (*p->p_name == 'i' && *p->p_obj <= 0) |
302 |
|
|
errx(1, "%s: ``%s must be greater of zero''", |
303 |
|
|
option_source, arg - 1); |
304 |
|
|
break; |
305 |
|
|
|
306 |
|
|
case PRO_FONT: |
307 |
|
|
parsefont((struct fstate *) p->p_obj, param_start); |
308 |
|
|
break; |
309 |
|
|
|
310 |
|
|
default: |
311 |
|
|
errx(1, "set_option: internal error: p_type %d", p->p_type); |
312 |
|
|
} |
313 |
|
|
} |