Blame src/argparse.c

Packit d7e8d0
/* [argparse.c wk 17.06.97] Argument Parser for option handling
Packit d7e8d0
 * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
Packit d7e8d0
 * Copyright (C) 1997-2001, 2006-2008, 2013-2015 Werner Koch
Packit d7e8d0
 *
Packit d7e8d0
 * This file is part of GnuPG.
Packit d7e8d0
 *
Packit d7e8d0
 * GnuPG is free software; you can redistribute it and/or modify it
Packit d7e8d0
 * under the terms of either
Packit d7e8d0
 *
Packit d7e8d0
 *   - the GNU Lesser General Public License as published by the Free
Packit d7e8d0
 *     Software Foundation; either version 3 of the License, or (at
Packit d7e8d0
 *     your option) any later version.
Packit d7e8d0
 *
Packit d7e8d0
 * or
Packit d7e8d0
 *
Packit d7e8d0
 *   - the GNU General Public License as published by the Free
Packit d7e8d0
 *     Software Foundation; either version 2 of the License, or (at
Packit d7e8d0
 *     your option) any later version.
Packit d7e8d0
 *
Packit d7e8d0
 * or both in parallel, as here.
Packit d7e8d0
 *
Packit d7e8d0
 * GnuPG is distributed in the hope that it will be useful, but
Packit d7e8d0
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit d7e8d0
 * General Public License for more details.
Packit d7e8d0
 *
Packit d7e8d0
 * You should have received a copies of the GNU General Public License
Packit d7e8d0
 * and the GNU Lesser General Public License along with this program;
Packit d7e8d0
 * if not, see <https://www.gnu.org/licenses/>.
Packit d7e8d0
 */
Packit d7e8d0
Packit d7e8d0
/* This file may be used as part of GnuPG or standalone.  A GnuPG
Packit d7e8d0
   build is detected by the presence of the macro GNUPG_MAJOR_VERSION.
Packit d7e8d0
   Some feature are only availalbe in the GnuPG build mode.
Packit d7e8d0
 */
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_CONFIG_H
Packit d7e8d0
#include <config.h>
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include <stdio.h>
Packit d7e8d0
#include <stdlib.h>
Packit d7e8d0
#include <ctype.h>
Packit d7e8d0
#include <string.h>
Packit d7e8d0
#include <stdarg.h>
Packit d7e8d0
#include <limits.h>
Packit d7e8d0
#include <errno.h>
Packit d7e8d0
Packit d7e8d0
#ifdef GNUPG_MAJOR_VERSION
Packit d7e8d0
# include "util.h"
Packit d7e8d0
# include "common-defs.h"
Packit d7e8d0
# include "i18n.h"
Packit d7e8d0
# include "mischelp.h"
Packit d7e8d0
# include "stringhelp.h"
Packit d7e8d0
# include "logging.h"
Packit d7e8d0
# include "utf8conv.h"
Packit d7e8d0
#endif /*GNUPG_MAJOR_VERSION*/
Packit d7e8d0
Packit d7e8d0
#include "argparse.h"
Packit d7e8d0
Packit d7e8d0
/* GnuPG uses GPLv3+ but a standalone version of this defaults to
Packit d7e8d0
   GPLv2+ because that is the license of this file.  Change this if
Packit d7e8d0
   you include it in a program which uses GPLv3.  If you don't want to
Packit d7e8d0
   set a a copyright string for your usage() you may also hardcode it
Packit d7e8d0
   here.  */
Packit d7e8d0
#ifndef GNUPG_MAJOR_VERSION
Packit d7e8d0
Packit d7e8d0
# define ARGPARSE_GPL_VERSION      2
Packit d7e8d0
# define ARGPARSE_CRIGHT_STR "Copyright (C) YEAR NAME"
Packit d7e8d0
Packit d7e8d0
#else /* Used by GnuPG  */
Packit d7e8d0
Packit d7e8d0
# define ARGPARSE_GPL_VERSION      3
Packit d7e8d0
# define ARGPARSE_CRIGHT_STR "Copyright (C) 2015 Free Software Foundation, Inc."
Packit d7e8d0
Packit d7e8d0
#endif /*GNUPG_MAJOR_VERSION*/
Packit d7e8d0
Packit d7e8d0
/* Replacements for standalone builds.  */
Packit d7e8d0
#ifndef GNUPG_MAJOR_VERSION
Packit d7e8d0
# ifndef _
Packit d7e8d0
#  define _(a)  (a)
Packit d7e8d0
# endif
Packit d7e8d0
# ifndef DIM
Packit d7e8d0
#  define DIM(v)           (sizeof(v)/sizeof((v)[0]))
Packit d7e8d0
# endif
Packit d7e8d0
# define xtrymalloc(a)    malloc ((a))
Packit d7e8d0
# define xtryrealloc(a,b) realloc ((a), (b))
Packit d7e8d0
# define xtrystrdup(a)    strdup ((a))
Packit d7e8d0
# define xfree(a)         free ((a))
Packit d7e8d0
# define log_error        my_log_error
Packit d7e8d0
# define log_bug	  my_log_bug
Packit d7e8d0
# define trim_spaces(a)   my_trim_spaces ((a))
Packit d7e8d0
# define map_static_macro_string(a)  (a)
Packit d7e8d0
#endif /*!GNUPG_MAJOR_VERSION*/
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
#define ARGPARSE_STR(v) #v
Packit d7e8d0
#define ARGPARSE_STR2(v) ARGPARSE_STR(v)
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Replacements for standalone builds.  */
Packit d7e8d0
#ifndef GNUPG_MAJOR_VERSION
Packit d7e8d0
static void
Packit d7e8d0
my_log_error (const char *fmt, ...)
Packit d7e8d0
{
Packit d7e8d0
  va_list arg_ptr ;
Packit d7e8d0
Packit d7e8d0
  va_start (arg_ptr, fmt);
Packit d7e8d0
  fprintf (stderr, "%s: ", strusage (11));
Packit d7e8d0
  vfprintf (stderr, fmt, arg_ptr);
Packit d7e8d0
  va_end (arg_ptr);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static void
Packit d7e8d0
my_log_bug (const char *fmt, ...)
Packit d7e8d0
{
Packit d7e8d0
  va_list arg_ptr ;
Packit d7e8d0
Packit d7e8d0
  va_start (arg_ptr, fmt);
Packit d7e8d0
  fprintf (stderr, "%s: Ohhhh jeeee: ", strusage (11));
Packit d7e8d0
  vfprintf (stderr, fmt, arg_ptr);
Packit d7e8d0
  va_end (arg_ptr);
Packit d7e8d0
  abort ();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Return true if the native charset is utf-8.  */
Packit d7e8d0
static int
Packit d7e8d0
is_native_utf8 (void)
Packit d7e8d0
{
Packit d7e8d0
  return 1;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static char *
Packit d7e8d0
my_trim_spaces (char *str)
Packit d7e8d0
{
Packit d7e8d0
  char *string, *p, *mark;
Packit d7e8d0
Packit d7e8d0
  string = str;
Packit d7e8d0
  /* Find first non space character. */
Packit d7e8d0
  for (p=string; *p && isspace (*(unsigned char*)p) ; p++)
Packit d7e8d0
    ;
Packit d7e8d0
  /* Move characters. */
Packit d7e8d0
  for ((mark = NULL); (*string = *p); string++, p++)
Packit d7e8d0
    if (isspace (*(unsigned char*)p))
Packit d7e8d0
      {
Packit d7e8d0
        if (!mark)
Packit d7e8d0
          mark = string;
Packit d7e8d0
      }
Packit d7e8d0
    else
Packit d7e8d0
      mark = NULL;
Packit d7e8d0
  if (mark)
Packit d7e8d0
    *mark = '\0' ;  /* Remove trailing spaces. */
Packit d7e8d0
Packit d7e8d0
  return str ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
#endif /*!GNUPG_MAJOR_VERSION*/
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/*********************************
Packit d7e8d0
 * @Summary arg_parse
Packit d7e8d0
 *  #include "argparse.h"
Packit d7e8d0
 *
Packit d7e8d0
 *  typedef struct {
Packit d7e8d0
 *	char *argc;		  pointer to argc (value subject to change)
Packit d7e8d0
 *	char ***argv;		  pointer to argv (value subject to change)
Packit d7e8d0
 *	unsigned flags; 	  Global flags (DO NOT CHANGE)
Packit d7e8d0
 *	int err;		  print error about last option
Packit d7e8d0
 *				  1 = warning, 2 = abort
Packit d7e8d0
 *	int r_opt;		  return option
Packit d7e8d0
 *	int r_type;		  type of return value (0 = no argument found)
Packit d7e8d0
 *	union {
Packit d7e8d0
 *	    int   ret_int;
Packit d7e8d0
 *	    long  ret_long
Packit d7e8d0
 *	    ulong ret_ulong;
Packit d7e8d0
 *	    char *ret_str;
Packit d7e8d0
 *	} r;			  Return values
Packit d7e8d0
 *	struct {
Packit d7e8d0
 *	    int idx;
Packit d7e8d0
 *	    const char *last;
Packit d7e8d0
 *	    void *aliases;
Packit d7e8d0
 *	} internal;		  DO NOT CHANGE
Packit d7e8d0
 *  } ARGPARSE_ARGS;
Packit d7e8d0
 *
Packit d7e8d0
 *  typedef struct {
Packit d7e8d0
 *	int	    short_opt;
Packit d7e8d0
 *	const char *long_opt;
Packit d7e8d0
 *	unsigned flags;
Packit d7e8d0
 *  } ARGPARSE_OPTS;
Packit d7e8d0
 *
Packit d7e8d0
 *  int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
Packit d7e8d0
 *
Packit d7e8d0
 * @Description
Packit d7e8d0
 *  This is my replacement for getopt(). See the example for a typical usage.
Packit d7e8d0
 *  Global flags are:
Packit d7e8d0
 *     Bit 0 : Do not remove options form argv
Packit d7e8d0
 *     Bit 1 : Do not stop at last option but return other args
Packit d7e8d0
 *	       with r_opt set to -1.
Packit d7e8d0
 *     Bit 2 : Assume options and real args are mixed.
Packit d7e8d0
 *     Bit 3 : Do not use -- to stop option processing.
Packit d7e8d0
 *     Bit 4 : Do not skip the first arg.
Packit d7e8d0
 *     Bit 5 : allow usage of long option with only one dash
Packit d7e8d0
 *     Bit 6 : ignore --version
Packit d7e8d0
 *     all other bits must be set to zero, this value is modified by the
Packit d7e8d0
 *     function, so assume this is write only.
Packit d7e8d0
 *  Local flags (for each option):
Packit d7e8d0
 *     Bit 2-0 : 0 = does not take an argument
Packit d7e8d0
 *		 1 = takes int argument
Packit d7e8d0
 *		 2 = takes string argument
Packit d7e8d0
 *		 3 = takes long argument
Packit d7e8d0
 *		 4 = takes ulong argument
Packit d7e8d0
 *     Bit 3 : argument is optional (r_type will the be set to 0)
Packit d7e8d0
 *     Bit 4 : allow 0x etc. prefixed values.
Packit d7e8d0
 *     Bit 6 : Ignore this option
Packit d7e8d0
 *     Bit 7 : This is a command and not an option
Packit d7e8d0
 *  You stop the option processing by setting opts to NULL, the function will
Packit d7e8d0
 *  then return 0.
Packit d7e8d0
 * @Return Value
Packit d7e8d0
 *   Returns the args.r_opt or 0 if ready
Packit d7e8d0
 *   r_opt may be -2/-7 to indicate an unknown option/command.
Packit d7e8d0
 * @See Also
Packit d7e8d0
 *   ArgExpand
Packit d7e8d0
 * @Notes
Packit d7e8d0
 *  You do not need to process the options 'h', '--help' or '--version'
Packit d7e8d0
 *  because this function includes standard help processing; but if you
Packit d7e8d0
 *  specify '-h', '--help' or '--version' you have to do it yourself.
Packit d7e8d0
 *  The option '--' stops argument processing; if bit 1 is set the function
Packit d7e8d0
 *  continues to return normal arguments.
Packit d7e8d0
 *  To process float args or unsigned args you must use a string args and do
Packit d7e8d0
 *  the conversion yourself.
Packit d7e8d0
 * @Example
Packit d7e8d0
 *
Packit d7e8d0
 *     ARGPARSE_OPTS opts[] = {
Packit d7e8d0
 *     { 'v', "verbose",   0 },
Packit d7e8d0
 *     { 'd', "debug",     0 },
Packit d7e8d0
 *     { 'o', "output",    2 },
Packit d7e8d0
 *     { 'c', "cross-ref", 2|8 },
Packit d7e8d0
 *     { 'm', "my-option", 1|8 },
Packit d7e8d0
 *     { 300, "ignored-long-option, ARGPARSE_OP_IGNORE},
Packit d7e8d0
 *     { 500, "have-no-short-option-for-this-long-option", 0 },
Packit d7e8d0
 *     {0} };
Packit d7e8d0
 *     ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
Packit d7e8d0
 *
Packit d7e8d0
 *     while( ArgParse( &pargs, &opts) ) {
Packit d7e8d0
 *	   switch( pargs.r_opt ) {
Packit d7e8d0
 *	     case 'v': opt.verbose++; break;
Packit d7e8d0
 *	     case 'd': opt.debug++; break;
Packit d7e8d0
 *	     case 'o': opt.outfile = pargs.r.ret_str; break;
Packit d7e8d0
 *	     case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
Packit d7e8d0
 *	     case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
Packit d7e8d0
 *	     case 500: opt.a_long_one++;  break
Packit d7e8d0
 *	     default : pargs.err = 1; break; -- force warning output --
Packit d7e8d0
 *	   }
Packit d7e8d0
 *     }
Packit d7e8d0
 *     if( argc > 1 )
Packit d7e8d0
 *	   log_fatal( "Too many args");
Packit d7e8d0
 *
Packit d7e8d0
 */
Packit d7e8d0
Packit d7e8d0
typedef struct alias_def_s *ALIAS_DEF;
Packit d7e8d0
struct alias_def_s {
Packit d7e8d0
    ALIAS_DEF next;
Packit d7e8d0
    char *name;   /* malloced buffer with name, \0, value */
Packit d7e8d0
    const char *value; /* ptr into name */
Packit d7e8d0
};
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Object to store the names for the --ignore-invalid-option option.
Packit d7e8d0
   This is a simple linked list.  */
Packit d7e8d0
typedef struct iio_item_def_s *IIO_ITEM_DEF;
Packit d7e8d0
struct iio_item_def_s
Packit d7e8d0
{
Packit d7e8d0
  IIO_ITEM_DEF next;
Packit d7e8d0
  char name[1];      /* String with the long option name.  */
Packit d7e8d0
};
Packit d7e8d0
Packit d7e8d0
static const char *(*strusage_handler)( int ) = NULL;
Packit d7e8d0
static int (*custom_outfnc) (int, const char *);
Packit d7e8d0
Packit d7e8d0
static int  set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
Packit d7e8d0
static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
Packit d7e8d0
static void show_version(void);
Packit d7e8d0
static int writestrings (int is_error, const char *string, ...)
Packit d7e8d0
#if __GNUC__ >= 4
Packit d7e8d0
  __attribute__ ((sentinel(0)))
Packit d7e8d0
#endif
Packit d7e8d0
  ;
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
void
Packit d7e8d0
argparse_register_outfnc (int (*fnc)(int, const char *))
Packit d7e8d0
{
Packit d7e8d0
  custom_outfnc = fnc;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Write STRING and all following const char * arguments either to
Packit d7e8d0
   stdout or, if IS_ERROR is set, to stderr.  The list of strings must
Packit d7e8d0
   be terminated by a NULL.  */
Packit d7e8d0
static int
Packit d7e8d0
writestrings (int is_error, const char *string, ...)
Packit d7e8d0
{
Packit d7e8d0
  va_list arg_ptr;
Packit d7e8d0
  const char *s;
Packit d7e8d0
  int count = 0;
Packit d7e8d0
Packit d7e8d0
  if (string)
Packit d7e8d0
    {
Packit d7e8d0
      s = string;
Packit d7e8d0
      va_start (arg_ptr, string);
Packit d7e8d0
      do
Packit d7e8d0
        {
Packit d7e8d0
          if (custom_outfnc)
Packit d7e8d0
            custom_outfnc (is_error? 2:1, s);
Packit d7e8d0
          else
Packit d7e8d0
            fputs (s, is_error? stderr : stdout);
Packit d7e8d0
          count += strlen (s);
Packit d7e8d0
        }
Packit d7e8d0
      while ((s = va_arg (arg_ptr, const char *)));
Packit d7e8d0
      va_end (arg_ptr);
Packit d7e8d0
    }
Packit d7e8d0
  return count;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
static void
Packit d7e8d0
flushstrings (int is_error)
Packit d7e8d0
{
Packit d7e8d0
  if (custom_outfnc)
Packit d7e8d0
    custom_outfnc (is_error? 2:1, NULL);
Packit d7e8d0
  else
Packit d7e8d0
    fflush (is_error? stderr : stdout);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
static void
Packit d7e8d0
initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
Packit d7e8d0
{
Packit d7e8d0
  if( !(arg->flags & (1<<15)) )
Packit d7e8d0
    {
Packit d7e8d0
      /* Initialize this instance. */
Packit d7e8d0
      arg->internal.idx = 0;
Packit d7e8d0
      arg->internal.last = NULL;
Packit d7e8d0
      arg->internal.inarg = 0;
Packit d7e8d0
      arg->internal.stopped = 0;
Packit d7e8d0
      arg->internal.aliases = NULL;
Packit d7e8d0
      arg->internal.cur_alias = NULL;
Packit d7e8d0
      arg->internal.iio_list = NULL;
Packit d7e8d0
      arg->err = 0;
Packit d7e8d0
      arg->flags |= 1<<15; /* Mark as initialized.  */
Packit d7e8d0
      if ( *arg->argc < 0 )
Packit d7e8d0
        log_bug ("invalid argument for arg_parse\n");
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
  if (arg->err)
Packit d7e8d0
    {
Packit d7e8d0
      /* Last option was erroneous.  */
Packit d7e8d0
      const char *s;
Packit d7e8d0
Packit d7e8d0
      if (filename)
Packit d7e8d0
        {
Packit d7e8d0
          if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
Packit d7e8d0
            s = _("argument not expected");
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_READ_ERROR )
Packit d7e8d0
            s = _("read error");
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG )
Packit d7e8d0
            s = _("keyword too long");
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_MISSING_ARG )
Packit d7e8d0
            s = _("missing argument");
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
Packit d7e8d0
            s = _("invalid argument");
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
Packit d7e8d0
            s = _("invalid command");
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS )
Packit d7e8d0
            s = _("invalid alias definition");
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
Packit d7e8d0
            s = _("out of core");
Packit d7e8d0
          else
Packit d7e8d0
            s = _("invalid option");
Packit d7e8d0
          log_error ("%s:%u: %s\n", filename, *lineno, s);
Packit d7e8d0
	}
Packit d7e8d0
      else
Packit d7e8d0
        {
Packit d7e8d0
          s = arg->internal.last? arg->internal.last:"[??]";
Packit d7e8d0
Packit d7e8d0
          if ( arg->r_opt == ARGPARSE_MISSING_ARG )
Packit d7e8d0
            log_error (_("missing argument for option \"%.50s\"\n"), s);
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
Packit d7e8d0
            log_error (_("invalid argument for option \"%.50s\"\n"), s);
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
Packit d7e8d0
            log_error (_("option \"%.50s\" does not expect an argument\n"), s);
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
Packit d7e8d0
            log_error (_("invalid command \"%.50s\"\n"), s);
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION )
Packit d7e8d0
            log_error (_("option \"%.50s\" is ambiguous\n"), s);
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND )
Packit d7e8d0
            log_error (_("command \"%.50s\" is ambiguous\n"),s );
Packit d7e8d0
          else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
Packit d7e8d0
            log_error ("%s\n", _("out of core\n"));
Packit d7e8d0
          else
Packit d7e8d0
            log_error (_("invalid option \"%.50s\"\n"), s);
Packit d7e8d0
	}
Packit d7e8d0
      if (arg->err != ARGPARSE_PRINT_WARNING)
Packit d7e8d0
        exit (2);
Packit d7e8d0
      arg->err = 0;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  /* Zero out the return value union.  */
Packit d7e8d0
  arg->r.ret_str = NULL;
Packit d7e8d0
  arg->r.ret_long = 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
static void
Packit d7e8d0
store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
Packit d7e8d0
{
Packit d7e8d0
    /* TODO: replace this dummy function with a rea one
Packit Service 30b792
     * and fix the problems IRIX has with (ALIAS_DEV)arg..
Packit d7e8d0
     * used as lvalue
Packit d7e8d0
     */
Packit d7e8d0
  (void)arg;
Packit d7e8d0
  (void)name;
Packit d7e8d0
  (void)value;
Packit d7e8d0
#if 0
Packit d7e8d0
    ALIAS_DEF a = xmalloc( sizeof *a );
Packit d7e8d0
    a->name = name;
Packit d7e8d0
    a->value = value;
Packit d7e8d0
    a->next = (ALIAS_DEF)arg->internal.aliases;
Packit d7e8d0
    (ALIAS_DEF)arg->internal.aliases = a;
Packit d7e8d0
#endif
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Return true if KEYWORD is in the ignore-invalid-option list.  */
Packit d7e8d0
static int
Packit d7e8d0
ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword)
Packit d7e8d0
{
Packit d7e8d0
  IIO_ITEM_DEF item = arg->internal.iio_list;
Packit d7e8d0
Packit d7e8d0
  for (; item; item = item->next)
Packit d7e8d0
    if (!strcmp (item->name, keyword))
Packit d7e8d0
      return 1;
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Add the keywords up to the next LF to the list of to be ignored
Packit d7e8d0
   options.  After returning FP will either be at EOF or the next
Packit Service 30b792
   character read will be the first of a new line.  The function
Packit d7e8d0
   returns 0 on success or true on malloc failure.  */
Packit d7e8d0
static int
Packit d7e8d0
ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp)
Packit d7e8d0
{
Packit d7e8d0
  IIO_ITEM_DEF item;
Packit d7e8d0
  int c;
Packit d7e8d0
  char name[100];
Packit d7e8d0
  int namelen = 0;
Packit d7e8d0
  int ready = 0;
Packit d7e8d0
  enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS;
Packit d7e8d0
Packit d7e8d0
  while (!ready)
Packit d7e8d0
    {
Packit d7e8d0
      c = getc (fp);
Packit d7e8d0
      if (c == '\n')
Packit d7e8d0
        ready = 1;
Packit d7e8d0
      else if (c == EOF)
Packit d7e8d0
        {
Packit d7e8d0
          c = '\n';
Packit d7e8d0
          ready = 1;
Packit d7e8d0
        }
Packit d7e8d0
    again:
Packit d7e8d0
      switch (state)
Packit d7e8d0
        {
Packit d7e8d0
        case skipWS:
Packit d7e8d0
          if (!isascii (c) || !isspace(c))
Packit d7e8d0
            {
Packit d7e8d0
              namelen = 0;
Packit d7e8d0
              state = collectNAME;
Packit d7e8d0
              goto again;
Packit d7e8d0
            }
Packit d7e8d0
          break;
Packit d7e8d0
Packit d7e8d0
        case collectNAME:
Packit d7e8d0
          if (isspace (c))
Packit d7e8d0
            {
Packit d7e8d0
              state = addNAME;
Packit d7e8d0
              goto again;
Packit d7e8d0
            }
Packit d7e8d0
          else if (namelen < DIM(name)-1)
Packit d7e8d0
            name[namelen++] = c;
Packit d7e8d0
          else /* Too long.  */
Packit d7e8d0
            state = skipNAME;
Packit d7e8d0
          break;
Packit d7e8d0
Packit d7e8d0
        case skipNAME:
Packit d7e8d0
          if (isspace (c))
Packit d7e8d0
            {
Packit d7e8d0
              state = skipWS;
Packit d7e8d0
              goto again;
Packit d7e8d0
            }
Packit d7e8d0
          break;
Packit d7e8d0
Packit d7e8d0
        case addNAME:
Packit d7e8d0
          name[namelen] = 0;
Packit d7e8d0
          if (!ignore_invalid_option_p (arg, name))
Packit d7e8d0
            {
Packit d7e8d0
              item = xtrymalloc (sizeof *item + namelen);
Packit d7e8d0
              if (!item)
Packit d7e8d0
                return 1;
Packit d7e8d0
              strcpy (item->name, name);
Packit d7e8d0
              item->next = (IIO_ITEM_DEF)arg->internal.iio_list;
Packit d7e8d0
              arg->internal.iio_list = item;
Packit d7e8d0
            }
Packit d7e8d0
          state = skipWS;
Packit d7e8d0
          goto again;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Clear the entire ignore-invalid-option list.  */
Packit d7e8d0
static void
Packit d7e8d0
ignore_invalid_option_clear (ARGPARSE_ARGS *arg)
Packit d7e8d0
{
Packit d7e8d0
  IIO_ITEM_DEF item, tmpitem;
Packit d7e8d0
Packit d7e8d0
  for (item = arg->internal.iio_list; item; item = tmpitem)
Packit d7e8d0
    {
Packit d7e8d0
      tmpitem = item->next;
Packit d7e8d0
      xfree (item);
Packit d7e8d0
    }
Packit d7e8d0
  arg->internal.iio_list = NULL;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/****************
Packit d7e8d0
 * Get options from a file.
Packit d7e8d0
 * Lines starting with '#' are comment lines.
Packit d7e8d0
 * Syntax is simply a keyword and the argument.
Packit d7e8d0
 * Valid keywords are all keywords from the long_opt list without
Packit d7e8d0
 * the leading dashes. The special keywords "help", "warranty" and "version"
Packit d7e8d0
 * are not valid here.
Packit d7e8d0
 * The special keyword "alias" may be used to store alias definitions,
Packit d7e8d0
 * which are later expanded like long options.
Packit d7e8d0
 * The option
Packit d7e8d0
 *   ignore-invalid-option OPTIONNAMEs
Packit d7e8d0
 * is recognized and updates a list of option which should be ignored if they
Packit d7e8d0
 * are not defined.
Packit d7e8d0
 * Caller must free returned strings.
Packit d7e8d0
 * If called with FP set to NULL command line args are parse instead.
Packit d7e8d0
 *
Packit d7e8d0
 * Q: Should we allow the syntax
Packit d7e8d0
 *     keyword = value
Packit d7e8d0
 *    and accept for boolean options a value of 1/0, yes/no or true/false?
Packit d7e8d0
 * Note: Abbreviation of options is here not allowed.
Packit d7e8d0
 */
Packit d7e8d0
int
Packit d7e8d0
optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
Packit d7e8d0
	       ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
Packit d7e8d0
{
Packit d7e8d0
  int state, i, c;
Packit d7e8d0
  int idx=0;
Packit d7e8d0
  char keyword[100];
Packit d7e8d0
  char *buffer = NULL;
Packit d7e8d0
  size_t buflen = 0;
Packit d7e8d0
  int in_alias=0;
Packit d7e8d0
Packit d7e8d0
  if (!fp) /* Divert to to arg_parse() in this case.  */
Packit d7e8d0
    return arg_parse (arg, opts);
Packit d7e8d0
Packit d7e8d0
  initialize (arg, filename, lineno);
Packit d7e8d0
Packit d7e8d0
  /* Find the next keyword.  */
Packit d7e8d0
  state = i = 0;
Packit d7e8d0
  for (;;)
Packit d7e8d0
    {
Packit d7e8d0
      c = getc (fp);
Packit d7e8d0
      if (c == '\n' || c== EOF )
Packit d7e8d0
        {
Packit d7e8d0
          if ( c != EOF )
Packit d7e8d0
            ++*lineno;
Packit d7e8d0
          if (state == -1)
Packit d7e8d0
            break;
Packit d7e8d0
          else if (state == 2)
Packit d7e8d0
            {
Packit d7e8d0
              keyword[i] = 0;
Packit d7e8d0
              for (i=0; opts[i].short_opt; i++ )
Packit d7e8d0
                {
Packit d7e8d0
                  if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
Packit d7e8d0
                    break;
Packit d7e8d0
                }
Packit d7e8d0
              idx = i;
Packit d7e8d0
              arg->r_opt = opts[idx].short_opt;
Packit d7e8d0
              if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
Packit d7e8d0
                {
Packit d7e8d0
                  state = i = 0;
Packit d7e8d0
                  continue;
Packit d7e8d0
                }
Packit d7e8d0
              else if (!opts[idx].short_opt )
Packit d7e8d0
                {
Packit d7e8d0
                  if (!strcmp (keyword, "ignore-invalid-option"))
Packit d7e8d0
                    {
Packit d7e8d0
                      /* No argument - ignore this meta option.  */
Packit d7e8d0
                      state = i = 0;
Packit d7e8d0
                      continue;
Packit d7e8d0
                    }
Packit d7e8d0
                  else if (ignore_invalid_option_p (arg, keyword))
Packit d7e8d0
                    {
Packit d7e8d0
                      /* This invalid option is in the iio list.  */
Packit d7e8d0
                      state = i = 0;
Packit d7e8d0
                      continue;
Packit d7e8d0
                    }
Packit d7e8d0
                  arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
Packit d7e8d0
                                ? ARGPARSE_INVALID_COMMAND
Packit d7e8d0
                                : ARGPARSE_INVALID_OPTION);
Packit d7e8d0
                }
Packit d7e8d0
              else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
Packit d7e8d0
                arg->r_type = 0; /* Does not take an arg. */
Packit d7e8d0
              else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) )
Packit d7e8d0
                arg->r_type = 0; /* Arg is optional.  */
Packit d7e8d0
              else
Packit d7e8d0
                arg->r_opt = ARGPARSE_MISSING_ARG;
Packit d7e8d0
Packit d7e8d0
              break;
Packit d7e8d0
	    }
Packit d7e8d0
          else if (state == 3)
Packit d7e8d0
            {
Packit d7e8d0
              /* No argument found.  */
Packit d7e8d0
              if (in_alias)
Packit d7e8d0
                arg->r_opt = ARGPARSE_MISSING_ARG;
Packit d7e8d0
              else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
Packit d7e8d0
                arg->r_type = 0; /* Does not take an arg. */
Packit d7e8d0
              else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
Packit d7e8d0
                arg->r_type = 0; /* No optional argument. */
Packit d7e8d0
              else
Packit d7e8d0
                arg->r_opt = ARGPARSE_MISSING_ARG;
Packit d7e8d0
Packit d7e8d0
              break;
Packit d7e8d0
	    }
Packit d7e8d0
          else if (state == 4)
Packit d7e8d0
            {
Packit d7e8d0
              /* Has an argument. */
Packit d7e8d0
              if (in_alias)
Packit d7e8d0
                {
Packit d7e8d0
                  if (!buffer)
Packit d7e8d0
                    arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
Packit d7e8d0
                  else
Packit d7e8d0
                    {
Packit d7e8d0
                      char *p;
Packit d7e8d0
Packit d7e8d0
                      buffer[i] = 0;
Packit d7e8d0
                      p = strpbrk (buffer, " \t");
Packit d7e8d0
                      if (p)
Packit d7e8d0
                        {
Packit d7e8d0
                          *p++ = 0;
Packit d7e8d0
                          trim_spaces (p);
Packit d7e8d0
			}
Packit d7e8d0
                      if (!p || !*p)
Packit d7e8d0
                        {
Packit d7e8d0
                          xfree (buffer);
Packit d7e8d0
                          arg->r_opt = ARGPARSE_INVALID_ALIAS;
Packit d7e8d0
                        }
Packit d7e8d0
                      else
Packit d7e8d0
                        {
Packit d7e8d0
                          store_alias (arg, buffer, p);
Packit d7e8d0
                        }
Packit d7e8d0
		    }
Packit d7e8d0
		}
Packit d7e8d0
              else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
Packit d7e8d0
                arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
Packit d7e8d0
              else
Packit d7e8d0
                {
Packit d7e8d0
                  char *p;
Packit d7e8d0
Packit d7e8d0
                  if (!buffer)
Packit d7e8d0
                    {
Packit d7e8d0
                      keyword[i] = 0;
Packit d7e8d0
                      buffer = xtrystrdup (keyword);
Packit d7e8d0
                      if (!buffer)
Packit d7e8d0
                        arg->r_opt = ARGPARSE_OUT_OF_CORE;
Packit d7e8d0
		    }
Packit d7e8d0
                  else
Packit d7e8d0
                    buffer[i] = 0;
Packit d7e8d0
Packit d7e8d0
                  if (buffer)
Packit d7e8d0
                    {
Packit d7e8d0
                      trim_spaces (buffer);
Packit d7e8d0
                      p = buffer;
Packit d7e8d0
                      if (*p == '"')
Packit d7e8d0
                        {
Packit d7e8d0
                          /* Remove quotes. */
Packit d7e8d0
                          p++;
Packit d7e8d0
                          if (*p && p[strlen(p)-1] == '\"' )
Packit d7e8d0
                            p[strlen(p)-1] = 0;
Packit d7e8d0
                        }
Packit d7e8d0
                      if (!set_opt_arg (arg, opts[idx].flags, p))
Packit d7e8d0
                        xfree (buffer);
Packit d7e8d0
                    }
Packit d7e8d0
                }
Packit d7e8d0
              break;
Packit d7e8d0
            }
Packit d7e8d0
          else if (c == EOF)
Packit d7e8d0
            {
Packit d7e8d0
              ignore_invalid_option_clear (arg);
Packit d7e8d0
              if (ferror (fp))
Packit d7e8d0
                arg->r_opt = ARGPARSE_READ_ERROR;
Packit d7e8d0
              else
Packit d7e8d0
                arg->r_opt = 0; /* EOF. */
Packit d7e8d0
              break;
Packit d7e8d0
            }
Packit d7e8d0
          state = 0;
Packit d7e8d0
          i = 0;
Packit d7e8d0
        }
Packit d7e8d0
      else if (state == -1)
Packit d7e8d0
        ; /* Skip. */
Packit d7e8d0
      else if (state == 0 && isascii (c) && isspace(c))
Packit d7e8d0
        ; /* Skip leading white space.  */
Packit d7e8d0
      else if (state == 0 && c == '#' )
Packit d7e8d0
        state = 1;	/* Start of a comment.  */
Packit d7e8d0
      else if (state == 1)
Packit d7e8d0
        ; /* Skip comments. */
Packit d7e8d0
      else if (state == 2 && isascii (c) && isspace(c))
Packit d7e8d0
        {
Packit d7e8d0
          /* Check keyword.  */
Packit d7e8d0
          keyword[i] = 0;
Packit d7e8d0
          for (i=0; opts[i].short_opt; i++ )
Packit d7e8d0
            if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
Packit d7e8d0
              break;
Packit d7e8d0
          idx = i;
Packit d7e8d0
          arg->r_opt = opts[idx].short_opt;
Packit d7e8d0
          if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
Packit d7e8d0
            {
Packit d7e8d0
              state = 1; /* Process like a comment.  */
Packit d7e8d0
            }
Packit d7e8d0
          else if (!opts[idx].short_opt)
Packit d7e8d0
            {
Packit d7e8d0
              if (!strcmp (keyword, "alias"))
Packit d7e8d0
                {
Packit d7e8d0
                  in_alias = 1;
Packit d7e8d0
                  state = 3;
Packit d7e8d0
                }
Packit d7e8d0
              else if (!strcmp (keyword, "ignore-invalid-option"))
Packit d7e8d0
                {
Packit d7e8d0
                  if (ignore_invalid_option_add (arg, fp))
Packit d7e8d0
                    {
Packit d7e8d0
                      arg->r_opt = ARGPARSE_OUT_OF_CORE;
Packit d7e8d0
                      break;
Packit d7e8d0
                    }
Packit d7e8d0
                  state = i = 0;
Packit d7e8d0
                  ++*lineno;
Packit d7e8d0
                }
Packit d7e8d0
              else if (ignore_invalid_option_p (arg, keyword))
Packit d7e8d0
                state = 1; /* Process like a comment.  */
Packit d7e8d0
              else
Packit d7e8d0
                {
Packit d7e8d0
                  arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
Packit d7e8d0
                                ? ARGPARSE_INVALID_COMMAND
Packit d7e8d0
                                : ARGPARSE_INVALID_OPTION);
Packit d7e8d0
                  state = -1; /* Skip rest of line and leave.  */
Packit d7e8d0
                }
Packit d7e8d0
            }
Packit d7e8d0
          else
Packit d7e8d0
            state = 3;
Packit d7e8d0
        }
Packit d7e8d0
      else if (state == 3)
Packit d7e8d0
        {
Packit d7e8d0
          /* Skip leading spaces of the argument.  */
Packit d7e8d0
          if (!isascii (c) || !isspace(c))
Packit d7e8d0
            {
Packit d7e8d0
              i = 0;
Packit d7e8d0
              keyword[i++] = c;
Packit d7e8d0
              state = 4;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
      else if (state == 4)
Packit d7e8d0
        {
Packit d7e8d0
          /* Collect the argument. */
Packit d7e8d0
          if (buffer)
Packit d7e8d0
            {
Packit d7e8d0
              if (i < buflen-1)
Packit d7e8d0
                buffer[i++] = c;
Packit d7e8d0
              else
Packit d7e8d0
                {
Packit d7e8d0
                  char *tmp;
Packit d7e8d0
                  size_t tmplen = buflen + 50;
Packit d7e8d0
Packit d7e8d0
                  tmp = xtryrealloc (buffer, tmplen);
Packit d7e8d0
                  if (tmp)
Packit d7e8d0
                    {
Packit d7e8d0
                      buflen = tmplen;
Packit d7e8d0
                      buffer = tmp;
Packit d7e8d0
                      buffer[i++] = c;
Packit d7e8d0
                    }
Packit d7e8d0
                  else
Packit d7e8d0
                    {
Packit d7e8d0
                      xfree (buffer);
Packit d7e8d0
                      arg->r_opt = ARGPARSE_OUT_OF_CORE;
Packit d7e8d0
                      break;
Packit d7e8d0
                    }
Packit d7e8d0
                }
Packit d7e8d0
            }
Packit d7e8d0
          else if (i < DIM(keyword)-1)
Packit d7e8d0
            keyword[i++] = c;
Packit d7e8d0
          else
Packit d7e8d0
            {
Packit d7e8d0
              size_t tmplen = DIM(keyword) + 50;
Packit d7e8d0
              buffer = xtrymalloc (tmplen);
Packit d7e8d0
              if (buffer)
Packit d7e8d0
                {
Packit d7e8d0
                  buflen = tmplen;
Packit d7e8d0
                  memcpy(buffer, keyword, i);
Packit d7e8d0
                  buffer[i++] = c;
Packit d7e8d0
                }
Packit d7e8d0
              else
Packit d7e8d0
                {
Packit d7e8d0
                  arg->r_opt = ARGPARSE_OUT_OF_CORE;
Packit d7e8d0
                  break;
Packit d7e8d0
                }
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
      else if (i >= DIM(keyword)-1)
Packit d7e8d0
        {
Packit d7e8d0
          arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG;
Packit d7e8d0
          state = -1; /* Skip rest of line and leave.  */
Packit d7e8d0
        }
Packit d7e8d0
      else
Packit d7e8d0
        {
Packit d7e8d0
          keyword[i++] = c;
Packit d7e8d0
          state = 2;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  return arg->r_opt;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
static int
Packit d7e8d0
find_long_option( ARGPARSE_ARGS *arg,
Packit d7e8d0
		  ARGPARSE_OPTS *opts, const char *keyword )
Packit d7e8d0
{
Packit d7e8d0
    int i;
Packit d7e8d0
    size_t n;
Packit d7e8d0
Packit d7e8d0
    (void)arg;
Packit d7e8d0
Packit d7e8d0
    /* Would be better if we can do a binary search, but it is not
Packit d7e8d0
       possible to reorder our option table because we would mess
Packit d7e8d0
       up our help strings - What we can do is: Build a nice option
Packit d7e8d0
       lookup table when this function is first invoked */
Packit d7e8d0
    if( !*keyword )
Packit d7e8d0
	return -1;
Packit d7e8d0
    for(i=0; opts[i].short_opt; i++ )
Packit d7e8d0
	if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
Packit d7e8d0
	    return i;
Packit d7e8d0
#if 0
Packit d7e8d0
    {
Packit d7e8d0
	ALIAS_DEF a;
Packit d7e8d0
	/* see whether it is an alias */
Packit d7e8d0
	for( a = args->internal.aliases; a; a = a->next ) {
Packit d7e8d0
	    if( !strcmp( a->name, keyword) ) {
Packit d7e8d0
		/* todo: must parse the alias here */
Packit d7e8d0
		args->internal.cur_alias = a;
Packit d7e8d0
		return -3; /* alias available */
Packit d7e8d0
	    }
Packit d7e8d0
	}
Packit d7e8d0
    }
Packit d7e8d0
#endif
Packit d7e8d0
    /* not found, see whether it is an abbreviation */
Packit d7e8d0
    /* aliases may not be abbreviated */
Packit d7e8d0
    n = strlen( keyword );
Packit d7e8d0
    for(i=0; opts[i].short_opt; i++ ) {
Packit d7e8d0
	if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
Packit d7e8d0
	    int j;
Packit d7e8d0
	    for(j=i+1; opts[j].short_opt; j++ ) {
Packit d7e8d0
		if( opts[j].long_opt
Packit d7e8d0
		    && !strncmp( opts[j].long_opt, keyword, n ) )
Packit d7e8d0
		    return -2;	/* abbreviation is ambiguous */
Packit d7e8d0
	    }
Packit d7e8d0
	    return i;
Packit d7e8d0
	}
Packit d7e8d0
    }
Packit d7e8d0
    return -1;  /* Not found.  */
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
int
Packit d7e8d0
arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
Packit d7e8d0
{
Packit d7e8d0
  int idx;
Packit d7e8d0
  int argc;
Packit d7e8d0
  char **argv;
Packit d7e8d0
  char *s, *s2;
Packit d7e8d0
  int i;
Packit d7e8d0
  char string_with_x[] = "x";
Packit d7e8d0
Packit d7e8d0
  initialize( arg, NULL, NULL );
Packit d7e8d0
  argc = *arg->argc;
Packit d7e8d0
  argv = *arg->argv;
Packit d7e8d0
  idx = arg->internal.idx;
Packit d7e8d0
Packit d7e8d0
  if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0))
Packit d7e8d0
    {
Packit d7e8d0
      /* Skip the first argument.  */
Packit d7e8d0
      argc--; argv++; idx++;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
 next_one:
Packit d7e8d0
  if (!argc)
Packit d7e8d0
    {
Packit d7e8d0
      /* No more args.  */
Packit d7e8d0
      arg->r_opt = 0;
Packit d7e8d0
      goto leave; /* Ready. */
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  s = *argv;
Packit d7e8d0
  arg->internal.last = s;
Packit d7e8d0
Packit d7e8d0
  if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL))
Packit d7e8d0
    {
Packit d7e8d0
      arg->r_opt = ARGPARSE_IS_ARG;  /* Not an option but an argument.  */
Packit d7e8d0
      arg->r_type = 2;
Packit d7e8d0
      arg->r.ret_str = s;
Packit d7e8d0
      argc--; argv++; idx++; /* set to next one */
Packit d7e8d0
    }
Packit d7e8d0
  else if( arg->internal.stopped )
Packit d7e8d0
    {
Packit d7e8d0
      arg->r_opt = 0;
Packit d7e8d0
      goto leave; /* Ready.  */
Packit d7e8d0
    }
Packit d7e8d0
  else if ( *s == '-' && s[1] == '-' )
Packit d7e8d0
    {
Packit d7e8d0
      /* Long option.  */
Packit d7e8d0
      char *argpos;
Packit d7e8d0
Packit d7e8d0
      arg->internal.inarg = 0;
Packit d7e8d0
      if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP))
Packit d7e8d0
        {
Packit d7e8d0
          /* Stop option processing.  */
Packit d7e8d0
          arg->internal.stopped = 1;
Packit d7e8d0
          arg->flags |= ARGPARSE_FLAG_STOP_SEEN;
Packit d7e8d0
          argc--; argv++; idx++;
Packit d7e8d0
          goto next_one;
Packit d7e8d0
	}
Packit d7e8d0
Packit d7e8d0
      argpos = strchr( s+2, '=' );
Packit d7e8d0
      if ( argpos )
Packit d7e8d0
        *argpos = 0;
Packit d7e8d0
      i = find_long_option ( arg, opts, s+2 );
Packit d7e8d0
      if ( argpos )
Packit d7e8d0
        *argpos = '=';
Packit d7e8d0
Packit d7e8d0
      if ( i < 0 && !strcmp ( "help", s+2) )
Packit d7e8d0
        show_help (opts, arg->flags);
Packit d7e8d0
      else if ( i < 0 && !strcmp ( "version", s+2) )
Packit d7e8d0
        {
Packit d7e8d0
          if (!(arg->flags & ARGPARSE_FLAG_NOVERSION))
Packit d7e8d0
            {
Packit d7e8d0
              show_version ();
Packit d7e8d0
              exit(0);
Packit d7e8d0
            }
Packit d7e8d0
	}
Packit d7e8d0
      else if ( i < 0 && !strcmp( "warranty", s+2))
Packit d7e8d0
        {
Packit d7e8d0
          writestrings (0, strusage (16), "\n", NULL);
Packit d7e8d0
          exit (0);
Packit d7e8d0
	}
Packit d7e8d0
      else if ( i < 0 && !strcmp( "dump-options", s+2) )
Packit d7e8d0
        {
Packit d7e8d0
          for (i=0; opts[i].short_opt; i++ )
Packit d7e8d0
            {
Packit d7e8d0
              if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE))
Packit d7e8d0
                writestrings (0, "--", opts[i].long_opt, "\n", NULL);
Packit d7e8d0
	    }
Packit d7e8d0
          writestrings (0, "--dump-options\n--help\n--version\n--warranty\n",
Packit d7e8d0
                        NULL);
Packit d7e8d0
          exit (0);
Packit d7e8d0
	}
Packit d7e8d0
Packit d7e8d0
      if ( i == -2 )
Packit d7e8d0
        arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION;
Packit d7e8d0
      else if ( i == -1 )
Packit d7e8d0
        {
Packit d7e8d0
          arg->r_opt = ARGPARSE_INVALID_OPTION;
Packit d7e8d0
          arg->r.ret_str = s+2;
Packit d7e8d0
	}
Packit d7e8d0
      else
Packit d7e8d0
        arg->r_opt = opts[i].short_opt;
Packit d7e8d0
      if ( i < 0 )
Packit d7e8d0
        ;
Packit d7e8d0
      else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
Packit d7e8d0
        {
Packit d7e8d0
          if ( argpos )
Packit d7e8d0
            {
Packit d7e8d0
              s2 = argpos+1;
Packit d7e8d0
              if ( !*s2 )
Packit d7e8d0
                s2 = NULL;
Packit d7e8d0
	    }
Packit d7e8d0
          else
Packit d7e8d0
            s2 = argv[1];
Packit d7e8d0
          if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
Packit d7e8d0
            {
Packit d7e8d0
              arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional.  */
Packit d7e8d0
	    }
Packit d7e8d0
          else if ( !s2 )
Packit d7e8d0
            {
Packit d7e8d0
              arg->r_opt = ARGPARSE_MISSING_ARG;
Packit d7e8d0
	    }
Packit d7e8d0
          else if ( !argpos && *s2 == '-'
Packit d7e8d0
                    && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
Packit d7e8d0
            {
Packit d7e8d0
              /* The argument is optional and the next seems to be an
Packit d7e8d0
                 option.  We do not check this possible option but
Packit d7e8d0
                 assume no argument */
Packit d7e8d0
              arg->r_type = ARGPARSE_TYPE_NONE;
Packit d7e8d0
	    }
Packit d7e8d0
          else
Packit d7e8d0
            {
Packit d7e8d0
              set_opt_arg (arg, opts[i].flags, s2);
Packit d7e8d0
              if ( !argpos )
Packit d7e8d0
                {
Packit d7e8d0
                  argc--; argv++; idx++; /* Skip one.  */
Packit d7e8d0
		}
Packit d7e8d0
	    }
Packit d7e8d0
	}
Packit d7e8d0
      else
Packit d7e8d0
        {
Packit d7e8d0
          /* Does not take an argument. */
Packit d7e8d0
          if ( argpos )
Packit d7e8d0
            arg->r_type = ARGPARSE_UNEXPECTED_ARG;
Packit d7e8d0
          else
Packit d7e8d0
            arg->r_type = 0;
Packit d7e8d0
	}
Packit d7e8d0
      argc--; argv++; idx++; /* Set to next one.  */
Packit d7e8d0
    }
Packit d7e8d0
    else if ( (*s == '-' && s[1]) || arg->internal.inarg )
Packit d7e8d0
      {
Packit d7e8d0
        /* Short option.  */
Packit d7e8d0
	int dash_kludge = 0;
Packit d7e8d0
Packit d7e8d0
	i = 0;
Packit d7e8d0
	if ( !arg->internal.inarg )
Packit d7e8d0
          {
Packit d7e8d0
	    arg->internal.inarg++;
Packit d7e8d0
	    if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) )
Packit d7e8d0
              {
Packit d7e8d0
                for (i=0; opts[i].short_opt; i++ )
Packit d7e8d0
                  if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1))
Packit d7e8d0
                    {
Packit d7e8d0
                      dash_kludge = 1;
Packit d7e8d0
                      break;
Packit d7e8d0
		    }
Packit d7e8d0
              }
Packit d7e8d0
          }
Packit d7e8d0
	s += arg->internal.inarg;
Packit d7e8d0
Packit d7e8d0
	if (!dash_kludge )
Packit d7e8d0
          {
Packit d7e8d0
	    for (i=0; opts[i].short_opt; i++ )
Packit d7e8d0
              if ( opts[i].short_opt == *s )
Packit d7e8d0
                break;
Packit d7e8d0
          }
Packit d7e8d0
Packit d7e8d0
	if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
Packit d7e8d0
          show_help (opts, arg->flags);
Packit d7e8d0
Packit d7e8d0
	arg->r_opt = opts[i].short_opt;
Packit d7e8d0
	if (!opts[i].short_opt )
Packit d7e8d0
          {
Packit d7e8d0
	    arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)?
Packit d7e8d0
              ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION;
Packit d7e8d0
	    arg->internal.inarg++; /* Point to the next arg.  */
Packit d7e8d0
	    arg->r.ret_str = s;
Packit d7e8d0
          }
Packit d7e8d0
	else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
Packit d7e8d0
          {
Packit d7e8d0
	    if ( s[1] && !dash_kludge )
Packit d7e8d0
              {
Packit d7e8d0
		s2 = s+1;
Packit d7e8d0
		set_opt_arg (arg, opts[i].flags, s2);
Packit d7e8d0
              }
Packit d7e8d0
	    else
Packit d7e8d0
              {
Packit d7e8d0
		s2 = argv[1];
Packit d7e8d0
		if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
Packit d7e8d0
                  {
Packit d7e8d0
		    arg->r_type = ARGPARSE_TYPE_NONE;
Packit d7e8d0
                  }
Packit d7e8d0
		else if ( !s2 )
Packit d7e8d0
                  {
Packit d7e8d0
		    arg->r_opt = ARGPARSE_MISSING_ARG;
Packit d7e8d0
                  }
Packit d7e8d0
		else if ( *s2 == '-' && s2[1]
Packit d7e8d0
                          && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
Packit d7e8d0
                  {
Packit d7e8d0
		    /* The argument is optional and the next seems to
Packit d7e8d0
	               be an option.  We do not check this possible
Packit d7e8d0
	               option but assume no argument.  */
Packit d7e8d0
		    arg->r_type = ARGPARSE_TYPE_NONE;
Packit d7e8d0
                  }
Packit d7e8d0
		else
Packit d7e8d0
                  {
Packit d7e8d0
		    set_opt_arg (arg, opts[i].flags, s2);
Packit d7e8d0
		    argc--; argv++; idx++; /* Skip one.  */
Packit d7e8d0
                  }
Packit d7e8d0
              }
Packit d7e8d0
	    s = string_with_x; /* This is so that !s[1] yields false.  */
Packit d7e8d0
          }
Packit d7e8d0
	else
Packit d7e8d0
          {
Packit d7e8d0
            /* Does not take an argument.  */
Packit d7e8d0
	    arg->r_type = ARGPARSE_TYPE_NONE;
Packit d7e8d0
	    arg->internal.inarg++; /* Point to the next arg.  */
Packit d7e8d0
          }
Packit d7e8d0
	if ( !s[1] || dash_kludge )
Packit d7e8d0
          {
Packit d7e8d0
            /* No more concatenated short options.  */
Packit d7e8d0
	    arg->internal.inarg = 0;
Packit d7e8d0
	    argc--; argv++; idx++;
Packit d7e8d0
          }
Packit d7e8d0
      }
Packit d7e8d0
  else if ( arg->flags & ARGPARSE_FLAG_MIXED )
Packit d7e8d0
    {
Packit d7e8d0
      arg->r_opt = ARGPARSE_IS_ARG;
Packit d7e8d0
      arg->r_type = 2;
Packit d7e8d0
      arg->r.ret_str = s;
Packit d7e8d0
      argc--; argv++; idx++; /* Set to next one.  */
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      arg->internal.stopped = 1; /* Stop option processing.  */
Packit d7e8d0
      goto next_one;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  *arg->argc = argc;
Packit d7e8d0
  *arg->argv = argv;
Packit d7e8d0
  arg->internal.idx = idx;
Packit d7e8d0
  return arg->r_opt;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Returns: -1 on error, 0 for an integer type and 1 for a non integer
Packit d7e8d0
   type argument.  */
Packit d7e8d0
static int
Packit d7e8d0
set_opt_arg (ARGPARSE_ARGS *arg, unsigned flags, char *s)
Packit d7e8d0
{
Packit d7e8d0
  int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10;
Packit d7e8d0
  long l;
Packit d7e8d0
Packit d7e8d0
  switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) )
Packit d7e8d0
    {
Packit d7e8d0
    case ARGPARSE_TYPE_LONG:
Packit d7e8d0
    case ARGPARSE_TYPE_INT:
Packit d7e8d0
      errno = 0;
Packit d7e8d0
      l = strtol (s, NULL, base);
Packit d7e8d0
      if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
Packit d7e8d0
        {
Packit d7e8d0
          arg->r_opt = ARGPARSE_INVALID_ARG;
Packit d7e8d0
          return -1;
Packit d7e8d0
        }
Packit d7e8d0
      if (arg->r_type == ARGPARSE_TYPE_LONG)
Packit d7e8d0
        arg->r.ret_long = l;
Packit d7e8d0
      else if ( (l < 0 && l < INT_MIN) || l > INT_MAX )
Packit d7e8d0
        {
Packit d7e8d0
          arg->r_opt = ARGPARSE_INVALID_ARG;
Packit d7e8d0
          return -1;
Packit d7e8d0
        }
Packit d7e8d0
      else
Packit d7e8d0
        arg->r.ret_int = (int)l;
Packit d7e8d0
      return 0;
Packit d7e8d0
Packit d7e8d0
    case ARGPARSE_TYPE_ULONG:
Packit d7e8d0
      while (isascii (*s) && isspace(*s))
Packit d7e8d0
        s++;
Packit d7e8d0
      if (*s == '-')
Packit d7e8d0
        {
Packit d7e8d0
          arg->r.ret_ulong = 0;
Packit d7e8d0
          arg->r_opt = ARGPARSE_INVALID_ARG;
Packit d7e8d0
          return -1;
Packit d7e8d0
        }
Packit d7e8d0
      errno = 0;
Packit d7e8d0
      arg->r.ret_ulong = strtoul (s, NULL, base);
Packit d7e8d0
      if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE)
Packit d7e8d0
        {
Packit d7e8d0
          arg->r_opt = ARGPARSE_INVALID_ARG;
Packit d7e8d0
          return -1;
Packit d7e8d0
        }
Packit d7e8d0
      return 0;
Packit d7e8d0
Packit d7e8d0
    case ARGPARSE_TYPE_STRING:
Packit d7e8d0
    default:
Packit d7e8d0
      arg->r.ret_str = s;
Packit d7e8d0
      return 1;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
static size_t
Packit d7e8d0
long_opt_strlen( ARGPARSE_OPTS *o )
Packit d7e8d0
{
Packit d7e8d0
  size_t n = strlen (o->long_opt);
Packit d7e8d0
Packit d7e8d0
  if ( o->description && *o->description == '|' )
Packit d7e8d0
    {
Packit d7e8d0
      const char *s;
Packit d7e8d0
      int is_utf8 = is_native_utf8 ();
Packit d7e8d0
Packit d7e8d0
      s=o->description+1;
Packit d7e8d0
      if ( *s != '=' )
Packit d7e8d0
        n++;
Packit d7e8d0
      /* For a (mostly) correct length calculation we exclude
Packit d7e8d0
         continuation bytes (10xxxxxx) if we are on a native utf8
Packit d7e8d0
         terminal. */
Packit d7e8d0
      for (; *s && *s != '|'; s++ )
Packit d7e8d0
        if ( is_utf8 && (*s&0xc0) != 0x80 )
Packit d7e8d0
          n++;
Packit d7e8d0
    }
Packit d7e8d0
  return n;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/****************
Packit d7e8d0
 * Print formatted help. The description string has some special
Packit d7e8d0
 * meanings:
Packit d7e8d0
 *  - A description string which is "@" suppresses help output for
Packit d7e8d0
 *    this option
Packit d7e8d0
 *  - a description,ine which starts with a '@' and is followed by
Packit d7e8d0
 *    any other characters is printed as is; this may be used for examples
Packit Service 30b792
 *    as such.
Packit d7e8d0
 *  - A description which starts with a '|' outputs the string between this
Packit d7e8d0
 *    bar and the next one as arguments of the long option.
Packit d7e8d0
 */
Packit d7e8d0
static void
Packit d7e8d0
show_help (ARGPARSE_OPTS *opts, unsigned int flags)
Packit d7e8d0
{
Packit d7e8d0
  const char *s;
Packit d7e8d0
  char tmp[2];
Packit d7e8d0
Packit d7e8d0
  show_version ();
Packit d7e8d0
  writestrings (0, "\n", NULL);
Packit d7e8d0
  s = strusage (42);
Packit d7e8d0
  if (s && *s == '1')
Packit d7e8d0
    {
Packit d7e8d0
      s = strusage (40);
Packit d7e8d0
      writestrings (1, s, NULL);
Packit d7e8d0
      if (*s && s[strlen(s)] != '\n')
Packit d7e8d0
        writestrings (1, "\n", NULL);
Packit d7e8d0
    }
Packit d7e8d0
  s = strusage(41);
Packit d7e8d0
  writestrings (0, s, "\n", NULL);
Packit d7e8d0
  if ( opts[0].description )
Packit d7e8d0
    {
Packit d7e8d0
      /* Auto format the option description.  */
Packit d7e8d0
      int i,j, indent;
Packit d7e8d0
Packit d7e8d0
      /* Get max. length of long options.  */
Packit d7e8d0
      for (i=indent=0; opts[i].short_opt; i++ )
Packit d7e8d0
        {
Packit d7e8d0
          if ( opts[i].long_opt )
Packit d7e8d0
            if ( !opts[i].description || *opts[i].description != '@' )
Packit d7e8d0
              if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
Packit d7e8d0
                indent = j;
Packit d7e8d0
	}
Packit d7e8d0
Packit d7e8d0
      /* Example: " -v, --verbose   Viele Sachen ausgeben" */
Packit d7e8d0
      indent += 10;
Packit d7e8d0
      if ( *opts[0].description != '@' )
Packit d7e8d0
        writestrings (0, "Options:", "\n", NULL);
Packit d7e8d0
      for (i=0; opts[i].short_opt; i++ )
Packit d7e8d0
        {
Packit d7e8d0
          s = map_static_macro_string (_( opts[i].description ));
Packit d7e8d0
          if ( s && *s== '@' && !s[1] ) /* Hide this line.  */
Packit d7e8d0
            continue;
Packit d7e8d0
          if ( s && *s == '@' )  /* Unindented comment only line.  */
Packit d7e8d0
            {
Packit d7e8d0
              for (s++; *s; s++ )
Packit d7e8d0
                {
Packit d7e8d0
                  if ( *s == '\n' )
Packit d7e8d0
                    {
Packit d7e8d0
                      if( s[1] )
Packit d7e8d0
                        writestrings (0, "\n", NULL);
Packit d7e8d0
		    }
Packit d7e8d0
                  else
Packit d7e8d0
                    {
Packit d7e8d0
                      tmp[0] = *s;
Packit d7e8d0
                      tmp[1] = 0;
Packit d7e8d0
                      writestrings (0, tmp, NULL);
Packit d7e8d0
                    }
Packit d7e8d0
                }
Packit d7e8d0
              writestrings (0, "\n", NULL);
Packit d7e8d0
              continue;
Packit d7e8d0
	    }
Packit d7e8d0
Packit d7e8d0
          j = 3;
Packit d7e8d0
          if ( opts[i].short_opt < 256 )
Packit d7e8d0
            {
Packit d7e8d0
              tmp[0] = opts[i].short_opt;
Packit d7e8d0
              tmp[1] = 0;
Packit d7e8d0
              writestrings (0, " -", tmp, NULL );
Packit d7e8d0
              if ( !opts[i].long_opt )
Packit d7e8d0
                {
Packit d7e8d0
                  if (s && *s == '|' )
Packit d7e8d0
                    {
Packit d7e8d0
                      writestrings (0, " ", NULL); j++;
Packit d7e8d0
                      for (s++ ; *s && *s != '|'; s++, j++ )
Packit d7e8d0
                        {
Packit d7e8d0
                          tmp[0] = *s;
Packit d7e8d0
                          tmp[1] = 0;
Packit d7e8d0
                          writestrings (0, tmp, NULL);
Packit d7e8d0
                        }
Packit d7e8d0
                      if ( *s )
Packit d7e8d0
                        s++;
Packit d7e8d0
		    }
Packit d7e8d0
		}
Packit d7e8d0
	    }
Packit d7e8d0
          else
Packit d7e8d0
            writestrings (0, "   ", NULL);
Packit d7e8d0
          if ( opts[i].long_opt )
Packit d7e8d0
            {
Packit d7e8d0
              tmp[0] = opts[i].short_opt < 256?',':' ';
Packit d7e8d0
              tmp[1] = 0;
Packit d7e8d0
              j += writestrings (0, tmp, " --", opts[i].long_opt, NULL);
Packit d7e8d0
              if (s && *s == '|' )
Packit d7e8d0
                {
Packit d7e8d0
                  if ( *++s != '=' )
Packit d7e8d0
                    {
Packit d7e8d0
                      writestrings (0, " ", NULL);
Packit d7e8d0
                      j++;
Packit d7e8d0
		    }
Packit d7e8d0
                  for ( ; *s && *s != '|'; s++, j++ )
Packit d7e8d0
                    {
Packit d7e8d0
                      tmp[0] = *s;
Packit d7e8d0
                      tmp[1] = 0;
Packit d7e8d0
                      writestrings (0, tmp, NULL);
Packit d7e8d0
                    }
Packit d7e8d0
                  if ( *s )
Packit d7e8d0
                    s++;
Packit d7e8d0
		}
Packit d7e8d0
              writestrings (0, "   ", NULL);
Packit d7e8d0
              j += 3;
Packit d7e8d0
	    }
Packit d7e8d0
          for (;j < indent; j++ )
Packit d7e8d0
            writestrings (0, " ", NULL);
Packit d7e8d0
          if ( s )
Packit d7e8d0
            {
Packit d7e8d0
              if ( *s && j > indent )
Packit d7e8d0
                {
Packit d7e8d0
                  writestrings (0, "\n", NULL);
Packit d7e8d0
                  for (j=0;j < indent; j++ )
Packit d7e8d0
                    writestrings (0, " ", NULL);
Packit d7e8d0
		}
Packit d7e8d0
              for (; *s; s++ )
Packit d7e8d0
                {
Packit d7e8d0
                  if ( *s == '\n' )
Packit d7e8d0
                    {
Packit d7e8d0
                      if ( s[1] )
Packit d7e8d0
                        {
Packit d7e8d0
                          writestrings (0, "\n", NULL);
Packit d7e8d0
                          for (j=0; j < indent; j++ )
Packit d7e8d0
                            writestrings (0, " ", NULL);
Packit d7e8d0
			}
Packit d7e8d0
		    }
Packit d7e8d0
                  else
Packit d7e8d0
                    {
Packit d7e8d0
                      tmp[0] = *s;
Packit d7e8d0
                      tmp[1] = 0;
Packit d7e8d0
                      writestrings (0, tmp, NULL);
Packit d7e8d0
                    }
Packit d7e8d0
		}
Packit d7e8d0
	    }
Packit d7e8d0
          writestrings (0, "\n", NULL);
Packit d7e8d0
	}
Packit d7e8d0
	if ( (flags & ARGPARSE_FLAG_ONEDASH) )
Packit d7e8d0
          writestrings (0, "\n(A single dash may be used "
Packit d7e8d0
                        "instead of the double ones)\n", NULL);
Packit d7e8d0
    }
Packit d7e8d0
  if ( (s=strusage(19)) )
Packit d7e8d0
    {
Packit d7e8d0
      writestrings (0, "\n", NULL);
Packit d7e8d0
      writestrings (0, s, NULL);
Packit d7e8d0
    }
Packit d7e8d0
  flushstrings (0);
Packit d7e8d0
  exit(0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static void
Packit d7e8d0
show_version ()
Packit d7e8d0
{
Packit d7e8d0
  const char *s;
Packit d7e8d0
  int i;
Packit d7e8d0
Packit d7e8d0
  /* Version line.  */
Packit d7e8d0
  writestrings (0, strusage (11), NULL);
Packit d7e8d0
  if ((s=strusage (12)))
Packit d7e8d0
    writestrings (0, " (", s, ")", NULL);
Packit d7e8d0
  writestrings (0, " ", strusage (13), "\n", NULL);
Packit d7e8d0
  /* Additional version lines. */
Packit d7e8d0
  for (i=20; i < 30; i++)
Packit d7e8d0
    if ((s=strusage (i)))
Packit d7e8d0
      writestrings (0, s, "\n", NULL);
Packit d7e8d0
  /* Copyright string.  */
Packit d7e8d0
  if ((s=strusage (14)))
Packit d7e8d0
    writestrings (0, s, "\n", NULL);
Packit d7e8d0
  /* Licence string.  */
Packit d7e8d0
  if( (s=strusage (10)) )
Packit d7e8d0
    writestrings (0, s, "\n", NULL);
Packit d7e8d0
  /* Copying conditions. */
Packit d7e8d0
  if ( (s=strusage(15)) )
Packit d7e8d0
    writestrings (0, s, NULL);
Packit d7e8d0
  /* Thanks. */
Packit d7e8d0
  if ((s=strusage(18)))
Packit d7e8d0
    writestrings (0, s, NULL);
Packit d7e8d0
  /* Additional program info. */
Packit d7e8d0
  for (i=30; i < 40; i++ )
Packit d7e8d0
    if ( (s=strusage (i)) )
Packit d7e8d0
      writestrings (0, s, NULL);
Packit d7e8d0
  flushstrings (0);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
void
Packit d7e8d0
usage (int level)
Packit d7e8d0
{
Packit d7e8d0
  const char *p;
Packit d7e8d0
Packit d7e8d0
  if (!level)
Packit d7e8d0
    {
Packit d7e8d0
      writestrings (1, strusage(11), " ", strusage(13), "; ",
Packit d7e8d0
                    strusage (14), "\n", NULL);
Packit d7e8d0
      flushstrings (1);
Packit d7e8d0
    }
Packit d7e8d0
  else if (level == 1)
Packit d7e8d0
    {
Packit d7e8d0
      p = strusage (40);
Packit d7e8d0
      writestrings (1, p, NULL);
Packit d7e8d0
      if (*p && p[strlen(p)] != '\n')
Packit d7e8d0
        writestrings (1, "\n", NULL);
Packit d7e8d0
      exit (2);
Packit d7e8d0
    }
Packit d7e8d0
  else if (level == 2)
Packit d7e8d0
    {
Packit d7e8d0
      p = strusage (42);
Packit d7e8d0
      if (p && *p == '1')
Packit d7e8d0
        {
Packit d7e8d0
          p = strusage (40);
Packit d7e8d0
          writestrings (1, p, NULL);
Packit d7e8d0
          if (*p && p[strlen(p)] != '\n')
Packit d7e8d0
            writestrings (1, "\n", NULL);
Packit d7e8d0
        }
Packit d7e8d0
      writestrings (0, strusage(41), "\n", NULL);
Packit d7e8d0
      exit (0);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Level
Packit d7e8d0
 *     0: Print copyright string to stderr
Packit d7e8d0
 *     1: Print a short usage hint to stderr and terminate
Packit d7e8d0
 *     2: Print a long usage hint to stdout and terminate
Packit d7e8d0
 *    10: Return license info string
Packit d7e8d0
 *    11: Return the name of the program
Packit d7e8d0
 *    12: Return optional name of package which includes this program.
Packit d7e8d0
 *    13: version  string
Packit d7e8d0
 *    14: copyright string
Packit d7e8d0
 *    15: Short copying conditions (with LFs)
Packit d7e8d0
 *    16: Long copying conditions (with LFs)
Packit d7e8d0
 *    17: Optional printable OS name
Packit d7e8d0
 *    18: Optional thanks list (with LFs)
Packit d7e8d0
 *    19: Bug report info
Packit d7e8d0
 *20..29: Additional lib version strings.
Packit d7e8d0
 *30..39: Additional program info (with LFs)
Packit d7e8d0
 *    40: short usage note (with LF)
Packit d7e8d0
 *    41: long usage note (with LF)
Packit d7e8d0
 *    42: Flag string:
Packit d7e8d0
 *          First char is '1':
Packit d7e8d0
 *             The short usage notes needs to be printed
Packit d7e8d0
 *             before the long usage note.
Packit d7e8d0
 */
Packit d7e8d0
const char *
Packit d7e8d0
strusage( int level )
Packit d7e8d0
{
Packit d7e8d0
  const char *p = strusage_handler? strusage_handler(level) : NULL;
Packit d7e8d0
Packit d7e8d0
  if ( p )
Packit d7e8d0
    return map_static_macro_string (p);
Packit d7e8d0
Packit d7e8d0
  switch ( level )
Packit d7e8d0
    {
Packit d7e8d0
Packit d7e8d0
    case 10:
Packit d7e8d0
#if ARGPARSE_GPL_VERSION == 3
Packit d7e8d0
      p = ("License GPLv3+: GNU GPL version 3 or later "
Packit Service 30b792
           "<https://www.gnu.org/licenses/gpl.html>");
Packit d7e8d0
#else
Packit d7e8d0
      p = ("License GPLv2+: GNU GPL version 2 or later "
Packit Service 30b792
           "<https://www.gnu.org/licenses/>");
Packit d7e8d0
#endif
Packit d7e8d0
      break;
Packit d7e8d0
    case 11: p = "foo"; break;
Packit d7e8d0
    case 13: p = "0.0"; break;
Packit d7e8d0
    case 14: p = ARGPARSE_CRIGHT_STR; break;
Packit d7e8d0
    case 15: p =
Packit d7e8d0
"This is free software: you are free to change and redistribute it.\n"
Packit d7e8d0
"There is NO WARRANTY, to the extent permitted by law.\n";
Packit d7e8d0
      break;
Packit d7e8d0
    case 16: p =
Packit d7e8d0
"This is free software; you can redistribute it and/or modify\n"
Packit d7e8d0
"it under the terms of the GNU General Public License as published by\n"
Packit d7e8d0
"the Free Software Foundation; either version "
Packit d7e8d0
ARGPARSE_STR2(ARGPARSE_GPL_VERSION)
Packit d7e8d0
" of the License, or\n"
Packit d7e8d0
"(at your option) any later version.\n\n"
Packit d7e8d0
"It is distributed in the hope that it will be useful,\n"
Packit d7e8d0
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
Packit d7e8d0
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
Packit d7e8d0
"GNU General Public License for more details.\n\n"
Packit d7e8d0
"You should have received a copy of the GNU General Public License\n"
Packit d7e8d0
"along with this software.  If not, see <https://www.gnu.org/licenses/>.\n";
Packit d7e8d0
      break;
Packit d7e8d0
    case 40: /* short and long usage */
Packit d7e8d0
    case 41: p = ""; break;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  return p;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Set the usage handler.  This function is basically a constructor.  */
Packit d7e8d0
void
Packit d7e8d0
set_strusage ( const char *(*f)( int ) )
Packit d7e8d0
{
Packit d7e8d0
  strusage_handler = f;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
#ifdef TEST
Packit d7e8d0
static struct {
Packit d7e8d0
    int verbose;
Packit d7e8d0
    int debug;
Packit d7e8d0
    char *outfile;
Packit d7e8d0
    char *crf;
Packit d7e8d0
    int myopt;
Packit d7e8d0
    int echo;
Packit d7e8d0
    int a_long_one;
Packit d7e8d0
} opt;
Packit d7e8d0
Packit d7e8d0
int
Packit d7e8d0
main(int argc, char **argv)
Packit d7e8d0
{
Packit d7e8d0
  ARGPARSE_OPTS opts[] = {
Packit d7e8d0
    ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"),
Packit d7e8d0
    ARGPARSE_s_n('e', "echo"   , ("Zeile ausgeben, damit wir sehen, "
Packit d7e8d0
                                  "was wir eingegeben haben")),
Packit d7e8d0
    ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"),
Packit d7e8d0
    ARGPARSE_s_s('o', "output", 0 ),
Packit d7e8d0
    ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ),
Packit d7e8d0
    /* Note that on a non-utf8 terminal the ß might garble the output. */
Packit d7e8d0
    ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"),
Packit d7e8d0
    ARGPARSE_o_i('m', "my-option", 0),
Packit d7e8d0
    ARGPARSE_s_n(500, "a-long-option", 0 ),
Packit d7e8d0
    ARGPARSE_end()
Packit d7e8d0
  };
Packit d7e8d0
  ARGPARSE_ARGS pargs = { &argc, &argv, (ARGPARSE_FLAG_ALL
Packit d7e8d0
                                         | ARGPARSE_FLAG_MIXED
Packit d7e8d0
                                         | ARGPARSE_FLAG_ONEDASH) };
Packit d7e8d0
  int i;
Packit d7e8d0
Packit d7e8d0
  while (arg_parse  (&pargs, opts))
Packit d7e8d0
    {
Packit d7e8d0
      switch (pargs.r_opt)
Packit d7e8d0
        {
Packit d7e8d0
        case ARGPARSE_IS_ARG :
Packit d7e8d0
          printf ("arg='%s'\n", pargs.r.ret_str);
Packit d7e8d0
          break;
Packit d7e8d0
        case 'v': opt.verbose++; break;
Packit d7e8d0
        case 'e': opt.echo++; break;
Packit d7e8d0
        case 'd': opt.debug++; break;
Packit d7e8d0
        case 'o': opt.outfile = pargs.r.ret_str; break;
Packit d7e8d0
        case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
Packit d7e8d0
        case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
Packit d7e8d0
        case 500: opt.a_long_one++;  break;
Packit d7e8d0
        default : pargs.err = ARGPARSE_PRINT_WARNING; break;
Packit d7e8d0
	}
Packit d7e8d0
    }
Packit d7e8d0
  for (i=0; i < argc; i++ )
Packit d7e8d0
    printf ("%3d -> (%s)\n", i, argv[i] );
Packit d7e8d0
  puts ("Options:");
Packit d7e8d0
  if (opt.verbose)
Packit d7e8d0
    printf ("  verbose=%d\n", opt.verbose );
Packit d7e8d0
  if (opt.debug)
Packit d7e8d0
    printf ("  debug=%d\n", opt.debug );
Packit d7e8d0
  if (opt.outfile)
Packit d7e8d0
    printf ("  outfile='%s'\n", opt.outfile );
Packit d7e8d0
  if (opt.crf)
Packit d7e8d0
    printf ("  crffile='%s'\n", opt.crf );
Packit d7e8d0
  if (opt.myopt)
Packit d7e8d0
    printf ("  myopt=%d\n", opt.myopt );
Packit d7e8d0
  if (opt.a_long_one)
Packit d7e8d0
    printf ("  a-long-one=%d\n", opt.a_long_one );
Packit d7e8d0
  if (opt.echo)
Packit d7e8d0
    printf ("  echo=%d\n", opt.echo );
Packit d7e8d0
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
#endif /*TEST*/
Packit d7e8d0
Packit d7e8d0
/**** bottom of file ****/