Blame src/argparse.c

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