X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fargp-help.c;h=c506b57b0ac4dc49bafe4d9eb0266c93ecf6bf4e;hb=cbb86267fda18ba3e409e16cf9c460cbbed1846c;hp=497bae148855bee17056d2bb1f4a660719b0833f;hpb=a82fdff58064e24994117ed668ae13362253be46;p=gnulib.git diff --git a/lib/argp-help.c b/lib/argp-help.c index 497bae148..c506b57b0 100644 --- a/lib/argp-help.c +++ b/lib/argp-help.c @@ -1,5 +1,5 @@ /* 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 . @@ -25,53 +25,35 @@ #include #endif -#ifndef alloca -# ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -# else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -# endif -#endif - +#include +#include #include #include #include #include #include -#include #include +#include #ifdef USE_IN_LIBIO # include #endif -#ifndef _ -/* This is for other GNU distributions with internationalized messages. */ -# if defined HAVE_LIBINTL_H || defined _LIBC -# include -# 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 +# undef dgettext +# define dgettext(domain, msgid) \ + INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) +#else +# include "gettext.h" #endif #include "argp.h" #include "argp-fmtstream.h" #include "argp-namefrob.h" + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif /* User-selectable (using an environment variable) formatting parameters. @@ -246,6 +228,9 @@ fill_in_uparams (const struct argp_state *state) /* 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) @@ -441,6 +426,8 @@ make_hol (const struct argp *argp, struct hol_cluster *cluster) hol->short_options = malloc (num_short_options + 1); 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; @@ -546,7 +533,7 @@ hol_entry_short_iterate (const struct hol_entry *entry, } 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, @@ -692,14 +679,20 @@ static int 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; } @@ -833,6 +826,10 @@ hol_append (struct hol *hol, struct hol *more) char *short_options = malloc (hol_so_len + strlen (more->short_options) + 1); + 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)), more->entries, @@ -1058,7 +1055,13 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, 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. */ - struct pentry_state pest = { entry, stream, hhstate, 1, state }; + 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--) @@ -1093,13 +1096,15 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, { __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)); } @@ -1529,7 +1534,9 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, if (! stream) return; +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) __flockfile (stream); +#endif if (! uparams.valid) fill_in_uparams (state); @@ -1537,7 +1544,9 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); if (! fs) { +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) __funlockfile (stream); +#endif return; } @@ -1645,7 +1654,9 @@ Try `%s --help' or `%s --usage' for more information.\n"), anything = 1; } +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) __funlockfile (stream); +#endif if (hol) hol_free (hol); @@ -1664,6 +1675,25 @@ void __argp_help (const struct argp *argp, FILE *stream, 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 @@ -1675,7 +1705,7 @@ __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) 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)) { @@ -1704,7 +1734,9 @@ __argp_error (const struct argp_state *state, const char *fmt, ...) { va_list ap; +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) __flockfile (stream); +#endif va_start (ap, fmt); @@ -1716,7 +1748,7 @@ __argp_error (const struct argp_state *state, const char *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); @@ -1725,7 +1757,7 @@ __argp_error (const struct argp_state *state, const char *fmt, ...) #endif { fputs_unlocked (state - ? state->name : program_invocation_short_name, + ? state->name : __argp_short_program_name (), stream); putc_unlocked (':', stream); putc_unlocked (' ', stream); @@ -1739,7 +1771,9 @@ __argp_error (const struct argp_state *state, const char *fmt, ...) va_end (ap); +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) __funlockfile (stream); +#endif } } } @@ -1765,16 +1799,18 @@ __argp_failure (const struct argp_state *state, int status, int errnum, 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) @@ -1816,9 +1852,20 @@ __argp_failure (const struct argp_state *state, int status, int errnum, 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); } } @@ -1829,7 +1876,9 @@ __argp_failure (const struct argp_state *state, int status, int errnum, #endif putc_unlocked ('\n', stream); +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) __funlockfile (stream); +#endif if (status && (!state || !(state->flags & ARGP_NO_EXIT))) exit (status);