about summary refs log tree commit diff
path: root/argp
diff options
context:
space:
mode:
Diffstat (limited to 'argp')
-rw-r--r--argp/Makefile6
-rw-r--r--argp/argp-help.c64
-rw-r--r--argp/bug-argp1.c26
3 files changed, 60 insertions, 36 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..7ba621b735 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
@@ -1129,19 +1132,13 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
   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->root_argp->argp_domain, stream);
 	  }
     }
 
@@ -1555,8 +1552,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"