diff options
Diffstat (limited to 'contrib/argp-standalone/argp-help.c')
| -rw-r--r-- | contrib/argp-standalone/argp-help.c | 1849 | 
1 files changed, 0 insertions, 1849 deletions
diff --git a/contrib/argp-standalone/argp-help.c b/contrib/argp-standalone/argp-help.c deleted file mode 100644 index 5ad758f0726..00000000000 --- a/contrib/argp-standalone/argp-help.c +++ /dev/null @@ -1,1849 +0,0 @@ -/* Hierarchial argument parsing help output -   Copyright (C) 1995,96,97,98,99,2000, 2003 Free Software Foundation, Inc. -   This file is part of the GNU C Library. -   Written by Miles Bader <miles@gnu.ai.mit.edu>. - -   The GNU C Library is free software; you can redistribute it and/or -   modify it under the terms of the GNU Library General Public License as -   published by the Free Software Foundation; either version 2 of the -   License, or (at your option) any later version. - -   The GNU C Library is distributed in the hope that it will be useful, -   but WITHOUT ANY WARRANTY; without even the implied warranty of -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -   Library General Public License for more details. - -   You should have received a copy of the GNU Library General Public -   License along with the GNU C Library; see the file COPYING.LIB.  If not, -   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -   Boston, MA 02111-1307, USA.  */ - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE	1 -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <stdarg.h> -#include <ctype.h> -#if HAVE_MALLOC_H -/* Needed, for alloca on windows */ -# include <malloc.h> -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages.  */ -# if defined HAVE_LIBINTL_H || defined _LIBC -#  include <libintl.h> -#  ifdef _LIBC -#   undef dgettext -#   define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) -#  endif -# else -#  define dgettext(domain, msgid) (msgid) -# endif -#endif - -#include "argp.h" -#include "argp-fmtstream.h" -#include "argp-namefrob.h" - - -#ifndef _LIBC -# ifndef __strchrnul -#  define __strchrnul strchrnul -# endif -# ifndef __mempcpy -#  define __mempcpy mempcpy -# endif -/* We need to use a different name, as __strndup is likely a macro. */ -# define STRNDUP strndup -# if HAVE_STRERROR -#  define STRERROR strerror -# else -#  define STRERROR(x) (sys_errlist[x]) -# endif -#else /* _LIBC */ -# define FLOCKFILE __flockfile -# define FUNLOCKFILE __funlockfile -# define STRNDUP __strndup -# define STRERROR strerror -#endif - -#if !_LIBC -# if !HAVE_STRNDUP -char *strndup (const char *s, size_t size); -# endif /* !HAVE_STRNDUP */ - -# if !HAVE_MEMPCPY -void *mempcpy (void *to, const void *from, size_t size); -# endif /* !HAVE_MEMPCPY */ - -# if !HAVE_STRCHRNUL -char *strchrnul(const char *s, int c); -# endif /* !HAVE_STRCHRNUL */ - -# if !HAVE_STRCASECMP -int strcasecmp(const char *s1, const char *s2); -#endif - -#endif /* !_LIBC */ - - -/* User-selectable (using an environment variable) formatting parameters. - -   These may be specified in an environment variable called `ARGP_HELP_FMT', -   with a contents like:  VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 -   Where VALn must be a positive integer.  The list of variables is in the -   UPARAM_NAMES vector, below.  */ - -/* Default parameters.  */ -#define DUP_ARGS      0		/* True if option argument can be duplicated. */ -#define DUP_ARGS_NOTE 1		/* True to print a note about duplicate args. */ -#define SHORT_OPT_COL 2		/* column in which short options start */ -#define LONG_OPT_COL  6		/* column in which long options start */ -#define DOC_OPT_COL   2		/* column in which doc options start */ -#define OPT_DOC_COL  29		/* column in which option text starts */ -#define HEADER_COL    1		/* column in which group headers are printed */ -#define USAGE_INDENT 12		/* indentation of wrapped usage lines */ -#define RMARGIN      79		/* right margin used for wrapping */ - -/* User-selectable (using an environment variable) formatting parameters. -   They must all be of type `int' for the parsing code to work.  */ -struct uparams -{ -  /* If true, arguments for an option are shown with both short and long -     options, even when a given option has both, e.g. `-x ARG, --longx=ARG'. -     If false, then if an option has both, the argument is only shown with -     the long one, e.g., `-x, --longx=ARG', and a message indicating that -     this really means both is printed below the options.  */ -  int dup_args; - -  /* This is true if when DUP_ARGS is false, and some duplicate arguments have -     been suppressed, an explanatory message should be printed.  */ -  int dup_args_note; - -  /* Various output columns.  */ -  int short_opt_col; -  int long_opt_col; -  int doc_opt_col; -  int opt_doc_col; -  int header_col; -  int usage_indent; -  int rmargin; - -  int valid;			/* True when the values in here are valid.  */ -}; - -/* This is a global variable, as user options are only ever read once.  */ -static struct uparams uparams = { -  DUP_ARGS, DUP_ARGS_NOTE, -  SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL, -  USAGE_INDENT, RMARGIN, -  0 -}; - -/* A particular uparam, and what the user name is.  */ -struct uparam_name -{ -  const char *name;		/* User name.  */ -  int is_bool;			/* Whether it's `boolean'.  */ -  size_t uparams_offs;		/* Location of the (int) field in UPARAMS.  */ -}; - -/* The name-field mappings we know about.  */ -static const struct uparam_name uparam_names[] = -{ -  { "dup-args",       1, offsetof (struct uparams, dup_args) }, -  { "dup-args-note",  1, offsetof (struct uparams, dup_args_note) }, -  { "short-opt-col",  0, offsetof (struct uparams, short_opt_col) }, -  { "long-opt-col",   0, offsetof (struct uparams, long_opt_col) }, -  { "doc-opt-col",    0, offsetof (struct uparams, doc_opt_col) }, -  { "opt-doc-col",    0, offsetof (struct uparams, opt_doc_col) }, -  { "header-col",     0, offsetof (struct uparams, header_col) }, -  { "usage-indent",   0, offsetof (struct uparams, usage_indent) }, -  { "rmargin",        0, offsetof (struct uparams, rmargin) }, -  { 0, 0, 0 } -}; - -/* Read user options from the environment, and fill in UPARAMS appropriately.*/ -static void -fill_in_uparams (const struct argp_state *state) -{ - -  const char *var = getenv ("ARGP_HELP_FMT"); - -#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0); - -  if (var) -    /* Parse var. */ -    while (*var) -      { -	SKIPWS (var); - -	if (isalpha (*var)) -	  { -	    size_t var_len; -	    const struct uparam_name *un; -	    int unspec = 0, val = 0; -	    const char *arg = var; - -	    while (isalnum (*arg) || *arg == '-' || *arg == '_') -	      arg++; -	    var_len = arg - var; - -	    SKIPWS (arg); - -	    if (*arg == '\0' || *arg == ',') -	      unspec = 1; -	    else if (*arg == '=') -	      { -		arg++; -		SKIPWS (arg); -	      } - -	    if (unspec) -	      { -		if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') -		  { -		    val = 0; -		    var += 3; -		    var_len -= 3; -		  } -		else -		  val = 1; -	      } -	    else if (isdigit (*arg)) -	      { -		val = atoi (arg); -		while (isdigit (*arg)) -		  arg++; -		SKIPWS (arg); -	      } - -	    for (un = uparam_names; un->name; un++) -	      if (strlen (un->name) == var_len -		  && strncmp (var, un->name, var_len) == 0) -		{ -		  if (unspec && !un->is_bool) -		    __argp_failure (state, 0, 0, -				    dgettext (state->root_argp->argp_domain, "\ -%.*s: ARGP_HELP_FMT parameter requires a value"), -				    (int) var_len, var); -		  else -		    *(int *)((char *)&uparams + un->uparams_offs) = val; -		  break; -		} -	    if (! un->name) -	      __argp_failure (state, 0, 0, -			      dgettext (state->root_argp->argp_domain, "\ -%.*s: Unknown ARGP_HELP_FMT parameter"), -			      (int) var_len, var); - -	    var = arg; -	    if (*var == ',') -	      var++; -	  } -	else if (*var) -	  { -	    __argp_failure (state, 0, 0, -			    dgettext (state->root_argp->argp_domain, -				      "Garbage in ARGP_HELP_FMT: %s"), var); -	    break; -	  } -      } -} - -/* Returns true if OPT hasn't been marked invisible.  Visibility only affects -   whether OPT is displayed or used in sorting, not option shadowing.  */ -#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN)) - -/* Returns true if OPT is an alias for an earlier option.  */ -#define oalias(opt) ((opt)->flags & OPTION_ALIAS) - -/* Returns true if OPT is an documentation-only entry.  */ -#define odoc(opt) ((opt)->flags & OPTION_DOC) - -/* Returns true if OPT is the end-of-list marker for a list of options.  */ -#define oend(opt) __option_is_end (opt) - -/* Returns true if OPT has a short option.  */ -#define oshort(opt) __option_is_short (opt) - -/* -   The help format for a particular option is like: - -     -xARG, -yARG, --long1=ARG, --long2=ARG        Documentation... - -   Where ARG will be omitted if there's no argument, for this option, or -   will be surrounded by "[" and "]" appropriately if the argument is -   optional.  The documentation string is word-wrapped appropriately, and if -   the list of options is long enough, it will be started on a separate line. -   If there are no short options for a given option, the first long option is -   indented slightly in a way that's supposed to make most long options appear -   to be in a separate column. - -   For example, the following output (from ps): - -     -p PID, --pid=PID          List the process PID -	 --pgrp=PGRP            List processes in the process group PGRP -     -P, -x, --no-parent        Include processes without parents -     -Q, --all-fields           Don't elide unusable fields (normally if there's -				some reason ps can't print a field for any -				process, it's removed from the output entirely) -     -r, --reverse, --gratuitously-long-reverse-option -				Reverse the order of any sort -	 --session[=SID]        Add the processes from the session SID (which -				defaults to the sid of the current process) - -    Here are some more options: -     -f ZOT, --foonly=ZOT       Glork a foonly -     -z, --zaza                 Snit a zar - -     -?, --help                 Give this help list -	 --usage                Give a short usage message -     -V, --version              Print program version - -   The struct argp_option array for the above could look like: - -   { -     {"pid",       'p',      "PID",  0, "List the process PID"}, -     {"pgrp",      OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"}, -     {"no-parent", 'P',	      0,     0, "Include processes without parents"}, -     {0,           'x',       0,     OPTION_ALIAS}, -     {"all-fields",'Q',       0,     0, "Don't elide unusable fields (normally" -                                        " if there's some reason ps can't" -					" print a field for any process, it's" -                                        " removed from the output entirely)" }, -     {"reverse",   'r',       0,     0, "Reverse the order of any sort"}, -     {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, -     {"session",   OPT_SESS,  "SID", OPTION_ARG_OPTIONAL, -                                        "Add the processes from the session" -					" SID (which defaults to the sid of" -					" the current process)" }, - -     {0,0,0,0, "Here are some more options:"}, -     {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, -     {"zaza", 'z', 0, 0, "Snit a zar"}, - -     {0} -   } - -   Note that the last three options are automatically supplied by argp_parse, -   unless you tell it not to with ARGP_NO_HELP. - -*/ - -/* Returns true if CH occurs between BEG and END.  */ -static int -find_char (char ch, char *beg, char *end) -{ -  while (beg < end) -    if (*beg == ch) -      return 1; -    else -      beg++; -  return 0; -} - -struct hol_cluster;		/* fwd decl */ - -struct hol_entry -{ -  /* First option.  */ -  const struct argp_option *opt; -  /* Number of options (including aliases).  */ -  unsigned num; - -  /* A pointers into the HOL's short_options field, to the first short option -     letter for this entry.  The order of the characters following this point -     corresponds to the order of options pointed to by OPT, and there are at -     most NUM.  A short option recorded in a option following OPT is only -     valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's -     probably been shadowed by some other entry).  */ -  char *short_options; - -  /* Entries are sorted by their group first, in the order: -       1, 2, ..., n, 0, -m, ..., -2, -1 -     and then alphabetically within each group.  The default is 0.  */ -  int group; - -  /* The cluster of options this entry belongs to, or 0 if none.  */ -  struct hol_cluster *cluster; - -  /* The argp from which this option came.  */ -  const struct argp *argp; -}; - -/* A cluster of entries to reflect the argp tree structure.  */ -struct hol_cluster -{ -  /* A descriptive header printed before options in this cluster.  */ -  const char *header; - -  /* Used to order clusters within the same group with the same parent, -     according to the order in which they occurred in the parent argp's child -     list.  */ -  int index; - -  /* How to sort this cluster with respect to options and other clusters at the -     same depth (clusters always follow options in the same group).  */ -  int group; - -  /* The cluster to which this cluster belongs, or 0 if it's at the base -     level.  */ -  struct hol_cluster *parent; - -  /* The argp from which this cluster is (eventually) derived.  */ -  const struct argp *argp; - -  /* The distance this cluster is from the root.  */ -  int depth; - -  /* Clusters in a given hol are kept in a linked list, to make freeing them -     possible.  */ -  struct hol_cluster *next; -}; - -/* A list of options for help.  */ -struct hol -{ -  /* An array of hol_entry's.  */ -  struct hol_entry *entries; -  /* The number of entries in this hol.  If this field is zero, the others -     are undefined.  */ -  unsigned num_entries; - -  /* A string containing all short options in this HOL.  Each entry contains -     pointers into this string, so the order can't be messed with blindly.  */ -  char *short_options; - -  /* Clusters of entries in this hol.  */ -  struct hol_cluster *clusters; -}; - -/* Create a struct hol from the options in ARGP.  CLUSTER is the -   hol_cluster in which these entries occur, or 0, if at the root.  */ -static struct hol * -make_hol (const struct argp *argp, struct hol_cluster *cluster) -{ -  char *so; -  const struct argp_option *o; -  const struct argp_option *opts = argp->options; -  struct hol_entry *entry; -  unsigned num_short_options = 0; -  struct hol *hol = malloc (sizeof (struct hol)); - -  assert (hol); - -  hol->num_entries = 0; -  hol->clusters = 0; - -  if (opts) -    { -      int cur_group = 0; - -      /* The first option must not be an alias.  */ -      assert (! oalias (opts)); - -      /* Calculate the space needed.  */ -      for (o = opts; ! oend (o); o++) -	{ -	  if (! oalias (o)) -	    hol->num_entries++; -	  if (oshort (o)) -	    num_short_options++;	/* This is an upper bound.  */ -	} - -      hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); -      hol->short_options = malloc (num_short_options + 1); - -      assert (hol->entries && hol->short_options); - -      /* Fill in the entries.  */ -      so = hol->short_options; -      for (o = opts, entry = hol->entries; ! oend (o); entry++) -	{ -	  entry->opt = o; -	  entry->num = 0; -	  entry->short_options = so; -	  entry->group = cur_group = -	    o->group -	    ? o->group -	    : ((!o->name && !o->key) -	       ? cur_group + 1 -	       : cur_group); -	  entry->cluster = cluster; -	  entry->argp = argp; - -	  do -	    { -	      entry->num++; -	      if (oshort (o) && ! find_char (o->key, hol->short_options, so)) -		/* O has a valid short option which hasn't already been used.*/ -		*so++ = o->key; -	      o++; -	    } -	  while (! oend (o) && oalias (o)); -	} -      *so = '\0';		/* null terminated so we can find the length */ -    } - -  return hol; -} - -/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the -   associated argp child list entry), INDEX, and PARENT, and return a pointer -   to it.  ARGP is the argp that this cluster results from.  */ -static struct hol_cluster * -hol_add_cluster (struct hol *hol, int group, const char *header, int index, -		 struct hol_cluster *parent, const struct argp *argp) -{ -  struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); -  if (cl) -    { -      cl->group = group; -      cl->header = header; - -      cl->index = index; -      cl->parent = parent; -      cl->argp = argp; -      cl->depth = parent ? parent->depth + 1 : 0; - -      cl->next = hol->clusters; -      hol->clusters = cl; -    } -  return cl; -} - -/* Free HOL and any resources it uses.  */ -static void -hol_free (struct hol *hol) -{ -  struct hol_cluster *cl = hol->clusters; - -  while (cl) -    { -      struct hol_cluster *next = cl->next; -      free (cl); -      cl = next; -    } - -  if (hol->num_entries > 0) -    { -      free (hol->entries); -      free (hol->short_options); -    } - -  free (hol); -} - -static inline int -hol_entry_short_iterate (const struct hol_entry *entry, -			 int (*func)(const struct argp_option *opt, -				     const struct argp_option *real, -				     const char *domain, void *cookie), -			 const char *domain, void *cookie) -{ -  unsigned nopts; -  int val = 0; -  const struct argp_option *opt, *real = entry->opt; -  char *so = entry->short_options; - -  for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) -    if (oshort (opt) && *so == opt->key) -      { -	if (!oalias (opt)) -	  real = opt; -	if (ovisible (opt)) -	  val = (*func)(opt, real, domain, cookie); -	so++; -      } - -  return val; -} - -static inline int -hol_entry_long_iterate (const struct hol_entry *entry, -			int (*func)(const struct argp_option *opt, -				    const struct argp_option *real, -				    const char *domain, void *cookie), -			const char *domain, void *cookie) -{ -  unsigned nopts; -  int val = 0; -  const struct argp_option *opt, *real = entry->opt; - -  for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) -    if (opt->name) -      { -	if (!oalias (opt)) -	  real = opt; -	if (ovisible (opt)) -	  val = (*func)(opt, real, domain, cookie); -      } - -  return val; -} - -/* Iterator that returns true for the first short option.  */ -static inline int -until_short (const struct argp_option *opt, const struct argp_option *real UNUSED, -	     const char *domain UNUSED, void *cookie UNUSED) -{ -  return oshort (opt) ? opt->key : 0; -} - -/* Returns the first valid short option in ENTRY, or 0 if there is none.  */ -static char -hol_entry_first_short (const struct hol_entry *entry) -{ -  return hol_entry_short_iterate (entry, until_short, -				  entry->argp->argp_domain, 0); -} - -/* Returns the first valid long option in ENTRY, or 0 if there is none.  */ -static const char * -hol_entry_first_long (const struct hol_entry *entry) -{ -  const struct argp_option *opt; -  unsigned num; -  for (opt = entry->opt, num = entry->num; num > 0; opt++, num--) -    if (opt->name && ovisible (opt)) -      return opt->name; -  return 0; -} - -/* Returns the entry in HOL with the long option name NAME, or 0 if there is -   none.  */ -static struct hol_entry * -hol_find_entry (struct hol *hol, const char *name) -{ -  struct hol_entry *entry = hol->entries; -  unsigned num_entries = hol->num_entries; - -  while (num_entries-- > 0) -    { -      const struct argp_option *opt = entry->opt; -      unsigned num_opts = entry->num; - -      while (num_opts-- > 0) -	if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) -	  return entry; -	else -	  opt++; - -      entry++; -    } - -  return 0; -} - -/* If an entry with the long option NAME occurs in HOL, set it's special -   sort position to GROUP.  */ -static void -hol_set_group (struct hol *hol, const char *name, int group) -{ -  struct hol_entry *entry = hol_find_entry (hol, name); -  if (entry) -    entry->group = group; -} - -/* Order by group:  0, 1, 2, ..., n, -m, ..., -2, -1. -   EQ is what to return if GROUP1 and GROUP2 are the same.  */ -static int -group_cmp (int group1, int group2, int eq) -{ -  if (group1 == group2) -    return eq; -  else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0)) -    return group1 - group2; -  else -    return group2 - group1; -} - -/* Compare clusters CL1 & CL2 by the order that they should appear in -   output.  */ -static int -hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2) -{ -  /* If one cluster is deeper than the other, use its ancestor at the same -     level, so that finding the common ancestor is straightforward.  */ -  while (cl1->depth < cl2->depth) -    cl1 = cl1->parent; -  while (cl2->depth < cl1->depth) -    cl2 = cl2->parent; - -  /* Now reduce both clusters to their ancestors at the point where both have -     a common parent; these can be directly compared.  */ -  while (cl1->parent != cl2->parent) -    cl1 = cl1->parent, cl2 = cl2->parent; - -  return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index); -} - -/* Return the ancestor of CL that's just below the root (i.e., has a parent -   of 0).  */ -static struct hol_cluster * -hol_cluster_base (struct hol_cluster *cl) -{ -  while (cl->parent) -    cl = cl->parent; -  return cl; -} - -/* Return true if CL1 is a child of CL2.  */ -static int -hol_cluster_is_child (const struct hol_cluster *cl1, -		      const struct hol_cluster *cl2) -{ -  while (cl1 && cl1 != cl2) -    cl1 = cl1->parent; -  return cl1 == cl2; -} - -/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail -   that should be used for comparisons, and returns true iff it should be -   treated as a non-option.  */ - -/* FIXME: Can we use unsigned char * for the argument? */ -static int -canon_doc_option (const char **name) -{ -  int non_opt; -  /* Skip initial whitespace.  */ -  while (isspace ( (unsigned char) **name)) -    (*name)++; -  /* Decide whether this looks like an option (leading `-') or not.  */ -  non_opt = (**name != '-'); -  /* Skip until part of name used for sorting.  */ -  while (**name && !isalnum ( (unsigned char) **name)) -    (*name)++; -  return non_opt; -} - -/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help -   listing.  */ -static int -hol_entry_cmp (const struct hol_entry *entry1, -	       const struct hol_entry *entry2) -{ -  /* The group numbers by which the entries should be ordered; if either is -     in a cluster, then this is just the group within the cluster.  */ -  int group1 = entry1->group, group2 = entry2->group; - -  if (entry1->cluster != entry2->cluster) -    { -      /* The entries are not within the same cluster, so we can't compare them -	 directly, we have to use the appropriate clustering level too.  */ -      if (! entry1->cluster) -	/* ENTRY1 is at the `base level', not in a cluster, so we have to -	   compare it's group number with that of the base cluster in which -	   ENTRY2 resides.  Note that if they're in the same group, the -	   clustered option always comes laster.  */ -	return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); -      else if (! entry2->cluster) -	/* Likewise, but ENTRY2's not in a cluster.  */ -	return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); -      else -	/* Both entries are in clusters, we can just compare the clusters.  */ -	return hol_cluster_cmp (entry1->cluster, entry2->cluster); -    } -  else if (group1 == group2) -    /* The entries are both in the same cluster and group, so compare them -       alphabetically.  */ -    { -      int short1 = hol_entry_first_short (entry1); -      int short2 = hol_entry_first_short (entry2); -      int doc1 = odoc (entry1->opt); -      int doc2 = odoc (entry2->opt); -      /* FIXME: Can we use unsigned char * instead? */ -      const char *long1 = hol_entry_first_long (entry1); -      const char *long2 = hol_entry_first_long (entry2); - -      if (doc1) -	doc1 = canon_doc_option (&long1); -      if (doc2) -	doc2 = canon_doc_option (&long2); - -      if (doc1 != doc2) -	/* `documentation' options always follow normal options (or -	   documentation options that *look* like normal options).  */ -	return doc1 - doc2; -      else if (!short1 && !short2 && long1 && long2) -	/* Only long options.  */ -	return __strcasecmp (long1, long2); -      else -	/* Compare short/short, long/short, short/long, using the first -	   character of long options.  Entries without *any* valid -	   options (such as options with OPTION_HIDDEN set) will be put -	   first, but as they're not displayed, it doesn't matter where -	   they are.  */ -	{ -	  unsigned char first1 = short1 ? short1 : long1 ? *long1 : 0; -	  unsigned char first2 = short2 ? short2 : long2 ? *long2 : 0; -#ifdef _tolower -	  int lower_cmp = _tolower (first1) - _tolower (first2); -#else -	  int lower_cmp = tolower (first1) - tolower (first2); -#endif -	  /* Compare ignoring case, except when the options are both the -	     same letter, in which case lower-case always comes first.  */ -	  /* NOTE: The subtraction below does the right thing -	     even with eight-bit chars: first1 and first2 are -	     converted to int *before* the subtraction. */ -	  return lower_cmp ? lower_cmp : first2 - first1; -	} -    } -  else -    /* Within the same cluster, but not the same group, so just compare -       groups.  */ -    return group_cmp (group1, group2, 0); -} - -/* Version of hol_entry_cmp with correct signature for qsort.  */ -static int -hol_entry_qcmp (const void *entry1_v, const void *entry2_v) -{ -  return hol_entry_cmp (entry1_v, entry2_v); -} - -/* Sort HOL by group and alphabetically by option name (with short options -   taking precedence over long).  Since the sorting is for display purposes -   only, the shadowing of options isn't effected.  */ -static void -hol_sort (struct hol *hol) -{ -  if (hol->num_entries > 0) -    qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), -	   hol_entry_qcmp); -} - -/* Append MORE to HOL, destroying MORE in the process.  Options in HOL shadow -   any in MORE with the same name.  */ -static void -hol_append (struct hol *hol, struct hol *more) -{ -  struct hol_cluster **cl_end = &hol->clusters; - -  /* Steal MORE's cluster list, and add it to the end of HOL's.  */ -  while (*cl_end) -    cl_end = &(*cl_end)->next; -  *cl_end = more->clusters; -  more->clusters = 0; - -  /* Merge entries.  */ -  if (more->num_entries > 0) -    { -      if (hol->num_entries == 0) -	{ -	  hol->num_entries = more->num_entries; -	  hol->entries = more->entries; -	  hol->short_options = more->short_options; -	  more->num_entries = 0;	/* Mark MORE's fields as invalid.  */ -	} -      else -	/* Append the entries in MORE to those in HOL, taking care to only add -	   non-shadowed SHORT_OPTIONS values.  */ -	{ -	  unsigned left; -	  char *so, *more_so; -	  struct hol_entry *e; -	  unsigned num_entries = hol->num_entries + more->num_entries; -	  struct hol_entry *entries = -	    malloc (num_entries * sizeof (struct hol_entry)); -	  unsigned hol_so_len = strlen (hol->short_options); -	  char *short_options = -	    malloc (hol_so_len + strlen (more->short_options) + 1); - -	  __mempcpy (__mempcpy (entries, hol->entries, -				hol->num_entries * sizeof (struct hol_entry)), -		     more->entries, -		     more->num_entries * sizeof (struct hol_entry)); - -	  __mempcpy (short_options, hol->short_options, hol_so_len); - -	  /* Fix up the short options pointers from HOL.  */ -	  for (e = entries, left = hol->num_entries; left > 0; e++, left--) -	    e->short_options += (short_options - hol->short_options); - -	  /* Now add the short options from MORE, fixing up its entries -	     too.  */ -	  so = short_options + hol_so_len; -	  more_so = more->short_options; -	  for (left = more->num_entries; left > 0; e++, left--) -	    { -	      int opts_left; -	      const struct argp_option *opt; - -	      e->short_options = so; - -	      for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) -		{ -		  int ch = *more_so; -		  if (oshort (opt) && ch == opt->key) -		    /* The next short option in MORE_SO, CH, is from OPT.  */ -		    { -		      if (! find_char (ch, short_options, -				       short_options + hol_so_len)) -			/* The short option CH isn't shadowed by HOL's options, -			   so add it to the sum.  */ -			*so++ = ch; -		      more_so++; -		    } -		} -	    } - -	  *so = '\0'; - -	  free (hol->entries); -	  free (hol->short_options); - -	  hol->entries = entries; -	  hol->num_entries = num_entries; -	  hol->short_options = short_options; -	} -    } - -  hol_free (more); -} - -/* Inserts enough spaces to make sure STREAM is at column COL.  */ -static void -indent_to (argp_fmtstream_t stream, unsigned col) -{ -  int needed = col - __argp_fmtstream_point (stream); -  while (needed-- > 0) -    __argp_fmtstream_putc (stream, ' '); -} - -/* Output to STREAM either a space, or a newline if there isn't room for at -   least ENSURE characters before the right margin.  */ -static void -space (argp_fmtstream_t stream, size_t ensure) -{ -  if (__argp_fmtstream_point (stream) + ensure -      >= __argp_fmtstream_rmargin (stream)) -    __argp_fmtstream_putc (stream, '\n'); -  else -    __argp_fmtstream_putc (stream, ' '); -} - -/* If the option REAL has an argument, we print it in using the printf -   format REQ_FMT or OPT_FMT depending on whether it's a required or -   optional argument.  */ -static void -arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, -     const char *domain UNUSED, argp_fmtstream_t stream) -{ -  if (real->arg) -    { -      if (real->flags & OPTION_ARG_OPTIONAL) -	__argp_fmtstream_printf (stream, opt_fmt, -				 dgettext (domain, real->arg)); -      else -	__argp_fmtstream_printf (stream, req_fmt, -				 dgettext (domain, real->arg)); -    } -} - -/* Helper functions for hol_entry_help.  */ - -/* State used during the execution of hol_help.  */ -struct hol_help_state -{ -  /* PREV_ENTRY should contain the previous entry printed, or 0.  */ -  struct hol_entry *prev_entry; - -  /* If an entry is in a different group from the previous one, and SEP_GROUPS -     is true, then a blank line will be printed before any output. */ -  int sep_groups; - -  /* True if a duplicate option argument was suppressed (only ever set if -     UPARAMS.dup_args is false).  */ -  int suppressed_dup_arg; -}; - -/* Some state used while printing a help entry (used to communicate with -   helper functions).  See the doc for hol_entry_help for more info, as most -   of the fields are copied from its arguments.  */ -struct pentry_state -{ -  const struct hol_entry *entry; -  argp_fmtstream_t stream; -  struct hol_help_state *hhstate; - -  /* True if nothing's been printed so far.  */ -  int first; - -  /* If non-zero, the state that was used to print this help.  */ -  const struct argp_state *state; -}; - -/* If a user doc filter should be applied to DOC, do so.  */ -static const char * -filter_doc (const char *doc, int key, const struct argp *argp, -	    const struct argp_state *state) -{ -  if (argp->help_filter) -    /* We must apply a user filter to this output.  */ -    { -      void *input = __argp_input (argp, state); -      return (*argp->help_filter) (key, doc, input); -    } -  else -    /* No filter.  */ -    return doc; -} - -/* Prints STR as a header line, with the margin lines set appropriately, and -   notes the fact that groups should be separated with a blank line.  ARGP is -   the argp that should dictate any user doc filtering to take place.  Note -   that the previous wrap margin isn't restored, but the left margin is reset -   to 0.  */ -static void -print_header (const char *str, const struct argp *argp, -	      struct pentry_state *pest) -{ -  const char *tstr = dgettext (argp->argp_domain, str); -  const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); - -  if (fstr) -    { -      if (*fstr) -	{ -	  if (pest->hhstate->prev_entry) -	    /* Precede with a blank line.  */ -	    __argp_fmtstream_putc (pest->stream, '\n'); -	  indent_to (pest->stream, uparams.header_col); -	  __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); -	  __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); -	  __argp_fmtstream_puts (pest->stream, fstr); -	  __argp_fmtstream_set_lmargin (pest->stream, 0); -	  __argp_fmtstream_putc (pest->stream, '\n'); -	} - -      pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ -    } - -  if (fstr != tstr) -    free ((char *) fstr); -} - -/* Inserts a comma if this isn't the first item on the line, and then makes -   sure we're at least to column COL.  If this *is* the first item on a line, -   prints any pending whitespace/headers that should precede this line. Also -   clears FIRST.  */ -static void -comma (unsigned col, struct pentry_state *pest) -{ -  if (pest->first) -    { -      const struct hol_entry *pe = pest->hhstate->prev_entry; -      const struct hol_cluster *cl = pest->entry->cluster; - -      if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) -	__argp_fmtstream_putc (pest->stream, '\n'); - -      if (cl && cl->header && *cl->header -	  && (!pe -	      || (pe->cluster != cl -		  && !hol_cluster_is_child (pe->cluster, cl)))) -	/* If we're changing clusters, then this must be the start of the -	   ENTRY's cluster unless that is an ancestor of the previous one -	   (in which case we had just popped into a sub-cluster for a bit). -	   If so, then print the cluster's header line.  */ -	{ -	  int old_wm = __argp_fmtstream_wmargin (pest->stream); -	  print_header (cl->header, cl->argp, pest); -	  __argp_fmtstream_set_wmargin (pest->stream, old_wm); -	} - -      pest->first = 0; -    } -  else -    __argp_fmtstream_puts (pest->stream, ", "); - -  indent_to (pest->stream, col); -} - -/* Print help for ENTRY to STREAM.  */ -static void -hol_entry_help (struct hol_entry *entry, const struct argp_state *state, -		argp_fmtstream_t stream, struct hol_help_state *hhstate) -{ -  unsigned num; -  const struct argp_option *real = entry->opt, *opt; -  char *so = entry->short_options; -  int have_long_opt = 0;	/* We have any long options.  */ -  /* Saved margins.  */ -  int old_lm = __argp_fmtstream_set_lmargin (stream, 0); -  int old_wm = __argp_fmtstream_wmargin (stream); -  /* PEST is a state block holding some of our variables that we'd like to -     share with helper functions.  */ - -  /* Decent initializers are a GNU extension, so don't use it here. */ -  struct pentry_state pest; -  pest.entry = entry; -  pest.stream = stream; -  pest.hhstate = hhstate; -  pest.first = 1; -  pest.state = state; - -  if (! odoc (real)) -    for (opt = real, num = entry->num; num > 0; opt++, num--) -      if (opt->name && ovisible (opt)) -	{ -	  have_long_opt = 1; -	  break; -	} - -  /* First emit short options.  */ -  __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ -  for (opt = real, num = entry->num; num > 0; opt++, num--) -    if (oshort (opt) && opt->key == *so) -      /* OPT has a valid (non shadowed) short option.  */ -      { -	if (ovisible (opt)) -	  { -	    comma (uparams.short_opt_col, &pest); -	    __argp_fmtstream_putc (stream, '-'); -	    __argp_fmtstream_putc (stream, *so); -	    if (!have_long_opt || uparams.dup_args) -	      arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream); -	    else if (real->arg) -	      hhstate->suppressed_dup_arg = 1; -	  } -	so++; -      } - -  /* Now, long options.  */ -  if (odoc (real)) -    /* A `documentation' option.  */ -    { -      __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); -      for (opt = real, num = entry->num; num > 0; opt++, num--) -	if (opt->name && ovisible (opt)) -	  { -	    comma (uparams.doc_opt_col, &pest); -	    /* Calling gettext here isn't quite right, since sorting will -	       have been done on the original; but documentation options -	       should be pretty rare anyway...  */ -	    __argp_fmtstream_puts (stream, -				   dgettext (state->root_argp->argp_domain, -					     opt->name)); -	  } -    } -  else -    /* A real long option.  */ -    { -      int first_long_opt = 1; - -      __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); -      for (opt = real, num = entry->num; num > 0; opt++, num--) -	if (opt->name && ovisible (opt)) -	  { -	    comma (uparams.long_opt_col, &pest); -	    __argp_fmtstream_printf (stream, "--%s", opt->name); -	    if (first_long_opt || uparams.dup_args) -	      arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, -		   stream); -	    else if (real->arg) -	      hhstate->suppressed_dup_arg = 1; -	  } -    } - -  /* Next, documentation strings.  */ -  __argp_fmtstream_set_lmargin (stream, 0); - -  if (pest.first) -    { -      /* Didn't print any switches, what's up?  */ -      if (!oshort (real) && !real->name) -	/* This is a group header, print it nicely.  */ -	print_header (real->doc, entry->argp, &pest); -      else -	/* Just a totally shadowed option or null header; print nothing.  */ -	goto cleanup;		/* Just return, after cleaning up.  */ -    } -  else -    { -      const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain, -					       real->doc) : 0; -      const char *fstr = filter_doc (tstr, real->key, entry->argp, state); -      if (fstr && *fstr) -	{ -	  unsigned int col = __argp_fmtstream_point (stream); - -	  __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); -	  __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); - -	  if (col > (unsigned int) (uparams.opt_doc_col + 3)) -	    __argp_fmtstream_putc (stream, '\n'); -	  else if (col >= (unsigned int) uparams.opt_doc_col) -	    __argp_fmtstream_puts (stream, "   "); -	  else -	    indent_to (stream, uparams.opt_doc_col); - -	  __argp_fmtstream_puts (stream, fstr); -	} -      if (fstr && fstr != tstr) -	free ((char *) fstr); - -      /* Reset the left margin.  */ -      __argp_fmtstream_set_lmargin (stream, 0); -      __argp_fmtstream_putc (stream, '\n'); -    } - -  hhstate->prev_entry = entry; - -cleanup: -  __argp_fmtstream_set_lmargin (stream, old_lm); -  __argp_fmtstream_set_wmargin (stream, old_wm); -} - -/* Output a long help message about the options in HOL to STREAM.  */ -static void -hol_help (struct hol *hol, const struct argp_state *state, -	  argp_fmtstream_t stream) -{ -  unsigned num; -  struct hol_entry *entry; -  struct hol_help_state hhstate = { 0, 0, 0 }; - -  for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--) -    hol_entry_help (entry, state, stream, &hhstate); - -  if (hhstate.suppressed_dup_arg && uparams.dup_args_note) -    { -      const char *tstr = dgettext (state->root_argp->argp_domain, "\ -Mandatory or optional arguments to long options are also mandatory or \ -optional for any corresponding short options."); -      const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, -				     state ? state->root_argp : 0, state); -      if (fstr && *fstr) -	{ -	  __argp_fmtstream_putc (stream, '\n'); -	  __argp_fmtstream_puts (stream, fstr); -	  __argp_fmtstream_putc (stream, '\n'); -	} -      if (fstr && fstr != tstr) -	free ((char *) fstr); -    } -} - -/* Helper functions for hol_usage.  */ - -/* If OPT is a short option without an arg, append its key to the string -   pointer pointer to by COOKIE, and advance the pointer.  */ -static int -add_argless_short_opt (const struct argp_option *opt, -		       const struct argp_option *real, -		       const char *domain UNUSED, void *cookie) -{ -  char **snao_end = cookie; -  if (!(opt->arg || real->arg) -      && !((opt->flags | real->flags) & OPTION_NO_USAGE)) -    *(*snao_end)++ = opt->key; -  return 0; -} - -/* If OPT is a short option with an arg, output a usage entry for it to the -   stream pointed at by COOKIE.  */ -static int -usage_argful_short_opt (const struct argp_option *opt, -			const struct argp_option *real, -			const char *domain UNUSED, void *cookie) -{ -  argp_fmtstream_t stream = cookie; -  const char *arg = opt->arg; -  int flags = opt->flags | real->flags; - -  if (! arg) -    arg = real->arg; - -  if (arg && !(flags & OPTION_NO_USAGE)) -    { -      arg = dgettext (domain, arg); - -      if (flags & OPTION_ARG_OPTIONAL) -	__argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); -      else -	{ -	  /* Manually do line wrapping so that it (probably) won't -	     get wrapped at the embedded space.  */ -	  space (stream, 6 + strlen (arg)); -	  __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); -	} -    } - -  return 0; -} - -/* Output a usage entry for the long option opt to the stream pointed at by -   COOKIE.  */ -static int -usage_long_opt (const struct argp_option *opt, -		const struct argp_option *real, -		const char *domain UNUSED, void *cookie) -{ -  argp_fmtstream_t stream = cookie; -  const char *arg = opt->arg; -  int flags = opt->flags | real->flags; - -  if (! arg) -    arg = real->arg; - -  if (! (flags & OPTION_NO_USAGE)) -    { -      if (arg) -	{ -	  arg = dgettext (domain, arg); -	  if (flags & OPTION_ARG_OPTIONAL) -	    __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); -	  else -	    __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); -	} -      else -	__argp_fmtstream_printf (stream, " [--%s]", opt->name); -    } - -  return 0; -} - -/* Print a short usage description for the arguments in HOL to STREAM.  */ -static void -hol_usage (struct hol *hol, argp_fmtstream_t stream) -{ -  if (hol->num_entries > 0) -    { -      unsigned nentries; -      struct hol_entry *entry; -      char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); -      char *snao_end = short_no_arg_opts; - -      /* First we put a list of short options without arguments.  */ -      for (entry = hol->entries, nentries = hol->num_entries -	   ; nentries > 0 -	   ; entry++, nentries--) -	hol_entry_short_iterate (entry, add_argless_short_opt, -				 entry->argp->argp_domain, &snao_end); -      if (snao_end > short_no_arg_opts) -	{ -	  *snao_end++ = 0; -	  __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); -	} - -      /* Now a list of short options *with* arguments.  */ -      for (entry = hol->entries, nentries = hol->num_entries -	   ; nentries > 0 -	   ; entry++, nentries--) -	hol_entry_short_iterate (entry, usage_argful_short_opt, -				 entry->argp->argp_domain, stream); - -      /* Finally, a list of long options (whew!).  */ -      for (entry = hol->entries, nentries = hol->num_entries -	   ; nentries > 0 -	   ; entry++, nentries--) -	hol_entry_long_iterate (entry, usage_long_opt, -				entry->argp->argp_domain, stream); -    } -} - -/* Make a HOL containing all levels of options in ARGP.  CLUSTER is the -   cluster in which ARGP's entries should be clustered, or 0.  */ -static struct hol * -argp_hol (const struct argp *argp, struct hol_cluster *cluster) -{ -  const struct argp_child *child = argp->children; -  struct hol *hol = make_hol (argp, cluster); -  if (child) -    while (child->argp) -      { -	struct hol_cluster *child_cluster = -	  ((child->group || child->header) -	   /* Put CHILD->argp within its own cluster.  */ -	   ? hol_add_cluster (hol, child->group, child->header, -			      child - argp->children, cluster, argp) -	   /* Just merge it into the parent's cluster.  */ -	   : cluster); -	hol_append (hol, argp_hol (child->argp, child_cluster)) ; -	child++; -      } -  return hol; -} - -/* Calculate how many different levels with alternative args strings exist in -   ARGP.  */ -static size_t -argp_args_levels (const struct argp *argp) -{ -  size_t levels = 0; -  const struct argp_child *child = argp->children; - -  if (argp->args_doc && strchr (argp->args_doc, '\n')) -    levels++; - -  if (child) -    while (child->argp) -      levels += argp_args_levels ((child++)->argp); - -  return levels; -} - -/* Print all the non-option args documented in ARGP to STREAM.  Any output is -   preceded by a space.  LEVELS is a pointer to a byte vector the length -   returned by argp_args_levels; it should be initialized to zero, and -   updated by this routine for the next call if ADVANCE is true.  True is -   returned as long as there are more patterns to output.  */ -static int -argp_args_usage (const struct argp *argp, const struct argp_state *state, -		 char **levels, int advance, argp_fmtstream_t stream) -{ -  char *our_level = *levels; -  int multiple = 0; -  const struct argp_child *child = argp->children; -  const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0; -  const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); - -  if (fdoc) -    { -      const char *cp = fdoc; -      nl = __strchrnul (cp, '\n'); -      if (*nl != '\0') -	/* This is a `multi-level' args doc; advance to the correct position -	   as determined by our state in LEVELS, and update LEVELS.  */ -	{ -	  int i; -	  multiple = 1; -	  for (i = 0; i < *our_level; i++) -	    cp = nl + 1, nl = __strchrnul (cp, '\n'); -	  (*levels)++; -	} - -      /* Manually do line wrapping so that it (probably) won't get wrapped at -	 any embedded spaces.  */ -      space (stream, 1 + nl - cp); - -      __argp_fmtstream_write (stream, cp, nl - cp); -    } -  if (fdoc && fdoc != tdoc) -    free ((char *)fdoc);	/* Free user's modified doc string.  */ - -  if (child) -    while (child->argp) -      advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream); - -  if (advance && multiple) -    { -      /* Need to increment our level.  */ -      if (*nl) -	/* There's more we can do here.  */ -	{ -	  (*our_level)++; -	  advance = 0;		/* Our parent shouldn't advance also. */ -	} -      else if (*our_level > 0) -	/* We had multiple levels, but used them up; reset to zero.  */ -	*our_level = 0; -    } - -  return !advance; -} - -/* Print the documentation for ARGP to STREAM; if POST is false, then -   everything preceding a `\v' character in the documentation strings (or -   the whole string, for those with none) is printed, otherwise, everything -   following the `\v' character (nothing for strings without).  Each separate -   bit of documentation is separated a blank line, and if PRE_BLANK is true, -   then the first is as well.  If FIRST_ONLY is true, only the first -   occurrence is output.  Returns true if anything was output.  */ -static int -argp_doc (const struct argp *argp, const struct argp_state *state, -	  int post, int pre_blank, int first_only, -	  argp_fmtstream_t stream) -{ -  const char *text; -  const char *inp_text; -  void *input = 0; -  int anything = 0; -  size_t inp_text_limit = 0; -  const char *doc = dgettext (argp->argp_domain, argp->doc); -  const struct argp_child *child = argp->children; - -  if (doc) -    { -      char *vt = strchr (doc, '\v'); -      inp_text = post ? (vt ? vt + 1 : 0) : doc; -      inp_text_limit = (!post && vt) ? (vt - doc) : 0; -    } -  else -    inp_text = 0; - -  if (argp->help_filter) -    /* We have to filter the doc strings.  */ -    { -      if (inp_text_limit) -	/* Copy INP_TEXT so that it's nul-terminated.  */ -	inp_text = STRNDUP (inp_text, inp_text_limit); -      input = __argp_input (argp, state); -      text = -	(*argp->help_filter) (post -			      ? ARGP_KEY_HELP_POST_DOC -			      : ARGP_KEY_HELP_PRE_DOC, -			      inp_text, input); -    } -  else -    text = (const char *) inp_text; - -  if (text) -    { -      if (pre_blank) -	__argp_fmtstream_putc (stream, '\n'); - -      if (text == inp_text && inp_text_limit) -	__argp_fmtstream_write (stream, inp_text, inp_text_limit); -      else -	__argp_fmtstream_puts (stream, text); - -      if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) -	__argp_fmtstream_putc (stream, '\n'); - -      anything = 1; -    } - -  if (text && text != inp_text) -    free ((char *) text);	/* Free TEXT returned from the help filter.  */ -  if (inp_text && inp_text_limit && argp->help_filter) -    free ((char *) inp_text);	/* We copied INP_TEXT, so free it now.  */ - -  if (post && argp->help_filter) -    /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text.  */ -    { -      text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); -      if (text) -	{ -	  if (anything || pre_blank) -	    __argp_fmtstream_putc (stream, '\n'); -	  __argp_fmtstream_puts (stream, text); -	  free ((char *) text); -	  if (__argp_fmtstream_point (stream) -	      > __argp_fmtstream_lmargin (stream)) -	    __argp_fmtstream_putc (stream, '\n'); -	  anything = 1; -	} -    } - -  if (child) -    while (child->argp && !(first_only && anything)) -      anything |= -	argp_doc ((child++)->argp, state, -		  post, anything || pre_blank, first_only, -		  stream); - -  return anything; -} - -/* Output a usage message for ARGP to STREAM.  If called from -   argp_state_help, STATE is the relevant parsing state.  FLAGS are from the -   set ARGP_HELP_*.  NAME is what to use wherever a `program name' is -   needed. */ - -static void -_help (const struct argp *argp, const struct argp_state *state, FILE *stream, -       unsigned flags, const char *name) -{ -  int anything = 0;		/* Whether we've output anything.  */ -  struct hol *hol = 0; -  argp_fmtstream_t fs; - -  if (! stream) -    return; - -  FLOCKFILE (stream); - -  if (! uparams.valid) -    fill_in_uparams (state); - -  fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); -  if (! fs) -    { -      FUNLOCKFILE (stream); -      return; -    } - -  if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) -    { -      hol = argp_hol (argp, 0); - -      /* If present, these options always come last.  */ -      hol_set_group (hol, "help", -1); -      hol_set_group (hol, "version", -1); - -      hol_sort (hol); -    } - -  if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) -    /* Print a short `Usage:' message.  */ -    { -      int first_pattern = 1, more_patterns; -      size_t num_pattern_levels = argp_args_levels (argp); -      char *pattern_levels = alloca (num_pattern_levels); - -      memset (pattern_levels, 0, num_pattern_levels); - -      do -	{ -	  int old_lm; -	  int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); -	  char *levels = pattern_levels; - -	  if (first_pattern) -	    __argp_fmtstream_printf (fs, "%s %s", -				     dgettext (argp->argp_domain, "Usage:"), -				     name); -	  else -	    __argp_fmtstream_printf (fs, "%s %s", -				     dgettext (argp->argp_domain, "  or: "), -				     name); - -	  /* We set the lmargin as well as the wmargin, because hol_usage -	     manually wraps options with newline to avoid annoying breaks.  */ -	  old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); - -	  if (flags & ARGP_HELP_SHORT_USAGE) -	    /* Just show where the options go.  */ -	    { -	      if (hol->num_entries > 0) -		__argp_fmtstream_puts (fs, dgettext (argp->argp_domain, -						     " [OPTION...]")); -	    } -	  else -	    /* Actually print the options.  */ -	    { -	      hol_usage (hol, fs); -	      flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once.  */ -	    } - -	  more_patterns = argp_args_usage (argp, state, &levels, 1, fs); - -	  __argp_fmtstream_set_wmargin (fs, old_wm); -	  __argp_fmtstream_set_lmargin (fs, old_lm); - -	  __argp_fmtstream_putc (fs, '\n'); -	  anything = 1; - -	  first_pattern = 0; -	} -      while (more_patterns); -    } - -  if (flags & ARGP_HELP_PRE_DOC) -    anything |= argp_doc (argp, state, 0, 0, 1, fs); - -  if (flags & ARGP_HELP_SEE) -    { -      __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ -Try `%s --help' or `%s --usage' for more information.\n"), -			       name, name); -      anything = 1; -    } - -  if (flags & ARGP_HELP_LONG) -    /* Print a long, detailed help message.  */ -    { -      /* Print info about all the options.  */ -      if (hol->num_entries > 0) -	{ -	  if (anything) -	    __argp_fmtstream_putc (fs, '\n'); -	  hol_help (hol, state, fs); -	  anything = 1; -	} -    } - -  if (flags & ARGP_HELP_POST_DOC) -    /* Print any documentation strings at the end.  */ -    anything |= argp_doc (argp, state, 1, anything, 0, fs); - -  if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) -    { -      if (anything) -	__argp_fmtstream_putc (fs, '\n'); -      __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, -					     "Report bugs to %s.\n"), - 			       argp_program_bug_address); -      anything = 1; -    } - -  FUNLOCKFILE (stream); - -  if (hol) -    hol_free (hol); - -  __argp_fmtstream_free (fs); -} - -/* Output a usage message for ARGP to STREAM.  FLAGS are from the set -   ARGP_HELP_*.  NAME is what to use wherever a `program name' is needed. */ -void __argp_help (const struct argp *argp, FILE *stream, -		  unsigned flags, char *name) -{ -  _help (argp, 0, stream, flags, name); -} -#ifdef weak_alias -weak_alias (__argp_help, argp_help) -#endif - -char *__argp_basename(char *name) -{ -  char *short_name = strrchr(name, '/'); -  return short_name ? short_name + 1 : name; -} - -char * -__argp_short_program_name(const struct argp_state *state) -{ -  if (state) -    return state->name; -#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME -  return program_invocation_short_name; -#elif HAVE_DECL_PROGRAM_INVOCATION_NAME -  return __argp_basename(program_invocation_name); -#else /* !HAVE_DECL_PROGRAM_INVOCATION_NAME */ -  /* FIXME: What now? Miles suggests that it is better to use NULL, -     but currently the value is passed on directly to fputs_unlocked, -     so that requires more changes. */ -# if __GNUC__ -  return ""; -# endif /* __GNUC__ */ -#endif /* !HAVE_DECL_PROGRAM_INVOCATION_NAME */ -} - -/* Output, if appropriate, a usage message for STATE to STREAM.  FLAGS are -   from the set ARGP_HELP_*.  */ -void -__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) -{ -  if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) -    { -      if (state && (state->flags & ARGP_LONG_ONLY)) -	flags |= ARGP_HELP_LONG_ONLY; - -      _help (state ? state->root_argp : 0, state, stream, flags, -	     __argp_short_program_name(state)); - -      if (!state || ! (state->flags & ARGP_NO_EXIT)) -	{ -	  if (flags & ARGP_HELP_EXIT_ERR) -	    exit (argp_err_exit_status); -	  if (flags & ARGP_HELP_EXIT_OK) -	    exit (0); -	} -  } -} -#ifdef weak_alias -weak_alias (__argp_state_help, argp_state_help) -#endif - -/* If appropriate, print the printf string FMT and following args, preceded -   by the program name and `:', to stderr, and followed by a `Try ... --help' -   message, then exit (1).  */ -void -__argp_error (const struct argp_state *state, const char *fmt, ...) -{ -  if (!state || !(state->flags & ARGP_NO_ERRS)) -    { -      FILE *stream = state ? state->err_stream : stderr; - -      if (stream) -	{ -	  va_list ap; - -	  FLOCKFILE (stream); - -	  FPUTS_UNLOCKED (__argp_short_program_name(state), -			  stream); -	  PUTC_UNLOCKED (':', stream); -	  PUTC_UNLOCKED (' ', stream); - -	  va_start (ap, fmt); -	  vfprintf (stream, fmt, ap); -	  va_end (ap); - -	  PUTC_UNLOCKED ('\n', stream); - -	  __argp_state_help (state, stream, ARGP_HELP_STD_ERR); - -	  FUNLOCKFILE (stream); -	} -    } -} -#ifdef weak_alias -weak_alias (__argp_error, argp_error) -#endif - -/* Similar to the standard gnu error-reporting function error(), but will -   respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print -   to STATE->err_stream.  This is useful for argument parsing code that is -   shared between program startup (when exiting is desired) and runtime -   option parsing (when typically an error code is returned instead).  The -   difference between this function and argp_error is that the latter is for -   *parsing errors*, and the former is for other problems that occur during -   parsing but don't reflect a (syntactic) problem with the input.  */ -void -__argp_failure (const struct argp_state *state, int status, int errnum, -		const char *fmt, ...) -{ -  if (!state || !(state->flags & ARGP_NO_ERRS)) -    { -      FILE *stream = state ? state->err_stream : stderr; - -      if (stream) -	{ -	  FLOCKFILE (stream); - -	  FPUTS_UNLOCKED (__argp_short_program_name(state), -			  stream); - -	  if (fmt) -	    { -	      va_list ap; - -	      PUTC_UNLOCKED (':', stream); -	      PUTC_UNLOCKED (' ', stream); - -	      va_start (ap, fmt); -	      vfprintf (stream, fmt, ap); -	      va_end (ap); -	    } - -	  if (errnum) -	    { -	      PUTC_UNLOCKED (':', stream); -	      PUTC_UNLOCKED (' ', stream); -	      fputs (STRERROR (errnum), stream); -	    } - -	  PUTC_UNLOCKED ('\n', stream); - -	  FUNLOCKFILE (stream); - -	  if (status && (!state || !(state->flags & ARGP_NO_EXIT))) -	    exit (status); -	} -    } -} -#ifdef weak_alias -weak_alias (__argp_failure, argp_failure) -#endif  | 
