|
Packit |
fc043f |
/* argparse.c - Argument Parser for option handling
|
|
Packit |
fc043f |
* Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch
|
|
Packit |
fc043f |
* Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
|
|
Packit |
fc043f |
* Copyright (C) 2015-2018 g10 Code GmbH
|
|
Packit |
fc043f |
*
|
|
Packit |
fc043f |
* This file is part of Libgpg-error.
|
|
Packit |
fc043f |
*
|
|
Packit |
fc043f |
* This file is free software; you can redistribute it and/or modify
|
|
Packit |
fc043f |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit |
fc043f |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
fc043f |
* the License, or (at your option) any later version.
|
|
Packit |
fc043f |
*
|
|
Packit |
fc043f |
* This file is distributed in the hope that it will be useful,
|
|
Packit |
fc043f |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
fc043f |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
fc043f |
* GNU General Public License for more details.
|
|
Packit |
fc043f |
*
|
|
Packit |
fc043f |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
fc043f |
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
|
Packit |
fc043f |
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
Packit |
fc043f |
*
|
|
Packit |
fc043f |
* This file was originally a part of GnuPG.
|
|
Packit |
fc043f |
*/
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
#ifdef HAVE_CONFIG_H
|
|
Packit |
fc043f |
#include <config.h>
|
|
Packit |
fc043f |
#endif
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
#include <stdio.h>
|
|
Packit |
fc043f |
#include <stdlib.h>
|
|
Packit |
fc043f |
#include <ctype.h>
|
|
Packit |
fc043f |
#include <string.h>
|
|
Packit |
fc043f |
#include <stdarg.h>
|
|
Packit |
fc043f |
#include <limits.h>
|
|
Packit |
fc043f |
#include <errno.h>
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
#include "gpgrt-int.h"
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Special short options which are auto-inserterd. */
|
|
Packit |
fc043f |
#define ARGPARSE_SHORTOPT_HELP 32768
|
|
Packit |
fc043f |
#define ARGPARSE_SHORTOPT_VERSION 32769
|
|
Packit |
fc043f |
#define ARGPARSE_SHORTOPT_WARRANTY 32770
|
|
Packit |
fc043f |
#define ARGPARSE_SHORTOPT_DUMP_OPTIONS 32771
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* A mask for the types. */
|
|
Packit |
fc043f |
#define ARGPARSE_TYPE_MASK 7 /* Mask for the type values. */
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Internal object of the public gpgrt_argparse_t object. */
|
|
Packit |
fc043f |
struct _gpgrt_argparse_internal_s
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
int idx;
|
|
Packit |
fc043f |
int inarg;
|
|
Packit |
fc043f |
int stopped;
|
|
Packit |
fc043f |
const char *last;
|
|
Packit |
fc043f |
void *aliases;
|
|
Packit |
fc043f |
const void *cur_alias;
|
|
Packit |
fc043f |
void *iio_list;
|
|
Packit |
fc043f |
gpgrt_opt_t **opts; /* Malloced array of pointer to user provided opts. */
|
|
Packit |
fc043f |
};
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
typedef struct alias_def_s *ALIAS_DEF;
|
|
Packit |
fc043f |
struct alias_def_s {
|
|
Packit |
fc043f |
ALIAS_DEF next;
|
|
Packit |
fc043f |
char *name; /* malloced buffer with name, \0, value */
|
|
Packit |
fc043f |
const char *value; /* ptr into name */
|
|
Packit |
fc043f |
};
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Object to store the names for the --ignore-invalid-option option.
|
|
Packit |
fc043f |
This is a simple linked list. */
|
|
Packit |
fc043f |
typedef struct iio_item_def_s *IIO_ITEM_DEF;
|
|
Packit |
fc043f |
struct iio_item_def_s
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
IIO_ITEM_DEF next;
|
|
Packit |
fc043f |
char name[1]; /* String with the long option name. */
|
|
Packit |
fc043f |
};
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* The almost always needed user handler for strusage. */
|
|
Packit |
fc043f |
static const char *(*strusage_handler)( int ) = NULL;
|
|
Packit |
fc043f |
/* Optional handler to write strings. See _gpgrt_set_usage_outfnc. */
|
|
Packit |
fc043f |
static int (*custom_outfnc) (int, const char *);
|
|
Packit |
fc043f |
/* Optional handler to map strings. See _gpgrt_set_fixed_string_mapper. */
|
|
Packit |
fc043f |
static const char *(*fixed_string_mapper)(const char*);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static int set_opt_arg (gpgrt_argparse_t *arg, unsigned int flags, char *s);
|
|
Packit |
fc043f |
static void show_help (gpgrt_opt_t **opts, unsigned int flags);
|
|
Packit |
fc043f |
static void show_version (void);
|
|
Packit |
fc043f |
static int writestrings (int is_error, const char *string,
|
|
Packit |
fc043f |
...) GPGRT_ATTR_SENTINEL(0);
|
|
Packit |
fc043f |
static int arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Return true if the native charset is utf-8. */
|
|
Packit |
fc043f |
static int
|
|
Packit |
fc043f |
is_native_utf8 (void)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
static char result;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (!result)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
const char *p = _gpgrt_strusage (8);
|
|
Packit |
fc043f |
if (!p || !*p || !strcmp (p, "utf-8"))
|
|
Packit |
fc043f |
result = 1;
|
|
Packit |
fc043f |
result |= 128;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
return (result & 1);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static char *
|
|
Packit |
fc043f |
trim_spaces (char *str)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
char *string, *p, *mark;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
string = str;
|
|
Packit |
fc043f |
/* Find first non space character. */
|
|
Packit |
fc043f |
for (p=string; *p && isspace (*(unsigned char*)p) ; p++)
|
|
Packit |
fc043f |
;
|
|
Packit |
fc043f |
/* Move characters. */
|
|
Packit |
fc043f |
for ((mark = NULL); (*string = *p); string++, p++)
|
|
Packit |
fc043f |
if (isspace (*(unsigned char*)p))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!mark)
|
|
Packit |
fc043f |
mark = string;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
mark = NULL;
|
|
Packit |
fc043f |
if (mark)
|
|
Packit |
fc043f |
*mark = '\0' ; /* Remove trailing spaces. */
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
return str ;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static const char *
|
|
Packit |
fc043f |
map_fixed_string (const char *string)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
return fixed_string_mapper? fixed_string_mapper (string) : string;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Write STRING and all following const char * arguments either to
|
|
Packit |
fc043f |
stdout or, if IS_ERROR is set, to stderr. The list of strings must
|
|
Packit |
fc043f |
be terminated by a NULL. */
|
|
Packit |
fc043f |
static int
|
|
Packit |
fc043f |
writestrings (int is_error, const char *string, ...)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
va_list arg_ptr;
|
|
Packit |
fc043f |
const char *s;
|
|
Packit |
fc043f |
int count = 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (string)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
s = string;
|
|
Packit |
fc043f |
va_start (arg_ptr, string);
|
|
Packit |
fc043f |
do
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (custom_outfnc)
|
|
Packit |
fc043f |
custom_outfnc (is_error? 2:1, s);
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
fputs (s, is_error? stderr : stdout);
|
|
Packit |
fc043f |
count += strlen (s);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
while ((s = va_arg (arg_ptr, const char *)));
|
|
Packit |
fc043f |
va_end (arg_ptr);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
return count;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static void
|
|
Packit |
fc043f |
flushstrings (int is_error)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (custom_outfnc)
|
|
Packit |
fc043f |
custom_outfnc (is_error? 2:1, NULL);
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
_gpgrt_fflush (is_error? es_stderr : es_stdout);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static void
|
|
Packit |
fc043f |
deinitialize (gpgrt_argparse_t *arg)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (arg->internal)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
xfree (arg->internal->opts);
|
|
Packit |
fc043f |
xfree (arg->internal);
|
|
Packit |
fc043f |
arg->internal = NULL;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
arg->lineno = 0;
|
|
Packit |
fc043f |
arg->err = 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Our own exit handler to clean up used memory. */
|
|
Packit |
fc043f |
static void
|
|
Packit |
fc043f |
my_exit (gpgrt_argparse_t *arg, int code)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
deinitialize (arg);
|
|
Packit |
fc043f |
exit (code);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static gpg_err_code_t
|
|
Packit |
fc043f |
initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!arg->internal || (arg->flags & ARGPARSE_FLAG_RESET))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Allocate internal data. */
|
|
Packit |
fc043f |
if (!arg->internal)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->internal = xtrymalloc (sizeof *arg->internal);
|
|
Packit |
fc043f |
if (!arg->internal)
|
|
Packit |
fc043f |
return _gpg_err_code_from_syserror ();
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (arg->internal->opts)
|
|
Packit |
fc043f |
xfree (arg->internal->opts);
|
|
Packit |
fc043f |
arg->internal->opts = NULL;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Initialize this instance. */
|
|
Packit |
fc043f |
arg->internal->idx = 0;
|
|
Packit |
fc043f |
arg->internal->last = NULL;
|
|
Packit |
fc043f |
arg->internal->inarg = 0;
|
|
Packit |
fc043f |
arg->internal->stopped = 0;
|
|
Packit |
fc043f |
arg->internal->aliases = NULL;
|
|
Packit |
fc043f |
arg->internal->cur_alias = NULL;
|
|
Packit |
fc043f |
arg->internal->iio_list = NULL;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Clear the copy of the option list. */
|
|
Packit |
fc043f |
/* Clear the error indicator. */
|
|
Packit |
fc043f |
arg->err = 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Usually an option file will be parsed from the start.
|
|
Packit |
fc043f |
* However, we do not open the stream and thus we have no way to
|
|
Packit |
fc043f |
* know the current lineno. Using this flag we can allow the
|
|
Packit |
fc043f |
* user to provide a lineno which we don't reset. */
|
|
Packit |
fc043f |
if (fp || !(arg->flags & ARGPARSE_FLAG_NOLINENO))
|
|
Packit |
fc043f |
arg->lineno = 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Need to clear the reset request. */
|
|
Packit |
fc043f |
arg->flags &= ~ARGPARSE_FLAG_RESET;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Check initial args. */
|
|
Packit |
fc043f |
if ( *arg->argc < 0 )
|
|
Packit |
fc043f |
_gpgrt_log_bug ("invalid argument passed to gpgrt_argparse\n");
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Create an array with pointers to the provided list of options.
|
|
Packit |
fc043f |
* Keeping a copy is useful to sort that array and thus do a binary
|
|
Packit |
fc043f |
* search and to allow for extra space at the end to insert the
|
|
Packit |
fc043f |
* hidden options. An ARGPARSE_FLAG_RESET can be used to reinit
|
|
Packit |
fc043f |
* this array. */
|
|
Packit |
fc043f |
if (!arg->internal->opts)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
static gpgrt_opt_t help_opt
|
|
Packit |
fc043f |
= ARGPARSE_s_n (ARGPARSE_SHORTOPT_HELP, "help", "@");
|
|
Packit |
fc043f |
static gpgrt_opt_t version_opt
|
|
Packit |
fc043f |
= ARGPARSE_s_n (ARGPARSE_SHORTOPT_VERSION, "version", "@");
|
|
Packit |
fc043f |
static gpgrt_opt_t warranty_opt
|
|
Packit |
fc043f |
= ARGPARSE_s_n (ARGPARSE_SHORTOPT_WARRANTY, "warranty", "@");
|
|
Packit |
fc043f |
static gpgrt_opt_t dump_options_opt
|
|
Packit |
fc043f |
= ARGPARSE_s_n(ARGPARSE_SHORTOPT_DUMP_OPTIONS, "dump-options", "@");
|
|
Packit |
fc043f |
static gpgrt_opt_t end_marker
|
|
Packit |
fc043f |
= ARGPARSE_end ();
|
|
Packit |
fc043f |
int seen_help = 0;
|
|
Packit |
fc043f |
int seen_version = 0;
|
|
Packit |
fc043f |
int seen_warranty = 0;
|
|
Packit |
fc043f |
int seen_dump_options = 0;
|
|
Packit |
fc043f |
int i;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
for (i=0; opts[i].short_opt; i++)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (opts[i].long_opt)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!strcmp(opts[i].long_opt, help_opt.long_opt))
|
|
Packit |
fc043f |
seen_help = 1;
|
|
Packit |
fc043f |
else if (!strcmp(opts[i].long_opt, version_opt.long_opt))
|
|
Packit |
fc043f |
seen_version = 1;
|
|
Packit |
fc043f |
else if (!strcmp(opts[i].long_opt, warranty_opt.long_opt))
|
|
Packit |
fc043f |
seen_warranty = 1;
|
|
Packit |
fc043f |
else if (!strcmp(opts[i].long_opt, dump_options_opt.long_opt))
|
|
Packit |
fc043f |
seen_dump_options = 1;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
i += 4; /* The number of the above internal options. */
|
|
Packit |
fc043f |
i++; /* End of list marker. */
|
|
Packit |
fc043f |
arg->internal->opts = xtrycalloc (i, sizeof *arg->internal->opts);
|
|
Packit |
fc043f |
if (!arg->internal->opts)
|
|
Packit |
fc043f |
return _gpg_err_code_from_syserror ();
|
|
Packit |
fc043f |
for(i=0; opts[i].short_opt; i++)
|
|
Packit |
fc043f |
arg->internal->opts[i] = opts + i;
|
|
Packit |
fc043f |
if (!seen_help)
|
|
Packit |
fc043f |
arg->internal->opts[i++] = &help_opt;
|
|
Packit |
fc043f |
if (!seen_version)
|
|
Packit |
fc043f |
arg->internal->opts[i++] = &version_opt;
|
|
Packit |
fc043f |
if (!seen_warranty)
|
|
Packit |
fc043f |
arg->internal->opts[i++] = &warranty_opt;
|
|
Packit |
fc043f |
if (!seen_dump_options)
|
|
Packit |
fc043f |
arg->internal->opts[i++] = &dump_options_opt;
|
|
Packit |
fc043f |
arg->internal->opts[i] = &end_marker;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (arg->err)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Last option was erroneous. */
|
|
Packit |
fc043f |
const char *s;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (fp)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
|
|
Packit |
fc043f |
s = _("argument not expected");
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_READ_ERROR )
|
|
Packit |
fc043f |
s = _("read error");
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG )
|
|
Packit |
fc043f |
s = _("keyword too long");
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_MISSING_ARG )
|
|
Packit |
fc043f |
s = _("missing argument");
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
|
|
Packit |
fc043f |
s = _("invalid argument");
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
|
|
Packit |
fc043f |
s = _("invalid command");
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS )
|
|
Packit |
fc043f |
s = _("invalid alias definition");
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
|
|
Packit |
fc043f |
s = _("out of core");
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
s = _("invalid option");
|
|
Packit |
fc043f |
_gpgrt_log_error ("%s:%u: %s\n",
|
|
Packit |
fc043f |
_gpgrt_fname_get (fp), arg->lineno, s);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
s = arg->internal->last? arg->internal->last:"[??]";
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if ( arg->r_opt == ARGPARSE_MISSING_ARG )
|
|
Packit |
fc043f |
_gpgrt_log_error (_("missing argument for option \"%.50s\"\n"), s);
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
|
|
Packit |
fc043f |
_gpgrt_log_error (_("invalid argument for option \"%.50s\"\n"), s);
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
|
|
Packit |
fc043f |
_gpgrt_log_error (_("option \"%.50s\" does not expect "
|
|
Packit |
fc043f |
"an argument\n"), s);
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
|
|
Packit |
fc043f |
_gpgrt_log_error (_("invalid command \"%.50s\"\n"), s);
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION )
|
|
Packit |
fc043f |
_gpgrt_log_error (_("option \"%.50s\" is ambiguous\n"), s);
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND )
|
|
Packit |
fc043f |
_gpgrt_log_error (_("command \"%.50s\" is ambiguous\n"),s );
|
|
Packit |
fc043f |
else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
|
|
Packit |
fc043f |
_gpgrt_log_error ("%s\n", _("out of core\n"));
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
_gpgrt_log_error (_("invalid option \"%.50s\"\n"), s);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if (arg->err != ARGPARSE_PRINT_WARNING)
|
|
Packit |
fc043f |
my_exit (arg, 2);
|
|
Packit |
fc043f |
arg->err = 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Zero out the return value union. */
|
|
Packit |
fc043f |
arg->r.ret_str = NULL;
|
|
Packit |
fc043f |
arg->r.ret_long = 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
return 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static void
|
|
Packit |
fc043f |
store_alias( gpgrt_argparse_t *arg, char *name, char *value )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* TODO: replace this dummy function with a rea one
|
|
Packit |
fc043f |
* and fix the probelms IRIX has with (ALIAS_DEV)arg..
|
|
Packit |
fc043f |
* used as lvalue
|
|
Packit |
fc043f |
*/
|
|
Packit |
fc043f |
(void)arg;
|
|
Packit |
fc043f |
(void)name;
|
|
Packit |
fc043f |
(void)value;
|
|
Packit |
fc043f |
#if 0
|
|
Packit |
fc043f |
ALIAS_DEF a = xmalloc( sizeof *a );
|
|
Packit |
fc043f |
a->name = name;
|
|
Packit |
fc043f |
a->value = value;
|
|
Packit |
fc043f |
a->next = (ALIAS_DEF)arg->internal->aliases;
|
|
Packit |
fc043f |
(ALIAS_DEF)arg->internal->aliases = a;
|
|
Packit |
fc043f |
#endif
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Return true if KEYWORD is in the ignore-invalid-option list. */
|
|
Packit |
fc043f |
static int
|
|
Packit |
fc043f |
ignore_invalid_option_p (gpgrt_argparse_t *arg, const char *keyword)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
IIO_ITEM_DEF item = arg->internal->iio_list;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
for (; item; item = item->next)
|
|
Packit |
fc043f |
if (!strcmp (item->name, keyword))
|
|
Packit |
fc043f |
return 1;
|
|
Packit |
fc043f |
return 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Add the keywords up to the next LF to the list of to be ignored
|
|
Packit |
fc043f |
options. After returning FP will either be at EOF or the next
|
|
Packit |
fc043f |
character read wll be the first of a new line. The function
|
|
Packit |
fc043f |
returns 0 on success or true on malloc failure. */
|
|
Packit |
fc043f |
static int
|
|
Packit |
fc043f |
ignore_invalid_option_add (gpgrt_argparse_t *arg, estream_t fp)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
IIO_ITEM_DEF item;
|
|
Packit |
fc043f |
int c;
|
|
Packit |
fc043f |
char name[100];
|
|
Packit |
fc043f |
int namelen = 0;
|
|
Packit |
fc043f |
int ready = 0;
|
|
Packit |
fc043f |
enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
while (!ready)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
c = _gpgrt_fgetc (fp);
|
|
Packit |
fc043f |
if (c == '\n')
|
|
Packit |
fc043f |
ready = 1;
|
|
Packit |
fc043f |
else if (c == EOF)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
c = '\n';
|
|
Packit |
fc043f |
ready = 1;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
again:
|
|
Packit |
fc043f |
switch (state)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
case skipWS:
|
|
Packit |
fc043f |
if (!isascii (c) || !isspace(c))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
namelen = 0;
|
|
Packit |
fc043f |
state = collectNAME;
|
|
Packit |
fc043f |
goto again;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
case collectNAME:
|
|
Packit |
fc043f |
if (isspace (c))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
state = addNAME;
|
|
Packit |
fc043f |
goto again;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (namelen < DIM(name)-1)
|
|
Packit |
fc043f |
name[namelen++] = c;
|
|
Packit |
fc043f |
else /* Too long. */
|
|
Packit |
fc043f |
state = skipNAME;
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
case skipNAME:
|
|
Packit |
fc043f |
if (isspace (c))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
state = skipWS;
|
|
Packit |
fc043f |
goto again;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
case addNAME:
|
|
Packit |
fc043f |
name[namelen] = 0;
|
|
Packit |
fc043f |
if (!ignore_invalid_option_p (arg, name))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
item = xtrymalloc (sizeof *item + namelen);
|
|
Packit |
fc043f |
if (!item)
|
|
Packit |
fc043f |
return 1;
|
|
Packit |
fc043f |
strcpy (item->name, name);
|
|
Packit |
fc043f |
item->next = (IIO_ITEM_DEF)arg->internal->iio_list;
|
|
Packit |
fc043f |
arg->internal->iio_list = item;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
state = skipWS;
|
|
Packit |
fc043f |
goto again;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
return 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Clear the entire ignore-invalid-option list. */
|
|
Packit |
fc043f |
static void
|
|
Packit |
fc043f |
ignore_invalid_option_clear (gpgrt_argparse_t *arg)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
IIO_ITEM_DEF item, tmpitem;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
for (item = arg->internal->iio_list; item; item = tmpitem)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
tmpitem = item->next;
|
|
Packit |
fc043f |
xfree (item);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
arg->internal->iio_list = NULL;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/****************
|
|
Packit |
fc043f |
* Get options from a file.
|
|
Packit |
fc043f |
* Lines starting with '#' are comment lines.
|
|
Packit |
fc043f |
* Syntax is simply a keyword and the argument.
|
|
Packit |
fc043f |
* Valid keywords are all keywords from the long_opt list without
|
|
Packit |
fc043f |
* the leading dashes. The special keywords "help", "warranty" and "version"
|
|
Packit |
fc043f |
* are not valid here.
|
|
Packit |
fc043f |
* The special keyword "alias" may be used to store alias definitions,
|
|
Packit |
fc043f |
* which are later expanded like long options.
|
|
Packit |
fc043f |
* The option
|
|
Packit |
fc043f |
* ignore-invalid-option OPTIONNAMEs
|
|
Packit |
fc043f |
* is recognized and updates a list of option which should be ignored if they
|
|
Packit |
fc043f |
* are not defined.
|
|
Packit |
fc043f |
* Caller must free returned strings.
|
|
Packit |
fc043f |
* If called with FP set to NULL command line args are parse instead.
|
|
Packit |
fc043f |
*
|
|
Packit |
fc043f |
* Q: Should we allow the syntax
|
|
Packit |
fc043f |
* keyword = value
|
|
Packit |
fc043f |
* and accept for boolean options a value of 1/0, yes/no or true/false?
|
|
Packit |
fc043f |
* Note: Abbreviation of options is here not allowed.
|
|
Packit |
fc043f |
*/
|
|
Packit |
fc043f |
int
|
|
Packit |
fc043f |
_gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
gpgrt_opt_t **opts;
|
|
Packit |
fc043f |
int state, i, c;
|
|
Packit |
fc043f |
int idx = 0;
|
|
Packit |
fc043f |
char keyword[100];
|
|
Packit |
fc043f |
char *buffer = NULL;
|
|
Packit |
fc043f |
size_t buflen = 0;
|
|
Packit |
fc043f |
int in_alias=0;
|
|
Packit |
fc043f |
int unread_buf[3]; /* We use an int so that we can store EOF. */
|
|
Packit |
fc043f |
int unread_buf_count = 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (arg && !opts_orig)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
deinitialize (arg);
|
|
Packit |
fc043f |
return 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (!fp) /* Divert to arg_parse() in this case. */
|
|
Packit |
fc043f |
return arg_parse (arg, opts_orig);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (initialize (arg, opts_orig, fp))
|
|
Packit |
fc043f |
return (arg->r_opt = ARGPARSE_OUT_OF_CORE);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
opts = arg->internal->opts;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* If the LINENO is zero we assume that we are at the start of a
|
|
Packit |
fc043f |
* file and we skip over a possible Byte Order Mark. */
|
|
Packit |
fc043f |
if (!arg->lineno)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
unread_buf[0] = _gpgrt_fgetc (fp);
|
|
Packit |
fc043f |
unread_buf[1] = _gpgrt_fgetc (fp);
|
|
Packit |
fc043f |
unread_buf[2] = _gpgrt_fgetc (fp);
|
|
Packit |
fc043f |
if (unread_buf[0] != 0xef
|
|
Packit |
fc043f |
|| unread_buf[1] != 0xbb
|
|
Packit |
fc043f |
|| unread_buf[2] != 0xbf)
|
|
Packit |
fc043f |
unread_buf_count = 3;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Find the next keyword. */
|
|
Packit |
fc043f |
state = i = 0;
|
|
Packit |
fc043f |
for (;;)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (unread_buf_count)
|
|
Packit |
fc043f |
c = unread_buf[3 - unread_buf_count--];
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
c = _gpgrt_fgetc (fp);
|
|
Packit |
fc043f |
if (c == '\n' || c== EOF )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( c != EOF )
|
|
Packit |
fc043f |
arg->lineno++;
|
|
Packit |
fc043f |
if (state == -1)
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
else if (state == 2)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
keyword[i] = 0;
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (opts[i]->long_opt && !strcmp (opts[i]->long_opt, keyword))
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
idx = i;
|
|
Packit |
fc043f |
arg->r_opt = opts[idx]->short_opt;
|
|
Packit |
fc043f |
if ((opts[idx]->flags & ARGPARSE_OPT_IGNORE))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
state = i = 0;
|
|
Packit |
fc043f |
continue;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (!opts[idx]->short_opt )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!strcmp (keyword, "ignore-invalid-option"))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* No argument - ignore this meta option. */
|
|
Packit |
fc043f |
state = i = 0;
|
|
Packit |
fc043f |
continue;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (ignore_invalid_option_p (arg, keyword))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* This invalid option is in the iio list. */
|
|
Packit |
fc043f |
state = i = 0;
|
|
Packit |
fc043f |
continue;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
arg->r_opt = ((opts[idx]->flags & ARGPARSE_OPT_COMMAND)
|
|
Packit |
fc043f |
? ARGPARSE_INVALID_COMMAND
|
|
Packit |
fc043f |
: ARGPARSE_INVALID_OPTION);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (!(opts[idx]->flags & ARGPARSE_TYPE_MASK))
|
|
Packit |
fc043f |
arg->r_type = 0; /* Does not take an arg. */
|
|
Packit |
fc043f |
else if ((opts[idx]->flags & ARGPARSE_OPT_OPTIONAL) )
|
|
Packit |
fc043f |
arg->r_type = 0; /* Arg is optional. */
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_MISSING_ARG;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (state == 3)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* No argument found. */
|
|
Packit |
fc043f |
if (in_alias)
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_MISSING_ARG;
|
|
Packit |
fc043f |
else if (!(opts[idx]->flags & ARGPARSE_TYPE_MASK))
|
|
Packit |
fc043f |
arg->r_type = 0; /* Does not take an arg. */
|
|
Packit |
fc043f |
else if ((opts[idx]->flags & ARGPARSE_OPT_OPTIONAL))
|
|
Packit |
fc043f |
arg->r_type = 0; /* No optional argument. */
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_MISSING_ARG;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (state == 4)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Has an argument. */
|
|
Packit |
fc043f |
if (in_alias)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!buffer)
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
char *p;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
buffer[i] = 0;
|
|
Packit |
fc043f |
p = strpbrk (buffer, " \t");
|
|
Packit |
fc043f |
if (p)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
*p++ = 0;
|
|
Packit |
fc043f |
trim_spaces (p);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if (!p || !*p)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
xfree (buffer);
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_INVALID_ALIAS;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
store_alias (arg, buffer, p);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (!(opts[idx]->flags & ARGPARSE_TYPE_MASK))
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
char *p;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (!buffer)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
keyword[i] = 0;
|
|
Packit |
fc043f |
buffer = xtrystrdup (keyword);
|
|
Packit |
fc043f |
if (!buffer)
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_OUT_OF_CORE;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
buffer[i] = 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (buffer)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
trim_spaces (buffer);
|
|
Packit |
fc043f |
p = buffer;
|
|
Packit |
fc043f |
if (*p == '"')
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Remove quotes. */
|
|
Packit |
fc043f |
p++;
|
|
Packit |
fc043f |
if (*p && p[strlen(p)-1] == '\"' )
|
|
Packit |
fc043f |
p[strlen(p)-1] = 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if (!set_opt_arg (arg, opts[idx]->flags, p))
|
|
Packit |
fc043f |
xfree (buffer);
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
gpgrt_annotate_leaked_object (buffer);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (c == EOF)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
ignore_invalid_option_clear (arg);
|
|
Packit |
fc043f |
if (_gpgrt_ferror (fp))
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_READ_ERROR;
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
arg->r_opt = 0; /* EOF. */
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
state = 0;
|
|
Packit |
fc043f |
i = 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (state == -1)
|
|
Packit |
fc043f |
; /* Skip. */
|
|
Packit |
fc043f |
else if (state == 0 && isascii (c) && isspace(c))
|
|
Packit |
fc043f |
; /* Skip leading white space. */
|
|
Packit |
fc043f |
else if (state == 0 && c == '#' )
|
|
Packit |
fc043f |
state = 1; /* Start of a comment. */
|
|
Packit |
fc043f |
else if (state == 1)
|
|
Packit |
fc043f |
; /* Skip comments. */
|
|
Packit |
fc043f |
else if (state == 2 && isascii (c) && isspace(c))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Check keyword. */
|
|
Packit |
fc043f |
keyword[i] = 0;
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
if (opts[i]->long_opt && !strcmp (opts[i]->long_opt, keyword))
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
idx = i;
|
|
Packit |
fc043f |
arg->r_opt = opts[idx]->short_opt;
|
|
Packit |
fc043f |
if ((opts[idx]->flags & ARGPARSE_OPT_IGNORE))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
state = 1; /* Process like a comment. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (!opts[idx]->short_opt)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!strcmp (keyword, "alias"))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
in_alias = 1;
|
|
Packit |
fc043f |
state = 3;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (!strcmp (keyword, "ignore-invalid-option"))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (ignore_invalid_option_add (arg, fp))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_OUT_OF_CORE;
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
state = i = 0;
|
|
Packit |
fc043f |
arg->lineno++;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (ignore_invalid_option_p (arg, keyword))
|
|
Packit |
fc043f |
state = 1; /* Process like a comment. */
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ((opts[idx]->flags & ARGPARSE_OPT_COMMAND)
|
|
Packit |
fc043f |
? ARGPARSE_INVALID_COMMAND
|
|
Packit |
fc043f |
: ARGPARSE_INVALID_OPTION);
|
|
Packit |
fc043f |
state = -1; /* Skip rest of line and leave. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
state = 3;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (state == 3)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Skip leading spaces of the argument. */
|
|
Packit |
fc043f |
if (!isascii (c) || !isspace(c))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
i = 0;
|
|
Packit |
fc043f |
keyword[i++] = c;
|
|
Packit |
fc043f |
state = 4;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (state == 4)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Collect the argument. */
|
|
Packit |
fc043f |
if (buffer)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (i < buflen-1)
|
|
Packit |
fc043f |
buffer[i++] = c;
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
char *tmp;
|
|
Packit |
fc043f |
size_t tmplen = buflen + 50;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
tmp = xtryrealloc (buffer, tmplen);
|
|
Packit |
fc043f |
if (tmp)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
buflen = tmplen;
|
|
Packit |
fc043f |
buffer = tmp;
|
|
Packit |
fc043f |
buffer[i++] = c;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
xfree (buffer);
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_OUT_OF_CORE;
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (i < DIM(keyword)-1)
|
|
Packit |
fc043f |
keyword[i++] = c;
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
size_t tmplen = DIM(keyword) + 50;
|
|
Packit |
fc043f |
buffer = xtrymalloc (tmplen);
|
|
Packit |
fc043f |
if (buffer)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
buflen = tmplen;
|
|
Packit |
fc043f |
memcpy(buffer, keyword, i);
|
|
Packit |
fc043f |
buffer[i++] = c;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_OUT_OF_CORE;
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (i >= DIM(keyword)-1)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG;
|
|
Packit |
fc043f |
state = -1; /* Skip rest of line and leave. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
keyword[i++] = c;
|
|
Packit |
fc043f |
state = 2;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
return arg->r_opt;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Given the list of options OPTS and a keyword, return the index of
|
|
Packit |
fc043f |
* the long option macthing KEYWORD. On error -1 is retruned for not
|
|
Packit |
fc043f |
* found or -2 for ambigious keyword. */
|
|
Packit |
fc043f |
static int
|
|
Packit |
fc043f |
find_long_option (gpgrt_argparse_t *arg, gpgrt_opt_t **opts,
|
|
Packit |
fc043f |
const char *keyword)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
int i;
|
|
Packit |
fc043f |
size_t n;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
(void)arg; /* Not yet required. */
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Would be better if we can do a binary search, but it is not
|
|
Packit |
fc043f |
* possible to reorder our option table because we would mess up our
|
|
Packit |
fc043f |
* help strings. What we can do is: Build an option lookup table
|
|
Packit |
fc043f |
* when this function is first invoked. */
|
|
Packit |
fc043f |
if (!*keyword)
|
|
Packit |
fc043f |
return -1;
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
if (opts[i]->long_opt && !strcmp (opts[i]->long_opt, keyword))
|
|
Packit |
fc043f |
return i;
|
|
Packit |
fc043f |
#if 0
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
ALIAS_DEF a;
|
|
Packit |
fc043f |
/* see whether it is an alias */
|
|
Packit |
fc043f |
for (a = args->internal->aliases; a; a = a->next)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!strcmp( a->name, keyword))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* todo: must parse the alias here */
|
|
Packit |
fc043f |
args->internal->cur_alias = a;
|
|
Packit |
fc043f |
return -3; /* alias available */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
#endif
|
|
Packit |
fc043f |
/* Not found. See whether it is an abbreviation. Aliases may not
|
|
Packit |
fc043f |
* be abbreviated, though. */
|
|
Packit |
fc043f |
n = strlen (keyword);
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (opts[i]->long_opt && !strncmp (opts[i]->long_opt, keyword, n))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
int j;
|
|
Packit |
fc043f |
for (j=i+1; opts[j]->short_opt; j++)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (opts[j]->long_opt
|
|
Packit |
fc043f |
&& !strncmp (opts[j]->long_opt, keyword, n)
|
|
Packit |
fc043f |
&& !(opts[j]->short_opt == opts[i]->short_opt
|
|
Packit |
fc043f |
&& opts[j]->flags == opts[i]->flags ) )
|
|
Packit |
fc043f |
return -2; /* Abbreviation is ambiguous. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
return i;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
return -1; /* Not found. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* The option parser for command line options. */
|
|
Packit |
fc043f |
static int
|
|
Packit |
fc043f |
arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
int idx;
|
|
Packit |
fc043f |
gpgrt_opt_t **opts;
|
|
Packit |
fc043f |
int argc;
|
|
Packit |
fc043f |
char **argv;
|
|
Packit |
fc043f |
char *s, *s2;
|
|
Packit |
fc043f |
int i;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (initialize (arg, opts_orig, NULL))
|
|
Packit |
fc043f |
return (arg->r_opt = ARGPARSE_OUT_OF_CORE);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
opts = arg->internal->opts;
|
|
Packit |
fc043f |
argc = *arg->argc;
|
|
Packit |
fc043f |
argv = *arg->argv;
|
|
Packit |
fc043f |
idx = arg->internal->idx;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Skip the first argument. */
|
|
Packit |
fc043f |
argc--; argv++; idx++;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
next_one:
|
|
Packit |
fc043f |
if (!argc)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* No more args. */
|
|
Packit |
fc043f |
arg->r_opt = 0;
|
|
Packit |
fc043f |
goto leave; /* Ready. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
s = *argv;
|
|
Packit |
fc043f |
arg->internal->last = s;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (arg->internal->stopped && (arg->flags & ARGPARSE_FLAG_ALL))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */
|
|
Packit |
fc043f |
arg->r_type = 2;
|
|
Packit |
fc043f |
arg->r.ret_str = s;
|
|
Packit |
fc043f |
argc--; argv++; idx++; /* set to next one */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if( arg->internal->stopped )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = 0;
|
|
Packit |
fc043f |
goto leave; /* Ready. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( *s == '-' && s[1] == '-' )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Long option. */
|
|
Packit |
fc043f |
char *argpos;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
arg->internal->inarg = 0;
|
|
Packit |
fc043f |
if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Stop option processing. */
|
|
Packit |
fc043f |
arg->internal->stopped = 1;
|
|
Packit |
fc043f |
arg->flags |= ARGPARSE_FLAG_STOP_SEEN;
|
|
Packit |
fc043f |
argc--; argv++; idx++;
|
|
Packit |
fc043f |
goto next_one;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
argpos = strchr( s+2, '=' );
|
|
Packit |
fc043f |
if ( argpos )
|
|
Packit |
fc043f |
*argpos = 0;
|
|
Packit |
fc043f |
i = find_long_option ( arg, opts, s+2 );
|
|
Packit |
fc043f |
if ( argpos )
|
|
Packit |
fc043f |
*argpos = '=';
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (i > 0 && opts[i]->short_opt == ARGPARSE_SHORTOPT_HELP)
|
|
Packit |
fc043f |
show_help (opts, arg->flags);
|
|
Packit |
fc043f |
else if (i > 0 && opts[i]->short_opt == ARGPARSE_SHORTOPT_VERSION)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (!(arg->flags & ARGPARSE_FLAG_NOVERSION))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
show_version ();
|
|
Packit |
fc043f |
my_exit (arg, 0);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (i > 0 && opts[i]->short_opt == ARGPARSE_SHORTOPT_WARRANTY)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
writestrings (0, _gpgrt_strusage (16), "\n", NULL);
|
|
Packit |
fc043f |
my_exit (arg, 0);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (i > 0 && opts[i]->short_opt == ARGPARSE_SHORTOPT_DUMP_OPTIONS)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (opts[i]->long_opt && !(opts[i]->flags & ARGPARSE_OPT_IGNORE))
|
|
Packit |
fc043f |
writestrings (0, "--", opts[i]->long_opt, "\n", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
my_exit (arg, 0);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if ( i == -2 )
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION;
|
|
Packit |
fc043f |
else if ( i == -1 )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_INVALID_OPTION;
|
|
Packit |
fc043f |
arg->r.ret_str = s+2;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
arg->r_opt = opts[i]->short_opt;
|
|
Packit |
fc043f |
if ( i < 0 )
|
|
Packit |
fc043f |
;
|
|
Packit |
fc043f |
else if ( (opts[i]->flags & ARGPARSE_TYPE_MASK) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( argpos )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
s2 = argpos+1;
|
|
Packit |
fc043f |
if ( !*s2 )
|
|
Packit |
fc043f |
s2 = NULL;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
s2 = argv[1];
|
|
Packit |
fc043f |
if ( !s2 && (opts[i]->flags & ARGPARSE_OPT_OPTIONAL) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( !s2 )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_MISSING_ARG;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( !argpos && *s2 == '-'
|
|
Packit |
fc043f |
&& (opts[i]->flags & ARGPARSE_OPT_OPTIONAL) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* The argument is optional and the next seems to be an
|
|
Packit |
fc043f |
option. We do not check this possible option but
|
|
Packit |
fc043f |
assume no argument */
|
|
Packit |
fc043f |
arg->r_type = ARGPARSE_TYPE_NONE;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
set_opt_arg (arg, opts[i]->flags, s2);
|
|
Packit |
fc043f |
if ( !argpos )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
argc--; argv++; idx++; /* Skip one. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Does not take an argument. */
|
|
Packit |
fc043f |
if ( argpos )
|
|
Packit |
fc043f |
arg->r_type = ARGPARSE_UNEXPECTED_ARG;
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
arg->r_type = 0;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
argc--; argv++; idx++; /* Set to next one. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( (*s == '-' && s[1]) || arg->internal->inarg )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Short option. */
|
|
Packit |
fc043f |
int dash_kludge = 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
i = 0;
|
|
Packit |
fc043f |
if ( !arg->internal->inarg )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->internal->inarg++;
|
|
Packit |
fc043f |
if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
if ( opts[i]->long_opt && !strcmp (opts[i]->long_opt, s+1))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
dash_kludge = 1;
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
s += arg->internal->inarg;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (!dash_kludge )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
if ( opts[i]->short_opt == *s )
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if ( !opts[i]->short_opt && ( *s == 'h' || *s == '?' ) )
|
|
Packit |
fc043f |
show_help (opts, arg->flags);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
arg->r_opt = opts[i]->short_opt;
|
|
Packit |
fc043f |
if (!opts[i]->short_opt )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = (opts[i]->flags & ARGPARSE_OPT_COMMAND)?
|
|
Packit |
fc043f |
ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION;
|
|
Packit |
fc043f |
arg->internal->inarg++; /* Point to the next arg. */
|
|
Packit |
fc043f |
arg->r.ret_str = s;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( (opts[i]->flags & ARGPARSE_TYPE_MASK) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( s[1] && !dash_kludge )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
s2 = s+1;
|
|
Packit |
fc043f |
set_opt_arg (arg, opts[i]->flags, s2);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
s2 = argv[1];
|
|
Packit |
fc043f |
if ( !s2 && (opts[i]->flags & ARGPARSE_OPT_OPTIONAL) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_type = ARGPARSE_TYPE_NONE;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( !s2 )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_MISSING_ARG;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( *s2 == '-' && s2[1]
|
|
Packit |
fc043f |
&& (opts[i]->flags & ARGPARSE_OPT_OPTIONAL) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* The argument is optional and the next seems to
|
|
Packit |
fc043f |
be an option. We do not check this possible
|
|
Packit |
fc043f |
option but assume no argument. */
|
|
Packit |
fc043f |
arg->r_type = ARGPARSE_TYPE_NONE;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
set_opt_arg (arg, opts[i]->flags, s2);
|
|
Packit |
fc043f |
argc--; argv++; idx++; /* Skip one. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
s = "x"; /* This is so that !s[1] yields false. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Does not take an argument. */
|
|
Packit |
fc043f |
arg->r_type = ARGPARSE_TYPE_NONE;
|
|
Packit |
fc043f |
arg->internal->inarg++; /* Point to the next arg. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if ( !s[1] || dash_kludge )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* No more concatenated short options. */
|
|
Packit |
fc043f |
arg->internal->inarg = 0;
|
|
Packit |
fc043f |
argc--; argv++; idx++;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if ( arg->flags & ARGPARSE_FLAG_MIXED )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_IS_ARG;
|
|
Packit |
fc043f |
arg->r_type = 2;
|
|
Packit |
fc043f |
arg->r.ret_str = s;
|
|
Packit |
fc043f |
argc--; argv++; idx++; /* Set to next one. */
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->internal->stopped = 1; /* Stop option processing. */
|
|
Packit |
fc043f |
goto next_one;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
leave:
|
|
Packit |
fc043f |
*arg->argc = argc;
|
|
Packit |
fc043f |
*arg->argv = argv;
|
|
Packit |
fc043f |
arg->internal->idx = idx;
|
|
Packit |
fc043f |
return arg->r_opt;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Returns: -1 on error, 0 for an integer type and 1 for a non integer
|
|
Packit |
fc043f |
type argument. */
|
|
Packit |
fc043f |
static int
|
|
Packit |
fc043f |
set_opt_arg (gpgrt_argparse_t *arg, unsigned flags, char *s)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10;
|
|
Packit |
fc043f |
long l;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
case ARGPARSE_TYPE_LONG:
|
|
Packit |
fc043f |
case ARGPARSE_TYPE_INT:
|
|
Packit |
fc043f |
errno = 0;
|
|
Packit |
fc043f |
l = strtol (s, NULL, base);
|
|
Packit |
fc043f |
if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_INVALID_ARG;
|
|
Packit |
fc043f |
return -1;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if (arg->r_type == ARGPARSE_TYPE_LONG)
|
|
Packit |
fc043f |
arg->r.ret_long = l;
|
|
Packit |
fc043f |
else if ( (l < 0 && l < INT_MIN) || l > INT_MAX )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_INVALID_ARG;
|
|
Packit |
fc043f |
return -1;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
arg->r.ret_int = (int)l;
|
|
Packit |
fc043f |
return 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
case ARGPARSE_TYPE_ULONG:
|
|
Packit |
fc043f |
while (isascii (*s) && isspace(*s))
|
|
Packit |
fc043f |
s++;
|
|
Packit |
fc043f |
if (*s == '-')
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r.ret_ulong = 0;
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_INVALID_ARG;
|
|
Packit |
fc043f |
return -1;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
errno = 0;
|
|
Packit |
fc043f |
arg->r.ret_ulong = strtoul (s, NULL, base);
|
|
Packit |
fc043f |
if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
arg->r_opt = ARGPARSE_INVALID_ARG;
|
|
Packit |
fc043f |
return -1;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
return 0;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
case ARGPARSE_TYPE_STRING:
|
|
Packit |
fc043f |
default:
|
|
Packit |
fc043f |
arg->r.ret_str = s;
|
|
Packit |
fc043f |
return 1;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Return the length of the option O. This needs to consider the
|
|
Packit |
fc043f |
* description as weel as the option name. */
|
|
Packit |
fc043f |
static size_t
|
|
Packit |
fc043f |
long_opt_strlen (gpgrt_opt_t *o)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
size_t n = strlen (o->long_opt);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if ( o->description && *o->description == '|' )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
const char *s;
|
|
Packit |
fc043f |
int is_utf8 = is_native_utf8 ();
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
s=o->description+1;
|
|
Packit |
fc043f |
if ( *s != '=' )
|
|
Packit |
fc043f |
n++;
|
|
Packit |
fc043f |
/* For a (mostly) correct length calculation we exclude
|
|
Packit |
fc043f |
* continuation bytes (10xxxxxx) if we are on a native utf8
|
|
Packit |
fc043f |
* terminal. */
|
|
Packit |
fc043f |
for (; *s && *s != '|'; s++ )
|
|
Packit |
fc043f |
if ( is_utf8 && (*s&0xc0) != 0x80 )
|
|
Packit |
fc043f |
n++;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
return n;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/****************
|
|
Packit |
fc043f |
* Print formatted help. The description string has some special
|
|
Packit |
fc043f |
* meanings:
|
|
Packit |
fc043f |
* - A description string which is "@" suppresses help output for
|
|
Packit |
fc043f |
* this option
|
|
Packit |
fc043f |
* - a description,ine which starts with a '@' and is followed by
|
|
Packit |
fc043f |
* any other characters is printed as is; this may be used for examples
|
|
Packit |
fc043f |
* ans such.
|
|
Packit |
fc043f |
* - A description which starts with a '|' outputs the string between this
|
|
Packit |
fc043f |
* bar and the next one as arguments of the long option.
|
|
Packit |
fc043f |
*/
|
|
Packit |
fc043f |
static void
|
|
Packit |
fc043f |
show_help (gpgrt_opt_t **opts, unsigned int flags)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
const char *s;
|
|
Packit |
fc043f |
char tmp[2];
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
show_version ();
|
|
Packit |
fc043f |
writestrings (0, "\n", NULL);
|
|
Packit |
fc043f |
s = _gpgrt_strusage (42);
|
|
Packit |
fc043f |
if (s && *s == '1')
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
s = _gpgrt_strusage (40);
|
|
Packit |
fc043f |
writestrings (1, s, NULL);
|
|
Packit |
fc043f |
if (*s && s[strlen(s)] != '\n')
|
|
Packit |
fc043f |
writestrings (1, "\n", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
s = _gpgrt_strusage(41);
|
|
Packit |
fc043f |
writestrings (0, s, "\n", NULL);
|
|
Packit |
fc043f |
if ( opts[0]->description )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
/* Auto format the option description. */
|
|
Packit |
fc043f |
int i,j, indent;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Get max. length of long options. */
|
|
Packit |
fc043f |
for (i=indent=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( opts[i]->long_opt )
|
|
Packit |
fc043f |
if ( !opts[i]->description || *opts[i]->description != '@' )
|
|
Packit |
fc043f |
if ( (j=long_opt_strlen(opts[i])) > indent && j < 35 )
|
|
Packit |
fc043f |
indent = j;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Example: " -v, --verbose Viele Sachen ausgeben" */
|
|
Packit |
fc043f |
indent += 10;
|
|
Packit |
fc043f |
if ( *opts[0]->description != '@' )
|
|
Packit |
fc043f |
writestrings (0, "Options:", "\n", NULL);
|
|
Packit |
fc043f |
for (i=0; opts[i]->short_opt; i++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
s = map_fixed_string (_( opts[i]->description ));
|
|
Packit |
fc043f |
if ( s && *s== '@' && !s[1] ) /* Hide this line. */
|
|
Packit |
fc043f |
continue;
|
|
Packit |
fc043f |
if ( s && *s == '@' ) /* Unindented comment only line. */
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
for (s++; *s; s++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( *s == '\n' )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if( s[1] )
|
|
Packit |
fc043f |
writestrings (0, "\n", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
tmp[0] = *s;
|
|
Packit |
fc043f |
tmp[1] = 0;
|
|
Packit |
fc043f |
writestrings (0, tmp, NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
writestrings (0, "\n", NULL);
|
|
Packit |
fc043f |
continue;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
j = 3;
|
|
Packit |
fc043f |
if ( opts[i]->short_opt < 256 )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
tmp[0] = opts[i]->short_opt;
|
|
Packit |
fc043f |
tmp[1] = 0;
|
|
Packit |
fc043f |
writestrings (0, " -", tmp, NULL );
|
|
Packit |
fc043f |
if ( !opts[i]->long_opt )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if (s && *s == '|' )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
writestrings (0, " ", NULL); j++;
|
|
Packit |
fc043f |
for (s++ ; *s && *s != '|'; s++, j++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
tmp[0] = *s;
|
|
Packit |
fc043f |
tmp[1] = 0;
|
|
Packit |
fc043f |
writestrings (0, tmp, NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if ( *s )
|
|
Packit |
fc043f |
s++;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
writestrings (0, " ", NULL);
|
|
Packit |
fc043f |
if ( opts[i]->long_opt )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
tmp[0] = opts[i]->short_opt < 256?',':' ';
|
|
Packit |
fc043f |
tmp[1] = 0;
|
|
Packit |
fc043f |
j += writestrings (0, tmp, " --", opts[i]->long_opt, NULL);
|
|
Packit |
fc043f |
if (s && *s == '|' )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( *++s != '=' )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
writestrings (0, " ", NULL);
|
|
Packit |
fc043f |
j++;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
for ( ; *s && *s != '|'; s++, j++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
tmp[0] = *s;
|
|
Packit |
fc043f |
tmp[1] = 0;
|
|
Packit |
fc043f |
writestrings (0, tmp, NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if ( *s )
|
|
Packit |
fc043f |
s++;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
writestrings (0, " ", NULL);
|
|
Packit |
fc043f |
j += 3;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
for (;j < indent; j++ )
|
|
Packit |
fc043f |
writestrings (0, " ", NULL);
|
|
Packit |
fc043f |
if ( s )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( *s && j > indent )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
writestrings (0, "\n", NULL);
|
|
Packit |
fc043f |
for (j=0;j < indent; j++ )
|
|
Packit |
fc043f |
writestrings (0, " ", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
for (; *s; s++ )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( *s == '\n' )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
if ( s[1] )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
writestrings (0, "\n", NULL);
|
|
Packit |
fc043f |
for (j=0; j < indent; j++ )
|
|
Packit |
fc043f |
writestrings (0, " ", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
tmp[0] = *s;
|
|
Packit |
fc043f |
tmp[1] = 0;
|
|
Packit |
fc043f |
writestrings (0, tmp, NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
writestrings (0, "\n", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if ( (flags & ARGPARSE_FLAG_ONEDASH) )
|
|
Packit |
fc043f |
writestrings (0, "\n(A single dash may be used "
|
|
Packit |
fc043f |
"instead of the double ones)\n", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
if ( (s=_gpgrt_strusage(19)) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
writestrings (0, "\n", NULL);
|
|
Packit |
fc043f |
writestrings (0, s, NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
flushstrings (0);
|
|
Packit |
fc043f |
exit (0);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
static void
|
|
Packit |
fc043f |
show_version ()
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
const char *s;
|
|
Packit |
fc043f |
int i;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Version line. */
|
|
Packit |
fc043f |
writestrings (0, _gpgrt_strusage (11), NULL);
|
|
Packit |
fc043f |
if ((s=_gpgrt_strusage (12)))
|
|
Packit |
fc043f |
writestrings (0, " (", s, ")", NULL);
|
|
Packit |
fc043f |
writestrings (0, " ", _gpgrt_strusage (13), "\n", NULL);
|
|
Packit |
fc043f |
/* Additional version lines. */
|
|
Packit |
fc043f |
for (i=20; i < 30; i++)
|
|
Packit |
fc043f |
if ((s=_gpgrt_strusage (i)))
|
|
Packit |
fc043f |
writestrings (0, s, "\n", NULL);
|
|
Packit |
fc043f |
/* Copyright string. */
|
|
Packit |
fc043f |
if ((s=_gpgrt_strusage (14)))
|
|
Packit |
fc043f |
writestrings (0, s, "\n", NULL);
|
|
Packit |
fc043f |
/* Licence string. */
|
|
Packit |
fc043f |
if( (s=_gpgrt_strusage (10)) )
|
|
Packit |
fc043f |
writestrings (0, s, "\n", NULL);
|
|
Packit |
fc043f |
/* Copying conditions. */
|
|
Packit |
fc043f |
if ( (s=_gpgrt_strusage(15)) )
|
|
Packit |
fc043f |
writestrings (0, s, NULL);
|
|
Packit |
fc043f |
/* Thanks. */
|
|
Packit |
fc043f |
if ((s=_gpgrt_strusage(18)))
|
|
Packit |
fc043f |
writestrings (0, s, NULL);
|
|
Packit |
fc043f |
/* Additional program info. */
|
|
Packit |
fc043f |
for (i=30; i < 40; i++ )
|
|
Packit |
fc043f |
if ( (s=_gpgrt_strusage (i)) )
|
|
Packit |
fc043f |
writestrings (0, s, NULL);
|
|
Packit |
fc043f |
flushstrings (0);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
void
|
|
Packit |
fc043f |
_gpgrt_usage (int level)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
const char *p;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if (!level)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
writestrings (1, _gpgrt_strusage(11), " ", _gpgrt_strusage(13), "; ",
|
|
Packit |
fc043f |
_gpgrt_strusage (14), "\n", NULL);
|
|
Packit |
fc043f |
flushstrings (1);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (level == 1)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
p = _gpgrt_strusage (40);
|
|
Packit |
fc043f |
writestrings (1, p, NULL);
|
|
Packit |
fc043f |
if (*p && p[strlen(p)] != '\n')
|
|
Packit |
fc043f |
writestrings (1, "\n", NULL);
|
|
Packit |
fc043f |
exit (2);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
else if (level == 2)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
p = _gpgrt_strusage (42);
|
|
Packit |
fc043f |
if (p && *p == '1')
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
p = _gpgrt_strusage (40);
|
|
Packit |
fc043f |
writestrings (1, p, NULL);
|
|
Packit |
fc043f |
if (*p && p[strlen(p)] != '\n')
|
|
Packit |
fc043f |
writestrings (1, "\n", NULL);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
writestrings (0, _gpgrt_strusage(41), "\n", NULL);
|
|
Packit |
fc043f |
exit (0);
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Level
|
|
Packit |
fc043f |
* 0: Print copyright string to stderr
|
|
Packit |
fc043f |
* 1: Print a short usage hint to stderr and terminate
|
|
Packit |
fc043f |
* 2: Print a long usage hint to stdout and terminate
|
|
Packit |
fc043f |
* 8: Return NULL for UTF-8 or string with the native charset.
|
|
Packit |
fc043f |
* 9: Return the SPDX License tag.
|
|
Packit |
fc043f |
* 10: Return license info string
|
|
Packit |
fc043f |
* 11: Return the name of the program
|
|
Packit |
fc043f |
* 12: Return optional name of package which includes this program.
|
|
Packit |
fc043f |
* 13: version string
|
|
Packit |
fc043f |
* 14: copyright string
|
|
Packit |
fc043f |
* 15: Short copying conditions (with LFs)
|
|
Packit |
fc043f |
* 16: Long copying conditions (with LFs)
|
|
Packit |
fc043f |
* 17: Optional printable OS name
|
|
Packit |
fc043f |
* 18: Optional thanks list (with LFs)
|
|
Packit |
fc043f |
* 19: Bug report info
|
|
Packit |
fc043f |
*20..29: Additional lib version strings.
|
|
Packit |
fc043f |
*30..39: Additional program info (with LFs)
|
|
Packit |
fc043f |
* 40: short usage note (with LF)
|
|
Packit |
fc043f |
* 41: long usage note (with LF)
|
|
Packit |
fc043f |
* 42: Flag string:
|
|
Packit |
fc043f |
* First char is '1':
|
|
Packit |
fc043f |
* The short usage notes needs to be printed
|
|
Packit |
fc043f |
* before the long usage note.
|
|
Packit |
fc043f |
*/
|
|
Packit |
fc043f |
const char *
|
|
Packit |
fc043f |
_gpgrt_strusage (int level)
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
const char *p = strusage_handler? strusage_handler(level) : NULL;
|
|
Packit |
fc043f |
const char *tmp;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
if ( p )
|
|
Packit |
fc043f |
return map_fixed_string (p);
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
switch ( level )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
case 8: break; /* Default to utf-8. */
|
|
Packit |
fc043f |
case 9:
|
|
Packit |
fc043f |
p = "GPL-3.0-or-later"; /* Suggested license. */
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
case 10:
|
|
Packit |
fc043f |
tmp = _gpgrt_strusage (9);
|
|
Packit |
fc043f |
if (tmp && !strcmp (tmp, "GPL-2.0-or-later"))
|
|
Packit |
fc043f |
p = ("License GPL-2.0-or-later <https://gnu.org/licenses/>");
|
|
Packit |
fc043f |
else if (tmp && !strcmp (tmp, "LGPL-2.1-or-later"))
|
|
Packit |
fc043f |
p = ("License LGPL-2.1-or-later <https://gnu.org/licenses/>");
|
|
Packit |
fc043f |
else /* Default to GPLv3+. */
|
|
Packit |
fc043f |
p = ("License GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>");
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
case 11: p = "foo"; break;
|
|
Packit |
fc043f |
case 13: p = "0.0"; break;
|
|
Packit |
fc043f |
case 14: p = "Copyright (C) YEAR NAME"; break;
|
|
Packit |
fc043f |
case 15: p =
|
|
Packit |
fc043f |
"This is free software: you are free to change and redistribute it.\n"
|
|
Packit |
fc043f |
"There is NO WARRANTY, to the extent permitted by law.\n";
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
case 16:
|
|
Packit |
fc043f |
tmp = _gpgrt_strusage (9);
|
|
Packit |
fc043f |
if (tmp && !strcmp (tmp, "GPL-2.0-or-later"))
|
|
Packit |
fc043f |
p =
|
|
Packit |
fc043f |
"This is free software; you can redistribute it and/or modify\n"
|
|
Packit |
fc043f |
"it under the terms of the GNU General Public License as published by\n"
|
|
Packit |
fc043f |
"the Free Software Foundation; either version 2 of the License, or\n"
|
|
Packit |
fc043f |
"(at your option) any later version.\n\n"
|
|
Packit |
fc043f |
"It is distributed in the hope that it will be useful,\n"
|
|
Packit |
fc043f |
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
Packit |
fc043f |
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
Packit |
fc043f |
"GNU General Public License for more details.\n\n"
|
|
Packit |
fc043f |
"You should have received a copy of the GNU General Public License\n"
|
|
Packit |
fc043f |
"along with this software. If not, see <https://gnu.org/licenses/>.\n";
|
|
Packit |
fc043f |
else if (tmp && !strcmp (tmp, "LGPL-2.1-or-later"))
|
|
Packit |
fc043f |
p =
|
|
Packit |
fc043f |
"This is free software; you can redistribute it and/or modify\n"
|
|
Packit |
fc043f |
"it under the terms of the GNU Lesser General Public License as\n"
|
|
Packit |
fc043f |
"published by the Free Software Foundation; either version 2.1 of\n"
|
|
Packit |
fc043f |
"the License, or (at your option) any later version.\n\n"
|
|
Packit |
fc043f |
"It is distributed in the hope that it will be useful,\n"
|
|
Packit |
fc043f |
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
Packit |
fc043f |
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
Packit |
fc043f |
"GNU Lesser General Public License for more details.\n\n"
|
|
Packit |
fc043f |
"You should have received a copy of the GNU General Public License\n"
|
|
Packit |
fc043f |
"along with this software. If not, see <https://gnu.org/licenses/>.\n";
|
|
Packit |
fc043f |
else /* Default */
|
|
Packit |
fc043f |
p =
|
|
Packit |
fc043f |
"This is free software; you can redistribute it and/or modify\n"
|
|
Packit |
fc043f |
"it under the terms of the GNU General Public License as published by\n"
|
|
Packit |
fc043f |
"the Free Software Foundation; either version 3 of the License, or\n"
|
|
Packit |
fc043f |
"(at your option) any later version.\n\n"
|
|
Packit |
fc043f |
"It is distributed in the hope that it will be useful,\n"
|
|
Packit |
fc043f |
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
Packit |
fc043f |
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
Packit |
fc043f |
"GNU General Public License for more details.\n\n"
|
|
Packit |
fc043f |
"You should have received a copy of the GNU General Public License\n"
|
|
Packit |
fc043f |
"along with this software. If not, see <https://gnu.org/licenses/>.\n";
|
|
Packit |
fc043f |
break;
|
|
Packit |
fc043f |
case 40: /* short and long usage */
|
|
Packit |
fc043f |
case 41: p = ""; break;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
return p;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Set the usage handler. This function is basically a constructor. */
|
|
Packit |
fc043f |
void
|
|
Packit |
fc043f |
_gpgrt_set_strusage (const char *(*f)(int) )
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
strusage_handler = f;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Set a function to write strings which is the used instead of
|
|
Packit |
fc043f |
* estream. The first arg of that function is MODE and the second the
|
|
Packit |
fc043f |
* STRING to write. A mode of 1 is used for writing to stdout and a
|
|
Packit |
fc043f |
* mode of 2 to write to stderr. Other modes are reserved and should
|
|
Packit |
fc043f |
* not output anything. A NULL for STRING requests a flush. */
|
|
Packit |
fc043f |
void
|
|
Packit |
fc043f |
_gpgrt_set_usage_outfnc (int (*f)(int, const char *))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
custom_outfnc = f;
|
|
Packit |
fc043f |
}
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
|
|
Packit |
fc043f |
/* Register function F as a string mapper which takes a string as
|
|
Packit |
fc043f |
* argument, replaces known "@FOO@" style macros and returns a new
|
|
Packit |
fc043f |
* fixed string. Warning: The input STRING must have been allocated
|
|
Packit |
fc043f |
* statically. */
|
|
Packit |
fc043f |
void
|
|
Packit |
fc043f |
_gpgrt_set_fixed_string_mapper (const char *(*f)(const char*))
|
|
Packit |
fc043f |
{
|
|
Packit |
fc043f |
fixed_string_mapper = f;
|
|
Packit |
fc043f |
}
|