summaryrefslogtreecommitdiffstats
path: root/util/argparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/argparse.c')
-rw-r--r--util/argparse.c996
1 files changed, 0 insertions, 996 deletions
diff --git a/util/argparse.c b/util/argparse.c
deleted file mode 100644
index ba51980a9..000000000
--- a/util/argparse.c
+++ /dev/null
@@ -1,996 +0,0 @@
-/* [argparse.c wk 17.06.97] Argument Parser for option handling
- * Copyright (C) 1998,1999 Free Software Foundation, Inc.
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "libutil-config.h"
-#include "mischelp.h"
-#include "stringhelp.h"
-#ifndef LIBUTIL_CONFIG_OF_GNUPG
- #include "logging.h" /* currently not used in GnUPG */
-#endif
-#include "argparse.h"
-
-
-/*********************************
- * @Summary arg_parse
- * #include <wk/lib.h>
- *
- * typedef struct {
- * char *argc; pointer to argc (value subject to change)
- * char ***argv; pointer to argv (value subject to change)
- * unsigned flags; Global flags (DO NOT CHANGE)
- * int err; print error about last option
- * 1 = warning, 2 = abort
- * int r_opt; return option
- * int r_type; type of return value (0 = no argument found)
- * union {
- * int ret_int;
- * long ret_long
- * ulong ret_ulong;
- * char *ret_str;
- * } r; Return values
- * struct {
- * int idx;
- * const char *last;
- * void *aliases;
- * } internal; DO NOT CHANGE
- * } ARGPARSE_ARGS;
- *
- * typedef struct {
- * int short_opt;
- * const char *long_opt;
- * unsigned flags;
- * } ARGPARSE_OPTS;
- *
- * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
- *
- * @Description
- * This is my replacement for getopt(). See the example for a typical usage.
- * Global flags are:
- * Bit 0 : Do not remove options form argv
- * Bit 1 : Do not stop at last option but return other args
- * with r_opt set to -1.
- * Bit 2 : Assume options and real args are mixed.
- * Bit 3 : Do not use -- to stop option processing.
- * Bit 4 : Do not skip the first arg.
- * Bit 5 : allow usage of long option with only one dash
- * Bit 6 : ignore --version
- * all other bits must be set to zero, this value is modified by the
- * function, so assume this is write only.
- * Local flags (for each option):
- * Bit 2-0 : 0 = does not take an argument
- * 1 = takes int argument
- * 2 = takes string argument
- * 3 = takes long argument
- * 4 = takes ulong argument
- * Bit 3 : argument is optional (r_type will the be set to 0)
- * Bit 4 : allow 0x etc. prefixed values.
- * Bit 7 : this is a command and not an option
- * You stop the option processing by setting opts to NULL, the function will
- * then return 0.
- * @Return Value
- * Returns the args.r_opt or 0 if ready
- * r_opt may be -2/-7 to indicate an unknown option/command.
- * @See Also
- * ArgExpand
- * @Notes
- * You do not need to process the options 'h', '--help' or '--version'
- * because this function includes standard help processing; but if you
- * specify '-h', '--help' or '--version' you have to do it yourself.
- * The option '--' stops argument processing; if bit 1 is set the function
- * continues to return normal arguments.
- * To process float args or unsigned args you must use a string args and do
- * the conversion yourself.
- * @Example
- *
- * ARGPARSE_OPTS opts[] = {
- * { 'v', "verbose", 0 },
- * { 'd', "debug", 0 },
- * { 'o', "output", 2 },
- * { 'c', "cross-ref", 2|8 },
- * { 'm', "my-option", 1|8 },
- * { 500, "have-no-short-option-for-this-long-option", 0 },
- * {0} };
- * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
- *
- * while( ArgParse( &pargs, &opts) ) {
- * switch( pargs.r_opt ) {
- * case 'v': opt.verbose++; break;
- * case 'd': opt.debug++; break;
- * case 'o': opt.outfile = pargs.r.ret_str; break;
- * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
- * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
- * case 500: opt.a_long_one++; break
- * default : pargs.err = 1; break; -- force warning output --
- * }
- * }
- * if( argc > 1 )
- * log_fatal( "Too many args");
- *
- */
-
-typedef struct alias_def_s *ALIAS_DEF;
-struct alias_def_s {
- ALIAS_DEF next;
- char *name; /* malloced buffer with name, \0, value */
- const char *value; /* ptr into name */
-};
-
-static const char *(*strusage_handler)( int ) = NULL;
-
-static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
-static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
-static void show_version(void);
-
-
-static void
-initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
-{
- if( !(arg->flags & (1<<15)) ) { /* initialize this instance */
- arg->internal.idx = 0;
- arg->internal.last = NULL;
- arg->internal.inarg = 0;
- arg->internal.stopped = 0;
- arg->internal.aliases = NULL;
- arg->internal.cur_alias = NULL;
- arg->err = 0;
- arg->flags |= 1<<15; /* mark initialized */
- if( *arg->argc < 0 )
- libutil_log_bug("Invalid argument for ArgParse\n");
- }
-
-
- if( arg->err ) { /* last option was erroneous */
- const char *s;
-
- if( filename ) {
- if( arg->r_opt == -6 )
- s = "%s:%u: argument not expected\n";
- else if( arg->r_opt == -5 )
- s = "%s:%u: read error\n";
- else if( arg->r_opt == -4 )
- s = "%s:%u: keyword too long\n";
- else if( arg->r_opt == -3 )
- s = "%s:%u: missing argument\n";
- else if( arg->r_opt == -7 )
- s = "%s:%u: invalid command\n";
- else if( arg->r_opt == -10 )
- s = "%s:%u: invalid alias definition\n";
- else
- s = "%s:%u: invalid option\n";
- libutil_log_error(s, filename, *lineno );
- }
- else {
- if( arg->r_opt == -3 )
- s = "Missing argument for option \"%.50s\"\n";
- else if( arg->r_opt == -6 )
- s = "Option \"%.50s\" does not expect an argument\n";
- else if( arg->r_opt == -7 )
- s = "Invalid command \"%.50s\"\n";
- else if( arg->r_opt == -8 )
- s = "Option \"%.50s\" is ambiguous\n";
- else if( arg->r_opt == -9 )
- s = "Command \"%.50s\" is ambiguous\n";
- else
- s = "Invalid option \"%.50s\"\n";
- libutil_log_error(s, arg->internal.last? arg->internal.last:"[??]" );
- }
- if( arg->err != 1 )
- exit(2);
- arg->err = 0;
- }
-
- /* clearout the return value union */
- arg->r.ret_str = NULL;
- arg->r.ret_long= 0;
-}
-
-
-static void
-store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
-{
- /* TODO: replace this dummy function with a rea one
- * and fix the probelms IRIX has with (ALIAS_DEV)arg..
- * used as lvalue
- */
-#if 0
- ALIAS_DEF a = m_alloc( sizeof *a );
- a->name = name;
- a->value = value;
- a->next = (ALIAS_DEF)arg->internal.aliases;
- (ALIAS_DEF)arg->internal.aliases = a;
-#endif
-}
-
-/****************
- * Get options from a file.
- * Lines starting with '#' are comment lines.
- * Syntax is simply a keyword and the argument.
- * Valid keywords are all keywords from the long_opt list without
- * the leading dashes. The special keywords "help", "warranty" and "version"
- * are not valid here.
- * The special keyword "alias" may be used to store alias definitions,
- * which are later expanded like long options.
- * Caller must free returned strings.
- * If called with FP set to NULL command line args are parse instead.
- *
- * Q: Should we allow the syntax
- * keyword = value
- * and accept for boolean options a value of 1/0, yes/no or true/false?
- * Note: Abbreviation of options is here not allowed.
- */
-int
-optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
- ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
-{
- int state, i, c;
- int idx=0;
- char keyword[100];
- char *buffer = NULL;
- size_t buflen = 0;
- int inverse=0;
- int in_alias=0;
-
- if( !fp ) /* same as arg_parse() in this case */
- return arg_parse( arg, opts );
-
- initialize( arg, filename, lineno );
-
- /* find the next keyword */
- state = i = 0;
- for(;;) {
- c=getc(fp);
- if( c == '\n' || c== EOF ) {
- if( c != EOF )
- ++*lineno;
- if( state == -1 )
- break;
- else if( state == 2 ) {
- keyword[i] = 0;
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
- break;
- idx = i;
- arg->r_opt = opts[idx].short_opt;
- if( inverse ) /* this does not have an effect, hmmm */
- arg->r_opt = -arg->r_opt;
- if( !opts[idx].short_opt ) /* unknown command/option */
- arg->r_opt = (opts[idx].flags & 256)? -7:-2;
- else if( (opts[idx].flags & 8) ) /* no argument */
- arg->r_opt = -3; /* error */
- else /* no or optional argument */
- arg->r_type = 0; /* okay */
- break;
- }
- else if( state == 3 ) { /* no argument found */
- if( in_alias )
- arg->r_opt = -3; /* error */
- else if( !(opts[idx].flags & 7) ) /* does not take an arg */
- arg->r_type = 0; /* okay */
- else if( (opts[idx].flags & 8) ) /* no optional argument */
- arg->r_type = 0; /* okay */
- else /* no required argument */
- arg->r_opt = -3; /* error */
- break;
- }
- else if( state == 4 ) { /* have an argument */
- if( in_alias ) {
- if( !buffer )
- arg->r_opt = -6;
- else {
- char *p;
-
- buffer[i] = 0;
- p = strpbrk( buffer, " \t" );
- if( p ) {
- *p++ = 0;
- trim_spaces( p );
- }
- if( !p || !*p ) {
- libutil_free( buffer );
- arg->r_opt = -10;
- }
- else {
- store_alias( arg, buffer, p );
- }
- }
- }
- else if( !(opts[idx].flags & 7) ) /* does not take an arg */
- arg->r_opt = -6; /* error */
- else {
- char *p;
- if( !buffer ) {
- keyword[i] = 0;
- buffer = libutil_strdup(keyword);
- }
- else
- buffer[i] = 0;
-
- trim_spaces( buffer );
- p = buffer;
- if( *p == '"' ) { /* remove quotes */
- p++;
- if( *p && p[strlen(p)-1] == '"' )
- p[strlen(p)-1] = 0;
- }
- if( !set_opt_arg(arg, opts[idx].flags, p) )
- libutil_free(buffer);
- }
- break;
- }
- else if( c == EOF ) {
- if( ferror(fp) )
- arg->r_opt = -5; /* read error */
- else
- arg->r_opt = 0; /* eof */
- break;
- }
- state = 0;
- i = 0;
- }
- else if( state == -1 )
- ; /* skip */
- else if( !state && isspace(c) )
- ; /* skip leading white space */
- else if( !state && c == '#' )
- state = 1; /* start of a comment */
- else if( state == 1 )
- ; /* skip comments */
- else if( state == 2 && isspace(c) ) {
- keyword[i] = 0;
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
- break;
- idx = i;
- arg->r_opt = opts[idx].short_opt;
- if( !opts[idx].short_opt ) {
- if( !strcmp( keyword, "alias" ) ) {
- in_alias = 1;
- state = 3;
- }
- else {
- arg->r_opt = (opts[idx].flags & 256)? -7:-2;
- state = -1; /* skip rest of line and leave */
- }
- }
- else
- state = 3;
- }
- else if( state == 3 ) { /* skip leading spaces of the argument */
- if( !isspace(c) ) {
- i = 0;
- keyword[i++] = c;
- state = 4;
- }
- }
- else if( state == 4 ) { /* collect the argument */
- if( buffer ) {
- if( i < buflen-1 )
- buffer[i++] = c;
- else {
- buflen += 50;
- buffer = libutil_realloc(buffer, buflen);
- buffer[i++] = c;
- }
- }
- else if( i < DIM(keyword)-1 )
- keyword[i++] = c;
- else {
- buflen = DIM(keyword)+50;
- buffer = libutil_xmalloc(buflen);
- memcpy(buffer, keyword, i);
- buffer[i++] = c;
- }
- }
- else if( i >= DIM(keyword)-1 ) {
- arg->r_opt = -4; /* keyword to long */
- state = -1; /* skip rest of line and leave */
- }
- else {
- keyword[i++] = c;
- state = 2;
- }
- }
-
- return arg->r_opt;
-}
-
-
-
-static int
-find_long_option( ARGPARSE_ARGS *arg,
- ARGPARSE_OPTS *opts, const char *keyword )
-{
- int i;
- size_t n;
-
- /* Would be better if we can do a binary search, but it is not
- possible to reorder our option table because we would mess
- up our help strings - What we can do is: Build a nice option
- lookup table wehn this function is first invoked */
- if( !*keyword )
- return -1;
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
- return i;
- #if 0
- {
- ALIAS_DEF a;
- /* see whether it is an alias */
- for( a = args->internal.aliases; a; a = a->next ) {
- if( !strcmp( a->name, keyword) ) {
- /* todo: must parse the alias here */
- args->internal.cur_alias = a;
- return -3; /* alias available */
- }
- }
- }
- #endif
- /* not found, see whether it is an abbreviation */
- /* aliases may not be abbreviated */
- n = strlen( keyword );
- for(i=0; opts[i].short_opt; i++ ) {
- if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
- int j;
- for(j=i+1; opts[j].short_opt; j++ ) {
- if( opts[j].long_opt
- && !strncmp( opts[j].long_opt, keyword, n ) )
- return -2; /* abbreviation is ambiguous */
- }
- return i;
- }
- }
- return -1;
-}
-
-int
-arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
-{
- int idx;
- int argc;
- char **argv;
- char *s, *s2;
- int i;
-
- initialize( arg, NULL, NULL );
- argc = *arg->argc;
- argv = *arg->argv;
- idx = arg->internal.idx;
-
- if( !idx && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */
- argc--; argv++; idx++;
- }
-
- next_one:
- if( !argc ) { /* no more args */
- arg->r_opt = 0;
- goto leave; /* ready */
- }
-
- s = *argv;
- arg->internal.last = s;
-
- if( arg->internal.stopped && (arg->flags & (1<<1)) ) {
- arg->r_opt = -1; /* not an option but a argument */
- arg->r_type = 2;
- arg->r.ret_str = s;
- argc--; argv++; idx++; /* set to next one */
- }
- else if( arg->internal.stopped ) { /* ready */
- arg->r_opt = 0;
- goto leave;
- }
- else if( *s == '-' && s[1] == '-' ) { /* long option */
- char *argpos;
-
- arg->internal.inarg = 0;
- if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */
- arg->internal.stopped = 1;
- argc--; argv++; idx++;
- goto next_one;
- }
-
- argpos = strchr( s+2, '=' );
- if( argpos )
- *argpos = 0;
- i = find_long_option( arg, opts, s+2 );
- if( argpos )
- *argpos = '=';
-
- if( i < 0 && !strcmp( "help", s+2) )
- show_help(opts, arg->flags);
- else if( i < 0 && !strcmp( "version", s+2) ) {
- if( !(arg->flags & (1<<6)) ) {
- show_version();
- exit(0);
- }
- }
- else if( i < 0 && !strcmp( "warranty", s+2) ) {
- puts( strusage(16) );
- exit(0);
- }
- else if( i < 0 && !strcmp( "dump-options", s+2) ) {
- for(i=0; opts[i].short_opt; i++ ) {
- if( opts[i].long_opt )
- printf( "--%s\n", opts[i].long_opt );
- }
- fputs("--dump-options\n--help\n--version\n--warranty\n", stdout );
- exit(0);
- }
-
- if( i == -2 ) /* ambiguous option */
- arg->r_opt = -8;
- else if( i == -1 ) {
- arg->r_opt = -2;
- arg->r.ret_str = s+2;
- }
- else
- arg->r_opt = opts[i].short_opt;
- if( i < 0 )
- ;
- else if( (opts[i].flags & 7) ) {
- if( argpos ) {
- s2 = argpos+1;
- if( !*s2 )
- s2 = NULL;
- }
- else
- s2 = argv[1];
- if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
- arg->r_type = 0; /* because it is optional */
- }
- else if( !s2 ) {
- arg->r_opt = -3; /* missing argument */
- }
- else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) {
- /* the argument is optional and the next seems to be
- * an option. We do not check this possible option
- * but assume no argument */
- arg->r_type = 0;
- }
- else {
- set_opt_arg(arg, opts[i].flags, s2);
- if( !argpos ) {
- argc--; argv++; idx++; /* skip one */
- }
- }
- }
- else { /* does not take an argument */
- if( argpos )
- arg->r_type = -6; /* argument not expected */
- else
- arg->r_type = 0;
- }
- argc--; argv++; idx++; /* set to next one */
- }
- else if( (*s == '-' && s[1]) || arg->internal.inarg ) { /* short option */
- int dash_kludge = 0;
- i = 0;
- if( !arg->internal.inarg ) {
- arg->internal.inarg++;
- if( arg->flags & (1<<5) ) {
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+1)) {
- dash_kludge=1;
- break;
- }
- }
- }
- s += arg->internal.inarg;
-
- if( !dash_kludge ) {
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].short_opt == *s )
- break;
- }
-
- if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
- show_help(opts, arg->flags);
-
- arg->r_opt = opts[i].short_opt;
- if( !opts[i].short_opt ) {
- arg->r_opt = (opts[i].flags & 256)? -7:-2;
- arg->internal.inarg++; /* point to the next arg */
- arg->r.ret_str = s;
- }
- else if( (opts[i].flags & 7) ) {
- if( s[1] && !dash_kludge ) {
- s2 = s+1;
- set_opt_arg(arg, opts[i].flags, s2);
- }
- else {
- s2 = argv[1];
- if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
- arg->r_type = 0; /* because it is optional */
- }
- else if( !s2 ) {
- arg->r_opt = -3; /* missing argument */
- }
- else if( *s2 == '-' && s2[1] && (opts[i].flags & 8) ) {
- /* the argument is optional and the next seems to be
- * an option. We do not check this possible option
- * but assume no argument */
- arg->r_type = 0;
- }
- else {
- set_opt_arg(arg, opts[i].flags, s2);
- argc--; argv++; idx++; /* skip one */
- }
- }
- s = "x"; /* so that !s[1] yields false */
- }
- else { /* does not take an argument */
- arg->r_type = 0;
- arg->internal.inarg++; /* point to the next arg */
- }
- if( !s[1] || dash_kludge ) { /* no more concatenated short options */
- arg->internal.inarg = 0;
- argc--; argv++; idx++;
- }
- }
- else if( arg->flags & (1<<2) ) {
- arg->r_opt = -1; /* not an option but a argument */
- arg->r_type = 2;
- arg->r.ret_str = s;
- argc--; argv++; idx++; /* set to next one */
- }
- else {
- arg->internal.stopped = 1; /* stop option processing */
- goto next_one;
- }
-
- leave:
- *arg->argc = argc;
- *arg->argv = argv;
- arg->internal.idx = idx;
- return arg->r_opt;
-}
-
-
-
-static int
-set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
-{
- int base = (flags & 16)? 0 : 10;
-
- switch( arg->r_type = (flags & 7) ) {
- case 1: /* takes int argument */
- arg->r.ret_int = (int)strtol(s,NULL,base);
- return 0;
- case 3: /* takes long argument */
- arg->r.ret_long= strtol(s,NULL,base);
- return 0;
- case 4: /* takes ulong argument */
- arg->r.ret_ulong= strtoul(s,NULL,base);
- return 0;
- case 2: /* takes string argument */
- default:
- arg->r.ret_str = s;
- return 1;
- }
-}
-
-
-static size_t
-long_opt_strlen( ARGPARSE_OPTS *o )
-{
- size_t n = strlen(o->long_opt);
-
- if( o->description && *o->description == '|' ) {
- const char *s;
-
- s=o->description+1;
- if( *s != '=' )
- n++;
- for(; *s && *s != '|'; s++ )
- n++;
- }
- return n;
-}
-
-/****************
- * Print formatted help. The description string has some special
- * meanings:
- * - A description string which is "@" suppresses help output for
- * this option
- * - a description,ine which starts with a '@' and is followed by
- * any other characters is printed as is; this may be used for examples
- * ans such.
- * - A description which starts with a '|' outputs the string between this
- * bar and the next one as arguments of the long option.
- */
-static void
-show_help( ARGPARSE_OPTS *opts, unsigned flags )
-{
- const char *s;
-
- show_version();
- putchar('\n');
- s = strusage(41);
- puts(s);
- if( opts[0].description ) { /* auto format the option description */
- int i,j, indent;
- /* get max. length of long options */
- for(i=indent=0; opts[i].short_opt; i++ ) {
- if( opts[i].long_opt )
- if( !opts[i].description || *opts[i].description != '@' )
- if( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
- indent = j;
- }
- /* example: " -v, --verbose Viele Sachen ausgeben" */
- indent += 10;
- if( *opts[0].description != '@' )
- puts("Options:");
- for(i=0; opts[i].short_opt; i++ ) {
- s = _( opts[i].description );
- if( s && *s== '@' && !s[1] ) /* hide this line */
- continue;
- if( s && *s == '@' ) { /* unindented comment only line */
- for(s++; *s; s++ ) {
- if( *s == '\n' ) {
- if( s[1] )
- putchar('\n');
- }
- else
- putchar(*s);
- }
- putchar('\n');
- continue;
- }
-
- j = 3;
- if( opts[i].short_opt < 256 ) {
- printf(" -%c", opts[i].short_opt );
- if( !opts[i].long_opt ) {
- if(s && *s == '|' ) {
- putchar(' '); j++;
- for(s++ ; *s && *s != '|'; s++, j++ )
- putchar(*s);
- if( *s )
- s++;
- }
- }
- }
- else
- fputs(" ", stdout);
- if( opts[i].long_opt ) {
- j += printf("%c --%s", opts[i].short_opt < 256?',':' ',
- opts[i].long_opt );
- if(s && *s == '|' ) {
- if( *++s != '=' ) {
- putchar(' ');
- j++;
- }
- for( ; *s && *s != '|'; s++, j++ )
- putchar(*s);
- if( *s )
- s++;
- }
- fputs(" ", stdout);
- j += 3;
- }
- for(;j < indent; j++ )
- putchar(' ');
- if( s ) {
- if( *s && j > indent ) {
- putchar('\n');
- for(j=0;j < indent; j++ )
- putchar(' ');
- }
- for(; *s; s++ ) {
- if( *s == '\n' ) {
- if( s[1] ) {
- putchar('\n');
- for(j=0;j < indent; j++ )
- putchar(' ');
- }
- }
- else
- putchar(*s);
- }
- }
- putchar('\n');
- }
- if( flags & 32 )
- puts("\n(A single dash may be used instead of the double ones)");
- }
- if( (s=strusage(19)) ) { /* bug reports to ... */
- putchar('\n');
- fputs(s, stdout);
- }
- fflush(stdout);
- exit(0);
-}
-
-static void
-show_version()
-{
- const char *s;
- int i;
- /* version line */
- fputs(strusage(11), stdout);
- if( (s=strusage(12)) )
- printf(" (%s)", s );
- printf(" %s\n", strusage(13) );
- /* additional version lines */
- for(i=20; i < 30; i++ )
- if( (s=strusage(i)) )
- printf("%s\n", s );
- /* copyright string */
- if( (s=strusage(14)) )
- printf("%s\n", s );
- /* copying conditions */
- if( (s=strusage(15)) )
- fputs(s, stdout);
- /* thanks */
- if( (s=strusage(18)) )
- fputs(s, stdout);
- /* additional program info */
- for(i=30; i < 40; i++ )
- if( (s=strusage(i)) )
- fputs( (const byte*)s, stdout);
- fflush(stdout);
-}
-
-
-void
-usage( int level )
-{
- if( !level ) {
- fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13),
- strusage(14) );
- fflush(stderr);
- }
- else if( level == 1 ) {
- fputs(strusage(40),stderr);
- exit(2);
- }
- else if( level == 2 ) {
- puts(strusage(41));
- exit(0);
- }
-}
-
-/* Level
- * 0: Copyright String auf stderr ausgeben
- * 1: Kurzusage auf stderr ausgeben und beenden
- * 2: Langusage auf stdout ausgeben und beenden
- * 11: name of program
- * 12: optional name of package which includes this program.
- * 13: version string
- * 14: copyright string
- * 15: Short copying conditions (with LFs)
- * 16: Long copying conditions (with LFs)
- * 17: Optional printable OS name
- * 18: Optional thanks list (with LFs)
- * 19: Bug report info
- *20..29: Additional lib version strings.
- *30..39: Additional program info (with LFs)
- * 40: short usage note (with LF)
- * 41: long usage note (with LF)
- */
-const char *
-strusage( int level )
-{
- const char *p = strusage_handler? strusage_handler(level) : NULL;
-
- if( p )
- return p;
-
- switch( level ) {
- case 11: p = "foo"; break;
- case 13: p = "0.0"; break;
- case 14: p = "Copyright (C) 1999 Free Software Foundation, Inc."; break;
- case 15: p =
-"This program comes with ABSOLUTELY NO WARRANTY.\n"
-"This is free software, and you are welcome to redistribute it\n"
-"under certain conditions. See the file COPYING for details.\n"; break;
- case 16: p =
-"This is free software; you can redistribute it and/or modify\n"
-"it under the terms of the GNU General Public License as published by\n"
-"the Free Software Foundation; either version 2 of the License, or\n"
-"(at your option) any later version.\n\n"
-"It is distributed in the hope that it will be useful,\n"
-"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
-"GNU General Public License for more details.\n\n"
-"You should have received a copy of the GNU General Public License\n"
-"along with this program; if not, write to the Free Software\n"
-"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
- break;
- case 40: /* short and long usage */
- case 41: p = ""; break;
- }
-
- return p;
-}
-
-void
-set_strusage( const char *(*f)( int ) )
-{
- strusage_handler = f;
-}
-
-
-#ifdef TEST
-static struct {
- int verbose;
- int debug;
- char *outfile;
- char *crf;
- int myopt;
- int echo;
- int a_long_one;
-}opt;
-
-int
-main(int argc, char **argv)
-{
- ARGPARSE_OPTS opts[] = {
- { 'v', "verbose", 0 , "Laut sein"},
- { 'e', "echo" , 0 , "Zeile ausgeben, damit wir sehen, was wir einegegeben haben"},
- { 'd', "debug", 0 , "Debug\nfalls mal etasws\nSchief geht"},
- { 'o', "output", 2 },
- { 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" },
- { 'm', "my-option", 1|8 },
- { 500, "a-long-option", 0 },
- {0} };
- ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 };
- int i;
-
- while( ArgParse( &pargs, opts) ) {
- switch( pargs.r_opt ) {
- case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break;
- case 'v': opt.verbose++; break;
- case 'e': opt.echo++; break;
- case 'd': opt.debug++; break;
- case 'o': opt.outfile = pargs.r.ret_str; break;
- case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
- case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
- case 500: opt.a_long_one++; break;
- default : pargs.err = 1; break; /* force warning output */
- }
- }
- for(i=0; i < argc; i++ )
- printf("%3d -> (%s)\n", i, argv[i] );
- puts("Options:");
- if( opt.verbose )
- printf(" verbose=%d\n", opt.verbose );
- if( opt.debug )
- printf(" debug=%d\n", opt.debug );
- if( opt.outfile )
- printf(" outfile=`%s'\n", opt.outfile );
- if( opt.crf )
- printf(" crffile=`%s'\n", opt.crf );
- if( opt.myopt )
- printf(" myopt=%d\n", opt.myopt );
- if( opt.a_long_one )
- printf(" a-long-one=%d\n", opt.a_long_one );
- if( opt.echo )
- printf(" echo=%d\n", opt.echo );
- return 0;
-}
-#endif
-
-/**** bottom of file ****/