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 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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 #include "libjnlib-config.h"
31 #include "stringhelp.h"
33 #ifdef JNLIB_NEED_UTF8CONV
39 /*********************************
44 * char *argc; pointer to argc (value subject to change)
45 * char ***argv; pointer to argv (value subject to change)
46 * unsigned flags; Global flags (DO NOT CHANGE)
47 * int err; print error about last option
48 * 1 = warning, 2 = abort
49 * int r_opt; return option
50 * int r_type; type of return value (0 = no argument found)
61 * } internal; DO NOT CHANGE
66 * const char *long_opt;
70 * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
73 * This is my replacement for getopt(). See the example for a typical usage.
75 * Bit 0 : Do not remove options form argv
76 * Bit 1 : Do not stop at last option but return other args
77 * with r_opt set to -1.
78 * Bit 2 : Assume options and real args are mixed.
79 * Bit 3 : Do not use -- to stop option processing.
80 * Bit 4 : Do not skip the first arg.
81 * Bit 5 : allow usage of long option with only one dash
82 * Bit 6 : ignore --version
83 * all other bits must be set to zero, this value is modified by the
84 * function, so assume this is write only.
85 * Local flags (for each option):
86 * Bit 2-0 : 0 = does not take an argument
87 * 1 = takes int argument
88 * 2 = takes string argument
89 * 3 = takes long argument
90 * 4 = takes ulong argument
91 * Bit 3 : argument is optional (r_type will the be set to 0)
92 * Bit 4 : allow 0x etc. prefixed values.
93 * Bit 7 : this is a command and not an option
94 * You stop the option processing by setting opts to NULL, the function will
97 * Returns the args.r_opt or 0 if ready
98 * r_opt may be -2/-7 to indicate an unknown option/command.
102 * You do not need to process the options 'h', '--help' or '--version'
103 * because this function includes standard help processing; but if you
104 * specify '-h', '--help' or '--version' you have to do it yourself.
105 * The option '--' stops argument processing; if bit 1 is set the function
106 * continues to return normal arguments.
107 * To process float args or unsigned args you must use a string args and do
108 * the conversion yourself.
111 * ARGPARSE_OPTS opts[] = {
112 * { 'v', "verbose", 0 },
113 * { 'd', "debug", 0 },
114 * { 'o', "output", 2 },
115 * { 'c', "cross-ref", 2|8 },
116 * { 'm', "my-option", 1|8 },
117 * { 500, "have-no-short-option-for-this-long-option", 0 },
119 * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
121 * while( ArgParse( &pargs, &opts) ) {
122 * switch( pargs.r_opt ) {
123 * case 'v': opt.verbose++; break;
124 * case 'd': opt.debug++; break;
125 * case 'o': opt.outfile = pargs.r.ret_str; break;
126 * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
127 * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
128 * case 500: opt.a_long_one++; break
129 * default : pargs.err = 1; break; -- force warning output --
133 * log_fatal( "Too many args");
137 typedef struct alias_def_s
*ALIAS_DEF
;
140 char *name
; /* malloced buffer with name, \0, value */
141 const char *value
; /* ptr into name */
144 static const char *(*strusage_handler
)( int ) = NULL
;
146 static int set_opt_arg(ARGPARSE_ARGS
*arg
, unsigned flags
, char *s
);
147 static void show_help(ARGPARSE_OPTS
*opts
, unsigned flags
);
148 static void show_version(void);
152 initialize( ARGPARSE_ARGS
*arg
, const char *filename
, unsigned *lineno
)
154 if( !(arg
->flags
& (1<<15)) ) { /* 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 initialized */
164 jnlib_log_bug("Invalid argument for ArgParse\n");
168 if( arg
->err
) { /* last option was erroneous */
172 if( arg
->r_opt
== -6 )
173 s
= "argument not expected\n";
174 else if( arg
->r_opt
== -5 )
176 else if( arg
->r_opt
== -4 )
177 s
= "keyword too long\n";
178 else if( arg
->r_opt
== -3 )
179 s
= "missing argument\n";
180 else if( arg
->r_opt
== -7 )
181 s
= "invalid command\n";
182 else if( arg
->r_opt
== -10 )
183 s
= "invalid alias definition\n";
185 s
= "invalid option\n";
186 jnlib_log_error("%s:%u: %s\n", filename
, *lineno
, s
);
189 s
= arg
->internal
.last
? arg
->internal
.last
:"[??]";
191 if( arg
->r_opt
== -3 )
192 jnlib_log_error ("Missing argument for option \"%.50s\"\n", s
);
193 else if( arg
->r_opt
== -6 )
194 jnlib_log_error ("Option \"%.50s\" does not expect an argument\n",
196 else if( arg
->r_opt
== -7 )
197 jnlib_log_error ("Invalid command \"%.50s\"\n", s
);
198 else if( arg
->r_opt
== -8 )
199 jnlib_log_error ("Option \"%.50s\" is ambiguous\n", s
);
200 else if( arg
->r_opt
== -9 )
201 jnlib_log_error ("Command \"%.50s\" is ambiguous\n",s
);
203 jnlib_log_error ("Invalid option \"%.50s\"\n", s
);
210 /* clearout the return value union */
211 arg
->r
.ret_str
= NULL
;
217 store_alias( ARGPARSE_ARGS
*arg
, char *name
, char *value
)
219 /* TODO: replace this dummy function with a rea one
220 * and fix the probelms IRIX has with (ALIAS_DEV)arg..
224 ALIAS_DEF a
= jnlib_xmalloc( sizeof *a
);
227 a
->next
= (ALIAS_DEF
)arg
->internal
.aliases
;
228 (ALIAS_DEF
)arg
->internal
.aliases
= a
;
233 * Get options from a file.
234 * Lines starting with '#' are comment lines.
235 * Syntax is simply a keyword and the argument.
236 * Valid keywords are all keywords from the long_opt list without
237 * the leading dashes. The special keywords "help", "warranty" and "version"
238 * are not valid here.
239 * The special keyword "alias" may be used to store alias definitions,
240 * which are later expanded like long options.
241 * Caller must free returned strings.
242 * If called with FP set to NULL command line args are parse instead.
244 * Q: Should we allow the syntax
246 * and accept for boolean options a value of 1/0, yes/no or true/false?
247 * Note: Abbreviation of options is here not allowed.
250 optfile_parse( FILE *fp
, const char *filename
, unsigned *lineno
,
251 ARGPARSE_ARGS
*arg
, ARGPARSE_OPTS
*opts
)
261 if( !fp
) /* same as arg_parse() in this case */
262 return arg_parse( arg
, opts
);
264 initialize( arg
, filename
, lineno
);
266 /* find the next keyword */
270 if( c
== '\n' || c
== EOF
) {
275 else if( state
== 2 ) {
277 for(i
=0; opts
[i
].short_opt
; i
++ )
278 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, keyword
) )
281 arg
->r_opt
= opts
[idx
].short_opt
;
282 if( inverse
) /* this does not have an effect, hmmm */
283 arg
->r_opt
= -arg
->r_opt
;
284 if( !opts
[idx
].short_opt
) /* unknown command/option */
285 arg
->r_opt
= (opts
[idx
].flags
& 256)? -7:-2;
286 else if( !(opts
[idx
].flags
& 7) ) /* does not take an arg */
287 arg
->r_type
= 0; /* okay */
288 else if( (opts
[idx
].flags
& 8) ) /* argument is optional */
289 arg
->r_type
= 0; /* okay */
290 else /* required argument */
291 arg
->r_opt
= -3; /* error */
294 else if( state
== 3 ) { /* no argument found */
296 arg
->r_opt
= -3; /* error */
297 else if( !(opts
[idx
].flags
& 7) ) /* does not take an arg */
298 arg
->r_type
= 0; /* okay */
299 else if( (opts
[idx
].flags
& 8) ) /* no optional argument */
300 arg
->r_type
= 0; /* okay */
301 else /* no required argument */
302 arg
->r_opt
= -3; /* error */
305 else if( state
== 4 ) { /* have an argument */
313 p
= strpbrk( buffer
, " \t" );
319 jnlib_free( buffer
);
323 store_alias( arg
, buffer
, p
);
327 else if( !(opts
[idx
].flags
& 7) ) /* does not take an arg */
328 arg
->r_opt
= -6; /* error */
333 buffer
= jnlib_xstrdup(keyword
);
338 trim_spaces( buffer
);
340 if( *p
== '"' ) { /* remove quotes */
342 if( *p
&& p
[strlen(p
)-1] == '"' )
345 if( !set_opt_arg(arg
, opts
[idx
].flags
, p
) )
350 else if( c
== EOF
) {
352 arg
->r_opt
= -5; /* read error */
354 arg
->r_opt
= 0; /* eof */
360 else if( state
== -1 )
362 else if( !state
&& isspace(c
) )
363 ; /* skip leading white space */
364 else if( !state
&& c
== '#' )
365 state
= 1; /* start of a comment */
366 else if( state
== 1 )
367 ; /* skip comments */
368 else if( state
== 2 && isspace(c
) ) {
370 for(i
=0; opts
[i
].short_opt
; i
++ )
371 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, keyword
) )
374 arg
->r_opt
= opts
[idx
].short_opt
;
375 if( !opts
[idx
].short_opt
) {
376 if( !strcmp( keyword
, "alias" ) ) {
381 arg
->r_opt
= (opts
[idx
].flags
& 256)? -7:-2;
382 state
= -1; /* skip rest of line and leave */
388 else if( state
== 3 ) { /* skip leading spaces of the argument */
395 else if( state
== 4 ) { /* collect the argument */
401 buffer
= jnlib_xrealloc(buffer
, buflen
);
405 else if( i
< DIM(keyword
)-1 )
408 buflen
= DIM(keyword
)+50;
409 buffer
= jnlib_xmalloc(buflen
);
410 memcpy(buffer
, keyword
, i
);
414 else if( i
>= DIM(keyword
)-1 ) {
415 arg
->r_opt
= -4; /* keyword to long */
416 state
= -1; /* skip rest of line and leave */
430 find_long_option( ARGPARSE_ARGS
*arg
,
431 ARGPARSE_OPTS
*opts
, const char *keyword
)
436 /* Would be better if we can do a binary search, but it is not
437 possible to reorder our option table because we would mess
438 up our help strings - What we can do is: Build a nice option
439 lookup table wehn this function is first invoked */
442 for(i
=0; opts
[i
].short_opt
; i
++ )
443 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, keyword
) )
448 /* see whether it is an alias */
449 for( a
= args
->internal
.aliases
; a
; a
= a
->next
) {
450 if( !strcmp( a
->name
, keyword
) ) {
451 /* todo: must parse the alias here */
452 args
->internal
.cur_alias
= a
;
453 return -3; /* alias available */
458 /* not found, see whether it is an abbreviation */
459 /* aliases may not be abbreviated */
460 n
= strlen( keyword
);
461 for(i
=0; opts
[i
].short_opt
; i
++ ) {
462 if( opts
[i
].long_opt
&& !strncmp( opts
[i
].long_opt
, keyword
, n
) ) {
464 for(j
=i
+1; opts
[j
].short_opt
; j
++ ) {
466 && !strncmp( opts
[j
].long_opt
, keyword
, n
) )
467 return -2; /* abbreviation is ambiguous */
476 arg_parse( ARGPARSE_ARGS
*arg
, ARGPARSE_OPTS
*opts
)
484 initialize( arg
, NULL
, NULL
);
487 idx
= arg
->internal
.idx
;
489 if( !idx
&& argc
&& !(arg
->flags
& (1<<4)) ) { /* skip the first entry */
490 argc
--; argv
++; idx
++;
494 if( !argc
) { /* no more args */
496 goto leave
; /* ready */
500 arg
->internal
.last
= s
;
502 if( arg
->internal
.stopped
&& (arg
->flags
& (1<<1)) ) {
503 arg
->r_opt
= -1; /* not an option but a argument */
506 argc
--; argv
++; idx
++; /* set to next one */
508 else if( arg
->internal
.stopped
) { /* ready */
512 else if( *s
== '-' && s
[1] == '-' ) { /* long option */
515 arg
->internal
.inarg
= 0;
516 if( !s
[2] && !(arg
->flags
& (1<<3)) ) { /* stop option processing */
517 arg
->internal
.stopped
= 1;
518 argc
--; argv
++; idx
++;
522 argpos
= strchr( s
+2, '=' );
525 i
= find_long_option( arg
, opts
, s
+2 );
529 if( i
< 0 && !strcmp( "help", s
+2) )
530 show_help(opts
, arg
->flags
);
531 else if( i
< 0 && !strcmp( "version", s
+2) ) {
532 if( !(arg
->flags
& (1<<6)) ) {
537 else if( i
< 0 && !strcmp( "warranty", s
+2) ) {
538 puts( strusage(16) );
541 else if( i
< 0 && !strcmp( "dump-options", s
+2) ) {
542 for(i
=0; opts
[i
].short_opt
; i
++ ) {
543 if( opts
[i
].long_opt
)
544 printf( "--%s\n", opts
[i
].long_opt
);
546 fputs("--dump-options\n--help\n--version\n--warranty\n", stdout
);
550 if( i
== -2 ) /* ambiguous option */
554 arg
->r
.ret_str
= s
+2;
557 arg
->r_opt
= opts
[i
].short_opt
;
560 else if( (opts
[i
].flags
& 7) ) {
568 if( !s2
&& (opts
[i
].flags
& 8) ) { /* no argument but it is okay*/
569 arg
->r_type
= 0; /* because it is optional */
572 arg
->r_opt
= -3; /* missing argument */
574 else if( !argpos
&& *s2
== '-' && (opts
[i
].flags
& 8) ) {
575 /* the argument is optional and the next seems to be
576 * an option. We do not check this possible option
577 * but assume no argument */
581 set_opt_arg(arg
, opts
[i
].flags
, s2
);
583 argc
--; argv
++; idx
++; /* skip one */
587 else { /* does not take an argument */
589 arg
->r_type
= -6; /* argument not expected */
593 argc
--; argv
++; idx
++; /* set to next one */
595 else if( (*s
== '-' && s
[1]) || arg
->internal
.inarg
) { /* short option */
598 if( !arg
->internal
.inarg
) {
599 arg
->internal
.inarg
++;
600 if( arg
->flags
& (1<<5) ) {
601 for(i
=0; opts
[i
].short_opt
; i
++ )
602 if( opts
[i
].long_opt
&& !strcmp( opts
[i
].long_opt
, s
+1)) {
608 s
+= arg
->internal
.inarg
;
611 for(i
=0; opts
[i
].short_opt
; i
++ )
612 if( opts
[i
].short_opt
== *s
)
616 if( !opts
[i
].short_opt
&& ( *s
== 'h' || *s
== '?' ) )
617 show_help(opts
, arg
->flags
);
619 arg
->r_opt
= opts
[i
].short_opt
;
620 if( !opts
[i
].short_opt
) {
621 arg
->r_opt
= (opts
[i
].flags
& 256)? -7:-2;
622 arg
->internal
.inarg
++; /* point to the next arg */
625 else if( (opts
[i
].flags
& 7) ) {
626 if( s
[1] && !dash_kludge
) {
628 set_opt_arg(arg
, opts
[i
].flags
, s2
);
632 if( !s2
&& (opts
[i
].flags
& 8) ) { /* no argument but it is okay*/
633 arg
->r_type
= 0; /* because it is optional */
636 arg
->r_opt
= -3; /* missing argument */
638 else if( *s2
== '-' && s2
[1] && (opts
[i
].flags
& 8) ) {
639 /* the argument is optional and the next seems to be
640 * an option. We do not check this possible option
641 * but assume no argument */
645 set_opt_arg(arg
, opts
[i
].flags
, s2
);
646 argc
--; argv
++; idx
++; /* skip one */
649 s
= "x"; /* so that !s[1] yields false */
651 else { /* does not take an argument */
653 arg
->internal
.inarg
++; /* point to the next arg */
655 if( !s
[1] || dash_kludge
) { /* no more concatenated short options */
656 arg
->internal
.inarg
= 0;
657 argc
--; argv
++; idx
++;
660 else if( arg
->flags
& (1<<2) ) {
661 arg
->r_opt
= -1; /* not an option but a argument */
664 argc
--; argv
++; idx
++; /* set to next one */
667 arg
->internal
.stopped
= 1; /* stop option processing */
674 arg
->internal
.idx
= idx
;
681 set_opt_arg(ARGPARSE_ARGS
*arg
, unsigned flags
, char *s
)
683 int base
= (flags
& 16)? 0 : 10;
685 switch( arg
->r_type
= (flags
& 7) ) {
686 case 1: /* takes int argument */
687 arg
->r
.ret_int
= (int)strtol(s
,NULL
,base
);
689 case 3: /* takes long argument */
690 arg
->r
.ret_long
= strtol(s
,NULL
,base
);
692 case 4: /* takes ulong argument */
693 arg
->r
.ret_ulong
= strtoul(s
,NULL
,base
);
695 case 2: /* takes string argument */
704 long_opt_strlen( ARGPARSE_OPTS
*o
)
706 size_t n
= strlen (o
->long_opt
);
708 if ( o
->description
&& *o
->description
== '|' )
711 #ifdef JNLIB_NEED_UTF8CONV
712 int is_utf8
= is_native_utf8 ();
718 /* For a (mostly) correct length calculation we exclude
719 continuation bytes (10xxxxxx) if we are on a native utf8
721 for (; *s
&& *s
!= '|'; s
++ )
722 #ifdef JNLIB_NEED_UTF8CONV
723 if ( is_utf8
&& (*s
&0xc0) != 0x80 )
731 * Print formatted help. The description string has some special
733 * - A description string which is "@" suppresses help output for
735 * - a description,ine which starts with a '@' and is followed by
736 * any other characters is printed as is; this may be used for examples
738 * - A description which starts with a '|' outputs the string between this
739 * bar and the next one as arguments of the long option.
742 show_help( ARGPARSE_OPTS
*opts
, unsigned flags
)
750 if( opts
[0].description
) { /* auto format the option description */
752 /* get max. length of long options */
753 for(i
=indent
=0; opts
[i
].short_opt
; i
++ ) {
754 if( opts
[i
].long_opt
)
755 if( !opts
[i
].description
|| *opts
[i
].description
!= '@' )
756 if( (j
=long_opt_strlen(opts
+i
)) > indent
&& j
< 35 )
759 /* example: " -v, --verbose Viele Sachen ausgeben" */
761 if( *opts
[0].description
!= '@' )
763 for(i
=0; opts
[i
].short_opt
; i
++ ) {
764 s
= _( opts
[i
].description
);
765 if( s
&& *s
== '@' && !s
[1] ) /* hide this line */
767 if( s
&& *s
== '@' ) { /* unindented comment only line */
781 if( opts
[i
].short_opt
< 256 ) {
782 printf(" -%c", opts
[i
].short_opt
);
783 if( !opts
[i
].long_opt
) {
784 if(s
&& *s
== '|' ) {
786 for(s
++ ; *s
&& *s
!= '|'; s
++, j
++ )
795 if( opts
[i
].long_opt
) {
796 j
+= printf("%c --%s", opts
[i
].short_opt
< 256?',':' ',
798 if(s
&& *s
== '|' ) {
803 for( ; *s
&& *s
!= '|'; s
++, j
++ )
811 for(;j
< indent
; j
++ )
814 if( *s
&& j
> indent
) {
816 for(j
=0;j
< indent
; j
++ )
823 for(j
=0;j
< indent
; j
++ )
834 puts("\n(A single dash may be used instead of the double ones)");
836 if( (s
=strusage(19)) ) { /* bug reports to ... */
850 fputs(strusage(11), stdout
);
851 if( (s
=strusage(12)) )
853 printf(" %s\n", strusage(13) );
854 /* additional version lines */
855 for(i
=20; i
< 30; i
++ )
856 if( (s
=strusage(i
)) )
858 /* copyright string */
859 if( (s
=strusage(14)) )
861 /* copying conditions */
862 if( (s
=strusage(15)) )
865 if( (s
=strusage(18)) )
867 /* additional program info */
868 for(i
=30; i
< 40; i
++ )
869 if( (s
=strusage(i
)) )
879 fprintf(stderr
,"%s %s; %s\n", strusage(11), strusage(13),
883 else if( level
== 1 ) {
884 fputs(strusage(40),stderr
);
887 else if( level
== 2 ) {
894 * 0: Copyright String auf stderr ausgeben
895 * 1: Kurzusage auf stderr ausgeben und beenden
896 * 2: Langusage auf stdout ausgeben und beenden
897 * 11: name of program
898 * 12: optional name of package which includes this program.
900 * 14: copyright string
901 * 15: Short copying conditions (with LFs)
902 * 16: Long copying conditions (with LFs)
903 * 17: Optional printable OS name
904 * 18: Optional thanks list (with LFs)
905 * 19: Bug report info
906 *20..29: Additional lib version strings.
907 *30..39: Additional program info (with LFs)
908 * 40: short usage note (with LF)
909 * 41: long usage note (with LF)
912 strusage( int level
)
914 const char *p
= strusage_handler
? strusage_handler(level
) : NULL
;
920 case 11: p
= "foo"; break;
921 case 13: p
= "0.0"; break;
922 case 14: p
= "Copyright (C) 2007 Free Software Foundation, Inc."; break;
924 "This program comes with ABSOLUTELY NO WARRANTY.\n"
925 "This is free software, and you are welcome to redistribute it\n"
926 "under certain conditions. See the file COPYING for details.\n"; break;
928 "This is free software; you can redistribute it and/or modify\n"
929 "it under the terms of the GNU General Public License as published by\n"
930 "the Free Software Foundation; either version 2 of the License, or\n"
931 "(at your option) any later version.\n\n"
932 "It is distributed in the hope that it will be useful,\n"
933 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
934 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
935 "GNU General Public License for more details.\n\n"
936 "You should have received a copy of the GNU General Public License\n"
937 "along with this program; if not, write to the Free Software\n"
938 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
941 case 40: /* short and long usage */
942 case 41: p
= ""; break;
949 set_strusage( const char *(*f
)( int ) )
951 strusage_handler
= f
;
967 main(int argc
, char **argv
)
969 ARGPARSE_OPTS opts
[] = {
970 { 'v', "verbose", 0 , "Laut sein"},
971 { 'e', "echo" , 0 , ("Zeile ausgeben, damit wir sehen, was wir ein"
973 { 'd', "debug", 0 , "Debug\nfalls mal etwas\nschief geht"},
974 { 'o', "output", 2 },
975 { 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" },
976 /* Note that on a non-utf8 terminal the ß might garble the output. */
977 { 's', "street", 0, "|Straße|set the name of the street to Straße" },
978 { 'm', "my-option", 1|8 },
979 { 500, "a-long-option", 0 },
981 ARGPARSE_ARGS pargs
= { &argc
, &argv
, 2|4|32 };
984 while( arg_parse ( &pargs
, opts
) ) {
985 switch( pargs
.r_opt
) {
986 case -1 : printf( "arg=`%s'\n", pargs
.r
.ret_str
); break;
987 case 'v': opt
.verbose
++; break;
988 case 'e': opt
.echo
++; break;
989 case 'd': opt
.debug
++; break;
990 case 'o': opt
.outfile
= pargs
.r
.ret_str
; break;
991 case 'c': opt
.crf
= pargs
.r_type
? pargs
.r
.ret_str
:"a.crf"; break;
992 case 'm': opt
.myopt
= pargs
.r_type
? pargs
.r
.ret_int
: 1; break;
993 case 500: opt
.a_long_one
++; break;
994 default : pargs
.err
= 1; break; /* force warning output */
997 for(i
=0; i
< argc
; i
++ )
998 printf("%3d -> (%s)\n", i
, argv
[i
] );
1001 printf(" verbose=%d\n", opt
.verbose
);
1003 printf(" debug=%d\n", opt
.debug
);
1005 printf(" outfile=`%s'\n", opt
.outfile
);
1007 printf(" crffile=`%s'\n", opt
.crf
);
1009 printf(" myopt=%d\n", opt
.myopt
);
1010 if( opt
.a_long_one
)
1011 printf(" a-long-one=%d\n", opt
.a_long_one
);
1013 printf(" echo=%d\n", opt
.echo
);
1018 /**** bottom of file ****/