WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] Fix xenmon/xentrace compile on Solaris

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Fix xenmon/xentrace compile on Solaris
From: john.levon@xxxxxxx
Date: Tue, 07 Aug 2007 06:14:01 -0700
Delivery-date: Tue, 07 Aug 2007 06:11:35 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User john.levon@xxxxxxx
# Date 1186492378 25200
# Node ID ae465d2d2b2ec9ab31598511fb35814ba6ab5602
# Parent  1ddb3b21f4d8a6b449580ae45cf707f4b43198f9
Fix xenmon/xentrace compile on Solaris

The argp interface is only present in GNU libc. Include a local copy when
compiling on Solaris, and fix a couple of a trivial compile problems.

Signed-off-by: Tariq Magdon-Ismail <tariqmi@xxxxxxx>

diff --git a/tools/Makefile b/tools/Makefile
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -5,6 +5,7 @@ SUBDIRS-y += xenstore
 SUBDIRS-y += xenstore
 SUBDIRS-y += misc
 SUBDIRS-y += examples
+SUBDIRS-$(CONFIG_SunOS) += libargp 
 SUBDIRS-y += xentrace
 SUBDIRS-$(CONFIG_XCUTILS) += xcutils
 SUBDIRS-$(CONFIG_X86) += firmware
diff --git a/tools/libargp/Makefile b/tools/libargp/Makefile
new file mode 100644
--- /dev/null
+++ b/tools/libargp/Makefile
@@ -0,0 +1,28 @@
+XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+ARFLAGS = cru
+DEFINES = -DHAVE_CONFIG_H
+CFLAGS += $(DEFINES) -Wmissing-prototypes \
+       -Wmissing-declarations -Waggregate-return \
+       -Wpointer-arith -Wbad-function-cast -Wnested-externs
+CPPFLAGS += -I.
+OBJECTS = argp-ba.o argp-eexst.o argp-fmtstream.o argp-help.o \
+       argp-parse.o argp-pv.o argp-pvh.o mempcpy.o strndup.o strchrnul.o
+LIB = libargp.a
+
+.PHONY: all
+all: $(LIB) 
+
+.PHONY: install
+install: all
+
+.PHONY: clean
+clean:
+       -rm -f *.o $(LIB) 
+
+$(LIB): $(OBJECTS)     
+       -rm -f $(LIB)
+       $(AR) $(ARFLAGS) $(LIB) $(OBJECTS)
+       $(RANLIB) $(LIB)
+
diff --git a/tools/libargp/argp-ba.c b/tools/libargp/argp-ba.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-ba.c
@@ -0,0 +1,26 @@
+/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
+   Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* If set by the user program, it should point to string that is the
+   bug-reporting address for the program.  It will be printed by argp_help if
+   the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help
+   messages), embedded in a sentence that says something like `Report bugs to
+   ADDR.'.  */
+const char *argp_program_bug_address = 0;
diff --git a/tools/libargp/argp-eexst.c b/tools/libargp/argp-eexst.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-eexst.c
@@ -0,0 +1,32 @@
+/* Default definition for ARGP_ERR_EXIT_STATUS
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sysexits.h>
+
+#include "argp.h"
+
+/* The exit status that argp will use when exiting due to a parsing error.
+   If not defined or set by the user program, this defaults to EX_USAGE from
+   <sysexits.h>.  */
+error_t argp_err_exit_status = EX_USAGE;
diff --git a/tools/libargp/argp-fmtstream.c b/tools/libargp/argp-fmtstream.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-fmtstream.c
@@ -0,0 +1,475 @@
+/* Word-wrapping and line-truncating streams
+   Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This package emulates glibc `line_wrap_stream' semantics for systems that
+   don't have that.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "argp-fmtstream.h"
+#include "argp-namefrob.h"
+
+#ifndef ARGP_FMTSTREAM_USE_LINEWRAP
+
+#ifndef isblank
+#define isblank(ch) ((ch)==' ' || (ch)=='\t')
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <libio/libioP.h>
+# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
+#endif
+
+#define INIT_BUF_SIZE 200
+#define PRINTF_SIZE_GUESS 150
+
+/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
+   written on it with LMARGIN spaces and limits them to RMARGIN columns
+   total.  If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
+   replacing the whitespace before them with a newline and WMARGIN spaces.
+   Otherwise, chars beyond RMARGIN are simply dropped until a newline.
+   Returns NULL if there was an error.  */
+argp_fmtstream_t
+__argp_make_fmtstream (FILE *stream,
+                      size_t lmargin, size_t rmargin, ssize_t wmargin)
+{
+  argp_fmtstream_t fs = malloc (sizeof (struct argp_fmtstream));
+  if (fs)
+    {
+      fs->stream = stream;
+
+      fs->lmargin = lmargin;
+      fs->rmargin = rmargin;
+      fs->wmargin = wmargin;
+      fs->point_col = 0;
+      fs->point_offs = 0;
+
+      fs->buf = malloc (INIT_BUF_SIZE);
+      if (! fs->buf)
+       {
+         free (fs);
+         fs = 0;
+       }
+      else
+       {
+         fs->p = fs->buf;
+         fs->end = fs->buf + INIT_BUF_SIZE;
+       }
+    }
+
+  return fs;
+}
+#ifdef weak_alias
+weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
+#endif
+
+/* Flush FS to its stream, and free it (but don't close the stream).  */
+void
+__argp_fmtstream_free (argp_fmtstream_t fs)
+{
+  __argp_fmtstream_update (fs);
+  if (fs->p > fs->buf)
+    FWRITE_UNLOCKED (fs->buf, 1, fs->p - fs->buf, fs->stream);
+  free (fs->buf);
+  free (fs);
+}
+#ifdef weak_alias
+weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
+#endif
+
+/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
+   end of its buffer.  This code is mostly from glibc stdio/linewrap.c.  */
+void
+__argp_fmtstream_update (argp_fmtstream_t fs)
+{
+  char *buf, *nl;
+  size_t len;
+
+  /* Scan the buffer for newlines.  */
+  buf = fs->buf + fs->point_offs;
+  while (buf < fs->p)
+    {
+      size_t r;
+
+      if (fs->point_col == 0 && fs->lmargin != 0)
+       {
+         /* We are starting a new line.  Print spaces to the left margin.  */
+         const size_t pad = fs->lmargin;
+         if (fs->p + pad < fs->end)
+           {
+             /* We can fit in them in the buffer by moving the
+                buffer text up and filling in the beginning.  */
+             memmove (buf + pad, buf, fs->p - buf);
+             fs->p += pad; /* Compensate for bigger buffer. */
+             memset (buf, ' ', pad); /* Fill in the spaces.  */
+             buf += pad; /* Don't bother searching them.  */
+           }
+         else
+           {
+             /* No buffer space for spaces.  Must flush.  */
+             size_t i;
+             for (i = 0; i < pad; i++)
+               PUTC_UNLOCKED (' ', fs->stream);
+           }
+         fs->point_col = pad;
+       }
+
+      len = fs->p - buf;
+      nl = memchr (buf, '\n', len);
+
+      if (fs->point_col < 0)
+       fs->point_col = 0;
+
+      if (!nl)
+       {
+         /* The buffer ends in a partial line.  */
+
+         if (fs->point_col + len < fs->rmargin)
+           {
+             /* The remaining buffer text is a partial line and fits
+                within the maximum line width.  Advance point for the
+                characters to be written and stop scanning.  */
+             fs->point_col += len;
+             break;
+           }
+         else
+           /* Set the end-of-line pointer for the code below to
+              the end of the buffer.  */
+           nl = fs->p;
+       }
+      else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
+       {
+         /* The buffer contains a full line that fits within the maximum
+            line width.  Reset point and scan the next line.  */
+         fs->point_col = 0;
+         buf = nl + 1;
+         continue;
+       }
+
+      /* This line is too long.  */
+      r = fs->rmargin - 1;
+
+      if (fs->wmargin < 0)
+       {
+         /* Truncate the line by overwriting the excess with the
+            newline and anything after it in the buffer.  */
+         if (nl < fs->p)
+           {
+             memmove (buf + (r - fs->point_col), nl, fs->p - nl);
+             fs->p -= buf + (r - fs->point_col) - nl;
+             /* Reset point for the next line and start scanning it.  */
+             fs->point_col = 0;
+             buf += r + 1; /* Skip full line plus \n. */
+           }
+         else
+           {
+             /* The buffer ends with a partial line that is beyond the
+                maximum line width.  Advance point for the characters
+                written, and discard those past the max from the buffer.  */
+             fs->point_col += len;
+             fs->p -= fs->point_col - r;
+             break;
+           }
+       }
+      else
+       {
+         /* Do word wrap.  Go to the column just past the maximum line
+            width and scan back for the beginning of the word there.
+            Then insert a line break.  */
+
+         char *p, *nextline;
+         int i;
+
+         p = buf + (r + 1 - fs->point_col);
+         while (p >= buf && !isblank (*p))
+           --p;
+         nextline = p + 1;     /* This will begin the next line.  */
+
+         if (nextline > buf)
+           {
+             /* Swallow separating blanks.  */
+             if (p >= buf)
+               do
+                 --p;
+               while (p >= buf && isblank (*p));
+             nl = p + 1;       /* The newline will replace the first blank. */
+           }
+         else
+           {
+             /* A single word that is greater than the maximum line width.
+                Oh well.  Put it on an overlong line by itself.  */
+             p = buf + (r + 1 - fs->point_col);
+             /* Find the end of the long word.  */
+             do
+               ++p;
+             while (p < nl && !isblank (*p));
+             if (p == nl)
+               {
+                 /* It already ends a line.  No fussing required.  */
+                 fs->point_col = 0;
+                 buf = nl + 1;
+                 continue;
+               }
+             /* We will move the newline to replace the first blank.  */
+             nl = p;
+             /* Swallow separating blanks.  */
+             do
+               ++p;
+             while (isblank (*p));
+             /* The next line will start here.  */
+             nextline = p;
+           }
+
+         /* Note: There are a bunch of tests below for
+            NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall
+            at the end of the buffer, and NEXTLINE is in fact empty (and so
+            we need not be careful to maintain its contents).  */
+
+         if (nextline == buf + len + 1
+             ? fs->end - nl < fs->wmargin + 1
+             : nextline - (nl + 1) < fs->wmargin)
+           {
+             /* The margin needs more blanks than we removed.  */
+             if (fs->end - fs->p > fs->wmargin + 1)
+               /* Make some space for them.  */
+               {
+                 size_t mv = fs->p - nextline;
+                 memmove (nl + 1 + fs->wmargin, nextline, mv);
+                 nextline = nl + 1 + fs->wmargin;
+                 len = nextline + mv - buf;
+                 *nl++ = '\n';
+               }
+             else
+               /* Output the first line so we can use the space.  */
+               {
+                 if (nl > fs->buf)
+                   FWRITE_UNLOCKED (fs->buf, 1, nl - fs->buf, fs->stream);
+                 PUTC_UNLOCKED ('\n', fs->stream);
+                 len += buf - fs->buf;
+                 nl = buf = fs->buf;
+               }
+           }
+         else
+           /* We can fit the newline and blanks in before
+              the next word.  */
+           *nl++ = '\n';
+
+         if (nextline - nl >= fs->wmargin
+             || (nextline == buf + len + 1 && fs->end - nextline >= 
fs->wmargin))
+           /* Add blanks up to the wrap margin column.  */
+           for (i = 0; i < fs->wmargin; ++i)
+             *nl++ = ' ';
+         else
+           for (i = 0; i < fs->wmargin; ++i)
+             PUTC_UNLOCKED (' ', fs->stream);
+
+         /* Copy the tail of the original buffer into the current buffer
+            position.  */
+         if (nl < nextline)
+           memmove (nl, nextline, buf + len - nextline);
+         len -= nextline - buf;
+
+         /* Continue the scan on the remaining lines in the buffer.  */
+         buf = nl;
+
+         /* Restore bufp to include all the remaining text.  */
+         fs->p = nl + len;
+
+         /* Reset the counter of what has been output this line.  If wmargin
+            is 0, we want to avoid the lmargin getting added, so we set
+            point_col to a magic value of -1 in that case.  */
+         fs->point_col = fs->wmargin ? fs->wmargin : -1;
+       }
+    }
+
+  /* Remember that we've scanned as far as the end of the buffer.  */
+  fs->point_offs = fs->p - fs->buf;
+}
+
+/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by
+   growing the buffer, or by flushing it.  True is returned iff we succeed. */
+int
+__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
+{
+  if ((size_t) (fs->end - fs->p) < amount)
+    {
+      ssize_t wrote;
+
+      /* Flush FS's buffer.  */
+      __argp_fmtstream_update (fs);
+
+      wrote = FWRITE_UNLOCKED (fs->buf, 1, fs->p - fs->buf, fs->stream);
+      if (wrote == fs->p - fs->buf)
+       {
+         fs->p = fs->buf;
+         fs->point_offs = 0;
+       }
+      else
+       {
+         fs->p -= wrote;
+         fs->point_offs -= wrote;
+         memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
+         return 0;
+       }
+
+      if ((size_t) (fs->end - fs->buf) < amount)
+       /* Gotta grow the buffer.  */
+       {
+         size_t new_size = fs->end - fs->buf + amount;
+         char *new_buf = realloc (fs->buf, new_size);
+
+         if (! new_buf)
+           {
+             __set_errno (ENOMEM);
+             return 0;
+           }
+
+         fs->buf = new_buf;
+         fs->end = new_buf + new_size;
+         fs->p = fs->buf;
+       }
+    }
+
+  return 1;
+}
+
+ssize_t
+__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
+{
+  size_t out;
+  size_t avail;
+  size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */
+
+  do
+    {
+      va_list args;
+
+      if (! __argp_fmtstream_ensure (fs, size_guess))
+       return -1;
+
+      va_start (args, fmt);
+      avail = fs->end - fs->p;
+      out = __vsnprintf (fs->p, avail, fmt, args);
+      va_end (args);
+      if (out >= avail)
+       size_guess = out + 1;
+    }
+  while (out >= avail);
+
+  fs->p += out;
+
+  return out;
+}
+#ifdef weak_alias
+weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
+#endif
+
+/* Duplicate the inline definitions in argp-fmtstream.h, for compilers
+ * that don't do inlining. */
+size_t
+__argp_fmtstream_write (argp_fmtstream_t __fs,
+                       __const char *__str, size_t __len)
+{
+  if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
+    {
+      memcpy (__fs->p, __str, __len);
+      __fs->p += __len;
+      return __len;
+    }
+  else
+    return 0;
+}
+
+int
+__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
+{
+  size_t __len = strlen (__str);
+  if (__len)
+    {
+      size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
+      return __wrote == __len ? 0 : -1;
+    }
+  else
+    return 0;
+}
+
+int
+__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
+{
+  if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
+    return *__fs->p++ = __ch;
+  else
+    return EOF;
+}
+
+/* Set __FS's left margin to __LMARGIN and return the old value.  */
+size_t
+__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->lmargin;
+  __fs->lmargin = __lmargin;
+  return __old;
+}
+
+/* Set __FS's right margin to __RMARGIN and return the old value.  */
+size_t
+__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->rmargin;
+  __fs->rmargin = __rmargin;
+  return __old;
+}
+
+/* Set FS's wrap margin to __WMARGIN and return the old value.  */
+size_t
+__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->wmargin;
+  __fs->wmargin = __wmargin;
+  return __old;
+}
+
+/* Return the column number of the current output point in __FS.  */
+size_t
+__argp_fmtstream_point (argp_fmtstream_t __fs)
+{
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  return __fs->point_col >= 0 ? __fs->point_col : 0;
+}
+
+#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */
diff --git a/tools/libargp/argp-fmtstream.h b/tools/libargp/argp-fmtstream.h
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-fmtstream.h
@@ -0,0 +1,311 @@
+/* Word-wrapping and line-truncating streams.
+   Copyright (C) 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This package emulates glibc `line_wrap_stream' semantics for systems that
+   don't have that.  If the system does have it, it is just a wrapper for
+   that.  This header file is only used internally while compiling argp, and
+   shouldn't be installed.  */
+
+#ifndef _ARGP_FMTSTREAM_H
+#define _ARGP_FMTSTREAM_H
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#if _LIBC || (defined (HAVE_FLOCKFILE) && defined(HAVE_PUTC_UNLOCKED) \
+     && defined (HAVE_FPUTS_UNLOCKED) && defined (HAVE_FWRITE_UNLOCKED) )
+/* Use locking funxtions */
+# define FLOCKFILE(f) flockfile(f)
+# define FUNLOCKFILE(f) funlockfile(f)
+# define PUTC_UNLOCKED(c, f) putc_unlocked((c), (f))
+# define FPUTS_UNLOCKED(s, f) fputs_unlocked((s), (f))
+# define FWRITE_UNLOCKED(b, s, n, f) fwrite_unlocked((b), (s), (n), (f))
+#else
+/* Disable stdio locking */
+# define FLOCKFILE(f)
+# define FUNLOCKFILE(f)
+# define PUTC_UNLOCKED(c, f) putc((c), (f))
+# define FPUTS_UNLOCKED(s, f) fputs((s), (f))
+# define FWRITE_UNLOCKED(b, s, n, f) fwrite((b), (s), (n), (f))
+#endif /* No thread safe i/o */
+
+#if    (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
+    || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
+/* line_wrap_stream is available, so use that.  */
+#define ARGP_FMTSTREAM_USE_LINEWRAP
+#endif
+
+#ifdef ARGP_FMTSTREAM_USE_LINEWRAP
+/* Just be a simple wrapper for line_wrap_stream; the semantics are
+   *slightly* different, as line_wrap_stream doesn't actually make a new
+   object, it just modifies the given stream (reversibly) to do
+   line-wrapping.  Since we control who uses this code, it doesn't matter.  */
+
+#include <linewrap.h>
+
+typedef FILE *argp_fmtstream_t;
+
+#define argp_make_fmtstream line_wrap_stream
+#define __argp_make_fmtstream line_wrap_stream
+#define argp_fmtstream_free line_unwrap_stream
+#define __argp_fmtstream_free line_unwrap_stream
+
+#define __argp_fmtstream_putc(fs,ch) putc(ch,fs)
+#define argp_fmtstream_putc(fs,ch) putc(ch,fs)
+#define __argp_fmtstream_puts(fs,str) fputs(str,fs)
+#define argp_fmtstream_puts(fs,str) fputs(str,fs)
+#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
+#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
+#define __argp_fmtstream_printf fprintf
+#define argp_fmtstream_printf fprintf
+
+#define __argp_fmtstream_lmargin line_wrap_lmargin
+#define argp_fmtstream_lmargin line_wrap_lmargin
+#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin
+#define argp_fmtstream_set_lmargin line_wrap_set_lmargin
+#define __argp_fmtstream_rmargin line_wrap_rmargin
+#define argp_fmtstream_rmargin line_wrap_rmargin
+#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin
+#define argp_fmtstream_set_rmargin line_wrap_set_rmargin
+#define __argp_fmtstream_wmargin line_wrap_wmargin
+#define argp_fmtstream_wmargin line_wrap_wmargin
+#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin
+#define argp_fmtstream_set_wmargin line_wrap_set_wmargin
+#define __argp_fmtstream_point line_wrap_point
+#define argp_fmtstream_point line_wrap_point
+
+#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
+/* Guess we have to define our own version.  */
+
+#ifndef __const
+#define __const const
+#endif
+
+
+struct argp_fmtstream
+{
+  FILE *stream;                        /* The stream we're outputting to.  */
+
+  size_t lmargin, rmargin;     /* Left and right margins.  */
+  ssize_t wmargin;             /* Margin to wrap to, or -1 to truncate.  */
+
+  /* Point in buffer to which we've processed for wrapping, but not output.  */
+  size_t point_offs;
+  /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin.  */
+  ssize_t point_col;
+
+  char *buf;                   /* Output buffer.  */
+  char *p;                     /* Current end of text in BUF. */
+  char *end;                   /* Absolute end of BUF.  */
+};
+
+typedef struct argp_fmtstream *argp_fmtstream_t;
+
+/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
+   written on it with LMARGIN spaces and limits them to RMARGIN columns
+   total.  If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
+   replacing the whitespace before them with a newline and WMARGIN spaces.
+   Otherwise, chars beyond RMARGIN are simply dropped until a newline.
+   Returns NULL if there was an error.  */
+extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream,
+                                              size_t __lmargin,
+                                              size_t __rmargin,
+                                              ssize_t __wmargin);
+extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream,
+                                            size_t __lmargin,
+                                            size_t __rmargin,
+                                            ssize_t __wmargin);
+
+/* Flush __FS to its stream, and free it (but don't close the stream).  */
+extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
+extern void argp_fmtstream_free (argp_fmtstream_t __fs);
+
+extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
+                                      __const char *__fmt, ...)
+     PRINTF_STYLE(2,3);
+extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
+                                     __const char *__fmt, ...)
+     PRINTF_STYLE(2,3);
+
+extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
+extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
+
+extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
+extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
+
+extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
+                                     __const char *__str, size_t __len);
+extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
+                                   __const char *__str, size_t __len);
+
+/* Access macros for various bits of state.  */
+#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
+#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin)
+#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin)
+#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
+#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
+#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
+
+/* Set __FS's left margin to LMARGIN and return the old value.  */
+extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
+                                         size_t __lmargin);
+extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
+                                           size_t __lmargin);
+
+/* Set __FS's right margin to __RMARGIN and return the old value.  */
+extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
+                                         size_t __rmargin);
+extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
+                                           size_t __rmargin);
+
+/* Set __FS's wrap margin to __WMARGIN and return the old value.  */
+extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
+                                         size_t __wmargin);
+extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
+                                           size_t __wmargin);
+
+/* Return the column number of the current output point in __FS.  */
+extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
+extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs);
+
+/* Internal routines.  */
+extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
+extern void __argp_fmtstream_update (argp_fmtstream_t __fs);
+extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
+extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
+
+#ifdef __OPTIMIZE__
+/* Inline versions of above routines.  */
+
+#if !_LIBC
+#define __argp_fmtstream_putc argp_fmtstream_putc
+#define __argp_fmtstream_puts argp_fmtstream_puts
+#define __argp_fmtstream_write argp_fmtstream_write
+#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
+#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
+#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
+#define __argp_fmtstream_point argp_fmtstream_point
+#define __argp_fmtstream_update _argp_fmtstream_update
+#define __argp_fmtstream_ensure _argp_fmtstream_ensure
+#endif
+
+#ifndef ARGP_FS_EI
+#define ARGP_FS_EI extern inline
+#endif
+
+ARGP_FS_EI size_t
+__argp_fmtstream_write (argp_fmtstream_t __fs,
+                       __const char *__str, size_t __len)
+{
+  if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
+    {
+      memcpy (__fs->p, __str, __len);
+      __fs->p += __len;
+      return __len;
+    }
+  else
+    return 0;
+}
+
+ARGP_FS_EI int
+__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
+{
+  size_t __len = strlen (__str);
+  if (__len)
+    {
+      size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
+      return __wrote == __len ? 0 : -1;
+    }
+  else
+    return 0;
+}
+
+ARGP_FS_EI int
+__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
+{
+  if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
+    return *__fs->p++ = __ch;
+  else
+    return EOF;
+}
+
+/* Set __FS's left margin to __LMARGIN and return the old value.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->lmargin;
+  __fs->lmargin = __lmargin;
+  return __old;
+}
+
+/* Set __FS's right margin to __RMARGIN and return the old value.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->rmargin;
+  __fs->rmargin = __rmargin;
+  return __old;
+}
+
+/* Set FS's wrap margin to __WMARGIN and return the old value.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->wmargin;
+  __fs->wmargin = __wmargin;
+  return __old;
+}
+
+/* Return the column number of the current output point in __FS.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_point (argp_fmtstream_t __fs)
+{
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  return __fs->point_col >= 0 ? __fs->point_col : 0;
+}
+
+#if !_LIBC
+#undef __argp_fmtstream_putc
+#undef __argp_fmtstream_puts
+#undef __argp_fmtstream_write
+#undef __argp_fmtstream_set_lmargin
+#undef __argp_fmtstream_set_rmargin
+#undef __argp_fmtstream_set_wmargin
+#undef __argp_fmtstream_point
+#undef __argp_fmtstream_update
+#undef __argp_fmtstream_ensure
+#endif
+
+#endif /* __OPTIMIZE__ */
+
+#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
+
+#endif /* argp-fmtstream.h */
diff --git a/tools/libargp/argp-help.c b/tools/libargp/argp-help.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-help.c
@@ -0,0 +1,1855 @@
+/* Hierarchial argument parsing help output
+   Copyright (C) 1995,96,97,98,99,2000, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE   1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+/* Does any system still need malloc.h? If so, we'd need a configure
+   test. */
+
+#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) __dcgettext (domain, msgid, LC_MESSAGES)
+#  endif
+# else
+#  define dgettext(domain, msgid) (msgid)
+# endif
+#endif
+
+#include "argp.h"
+#include "argp-fmtstream.h"
+#include "argp-namefrob.h"
+
+
+#ifndef _LIBC
+# ifndef __strchrnul
+#  define __strchrnul strchrnul
+# endif
+# ifndef __mempcpy
+#  define __mempcpy mempcpy
+# endif
+/* We need to use a different name, as __strndup is likely a macro. */
+# define STRNDUP strndup
+# if HAVE_STRERROR
+#  define STRERROR strerror
+# else
+#  define STRERROR(x) (sys_errlist[x])
+# endif
+#else /* _LIBC */
+# define FLOCKFILE __flockfile
+# define FUNLOCKFILE __funlockfile
+# define STRNDUP __strndup
+# define STRERROR strerror
+#endif
+
+#if !_LIBC
+# if !HAVE_STRNDUP
+char *strndup (const char *s, size_t size);
+# endif /* !HAVE_STRNDUP */
+
+# if !HAVE_MEMPCPY
+void *mempcpy (void *to, const void *from, size_t size);
+# endif /* !HAVE_MEMPCPY */
+
+# if !HAVE_STRCHRNUL
+char *strchrnul(const char *s, int c);
+# endif /* !HAVE_STRCHRNUL */
+
+#endif /* !_LIBC */
+
+
+/* User-selectable (using an environment variable) formatting parameters.
+
+   These may be specified in an environment variable called `ARGP_HELP_FMT',
+   with a contents like:  VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2
+   Where VALn must be a positive integer.  The list of variables is in the
+   UPARAM_NAMES vector, below.  */
+
+/* Default parameters.  */
+#define DUP_ARGS      0                /* True if option argument can be 
duplicated. */
+#define DUP_ARGS_NOTE 1                /* True to print a note about duplicate 
args. */
+#define SHORT_OPT_COL 2                /* column in which short options start 
*/
+#define LONG_OPT_COL  6                /* column in which long options start */
+#define DOC_OPT_COL   2                /* column in which doc options start */
+#define OPT_DOC_COL  29                /* column in which option text starts */
+#define HEADER_COL    1                /* column in which group headers are 
printed */
+#define USAGE_INDENT 12                /* indentation of wrapped usage lines */
+#define RMARGIN      79                /* right margin used for wrapping */
+
+/* User-selectable (using an environment variable) formatting parameters.
+   They must all be of type `int' for the parsing code to work.  */
+struct uparams
+{
+  /* If true, arguments for an option are shown with both short and long
+     options, even when a given option has both, e.g. `-x ARG, --longx=ARG'.
+     If false, then if an option has both, the argument is only shown with
+     the long one, e.g., `-x, --longx=ARG', and a message indicating that
+     this really means both is printed below the options.  */
+  int dup_args;
+
+  /* This is true if when DUP_ARGS is false, and some duplicate arguments have
+     been suppressed, an explanatory message should be printed.  */
+  int dup_args_note;
+
+  /* Various output columns.  */
+  int short_opt_col;
+  int long_opt_col;
+  int doc_opt_col;
+  int opt_doc_col;
+  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
+};
+
+/* 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.  */
+};
+
+/* 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, 0, 0 }
+};
+
+/* Read user options from the environment, and fill in UPARAMS appropiately.  
*/
+static void
+fill_in_uparams (const struct argp_state *state)
+{
+  /* FIXME: Can we get away without an explicit cast? */
+  const unsigned char *var = (unsigned char *) getenv ("ARGP_HELP_FMT");
+
+#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
+
+  if (var)
+    /* Parse var. */
+    while (*var)
+      {
+       SKIPWS (var);
+
+       if (isalpha (*var))
+         {
+           size_t var_len;
+           const struct uparam_name *un;
+           int unspec = 0, val = 0;
+           const unsigned char *arg = var;
+
+           while (isalnum (*arg) || *arg == '-' || *arg == '_')
+             arg++;
+           var_len = arg - var;
+
+           SKIPWS (arg);
+
+           if (*arg == '\0' || *arg == ',')
+             unspec = 1;
+           else if (*arg == '=')
+             {
+               arg++;
+               SKIPWS (arg);
+             }
+
+           if (unspec)
+             {
+               if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
+                 {
+                   val = 0;
+                   var += 3;
+                   var_len -= 3;
+                 }
+               else
+                 val = 1;
+             }
+           else if (isdigit (*arg))
+             {
+               val = atoi (arg);
+               while (isdigit (*arg))
+                 arg++;
+               SKIPWS (arg);
+             }
+
+           for (un = uparam_names; un->name; un++)
+             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, "\
+%.*s: ARGP_HELP_FMT parameter requires a value"),
+                                   (int) var_len, var);
+                 else
+                   *(int *)((char *)&uparams + un->uparams_offs) = val;
+                 break;
+               }
+           if (! un->name)
+             __argp_failure (state, 0, 0,
+                             dgettext (state->root_argp->argp_domain, "\
+%.*s: Unknown ARGP_HELP_FMT parameter"),
+                             (int) var_len, var);
+
+           var = arg;
+           if (*var == ',')
+             var++;
+         }
+       else if (*var)
+         {
+           __argp_failure (state, 0, 0,
+                           dgettext (state->root_argp->argp_domain,
+                                     "Garbage in ARGP_HELP_FMT: %s"), var);
+           break;
+         }
+      }
+}
+
+/* Returns true if OPT hasn't been marked invisible.  Visibility only affects
+   whether OPT is displayed or used in sorting, not option shadowing.  */
+#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
+
+/* Returns true if OPT is an alias for an earlier option.  */
+#define oalias(opt) ((opt)->flags & OPTION_ALIAS)
+
+/* Returns true if OPT is an documentation-only entry.  */
+#define odoc(opt) ((opt)->flags & OPTION_DOC)
+
+/* Returns true if OPT is the end-of-list marker for a list of options.  */
+#define oend(opt) __option_is_end (opt)
+
+/* Returns true if OPT has a short option.  */
+#define oshort(opt) __option_is_short (opt)
+
+/*
+   The help format for a particular option is like:
+
+     -xARG, -yARG, --long1=ARG, --long2=ARG        Documentation...
+
+   Where ARG will be omitted if there's no argument, for this option, or
+   will be surrounded by "[" and "]" appropiately if the argument is
+   optional.  The documentation string is word-wrapped appropiately, and if
+   the list of options is long enough, it will be started on a separate line.
+   If there are no short options for a given option, the first long option is
+   indented slighly in a way that's supposed to make most long options appear
+   to be in a separate column.
+
+   For example, the following output (from ps):
+
+     -p PID, --pid=PID          List the process PID
+        --pgrp=PGRP            List processes in the process group PGRP
+     -P, -x, --no-parent        Include processes without parents
+     -Q, --all-fields           Don't elide unusable fields (normally if 
there's
+                               some reason ps can't print a field for any
+                               process, it's removed from the output entirely)
+     -r, --reverse, --gratuitously-long-reverse-option
+                               Reverse the order of any sort
+        --session[=SID]        Add the processes from the session SID (which
+                               defaults to the sid of the current process)
+
+    Here are some more options:
+     -f ZOT, --foonly=ZOT       Glork a foonly
+     -z, --zaza                 Snit a zar
+
+     -?, --help                 Give this help list
+        --usage                Give a short usage message
+     -V, --version              Print program version
+
+   The struct argp_option array for the above could look like:
+
+   {
+     {"pid",       'p',      "PID",  0, "List the process PID"},
+     {"pgrp",      OPT_PGRP, "PGRP", 0, "List processes in the process group 
PGRP"},
+     {"no-parent", 'P',              0,     0, "Include processes without 
parents"},
+     {0,           'x',       0,     OPTION_ALIAS},
+     {"all-fields",'Q',       0,     0, "Don't elide unusable fields (normally"
+                                        " if there's some reason ps can't"
+                                       " print a field for any process, it's"
+                                        " removed from the output entirely)" },
+     {"reverse",   'r',       0,     0, "Reverse the order of any sort"},
+     {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS},
+     {"session",   OPT_SESS,  "SID", OPTION_ARG_OPTIONAL,
+                                        "Add the processes from the session"
+                                       " SID (which defaults to the sid of"
+                                       " the current process)" },
+
+     {0,0,0,0, "Here are some more options:"},
+     {"foonly", 'f', "ZOT", 0, "Glork a foonly"},
+     {"zaza", 'z', 0, 0, "Snit a zar"},
+
+     {0}
+   }
+
+   Note that the last three options are automatically supplied by argp_parse,
+   unless you tell it not to with ARGP_NO_HELP.
+
+*/
+
+/* Returns true if CH occurs between BEG and END.  */
+static int
+find_char (char ch, char *beg, char *end)
+{
+  while (beg < end)
+    if (*beg == ch)
+      return 1;
+    else
+      beg++;
+  return 0;
+}
+
+struct hol_cluster;            /* fwd decl */
+
+struct hol_entry
+{
+  /* First option.  */
+  const struct argp_option *opt;
+  /* Number of options (including aliases).  */
+  unsigned num;
+
+  /* A pointers into the HOL's short_options field, to the first short option
+     letter for this entry.  The order of the characters following this point
+     corresponds to the order of options pointed to by OPT, and there are at
+     most NUM.  A short option recorded in a option following OPT is only
+     valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's
+     probably been shadowed by some other entry).  */
+  char *short_options;
+
+  /* Entries are sorted by their group first, in the order:
+       1, 2, ..., n, 0, -m, ..., -2, -1
+     and then alphabetically within each group.  The default is 0.  */
+  int group;
+
+  /* The cluster of options this entry belongs to, or 0 if none.  */
+  struct hol_cluster *cluster;
+
+  /* The argp from which this option came.  */
+  const struct argp *argp;
+};
+
+/* A cluster of entries to reflect the argp tree structure.  */
+struct hol_cluster
+{
+  /* A descriptive header printed before options in this cluster.  */
+  const char *header;
+
+  /* Used to order clusters within the same group with the same parent,
+     according to the order in which they occurred in the parent argp's child
+     list.  */
+  int index;
+
+  /* How to sort this cluster with respect to options and other clusters at the
+     same depth (clusters always follow options in the same group).  */
+  int group;
+
+  /* The cluster to which this cluster belongs, or 0 if it's at the base
+     level.  */
+  struct hol_cluster *parent;
+
+  /* The argp from which this cluster is (eventually) derived.  */
+  const struct argp *argp;
+
+  /* The distance this cluster is from the root.  */
+  int depth;
+
+  /* Clusters in a given hol are kept in a linked list, to make freeing them
+     possible.  */
+  struct hol_cluster *next;
+};
+
+/* A list of options for help.  */
+struct hol
+{
+  /* An array of hol_entry's.  */
+  struct hol_entry *entries;
+  /* The number of entries in this hol.  If this field is zero, the others
+     are undefined.  */
+  unsigned num_entries;
+
+  /* A string containing all short options in this HOL.  Each entry contains
+     pointers into this string, so the order can't be messed with blindly.  */
+  char *short_options;
+
+  /* Clusters of entries in this hol.  */
+  struct hol_cluster *clusters;
+};
+
+/* Create a struct hol from the options in ARGP.  CLUSTER is the
+   hol_cluster in which these entries occur, or 0, if at the root.  */
+static struct hol *
+make_hol (const struct argp *argp, struct hol_cluster *cluster)
+{
+  char *so;
+  const struct argp_option *o;
+  const struct argp_option *opts = argp->options;
+  struct hol_entry *entry;
+  unsigned num_short_options = 0;
+  struct hol *hol = malloc (sizeof (struct hol));
+
+  assert (hol);
+
+  hol->num_entries = 0;
+  hol->clusters = 0;
+
+  if (opts)
+    {
+      int cur_group = 0;
+
+      /* The first option must not be an alias.  */
+      assert (! oalias (opts));
+
+      /* Calculate the space needed.  */
+      for (o = opts; ! oend (o); o++)
+       {
+         if (! oalias (o))
+           hol->num_entries++;
+         if (oshort (o))
+           num_short_options++;        /* This is an upper bound.  */
+       }
+
+      hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
+      hol->short_options = malloc (num_short_options + 1);
+
+      assert (hol->entries && hol->short_options);
+
+      /* Fill in the entries.  */
+      so = hol->short_options;
+      for (o = opts, entry = hol->entries; ! oend (o); entry++)
+       {
+         entry->opt = o;
+         entry->num = 0;
+         entry->short_options = so;
+         entry->group = cur_group =
+           o->group
+           ? o->group
+           : ((!o->name && !o->key)
+              ? cur_group + 1
+              : cur_group);
+         entry->cluster = cluster;
+         entry->argp = argp;
+
+         do
+           {
+             entry->num++;
+             if (oshort (o) && ! find_char (o->key, hol->short_options, so))
+               /* O has a valid short option which hasn't already been used.*/
+               *so++ = o->key;
+             o++;
+           }
+         while (! oend (o) && oalias (o));
+       }
+      *so = '\0';              /* null terminated so we can find the length */
+    }
+
+  return hol;
+}
+
+/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the
+   associated argp child list entry), INDEX, and PARENT, and return a pointer
+   to it.  ARGP is the argp that this cluster results from.  */
+static struct hol_cluster *
+hol_add_cluster (struct hol *hol, int group, const char *header, int index,
+                struct hol_cluster *parent, const struct argp *argp)
+{
+  struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
+  if (cl)
+    {
+      cl->group = group;
+      cl->header = header;
+
+      cl->index = index;
+      cl->parent = parent;
+      cl->argp = argp;
+      cl->depth = parent ? parent->depth + 1 : 0;
+
+      cl->next = hol->clusters;
+      hol->clusters = cl;
+    }
+  return cl;
+}
+
+/* Free HOL and any resources it uses.  */
+static void
+hol_free (struct hol *hol)
+{
+  struct hol_cluster *cl = hol->clusters;
+
+  while (cl)
+    {
+      struct hol_cluster *next = cl->next;
+      free (cl);
+      cl = next;
+    }
+
+  if (hol->num_entries > 0)
+    {
+      free (hol->entries);
+      free (hol->short_options);
+    }
+
+  free (hol);
+}
+
+static inline int
+hol_entry_short_iterate (const struct hol_entry *entry,
+                        int (*func)(const struct argp_option *opt,
+                                    const struct argp_option *real,
+                                    const char *domain, void *cookie),
+                        const char *domain, void *cookie)
+{
+  unsigned nopts;
+  int val = 0;
+  const struct argp_option *opt, *real = entry->opt;
+  char *so = entry->short_options;
+
+  for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
+    if (oshort (opt) && *so == opt->key)
+      {
+       if (!oalias (opt))
+         real = opt;
+       if (ovisible (opt))
+         val = (*func)(opt, real, domain, cookie);
+       so++;
+      }
+
+  return val;
+}
+
+static inline int
+hol_entry_long_iterate (const struct hol_entry *entry,
+                       int (*func)(const struct argp_option *opt,
+                                   const struct argp_option *real,
+                                   const char *domain, void *cookie),
+                       const char *domain, void *cookie)
+{
+  unsigned nopts;
+  int val = 0;
+  const struct argp_option *opt, *real = entry->opt;
+
+  for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
+    if (opt->name)
+      {
+       if (!oalias (opt))
+         real = opt;
+       if (ovisible (opt))
+         val = (*func)(opt, real, domain, cookie);
+      }
+
+  return val;
+}
+
+/* Iterator that returns true for the first short option.  */
+static inline int
+until_short (const struct argp_option *opt, const struct argp_option *real 
UNUSED,
+            const char *domain UNUSED, void *cookie UNUSED)
+{
+  return oshort (opt) ? opt->key : 0;
+}
+
+/* Returns the first valid short option in ENTRY, or 0 if there is none.  */
+static char
+hol_entry_first_short (const struct hol_entry *entry)
+{
+  return hol_entry_short_iterate (entry, until_short,
+                                 entry->argp->argp_domain, 0);
+}
+
+/* Returns the first valid long option in ENTRY, or 0 if there is none.  */
+static const char *
+hol_entry_first_long (const struct hol_entry *entry)
+{
+  const struct argp_option *opt;
+  unsigned num;
+  for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
+    if (opt->name && ovisible (opt))
+      return opt->name;
+  return 0;
+}
+
+/* Returns the entry in HOL with the long option name NAME, or 0 if there is
+   none.  */
+static struct hol_entry *
+hol_find_entry (struct hol *hol, const char *name)
+{
+  struct hol_entry *entry = hol->entries;
+  unsigned num_entries = hol->num_entries;
+
+  while (num_entries-- > 0)
+    {
+      const struct argp_option *opt = entry->opt;
+      unsigned num_opts = entry->num;
+
+      while (num_opts-- > 0)
+       if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
+         return entry;
+       else
+         opt++;
+
+      entry++;
+    }
+
+  return 0;
+}
+
+/* If an entry with the long option NAME occurs in HOL, set it's special
+   sort position to GROUP.  */
+static void
+hol_set_group (struct hol *hol, const char *name, int group)
+{
+  struct hol_entry *entry = hol_find_entry (hol, name);
+  if (entry)
+    entry->group = group;
+}
+
+/* Order by group:  0, 1, 2, ..., n, -m, ..., -2, -1.
+   EQ is what to return if GROUP1 and GROUP2 are the same.  */
+static int
+group_cmp (int group1, int group2, int eq)
+{
+  if (group1 == group2)
+    return eq;
+  else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
+    return group1 - group2;
+  else
+    return group2 - group1;
+}
+
+/* Compare clusters CL1 & CL2 by the order that they should appear in
+   output.  */
+static int
+hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
+{
+  /* If one cluster is deeper than the other, use its ancestor at the same
+     level, so that finding the common ancestor is straightforward.  */
+  while (cl1->depth < cl2->depth)
+    cl1 = cl1->parent;
+  while (cl2->depth < cl1->depth)
+    cl2 = cl2->parent;
+
+  /* Now reduce both clusters to their ancestors at the point where both have
+     a common parent; these can be directly compared.  */
+  while (cl1->parent != cl2->parent)
+    cl1 = cl1->parent, cl2 = cl2->parent;
+
+  return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index);
+}
+
+/* Return the ancestor of CL that's just below the root (i.e., has a parent
+   of 0).  */
+static struct hol_cluster *
+hol_cluster_base (struct hol_cluster *cl)
+{
+  while (cl->parent)
+    cl = cl->parent;
+  return cl;
+}
+
+/* Return true if CL1 is a child of CL2.  */
+static int
+hol_cluster_is_child (const struct hol_cluster *cl1,
+                     const struct hol_cluster *cl2)
+{
+  while (cl1 && cl1 != cl2)
+    cl1 = cl1->parent;
+  return cl1 == cl2;
+}
+
+/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail
+   that should be used for comparisons, and returns true iff it should be
+   treated as a non-option.  */
+
+/* FIXME: Can we use unsigned char * for the argument? */
+static int
+canon_doc_option (const char **name)
+{
+  int non_opt;
+  /* Skip initial whitespace.  */
+  while (isspace ( (unsigned char) **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 ( (unsigned char) **name))
+    (*name)++;
+  return non_opt;
+}
+
+/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
+   listing.  */
+static int
+hol_entry_cmp (const struct hol_entry *entry1,
+              const struct hol_entry *entry2)
+{
+  /* The group numbers by which the entries should be ordered; if either is
+     in a cluster, then this is just the group within the cluster.  */
+  int group1 = entry1->group, group2 = entry2->group;
+
+  if (entry1->cluster != entry2->cluster)
+    {
+      /* The entries are not within the same cluster, so we can't compare them
+        directly, we have to use the appropiate clustering level too.  */
+      if (! entry1->cluster)
+       /* ENTRY1 is at the `base level', not in a cluster, so we have to
+          compare it's group number with that of the base cluster in which
+          ENTRY2 resides.  Note that if they're in the same group, the
+          clustered option always comes laster.  */
+       return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, 
-1);
+      else if (! entry2->cluster)
+       /* Likewise, but ENTRY2's not in a cluster.  */
+       return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
+      else
+       /* Both entries are in clusters, we can just compare the clusters.  */
+       return hol_cluster_cmp (entry1->cluster, entry2->cluster);
+    }
+  else if (group1 == group2)
+    /* The entries are both in the same cluster and group, so compare them
+       alphabetically.  */
+    {
+      int short1 = hol_entry_first_short (entry1);
+      int short2 = hol_entry_first_short (entry2);
+      int doc1 = odoc (entry1->opt);
+      int doc2 = odoc (entry2->opt);
+      /* FIXME: Can we use unsigned char * instead? */
+      const char *long1 = hol_entry_first_long (entry1);
+      const char *long2 = hol_entry_first_long (entry2);
+
+      if (doc1)
+       doc1 = canon_doc_option (&long1);
+      if (doc2)
+       doc2 = canon_doc_option (&long2);
+
+      if (doc1 != doc2)
+       /* `documentation' options always follow normal options (or
+          documentation options that *look* like normal options).  */
+       return doc1 - doc2;
+      else if (!short1 && !short2 && long1 && long2)
+       /* Only long options.  */
+       return __strcasecmp (long1, long2);
+      else
+       /* Compare short/short, long/short, short/long, using the first
+          character of long options.  Entries without *any* valid
+          options (such as options with OPTION_HIDDEN set) will be put
+          first, but as they're not displayed, it doesn't matter where
+          they are.  */
+       {
+         unsigned char first1 = short1 ? short1 : long1 ? *long1 : 0;
+         unsigned char first2 = short2 ? short2 : long2 ? *long2 : 0;
+#ifdef _tolower
+         int lower_cmp = _tolower (first1) - _tolower (first2);
+#else
+         int lower_cmp = tolower (first1) - tolower (first2);
+#endif
+         /* Compare ignoring case, except when the options are both the
+            same letter, in which case lower-case always comes first.  */
+         /* NOTE: The subtraction below does the right thing
+            even with eight-bit chars: first1 and first2 are
+            converted to int *before* the subtraction. */
+         return lower_cmp ? lower_cmp : first2 - first1;
+       }
+    }
+  else
+    /* Within the same cluster, but not the same group, so just compare
+       groups.  */
+    return group_cmp (group1, group2, 0);
+}
+
+/* Version of hol_entry_cmp with correct signature for qsort.  */
+static int
+hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
+{
+  return hol_entry_cmp (entry1_v, entry2_v);
+}
+
+/* Sort HOL by group and alphabetically by option name (with short options
+   taking precedence over long).  Since the sorting is for display purposes
+   only, the shadowing of options isn't effected.  */
+static void
+hol_sort (struct hol *hol)
+{
+  if (hol->num_entries > 0)
+    qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
+          hol_entry_qcmp);
+}
+
+/* Append MORE to HOL, destroying MORE in the process.  Options in HOL shadow
+   any in MORE with the same name.  */
+static void
+hol_append (struct hol *hol, struct hol *more)
+{
+  struct hol_cluster **cl_end = &hol->clusters;
+
+  /* Steal MORE's cluster list, and add it to the end of HOL's.  */
+  while (*cl_end)
+    cl_end = &(*cl_end)->next;
+  *cl_end = more->clusters;
+  more->clusters = 0;
+
+  /* Merge entries.  */
+  if (more->num_entries > 0)
+    {
+      if (hol->num_entries == 0)
+       {
+         hol->num_entries = more->num_entries;
+         hol->entries = more->entries;
+         hol->short_options = more->short_options;
+         more->num_entries = 0;        /* Mark MORE's fields as invalid.  */
+       }
+      else
+       /* Append the entries in MORE to those in HOL, taking care to only add
+          non-shadowed SHORT_OPTIONS values.  */
+       {
+         unsigned left;
+         char *so, *more_so;
+         struct hol_entry *e;
+         unsigned num_entries = hol->num_entries + more->num_entries;
+         struct hol_entry *entries =
+           malloc (num_entries * sizeof (struct hol_entry));
+         unsigned hol_so_len = strlen (hol->short_options);
+         char *short_options =
+           malloc (hol_so_len + strlen (more->short_options) + 1);
+
+         __mempcpy (__mempcpy (entries, hol->entries,
+                               hol->num_entries * sizeof (struct hol_entry)),
+                    more->entries,
+                    more->num_entries * sizeof (struct hol_entry));
+
+         __mempcpy (short_options, hol->short_options, hol_so_len);
+
+         /* Fix up the short options pointers from HOL.  */
+         for (e = entries, left = hol->num_entries; left > 0; e++, left--)
+           e->short_options += (short_options - hol->short_options);
+
+         /* Now add the short options from MORE, fixing up its entries
+            too.  */
+         so = short_options + hol_so_len;
+         more_so = more->short_options;
+         for (left = more->num_entries; left > 0; e++, left--)
+           {
+             int opts_left;
+             const struct argp_option *opt;
+
+             e->short_options = so;
+
+             for (opts_left = e->num, opt = e->opt; opts_left; opt++, 
opts_left--)
+               {
+                 int ch = *more_so;
+                 if (oshort (opt) && ch == opt->key)
+                   /* The next short option in MORE_SO, CH, is from OPT.  */
+                   {
+                     if (! find_char (ch, short_options,
+                                      short_options + hol_so_len))
+                       /* The short option CH isn't shadowed by HOL's options,
+                          so add it to the sum.  */
+                       *so++ = ch;
+                     more_so++;
+                   }
+               }
+           }
+
+         *so = '\0';
+
+         free (hol->entries);
+         free (hol->short_options);
+
+         hol->entries = entries;
+         hol->num_entries = num_entries;
+         hol->short_options = short_options;
+       }
+    }
+
+  hol_free (more);
+}
+
+/* Inserts enough spaces to make sure STREAM is at column COL.  */
+static void
+indent_to (argp_fmtstream_t stream, unsigned col)
+{
+  int needed = col - __argp_fmtstream_point (stream);
+  while (needed-- > 0)
+    __argp_fmtstream_putc (stream, ' ');
+}
+
+/* Output to STREAM either a space, or a newline if there isn't room for at
+   least ENSURE characters before the right margin.  */
+static void
+space (argp_fmtstream_t stream, size_t ensure)
+{
+  if (__argp_fmtstream_point (stream) + ensure
+      >= __argp_fmtstream_rmargin (stream))
+    __argp_fmtstream_putc (stream, '\n');
+  else
+    __argp_fmtstream_putc (stream, ' ');
+}
+
+/* If the option REAL has an argument, we print it in using the printf
+   format REQ_FMT or OPT_FMT depending on whether it's a required or
+   optional argument.  */
+static void
+arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
+     const char *domain UNUSED, argp_fmtstream_t stream)
+{
+  if (real->arg)
+    {
+      if (real->flags & OPTION_ARG_OPTIONAL)
+       __argp_fmtstream_printf (stream, opt_fmt,
+                                dgettext (domain, real->arg));
+      else
+       __argp_fmtstream_printf (stream, req_fmt,
+                                dgettext (domain, real->arg));
+    }
+}
+
+/* Helper functions for hol_entry_help.  */
+
+/* State used during the execution of hol_help.  */
+struct hol_help_state
+{
+  /* PREV_ENTRY should contain the previous entry printed, or 0.  */
+  struct hol_entry *prev_entry;
+
+  /* If an entry is in a different group from the previous one, and SEP_GROUPS
+     is true, then a blank line will be printed before any output. */
+  int sep_groups;
+
+  /* True if a duplicate option argument was suppressed (only ever set if
+     UPARAMS.dup_args is false).  */
+  int suppressed_dup_arg;
+};
+
+/* Some state used while printing a help entry (used to communicate with
+   helper functions).  See the doc for hol_entry_help for more info, as most
+   of the fields are copied from its arguments.  */
+struct pentry_state
+{
+  const struct hol_entry *entry;
+  argp_fmtstream_t stream;
+  struct hol_help_state *hhstate;
+
+  /* True if nothing's been printed so far.  */
+  int first;
+
+  /* If non-zero, the state that was used to print this help.  */
+  const struct argp_state *state;
+};
+
+/* If a user doc filter should be applied to DOC, do so.  */
+static const char *
+filter_doc (const char *doc, int key, const struct argp *argp,
+           const struct argp_state *state)
+{
+  if (argp->help_filter)
+    /* We must apply a user filter to this output.  */
+    {
+      void *input = __argp_input (argp, state);
+      return (*argp->help_filter) (key, doc, input);
+    }
+  else
+    /* No filter.  */
+    return doc;
+}
+
+/* Prints STR as a header line, with the margin lines set appropiately, and
+   notes the fact that groups should be separated with a blank line.  ARGP is
+   the argp that should dictate any user doc filtering to take place.  Note
+   that the previous wrap margin isn't restored, but the left margin is reset
+   to 0.  */
+static void
+print_header (const char *str, const struct argp *argp,
+             struct pentry_state *pest)
+{
+  const char *tstr = dgettext (argp->argp_domain, str);
+  const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, 
pest->state);
+
+  if (fstr)
+    {
+      if (*fstr)
+       {
+         if (pest->hhstate->prev_entry)
+           /* Precede with a blank line.  */
+           __argp_fmtstream_putc (pest->stream, '\n');
+         indent_to (pest->stream, uparams.header_col);
+         __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col);
+         __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col);
+         __argp_fmtstream_puts (pest->stream, fstr);
+         __argp_fmtstream_set_lmargin (pest->stream, 0);
+         __argp_fmtstream_putc (pest->stream, '\n');
+       }
+
+      pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */
+    }
+
+  if (fstr != tstr)
+    free ((char *) fstr);
+}
+
+/* Inserts a comma if this isn't the first item on the line, and then makes
+   sure we're at least to column COL.  If this *is* the first item on a line,
+   prints any pending whitespace/headers that should precede this line. Also
+   clears FIRST.  */
+static void
+comma (unsigned col, struct pentry_state *pest)
+{
+  if (pest->first)
+    {
+      const struct hol_entry *pe = pest->hhstate->prev_entry;
+      const struct hol_cluster *cl = pest->entry->cluster;
+
+      if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group)
+       __argp_fmtstream_putc (pest->stream, '\n');
+
+      if (cl && cl->header && *cl->header
+         && (!pe
+             || (pe->cluster != cl
+                 && !hol_cluster_is_child (pe->cluster, cl))))
+       /* If we're changing clusters, then this must be the start of the
+          ENTRY's cluster unless that is an ancestor of the previous one
+          (in which case we had just popped into a sub-cluster for a bit).
+          If so, then print the cluster's header line.  */
+       {
+         int old_wm = __argp_fmtstream_wmargin (pest->stream);
+         print_header (cl->header, cl->argp, pest);
+         __argp_fmtstream_set_wmargin (pest->stream, old_wm);
+       }
+
+      pest->first = 0;
+    }
+  else
+    __argp_fmtstream_puts (pest->stream, ", ");
+
+  indent_to (pest->stream, col);
+}
+
+/* Print help for ENTRY to STREAM.  */
+static void
+hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
+               argp_fmtstream_t stream, struct hol_help_state *hhstate)
+{
+  unsigned num;
+  const struct argp_option *real = entry->opt, *opt;
+  char *so = entry->short_options;
+  int have_long_opt = 0;       /* We have any long options.  */
+  /* Saved margins.  */
+  int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
+  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.  */
+
+  /* Decent initializers are a GNU extension, so don't use it here. */
+  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--)
+      if (opt->name && ovisible (opt))
+       {
+         have_long_opt = 1;
+         break;
+       }
+
+  /* First emit short options.  */
+  __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly 
bizarre cases. */
+  for (opt = real, num = entry->num; num > 0; opt++, num--)
+    if (oshort (opt) && opt->key == *so)
+      /* OPT has a valid (non shadowed) short option.  */
+      {
+       if (ovisible (opt))
+         {
+           comma (uparams.short_opt_col, &pest);
+           __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);
+           else if (real->arg)
+             hhstate->suppressed_dup_arg = 1;
+         }
+       so++;
+      }
+
+  /* Now, long options.  */
+  if (odoc (real))
+    /* A `documentation' option.  */
+    {
+      __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
+      for (opt = real, num = entry->num; num > 0; opt++, num--)
+       if (opt->name && ovisible (opt))
+         {
+           comma (uparams.doc_opt_col, &pest);
+           /* Calling gettext 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,
+                                  dgettext (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;
+         }
+    }
+
+  /* Next, documentation strings.  */
+  __argp_fmtstream_set_lmargin (stream, 0);
+
+  if (pest.first)
+    {
+      /* Didn't print any switches, what's up?  */
+      if (!oshort (real) && !real->name)
+       /* This is a group header, print it nicely.  */
+       print_header (real->doc, entry->argp, &pest);
+      else
+       /* Just a totally shadowed option or null header; print nothing.  */
+       goto cleanup;           /* Just return, after cleaning up.  */
+    }
+  else
+    {
+      const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain,
+                                              real->doc) : 0;
+      const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
+      if (fstr && *fstr)
+       {
+         unsigned int col = __argp_fmtstream_point (stream);
+
+         __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col);
+         __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col);
+
+         if (col > (unsigned int) (uparams.opt_doc_col + 3))
+           __argp_fmtstream_putc (stream, '\n');
+         else if (col >= (unsigned int) uparams.opt_doc_col)
+           __argp_fmtstream_puts (stream, "   ");
+         else
+           indent_to (stream, uparams.opt_doc_col);
+
+         __argp_fmtstream_puts (stream, fstr);
+       }
+      if (fstr && fstr != tstr)
+       free ((char *) fstr);
+
+      /* Reset the left margin.  */
+      __argp_fmtstream_set_lmargin (stream, 0);
+      __argp_fmtstream_putc (stream, '\n');
+    }
+
+  hhstate->prev_entry = entry;
+
+cleanup:
+  __argp_fmtstream_set_lmargin (stream, old_lm);
+  __argp_fmtstream_set_wmargin (stream, old_wm);
+}
+
+/* Output a long help message about the options in HOL to STREAM.  */
+static void
+hol_help (struct hol *hol, const struct argp_state *state,
+         argp_fmtstream_t stream)
+{
+  unsigned num;
+  struct hol_entry *entry;
+  struct hol_help_state hhstate = { 0, 0, 0 };
+
+  for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
+    hol_entry_help (entry, state, stream, &hhstate);
+
+  if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
+    {
+      const char *tstr = dgettext (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,
+                                    state ? state->root_argp : 0, state);
+      if (fstr && *fstr)
+       {
+         __argp_fmtstream_putc (stream, '\n');
+         __argp_fmtstream_puts (stream, fstr);
+         __argp_fmtstream_putc (stream, '\n');
+       }
+      if (fstr && fstr != tstr)
+       free ((char *) fstr);
+    }
+}
+
+/* Helper functions for hol_usage.  */
+
+/* If OPT is a short option without an arg, append its key to the string
+   pointer pointer to by COOKIE, and advance the pointer.  */
+static int
+add_argless_short_opt (const struct argp_option *opt,
+                      const struct argp_option *real,
+                      const char *domain UNUSED, void *cookie)
+{
+  char **snao_end = cookie;
+  if (!(opt->arg || real->arg)
+      && !((opt->flags | real->flags) & OPTION_NO_USAGE))
+    *(*snao_end)++ = opt->key;
+  return 0;
+}
+
+/* If OPT is a short option with an arg, output a usage entry for it to the
+   stream pointed at by COOKIE.  */
+static int
+usage_argful_short_opt (const struct argp_option *opt,
+                       const struct argp_option *real,
+                       const char *domain UNUSED, void *cookie)
+{
+  argp_fmtstream_t stream = cookie;
+  const char *arg = opt->arg;
+  int flags = opt->flags | real->flags;
+
+  if (! arg)
+    arg = real->arg;
+
+  if (arg && !(flags & OPTION_NO_USAGE))
+    {
+      arg = dgettext (domain, arg);
+
+      if (flags & OPTION_ARG_OPTIONAL)
+       __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg);
+      else
+       {
+         /* Manually do line wrapping so that it (probably) won't
+            get wrapped at the embedded space.  */
+         space (stream, 6 + strlen (arg));
+         __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
+       }
+    }
+
+  return 0;
+}
+
+/* Output a usage entry for the long option opt to the stream pointed at by
+   COOKIE.  */
+static int
+usage_long_opt (const struct argp_option *opt,
+               const struct argp_option *real,
+               const char *domain UNUSED, void *cookie)
+{
+  argp_fmtstream_t stream = cookie;
+  const char *arg = opt->arg;
+  int flags = opt->flags | real->flags;
+
+  if (! arg)
+    arg = real->arg;
+
+  if (! (flags & OPTION_NO_USAGE))
+    {
+      if (arg)
+       {
+         arg = dgettext (domain, arg);
+         if (flags & OPTION_ARG_OPTIONAL)
+           __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg);
+         else
+           __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg);
+       }
+      else
+       __argp_fmtstream_printf (stream, " [--%s]", opt->name);
+    }
+
+  return 0;
+}
+
+/* Print a short usage description for the arguments in HOL to STREAM.  */
+static void
+hol_usage (struct hol *hol, argp_fmtstream_t stream)
+{
+  if (hol->num_entries > 0)
+    {
+      unsigned nentries;
+      struct hol_entry *entry;
+      char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
+      char *snao_end = short_no_arg_opts;
+
+      /* First we put a list of short options without arguments.  */
+      for (entry = hol->entries, nentries = hol->num_entries
+          ; nentries > 0
+          ; entry++, nentries--)
+       hol_entry_short_iterate (entry, add_argless_short_opt,
+                                entry->argp->argp_domain, &snao_end);
+      if (snao_end > short_no_arg_opts)
+       {
+         *snao_end++ = 0;
+         __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts);
+       }
+
+      /* Now a list of short options *with* arguments.  */
+      for (entry = hol->entries, nentries = hol->num_entries
+          ; nentries > 0
+          ; entry++, nentries--)
+       hol_entry_short_iterate (entry, usage_argful_short_opt,
+                                entry->argp->argp_domain, stream);
+
+      /* Finally, a list of long options (whew!).  */
+      for (entry = hol->entries, nentries = hol->num_entries
+          ; nentries > 0
+          ; entry++, nentries--)
+       hol_entry_long_iterate (entry, usage_long_opt,
+                               entry->argp->argp_domain, stream);
+    }
+}
+
+/* Make a HOL containing all levels of options in ARGP.  CLUSTER is the
+   cluster in which ARGP's entries should be clustered, or 0.  */
+static struct hol *
+argp_hol (const struct argp *argp, struct hol_cluster *cluster)
+{
+  const struct argp_child *child = argp->children;
+  struct hol *hol = make_hol (argp, cluster);
+  if (child)
+    while (child->argp)
+      {
+       struct hol_cluster *child_cluster =
+         ((child->group || child->header)
+          /* Put CHILD->argp within its own cluster.  */
+          ? hol_add_cluster (hol, child->group, child->header,
+                             child - argp->children, cluster, argp)
+          /* Just merge it into the parent's cluster.  */
+          : cluster);
+       hol_append (hol, argp_hol (child->argp, child_cluster)) ;
+       child++;
+      }
+  return hol;
+}
+
+/* Calculate how many different levels with alternative args strings exist in
+   ARGP.  */
+static size_t
+argp_args_levels (const struct argp *argp)
+{
+  size_t levels = 0;
+  const struct argp_child *child = argp->children;
+
+  if (argp->args_doc && strchr (argp->args_doc, '\n'))
+    levels++;
+
+  if (child)
+    while (child->argp)
+      levels += argp_args_levels ((child++)->argp);
+
+  return levels;
+}
+
+/* Print all the non-option args documented in ARGP to STREAM.  Any output is
+   preceded by a space.  LEVELS is a pointer to a byte vector the length
+   returned by argp_args_levels; it should be initialized to zero, and
+   updated by this routine for the next call if ADVANCE is true.  True is
+   returned as long as there are more patterns to output.  */
+static int
+argp_args_usage (const struct argp *argp, const struct argp_state *state,
+                char **levels, int advance, argp_fmtstream_t stream)
+{
+  char *our_level = *levels;
+  int multiple = 0;
+  const struct argp_child *child = argp->children;
+  const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0;
+  const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
+
+  if (fdoc)
+    {
+      const char *cp = fdoc;
+      nl = __strchrnul (cp, '\n');
+      if (*nl != '\0')
+       /* This is a `multi-level' args doc; advance to the correct position
+          as determined by our state in LEVELS, and update LEVELS.  */
+       {
+         int i;
+         multiple = 1;
+         for (i = 0; i < *our_level; i++)
+           cp = nl + 1, nl = __strchrnul (cp, '\n');
+         (*levels)++;
+       }
+
+      /* Manually do line wrapping so that it (probably) won't get wrapped at
+        any embedded spaces.  */
+      space (stream, 1 + nl - cp);
+
+      __argp_fmtstream_write (stream, cp, nl - cp);
+    }
+  if (fdoc && fdoc != tdoc)
+    free ((char *)fdoc);       /* Free user's modified doc string.  */
+
+  if (child)
+    while (child->argp)
+      advance = !argp_args_usage ((child++)->argp, state, levels, advance, 
stream);
+
+  if (advance && multiple)
+    {
+      /* Need to increment our level.  */
+      if (*nl)
+       /* There's more we can do here.  */
+       {
+         (*our_level)++;
+         advance = 0;          /* Our parent shouldn't advance also. */
+       }
+      else if (*our_level > 0)
+       /* We had multiple levels, but used them up; reset to zero.  */
+       *our_level = 0;
+    }
+
+  return !advance;
+}
+
+/* Print the documentation for ARGP to STREAM; if POST is false, then
+   everything preceeding a `\v' character in the documentation strings (or
+   the whole string, for those with none) is printed, otherwise, everything
+   following the `\v' character (nothing for strings without).  Each separate
+   bit of documentation is separated a blank line, and if PRE_BLANK is true,
+   then the first is as well.  If FIRST_ONLY is true, only the first
+   occurrence is output.  Returns true if anything was output.  */
+static int
+argp_doc (const struct argp *argp, const struct argp_state *state,
+         int post, int pre_blank, int first_only,
+         argp_fmtstream_t stream)
+{
+  const char *text;
+  const char *inp_text;
+  void *input = 0;
+  int anything = 0;
+  size_t inp_text_limit = 0;
+  const char *doc = dgettext (argp->argp_domain, argp->doc);
+  const struct argp_child *child = argp->children;
+
+  if (doc)
+    {
+      char *vt = strchr (doc, '\v');
+      inp_text = post ? (vt ? vt + 1 : 0) : doc;
+      inp_text_limit = (!post && vt) ? (vt - doc) : 0;
+    }
+  else
+    inp_text = 0;
+
+  if (argp->help_filter)
+    /* We have to filter the doc strings.  */
+    {
+      if (inp_text_limit)
+       /* Copy INP_TEXT so that it's nul-terminated.  */
+       inp_text = STRNDUP (inp_text, inp_text_limit);
+      input = __argp_input (argp, state);
+      text =
+       (*argp->help_filter) (post
+                             ? ARGP_KEY_HELP_POST_DOC
+                             : ARGP_KEY_HELP_PRE_DOC,
+                             inp_text, input);
+    }
+  else
+    text = (const char *) inp_text;
+
+  if (text)
+    {
+      if (pre_blank)
+       __argp_fmtstream_putc (stream, '\n');
+
+      if (text == inp_text && inp_text_limit)
+       __argp_fmtstream_write (stream, inp_text, inp_text_limit);
+      else
+       __argp_fmtstream_puts (stream, text);
+
+      if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
+       __argp_fmtstream_putc (stream, '\n');
+
+      anything = 1;
+    }
+
+  if (text && text != inp_text)
+    free ((char *) text);      /* Free TEXT returned from the help filter.  */
+  if (inp_text && inp_text_limit && argp->help_filter)
+    free ((char *) inp_text);  /* We copied INP_TEXT, so free it now.  */
+
+  if (post && argp->help_filter)
+    /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text.  */
+    {
+      text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
+      if (text)
+       {
+         if (anything || pre_blank)
+           __argp_fmtstream_putc (stream, '\n');
+         __argp_fmtstream_puts (stream, text);
+         free ((char *) text);
+         if (__argp_fmtstream_point (stream)
+             > __argp_fmtstream_lmargin (stream))
+           __argp_fmtstream_putc (stream, '\n');
+         anything = 1;
+       }
+    }
+
+  if (child)
+    while (child->argp && !(first_only && anything))
+      anything |=
+       argp_doc ((child++)->argp, state,
+                 post, anything || pre_blank, first_only,
+                 stream);
+
+  return anything;
+}
+
+/* Output a usage message for ARGP to STREAM.  If called from
+   argp_state_help, STATE is the relevent parsing state.  FLAGS are from the
+   set ARGP_HELP_*.  NAME is what to use wherever a `program name' is
+   needed. */
+
+static void
+_help (const struct argp *argp, const struct argp_state *state, FILE *stream,
+       unsigned flags, const char *name)
+{
+  int anything = 0;            /* Whether we've output anything.  */
+  struct hol *hol = 0;
+  argp_fmtstream_t fs;
+
+  if (! stream)
+    return;
+
+  FLOCKFILE (stream);
+
+  if (! uparams.valid)
+    fill_in_uparams (state);
+
+  fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
+  if (! fs)
+    {
+      FUNLOCKFILE (stream);
+      return;
+    }
+
+  if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
+    {
+      hol = argp_hol (argp, 0);
+
+      /* If present, these options always come last.  */
+      hol_set_group (hol, "help", -1);
+      hol_set_group (hol, "version", -1);
+
+      hol_sort (hol);
+    }
+
+  if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
+    /* Print a short `Usage:' message.  */
+    {
+      int first_pattern = 1, more_patterns;
+      size_t num_pattern_levels = argp_args_levels (argp);
+      char *pattern_levels = alloca (num_pattern_levels);
+
+      memset (pattern_levels, 0, num_pattern_levels);
+
+      do
+       {
+         int old_lm;
+         int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent);
+         char *levels = pattern_levels;
+
+         if (first_pattern)
+           __argp_fmtstream_printf (fs, "%s %s",
+                                    dgettext (argp->argp_domain, "Usage:"),
+                                    name);
+         else
+           __argp_fmtstream_printf (fs, "%s %s",
+                                    dgettext (argp->argp_domain, "  or: "),
+                                    name);
+
+         /* We set the lmargin as well as the wmargin, because hol_usage
+            manually wraps options with newline to avoid annoying breaks.  */
+         old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent);
+
+         if (flags & ARGP_HELP_SHORT_USAGE)
+           /* Just show where the options go.  */
+           {
+             if (hol->num_entries > 0)
+               __argp_fmtstream_puts (fs, dgettext (argp->argp_domain,
+                                                    " [OPTION...]"));
+           }
+         else
+           /* Actually print the options.  */
+           {
+             hol_usage (hol, fs);
+             flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once.  */
+           }
+
+         more_patterns = argp_args_usage (argp, state, &levels, 1, fs);
+
+         __argp_fmtstream_set_wmargin (fs, old_wm);
+         __argp_fmtstream_set_lmargin (fs, old_lm);
+
+         __argp_fmtstream_putc (fs, '\n');
+         anything = 1;
+
+         first_pattern = 0;
+       }
+      while (more_patterns);
+    }
+
+  if (flags & ARGP_HELP_PRE_DOC)
+    anything |= argp_doc (argp, state, 0, 0, 1, fs);
+
+  if (flags & ARGP_HELP_SEE)
+    {
+      __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\
+Try `%s --help' or `%s --usage' for more information.\n"),
+                              name, name);
+      anything = 1;
+    }
+
+  if (flags & ARGP_HELP_LONG)
+    /* Print a long, detailed help message.  */
+    {
+      /* Print info about all the options.  */
+      if (hol->num_entries > 0)
+       {
+         if (anything)
+           __argp_fmtstream_putc (fs, '\n');
+         hol_help (hol, state, fs);
+         anything = 1;
+       }
+    }
+
+  if (flags & ARGP_HELP_POST_DOC)
+    /* Print any documentation strings at the end.  */
+    anything |= argp_doc (argp, state, 1, anything, 0, fs);
+
+  if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
+    {
+      if (anything)
+       __argp_fmtstream_putc (fs, '\n');
+      __argp_fmtstream_printf (fs, dgettext (argp->argp_domain,
+                                            "Report bugs to %s.\n"),
+                              argp_program_bug_address);
+      anything = 1;
+    }
+
+  FUNLOCKFILE (stream);
+
+  if (hol)
+    hol_free (hol);
+
+  __argp_fmtstream_free (fs);
+}
+
+/* Output a usage message for ARGP to STREAM.  FLAGS are from the set
+   ARGP_HELP_*.  NAME is what to use wherever a `program name' is needed. */
+void __argp_help (const struct argp *argp, FILE *stream,
+                 unsigned flags, char *name)
+{
+  _help (argp, 0, stream, flags, name);
+}
+#ifdef weak_alias
+weak_alias (__argp_help, argp_help)
+#endif
+
+char *__argp_basename(char *name)
+{
+  char *short_name = strrchr(name, '/');
+  return short_name ? short_name + 1 : name;
+}
+
+char *
+__argp_short_program_name(const struct argp_state *state)
+{
+  if (state)
+    return state->name;
+#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+  return program_invocation_short_name;
+#elif HAVE_DECL_PROGRAM_INVOCATION_NAME
+  return __argp_basename(program_invocation_name);
+#else /* !HAVE_DECL_PROGRAM_INVOCATION_NAME */
+  /* 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
+  return "";
+# endif /* __GNUC__ */
+#endif /* !HAVE_DECL_PROGRAM_INVOCATION_NAME */
+}
+
+/* Output, if appropriate, a usage message for STATE to STREAM.  FLAGS are
+   from the set ARGP_HELP_*.  */
+void
+__argp_state_help (const struct argp_state *state, FILE *stream, unsigned 
flags)
+{
+  if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
+    {
+      if (state && (state->flags & ARGP_LONG_ONLY))
+       flags |= ARGP_HELP_LONG_ONLY;
+
+      _help (state ? state->root_argp : 0, state, stream, flags,
+            __argp_short_program_name(state));
+
+      if (!state || ! (state->flags & ARGP_NO_EXIT))
+       {
+         if (flags & ARGP_HELP_EXIT_ERR)
+           exit (argp_err_exit_status);
+         if (flags & ARGP_HELP_EXIT_OK)
+           exit (0);
+       }
+  }
+}
+#ifdef weak_alias
+weak_alias (__argp_state_help, argp_state_help)
+#endif
+
+/* If appropriate, print the printf string FMT and following args, preceded
+   by the program name and `:', to stderr, and followed by a `Try ... --help'
+   message, then exit (1).  */
+void
+__argp_error (const struct argp_state *state, const char *fmt, ...)
+{
+  if (!state || !(state->flags & ARGP_NO_ERRS))
+    {
+      FILE *stream = state ? state->err_stream : stderr;
+
+      if (stream)
+       {
+         va_list ap;
+
+         FLOCKFILE (stream);
+
+         FPUTS_UNLOCKED (__argp_short_program_name(state),
+                         stream);
+         PUTC_UNLOCKED (':', stream);
+         PUTC_UNLOCKED (' ', stream);
+
+         va_start (ap, fmt);
+         vfprintf (stream, fmt, ap);
+         va_end (ap);
+
+         PUTC_UNLOCKED ('\n', stream);
+
+         __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
+
+         FUNLOCKFILE (stream);
+       }
+    }
+}
+#ifdef weak_alias
+weak_alias (__argp_error, argp_error)
+#endif
+
+/* Similar to the standard gnu error-reporting function error(), but will
+   respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
+   to STATE->err_stream.  This is useful for argument parsing code that is
+   shared between program startup (when exiting is desired) and runtime
+   option parsing (when typically an error code is returned instead).  The
+   difference between this function and argp_error is that the latter is for
+   *parsing errors*, and the former is for other problems that occur during
+   parsing but don't reflect a (syntactic) problem with the input.  */
+void
+__argp_failure (const struct argp_state *state, int status, int errnum,
+               const char *fmt, ...)
+{
+  if (!state || !(state->flags & ARGP_NO_ERRS))
+    {
+      FILE *stream = state ? state->err_stream : stderr;
+
+      if (stream)
+       {
+         FLOCKFILE (stream);
+
+         FPUTS_UNLOCKED (__argp_short_program_name(state),
+                         stream);
+
+         if (fmt)
+           {
+             va_list ap;
+
+             PUTC_UNLOCKED (':', stream);
+             PUTC_UNLOCKED (' ', stream);
+
+             va_start (ap, fmt);
+             vfprintf (stream, fmt, ap);
+             va_end (ap);
+           }
+
+         if (errnum)
+           {
+             PUTC_UNLOCKED (':', stream);
+             PUTC_UNLOCKED (' ', stream);
+             fputs (STRERROR (errnum), stream);
+           }
+
+         PUTC_UNLOCKED ('\n', stream);
+
+         FUNLOCKFILE (stream);
+
+         if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
+           exit (status);
+       }
+    }
+}
+#ifdef weak_alias
+weak_alias (__argp_failure, argp_failure)
+#endif
diff --git a/tools/libargp/argp-namefrob.h b/tools/libargp/argp-namefrob.h
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-namefrob.h
@@ -0,0 +1,96 @@
+/* Name frobnication for compiling argp outside of glibc
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#if !_LIBC
+/* This code is written for inclusion in gnu-libc, and uses names in the
+   namespace reserved for libc.  If we're not compiling in libc, define those
+   names to be the normal ones instead.  */
+
+/* argp-parse functions */
+#undef __argp_parse
+#define __argp_parse argp_parse
+#undef __option_is_end
+#define __option_is_end _option_is_end
+#undef __option_is_short
+#define __option_is_short _option_is_short
+#undef __argp_input
+#define __argp_input _argp_input
+
+/* argp-help functions */
+#undef __argp_help
+#define __argp_help argp_help
+#undef __argp_error
+#define __argp_error argp_error
+#undef __argp_failure
+#define __argp_failure argp_failure
+#undef __argp_state_help
+#define __argp_state_help argp_state_help
+#undef __argp_usage
+#define __argp_usage argp_usage
+#undef __argp_basename
+#define __argp_basename _argp_basename
+#undef __argp_short_program_name
+#define __argp_short_program_name _argp_short_program_name
+
+/* argp-fmtstream functions */
+#undef __argp_make_fmtstream
+#define __argp_make_fmtstream argp_make_fmtstream
+#undef __argp_fmtstream_free
+#define __argp_fmtstream_free argp_fmtstream_free
+#undef __argp_fmtstream_putc
+#define __argp_fmtstream_putc argp_fmtstream_putc
+#undef __argp_fmtstream_puts
+#define __argp_fmtstream_puts argp_fmtstream_puts
+#undef __argp_fmtstream_write
+#define __argp_fmtstream_write argp_fmtstream_write
+#undef __argp_fmtstream_printf
+#define __argp_fmtstream_printf argp_fmtstream_printf
+#undef __argp_fmtstream_set_lmargin
+#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
+#undef __argp_fmtstream_set_rmargin
+#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
+#undef __argp_fmtstream_set_wmargin
+#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
+#undef __argp_fmtstream_point
+#define __argp_fmtstream_point argp_fmtstream_point
+#undef __argp_fmtstream_update
+#define __argp_fmtstream_update _argp_fmtstream_update
+#undef __argp_fmtstream_ensure
+#define __argp_fmtstream_ensure _argp_fmtstream_ensure
+#undef __argp_fmtstream_lmargin
+#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
+#undef __argp_fmtstream_rmargin
+#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
+#undef __argp_fmtstream_wmargin
+#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
+
+/* normal libc functions we call */
+#undef __sleep
+#define __sleep sleep
+#undef __strcasecmp
+#define __strcasecmp strcasecmp
+#undef __vsnprintf
+#define __vsnprintf vsnprintf
+
+#endif /* !_LIBC */
+
+#ifndef __set_errno
+#define __set_errno(e) (errno = (e))
+#endif
diff --git a/tools/libargp/argp-parse.c b/tools/libargp/argp-parse.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-parse.c
@@ -0,0 +1,1303 @@
+/* Hierarchial argument parsing
+   Copyright (C) 1995, 96, 97, 98, 99, 2000,2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE   1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+   When compiling libc, the _ macro is predefined.  */
+# if defined HAVE_LIBINTL_H || defined _LIBC
+#  include <libintl.h>
+#  ifdef _LIBC
+#   undef dgettext
+#   define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES)
+#  endif
+# else
+#  define dgettext(domain, msgid) (msgid)
+#  define gettext(msgid) (msgid)
+# endif
+#endif
+#ifndef N_
+# define N_(msgid) (msgid)
+#endif
+
+#if _LIBC - 0
+#include <bits/libc-lock.h>
+#else
+#ifdef HAVE_CTHREADS_H
+#include <cthreads.h>
+#endif
+#endif /* _LIBC */
+
+#include "argp.h"
+#include "argp-namefrob.h"
+
+
+/* The meta-argument used to prevent any further arguments being interpreted
+   as options.  */
+#define QUOTE "--"
+
+/* EZ alias for ARGP_ERR_UNKNOWN.  */
+#define EBADKEY ARGP_ERR_UNKNOWN
+
+
+/* Default options.  */
+
+/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
+   for one second intervals, decrementing _ARGP_HANG until it's zero.  Thus
+   you can force the program to continue by attaching a debugger and setting
+   it to 0 yourself.  */
+volatile int _argp_hang;
+
+#define OPT_PROGNAME   -2
+#define OPT_USAGE      -3
+#define OPT_HANG       -4
+
+static const struct argp_option argp_default_options[] =
+{
+  {"help",       '?',          0, 0,  N_("Give this help list"), -1},
+  {"usage",      OPT_USAGE,    0, 0,  N_("Give a short usage message"), 0 },
+  {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN,
+     N_("Set the program name"), 0},
+  {"HANG",       OPT_HANG,    "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
+     N_("Hang for SECS seconds (default 3600)"), 0 },
+  {0, 0, 0, 0, 0, 0}
+};
+
+static error_t
+argp_default_parser (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case '?':
+      __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
+      break;
+    case OPT_USAGE:
+      __argp_state_help (state, state->out_stream,
+                      ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
+      break;
+
+    case OPT_PROGNAME:         /* Set the program name.  */
+#if HAVE_DECL_PROGRAM_INVOCATION_NAME
+      program_invocation_name = arg;
+#endif
+      /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka
+        __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined
+        to be that, so we have to be a bit careful here.]  */
+
+      /* Update what we use for messages.  */
+
+      state->name = __argp_basename(arg);
+      
+#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+      program_invocation_short_name = state->name;
+#endif
+
+      if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
+         == ARGP_PARSE_ARGV0)
+       /* Update what getopt uses too.  */
+       state->argv[0] = arg;
+
+      break;
+
+    case OPT_HANG:
+      _argp_hang = atoi (arg ? arg : "3600");
+      fprintf(state->err_stream, "%s: pid = %ld\n",
+             state->name, (long) getpid());
+      while (_argp_hang-- > 0)
+       __sleep (1);
+      break;
+
+    default:
+      return EBADKEY;
+    }
+  return 0;
+}
+
+static const struct argp argp_default_argp =
+  {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"};
+
+
+static const struct argp_option argp_version_options[] =
+{
+  {"version",    'V',          0, 0,  N_("Print program version"), -1},
+  {0, 0, 0, 0, 0, 0 }
+};
+
+static error_t
+argp_version_parser (int key, char *arg UNUSED, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'V':
+      if (argp_program_version_hook)
+       (*argp_program_version_hook) (state->out_stream, state);
+      else if (argp_program_version)
+       fprintf (state->out_stream, "%s\n", argp_program_version);
+      else
+       __argp_error (state, dgettext (state->root_argp->argp_domain,
+                                      "(PROGRAM ERROR) No version known!?"));
+      if (! (state->flags & ARGP_NO_EXIT))
+       exit (0);
+      break;
+    default:
+      return EBADKEY;
+    }
+  return 0;
+}
+
+static const struct argp argp_version_argp =
+  {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"};
+
+
+
+/* The state of a `group' during parsing.  Each group corresponds to a
+   particular argp structure from the tree of such descending from the top
+   level argp passed to argp_parse.  */
+struct group
+{
+  /* This group's parsing function.  */
+  argp_parser_t parser;
+
+  /* Which argp this group is from.  */
+  const struct argp *argp;
+
+  /* The number of non-option args sucessfully handled by this parser.  */
+  unsigned args_processed;
+
+  /* This group's parser's parent's group.  */
+  struct group *parent;
+  unsigned parent_index;       /* And the our position in the parent.   */
+
+  /* These fields are swapped into and out of the state structure when
+     calling this group's parser.  */
+  void *input, **child_inputs;
+  void *hook;
+};
+
+/* Call GROUP's parser with KEY and ARG, swapping any group-specific info
+   from STATE before calling, and back into state afterwards.  If GROUP has
+   no parser, EBADKEY is returned.  */
+static error_t
+group_parse (struct group *group, struct argp_state *state, int key, char *arg)
+{
+  if (group->parser)
+    {
+      error_t err;
+      state->hook = group->hook;
+      state->input = group->input;
+      state->child_inputs = group->child_inputs;
+      state->arg_num = group->args_processed;
+      err = (*group->parser)(key, arg, state);
+      group->hook = state->hook;
+      return err;
+    }
+  else
+    return EBADKEY;
+}
+
+struct parser
+{
+  const struct argp *argp;
+
+  const char *posixly_correct;
+  
+  /* True if there are only no-option arguments left, which are just
+     passed verbatim with ARGP_KEY_ARG. This is set if we encounter a
+     quote, or the end of the proper options, but may be cleared again
+     if the user moves the next argument pointer backwards. */
+  int args_only;
+
+  /* Describe how to deal with options that follow non-option ARGV-elements.
+
+     If the caller did not specify anything, the default is
+     REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is
+     defined, PERMUTE otherwise.
+
+     REQUIRE_ORDER means don't recognize them as options; stop option
+     processing when the first non-option is seen. This is what Unix
+     does. This mode of operation is selected by either setting the
+     environment variable POSIXLY_CORRECT, or using `+' as the first
+     character of the list of option characters.
+
+     PERMUTE is the default. We permute the contents of ARGV as we
+     scan, so that eventually all the non-options are at the end. This
+     allows options to be given in any order, even with programs that
+     were not written to expect this.
+
+     RETURN_IN_ORDER is an option available to programs that were
+     written to expect options and other ARGV-elements in any order
+     and that care about the ordering of the two. We describe each
+     non-option ARGV-element as if it were the argument of an option
+     with character code 1. Using `-' as the first character of the
+     list of option characters selects this mode of operation.
+
+  */
+  enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering;
+
+  /* A segment of non-option arguments that have been skipped for
+     later processing, after all options. `first_nonopt' is the index
+     in ARGV of the first of them; `last_nonopt' is the index after
+     the last of them.
+
+     If quoted or args_only is non-zero, this segment should be empty. */
+
+  /* FIXME: I'd prefer to use unsigned, but it's more consistent to
+     use the same type as for state.next. */
+  int first_nonopt;
+  int last_nonopt;
+  
+  /* String of all recognized short options. Needed for ARGP_LONG_ONLY. */
+  /* FIXME: Perhaps change to a pointer to a suitable bitmap instead? */
+  char *short_opts;
+
+  /* For parsing combined short options. */
+  char *nextchar;
+  
+  /* States of the various parsing groups.  */
+  struct group *groups;
+  /* The end of the GROUPS array.  */
+  struct group *egroup;
+  /* An vector containing storage for the CHILD_INPUTS field in all groups.  */
+  void **child_inputs;
+  
+  /* State block supplied to parsing routines.  */
+  struct argp_state state;
+
+  /* Memory used by this parser.  */
+  void *storage;
+};
+
+/* Search for a group defining a short option. */
+static const struct argp_option *
+find_short_option(struct parser *parser, int key, struct group **p)
+{
+  struct group *group;
+  
+  assert(key >= 0);
+  assert(isascii(key));
+
+  for (group = parser->groups; group < parser->egroup; group++)
+    {
+      const struct argp_option *opts;
+
+      for (opts = group->argp->options; !__option_is_end(opts); opts++)
+       if (opts->key == key)
+         {
+           *p = group;
+           return opts;
+         }
+    }
+  return NULL;
+}
+
+enum match_result { MATCH_EXACT, MATCH_PARTIAL, MATCH_NO };
+
+/* If defined, allow complete.el-like abbreviations of long options. */
+#ifndef ARGP_COMPLETE
+#define ARGP_COMPLETE 0
+#endif
+
+/* Matches an encountern long-option argument ARG against an option NAME.
+ * ARG is terminated by NUL or '='. */
+static enum match_result
+match_option(const char *arg, const char *name)
+{
+  unsigned i, j;
+  for (i = j = 0;; i++, j++)
+    {
+      switch(arg[i])
+       {
+       case '\0':
+       case '=':
+         return name[j] ? MATCH_PARTIAL : MATCH_EXACT;
+#if ARGP_COMPLETE
+       case '-':
+         while (name[j] != '-')
+           if (!name[j++])
+             return MATCH_NO;
+         break;
+#endif
+       default:
+         if (arg[i] != name[j])
+           return MATCH_NO;
+       }
+    }
+}
+
+static const struct argp_option *
+find_long_option(struct parser *parser,
+                const char *arg,
+                struct group **p)
+{
+  struct group *group;
+
+  /* Partial match found so far. */
+  struct group *matched_group = NULL;
+  const struct argp_option *matched_option = NULL;
+
+  /* Number of partial matches. */
+  int num_partial = 0;
+
+  for (group = parser->groups; group < parser->egroup; group++)
+    {
+      const struct argp_option *opts;
+
+      for (opts = group->argp->options; !__option_is_end(opts); opts++)
+       {
+         if (!opts->name)
+           continue;
+         switch (match_option(arg, opts->name))
+           {
+           case MATCH_NO:
+             break;
+           case MATCH_PARTIAL:
+             num_partial++;
+
+             matched_group = group;
+             matched_option = opts;
+
+             break;
+           case MATCH_EXACT:
+             /* Exact match. */
+             *p = group;
+             return opts;
+           }
+       }
+    }
+  if (num_partial == 1)
+    {
+      *p = matched_group;
+      return matched_option;
+    }
+
+  return NULL;
+}
+
+
+/* The next usable entries in the various parser tables being filled in by
+   convert_options.  */
+struct parser_convert_state
+{
+  struct parser *parser;
+  char *short_end;
+  void **child_inputs_end;
+};
+
+/* Initialize GROUP from ARGP. If CVT->SHORT_END is non-NULL, short
+   options are recorded in the short options string. Returns the next
+   unused group entry. CVT holds state used during the conversion. */
+static struct group *
+convert_options (const struct argp *argp,
+                struct group *parent, unsigned parent_index,
+                struct group *group, struct parser_convert_state *cvt)
+{
+  const struct argp_option *opt = argp->options;
+  const struct argp_child *children = argp->children;
+
+  if (opt || argp->parser)
+    {
+      /* This parser needs a group. */
+      if (cvt->short_end)
+       {
+         /* Record any short options. */
+         for ( ; !__option_is_end (opt); opt++)
+           if (__option_is_short(opt))
+             *cvt->short_end++ = opt->key;
+       }
+      
+      group->parser = argp->parser;
+      group->argp = argp;
+      group->args_processed = 0;
+      group->parent = parent;
+      group->parent_index = parent_index;
+      group->input = 0;
+      group->hook = 0;
+      group->child_inputs = 0;
+      
+      if (children)
+       /* Assign GROUP's CHILD_INPUTS field some space from
+          CVT->child_inputs_end.*/
+       {
+         unsigned num_children = 0;
+         while (children[num_children].argp)
+           num_children++;
+         group->child_inputs = cvt->child_inputs_end;
+         cvt->child_inputs_end += num_children;
+       }
+      parent = group++;
+    }
+  else
+    parent = 0;
+
+  if (children)
+    {
+      unsigned index = 0;
+      while (children->argp)
+       group =
+         convert_options (children++->argp, parent, index++, group, cvt);
+    }
+
+  return group;
+}
+/* Allocate and initialize the group structures, so that they are
+   ordered as if by traversing the corresponding argp parser tree in
+   pre-order. Also build the list of short options, if that is needed. */
+static void
+parser_convert (struct parser *parser, const struct argp *argp)
+{
+  struct parser_convert_state cvt;
+
+  cvt.parser = parser;
+  cvt.short_end = parser->short_opts;
+  cvt.child_inputs_end = parser->child_inputs;
+
+  parser->argp = argp;
+
+  if (argp)
+    parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
+  else
+    parser->egroup = parser->groups; /* No parsers at all! */
+
+  if (parser->short_opts)
+    *cvt.short_end ='\0';
+}
+
+/* Lengths of various parser fields which we will allocated.  */
+struct parser_sizes
+{
+  /* Needed only ARGP_LONG_ONLY */
+  size_t short_len;            /* Number of short options.  */
+
+  size_t num_groups;           /* Group structures we allocate.  */
+  size_t num_child_inputs;     /* Child input slots.  */
+};
+
+/* For ARGP, increments the NUM_GROUPS field in SZS by the total
+   number of argp structures descended from it, and the SHORT_LEN by
+   the total number of short options. */
+static void
+calc_sizes (const struct argp *argp,  struct parser_sizes *szs)
+{
+  const struct argp_child *child = argp->children;
+  const struct argp_option *opt = argp->options;
+
+  if (opt || argp->parser)
+    {
+      /* This parser needs a group. */
+      szs->num_groups++;
+      if (opt)
+       {
+         while (__option_is_short (opt++))
+           szs->short_len++;
+       }
+    }
+
+  if (child)
+    while (child->argp)
+      {
+       calc_sizes ((child++)->argp, szs);
+       szs->num_child_inputs++;
+      }
+}
+
+/* Initializes PARSER to parse ARGP in a manner described by FLAGS.  */
+static error_t
+parser_init (struct parser *parser, const struct argp *argp,
+            int argc, char **argv, int flags, void *input)
+{
+  error_t err = 0;
+  struct group *group;
+  struct parser_sizes szs;
+
+  parser->posixly_correct = getenv ("POSIXLY_CORRECT");
+
+  if (flags & ARGP_IN_ORDER)
+    parser->ordering = RETURN_IN_ORDER;
+  else if (flags & ARGP_NO_ARGS)
+    parser->ordering = REQUIRE_ORDER;
+  else if (parser->posixly_correct)
+    parser->ordering = REQUIRE_ORDER;
+  else
+    parser->ordering = PERMUTE;
+  
+  szs.short_len = 0;
+  szs.num_groups = 0;
+  szs.num_child_inputs = 0;
+
+  if (argp)
+    calc_sizes (argp, &szs);
+
+  if (!(flags & ARGP_LONG_ONLY))
+    /* We have no use for the short option array. */
+    szs.short_len = 0;
+  
+  /* Lengths of the various bits of storage used by PARSER.  */
+#define GLEN (szs.num_groups + 1) * sizeof (struct group)
+#define CLEN (szs.num_child_inputs * sizeof (void *))
+#define SLEN (szs.short_len + 1)
+#define STORAGE(offset) ((void *) (((char *) parser->storage) + (offset)))
+
+  parser->storage = malloc (GLEN + CLEN + SLEN);
+  if (! parser->storage)
+    return ENOMEM;
+
+  parser->groups = parser->storage;
+
+  parser->child_inputs = STORAGE(GLEN);
+  memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
+
+  if (flags & ARGP_LONG_ONLY)
+    parser->short_opts = STORAGE(GLEN + CLEN);
+  else
+    parser->short_opts = NULL;
+
+  parser_convert (parser, argp);
+
+  memset (&parser->state, 0, sizeof (struct argp_state));
+  
+  parser->state.root_argp = parser->argp;
+  parser->state.argc = argc;
+  parser->state.argv = argv;
+  parser->state.flags = flags;
+  parser->state.err_stream = stderr;
+  parser->state.out_stream = stdout;
+  parser->state.pstate = parser;
+
+  parser->args_only = 0;
+  parser->nextchar = NULL;
+  parser->first_nonopt = parser->last_nonopt = 0;
+    
+  /* Call each parser for the first time, giving it a chance to propagate
+     values to child parsers.  */
+  if (parser->groups < parser->egroup)
+    parser->groups->input = input;
+  for (group = parser->groups;
+       group < parser->egroup && (!err || err == EBADKEY);
+       group++)
+    {
+      if (group->parent)
+       /* If a child parser, get the initial input value from the parent. */
+       group->input = group->parent->child_inputs[group->parent_index];
+
+      if (!group->parser
+         && group->argp->children && group->argp->children->argp)
+       /* For the special case where no parsing function is supplied for an
+          argp, propagate its input to its first child, if any (this just
+          makes very simple wrapper argps more convenient).  */
+       group->child_inputs[0] = group->input;
+
+      err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);
+    }
+  if (err == EBADKEY)
+    err = 0;                   /* Some parser didn't understand.  */
+
+  if (err)
+    return err;
+
+  if (argv[0] && !(parser->state.flags & ARGP_PARSE_ARGV0))
+    /* There's an argv[0]; use it for messages.  */
+    {
+      parser->state.name = __argp_basename(argv[0]);
+
+      /* Don't parse it as an argument. */
+      parser->state.next = 1;
+    }
+  else
+    parser->state.name = __argp_short_program_name(NULL);
+  
+  return 0;
+}
+
+/* Free any storage consumed by PARSER (but not PARSER itself).  */
+static error_t
+parser_finalize (struct parser *parser,
+                error_t err, int arg_ebadkey, int *end_index)
+{
+  struct group *group;
+
+  if (err == EBADKEY && arg_ebadkey)
+    /* Suppress errors generated by unparsed arguments.  */
+    err = 0;
+
+  if (! err)
+    {
+      if (parser->state.next == parser->state.argc)
+       /* We successfully parsed all arguments!  Call all the parsers again,
+          just a few more times... */
+       {
+         for (group = parser->groups;
+              group < parser->egroup && (!err || err==EBADKEY);
+              group++)
+           if (group->args_processed == 0)
+             err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0);
+         for (group = parser->egroup - 1;
+              group >= parser->groups && (!err || err==EBADKEY);
+              group--)
+           err = group_parse (group, &parser->state, ARGP_KEY_END, 0);
+
+         if (err == EBADKEY)
+           err = 0;            /* Some parser didn't understand.  */
+
+         /* Tell the user that all arguments are parsed.  */
+         if (end_index)
+           *end_index = parser->state.next;
+       }
+      else if (end_index)
+       /* Return any remaining arguments to the user.  */
+       *end_index = parser->state.next;
+      else
+       /* No way to return the remaining arguments, they must be bogus. */
+       {
+         if (!(parser->state.flags & ARGP_NO_ERRS)
+             && parser->state.err_stream)
+           fprintf (parser->state.err_stream,
+                    dgettext (parser->argp->argp_domain,
+                              "%s: Too many arguments\n"),
+                    parser->state.name);
+         err = EBADKEY;
+       }
+    }
+
+  /* Okay, we're all done, with either an error or success; call the parsers
+     to indicate which one.  */
+
+  if (err)
+    {
+      /* Maybe print an error message.  */
+      if (err == EBADKEY)
+       /* An appropriate message describing what the error was should have
+          been printed earlier.  */
+       __argp_state_help (&parser->state, parser->state.err_stream,
+                          ARGP_HELP_STD_ERR);
+
+      /* Since we didn't exit, give each parser an error indication.  */
+      for (group = parser->groups; group < parser->egroup; group++)
+       group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);
+    }
+  else
+    /* 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
+        the parent.  */
+      for (group = parser->egroup - 1
+          ; group >= parser->groups && (!err || err == EBADKEY)
+          ; group--)
+       err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0);
+      if (err == EBADKEY)
+       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;
+
+  free (parser->storage);
+
+  return err;
+}
+
+/* Call the user parsers to parse the non-option argument VAL, at the
+   current position, returning any error. The state NEXT pointer
+   should point to the 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)
+{
+  /* Save the starting value of NEXT */
+  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++)
+    {
+      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, so try looking for options 
again.  */
+       parser->args_only = 0;
+    }
+
+  return err;
+}
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,next), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (struct parser *parser)
+{
+  int bottom = parser->first_nonopt;
+  int middle = parser->last_nonopt;
+  int top = parser->state.next;
+  char **argv = parser->state.argv;
+  
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+       {
+         /* Bottom segment is the short one.  */
+         int len = middle - bottom;
+         register int i;
+
+         /* Swap it with the top part of the top segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[top - (middle - bottom) + i];
+             argv[top - (middle - bottom) + i] = tem;
+           }
+         /* Exclude the moved bottom segment from further swapping.  */
+         top -= len;
+       }
+      else
+       {
+         /* Top segment is the short one.  */
+         int len = top - middle;
+         register int i;
+
+         /* Swap it with the bottom part of the bottom segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[middle + i];
+             argv[middle + i] = tem;
+           }
+         /* Exclude the moved top segment from further swapping.  */
+         bottom += len;
+       }
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  parser->first_nonopt += (parser->state.next - parser->last_nonopt);
+  parser->last_nonopt = parser->state.next;
+}
+
+
+
+enum arg_type { ARG_ARG, ARG_SHORT_OPTION,
+               ARG_LONG_OPTION, ARG_LONG_ONLY_OPTION,
+               ARG_QUOTE };
+
+static enum arg_type
+classify_arg(struct parser *parser, char *arg, char **opt)
+{
+  if (arg[0] == '-')
+    /* Looks like an option... */
+    switch (arg[1])
+      {
+      case '\0':
+       /* "-" is not an option. */
+       return ARG_ARG;
+      case '-':
+       /* Long option, or quote. */
+       if (!arg[2])
+         return ARG_QUOTE;
+         
+       /* A long option. */
+       if (opt)
+         *opt = arg + 2;
+       return ARG_LONG_OPTION;
+
+      default:
+       /* Short option. But if ARGP_LONG_ONLY, it can also be a long option. */
+
+       if (opt)
+         *opt = arg + 1;
+
+       if (parser->state.flags & ARGP_LONG_ONLY)
+         {
+           /* Rules from getopt.c:
+
+              If long_only and the ARGV-element has the form "-f",
+              where f is a valid short option, don't consider it an
+              abbreviated form of a long option that starts with f.
+              Otherwise there would be no way to give the -f short
+              option.
+
+              On the other hand, if there's a long option "fubar" and
+              the ARGV-element is "-fu", do consider that an
+              abbreviation of the long option, just like "--fu", and
+              not "-f" with arg "u".
+
+              This distinction seems to be the most useful approach. */
+
+           assert(parser->short_opts);
+           
+           if (arg[2] || !strchr(parser->short_opts, arg[1]))
+             return ARG_LONG_ONLY_OPTION;
+         }
+
+       return ARG_SHORT_OPTION;
+      }
+  
+  else
+    return ARG_ARG;
+}
+
+/* Parse the next argument in PARSER (as indicated by PARSER->state.next).
+   Any error from the parsers is returned, and *ARGP_EBADKEY indicates
+   whether a value of EBADKEY is due to an unrecognized argument (which is
+   generally not fatal).  */
+static error_t
+parser_parse_next (struct parser *parser, int *arg_ebadkey)
+{
+  if (parser->state.quoted && parser->state.next < parser->state.quoted)
+    /* The next argument pointer has been moved to before the quoted
+       region, so pretend we never saw the quoting `--', and start
+       looking for options again. If the `--' is still there we'll just
+       process it one more time. */
+    parser->state.quoted = parser->args_only = 0;
+
+  /* Give FIRST_NONOPT & LAST_NONOPT rational values if NEXT has been
+     moved back by the user (who may also have changed the arguments).  */
+  if (parser->last_nonopt > parser->state.next)
+    parser->last_nonopt = parser->state.next;
+  if (parser->first_nonopt > parser->state.next)
+    parser->first_nonopt = parser->state.next;
+
+  if (parser->nextchar)
+    /* Deal with short options. */
+    {
+      struct group *group;
+      char c;
+      const struct argp_option *option;
+      char *value = NULL;;
+
+      assert(!parser->args_only);
+
+      c = *parser->nextchar++;
+      
+      option = find_short_option(parser, c, &group);
+      if (!option)
+       {
+         if (parser->posixly_correct)
+           /* 1003.2 specifies the format of this message.  */
+           fprintf (parser->state.err_stream,
+                    dgettext(parser->state.root_argp->argp_domain,
+                             "%s: illegal option -- %c\n"),
+                    parser->state.name, c);
+         else
+           fprintf (parser->state.err_stream,
+                    dgettext(parser->state.root_argp->argp_domain,
+                             "%s: invalid option -- %c\n"),
+                    parser->state.name, c);
+
+         *arg_ebadkey = 0;
+         return EBADKEY;
+       }
+
+      if (!*parser->nextchar)
+       parser->nextchar = NULL;
+
+      if (option->arg)
+       {
+         value = parser->nextchar;
+         parser->nextchar = NULL;
+             
+         if (!value
+             && !(option->flags & OPTION_ARG_OPTIONAL))
+           /* We need an mandatory argument. */
+           {
+             if (parser->state.next == parser->state.argc)
+               /* Missing argument */
+               {
+                 /* 1003.2 specifies the format of this message.  */
+                 fprintf (parser->state.err_stream,
+                          dgettext(parser->state.root_argp->argp_domain,
+                                   "%s: option requires an argument -- %c\n"),
+                          parser->state.name, c);
+
+                 *arg_ebadkey = 0;
+                 return EBADKEY;
+               }
+             value = parser->state.argv[parser->state.next++];
+           }
+       }
+      return group_parse(group, &parser->state,
+                        option->key, value);
+    }
+  else
+    /* Advance to the next ARGV-element.  */
+    {
+      if (parser->args_only)
+       {
+         *arg_ebadkey = 1;
+         if (parser->state.next >= parser->state.argc)
+           /* We're done. */
+           return EBADKEY;
+         else
+           return parser_parse_arg(parser,
+                                   parser->state.argv[parser->state.next]);
+       }
+      
+      if (parser->state.next >= parser->state.argc)
+       /* Almost done. If there are non-options that we skipped
+          previously, we should process them now. */
+       {
+         *arg_ebadkey = 1;
+         if (parser->first_nonopt != parser->last_nonopt)
+           {
+             exchange(parser);
+             
+             /* Start processing the arguments we skipped previously. */
+             parser->state.next = parser->first_nonopt;
+             
+             parser->first_nonopt = parser->last_nonopt = 0;
+
+             parser->args_only = 1;
+             return 0;
+           }
+         else
+           /* Indicate that we're really done. */
+           return EBADKEY;
+       }
+      else
+       /* Look for options. */
+       {
+         char *arg = parser->state.argv[parser->state.next];
+
+         char *optstart;
+         enum arg_type token = classify_arg(parser, arg, &optstart);
+         
+         switch (token)
+           {
+           case ARG_ARG:
+             switch (parser->ordering)
+               {
+               case PERMUTE:
+                 if (parser->first_nonopt == parser->last_nonopt)
+                   /* Skipped sequence is empty; start a new one. */
+                   parser->first_nonopt = parser->last_nonopt = 
parser->state.next;
+
+                 else if (parser->last_nonopt != parser->state.next)
+                   /* We have a non-empty skipped sequence, and
+                      we're not at the end-point, so move it. */
+                   exchange(parser);
+
+                 assert(parser->last_nonopt == parser->state.next);
+                 
+                 /* Skip this argument for now. */
+                 parser->state.next++;
+                 parser->last_nonopt = parser->state.next; 
+                 
+                 return 0;
+
+               case REQUIRE_ORDER:
+                 /* Implicit quote before the first argument. */
+                  parser->args_only = 1;
+                  return 0;
+                  
+               case RETURN_IN_ORDER:
+                 *arg_ebadkey = 1;
+                 return parser_parse_arg(parser, arg);
+
+               default:
+                 abort();
+               }
+           case ARG_QUOTE:
+             /* Skip it, then exchange with any previous non-options. */
+             parser->state.next++;
+             assert (parser->last_nonopt != parser->state.next);
+
+             if (parser->first_nonopt != parser->last_nonopt)
+               {
+                 exchange(parser);
+                 
+                 /* Start processing the skipped and the quoted
+                    arguments. */
+
+                 parser->state.quoted = parser->state.next = 
parser->first_nonopt;
+
+                 /* Also empty the skipped-list, to avoid confusion
+                    if the user resets the next pointer. */
+                 parser->first_nonopt = parser->last_nonopt = 0;
+               }
+             else
+               parser->state.quoted = parser->state.next;
+
+             parser->args_only = 1;          
+             return 0;
+
+           case ARG_LONG_ONLY_OPTION:
+           case ARG_LONG_OPTION:
+             {
+               struct group *group;
+               const struct argp_option *option;
+               char *value;
+
+               parser->state.next++;
+               option = find_long_option(parser, optstart, &group);
+               
+               if (!option)
+                 {
+                   /* NOTE: This includes any "=something" in the output. */
+                   fprintf (parser->state.err_stream,
+                            dgettext(parser->state.root_argp->argp_domain,
+                                     "%s: unrecognized option `%s'\n"),
+                            parser->state.name, arg);
+                   *arg_ebadkey = 0;
+                   return EBADKEY;
+                 }
+
+               value = strchr(optstart, '=');
+               if (value)
+                 value++;
+               
+               if (value && !option->arg)
+                 /* Unexpected argument. */
+                 {
+                   if (token == ARG_LONG_OPTION)
+                     /* --option */
+                     fprintf (parser->state.err_stream,
+                              dgettext(parser->state.root_argp->argp_domain,
+                                       "%s: option `--%s' doesn't allow an 
argument\n"),
+                              parser->state.name, option->name);
+                   else
+                     /* +option or -option */
+                     fprintf (parser->state.err_stream,
+                              dgettext(parser->state.root_argp->argp_domain,
+                                       "%s: option `%c%s' doesn't allow an 
argument\n"),
+                              parser->state.name, arg[0], option->name);
+
+                   *arg_ebadkey = 0;
+                   return EBADKEY;
+                 }
+               
+               if (option->arg && !value
+                   && !(option->flags & OPTION_ARG_OPTIONAL))
+                 /* We need an mandatory argument. */
+                 {
+                   if (parser->state.next == parser->state.argc)
+                     /* Missing argument */
+                     {
+                       if (token == ARG_LONG_OPTION)
+                         /* --option */
+                         fprintf (parser->state.err_stream,
+                                  
dgettext(parser->state.root_argp->argp_domain,
+                                           "%s: option `--%s' requires an 
argument\n"),
+                                parser->state.name, option->name);
+                       else
+                         /* +option or -option */
+                         fprintf (parser->state.err_stream,
+                                  
dgettext(parser->state.root_argp->argp_domain,
+                                           "%s: option `%c%s' requires an 
argument\n"),
+                                  parser->state.name, arg[0], option->name);
+
+                       *arg_ebadkey = 0;
+                       return EBADKEY;
+                     }
+
+                   value = parser->state.argv[parser->state.next++];
+                 }
+               *arg_ebadkey = 0;
+               return group_parse(group, &parser->state,
+                                  option->key, value);
+             }
+           case ARG_SHORT_OPTION:
+             parser->state.next++;
+             parser->nextchar = optstart;
+             return 0;
+
+           default:
+             abort();
+           }
+       }
+    }
+}
+
+/* Parse the options strings in ARGC & ARGV according to the argp in ARGP.
+   FLAGS is one of the ARGP_ flags above.  If END_INDEX is non-NULL, the
+   index in ARGV of the first unparsed option is returned in it.  If an
+   unknown option is present, EINVAL is returned; if some parser routine
+   returned a non-zero value, it is returned; otherwise 0 is returned.  */
+error_t
+__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
+             int *end_index, void *input)
+{
+  error_t err;
+  struct parser parser;
+
+  /* If true, then err == EBADKEY is a result of a non-option argument failing
+     to be parsed (which in some cases isn't actually an error).  */
+  int arg_ebadkey = 0;
+
+  if (! (flags & ARGP_NO_HELP))
+    /* Add our own options.  */
+    {
+      struct argp_child *child = alloca (4 * sizeof (struct argp_child));
+      struct argp *top_argp = alloca (sizeof (struct argp));
+
+      /* TOP_ARGP has no options, it just serves to group the user & default
+        argps.  */
+      memset (top_argp, 0, sizeof (*top_argp));
+      top_argp->children = child;
+
+      memset (child, 0, 4 * sizeof (struct argp_child));
+
+      if (argp)
+       (child++)->argp = argp;
+      (child++)->argp = &argp_default_argp;
+      if (argp_program_version || argp_program_version_hook)
+       (child++)->argp = &argp_version_argp;
+      child->argp = 0;
+
+      argp = top_argp;
+    }
+
+  /* Construct a parser for these arguments.  */
+  err = parser_init (&parser, argp, argc, argv, flags, input);
+
+  if (! err)
+    /* Parse! */
+    {
+      while (! err)
+       err = parser_parse_next (&parser, &arg_ebadkey);
+      err = parser_finalize (&parser, err, arg_ebadkey, end_index);
+    }
+
+  return err;
+}
+#ifdef weak_alias
+weak_alias (__argp_parse, argp_parse)
+#endif
+
+/* Return the input field for ARGP in the parser corresponding to STATE; used
+   by the help routines.  */
+void *
+__argp_input (const struct argp *argp, const struct argp_state *state)
+{
+  if (state)
+    {
+      struct group *group;
+      struct parser *parser = state->pstate;
+
+      for (group = parser->groups; group < parser->egroup; group++)
+       if (group->argp == argp)
+         return group->input;
+    }
+
+  return 0;
+}
+#ifdef weak_alias
+weak_alias (__argp_input, _argp_input)
+#endif
+
+/* Defined here, in case a user is not inlining the definitions in
+ * argp.h */
+void
+__argp_usage (__const struct argp_state *__state) __THROW
+{
+  __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
+}
+
+int
+__option_is_short (__const struct argp_option *__opt) __THROW
+{
+  if (__opt->flags & OPTION_DOC)
+    return 0;
+  else
+    {
+      int __key = __opt->key;
+      /* FIXME: whether or not a particular key implies a short option
+       * ought not to be locale dependent. */
+      return __key > 0 && isprint (__key);
+    }
+}
+
+int
+__option_is_end (__const struct argp_option *__opt) __THROW
+{
+  return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
+}
diff --git a/tools/libargp/argp-pv.c b/tools/libargp/argp-pv.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-pv.c
@@ -0,0 +1,25 @@
+/* Default definition for ARGP_PROGRAM_VERSION.
+   Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* If set by the user program to a non-zero value, then a default option
+   --version is added (unless the ARGP_NO_HELP flag is used), which will
+   print this this string followed by a newline and exit (unless the
+   ARGP_NO_EXIT flag is used).  Overridden by ARGP_PROGRAM_VERSION_HOOK.  */
+const char *argp_program_version = 0;
diff --git a/tools/libargp/argp-pvh.c b/tools/libargp/argp-pvh.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp-pvh.c
@@ -0,0 +1,32 @@
+/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
+   Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "argp.h"
+
+/* If set by the user program to a non-zero value, then a default option
+   --version is added (unless the ARGP_NO_HELP flag is used), which calls
+   this function with a stream to print the version to and a pointer to the
+   current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
+   used).  This variable takes precedent over ARGP_PROGRAM_VERSION.  */
+void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = 0;
diff --git a/tools/libargp/argp.h b/tools/libargp/argp.h
new file mode 100644
--- /dev/null
+++ b/tools/libargp/argp.h
@@ -0,0 +1,602 @@
+/* Hierarchial argument parsing.
+   Copyright (C) 1995, 96, 97, 98, 99, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@xxxxxxxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _ARGP_H
+#define _ARGP_H
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define __need_error_t
+#include <errno.h>
+
+#ifndef __THROW
+# define __THROW
+#endif
+
+#ifndef __const
+# define __const const
+#endif
+
+#ifndef __error_t_defined
+typedef int error_t;
+# define __error_t_defined
+#endif
+
+/* FIXME: What's the right way to check for __restrict? Sun's cc seems
+   not to have it. Perhaps it's easiest to just delete the use of
+   __restrict from the prototypes. */
+#ifndef __restrict
+# ifndef __GNUC___
+#  define __restrict
+# endif
+#endif
+
+/* NOTE: We can't use the autoconf tests, since this is supposed to be
+   an installed header file and argp's config.h is of course not
+   installed. */
+#ifndef PRINTF_STYLE
+# if __GNUC__ >= 2
+#  define PRINTF_STYLE(f, a) __attribute__ ((__format__ (__printf__, f, a)))
+# else
+#  define PRINTF_STYLE(f, a)
+# endif
+#endif
+
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* A description of a particular option.  A pointer to an array of
+   these is passed in the OPTIONS field of an argp structure.  Each option
+   entry can correspond to one long option and/or one short option; more
+   names for the same option can be added by following an entry in an option
+   array with options having the OPTION_ALIAS flag set.  */
+struct argp_option
+{
+  /* The long option name.  For more than one name for the same option, you
+     can use following options with the OPTION_ALIAS flag set.  */
+  __const char *name;
+
+  /* What key is returned for this option.  If > 0 and printable, then it's
+     also accepted as a short option.  */
+  int key;
+
+  /* If non-NULL, this is the name of the argument associated with this
+     option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */
+  __const char *arg;
+
+  /* OPTION_ flags.  */
+  int flags;
+
+  /* The doc string for this option.  If both NAME and KEY are 0, This string
+     will be printed outdented from the normal option column, making it
+     useful as a group header (it will be the first thing printed in its
+     group); in this usage, it's conventional to end the string with a `:'.  */
+  __const char *doc;
+
+  /* The group this option is in.  In a long help message, options are sorted
+     alphabetically within each group, and the groups presented in the order
+     0, 1, 2, ..., n, -m, ..., -2, -1.  Every entry in an options array with
+     if this field 0 will inherit the group number of the previous entry, or
+     zero if it's the first one, unless its a group header (NAME and KEY both
+     0), in which case, the previous entry + 1 is the default.  Automagic
+     options such as --help are put into group -1.  */
+  int group;
+};
+
+/* The argument associated with this option is optional.  */
+#define OPTION_ARG_OPTIONAL    0x1
+
+/* This option isn't displayed in any help messages.  */
+#define OPTION_HIDDEN          0x2
+
+/* This option is an alias for the closest previous non-alias option.  This
+   means that it will be displayed in the same help entry, and will inherit
+   fields other than NAME and KEY from the aliased option.  */
+#define OPTION_ALIAS           0x4
+
+/* This option isn't actually an option (and so should be ignored by the
+   actual option parser), but rather an arbitrary piece of documentation that
+   should be displayed in much the same manner as the options.  If this flag
+   is set, then the option NAME field is displayed unmodified (e.g., no `--'
+   prefix is added) at the left-margin (where a *short* option would normally
+   be displayed), and the documentation string in the normal place.  For
+   purposes of sorting, any leading whitespace and puncuation is ignored,
+   except that if the first non-whitespace character is not `-', this entry
+   is displayed after all options (and OPTION_DOC entries with a leading `-')
+   in the same group.  */
+#define OPTION_DOC             0x8
+
+/* This option shouldn't be included in `long' usage messages (but is still
+   included in help messages).  This is mainly intended for options that are
+   completely documented in an argp's ARGS_DOC field, in which case including
+   the option in the generic usage list would be redundant.  For instance,
+   if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to
+   distinguish these two cases, -x should probably be marked
+   OPTION_NO_USAGE.  */
+#define OPTION_NO_USAGE                0x10
+
+struct argp;                   /* fwd declare this type */
+struct argp_state;             /* " */
+struct argp_child;             /* " */
+
+/* The type of a pointer to an argp parsing function.  */
+typedef error_t (*argp_parser_t) (int key, char *arg,
+                                 struct argp_state *state);
+
+/* What to return for unrecognized keys.  For special ARGP_KEY_ keys, such
+   returns will simply be ignored.  For user keys, this error will be turned
+   into EINVAL (if the call to argp_parse is such that errors are propagated
+   back to the user instead of exiting); returning EINVAL itself would result
+   in an immediate stop to parsing in *all* cases.  */
+#define ARGP_ERR_UNKNOWN       E2BIG /* Hurd should never need E2BIG.  XXX */
+
+/* Special values for the KEY argument to an argument parsing function.
+   ARGP_ERR_UNKNOWN should be returned if they aren't understood.
+
+   The sequence of keys to a parsing function is either (where each
+   uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key):
+
+       INIT opt... NO_ARGS END SUCCESS  -- No non-option arguments at all
+   or  INIT (opt | ARG)... END SUCCESS  -- All non-option args parsed
+   or  INIT (opt | ARG)... SUCCESS      -- Some non-option arg unrecognized
+
+   The third case is where every parser returned ARGP_KEY_UNKNOWN for an
+   argument, in which case parsing stops at that argument (returning the
+   unparsed arguments to the caller of argp_parse if requested, or stopping
+   with an error message if not).
+
+   If an error occurs (either detected by argp, or because the parsing
+   function returned an error value), then the parser is called with
+   ARGP_KEY_ERROR, and no further calls are made.  */
+
+/* This is not an option at all, but rather a command line argument.  If a
+   parser receiving this key returns success, the fact is recorded, and the
+   ARGP_KEY_NO_ARGS case won't be used.  HOWEVER, if while processing the
+   argument, a parser function decrements the NEXT field of the state it's
+   passed, the option won't be considered processed; this is to allow you to
+   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
+   any non-option args, user parsers are called with this key if they didn't
+   successfully process any non-option arguments.  Called just before
+   ARGP_KEY_END (where more general validity checks on previously parsed
+   arguments can take place).  */
+#define ARGP_KEY_NO_ARGS       0x1000002
+/* Passed in before any parsing is done.  Afterwards, the values of each
+   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.  */
+#define ARGP_KEY_ERROR         0x1000005
+
+/* An argp structure contains a set of options declarations, a function to
+   deal with parsing one, documentation string, a possible vector of child
+   argp's, and perhaps a function to filter help output.  When actually
+   parsing options, getopt is called with the union of all the argp
+   structures chained together through their CHILD pointers, with conflicts
+   being resolved in favor of the first occurrence in the chain.  */
+struct argp
+{
+  /* An array of argp_option structures, terminated by an entry with both
+     NAME and KEY having a value of 0.  */
+  __const struct argp_option *options;
+
+  /* What to do with an option from this structure.  KEY is the key
+     associated with the option, and ARG is any associated argument (NULL if
+     none was supplied).  If KEY isn't understood, ARGP_ERR_UNKNOWN should be
+     returned.  If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then
+     parsing is stopped immediately, and that value is returned from
+     argp_parse().  For special (non-user-supplied) values of KEY, see the
+     ARGP_KEY_ definitions below.  */
+  argp_parser_t parser;
+
+  /* A string describing what other arguments are wanted by this program.  It
+     is only used by argp_usage to print the `Usage:' message.  If it
+     contains newlines, the strings separated by them are considered
+     alternative usage patterns, and printed on separate lines (lines after
+     the first are prefix by `  or: ' instead of `Usage:').  */
+  __const char *args_doc;
+
+  /* If non-NULL, a string containing extra text to be printed before and
+     after the options in a long help message (separated by a vertical tab
+     `\v' character).  */
+  __const char *doc;
+
+  /* A vector of argp_children structures, terminated by a member with a 0
+     argp field, pointing to child argps should be parsed with this one.  Any
+     conflicts are resolved in favor of this argp, or early argps in the
+     CHILDREN list.  This field is useful if you use libraries that supply
+     their own argp structure, which you want to use in conjunction with your
+     own.  */
+  __const struct argp_child *children;
+
+  /* If non-zero, this should be a function to filter the output of help
+     messages.  KEY is either a key from an option, in which case TEXT is
+     that option's help text, or a special key from the ARGP_KEY_HELP_
+     defines, below, describing which other help text TEXT is.  The function
+     should return either TEXT, if it should be used as-is, a replacement
+     string, which should be malloced, and will be freed by argp, or NULL,
+     meaning `print nothing'.  The value for TEXT is *after* any translation
+     has been done, so if any of the replacement text also needs translation,
+     that should be done by the filter function.  INPUT is either the input
+     supplied to argp_parse, or NULL, if argp_help was called directly.  */
+  char *(*help_filter) (int __key, __const char *__text, void *__input);
+
+  /* If non-zero the strings used in the argp library are translated using
+     the domain described by this string.  Otherwise the currently installed
+     default domain is used.  */
+  const char *argp_domain;
+};
+
+/* Possible KEY arguments to a help filter function.  */
+#define ARGP_KEY_HELP_PRE_DOC  0x2000001 /* Help text preceeding options. */
+#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */
+#define ARGP_KEY_HELP_HEADER   0x2000003 /* Option header string. */
+#define ARGP_KEY_HELP_EXTRA    0x2000004 /* After all other documentation;
+                                            TEXT is NULL for this key.  */
+/* Explanatory note emitted when duplicate option arguments have been
+   suppressed.  */
+#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005
+#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string.  */
+
+/* When an argp has a non-zero CHILDREN field, it should point to a vector of
+   argp_child structures, each of which describes a subsidiary argp.  */
+struct argp_child
+{
+  /* The child parser.  */
+  __const struct argp *argp;
+
+  /* Flags for this child.  */
+  int flags;
+
+  /* If non-zero, an optional header to be printed in help output before the
+     child options.  As a side-effect, a non-zero value forces the child
+     options to be grouped together; to achieve this effect without actually
+     printing a header string, use a value of "".  */
+  __const char *header;
+
+  /* Where to group the child options relative to the other (`consolidated')
+     options in the parent argp; the values are the same as the GROUP field
+     in argp_option structs, but all child-groupings follow parent options at
+     a particular group level.  If both this field and HEADER are zero, then
+     they aren't grouped at all, but rather merged with the parent options
+     (merging the child's grouping levels with the parents).  */
+  int group;
+};
+
+/* Parsing state.  This is provided to parsing functions called by argp,
+   which may examine and, as noted, modify fields.  */
+struct argp_state
+{
+  /* The top level ARGP being parsed.  */
+  __const struct argp *root_argp;
+
+  /* The argument vector being parsed.  May be modified.  */
+  int argc;
+  char **argv;
+
+  /* The index in ARGV of the next arg that to be parsed.  May be modified. */
+  int next;
+
+  /* The flags supplied to argp_parse.  May be modified.  */
+  unsigned flags;
+
+  /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the
+     number of the current arg, starting at zero, and incremented after each
+     such call returns.  At all other times, this is the number of such
+     arguments that have been processed.  */
+  unsigned arg_num;
+
+  /* If non-zero, the index in ARGV of the first argument following a special
+     `--' argument (which prevents anything following being interpreted as an
+     option).  Only set once argument parsing has proceeded past this point. */
+  int quoted;
+
+  /* An arbitrary pointer passed in from the user.  */
+  void *input;
+  /* Values to pass to child parsers.  This vector will be the same length as
+     the number of children for the current parser.  */
+  void **child_inputs;
+
+  /* For the parser's use.  Initialized to 0.  */
+  void *hook;
+
+  /* The name used when printing messages.  This is initialized to ARGV[0],
+     or PROGRAM_INVOCATION_NAME if that is unavailable.  */
+  char *name;
+
+  /* Streams used when argp prints something.  */
+  FILE *err_stream;            /* For errors; initialized to stderr. */
+  FILE *out_stream;            /* For information; initialized to stdout. */
+
+  void *pstate;                        /* Private, for use by argp.  */
+};
+
+/* Flags for argp_parse (note that the defaults are those that are
+   convenient for program command line parsing): */
+
+/* Don't ignore the first element of ARGV.  Normally (and always unless
+   ARGP_NO_ERRS is set) the first element of the argument vector is
+   skipped for option parsing purposes, as it corresponds to the program name
+   in a command line.  */
+#define ARGP_PARSE_ARGV0  0x01
+
+/* Don't print error messages for unknown options to stderr; unless this flag
+   is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program
+   name in the error messages.  This flag implies ARGP_NO_EXIT (on the
+   assumption that silent exiting upon errors is bad behaviour).  */
+#define ARGP_NO_ERRS   0x02
+
+/* Don't parse any non-option args.  Normally non-option args are parsed by
+   calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg
+   as the value.  Since it's impossible to know which parse function wants to
+   handle it, each one is called in turn, until one returns 0 or an error
+   other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the
+   argp_parse returns prematurely (but with a return value of 0).  If all
+   args have been parsed without error, all parsing functions are called one
+   last time with a key of ARGP_KEY_END.  This flag needn't normally be set,
+   as the normal behavior is to stop parsing as soon as some argument can't
+   be handled.  */
+#define ARGP_NO_ARGS   0x04
+
+/* Parse options and arguments in the same order they occur on the command
+   line -- normally they're rearranged so that all options come first. */
+#define ARGP_IN_ORDER  0x08
+
+/* Don't provide the standard long option --help, which causes usage and
+      option help information to be output to stdout, and exit (0) called. */
+#define ARGP_NO_HELP   0x10
+
+/* Don't exit on errors (they may still result in error messages).  */
+#define ARGP_NO_EXIT   0x20
+
+/* Use the gnu getopt `long-only' rules for parsing arguments.  */
+#define ARGP_LONG_ONLY 0x40
+
+/* Turns off any message-printing/exiting options.  */
+#define ARGP_SILENT    (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP)
+
+/* Parse the options strings in ARGC & ARGV according to the options in ARGP.
+   FLAGS is one of the ARGP_ flags above.  If ARG_INDEX is non-NULL, the
+   index in ARGV of the first unparsed option is returned in it.  If an
+   unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser
+   routine returned a non-zero value, it is returned; otherwise 0 is
+   returned.  This function may also call exit unless the ARGP_NO_HELP flag
+   is set.  INPUT is a pointer to a value to be passed in to the parser.  */
+extern error_t argp_parse (__const struct argp *__restrict __argp,
+                          int __argc, char **__restrict __argv,
+                          unsigned __flags, int *__restrict __arg_index,
+                          void *__restrict __input) __THROW;
+extern error_t __argp_parse (__const struct argp *__restrict __argp,
+                            int __argc, char **__restrict __argv,
+                            unsigned __flags, int *__restrict __arg_index,
+                            void *__restrict __input) __THROW;
+
+/* Global variables.  */
+
+/* If defined or set by the user program to a non-zero value, then a default
+   option --version is added (unless the ARGP_NO_HELP flag is used), which
+   will print this string followed by a newline and exit (unless the
+   ARGP_NO_EXIT flag is used).  Overridden by ARGP_PROGRAM_VERSION_HOOK.  */
+extern __const char *argp_program_version;
+
+/* If defined or set by the user program to a non-zero value, then a default
+   option --version is added (unless the ARGP_NO_HELP flag is used), which
+   calls this function with a stream to print the version to and a pointer to
+   the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
+   used).  This variable takes precedent over ARGP_PROGRAM_VERSION.  */
+extern void (*argp_program_version_hook) (FILE *__restrict __stream,
+                                         struct argp_state *__restrict
+                                         __state);
+
+/* If defined or set by the user program, it should point to string that is
+   the bug-reporting address for the program.  It will be printed by
+   argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
+   standard help messages), embedded in a sentence that says something like
+   `Report bugs to ADDR.'.  */
+extern __const char *argp_program_bug_address;
+
+/* The exit status that argp will use when exiting due to a parsing error.
+   If not defined or set by the user program, this defaults to EX_USAGE from
+   <sysexits.h>.  */
+extern error_t argp_err_exit_status;
+
+/* Flags for argp_help.  */
+#define ARGP_HELP_USAGE                0x01 /* a Usage: message. */
+#define ARGP_HELP_SHORT_USAGE  0x02 /*  " but don't actually print options. */
+#define ARGP_HELP_SEE          0x04 /* a `Try ... for more help' message. */
+#define ARGP_HELP_LONG         0x08 /* a long help message. */
+#define ARGP_HELP_PRE_DOC      0x10 /* doc string preceding long help.  */
+#define ARGP_HELP_POST_DOC     0x20 /* doc string following long help.  */
+#define ARGP_HELP_DOC          (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
+#define ARGP_HELP_BUG_ADDR     0x40 /* bug report address */
+#define ARGP_HELP_LONG_ONLY    0x80 /* modify output appropriately to
+                                       reflect ARGP_LONG_ONLY mode.  */
+
+/* These ARGP_HELP flags are only understood by argp_state_help.  */
+#define ARGP_HELP_EXIT_ERR     0x100 /* Call exit(1) instead of returning.  */
+#define ARGP_HELP_EXIT_OK      0x200 /* Call exit(0) instead of returning.  */
+
+/* The standard thing to do after a program command line parsing error, if an
+   error message has already been printed.  */
+#define ARGP_HELP_STD_ERR \
+  (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
+/* The standard thing to do after a program command line parsing error, if no
+   more specific error message has been printed.  */
+#define ARGP_HELP_STD_USAGE \
+  (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
+/* The standard thing to do in response to a --help option.  */
+#define ARGP_HELP_STD_HELP \
+  (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
+   | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
+
+/* Output a usage message for ARGP to STREAM.  FLAGS are from the set
+   ARGP_HELP_*.  */
+extern void argp_help (__const struct argp *__restrict __argp,
+                      FILE *__restrict __stream,
+                      unsigned __flags, char *__restrict __name) __THROW;
+extern void __argp_help (__const struct argp *__restrict __argp,
+                        FILE *__restrict __stream, unsigned __flags,
+                        char *__name) __THROW;
+
+/* The following routines are intended to be called from within an argp
+   parsing routine (thus taking an argp_state structure as the first
+   argument).  They may or may not print an error message and exit, depending
+   on the flags in STATE -- in any case, the caller should be prepared for
+   them *not* to exit, and should return an appropiate error after calling
+   them.  [argp_usage & argp_error should probably be called argp_state_...,
+   but they're used often enough that they should be short]  */
+
+/* Output, if appropriate, a usage message for STATE to STREAM.  FLAGS are
+   from the set ARGP_HELP_*.  */
+extern void argp_state_help (__const struct argp_state *__restrict __state,
+                            FILE *__restrict __stream,
+                            unsigned int __flags) __THROW;
+extern void __argp_state_help (__const struct argp_state *__restrict __state,
+                              FILE *__restrict __stream,
+                              unsigned int __flags) __THROW;
+
+/* Possibly output the standard usage message for ARGP to stderr and exit.  */
+extern void argp_usage (__const struct argp_state *__state) __THROW;
+extern void __argp_usage (__const struct argp_state *__state) __THROW;
+
+/* If appropriate, print the printf string FMT and following args, preceded
+   by the program name and `:', to stderr, and followed by a `Try ... --help'
+   message, then exit (1).  */
+extern void argp_error (__const struct argp_state *__restrict __state,
+                       __const char *__restrict __fmt, ...) __THROW
+     PRINTF_STYLE(2,3);
+extern void __argp_error (__const struct argp_state *__restrict __state,
+                         __const char *__restrict __fmt, ...) __THROW
+     PRINTF_STYLE(2,3);
+
+/* Similar to the standard gnu error-reporting function error(), but will
+   respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
+   to STATE->err_stream.  This is useful for argument parsing code that is
+   shared between program startup (when exiting is desired) and runtime
+   option parsing (when typically an error code is returned instead).  The
+   difference between this function and argp_error is that the latter is for
+   *parsing errors*, and the former is for other problems that occur during
+   parsing but don't reflect a (syntactic) problem with the input.  */
+extern void argp_failure (__const struct argp_state *__restrict __state,
+                         int __status, int __errnum,
+                         __const char *__restrict __fmt, ...) __THROW
+     PRINTF_STYLE(4,5);
+extern void __argp_failure (__const struct argp_state *__restrict __state,
+                           int __status, int __errnum,
+                           __const char *__restrict __fmt, ...) __THROW
+     PRINTF_STYLE(4,5);
+
+/* Returns true if the option OPT is a valid short option.  */
+extern int _option_is_short (__const struct argp_option *__opt) __THROW;
+extern int __option_is_short (__const struct argp_option *__opt) __THROW;
+
+/* Returns true if the option OPT is in fact the last (unused) entry in an
+   options array.  */
+extern int _option_is_end (__const struct argp_option *__opt) __THROW;
+extern int __option_is_end (__const struct argp_option *__opt) __THROW;
+
+/* Return the input field for ARGP in the parser corresponding to STATE; used
+   by the help routines.  */
+extern void *_argp_input (__const struct argp *__restrict __argp,
+                         __const struct argp_state *__restrict __state)
+     __THROW;
+extern void *__argp_input (__const struct argp *__restrict __argp,
+                          __const struct argp_state *__restrict __state)
+     __THROW;
+
+/* Used for extracting the program name from argv[0] */
+extern char *_argp_basename(char *name) __THROW;
+extern char *__argp_basename(char *name) __THROW;
+
+/* Getting the program name given an argp state */
+extern char *
+_argp_short_program_name(const struct argp_state *state) __THROW;
+extern char *
+__argp_short_program_name(const struct argp_state *state) __THROW;
+
+
+#ifdef __USE_EXTERN_INLINES
+
+# if !_LIBC
+#  define __argp_usage argp_usage
+#  define __argp_state_help argp_state_help
+#  define __option_is_short _option_is_short
+#  define __option_is_end _option_is_end
+# endif
+
+# ifndef ARGP_EI
+#  define ARGP_EI extern __inline__
+# endif
+
+ARGP_EI void
+__argp_usage (__const struct argp_state *__state) __THROW
+{
+  __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
+}
+
+ARGP_EI int
+__option_is_short (__const struct argp_option *__opt) __THROW
+{
+  if (__opt->flags & OPTION_DOC)
+    return 0;
+  else
+    {
+      int __key = __opt->key;
+      return __key > 0 && isprint (__key);
+    }
+}
+
+ARGP_EI int
+__option_is_end (__const struct argp_option *__opt) __THROW
+{
+  return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
+}
+
+# if !_LIBC
+#  undef __argp_usage
+#  undef __argp_state_help
+#  undef __option_is_short
+#  undef __option_is_end
+# endif
+#endif /* Use extern inlines.  */
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* argp.h */
diff --git a/tools/libargp/config.h b/tools/libargp/config.h
new file mode 100644
--- /dev/null
+++ b/tools/libargp/config.h
@@ -0,0 +1,106 @@
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the declaration of `program_invocation_name', and
+   to 0 if you don't. */
+#define HAVE_DECL_PROGRAM_INVOCATION_NAME 0
+
+/* Define to 1 if you have the declaration of `program_invocation_short_name',
+   and to 0 if you don't. */
+#define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 0
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#define HAVE_DOPRNT 1
+
+/* Define to 1 if you have the `flockfile' function. */
+#define HAVE_FLOCKFILE 1
+
+/* Define if the compiler understands __attribute__ */
+#define HAVE_GCC_ATTRIBUTE 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `putc_unlocked' function. */
+#define HAVE_PUTC_UNLOCKED 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Name of package */
+#define PACKAGE "argp"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "standalone-1.3"
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#if __GNUC__ && HAVE_GCC_ATTRIBUTE
+# define NORETURN __attribute__ ((__noreturn__))
+# define PRINTF_STYLE(f, a) __attribute__ ((__format__ (__printf__, f, a)))
+# define UNUSED __attribute__ ((__unused__))
+#else
+# define NORETURN
+# define PRINTF_STYLE(f, a)
+# define UNUSED
+#endif
diff --git a/tools/libargp/mempcpy.c b/tools/libargp/mempcpy.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/mempcpy.c
@@ -0,0 +1,18 @@
+/* strndup.c
+ *
+ */
+
+/* Written by Niels Möller <nisse@xxxxxxxxxxxxxx>
+ *
+ * This file is hereby placed in the public domain.
+ */
+
+#include <string.h>
+
+void *
+mempcpy (void *to, const void *from, size_t size)
+{
+  memcpy(to, from, size);
+  return (char *) to + size;
+}
+
diff --git a/tools/libargp/strchrnul.c b/tools/libargp/strchrnul.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/strchrnul.c
@@ -0,0 +1,21 @@
+/* strchrnul.c
+ *
+ */
+
+/* Written by Niels Möller <nisse@xxxxxxxxxxxxxx>
+ *
+ * This file is hereby placed in the public domain.
+ */
+
+/* FIXME: What is this function supposed to do? My guess is that it is
+ * like strchr, but returns a pointer to the NUL character, not a NULL
+ * pointer, if the character isn't found. */
+
+char *strchrnul(const char *s, int c)
+{
+  const char *p = s;
+  while (*p && (*p != c))
+    p++;
+
+  return (char *) p;
+}
diff --git a/tools/libargp/strndup.c b/tools/libargp/strndup.c
new file mode 100644
--- /dev/null
+++ b/tools/libargp/strndup.c
@@ -0,0 +1,31 @@
+/* strndup.c
+ *
+ */
+
+/* Written by Niels Möller <nisse@xxxxxxxxxxxxxx>
+ *
+ * This file is hereby placed in the public domain.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+char *
+strndup (const char *s, size_t size)
+{
+  char *r;
+  char *end = memchr(s, 0, size);
+  
+  if (end)
+    /* Length + 1 */
+    size = end - s + 1;
+  
+  r = malloc(size);
+
+  if (size)
+    {
+      memcpy(r, s, size-1);
+      r[size-1] = '\0';
+    }
+  return r;
+}
diff --git a/tools/xenmon/Makefile b/tools/xenmon/Makefile
--- a/tools/xenmon/Makefile
+++ b/tools/xenmon/Makefile
@@ -15,10 +15,14 @@ include $(XEN_ROOT)/tools/Rules.mk
 
 sbindir=/usr/sbin
 
+CFLAGS-$(CONFIG_SunOS) = -I ../libargp
+CFLAGS  += $(CFLAGS-y)
 CFLAGS  += -Werror
 CFLAGS  += -I $(XEN_XC)
 CFLAGS  += -I $(XEN_LIBXC)
 LDFLAGS += -L $(XEN_LIBXC)
+LDLIBS-$(CONFIG_SunOS) = ../libargp/libargp.a
+LDLIBS = -lxenctrl $(LDLIBS-y)
 
 BIN = xentrace_setmask xenbaked
 SCRIPTS = xenmon.py
@@ -42,6 +46,6 @@ clean:
 
 
 %: %.c Makefile
-       $(CC) $(CFLAGS) $(LDFLAGS) -lxenctrl -o $@ $<
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) 
 xentrace_%: %.c Makefile
-       $(CC) $(CFLAGS) $(LDFLAGS) -lxenctrl -o $@ $<
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -57,7 +57,6 @@ typedef struct { int counter; } atomic_t
 #include <xen/trace.h>
 #include "xenbaked.h"
 
-extern FILE *stderr;
 
 /***** Compile time configuration of defaults ********************************/
 
diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile
--- a/tools/xentrace/Makefile
+++ b/tools/xentrace/Makefile
@@ -1,10 +1,13 @@ XEN_ROOT=../..
 XEN_ROOT=../..
 include $(XEN_ROOT)/tools/Rules.mk
 
+CFLAGS-$(CONFIG_SunOS) = -I ../libargp 
+CFLAGS  += $(CFLAGS-y)
 CFLAGS  += -Werror
-
 CFLAGS  += -I $(XEN_XC)
 CFLAGS  += -I $(XEN_LIBXC)
+LDLIBS-$(CONFIG_SunOS) = ../libargp/libargp.a
+LDLIBS = -lxenctrl $(LDLIBS-y) 
 
 HDRS     = $(wildcard *.h)
 OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
@@ -52,6 +55,6 @@ clean:
        $(RM) *.a *.so *.o *.rpm $(BIN) $(LIBBIN)
 
 %: %.c $(HDRS) Makefile
-       $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl
+       $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) $(LDLIBS) 
 xentrace_%: %.c $(HDRS) Makefile
-       $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl
+       $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) $(LDLIBS) 
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -36,7 +36,6 @@ do {                                    
     errno = __saved_errno;                                      \
 } while (0)
 
-extern FILE *stderr;
 
 /***** Compile time configuration of defaults ********************************/
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>