1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #ifdef HAVE_CONFIG_H
22: #include <config.h>
23: #endif
24:
25:
26: #ifndef __GNUC__
27: # if HAVE_ALLOCA_H || defined _LIBC
28: # include <alloca.h>
29: # else
30: # ifdef _AIX
31: #pragma alloca
32: # else
33: # ifndef alloca
34: char *alloca ();
35: # endif
36: # endif
37: # endif
38: #endif
39:
40: #include <stdlib.h>
41: #include <string.h>
42: #include <unistd.h>
43: #include <limits.h>
44: #include <getopt.h>
45: #include <getopt_int.h>
46:
47: #ifndef _
48:
49:
50: # if defined HAVE_LIBINTL_H || defined _LIBC
51: # include <libintl.h>
52: # ifdef _LIBC
53: # undef dgettext
54: # define dgettext(domain, msgid) \
55: INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
56: # endif
57: # else
58: # define dgettext(domain, msgid) (msgid)
59: # define gettext(msgid) (msgid)
60: # endif
61: #endif
62: #ifndef N_
63: # define N_(msgid) (msgid)
64: #endif
65:
66: #include "argp.h"
67: #include "argp-namefrob.h"
68:
69:
70: #define KEY_END (-1)
71: #define KEY_ARG 1
72: #define KEY_ERR '?'
73:
74:
75:
76: #define QUOTE "--"
77:
78:
79: #define GROUP_BITS CHAR_BIT
80:
81:
82: #define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
83: #define USER_MASK ((1 << USER_BITS) - 1)
84:
85:
86: #define EBADKEY ARGP_ERR_UNKNOWN
87: ^L
88:
89:
90:
91:
92:
93:
94: static volatile int _argp_hang;
95:
96: #define OPT_PROGNAME -2
97: #define OPT_USAGE -3
98: #define OPT_HANG -4
99:
100: static const struct argp_option argp_default_options[] =
101: {
102: {"help", '?', 0, 0, N_("Give this help list"), -1},
103: {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message")},
104: {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")},
105: {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
106: N_("Hang for SECS seconds (default 3600)")},
107: {0, 0}
108: };
109:
110: static error_t
111: argp_default_parser (int key, char *arg, struct argp_state *state)
112: {
113: switch (key)
114: {
115: case '?':
116: __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
117: break;
118: case OPT_USAGE:
119: __argp_state_help (state, state->out_stream,
120: ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
121: break;
122:
123: case OPT_PROGNAME:
124: #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME
125: program_invocation_name = arg;
126: #endif
127:
128:
129:
130:
131:
132: state->name = strrchr (arg, '/');
133: if (state->name)
134: state->name++;
135: else
136: state->name = arg;
137:
138: #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
139: program_invocation_short_name = state->name;
140: #endif
141:
142: if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
143: == ARGP_PARSE_ARGV0)
144:
145: state->argv[0] = arg;
146:
147: break;
148:
149: case OPT_HANG:
150: _argp_hang = atoi (arg ? arg : "3600");
151: while (_argp_hang-- > 0)
152: __sleep (1);
153: break;
154:
155: default:
156: return EBADKEY;
157: }
158: return 0;
159: }
160:
161: static const struct argp argp_default_argp =
162: {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"};
163:
164: ^L
165: static const struct argp_option argp_version_options[] =
166: {
167: {"version", 'V', 0, 0, N_("Print program version"), -1},
168: {0, 0}
169: };
170:
171: static error_t
172: argp_version_parser (int key, char *arg, struct argp_state *state)
173: {
174: switch (key)
175: {
176: case 'V':
177: if (argp_program_version_hook)
178: (*argp_program_version_hook) (state->out_stream, state);
179: else if (argp_program_version)
180: fprintf (state->out_stream, "%s\n", argp_program_version);
181: else
182: __argp_error (state, dgettext (state->root_argp->argp_domain,
183: "(PROGRAM ERROR) No version known!?"));
184: if (! (state->flags & ARGP_NO_EXIT))
185: exit (0);
186: break;
187: default:
188: return EBADKEY;
189: }
190: return 0;
191: }
192:
193: static const struct argp argp_version_argp =
194: {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"};
195: ^L
196:
197:
198:
199: static int
200: find_long_option (struct option *long_options, const char *name)
201: {
202: struct option *l = long_options;
203: while (l->name != NULL)
204: if (name != NULL && strcmp (l->name, name) == 0)
205: return l - long_options;
206: else
207: l++;
208: if (name == NULL)
209: return l - long_options;
210: else
211: return -1;
212: }
213:
214: ^L
215:
216:
217:
218: struct group
219: {
220:
221: argp_parser_t parser;
222:
223:
224: const struct argp *argp;
225:
226:
227:
228:
229: char *short_end;
230:
231:
232: unsigned args_processed;
233:
234:
235: struct group *parent;
236: unsigned parent_index;
237:
238:
239:
240: void *input, **child_inputs;
241: void *hook;
242: };
243:
244:
245:
246:
247: static error_t
248: group_parse (struct group *group, struct argp_state *state, int key, char *arg)
249: {
250: if (group->parser)
251: {
252: error_t err;
253: state->hook = group->hook;
254: state->input = group->input;
255: state->child_inputs = group->child_inputs;
256: state->arg_num = group->args_processed;
257: err = (*group->parser)(key, arg, state);
258: group->hook = state->hook;
259: return err;
260: }
261: else
262: return EBADKEY;
263: }
264: ^L
265: struct parser
266: {
267: const struct argp *argp;
268:
269:
270:
271: char *short_opts;
272:
273:
274: struct option *long_opts;
275:
276: struct _getopt_data opt_data;
277:
278:
279: struct group *groups;
280:
281: struct group *egroup;
282:
283: void **child_inputs;
284:
285:
286:
287:
288:
289: int try_getopt;
290:
291:
292: struct argp_state state;
293:
294:
295: void *storage;
296: };
297: ^L
298:
299:
300: struct parser_convert_state
301: {
302: struct parser *parser;
303: char *short_end;
304: struct option *long_end;
305: void **child_inputs_end;
306: };
307:
308:
309:
310:
311:
312: static struct group *
313: convert_options (const struct argp *argp,
314: struct group *parent, unsigned parent_index,
315: struct group *group, struct parser_convert_state *cvt)
316: {
317:
318: const struct argp_option *real = argp->options;
319: const struct argp_child *children = argp->children;
320:
321: if (real || argp->parser)
322: {
323: const struct argp_option *opt;
324:
325: if (real)
326: for (opt = real; !__option_is_end (opt); opt++)
327: {
328: if (! (opt->flags & OPTION_ALIAS))
329:
330: real = opt;
331:
332: if (! (real->flags & OPTION_DOC))
333:
334: {
335: if (__option_is_short (opt))
336:
337: {
338: *cvt->short_end++ = opt->key;
339: if (real->arg)
340: {
341: *cvt->short_end++ = ':';
342: if (real->flags & OPTION_ARG_OPTIONAL)
343: *cvt->short_end++ = ':';
344: }
345: *cvt->short_end = '\0';
346: }
347:
348: if (opt->name
349: && find_long_option (cvt->parser->long_opts, opt->name) < 0)
350:
351: {
352: cvt->long_end->name = opt->name;
353: cvt->long_end->has_arg =
354: (real->arg
355: ? (real->flags & OPTION_ARG_OPTIONAL
356: ? optional_argument
357: : required_argument)
358: : no_argument);
359: cvt->long_end->flag = 0;
360:
361:
362:
363:
364:
365:
366: cvt->long_end->val =
367: ((opt->key | real->key) & USER_MASK)
368: + (((group - cvt->parser->groups) + 1) << USER_BITS);
369:
370:
371: (++cvt->long_end)->name = NULL;
372: }
373: }
374: }
375:
376: group->parser = argp->parser;
377: group->argp = argp;
378: group->short_end = cvt->short_end;
379: group->args_processed = 0;
380: group->parent = parent;
381: group->parent_index = parent_index;
382: group->input = 0;
383: group->hook = 0;
384: group->child_inputs = 0;
385:
386: if (children)
387:
388:
389: {
390: unsigned num_children = 0;
391: while (children[num_children].argp)
392: num_children++;
393: group->child_inputs = cvt->child_inputs_end;
394: cvt->child_inputs_end += num_children;
395: }
396:
397: parent = group++;
398: }
399: else
400: parent = 0;
401:
402: if (children)
403: {
404: unsigned index = 0;
405: while (children->argp)
406: group =
407: convert_options (children++->argp, parent, index++, group, cvt);
408: }
409:
410: return group;
411: }
412:
413:
414: static void
415: parser_convert (struct parser *parser, const struct argp *argp, int flags)
416: {
417: struct parser_convert_state cvt;
418:
419: cvt.parser = parser;
420: cvt.short_end = parser->short_opts;
421: cvt.long_end = parser->long_opts;
422: cvt.child_inputs_end = parser->child_inputs;
423:
424: if (flags & ARGP_IN_ORDER)
425: *cvt.short_end++ = '-';
426: else if (flags & ARGP_NO_ARGS)
427: *cvt.short_end++ = '+';
428: *cvt.short_end = '\0';
429:
430: cvt.long_end->name = NULL;
431:
432: parser->argp = argp;
433:
434: if (argp)
435: parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
436: else
437: parser->egroup = parser->groups;
438: }
439: ^L
440:
441: struct parser_sizes
442: {
443: size_t short_len;
444: size_t long_len;
445: size_t num_groups;
446: size_t num_child_inputs;
447: };
448:
449:
450:
451:
452:
453: static void
454: calc_sizes (const struct argp *argp, struct parser_sizes *szs)
455: {
456: const struct argp_child *child = argp->children;
457: const struct argp_option *opt = argp->options;
458:
459: if (opt || argp->parser)
460: {
461: szs->num_groups++;
462: if (opt)
463: {
464: int num_opts = 0;
465: while (!__option_is_end (opt++))
466: num_opts++;
467: szs->short_len += num_opts * 3;
468: szs->long_len += num_opts;
469: }
470: }
471:
472: if (child)
473: while (child->argp)
474: {
475: calc_sizes ((child++)->argp, szs);
476: szs->num_child_inputs++;
477: }
478: }
479:
480:
481: static error_t
482: parser_init (struct parser *parser, const struct argp *argp,
483: int argc, char **argv, int flags, void *input)
484: {
485: error_t err = 0;
486: struct group *group;
487: struct parser_sizes szs;
488: struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
489:
490: szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
491: szs.long_len = 0;
492: szs.num_groups = 0;
493: szs.num_child_inputs = 0;
494:
495: if (argp)
496: calc_sizes (argp, &szs);
497:
498:
499: #define GLEN (szs.num_groups + 1) * sizeof (struct group)
500: #define CLEN (szs.num_child_inputs * sizeof (void *))
501: #define LLEN ((szs.long_len + 1) * sizeof (struct option))
502: #define SLEN (szs.short_len + 1)
503:
504: parser->storage = malloc (GLEN + CLEN + LLEN + SLEN);
505: if (! parser->storage)
506: return ENOMEM;
507:
508: parser->groups = parser->storage;
509: parser->child_inputs = parser->storage + GLEN;
510: parser->long_opts = parser->storage + GLEN + CLEN;
511: parser->short_opts = parser->storage + GLEN + CLEN + LLEN;
512: parser->opt_data = opt_data;
513:
514: memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
515: parser_convert (parser, argp, flags);
516:
517: memset (&parser->state, 0, sizeof (struct argp_state));
518: parser->state.root_argp = parser->argp;
519: parser->state.argc = argc;
520: parser->state.argv = argv;
521: parser->state.flags = flags;
522: parser->state.err_stream = stderr;
523: parser->state.out_stream = stdout;
524: parser->state.next = 0;
525: parser->state.pstate = parser;
526:
527: parser->try_getopt = 1;
528:
529:
530:
531: if (parser->groups < parser->egroup)
532: parser->groups->input = input;
533: for (group = parser->groups;
534: group < parser->egroup && (!err || err == EBADKEY);
535: group++)
536: {
537: if (group->parent)
538:
539: group->input = group->parent->child_inputs[group->parent_index];
540:
541: if (!group->parser
542: && group->argp->children && group->argp->children->argp)
543:
544:
545:
546: group->child_inputs[0] = group->input;
547:
548: err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);
549: }
550: if (err == EBADKEY)
551: err = 0;
552:
553: if (err)
554: return err;
555:
556: if (parser->state.flags & ARGP_NO_ERRS)
557: {
558: parser->opt_data.opterr = 0;
559: