File: | src/hest/parseHest.c |
Location: | line 1065, column 31 |
Description: | Array access results in a null pointer dereference |
1 | /* | |||
2 | Teem: Tools to process and visualize scientific data and images . | |||
3 | Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago | |||
4 | Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann | |||
5 | Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah | |||
6 | ||||
7 | This library is free software; you can redistribute it and/or | |||
8 | modify it under the terms of the GNU Lesser General Public License | |||
9 | (LGPL) as published by the Free Software Foundation; either | |||
10 | version 2.1 of the License, or (at your option) any later version. | |||
11 | The terms of redistributing and/or modifying this software also | |||
12 | include exceptions to the LGPL that facilitate static linking. | |||
13 | ||||
14 | This library is distributed in the hope that it will be useful, | |||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
17 | Lesser General Public License for more details. | |||
18 | ||||
19 | You should have received a copy of the GNU Lesser General Public License | |||
20 | along with this library; if not, write to Free Software Foundation, Inc., | |||
21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
22 | */ | |||
23 | ||||
24 | /* | |||
25 | learned: well duh: when you send arguments to printf(), they will | |||
26 | be evaluated before printf() sees them, so you can't use _hestIdent() | |||
27 | twice with differen values | |||
28 | */ | |||
29 | ||||
30 | #include "hest.h" | |||
31 | #include "privateHest.h" | |||
32 | ||||
33 | #include <string.h> | |||
34 | ||||
35 | #define ME((parm && parm->verbosity) ? me : "") ((parm && parm->verbosity) ? me : "") | |||
36 | ||||
37 | /* | |||
38 | ** _hestArgsInResponseFiles() | |||
39 | ** | |||
40 | ** returns the number of args that will be parsed from the response files. | |||
41 | ** The role of this function is solely to simplify the task of avoiding | |||
42 | ** memory leaks. By knowing exactly how many args we'll get in the response | |||
43 | ** file, then hestParse() can allocate its local argv[] for exactly as | |||
44 | ** long as it needs to be, and we can avoid using an airArray. The drawback | |||
45 | ** is that we open and read through the response files twice. Alas. | |||
46 | */ | |||
47 | int | |||
48 | _hestArgsInResponseFiles(int *argcP, int *nrfP, | |||
49 | const char **argv, char *err, | |||
50 | const hestParm *parm) { | |||
51 | FILE *file; | |||
52 | char me[]="_hestArgsInResponseFiles: ", line[AIR_STRLEN_HUGE(1024+1)], *pound; | |||
53 | int ai, len; | |||
54 | ||||
55 | *argcP = 0; | |||
56 | *nrfP = 0; | |||
57 | if (!parm->respFileEnable) { | |||
58 | /* don't do response files; we're done */ | |||
59 | return 0; | |||
60 | } | |||
61 | ||||
62 | ai = 0; | |||
63 | while (argv[ai]) { | |||
64 | if (parm->respFileFlag == argv[ai][0]) { | |||
65 | if (!(file = fopen(argv[ai]+1, "rb"))) { | |||
66 | /* can't open the indicated response file for reading */ | |||
67 | sprintf(err, "%scouldn't open \"%s\" for reading as response file",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't open \"%s\" for reading as response file" , ((parm && parm->verbosity) ? me : ""), argv[ai]+ 1) | |||
68 | ME, argv[ai]+1)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't open \"%s\" for reading as response file" , ((parm && parm->verbosity) ? me : ""), argv[ai]+ 1); | |||
69 | *argcP = 0; | |||
70 | *nrfP = 0; | |||
71 | return 1; | |||
72 | } | |||
73 | len = airOneLine(file, line, AIR_STRLEN_HUGE(1024+1)); | |||
74 | while (len > 0) { | |||
75 | if ( (pound = strchr(line, parm->respFileComment)) ) | |||
76 | *pound = '\0'; | |||
77 | airOneLinify(line); | |||
78 | *argcP += airStrntok(line, AIR_WHITESPACE" \t\n\r\v\f"); | |||
79 | len = airOneLine(file, line, AIR_STRLEN_HUGE(1024+1)); | |||
80 | } | |||
81 | fclose(file); | |||
82 | (*nrfP)++; | |||
83 | } | |||
84 | ai++; | |||
85 | } | |||
86 | return 0; | |||
87 | } | |||
88 | ||||
89 | /* | |||
90 | ** _hestResponseFiles() | |||
91 | ** | |||
92 | ** This function is badly named. Even if there are no response files, | |||
93 | ** even if response files are disabled, this is the function that | |||
94 | ** copies from the user's argc,argv to our local copy. | |||
95 | */ | |||
96 | int | |||
97 | _hestResponseFiles(char **newArgv, const char **oldArgv, | |||
98 | const hestParm *parm, airArray *pmop) { | |||
99 | char line[AIR_STRLEN_HUGE(1024+1)], *pound; | |||
100 | int len, newArgc, oldArgc, incr, ai; | |||
101 | FILE *file; | |||
102 | ||||
103 | newArgc = oldArgc = 0; | |||
104 | while(oldArgv[oldArgc]) { | |||
105 | if (parm->verbosity) { | |||
106 | printf("!%s:________ newArgc = %d, oldArgc = %d\n", | |||
107 | "dammit", newArgc, oldArgc); | |||
108 | _hestPrintArgv(newArgc, newArgv); | |||
109 | } | |||
110 | if (!parm->respFileEnable | |||
111 | || parm->respFileFlag != oldArgv[oldArgc][0]) { | |||
112 | /* nothing to do with a response file */ | |||
113 | newArgv[newArgc] = airStrdup(oldArgv[oldArgc]); | |||
114 | airMopAdd(pmop, newArgv[newArgc], airFree, airMopAlways); | |||
115 | newArgc += 1; | |||
116 | } | |||
117 | else { | |||
118 | /* It is a response file. Error checking on open-ability | |||
119 | should have been done by _hestArgsInResponseFiles() */ | |||
120 | file = fopen(oldArgv[oldArgc]+1, "rb"); | |||
121 | len = airOneLine(file, line, AIR_STRLEN_HUGE(1024+1)); | |||
122 | while (len > 0) { | |||
123 | if (parm->verbosity) | |||
124 | printf("_hestResponseFiles: line: |%s|\n", line); | |||
125 | if ( (pound = strchr(line, parm->respFileComment)) ) | |||
126 | *pound = '\0'; | |||
127 | if (parm->verbosity) | |||
128 | printf("_hestResponseFiles: -0-> line: |%s|\n", line); | |||
129 | airOneLinify(line); | |||
130 | incr = airStrntok(line, AIR_WHITESPACE" \t\n\r\v\f"); | |||
131 | if (parm->verbosity) | |||
132 | printf("_hestResponseFiles: -1-> line: |%s|, incr=%d\n", | |||
133 | line, incr); | |||
134 | airParseStrS(newArgv + newArgc, line, AIR_WHITESPACE" \t\n\r\v\f", incr, AIR_FALSE0); | |||
135 | for (ai=0; ai<incr; ai++) { | |||
136 | /* This time, we did allocate memory. We can use airFree and | |||
137 | not airFreeP because these will not be reset before mopping */ | |||
138 | airMopAdd(pmop, newArgv[newArgc+ai], airFree, airMopAlways); | |||
139 | } | |||
140 | len = airOneLine(file, line, AIR_STRLEN_HUGE(1024+1)); | |||
141 | newArgc += incr; | |||
142 | } | |||
143 | fclose(file); | |||
144 | } | |||
145 | oldArgc++; | |||
146 | if (parm->verbosity) { | |||
147 | _hestPrintArgv(newArgc, newArgv); | |||
148 | printf("!%s: ^^^^^^^ newArgc = %d, oldArgc = %d\n", | |||
149 | "dammit", newArgc, oldArgc); | |||
150 | } | |||
151 | } | |||
152 | newArgv[newArgc] = NULL((void*)0); | |||
153 | ||||
154 | return 0; | |||
155 | } | |||
156 | ||||
157 | /* | |||
158 | ** _hestPanic() | |||
159 | ** | |||
160 | ** all error checking on the given hest array itself (not the | |||
161 | ** command line to be parsed). Also, sets the "kind" field of | |||
162 | ** the opt struct | |||
163 | */ | |||
164 | int | |||
165 | _hestPanic(hestOpt *opt, char *err, const hestParm *parm) { | |||
166 | char me[]="_hestPanic: ", tbuff[AIR_STRLEN_HUGE(1024+1)], *sep; | |||
167 | int numvar, op, numOpts; | |||
168 | ||||
169 | numOpts = _hestNumOpts(opt); | |||
170 | numvar = 0; | |||
171 | for (op=0; op<numOpts; op++) { | |||
172 | opt[op].kind = _hestKind(opt + op); | |||
173 | if (!(AIR_IN_OP(airTypeUnknown, opt[op].type, airTypeLast)((airTypeUnknown) < (opt[op].type) && (opt[op].type ) < (airTypeLast)))) { | |||
174 | if (err) | |||
175 | sprintf(err, "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]" , ((parm && parm->verbosity) ? me : ""), op, opt[op ].type, airTypeUnknown+1, airTypeLast-1) | |||
176 | ME, op, opt[op].type, airTypeUnknown+1, airTypeLast-1)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]" , ((parm && parm->verbosity) ? me : ""), op, opt[op ].type, airTypeUnknown+1, airTypeLast-1); | |||
177 | else | |||
178 | fprintf(stderr__stderrp, "%s: panic 0\n", me); | |||
179 | return 1; | |||
180 | } | |||
181 | if (!( opt[op].valueP )) { | |||
182 | if (err) | |||
183 | sprintf(err, "%s!!!!!! opt[%d]'s valueP is NULL!", ME, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s valueP is NULL!", ((parm && parm->verbosity) ? me : ""), op); | |||
184 | else | |||
185 | fprintf(stderr__stderrp, "%s: panic 0.5\n", me); | |||
186 | return 1; | |||
187 | } | |||
188 | if (-1 == opt[op].kind) { | |||
189 | if (err) | |||
190 | sprintf(err, "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible" , ((parm && parm->verbosity) ? me : ""), op, opt[op ].min, opt[op].max) | |||
191 | ME, op, opt[op].min, opt[op].max)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible" , ((parm && parm->verbosity) ? me : ""), op, opt[op ].min, opt[op].max); | |||
192 | else | |||
193 | fprintf(stderr__stderrp, "%s: panic 1\n", me); | |||
194 | return 1; | |||
195 | } | |||
196 | if (5 == opt[op].kind && !(opt[op].sawP)) { | |||
197 | if (err) | |||
198 | sprintf(err, "%s!!!!!! have multiple variable parameters, "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! have multiple variable parameters, " "but sawP is NULL", ((parm && parm->verbosity) ? me : "")) | |||
199 | "but sawP is NULL", ME)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! have multiple variable parameters, " "but sawP is NULL", ((parm && parm->verbosity) ? me : "")); | |||
200 | else | |||
201 | fprintf(stderr__stderrp, "%s: panic 2\n", me); | |||
202 | return 1; | |||
203 | } | |||
204 | if (airTypeEnum == opt[op].type) { | |||
205 | if (!(opt[op].enm)) { | |||
206 | if (err) { | |||
207 | sprintf(err, "%s!!!!!! opt[%d] (%s) is type \"enum\", but no "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] (%s) is type \"enum\", but no " "airEnum pointer given", ((parm && parm->verbosity ) ? me : ""), op, opt[op].flag ? opt[op].flag : "?") | |||
208 | "airEnum pointer given", ME, op,__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] (%s) is type \"enum\", but no " "airEnum pointer given", ((parm && parm->verbosity ) ? me : ""), op, opt[op].flag ? opt[op].flag : "?") | |||
209 | opt[op].flag ? opt[op].flag : "?")__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] (%s) is type \"enum\", but no " "airEnum pointer given", ((parm && parm->verbosity ) ? me : ""), op, opt[op].flag ? opt[op].flag : "?"); | |||
210 | } else { | |||
211 | fprintf(stderr__stderrp, "%s: panic 3\n", me); | |||
212 | } | |||
213 | return 1; | |||
214 | } | |||
215 | } | |||
216 | if (airTypeOther == opt[op].type) { | |||
217 | if (!(opt[op].CB)) { | |||
218 | if (err) { | |||
219 | sprintf(err, "%s!!!!!! opt[%d] (%s) is type \"other\", but no "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] (%s) is type \"other\", but no " "callbacks given", ((parm && parm->verbosity) ? me : ""), op, opt[op].flag ? opt[op].flag : "?") | |||
220 | "callbacks given", ME, op,__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] (%s) is type \"other\", but no " "callbacks given", ((parm && parm->verbosity) ? me : ""), op, opt[op].flag ? opt[op].flag : "?") | |||
221 | opt[op].flag ? opt[op].flag : "?")__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] (%s) is type \"other\", but no " "callbacks given", ((parm && parm->verbosity) ? me : ""), op, opt[op].flag ? opt[op].flag : "?"); | |||
222 | } else { | |||
223 | fprintf(stderr__stderrp, "%s: panic 4\n", me); | |||
224 | } | |||
225 | return 1; | |||
226 | } | |||
227 | if (!( opt[op].CB->size > 0 )) { | |||
228 | if (err) | |||
229 | sprintf(err, "%s!!!!!! opt[%d]'s \"size\" (%d) invalid",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s \"size\" (%d) invalid", ((parm && parm->verbosity) ? me : ""), op, (int)( opt[op].CB->size)) | |||
230 | ME, op, (int)(opt[op].CB->size))__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s \"size\" (%d) invalid", ((parm && parm->verbosity) ? me : ""), op, (int)( opt[op].CB->size)); | |||
231 | else | |||
232 | fprintf(stderr__stderrp, "%s: panic 5\n", me); | |||
233 | return 1; | |||
234 | } | |||
235 | if (!( opt[op].type )) { | |||
236 | if (err) | |||
237 | sprintf(err, "%s!!!!!! opt[%d]'s \"type\" is NULL",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s \"type\" is NULL", ((parm && parm->verbosity) ? me : ""), op) | |||
238 | ME, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s \"type\" is NULL", ((parm && parm->verbosity) ? me : ""), op); | |||
239 | else | |||
240 | fprintf(stderr__stderrp, "%s: panic 6\n", me); | |||
241 | return 1; | |||
242 | ||||
243 | } | |||
244 | if (!( opt[op].CB->parse )) { | |||
245 | if (err) | |||
246 | sprintf(err, "%s!!!!!! opt[%d]'s \"parse\" callback NULL", ME, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d]'s \"parse\" callback NULL" , ((parm && parm->verbosity) ? me : ""), op); | |||
247 | else | |||
248 | fprintf(stderr__stderrp, "%s: panic 7\n", me); | |||
249 | return 1; | |||
250 | } | |||
251 | if (opt[op].CB->destroy && (sizeof(void*) != opt[op].CB->size)) { | |||
252 | if (err) | |||
253 | sprintf(err, "%s!!!!!! opt[%d] has a \"destroy\", but size isn't "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] has a \"destroy\", but size isn't " "sizeof(void*)", ((parm && parm->verbosity) ? me : ""), op) | |||
254 | "sizeof(void*)", ME, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] has a \"destroy\", but size isn't " "sizeof(void*)", ((parm && parm->verbosity) ? me : ""), op); | |||
255 | else | |||
256 | fprintf(stderr__stderrp, "%s: panic 8\n", me); | |||
257 | return 1; | |||
258 | } | |||
259 | } | |||
260 | if (opt[op].flag) { | |||
261 | strcpy(tbuff, opt[op].flag)__builtin___strcpy_chk (tbuff, opt[op].flag, __builtin_object_size (tbuff, 2 > 1 ? 1 : 0)); | |||
262 | if (( sep = strchr(tbuff, parm->multiFlagSep) )) { | |||
263 | *sep = '\0'; | |||
264 | if (!( strlen(tbuff) && strlen(sep+1) )) { | |||
265 | if (err) | |||
266 | sprintf(err, "%s!!!!!! either short (\"%s\") or long (\"%s\") flag"__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! either short (\"%s\") or long (\"%s\") flag" " of opt[%d] is zero length", ((parm && parm->verbosity ) ? me : ""), tbuff, sep+1, op) | |||
267 | " of opt[%d] is zero length", ME, tbuff, sep+1, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! either short (\"%s\") or long (\"%s\") flag" " of opt[%d] is zero length", ((parm && parm->verbosity ) ? me : ""), tbuff, sep+1, op); | |||
268 | else | |||
269 | fprintf(stderr__stderrp, "%s: panic 9\n", me); | |||
270 | return 1; | |||
271 | } | |||
272 | } | |||
273 | else { | |||
274 | if (!strlen(opt[op].flag)) { | |||
275 | if (err) | |||
276 | sprintf(err, "%s!!!!!! opt[%d].flag is zero length",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d].flag is zero length", ((parm && parm->verbosity) ? me : ""), op) | |||
277 | ME, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d].flag is zero length", ((parm && parm->verbosity) ? me : ""), op); | |||
278 | else | |||
279 | fprintf(stderr__stderrp, "%s: panic 10\n", me); | |||
280 | return 1; | |||
281 | } | |||
282 | } | |||
283 | if (4 == opt[op].kind) { | |||
284 | if (!opt[op].dflt) { | |||
285 | if (err) | |||
286 | sprintf(err, "%s!!!!!! flagged single variable parameter must "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! flagged single variable parameter must " "specify a default", ((parm && parm->verbosity) ? me : "")) | |||
287 | "specify a default", ME)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! flagged single variable parameter must " "specify a default", ((parm && parm->verbosity) ? me : "")); | |||
288 | else | |||
289 | fprintf(stderr__stderrp, "%s: panic 11\n", me); | |||
290 | return 1; | |||
291 | } | |||
292 | if (!strlen(opt[op].dflt)) { | |||
293 | if (err) | |||
294 | sprintf(err, "%s!!!!!! flagged single variable parameter default "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! flagged single variable parameter default " "must be non-zero length", ((parm && parm->verbosity ) ? me : "")) | |||
295 | "must be non-zero length", ME)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! flagged single variable parameter default " "must be non-zero length", ((parm && parm->verbosity ) ? me : "")); | |||
296 | else | |||
297 | fprintf(stderr__stderrp, "%s: panic 12\n", me); | |||
298 | return 1; | |||
299 | } | |||
300 | } | |||
301 | /* | |||
302 | sprintf(tbuff, "-%s", opt[op].flag); | |||
303 | if (1 == sscanf(tbuff, "%f", &tmpF)) { | |||
304 | if (err) | |||
305 | sprintf(err, "%s!!!!!! opt[%d].flag (\"%s\") is numeric, bad news", | |||
306 | ME, op, opt[op].flag); | |||
307 | return 1; | |||
308 | } | |||
309 | */ | |||
310 | } | |||
311 | if (1 == opt[op].kind) { | |||
312 | if (!opt[op].flag) { | |||
313 | if (err) | |||
314 | sprintf(err, "%s!!!!!! flags must have flags", ME)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! flags must have flags", ((parm && parm->verbosity) ? me : "")); | |||
315 | else | |||
316 | fprintf(stderr__stderrp, "%s: panic 13\n", me); | |||
317 | return 1; | |||
318 | } | |||
319 | } | |||
320 | else { | |||
321 | if (!opt[op].name) { | |||
322 | if (err) | |||
323 | sprintf(err, "%s!!!!!! opt[%d] isn't a flag: must have \"name\"",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] isn't a flag: must have \"name\"" , ((parm && parm->verbosity) ? me : ""), op) | |||
324 | ME, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] isn't a flag: must have \"name\"" , ((parm && parm->verbosity) ? me : ""), op); | |||
325 | else | |||
326 | fprintf(stderr__stderrp, "%s: panic 14\n", me); | |||
327 | return 1; | |||
328 | } | |||
329 | } | |||
330 | if (4 == opt[op].kind && !opt[op].dflt) { | |||
331 | if (err) | |||
332 | sprintf(err, "%s!!!!!! opt[%d] is single variable parameter, but "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] is single variable parameter, but " "no default set", ((parm && parm->verbosity) ? me : ""), op) | |||
333 | "no default set", ME, op)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! opt[%d] is single variable parameter, but " "no default set", ((parm && parm->verbosity) ? me : ""), op); | |||
334 | else | |||
335 | fprintf(stderr__stderrp, "%s: panic 15\n", me); | |||
336 | return 1; | |||
337 | } | |||
338 | numvar += ((int)opt[op].min < _hestMax(opt[op].max) && (NULL((void*)0) == opt[op].flag)); /* HEY scrutinize casts */ | |||
339 | } | |||
340 | if (numvar > 1) { | |||
341 | if (err) | |||
342 | sprintf(err, "%s!!!!!! can't have %d unflagged min<max opts, only one",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! can't have %d unflagged min<max opts, only one" , ((parm && parm->verbosity) ? me : ""), numvar) | |||
343 | ME, numvar)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s!!!!!! can't have %d unflagged min<max opts, only one" , ((parm && parm->verbosity) ? me : ""), numvar); | |||
344 | else | |||
345 | fprintf(stderr__stderrp, "%s: panic 16\n", me); | |||
346 | return 1; | |||
347 | } | |||
348 | return 0; | |||
349 | } | |||
350 | ||||
351 | int | |||
352 | _hestErrStrlen(const hestOpt *opt, int argc, const char **argv) { | |||
353 | int a, numOpts, ret, other; | |||
354 | ||||
355 | ret = 0; | |||
356 | numOpts = _hestNumOpts(opt); | |||
357 | other = AIR_FALSE0; | |||
358 | if (argv) { | |||
359 | for (a=0; a<argc; a++) { | |||
360 | ret = AIR_MAX(ret, (int)airStrlen(argv[a]))((ret) > ((int)airStrlen(argv[a])) ? (ret) : ((int)airStrlen (argv[a]))); | |||
361 | } | |||
362 | } | |||
363 | for (a=0; a<numOpts; a++) { | |||
364 | ret = AIR_MAX(ret, (int)airStrlen(opt[a].flag))((ret) > ((int)airStrlen(opt[a].flag)) ? (ret) : ((int)airStrlen (opt[a].flag))); | |||
365 | ret = AIR_MAX(ret, (int)airStrlen(opt[a].name))((ret) > ((int)airStrlen(opt[a].name)) ? (ret) : ((int)airStrlen (opt[a].name))); | |||
366 | other |= opt[a].type == airTypeOther; | |||
367 | } | |||
368 | for (a=airTypeUnknown+1; a<airTypeLast; a++) { | |||
369 | ret = AIR_MAX(ret, (int)airStrlen(airTypeStr[a]))((ret) > ((int)airStrlen(airTypeStr[a])) ? (ret) : ((int)airStrlen (airTypeStr[a]))); | |||
370 | } | |||
371 | if (other) { | |||
372 | /* the callback's error() function may sprintf an error message | |||
373 | into a buffer which is size AIR_STRLEN_HUGE */ | |||
374 | ret += AIR_STRLEN_HUGE(1024+1); | |||
375 | } | |||
376 | ret += 4 * 12; /* as many as 4 ints per error message */ | |||
377 | ret += 257; /* function name and text of hest's error message */ | |||
378 | ||||
379 | return ret; | |||
380 | } | |||
381 | ||||
382 | /* | |||
383 | ** _hestExtractFlagged() | |||
384 | ** | |||
385 | ** extracts the parameters associated with all flagged options from the | |||
386 | ** given argc and argv, storing them in prms[], recording the number | |||
387 | ** of parameters in nprm[], and whether or not the flagged option appeared | |||
388 | ** in appr[]. | |||
389 | ** | |||
390 | ** The "saw" information is not set here, since it is better set | |||
391 | ** at value parsing time, which happens after defaults are enstated. | |||
392 | */ | |||
393 | int | |||
394 | _hestExtractFlagged(char **prms, unsigned int *nprm, int *appr, | |||
395 | int *argcP, char **argv, | |||
396 | hestOpt *opt, | |||
397 | char *err, const hestParm *parm, airArray *pmop) { | |||
398 | char me[]="_hestExtractFlagged: ", ident1[AIR_STRLEN_HUGE(1024+1)], | |||
399 | ident2[AIR_STRLEN_HUGE(1024+1)]; | |||
400 | int a, np, flag, endflag, numOpts, op; | |||
401 | ||||
402 | a = 0; | |||
403 | if (parm->verbosity) | |||
404 | printf("!%s: *argcP = %d\n", me, *argcP); | |||
405 | while (a<=*argcP-1) { | |||
406 | if (parm->verbosity) | |||
407 | printf("!%s: a = %d -> argv[a] = %s\n", me, a, argv[a]); | |||
408 | flag = _hestWhichFlag(opt, argv[a], parm); | |||
409 | if (parm->verbosity) | |||
410 | printf("!%s: A: a = %d -> flag = %d\n", me, a, flag); | |||
411 | if (!(0 <= flag)) { | |||
412 | /* not a flag, move on */ | |||
413 | a++; | |||
414 | continue; | |||
415 | } | |||
416 | /* see if we can associate some parameters with the flag */ | |||
417 | np = 0; | |||
418 | endflag = 0; | |||
419 | while (np < _hestMax(opt[flag].max) && | |||
420 | a+np+1 <= *argcP-1 && | |||
421 | -1 == (endflag = _hestWhichFlag(opt, argv[a+np+1], parm))) { | |||
422 | np++; | |||
423 | if (parm->verbosity) | |||
424 | printf("!%s: np --> %d with endflag = %d\n", me, np, endflag); | |||
425 | } | |||
426 | /* we stopped because we got the max number of parameters, or | |||
427 | because we hit the end of the command line, or | |||
428 | because _hestWhichFlag() returned something other than -1, | |||
429 | which means it returned -2, or a valid option index. If | |||
430 | we stopped because of _hestWhichFlag()'s return value, | |||
431 | endflag has been set to that return value */ | |||
432 | if (parm->verbosity) | |||
433 | printf("!%s: B: np = %d; endflag = %d\n", me, np, endflag); | |||
434 | if (np < (int)opt[flag].min) { /* HEY scrutinize casts */ | |||
435 | /* didn't get minimum number of parameters */ | |||
436 | if (!( a+np+1 <= *argcP-1 )) { | |||
437 | sprintf(err, "%shit end of line before getting %d parameter%s "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit end of line before getting %d parameter%s " "for %s (got %d)", ((parm && parm->verbosity) ? me : ""), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent (ident1, opt+flag, parm, 1), np) | |||
438 | "for %s (got %d)",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit end of line before getting %d parameter%s " "for %s (got %d)", ((parm && parm->verbosity) ? me : ""), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent (ident1, opt+flag, parm, 1), np) | |||
439 | ME, opt[flag].min, opt[flag].min > 1 ? "s" : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit end of line before getting %d parameter%s " "for %s (got %d)", ((parm && parm->verbosity) ? me : ""), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent (ident1, opt+flag, parm, 1), np) | |||
440 | _hestIdent(ident1, opt+flag, parm, AIR_TRUE), np)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit end of line before getting %d parameter%s " "for %s (got %d)", ((parm && parm->verbosity) ? me : ""), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent (ident1, opt+flag, parm, 1), np); | |||
441 | } | |||
442 | else { | |||
443 | sprintf(err, "%shit %s before getting %d parameter%s for %s (got %d)",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit %s before getting %d parameter%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), _hestIdent (ident1, opt+endflag, parm, 0), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent(ident2, opt+flag, parm, 0), np) | |||
444 | ME, _hestIdent(ident1, opt+endflag, parm, AIR_FALSE),__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit %s before getting %d parameter%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), _hestIdent (ident1, opt+endflag, parm, 0), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent(ident2, opt+flag, parm, 0), np) | |||
445 | opt[flag].min, opt[flag].min > 1 ? "s" : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit %s before getting %d parameter%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), _hestIdent (ident1, opt+endflag, parm, 0), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent(ident2, opt+flag, parm, 0), np) | |||
446 | _hestIdent(ident2, opt+flag, parm, AIR_FALSE), np)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%shit %s before getting %d parameter%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), _hestIdent (ident1, opt+endflag, parm, 0), opt[flag].min, opt[flag].min > 1 ? "s" : "", _hestIdent(ident2, opt+flag, parm, 0), np); | |||
447 | } | |||
448 | return 1; | |||
449 | } | |||
450 | nprm[flag] = np; | |||
451 | if (parm->verbosity) { | |||
452 | printf("!%s:________ a=%d, *argcP = %d -> flag = %d\n", | |||
453 | me, a, *argcP, flag); | |||
454 | _hestPrintArgv(*argcP, argv); | |||
455 | } | |||
456 | /* lose the flag argument */ | |||
457 | free(_hestExtract(argcP, argv, a, 1)); | |||
458 | /* extract the args after the flag */ | |||
459 | if (appr[flag]) { | |||
460 | airMopSub(pmop, prms[flag], airFree); | |||
461 | prms[flag] = (char *)airFree(prms[flag]); | |||
462 | } | |||
463 | prms[flag] = _hestExtract(argcP, argv, a, nprm[flag]); | |||
464 | airMopAdd(pmop, prms[flag], airFree, airMopAlways); | |||
465 | appr[flag] = AIR_TRUE1; | |||
466 | if (-2 == endflag) { | |||
467 | /* we should lose the end-of-variable-parameter marker */ | |||
468 | free(_hestExtract(argcP, argv, a, 1)); | |||
469 | } | |||
470 | if (parm->verbosity) { | |||
471 | _hestPrintArgv(*argcP, argv); | |||
472 | printf("!%s:^^^^^^^^ *argcP = %d\n", me, *argcP); | |||
473 | printf("!%s: prms[%d] = %s\n", me, flag, | |||
474 | prms[flag] ? prms[flag] : "(null)"); | |||
475 | } | |||
476 | } | |||
477 | ||||
478 | /* make sure that flagged options without default were given */ | |||
479 | numOpts = _hestNumOpts(opt); | |||
480 | for (op=0; op<numOpts; op++) { | |||
481 | if (1 != opt[op].kind && opt[op].flag && !opt[op].dflt && !appr[op]) { | |||
482 | sprintf(err, "%sdidn't get required %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdidn't get required %s", ((parm && parm->verbosity) ? me : ""), _hestIdent(ident1, opt+op, parm , 0)) | |||
483 | ME, _hestIdent(ident1, opt+op, parm, AIR_FALSE))__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdidn't get required %s", ((parm && parm->verbosity) ? me : ""), _hestIdent(ident1, opt+op, parm , 0)); | |||
484 | return 1; | |||
485 | } | |||
486 | } | |||
487 | ||||
488 | return 0; | |||
489 | } | |||
490 | ||||
491 | int | |||
492 | _hestNextUnflagged(int op, hestOpt *opt, int numOpts) { | |||
493 | ||||
494 | for(; op<=numOpts-1; op++) { | |||
495 | if (!opt[op].flag) | |||
496 | break; | |||
497 | } | |||
498 | return op; | |||
499 | } | |||
500 | ||||
501 | int | |||
502 | _hestExtractUnflagged(char **prms, unsigned int *nprm, | |||
503 | int *argcP, char **argv, | |||
504 | hestOpt *opt, | |||
505 | char *err, const hestParm *parm, airArray *pmop) { | |||
506 | char me[]="_hestExtractUnflagged: ", ident[AIR_STRLEN_HUGE(1024+1)]; | |||
507 | int nvp, np, op, unflag1st, unflagVar, numOpts; | |||
508 | ||||
509 | numOpts = _hestNumOpts(opt); | |||
510 | unflag1st = _hestNextUnflagged(0, opt, numOpts); | |||
511 | if (numOpts == unflag1st) { | |||
512 | /* no unflagged options; we're done */ | |||
513 | return 0; | |||
514 | } | |||
515 | ||||
516 | for (unflagVar = unflag1st; | |||
517 | unflagVar != numOpts; | |||
518 | unflagVar = _hestNextUnflagged(unflagVar+1, opt, numOpts)) { | |||
519 | if ((int)opt[unflagVar].min < _hestMax(opt[unflagVar].max)) /* HEY scrutinize casts */ | |||
520 | break; | |||
521 | } | |||
522 | /* now, if there is a variable parameter unflagged opt, unflagVar is its | |||
523 | index in opt[], or else unflagVar is numOpts */ | |||
524 | ||||
525 | /* grab parameters for all unflagged opts before opt[t] */ | |||
526 | for (op = _hestNextUnflagged(0, opt, numOpts); | |||
527 | op < unflagVar; | |||
528 | op = _hestNextUnflagged(op+1, opt, numOpts)) { | |||
529 | /* printf("!%s: op = %d; unflagVar = %d\n", me, op, unflagVar); */ | |||
530 | np = opt[op].min; /* min == max */ | |||
531 | if (!(np <= *argcP)) { | |||
532 | sprintf(err, "%sdon't have %d parameter%s %s%s%sfor %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s %s%s%sfor %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", argv[0] ? "starting at \"" : "", argv[0] ? argv [0] : "", argv[0] ? "\" " : "", _hestIdent(ident, opt+op, parm , 1)) | |||
533 | ME, np, np > 1 ? "s" : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s %s%s%sfor %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", argv[0] ? "starting at \"" : "", argv[0] ? argv [0] : "", argv[0] ? "\" " : "", _hestIdent(ident, opt+op, parm , 1)) | |||
534 | argv[0] ? "starting at \"" : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s %s%s%sfor %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", argv[0] ? "starting at \"" : "", argv[0] ? argv [0] : "", argv[0] ? "\" " : "", _hestIdent(ident, opt+op, parm , 1)) | |||
535 | argv[0] ? argv[0] : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s %s%s%sfor %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", argv[0] ? "starting at \"" : "", argv[0] ? argv [0] : "", argv[0] ? "\" " : "", _hestIdent(ident, opt+op, parm , 1)) | |||
536 | argv[0] ? "\" " : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s %s%s%sfor %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", argv[0] ? "starting at \"" : "", argv[0] ? argv [0] : "", argv[0] ? "\" " : "", _hestIdent(ident, opt+op, parm , 1)) | |||
537 | _hestIdent(ident, opt+op, parm, AIR_TRUE))__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s %s%s%sfor %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", argv[0] ? "starting at \"" : "", argv[0] ? argv [0] : "", argv[0] ? "\" " : "", _hestIdent(ident, opt+op, parm , 1)); | |||
538 | return 1; | |||
539 | } | |||
540 | prms[op] = _hestExtract(argcP, argv, 0, np); | |||
541 | airMopAdd(pmop, prms[op], airFree, airMopAlways); | |||
542 | nprm[op] = np; | |||
543 | } | |||
544 | /* | |||
545 | _hestPrintArgv(*argcP, argv); | |||
546 | */ | |||
547 | /* we skip over the variable parameter unflagged option, subtract from *argcP | |||
548 | the number of parameters in all the opts which follow it, in order to get | |||
549 | the number of parameters in the sole variable parameter option, | |||
550 | store this in nvp */ | |||
551 | nvp = *argcP; | |||
552 | for (op = _hestNextUnflagged(unflagVar+1, opt, numOpts); | |||
553 | op < numOpts; | |||
554 | op = _hestNextUnflagged(op+1, opt, numOpts)) { | |||
555 | nvp -= opt[op].min; /* min == max */ | |||
556 | } | |||
557 | if (nvp < 0) { | |||
558 | op = _hestNextUnflagged(unflagVar+1, opt, numOpts); | |||
559 | np = opt[op].min; | |||
560 | sprintf(err, "%sdon't have %d parameter%s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s for %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", _hestIdent(ident, opt+op, parm, 0)) | |||
561 | ME, np, np > 1 ? "s" : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s for %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", _hestIdent(ident, opt+op, parm, 0)) | |||
562 | _hestIdent(ident, opt+op, parm, AIR_FALSE))__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdon't have %d parameter%s for %s", ((parm && parm->verbosity) ? me : ""), np, np > 1 ? "s" : "", _hestIdent(ident, opt+op, parm, 0)); | |||
563 | return 1; | |||
564 | } | |||
565 | /* else we had enough args for all the unflagged options following | |||
566 | the sole variable parameter unflagged option, so snarf them up */ | |||
567 | for (op = _hestNextUnflagged(unflagVar+1, opt, numOpts); | |||
568 | op < numOpts; | |||
569 | op = _hestNextUnflagged(op+1, opt, numOpts)) { | |||
570 | np = opt[op].min; | |||
571 | prms[op] = _hestExtract(argcP, argv, nvp, np); | |||
572 | airMopAdd(pmop, prms[op], airFree, airMopAlways); | |||
573 | nprm[op] = np; | |||
574 | } | |||
575 | ||||
576 | /* now we grab the parameters of the sole variable parameter unflagged opt, | |||
577 | if it exists (unflagVar < numOpts) */ | |||
578 | if (unflagVar < numOpts) { | |||
579 | /* | |||
580 | printf("!%s: unflagVar=%d: min, nvp, max = %d %d %d\n", me, unflagVar, | |||
581 | opt[unflagVar].min, nvp, _hestMax(opt[unflagVar].max)); | |||
582 | */ | |||
583 | /* we'll do error checking for unexpected args later */ | |||
584 | nvp = AIR_MIN(nvp, _hestMax(opt[unflagVar].max))((nvp) < (_hestMax(opt[unflagVar].max)) ? (nvp) : (_hestMax (opt[unflagVar].max))); | |||
585 | if (nvp < (int)opt[unflagVar].min) { /* HEY scrutinize casts */ | |||
586 | sprintf(err, "%sdidn't get minimum of %d arg%s for %s (got %d)",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdidn't get minimum of %d arg%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), opt[unflagVar ].min, opt[unflagVar].min > 1 ? "s" : "", _hestIdent(ident , opt+unflagVar, parm, 1), nvp) | |||
587 | ME, opt[unflagVar].min,__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdidn't get minimum of %d arg%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), opt[unflagVar ].min, opt[unflagVar].min > 1 ? "s" : "", _hestIdent(ident , opt+unflagVar, parm, 1), nvp) | |||
588 | opt[unflagVar].min > 1 ? "s" : "",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdidn't get minimum of %d arg%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), opt[unflagVar ].min, opt[unflagVar].min > 1 ? "s" : "", _hestIdent(ident , opt+unflagVar, parm, 1), nvp) | |||
589 | _hestIdent(ident, opt+unflagVar, parm, AIR_TRUE), nvp)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sdidn't get minimum of %d arg%s for %s (got %d)" , ((parm && parm->verbosity) ? me : ""), opt[unflagVar ].min, opt[unflagVar].min > 1 ? "s" : "", _hestIdent(ident , opt+unflagVar, parm, 1), nvp); | |||
590 | return 1; | |||
591 | } | |||
592 | if (nvp) { | |||
593 | prms[unflagVar] = _hestExtract(argcP, argv, 0, nvp); | |||
594 | airMopAdd(pmop, prms[unflagVar], airFree, airMopAlways); | |||
595 | nprm[unflagVar] = nvp; | |||
596 | } | |||
597 | else { | |||
598 | prms[unflagVar] = NULL((void*)0); | |||
599 | nprm[unflagVar] = 0; | |||
600 | } | |||
601 | } | |||
602 | return 0; | |||
603 | } | |||
604 | ||||
605 | int | |||
606 | _hestDefaults(char **prms, int *udflt, unsigned int *nprm, int *appr, | |||
607 | hestOpt *opt, | |||
608 | char *err, const hestParm *parm, airArray *mop) { | |||
609 | char *tmpS, me[]="_hestDefaults: ", ident[AIR_STRLEN_HUGE(1024+1)]; | |||
610 | int op, numOpts; | |||
611 | ||||
612 | numOpts = _hestNumOpts(opt); | |||
613 | for (op=0; op<numOpts; op++) { | |||
614 | if (parm->verbosity) | |||
615 | printf("%s op=%d/%d: \"%s\" --> kind=%d, nprm=%u, appr=%d\n", | |||
616 | me, op, numOpts-1, prms[op], opt[op].kind, | |||
617 | nprm[op], appr[op]); | |||
618 | switch(opt[op].kind) { | |||
619 | case 1: | |||
620 | /* -------- (no-parameter) boolean flags -------- */ | |||
621 | /* default is indeed always ignored for the sake of setting the | |||
622 | option's value, but udflt is used downstream to set | |||
623 | the option's source. The info came from the user if | |||
624 | the flag appears, otherwise it is from the default. */ | |||
625 | udflt[op] = !appr[op]; | |||
626 | break; | |||
627 | case 2: | |||
628 | case 3: | |||
629 | /* -------- one required parameter -------- */ | |||
630 | /* -------- multiple required parameters -------- */ | |||
631 | /* we'll used defaults if the flag didn't appear */ | |||
632 | udflt[op] = opt[op].flag && !appr[op]; | |||
633 | break; | |||
634 | case 4: | |||
635 | /* -------- optional single variables -------- */ | |||
636 | /* if the flag appeared (if there is a flag) but the paramter didn't, | |||
637 | we'll "invert" the default; if the flag didn't appear (or if there | |||
638 | isn't a flag) and the parameter also didn't appear, we'll use the | |||
639 | default. In either case, nprm[op] will be zero, and in both cases, | |||
640 | we need to use the default information. */ | |||
641 | udflt[op] = (0 == nprm[op]); | |||
642 | /* | |||
643 | fprintf(stderr, "%s nprm[%d] = %u --> udflt[%d] = %d\n", me, | |||
644 | op, nprm[op], op, udflt[op]); | |||
645 | */ | |||
646 | break; | |||
647 | case 5: | |||
648 | /* -------- multiple optional parameters -------- */ | |||
649 | /* we'll use the default if the flag didn't appear (if there is a | |||
650 | flag) Otherwise, if nprm[op] is zero, then the user is saying, | |||
651 | I want zero parameters */ | |||
652 | udflt[op] = opt[op].flag && !appr[op]; | |||
653 | break; | |||
654 | } | |||
655 | if (!udflt[op]) | |||
656 | continue; | |||
657 | prms[op] = airStrdup(opt[op].dflt); | |||
658 | /* fprintf(stderr, "%s: prms[%d] = |%s|\n", me, op, prms[op]); */ | |||
659 | if (prms[op]) { | |||
660 | airMopAdd(mop, prms[op], airFree, airMopAlways); | |||
661 | airOneLinify(prms[op]); | |||
662 | tmpS = airStrdup(prms[op]); | |||
663 | nprm[op] = airStrntok(tmpS, " "); | |||
664 | airFree(tmpS); | |||
665 | /* printf("!%s: nprm[%d] in default = %u\n", me, op, nprm[op]); */ | |||
666 | if ((int)opt[op].min < _hestMax(opt[op].max)) { /* HEY scrutinize casts */ | |||
667 | if (!( AIR_IN_CL((int)opt[op].min, (int)nprm[op], _hestMax(opt[op].max))(((int)opt[op].min) <= ((int)nprm[op]) && ((int)nprm [op]) <= (_hestMax(opt[op].max))) /* HEY scrutinize casts */ | |||
668 | || (airTypeString == opt[op].type | |||
669 | && parm->elideMultipleEmptyStringDefault) )) { | |||
670 | sprintf(err, "%s# parameters (in default) for %s is %d, "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s# parameters (in default) for %s is %d, " "but need between %d and %d", ((parm && parm->verbosity ) ? me : ""), _hestIdent(ident, opt+op, parm, 1), nprm[op], opt [op].min, _hestMax(opt[op].max)) | |||
671 | "but need between %d and %d",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s# parameters (in default) for %s is %d, " "but need between %d and %d", ((parm && parm->verbosity ) ? me : ""), _hestIdent(ident, opt+op, parm, 1), nprm[op], opt [op].min, _hestMax(opt[op].max)) | |||
672 | ME, _hestIdent(ident, opt+op, parm, AIR_TRUE), nprm[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s# parameters (in default) for %s is %d, " "but need between %d and %d", ((parm && parm->verbosity ) ? me : ""), _hestIdent(ident, opt+op, parm, 1), nprm[op], opt [op].min, _hestMax(opt[op].max)) | |||
673 | opt[op].min, _hestMax(opt[op].max))__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s# parameters (in default) for %s is %d, " "but need between %d and %d", ((parm && parm->verbosity ) ? me : ""), _hestIdent(ident, opt+op, parm, 1), nprm[op], opt [op].min, _hestMax(opt[op].max)); | |||
674 | return 1; | |||
675 | } | |||
676 | } | |||
677 | } | |||
678 | } | |||
679 | return 0; | |||
680 | } | |||
681 | ||||
682 | /* | |||
683 | ** this function moved from air/miscAir; the usage below | |||
684 | ** is its only usage in Teem | |||
685 | */ | |||
686 | static int | |||
687 | airIStore(void *v, int t, int i) { | |||
688 | ||||
689 | switch(t) { | |||
690 | case airTypeBool: return (*((int*)v) = !!i); break; | |||
691 | case airTypeInt: return (*((int*)v) = i); break; | |||
692 | case airTypeUInt: return (int)(*((unsigned int*)v) = i); break; | |||
693 | case airTypeLongInt:return (int)(*((long int*)v) = i); break; | |||
694 | case airTypeULongInt:return (int)(*((unsigned long int*)v) = i); break; | |||
695 | case airTypeSize_t: return (int)(*((size_t*)v) = i); break; | |||
696 | case airTypeFloat: return (int)(*((float*)v) = (float)(i)); break; | |||
697 | case airTypeDouble: return (int)(*((double*)v) = (double)(i)); break; | |||
698 | case airTypeChar: return (*((char*)v) = (char)(i)); break; | |||
699 | default: return 0; break; | |||
700 | } | |||
701 | } | |||
702 | ||||
703 | /* | |||
704 | ** this function moved from air/miscAir; the usage below | |||
705 | ** is its only usage in Teem | |||
706 | */ | |||
707 | double | |||
708 | airDLoad(void *v, int t) { | |||
709 | ||||
710 | switch(t) { | |||
711 | case airTypeBool: return AIR_CAST(double,*((int*)v))((double)(*((int*)v))); break; | |||
712 | case airTypeInt: return AIR_CAST(double,*((int*)v))((double)(*((int*)v))); break; | |||
713 | case airTypeUInt: return AIR_CAST(double,*((unsigned int*)v))((double)(*((unsigned int*)v))); break; | |||
714 | case airTypeLongInt:return AIR_CAST(double,*((long int*)v))((double)(*((long int*)v))); break; | |||
715 | case airTypeULongInt:return AIR_CAST(double,*((unsigned long int*)v))((double)(*((unsigned long int*)v))); break; | |||
716 | case airTypeSize_t: return AIR_CAST(double, *((size_t*)v))((double)(*((size_t*)v))); break; | |||
717 | case airTypeFloat: return AIR_CAST(double,*((float*)v))((double)(*((float*)v))); break; | |||
718 | case airTypeDouble: return *((double*)v); break; | |||
719 | case airTypeChar: return AIR_CAST(double,*((char*)v))((double)(*((char*)v))); break; | |||
720 | default: return 0; break; | |||
721 | } | |||
722 | } | |||
723 | ||||
724 | ||||
725 | int | |||
726 | _hestSetValues(char **prms, int *udflt, unsigned int *nprm, int *appr, | |||
727 | hestOpt *opt, | |||
728 | char *err, const hestParm *parm, airArray *pmop) { | |||
729 | char ident[AIR_STRLEN_HUGE(1024+1)], me[]="_hestSetValues: ", | |||
730 | cberr[AIR_STRLEN_HUGE(1024+1)], *tok, *last, *prmsCopy; | |||
731 | double tmpD; | |||
732 | int op, type, numOpts, p, ret; | |||
733 | void *vP; | |||
734 | char *cP; | |||
735 | size_t size; | |||
736 | ||||
737 | numOpts = _hestNumOpts(opt); | |||
738 | for (op=0; op<numOpts; op++) { | |||
| ||||
739 | _hestIdent(ident, opt+op, parm, AIR_TRUE1); | |||
740 | opt[op].source = udflt[op] ? hestSourceDefault : hestSourceUser; | |||
741 | type = opt[op].type; | |||
742 | size = (airTypeEnum == type | |||
743 | ? (int)sizeof(int) /* HEY scrutinize casts */ | |||
744 | : (airTypeOther == type | |||
745 | ? (int)opt[op].CB->size /* HEY scrutinize casts */ | |||
746 | : (int)airTypeSize[type])); /* HEY scrutinize casts */ | |||
747 | cP = (char *)(vP = opt[op].valueP); | |||
748 | if (parm->verbosity) { | |||
749 | printf("%s %d of %d: \"%s\": |%s| --> kind=%d, type=%d, size=%d\n", | |||
750 | me, op, numOpts-1, prms[op], ident, opt[op].kind, type, | |||
751 | (int)size); | |||
752 | } | |||
753 | /* we may over-write these */ | |||
754 | opt[op].alloc = 0; | |||
755 | if (opt[op].sawP) { | |||
756 | *(opt[op].sawP) = 0; | |||
757 | } | |||
758 | switch(opt[op].kind) { | |||
759 | case 1: | |||
760 | /* -------- parameter-less boolean flags -------- */ | |||
761 | if (vP) | |||
762 | *((int*)vP) = appr[op]; | |||
763 | break; | |||
764 | case 2: | |||
765 | /* -------- one required parameter -------- */ | |||
766 | if (prms[op] && vP) { | |||
767 | switch (type) { | |||
768 | case airTypeEnum: | |||
769 | if (1 != airParseStrE((int *)vP, prms[op], " ", 1, opt[op].enm)) { | |||
770 | sprintf(err, "%scouldn\'t parse %s\"%s\" as %s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn\'t parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].enm->name, ident) | |||
771 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn\'t parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].enm->name, ident) | |||
772 | opt[op].enm->name, ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn\'t parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].enm->name, ident); | |||
773 | return 1; | |||
774 | } | |||
775 | break; | |||
776 | case airTypeOther: | |||
777 | strcpy(cberr, "")__builtin___strcpy_chk (cberr, "", __builtin_object_size (cberr , 2 > 1 ? 1 : 0)); | |||
778 | ret = opt[op].CB->parse(vP, prms[op], cberr); | |||
779 | if (ret) { | |||
780 | if (strlen(cberr)) { | |||
781 | sprintf(err, "%serror parsing \"%s\" as %s for %s:\n%s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s:\n%s", ((parm && parm->verbosity) ? me : ""), prms[op], opt [op].CB->type, ident, cberr) | |||
782 | ME, prms[op], opt[op].CB->type, ident, cberr)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s:\n%s", ((parm && parm->verbosity) ? me : ""), prms[op], opt [op].CB->type, ident, cberr); | |||
783 | } else { | |||
784 | sprintf(err, "%serror parsing \"%s\" as %s for %s: returned %d",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s: returned %d" , ((parm && parm->verbosity) ? me : ""), prms[op], opt[op].CB->type, ident, ret) | |||
785 | ME, prms[op], opt[op].CB->type, ident, ret)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s: returned %d" , ((parm && parm->verbosity) ? me : ""), prms[op], opt[op].CB->type, ident, ret); | |||
786 | } | |||
787 | return ret; | |||
788 | } | |||
789 | if (opt[op].CB->destroy) { | |||
790 | /* vP is the address of a void*, we manage the void * */ | |||
791 | opt[op].alloc = 1; | |||
792 | airMopAdd(pmop, (void**)vP, (airMopper)airSetNull, airMopOnError); | |||
793 | airMopAdd(pmop, *((void**)vP), opt[op].CB->destroy, airMopOnError); | |||
794 | } | |||
795 | break; | |||
796 | case airTypeString: | |||
797 | if (1 != airParseStrS((char **)vP, prms[op], " ", 1, | |||
798 | parm->greedySingleString)) { | |||
799 | sprintf(err, "%scouldn't parse %s\"%s\" as %s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
800 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
801 | airTypeStr[type], ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident); | |||
802 | return 1; | |||
803 | } | |||
804 | /* vP is the address of a char* (a char **), but what we | |||
805 | manage with airMop is the char * */ | |||
806 | opt[op].alloc = 1; | |||
807 | airMopMem(pmop, vP, airMopOnError); | |||
808 | break; | |||
809 | default: | |||
810 | /* type isn't string or enum, so no last arg to airParseStr[type] */ | |||
811 | if (1 != airParseStr[type](vP, prms[op], " ", 1)) { | |||
812 | sprintf(err, "%scouldn't parse %s\"%s\" as %s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
813 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
814 | airTypeStr[type], ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident); | |||
815 | return 1; | |||
816 | } | |||
817 | break; | |||
818 | } | |||
819 | } | |||
820 | break; | |||
821 | case 3: | |||
822 | /* -------- multiple required parameters -------- */ | |||
823 | if (prms[op] && vP) { | |||
824 | switch (type) { | |||
825 | case airTypeEnum: | |||
826 | if (opt[op].min != /* min == max */ | |||
827 | airParseStrE((int *)vP, prms[op], " ", opt[op].min, opt[op].enm)) { | |||
828 | sprintf(err, "%scouldn't parse %s\"%s\" as %d %s%s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, opt[op].enm-> name, opt[op].min > 1 ? "s" : "", ident) | |||
829 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, opt[op].enm-> name, opt[op].min > 1 ? "s" : "", ident) | |||
830 | opt[op].min, opt[op].enm->name,__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, opt[op].enm-> name, opt[op].min > 1 ? "s" : "", ident) | |||
831 | opt[op].min > 1 ? "s" : "", ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, opt[op].enm-> name, opt[op].min > 1 ? "s" : "", ident); | |||
832 | return 1; | |||
833 | } | |||
834 | break; | |||
835 | case airTypeOther: | |||
836 | prmsCopy = airStrdup(prms[op]); | |||
837 | for (p=0; p<(int)opt[op].min; p++) { /* HEY scrutinize casts */ | |||
838 | tok = airStrtok(!p ? prmsCopy : NULL((void*)0), " ", &last); | |||
839 | strcpy(cberr, "")__builtin___strcpy_chk (cberr, "", __builtin_object_size (cberr , 2 > 1 ? 1 : 0)); | |||
840 | ret = opt[op].CB->parse(cP + p*size, tok, cberr); | |||
841 | if (ret) { | |||
842 | if (strlen(cberr)) | |||
843 | sprintf(err, "%serror parsing \"%s\" (in \"%s\") as %s "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s:\n%s", ((parm && parm->verbosity) ? me : "" ), tok, prms[op], opt[op].CB->type, ident, cberr) | |||
844 | "for %s:\n%s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s:\n%s", ((parm && parm->verbosity) ? me : "" ), tok, prms[op], opt[op].CB->type, ident, cberr) | |||
845 | ME, tok, prms[op], opt[op].CB->type, ident, cberr)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s:\n%s", ((parm && parm->verbosity) ? me : "" ), tok, prms[op], opt[op].CB->type, ident, cberr); | |||
846 | else | |||
847 | sprintf(err, "%serror parsing \"%s\" (in \"%s\") as %s "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s: returned %d", ((parm && parm->verbosity) ? me : ""), tok, prms[op], opt[op].CB->type, ident, ret) | |||
848 | "for %s: returned %d",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s: returned %d", ((parm && parm->verbosity) ? me : ""), tok, prms[op], opt[op].CB->type, ident, ret) | |||
849 | ME, tok, prms[op], opt[op].CB->type, ident, ret)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s: returned %d", ((parm && parm->verbosity) ? me : ""), tok, prms[op], opt[op].CB->type, ident, ret); | |||
850 | free(prmsCopy); | |||
851 | return 1; | |||
852 | } | |||
853 | } | |||
854 | free(prmsCopy); | |||
855 | if (opt[op].CB->destroy) { | |||
856 | /* vP is an array of void*s, we manage the individual void*s */ | |||
857 | opt[op].alloc = 2; | |||
858 | for (p=0; p<(int)opt[op].min; p++) { /* HEY scrutinize casts */ | |||
859 | airMopAdd(pmop, ((void**)vP)+p, (airMopper)airSetNull, | |||
860 | airMopOnError); | |||
861 | airMopAdd(pmop, *(((void**)vP)+p), opt[op].CB->destroy, | |||
862 | airMopOnError); | |||
863 | } | |||
864 | } | |||
865 | break; | |||
866 | case airTypeString: | |||
867 | if (opt[op].min != /* min == max */ | |||
868 | airParseStr[type](vP, prms[op], " ", opt[op].min, AIR_FALSE0)) { | |||
869 | sprintf(err, "%scouldn't parse %s\"%s\" as %d %s%s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident) | |||
870 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident) | |||
871 | opt[op].min, airTypeStr[type],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident) | |||
872 | opt[op].min > 1 ? "s" : "", ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident); | |||
873 | return 1; | |||
874 | } | |||
875 | /* vP is an array of char*s, (a char**), and what we manage | |||
876 | with airMop are the individual vP[p]. */ | |||
877 | opt[op].alloc = 2; | |||
878 | for (p=0; p<(int)opt[op].min; p++) { /* HEY scrutinize casts */ | |||
879 | airMopMem(pmop, &(((char**)vP)[p]), airMopOnError); | |||
880 | } | |||
881 | break; | |||
882 | default: | |||
883 | if (opt[op].min != /* min == max */ | |||
884 | airParseStr[type](vP, prms[op], " ", opt[op].min)) { | |||
885 | sprintf(err, "%scouldn't parse %s\"%s\" as %d %s%s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident) | |||
886 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident) | |||
887 | opt[op].min, airTypeStr[type],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident) | |||
888 | opt[op].min > 1 ? "s" : "", ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].min, airTypeStr[type] , opt[op].min > 1 ? "s" : "", ident); | |||
889 | return 1; | |||
890 | } | |||
891 | break; | |||
892 | } | |||
893 | } | |||
894 | break; | |||
895 | case 4: | |||
896 | /* -------- optional single variables -------- */ | |||
897 | if (prms[op] && vP) { | |||
898 | switch (type) { | |||
899 | case airTypeEnum: | |||
900 | if (1 != airParseStrE((int *)vP, prms[op], " ", 1, opt[op].enm)) { | |||
901 | sprintf(err, "%scouldn't parse %s\"%s\" as %s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].enm->name, ident) | |||
902 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].enm->name, ident) | |||
903 | opt[op].enm->name, ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], opt[op].enm->name, ident); | |||
904 | return 1; | |||
905 | } | |||
906 | break; | |||
907 | case airTypeOther: | |||
908 | /* we're parsing an "other". We will not perform the special | |||
909 | flagged single variable parameter games as done above, so | |||
910 | whether this option is flagged or unflagged, we're going | |||
911 | to treat it like an unflagged single variable parameter option: | |||
912 | if the parameter didn't appear, we'll parse it from the default, | |||
913 | if it did appear, we'll parse it from the command line. Setting | |||
914 | up prms[op] thusly has already been done by _hestDefaults() */ | |||
915 | strcpy(cberr, "")__builtin___strcpy_chk (cberr, "", __builtin_object_size (cberr , 2 > 1 ? 1 : 0)); | |||
916 | ret = opt[op].CB->parse(vP, prms[op], cberr); | |||
917 | if (ret) { | |||
918 | if (strlen(cberr)) | |||
919 | sprintf(err, "%serror parsing \"%s\" as %s for %s:\n%s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s:\n%s", ((parm && parm->verbosity) ? me : ""), prms[op], opt [op].CB->type, ident, cberr) | |||
920 | ME, prms[op], opt[op].CB->type, ident, cberr)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s:\n%s", ((parm && parm->verbosity) ? me : ""), prms[op], opt [op].CB->type, ident, cberr); | |||
921 | else | |||
922 | sprintf(err, "%serror parsing \"%s\" as %s for %s: returned %d",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s: returned %d" , ((parm && parm->verbosity) ? me : ""), prms[op], opt[op].CB->type, ident, ret) | |||
923 | ME, prms[op], opt[op].CB->type, ident, ret)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" as %s for %s: returned %d" , ((parm && parm->verbosity) ? me : ""), prms[op], opt[op].CB->type, ident, ret); | |||
924 | return 1; | |||
925 | } | |||
926 | if (opt[op].CB->destroy) { | |||
927 | /* vP is the address of a void*, we manage the void* */ | |||
928 | opt[op].alloc = 1; | |||
929 | airMopAdd(pmop, vP, (airMopper)airSetNull, airMopOnError); | |||
930 | airMopAdd(pmop, *((void**)vP), opt[op].CB->destroy, airMopOnError); | |||
931 | } | |||
932 | break; | |||
933 | case airTypeString: | |||
934 | if (1 != airParseStr[type](vP, prms[op], " ", 1, | |||
935 | parm->greedySingleString)) { | |||
936 | sprintf(err, "%scouldn't parse %s\"%s\" as %s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
937 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
938 | airTypeStr[type], ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident); | |||
939 | return 1; | |||
940 | } | |||
941 | opt[op].alloc = 1; | |||
942 | if (opt[op].flag && 1 == _hestCase(opt, udflt, nprm, appr, op)) { | |||
943 | /* we just parsed the default, but now we want to "invert" it */ | |||
944 | *((char**)vP) = (char *)airFree(*((char**)vP)); | |||
945 | opt[op].alloc = 0; | |||
946 | } | |||
947 | /* vP is the address of a char* (a char**), and what we | |||
948 | manage with airMop is the char * */ | |||
949 | airMopMem(pmop, vP, airMopOnError); | |||
950 | break; | |||
951 | default: | |||
952 | if (1 != airParseStr[type](vP, prms[op], " ", 1)) { | |||
953 | sprintf(err, "%scouldn't parse %s\"%s\" as %s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
954 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident) | |||
955 | airTypeStr[type], ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %s for %s", ( (parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], airTypeStr[type], ident); | |||
956 | return 1; | |||
957 | } | |||
958 | opt[op].alloc = 0; | |||
959 | if (1 == _hestCase(opt, udflt, nprm, appr, op)) { | |||
960 | /* we just parsed the default, but now we want to "invert" it */ | |||
961 | tmpD = airDLoad(vP, type); | |||
962 | airIStore(vP, type, tmpD ? 0 : 1); | |||
963 | } | |||
964 | break; | |||
965 | } | |||
966 | } | |||
967 | break; | |||
968 | case 5: | |||
969 | /* -------- multiple optional parameters -------- */ | |||
970 | /* hammerhead problems in this case; | |||
971 | may have been from calloc(0), fixed below */ | |||
972 | if (prms[op] && vP) { | |||
973 | if (1 == _hestCase(opt, udflt, nprm, appr, op)) { | |||
974 | *((void**)vP) = NULL((void*)0); | |||
975 | /* alloc and sawP set above */ | |||
976 | } else { | |||
977 | if (airTypeString == type) { | |||
978 | /* this is sneakiness: we allocate one more element so that | |||
979 | the resulting char** is, like argv, NULL-terminated */ | |||
980 | *((void**)vP) = calloc(nprm[op]+1, size); | |||
981 | } else { | |||
982 | if (nprm[op]) { | |||
983 | /* only allocate if there's something to allocate */ | |||
984 | *((void**)vP) = calloc(nprm[op], size); | |||
985 | } else { | |||
986 | *((void**)vP) = NULL((void*)0); | |||
987 | } | |||
988 | } | |||
989 | if (parm->verbosity) { | |||
990 | printf("!%s: nprm[%d] = %u\n", me, op, nprm[op]); | |||
991 | printf("!%s: new array (size %u*%u) is at 0x%p\n", me, | |||
992 | nprm[op], (unsigned int)size, *((void**)vP)); | |||
993 | } | |||
994 | if (*((void**)vP)) { | |||
995 | airMopMem(pmop, vP, airMopOnError); | |||
996 | } | |||
997 | *(opt[op].sawP) = nprm[op]; | |||
998 | /* so far everything we've done is regardless of type */ | |||
999 | switch (type) { | |||
1000 | case airTypeEnum: | |||
1001 | opt[op].alloc = 1; | |||
1002 | if (nprm[op] != | |||
1003 | airParseStrE((int *)(*((void**)vP)), prms[op], " ", nprm[op], | |||
1004 | opt[op].enm)) { | |||
1005 | sprintf(err, "%scouldn't parse %s\"%s\" as %u %s%s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %u %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], opt[op].enm->name , nprm[op] > 1 ? "s" : "", ident) | |||
1006 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %u %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], opt[op].enm->name , nprm[op] > 1 ? "s" : "", ident) | |||
1007 | nprm[op], opt[op].enm->name,__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %u %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], opt[op].enm->name , nprm[op] > 1 ? "s" : "", ident) | |||
1008 | nprm[op] > 1 ? "s" : "", ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %u %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], opt[op].enm->name , nprm[op] > 1 ? "s" : "", ident); | |||
1009 | return 1; | |||
1010 | } | |||
1011 | break; | |||
1012 | case airTypeOther: | |||
1013 | cP = (char *)(*((void**)vP)); | |||
1014 | prmsCopy = airStrdup(prms[op]); | |||
1015 | opt[op].alloc = (opt[op].CB->destroy ? 3 : 1); | |||
1016 | for (p=0; p<(int)nprm[op]; p++) { /* HEY scrutinize casts */ | |||
1017 | tok = airStrtok(!p ? prmsCopy : NULL((void*)0), " ", &last); | |||
1018 | /* hammerhead problems went away when this line | |||
1019 | was replaced by the following one: | |||
1020 | strcpy(cberr, ""); | |||
1021 | */ | |||
1022 | cberr[0] = 0; | |||
1023 | ret = opt[op].CB->parse(cP + p*size, tok, cberr); | |||
1024 | if (ret) { | |||
1025 | if (strlen(cberr)) | |||
1026 | sprintf(err,"%serror parsing \"%s\" (in \"%s\") as %s "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s:\n%s", ((parm && parm->verbosity) ? me : "" ), tok, prms[op], opt[op].CB->type, ident, cberr) | |||
1027 | "for %s:\n%s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s:\n%s", ((parm && parm->verbosity) ? me : "" ), tok, prms[op], opt[op].CB->type, ident, cberr) | |||
1028 | ME, tok, prms[op], opt[op].CB->type, ident, cberr)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s:\n%s", ((parm && parm->verbosity) ? me : "" ), tok, prms[op], opt[op].CB->type, ident, cberr); | |||
1029 | ||||
1030 | else | |||
1031 | sprintf(err, "%serror parsing \"%s\" (in \"%s\") as %s "__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s: returned %d", ((parm && parm->verbosity) ? me : ""), tok, prms[op], opt[op].CB->type, ident, ret) | |||
1032 | "for %s: returned %d",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s: returned %d", ((parm && parm->verbosity) ? me : ""), tok, prms[op], opt[op].CB->type, ident, ret) | |||
1033 | ME, tok, prms[op], opt[op].CB->type, ident, ret)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%serror parsing \"%s\" (in \"%s\") as %s " "for %s: returned %d", ((parm && parm->verbosity) ? me : ""), tok, prms[op], opt[op].CB->type, ident, ret); | |||
1034 | free(prmsCopy); | |||
1035 | return 1; | |||
1036 | } | |||
1037 | } | |||
1038 | free(prmsCopy); | |||
1039 | if (opt[op].CB->destroy) { | |||
1040 | for (p=0; p<(int)nprm[op]; p++) { /* HEY scrutinize casts */ | |||
1041 | /* avert your eyes. vP is the address of an array of void*s. | |||
1042 | We manage the void*s */ | |||
1043 | airMopAdd(pmop, (*((void***)vP))+p, (airMopper)airSetNull, | |||
1044 | airMopOnError); | |||
1045 | airMopAdd(pmop, *((*((void***)vP))+p), opt[op].CB->destroy, | |||
1046 | airMopOnError); | |||
1047 | } | |||
1048 | } | |||
1049 | break; | |||
1050 | case airTypeString: | |||
1051 | opt[op].alloc = 3; | |||
1052 | if (nprm[op] != | |||
1053 | airParseStrS((char **)(*((void**)vP)), prms[op], " ", nprm[op], | |||
1054 | parm->greedySingleString)) { | |||
1055 | sprintf(err, "%scouldn't parse %s\"%s\" as %d %s%s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident) | |||
1056 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident) | |||
1057 | nprm[op], airTypeStr[type],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident) | |||
1058 | nprm[op] > 1 ? "s" : "", ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident); | |||
1059 | return 1; | |||
1060 | } | |||
1061 | /* vP is the address of an array of char*s (a char ***), and | |||
1062 | what we manage with airMop is the individual (*vP)[p], | |||
1063 | as well as vP itself (above). */ | |||
1064 | for (p=0; p<(int)nprm[op]; p++) { /* HEY scrutinize casts */ | |||
1065 | airMopAdd(pmop, (*((char***)vP))[p], airFree, airMopOnError); | |||
| ||||
1066 | } | |||
1067 | /* do the NULL-termination described above */ | |||
1068 | (*((char***)vP))[nprm[op]] = NULL((void*)0); | |||
1069 | break; | |||
1070 | default: | |||
1071 | opt[op].alloc = 1; | |||
1072 | if (nprm[op] != | |||
1073 | airParseStr[type](*((void**)vP), prms[op], " ", nprm[op])) { | |||
1074 | sprintf(err, "%scouldn't parse %s\"%s\" as %d %s%s for %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident) | |||
1075 | ME, udflt[op] ? "(default) " : "", prms[op],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident) | |||
1076 | nprm[op], airTypeStr[type],__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident) | |||
1077 | nprm[op] > 1 ? "s" : "", ident)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%scouldn't parse %s\"%s\" as %d %s%s for %s" , ((parm && parm->verbosity) ? me : ""), udflt[op] ? "(default) " : "", prms[op], nprm[op], airTypeStr[type], nprm [op] > 1 ? "s" : "", ident); | |||
1078 | return 1; | |||
1079 | } | |||
1080 | break; | |||
1081 | } | |||
1082 | } | |||
1083 | } | |||
1084 | break; | |||
1085 | } | |||
1086 | } | |||
1087 | return 0; | |||
1088 | } | |||
1089 | ||||
1090 | /* | |||
1091 | ******** hestParse() | |||
1092 | ** | |||
1093 | ** documentation? | |||
1094 | */ | |||
1095 | int | |||
1096 | hestParse(hestOpt *opt, int _argc, const char **_argv, | |||
1097 | char **_errP, const hestParm *_parm) { | |||
1098 | char me[]="hestParse: "; | |||
1099 | char *param, *param_copy; | |||
1100 | char **argv, **prms, *err; | |||
1101 | int a, argc, argr, *appr, *udflt, nrf, numOpts, big, ret, i; | |||
1102 | unsigned int *nprm; | |||
1103 | airArray *mop; | |||
1104 | hestParm *parm; | |||
1105 | size_t start_index, end_index; | |||
1106 | ||||
1107 | numOpts = _hestNumOpts(opt); | |||
1108 | ||||
1109 | /* -------- initialize the mop! */ | |||
1110 | mop = airMopNew(); | |||
1111 | ||||
1112 | /* -------- either copy given _parm, or allocate one */ | |||
1113 | if (_parm) { | |||
1114 | parm = NULL((void*)0); | |||
1115 | } | |||
1116 | else { | |||
1117 | parm = hestParmNew(); | |||
1118 | airMopAdd(mop, parm, (airMopper)hestParmFree, airMopAlways); | |||
1119 | } | |||
1120 | /* how to const-correctly use parm or _parm in an expression */ | |||
1121 | #define PARM (_parm ? _parm : parm) | |||
1122 | ||||
1123 | /* -------- allocate the err string. To determine its size with total | |||
1124 | ridiculous safety we have to find the biggest things which can appear | |||
1125 | in the string. */ | |||
1126 | big = _hestErrStrlen(opt, _argc, _argv); | |||
1127 | if (!( err = AIR_CALLOC(big, char)(char*)(calloc((big), sizeof(char))) )) { | |||
1128 | fprintf(stderr__stderrp, "%s PANIC: couldn't allocate error message " | |||
1129 | "buffer (size %d)\n", me, big); | |||
1130 | /* exit(1); */ | |||
1131 | } | |||
1132 | if (_errP) { | |||
1133 | /* if they care about the error string, than it is mopped only | |||
1134 | when there _wasn't_ an error */ | |||
1135 | *_errP = err; | |||
1136 | airMopAdd(mop, _errP, (airMopper)airSetNull, airMopOnOkay); | |||
1137 | airMopAdd(mop, err, airFree, airMopOnOkay); | |||
1138 | } | |||
1139 | else { | |||
1140 | /* otherwise, we're making the error string just for our own | |||
1141 | convenience, and we'll always clean it up on exit */ | |||
1142 | airMopAdd(mop, err, airFree, airMopAlways); | |||
1143 | } | |||
1144 | ||||
1145 | /* -------- check on validity of the hestOpt array */ | |||
1146 | if (_hestPanic(opt, err, PARM)) { | |||
1147 | airMopError(mop); return 1; | |||
1148 | } | |||
1149 | ||||
1150 | /* -------- Create all the local arrays used to save state during | |||
1151 | the processing of all the different options */ | |||
1152 | nprm = AIR_CALLOC(numOpts, unsigned int)(unsigned int*)(calloc((numOpts), sizeof(unsigned int))); | |||
1153 | airMopMem(mop, &nprm, airMopAlways); | |||
1154 | appr = AIR_CALLOC(numOpts, int)(int*)(calloc((numOpts), sizeof(int))); | |||
1155 | airMopMem(mop, &appr, airMopAlways); | |||
1156 | udflt = AIR_CALLOC(numOpts, int)(int*)(calloc((numOpts), sizeof(int))); | |||
1157 | airMopMem(mop, &udflt, airMopAlways); | |||
1158 | prms = AIR_CALLOC(numOpts, char *)(char **)(calloc((numOpts), sizeof(char *))); | |||
1159 | airMopMem(mop, &prms, airMopAlways); | |||
1160 | for (a=0; a<numOpts; a++) { | |||
1161 | prms[a] = NULL((void*)0); | |||
1162 | } | |||
1163 | ||||
1164 | /* -------- find out how big the argv array needs to be, first | |||
1165 | by seeing how many args are in the response files, and then adding | |||
1166 | on the args from the actual argv (getting this right the first time | |||
1167 | greatly simplifies the problem of eliminating memory leaks) */ | |||
1168 | if (_hestArgsInResponseFiles(&argr, &nrf, _argv, err, PARM)) { | |||
1169 | airMopError(mop); return 1; | |||
1170 | } | |||
1171 | argc = argr + _argc - nrf; | |||
1172 | ||||
1173 | if (PARM->verbosity) { | |||
1174 | printf("!%s: nrf = %d; argr = %d; _argc = %d --> argc = %d\n", | |||
1175 | me, nrf, argr, _argc, argc); | |||
1176 | } | |||
1177 | argv = AIR_CALLOC(argc+1, char *)(char **)(calloc((argc+1), sizeof(char *))); | |||
1178 | airMopMem(mop, &argv, airMopAlways); | |||
1179 | ||||
1180 | /* -------- process response files (if any) and set the remaining | |||
1181 | elements of argv */ | |||
1182 | if (PARM->verbosity) printf("%s: #### calling hestResponseFiles\n", me); | |||
1183 | if (_hestResponseFiles(argv, _argv, PARM, mop)) { | |||
1184 | airMopError(mop); return 1; | |||
1185 | } | |||
1186 | if (PARM->verbosity) printf("%s: #### hestResponseFiles done!\n", me); | |||
1187 | /* | |||
1188 | _hestPrintArgv(argc, argv); | |||
1189 | */ | |||
1190 | ||||
1191 | /* -------- extract flags and their associated parameters from argv */ | |||
1192 | if (PARM->verbosity) printf("%s: #### calling hestExtractFlagged\n", me); | |||
1193 | if (_hestExtractFlagged(prms, nprm, appr, | |||
1194 | &argc, argv, | |||
1195 | opt, | |||
1196 | err, PARM, mop)) { | |||
1197 | airMopError(mop); return 1; | |||
1198 | } | |||
1199 | if (PARM->verbosity) printf("%s: #### hestExtractFlagged done!\n", me); | |||
1200 | /* | |||
1201 | _hestPrintArgv(argc, argv); | |||
1202 | */ | |||
1203 | ||||
1204 | /* -------- extract args for unflagged options */ | |||
1205 | if (PARM->verbosity) printf("%s: #### calling hestExtractUnflagged\n", me); | |||
1206 | if (_hestExtractUnflagged(prms, nprm, | |||
1207 | &argc, argv, | |||
1208 | opt, | |||
1209 | err, PARM, mop)) { | |||
1210 | airMopError(mop); return 1; | |||
1211 | } | |||
1212 | if (PARM->verbosity) printf("%s: #### hestExtractUnflagged done!\n", me); | |||
1213 | ||||
1214 | /* currently, any left over arguments indicate error */ | |||
1215 | if (argc) { | |||
1216 | sprintf(err, "%sunexpected arg%s: \"%s\"", ME,__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sunexpected arg%s: \"%s\"", ((parm && parm->verbosity) ? me : ""), ('-' == argv[0][0] ? " (or unrecognized flag)" : ""), argv[0]) | |||
1217 | ('-' == argv[0][0]__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sunexpected arg%s: \"%s\"", ((parm && parm->verbosity) ? me : ""), ('-' == argv[0][0] ? " (or unrecognized flag)" : ""), argv[0]) | |||
1218 | ? " (or unrecognized flag)"__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sunexpected arg%s: \"%s\"", ((parm && parm->verbosity) ? me : ""), ('-' == argv[0][0] ? " (or unrecognized flag)" : ""), argv[0]) | |||
1219 | : ""), argv[0])__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%sunexpected arg%s: \"%s\"", ((parm && parm->verbosity) ? me : ""), ('-' == argv[0][0] ? " (or unrecognized flag)" : ""), argv[0]); | |||
1220 | airMopError(mop); return 1; | |||
1221 | } | |||
1222 | ||||
1223 | /* -------- learn defaults */ | |||
1224 | if (PARM->verbosity) printf("%s: #### calling hestDefaults\n", me); | |||
1225 | if (_hestDefaults(prms, udflt, nprm, appr, | |||
1226 | opt, | |||
1227 | err, PARM, mop)) { | |||
1228 | airMopError(mop); return 1; | |||
1229 | } | |||
1230 | if (PARM->verbosity) printf("%s: #### hestDefaults done!\n", me); | |||
1231 | ||||
1232 | /* remove quotes from strings | |||
1233 | if greedy wasn't turned on for strings, then we have no hope | |||
1234 | of capturing filenames with spaces. */ | |||
1235 | if ( PARM->greedySingleString ) { | |||
1236 | for (i=0; i<numOpts; i++) { | |||
1237 | param = prms[i]; | |||
1238 | param_copy = NULL((void*)0); | |||
1239 | if (param && strstr(param, " ")) { | |||
1240 | start_index = 0; | |||
1241 | end_index = strlen(param)-1; | |||
1242 | if (param[start_index] == '\"') | |||
1243 | start_index++; | |||
1244 | if (param[end_index] == '\"') | |||
1245 | end_index--; | |||
1246 | param_copy = AIR_CALLOC(end_index-start_index+2, char)(char*)(calloc((end_index-start_index+2), sizeof(char))); | |||
1247 | strncpy(param_copy,¶m[start_index],end_index-start_index+1)__builtin___strncpy_chk (param_copy, ¶m[start_index], end_index-start_index+1, __builtin_object_size (param_copy, 2 > 1 ? 1 : 0)); | |||
1248 | param_copy[end_index-start_index+1] = '\0'; | |||
1249 | strcpy(param,param_copy)__builtin___strcpy_chk (param, param_copy, __builtin_object_size (param, 2 > 1 ? 1 : 0)); | |||
1250 | free(param_copy); | |||
1251 | } | |||
1252 | } | |||
1253 | } | |||
1254 | ||||
1255 | /* -------- now, the actual parsing of values */ | |||
1256 | /* hammerhead problems in _hestSetValues */ | |||
1257 | if (PARM->verbosity) printf("%s: #### calling hestSetValues\n", me); | |||
1258 | ret = _hestSetValues(prms, udflt, nprm, appr, | |||
1259 | opt, | |||
1260 | err, PARM, mop); | |||
1261 | if (ret) { | |||
1262 | airMopError(mop); return ret; | |||
1263 | } | |||
1264 | ||||
1265 | if (PARM->verbosity) printf("%s: #### hestSetValues done!\n", me); | |||
1266 | #undef PARM | |||
1267 | ||||
1268 | airMopOkay(mop); | |||
1269 | return 0; | |||
1270 | } | |||
1271 | ||||
1272 | /* | |||
1273 | ******** hestParseFree() | |||
1274 | ** | |||
1275 | ** free()s whatever was allocated by hestParse() | |||
1276 | ** | |||
1277 | ** returns NULL only to facilitate use with the airMop functions. | |||
1278 | ** You should probably just ignore this quirk. | |||
1279 | */ | |||
1280 | void * | |||
1281 | hestParseFree(hestOpt *opt) { | |||
1282 | int op, i, numOpts; | |||
1283 | unsigned int ui; | |||
1284 | void **vP; | |||
1285 | void ***vAP; | |||
1286 | char **str; | |||
1287 | char ***strP; | |||
1288 | ||||
1289 | numOpts = _hestNumOpts(opt); | |||
1290 | for (op=0; op<numOpts; op++) { | |||
1291 | /* | |||
1292 | printf("!hestParseFree: op = %d/%d -> kind = %d; type = %d; alloc = %d\n", | |||
1293 | op, numOpts-1, opt[op].kind, opt[op].type, opt[op].alloc); | |||
1294 | */ | |||
1295 | vP = (void **)opt[op].valueP; | |||
1296 | vAP = (void ***)opt[op].valueP; | |||
1297 | str = (char **)opt[op].valueP; | |||
1298 | strP = (char ***)opt[op].valueP; | |||
1299 | switch (opt[op].alloc) { | |||
1300 | case 0: | |||
1301 | /* nothing was allocated */ | |||
1302 | break; | |||
1303 | case 1: | |||
1304 | if (airTypeOther != opt[op].type) { | |||
1305 | *vP = airFree(*vP); | |||
1306 | } | |||
1307 | else { | |||
1308 | /* alloc is one either because we parsed one thing, and we have a | |||
1309 | destroy callback, or, because we parsed a dynamically-created array | |||
1310 | of things, and we don't have a destroy callback */ | |||
1311 | if (opt[op].CB->destroy) { | |||
1312 | *vP = opt[op].CB->destroy(*vP); | |||
1313 | } | |||
1314 | else { | |||
1315 | *vP = airFree(*vP); | |||
1316 | } | |||
1317 | } | |||
1318 | break; | |||
1319 | case 2: | |||
1320 | if (airTypeString == opt[op].type) { | |||
1321 | for (i=0; i<(int)opt[op].min; i++) { /* HEY scrutinize casts */ | |||
1322 | str[i] = (char *)airFree(str[i]); | |||
1323 | } | |||
1324 | } | |||
1325 | else { | |||
1326 | for (i=0; i<(int)opt[op].min; i++) { /* HEY scrutinize casts */ | |||
1327 | vP[i] = opt[op].CB->destroy(vP[i]); | |||
1328 | } | |||
1329 | } | |||
1330 | break; | |||
1331 | case 3: | |||
1332 | if (airTypeString == opt[op].type) { | |||
1333 | for (ui=0; ui<*(opt[op].sawP); ui++) { | |||
1334 | (*strP)[ui] = (char *)airFree((*strP)[ui]); | |||
1335 | } | |||
1336 | *strP = (char **)airFree(*strP); | |||
1337 | } | |||
1338 | else { | |||
1339 | for (ui=0; ui<*(opt[op].sawP); ui++) { | |||
1340 | (*vAP)[ui] = opt[op].CB->destroy((*vAP)[ui]); | |||
1341 | } | |||
1342 | *vAP = (void **)airFree(*vAP); | |||
1343 | } | |||
1344 | break; | |||
1345 | } | |||
1346 | } | |||
1347 | return NULL((void*)0); | |||
1348 | } | |||
1349 | ||||
1350 | /* | |||
1351 | ******** hestParseOrDie() | |||
1352 | ** | |||
1353 | ** dumb little function which encapsulate a common usage of hest: | |||
1354 | ** first, make sure hestOpt is valid with hestOptCheck(). Then, | |||
1355 | ** if argc is 0 (and !parm->noArgsIsNoProblem): maybe show | |||
1356 | ** info, usage, and glossary, all according to given flags, then exit(1) | |||
1357 | ** if parsing failed: show error message, and maybe usage and glossary, | |||
1358 | ** again according to boolean flags, then exit(1) | |||
1359 | ** if parsing succeeded: return | |||
1360 | */ | |||
1361 | void | |||
1362 | hestParseOrDie(hestOpt *opt, int argc, const char **argv, | |||
1363 | hestParm *parm, | |||
1364 | const char *me, const char *info, | |||
1365 | int doInfo, int doUsage, int doGlossary) { | |||
1366 | int E; | |||
1367 | int argcBad; | |||
1368 | char *errS; | |||
1369 | ||||
1370 | if (opt) { | |||
1371 | if (hestOptCheck(opt, &errS)) { | |||
1372 | fprintf(stderr__stderrp, "ERROR in hest usage:\n%s\n", errS); free(errS); | |||
1373 | exit(1); | |||
1374 | } | |||
1375 | E = 0; | |||
1376 | /* argc is good if its non-zero, or (else) being zero is ok */ | |||
1377 | argcBad = !(argc || (parm && parm->noArgsIsNoProblem)); | |||
1378 | if ( argcBad || | |||
1379 | (E = hestParse(opt, argc, argv, &errS, parm)) ) { | |||
1380 | if (E) { | |||
1381 | if (argv[0] && !strcmp(argv[0], "--version")) { | |||
1382 | /* print version info and bail */ | |||
1383 | char vbuff[AIR_STRLEN_LARGE(512+1)]; | |||
1384 | airTeemVersionSprint(vbuff); | |||
1385 | printf("%s\n", vbuff); | |||
1386 | hestParmFree(parm); | |||
1387 | hestOptFree(opt); | |||
1388 | exit(0); | |||
1389 | } else if (argv[0] && !strcmp(argv[0], "--help")) { | |||
1390 | /* actually, not an error, they were asking for help */ | |||
1391 | E = 0; | |||
1392 | } else { | |||
1393 | fprintf(stderr__stderrp, "ERROR: %s\n", errS); | |||
1394 | } | |||
1395 | free(errS); | |||
1396 | } | |||
1397 | if (!E) { | |||
1398 | /* no error, just !argc */ | |||
1399 | if (doInfo && info) hestInfo(stdout__stdoutp, me?me:"", info, parm); | |||
1400 | } | |||
1401 | if (doUsage) hestUsage(E ? stderr__stderrp : stdout__stdoutp, opt, me?me:"", parm); | |||
1402 | if (doGlossary) hestGlossary(E ? stderr__stderrp : stdout__stdoutp, opt, parm); | |||
1403 | hestParmFree(parm); | |||
1404 | hestOptFree(opt); | |||
1405 | exit(1); | |||
1406 | } | |||
1407 | } | |||
1408 | ||||
1409 | return; | |||
1410 | } |