1 /* [argparse.c wk 17.06.97] Argument Parser for option handling
2 * Copyright (C) 1998, 1999, 2000, 2001, 2006
3 * 2007, 2008 Free Software Foundation, Inc.
5 * This file is part of JNLIB.
7 * JNLIB is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
12 * JNLIB is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
30 #include "libjnlib-config.h"
32 #include "stringhelp.h"
34 #ifdef JNLIB_NEED_UTF8CONV
41 /*********************************
46 * char *argc; pointer to argc (value subject to change)
47 * char ***argv; pointer to argv (value subject to change)
48 * unsigned flags; Global flags (DO NOT CHANGE)
49 * int err; print error about last option
50 * 1 = warning, 2 = abort
51 * int r_opt; return option
52 * int r_type; type of return value (0 = no argument found)
63 * } internal; DO NOT CHANGE
68 * const char *long_opt;
72 * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
75 * This is my replacement for getopt(). See the example for a typical usage.
77 * Bit 0 : Do not remove options form argv
78 * Bit 1 : Do not stop at last option but return other args
79 * with r_opt set to -1.
80 * Bit 2 : Assume options and real args are mixed.
81 * Bit 3 : Do not use -- to stop option processing.
82 * Bit 4 : Do not skip the first arg.
83 * Bit 5 : allow usage of long option with only one dash
84 * Bit 6 : ignore --version
85 * all other bits must be set to zero, this value is modified by the
86 * function, so assume this is write only.
87 * Local flags (for each option):
88 * Bit 2-0 : 0 = does not take an argument
89 * 1 = takes int argument
90 * 2 = takes string argument
91 * 3 = takes long argument
92 * 4 = takes ulong argument
93 * Bit 3 : argument is optional (r_type will the be set to 0)
94 * Bit 4 : allow 0x etc. prefixed values.
95 * Bit 7 : this is a command and not an option
96 * You stop the option processing by setting opts to NULL, the function will
99 * Returns the args.r_opt or 0 if ready
100 * r_opt may be -2/-7 to indicate an unknown option/command.
104 * You do not need to process the options 'h', '--help' or '--version'
105 * because this function includes standard help processing; but if you
106 * specify '-h', '--help' or '--version' you have to do it yourself.
107 * The option '--' stops argument processing; if bit 1 is set the function
108 * continues to return normal arguments.
109 * To process float args or unsigned args you must use a string args and do
110 * the conversion yourself.
113 * ARGPARSE_OPTS opts[] = {
114 * { 'v', "verbose", 0 },
115 * { 'd', "debug", 0 },
116 * { 'o', "output", 2 },
117 * { 'c', "cross-ref", 2|8 },
118 * { 'm', "my-option", 1|8 },
119 * { 500, "have-no-short-option-for-this-long-option", 0 },
121 * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
123 * while( ArgParse( &pargs, &opts) ) {
124 * switch( pargs.r_opt ) {
125 * case 'v': opt.verbose++; break;
126 * case 'd': opt.debug++; break;
127 * case 'o': opt.outfile = pargs.r.ret_str; break;
128 * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
129 * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
130 * case 500: opt.a_long_one++; break
131 * default : pargs.err = 1; break; -- force warning output --
135 * log_fatal( "Too many args");
139 typedef struct alias_def_s
*ALIAS_DEF
;
142 char *name
; /* malloced buffer with name, \0, value */
143 const char *value
; /* ptr into name */
146 static const char *(*strusage_handler
)( int ) = NULL
;
148 static int set_opt_arg(ARGPARSE_ARGS
*arg
, unsigned flags
, char *s
);
149 static void show_help(ARGPARSE_OPTS
*opts
, unsigned flags
);
150 static void show_version(void);
154 initialize( ARGPARSE_ARGS
*arg
, const char *filename
, unsigned *lineno
)
156 if( !(arg
->flags
& (1<<15)) )
158 /* Initialize this instance. */
159 arg
->internal
.idx
= 0;
160 arg
->internal
.last
= NULL
;
161 arg
->internal
.inarg
= 0;
162 arg
->internal
.stopped
= 0;
163 arg
->internal
.aliases
= NULL
;
164 arg
->internal
.cur_alias
= NULL
;
166 arg
->flags
|= 1<<15; /* Mark as initialized. */
167 if ( *arg
->argc
< 0 )
168 jnlib_log_bug ("invalid argument for arg_parsee\n");
174 /* Last option was erroneous. */
179 if ( arg
->r_opt
== ARGPARSE_UNEXPECTED_ARG
)
180 s
= _("argument not expected");
181 else if ( arg
->r_opt
== ARGPARSE_READ_ERROR
)
183 else if ( arg
->r_opt
== ARGPARSE_KEYWORD_TOO_LONG
)
184 s
= _("keyword too long");
185 else if ( arg
->r_opt
== ARGPARSE_MISSING_ARG
)
186 s
= _("missing argument");
187 else if ( arg
->r_opt
== ARGPARSE_INVALID_COMMAND
)
188 s
= _("invalid command");
189 else if ( arg
->r_opt
== ARGPARSE_INVALID_ALIAS
)
190 s
= _("invalid alias definition");
191 else if ( arg
->r_opt
== ARGPARSE_OUT_OF_CORE
)
192 s
= _("out of core");
194 s
= _("invalid option");
195 jnlib_log_error ("%s:%u: %s\n", filename
, *lineno
, s
);
199 s
= arg
->internal
.last
? arg
->internal
.last
:"[??]";
201 if ( arg
->r_opt
== ARGPARSE_MISSING_ARG
)
202 jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s
);
203 else if ( arg
->r_opt
== ARGPARSE_UNEXPECTED_ARG
)
204 jnlib_log_error (_("option \"%.50s\" does not expect an "
206 else if ( arg
->r_opt
== ARGPARSE_INVALID_COMMAND
)
207 jnlib_log_error (_("invalid command \"%.50s\"\n"), s
);
208 else if ( arg
->r_opt
== ARGPARSE_AMBIGUOUS_OPTION
)
209 jnlib_log_error (_("option \"%.50s\" is ambiguous\n"), s
);
210 else if ( arg
->r_opt
== ARGPARSE_AMBIGUOUS_OPTION
)
211 jnlib_log_error (_("command \"%.50s\" is ambiguous\n"),s
);
212 else if ( arg
->r_opt
== ARGPARSE_OUT_OF_CORE
)
213 jnlib_log_error ("%s\n", _("out of core\n"));
215 jnlib_log_error (_("invalid option \"%.50s\"\n"), s
);
222 /* Zero out the return value union. */
223 arg
->r
.ret_str
= NULL
;
229 store_alias( ARGPARSE_ARGS
*arg
, char *name
, char *value
)
231 /* TODO: replace this dummy function with a rea one
232 * and fix the probelms IRIX has with (ALIAS_DEV)arg..
239 ALIAS_DEF a
= jnlib_xmalloc( sizeof *a
);
242 a
->next
= (ALIAS_DEF
)arg
->internal
.aliases
;
243 (ALIAS_DEF
)arg
->internal
.aliases
= a
;
248 * Get options from a file.
249 * Lines starting with '#' are comment lines.
250 * Syntax is simply a keyword and the argument.
251 * Valid keywords are all keywords from the long_opt list without
252 * the leading dashes. The special keywords "help", "warranty" and "version"
253 * are not valid here.
254 * The special keyword "alias" may be used to store alias definitions,
255 * which are later expanded like long options.
256 * Caller must free returned strings.
257 * If called with FP set to NULL command line args are parse instead.
259 * Q: Should we allow the syntax
261 * and accept for boolean options a value of 1/0, yes/no or true/false?
262 * Note: Abbreviation of options is here not allowed.
265 optfile_parse (FILE *fp
, const char *filename
, unsigned *lineno
,
266 ARGPARSE_ARGS
*arg
, ARGPARSE_OPTS
*opts
)
275 if (!fp
) /* Divert to to arg_parse() in this case. */
276 return arg_parse (arg
, opts
);
278 initialize (arg
, filename
, lineno
);
280 /* Find the next keyword. */
285 if (c
== '\n' || c
== EOF
)
294 for (i
=0; opts
[i
].short_opt
; i
++ )
296 if (opts
[i
].long_opt
&& !strcmp (opts
[i
].long_opt
, keyword
))
300 arg
->r_opt
= opts
[idx
].short_opt
;
301 if (!opts
[idx
].short_opt
)
302 arg
->r_opt
= ((opts
[idx
].flags
& ARGPARSE_OPT_COMMAND
)
303 ? ARGPARSE_INVALID_COMMAND
304 : ARGPARSE_INVALID_OPTION
);
305 else if (!(opts
[idx
].flags
& 7))
306 arg
->r_type
= 0; /* Does not take an arg. */
307 else if ((opts
[idx
].flags
& 8) )
308 arg
->r_type
= 0; /* Arg is optional. */
310 arg
->r_opt
= ARGPARSE_MISSING_ARG
;
316 /* No argument found. */
318 arg
->r_opt
= ARGPARSE_MISSING_ARG
;
319 else if (!(opts
[idx
].flags
& 7))
320 arg
->r_type
= 0; /* Does not take an arg. */
321 else if ((opts
[idx
].flags
& 8))
322 arg
->r_type
= 0; /* No optional argument. */
324 arg
->r_opt
= ARGPARSE_MISSING_ARG
;
330 /* Has an argument. */
334 arg
->r_opt
= ARGPARSE_UNEXPECTED_ARG
;
340 p
= strpbrk (buffer
, " \t");
349 arg
->r_opt
= ARGPARSE_INVALID_ALIAS
;
353 store_alias (arg
, buffer
, p
);
357 else if (!(opts
[idx
].flags
& 7))
358 arg
->r_opt
= ARGPARSE_UNEXPECTED_ARG
;
366 buffer
= jnlib_strdup (keyword
);
368 arg
->r_opt
= ARGPARSE_OUT_OF_CORE
;
375 trim_spaces (buffer
);
381 if (*p
&& p
[strlen(p
)-1] == '\"' )
384 if (!set_opt_arg (arg
, opts
[idx
].flags
, p
))
393 arg
->r_opt
= ARGPARSE_READ_ERROR
;
395 arg
->r_opt
= 0; /* EOF. */
401 else if (state
== -1)
403 else if (state
== 0 && isascii (c
) && isspace(c
))
404 ; /* Skip leading white space. */
405 else if (state
== 0 && c
== '#' )
406 state
= 1; /* Start of a comment. */
408 ; /* Skip comments. */
409 else if (state
== 2 && isascii (c
) && isspace(c
))
413 for (i
=0; opts
[i
].short_opt
; i
++ )
414 if (opts
[i
].long_opt
&& !strcmp (opts
[i
].long_opt
, keyword
))
417 arg
->r_opt
= opts
[idx
].short_opt
;
418 if (!opts
[idx
].short_opt
)
420 if (!strcmp (keyword
, "alias"))
427 arg
->r_opt
= ((opts
[idx
].flags
& ARGPARSE_OPT_COMMAND
)
428 ? ARGPARSE_INVALID_COMMAND
429 : ARGPARSE_INVALID_OPTION
);
430 state
= -1; /* Skip rest of line and leave. */
438 /* Skip leading spaces of the argument. */
439 if (!isascii (c
) || !isspace(c
))
448 /* Collect the argument. */
456 size_t tmplen
= buflen
+ 50;
458 tmp
= jnlib_realloc (buffer
, tmplen
);
468 arg
->r_opt
= ARGPARSE_OUT_OF_CORE
;
473 else if (i
< DIM(keyword
)-1)
477 size_t tmplen
= DIM(keyword
) + 50;
478 buffer
= jnlib_malloc (tmplen
);
482 memcpy(buffer
, keyword
, i
);
487 arg
->r_opt
= ARGPARSE_OUT_OF_CORE
;
492 else if (i
>= DIM(keyword
)-1)
494 arg
->r_opt
= ARGPARSE_KEYWORD_TOO_LONG
;
495 state
= -1; /* Skip rest of line and leave. */
510 find_long_option( ARGPARSE_ARGS
*arg
,
511 ARGPARSE_OPTS
*opts
, const char *keyword
)
518 /* Would be better if we can do a binary search, but it is not
519 possible to reorder our option table because we would mess
520 up our help strings - What we can do is: Build a nice option
521 lookup table wehn this function is first invoked */
524 for(i
=0; opts
[i
].short_opt
; i
++ )
525 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, keyword
) )
530 /* see whether it is an alias */
531 for( a
= args
->internal
.aliases
; a
; a
= a
->next
) {
532 if( !strcmp( a
->name
, keyword
) ) {
533 /* todo: must parse the alias here */
534 args
->internal
.cur_alias
= a
;
535 return -3; /* alias available */
540 /* not found, see whether it is an abbreviation */
541 /* aliases may not be abbreviated */
542 n
= strlen( keyword
);
543 for(i
=0; opts
[i
].short_opt
; i
++ ) {
544 if( opts
[i
].long_opt
&& !strncmp( opts
[i
].long_opt
, keyword
, n
) ) {
546 for(j
=i
+1; opts
[j
].short_opt
; j
++ ) {
548 && !strncmp( opts
[j
].long_opt
, keyword
, n
) )
549 return -2; /* abbreviation is ambiguous */
558 arg_parse( ARGPARSE_ARGS
*arg
, ARGPARSE_OPTS
*opts
)
566 initialize( arg
, NULL
, NULL
);
569 idx
= arg
->internal
.idx
;
571 if (!idx
&& argc
&& !(arg
->flags
& ARGPARSE_FLAG_ARG0
))
573 /* Skip the first argument. */
574 argc
--; argv
++; idx
++;
582 goto leave
; /* Ready. */
586 arg
->internal
.last
= s
;
588 if (arg
->internal
.stopped
&& (arg
->flags
& ARGPARSE_FLAG_ALL
))
590 arg
->r_opt
= ARGPARSE_IS_ARG
; /* Not an option but an argument. */
593 argc
--; argv
++; idx
++; /* set to next one */
595 else if( arg
->internal
.stopped
)
598 goto leave
; /* Ready. */
600 else if ( *s
== '-' && s
[1] == '-' )
605 arg
->internal
.inarg
= 0;
606 if (!s
[2] && !(arg
->flags
& ARGPARSE_FLAG_NOSTOP
))
608 /* Stop option processing. */
609 arg
->internal
.stopped
= 1;
610 argc
--; argv
++; idx
++;
614 argpos
= strchr( s
+2, '=' );
617 i
= find_long_option ( arg
, opts
, s
+2 );
621 if ( i
< 0 && !strcmp ( "help", s
+2) )
622 show_help (opts
, arg
->flags
);
623 else if ( i
< 0 && !strcmp ( "version", s
+2) )
625 if (!(arg
->flags
& ARGPARSE_FLAG_NOVERSION
))
631 else if ( i
< 0 && !strcmp( "warranty", s
+2))
633 puts ( strusage (16) );
636 else if ( i
< 0 && !strcmp( "dump-options", s
+2) )
638 for (i
=0; opts
[i
].short_opt
; i
++ )
640 if ( opts
[i
].long_opt
)
641 printf ("--%s\n", opts
[i
].long_opt
);
643 fputs ("--dump-options\n--help\n--version\n--warranty\n", stdout
);
648 arg
->r_opt
= ARGPARSE_AMBIGUOUS_OPTION
;
651 arg
->r_opt
= ARGPARSE_INVALID_OPTION
;
652 arg
->r
.ret_str
= s
+2;
655 arg
->r_opt
= opts
[i
].short_opt
;
658 else if ( (opts
[i
].flags
& 0x07) )
668 if ( !s2
&& (opts
[i
].flags
& ARGPARSE_OPT_OPTIONAL
) )
670 arg
->r_type
= ARGPARSE_TYPE_NONE
; /* Argument is optional. */
674 arg
->r_opt
= ARGPARSE_MISSING_ARG
;
676 else if ( !argpos
&& *s2
== '-'
677 && (opts
[i
].flags
& ARGPARSE_OPT_OPTIONAL
) )
679 /* The argument is optional and the next seems to be an
680 option. We do not check this possible option but
681 assume no argument */
682 arg
->r_type
= ARGPARSE_TYPE_NONE
;
686 set_opt_arg (arg
, opts
[i
].flags
, s2
);
689 argc
--; argv
++; idx
++; /* Skip one. */
695 /* Does not take an argument. */
697 arg
->r_type
= ARGPARSE_UNEXPECTED_ARG
;
701 argc
--; argv
++; idx
++; /* Set to next one. */
703 else if ( (*s
== '-' && s
[1]) || arg
->internal
.inarg
)
709 if ( !arg
->internal
.inarg
)
711 arg
->internal
.inarg
++;
712 if ( (arg
->flags
& ARGPARSE_FLAG_ONEDASH
) )
714 for (i
=0; opts
[i
].short_opt
; i
++ )
715 if ( opts
[i
].long_opt
&& !strcmp (opts
[i
].long_opt
, s
+1))
722 s
+= arg
->internal
.inarg
;
726 for (i
=0; opts
[i
].short_opt
; i
++ )
727 if ( opts
[i
].short_opt
== *s
)
731 if ( !opts
[i
].short_opt
&& ( *s
== 'h' || *s
== '?' ) )
732 show_help (opts
, arg
->flags
);
734 arg
->r_opt
= opts
[i
].short_opt
;
735 if (!opts
[i
].short_opt
)
737 arg
->r_opt
= (opts
[i
].flags
& ARGPARSE_OPT_COMMAND
)?
738 ARGPARSE_INVALID_COMMAND
:ARGPARSE_INVALID_OPTION
;
739 arg
->internal
.inarg
++; /* Point to the next arg. */
742 else if ( (opts
[i
].flags
& 7) )
744 if ( s
[1] && !dash_kludge
)
747 set_opt_arg (arg
, opts
[i
].flags
, s2
);
752 if ( !s2
&& (opts
[i
].flags
& ARGPARSE_OPT_OPTIONAL
) )
754 arg
->r_type
= ARGPARSE_TYPE_NONE
;
758 arg
->r_opt
= ARGPARSE_MISSING_ARG
;
760 else if ( *s2
== '-' && s2
[1]
761 && (opts
[i
].flags
& ARGPARSE_OPT_OPTIONAL
) )
763 /* The argument is optional and the next seems to
764 be an option. We do not check this possible
765 option but assume no argument. */
766 arg
->r_type
= ARGPARSE_TYPE_NONE
;
770 set_opt_arg (arg
, opts
[i
].flags
, s2
);
771 argc
--; argv
++; idx
++; /* Skip one. */
774 s
= "x"; /* This is so that !s[1] yields false. */
778 /* Does not take an argument. */
779 arg
->r_type
= ARGPARSE_TYPE_NONE
;
780 arg
->internal
.inarg
++; /* Point to the next arg. */
782 if ( !s
[1] || dash_kludge
)
784 /* No more concatenated short options. */
785 arg
->internal
.inarg
= 0;
786 argc
--; argv
++; idx
++;
789 else if ( arg
->flags
& ARGPARSE_FLAG_MIXED
)
791 arg
->r_opt
= ARGPARSE_IS_ARG
;
794 argc
--; argv
++; idx
++; /* Set to next one. */
798 arg
->internal
.stopped
= 1; /* Stop option processing. */
805 arg
->internal
.idx
= idx
;
812 set_opt_arg(ARGPARSE_ARGS
*arg
, unsigned flags
, char *s
)
814 int base
= (flags
& 16)? 0 : 10;
816 switch ( (arg
->r_type
= (flags
& 7)) )
818 case ARGPARSE_TYPE_INT
:
819 arg
->r
.ret_int
= (int)strtol(s
,NULL
,base
);
821 case ARGPARSE_TYPE_LONG
:
822 arg
->r
.ret_long
= strtol(s
,NULL
,base
);
824 case ARGPARSE_TYPE_ULONG
:
825 arg
->r
.ret_ulong
= strtoul(s
,NULL
,base
);
827 case ARGPARSE_TYPE_STRING
:
836 long_opt_strlen( ARGPARSE_OPTS
*o
)
838 size_t n
= strlen (o
->long_opt
);
840 if ( o
->description
&& *o
->description
== '|' )
843 #ifdef JNLIB_NEED_UTF8CONV
844 int is_utf8
= is_native_utf8 ();
850 /* For a (mostly) correct length calculation we exclude
851 continuation bytes (10xxxxxx) if we are on a native utf8
853 for (; *s
&& *s
!= '|'; s
++ )
854 #ifdef JNLIB_NEED_UTF8CONV
855 if ( is_utf8
&& (*s
&0xc0) != 0x80 )
864 * Print formatted help. The description string has some special
866 * - A description string which is "@" suppresses help output for
868 * - a description,ine which starts with a '@' and is followed by
869 * any other characters is printed as is; this may be used for examples
871 * - A description which starts with a '|' outputs the string between this
872 * bar and the next one as arguments of the long option.
875 show_help (ARGPARSE_OPTS
*opts
, unsigned int flags
)
883 if ( opts
[0].description
)
885 /* Auto format the option description. */
888 /* Get max. length of long options. */
889 for (i
=indent
=0; opts
[i
].short_opt
; i
++ )
891 if ( opts
[i
].long_opt
)
892 if ( !opts
[i
].description
|| *opts
[i
].description
!= '@' )
893 if ( (j
=long_opt_strlen(opts
+i
)) > indent
&& j
< 35 )
897 /* Example: " -v, --verbose Viele Sachen ausgeben" */
899 if ( *opts
[0].description
!= '@' )
901 for (i
=0; opts
[i
].short_opt
; i
++ )
903 s
= _( opts
[i
].description
);
904 if ( s
&& *s
== '@' && !s
[1] ) /* Hide this line. */
906 if ( s
&& *s
== '@' ) /* Unindented comment only line. */
923 if ( opts
[i
].short_opt
< 256 )
925 printf (" -%c", opts
[i
].short_opt
);
926 if ( !opts
[i
].long_opt
)
931 for (s
++ ; *s
&& *s
!= '|'; s
++, j
++ )
940 if ( opts
[i
].long_opt
)
942 j
+= printf ("%c --%s", opts
[i
].short_opt
< 256?',':' ',
951 for ( ; *s
&& *s
!= '|'; s
++, j
++ )
959 for (;j
< indent
; j
++ )
963 if ( *s
&& j
> indent
)
966 for (j
=0;j
< indent
; j
++ )
976 for (j
=0; j
< indent
; j
++ )
986 if ( (flags
& ARGPARSE_FLAG_ONEDASH
) )
987 puts ("\n(A single dash may be used instead of the double ones)");
989 if ( (s
=strusage(19)) )
991 /* bug reports to ... */
995 s2
= strstr (s
, "@EMAIL@");
999 fwrite (s
, s2
-s
, 1, stdout
);
1000 #ifdef PACKAGE_BUGREPORT
1001 fputs (PACKAGE_BUGREPORT
, stdout
);
1003 fputs ("bug@example.org", stdout
);
1023 fputs (strusage (11), stdout
);
1024 if ((s
=strusage (12)))
1025 printf (" (%s)", s
);
1026 printf (" %s\n", strusage (13) );
1027 /* Additional version lines. */
1028 for (i
=20; i
< 30; i
++)
1029 if ((s
=strusage (i
)))
1030 printf ("%s\n", s
);
1031 /* Copyright string. */
1032 if( (s
=strusage (14)) )
1034 /* Licence string. */
1035 if( (s
=strusage (10)) )
1037 /* Copying conditions. */
1038 if ( (s
=strusage(15)) )
1041 if ((s
=strusage(18)))
1043 /* Additional program info. */
1044 for (i
=30; i
< 40; i
++ )
1045 if ( (s
=strusage (i
)) )
1058 fprintf(stderr
,"%s %s; %s\n", strusage(11), strusage(13), strusage (14));
1061 else if (level
== 1)
1065 if (*p
&& p
[strlen(p
)] != '\n')
1066 putc ('\n', stderr
);
1069 else if (level
== 2)
1071 puts (strusage(41));
1077 * 0: Print copyright string to stderr
1078 * 1: Print a short usage hint to stderr and terminate
1079 * 2: Print a long usage hint to stdout and terminate
1080 * 10: Return license info string
1081 * 11: Return the name of the program
1082 * 12: Return optional name of package which includes this program.
1083 * 13: version string
1084 * 14: copyright string
1085 * 15: Short copying conditions (with LFs)
1086 * 16: Long copying conditions (with LFs)
1087 * 17: Optional printable OS name
1088 * 18: Optional thanks list (with LFs)
1089 * 19: Bug report info
1090 *20..29: Additional lib version strings.
1091 *30..39: Additional program info (with LFs)
1092 * 40: short usage note (with LF)
1093 * 41: long usage note (with LF)
1096 strusage( int level
)
1098 const char *p
= strusage_handler
? strusage_handler(level
) : NULL
;
1105 case 10: p
= ("License GPLv3+: GNU GPL version 3 or later "
1106 "<http://gnu.org/licenses/gpl.html>");
1108 case 11: p
= "foo"; break;
1109 case 13: p
= "0.0"; break;
1110 case 14: p
= "Copyright (C) 2009 Free Software Foundation, Inc."; break;
1112 "This is free software: you are free to change and redistribute it.\n"
1113 "There is NO WARRANTY, to the extent permitted by law.\n";
1116 "This is free software; you can redistribute it and/or modify\n"
1117 "it under the terms of the GNU General Public License as published by\n"
1118 "the Free Software Foundation; either version 3 of the License, or\n"
1119 "(at your option) any later version.\n\n"
1120 "It is distributed in the hope that it will be useful,\n"
1121 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1122 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1123 "GNU General Public License for more details.\n\n"
1124 "You should have received a copy of the GNU General Public License\n"
1125 "along with this software. If not, see <http://www.gnu.org/licenses/>.\n";
1127 case 40: /* short and long usage */
1128 case 41: p
= ""; break;
1135 set_strusage ( const char *(*f
)( int ) )
1137 strusage_handler
= f
;
1153 main(int argc
, char **argv
)
1155 ARGPARSE_OPTS opts
[] = {
1156 ARGPARSE_x('v', "verbose", NONE
, 0, "Laut sein"),
1157 ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, "
1158 "was wir ein gegeben haben")),
1159 ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"),
1160 ARGPARSE_s_s('o', "output", 0 ),
1161 ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ),
1162 /* Note that on a non-utf8 terminal the ß might garble the output. */
1163 ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"),
1164 ARGPARSE_o_i('m', "my-option", 0),
1165 ARGPARSE_s_n(500, "a-long-option", 0 ),
1168 ARGPARSE_ARGS pargs
= { &argc
, &argv
, 2|4|32 };
1171 while( arg_parse ( &pargs
, opts
) ) {
1172 switch( pargs
.r_opt
) {
1173 case -1 : printf( "arg=`%s'\n", pargs
.r
.ret_str
); break;
1174 case 'v': opt
.verbose
++; break;
1175 case 'e': opt
.echo
++; break;
1176 case 'd': opt
.debug
++; break;
1177 case 'o': opt
.outfile
= pargs
.r
.ret_str
; break;
1178 case 'c': opt
.crf
= pargs
.r_type
? pargs
.r
.ret_str
:"a.crf"; break;
1179 case 'm': opt
.myopt
= pargs
.r_type
? pargs
.r
.ret_int
: 1; break;
1180 case 500: opt
.a_long_one
++; break;
1181 default : pargs
.err
= ARGPARSE_PRINT_WARNING
; break;
1184 for(i
=0; i
< argc
; i
++ )
1185 printf("%3d -> (%s)\n", i
, argv
[i
] );
1188 printf(" verbose=%d\n", opt
.verbose
);
1190 printf(" debug=%d\n", opt
.debug
);
1192 printf(" outfile=`%s'\n", opt
.outfile
);
1194 printf(" crffile=`%s'\n", opt
.crf
);
1196 printf(" myopt=%d\n", opt
.myopt
);
1197 if( opt
.a_long_one
)
1198 printf(" a-long-one=%d\n", opt
.a_long_one
);
1200 printf(" echo=%d\n", opt
.echo
);
1205 /**** bottom of file ****/