1 /* [argparse.c wk 17.06.97] Argument Parser for option handling
2 * Copyright (C) 1998, 1999, 2000, 2001, 2006
3 * 2007 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 3 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/>.
27 #include "libjnlib-config.h"
29 #include "stringhelp.h"
31 #ifdef JNLIB_NEED_UTF8CONV
37 /*********************************
42 * char *argc; pointer to argc (value subject to change)
43 * char ***argv; pointer to argv (value subject to change)
44 * unsigned flags; Global flags (DO NOT CHANGE)
45 * int err; print error about last option
46 * 1 = warning, 2 = abort
47 * int r_opt; return option
48 * int r_type; type of return value (0 = no argument found)
59 * } internal; DO NOT CHANGE
64 * const char *long_opt;
68 * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
71 * This is my replacement for getopt(). See the example for a typical usage.
73 * Bit 0 : Do not remove options form argv
74 * Bit 1 : Do not stop at last option but return other args
75 * with r_opt set to -1.
76 * Bit 2 : Assume options and real args are mixed.
77 * Bit 3 : Do not use -- to stop option processing.
78 * Bit 4 : Do not skip the first arg.
79 * Bit 5 : allow usage of long option with only one dash
80 * Bit 6 : ignore --version
81 * all other bits must be set to zero, this value is modified by the
82 * function, so assume this is write only.
83 * Local flags (for each option):
84 * Bit 2-0 : 0 = does not take an argument
85 * 1 = takes int argument
86 * 2 = takes string argument
87 * 3 = takes long argument
88 * 4 = takes ulong argument
89 * Bit 3 : argument is optional (r_type will the be set to 0)
90 * Bit 4 : allow 0x etc. prefixed values.
91 * Bit 7 : this is a command and not an option
92 * You stop the option processing by setting opts to NULL, the function will
95 * Returns the args.r_opt or 0 if ready
96 * r_opt may be -2/-7 to indicate an unknown option/command.
100 * You do not need to process the options 'h', '--help' or '--version'
101 * because this function includes standard help processing; but if you
102 * specify '-h', '--help' or '--version' you have to do it yourself.
103 * The option '--' stops argument processing; if bit 1 is set the function
104 * continues to return normal arguments.
105 * To process float args or unsigned args you must use a string args and do
106 * the conversion yourself.
109 * ARGPARSE_OPTS opts[] = {
110 * { 'v', "verbose", 0 },
111 * { 'd', "debug", 0 },
112 * { 'o', "output", 2 },
113 * { 'c', "cross-ref", 2|8 },
114 * { 'm', "my-option", 1|8 },
115 * { 500, "have-no-short-option-for-this-long-option", 0 },
117 * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
119 * while( ArgParse( &pargs, &opts) ) {
120 * switch( pargs.r_opt ) {
121 * case 'v': opt.verbose++; break;
122 * case 'd': opt.debug++; break;
123 * case 'o': opt.outfile = pargs.r.ret_str; break;
124 * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
125 * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
126 * case 500: opt.a_long_one++; break
127 * default : pargs.err = 1; break; -- force warning output --
131 * log_fatal( "Too many args");
135 typedef struct alias_def_s
*ALIAS_DEF
;
138 char *name
; /* malloced buffer with name, \0, value */
139 const char *value
; /* ptr into name */
142 static const char *(*strusage_handler
)( int ) = NULL
;
144 static int set_opt_arg(ARGPARSE_ARGS
*arg
, unsigned flags
, char *s
);
145 static void show_help(ARGPARSE_OPTS
*opts
, unsigned flags
);
146 static void show_version(void);
150 initialize( ARGPARSE_ARGS
*arg
, const char *filename
, unsigned *lineno
)
152 if( !(arg
->flags
& (1<<15)) )
154 /* Initialize this instance. */
155 arg
->internal
.idx
= 0;
156 arg
->internal
.last
= NULL
;
157 arg
->internal
.inarg
= 0;
158 arg
->internal
.stopped
= 0;
159 arg
->internal
.aliases
= NULL
;
160 arg
->internal
.cur_alias
= NULL
;
162 arg
->flags
|= 1<<15; /* Mark as initialized. */
163 if ( *arg
->argc
< 0 )
164 jnlib_log_bug ("invalid argument for arg_parsee\n");
170 /* Last option was erroneous. */
175 if ( arg
->r_opt
== -6 )
176 s
= _("argument not expected");
177 else if ( arg
->r_opt
== -5 )
179 else if ( arg
->r_opt
== -4 )
180 s
= _("keyword too long");
181 else if ( arg
->r_opt
== -3 )
182 s
= _("missing argument");
183 else if ( arg
->r_opt
== -7 )
184 s
= _("invalid command");
185 else if ( arg
->r_opt
== -10 )
186 s
= _("invalid alias definition");
188 s
= _("invalid option");
189 jnlib_log_error ("%s:%u: %s\n", filename
, *lineno
, s
);
193 s
= arg
->internal
.last
? arg
->internal
.last
:"[??]";
195 if ( arg
->r_opt
== -3 )
196 jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s
);
197 else if ( arg
->r_opt
== -6 )
198 jnlib_log_error (_("option \"%.50s\" does not expect an "
200 else if ( arg
->r_opt
== -7 )
201 jnlib_log_error (_("invalid command \"%.50s\"\n"), s
);
202 else if ( arg
->r_opt
== -8 )
203 jnlib_log_error (_("option \"%.50s\" is ambiguous\n"), s
);
204 else if ( arg
->r_opt
== -9 )
205 jnlib_log_error (_("command \"%.50s\" is ambiguous\n"),s
);
207 jnlib_log_error (_("invalid option \"%.50s\"\n"), s
);
214 /* Zero out the return value union. */
215 arg
->r
.ret_str
= NULL
;
221 store_alias( ARGPARSE_ARGS
*arg
, char *name
, char *value
)
223 /* TODO: replace this dummy function with a rea one
224 * and fix the probelms IRIX has with (ALIAS_DEV)arg..
228 ALIAS_DEF a
= jnlib_xmalloc( sizeof *a
);
231 a
->next
= (ALIAS_DEF
)arg
->internal
.aliases
;
232 (ALIAS_DEF
)arg
->internal
.aliases
= a
;
237 * Get options from a file.
238 * Lines starting with '#' are comment lines.
239 * Syntax is simply a keyword and the argument.
240 * Valid keywords are all keywords from the long_opt list without
241 * the leading dashes. The special keywords "help", "warranty" and "version"
242 * are not valid here.
243 * The special keyword "alias" may be used to store alias definitions,
244 * which are later expanded like long options.
245 * Caller must free returned strings.
246 * If called with FP set to NULL command line args are parse instead.
248 * Q: Should we allow the syntax
250 * and accept for boolean options a value of 1/0, yes/no or true/false?
251 * Note: Abbreviation of options is here not allowed.
254 optfile_parse( FILE *fp
, const char *filename
, unsigned *lineno
,
255 ARGPARSE_ARGS
*arg
, ARGPARSE_OPTS
*opts
)
265 if( !fp
) /* same as arg_parse() in this case */
266 return arg_parse( arg
, opts
);
268 initialize( arg
, filename
, lineno
);
270 /* find the next keyword */
274 if( c
== '\n' || c
== EOF
) {
279 else if( state
== 2 ) {
281 for(i
=0; opts
[i
].short_opt
; i
++ )
282 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, keyword
) )
285 arg
->r_opt
= opts
[idx
].short_opt
;
286 if( inverse
) /* this does not have an effect, hmmm */
287 arg
->r_opt
= -arg
->r_opt
;
288 if( !opts
[idx
].short_opt
) /* unknown command/option */
289 arg
->r_opt
= (opts
[idx
].flags
& 256)? -7:-2;
290 else if( !(opts
[idx
].flags
& 7) ) /* does not take an arg */
291 arg
->r_type
= 0; /* okay */
292 else if( (opts
[idx
].flags
& 8) ) /* argument is optional */
293 arg
->r_type
= 0; /* okay */
294 else /* required argument */
295 arg
->r_opt
= -3; /* error */
298 else if( state
== 3 ) { /* no argument found */
300 arg
->r_opt
= -3; /* error */
301 else if( !(opts
[idx
].flags
& 7) ) /* does not take an arg */
302 arg
->r_type
= 0; /* okay */
303 else if( (opts
[idx
].flags
& 8) ) /* no optional argument */
304 arg
->r_type
= 0; /* okay */
305 else /* no required argument */
306 arg
->r_opt
= -3; /* error */
309 else if( state
== 4 ) { /* have an argument */
317 p
= strpbrk( buffer
, " \t" );
323 jnlib_free( buffer
);
327 store_alias( arg
, buffer
, p
);
331 else if( !(opts
[idx
].flags
& 7) ) /* does not take an arg */
332 arg
->r_opt
= -6; /* error */
337 buffer
= jnlib_xstrdup(keyword
);
342 trim_spaces( buffer
);
344 if( *p
== '"' ) { /* remove quotes */
346 if( *p
&& p
[strlen(p
)-1] == '"' )
349 if( !set_opt_arg(arg
, opts
[idx
].flags
, p
) )
354 else if( c
== EOF
) {
356 arg
->r_opt
= -5; /* read error */
358 arg
->r_opt
= 0; /* eof */
364 else if( state
== -1 )
366 else if( !state
&& isspace(c
) )
367 ; /* skip leading white space */
368 else if( !state
&& c
== '#' )
369 state
= 1; /* start of a comment */
370 else if( state
== 1 )
371 ; /* skip comments */
372 else if( state
== 2 && isspace(c
) ) {
374 for(i
=0; opts
[i
].short_opt
; i
++ )
375 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, keyword
) )
378 arg
->r_opt
= opts
[idx
].short_opt
;
379 if( !opts
[idx
].short_opt
) {
380 if( !strcmp( keyword
, "alias" ) ) {
385 arg
->r_opt
= (opts
[idx
].flags
& 256)? -7:-2;
386 state
= -1; /* skip rest of line and leave */
392 else if( state
== 3 ) { /* skip leading spaces of the argument */
399 else if( state
== 4 ) { /* collect the argument */
405 buffer
= jnlib_xrealloc(buffer
, buflen
);
409 else if( i
< DIM(keyword
)-1 )
412 buflen
= DIM(keyword
)+50;
413 buffer
= jnlib_xmalloc(buflen
);
414 memcpy(buffer
, keyword
, i
);
418 else if( i
>= DIM(keyword
)-1 ) {
419 arg
->r_opt
= -4; /* keyword to long */
420 state
= -1; /* skip rest of line and leave */
434 find_long_option( ARGPARSE_ARGS
*arg
,
435 ARGPARSE_OPTS
*opts
, const char *keyword
)
440 /* Would be better if we can do a binary search, but it is not
441 possible to reorder our option table because we would mess
442 up our help strings - What we can do is: Build a nice option
443 lookup table wehn this function is first invoked */
446 for(i
=0; opts
[i
].short_opt
; i
++ )
447 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, keyword
) )
452 /* see whether it is an alias */
453 for( a
= args
->internal
.aliases
; a
; a
= a
->next
) {
454 if( !strcmp( a
->name
, keyword
) ) {
455 /* todo: must parse the alias here */
456 args
->internal
.cur_alias
= a
;
457 return -3; /* alias available */
462 /* not found, see whether it is an abbreviation */
463 /* aliases may not be abbreviated */
464 n
= strlen( keyword
);
465 for(i
=0; opts
[i
].short_opt
; i
++ ) {
466 if( opts
[i
].long_opt
&& !strncmp( opts
[i
].long_opt
, keyword
, n
) ) {
468 for(j
=i
+1; opts
[j
].short_opt
; j
++ ) {
470 && !strncmp( opts
[j
].long_opt
, keyword
, n
) )
471 return -2; /* abbreviation is ambiguous */
480 arg_parse( ARGPARSE_ARGS
*arg
, ARGPARSE_OPTS
*opts
)
488 initialize( arg
, NULL
, NULL
);
491 idx
= arg
->internal
.idx
;
493 if( !idx
&& argc
&& !(arg
->flags
& (1<<4)) ) { /* skip the first entry */
494 argc
--; argv
++; idx
++;
498 if( !argc
) { /* no more args */
500 goto leave
; /* ready */
504 arg
->internal
.last
= s
;
506 if( arg
->internal
.stopped
&& (arg
->flags
& (1<<1)) ) {
507 arg
->r_opt
= -1; /* not an option but a argument */
510 argc
--; argv
++; idx
++; /* set to next one */
512 else if( arg
->internal
.stopped
) { /* ready */
516 else if( *s
== '-' && s
[1] == '-' ) { /* long option */
519 arg
->internal
.inarg
= 0;
520 if( !s
[2] && !(arg
->flags
& (1<<3)) ) { /* stop option processing */
521 arg
->internal
.stopped
= 1;
522 argc
--; argv
++; idx
++;
526 argpos
= strchr( s
+2, '=' );
529 i
= find_long_option( arg
, opts
, s
+2 );
533 if( i
< 0 && !strcmp( "help", s
+2) )
534 show_help(opts
, arg
->flags
);
535 else if( i
< 0 && !strcmp( "version", s
+2) ) {
536 if( !(arg
->flags
& (1<<6)) ) {
541 else if( i
< 0 && !strcmp( "warranty", s
+2) ) {
542 puts( strusage(16) );
545 else if( i
< 0 && !strcmp( "dump-options", s
+2) ) {
546 for(i
=0; opts
[i
].short_opt
; i
++ ) {
547 if( opts
[i
].long_opt
)
548 printf( "--%s\n", opts
[i
].long_opt
);
550 fputs("--dump-options\n--help\n--version\n--warranty\n", stdout
);
554 if( i
== -2 ) /* ambiguous option */
558 arg
->r
.ret_str
= s
+2;
561 arg
->r_opt
= opts
[i
].short_opt
;
564 else if( (opts
[i
].flags
& 7) ) {
572 if( !s2
&& (opts
[i
].flags
& 8) ) { /* no argument but it is okay*/
573 arg
->r_type
= 0; /* because it is optional */
576 arg
->r_opt
= -3; /* missing argument */
578 else if( !argpos
&& *s2
== '-' && (opts
[i
].flags
& 8) ) {
579 /* the argument is optional and the next seems to be
580 * an option. We do not check this possible option
581 * but assume no argument */
585 set_opt_arg(arg
, opts
[i
].flags
, s2
);
587 argc
--; argv
++; idx
++; /* skip one */
591 else { /* does not take an argument */
593 arg
->r_type
= -6; /* argument not expected */
597 argc
--; argv
++; idx
++; /* set to next one */
599 else if( (*s
== '-' && s
[1]) || arg
->internal
.inarg
) { /* short option */
602 if( !arg
->internal
.inarg
) {
603 arg
->internal
.inarg
++;
604 if( arg
->flags
& (1<<5) ) {
605 for(i
=0; opts
[i
].short_opt
; i
++ )
606 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, s
+1)) {
612 s
+= arg
->internal
.inarg
;
615 for(i
=0; opts
[i
].short_opt
; i
++ )
616 if( opts
[i
].short_opt
== *s
)
620 if( !opts
[i
].short_opt
&& ( *s
== 'h' || *s
== '?' ) )
621 show_help(opts
, arg
->flags
);
623 arg
->r_opt
= opts
[i
].short_opt
;
624 if( !opts
[i
].short_opt
) {
625 arg
->r_opt
= (opts
[i
].flags
& 256)? -7:-2;
626 arg
->internal
.inarg
++; /* point to the next arg */
629 else if( (opts
[i
].flags
& 7) ) {
630 if( s
[1] && !dash_kludge
) {
632 set_opt_arg(arg
, opts
[i
].flags
, s2
);
636 if( !s2
&& (opts
[i
].flags
& 8) ) { /* no argument but it is okay*/
637 arg
->r_type
= 0; /* because it is optional */
640 arg
->r_opt
= -3; /* missing argument */
642 else if( *s2
== '-' && s2
[1] && (opts
[i
].flags
& 8) ) {
643 /* the argument is optional and the next seems to be
644 * an option. We do not check this possible option
645 * but assume no argument */
649 set_opt_arg(arg
, opts
[i
].flags
, s2
);
650 argc
--; argv
++; idx
++; /* skip one */
653 s
= "x"; /* so that !s[1] yields false */
655 else { /* does not take an argument */
657 arg
->internal
.inarg
++; /* point to the next arg */
659 if( !s
[1] || dash_kludge
) { /* no more concatenated short options */
660 arg
->internal
.inarg
= 0;
661 argc
--; argv
++; idx
++;
664 else if( arg
->flags
& (1<<2) ) {
665 arg
->r_opt
= -1; /* not an option but a argument */
668 argc
--; argv
++; idx
++; /* set to next one */
671 arg
->internal
.stopped
= 1; /* stop option processing */
678 arg
->internal
.idx
= idx
;
685 set_opt_arg(ARGPARSE_ARGS
*arg
, unsigned flags
, char *s
)
687 int base
= (flags
& 16)? 0 : 10;
689 switch( arg
->r_type
= (flags
& 7) ) {
690 case 1: /* takes int argument */
691 arg
->r
.ret_int
= (int)strtol(s
,NULL
,base
);
693 case 3: /* takes long argument */
694 arg
->r
.ret_long
= strtol(s
,NULL
,base
);
696 case 4: /* takes ulong argument */
697 arg
->r
.ret_ulong
= strtoul(s
,NULL
,base
);
699 case 2: /* takes string argument */
708 long_opt_strlen( ARGPARSE_OPTS
*o
)
710 size_t n
= strlen (o
->long_opt
);
712 if ( o
->description
&& *o
->description
== '|' )
715 #ifdef JNLIB_NEED_UTF8CONV
716 int is_utf8
= is_native_utf8 ();
722 /* For a (mostly) correct length calculation we exclude
723 continuation bytes (10xxxxxx) if we are on a native utf8
725 for (; *s
&& *s
!= '|'; s
++ )
726 #ifdef JNLIB_NEED_UTF8CONV
727 if ( is_utf8
&& (*s
&0xc0) != 0x80 )
735 * Print formatted help. The description string has some special
737 * - A description string which is "@" suppresses help output for
739 * - a description,ine which starts with a '@' and is followed by
740 * any other characters is printed as is; this may be used for examples
742 * - A description which starts with a '|' outputs the string between this
743 * bar and the next one as arguments of the long option.
746 show_help( ARGPARSE_OPTS
*opts
, unsigned flags
)
754 if( opts
[0].description
) { /* auto format the option description */
756 /* get max. length of long options */
757 for(i
=indent
=0; opts
[i
].short_opt
; i
++ ) {
758 if( opts
[i
].long_opt
)
759 if( !opts
[i
].description
|| *opts
[i
].description
!= '@' )
760 if( (j
=long_opt_strlen(opts
+i
)) > indent
&& j
< 35 )
763 /* example: " -v, --verbose Viele Sachen ausgeben" */
765 if( *opts
[0].description
!= '@' )
767 for(i
=0; opts
[i
].short_opt
; i
++ ) {
768 s
= _( opts
[i
].description
);
769 if( s
&& *s
== '@' && !s
[1] ) /* hide this line */
771 if( s
&& *s
== '@' ) { /* unindented comment only line */
785 if( opts
[i
].short_opt
< 256 ) {
786 printf(" -%c", opts
[i
].short_opt
);
787 if( !opts
[i
].long_opt
) {
788 if(s
&& *s
== '|' ) {
790 for(s
++ ; *s
&& *s
!= '|'; s
++, j
++ )
799 if( opts
[i
].long_opt
) {
800 j
+= printf("%c --%s", opts
[i
].short_opt
< 256?',':' ',
802 if(s
&& *s
== '|' ) {
807 for( ; *s
&& *s
!= '|'; s
++, j
++ )
815 for(;j
< indent
; j
++ )
818 if( *s
&& j
> indent
) {
820 for(j
=0;j
< indent
; j
++ )
827 for(j
=0;j
< indent
; j
++ )
838 puts("\n(A single dash may be used instead of the double ones)");
840 if( (s
=strusage(19)) ) { /* bug reports to ... */
844 s2
= strstr (s
, "@EMAIL@");
848 fwrite (s
, s2
-s
, 1, stdout
);
849 fputs (PACKAGE_BUGREPORT
, stdout
);
868 fputs (strusage (11), stdout
);
869 if ((s
=strusage (12)))
870 printf (" (%s)", s
);
871 printf (" %s\n", strusage (13) );
872 /* Additional version lines. */
873 for (i
=20; i
< 30; i
++)
874 if ((s
=strusage (i
)))
876 /* Copyright string. */
877 if( (s
=strusage (14)) )
879 /* Licence string. */
880 if( (s
=strusage (10)) )
882 /* Copying conditions. */
883 if ( (s
=strusage(15)) )
886 if ((s
=strusage(18)))
888 /* Additional program info. */
889 for (i
=30; i
< 40; i
++ )
890 if ( (s
=strusage (i
)) )
901 fprintf(stderr
,"%s %s; %s\n", strusage(11), strusage(13), strusage (14));
906 fputs (strusage (40), stderr
);
917 * 0: Print copyright string to stderr
918 * 1: Print a short usage hint to stderr and terminate
919 * 2: Print a long usage hint to stdout and terminate
920 * 10: Return license info string
921 * 11: Return the name of the program
922 * 12: Return optional name of package which includes this program.
924 * 14: copyright string
925 * 15: Short copying conditions (with LFs)
926 * 16: Long copying conditions (with LFs)
927 * 17: Optional printable OS name
928 * 18: Optional thanks list (with LFs)
929 * 19: Bug report info
930 *20..29: Additional lib version strings.
931 *30..39: Additional program info (with LFs)
932 * 40: short usage note (with LF)
933 * 41: long usage note (with LF)
936 strusage( int level
)
938 const char *p
= strusage_handler
? strusage_handler(level
) : NULL
;
944 case 10: p
= ("License GPLv3+: GNU GPL version 3 or later "
945 "<http://gnu.org/licenses/gpl.html>");
947 case 11: p
= "foo"; break;
948 case 13: p
= "0.0"; break;
949 case 14: p
= "Copyright (C) 2007 Free Software Foundation, Inc."; break;
951 "This is free software: you are free to change and redistribute it.\n"
952 "There is NO WARRANTY, to the extent permitted by law.\n";
955 "This is free software; you can redistribute it and/or modify\n"
956 "it under the terms of the GNU General Public License as published by\n"
957 "the Free Software Foundation; either version 3 of the License, or\n"
958 "(at your option) any later version.\n\n"
959 "It is distributed in the hope that it will be useful,\n"
960 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
961 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
962 "GNU General Public License for more details.\n\n"
963 "You should have received a copy of the GNU General Public License\n"
964 "along with this software. If not, see <http://www.gnu.org/licenses/>.\n";
966 case 40: /* short and long usage */
967 case 41: p
= ""; break;
974 set_strusage( const char *(*f
)( int ) )
976 strusage_handler
= f
;
992 main(int argc
, char **argv
)
994 ARGPARSE_OPTS opts
[] = {
995 { 'v', "verbose", 0 , "Laut sein"},
996 { 'e', "echo" , 0 , ("Zeile ausgeben, damit wir sehen, was wir ein"
998 { 'd', "debug", 0 , "Debug\nfalls mal etwas\nschief geht"},
999 { 'o', "output", 2 },
1000 { 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" },
1001 /* Note that on a non-utf8 terminal the ß might garble the output. */
1002 { 's', "street", 0, "|Straße|set the name of the street to Straße" },
1003 { 'm', "my-option", 1|8 },
1004 { 500, "a-long-option", 0 },
1006 ARGPARSE_ARGS pargs
= { &argc
, &argv
, 2|4|32 };
1009 while( arg_parse ( &pargs
, opts
) ) {
1010 switch( pargs
.r_opt
) {
1011 case -1 : printf( "arg=`%s'\n", pargs
.r
.ret_str
); break;
1012 case 'v': opt
.verbose
++; break;
1013 case 'e': opt
.echo
++; break;
1014 case 'd': opt
.debug
++; break;
1015 case 'o': opt
.outfile
= pargs
.r
.ret_str
; break;
1016 case 'c': opt
.crf
= pargs
.r_type
? pargs
.r
.ret_str
:"a.crf"; break;
1017 case 'm': opt
.myopt
= pargs
.r_type
? pargs
.r
.ret_int
: 1; break;
1018 case 500: opt
.a_long_one
++; break;
1019 default : pargs
.err
= 1; break; /* force warning output */
1022 for(i
=0; i
< argc
; i
++ )
1023 printf("%3d -> (%s)\n", i
, argv
[i
] );
1026 printf(" verbose=%d\n", opt
.verbose
);
1028 printf(" debug=%d\n", opt
.debug
);
1030 printf(" outfile=`%s'\n", opt
.outfile
);
1032 printf(" crffile=`%s'\n", opt
.crf
);
1034 printf(" myopt=%d\n", opt
.myopt
);
1035 if( opt
.a_long_one
)
1036 printf(" a-long-one=%d\n", opt
.a_long_one
);
1038 printf(" echo=%d\n", opt
.echo
);
1043 /**** bottom of file ****/