diff options
Diffstat (limited to 'argp')
-rw-r--r-- | argp/Makefile | 6 | ||||
-rw-r--r-- | argp/argp-help.c | 78 | ||||
-rw-r--r-- | argp/bug-argp1.c | 26 |
3 files changed, 70 insertions, 40 deletions
diff --git a/argp/Makefile b/argp/Makefile index a68ca1bee3..5ade517476 100644 --- a/argp/Makefile +++ b/argp/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1997, 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 1997, 2002, 2003, 2006 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -26,10 +26,12 @@ distribute = argp-fmtstream.h argp-namefrob.h routines = $(addprefix argp-, ba fmtstream fs-xinl help parse pv \ pvh xinl eexst) -tests = argp-test tst-argp1 +tests = argp-test tst-argp1 bug-argp1 CFLAGS-argp-help.c = $(uses-callbacks) -fexceptions CFLAGS-argp-parse.c = $(uses-callbacks) CFLAGS-argp-fmtstream.c = -fexceptions +bug-argp1-ARGS = -- --help + include ../Rules diff --git a/argp/argp-help.c b/argp/argp-help.c index 4bc4d07b15..13c0820710 100644 --- a/argp/argp-help.c +++ b/argp/argp-help.c @@ -1,5 +1,5 @@ /* Hierarchial argument parsing help output - Copyright (C) 1995-2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995-2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. @@ -128,40 +128,37 @@ struct uparams 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 + USAGE_INDENT, RMARGIN }; /* 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. */ + const char name[14]; /* User name. */ + bool is_bool; /* Whether it's `boolean'. */ + uint8_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 } + { "dup-args", true, offsetof (struct uparams, dup_args) }, + { "dup-args-note", true, offsetof (struct uparams, dup_args_note) }, + { "short-opt-col", false, offsetof (struct uparams, short_opt_col) }, + { "long-opt-col", false, offsetof (struct uparams, long_opt_col) }, + { "doc-opt-col", false, offsetof (struct uparams, doc_opt_col) }, + { "opt-doc-col", false, offsetof (struct uparams, opt_doc_col) }, + { "header-col", false, offsetof (struct uparams, header_col) }, + { "usage-indent", false, offsetof (struct uparams, usage_indent) }, + { "rmargin", false, offsetof (struct uparams, rmargin) } }; +#define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0])) /* Read user options from the environment, and fill in UPARAMS appropiately. */ static void @@ -217,22 +214,27 @@ fill_in_uparams (const struct argp_state *state) SKIPWS (arg); } - for (un = uparam_names; un->name; un++) + un = uparam_names; + size_t u; + for (u = 0; u < nuparam_names; ++un, ++u) 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, "\ + dgettext (state == NULL ? NULL + : 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) + if (u == nuparam_names) __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, "\ + dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, "\ %.*s: Unknown ARGP_HELP_FMT parameter"), (int) var_len, var); @@ -243,7 +245,8 @@ fill_in_uparams (const struct argp_state *state) else if (*var) { __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, + dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, "Garbage in ARGP_HELP_FMT: %s"), var); break; } @@ -759,9 +762,9 @@ hol_entry_cmp (const struct hol_entry *entry1, const char *long2 = hol_entry_first_long (entry2); if (doc1) - doc1 = canon_doc_option (&long1); + doc1 = long1 != NULL && canon_doc_option (&long1); if (doc2) - doc2 = canon_doc_option (&long2); + doc2 = long2 != NULL && canon_doc_option (&long2); if (doc1 != doc2) /* `documentation' options always follow normal options (or @@ -1102,7 +1105,9 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, __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); + arg (real, " %s", "[%s]", + state == NULL ? NULL : state->root_argp->argp_domain, + stream); else if (real->arg) hhstate->suppressed_dup_arg = 1; } @@ -1122,26 +1127,22 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, have been done on the original; but documentation options should be pretty rare anyway... */ __argp_fmtstream_puts (stream, - dgettext (state->root_argp->argp_domain, + dgettext (state == NULL ? NULL + : 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; + arg (real, "=%s", "[=%s]", + state == NULL ? NULL : state->root_argp->argp_domain, stream); } } @@ -1160,7 +1161,8 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, } else { - const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain, + const char *tstr = real->doc ? dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, real->doc) : 0; const char *fstr = filter_doc (tstr, real->key, entry->argp, state); if (fstr && *fstr) @@ -1208,7 +1210,8 @@ hol_help (struct hol *hol, const struct argp_state *state, if (hhstate.suppressed_dup_arg && uparams.dup_args_note) { - const char *tstr = dgettext (state->root_argp->argp_domain, "\ + const char *tstr = dgettext (state == NULL ? NULL + : 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, @@ -1555,8 +1558,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, __flockfile (stream); #endif - if (! uparams.valid) - fill_in_uparams (state); + fill_in_uparams (state); fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); if (! fs) diff --git a/argp/bug-argp1.c b/argp/bug-argp1.c new file mode 100644 index 0000000000..a28cf4b9c7 --- /dev/null +++ b/argp/bug-argp1.c @@ -0,0 +1,26 @@ +#include <argp.h> + + +static const struct argp_option test_options[] = +{ + { NULL, 'a', NULL, OPTION_DOC, NULL }, + { NULL, 'b', NULL, OPTION_DOC, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static struct argp test_argp = +{ + test_options +}; + + +static int +do_test (int argc, char *argv[]) +{ + int i; + argp_parse (&test_argp, argc, argv, 0, &i, NULL); + return 0; +} + +#define TEST_FUNCTION do_test (argc, argv) +#include "../test-skeleton.c" |