summary refs log tree commit diff
path: root/argp
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-06-19 19:11:22 +0000
committerUlrich Drepper <drepper@redhat.com>1997-06-19 19:11:22 +0000
commitd705269e75ff9846000abea981774b381b076482 (patch)
tree7bd717a8489ad113cb0d10b7628a88d6a55cb836 /argp
parente7f1f046f51d95d5d05ada3abd3f2e88219118e9 (diff)
downloadglibc-d705269e75ff9846000abea981774b381b076482.tar.gz
glibc-d705269e75ff9846000abea981774b381b076482.tar.xz
glibc-d705269e75ff9846000abea981774b381b076482.zip
1997-06-19 19:38  Ulrich Drepper  <drepper@cygnus.com>

	* features.h: Define __STDC_IEC_559__ and _STDC_IEC_559_COMPLEX__.

	* elf/dl-minimal.c (__dcgettext): Remove assertion.

	* inet/rcmd.c: Correct a few typos.  Reported by Eric Troan.

	* manual/Makefile (distribute): Add dir.
	* manual/dir: New file.

	* math/Makefile (libm-support): Rename s_rinttol, s_rinttoll,
	s_roundtol, and s_roundtoll to s_lrint, s_llrint, s_lround,
	and s_llround respectively.
	(libm-calls): Add e_gamma_r.
	* math/libm-test.c (check_int_exc): New function.
	(signbit_test): Remove test for sign of NaN.
	(gamma_test): Clear exception after test of existence.
	Correct tests and and epsilons.
	(lgamma_test): Likewise.
	(ilogb_test): Correct all tests.
	(scalb_test): Rewrite.
	(rinttol_test): Rename to lrint_test and correct tests.
	(rinttoll_test): Likewise.
	(roundtol_test): Likewise.
	(roundtoll_test): Likewise.
	(main): Call lrint/lround functions instead of rinttol/roundtol.
	* math/math.h: Change prototypes for rinttol/roundtol.
	* math/mathcalls.h: Rearrange prototypes according to ISO C9X draft.
	* sysdeps/generic/mathbits.h: Define FP_ILOGB0 and FP_ILOGBNAN.
	* sysdeps/i386/mathbits.h: Likewise.
	* sysdeps/libm-i387/e_scalb.S: Handle special cases correctly.
	* sysdeps/libm-i387/e_scalbf.S: Likewise.
	* sysdeps/libm-i387/e_scalbl.S: Likewise.
	* sysdeps/libm-i387/s_asinh.S: Handle -inf correctly.
	* sysdeps/libm-i387/s_asinhf.S: Likewise.
	* sysdeps/libm-i387/s_asinhl.S: Likewise.
	* sysdeps/libm-i387/s_ilogb.S: Optimize.
	* sysdeps/libm-i387/s_ilogbf.S: Likewise.
	* sysdeps/libm-i387/s_ilogbl.S: Likewise.
	* sysdeps/libm-i387/s_rinttol.S: Rename to...
	* sysdeps/libm-i387/s_lrint.S: ...this.
	* sysdeps/libm-i387/s_rinttoll.S: Rename to...
	* sysdeps/libm-i387/s_llrint.S: ...this.
	* sysdeps/libm-i387/s_remquo.S: Correctly set sign of remainder.
	* sysdeps/libm-i387/s_remquof.S: Likewise.
	* sysdeps/libm-i387/s_remquol.S: Likewise.
	* sysdeps/libm-i387/e_gamma_r.c: New file.  Implementation of gamma
	function according to ISO C.
	* sysdeps/libm-i387/e_gammaf_r.c: New file.
	* sysdeps/libm-i387/e_gammal_r.c: New file.
	* sysdeps/libm-i387/e_lgamma_r.c: Don't let optimize compile the
	generation of exceptions away.
	* sysdeps/libm-i387/e_lgammaf_r.c: Likewise.
	* sysdeps/libm-i387/k_standard.c: Correct return value for infinity
	points of gamma function when not SVID mode.
	* sysdeps/libm-i387/s_rinttoll.c: Renamed to...
	* sysdeps/libm-i387/s_llrint.c: ...this.
	* sysdeps/libm-i387/s_rinttol.c: Renamed to...
	* sysdeps/libm-i387/s_lrint.c: ...this.
	* sysdeps/libm-i387/s_roundtoll.c: Renamed to...
	* sysdeps/libm-i387/s_llround.c: ...this.
	* sysdeps/libm-i387/s_roundtol.c: Renamed to...
	* sysdeps/libm-i387/s_lround.c: ..this.
	* sysdeps/libm-i387/s_scalbn.c: Change second parameter according to
	ISO C.
	* sysdeps/libm-i387/s_scalbnf.c: Likewise.
	* sysdeps/libm-i387/s_scalbnl.c: Likewise.
	* sysdeps/libm-i387/w_gamma.c: Call __ieee754_gamma_r if library
	mode is not _SVID_.
	* sysdeps/libm-i387/w_gammaf.c: Likewise.
	* sysdeps/libm-i387/w_gammal.c: Likewise.
	* sysdeps/m68k/fpu/__math.h: Rename __rinttol to __lrint and
	rinttol to lrint.
	* sysdeps/m68k/fpu/s_rinttol.c: Renamed to...
	* sysdeps/m68k/fpu/s_lrint.c: ...this.
	* sysdeps/m68k/fpu/s_rinttoll.c: Renamed to...
	* sysdeps/m68k/fpu/s_llrint.c: ...this.

	* md5-crypt/Makefile: Link md5test program with md5.o.

	* stdio-common/temptest.c: Don't use __stdio_gen_tempname which
	is not exported by the libc.so.

	* stdio-common/vfscanf.c: Correct scanning of strings after last
	change.

	* sysdeps/unix/sysv/linux/i386/sysdep.S: Use .comm to define errno.

1997-06-19 07:37  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* time/tzfile.c (__tzfile_read): Store getc () return in int.

1997-06-13  Miles Bader  <miles@gnu.ai.mit.edu>

	* argp/argp-parse.c (argp_version_parser): Include `(PROGRAM ERROR)' in
	the no-version error text to indicate that something's fucked.
	[!_] (N_): New macro.
	(argp_default_options, argp_version_options): Wrap doc strings in N_().

1997-06-12  Miles Bader  <miles@gnu.ai.mit.edu>

	* argp/argp-parse.c (parser_parse_opt): Detect and report unhandled
	options here.
	(parser_parse_arg): Handle ARGP_KEY_ARGS here.
	Adjust NEXT pointer back if we fail to parse anything.
	(parser_parse_next): Simplify arg code.  Leave state NEXT frobbing
	to parser_parse_arg.

1997-06-11  Miles Bader  <miles@gnu.ai.mit.edu>

	* argp/argp.h (ARGP_KEY_ARGS, ARGP_KEY_FINI): New macros.
	* argp/argp-parse.c (parser_finalize): Do another pass over the
	parsers with ARGP_KEY_FINI.

1997-06-18  Miles Bader  <miles@gnu.ai.mit.edu>

	* string/Makefile (routines): Add argz-replace.

1997-06-16 00:16  Miles Bader  <miles@gnu.ai.mit.edu>

	* manual/string.texi (Argz Functions): Document argz_replace.

1997-06-12  Miles Bader  <miles@gnu.ai.mit.edu>

	* string/argz.h (__argz_replace, argz_replace): New declarations.
	* string/argz-replace.c: New file.

1997-06-11  Miles Bader  <miles@gnu.ai.mit.edu>

	* manual/argp.texi (Argp Special Keys): Document ARGP_KEY_ARGS.

1997-06-16 23:08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* Makeconfig (libc-map): Remove definition.
	* Makerules (libc-map): Define it here, using the full name.
	(load-map-file): Remove case for empty $(..).
	($(common-objpfx)libc.so): Revert last change.

1997-06-17 22:18  Mark Kettenis  <kettenis@phys.uva.nl>

	* login/programs/utmpd.c (main): Improve signal handling.

	* login/programs/request.c (do_setutent, do_updwtmp):
	Allow arbitrary length filenames.
	* login/programs/utmpd.h (setutent_request, updwtmp_request):
	Get rid of fixed length file field.
	* login/utmp_daemon.c (do_setutent, do_updwtmp):
	Allow arbitrary	length filenames.

	* login/programs/request.c (do_pututline):
	Don't fail if connection->position is -1 on entry.

1997-06-15 16:32  Mark Kettenis  <kettenis@phys.uva.nl>

	* login/utmp_file.c (updwtmp_file): Use the same method for
	appending an entry as in pututline_file.

1997-06-11 18:59  Mark Kettenis  <kettenis@phys.uva.nl>

	* login/utmp_file.c (getutent_r_file):
	Use read lock instead of write lock.
	(getutline_r_file, internal_getut_r): Lock utmp file.
	(updwtmp_file): Use fcntl to lock file instead of flock.

1997-06-18 00:11  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* stdio-common/vfscanf.c (inchar, ungetc): Don't count EOF as
	character read in/put back.
	* stdio-common/tstscanf.c: Add test case for this.

1997-06-17 22:17  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* libc.map: Add more symbols.

1997-06-18 12:01  Ulrich Drepper  <drepper@cygnus.com>

	* manual/Makefile (install): Make sure `dir' file exists if we use
	install-info.

1997-06-17 19:32  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* manual/Makefile (info): Depend on dir-add.info.

1997-06-17 17:19  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* elf/ldd.bash.in: Fix spacing in message.

1997-06-17 14:28  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* elf/do-rel.h (elf_dynamic_do_rel): Always use version
	information if available.

1997-06-17 11:34  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sunrpc/Makefile ($(rpcsvc:%.x=$(objpfx)rpcsvc/%.h)): Make
	command non-empty to force make to recheck modification time.
	($(rpcsvc:%.x=$(objpfx)x%.c)): Likewise.

1997-06-17 00:26  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/stub/e_acoshl.c: Set errno to ENOSYS.
	* sysdeps/stub/e_acosl.c: Likewise.
	* sysdeps/stub/e_asinl.c: Likewise.
	* sysdeps/stub/e_atan2l.c: Likewise.
	* sysdeps/stub/e_expl.c: Likewise.
	* sysdeps/stub/e_fmodl.c: Likewise.
	* sysdeps/stub/e_j0l.c: Likewise.
	* sysdeps/stub/e_j1l.c: Likewise.
	* sysdeps/stub/e_jnl.c: Likewise.
	* sysdeps/stub/e_lgammal_r.c: Likewise.
	* sysdeps/stub/e_log10l.c: Likewise.
	* sysdeps/stub/e_logl.c: Likewise.
	* sysdeps/stub/e_powl.c: Likewise.
	* sysdeps/stub/e_rem_pio2l.c: Likewise.
	* sysdeps/stub/e_sqrtl.c: Likewise.
	* sysdeps/stub/k_cosl.c: Likewise.
	* sysdeps/stub/k_rem_pio2l.c: Likewise.
	* sysdeps/stub/k_sinl.c: Likewise.
	* sysdeps/stub/k_tanl.c: Likewise.
	* sysdeps/stub/s_atanl.c: Likewise.
	* sysdeps/stub/s_erfl.c: Likewise.
	* sysdeps/stub/s_exp2.c: Likewise.
	* sysdeps/stub/s_exp2f.c: Likewise.
	* sysdeps/stub/s_exp2l.c: Likewise.
	* sysdeps/stub/s_expm1l.c: Likewise.
	* sysdeps/stub/s_log1pl.c: Likewise.
	* sysdeps/stub/s_log2l.c: Likewise.

1997-06-18 11:46  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/libm-ieee754/w_gamma.c: If _LIB_VERSION is _SVID_ compute
	result as before last change.
	* sysdeps/libm-ieee754/w_gammaf.c: Likewise.
	* sysdeps/libm-ieee754/w_gammal.c: Likewise.

1997-06-16 23:37  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/libm-ieee754/s_remquo.c: Fix off-by-one when computing
	quotient.
	* sysdeps/libm-ieee754/s_remquof.c: Likewise.
	* sysdeps/libm-ieee754/s_remquol.c: Likewise.

	* sysdeps/m68k/fpu/s_remquo.c: Remove FIXME and special case for
	quotient.

	* sysdeps/libm-ieee754/w_gamma.c: Add missing call to exp
	function.  Don't use global signgam.
	* sysdeps/libm-ieee754/w_gammaf.c: Likewise.
	* sysdeps/libm-ieee754/w_gammal.c: Likewise.

	* math/Makefile (libm-calls): Remove w_gamma_r.
	* sysdeps/libm-ieee754/w_gamma_r.c: Remove file.
	* sysdeps/libm-ieee754/w_gammaf_r.c: Remove file.
	* sysdeps/libm-ieee754/w_gammal_r.c: Remove file.

	* math/libm-test.c (atanh_test): Declare x only if needed.
	(signbit_test): Fix typo.
	(gamma_test): Check whether function is implemented.  Add
	epsilons.
	(lgamma_test): Likewise.
	(fmod_test): Add epsilons.
	(exp2_test): Use right function for existence test.

1997-06-07 09:20  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/powerpc/Dist: Add fenv_const.c.
	* sysdeps/unix/sysv/linux/Dist: Add net/if_slip.h.
	* sysdeps/unix/sysv/linux/powerpc/Dist: Add init-first.h and
	syscall.h.
	* sysdeps/unix/sysv/linux/sparc/Dist: Add init-first.h.
	* string/Makefile (distribute): Add tst-svc.expect.
	* nis/Makefile (distribute): Add nis_intern.h and Banner.
	* elf/Makefile (distribute): Add dl-hash.h.
	* Rules (subdir_echo-distinfo): Add headers from $(distribute).

	* login/Makefile (others): Add utmpdump.
	* sysdeps/unix/sysv/linux/Makefile (sysdep_headers): Add
	net/if_slip.h.

	* manual/Makefile (dir-add.texi): Also look in indirectly included
	files.

1997-06-16 23:15  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/unix/sysv/linux/configure.in: Remove commands to
	generate stdio_lim.h.
	* sysdeps/unix/sysv/linux/mk-stdiolim.c: Remove.
	* sysdeps/unix/sysv/linux/Makefile: Add rules to generate
	stdio_lim.h here.
	(common-generated): Add generated files.
	(inhibit-stdio_lim): Define.
	* sysdeps/posix/Makefile [$(inhibit-stdio_lim)=yes]: Disable rules
	to generate stdio_lim.h.

	* sysdeps/unix/sysv/linux/Makefile: Suppress inclusion of
	dependecy files if no_deps is set.
	($(objpfx)syscall-%.d): Add header file as target to dependency
	generation.

1997-06-14 19:19  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/unix/sysv/linux/arm/Dist: New file.

1997-06-14 17:59  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* extra-lib.mk (others): Depend on versioned shared library, not
	the unversioned one.
	* Makerules (build-shlib): Don't make the version link here.
	($(common-objpfx)libc.so$(libc.so-version)): New rule for libc
	version link.

1997-06-16 03:07  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/libm-ieee754/k_standard.c: Undo change of Tue Aug 6
	01:13:56 1996.

	* argp/argp-help.c (argp_args_usage): Supply correct argp to
	filter_doc.
	* argp/argp-help.c (hol_add_cluster): Initialize CL->depth.
	* argp/argp-help.c (_help): Supply STATE to argp_args_usage.
	* argp/argp.h (ARGP_KEY_HELP_ARGS_DOC): New macro.
	* argp/argp-fmtstream.c: Add casts to prevent warnings.
	* argp/argp.h (OPTION_NO_USAGE): New macro.
	* argp/argp-help.c (usage_long_opt, usage_argful_short_opt,
	* argp/argp-fmtstream.c (__argp_fmtstream_update): Account for case
	* argp/argp-help.c <stddef.h>: New include.
	* argp/argp.h (argp_state_help, __argp_state_help, argp_usage,
	* argp/argp.h (argp_program_bug_address): Make const.
	* argp/argp-parse.c (argp_default_parser): Set STATE->name for OPT_PROGNAME.
	* argp/argp-help.c (__argp_error, __argp_failure, __argp_state_help):
	* argp/argp-parse.c (parser_init): Set PARSER->state.flags.
Diffstat (limited to 'argp')
-rw-r--r--argp/argp-parse.c126
-rw-r--r--argp/argp.h11
2 files changed, 100 insertions, 37 deletions
diff --git a/argp/argp-parse.c b/argp/argp-parse.c
index edc5516851..018a97807e 100644
--- a/argp/argp-parse.c
+++ b/argp/argp-parse.c
@@ -38,6 +38,7 @@
 # define _(msgid)       (msgid)
 # define gettext(msgid) (msgid)
 #endif
+#define N_(msgid) (msgid)
 #endif
 
 #if _LIBC - 0
@@ -84,11 +85,11 @@ volatile int _argp_hang = 0;
 
 static const struct argp_option argp_default_options[] =
 {
-  {"help",	  '?',    	0, 0,  "Give this help list", -1},
-  {"usage",	  OPT_USAGE,	0, 0,  "Give a short usage message"},
-  {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, "Set the program name"},
+  {"help",	  '?',    	0, 0,  N_("Give this help list"), -1},
+  {"usage",	  OPT_USAGE,	0, 0,  N_("Give a short usage message")},
+  {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")},
   {"HANG",	  OPT_HANG,    "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
-     "Hang for SECS seconds (default 3600)"},
+     N_("Hang for SECS seconds (default 3600)")},
   {0, 0}
 };
 
@@ -145,7 +146,7 @@ static const struct argp argp_default_argp =
 
 static const struct argp_option argp_version_options[] =
 {
-  {"version",	  'V',    	0, 0,  "Print program version", -1},
+  {"version",	  'V',    	0, 0,  N_("Print program version"), -1},
   {0, 0}
 };
 
@@ -160,7 +161,7 @@ argp_version_parser (int key, char *arg, struct argp_state *state)
       else if (argp_program_version)
 	fprintf (state->out_stream, "%s\n", argp_program_version);
       else
-	__argp_error (state, _("No version known!?"));
+	__argp_error (state, _("(PROGRAM ERROR) No version known!?"));
       if (! (state->flags & ARGP_NO_EXIT))
 	exit (0);
       break;
@@ -637,8 +638,8 @@ parser_finalize (struct parser *parser,
 	err = EBADKEY;
       }
 
-  /* Okay, we're all done, with either an error or success.  We only call the
-     parsers once more, to indicate which one.  */
+  /* Okay, we're all done, with either an error or success; call the parsers
+     to indicate which one.  */
 
   if (err)
     {
@@ -654,7 +655,7 @@ parser_finalize (struct parser *parser,
 	group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);
     }
   else
-    /* Do final cleanup, including propagating back values from parsers.  */
+    /* Notify parsers of success, and propagate back values from parsers.  */
     {
       /* We pass over the groups in reverse order so that child groups are
 	 given a chance to do there processing before passing back a value to
@@ -667,6 +668,10 @@ parser_finalize (struct parser *parser,
 	err = 0;		/* Some parser didn't understand.  */
     }
 
+  /* Call parsers once more, to do any final cleanup.  Errors are ignored.  */
+  for (group = parser->egroup - 1; group >= parser->groups; group--)
+    group_parse (group, &parser->state, ARGP_KEY_FINI, 0);
+
   if (err == EBADKEY)
     err = EINVAL;
 
@@ -676,28 +681,55 @@ parser_finalize (struct parser *parser,
 }
 
 /* Call the user parsers to parse the non-option argument VAL, at the current
-   position, returning any error.  */
+   position, returning any error.  The state NEXT pointer is assumed to have
+   been adjusted (by getopt) to point after this argument; this function will
+   adjust it correctly to reflect however many args actually end up being
+   consumed.  */
 static error_t
 parser_parse_arg (struct parser *parser, char *val)
 {
-  int index = parser->state.next;
+  /* Save the starting value of NEXT, first adjusting it so that the arg
+     we're parsing is again the front of the arg vector.  */
+  int index = --parser->state.next;
   error_t err = EBADKEY;
   struct group *group;
+  int key = 0;			/* Which of ARGP_KEY_ARG[S] we used.  */
 
+  /* Try to parse the argument in each parser.  */
   for (group = parser->groups
        ; group < parser->egroup && err == EBADKEY
        ; group++)
-    err = group_parse (group, &parser->state, ARGP_KEY_ARG, val);
-
-  if (!err)
-    if (parser->state.next >= index)
-      /* Remember that we successfully processed a non-option
-	 argument -- but only if the user hasn't gotten tricky and set
-	 the clock back.  */
-      (--group)->args_processed++;
-    else
-      /* The user wants to reparse some args, give getopt another try.  */
-      parser->try_getopt = 1;
+    {
+      parser->state.next++;	/* For ARGP_KEY_ARG, consume the arg.  */
+      key = ARGP_KEY_ARG;
+      err = group_parse (group, &parser->state, key, val);
+
+      if (err == EBADKEY)
+	/* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */
+	{
+	  parser->state.next--;	/* For ARGP_KEY_ARGS, put back the arg.  */
+	  key = ARGP_KEY_ARGS;
+	  err = group_parse (group, &parser->state, key, 0);
+	}
+    }
+
+  if (! err)
+    {
+      if (key == ARGP_KEY_ARGS)
+	/* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
+	   changed by the user, *all* arguments should be considered
+	   consumed.  */
+	parser->state.next = parser->state.argc;
+
+      if (parser->state.next > index)
+	/* Remember that we successfully processed a non-option
+	   argument -- but only if the user hasn't gotten tricky and set
+	   the clock back.  */
+	(--group)->args_processed += (parser->state.next - index);
+      else
+	/* The user wants to reparse some args, give getopt another try.  */
+	parser->try_getopt = 1;
+    }
 
   return err;
 }
@@ -710,6 +742,7 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
   /* The group key encoded in the high bits; 0 for short opts or
      group_number + 1 for long opts.  */
   int group_key = opt >> USER_BITS;
+  error_t err = EBADKEY;
 
   if (group_key == 0)
     /* A short option.  By comparing OPT's position in SHORT_OPTS to the
@@ -722,16 +755,39 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
       if (short_index)
 	for (group = parser->groups; group < parser->egroup; group++)
 	  if (group->short_end > short_index)
-	    return group_parse (group, &parser->state, opt, optarg);
-
-      return EBADKEY;		/* until otherwise asserted */
+	    {
+	      err = group_parse (group, &parser->state, opt, optarg);
+	      break;
+	    }
     }
   else
     /* A long option.  We use shifts instead of masking for extracting
        the user value in order to preserve the sign.  */
-    return
+    err =
       group_parse (&parser->groups[group_key - 1], &parser->state,
 		   (opt << GROUP_BITS) >> GROUP_BITS, optarg);
+
+  if (err == EBADKEY)
+    /* At least currently, an option not recognized is an error in the
+       parser, because we pre-compute which parser is supposed to deal
+       with each option.  */
+    {
+      static const char bad_key_err[] =
+	N_("(PROGRAM ERROR) Option should have been recognized!?");
+      if (group_key == 0)
+	__argp_error (&parser->state, "-%c: %s", opt, _(bad_key_err));
+      else
+	{
+	  struct option *long_opt = parser->long_opts;
+	  while (long_opt->val != opt && long_opt->name)
+	    long_opt++;
+	  __argp_error (&parser->state, "--%s: %s",
+			long_opt->name ? long_opt->name : "???",
+			_(bad_key_err));
+	}
+    }	
+
+  return err;
 }
 
 /* Parse the next argument in PARSER (as indicated by PARSER->state.next).
@@ -800,20 +856,20 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey)
 	return EBADKEY;
       }
     else
-      /* A non-option arg.  */
-      err =
-	parser_parse_arg (parser, parser->state.argv[parser->state.next++]);
-  else if (opt == KEY_ARG)
+      /* A non-option arg; simulate what getopt might have done.  */
+      {
+	opt = KEY_ARG;
+	optarg = parser->state.argv[parser->state.next++];
+      }
+
+  if (opt == KEY_ARG)
     /* A non-option argument; try each parser in turn.  */
     err = parser_parse_arg (parser, optarg);
   else
     err = parser_parse_opt (parser, opt, optarg);
-
+		      
   if (err == EBADKEY)
-    {
-      *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
-      parser->state.next--;	/* Put back the unused argument.  */
-    }
+    *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
 
   return err;
 }
diff --git a/argp/argp.h b/argp/argp.h
index 61ed8351e6..2305590a5d 100644
--- a/argp/argp.h
+++ b/argp/argp.h
@@ -160,6 +160,12 @@ typedef error_t (*argp_parser_t)(int key, char *arg, struct argp_state *state);
    actually modify the argument (perhaps into an option), and have it
    processed again.  */
 #define ARGP_KEY_ARG		0
+/* There are remaining arguments not parsed by any parser, which may be found
+   starting at (STATE->argv + STATE->next).  If success is returned, but
+   STATE->next left untouched, it's assumed that all arguments were consume,
+   otherwise, the parser should adjust STATE->next to reflect any arguments
+   consumed.  */
+#define ARGP_KEY_ARGS		0x1000006
 /* There are no more command line arguments at all.  */
 #define ARGP_KEY_END		0x1000001
 /* Because it's common to want to do some special processing if there aren't
@@ -172,11 +178,12 @@ typedef error_t (*argp_parser_t)(int key, char *arg, struct argp_state *state);
    element of the CHILD_INPUT field, if any, in the state structure is
    copied to each child's state to be the initial value of the INPUT field.  */
 #define ARGP_KEY_INIT		0x1000003
+/* Use after all other keys, including SUCCESS & END.  */
+#define ARGP_KEY_FINI		0x1000007
 /* Passed in when parsing has successfully been completed (even if there are
    still arguments remaining).  */
 #define ARGP_KEY_SUCCESS	0x1000004
-/* Passed in if an error occurs (in which case a call with ARGP_KEY_SUCCESS is
-   never made, so any cleanup must be done here).  */
+/* Passed in if an error occurs.  */
 #define ARGP_KEY_ERROR		0x1000005
 
 /* An argp structure contains a set of options declarations, a function to