Commit 2db5c711 2db5c7115e5b37734993603c0381aab7e62c4be9 by Sergey Poznyakoff

Updated by gnulib-sync

1 parent 96aac328
/* Copyright (C) 1992, 1995, 1996, 1997, 2001 Free Software Foundation, Inc.
This file based on setenv.c in the GNU C Library.
/* Copyright (C) 1992,1995-1999,2000-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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <alloca.h>
#include <errno.h>
#if HAVE_STDLIB_H
# include <stdlib.h>
#else
#include <sys/types.h> /* For `size_t' */
#include <stdio.h> /* For `NULL' */
#endif
#if HAVE_STRING_H
# include <string.h>
#ifndef __set_errno
# define __set_errno(ev) ((errno) = (ev))
#endif
#if HAVE_UNISTD_H
#include <stdlib.h>
#include <string.h>
#if _LIBC || HAVE_UNISTD_H
# include <unistd.h>
#endif
#define __environ environ
#if !_LIBC
# include "allocsa.h"
#endif
#if !_LIBC
# define __environ environ
# ifndef HAVE_ENVIRON_DECL
extern char **environ;
# endif
#endif
/* LOCK and UNLOCK are defined as no-ops. This makes the libiberty
* implementation MT-Unsafe. */
#define LOCK
#define UNLOCK
#if _LIBC
/* This lock protects against simultaneous modifications of `environ'. */
# include <bits/libc-lock.h>
__libc_lock_define_initialized (static, envlock)
# define LOCK __libc_lock_lock (envlock)
# define UNLOCK __libc_lock_unlock (envlock)
#else
# define LOCK
# define UNLOCK
#endif
/* In the GNU C library we must keep the namespace clean. */
#ifdef _LIBC
# define setenv __setenv
# define clearenv __clearenv
# define tfind __tfind
# define tsearch __tsearch
#endif
/* In the GNU C library implementation we try to be more clever and
allow arbitrarily many changes of the environment given that the used
values are from a small set. Outside glibc this will eat up all
memory after a while. */
#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
&& defined __GNUC__)
# define USE_TSEARCH 1
# include <search.h>
typedef int (*compar_fn_t) (const void *, const void *);
/* This is a pointer to the root of the search tree with the known
values. */
static void *known_values;
# define KNOWN_VALUE(Str) \
({ \
void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \
value != NULL ? *(char **) value : NULL; \
})
# define STORE_VALUE(Str) \
tsearch (Str, &known_values, (compar_fn_t) strcmp)
#else
# undef USE_TSEARCH
# define KNOWN_VALUE(Str) NULL
# define STORE_VALUE(Str) do { } while (0)
#endif
/* Below this point, it's verbatim code from the glibc-2.0 implementation */
/* If this variable is not a null pointer we allocated the current
environment. */
static char **last_environ;
/* This function is used by `setenv' and `putenv'. The difference between
the two functions is that for the former must create a new string which
is then placed in the environment, while the argument of `putenv'
must be used directly. This is all complicated by the fact that we try
to reuse values once generated for a `setenv' call since we can never
free the strings. */
int
setenv (name, value, replace)
const char *name;
const char *value;
int replace;
__add_to_environ (const char *name, const char *value, const char *combined,
int replace)
{
register char **ep;
register size_t size;
const size_t namelen = strlen (name);
const size_t vallen = strlen (value) + 1;
const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
LOCK;
/* We have to get the pointer now that we have the lock and not earlier
since another thread might have created a new environment. */
ep = __environ;
size = 0;
if (__environ != NULL)
for (ep = __environ; *ep != NULL; ++ep)
if (ep != NULL)
{
for (; *ep != NULL; ++ep)
if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
break;
else
++size;
}
if (__environ == NULL || *ep == NULL)
if (ep == NULL || *ep == NULL)
{
char **new_environ;
if (__environ == last_environ && __environ != NULL)
/* We allocated this space; we can extend it. */
new_environ = (char **) realloc (last_environ,
(size + 2) * sizeof (char *));
else
new_environ = (char **) malloc ((size + 2) * sizeof (char *));
#ifdef USE_TSEARCH
char *new_value;
#endif
/* We allocated this space; we can extend it. */
new_environ =
(char **) (last_environ == NULL
? malloc ((size + 2) * sizeof (char *))
: realloc (last_environ, (size + 2) * sizeof (char *)));
if (new_environ == NULL)
{
UNLOCK;
return -1;
}
new_environ[size] = malloc (namelen + 1 + vallen);
if (new_environ[size] == NULL)
/* If the whole entry is given add it. */
if (combined != NULL)
/* We must not add the string to the search tree since it belongs
to the user. */
new_environ[size] = (char *) combined;
else
{
free ((char *) new_environ);
errno = ENOMEM;
/* See whether the value is already known. */
#ifdef USE_TSEARCH
# ifdef _LIBC
new_value = (char *) alloca (namelen + 1 + vallen);
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
value, vallen);
# else
new_value = (char *) allocsa (namelen + 1 + vallen);
if (new_value == NULL)
{
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
memcpy (new_value, name, namelen);
new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen);
# endif
if (__environ != last_environ)
memcpy ((char *) new_environ, (char *) __environ,
size * sizeof (char *));
new_environ[size] = KNOWN_VALUE (new_value);
if (new_environ[size] == NULL)
#endif
{
new_environ[size] = (char *) malloc (namelen + 1 + vallen);
if (new_environ[size] == NULL)
{
#if defined USE_TSEARCH && !defined _LIBC
freesa (new_value);
#endif
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
#ifdef USE_TSEARCH
memcpy (new_environ[size], new_value, namelen + 1 + vallen);
#else
memcpy (new_environ[size], name, namelen);
new_environ[size][namelen] = '=';
memcpy (&new_environ[size][namelen + 1], value, vallen);
#endif
/* And save the value now. We cannot do this when we remove
the string since then we cannot decide whether it is a
user string or not. */
STORE_VALUE (new_environ[size]);
}
#if defined USE_TSEARCH && !defined _LIBC
freesa (new_value);
#endif
}
if (__environ != last_environ)
memcpy ((char *) new_environ, (char *) __environ,
size * sizeof (char *));
new_environ[size + 1] = NULL;
......@@ -110,21 +214,63 @@ setenv (name, value, replace)
}
else if (replace)
{
size_t len = strlen (*ep);
if (len + 1 < namelen + 1 + vallen)
char *np;
/* Use the user string if given. */
if (combined != NULL)
np = (char *) combined;
else
{
/* The existing string is too short; malloc a new one. */
char *new = malloc (namelen + 1 + vallen);
if (new == NULL)
#ifdef USE_TSEARCH
char *new_value;
# ifdef _LIBC
new_value = alloca (namelen + 1 + vallen);
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
value, vallen);
# else
new_value = allocsa (namelen + 1 + vallen);
if (new_value == NULL)
{
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
*ep = new;
memcpy (new_value, name, namelen);
new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen);
# endif
np = KNOWN_VALUE (new_value);
if (np == NULL)
#endif
{
np = malloc (namelen + 1 + vallen);
if (np == NULL)
{
#if defined USE_TSEARCH && !defined _LIBC
freesa (new_value);
#endif
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
memcpy (*ep, name, namelen);
(*ep)[namelen] = '=';
memcpy (&(*ep)[namelen + 1], value, vallen);
#ifdef USE_TSEARCH
memcpy (np, new_value, namelen + 1 + vallen);
#else
memcpy (np, name, namelen);
np[namelen] = '=';
memcpy (&np[namelen + 1], value, vallen);
#endif
/* And remember the value. */
STORE_VALUE (np);
}
#if defined USE_TSEARCH && !defined _LIBC
freesa (new_value);
#endif
}
*ep = np;
}
UNLOCK;
......@@ -132,25 +278,51 @@ setenv (name, value, replace)
return 0;
}
void
unsetenv (name)
const char *name;
int
setenv (const char *name, const char *value, int replace)
{
const size_t len = strlen (name);
char **ep;
return __add_to_environ (name, value, NULL, replace);
}
/* The `clearenv' was planned to be added to POSIX.1 but probably
never made it. Nevertheless the POSIX.9 standard (POSIX bindings
for Fortran 77) requires this function. */
int
clearenv (void)
{
LOCK;
for (ep = __environ; *ep; ++ep)
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
if (__environ == last_environ && __environ != NULL)
{
/* Found it. Remove this pointer by moving later ones back. */
char **dp = ep;
do
dp[0] = dp[1];
while (*dp++);
/* Continue the loop in case NAME appears again. */
/* We allocated this environment so we can free it. */
free (__environ);
last_environ = NULL;
}
/* Clear the environment pointer removes the whole environment. */
__environ = NULL;
UNLOCK;
return 0;
}
#ifdef _LIBC
static void
free_mem (void)
{
/* Remove all traces. */
clearenv ();
/* Now remove the search tree. */
__tdestroy (known_values, free);
known_values = NULL;
}
text_set_element (__libc_subfreeres, free_mem);
# undef setenv
# undef clearenv
weak_alias (__setenv, setenv)
weak_alias (__clearenv, clearenv)
#endif
......
/*
Unix snprintf implementation.
Version 1.3
/* Formatted output to strings.
Copyright (C) 2004 Free Software Foundation, Inc.
Written by Simon Josefsson.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Revision History:
1.3:
* add #include <config.h> ifdef HAVE_CONFIG_H
* cosmetic change, when exponent is 0 print xxxE+00
instead of xxxE-00
1.2:
* put the program under LGPL.
1.1:
* added changes from Miles Bader
* corrected a bug with %f
* added support for %#g
* added more comments :-)
1.0:
* supporting must ANSI syntaxic_sugars
0.0:
* suppot %s %c %d
THANKS(for the patches and ideas):
Miles Bader
Cyrille Rustom
Jacek Slabocewiz
Mike Parker(mouse)
*/
#include "snprintf.h"
/*
* Find the nth power of 10
*/
PRIVATE double
#ifdef __STDC__
pow_10(int n)
#else
pow_10(n)
int n;
#endif
{
int i;
double P;
if (n < 0)
for (i = 1, P = 1., n = -n ; i <= n ; i++) {P *= .1;}
else
for (i = 1, P = 1. ; i <= n ; i++) {P *= 10.0;}
return P;
}
/*
* Find the integral part of the log in base 10
* Note: this not a real log10()
I just need and approximation(integerpart) of x in:
10^x ~= r
* log_10(200) = 2;
* log_10(250) = 2;
*/
PRIVATE int
#ifdef __STDC__
log_10(double r)
#else
log_10(r)
double r;
#endif
{
int i = 0;
double result = 1.;
if (r < 0.)
r = -r;
if (r < 1.) {
while (result >= r) {result *= .1; i++;}
return (-i);
} else {
while (result <= r) {result *= 10.; i++;}
return (i - 1);
}
}
/*
* This function return the fraction part of a double
* and set in ip the integral part.
* In many ways it resemble the modf() found on most Un*x
*/
PRIVATE double
#ifdef __STDC__
integral(double real, double * ip)
#else
integral(real, ip)
double real;
double * ip;
#endif
{
int j;
double i, s, p;
double real_integral = 0.;
/* take care of the obvious */
/* equal to zero ? */
if (real == 0.) {
*ip = 0.;
return (0.);
}
/* negative number ? */
if (real < 0.)
real = -real;
/* a fraction ? */
if ( real < 1.) {
*ip = 0.;
return real;
}
/* the real work :-) */
for (j = log_10(real); j >= 0; j--) {
p = pow_10(j);
s = (real - real_integral)/p;
i = 0.;
while (i + 1. <= s) {i++;}
real_integral += i*p;
}
*ip = real_integral;
return (real - real_integral);
}
#define PRECISION 1.e-6
/*
* return an ascii representation of the integral part of the number
* and set fract to be an ascii representation of the fraction part
* the container for the fraction and the integral part or staticly
* declare with fix size
*/
PRIVATE char *
#ifdef __STDC__
numtoa(double number, int base, int precision, char ** fract)
#else
numtoa(number, base, precision, fract)
double number;
int base;
int precision;
char ** fract;
#endif
{
register int i, j;
double ip, fp; /* integer and fraction part */
double fraction;
int digits = MAX_INT - 1;
static char integral_part[MAX_INT];
static char fraction_part[MAX_FRACT];
double sign;
int ch;
/* taking care of the obvious case: 0.0 */
if (number == 0.) {
integral_part[0] = '0';
integral_part[1] = '\0';
fraction_part[0] = '0';
fraction_part[1] = '\0';
return integral_part;
}
/* for negative numbers */
if ((sign = number) < 0.) {
number = -number;
digits--; /* sign consume one digit */
}
fraction = integral(number, &ip);
number = ip;
/* do the integral part */
if ( ip == 0.) {
integral_part[0] = '0';
i = 1;
} else {
for ( i = 0; i < digits && number != 0.; ++i) {
number /= base;
fp = integral(number, &ip);
ch = (int)((fp + PRECISION)*base); /* force to round */
integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
if (! isxdigit(integral_part[i])) /* bail out overflow !! */
break;
number = ip;
}
}
/* Oh No !! out of bound, ho well fill it up ! */
if (number != 0.)
for (i = 0; i < digits; ++i)
integral_part[i] = '9';
GNU General Public License for more details.
/* put the sign ? */
if (sign < 0.)
integral_part[i++] = '-';
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
integral_part[i] = '\0';
/* reverse every thing */
for ( i--, j = 0; j < i; j++, i--)
SWAP_INT(integral_part[i], integral_part[j]);
/* the fractionnal part */
for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision-- ) {
fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
if (! isdigit(fraction_part[i])) /* underflow ? */
break;
fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
}
fraction_part[i] = '\0';
if (fract != (char **)0)
*fract = fraction_part;
return integral_part;
}
/* for %d and friends, it puts in holder
* the representation with the right padding
*/
PRIVATE void
#ifdef __STDC__
decimal(struct DATA *p, double d)
#else
decimal(p, d)
struct DATA *p;
double d;
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
{
char *tmp;
tmp = itoa(d);
p->width -= strlen(tmp);
PAD_RIGHT(p);
PUT_PLUS(d, p);
PUT_SPACE(d, p);
while (*tmp) { /* the integral */
PUT_CHAR(*tmp, p);
tmp++;
}
PAD_LEFT(p);
}
/* for %o octal representation */
PRIVATE void
#ifdef __STDC__
octal(struct DATA *p, double d)
#else
octal(p, d)
struct DATA *p;
double d;
#endif
{
char *tmp;
tmp = otoa(d);
p->width -= strlen(tmp);
PAD_RIGHT(p);
if (p->square == FOUND) /* had prefix '0' for octal */
PUT_CHAR('0', p);
while (*tmp) { /* octal */
PUT_CHAR(*tmp, p);
tmp++;
}
PAD_LEFT(p);
}
/* for %x %X hexadecimal representation */
PRIVATE void
#ifdef __STDC__
hexa(struct DATA *p, double d)
#else
hexa(p, d)
struct DATA *p;
double d;
#endif
{
char *tmp;
tmp = htoa(d);
p->width -= strlen(tmp);
PAD_RIGHT(p);
if (p->square == FOUND) { /* prefix '0x' for hexa */
PUT_CHAR('0', p); PUT_CHAR(*p->pf, p);
}
while (*tmp) { /* hexa */
PUT_CHAR((*p->pf == 'X' ? toupper(*tmp) : *tmp), p);
tmp++;
}
PAD_LEFT(p);
}
/* %s strings */
PRIVATE void
#ifdef __STDC__
strings(struct DATA *p, char *tmp)
#else
strings(p, tmp)
struct DATA *p;
char *tmp;
#endif
{
int i;
i = strlen(tmp);
if (p->precision != NOT_FOUND) /* the smallest number */
i = (i < p->precision ? i : p->precision);
p->width -= i;
PAD_RIGHT(p);
while (i-- > 0) { /* put the sting */
PUT_CHAR(*tmp, p);
tmp++;
}
PAD_LEFT(p);
}
/* %f or %g floating point representation */
PRIVATE void
#ifdef __STDC__
floating(struct DATA *p, double d)
#else
floating(p, d)
struct DATA *p;
double d;
#endif
{
char *tmp, *tmp2;
int i;
DEF_PREC(p);
d = ROUND(d, p);
tmp = dtoa(d, p->precision, &tmp2);
/* calculate the padding. 1 for the dot */
p->width = p->width -
((d > 0. && p->justify == RIGHT) ? 1:0) -
((p->space == FOUND) ? 1:0) -
strlen(tmp) - p->precision - 1;
PAD_RIGHT(p);
PUT_PLUS(d, p);
PUT_SPACE(d, p);
while (*tmp) { /* the integral */
PUT_CHAR(*tmp, p);
tmp++;
}
if (p->precision != 0 || p->square == FOUND)
PUT_CHAR('.', p); /* put the '.' */
if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
tmp2[i] = '\0';
for (; *tmp2; tmp2++)
PUT_CHAR(*tmp2, p); /* the fraction */
PAD_LEFT(p);
}
/* %e %E %g exponent representation */
PRIVATE void
#ifdef __STDC__
exponent(struct DATA *p, double d)
#else
exponent(p, d)
struct DATA *p;
double d;
#endif
{
char *tmp, *tmp2;
int j, i;
DEF_PREC(p);
j = log_10(d);
d = d / pow_10(j); /* get the Mantissa */
d = ROUND(d, p);
tmp = dtoa(d, p->precision, &tmp2);
/* 1 for unit, 1 for the '.', 1 for 'e|E',
* 1 for '+|-', 3 for 'exp' */
/* calculate how much padding need */
p->width = p->width -
((d > 0. && p->justify == RIGHT) ? 1:0) -
((p->space == FOUND) ? 1:0) - p->precision - 7;
PAD_RIGHT(p);
PUT_PLUS(d, p);
PUT_SPACE(d, p);
while (*tmp) {/* the integral */
PUT_CHAR(*tmp, p);
tmp++;
}
if (p->precision != 0 || p->square == FOUND)
PUT_CHAR('.', p); /* the '.' */
if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
tmp2[i] = '\0';
for (; *tmp2; tmp2++)
PUT_CHAR(*tmp2, p); /* the fraction */
if (*p->pf == 'g' || *p->pf == 'e') { /* the exponent put the 'e|E' */
PUT_CHAR('e', p);
} else
PUT_CHAR('E', p);
if (j >= 0) { /* the sign of the exp */
PUT_CHAR('+', p);
} else {
PUT_CHAR('-', p);
j = -j;
}
tmp = itoa((double)j);
if (j < 9) { /* need to pad the exponent with 0 '000' */
PUT_CHAR('0', p); PUT_CHAR('0', p);
} else if (j < 99)
PUT_CHAR('0', p);
while (*tmp) { /* the exponent */
PUT_CHAR(*tmp, p);
tmp++;
}
PAD_LEFT(p);
}
/* initialize the conversion specifiers */
PRIVATE void
#ifdef __STDC__
conv_flag(char * s, struct DATA * p)
#else
conv_flag(s, p)
char * s;
struct DATA * p;
#endif
{
char number[MAX_FIELD/2];
int i;
/* reset the flags. */
p->precision = p->width = NOT_FOUND;
p->star_w = p->star_p = NOT_FOUND;
p->square = p->space = NOT_FOUND;
p->a_long = p->justify = NOT_FOUND;
p->a_longlong = NOT_FOUND;
p->pad = ' ';
for(;s && *s ;s++) {
switch(*s) {
case ' ': p->space = FOUND; break;
case '#': p->square = FOUND; break;
case '*': if (p->width == NOT_FOUND)
p->width = p->star_w = FOUND;
else
p->precision = p->star_p = FOUND;
break;
case '+': p->justify = RIGHT; break;
case '-': p->justify = LEFT; break;
case '.': if (p->width == NOT_FOUND)
p->width = 0;
break;
case '0': p->pad = '0'; break;
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9': /* gob all the digits */
for (i = 0; isdigit(*s); i++, s++)
if (i < MAX_FIELD/2 - 1)
number[i] = *s;
number[i] = '\0';
if (p->width == NOT_FOUND)
p->width = atoi(number);
else
p->precision = atoi(number);
s--; /* went to far go back */
break;
}
}
}
PUBLIC int
#ifdef __STDC__
vsnprintf(char *string, size_t length, const char * format, va_list args)
#else
vsnprintf(string, length, format, args)
char *string;
size_t length;
char * format;
va_list args;
#endif
{
struct DATA data;
char conv_field[MAX_FIELD];
double d; /* temporary holder */
int state;
int i;
data.length = length - 1; /* leave room for '\0' */
data.holder = string;
data.pf = format;
data.counter = 0;
/* sanity check, the string must be > 1 */
if (length < 1)
return -1;
for (; *data.pf && (data.counter < data.length); data.pf++) {
if ( *data.pf == '%' ) { /* we got a magic % cookie */
conv_flag((char *)0, &data); /* initialise format flags */
for (state = 1; *data.pf && state;) {
switch (*(++data.pf)) {
case '\0': /* a NULL here ? ? bail out */
*data.holder = '\0';
return data.counter;
break;
case 'f': /* float, double */
STAR_ARGS(&data);
if (data.a_long == FOUND)
d = va_arg(args, LONG_DOUBLE);
else
d = va_arg(args, double);
floating(&data, d);
state = 0;
break;
case 'g':
case 'G':
STAR_ARGS(&data);
DEF_PREC(&data);
if (data.a_long == FOUND)
d = va_arg(args, LONG_DOUBLE);
else
d = va_arg(args, double);
i = log_10(d);
/*
* for '%g|%G' ANSI: use f if exponent
* is in the range or [-4,p] exclusively
* else use %e|%E
*/
if (-4 < i && i < data.precision)
floating(&data, d);
else
exponent(&data, d);
state = 0;
break;
case 'e':
case 'E': /* Exponent double */
STAR_ARGS(&data);
if (data.a_long == FOUND)
d = va_arg(args, LONG_DOUBLE);
else
d = va_arg(args, double);
exponent(&data, d);
state = 0;
break;
case 'u': /* unsigned decimal */
STAR_ARGS(&data);
if (data.a_longlong == FOUND)
d = va_arg(args, unsigned LONG_LONG);
else if (data.a_long == FOUND)
d = va_arg(args, unsigned long);
else
d = va_arg(args, unsigned int);
decimal(&data, d);
state = 0;
break;
case 'd': /* decimal */
STAR_ARGS(&data);
if (data.a_longlong == FOUND)
d = va_arg(args, LONG_LONG);
else if (data.a_long == FOUND)
d = va_arg(args, long);
else
d = va_arg(args, int);
decimal(&data, d);
state = 0;
break;
case 'o': /* octal */
STAR_ARGS(&data);
if (data.a_longlong == FOUND)
d = va_arg(args, LONG_LONG);
else if (data.a_long == FOUND)
d = va_arg(args, long);
else
d = va_arg(args, int);
octal(&data, d);
state = 0;
break;
case 'x':
case 'X': /* hexadecimal */
STAR_ARGS(&data);
if (data.a_longlong == FOUND)
d = va_arg(args, LONG_LONG);
else if (data.a_long == FOUND)
d = va_arg(args, long);
else
d = va_arg(args, int);
hexa(&data, d);
state = 0;
break;
case 'c': /* character */
d = va_arg(args, int);
PUT_CHAR(d, &data);
state = 0;
break;
case 's': /* string */
STAR_ARGS(&data);
strings(&data, va_arg(args, char *));
state = 0;
break;
case 'n':
*(va_arg(args, int *)) = data.counter; /* what's the count ? */
state = 0;
break;
case 'q':
data.a_longlong = FOUND;
break;
case 'L':
case 'l':
if (data.a_long == FOUND)
data.a_longlong = FOUND;
else
data.a_long = FOUND;
break;
case 'h':
break;
case '%': /* nothing just % */
PUT_CHAR('%', &data);
state = 0;
break;
case '#': case ' ': case '+': case '*':
case '-': case '.': case '0': case '1':
case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
/* initialize width and precision */
for (i = 0; isflag(*data.pf); i++, data.pf++)
if (i < MAX_FIELD - 1)
conv_field[i] = *data.pf;
conv_field[i] = '\0';
conv_flag(conv_field, &data);
data.pf--; /* went to far go back */
break;
default:
/* is this an error ? maybe bail out */
state = 0;
break;
} /* end switch */
} /* end of for state */
} else { /* not % */
PUT_CHAR(*data.pf, &data); /* add the char the string */
}
}
*data.holder = '\0'; /* the end ye ! */
#include "snprintf.h"
return data.counter;
}
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifndef HAVE_SNPRINTF
#include "minmax.h"
#include "vasnprintf.h"
PUBLIC int
#if __STDC__
snprintf(char *string, size_t length, const char * format, ...)
#else
snprintf(string, length, format, va_alist)
char *string;
size_t length;
char * format;
va_dcl
#endif
/* Print formatted output to string STR. Similar to sprintf, but
additional length SIZE limit how much is written into STR. Returns
string length of formatted string (which may be larger than SIZE).
STR may be NULL, in which case nothing will be written. On error,
return a negative value. */
int
snprintf (char *str, size_t size, const char *format, ...)
{
int rval;
char *output;
size_t len;
va_list args;
#if __STDC__
va_start(args, format);
#else
va_start(args);
#endif
rval = vsnprintf (string, length, format, args);
va_end(args);
return rval;
}
#endif /* HAVE_SNPRINTF */
#ifdef DRIVER
#include <stdio.h>
/* set of small tests for snprintf() */
int main()
{
char holder[100];
int i;
va_start (args, format);
len = size;
output = vasnprintf (str, &len, format, args);
va_end (args);
/*
printf("Suite of test for snprintf:\n");
printf("a_format\n");
printf("printf() format\n");
printf("snprintf() format\n\n");
*/
/* Checking the field widths */
printf("/%%d/, 336\n");
snprintf(holder, sizeof holder, "/%d/\n", 336);
printf("/%d/\n", 336);
printf("%s\n", holder);
printf("/%%2d/, 336\n");
snprintf(holder, sizeof holder, "/%2d/\n", 336);
printf("/%2d/\n", 336);
printf("%s\n", holder);
printf("/%%10d/, 336\n");
snprintf(holder, sizeof holder, "/%10d/\n", 336);
printf("/%10d/\n", 336);
printf("%s\n", holder);
printf("/%%-10d/, 336\n");
snprintf(holder, sizeof holder, "/%-10d/\n", 336);
printf("/%-10d/\n", 336);
printf("%s\n", holder);
/* long long */
printf("/%%lld/, 336\n");
snprintf(holder, sizeof holder, "/%lld/\n", (LONG_LONG)336);
printf("/%lld/\n", (LONG_LONG)336);
printf("%s\n", holder);
printf("/%%2qd/, 336\n");
snprintf(holder, sizeof holder, "/%2qd/\n", (LONG_LONG)336);
printf("/%2qd/\n", (LONG_LONG)336);
printf("%s\n", holder);
/* floating points */
printf("/%%f/, 1234.56\n");
snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
printf("/%f/\n", 1234.56);
printf("%s\n", holder);
printf("/%%e/, 1234.56\n");
snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
printf("/%e/\n", 1234.56);
printf("%s\n", holder);
printf("/%%4.2f/, 1234.56\n");
snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
printf("/%4.2f/\n", 1234.56);
printf("%s\n", holder);
printf("/%%3.1f/, 1234.56\n");
snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
printf("/%3.1f/\n", 1234.56);
printf("%s\n", holder);
printf("/%%10.3f/, 1234.56\n");
snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
printf("/%10.3f/\n", 1234.56);
printf("%s\n", holder);
printf("/%%10.3e/, 1234.56\n");
snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
printf("/%10.3e/\n", 1234.56);
printf("%s\n", holder);
printf("/%%+4.2f/, 1234.56\n");
snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
printf("/%+4.2f/\n", 1234.56);
printf("%s\n", holder);
printf("/%%010.2f/, 1234.56\n");
snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
printf("/%010.2f/\n", 1234.56);
printf("%s\n", holder);
#define BLURB "Outstanding acting !"
/* strings precisions */
printf("/%%2s/, \"%s\"\n", BLURB);
snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
printf("/%2s/\n", BLURB);
printf("%s\n", holder);
printf("/%%22s/ %s\n", BLURB);
snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
printf("/%22s/\n", BLURB);
printf("%s\n", holder);
printf("/%%22.5s/ %s\n", BLURB);
snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
printf("/%22.5s/\n", BLURB);
printf("%s\n", holder);
printf("/%%-22.5s/ %s\n", BLURB);
snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
printf("/%-22.5s/\n", BLURB);
printf("%s\n", holder);
/* see some flags */
printf("%%x %%X %%#x, 31, 31, 31\n");
snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
printf("%x %X %#x\n", 31, 31, 31);
printf("%s\n", holder);
printf("**%%d**%% d**%% d**, 42, 42, -42\n");
snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
printf("**%d**% d**% d**\n", 42, 42, -42);
printf("%s\n", holder);
/* other flags */
printf("/%%g/, 31.4\n");
snprintf(holder, sizeof holder, "/%g/\n", 31.4);
printf("/%g/\n", 31.4);
printf("%s\n", holder);
printf("/%%.6g/, 31.4\n");
snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
printf("/%.6g/\n", 31.4);
printf("%s\n", holder);
printf("/%%.1G/, 31.4\n");
snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
printf("/%.1G/\n", 31.4);
printf("%s\n", holder);
printf("abc%%n\n");
printf("abc%n", &i); printf("%d\n", i);
snprintf(holder, sizeof holder, "abc%n", &i);
printf("%s", holder); printf("%d\n\n", i);
printf("%%*.*s --> 10.10\n");
snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
printf("%*.*s\n", 10, 10, BLURB);
printf("%s\n", holder);
if (!output)
return -1;
printf("%%%%%%%%\n");
snprintf(holder, sizeof holder, "%%%%\n");
printf("%%%%\n");
printf("%s\n", holder);
if (str != NULL)
if (len > size - 1) /* equivalent to: (size > 0 && len >= size) */
str[size - 1] = '\0';
#define BIG "Hello this is a too big string for the buffer"
/* printf("A buffer to small of 10, trying to put this:\n");*/
printf("<%%>, %s\n", BIG);
i = snprintf(holder, 10, "%s\n", BIG);
printf("<%s>\n", BIG);
printf("<%s>\n", holder);
if (output != str)
free (output);
return 0;
return len;
}
#endif
......
/*
Unix snprintf implementation.
Version 1.3
/* Formatted output to strings.
Copyright (C) 2004 Free Software Foundation, Inc.
Written by Simon Josefsson.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
Revision History:
see header of snprintf.c.
#ifndef SNPRINTF_H
#define SNPRINTF_H
format:
int snprintf(holder, sizeof_holder, format, ...)
/* Get snprintf declaration, if available. */
#include <stdio.h>
Return values:
(sizeof_holder - 1)
THANKS(for the patches and ideas):
Miles Bader
Cyrille Rustom
Jacek Slabocewiz
Mike Parker(mouse)
Alain Magloire: alainm@rcsm.ee.mcgill.ca
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <stdlib.h> /* for atoi() */
#include <ctype.h>
/*
* For the FLOATING POINT FORMAT :
* the challenge was finding a way to
* manipulate the Real numbers without having
* to resort to mathematical function(it
* would require to link with -lm) and not
* going down to the bit pattern(not portable)
*
* so a number, a real is:
real = integral + fraction
integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
fraction = b(1)*10^-1 + b(2)*10^-2 + ...
where:
0 <= a(i) => 9
0 <= b(i) => 9
from then it was simple math
*/
/*
* size of the buffer for the integral part
* and the fraction part
*/
#define MAX_INT 99 + 1 /* 1 for the null */
#define MAX_FRACT 29 + 1
/*
* If the compiler supports (long long)
*/
#ifndef LONG_LONG
# define LONG_LONG long long
/*# define LONG_LONG int64_t*/
#endif
/*
* If the compiler supports (long double)
*/
#ifndef LONG_DOUBLE
# define LONG_DOUBLE long double
/*# define LONG_DOUBLE double*/
#if defined HAVE_DECL_SNPRINTF && !HAVE_DECL_SNPRINTF
int snprintf (char *str, size_t size, const char *format, ...);
#endif
/*
* numtoa() uses PRIVATE buffers to store the results,
* So this function is not reentrant
*/
#define itoa(n) numtoa(n, 10, 0, (char **)0)
#define otoa(n) numtoa(n, 8, 0, (char **)0)
#define htoa(n) numtoa(n, 16, 0, (char **)0)
#define dtoa(n, p, f) numtoa(n, 10, p, f)
#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
/* this struct holds everything we need */
struct DATA {
int length;
char *holder;
int counter;
#ifdef __STDC__
const char *pf;
#else
char *pf;
#endif
/* FLAGS */
int width, precision;
int justify; char pad;
int square, space, star_w, star_p, a_long, a_longlong;
};
#define PRIVATE static
#define PUBLIC
/* signature of the functions */
#ifdef __STDC__
/* the floating point stuff */
PRIVATE double pow_10(int);
PRIVATE int log_10(double);
PRIVATE double integral(double, double *);
PRIVATE char * numtoa(double, int, int, char **);
/* for the format */
PRIVATE void conv_flag(char *, struct DATA *);
PRIVATE void floating(struct DATA *, double);
PRIVATE void exponent(struct DATA *, double);
PRIVATE void decimal(struct DATA *, double);
PRIVATE void octal(struct DATA *, double);
PRIVATE void hexa(struct DATA *, double);
PRIVATE void strings(struct DATA *, char *);
#else
/* the floating point stuff */
PRIVATE double pow_10();
PRIVATE int log_10();
PRIVATE double integral();
PRIVATE char * numtoa();
/* for the format */
PRIVATE void conv_flag();
PRIVATE void floating();
PRIVATE void exponent();
PRIVATE void decimal();
PRIVATE void octal();
PRIVATE void hexa();
PRIVATE void strings();
#endif
/* those are defines specific to snprintf to hopefully
* make the code clearer :-)
*/
#define RIGHT 1
#define LEFT 0
#define NOT_FOUND -1
#define FOUND 1
#define MAX_FIELD 15
/* the conversion flags */
#define isflag(c) ((c) == '#' || (c) == ' ' || \
(c) == '*' || (c) == '+' || \
(c) == '-' || (c) == '.' || \
isdigit(c))
/* round off to the precision */
#define ROUND(d, p) \
(d < 0.) ? \
d - pow_10(-(p)->precision) * 0.5 : \
d + pow_10(-(p)->precision) * 0.5
/* set default precision */
#define DEF_PREC(p) \
if ((p)->precision == NOT_FOUND) \
(p)->precision = 6
/* put a char */
#define PUT_CHAR(c, p) \
if ((p)->counter < (p)->length) { \
*(p)->holder++ = (c); \
(p)->counter++; \
}
#define PUT_PLUS(d, p) \
if ((d) > 0. && (p)->justify == RIGHT) \
PUT_CHAR('+', p)
#define PUT_SPACE(d, p) \
if ((p)->space == FOUND && (d) > 0.) \
PUT_CHAR(' ', p)
/* pad right */
#define PAD_RIGHT(p) \
if ((p)->width > 0 && (p)->justify != LEFT) \
for (; (p)->width > 0; (p)->width--) \
PUT_CHAR((p)->pad, p)
/* pad left */
#define PAD_LEFT(p) \
if ((p)->width > 0 && (p)->justify == LEFT) \
for (; (p)->width > 0; (p)->width--) \
PUT_CHAR((p)->pad, p)
/* if width and prec. in the args */
#define STAR_ARGS(p) \
if ((p)->star_w == FOUND) \
(p)->width = va_arg(args, int); \
if ((p)->star_p == FOUND) \
(p)->precision = va_arg(args, int)
#endif /* SNPRINTF_H */
......
/* Like vsprintf but provides a pointer to malloc'd storage, which must
be freed by the caller.
Copyright (C) 1994 Free Software Foundation, Inc.
/* Formatted output to strings.
Copyright (C) 1999, 2002-2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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 <stdio.h>
#include <string.h>
/* Specification. */
#include "vasprintf.h"
#if __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#ifdef TEST
int global_total_width;
#endif
unsigned long strtoul ();
char *malloc ();
static int
int_vasprintf (result, format, args)
char **result;
const char *format;
va_list *args;
{
const char *p = format;
/* Add one to make sure that it is never zero, which might cause malloc
to return NULL. */
int total_width = strlen (format) + 1;
va_list ap;
memcpy (&ap, args, sizeof (va_list));
while (*p != '\0')
{
if (*p++ == '%')
{
while (strchr ("-+ #0", *p))
++p;
if (*p == '*')
{
++p;
total_width += abs (va_arg (ap, int));
}
else
total_width += strtoul (p, &p, 10);
if (*p == '.')
{
++p;
if (*p == '*')
{
++p;
total_width += abs (va_arg (ap, int));
}
else
total_width += strtoul (p, &p, 10);
}
while (strchr ("hlL", *p))
++p;
/* Should be big enough for any format specifier except %s. */
total_width += 30;
switch (*p)
{
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
case 'c':
(void) va_arg (ap, int);
break;
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
(void) va_arg (ap, double);
break;
case 's':
total_width += strlen (va_arg (ap, char *));
break;
case 'p':
case 'n':
(void) va_arg (ap, char *);
break;
}
}
}
#ifdef TEST
global_total_width = total_width;
#endif
*result = malloc (total_width);
if (*result != NULL)
return vsprintf (*result, format, *args);
else
return 0;
}
int
vasprintf (result, format, args)
char **result;
const char *format;
va_list args;
{
return int_vasprintf (result, format, &args);
}
#include <stdlib.h>
int
asprintf
#if __STDC__
(char **result, const char *format, ...)
#else
(result, va_alist)
char **result;
va_dcl
#endif
{
va_list args;
int done;
#if __STDC__
va_start (args, format);
#else
char *format;
va_start (args);
format = va_arg (args, char *);
#endif
done = vasprintf (result, format, args);
va_end (args);
return done;
}
#ifdef TEST
void
checkit
#if __STDC__
(const char* format, ...)
#else
(va_alist)
va_dcl
#endif
{
va_list args;
char *result;
#if __STDC__
va_start (args, format);
#else
char *format;
va_start (args);
format = va_arg (args, char *);
#endif
vasprintf (&result, format, args);
va_end (args);
if (strlen (result) < global_total_width)
printf ("PASS: ");
else
printf ("FAIL: ");
printf ("%d %s\n", global_total_width, result);
}
#include "vasnprintf.h"
int
main ()
vasprintf (char **resultp, const char *format, va_list args)
{
checkit ("%d", 0x12345678);
checkit ("%200d", 5);
checkit ("%.300d", 6);
checkit ("%100.150d", 7);
checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
777777777777777777333333333333366666666666622222222222777777777777733333");
checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
size_t length;
char *result = vasnprintf (NULL, &length, format, args);
if (result == NULL)
return -1;
*resultp = result;
/* Return the number of resulting bytes, excluding the trailing NUL.
If it wouldn't fit in an 'int', vasnprintf() would have returned NULL
and set errno to EOVERFLOW. */
return length;
}
#endif /* TEST */
......
/* xalloc.h -- malloc with out-of-memory checking
Copyright (C) 1990-1998, 1999 Free Software Foundation, Inc.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -18,14 +20,14 @@
#ifndef XALLOC_H_
# define XALLOC_H_
# ifndef PARAMS
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
# define PARAMS(Args) Args
# else
# define PARAMS(Args) ()
# endif
# include <stddef.h>
# ifdef __cplusplus
extern "C" {
# endif
# ifndef __attribute__
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
# define __attribute__(x)
......@@ -36,52 +38,42 @@
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
# endif
/* Exit value when the requested amount of memory is not available.
It is initialized to EXIT_FAILURE, but the caller may set it to
some other value. */
extern int xalloc_exit_failure;
/* If this pointer is non-zero, run the specified function upon each
allocation failure. It is initialized to zero. */
extern void (*xalloc_fail_func) PARAMS ((void));
/* If XALLOC_FAIL_FUNC is undefined or a function that returns, this
message must be non-NULL. It is translated via gettext.
The default value is "Memory exhausted". */
extern char *const xalloc_msg_memory_exhausted;
/* This function is always triggered when memory is exhausted. It is
in charge of honoring the three previous items. This is the
/* This function is always triggered when memory is exhausted.
It must be defined by the application, either explicitly
or by using gnulib's xalloc-die module. This is the
function to call when one wants the program to die because of a
memory allocation failure. */
extern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN;
void *xmalloc PARAMS ((size_t n));
void *xcalloc PARAMS ((size_t n, size_t s));
void *xrealloc PARAMS ((void *p, size_t n));
char *xstrdup PARAMS ((const char *str));
# define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items)))
# define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items)))
# define XREALLOC(Ptr, Type, N_items) \
((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items)))
/* Declare and alloc memory for VAR of type TYPE. */
# define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1)
/* Free VAR only if non NULL. */
# define XFREE(Var) \
do { \
if (Var) \
free (Var); \
} while (0)
/* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */
# define CCLONE(Src, Num) \
(memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num)))
/* Return a malloc'ed copy of SRC. */
# define CLONE(Src) CCLONE (Src, 1)
extern void xalloc_die (void) ATTRIBUTE_NORETURN;
void *xmalloc (size_t s);
void *xnmalloc (size_t n, size_t s);
void *xzalloc (size_t s);
void *xcalloc (size_t n, size_t s);
void *xrealloc (void *p, size_t s);
void *xnrealloc (void *p, size_t n, size_t s);
void *x2realloc (void *p, size_t *pn);
void *x2nrealloc (void *p, size_t *pn, size_t s);
void *xmemdup (void const *p, size_t s);
char *xstrdup (char const *str);
/* Return 1 if an array of N objects, each of size S, cannot exist due
to size arithmetic overflow. S must be positive and N must be
nonnegative. This is a macro, not an inline function, so that it
works correctly even when SIZE_MAX < N.
By gnulib convention, SIZE_MAX represents overflow in size
calculations, so the conservative dividend to use here is
SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
However, malloc (SIZE_MAX) fails on all known hosts where
sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
exactly-SIZE_MAX allocations on such hosts; this avoids a test and
branch when S is known to be 1. */
# define xalloc_oversized(n, s) \
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
# ifdef __cplusplus
}
# endif
#endif /* !XALLOC_H_ */
......
/* xmalloc.c -- malloc with out of memory checking
Copyright (C) 1990-1997, 98, 99 Free Software Foundation, Inc.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,64 +21,31 @@
# include <config.h>
#endif
#include <sys/types.h>
#include <mailutils/error.h>
#if STDC_HEADERS
# include <stdlib.h>
#else
void *calloc ();
void *malloc ();
void *realloc ();
void free ();
#endif
#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
#else
# define textdomain(Domain)
# define _(Text) Text
#endif
#define N_(Text) Text
#include "error.h"
#include "xalloc.h"
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif
#ifndef HAVE_MALLOC
# error "you must run the autoconf test for a properly working malloc -- see malloc.m4"
#endif
#include <stdlib.h>
#include <string.h>
#ifndef HAVE_REALLOC
# error "you must run the autoconf test for a properly working realloc -- see realloc.m4"
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
/* Exit value when the requested amount of memory is not available.
The caller may set it to some other value. */
int xalloc_exit_failure = EXIT_FAILURE;
/* If non NULL, call this function when memory is exhausted. */
void (*xalloc_fail_func) PARAMS ((void)) = 0;
/* Allocate an array of N objects, each with S bytes of memory,
dynamically, with error checking. S must be nonzero. */
/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
before exiting when memory is exhausted. Goes through gettext. */
char *const xalloc_msg_memory_exhausted = N_("Memory exhausted");
static inline void *
xnmalloc_inline (size_t n, size_t s)
{
void *p;
if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
xalloc_die ();
return p;
}
void
xalloc_die (void)
void *
xnmalloc (size_t n, size_t s)
{
if (xalloc_fail_func)
(*xalloc_fail_func) ();
mu_error ("%s", _(xalloc_msg_memory_exhausted));
/* The `noreturn' cannot be given to error, since it may return if
its first argument is 0. To help compilers understand the
xalloc_die does terminate, call exit. */
exit (xalloc_exit_failure);
return xnmalloc_inline (n, s);
}
/* Allocate N bytes of memory dynamically, with error checking. */
......@@ -84,36 +53,177 @@ xalloc_die (void)
void *
xmalloc (size_t n)
{
void *p;
return xnmalloc_inline (n, 1);
}
/* Change the size of an allocated block of memory P to an array of N
objects each of S bytes, with error checking. S must be nonzero. */
p = malloc (n);
if (p == 0)
static inline void *
xnrealloc_inline (void *p, size_t n, size_t s)
{
if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
xalloc_die ();
return p;
}
void *
xnrealloc (void *p, size_t n, size_t s)
{
return xnrealloc_inline (p, n, s);
}
/* Change the size of an allocated block of memory P to N bytes,
with error checking.
If P is NULL, run xmalloc. */
with error checking. */
void *
xrealloc (void *p, size_t n)
{
p = realloc (p, n);
if (p == 0)
return xnrealloc_inline (p, n, 1);
}
/* If P is null, allocate a block of at least *PN such objects;
otherwise, reallocate P so that it contains more than *PN objects
each of S bytes. *PN must be nonzero unless P is null, and S must
be nonzero. Set *PN to the new number of objects, and return the
pointer to the new block. *PN is never set to zero, and the
returned pointer is never null.
Repeated reallocations are guaranteed to make progress, either by
allocating an initial block with a nonzero size, or by allocating a
larger block.
In the following implementation, nonzero sizes are doubled so that
repeated reallocations have O(N log N) overall cost rather than
O(N**2) cost, but the specification for this function does not
guarantee that sizes are doubled.
Here is an example of use:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
void
append_int (int value)
{
if (used == allocated)
p = x2nrealloc (p, &allocated, sizeof *p);
p[used++] = value;
}
This causes x2nrealloc to allocate a block of some nonzero size the
first time it is called.
To have finer-grained control over the initial size, set *PN to a
nonzero value before calling this function with P == NULL. For
example:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
size_t allocated1 = 1000;
void
append_int (int value)
{
if (used == allocated)
{
p = x2nrealloc (p, &allocated1, sizeof *p);
allocated = allocated1;
}
p[used++] = value;
}
*/
static inline void *
x2nrealloc_inline (void *p, size_t *pn, size_t s)
{
size_t n = *pn;
if (! p)
{
if (! n)
{
/* The approximate size to use for initial small allocation
requests, when the invoking code specifies an old size of
zero. 64 bytes is the largest "small" request for the
GNU C library malloc. */
enum { DEFAULT_MXFAST = 64 };
n = DEFAULT_MXFAST / s;
n += !n;
}
}
else
{
if (SIZE_MAX / 2 / s < n)
xalloc_die ();
return p;
n *= 2;
}
*pn = n;
return xrealloc (p, n * s);
}
void *
x2nrealloc (void *p, size_t *pn, size_t s)
{
return x2nrealloc_inline (p, pn, s);
}
/* Allocate memory for N elements of S bytes, with error checking. */
/* If P is null, allocate a block of at least *PN bytes; otherwise,
reallocate P so that it contains more than *PN bytes. *PN must be
nonzero unless P is null. Set *PN to the new block's size, and
return the pointer to the new block. *PN is never set to zero, and
the returned pointer is never null. */
void *
x2realloc (void *p, size_t *pn)
{
return x2nrealloc_inline (p, pn, 1);
}
/* Allocate S bytes of zeroed memory dynamically, with error checking.
There's no need for xnzalloc (N, S), since it would be equivalent
to xcalloc (N, S). */
void *
xzalloc (size_t s)
{
return memset (xmalloc (s), 0, s);
}
/* Allocate zeroed memory for N elements of S bytes, with error
checking. S must be nonzero. */
void *
xcalloc (size_t n, size_t s)
{
void *p;
p = calloc (n, s);
if (p == 0)
/* Test for overflow, since some calloc implementations don't have
proper overflow checks. */
if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0))
xalloc_die ();
return p;
}
/* Clone an object P of size S, with error checking. There's no need
for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
need for an arithmetic overflow check. */
void *
xmemdup (void const *p, size_t s)
{
return memcpy (xmalloc (s), p, s);
}
/* Clone STRING. */
char *
xstrdup (char const *string)
{
return xmemdup (string, strlen (string) + 1);
}
......
/* A more useful interface to strtol.
Copyright 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2004 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -25,48 +27,32 @@
# define __strtol strtol
# define __strtol_t long int
# define __xstrtol xstrtol
# define STRTOL_T_MINIMUM LONG_MIN
# define STRTOL_T_MAXIMUM LONG_MAX
#endif
/* Some pre-ANSI implementations (e.g. SunOS 4)
need stderr defined if assertion checking is enabled. */
#include <stdio.h>
#if STDC_HEADERS
# include <stdlib.h>
#endif
#if HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
# ifndef strchr
# define strchr index
# endif
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#if HAVE_LIMITS_H
# include <limits.h>
#endif
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
#include <limits.h>
#include <stdlib.h>
#include <string.h>
/* The extra casts work around common compiler bugs. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
It is necessary at least when t == time_t. */
#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
#define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t))
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
: (t) 0))
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
#ifndef STRTOL_T_MINIMUM
# define STRTOL_T_MINIMUM TYPE_MINIMUM (__strtol_t)
# define STRTOL_T_MAXIMUM TYPE_MAXIMUM (__strtol_t)
#endif
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
# define IN_CTYPE_DOMAIN(c) 1
......@@ -78,36 +64,38 @@ extern int errno;
#include "xstrtol.h"
#ifndef strtol
long int strtol ();
#endif
#ifndef strtoul
unsigned long int strtoul ();
#if !HAVE_DECL_STRTOIMAX && !defined strtoimax
intmax_t strtoimax ();
#endif
#ifndef strtoumax
#if !HAVE_DECL_STRTOUMAX && !defined strtoumax
uintmax_t strtoumax ();
#endif
static int
static strtol_error
bkm_scale (__strtol_t *x, int scale_factor)
{
__strtol_t product = *x * scale_factor;
if (*x != product / scale_factor)
return 1;
*x = product;
return 0;
if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor)
{
*x = STRTOL_T_MINIMUM;
return LONGINT_OVERFLOW;
}
if (STRTOL_T_MAXIMUM / scale_factor < *x)
{
*x = STRTOL_T_MAXIMUM;
return LONGINT_OVERFLOW;
}
*x *= scale_factor;
return LONGINT_OK;
}
static int
static strtol_error
bkm_scale_by_power (__strtol_t *x, int base, int power)
{
strtol_error err = LONGINT_OK;
while (power--)
if (bkm_scale (x, base))
return 1;
return 0;
err |= bkm_scale (x, base);
return err;
}
/* FIXME: comment. */
......@@ -119,6 +107,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
char *t_ptr;
char **p;
__strtol_t tmp;
strtol_error err = LONGINT_OK;
assert (0 <= strtol_base && strtol_base <= 36);
......@@ -127,18 +116,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
if (! TYPE_SIGNED (__strtol_t))
{
const char *q = s;
while (ISSPACE ((unsigned char) *q))
++q;
if (*q == '-')
unsigned char ch = *q;
while (ISSPACE (ch))
ch = *++q;
if (ch == '-')
return LONGINT_INVALID;
}
errno = 0;
tmp = __strtol (s, p, strtol_base);
if (errno != 0)
return LONGINT_OVERFLOW;
if (*p == s)
{
/* If there is no number but there is a valid suffix, assume the
number is 1. The string is invalid otherwise. */
if (valid_suffixes && **p && strchr (valid_suffixes, **p))
tmp = 1;
else
return LONGINT_INVALID;
}
else if (errno != 0)
{
if (errno != ERANGE)
return LONGINT_INVALID;
err = LONGINT_OVERFLOW;
}
/* Let valid_suffixes == NULL mean `allow any suffix'. */
/* FIXME: update all callers except the ones that allow suffixes
......@@ -146,34 +148,39 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
if (!valid_suffixes)
{
*val = tmp;
return LONGINT_OK;
return err;
}
if (**p != '\0')
{
int base = 1024;
int suffixes = 1;
int overflow;
strtol_error overflow;
if (!strchr (valid_suffixes, **p))
{
*val = tmp;
return LONGINT_INVALID_SUFFIX_CHAR;
return err | LONGINT_INVALID_SUFFIX_CHAR;
}
if (strchr (valid_suffixes, '0'))
{
/* The ``valid suffix'' '0' is a special flag meaning that
an optional second suffix is allowed, which can change
the base, e.g. "100MD" for 100 megabytes decimal. */
the base. A suffix "B" (e.g. "100MB") stands for a power
of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for
a power of 1024. If no suffix (e.g. "100M"), assume
power-of-1024. */
switch (p[0][1])
{
case 'B':
suffixes++;
case 'i':
if (p[0][2] == 'B')
suffixes += 2;
break;
case 'D':
case 'B':
case 'D': /* 'D' is obsolescent */
base = 1000;
suffixes++;
break;
......@@ -194,28 +201,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
overflow = 0;
break;
case 'E': /* Exa */
case 'E': /* exa or exbi */
overflow = bkm_scale_by_power (&tmp, base, 6);
break;
case 'G': /* Giga */
case 'G': /* giga or gibi */
case 'g': /* 'g' is undocumented; for compatibility only */
overflow = bkm_scale_by_power (&tmp, base, 3);
break;
case 'k': /* kilo */
case 'K': /* kibi */
overflow = bkm_scale_by_power (&tmp, base, 1);
break;
case 'M': /* Mega */
case 'm': /* 'm' is undocumented; for backward compatibility only */
case 'M': /* mega or mebi */
case 'm': /* 'm' is undocumented; for compatibility only */
overflow = bkm_scale_by_power (&tmp, base, 2);
break;
case 'P': /* Peta */
case 'P': /* peta or pebi */
overflow = bkm_scale_by_power (&tmp, base, 5);
break;
case 'T': /* Tera */
case 'T': /* tera or tebi */
case 't': /* 't' is undocumented; for compatibility only */
overflow = bkm_scale_by_power (&tmp, base, 4);
break;
......@@ -223,28 +233,27 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
overflow = bkm_scale (&tmp, 2);
break;
case 'Y': /* Yotta */
case 'Y': /* yotta or 2**80 */
overflow = bkm_scale_by_power (&tmp, base, 8);
break;
case 'Z': /* Zetta */
case 'Z': /* zetta or 2**70 */
overflow = bkm_scale_by_power (&tmp, base, 7);
break;
default:
*val = tmp;
return LONGINT_INVALID_SUFFIX_CHAR;
break;
return err | LONGINT_INVALID_SUFFIX_CHAR;
}
if (overflow)
return LONGINT_OVERFLOW;
(*p) += suffixes;
err |= overflow;
*p += suffixes;
if (**p)
err |= LONGINT_INVALID_SUFFIX_CHAR;
}
*val = tmp;
return LONGINT_OK;
return err;
}
#ifdef TESTING_XSTRTO
......@@ -255,7 +264,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base,
char *program_name;
int
main (int argc, char** argv)
main (int argc, char **argv)
{
strtol_error s_err;
int i;
......
/* A more useful interface to strtol.
Copyright (C) 1995, 1996, 1998, 1999, 2001, 2002, 2003, 2004 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef XSTRTOL_H_
# define XSTRTOL_H_ 1
# if HAVE_INTTYPES_H
# include <inttypes.h> /* for uintmax_t */
# endif
# include "exitfail.h"
# ifndef PARAMS
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
# define PARAMS(Args) Args
# else
# define PARAMS(Args) ()
# if HAVE_INTTYPES_H
# include <inttypes.h>
# endif
# if HAVE_STDINT_H
# include <stdint.h>
# endif
# ifndef _STRTOL_ERROR
enum strtol_error
{
LONGINT_OK, LONGINT_INVALID, LONGINT_INVALID_SUFFIX_CHAR, LONGINT_OVERFLOW
LONGINT_OK = 0,
/* These two values can be ORed together, to indicate that both
errors occurred. */
LONGINT_OVERFLOW = 1,
LONGINT_INVALID_SUFFIX_CHAR = 2,
LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW = (LONGINT_INVALID_SUFFIX_CHAR
| LONGINT_OVERFLOW),
LONGINT_INVALID = 4
};
typedef enum strtol_error strtol_error;
# endif
# define _DECLARE_XSTRTOL(name, type) \
strtol_error \
name PARAMS ((const char *s, char **ptr, int base, \
type *val, const char *valid_suffixes));
strtol_error name (const char *, char **, int, type *, const char *);
_DECLARE_XSTRTOL (xstrtol, long int)
_DECLARE_XSTRTOL (xstrtoul, unsigned long int)
_DECLARE_XSTRTOL (xstrtoimax, intmax_t)
_DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
# define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \
......@@ -34,7 +58,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
{ \
switch ((Err)) \
{ \
case LONGINT_OK: \
default: \
abort (); \
\
case LONGINT_INVALID: \
......@@ -43,7 +67,8 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
break; \
\
case LONGINT_INVALID_SUFFIX_CHAR: \
error ((Exit_code), 0, "invalid character following %s `%s'", \
case LONGINT_INVALID_SUFFIX_CHAR | LONGINT_OVERFLOW: \
error ((Exit_code), 0, "invalid character following %s in `%s'", \
(Argument_type_string), (Str)); \
break; \
\
......@@ -56,7 +81,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
while (0)
# define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \
_STRTOL_ERROR (2, Str, Argument_type_string, Err)
_STRTOL_ERROR (exit_failure, Str, Argument_type_string, Err)
# define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \
_STRTOL_ERROR (0, Str, Argument_type_string, Err)
......
## $Id$
# getopt.m4 serial 7
dnl Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
## Check for getopt_long. This can't be done in AC_CHECK_FUNCS since
## the function can be present in different libraries (namely, libmysqlclient)
## but the necessary header files may be absent, thus AC_CHECK_FUNCS will
## mark function as existent, whereas the compilation will bail out.
# The getopt module assume you want GNU getopt, with getopt_long etc,
# rather than vanilla POSIX getopt. This means your your code should
# always include <getopt.h> for the getopt prototypes.
AH_TEMPLATE(HAVE_GNU_GETOPT, [Define if your system has GNU getopt functions])
AC_DEFUN([gl_GETOPT_SUBSTITUTE],
[
GETOPT_H=getopt.h
MU_LIBOBJ([getopt])
MU_LIBOBJ([getopt1])
AC_DEFINE([__GETOPT_PREFIX], [[rpl_]],
[Define to rpl_ if the getopt replacement functions and variables
should be used.])
AC_SUBST([GETOPT_H])
])
AC_DEFUN([MU_REPLACE_GNU_GETOPT],
AC_DEFUN([gl_GETOPT],
[
AC_CHECK_HEADER([getopt.h],
mu_cv_have_getopt_h=yes
AC_DEFINE(HAVE_GETOPT_H,1,[Define if the system has getopt.h]),
mu_cv_have_getopt_h=no)
AC_CACHE_CHECK([for GNU getopt], mu_cv_have_gnu_getopt,
[
AC_TRY_RUN([
#include <unistd.h>
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
gl_PREREQ_GETOPT
struct option longopt[] = {
"help", no_argument, 0, 'h',
(char*)0
};
if test -z "$GETOPT_H"; then
GETOPT_H=
AC_CHECK_HEADERS([getopt.h], [], [GETOPT_H=getopt.h])
AC_CHECK_FUNCS([getopt_long_only], [], [GETOPT_H=getopt.h])
main(argc, argv)
int argc; char **argv;
{
getopt_long_only(argc, argv, "h", longopt, (int*)0);
return 0;
} ],
mu_cv_have_gnu_getopt=yes,
mu_cv_have_gnu_getopt=no,
mu_cv_have_gnu_getopt=no)])
dnl BSD getopt_long uses an incompatible method to reset option processing,
dnl and (as of 2004-10-15) mishandles optional option-arguments.
AC_CHECK_DECL([optreset], [GETOPT_H=getopt.h], [], [#include <getopt.h>])
if test x"$mu_cv_have_gnu_getopt" != xyes ; then
mu_cv_have_getopt_h=no
MU_LIBOBJ(getopt)
MU_LIBOBJ(getopt1)
else
AC_DEFINE(HAVE_GNU_GETOPT)
if test -n "$GETOPT_H"; then
gl_GETOPT_SUBSTITUTE
fi
if test "$mu_cv_have_getopt_h" = no; then
MU_HEADER(getopt.h)
fi
])
# Prerequisites of lib/getopt*.
AC_DEFUN([gl_PREREQ_GETOPT], [:])
......
#serial 12
#serial 22
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free
# Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
dnl Initially derived from code in GNU grep.
dnl Mostly written by Jim Meyering.
dnl Usage: jm_INCLUDED_REGEX([lib/regex.c])
AC_DEFUN([gl_REGEX],
[
gl_INCLUDED_REGEX([lib/regex.c])
])
dnl Usage: gl_INCLUDED_REGEX([lib/regex.c])
dnl
AC_DEFUN([jm_INCLUDED_REGEX],
AC_DEFUN([gl_INCLUDED_REGEX],
[
dnl Even packages that don't use regex.c can use this macro.
dnl Of course, for them it doesn't do anything.
......@@ -22,6 +34,7 @@ AC_DEFUN([jm_INCLUDED_REGEX],
jm_cv_func_working_re_compile_pattern,
AC_TRY_RUN(
[#include <stdio.h>
#include <string.h>
#include <regex.h>
int
main ()
......@@ -30,12 +43,14 @@ AC_DEFUN([jm_INCLUDED_REGEX],
const char *s;
struct re_registers regs;
re_set_syntax (RE_SYNTAX_POSIX_EGREP);
memset (&regex, 0, sizeof (regex));
[s = re_compile_pattern ("a[[:@:>@:]]b\n", 9, &regex);]
/* This should fail with _Invalid character class name_ error. */
if (!s)
exit (1);
/* This should succeed, but doesn't for e.g. glibc-2.1.3. */
memset (&regex, 0, sizeof (regex));
s = re_compile_pattern ("{1", 2, &regex);
if (s)
......@@ -43,7 +58,8 @@ AC_DEFUN([jm_INCLUDED_REGEX],
/* The following example is derived from a problem report
against gawk from Jorge Stolfi <stolfi@ic.unicamp.br>. */
s = re_compile_pattern ("[[anù]]*n", 7, &regex);
memset (&regex, 0, sizeof (regex));
s = re_compile_pattern ("[[an\371]]*n", 7, &regex);
if (s)
exit (1);
......@@ -51,6 +67,16 @@ AC_DEFUN([jm_INCLUDED_REGEX],
if (re_match (&regex, "an", 2, 0, &regs) != 2)
exit (1);
memset (&regex, 0, sizeof (regex));
s = re_compile_pattern ("x", 1, &regex);
if (s)
exit (1);
/* The version of regex.c in e.g. GNU libc-2.2.93 didn't
work with a negative RANGE argument. */
if (re_search (&regex, "wxy", 3, 2, -2, &regs) != 1)
exit (1);
exit (0);
}
],
......@@ -67,16 +93,34 @@ AC_DEFUN([jm_INCLUDED_REGEX],
ifelse(m4_sysval, 0,
[
AC_ARG_WITH(included-regex,
AC_HELP_STRING([--without-included-regex],
[don't compile regex; this is the default on systems with version 2 of the GNU C library (use with caution on other system)]),
[ --without-included-regex don't compile regex; this is the default on
systems with version 2 of the GNU C library
(use with caution on other system)],
jm_with_regex=$withval,
jm_with_regex=$ac_use_included_regex)
if test "$jm_with_regex" = yes; then
MU_LIBOBJ(regex)
MU_HEADER(regex.h)
MU_HEADER(posix/regex.h)
gl_PREREQ_REGEX
fi
],
)
]
)
# Prerequisites of lib/regex.c.
AC_DEFUN([gl_PREREQ_REGEX],
[
dnl FIXME: Maybe provide a btowc replacement someday: Solaris 2.5.1 lacks it.
dnl FIXME: Check for wctype and iswctype, and and add -lw if necessary
dnl to get them.
dnl Persuade glibc <string.h> to declare mempcpy().
AC_REQUIRE([AC_GNU_SOURCE])
AC_REQUIRE([gl_C_RESTRICT])
AC_REQUIRE([AC_FUNC_ALLOCA])
AC_REQUIRE([AC_HEADER_STDC])
AC_CHECK_HEADERS_ONCE(wchar.h wctype.h)
AC_CHECK_FUNCS_ONCE(isascii mempcpy)
AC_CHECK_FUNCS(btowc)
])
......
......@@ -3,20 +3,19 @@
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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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
......
/* Default definition for ARGP_ERR_EXIT_STATUS
Copyright (C) 1997, 2001 Free Software Foundation, Inc.
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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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 HAVE_SYSEXITS_H
#include <sysexits.h>
#endif
#ifndef EX_USAGE
#define EX_USAGE 64
#endif
#include "argp.h"
......
/* Word-wrapping and line-truncating streams
Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
Copyright (C) 1997,1998,1999,2001,2002,2003 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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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. */
......@@ -40,6 +39,12 @@
#define isblank(ch) ((ch)==' ' || (ch)=='\t')
#endif
#if defined _LIBC && defined USE_IN_LIBIO
# include <wchar.h>
# include <libio/libioP.h>
# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
#endif
#define INIT_BUF_SIZE 200
#define PRINTF_SIZE_GUESS 150
......@@ -53,8 +58,10 @@ argp_fmtstream_t
__argp_make_fmtstream (FILE *stream,
size_t lmargin, size_t rmargin, ssize_t wmargin)
{
argp_fmtstream_t fs = malloc (sizeof (struct argp_fmtstream));
if (fs)
argp_fmtstream_t fs;
fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
if (fs != NULL)
{
fs->stream = stream;
......@@ -64,7 +71,7 @@ __argp_make_fmtstream (FILE *stream,
fs->point_col = 0;
fs->point_offs = 0;
fs->buf = malloc (INIT_BUF_SIZE);
fs->buf = (char *) malloc (INIT_BUF_SIZE);
if (! fs->buf)
{
free (fs);
......@@ -79,9 +86,12 @@ __argp_make_fmtstream (FILE *stream,
return fs;
}
#if 0
/* Not exported. */
#ifdef weak_alias
weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
#endif
#endif
/* Flush FS to its stream, and free it (but don't close the stream). */
void
......@@ -89,13 +99,23 @@ __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);
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
else
#endif
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
}
free (fs->buf);
free (fs);
}
#if 0
/* Not exported. */
#ifdef weak_alias
weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
#endif
#endif
/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
end of its buffer. This code is mostly from glibc stdio/linewrap.c. */
......@@ -129,7 +149,14 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
/* No buffer space for spaces. Must flush. */
size_t i;
for (i = 0; i < pad; i++)
putc (' ', fs->stream);
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
putwc_unlocked (L' ', fs->stream);
else
#endif
putc_unlocked (' ', fs->stream);
}
}
fs->point_col = pad;
}
......@@ -245,9 +272,10 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
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
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)
......@@ -262,9 +290,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
else
/* Output the first line so we can use the space. */
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
__fwprintf (fs->stream, L"%.*s\n",
(int) (nl - fs->buf), fs->buf);
else
#endif
{
if (nl > fs->buf)
fwrite (fs->buf, 1, nl - fs->buf, fs->stream);
putc ('\n', fs->stream);
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
putc_unlocked ('\n', fs->stream);
}
len += buf - fs->buf;
nl = buf = fs->buf;
}
......@@ -281,7 +317,12 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
*nl++ = ' ';
else
for (i = 0; i < fs->wmargin; ++i)
putc (' ', fs->stream);
#ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
putwc_unlocked (L' ', fs->stream);
else
#endif
putc_unlocked (' ', fs->stream);
/* Copy the tail of the original buffer into the current buffer
position. */
......@@ -318,7 +359,15 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
/* Flush FS's buffer. */
__argp_fmtstream_update (fs);
wrote = fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream);
#ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
{
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
wrote = fs->p - fs->buf;
}
else
#endif
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
if (wrote == fs->p - fs->buf)
{
fs->p = fs->buf;
......@@ -335,12 +384,13 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
if ((size_t) (fs->end - fs->buf) < amount)
/* Gotta grow the buffer. */
{
size_t new_size = fs->end - fs->buf + amount;
char *new_buf = realloc (fs->buf, new_size);
size_t old_size = fs->end - fs->buf;
size_t new_size = old_size + amount;
char *new_buf;
if (! new_buf)
if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
{
errno = ENOMEM;
__set_errno (ENOMEM);
return 0;
}
......@@ -369,19 +419,22 @@ __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
va_start (args, fmt);
avail = fs->end - fs->p;
out = vsnprintf (fs->p, avail, fmt, args);
out = __vsnprintf (fs->p, avail, fmt, args);
va_end (args);
if (out >= avail)
if ((size_t) out >= avail)
size_guess = out + 1;
}
while (out >= avail);
while ((size_t) out >= avail);
fs->p += out;
return out;
}
#if 0
/* Not exported. */
#ifdef weak_alias
weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
#endif
#endif
#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */
......
/* Word-wrapping and line-truncating streams.
Copyright (C) 1997, 2001 Free Software Foundation, Inc.
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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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
......@@ -34,6 +33,19 @@
#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
#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
|| (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
/* line_wrap_stream is available, so use that. */
......@@ -82,6 +94,9 @@ typedef FILE *argp_fmtstream_t;
#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
/* Guess we have to define our own version. */
#ifndef __const
#define __const const
#endif
struct argp_fmtstream
{
......@@ -122,20 +137,22 @@ extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
extern void argp_fmtstream_free (argp_fmtstream_t __fs);
extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
const char *__fmt, ...);
__const char *__fmt, ...)
__attribute__ ((__format__ (printf, 2, 3)));
extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
const char *__fmt, ...);
__const char *__fmt, ...)
__attribute__ ((__format__ (printf, 2, 3)));
extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
const char *__str, size_t __len);
__const char *__str, size_t __len);
extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
const char *__str, size_t __len);
__const char *__str, size_t __len);
/* Access macros for various bits of state. */
#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
......@@ -194,7 +211,7 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
ARGP_FS_EI size_t
__argp_fmtstream_write (argp_fmtstream_t __fs,
const char *__str, size_t __len)
__const char *__str, size_t __len)
{
if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
{
......@@ -207,7 +224,7 @@ __argp_fmtstream_write (argp_fmtstream_t __fs,
}
ARGP_FS_EI int
__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str)
__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
{
size_t __len = strlen (__str);
if (__len)
......
/* Real definitions for extern inline functions in argp-fmtstream.h
Copyright (C) 1997 Free Software Foundation, Inc.
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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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>
......@@ -24,9 +23,11 @@
#define ARGP_FS_EI
#undef __OPTIMIZE__
#define __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)
......@@ -39,3 +40,4 @@ weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin)
weak_alias (__argp_fmtstream_point, argp_fmtstream_point)
#endif
#endif
......
/* Hierarchial argument parsing help output
Copyright (C) 1995,1996,1997,1998,1999,2000, 2001 Free Software Foundation, Inc.
Copyright (C) 1995-2003, 2004, 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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
......@@ -26,73 +25,35 @@
#include <config.h>
#endif
#include <mailutils/nls.h>
#ifndef alloca
# ifdef __GNUC__
# define alloca __builtin_alloca
# define HAVE_ALLOCA 1
# else
# if defined HAVE_ALLOCA_H || defined _LIBC
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca
char *alloca ();
# endif
# endif
# endif
# endif
#endif
#include <alloca.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
#include <ctype.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#include <limits.h>
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
#ifndef _
/* This is for other GNU distributions with internationalized messages. */
# if defined HAVE_LIBINTL_H || defined _LIBC
#ifdef _LIBC
# include <libintl.h>
# ifdef _LIBC
# undef dgettext
# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES)
# endif
# else
# define dgettext(domain, msgid) (msgid)
# endif
# define dgettext(domain, msgid) \
INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
#else
# include "gettext.h"
#endif
#include "argp.h"
#include "argp-fmtstream.h"
#include "argp-namefrob.h"
#ifndef __P
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
# define __P(Args) Args
# else
# define __P(Args) ()
# endif
#endif
#if !HAVE_DECL_STRCHRNUL
extern char *strchrnul __P((const char *s, int c_in));
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#if !HAVE_DECL_STRNDUP
extern char *strndup __P((const char *s, size_t n));
#endif
/* User-selectable (using an environment variable) formatting parameters.
......@@ -267,6 +228,9 @@ fill_in_uparams (const struct argp_state *state)
/* Returns true if OPT is an documentation-only entry. */
#define odoc(opt) ((opt)->flags & OPTION_DOC)
/* Returns true if OPT should not be translated */
#define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS)
/* Returns true if OPT is the end-of-list marker for a list of options. */
#define oend(opt) __option_is_end (opt)
......@@ -462,6 +426,8 @@ make_hol (const struct argp *argp, struct hol_cluster *cluster)
hol->short_options = malloc (num_short_options + 1);
assert (hol->entries && hol->short_options);
if (SIZE_MAX <= UINT_MAX)
assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
/* Fill in the entries. */
so = hol->short_options;
......@@ -566,7 +532,8 @@ hol_entry_short_iterate (const struct hol_entry *entry,
return val;
}
static int
static inline int
__attribute__ ((always_inline))
hol_entry_long_iterate (const struct hol_entry *entry,
int (*func)(const struct argp_option *opt,
const struct argp_option *real,
......@@ -590,7 +557,7 @@ hol_entry_long_iterate (const struct hol_entry *entry,
}
/* Iterator that returns true for the first short option. */
static int
static inline int
until_short (const struct argp_option *opt, const struct argp_option *real,
const char *domain, void *cookie)
{
......@@ -712,6 +679,11 @@ static int
canon_doc_option (const char **name)
{
int non_opt;
if (!*name)
non_opt = 1;
else
{
/* Skip initial whitespace. */
while (isspace (**name))
(*name)++;
......@@ -720,6 +692,7 @@ canon_doc_option (const char **name)
/* Skip until part of name used for sorting. */
while (**name && !isalnum (**name))
(*name)++;
}
return non_opt;
}
......@@ -772,7 +745,7 @@ hol_entry_cmp (const struct hol_entry *entry1,
return doc1 - doc2;
else if (!short1 && !short2 && long1 && long2)
/* Only long options. */
return strcasecmp (long1, long2);
return __strcasecmp (long1, long2);
else
/* Compare short/short, long/short, short/long, using the first
character of long options. Entries without *any* valid
......@@ -853,12 +826,16 @@ hol_append (struct hol *hol, struct hol *more)
char *short_options =
malloc (hol_so_len + strlen (more->short_options) + 1);
memcpy (entries, hol->entries,
hol->num_entries * sizeof (struct hol_entry));
memcpy (entries + hol->num_entries, more->entries,
assert (entries && short_options);
if (SIZE_MAX <= UINT_MAX)
assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry));
__mempcpy (__mempcpy (entries, hol->entries,
hol->num_entries * sizeof (struct hol_entry)),
more->entries,
more->num_entries * sizeof (struct hol_entry));
memcpy (short_options, hol->short_options, hol_so_len);
__mempcpy (short_options, hol->short_options, hol_so_len);
/* Fix up the short options pointers from HOL. */
for (e = entries, left = hol->num_entries; left > 0; e++, left--)
......@@ -1078,9 +1055,8 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
int old_wm = __argp_fmtstream_wmargin (stream);
/* PEST is a state block holding some of our variables that we'd like to
share with helper functions. */
/* Some loosing compiler can not handle this ... lets play nice. */
/* struct pentry_state pest = { entry, stream, hhstate, 1, state }; */
struct pentry_state pest;
pest.entry = entry;
pest.stream = stream;
pest.hhstate = hhstate;
......@@ -1120,13 +1096,15 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
{
__argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
for (opt = real, num = entry->num; num > 0; opt++, num--)
if (opt->name && ovisible (opt))
if (opt->name && *opt->name && ovisible (opt))
{
comma (uparams.doc_opt_col, &pest);
/* Calling gettext here isn't quite right, since sorting will
/* Calling dgettext here isn't quite right, since sorting will
have been done on the original; but documentation options
should be pretty rare anyway... */
__argp_fmtstream_puts (stream,
onotrans (opt) ?
opt->name :
dgettext (state->root_argp->argp_domain,
opt->name));
}
......@@ -1406,7 +1384,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
if (fdoc)
{
const char *cp = fdoc;
nl = strchrnul (cp, '\n');
nl = __strchrnul (cp, '\n');
if (*nl != '\0')
/* This is a `multi-level' args doc; advance to the correct position
as determined by our state in LEVELS, and update LEVELS. */
......@@ -1414,7 +1392,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
int i;
multiple = 1;
for (i = 0; i < *our_level; i++)
cp = nl + 1, nl = strchrnul (cp, '\n');
cp = nl + 1, nl = __strchrnul (cp, '\n');
(*levels)++;
}
......@@ -1482,7 +1460,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
{
if (inp_text_limit)
/* Copy INP_TEXT so that it's nul-terminated. */
inp_text = strndup (inp_text, inp_text_limit);
inp_text = __strndup (inp_text, inp_text_limit);
input = __argp_input (argp, state);
text =
(*argp->help_filter) (post
......@@ -1556,12 +1534,19 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
if (! stream)
return;
#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__flockfile (stream);
#endif
if (! uparams.valid)
fill_in_uparams (state);
fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
if (! fs)
{
#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
#endif
return;
}
......@@ -1669,6 +1654,10 @@ Try `%s --help' or `%s --usage' for more information.\n"),
anything = 1;
}
#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
#endif
if (hol)
hol_free (hol);
......@@ -1680,12 +1669,34 @@ Try `%s --help' or `%s --usage' for more information.\n"),
void __argp_help (const struct argp *argp, FILE *stream,
unsigned flags, char *name)
{
_help (argp, 0, stream, flags, name);
struct argp_state state;
memset (&state, 0, sizeof state);
state.root_argp = argp;
_help (argp, &state, stream, flags, name);
}
#ifdef weak_alias
weak_alias (__argp_help, argp_help)
#endif
#if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
char *
__argp_short_program_name (void)
{
# if HAVE_DECL_PROGRAM_INVOCATION_NAME
char *name = strrchr (program_invocation_name, '/');
return name ? name + 1 : program_invocation_name;
# else
/* FIXME: What now? Miles suggests that it is better to use NULL,
but currently the value is passed on directly to fputs_unlocked,
so that requires more changes. */
# if __GNUC__
# warning No reasonable value to return
# endif /* __GNUC__ */
return "";
# endif
}
#endif
/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
from the set ARGP_HELP_*. */
void
......@@ -1697,7 +1708,7 @@ __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
flags |= ARGP_HELP_LONG_ONLY;
_help (state ? state->root_argp : 0, state, stream, flags,
state ? state->name : program_invocation_short_name);
state ? state->name : __argp_short_program_name ());
if (!state || ! (state->flags & ARGP_NO_EXIT))
{
......@@ -1726,19 +1737,47 @@ __argp_error (const struct argp_state *state, const char *fmt, ...)
{
va_list ap;
fputs (state ? state->name : program_invocation_short_name,
stream);
putc (':', stream);
putc (' ', stream);
#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__flockfile (stream);
#endif
va_start (ap, fmt);
#ifdef USE_IN_LIBIO
if (_IO_fwide (stream, 0) > 0)
{
char *buf;
if (__asprintf (&buf, fmt, ap) < 0)
buf = NULL;
__fwprintf (stream, L"%s: %s\n",
state ? state->name : __argp_short_program_name (),
buf);
free (buf);
}
else
#endif
{
fputs_unlocked (state
? state->name : __argp_short_program_name (),
stream);
putc_unlocked (':', stream);
putc_unlocked (' ', stream);
vfprintf (stream, fmt, ap);
va_end (ap);
putc ('\n', stream);
putc_unlocked ('\n', stream);
}
__argp_state_help (state, stream, ARGP_HELP_STD_ERR);
va_end (ap);
#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
#endif
}
}
}
......@@ -1764,29 +1803,88 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
if (stream)
{
fputs (state ? state->name : program_invocation_short_name,
#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__flockfile (stream);
#endif
#ifdef USE_IN_LIBIO
if (_IO_fwide (stream, 0) > 0)
__fwprintf (stream, L"%s",
state ? state->name : __argp_short_program_name ());
else
#endif
fputs_unlocked (state
? state->name : __argp_short_program_name (),
stream);
if (fmt)
{
va_list ap;
putc (':', stream);
putc (' ', stream);
va_start (ap, fmt);
#ifdef USE_IN_LIBIO
if (_IO_fwide (stream, 0) > 0)
{
char *buf;
if (__asprintf (&buf, fmt, ap) < 0)
buf = NULL;
__fwprintf (stream, L": %s", buf);
free (buf);
}
else
#endif
{
putc_unlocked (':', stream);
putc_unlocked (' ', stream);
vfprintf (stream, fmt, ap);
}
va_end (ap);
}
if (errnum)
{
putc (':', stream);
putc (' ', stream);
fputs (strerror (errnum), stream);
char buf[200];
#ifdef USE_IN_LIBIO
if (_IO_fwide (stream, 0) > 0)
__fwprintf (stream, L": %s",
__strerror_r (errnum, buf, sizeof (buf)));
else
#endif
{
char const *s = NULL;
putc_unlocked (':', stream);
putc_unlocked (' ', stream);
#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P)
s = __strerror_r (errnum, buf, sizeof buf);
#elif HAVE_DECL_STRERROR_R
if (__strerror_r (errnum, buf, sizeof buf) == 0)
s = buf;
#endif
#if !_LIBC
if (! s && ! (s = strerror (errnum)))
s = dgettext (state->root_argp->argp_domain,
"Unknown system error");
#endif
fputs (s, stream);
}
}
putc ('\n', stream);
#ifdef USE_IN_LIBIO
if (_IO_fwide (stream, 0) > 0)
putwc_unlocked (L'\n', stream);
else
#endif
putc_unlocked ('\n', stream);
#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
__funlockfile (stream);
#endif
if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
exit (status);
......
/* Name frobnication for compiling argp outside of glibc
Copyright (C) 1997, 2001 Free Software Foundation, Inc.
Copyright (C) 1997, 2003 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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !_LIBC
/* This code is written for inclusion in gnu-libc, and uses names in the
......@@ -77,12 +76,81 @@
#undef __argp_fmtstream_wmargin
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
#include "mempcpy.h"
#include "strcase.h"
#include "strchrnul.h"
#include "strndup.h"
/* normal libc functions we call */
#undef __flockfile
#define __flockfile flockfile
#undef __funlockfile
#define __funlockfile funlockfile
#undef __mempcpy
#define __mempcpy mempcpy
#undef __sleep
#define __sleep sleep
#undef __strcasecmp
#define __strcasecmp strcasecmp
#undef __strchrnul
#define __strchrnul strchrnul
#undef __strerror_r
#define __strerror_r strerror_r
#undef __strndup
#define __strndup strndup
#undef __vsnprintf
#define __vsnprintf vsnprintf
#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
# define clearerr_unlocked(x) clearerr (x)
#endif
#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
# define feof_unlocked(x) feof (x)
# endif
#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
# define ferror_unlocked(x) ferror (x)
# endif
#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
# define fflush_unlocked(x) fflush (x)
# endif
#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
# define fgets_unlocked(x,y,z) fgets (x,y,z)
# endif
#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED
# define fputc_unlocked(x,y) fputc (x,y)
# endif
#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
# define fputs_unlocked(x,y) fputs (x,y)
# endif
#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
# endif
#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
# endif
#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED
# define getc_unlocked(x) getc (x)
# endif
#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED
# define getchar_unlocked() getchar ()
# endif
#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED
# define putc_unlocked(x,y) putc (x,y)
# endif
#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED
# define putchar_unlocked(x) putchar (x)
# endif
extern char *__argp_basename (char *name);
#endif /* !_LIBC */
#ifndef __set_errno
#define __set_errno(e) (errno = (e))
#endif
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
# define __argp_short_program_name() (program_invocation_short_name)
#else
extern char *__argp_short_program_name (void);
#endif
......
/* Hierarchial argument parsing, layered over getopt
Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc.
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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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 <alloca.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <getopt.h>
#include <getopt_int.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#include <mailutils/nls.h>
#ifndef _
/* This is for other GNU distributions with internationalized messages.
When compiling libc, the _ macro is predefined. */
# if defined HAVE_LIBINTL_H || defined _LIBC
#ifdef _LIBC
# include <libintl.h>
# ifdef _LIBC
# undef dgettext
# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES)
# endif
# else
# define dgettext(domain, msgid) (msgid)
# define gettext(msgid) (msgid)
# endif
#endif
#ifndef N_
# define N_(msgid) msgid
#endif
#if _LIBC - 0
#include <bits/libc-lock.h>
# define dgettext(domain, msgid) \
INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
#else
#ifdef HAVE_CTHREADS_H
#include <cthreads.h>
# include "gettext.h"
#endif
#endif /* _LIBC */
#define N_(msgid) msgid
#include "argp.h"
#include "argp-namefrob.h"
#define alignof(type) offsetof (struct { char c; type x; }, x)
#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d))
/* Getopt return values. */
#define KEY_END (-1) /* The end of the options. */
#define KEY_ARG 1 /* A non-option argument. */
......@@ -92,7 +71,7 @@
for one second intervals, decrementing _ARGP_HANG until it's zero. Thus
you can force the program to continue by attaching a debugger and setting
it to 0 yourself. */
volatile int _argp_hang;
static volatile int _argp_hang;
#define OPT_PROGNAME -2
#define OPT_USAGE -3
......@@ -101,11 +80,11 @@ volatile int _argp_hang;
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")},
{"usage", OPT_USAGE, 0, 0, N_("Give a short usage message"), 0},
{"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name"), 0},
{"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
N_("Hang for SECS seconds (default 3600)")},
{0, 0}
N_("Hang for SECS seconds (default 3600)"), 0},
{NULL, 0, 0, 0, NULL, 0}
};
static error_t
......@@ -122,31 +101,35 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
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.] */
arg = strrchr (arg, '/');
if (arg)
program_invocation_short_name = arg + 1;
else
program_invocation_short_name = program_invocation_name;
/* Update what we use for messages. */
state->name = program_invocation_short_name;
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] = program_invocation_name;
state->argv[0] = arg;
break;
case OPT_HANG:
_argp_hang = atoi (arg ? arg : "3600");
while (_argp_hang-- > 0)
sleep (1);
__sleep (1);
break;
default:
......@@ -162,7 +145,7 @@ static const struct argp argp_default_argp =
static const struct argp_option argp_version_options[] =
{
{"version", 'V', 0, 0, N_("Print program version"), -1},
{0, 0}
{NULL, 0, 0, 0, NULL, 0}
};
static error_t
......@@ -208,41 +191,6 @@ find_long_option (struct option *long_options, const char *name)
return -1;
}
/* If we can, we regulate access to getopt, which is non-reentrant, with a
mutex. Since the case we're trying to guard against is two different
threads interfering, and it's possible that someone might want to call
argp_parse recursively (they're careful), we use a recursive lock if
possible. */
#if _LIBC - 0
__libc_lock_define_initialized_recursive (static, getopt_lock)
#define LOCK_GETOPT __libc_lock_lock_recursive (getopt_lock)
#define UNLOCK_GETOPT __libc_lock_unlock_recursive (getopt_lock)
#else /* !_LIBC */
#if defined(HAVE_CTHREADS_H)
static struct mutex getopt_lock = MUTEX_INITIALIZER;
#define LOCK_GETOPT mutex_lock (&getopt_lock)
#define UNLOCK_GETOPT mutex_unlock (&getopt_lock)
#else /* !HAVE_CTHREADS_H */
#define LOCK_GETOPT (void)0
#define UNLOCK_GETOPT (void)0
#endif /* HAVE_CTHREADS_H */
#endif /* _LIBC */
/* This hack to allow programs that know what's going on to call argp
recursively. If someday argp is changed not to use the non-reentrant
getopt interface, we can get rid of this shit. XXX */
void
_argp_unlock_xxx (void)
{
UNLOCK_GETOPT;
}
/* The state of a `group' during parsing. Each group corresponds to a
particular argp structure from the tree of such descending from the top
......@@ -304,6 +252,8 @@ struct parser
/* 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;
......@@ -515,6 +465,12 @@ parser_init (struct parser *parser, const struct argp *argp,
error_t err = 0;
struct group *group;
struct parser_sizes szs;
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
char *storage;
size_t glen, gsum;
size_t clen, csum;
size_t llen, lsum;
size_t slen, ssum;
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
szs.long_len = 0;
......@@ -525,26 +481,33 @@ parser_init (struct parser *parser, const struct argp *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);
glen = (szs.num_groups + 1) * sizeof (struct group);
clen = szs.num_child_inputs * sizeof (void *);
llen = (szs.long_len + 1) * sizeof (struct option);
slen = szs.short_len + 1;
/* Sums of previous lengths, properly aligned. There's no need to
align gsum, since struct group is aligned at least as strictly as
void * (since it contains a void * member). And there's no need
to align lsum, since struct option is aligned at least as
strictly as char. */
gsum = glen;
csum = alignto (gsum + clen, alignof (struct option));
lsum = csum + llen;
ssum = lsum + slen;
parser->storage = malloc (ssum);
if (! parser->storage)
return ENOMEM;
parser->groups = (struct group *) parser->storage;
/* To please Watcom CC
parser->child_inputs = parser->storage + GLEN;
parser->long_opts = parser->storage + GLEN + CLEN;
parser->short_opts = parser->storage + GLEN + CLEN + LLEN;
*/
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;
memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
storage = parser->storage;
parser->groups = parser->storage;
parser->child_inputs = (void **) (storage + gsum);
parser->long_opts = (struct option *) (storage + csum);
parser->short_opts = storage + lsum;
parser->opt_data = opt_data;
memset (parser->child_inputs, 0, clen);
parser_convert (parser, argp, flags);
memset (&parser->state, 0, sizeof (struct argp_state));
......@@ -586,19 +549,16 @@ parser_init (struct parser *parser, const struct argp *argp,
if (err)
return err;
/* Getopt is (currently) non-reentrant. */
LOCK_GETOPT;
if (parser->state.flags & ARGP_NO_ERRS)
{
opterr = 0;
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
opterr = 1; /* Print error messages. */
parser->opt_data.opterr = 1; /* Print error messages. */
if (parser->state.argv == argv && argv[0])
/* There's an argv[0]; use it for messages. */
......@@ -607,7 +567,7 @@ parser_init (struct parser *parser, const struct argp *argp,
parser->state.name = short_name ? short_name + 1 : argv[0];
}
else
parser->state.name = program_invocation_short_name;
parser->state.name = __argp_short_program_name ();
return 0;
}
......@@ -619,8 +579,6 @@ parser_finalize (struct parser *parser,
{
struct group *group;
UNLOCK_GETOPT;
if (err == EBADKEY && arg_ebadkey)
/* Suppress errors generated by unparsed arguments. */
err = 0;
......@@ -782,7 +740,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
for (group = parser->groups; group < parser->egroup; group++)
if (group->short_end > short_index)
{
err = group_parse (group, &parser->state, opt, optarg);
err = group_parse (group, &parser->state, opt,
parser->opt_data.optarg);
break;
}
}
......@@ -791,7 +750,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
the user value in order to preserve the sign. */
err =
group_parse (&parser->groups[group_key - 1], &parser->state,
(opt << GROUP_BITS) >> GROUP_BITS, optarg);
(opt << GROUP_BITS) >> GROUP_BITS,
parser->opt_data.optarg);
if (err == EBADKEY)
/* At least currently, an option not recognized is an error in the
......@@ -837,15 +797,20 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey)
if (parser->try_getopt && !parser->state.quoted)
/* Give getopt a chance to parse this. */
{
optind = parser->state.next; /* Put it back in OPTIND for getopt. */
optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */
/* 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 (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0);
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 (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0);
parser->state.next = optind; /* And see what getopt did. */
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
......@@ -861,7 +826,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey)
here, whatever happens. */
parser->state.quoted = parser->state.next;
}
else if (opt == KEY_ERR && optopt != KEY_END)
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. */
......@@ -887,15 +852,15 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey)
/* A non-option arg; simulate what getopt might have done. */
{
opt = KEY_ARG;
optarg = parser->state.argv[parser->state.next++];
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, optarg);
err = parser_parse_arg (parser, parser->opt_data.optarg);
else
err = parser_parse_opt (parser, opt, optarg);
err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
if (err == EBADKEY)
*arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
......
......@@ -3,20 +3,19 @@
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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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
......
/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1999, 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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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>
......@@ -29,4 +28,4 @@
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);
void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL;
......
/* Real definitions for extern inline functions in argp.h
Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc.
Copyright (C) 1997, 1998, 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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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
#if defined _LIBC || defined HAVE_FEATURES_H
# include <features.h>
#endif
#ifndef __USE_EXTERN_INLINES
# define __USE_EXTERN_INLINES 1
#endif
#define ARGP_EI
#undef __OPTIMIZE__
#define __OPTIMIZE__
#define __OPTIMIZE__ 1
#include "argp.h"
/* Add weak aliases. */
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
/* getline.c -- Replacement for GNU C library function getline
This 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 of the License, or (at your option) any later version.
Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003, 2004 Free
Software Foundation, Inc.
This library is distributed in the hope that it will be useful,
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* First implementation by Alain Magloire */
/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */
#ifdef HAVE_CONFIG_H
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ssize_t
getline (char **lineptr, size_t *n, FILE *stream)
{
return getdelim (lineptr, n, '\n', stream);
}
#include "getline.h"
#ifndef HAVE_GETDELIM
#if ! (defined __GNU_LIBRARY__ && HAVE_GETDELIM)
/* Default value for line length. */
static const int line_size = 128;
# include "getndelim2.h"
ssize_t
getdelim (char **lineptr, size_t *n, int delim, FILE *stream)
getdelim (char **lineptr, size_t *linesize, int delimiter, FILE *stream)
{
int indx = 0;
int c;
/* Sanity checks. */
if (lineptr == NULL || n == NULL || stream == NULL)
return -1;
/* Allocate the line the first time. */
if (*lineptr == NULL)
{
*lineptr = malloc (line_size);
if (*lineptr == NULL)
return -1;
*n = line_size;
}
while ((c = getc (stream)) != EOF)
{
/* Check if more memory is needed. */
if (indx >= *n)
{
*lineptr = realloc (*lineptr, *n + line_size);
if (*lineptr == NULL)
return -1;
*n += line_size;
}
/* Push the result in the line. */
(*lineptr)[indx++] = c;
/* Bail out. */
if (c == delim)
break;
}
/* Make room for the null character. */
if (indx >= *n)
{
*lineptr = realloc (*lineptr, *n + line_size);
if (*lineptr == NULL)
return -1;
*n += line_size;
}
/* Null terminate the buffer. */
(*lineptr)[indx++] = 0;
/* The last line may not have the delimiter, we have to
* return what we got and the error will be seen on the
* next iteration. */
return (c == EOF && (indx - 1) == 0) ? -1 : indx - 1;
return getndelim2 (lineptr, linesize, 0, GETNLINE_NO_LIMIT, delimiter, EOF,
stream);
}
#endif
#endif /* HAVE_GETDELIM */
#ifdef STANDALONE
int main(void)
ssize_t
getline (char **lineptr, size_t *linesize, FILE *stream)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/etc/passwd", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
if (line)
free(line);
return EXIT_SUCCESS;
return getdelim (lineptr, linesize, '\n', stream);
}
#endif
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
/* Replacement for GNU C library function getline
This 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 of the License, or (at your option) any later version.
Copyright (C) 1995, 1997, 1999, 2000, 2001, 2002, 2003 Free
Software Foundation, Inc.
This 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.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
This program 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 General Public License for more details.
#ifndef _GETLINE_H_
# define _GETLINE_H_ 1
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef GETLINE_H_
# define GETLINE_H_ 1
# include <stddef.h>
# include <stdio.h>
# ifndef PARAMS
# if defined (__GNUC__) || __STDC__
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
# endif
/* Get ssize_t. */
# include <sys/types.h>
extern int getline PARAMS ((char **_lineptr, size_t *_n, FILE *_stream));
/* glibc2 has these functions declared in <stdio.h>. Avoid redeclarations. */
# if __GLIBC__ < 2
extern int getdelim PARAMS ((char **_lineptr, size_t *_n, int _delimiter, FILE *_stream));
extern ssize_t getline (char **_lineptr, size_t *_linesize, FILE *_stream);
extern ssize_t getdelim (char **_lineptr, size_t *_linesize, int _delimiter,
FILE *_stream);
# endif
#endif /* ! _GETLINE_H_ */
#endif /* not GETLINE_H_ */
......
/* Getopt for GNU.
NOTE: The canonical source of this file is maintained with the GNU
C Library. Bugs can be reported to bug-glibc@gnu.org.
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it!
Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
......@@ -29,35 +30,8 @@
# include <config.h>
#endif
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
# ifndef const
# define const
# endif
#endif
#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__
......@@ -67,40 +41,43 @@
# include <unistd.h>
#endif /* GNU C library. */
#include <string.h>
#ifdef VMS
# include <unixlib.h>
# if HAVE_STRING_H - 0
# include <string.h>
# endif
#endif
#ifndef _
/* This is for other GNU distributions with internationalized messages. */
# if defined HAVE_LIBINTL_H || defined _LIBC
#ifdef _LIBC
# include <libintl.h>
# ifndef _
#else
# include "gettext.h"
# define _(msgid) gettext (msgid)
# endif
# else
# define _(msgid) (msgid)
# endif
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
#if defined _LIBC && defined USE_IN_LIBIO
# include <wchar.h>
#endif
#ifndef attribute_hidden
# define attribute_hidden
#endif
As `getopt' works, it permutes the elements of ARGV so that,
/* Unlike standard Unix `getopt', functions like `getopt_long'
let the user intersperse the options with the other arguments.
As `getopt_long' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
Using `getopt' or setting the environment variable POSIXLY_CORRECT
disables permutation.
Then the application's behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
#include "getopt_int.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
......@@ -125,21 +102,6 @@ char *optarg;
/* 1003.2 says this must be 1 before any call. */
int optind = 1;
/* Formerly, initialization of getopt depended on optind==0, which
causes problems with re-calling getopt as programs generally don't
know that. */
int __getopt_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. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
......@@ -151,57 +113,12 @@ int opterr = 1;
int optopt = '?';
/* 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.
/* Keep a global copy of all internal members of getopt_data. */
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.
static struct _getopt_data getopt_data;
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. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
static char *posixly_correct;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
# include <string.h>
# define my_index strchr
#else
# if HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
#ifndef __GNU_LIBRARY__
/* Avoid depending on library functions or files
whose names are inconsistent. */
......@@ -210,79 +127,34 @@ static char *posixly_correct;
extern char *getenv ();
#endif
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
# if (!defined __STDC__ || !__STDC__) && !defined strlen
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
extern int strlen (const char *);
# endif /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */
/* 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. */
static int first_nonopt;
static int last_nonopt;
#ifdef _LIBC
/* Stored original parameters.
XXX This is no good solution. We should rather copy the args so
that we can compare them later. But we must not use malloc(3). */
extern int __libc_argc;
extern char **__libc_argv;
/* Bash 2.0 gives us an environment variable containing flags
indicating ARGV elements that should not be considered arguments. */
# ifdef USE_NONOPTION_FLAGS
/* Defined in getopt_init.c */
extern char *__getopt_nonoption_flags;
# endif
static int nonoption_flags_max_len;
static int nonoption_flags_len;
static int original_argc;
static char *const *original_argv;
/* Make sure the environment variable bash 2.0 puts in the environment
is valid for the getopt call we must make sure that the ARGV passed
to getopt is that one passed to the process. */
static void
__attribute__ ((unused))
store_args_and_env (int argc, char *const *argv)
{
/* XXX This is no good solution. We should rather copy the args so
that we can compare them later. But we must not use malloc(3). */
original_argc = argc;
original_argv = argv;
}
# ifdef text_set_element
text_set_element (__libc_subinit, store_args_and_env);
# endif /* text_set_element */
# ifdef USE_NONOPTION_FLAGS
# define SWAP_FLAGS(ch1, ch2) \
if (nonoption_flags_len > 0) \
if (d->__nonoption_flags_len > 0) \
{ \
char __tmp = __getopt_nonoption_flags[ch1]; \
__getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
__getopt_nonoption_flags[ch2] = __tmp; \
}
# else
# define SWAP_FLAGS(ch1, ch2)
# endif
#else /* !_LIBC */
# define SWAP_FLAGS(ch1, ch2)
#endif /* _LIBC */
......@@ -296,17 +168,12 @@ text_set_element (__libc_subinit, store_args_and_env);
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
#if defined __STDC__ && __STDC__
static void exchange (char **);
#endif
static void
exchange (argv)
char **argv;
exchange (char **argv, struct _getopt_data *d)
{
int bottom = first_nonopt;
int middle = last_nonopt;
int top = optind;
int bottom = d->__first_nonopt;
int middle = d->__last_nonopt;
int top = d->optind;
char *tem;
/* Exchange the shorter segment with the far end of the longer segment.
......@@ -314,23 +181,23 @@ exchange (argv)
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
#ifdef _LIBC
#if defined _LIBC && defined USE_NONOPTION_FLAGS
/* First make sure the handling of the `__getopt_nonoption_flags'
string can work normally. Our top argument must be in the range
of the string. */
if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
{
/* We must extend the array. The user plays games with us and
presents new arguments. */
char *new_str = malloc (top + 1);
if (new_str == NULL)
nonoption_flags_len = nonoption_flags_max_len = 0;
d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
else
{
memset (__mempcpy (new_str, __getopt_nonoption_flags,
nonoption_flags_max_len),
'\0', top + 1 - nonoption_flags_max_len);
nonoption_flags_max_len = top + 1;
d->__nonoption_flags_max_len),
'\0', top + 1 - d->__nonoption_flags_max_len);
d->__nonoption_flags_max_len = top + 1;
__getopt_nonoption_flags = new_str;
}
}
......@@ -376,76 +243,71 @@ exchange (argv)
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
d->__first_nonopt += (d->optind - d->__last_nonopt);
d->__last_nonopt = d->optind;
}
/* Initialize the internal data when the first call is made. */
#if defined __STDC__ && __STDC__
static const char *_getopt_initialize (int, char *const *, const char *);
#endif
static const char *
_getopt_initialize (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
_getopt_initialize (int argc, char **argv, const char *optstring,
int posixly_correct, struct _getopt_data *d)
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
first_nonopt = last_nonopt = optind;
d->__first_nonopt = d->__last_nonopt = d->optind;
nextchar = NULL;
d->__nextchar = NULL;
posixly_correct = getenv ("POSIXLY_CORRECT");
d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
d->__ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
d->__ordering = REQUIRE_ORDER;
++optstring;
}
else if (posixly_correct != NULL)
ordering = REQUIRE_ORDER;
else if (d->__posixly_correct)
d->__ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
d->__ordering = PERMUTE;
#ifdef _LIBC
if (posixly_correct == NULL
&& argc == original_argc && argv == original_argv)
#if defined _LIBC && defined USE_NONOPTION_FLAGS
if (!d->__posixly_correct
&& argc == __libc_argc && argv == __libc_argv)
{
if (nonoption_flags_max_len == 0)
if (d->__nonoption_flags_max_len == 0)
{
if (__getopt_nonoption_flags == NULL
|| __getopt_nonoption_flags[0] == '\0')
nonoption_flags_max_len = -1;
d->__nonoption_flags_max_len = -1;
else
{
const char *orig_str = __getopt_nonoption_flags;
int len = nonoption_flags_max_len = strlen (orig_str);
if (nonoption_flags_max_len < argc)
nonoption_flags_max_len = argc;
int len = d->__nonoption_flags_max_len = strlen (orig_str);
if (d->__nonoption_flags_max_len < argc)
d->__nonoption_flags_max_len = argc;
__getopt_nonoption_flags =
(char *) malloc (nonoption_flags_max_len);
(char *) malloc (d->__nonoption_flags_max_len);
if (__getopt_nonoption_flags == NULL)
nonoption_flags_max_len = -1;
d->__nonoption_flags_max_len = -1;
else
memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
'\0', nonoption_flags_max_len - len);
'\0', d->__nonoption_flags_max_len - len);
}
}
nonoption_flags_len = nonoption_flags_max_len;
d->__nonoption_flags_len = d->__nonoption_flags_max_len;
}
else
nonoption_flags_len = 0;
d->__nonoption_flags_len = 0;
#endif
return optstring;
......@@ -493,10 +355,6 @@ _getopt_initialize (argc, argv, optstring)
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
......@@ -505,73 +363,74 @@ _getopt_initialize (argc, argv, optstring)
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
long-named options.
If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT
environment variable were set. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
_getopt_internal_r (int argc, char **argv, const char *optstring,
const struct option *longopts, int *longind,
int long_only, int posixly_correct, struct _getopt_data *d)
{
int print_errors = opterr;
int print_errors = d->opterr;
if (optstring[0] == ':')
print_errors = 0;
if (argc < 1)
return -1;
optarg = NULL;
d->optarg = NULL;
if (optind == 0 || !__getopt_initialized)
if (d->optind == 0 || !d->__initialized)
{
if (optind == 0)
optind = 1; /* Don't scan ARGV[0], the program name. */
optstring = _getopt_initialize (argc, argv, optstring);
__getopt_initialized = 1;
if (d->optind == 0)
d->optind = 1; /* Don't scan ARGV[0], the program name. */
optstring = _getopt_initialize (argc, argv, optstring,
posixly_correct, d);
d->__initialized = 1;
}
/* Test whether ARGV[optind] points to a non-option argument.
Either it does not have option syntax, or there is an environment flag
from the shell indicating it is not an option. The later information
is only used when the used in the GNU libc. */
#ifdef _LIBC
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|| (optind < nonoption_flags_len \
&& __getopt_nonoption_flags[optind] == '1'))
#if defined _LIBC && defined USE_NONOPTION_FLAGS
# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
|| (d->optind < d->__nonoption_flags_len \
&& __getopt_nonoption_flags[d->optind] == '1'))
#else
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
#endif
if (nextchar == NULL || *nextchar == '\0')
if (d->__nextchar == NULL || *d->__nextchar == '\0')
{
/* Advance to the next ARGV-element. */
/* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
moved back by the user (who may also have changed the arguments). */
if (last_nonopt > optind)
last_nonopt = optind;
if (first_nonopt > optind)
first_nonopt = optind;
if (d->__last_nonopt > d->optind)
d->__last_nonopt = d->optind;
if (d->__first_nonopt > d->optind)
d->__first_nonopt = d->optind;
if (ordering == PERMUTE)
if (d->__ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
exchange ((char **) argv, d);
else if (d->__last_nonopt != d->optind)
d->__first_nonopt = d->optind;
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc && NONOPTION_P)
optind++;
last_nonopt = optind;
while (d->optind < argc && NONOPTION_P)
d->optind++;
d->__last_nonopt = d->optind;
}
/* The special ARGV-element `--' means premature end of options.
......@@ -579,28 +438,29 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
if (d->optind != argc && !strcmp (argv[d->optind], "--"))
{
optind++;
d->optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
exchange ((char **) argv, d);
else if (d->__first_nonopt == d->__last_nonopt)
d->__first_nonopt = d->optind;
d->__last_nonopt = argc;
optind = argc;
d->optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
if (d->optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
if (d->__first_nonopt != d->__last_nonopt)
d->optind = d->__first_nonopt;
return -1;
}
......@@ -609,17 +469,17 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (NONOPTION_P)
{
if (ordering == REQUIRE_ORDER)
if (d->__ordering == REQUIRE_ORDER)
return -1;
optarg = argv[optind++];
d->optarg = argv[d->optind++];
return 1;
}
/* We have found another option-ARGV-element.
Skip the initial punctuation. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
d->__nextchar = (argv[d->optind] + 1
+ (longopts != NULL && argv[d->optind][1] == '-'));
}
/* Decode the current option-ARGV-element. */
......@@ -638,8 +498,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
This distinction seems to be the most useful approach. */
if (longopts != NULL
&& (argv[optind][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
&& (argv[d->optind][1] == '-'
|| (long_only && (argv[d->optind][2]
|| !strchr (optstring, argv[d->optind][1])))))
{
char *nameend;
const struct option *p;
......@@ -649,15 +510,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int indfound = -1;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ;
/* Test all long options for either exact match
or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
{
if ((unsigned int) (nameend - nextchar)
if ((unsigned int) (nameend - d->__nextchar)
== (unsigned int) strlen (p->name))
{
/* Exact match found. */
......@@ -683,62 +544,158 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (print_errors)
{
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[d->optind]) >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#else
fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
optopt = 0;
argv[0], argv[d->optind]);
#endif
}
d->__nextchar += strlen (d->__nextchar);
d->optind++;
d->optopt = 0;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
d->optind++;
if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = nameend + 1;
d->optarg = nameend + 1;
else
{
if (print_errors)
{
if (argv[optind - 1][1] == '-')
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
int n;
#endif
if (argv[d->optind - 1][1] == '-')
{
/* --option */
fprintf (stderr,
_("%s: option `--%s' doesn't allow an argument\n"),
#if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("\
%s: option `--%s' doesn't allow an argument\n"),
argv[0], pfound->name);
#else
fprintf (stderr, _("\
%s: option `--%s' doesn't allow an argument\n"),
argv[0], pfound->name);
#endif
}
else
{
/* +option or -option */
fprintf (stderr,
_("%s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[optind - 1][0], pfound->name);
#if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("\
%s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[d->optind - 1][0],
pfound->name);
#else
fprintf (stderr, _("\
%s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[d->optind - 1][0],
pfound->name);
#endif
}
#if defined _LIBC && defined USE_IN_LIBIO
if (n >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#endif
}
nextchar += strlen (nextchar);
d->__nextchar += strlen (d->__nextchar);
optopt = pfound->val;
d->optopt = pfound->val;
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
if (__asprintf (&buf, _("\
%s: option `%s' requires an argument\n"),
argv[0], argv[d->optind - 1]) >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#else
fprintf (stderr,
_("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
optopt = pfound->val;
argv[0], argv[d->optind - 1]);
#endif
}
d->__nextchar += strlen (d->__nextchar);
d->optopt = pfound->val;
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
d->__nextchar += strlen (d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
......@@ -753,23 +710,62 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
|| my_index (optstring, *nextchar) == NULL)
if (!long_only || argv[d->optind][1] == '-'
|| strchr (optstring, *d->__nextchar) == NULL)
{
if (print_errors)
{
if (argv[optind][1] == '-')
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
int n;
#endif
if (argv[d->optind][1] == '-')
{
/* --option */
#if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
argv[0], d->__nextchar);
#else
fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar);
argv[0], d->__nextchar);
#endif
}
else
{
/* +option or -option */
#if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[d->optind][0], d->__nextchar);
#else
fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar);
argv[0], argv[d->optind][0], d->__nextchar);
#endif
}
#if defined _LIBC && defined USE_IN_LIBIO
if (n >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#endif
}
nextchar = (char *) "";
optind++;
optopt = 0;
d->__nextchar = (char *) "";
d->optind++;
d->optopt = 0;
return '?';
}
}
......@@ -777,26 +773,63 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* Look at and handle the next short option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
char c = *d->__nextchar++;
char *temp = strchr (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (*d->__nextchar == '\0')
++d->optind;
if (temp == NULL || c == ':')
{
if (print_errors)
{
if (posixly_correct)
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
int n;
#endif
if (d->__posixly_correct)
{
/* 1003.2 specifies the format of this message. */
fprintf (stderr, _("%s: illegal option -- %c\n"),
#if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
argv[0], c);
#else
fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
#endif
}
else
fprintf (stderr, _("%s: invalid option -- %c\n"),
{
#if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
argv[0], c);
#else
fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
#endif
}
#if defined _LIBC && defined USE_IN_LIBIO
if (n >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
optopt = c;
#endif
}
d->optopt = c;
return '?';
}
/* Convenience. Treat POSIX -W foo same as long option --foo */
......@@ -811,22 +844,46 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int option_index;
/* This is an option that requires an argument. */
if (*nextchar != '\0')
if (*d->__nextchar != '\0')
{
optarg = nextchar;
d->optarg = d->__nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
d->optind++;
}
else if (optind == argc)
else if (d->optind == argc)
{
if (print_errors)
{
/* 1003.2 specifies the format of this message. */
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
if (__asprintf (&buf,
_("%s: option requires an argument -- %c\n"),
argv[0], c) >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#else
fprintf (stderr, _("%s: option requires an argument -- %c\n"),
argv[0], c);
#endif
}
optopt = c;
d->optopt = c;
if (optstring[0] == ':')
c = ':';
else
......@@ -834,22 +891,23 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
return c;
}
else
/* We already incremented `optind' once;
/* We already incremented `d->optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
d->optarg = argv[d->optind++];
/* optarg is now the argument, see if it's in the
table of longopts. */
for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
nameend++)
/* Do nothing. */ ;
/* Test all long options for either exact match
or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
{
if ((unsigned int) (nameend - nextchar) == strlen (p->name))
if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
{
/* Exact match found. */
pfound = p;
......@@ -870,10 +928,35 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (print_errors)
{
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
argv[0], argv[d->optind]) >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#else
fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
argv[0], argv[d->optind]);
#endif
}
d->__nextchar += strlen (d->__nextchar);
d->optind++;
return '?';
}
if (pfound != NULL)
......@@ -884,33 +967,87 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = nameend + 1;
d->optarg = nameend + 1;
else
{
if (print_errors)
{
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
if (__asprintf (&buf, _("\
%s: option `-W %s' doesn't allow an argument\n"),
argv[0], pfound->name) >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#else
fprintf (stderr, _("\
%s: option `-W %s' doesn't allow an argument\n"),
argv[0], pfound->name);
#endif
}
nextchar += strlen (nextchar);
d->__nextchar += strlen (d->__nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
if (__asprintf (&buf, _("\
%s: option `%s' requires an argument\n"),
argv[0], argv[d->optind - 1]) >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#else
fprintf (stderr,
_("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
argv[0], argv[d->optind - 1]);
#endif
}
d->__nextchar += strlen (d->__nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
d->__nextchar += strlen (d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
......@@ -920,7 +1057,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
return pfound->val;
}
nextchar = NULL;
d->__nextchar = NULL;
return 'W'; /* Let the application handle it. */
}
if (temp[1] == ':')
......@@ -928,35 +1065,59 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
if (*d->__nextchar != '\0')
{
optarg = nextchar;
optind++;
d->optarg = d->__nextchar;
d->optind++;
}
else
optarg = NULL;
nextchar = NULL;
d->optarg = NULL;
d->__nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
if (*d->__nextchar != '\0')
{
optarg = nextchar;
d->optarg = d->__nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
d->optind++;
}
else if (optind == argc)
else if (d->optind == argc)
{
if (print_errors)
{
/* 1003.2 specifies the format of this message. */
#if defined _LIBC && defined USE_IN_LIBIO
char *buf;
if (__asprintf (&buf, _("\
%s: option requires an argument -- %c\n"),
argv[0], c) >= 0)
{
_IO_flockfile (stderr);
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
free (buf);
}
#else
fprintf (stderr,
_("%s: option requires an argument -- %c\n"),
argv[0], c);
#endif
}
optopt = c;
d->optopt = c;
if (optstring[0] == ':')
c = ':';
else
......@@ -965,8 +1126,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
d->optarg = argv[d->optind++];
d->__nextchar = NULL;
}
}
return c;
......@@ -974,18 +1135,40 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
_getopt_internal (int argc, char **argv, const char *optstring,
const struct option *longopts, int *longind,
int long_only, int posixly_correct)
{
int result;
getopt_data.optind = optind;
getopt_data.opterr = opterr;
result = _getopt_internal_r (argc, argv, optstring, longopts, longind,
long_only, posixly_correct, &getopt_data);
optind = getopt_data.optind;
optarg = getopt_data.optarg;
optopt = getopt_data.optopt;
return result;
}
/* glibc gets a LSB-compliant getopt.
Standalone applications get a POSIX-compliant getopt. */
#if _LIBC
enum { POSIXLY_CORRECT = 0 };
#else
enum { POSIXLY_CORRECT = 1 };
#endif
int
getopt (int argc, char *const *argv, const char *optstring)
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0,
POSIXLY_CORRECT);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
......@@ -993,9 +1176,7 @@ getopt (argc, argv, optstring)
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
int c;
int digit_optind = 0;
......
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@gnu.org.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
You should have received a copy of the GNU General Public License along
with this program; 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 "getopt.h"
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#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__
......@@ -64,14 +41,20 @@
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 0, 0);
}
int
_getopt_long_r (int argc, char **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, 0, d);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
......@@ -80,27 +63,30 @@ getopt_long (argc, argv, options, long_options, opt_index)
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
getopt_long_only (int argc, char *__getopt_argv_const *argv,
const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 1, 0);
}
int
_getopt_long_only_r (int argc, char **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, 0, d);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
int c;
int digit_optind = 0;
......
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
/*
* Modified (2001-01-31) to work on Sparcs <gray@Mirddin.farlep.net>
*/
#if defined(HAVE_CONFIG_H)
/* md5.c - Functions to compute MD5 message digest of files or memory blocks
according to the definition of MD5 in RFC 1321 from April 1992.
Copyright (C) 1995, 1996, 2001, 2003, 2004 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define MD5_CRYPT
#include "md5.h"
#include <stddef.h>
#include <string.h>
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifdef _LIBC
# include <endian.h>
# if __BYTE_ORDER == __BIG_ENDIAN
# define WORDS_BIGENDIAN 1
# endif
/* We need to keep the namespace clean so define the MD5 function
protected using leading __ . */
# define md5_init_ctx __md5_init_ctx
# define md5_process_block __md5_process_block
# define md5_process_bytes __md5_process_bytes
# define md5_finish_ctx __md5_finish_ctx
# define md5_read_ctx __md5_read_ctx
# define md5_stream __md5_stream
# define md5_buffer __md5_buffer
#endif
#ifdef WORDS_BIGENDIAN
# define SWAP(n) \
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
#else
# define SWAP(n) (n)
#endif
#define BLOCKSIZE 4096
/* Ensure that BLOCKSIZE is a multiple of 64. */
#if BLOCKSIZE % 64 != 0
/* FIXME-someday (soon?): use #error instead of this kludge. */
"invalid BLOCKSIZE"
#endif
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
#ifdef MD5_CRYPT
#include <string.h> /* for memcpy() */
#include <md5.h>
/* Initialize structure containing state of computation.
(RFC 1321, 3.3: Step 3) */
void
md5_calc(unsigned char *output, unsigned char *input, unsigned int inlen)
md5_init_ctx (struct md5_ctx *ctx)
{
MD5_CTX context;
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
MD5Init(&context);
MD5Update(&context, input, inlen);
MD5Final(output, &context);
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 0;
}
/* Put result from CTX in first 16 bytes following RESBUF. The result
must be in little endian byte order.
static void
bytes_encode(unsigned char *output, uint32 *input, unsigned int len)
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
void *
md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
{
unsigned int i, j;
((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
return resbuf;
}
static void
bytes_decode(uint32 *output, unsigned char *input, unsigned int len)
/* Process the remaining bytes in the internal buffer and the usual
prolog according to the standard and write the result to RESBUF.
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
void *
md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
{
unsigned int i, j;
/* Take yet unprocessed bytes into account. */
md5_uint32 bytes = ctx->buflen;
size_t pad;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
if (ctx->total[0] < bytes)
++ctx->total[1];
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
memcpy (&ctx->buffer[bytes], fillbuf, pad);
/* Put the 64-bit file length in *bits* at the end of the buffer. */
*(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
*(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
(ctx->total[0] >> 29));
/* Process last bytes. */
md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32)input[j]) |
(((uint32)input[j+1]) << 8) |
(((uint32)input[j+2]) << 16) |
(((uint32)input[j+3]) << 24);
return md5_read_ctx (ctx, resbuf);
}
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void
MD5Init(struct MD5Context *ctx)
/* Compute MD5 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 16 bytes
beginning at RESBLOCK. */
int
md5_stream (FILE *stream, void *resblock)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
struct md5_ctx ctx;
char buffer[BLOCKSIZE + 72];
size_t sum;
/* Initialize the computation context. */
md5_init_ctx (&ctx);
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
{
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
sum += n;
if (sum == BLOCKSIZE)
break;
if (n == 0)
{
/* Check for the error flag IFF N == 0, so that we don't
exit the loop after a partial read due to e.g., EAGAIN
or EWOULDBLOCK. */
if (ferror (stream))
return 1;
goto process_partial_block;
}
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/* We've read at least one byte, so ignore errors. But always
check for EOF, since feof may be true even though N > 0.
Otherwise, we could end up calling fread after EOF. */
if (feof (stream))
goto process_partial_block;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 64 == 0
*/
void
MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{
uint32 t;
md5_process_block (buffer, BLOCKSIZE, &ctx);
}
/* Update bitcount */
process_partial_block:;
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
/* Process any remaining bytes. */
if (sum > 0)
md5_process_bytes (buffer, sum, &ctx);
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
/* Construct result in desired memory. */
md5_finish_ctx (&ctx, resblock);
return 0;
}
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
void *
md5_buffer (const char *buffer, size_t len, void *resblock)
{
struct md5_ctx ctx;
while (len >= 64) {
memcpy(ctx->in, buf, 64);
MD5Transform(ctx->buf, (uint32 const *) buf);
buf += 64;
len -= 64;
}
/* Initialize the computation context. */
md5_init_ctx (&ctx);
/* Handle any remaining bytes of data. */
/* Process whole buffer but last len % 64 bytes. */
md5_process_bytes (buffer, len, &ctx);
memcpy(ctx->in, buf, len);
/* Put result in desired memory area. */
return md5_finish_ctx (&ctx, resblock);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void
MD5Final(unsigned char digest[16], struct MD5Context *ctx)
md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if (ctx->buflen != 0)
{
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy (&ctx->buffer[left_over], buffer, add);
ctx->buflen += add;
if (ctx->buflen > 64)
{
md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap. */
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
ctx->buflen);
}
/* Append length in bits and transform */
bytes_encode((unsigned char*)((uint32 *) ctx->in + 14), ctx->bits, 8);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
bytes_encode(digest,ctx->buf,16);
memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
buffer = (const char *) buffer + add;
len -= add;
}
/* The four core functions - F1 is optimized somewhat */
/* Process available complete blocks. */
if (len >= 64)
{
#if !_STRING_ARCH_unaligned
# define alignof(type) offsetof (struct { char c; type x; }, x)
# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0)
if (UNALIGNED_P (buffer))
while (len > 64)
{
md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
buffer = (const char *) buffer + 64;
len -= 64;
}
else
#endif
{
md5_process_block (buffer, len & ~63, ctx);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
}
}
/*#define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* Move remaining bytes in internal buffer. */
if (len > 0)
{
size_t left_over = ctx->buflen;
memcpy (&ctx->buffer[left_over], buffer, len);
left_over += len;
if (left_over >= 64)
{
md5_process_block (ctx->buffer, 64, ctx);
left_over -= 64;
memcpy (ctx->buffer, &ctx->buffer[64], left_over);
}
ctx->buflen = left_over;
}
}
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x );
#if 0
dump(char *label,unsigned char *p, int len)
{
int i;
return;
printf("dump: %s\n", label);
for (i=0; i<len; i++)
printf("%x\n", p[i]);
printf("--\n");
/* These are the four functions used in the four steps of the MD5 algorithm
and defined in the RFC 1321. The first function is a little bit optimized
(as found in Colin Plumbs public domain implementation). */
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
#define FF(b, c, d) (d ^ (b & (c ^ d)))
#define FG(b, c, d) FF (d, b, c)
#define FH(b, c, d) (b ^ c ^ d)
#define FI(b, c, d) (c ^ (b | ~d))
}
#endif
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0. */
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void
MD5Transform(uint32 buf[4], uint32 const cin[16])
md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
{
register uint32 a, b, c, d;
uint32 in[16];
bytes_decode(in, (unsigned char *) cin, 64);
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
md5_uint32 correct_words[16];
const md5_uint32 *words = buffer;
size_t nwords = len / sizeof (md5_uint32);
const md5_uint32 *endp = words + nwords;
md5_uint32 A = ctx->A;
md5_uint32 B = ctx->B;
md5_uint32 C = ctx->C;
md5_uint32 D = ctx->D;
/* First increment the byte count. RFC 1321 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] += len;
if (ctx->total[0] < len)
++ctx->total[1];
/* Process all bytes in the buffer with 64 bytes in each round of
the loop. */
while (words < endp)
{
md5_uint32 *cwp = correct_words;
md5_uint32 A_save = A;
md5_uint32 B_save = B;
md5_uint32 C_save = C;
md5_uint32 D_save = D;
/* First round: using the given function, the context and a constant
the next context is computed. Because the algorithms processing
unit is a 32-bit word and it is determined to work on words in
little endian byte order we perhaps have to change the byte order
before the computation. To reduce the work for the next steps
we store the swapped words in the array CORRECT_WORDS. */
#define OP(a, b, c, d, s, T) \
do \
{ \
a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
++words; \
a = rol (a, s); \
a += b; \
} \
while (0)
/* Before we start, one word to the strange constants.
They are defined in RFC 1321 as
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or
perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}'
*/
#endif
#endif /* MD5_CRYPT */
/* Round 1. */
OP (A, B, C, D, 7, 0xd76aa478);
OP (D, A, B, C, 12, 0xe8c7b756);
OP (C, D, A, B, 17, 0x242070db);
OP (B, C, D, A, 22, 0xc1bdceee);
OP (A, B, C, D, 7, 0xf57c0faf);
OP (D, A, B, C, 12, 0x4787c62a);
OP (C, D, A, B, 17, 0xa8304613);
OP (B, C, D, A, 22, 0xfd469501);
OP (A, B, C, D, 7, 0x698098d8);
OP (D, A, B, C, 12, 0x8b44f7af);
OP (C, D, A, B, 17, 0xffff5bb1);
OP (B, C, D, A, 22, 0x895cd7be);
OP (A, B, C, D, 7, 0x6b901122);
OP (D, A, B, C, 12, 0xfd987193);
OP (C, D, A, B, 17, 0xa679438e);
OP (B, C, D, A, 22, 0x49b40821);
/* For the second to fourth round we have the possibly swapped words
in CORRECT_WORDS. Redefine the macro to take an additional first
argument specifying the function to use. */
#undef OP
#define OP(f, a, b, c, d, k, s, T) \
do \
{ \
a += f (b, c, d) + correct_words[k] + T; \
a = rol (a, s); \
a += b; \
} \
while (0)
/* Round 2. */
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
OP (FG, D, A, B, C, 10, 9, 0x02441453);
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
/* Round 3. */
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
/* Round 4. */
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
/* Add the starting values of the context. */
A += A_save;
B += B_save;
C += C_save;
D += D_save;
}
/* Put checksum in context given as argument. */
ctx->A = A;
ctx->B = B;
ctx->C = C;
ctx->D = D;
}
......
#ifndef MD5_H
#define MD5_H
/* md5.h - Declaration of functions and data types used for MD5 sum
computing library functions.
#ifdef __alpha
typedef unsigned int uint32;
#else
typedef unsigned long uint32;
Copyright (C) 1995, 1996, 1999, 2000, 2003, 2004 Free Software
Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _MD5_H
#define _MD5_H 1
#include <stdio.h>
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#if HAVE_STDINT_H || _LIBC
# include <stdint.h>
#endif
struct MD5Context {
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
typedef uint32_t md5_uint32;
/* Structure to save state of computation between the single steps. */
struct md5_ctx
{
md5_uint32 A;
md5_uint32 B;
md5_uint32 C;
md5_uint32 D;
md5_uint32 total[2];
md5_uint32 buflen;
char buffer[128];
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf,
unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context);
void MD5Transform(uint32 buf[4], uint32 const in[16]);
/*
* The following three functions are build up the low level used in
* the functions `md5_stream' and `md5_buffer'.
*/
/* Initialize structure containing state of computation.
(RFC 1321, 3.3: Step 3) */
extern void md5_init_ctx (struct md5_ctx *ctx);
typedef struct MD5Context MD5_CTX;
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is necessary that LEN is a multiple of 64!!! */
extern void md5_process_block (const void *buffer, size_t len,
struct md5_ctx *ctx);
#endif /* !MD5_H */
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is NOT required that LEN is a multiple of 64. */
extern void md5_process_bytes (const void *buffer, size_t len,
struct md5_ctx *ctx);
/* Process the remaining bytes in the buffer and put result from CTX
in first 16 bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest.
IMPORTANT: On some systems it is required that RESBUF be correctly
aligned for a 32 bits value. */
extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf);
/* Put result from CTX in first 16 bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest.
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf);
/* Compute MD5 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 16 bytes
beginning at RESBLOCK. */
extern int md5_stream (FILE *stream, void *resblock);
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
extern void *md5_buffer (const char *buffer, size_t len, void *resblock);
#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
#endif
......
This diff could not be displayed because it is too large.
/* Copyright (C) 1991,93,94,95,96,97,99,2000, 2001 Free Software Foundation, Inc.
Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
with help from Dan Sahlin (dan@sics.se) and
bug fix and commentary by Jim Blandy (jimb@ai.mit.edu);
adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
and implemented by Roland McGrath (roland@ai.mit.edu).
/* Searching in a string.
Copyright (C) 2003 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <string.h>
#include <stdlib.h>
/* Specification. */
#include "strchrnul.h"
/* Find the first occurrence of C in S or the final NUL byte. */
char *
strchrnul (s, c_in)
const char *s;
int c_in;
strchrnul (const char *s, int c_in)
{
const char *char_ptr;
const unsigned long int *longword_ptr;
unsigned long int longword, magic_bits, charmask;
unsigned char c;
char c = c_in;
while (*s && (*s != c))
s++;
c = (unsigned char) c_in;
/* Handle the first few characters by reading one character at a time.
Do this until CHAR_PTR is aligned on a longword boundary. */
for (char_ptr = s; ((unsigned long int) char_ptr
& (sizeof (longword) - 1)) != 0;
++char_ptr)
if (*char_ptr == c || *char_ptr == '\0')
return (void *) char_ptr;
/* All these elucidatory comments refer to 4-byte longwords,
but the theory applies equally well to 8-byte longwords. */
longword_ptr = (unsigned long int *) char_ptr;
/* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
the "holes." Note that there is a hole just to the left of
each byte, with an extra at the end:
bits: 01111110 11111110 11111110 11111111
bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
The 1-bits make sure that carries propagate to the next 0-bit.
The 0-bits provide holes for carries to fall into. */
switch (sizeof (longword))
{
case 4: magic_bits = 0x7efefeffL; break;
case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;
default:
abort ();
}
/* Set up a longword, each of whose bytes is C. */
charmask = c | (c << 8);
charmask |= charmask << 16;
if (sizeof (longword) > 4)
/* Do the shift in two steps to avoid a warning if long has 32 bits. */
charmask |= (charmask << 16) << 16;
if (sizeof (longword) > 8)
abort ();
/* Instead of the traditional loop which tests each character,
we will test a longword at a time. The tricky part is testing
if *any of the four* bytes in the longword in question are zero. */
for (;;)
{
/* We tentatively exit the loop if adding MAGIC_BITS to
LONGWORD fails to change any of the hole bits of LONGWORD.
1) Is this safe? Will it catch all the zero bytes?
Suppose there is a byte with all zeros. Any carry bits
propagating from its left will fall into the hole at its
least significant bit and stop. Since there will be no
carry from its most significant bit, the LSB of the
byte to the left will be unchanged, and the zero will be
detected.
2) Is this worthwhile? Will it ignore everything except
zero bytes? Suppose every byte of LONGWORD has a bit set
somewhere. There will be a carry into bit 8. If bit 8
is set, this will carry into bit 16. If bit 8 is clear,
one of bits 9-15 must be set, so there will be a carry
into bit 16. Similarly, there will be a carry into bit
24. If one of bits 24-30 is set, there will be a carry
into bit 31, so all of the hole bits will be changed.
The one misfire occurs when bits 24-30 are clear and bit
31 is set; in this case, the hole at bit 31 is not
changed. If we had access to the processor carry flag,
we could close this loophole by putting the fourth hole
at bit 32!
So it ignores everything except 128's, when they're aligned
properly.
3) But wait! Aren't we looking for C as well as zero?
Good point. So what we do is XOR LONGWORD with a longword,
each of whose bytes is C. This turns each byte that is C
into a zero. */
longword = *longword_ptr++;
/* Add MAGIC_BITS to LONGWORD. */
if ((((longword + magic_bits)
/* Set those bits that were unchanged by the addition. */
^ ~longword)
/* Look at only the hole bits. If any of the hole bits
are unchanged, most likely one of the bytes was a
zero. */
& ~magic_bits) != 0 ||
/* That caught zeroes. Now test for C. */
((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))
& ~magic_bits) != 0)
{
/* Which of the bytes was C or zero?
If none of them were, it was a misfire; continue the search. */
const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
if (*cp == c || *cp == '\0')
return (char *) cp;
if (*++cp == c || *cp == '\0')
return (char *) cp;
if (*++cp == c || *cp == '\0')
return (char *) cp;
if (*++cp == c || *cp == '\0')
return (char *) cp;
if (sizeof (longword) > 4)
{
if (*++cp == c || *cp == '\0')
return (char *) cp;
if (*++cp == c || *cp == '\0')
return (char *) cp;
if (*++cp == c || *cp == '\0')
return (char *) cp;
if (*++cp == c || *cp == '\0')
return (char *) cp;
}
}
}
/* This should never happen. */
return NULL;
return (char *) s;
}
......
/* Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
/* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
The GNU C Library is distributed in the hope that it will be useful,
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License
along with this program; 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 <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#ifndef HAVE_DECL_STRNLEN
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRNLEN
size_t strnlen ();
#endif
#undef __strndup
#undef strndup
#if defined _LIBC || defined STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#else
char *malloc ();
#ifndef weak_alias
# define __strndup strndup
#endif
char *
strndup (s, n)
const char *s;
size_t n;
__strndup (const char *s, size_t n)
{
size_t len = strnlen (s, n);
char *nouveau = malloc (len + 1);
char *new = malloc (len + 1);
if (nouveau == NULL)
if (new == NULL)
return NULL;
nouveau[len] = '\0';
return (char *) memcpy (nouveau, s, len);
new[len] = '\0';
return memcpy (new, s, len);
}
#ifdef weak_alias
weak_alias (__strndup, strndup)
#endif
......
/* Find the length of STRING, but scan at most MAXLEN characters.
Copyright (C) 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998, 2000-2003 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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#undef strnlen
#include <string.h>
#undef __strnlen
#undef strnlen
#ifndef _LIBC
# define strnlen rpl_strnlen
#endif
#ifndef weak_alias
# define __strnlen strnlen
#endif
/* Find the length of STRING, but scan at most MAXLEN characters.
If no '\0' terminator is found in that many characters, return MAXLEN. */
size_t
strnlen (const char *string, size_t maxlen)
__strnlen (const char *string, size_t maxlen)
{
const char *end = memchr (string, '\0', maxlen);
return end ? (size_t) (end - string) : maxlen;
}
#ifdef weak_alias
weak_alias (__strnlen, strnlen)
#endif
......
/* Reentrant string tokenizer. Generic version.
Copyright (C) 1991, 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
Copyright (C) 1991,1996-1999,2001,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 Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License along
with this program; 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 <string.h>
#undef strtok_r
#undef __strtok_r
#ifndef _LIBC
/* Get specification. */
# include "strtok_r.h"
# define __strtok_r strtok_r
# define __rawmemchr strchr
#endif
/* Parse S into tokens separated by characters in DELIM.
If S is NULL, the saved pointer in SAVE_PTR is used as
the next starting point. For example:
......@@ -30,10 +43,7 @@
// s = "abc\0-def\0"
*/
char *
strtok_r (s, delim, save_ptr)
char *s;
const char *delim;
char **save_ptr;
__strtok_r (char *s, const char *delim, char **save_ptr)
{
char *token;
......@@ -53,8 +63,7 @@ strtok_r (s, delim, save_ptr)
s = strpbrk (token, delim);
if (s == NULL)
/* This token finishes the string. */
/* *save_ptr = __rawmemchr (token, '\0'); */
*save_ptr = token + strlen (token);
*save_ptr = __rawmemchr (token, '\0');
else
{
/* Terminate the token and make *SAVE_PTR point past it. */
......@@ -63,4 +72,7 @@ strtok_r (s, delim, save_ptr)
}
return token;
}
/* weak_alias (__strtok_r, strtok_r) */
#ifdef weak_alias
libc_hidden_def (__strtok_r)
weak_alias (__strtok_r, strtok_r)
#endif
......