1 /* [argparse.c wk 17.06.97] Argument Parser for option handling
2 * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
3 * Copyright (C) 1997-2001, 2006-2008, 2013-2015 Werner Koch
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify it
8 * under the terms of either
10 * - the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at
12 * your option) any later version.
16 * - the GNU General Public License as published by the Free
17 * Software Foundation; either version 2 of the License, or (at
18 * your option) any later version.
20 * or both in parallel, as here.
22 * GnuPG is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
27 * You should have received a copies of the GNU General Public License
28 * and the GNU Lesser General Public License along with this program;
29 * if not, see <http://www.gnu.org/licenses/>.
32 /* This file may be used as part of GnuPG or standalone. A GnuPG
33 build is detected by the presence of the macro GNUPG_MAJOR_VERSION.
34 Some feature are only availalbe in the GnuPG build mode.
49 #ifdef GNUPG_MAJOR_VERSION
51 # include "common-defs.h"
53 # include "mischelp.h"
54 # include "stringhelp.h"
56 # include "utf8conv.h"
57 #endif /*GNUPG_MAJOR_VERSION*/
61 /* GnuPG uses GPLv3+ but a standalone version of this defaults to
62 GPLv2+ because that is the license of this file. Change this if
63 you include it in a program which uses GPLv3. If you don't want to
64 set a a copyright string for your usage() you may also hardcode it
66 #ifndef GNUPG_MAJOR_VERSION
68 # define ARGPARSE_GPL_VERSION 2
69 # define ARGPARSE_CRIGHT_STR "Copyright (C) YEAR NAME"
71 #else /* Used by GnuPG */
73 # define ARGPARSE_GPL_VERSION 3
74 # define ARGPARSE_CRIGHT_STR "Copyright (C) 2015 Free Software Foundation, Inc."
76 #endif /*GNUPG_MAJOR_VERSION*/
78 /* Replacements for standalone builds. */
79 #ifndef GNUPG_MAJOR_VERSION
84 # define DIM(v) (sizeof(v)/sizeof((v)[0]))
86 # define xtrymalloc(a) malloc ((a))
87 # define xtryrealloc(a,b) realloc ((a), (b))
88 # define xtrystrdup(a) strdup ((a))
89 # define xfree(a) free ((a))
90 # define log_error my_log_error
91 # define log_bug my_log_bug
92 # define trim_spaces(a) my_trim_spaces ((a))
93 # define map_static_macro_string(a) (a)
94 #endif /*!GNUPG_MAJOR_VERSION*/
97 #define ARGPARSE_STR(v) #v
98 #define ARGPARSE_STR2(v) ARGPARSE_STR(v)
101 /* Replacements for standalone builds. */
102 #ifndef GNUPG_MAJOR_VERSION
104 my_log_error (const char *fmt, ...)
108 va_start (arg_ptr, fmt);
109 fprintf (stderr, "%s: ", strusage (11));
110 vfprintf (stderr, fmt, arg_ptr);
115 my_log_bug (const char *fmt, ...)
119 va_start (arg_ptr, fmt);
120 fprintf (stderr, "%s: Ohhhh jeeee: ", strusage (11));
121 vfprintf (stderr, fmt, arg_ptr);
126 /* Return true if the native charset is utf-8. */
128 is_native_utf8 (void)
134 my_trim_spaces (char *str)
136 char *string, *p, *mark;
139 /* Find first non space character. */
140 for (p=string; *p && isspace (*(unsigned char*)p) ; p++)
142 /* Move characters. */
143 for ((mark = NULL); (*string = *p); string++, p++)
144 if (isspace (*(unsigned char*)p))
152 *mark = '\0' ; /* Remove trailing spaces. */
157 #endif /*!GNUPG_MAJOR_VERSION*/
161 /*********************************
163 * #include "argparse.h"
166 * char *argc; pointer to argc (value subject to change)
167 * char ***argv; pointer to argv (value subject to change)
168 * unsigned flags; Global flags (DO NOT CHANGE)
169 * int err; print error about last option
170 * 1 = warning, 2 = abort
171 * int r_opt; return option
172 * int r_type; type of return value (0 = no argument found)
183 * } internal; DO NOT CHANGE
188 * const char *long_opt;
192 * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
195 * This is my replacement for getopt(). See the example for a typical usage.
197 * Bit 0 : Do not remove options form argv
198 * Bit 1 : Do not stop at last option but return other args
199 * with r_opt set to -1.
200 * Bit 2 : Assume options and real args are mixed.
201 * Bit 3 : Do not use -- to stop option processing.
202 * Bit 4 : Do not skip the first arg.
203 * Bit 5 : allow usage of long option with only one dash
204 * Bit 6 : ignore --version
205 * all other bits must be set to zero, this value is modified by the
206 * function, so assume this is write only.
207 * Local flags (for each option):
208 * Bit 2-0 : 0 = does not take an argument
209 * 1 = takes int argument
210 * 2 = takes string argument
211 * 3 = takes long argument
212 * 4 = takes ulong argument
213 * Bit 3 : argument is optional (r_type will the be set to 0)
214 * Bit 4 : allow 0x etc. prefixed values.
215 * Bit 6 : Ignore this option
216 * Bit 7 : This is a command and not an option
217 * You stop the option processing by setting opts to NULL, the function will
220 * Returns the args.r_opt or 0 if ready
221 * r_opt may be -2/-7 to indicate an unknown option/command.
225 * You do not need to process the options 'h', '--help' or '--version'
226 * because this function includes standard help processing; but if you
227 * specify '-h', '--help' or '--version' you have to do it yourself.
228 * The option '--' stops argument processing; if bit 1 is set the function
229 * continues to return normal arguments.
230 * To process float args or unsigned args you must use a string args and do
231 * the conversion yourself.
234 * ARGPARSE_OPTS opts[] = {
235 * { 'v', "verbose", 0 },
236 * { 'd', "debug", 0 },
237 * { 'o', "output", 2 },
238 * { 'c', "cross-ref", 2|8 },
239 * { 'm', "my-option", 1|8 },
240 * { 300, "ignored-long-option, ARGPARSE_OP_IGNORE},
241 * { 500, "have-no-short-option-for-this-long-option", 0 },
243 * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
245 * while( ArgParse( &pargs, &opts) ) {
246 * switch( pargs.r_opt ) {
247 * case 'v': opt.verbose++; break;
248 * case 'd': opt.debug++; break;
249 * case 'o': opt.outfile = pargs.r.ret_str; break;
250 * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
251 * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
252 * case 500: opt.a_long_one++; break
253 * default : pargs.err = 1; break; -- force warning output --
257 * log_fatal( "Too many args");
261 typedef struct alias_def_s *ALIAS_DEF;
264 char *name; /* malloced buffer with name, \0, value */
265 const char *value; /* ptr into name */
269 /* Object to store the names for the --ignore-invalid-option option.
270 This is a simple linked list. */
271 typedef struct iio_item_def_s *IIO_ITEM_DEF;
272 struct iio_item_def_s
275 char name[1]; /* String with the long option name. */
278 static const char *(*strusage_handler)( int ) = NULL;
279 static int (*custom_outfnc) (int, const char *);
281 static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
282 static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
283 static void show_version(void);
284 static int writestrings (int is_error, const char *string, ...)
286 __attribute__ ((sentinel(0)))
292 argparse_register_outfnc (int (*fnc)(int, const char *))
298 /* Write STRING and all following const char * arguments either to
299 stdout or, if IS_ERROR is set, to stderr. The list of strings must
300 be terminated by a NULL. */
302 writestrings (int is_error, const char *string, ...)
311 va_start (arg_ptr, string);
315 custom_outfnc (is_error? 2:1, s);
317 fputs (s, is_error? stderr : stdout);
320 while ((s = va_arg (arg_ptr, const char *)));
328 flushstrings (int is_error)
331 custom_outfnc (is_error? 2:1, NULL);
333 fflush (is_error? stderr : stdout);
338 initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
340 if( !(arg->flags & (1<<15)) )
342 /* Initialize this instance. */
343 arg->internal.idx = 0;
344 arg->internal.last = NULL;
345 arg->internal.inarg = 0;
346 arg->internal.stopped = 0;
347 arg->internal.aliases = NULL;
348 arg->internal.cur_alias = NULL;
349 arg->internal.iio_list = NULL;
351 arg->flags |= 1<<15; /* Mark as initialized. */
352 if ( *arg->argc < 0 )
353 log_bug ("invalid argument for arg_parse\n");
359 /* Last option was erroneous. */
364 if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
365 s = _("argument not expected");
366 else if ( arg->r_opt == ARGPARSE_READ_ERROR )
368 else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG )
369 s = _("keyword too long");
370 else if ( arg->r_opt == ARGPARSE_MISSING_ARG )
371 s = _("missing argument");
372 else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
373 s = _("invalid argument");
374 else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
375 s = _("invalid command");
376 else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS )
377 s = _("invalid alias definition");
378 else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
379 s = _("out of core");
381 s = _("invalid option");
382 log_error ("%s:%u: %s\n", filename, *lineno, s);
386 s = arg->internal.last? arg->internal.last:"[??]";
388 if ( arg->r_opt == ARGPARSE_MISSING_ARG )
389 log_error (_("missing argument for option \"%.50s\"\n"), s);
390 else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
391 log_error (_("invalid argument for option \"%.50s\"\n"), s);
392 else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
393 log_error (_("option \"%.50s\" does not expect an argument\n"), s);
394 else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
395 log_error (_("invalid command \"%.50s\"\n"), s);
396 else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION )
397 log_error (_("option \"%.50s\" is ambiguous\n"), s);
398 else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND )
399 log_error (_("command \"%.50s\" is ambiguous\n"),s );
400 else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
401 log_error ("%s\n", _("out of core\n"));
403 log_error (_("invalid option \"%.50s\"\n"), s);
405 if (arg->err != ARGPARSE_PRINT_WARNING)
410 /* Zero out the return value union. */
411 arg->r.ret_str = NULL;
417 store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
419 /* TODO: replace this dummy function with a rea one
420 * and fix the probelms IRIX has with (ALIAS_DEV)arg..
427 ALIAS_DEF a = xmalloc( sizeof *a );
430 a->next = (ALIAS_DEF)arg->internal.aliases;
431 (ALIAS_DEF)arg->internal.aliases = a;
436 /* Return true if KEYWORD is in the ignore-invalid-option list. */
438 ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword)
440 IIO_ITEM_DEF item = arg->internal.iio_list;
442 for (; item; item = item->next)
443 if (!strcmp (item->name, keyword))
449 /* Add the keywords up to the next LF to the list of to be ignored
450 options. After returning FP will either be at EOF or the next
451 character read wll be the first of a new line. The function
452 returns 0 on success or true on malloc failure. */
454 ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp)
461 enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS;
477 if (!isascii (c) || !isspace(c))
491 else if (namelen < DIM(name)-1)
507 if (!ignore_invalid_option_p (arg, name))
509 item = xtrymalloc (sizeof *item + namelen);
512 strcpy (item->name, name);
513 item->next = (IIO_ITEM_DEF)arg->internal.iio_list;
514 arg->internal.iio_list = item;
524 /* Clear the entire ignore-invalid-option list. */
526 ignore_invalid_option_clear (ARGPARSE_ARGS *arg)
528 IIO_ITEM_DEF item, tmpitem;
530 for (item = arg->internal.iio_list; item; item = tmpitem)
532 tmpitem = item->next;
535 arg->internal.iio_list = NULL;
541 * Get options from a file.
542 * Lines starting with '#' are comment lines.
543 * Syntax is simply a keyword and the argument.
544 * Valid keywords are all keywords from the long_opt list without
545 * the leading dashes. The special keywords "help", "warranty" and "version"
546 * are not valid here.
547 * The special keyword "alias" may be used to store alias definitions,
548 * which are later expanded like long options.
550 * ignore-invalid-option OPTIONNAMEs
551 * is recognized and updates a list of option which should be ignored if they
553 * Caller must free returned strings.
554 * If called with FP set to NULL command line args are parse instead.
556 * Q: Should we allow the syntax
558 * and accept for boolean options a value of 1/0, yes/no or true/false?
559 * Note: Abbreviation of options is here not allowed.
562 optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
563 ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
572 if (!fp) /* Divert to to arg_parse() in this case. */
573 return arg_parse (arg, opts);
575 initialize (arg, filename, lineno);
577 /* Find the next keyword. */
582 if (c == '\n' || c== EOF )
591 for (i=0; opts[i].short_opt; i++ )
593 if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
597 arg->r_opt = opts[idx].short_opt;
598 if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
603 else if (!opts[idx].short_opt )
605 if (!strcmp (keyword, "ignore-invalid-option"))
607 /* No argument - ignore this meta option. */
611 else if (ignore_invalid_option_p (arg, keyword))
613 /* This invalid option is in the iio list. */
617 arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
618 ? ARGPARSE_INVALID_COMMAND
619 : ARGPARSE_INVALID_OPTION);
621 else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
622 arg->r_type = 0; /* Does not take an arg. */
623 else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) )
624 arg->r_type = 0; /* Arg is optional. */
626 arg->r_opt = ARGPARSE_MISSING_ARG;
632 /* No argument found. */
634 arg->r_opt = ARGPARSE_MISSING_ARG;
635 else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
636 arg->r_type = 0; /* Does not take an arg. */
637 else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
638 arg->r_type = 0; /* No optional argument. */
640 arg->r_opt = ARGPARSE_MISSING_ARG;
646 /* Has an argument. */
650 arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
656 p = strpbrk (buffer, " \t");
665 arg->r_opt = ARGPARSE_INVALID_ALIAS;
669 store_alias (arg, buffer, p);
673 else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
674 arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
682 buffer = xtrystrdup (keyword);
684 arg->r_opt = ARGPARSE_OUT_OF_CORE;
691 trim_spaces (buffer);
697 if (*p && p[strlen(p)-1] == '\"' )
700 if (!set_opt_arg (arg, opts[idx].flags, p))
708 ignore_invalid_option_clear (arg);
710 arg->r_opt = ARGPARSE_READ_ERROR;
712 arg->r_opt = 0; /* EOF. */
718 else if (state == -1)
720 else if (state == 0 && isascii (c) && isspace(c))
721 ; /* Skip leading white space. */
722 else if (state == 0 && c == '#' )
723 state = 1; /* Start of a comment. */
725 ; /* Skip comments. */
726 else if (state == 2 && isascii (c) && isspace(c))
730 for (i=0; opts[i].short_opt; i++ )
731 if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
734 arg->r_opt = opts[idx].short_opt;
735 if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
737 state = 1; /* Process like a comment. */
739 else if (!opts[idx].short_opt)
741 if (!strcmp (keyword, "alias"))
746 else if (!strcmp (keyword, "ignore-invalid-option"))
748 if (ignore_invalid_option_add (arg, fp))
750 arg->r_opt = ARGPARSE_OUT_OF_CORE;
756 else if (ignore_invalid_option_p (arg, keyword))
757 state = 1; /* Process like a comment. */
760 arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
761 ? ARGPARSE_INVALID_COMMAND
762 : ARGPARSE_INVALID_OPTION);
763 state = -1; /* Skip rest of line and leave. */
771 /* Skip leading spaces of the argument. */
772 if (!isascii (c) || !isspace(c))
781 /* Collect the argument. */
789 size_t tmplen = buflen + 50;
791 tmp = xtryrealloc (buffer, tmplen);
801 arg->r_opt = ARGPARSE_OUT_OF_CORE;
806 else if (i < DIM(keyword)-1)
810 size_t tmplen = DIM(keyword) + 50;
811 buffer = xtrymalloc (tmplen);
815 memcpy(buffer, keyword, i);
820 arg->r_opt = ARGPARSE_OUT_OF_CORE;
825 else if (i >= DIM(keyword)-1)
827 arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG;
828 state = -1; /* Skip rest of line and leave. */
843 find_long_option( ARGPARSE_ARGS *arg,
844 ARGPARSE_OPTS *opts, const char *keyword )
851 /* Would be better if we can do a binary search, but it is not
852 possible to reorder our option table because we would mess
853 up our help strings - What we can do is: Build a nice option
854 lookup table wehn this function is first invoked */
857 for(i=0; opts[i].short_opt; i++ )
858 if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
863 /* see whether it is an alias */
864 for( a = args->internal.aliases; a; a = a->next ) {
865 if( !strcmp( a->name, keyword) ) {
866 /* todo: must parse the alias here */
867 args->internal.cur_alias = a;
868 return -3; /* alias available */
873 /* not found, see whether it is an abbreviation */
874 /* aliases may not be abbreviated */
875 n = strlen( keyword );
876 for(i=0; opts[i].short_opt; i++ ) {
877 if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
879 for(j=i+1; opts[j].short_opt; j++ ) {
881 && !strncmp( opts[j].long_opt, keyword, n ) )
882 return -2; /* abbreviation is ambiguous */
887 return -1; /* Not found. */
891 arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
899 initialize( arg, NULL, NULL );
902 idx = arg->internal.idx;
904 if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0))
906 /* Skip the first argument. */
907 argc--; argv++; idx++;
915 goto leave; /* Ready. */
919 arg->internal.last = s;
921 if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL))
923 arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */
926 argc--; argv++; idx++; /* set to next one */
928 else if( arg->internal.stopped )
931 goto leave; /* Ready. */
933 else if ( *s == '-' && s[1] == '-' )
938 arg->internal.inarg = 0;
939 if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP))
941 /* Stop option processing. */
942 arg->internal.stopped = 1;
943 arg->flags |= ARGPARSE_FLAG_STOP_SEEN;
944 argc--; argv++; idx++;
948 argpos = strchr( s+2, '=' );
951 i = find_long_option ( arg, opts, s+2 );
955 if ( i < 0 && !strcmp ( "help", s+2) )
956 show_help (opts, arg->flags);
957 else if ( i < 0 && !strcmp ( "version", s+2) )
959 if (!(arg->flags & ARGPARSE_FLAG_NOVERSION))
965 else if ( i < 0 && !strcmp( "warranty", s+2))
967 writestrings (0, strusage (16), "\n", NULL);
970 else if ( i < 0 && !strcmp( "dump-options", s+2) )
972 for (i=0; opts[i].short_opt; i++ )
974 if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE))
975 writestrings (0, "--", opts[i].long_opt, "\n", NULL);
977 writestrings (0, "--dump-options\n--help\n--version\n--warranty\n",
983 arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION;
986 arg->r_opt = ARGPARSE_INVALID_OPTION;
987 arg->r.ret_str = s+2;
990 arg->r_opt = opts[i].short_opt;
993 else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
1003 if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
1005 arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */
1009 arg->r_opt = ARGPARSE_MISSING_ARG;
1011 else if ( !argpos && *s2 == '-'
1012 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
1014 /* The argument is optional and the next seems to be an
1015 option. We do not check this possible option but
1016 assume no argument */
1017 arg->r_type = ARGPARSE_TYPE_NONE;
1021 set_opt_arg (arg, opts[i].flags, s2);
1024 argc--; argv++; idx++; /* Skip one. */
1030 /* Does not take an argument. */
1032 arg->r_type = ARGPARSE_UNEXPECTED_ARG;
1036 argc--; argv++; idx++; /* Set to next one. */
1038 else if ( (*s == '-' && s[1]) || arg->internal.inarg )
1041 int dash_kludge = 0;
1044 if ( !arg->internal.inarg )
1046 arg->internal.inarg++;
1047 if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) )
1049 for (i=0; opts[i].short_opt; i++ )
1050 if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1))
1057 s += arg->internal.inarg;
1061 for (i=0; opts[i].short_opt; i++ )
1062 if ( opts[i].short_opt == *s )
1066 if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
1067 show_help (opts, arg->flags);
1069 arg->r_opt = opts[i].short_opt;
1070 if (!opts[i].short_opt )
1072 arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)?
1073 ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION;
1074 arg->internal.inarg++; /* Point to the next arg. */
1077 else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
1079 if ( s[1] && !dash_kludge )
1082 set_opt_arg (arg, opts[i].flags, s2);
1087 if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
1089 arg->r_type = ARGPARSE_TYPE_NONE;
1093 arg->r_opt = ARGPARSE_MISSING_ARG;
1095 else if ( *s2 == '-' && s2[1]
1096 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
1098 /* The argument is optional and the next seems to
1099 be an option. We do not check this possible
1100 option but assume no argument. */
1101 arg->r_type = ARGPARSE_TYPE_NONE;
1105 set_opt_arg (arg, opts[i].flags, s2);
1106 argc--; argv++; idx++; /* Skip one. */
1109 s = "x"; /* This is so that !s[1] yields false. */
1113 /* Does not take an argument. */
1114 arg->r_type = ARGPARSE_TYPE_NONE;
1115 arg->internal.inarg++; /* Point to the next arg. */
1117 if ( !s[1] || dash_kludge )
1119 /* No more concatenated short options. */
1120 arg->internal.inarg = 0;
1121 argc--; argv++; idx++;
1124 else if ( arg->flags & ARGPARSE_FLAG_MIXED )
1126 arg->r_opt = ARGPARSE_IS_ARG;
1129 argc--; argv++; idx++; /* Set to next one. */
1133 arg->internal.stopped = 1; /* Stop option processing. */
1140 arg->internal.idx = idx;
1145 /* Returns: -1 on error, 0 for an integer type and 1 for a non integer
1148 set_opt_arg (ARGPARSE_ARGS *arg, unsigned flags, char *s)
1150 int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10;
1153 switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) )
1155 case ARGPARSE_TYPE_LONG:
1156 case ARGPARSE_TYPE_INT:
1158 l = strtol (s, NULL, base);
1159 if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
1161 arg->r_opt = ARGPARSE_INVALID_ARG;
1164 if (arg->r_type == ARGPARSE_TYPE_LONG)
1165 arg->r.ret_long = l;
1166 else if ( (l < 0 && l < INT_MIN) || l > INT_MAX )
1168 arg->r_opt = ARGPARSE_INVALID_ARG;
1172 arg->r.ret_int = (int)l;
1175 case ARGPARSE_TYPE_ULONG:
1176 while (isascii (*s) && isspace(*s))
1180 arg->r.ret_ulong = 0;
1181 arg->r_opt = ARGPARSE_INVALID_ARG;
1185 arg->r.ret_ulong = strtoul (s, NULL, base);
1186 if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE)
1188 arg->r_opt = ARGPARSE_INVALID_ARG;
1193 case ARGPARSE_TYPE_STRING:
1202 long_opt_strlen( ARGPARSE_OPTS *o )
1204 size_t n = strlen (o->long_opt);
1206 if ( o->description && *o->description == '|' )
1209 int is_utf8 = is_native_utf8 ();
1214 /* For a (mostly) correct length calculation we exclude
1215 continuation bytes (10xxxxxx) if we are on a native utf8
1217 for (; *s && *s != '|'; s++ )
1218 if ( is_utf8 && (*s&0xc0) != 0x80 )
1226 * Print formatted help. The description string has some special
1228 * - A description string which is "@" suppresses help output for
1230 * - a description,ine which starts with a '@' and is followed by
1231 * any other characters is printed as is; this may be used for examples
1233 * - A description which starts with a '|' outputs the string between this
1234 * bar and the next one as arguments of the long option.
1237 show_help (ARGPARSE_OPTS *opts, unsigned int flags)
1243 writestrings (0, "\n", NULL);
1248 writestrings (1, s, NULL);
1249 if (*s && s[strlen(s)] != '\n')
1250 writestrings (1, "\n", NULL);
1253 writestrings (0, s, "\n", NULL);
1254 if ( opts[0].description )
1256 /* Auto format the option description. */
1259 /* Get max. length of long options. */
1260 for (i=indent=0; opts[i].short_opt; i++ )
1262 if ( opts[i].long_opt )
1263 if ( !opts[i].description || *opts[i].description != '@' )
1264 if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
1268 /* Example: " -v, --verbose Viele Sachen ausgeben" */
1270 if ( *opts[0].description != '@' )
1271 writestrings (0, "Options:", "\n", NULL);
1272 for (i=0; opts[i].short_opt; i++ )
1274 s = map_static_macro_string (_( opts[i].description ));
1275 if ( s && *s== '@' && !s[1] ) /* Hide this line. */
1277 if ( s && *s == '@' ) /* Unindented comment only line. */
1284 writestrings (0, "\n", NULL);
1290 writestrings (0, tmp, NULL);
1293 writestrings (0, "\n", NULL);
1298 if ( opts[i].short_opt < 256 )
1300 tmp[0] = opts[i].short_opt;
1302 writestrings (0, " -", tmp, NULL );
1303 if ( !opts[i].long_opt )
1305 if (s && *s == '|' )
1307 writestrings (0, " ", NULL); j++;
1308 for (s++ ; *s && *s != '|'; s++, j++ )
1312 writestrings (0, tmp, NULL);
1320 writestrings (0, " ", NULL);
1321 if ( opts[i].long_opt )
1323 tmp[0] = opts[i].short_opt < 256?',':' ';
1325 j += writestrings (0, tmp, " --", opts[i].long_opt, NULL);
1326 if (s && *s == '|' )
1330 writestrings (0, " ", NULL);
1333 for ( ; *s && *s != '|'; s++, j++ )
1337 writestrings (0, tmp, NULL);
1342 writestrings (0, " ", NULL);
1345 for (;j < indent; j++ )
1346 writestrings (0, " ", NULL);
1349 if ( *s && j > indent )
1351 writestrings (0, "\n", NULL);
1352 for (j=0;j < indent; j++ )
1353 writestrings (0, " ", NULL);
1361 writestrings (0, "\n", NULL);
1362 for (j=0; j < indent; j++ )
1363 writestrings (0, " ", NULL);
1370 writestrings (0, tmp, NULL);
1374 writestrings (0, "\n", NULL);
1376 if ( (flags & ARGPARSE_FLAG_ONEDASH) )
1377 writestrings (0, "\n(A single dash may be used "
1378 "instead of the double ones)\n", NULL);
1380 if ( (s=strusage(19)) )
1382 writestrings (0, "\n", NULL);
1383 writestrings (0, s, NULL);
1396 writestrings (0, strusage (11), NULL);
1397 if ((s=strusage (12)))
1398 writestrings (0, " (", s, ")", NULL);
1399 writestrings (0, " ", strusage (13), "\n", NULL);
1400 /* Additional version lines. */
1401 for (i=20; i < 30; i++)
1402 if ((s=strusage (i)))
1403 writestrings (0, s, "\n", NULL);
1404 /* Copyright string. */
1405 if ((s=strusage (14)))
1406 writestrings (0, s, "\n", NULL);
1407 /* Licence string. */
1408 if( (s=strusage (10)) )
1409 writestrings (0, s, "\n", NULL);
1410 /* Copying conditions. */
1411 if ( (s=strusage(15)) )
1412 writestrings (0, s, NULL);
1414 if ((s=strusage(18)))
1415 writestrings (0, s, NULL);
1416 /* Additional program info. */
1417 for (i=30; i < 40; i++ )
1418 if ( (s=strusage (i)) )
1419 writestrings (0, s, NULL);
1431 writestrings (1, strusage(11), " ", strusage(13), "; ",
1432 strusage (14), "\n", NULL);
1435 else if (level == 1)
1438 writestrings (1, p, NULL);
1439 if (*p && p[strlen(p)] != '\n')
1440 writestrings (1, "\n", NULL);
1443 else if (level == 2)
1449 writestrings (1, p, NULL);
1450 if (*p && p[strlen(p)] != '\n')
1451 writestrings (1, "\n", NULL);
1453 writestrings (0, strusage(41), "\n", NULL);
1459 * 0: Print copyright string to stderr
1460 * 1: Print a short usage hint to stderr and terminate
1461 * 2: Print a long usage hint to stdout and terminate
1462 * 10: Return license info string
1463 * 11: Return the name of the program
1464 * 12: Return optional name of package which includes this program.
1465 * 13: version string
1466 * 14: copyright string
1467 * 15: Short copying conditions (with LFs)
1468 * 16: Long copying conditions (with LFs)
1469 * 17: Optional printable OS name
1470 * 18: Optional thanks list (with LFs)
1471 * 19: Bug report info
1472 *20..29: Additional lib version strings.
1473 *30..39: Additional program info (with LFs)
1474 * 40: short usage note (with LF)
1475 * 41: long usage note (with LF)
1477 * First char is '1':
1478 * The short usage notes needs to be printed
1479 * before the long usage note.
1482 strusage( int level )
1484 const char *p = strusage_handler? strusage_handler(level) : NULL;
1487 return map_static_macro_string (p);
1493 #if ARGPARSE_GPL_VERSION == 3
1494 p = ("License GPLv3+: GNU GPL version 3 or later "
1495 "<http://gnu.org/licenses/gpl.html>");
1497 p = ("License GPLv2+: GNU GPL version 2 or later "
1498 "<http://gnu.org/licenses/>");
1501 case 11: p = "foo"; break;
1502 case 13: p = "0.0"; break;
1503 case 14: p = ARGPARSE_CRIGHT_STR; break;
1505 "This is free software: you are free to change and redistribute it.\n"
1506 "There is NO WARRANTY, to the extent permitted by law.\n";
1509 "This is free software; you can redistribute it and/or modify\n"
1510 "it under the terms of the GNU General Public License as published by\n"
1511 "the Free Software Foundation; either version "
1512 ARGPARSE_STR2(ARGPARSE_GPL_VERSION)
1513 " of the License, or\n"
1514 "(at your option) any later version.\n\n"
1515 "It is distributed in the hope that it will be useful,\n"
1516 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1517 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1518 "GNU General Public License for more details.\n\n"
1519 "You should have received a copy of the GNU General Public License\n"
1520 "along with this software. If not, see <http://www.gnu.org/licenses/>.\n";
1522 case 40: /* short and long usage */
1523 case 41: p = ""; break;
1530 /* Set the usage handler. This function is basically a constructor. */
1532 set_strusage ( const char *(*f)( int ) )
1534 strusage_handler = f;
1550 main(int argc, char **argv)
1552 ARGPARSE_OPTS opts[] = {
1553 ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"),
1554 ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, "
1555 "was wir eingegeben haben")),
1556 ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"),
1557 ARGPARSE_s_s('o', "output", 0 ),
1558 ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ),
1559 /* Note that on a non-utf8 terminal the ß might garble the output. */
1560 ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"),
1561 ARGPARSE_o_i('m', "my-option", 0),
1562 ARGPARSE_s_n(500, "a-long-option", 0 ),
1565 ARGPARSE_ARGS pargs = { &argc, &argv, (ARGPARSE_FLAG_ALL
1566 | ARGPARSE_FLAG_MIXED
1567 | ARGPARSE_FLAG_ONEDASH) };
1570 while (arg_parse (&pargs, opts))
1572 switch (pargs.r_opt)
1574 case ARGPARSE_IS_ARG :
1575 printf ("arg='%s'\n", pargs.r.ret_str);
1577 case 'v': opt.verbose++; break;
1578 case 'e': opt.echo++; break;
1579 case 'd': opt.debug++; break;
1580 case 'o': opt.outfile = pargs.r.ret_str; break;
1581 case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
1582 case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
1583 case 500: opt.a_long_one++; break;
1584 default : pargs.err = ARGPARSE_PRINT_WARNING; break;
1587 for (i=0; i < argc; i++ )
1588 printf ("%3d -> (%s)\n", i, argv[i] );
1591 printf (" verbose=%d\n", opt.verbose );
1593 printf (" debug=%d\n", opt.debug );
1595 printf (" outfile='%s'\n", opt.outfile );
1597 printf (" crffile='%s'\n", opt.crf );
1599 printf (" myopt=%d\n", opt.myopt );
1601 printf (" a-long-one=%d\n", opt.a_long_one );
1603 printf (" echo=%d\n", opt.echo );
1609 /**** bottom of file ****/