diff options
Diffstat (limited to 'jnlib/argparse.c')
-rw-r--r-- | jnlib/argparse.c | 1205 |
1 files changed, 0 insertions, 1205 deletions
diff --git a/jnlib/argparse.c b/jnlib/argparse.c deleted file mode 100644 index ab88922a4..000000000 --- a/jnlib/argparse.c +++ /dev/null @@ -1,1205 +0,0 @@ -/* [argparse.c wk 17.06.97] Argument Parser for option handling - * Copyright (C) 1998, 1999, 2000, 2001, 2006 - * 2007, 2008 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * JNLIB 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -#include "libjnlib-config.h" -#include "mischelp.h" -#include "stringhelp.h" -#include "logging.h" -#ifdef JNLIB_NEED_UTF8CONV -#include "utf8conv.h" -#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 as initialized. */ - if ( *arg->argc < 0 ) - jnlib_log_bug ("invalid argument for arg_parsee\n"); - } - - - if (arg->err) - { - /* Last option was erroneous. */ - const char *s; - - if (filename) - { - if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - s = _("argument not expected"); - else if ( arg->r_opt == ARGPARSE_READ_ERROR ) - s = _("read error"); - else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG ) - s = _("keyword too long"); - else if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - s = _("missing argument"); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - s = _("invalid command"); - else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS ) - s = _("invalid alias definition"); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - s = _("out of core"); - else - s = _("invalid option"); - jnlib_log_error ("%s:%u: %s\n", filename, *lineno, s); - } - else - { - s = arg->internal.last? arg->internal.last:"[??]"; - - if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - jnlib_log_error (_("option \"%.50s\" does not expect an " - "argument\n"), s ); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - jnlib_log_error (_("invalid command \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) - jnlib_log_error (_("option \"%.50s\" is ambiguous\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) - jnlib_log_error (_("command \"%.50s\" is ambiguous\n"),s ); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - jnlib_log_error ("%s\n", _("out of core\n")); - else - jnlib_log_error (_("invalid option \"%.50s\"\n"), s); - } - if ( arg->err != 1 ) - exit (2); - arg->err = 0; - } - - /* Zero out 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 - */ - (void)arg; - (void)name; - (void)value; -#if 0 - ALIAS_DEF a = jnlib_xmalloc( 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 in_alias=0; - - if (!fp) /* Divert to to 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 (!opts[idx].short_opt ) - arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - else if (!(opts[idx].flags & 7)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & 8) ) - arg->r_type = 0; /* Arg is optional. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 3) - { - /* No argument found. */ - if (in_alias) - arg->r_opt = ARGPARSE_MISSING_ARG; - else if (!(opts[idx].flags & 7)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & 8)) - arg->r_type = 0; /* No optional argument. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 4) - { - /* Has an argument. */ - if (in_alias) - { - if (!buffer) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - buffer[i] = 0; - p = strpbrk (buffer, " \t"); - if (p) - { - *p++ = 0; - trim_spaces (p); - } - if (!p || !*p) - { - jnlib_free (buffer); - arg->r_opt = ARGPARSE_INVALID_ALIAS; - } - else - { - store_alias (arg, buffer, p); - } - } - } - else if (!(opts[idx].flags & 7)) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - if (!buffer) - { - keyword[i] = 0; - buffer = jnlib_strdup (keyword); - if (!buffer) - arg->r_opt = ARGPARSE_OUT_OF_CORE; - } - else - buffer[i] = 0; - - if (buffer) - { - 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)) - jnlib_free(buffer); - } - } - break; - } - else if (c == EOF) - { - if (ferror (fp)) - arg->r_opt = ARGPARSE_READ_ERROR; - else - arg->r_opt = 0; /* EOF. */ - break; - } - state = 0; - i = 0; - } - else if (state == -1) - ; /* Skip. */ - else if (state == 0 && isascii (c) && isspace(c)) - ; /* Skip leading white space. */ - else if (state == 0 && c == '#' ) - state = 1; /* Start of a comment. */ - else if (state == 1) - ; /* Skip comments. */ - else if (state == 2 && isascii (c) && isspace(c)) - { - /* Check keyword. */ - 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 & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - state = -1; /* Skip rest of line and leave. */ - } - } - else - state = 3; - } - else if (state == 3) - { - /* Skip leading spaces of the argument. */ - if (!isascii (c) || !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 - { - char *tmp; - size_t tmplen = buflen + 50; - - tmp = jnlib_realloc (buffer, tmplen); - if (tmp) - { - buflen = tmplen; - buffer = tmp; - buffer[i++] = c; - } - else - { - jnlib_free (buffer); - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i < DIM(keyword)-1) - keyword[i++] = c; - else - { - size_t tmplen = DIM(keyword) + 50; - buffer = jnlib_malloc (tmplen); - if (buffer) - { - buflen = tmplen; - memcpy(buffer, keyword, i); - buffer[i++] = c; - } - else - { - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i >= DIM(keyword)-1) - { - arg->r_opt = ARGPARSE_KEYWORD_TOO_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; - - (void)arg; - - /* 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 & ARGPARSE_FLAG_ARG0)) - { - /* Skip the first argument. */ - 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 & ARGPARSE_FLAG_ALL)) - { - arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */ - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* set to next one */ - } - else if( arg->internal.stopped ) - { - arg->r_opt = 0; - goto leave; /* Ready. */ - } - else if ( *s == '-' && s[1] == '-' ) - { - /* Long option. */ - char *argpos; - - arg->internal.inarg = 0; - if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP)) - { - /* 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 & ARGPARSE_FLAG_NOVERSION)) - { - 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 ) - arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION; - else if ( i == -1 ) - { - arg->r_opt = ARGPARSE_INVALID_OPTION; - arg->r.ret_str = s+2; - } - else - arg->r_opt = opts[i].short_opt; - if ( i < 0 ) - ; - else if ( (opts[i].flags & 0x07) ) - { - if ( argpos ) - { - s2 = argpos+1; - if ( !*s2 ) - s2 = NULL; - } - else - s2 = argv[1]; - if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */ - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( !argpos && *s2 == '-' - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* 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 = ARGPARSE_TYPE_NONE; - } - 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 = ARGPARSE_UNEXPECTED_ARG; - 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 & ARGPARSE_FLAG_ONEDASH) ) - { - 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 & ARGPARSE_OPT_COMMAND)? - ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION; - 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 & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( *s2 == '-' && s2[1] - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* 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 = ARGPARSE_TYPE_NONE; - } - else - { - set_opt_arg (arg, opts[i].flags, s2); - argc--; argv++; idx++; /* Skip one. */ - } - } - s = "x"; /* This is so that !s[1] yields false. */ - } - else - { - /* Does not take an argument. */ - arg->r_type = ARGPARSE_TYPE_NONE; - 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 & ARGPARSE_FLAG_MIXED ) - { - arg->r_opt = ARGPARSE_IS_ARG; - 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 ARGPARSE_TYPE_INT: - arg->r.ret_int = (int)strtol(s,NULL,base); - return 0; - case ARGPARSE_TYPE_LONG: - arg->r.ret_long= strtol(s,NULL,base); - return 0; - case ARGPARSE_TYPE_ULONG: - arg->r.ret_ulong= strtoul(s,NULL,base); - return 0; - case ARGPARSE_TYPE_STRING: - 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; -#ifdef JNLIB_NEED_UTF8CONV - int is_utf8 = is_native_utf8 (); -#endif - - s=o->description+1; - if ( *s != '=' ) - n++; - /* For a (mostly) correct length calculation we exclude - continuation bytes (10xxxxxx) if we are on a native utf8 - terminal. */ - for (; *s && *s != '|'; s++ ) -#ifdef JNLIB_NEED_UTF8CONV - if ( is_utf8 && (*s&0xc0) != 0x80 ) -#endif - 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 int 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 & ARGPARSE_FLAG_ONEDASH) ) - puts ("\n(A single dash may be used instead of the double ones)"); - } - if ( (s=strusage(19)) ) - { - /* bug reports to ... */ - char *s2; - - putchar('\n'); - s2 = strstr (s, "@EMAIL@"); - if (s2) - { - if (s2-s) - fwrite (s, s2-s, 1, stdout); -#ifdef PACKAGE_BUGREPORT - fputs (PACKAGE_BUGREPORT, stdout); -#else - fputs ("[email protected]", stdout); -#endif - s2 += 7; - if (*s2) - fputs (s2, stdout); - } - else - 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 ); - /* Licence string. */ - if( (s=strusage (10)) ) - 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 (s, stdout); - fflush (stdout); -} - - -void -usage (int level) -{ - const char *p; - - if (!level) - { - fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13), strusage (14)); - fflush (stderr); - } - else if (level == 1) - { - p = strusage (40); - fputs (p, stderr); - if (*p && p[strlen(p)] != '\n') - putc ('\n', stderr); - exit (2); - } - else if (level == 2) - { - puts (strusage(41)); - exit (0); - } -} - -/* Level - * 0: Print copyright string to stderr - * 1: Print a short usage hint to stderr and terminate - * 2: Print a long usage hint to stdout and terminate - * 10: Return license info string - * 11: Return the name of the program - * 12: Return 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 10: p = ("License GPLv3+: GNU GPL version 3 or later " - "<http://gnu.org/licenses/gpl.html>"); - break; - case 11: p = "foo"; break; - case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2010 Free Software Foundation, Inc."; break; - case 15: p = -"This is free software: you are free to change and redistribute it.\n" -"There is NO WARRANTY, to the extent permitted by law.\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 3 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 software. If not, see <http://www.gnu.org/licenses/>.\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[] = { - ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"), - ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, " - "was wir ein gegeben haben")), - ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"), - ARGPARSE_s_s('o', "output", 0 ), - ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ), - /* Note that on a non-utf8 terminal the ß might garble the output. */ - ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"), - ARGPARSE_o_i('m', "my-option", 0), - ARGPARSE_s_n(500, "a-long-option", 0 ), - ARGPARSE_end - }; - ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 }; - int i; - - while( arg_parse ( &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 = ARGPARSE_PRINT_WARNING; break; - } - } - 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 ****/ |