fix windows build, add argp to tree to allow building for windows

This commit is contained in:
Carl Philipp Klemm 2023-07-10 15:55:39 +02:00
parent e25d7347c6
commit ff6b89b495
19 changed files with 5951 additions and 2 deletions

View file

@ -11,6 +11,17 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(SRC_FILES eismultiplexer.c usbshm.c) set(SRC_FILES eismultiplexer.c usbshm.c)
message("Platform " ${CMAKE_SYSTEM_NAME})
if(WIN32)
message("Building for Windows")
file(GLOB_RECURSE ARGP_SRC ${PROJECT_SOURCE_DIR}/argp/*.*)
set(SRC_FILES ${SRC_FILES} ${ARGP_SRC})
include_directories(./argp)
else()
message("Building for UNIX")
endif(WIN32)
add_library(${PROJECT_NAME} SHARED ${SRC_FILES}) add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
target_link_libraries(${PROJECT_NAME} ${LIBUSB_LIBRARIES}) target_link_libraries(${PROJECT_NAME} ${LIBUSB_LIBRARIES})
target_include_directories(${PROJECT_NAME} PUBLIC ${LIBUSB_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PUBLIC ${LIBUSB_INCLUDE_DIRS})

26
argp/argp-ba.c Normal file
View file

@ -0,0 +1,26 @@
/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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;

34
argp/argp-eexst.c Normal file
View file

@ -0,0 +1,34 @@
/* 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@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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
/* Modified by Chris Piker, 2009-03-10 */
/* #include <sysexits.h> */
#define EX_USAGE 64 /* command line usage error */
#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;

474
argp/argp-fmtstream.c Normal file
View file

@ -0,0 +1,474 @@
/* Word-wrapping and line-truncating streams
Copyright (C) 1997-1999,2001,2002,2003,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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"
#ifndef isblank
#define isblank(ch) ((ch)==' ' || (ch)=='\t')
#endif
#define INIT_BUF_SIZE 200
#define PRINTF_SIZE_GUESS 150
/* The inline functions from argp-fmtstream.h */
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;
}
/* End of the inlines from argp-fmtstream.h */
/* 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;
fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
if (fs != NULL)
{
fs->stream = stream;
fs->lmargin = lmargin;
fs->rmargin = rmargin;
fs->wmargin = wmargin;
fs->point_col = 0;
fs->point_offs = 0;
fs->buf = (char *) 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;
}
/* 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 (fs->buf, 1, fs->p - fs->buf, fs->stream);
}
free (fs->buf);
free (fs);
}
/* 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 (' ', 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)
&& fs->p > nextline)
{
/* 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 (fs->buf, 1, nl - fs->buf, fs->stream);
putc ('\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 (' ', 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 (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 old_size = fs->end - fs->buf;
size_t new_size = old_size + amount;
char *new_buf;
if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
{
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, ...)
{
int 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 ((size_t) out >= avail)
size_guess = out + 1;
}
while ((size_t) out >= avail);
fs->p += out;
return out;
}

120
argp/argp-fmtstream.h Normal file
View file

@ -0,0 +1,120 @@
/* Word-wrapping and line-truncating streams.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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>
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
# define __attribute__(Spec) /* empty */
# endif
/* The __-protected variants of `format' and `printf' attributes
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
# define __format__ format
# define __printf__ printf
# endif
#endif
/* Guess we have to define our own version. */
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);
/* Flush __FS to its stream, and free it (but don't close the stream). */
extern void argp_fmtstream_free (argp_fmtstream_t __fs);
extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
const char *__fmt, ...)
__attribute__ ((__format__ (printf, 2, 3)));
extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
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);
/* 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)
/* 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);
/* 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);
/* 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);
/* Return the column number of the current output point in __FS. */
extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
/* Internal routines. */
extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
#endif /* argp-fmtstream.h */

44
argp/argp-fs-xinl.c Normal file
View file

@ -0,0 +1,44 @@
/* Real definitions for extern inline functions in argp-fmtstream.h
Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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
#define ARGP_FS_EI
#undef __OPTIMIZE__
#define __OPTIMIZE__ 1
#include "argp-fmtstream.h"
#if 0
/* Not exported. */
/* Add weak aliases. */
#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias)
weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc)
weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts)
weak_alias (__argp_fmtstream_write, argp_fmtstream_write)
weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin)
weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin)
weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin)
weak_alias (__argp_fmtstream_point, argp_fmtstream_point)
#endif
#endif

1887
argp/argp-help.c Normal file

File diff suppressed because it is too large Load diff

993
argp/argp-parse.c Normal file
View file

@ -0,0 +1,993 @@
/* Hierarchial argument parsing, layered over getopt
Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* cwp: solaris 10 hack */
#define HAVE_ALLOCA_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/* cwp: solaris 10 hack */
//#include <alloca.h>
/* AIX requires this to be the first thing in the file. */
/* #ifndef __GNUC__
/* # if HAVE_ALLOCA_H || defined _LIBC */
/* # 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 "./getopt.h"
#include "./getopt_int.h"
#ifdef __MINGW32__
#include <malloc.h>
#include <windows.h>
/* Use windows API millisecond sleep */
#define sleep(n) Sleep(1000 * n)
#endif
#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) \
INTUSE(__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
#include "argp.h"
/* Getopt return values. */
#define KEY_END (-1) /* The end of the options. */
#define KEY_ARG 1 /* A non-option argument. */
#define KEY_ERR '?' /* An error parsing the options. */
/* The meta-argument used to prevent any further arguments being interpreted
as options. */
#define QUOTE "--"
/* The number of bits we steal in a long-option value for our own use. */
#define GROUP_BITS CHAR_BIT
/* The number of bits available for the user value. */
#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
#define USER_MASK ((1 << USER_BITS) - 1)
/* 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. */
static 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")},
{"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")},
{"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
N_("Hang for SECS seconds (default 3600)")},
{0, 0}
};
void argp_usage (const struct argp_state *__state)
{
argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
}
int _option_is_short (const struct argp_option *__opt)
{
if (__opt->flags & OPTION_DOC)
return 0;
else
{
int __key = __opt->key;
return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
}
}
int _option_is_end (const struct argp_option *__opt)
{
return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
}
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 defined _LIBC || 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 = strrchr (arg, '/');
if (state->name)
state->name++;
else
state->name = arg;
#if defined _LIBC || 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");
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}
};
static error_t
argp_version_parser (int key, char *arg, 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"};
/* Returns the offset into the getopt long options array LONG_OPTIONS of a
long option with called NAME, or -1 if none is found. Passing NULL as
NAME will return the number of options. */
static int
find_long_option (struct option *long_options, const char *name)
{
struct option *l = long_options;
while (l->name != NULL)
if (name != NULL && strcmp (l->name, name) == 0)
return l - long_options;
else
l++;
if (name == NULL)
return l - long_options;
else
return -1;
}
/* 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;
/* Points to the point in SHORT_OPTS corresponding to the end of the short
options for this group. We use it to determine from which group a
particular short options is from. */
char *short_end;
/* 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;
/* SHORT_OPTS is the getopt short options string for the union of all the
groups of options. */
char *short_opts;
/* LONG_OPTS is the array of getop long option structures for the union of
all the groups of options. */
struct option *long_opts;
/* OPT_DATA is the getopt data used for the re-entrant getopt. */
struct _getopt_data opt_data;
/* 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;
/* True if we think using getopt is still useful; if false, then
remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is
cleared whenever getopt returns KEY_END, but may be set again if the user
moves the next argument pointer backwards. */
int try_getopt;
/* State block supplied to parsing routines. */
struct argp_state state;
/* Memory used by this parser. */
void *storage;
};
/* 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;
struct option *long_end;
void **child_inputs_end;
};
/* Converts all options in ARGP (which is put in GROUP) and ancestors
into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and
CVT->LONG_END are the points at which new options are added. 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)
{
/* REAL is the most recent non-alias value of OPT. */
const struct argp_option *real = argp->options;
const struct argp_child *children = argp->children;
if (real || argp->parser)
{
const struct argp_option *opt;
if (real)
for (opt = real; !_option_is_end (opt); opt++)
{
if (! (opt->flags & OPTION_ALIAS))
/* OPT isn't an alias, so we can use values from it. */
real = opt;
if (! (real->flags & OPTION_DOC))
/* A real option (not just documentation). */
{
if (_option_is_short (opt))
/* OPT can be used as a short option. */
{
*cvt->short_end++ = opt->key;
if (real->arg)
{
*cvt->short_end++ = ':';
if (real->flags & OPTION_ARG_OPTIONAL)
*cvt->short_end++ = ':';
}
*cvt->short_end = '\0'; /* keep 0 terminated */
}
if (opt->name
&& find_long_option (cvt->parser->long_opts, opt->name) < 0)
/* OPT can be used as a long option. */
{
cvt->long_end->name = opt->name;
cvt->long_end->has_arg =
(real->arg
? (real->flags & OPTION_ARG_OPTIONAL
? optional_argument
: required_argument)
: no_argument);
cvt->long_end->flag = 0;
/* we add a disambiguating code to all the user's
values (which is removed before we actually call
the function to parse the value); this means that
the user loses use of the high 8 bits in all his
values (the sign of the lower bits is preserved
however)... */
cvt->long_end->val =
((opt->key | real->key) & USER_MASK)
+ (((group - cvt->parser->groups) + 1) << USER_BITS);
/* Keep the LONG_OPTS list terminated. */
(++cvt->long_end)->name = NULL;
}
}
}
group->parser = argp->parser;
group->argp = argp;
group->short_end = cvt->short_end;
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;
}
/* Find the merged set of getopt options, with keys appropiately prefixed. */
static void
parser_convert (struct parser *parser, const struct argp *argp, int flags)
{
struct parser_convert_state cvt;
cvt.parser = parser;
cvt.short_end = parser->short_opts;
cvt.long_end = parser->long_opts;
cvt.child_inputs_end = parser->child_inputs;
if (flags & ARGP_IN_ORDER)
*cvt.short_end++ = '-';
else if (flags & ARGP_NO_ARGS)
*cvt.short_end++ = '+';
*cvt.short_end = '\0';
cvt.long_end->name = NULL;
parser->argp = argp;
if (argp)
parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
else
parser->egroup = parser->groups; /* No parsers at all! */
}
/* Lengths of various parser fields which we will allocated. */
struct parser_sizes
{
size_t short_len; /* Getopt short options string. */
size_t long_len; /* Getopt long options vector. */
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 & LONG_LEN fields by
the maximum lengths of the resulting merged getopt short options string and
long-options array, respectively. */
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)
{
szs->num_groups++;
if (opt)
{
int num_opts = 0;
while (!_option_is_end (opt++))
num_opts++;
szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */
szs->long_len += num_opts;
}
}
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;
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
szs.long_len = 0;
szs.num_groups = 0;
szs.num_child_inputs = 0;
if (argp)
calc_sizes (argp, &szs);
/* 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 LLEN ((szs.long_len + 1) * sizeof (struct option))
#define SLEN (szs.short_len + 1)
parser->storage = malloc (GLEN + CLEN + LLEN + SLEN);
if (! parser->storage)
return ENOMEM;
/* In C, sizeof(void) is taken to be 1, so we can use char* casts
to make the sun compiler happy and keep with the intent of the
developers. --cwp */
parser->groups = parser->storage;
parser->child_inputs = (void**) (((char*)parser->storage) + GLEN);
parser->long_opts = (struct option *) (((char*)parser->storage) + GLEN + CLEN);
parser->short_opts = ((char*)parser->storage) + GLEN + CLEN + LLEN;
parser->opt_data = opt_data;
memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
parser_convert (parser, argp, flags);
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.next = 0; /* Tell getopt to initialize. */
parser->state.pstate = parser;
parser->try_getopt = 1;
/* 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 (parser->state.flags & ARGP_NO_ERRS)
{
parser->opt_data.opterr = 0;
if (parser->state.flags & ARGP_PARSE_ARGV0)
/* getopt always skips ARGV[0], so we have to fake it out. As long
as OPTERR is 0, then it shouldn't actually try to access it. */
parser->state.argv--, parser->state.argc++;
}
else
parser->opt_data.opterr = 1; /* Print error messages. */
if (parser->state.argv == argv && argv[0])
/* There's an argv[0]; use it for messages. */
{
#ifndef _WIN32
char *short_name = strrchr (argv[0], '/');
#else
char *short_name = strrchr (argv[0], '\\');
#endif
parser->state.name = short_name ? short_name + 1 : argv[0];
}
else
parser->state.name = argp_short_program_name ();
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 is assumed to have
been adjusted (by getopt) to point after this argument; this function will
adjust it correctly to reflect however many args actually end up being
consumed. */
static error_t
parser_parse_arg (struct parser *parser, char *val)
{
/* Save the starting value of NEXT, first adjusting it so that the arg
we're parsing is again the front of the arg vector. */
int index = --parser->state.next;
error_t err = EBADKEY;
struct group *group;
int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */
/* Try to parse the argument in each parser. */
for (group = parser->groups
; group < parser->egroup && err == EBADKEY
; group++)
{
parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */
key = ARGP_KEY_ARG;
err = group_parse (group, &parser->state, key, val);
if (err == EBADKEY)
/* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */
{
parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */
key = ARGP_KEY_ARGS;
err = group_parse (group, &parser->state, key, 0);
}
}
if (! err)
{
if (key == ARGP_KEY_ARGS)
/* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
changed by the user, *all* arguments should be considered
consumed. */
parser->state.next = parser->state.argc;
if (parser->state.next > index)
/* Remember that we successfully processed a non-option
argument -- but only if the user hasn't gotten tricky and set
the clock back. */
(--group)->args_processed += (parser->state.next - index);
else
/* The user wants to reparse some args, give getopt another try. */
parser->try_getopt = 1;
}
return err;
}
/* Call the user parsers to parse the option OPT, with argument VAL, at the
current position, returning any error. */
static error_t
parser_parse_opt (struct parser *parser, int opt, char *val)
{
/* The group key encoded in the high bits; 0 for short opts or
group_number + 1 for long opts. */
int group_key = opt >> USER_BITS;
error_t err = EBADKEY;
if (group_key == 0)
/* A short option. By comparing OPT's position in SHORT_OPTS to the
various starting positions in each group's SHORT_END field, we can
determine which group OPT came from. */
{
struct group *group;
char *short_index = strchr (parser->short_opts, opt);
if (short_index)
for (group = parser->groups; group < parser->egroup; group++)
if (group->short_end > short_index)
{
err = group_parse (group, &parser->state, opt,
parser->opt_data.optarg);
break;
}
}
else
/* A long option. We use shifts instead of masking for extracting
the user value in order to preserve the sign. */
err =
group_parse (&parser->groups[group_key - 1], &parser->state,
(opt << GROUP_BITS) >> GROUP_BITS,
parser->opt_data.optarg);
if (err == EBADKEY)
/* At least currently, an option not recognized is an error in the
parser, because we pre-compute which parser is supposed to deal
with each option. */
{
static const char bad_key_err[] =
N_("(PROGRAM ERROR) Option should have been recognized!?");
if (group_key == 0)
argp_error (&parser->state, "-%c: %s", opt,
dgettext (parser->argp->argp_domain, bad_key_err));
else
{
struct option *long_opt = parser->long_opts;
while (long_opt->val != opt && long_opt->name)
long_opt++;
argp_error (&parser->state, "--%s: %s",
long_opt->name ? long_opt->name : "???",
dgettext (parser->argp->argp_domain, bad_key_err));
}
}
return err;
}
/* 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)
{
int opt;
error_t err = 0;
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 give getopt
another chance. If the user hasn't removed it, getopt will just
process it again. */
parser->state.quoted = 0;
if (parser->try_getopt && !parser->state.quoted)
/* Give getopt a chance to parse this. */
{
/* Put it back in OPTIND for getopt. */
parser->opt_data.optind = parser->state.next;
/* Distinguish KEY_ERR from a real option. */
parser->opt_data.optopt = KEY_END;
if (parser->state.flags & ARGP_LONG_ONLY)
opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0,
&parser->opt_data);
else
opt = _getopt_long_r (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0,
&parser->opt_data);
/* And see what getopt did. */
parser->state.next = parser->opt_data.optind;
if (opt == KEY_END)
/* Getopt says there are no more options, so stop using
getopt; we'll continue if necessary on our own. */
{
parser->try_getopt = 0;
if (parser->state.next > 1
&& strcmp (parser->state.argv[parser->state.next - 1], QUOTE)
== 0)
/* Not only is this the end of the options, but it's a
`quoted' region, which may have args that *look* like
options, so we definitely shouldn't try to use getopt past
here, whatever happens. */
parser->state.quoted = parser->state.next;
}
else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)
/* KEY_ERR can have the same value as a valid user short
option, but in the case of a real error, getopt sets OPTOPT
to the offending character, which can never be KEY_END. */
{
*arg_ebadkey = 0;
return EBADKEY;
}
}
else
opt = KEY_END;
if (opt == KEY_END)
{
/* We're past what getopt considers the options. */
if (parser->state.next >= parser->state.argc
|| (parser->state.flags & ARGP_NO_ARGS))
/* Indicate that we're done. */
{
*arg_ebadkey = 1;
return EBADKEY;
}
else
/* A non-option arg; simulate what getopt might have done. */
{
opt = KEY_ARG;
parser->opt_data.optarg = parser->state.argv[parser->state.next++];
}
}
if (opt == KEY_ARG)
/* A non-option argument; try each parser in turn. */
err = parser_parse_arg (parser, parser->opt_data.optarg);
else
err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
if (err == EBADKEY)
*arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
return err;
}
/* 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 = (struct argp_child *)alloca (4 * sizeof (struct argp_child));
struct argp *top_argp = (struct 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;
}
/* 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;
}

3
argp/argp-pin.c Normal file
View file

@ -0,0 +1,3 @@
#include <stdlib.h>
char *program_invocation_name = NULL;

25
argp/argp-pv.c Normal file
View file

@ -0,0 +1,25 @@
/* Default definition for ARGP_PROGRAM_VERSION.
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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;

32
argp/argp-pvh.c Normal file
View file

@ -0,0 +1,32 @@
/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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);

532
argp/argp.h Normal file
View file

@ -0,0 +1,532 @@
/* Hierarchial argument parsing, layered over getopt.
Copyright (C) 1995-1999, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Warning THIS IS NOT THE ORIGINAL gnu provided file!
*
* This file modified to compile as a standard library (not part of GLIBC)
* under the mingw environment by chris-piker@uiowa.edu
*/
#ifdef __linux__
#error Stop! Do not use this file it is a hacked version to port argp to windows and Solaris
#endif
#ifndef _ARGP_H
#define _ARGP_H
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#define __need_error_t
#include <errno.h>
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
# define __attribute__(Spec) /* empty */
# endif
/* The __-protected variants of `format' and `printf' attributes
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
# define __format__ format
# define __printf__ printf
# endif
#endif
#ifndef __error_t_defined
typedef int error_t;
# define __error_t_defined
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __MINGW32__
extern char *program_invocation_name;
#define HAVE_DECL_PROGRAM_INVOCATION_NAME 1
#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 punctuation 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 * argp,
int argc, char ** argv,
unsigned __flags, int * arg_index,
void * input);
/* 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 * __stream,
struct argp_state *
__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 * __argp,
FILE * __stream,
unsigned __flags, char * __name);
/* 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 * __state,
FILE * __stream,
unsigned int __flags);
/* Possibly output the standard usage message for ARGP to stderr and exit. */
extern void argp_usage (const struct argp_state *__state);
/* 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 * __state,
const char * __fmt, ...)
__attribute__ ((__format__ (__printf__, 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 * __state,
int __status, int __errnum,
const char * __fmt, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
/* Returns true if the option OPT is a valid short option. */
extern int _option_is_short (const struct argp_option *__opt) ;
/* 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) ;
/* Return the input field for ARGP in the parser corresponding to STATE; used
by the help routines. */
extern void *_argp_input (const struct argp * __argp,
const struct argp_state * __state);
char* argp_short_program_name (void);
#ifdef __cplusplus
}
#endif
#endif /* argp.h */

1194
argp/getopt.c Normal file

File diff suppressed because it is too large Load diff

177
argp/getopt.h Normal file
View file

@ -0,0 +1,177 @@
/* Declarations for getopt.
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifndef __THROW
# ifndef __GNUC_PREREQ
# define __GNUC_PREREQ(maj, min) (0)
# endif
# if defined __cplusplus && __GNUC_PREREQ (2,8)
# define __THROW throw ()
# else
# define __THROW
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW;
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* __GNU_LIBRARY__ */
#ifndef __need_getopt
extern int getopt_long (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
extern int getopt_long_only (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
#endif
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */

192
argp/getopt1.c Normal file
View file

@ -0,0 +1,192 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; 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
#ifdef _LIBC
# include <getopt.h>
#else
# include "getopt.h"
#endif
#include "getopt_int.h"
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (int argc, char *const *argv, const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
int
_getopt_long_r (int argc, char *const *argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
0, d);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (int argc, char *const *argv, const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
int
_getopt_long_only_r (int argc, char *const *argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
1, d);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (int argc, char **argv)
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

75
argp/getopt_init.c Normal file
View file

@ -0,0 +1,75 @@
/* Perform additional initialization for getopt functions in GNU libc.
Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifdef USE_NONOPTION_FLAGS
/* Attention: this file is *not* necessary when the GNU getopt functions
are used outside the GNU libc. Some additional functionality of the
getopt functions in GNU libc require this additional work. */
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio-common/_itoa.h>
/* Variable to synchronize work. */
char *__getopt_nonoption_flags;
/* Remove the environment variable "_<PID>_GNU_nonoption_argv_flags_" if
it is still available. If the getopt functions are also used in the
application it does not exist anymore since it was saved for the use
in getopt. */
void
__getopt_clean_environment (char **env)
{
/* Bash 2.0 puts a special variable in the environment for each
command it runs, specifying which ARGV elements are the results
of file name wildcard expansion and therefore should not be
considered as options. */
static const char envvar_tail[] = "_GNU_nonoption_argv_flags_=";
char var[50];
char *cp, **ep;
size_t len;
/* Construct the "_<PID>_GNU_nonoption_argv_flags_=" string. We must
not use `sprintf'. */
cp = memcpy (&var[sizeof (var) - sizeof (envvar_tail)], envvar_tail,
sizeof (envvar_tail));
cp = _itoa_word (__getpid (), cp, 10, 0);
/* Note: we omit adding the leading '_' since we explicitly test for
it before calling strncmp. */
len = (var + sizeof (var) - 1) - cp;
for (ep = env; *ep != NULL; ++ep)
if ((*ep)[0] == '_'
&& __builtin_expect (strncmp (*ep + 1, cp, len) == 0, 0))
{
/* Found it. Store this pointer and move later ones back. */
char **dp = ep;
__getopt_nonoption_flags = &(*ep)[len];
do
dp[0] = dp[1];
while (*dp++);
/* Continue the loop in case the name appears again. */
}
}
#endif /* USE_NONOPTION_FLAGS */

130
argp/getopt_int.h Normal file
View file

@ -0,0 +1,130 @@
/* Internal declarations for getopt.
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
extern int _getopt_internal (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
/* Reentrant versions which can handle parsing multiple argument
vectors at the same time. */
/* Data type for reentrant functions. */
struct _getopt_data
{
/* These have exactly the same meaning as the corresponding global
variables, except that they are used for the reentrant
versions of getopt. */
int optind;
int opterr;
int optopt;
char *optarg;
/* Internal members. */
/* True if the internal members have been initialized. */
int __initialized;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
char *__nextchar;
/* 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.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} __ordering;
/* If the POSIXLY_CORRECT environment variable is set. */
int __posixly_correct;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first
of them; `last_nonopt' is the index after the last of them. */
int __first_nonopt;
int __last_nonopt;
#if defined _LIBC && defined USE_NONOPTION_FLAGS
int __nonoption_flags_max_len;
int __nonoption_flags_len;
# endif
};
/* The initializer is necessary to set OPTIND and OPTERR to their
default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
extern int _getopt_internal_r (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data);
extern int _getopt_long_r (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
struct _getopt_data *__data);
extern int _getopt_long_only_r (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind,
struct _getopt_data *__data);
#endif /* getopt_int.h */

2
main.c
View file

@ -259,7 +259,9 @@ int main(int argc, char* argv[])
++i; ++i;
} }
eismultiplexer_set_led(&multiplexer, true);
int cmdRet = process_commands(commands, i, &multiplexer, ""); int cmdRet = process_commands(commands, i, &multiplexer, "");
eismultiplexer_set_led(&multiplexer, false);
if(cmdRet == 0) if(cmdRet == 0)
puts("OK"); puts("OK");
else else

View file

@ -67,7 +67,6 @@ void usbshm_distroy(struct usbshm* instance)
libusb_exit(NULL); libusb_exit(NULL);
pthread_mutex_destroy(libusbDataMutex); pthread_mutex_destroy(libusbDataMutex);
} }
} }
static void* usbshm_libusbPoll(void* arg) static void* usbshm_libusbPoll(void* arg)
@ -100,7 +99,6 @@ int usbshm_init(struct usbshm* instance, void (*dataCallback)(uint8_t request, u
ret = libusb_init(NULL) < 0 ? USBSHM_ERROR_ERR : 0; ret = libusb_init(NULL) < 0 ? USBSHM_ERROR_ERR : 0;
libusbDataMutex = malloc(sizeof(*libusbDataMutex)); libusbDataMutex = malloc(sizeof(*libusbDataMutex));
pthread_mutex_init(libusbDataMutex, NULL); pthread_mutex_init(libusbDataMutex, NULL);
//libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
pthread_create(&libusbThread, NULL, &usbshm_libusbPoll, NULL); pthread_create(&libusbThread, NULL, &usbshm_libusbPoll, NULL);
} }
if(ret == 0) objectCounter++; if(ret == 0) objectCounter++;