File: | tools/polly/lib/External/isl/isl_arg.c |
Warning: | line 543, column 35 Dereference of null pointer (loaded from variable 'p') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright 2008-2009 Katholieke Universiteit Leuven | |||
3 | * | |||
4 | * Use of this software is governed by the MIT license | |||
5 | * | |||
6 | * Written by Sven Verdoolaege, K.U.Leuven, Departement | |||
7 | * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium | |||
8 | */ | |||
9 | ||||
10 | #include <stdio.h> | |||
11 | #include <stdlib.h> | |||
12 | #include <string.h> | |||
13 | ||||
14 | #include <isl/arg.h> | |||
15 | #include <isl/ctx.h> | |||
16 | #include <isl_config.h> | |||
17 | ||||
18 | static struct isl_arg help_arg[] = { | |||
19 | ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit"){ .type = isl_arg_bool, .short_name = 'h', .long_name = "help" , .offset = -1, .help_msg = "print this help, then exit", .flags = 0, .u = { .b = { .default_value = 0, .set = ((void*)0) } } }, | |||
20 | }; | |||
21 | ||||
22 | static void set_default_choice(struct isl_arg *arg, void *opt) | |||
23 | { | |||
24 | if (arg->offset == (size_t) -1) | |||
25 | return; | |||
26 | *(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value; | |||
27 | } | |||
28 | ||||
29 | static void set_default_flags(struct isl_arg *arg, void *opt) | |||
30 | { | |||
31 | *(unsigned *)(((char *)opt) + arg->offset) = arg->u.flags.default_value; | |||
32 | } | |||
33 | ||||
34 | static void set_default_bool(struct isl_arg *arg, void *opt) | |||
35 | { | |||
36 | if (arg->offset == (size_t) -1) | |||
37 | return; | |||
38 | *(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value; | |||
39 | } | |||
40 | ||||
41 | static void set_default_child(struct isl_arg *arg, void *opt) | |||
42 | { | |||
43 | void *child; | |||
44 | ||||
45 | if (arg->offset == (size_t) -1) | |||
46 | child = opt; | |||
47 | else { | |||
48 | child = calloc(1, arg->u.child.child->options_size); | |||
49 | *(void **)(((char *)opt) + arg->offset) = child; | |||
50 | } | |||
51 | ||||
52 | if (child) | |||
53 | isl_args_set_defaults(arg->u.child.child, child); | |||
54 | } | |||
55 | ||||
56 | static void set_default_user(struct isl_arg *arg, void *opt) | |||
57 | { | |||
58 | arg->u.user.init(((char *)opt) + arg->offset); | |||
59 | } | |||
60 | ||||
61 | static void set_default_int(struct isl_arg *arg, void *opt) | |||
62 | { | |||
63 | *(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value; | |||
64 | } | |||
65 | ||||
66 | static void set_default_long(struct isl_arg *arg, void *opt) | |||
67 | { | |||
68 | *(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value; | |||
69 | } | |||
70 | ||||
71 | static void set_default_ulong(struct isl_arg *arg, void *opt) | |||
72 | { | |||
73 | *(unsigned long *)(((char *)opt) + arg->offset) = arg->u.ul.default_value; | |||
74 | } | |||
75 | ||||
76 | static void set_default_str(struct isl_arg *arg, void *opt) | |||
77 | { | |||
78 | const char *str = NULL((void*)0); | |||
79 | if (arg->u.str.default_value) | |||
80 | str = strdup(arg->u.str.default_value); | |||
81 | *(const char **)(((char *)opt) + arg->offset) = str; | |||
82 | } | |||
83 | ||||
84 | static void set_default_str_list(struct isl_arg *arg, void *opt) | |||
85 | { | |||
86 | *(const char ***)(((char *) opt) + arg->offset) = NULL((void*)0); | |||
87 | *(int *)(((char *) opt) + arg->u.str_list.offset_n) = 0; | |||
88 | } | |||
89 | ||||
90 | void isl_args_set_defaults(struct isl_args *args, void *opt) | |||
91 | { | |||
92 | int i; | |||
93 | ||||
94 | for (i = 0; args->args[i].type != isl_arg_end; ++i) { | |||
95 | switch (args->args[i].type) { | |||
96 | case isl_arg_choice: | |||
97 | set_default_choice(&args->args[i], opt); | |||
98 | break; | |||
99 | case isl_arg_flags: | |||
100 | set_default_flags(&args->args[i], opt); | |||
101 | break; | |||
102 | case isl_arg_bool: | |||
103 | set_default_bool(&args->args[i], opt); | |||
104 | break; | |||
105 | case isl_arg_child: | |||
106 | set_default_child(&args->args[i], opt); | |||
107 | break; | |||
108 | case isl_arg_user: | |||
109 | set_default_user(&args->args[i], opt); | |||
110 | break; | |||
111 | case isl_arg_int: | |||
112 | set_default_int(&args->args[i], opt); | |||
113 | break; | |||
114 | case isl_arg_long: | |||
115 | set_default_long(&args->args[i], opt); | |||
116 | break; | |||
117 | case isl_arg_ulong: | |||
118 | set_default_ulong(&args->args[i], opt); | |||
119 | break; | |||
120 | case isl_arg_arg: | |||
121 | case isl_arg_str: | |||
122 | set_default_str(&args->args[i], opt); | |||
123 | break; | |||
124 | case isl_arg_str_list: | |||
125 | set_default_str_list(&args->args[i], opt); | |||
126 | break; | |||
127 | case isl_arg_alias: | |||
128 | case isl_arg_footer: | |||
129 | case isl_arg_version: | |||
130 | case isl_arg_end: | |||
131 | break; | |||
132 | } | |||
133 | } | |||
134 | } | |||
135 | ||||
136 | static void free_args(struct isl_arg *arg, void *opt); | |||
137 | ||||
138 | static void free_child(struct isl_arg *arg, void *opt) | |||
139 | { | |||
140 | if (arg->offset == (size_t) -1) | |||
141 | free_args(arg->u.child.child->args, opt); | |||
142 | else | |||
143 | isl_args_free(arg->u.child.child, | |||
144 | *(void **)(((char *)opt) + arg->offset)); | |||
145 | } | |||
146 | ||||
147 | static void free_str_list(struct isl_arg *arg, void *opt) | |||
148 | { | |||
149 | int i; | |||
150 | int n = *(int *)(((char *) opt) + arg->u.str_list.offset_n); | |||
151 | char **list = *(char ***)(((char *) opt) + arg->offset); | |||
152 | ||||
153 | for (i = 0; i < n; ++i) | |||
154 | free(list[i]); | |||
155 | free(list); | |||
156 | } | |||
157 | ||||
158 | static void free_user(struct isl_arg *arg, void *opt) | |||
159 | { | |||
160 | if (arg->u.user.clear) | |||
161 | arg->u.user.clear(((char *)opt) + arg->offset); | |||
162 | } | |||
163 | ||||
164 | static void free_args(struct isl_arg *arg, void *opt) | |||
165 | { | |||
166 | int i; | |||
167 | ||||
168 | for (i = 0; arg[i].type != isl_arg_end; ++i) { | |||
169 | switch (arg[i].type) { | |||
170 | case isl_arg_child: | |||
171 | free_child(&arg[i], opt); | |||
172 | break; | |||
173 | case isl_arg_arg: | |||
174 | case isl_arg_str: | |||
175 | free(*(char **)(((char *)opt) + arg[i].offset)); | |||
176 | break; | |||
177 | case isl_arg_str_list: | |||
178 | free_str_list(&arg[i], opt); | |||
179 | break; | |||
180 | case isl_arg_user: | |||
181 | free_user(&arg[i], opt); | |||
182 | break; | |||
183 | case isl_arg_alias: | |||
184 | case isl_arg_bool: | |||
185 | case isl_arg_choice: | |||
186 | case isl_arg_flags: | |||
187 | case isl_arg_int: | |||
188 | case isl_arg_long: | |||
189 | case isl_arg_ulong: | |||
190 | case isl_arg_version: | |||
191 | case isl_arg_footer: | |||
192 | case isl_arg_end: | |||
193 | break; | |||
194 | } | |||
195 | } | |||
196 | } | |||
197 | ||||
198 | void isl_args_free(struct isl_args *args, void *opt) | |||
199 | { | |||
200 | if (!opt) | |||
201 | return; | |||
202 | ||||
203 | free_args(args->args, opt); | |||
204 | ||||
205 | free(opt); | |||
206 | } | |||
207 | ||||
208 | /* Data structure for collecting the prefixes of ancestor nodes. | |||
209 | * | |||
210 | * n is the number of prefixes. | |||
211 | * prefix[i] for i < n is a prefix of an ancestor. | |||
212 | * len[i] for i < n is the length of prefix[i]. | |||
213 | */ | |||
214 | struct isl_prefixes { | |||
215 | int n; | |||
216 | const char *prefix[10]; | |||
217 | size_t len[10]; | |||
218 | }; | |||
219 | ||||
220 | /* Add "prefix" to the list of prefixes and return the updated | |||
221 | * number of prefixes. | |||
222 | */ | |||
223 | static int add_prefix(struct isl_prefixes *prefixes, const char *prefix) | |||
224 | { | |||
225 | int n = prefixes->n; | |||
226 | ||||
227 | if (!prefix) | |||
228 | return n; | |||
229 | ||||
230 | if (prefixes->n >= 10) { | |||
231 | fprintf(stderrstderr, "too many prefixes\n"); | |||
232 | exit(EXIT_FAILURE1); | |||
233 | } | |||
234 | prefixes->len[prefixes->n] = strlen(prefix); | |||
235 | prefixes->prefix[prefixes->n] = prefix; | |||
236 | prefixes->n++; | |||
237 | ||||
238 | return n; | |||
239 | } | |||
240 | ||||
241 | /* Drop all prefixes starting at "first". | |||
242 | */ | |||
243 | static void drop_prefix(struct isl_prefixes *prefixes, int first) | |||
244 | { | |||
245 | prefixes->n = first; | |||
246 | } | |||
247 | ||||
248 | /* Print the prefixes in "prefixes". | |||
249 | */ | |||
250 | static int print_prefixes(struct isl_prefixes *prefixes) | |||
251 | { | |||
252 | int i; | |||
253 | int len = 0; | |||
254 | ||||
255 | if (!prefixes) | |||
256 | return 0; | |||
257 | ||||
258 | for (i = 0; i < prefixes->n; ++i) { | |||
259 | printf("%s-", prefixes->prefix[i]); | |||
260 | len += strlen(prefixes->prefix[i]) + 1; | |||
261 | } | |||
262 | ||||
263 | return len; | |||
264 | } | |||
265 | ||||
266 | /* Check if "name" starts with one or more of the prefixes in "prefixes", | |||
267 | * starting at *first. If so, advance the pointer beyond the prefixes | |||
268 | * and return the updated pointer. Additionally, update *first to | |||
269 | * the index after the last prefix found. | |||
270 | */ | |||
271 | static const char *skip_prefixes(const char *name, | |||
272 | struct isl_prefixes *prefixes, int *first) | |||
273 | { | |||
274 | int i; | |||
275 | ||||
276 | for (i = first ? *first : 0; i < prefixes->n; ++i) { | |||
277 | size_t len = prefixes->len[i]; | |||
278 | const char *prefix = prefixes->prefix[i]; | |||
279 | if (strncmp(name, prefix, len) == 0 && name[len] == '-') { | |||
280 | name += len + 1; | |||
281 | if (first) | |||
282 | *first = i + 1; | |||
283 | } | |||
284 | } | |||
285 | ||||
286 | return name; | |||
287 | } | |||
288 | ||||
289 | static int print_arg_help(struct isl_arg *decl, struct isl_prefixes *prefixes, | |||
290 | int no) | |||
291 | { | |||
292 | int len = 0; | |||
293 | ||||
294 | if (!decl->long_name) { | |||
295 | printf(" -%c", decl->short_name); | |||
296 | return 4; | |||
297 | } | |||
298 | ||||
299 | if (decl->short_name) { | |||
300 | printf(" -%c, --", decl->short_name); | |||
301 | len += 8; | |||
302 | } else if (decl->flags & ISL_ARG_SINGLE_DASH(1 << 0)) { | |||
303 | printf(" -"); | |||
304 | len += 3; | |||
305 | } else { | |||
306 | printf(" --"); | |||
307 | len += 8; | |||
308 | } | |||
309 | ||||
310 | if (no) { | |||
311 | printf("no-"); | |||
312 | len += 3; | |||
313 | } | |||
314 | len += print_prefixes(prefixes); | |||
315 | printf("%s", decl->long_name); | |||
316 | len += strlen(decl->long_name); | |||
317 | ||||
318 | while ((++decl)->type == isl_arg_alias) { | |||
319 | printf(", --"); | |||
320 | len += 4; | |||
321 | if (no) { | |||
322 | printf("no-"); | |||
323 | len += 3; | |||
324 | } | |||
325 | printf("%s", decl->long_name); | |||
326 | len += strlen(decl->long_name); | |||
327 | } | |||
328 | ||||
329 | return len; | |||
330 | } | |||
331 | ||||
332 | const void *isl_memrchr(const void *s, int c, size_t n) | |||
333 | { | |||
334 | const char *p = s; | |||
335 | while (n-- > 0) | |||
336 | if (p[n] == c) | |||
337 | return p + n; | |||
338 | return NULL((void*)0); | |||
339 | } | |||
340 | ||||
341 | static int wrap_msg(const char *s, int indent, int pos) | |||
342 | { | |||
343 | int len; | |||
344 | int wrap_len = 75 - indent; | |||
345 | ||||
346 | if (pos + 1 >= indent) | |||
347 | printf("\n%*s", indent, ""); | |||
348 | else | |||
349 | printf("%*s", indent - pos, ""); | |||
350 | ||||
351 | len = strlen(s); | |||
352 | while (len > wrap_len) { | |||
353 | const char *space = isl_memrchr(s, ' ', wrap_len); | |||
354 | int l; | |||
355 | ||||
356 | if (!space) | |||
357 | space = strchr(s + wrap_len, ' '); | |||
358 | if (!space) | |||
359 | break; | |||
360 | l = space - s; | |||
361 | printf("%.*s", l, s); | |||
362 | s = space + 1; | |||
363 | len -= l + 1; | |||
364 | printf("\n%*s", indent, ""); | |||
365 | } | |||
366 | ||||
367 | printf("%s", s); | |||
368 | return len; | |||
369 | } | |||
370 | ||||
371 | static int print_help_msg(struct isl_arg *decl, int pos) | |||
372 | { | |||
373 | if (!decl->help_msg) | |||
374 | return pos; | |||
375 | ||||
376 | return wrap_msg(decl->help_msg, 30, pos); | |||
377 | } | |||
378 | ||||
379 | static void print_default(struct isl_arg *decl, const char *def, int pos) | |||
380 | { | |||
381 | const char *default_prefix = "[default: "; | |||
382 | const char *default_suffix = "]"; | |||
383 | int len; | |||
384 | ||||
385 | len = strlen(default_prefix) + strlen(def) + strlen(default_suffix); | |||
386 | ||||
387 | if (!decl->help_msg) { | |||
388 | if (pos >= 29) | |||
389 | printf("\n%30s", ""); | |||
390 | else | |||
391 | printf("%*s", 30 - pos, ""); | |||
392 | } else { | |||
393 | if (pos + len >= 48) | |||
394 | printf("\n%30s", ""); | |||
395 | else | |||
396 | printf(" "); | |||
397 | } | |||
398 | printf("%s%s%s", default_prefix, def, default_suffix); | |||
399 | } | |||
400 | ||||
401 | static void print_default_choice(struct isl_arg *decl, void *opt, int pos) | |||
402 | { | |||
403 | int i; | |||
404 | const char *s = "none"; | |||
405 | unsigned *p; | |||
406 | ||||
407 | p = (unsigned *)(((char *) opt) + decl->offset); | |||
408 | for (i = 0; decl->u.choice.choice[i].name; ++i) | |||
409 | if (decl->u.choice.choice[i].value == *p) { | |||
410 | s = decl->u.choice.choice[i].name; | |||
411 | break; | |||
412 | } | |||
413 | ||||
414 | print_default(decl, s, pos); | |||
415 | } | |||
416 | ||||
417 | static void print_choice_help(struct isl_arg *decl, | |||
418 | struct isl_prefixes *prefixes, void *opt) | |||
419 | { | |||
420 | int i; | |||
421 | int pos; | |||
422 | ||||
423 | pos = print_arg_help(decl, prefixes, 0); | |||
424 | printf("="); | |||
425 | pos++; | |||
426 | ||||
427 | for (i = 0; decl->u.choice.choice[i].name; ++i) { | |||
428 | if (i) { | |||
429 | printf("|"); | |||
430 | pos++; | |||
431 | } | |||
432 | printf("%s", decl->u.choice.choice[i].name); | |||
433 | pos += strlen(decl->u.choice.choice[i].name); | |||
434 | } | |||
435 | ||||
436 | pos = print_help_msg(decl, pos); | |||
437 | print_default_choice(decl, opt, pos); | |||
438 | ||||
439 | printf("\n"); | |||
440 | } | |||
441 | ||||
442 | static void print_default_flags(struct isl_arg *decl, void *opt, int pos) | |||
443 | { | |||
444 | int i, first; | |||
445 | const char *default_prefix = "[default: "; | |||
446 | const char *default_suffix = "]"; | |||
447 | int len = strlen(default_prefix) + strlen(default_suffix); | |||
448 | unsigned *p; | |||
449 | ||||
450 | p = (unsigned *)(((char *) opt) + decl->offset); | |||
451 | for (i = 0; decl->u.flags.flags[i].name; ++i) | |||
452 | if ((*p & decl->u.flags.flags[i].mask) == | |||
453 | decl->u.flags.flags[i].value) | |||
454 | len += strlen(decl->u.flags.flags[i].name); | |||
455 | ||||
456 | if (!decl->help_msg) { | |||
457 | if (pos >= 29) | |||
458 | printf("\n%30s", ""); | |||
459 | else | |||
460 | printf("%*s", 30 - pos, ""); | |||
461 | } else { | |||
462 | if (pos + len >= 48) | |||
463 | printf("\n%30s", ""); | |||
464 | else | |||
465 | printf(" "); | |||
466 | } | |||
467 | printf("%s", default_prefix); | |||
468 | ||||
469 | for (first = 1, i = 0; decl->u.flags.flags[i].name; ++i) | |||
470 | if ((*p & decl->u.flags.flags[i].mask) == | |||
471 | decl->u.flags.flags[i].value) { | |||
472 | if (!first) | |||
473 | printf(","); | |||
474 | printf("%s", decl->u.flags.flags[i].name); | |||
475 | first = 0; | |||
476 | } | |||
477 | ||||
478 | printf("%s", default_suffix); | |||
479 | } | |||
480 | ||||
481 | static void print_flags_help(struct isl_arg *decl, | |||
482 | struct isl_prefixes *prefixes, void *opt) | |||
483 | { | |||
484 | int i, j; | |||
485 | int pos; | |||
486 | ||||
487 | pos = print_arg_help(decl, prefixes, 0); | |||
488 | printf("="); | |||
489 | pos++; | |||
490 | ||||
491 | for (i = 0; decl->u.flags.flags[i].name; ++i) { | |||
492 | if (i) { | |||
493 | printf(","); | |||
494 | pos++; | |||
495 | } | |||
496 | for (j = i; | |||
497 | decl->u.flags.flags[j].mask == decl->u.flags.flags[i].mask; | |||
498 | ++j) { | |||
499 | if (j != i) { | |||
500 | printf("|"); | |||
501 | pos++; | |||
502 | } | |||
503 | printf("%s", decl->u.flags.flags[j].name); | |||
504 | pos += strlen(decl->u.flags.flags[j].name); | |||
505 | } | |||
506 | i = j - 1; | |||
507 | } | |||
508 | ||||
509 | pos = print_help_msg(decl, pos); | |||
510 | print_default_flags(decl, opt, pos); | |||
511 | ||||
512 | printf("\n"); | |||
513 | } | |||
514 | ||||
515 | static void print_bool_help(struct isl_arg *decl, | |||
516 | struct isl_prefixes *prefixes, void *opt) | |||
517 | { | |||
518 | int pos; | |||
519 | unsigned *p = opt ? (unsigned *)(((char *) opt) + decl->offset) : NULL((void*)0); | |||
520 | int no = p ? *p == 1 : 0; | |||
521 | pos = print_arg_help(decl, prefixes, no); | |||
522 | pos = print_help_msg(decl, pos); | |||
523 | if (decl->offset != (size_t) -1) | |||
524 | print_default(decl, no ? "yes" : "no", pos); | |||
525 | printf("\n"); | |||
526 | } | |||
527 | ||||
528 | static int print_argument_name(struct isl_arg *decl, const char *name, int pos) | |||
529 | { | |||
530 | printf("%c<%s>", decl->long_name ? '=' : ' ', name); | |||
531 | return pos + 3 + strlen(name); | |||
532 | } | |||
533 | ||||
534 | static void print_int_help(struct isl_arg *decl, | |||
535 | struct isl_prefixes *prefixes, void *opt) | |||
536 | { | |||
537 | int pos; | |||
538 | char val[20]; | |||
539 | int *p = (int *)(((char *) opt) + decl->offset); | |||
540 | pos = print_arg_help(decl, prefixes, 0); | |||
541 | pos = print_argument_name(decl, decl->argument_name, pos); | |||
542 | pos = print_help_msg(decl, pos); | |||
543 | snprintf(val, sizeof(val), "%d", *p); | |||
| ||||
544 | print_default(decl, val, pos); | |||
545 | printf("\n"); | |||
546 | } | |||
547 | ||||
548 | static void print_long_help(struct isl_arg *decl, | |||
549 | struct isl_prefixes *prefixes, void *opt) | |||
550 | { | |||
551 | int pos; | |||
552 | long *p = (long *)(((char *) opt) + decl->offset); | |||
553 | pos = print_arg_help(decl, prefixes, 0); | |||
554 | if (*p != decl->u.l.default_selected) { | |||
555 | printf("["); | |||
556 | pos++; | |||
557 | } | |||
558 | printf("=long"); | |||
559 | pos += 5; | |||
560 | if (*p != decl->u.l.default_selected) { | |||
561 | printf("]"); | |||
562 | pos++; | |||
563 | } | |||
564 | print_help_msg(decl, pos); | |||
565 | printf("\n"); | |||
566 | } | |||
567 | ||||
568 | static void print_ulong_help(struct isl_arg *decl, | |||
569 | struct isl_prefixes *prefixes) | |||
570 | { | |||
571 | int pos; | |||
572 | pos = print_arg_help(decl, prefixes, 0); | |||
573 | printf("=ulong"); | |||
574 | pos += 6; | |||
575 | print_help_msg(decl, pos); | |||
576 | printf("\n"); | |||
577 | } | |||
578 | ||||
579 | static void print_str_help(struct isl_arg *decl, | |||
580 | struct isl_prefixes *prefixes, void *opt) | |||
581 | { | |||
582 | int pos; | |||
583 | const char *a = decl->argument_name ? decl->argument_name : "string"; | |||
584 | const char **p = (const char **)(((char *) opt) + decl->offset); | |||
585 | pos = print_arg_help(decl, prefixes, 0); | |||
586 | pos = print_argument_name(decl, a, pos); | |||
587 | pos = print_help_msg(decl, pos); | |||
588 | if (*p) | |||
589 | print_default(decl, *p, pos); | |||
590 | printf("\n"); | |||
591 | } | |||
592 | ||||
593 | static void print_str_list_help(struct isl_arg *decl, | |||
594 | struct isl_prefixes *prefixes) | |||
595 | { | |||
596 | int pos; | |||
597 | const char *a = decl->argument_name ? decl->argument_name : "string"; | |||
598 | pos = print_arg_help(decl, prefixes, 0); | |||
599 | pos = print_argument_name(decl, a, pos); | |||
600 | pos = print_help_msg(decl, pos); | |||
601 | printf("\n"); | |||
602 | } | |||
603 | ||||
604 | static void print_help(struct isl_arg *arg, | |||
605 | struct isl_prefixes *prefixes, void *opt) | |||
606 | { | |||
607 | int i; | |||
608 | int any = 0; | |||
609 | ||||
610 | for (i = 0; arg[i].type != isl_arg_end; ++i) { | |||
611 | if (arg[i].flags & ISL_ARG_HIDDEN(1 << 2)) | |||
612 | continue; | |||
613 | switch (arg[i].type) { | |||
614 | case isl_arg_flags: | |||
615 | print_flags_help(&arg[i], prefixes, opt); | |||
616 | any = 1; | |||
617 | break; | |||
618 | case isl_arg_choice: | |||
619 | print_choice_help(&arg[i], prefixes, opt); | |||
620 | any = 1; | |||
621 | break; | |||
622 | case isl_arg_bool: | |||
623 | print_bool_help(&arg[i], prefixes, opt); | |||
624 | any = 1; | |||
625 | break; | |||
626 | case isl_arg_int: | |||
627 | print_int_help(&arg[i], prefixes, opt); | |||
628 | any = 1; | |||
629 | break; | |||
630 | case isl_arg_long: | |||
631 | print_long_help(&arg[i], prefixes, opt); | |||
632 | any = 1; | |||
633 | break; | |||
634 | case isl_arg_ulong: | |||
635 | print_ulong_help(&arg[i], prefixes); | |||
636 | any = 1; | |||
637 | break; | |||
638 | case isl_arg_str: | |||
639 | print_str_help(&arg[i], prefixes, opt); | |||
640 | any = 1; | |||
641 | break; | |||
642 | case isl_arg_str_list: | |||
643 | print_str_list_help(&arg[i], prefixes); | |||
644 | any = 1; | |||
645 | break; | |||
646 | case isl_arg_alias: | |||
647 | case isl_arg_version: | |||
648 | case isl_arg_arg: | |||
649 | case isl_arg_footer: | |||
650 | case isl_arg_child: | |||
651 | case isl_arg_user: | |||
652 | case isl_arg_end: | |||
653 | break; | |||
654 | } | |||
655 | } | |||
656 | ||||
657 | for (i = 0; arg[i].type != isl_arg_end; ++i) { | |||
658 | void *child; | |||
659 | int first; | |||
660 | ||||
661 | if (arg[i].type != isl_arg_child) | |||
662 | continue; | |||
663 | if (arg[i].flags & ISL_ARG_HIDDEN(1 << 2)) | |||
664 | continue; | |||
665 | ||||
666 | if (any) | |||
667 | printf("\n"); | |||
668 | if (arg[i].help_msg) | |||
669 | printf(" %s\n", arg[i].help_msg); | |||
670 | if (arg[i].offset == (size_t) -1) | |||
671 | child = opt; | |||
672 | else | |||
673 | child = *(void **)(((char *) opt) + arg[i].offset); | |||
674 | first = add_prefix(prefixes, arg[i].long_name); | |||
675 | print_help(arg[i].u.child.child->args, prefixes, child); | |||
676 | drop_prefix(prefixes, first); | |||
677 | any = 1; | |||
678 | } | |||
679 | } | |||
680 | ||||
681 | static const char *prog_name(const char *prog) | |||
682 | { | |||
683 | const char *slash; | |||
684 | ||||
685 | slash = strrchr(prog, '/'); | |||
686 | if (slash) | |||
687 | prog = slash + 1; | |||
688 | if (strncmp(prog, "lt-", 3) == 0) | |||
689 | prog += 3; | |||
690 | ||||
691 | return prog; | |||
692 | } | |||
693 | ||||
694 | static int any_version(struct isl_arg *decl) | |||
695 | { | |||
696 | int i; | |||
697 | ||||
698 | for (i = 0; decl[i].type != isl_arg_end; ++i) { | |||
699 | switch (decl[i].type) { | |||
700 | case isl_arg_version: | |||
701 | return 1; | |||
702 | case isl_arg_child: | |||
703 | if (any_version(decl[i].u.child.child->args)) | |||
704 | return 1; | |||
705 | break; | |||
706 | default: | |||
707 | break; | |||
708 | } | |||
709 | } | |||
710 | ||||
711 | return 0; | |||
712 | } | |||
713 | ||||
714 | static void print_help_and_exit(struct isl_arg *arg, const char *prog, | |||
715 | void *opt) | |||
716 | { | |||
717 | int i; | |||
718 | struct isl_prefixes prefixes = { 0 }; | |||
719 | ||||
720 | printf("Usage: %s [OPTION...]", prog_name(prog)); | |||
721 | ||||
722 | for (i = 0; arg[i].type != isl_arg_end; ++i) | |||
723 | if (arg[i].type == isl_arg_arg) | |||
724 | printf(" %s", arg[i].argument_name); | |||
725 | ||||
726 | printf("\n\n"); | |||
727 | ||||
728 | print_help(arg, &prefixes, opt); | |||
729 | printf("\n"); | |||
730 | if (any_version(arg)) | |||
731 | printf(" -V, --version\n"); | |||
732 | print_bool_help(help_arg, NULL((void*)0), NULL((void*)0)); | |||
733 | ||||
734 | for (i = 0; arg[i].type != isl_arg_end; ++i) { | |||
735 | if (arg[i].type != isl_arg_footer) | |||
736 | continue; | |||
737 | wrap_msg(arg[i].help_msg, 0, 0); | |||
738 | printf("\n"); | |||
739 | } | |||
740 | ||||
741 | exit(0); | |||
742 | } | |||
743 | ||||
744 | static int match_long_name(struct isl_arg *decl, | |||
745 | const char *start, const char *end) | |||
746 | { | |||
747 | do { | |||
748 | if (end - start == strlen(decl->long_name) && | |||
749 | !strncmp(start, decl->long_name, end - start)) | |||
750 | return 1; | |||
751 | } while ((++decl)->type == isl_arg_alias); | |||
752 | ||||
753 | return 0; | |||
754 | } | |||
755 | ||||
756 | static const char *skip_dash_dash(struct isl_arg *decl, const char *arg) | |||
757 | { | |||
758 | if (!strncmp(arg, "--", 2)) | |||
759 | return arg + 2; | |||
760 | if ((decl->flags & ISL_ARG_SINGLE_DASH(1 << 0)) && arg[0] == '-') | |||
761 | return arg + 1; | |||
762 | return NULL((void*)0); | |||
763 | } | |||
764 | ||||
765 | static const char *skip_name(struct isl_arg *decl, const char *arg, | |||
766 | struct isl_prefixes *prefixes, int need_argument, int *has_argument) | |||
767 | { | |||
768 | const char *equal; | |||
769 | const char *name; | |||
770 | const char *end; | |||
771 | ||||
772 | if (arg[0] == '-' && arg[1] && arg[1] == decl->short_name) { | |||
773 | if (need_argument && !arg[2]) | |||
774 | return NULL((void*)0); | |||
775 | if (has_argument) | |||
776 | *has_argument = arg[2] != '\0'; | |||
777 | return arg + 2; | |||
778 | } | |||
779 | if (!decl->long_name) | |||
780 | return NULL((void*)0); | |||
781 | ||||
782 | name = skip_dash_dash(decl, arg); | |||
783 | if (!name) | |||
784 | return NULL((void*)0); | |||
785 | ||||
786 | equal = strchr(name, '='); | |||
787 | if (need_argument && !equal) | |||
788 | return NULL((void*)0); | |||
789 | ||||
790 | if (has_argument) | |||
791 | *has_argument = !!equal; | |||
792 | end = equal ? equal : name + strlen(name); | |||
793 | ||||
794 | name = skip_prefixes(name, prefixes, NULL((void*)0)); | |||
795 | ||||
796 | if (!match_long_name(decl, name, end)) | |||
797 | return NULL((void*)0); | |||
798 | ||||
799 | return equal ? equal + 1 : end; | |||
800 | } | |||
801 | ||||
802 | static int parse_choice_option(struct isl_arg *decl, char **arg, | |||
803 | struct isl_prefixes *prefixes, void *opt) | |||
804 | { | |||
805 | int i; | |||
806 | int has_argument; | |||
807 | const char *choice; | |||
808 | ||||
809 | choice = skip_name(decl, arg[0], prefixes, 0, &has_argument); | |||
810 | if (!choice) | |||
811 | return 0; | |||
812 | ||||
813 | if (!has_argument && (!arg[1] || arg[1][0] == '-')) { | |||
814 | unsigned u = decl->u.choice.default_selected; | |||
815 | if (decl->offset != (size_t) -1) | |||
816 | *(unsigned *)(((char *)opt) + decl->offset) = u; | |||
817 | if (decl->u.choice.set) | |||
818 | decl->u.choice.set(opt, u); | |||
819 | ||||
820 | return 1; | |||
821 | } | |||
822 | ||||
823 | if (!has_argument) | |||
824 | choice = arg[1]; | |||
825 | ||||
826 | for (i = 0; decl->u.choice.choice[i].name; ++i) { | |||
827 | unsigned u; | |||
828 | ||||
829 | if (strcmp(choice, decl->u.choice.choice[i].name)) | |||
830 | continue; | |||
831 | ||||
832 | u = decl->u.choice.choice[i].value; | |||
833 | if (decl->offset != (size_t) -1) | |||
834 | *(unsigned *)(((char *)opt) + decl->offset) = u; | |||
835 | if (decl->u.choice.set) | |||
836 | decl->u.choice.set(opt, u); | |||
837 | ||||
838 | return has_argument ? 1 : 2; | |||
839 | } | |||
840 | ||||
841 | return 0; | |||
842 | } | |||
843 | ||||
844 | static int set_flag(struct isl_arg *decl, unsigned *val, const char *flag, | |||
845 | size_t len) | |||
846 | { | |||
847 | int i; | |||
848 | ||||
849 | for (i = 0; decl->u.flags.flags[i].name; ++i) { | |||
850 | if (strncmp(flag, decl->u.flags.flags[i].name, len)) | |||
851 | continue; | |||
852 | ||||
853 | *val &= ~decl->u.flags.flags[i].mask; | |||
854 | *val |= decl->u.flags.flags[i].value; | |||
855 | ||||
856 | return 1; | |||
857 | } | |||
858 | ||||
859 | return 0; | |||
860 | } | |||
861 | ||||
862 | static int parse_flags_option(struct isl_arg *decl, char **arg, | |||
863 | struct isl_prefixes *prefixes, void *opt) | |||
864 | { | |||
865 | int has_argument; | |||
866 | const char *flags; | |||
867 | const char *comma; | |||
868 | unsigned val; | |||
869 | ||||
870 | flags = skip_name(decl, arg[0], prefixes, 0, &has_argument); | |||
871 | if (!flags) | |||
872 | return 0; | |||
873 | ||||
874 | if (!has_argument && !arg[1]) | |||
875 | return 0; | |||
876 | ||||
877 | if (!has_argument) | |||
878 | flags = arg[1]; | |||
879 | ||||
880 | val = 0; | |||
881 | ||||
882 | while ((comma = strchr(flags, ',')) != NULL((void*)0)) { | |||
883 | if (!set_flag(decl, &val, flags, comma - flags)) | |||
884 | return 0; | |||
885 | flags = comma + 1; | |||
886 | } | |||
887 | if (!set_flag(decl, &val, flags, strlen(flags))) | |||
888 | return 0; | |||
889 | ||||
890 | *(unsigned *)(((char *)opt) + decl->offset) = val; | |||
891 | ||||
892 | return has_argument ? 1 : 2; | |||
893 | } | |||
894 | ||||
895 | static int parse_bool_option(struct isl_arg *decl, char **arg, | |||
896 | struct isl_prefixes *prefixes, void *opt) | |||
897 | { | |||
898 | const char *name; | |||
899 | unsigned *p = (unsigned *)(((char *)opt) + decl->offset); | |||
900 | int next_prefix; | |||
901 | ||||
902 | if (skip_name(decl, arg[0], prefixes, 0, NULL((void*)0))) { | |||
903 | if ((decl->flags & ISL_ARG_BOOL_ARG(1 << 1)) && arg[1]) { | |||
904 | char *endptr; | |||
905 | int val = strtol(arg[1], &endptr, 0); | |||
906 | if (*endptr == '\0' && (val == 0 || val == 1)) { | |||
907 | if (decl->offset != (size_t) -1) | |||
908 | *p = val; | |||
909 | if (decl->u.b.set) | |||
910 | decl->u.b.set(opt, val); | |||
911 | return 2; | |||
912 | } | |||
913 | } | |||
914 | if (decl->offset != (size_t) -1) | |||
915 | *p = 1; | |||
916 | if (decl->u.b.set) | |||
917 | decl->u.b.set(opt, 1); | |||
918 | ||||
919 | return 1; | |||
920 | } | |||
921 | ||||
922 | if (!decl->long_name) | |||
923 | return 0; | |||
924 | ||||
925 | name = skip_dash_dash(decl, arg[0]); | |||
926 | if (!name) | |||
927 | return 0; | |||
928 | ||||
929 | next_prefix = 0; | |||
930 | name = skip_prefixes(name, prefixes, &next_prefix); | |||
931 | ||||
932 | if (strncmp(name, "no-", 3)) | |||
933 | return 0; | |||
934 | name += 3; | |||
935 | ||||
936 | name = skip_prefixes(name, prefixes, &next_prefix); | |||
937 | ||||
938 | if (match_long_name(decl, name, name + strlen(name))) { | |||
939 | if (decl->offset != (size_t) -1) | |||
940 | *p = 0; | |||
941 | if (decl->u.b.set) | |||
942 | decl->u.b.set(opt, 0); | |||
943 | ||||
944 | return 1; | |||
945 | } | |||
946 | ||||
947 | return 0; | |||
948 | } | |||
949 | ||||
950 | static int parse_str_option(struct isl_arg *decl, char **arg, | |||
951 | struct isl_prefixes *prefixes, void *opt) | |||
952 | { | |||
953 | int has_argument; | |||
954 | const char *s; | |||
955 | char **p = (char **)(((char *)opt) + decl->offset); | |||
956 | ||||
957 | s = skip_name(decl, arg[0], prefixes, 0, &has_argument); | |||
958 | if (!s) | |||
959 | return 0; | |||
960 | ||||
961 | if (has_argument) { | |||
962 | free(*p); | |||
963 | *p = strdup(s); | |||
964 | return 1; | |||
965 | } | |||
966 | ||||
967 | if (arg[1]) { | |||
968 | free(*p); | |||
969 | *p = strdup(arg[1]); | |||
970 | return 2; | |||
971 | } | |||
972 | ||||
973 | return 0; | |||
974 | } | |||
975 | ||||
976 | static int isl_arg_str_list_append(struct isl_arg *decl, void *opt, | |||
977 | const char *s) | |||
978 | { | |||
979 | int *n = (int *)(((char *) opt) + decl->u.str_list.offset_n); | |||
980 | char **list = *(char ***)(((char *) opt) + decl->offset); | |||
981 | ||||
982 | list = realloc(list, (*n + 1) * sizeof(char *)); | |||
983 | if (!list) | |||
984 | return -1; | |||
985 | *(char ***)(((char *) opt) + decl->offset) = list; | |||
986 | list[*n] = strdup(s); | |||
987 | (*n)++; | |||
988 | return 0; | |||
989 | } | |||
990 | ||||
991 | static int parse_str_list_option(struct isl_arg *decl, char **arg, | |||
992 | struct isl_prefixes *prefixes, void *opt) | |||
993 | { | |||
994 | int has_argument; | |||
995 | const char *s; | |||
996 | ||||
997 | s = skip_name(decl, arg[0], prefixes, 0, &has_argument); | |||
998 | if (!s) | |||
999 | return 0; | |||
1000 | ||||
1001 | if (has_argument) { | |||
1002 | isl_arg_str_list_append(decl, opt, s); | |||
1003 | return 1; | |||
1004 | } | |||
1005 | ||||
1006 | if (arg[1]) { | |||
1007 | isl_arg_str_list_append(decl, opt, arg[1]); | |||
1008 | return 2; | |||
1009 | } | |||
1010 | ||||
1011 | return 0; | |||
1012 | } | |||
1013 | ||||
1014 | static int parse_int_option(struct isl_arg *decl, char **arg, | |||
1015 | struct isl_prefixes *prefixes, void *opt) | |||
1016 | { | |||
1017 | int has_argument; | |||
1018 | const char *val; | |||
1019 | char *endptr; | |||
1020 | int *p = (int *)(((char *)opt) + decl->offset); | |||
1021 | ||||
1022 | val = skip_name(decl, arg[0], prefixes, 0, &has_argument); | |||
1023 | if (!val) | |||
1024 | return 0; | |||
1025 | ||||
1026 | if (has_argument) { | |||
1027 | *p = atoi(val); | |||
1028 | return 1; | |||
1029 | } | |||
1030 | ||||
1031 | if (arg[1]) { | |||
1032 | int i = strtol(arg[1], &endptr, 0); | |||
1033 | if (*endptr == '\0') { | |||
1034 | *p = i; | |||
1035 | return 2; | |||
1036 | } | |||
1037 | } | |||
1038 | ||||
1039 | return 0; | |||
1040 | } | |||
1041 | ||||
1042 | static int parse_long_option(struct isl_arg *decl, char **arg, | |||
1043 | struct isl_prefixes *prefixes, void *opt) | |||
1044 | { | |||
1045 | int has_argument; | |||
1046 | const char *val; | |||
1047 | char *endptr; | |||
1048 | long *p = (long *)(((char *)opt) + decl->offset); | |||
1049 | ||||
1050 | val = skip_name(decl, arg[0], prefixes, 0, &has_argument); | |||
1051 | if (!val) | |||
1052 | return 0; | |||
1053 | ||||
1054 | if (has_argument) { | |||
1055 | long l = strtol(val, NULL((void*)0), 0); | |||
1056 | *p = l; | |||
1057 | if (decl->u.l.set) | |||
1058 | decl->u.l.set(opt, l); | |||
1059 | return 1; | |||
1060 | } | |||
1061 | ||||
1062 | if (arg[1]) { | |||
1063 | long l = strtol(arg[1], &endptr, 0); | |||
1064 | if (*endptr == '\0') { | |||
1065 | *p = l; | |||
1066 | if (decl->u.l.set) | |||
1067 | decl->u.l.set(opt, l); | |||
1068 | return 2; | |||
1069 | } | |||
1070 | } | |||
1071 | ||||
1072 | if (decl->u.l.default_value != decl->u.l.default_selected) { | |||
1073 | *p = decl->u.l.default_selected; | |||
1074 | if (decl->u.l.set) | |||
1075 | decl->u.l.set(opt, decl->u.l.default_selected); | |||
1076 | return 1; | |||
1077 | } | |||
1078 | ||||
1079 | return 0; | |||
1080 | } | |||
1081 | ||||
1082 | static int parse_ulong_option(struct isl_arg *decl, char **arg, | |||
1083 | struct isl_prefixes *prefixes, void *opt) | |||
1084 | { | |||
1085 | int has_argument; | |||
1086 | const char *val; | |||
1087 | char *endptr; | |||
1088 | unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset); | |||
1089 | ||||
1090 | val = skip_name(decl, arg[0], prefixes, 0, &has_argument); | |||
1091 | if (!val) | |||
1092 | return 0; | |||
1093 | ||||
1094 | if (has_argument) { | |||
1095 | *p = strtoul(val, NULL((void*)0), 0); | |||
1096 | return 1; | |||
1097 | } | |||
1098 | ||||
1099 | if (arg[1]) { | |||
1100 | unsigned long ul = strtoul(arg[1], &endptr, 0); | |||
1101 | if (*endptr == '\0') { | |||
1102 | *p = ul; | |||
1103 | return 2; | |||
1104 | } | |||
1105 | } | |||
1106 | ||||
1107 | return 0; | |||
1108 | } | |||
1109 | ||||
1110 | static int parse_option(struct isl_arg *decl, char **arg, | |||
1111 | struct isl_prefixes *prefixes, void *opt); | |||
1112 | ||||
1113 | static int parse_child_option(struct isl_arg *decl, char **arg, | |||
1114 | struct isl_prefixes *prefixes, void *opt) | |||
1115 | { | |||
1116 | void *child; | |||
1117 | int first, parsed; | |||
1118 | ||||
1119 | if (decl->offset == (size_t) -1) | |||
1120 | child = opt; | |||
1121 | else | |||
1122 | child = *(void **)(((char *)opt) + decl->offset); | |||
1123 | ||||
1124 | first = add_prefix(prefixes, decl->long_name); | |||
1125 | parsed = parse_option(decl->u.child.child->args, arg, prefixes, child); | |||
1126 | drop_prefix(prefixes, first); | |||
1127 | ||||
1128 | return parsed; | |||
1129 | } | |||
1130 | ||||
1131 | static int parse_option(struct isl_arg *decl, char **arg, | |||
1132 | struct isl_prefixes *prefixes, void *opt) | |||
1133 | { | |||
1134 | int i; | |||
1135 | ||||
1136 | for (i = 0; decl[i].type != isl_arg_end; ++i) { | |||
1137 | int parsed = 0; | |||
1138 | switch (decl[i].type) { | |||
1139 | case isl_arg_choice: | |||
1140 | parsed = parse_choice_option(&decl[i], arg, | |||
1141 | prefixes, opt); | |||
1142 | break; | |||
1143 | case isl_arg_flags: | |||
1144 | parsed = parse_flags_option(&decl[i], arg, | |||
1145 | prefixes, opt); | |||
1146 | break; | |||
1147 | case isl_arg_int: | |||
1148 | parsed = parse_int_option(&decl[i], arg, prefixes, opt); | |||
1149 | break; | |||
1150 | case isl_arg_long: | |||
1151 | parsed = parse_long_option(&decl[i], arg, | |||
1152 | prefixes, opt); | |||
1153 | break; | |||
1154 | case isl_arg_ulong: | |||
1155 | parsed = parse_ulong_option(&decl[i], arg, | |||
1156 | prefixes, opt); | |||
1157 | break; | |||
1158 | case isl_arg_bool: | |||
1159 | parsed = parse_bool_option(&decl[i], arg, | |||
1160 | prefixes, opt); | |||
1161 | break; | |||
1162 | case isl_arg_str: | |||
1163 | parsed = parse_str_option(&decl[i], arg, prefixes, opt); | |||
1164 | break; | |||
1165 | case isl_arg_str_list: | |||
1166 | parsed = parse_str_list_option(&decl[i], arg, prefixes, | |||
1167 | opt); | |||
1168 | break; | |||
1169 | case isl_arg_child: | |||
1170 | parsed = parse_child_option(&decl[i], arg, | |||
1171 | prefixes, opt); | |||
1172 | break; | |||
1173 | case isl_arg_alias: | |||
1174 | case isl_arg_arg: | |||
1175 | case isl_arg_footer: | |||
1176 | case isl_arg_user: | |||
1177 | case isl_arg_version: | |||
1178 | case isl_arg_end: | |||
1179 | break; | |||
1180 | } | |||
1181 | if (parsed) | |||
1182 | return parsed; | |||
1183 | } | |||
1184 | ||||
1185 | return 0; | |||
1186 | } | |||
1187 | ||||
1188 | static void print_version(struct isl_arg *decl) | |||
1189 | { | |||
1190 | int i; | |||
1191 | ||||
1192 | for (i = 0; decl[i].type != isl_arg_end; ++i) { | |||
1193 | switch (decl[i].type) { | |||
1194 | case isl_arg_version: | |||
1195 | decl[i].u.version.print_version(); | |||
1196 | break; | |||
1197 | case isl_arg_child: | |||
1198 | print_version(decl[i].u.child.child->args); | |||
1199 | break; | |||
1200 | default: | |||
1201 | break; | |||
1202 | } | |||
1203 | } | |||
1204 | } | |||
1205 | ||||
1206 | static void print_version_and_exit(struct isl_arg *decl) | |||
1207 | { | |||
1208 | print_version(decl); | |||
1209 | ||||
1210 | exit(0); | |||
1211 | } | |||
1212 | ||||
1213 | static int drop_argument(int argc, char **argv, int drop, int n) | |||
1214 | { | |||
1215 | for (; drop + n < argc; ++drop) | |||
1216 | argv[drop] = argv[drop + n]; | |||
1217 | ||||
1218 | return argc - n; | |||
1219 | } | |||
1220 | ||||
1221 | static int n_arg(struct isl_arg *arg) | |||
1222 | { | |||
1223 | int i; | |||
1224 | int n_arg = 0; | |||
1225 | ||||
1226 | for (i = 0; arg[i].type != isl_arg_end; ++i) | |||
1227 | if (arg[i].type == isl_arg_arg) | |||
1228 | n_arg++; | |||
1229 | ||||
1230 | return n_arg; | |||
1231 | } | |||
1232 | ||||
1233 | static int next_arg(struct isl_arg *arg, int a) | |||
1234 | { | |||
1235 | for (++a; arg[a].type != isl_arg_end; ++a) | |||
1236 | if (arg[a].type == isl_arg_arg) | |||
1237 | return a; | |||
1238 | ||||
1239 | return -1; | |||
1240 | } | |||
1241 | ||||
1242 | /* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is | |||
1243 | * equal to "--help" and if so call print_help_and_exit. | |||
1244 | */ | |||
1245 | static void check_help(struct isl_args *args, char *arg, char *prog, void *opt, | |||
1246 | unsigned flags) | |||
1247 | { | |||
1248 | if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP)(!!((flags) & ((1 << 1))))) | |||
1249 | return; | |||
1250 | ||||
1251 | if (strcmp(arg, "--help") == 0) | |||
1252 | print_help_and_exit(args->args, prog, opt); | |||
1253 | } | |||
1254 | ||||
1255 | int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt, | |||
1256 | unsigned flags) | |||
1257 | { | |||
1258 | int a = -1; | |||
1259 | int skip = 0; | |||
1260 | int i; | |||
1261 | int n; | |||
1262 | struct isl_prefixes prefixes = { 0 }; | |||
1263 | ||||
1264 | n = n_arg(args->args); | |||
1265 | ||||
1266 | for (i = 1; i < argc; ++i) { | |||
| ||||
1267 | if ((strcmp(argv[i], "--version") == 0 || | |||
1268 | strcmp(argv[i], "-V") == 0) && any_version(args->args)) | |||
1269 | print_version_and_exit(args->args); | |||
1270 | } | |||
1271 | ||||
1272 | while (argc > 1 + skip) { | |||
1273 | int parsed; | |||
1274 | if (argv[1 + skip][0] != '-') { | |||
1275 | a = next_arg(args->args, a); | |||
1276 | if (a >= 0) { | |||
1277 | char **p; | |||
1278 | p = (char **)(((char *)opt)+args->args[a].offset); | |||
1279 | free(*p); | |||
1280 | *p = strdup(argv[1 + skip]); | |||
1281 | argc = drop_argument(argc, argv, 1 + skip, 1); | |||
1282 | --n; | |||
1283 | } else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)(!!((flags) & ((1 << 0))))) { | |||
1284 | fprintf(stderrstderr, "%s: extra argument: %s\n", | |||
1285 | prog_name(argv[0]), argv[1 + skip]); | |||
1286 | exit(-1); | |||
1287 | } else | |||
1288 | ++skip; | |||
1289 | continue; | |||
1290 | } | |||
1291 | check_help(args, argv[1 + skip], argv[0], opt, flags); | |||
1292 | parsed = parse_option(args->args, &argv[1 + skip], | |||
1293 | &prefixes, opt); | |||
1294 | if (parsed) | |||
1295 | argc = drop_argument(argc, argv, 1 + skip, parsed); | |||
1296 | else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)(!!((flags) & ((1 << 0))))) { | |||
1297 | fprintf(stderrstderr, "%s: unrecognized option: %s\n", | |||
1298 | prog_name(argv[0]), argv[1 + skip]); | |||
1299 | exit(-1); | |||
1300 | } else | |||
1301 | ++skip; | |||
1302 | } | |||
1303 | ||||
1304 | if (n > 0) { | |||
1305 | fprintf(stderrstderr, "%s: expecting %d more argument(s)\n", | |||
1306 | prog_name(argv[0]), n); | |||
1307 | exit(-1); | |||
1308 | } | |||
1309 | ||||
1310 | return argc; | |||
1311 | } |