/* Hierarchial argument parsing help output
- Copyright (C) 1995-2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
#include <config.h>
#endif
-#ifndef alloca
-# ifdef __GNUC__
-# define alloca __builtin_alloca
-# define HAVE_ALLOCA 1
-# else
-# if defined HAVE_ALLOCA_H || defined _LIBC
-# include <alloca.h>
-# else
-# ifdef _AIX
- #pragma alloca
-# else
-# ifndef alloca
-char *alloca ();
-# endif
-# endif
-# endif
-# endif
-#endif
-
+#include <alloca.h>
+#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
-#include <malloc.h>
#include <ctype.h>
+#include <limits.h>
#ifdef USE_IN_LIBIO
# include <wchar.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) \
- INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
-# endif
-# else
-# define dgettext(domain, msgid) (msgid)
-# endif
+#ifdef _LIBC
+# include <libintl.h>
+# undef dgettext
+# define dgettext(domain, msgid) \
+ INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
+#else
+# include "gettext.h"
#endif
#include "argp.h"
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
-#endif
+#endif
\f
/* User-selectable (using an environment variable) formatting parameters.
/* Returns true if OPT is an documentation-only entry. */
#define odoc(opt) ((opt)->flags & OPTION_DOC)
+/* Returns true if OPT should not be translated */
+#define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS)
+
/* Returns true if OPT is the end-of-list marker for a list of options. */
#define oend(opt) __option_is_end (opt)
hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
hol->short_options = malloc (num_short_options + 1);
- assert (hol->entries && hol->short_options
- && hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
+ assert (hol->entries && hol->short_options);
+ if (SIZE_MAX <= UINT_MAX)
+ assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
/* Fill in the entries. */
so = hol->short_options;
}
static inline int
-__attribute ((always_inline))
+__attribute__ ((always_inline))
hol_entry_long_iterate (const struct hol_entry *entry,
int (*func)(const struct argp_option *opt,
const struct argp_option *real,
canon_doc_option (const char **name)
{
int non_opt;
- /* Skip initial whitespace. */
- while (isspace (**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 (**name))
- (*name)++;
+
+ if (!*name)
+ non_opt = 1;
+ else
+ {
+ /* Skip initial whitespace. */
+ while (isspace (**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 (**name))
+ (*name)++;
+ }
return non_opt;
}
char *short_options =
malloc (hol_so_len + strlen (more->short_options) + 1);
- assert (entries && short_options
- && num_entries <= SIZE_MAX / sizeof (struct hol_entry));
+ assert (entries && short_options);
+ if (SIZE_MAX <= UINT_MAX)
+ assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry));
__mempcpy (__mempcpy (entries, hol->entries,
hol->num_entries * sizeof (struct hol_entry)),
{
__argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
for (opt = real, num = entry->num; num > 0; opt++, num--)
- if (opt->name && ovisible (opt))
+ if (opt->name && *opt->name && ovisible (opt))
{
comma (uparams.doc_opt_col, &pest);
- /* Calling gettext here isn't quite right, since sorting will
+ /* Calling dgettext 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,
+ onotrans (opt) ?
+ opt->name :
dgettext (state->root_argp->argp_domain,
opt->name));
}
if (! stream)
return;
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__flockfile (stream);
+#endif
if (! uparams.valid)
fill_in_uparams (state);
fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
if (! fs)
{
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
+#endif
return;
}
anything = 1;
}
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
+#endif
if (hol)
hol_free (hol);
weak_alias (__argp_help, argp_help)
#endif
+#if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
+char *
+__argp_short_program_name (void)
+{
+# if HAVE_DECL_PROGRAM_INVOCATION_NAME
+ char *name = strrchr (program_invocation_name, '/');
+ return name ? name + 1 : program_invocation_name;
+# else
+ /* 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__
+# warning No reasonable value to return
+# endif /* __GNUC__ */
+ return "";
+# endif
+}
+#endif
+
/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
from the set ARGP_HELP_*. */
void
flags |= ARGP_HELP_LONG_ONLY;
_help (state ? state->root_argp : 0, state, stream, flags,
- state ? state->name : program_invocation_short_name);
+ state ? state->name : __argp_short_program_name ());
if (!state || ! (state->flags & ARGP_NO_EXIT))
{
{
va_list ap;
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__flockfile (stream);
+#endif
va_start (ap, fmt);
__asprintf (&buf, fmt, ap);
__fwprintf (stream, L"%s: %s\n",
- state ? state->name : program_invocation_short_name,
+ state ? state->name : __argp_short_program_name (),
buf);
free (buf);
#endif
{
fputs_unlocked (state
- ? state->name : program_invocation_short_name,
+ ? state->name : __argp_short_program_name (),
stream);
putc_unlocked (':', stream);
putc_unlocked (' ', stream);
va_end (ap);
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
+#endif
}
}
}
if (stream)
{
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__flockfile (stream);
+#endif
#ifdef USE_IN_LIBIO
if (_IO_fwide (stream, 0) > 0)
__fwprintf (stream, L"%s",
- state ? state->name : program_invocation_short_name);
+ state ? state->name : __argp_short_program_name ());
else
#endif
fputs_unlocked (state
- ? state->name : program_invocation_short_name,
+ ? state->name : __argp_short_program_name (),
stream);
if (fmt)
else
#endif
{
+ char const *s = NULL;
putc_unlocked (':', stream);
putc_unlocked (' ', stream);
- fputs (__strerror_r (errnum, buf, sizeof (buf)), stream);
+#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P)
+ s = __strerror_r (errnum, buf, sizeof buf);
+#elif HAVE_DECL_STRERROR_R
+ if (__strerror_r (errnum, buf, sizeof buf) == 0)
+ s = buf;
+#endif
+#if !_LIBC
+ if (! s && ! (s = strerror (errnum)))
+ s = "Unknown system error"; /* FIXME: translate this */
+#endif
+ fputs (s, stream);
}
}
#endif
putc_unlocked ('\n', stream);
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
+#endif
if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
exit (status);