Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
John McEleney
/
mailutils
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit
2db5c711
...
2db5c7115e5b37734993603c0381aab7e62c4be9
authored
2005-02-23 15:09:34 +0000
by
Sergey Poznyakoff
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Updated by gnulib-sync
1 parent
96aac328
Show whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
2563 additions
and
2930 deletions
lib/setenv.c
lib/snprintf.c
lib/snprintf.h
lib/vasprintf.c
lib/xalloc.h
lib/xmalloc.c
lib/xstrtol.c
lib/xstrtol.h
m4/getopt.m4
m4/regex.m4
mailbox/argp-ba.c
mailbox/argp-eexst.c
mailbox/argp-fmtstream.c
mailbox/argp-fmtstream.h
mailbox/argp-fs-xinl.c
mailbox/argp-help.c
mailbox/argp-namefrob.h
mailbox/argp-parse.c
mailbox/argp-pv.c
mailbox/argp-pvh.c
mailbox/argp-xinl.c
mailbox/getline.c
mailbox/getline.h
mailbox/getopt.c
mailbox/getopt1.c
mailbox/md5.c
mailbox/md5.h
mailbox/regex.c
mailbox/strchrnul.c
mailbox/strndup.c
mailbox/strnlen.c
mailbox/strtok_r.c
lib/setenv.c
View file @
2db5c71
/* 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.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
(
nam
e
);
char
**
ep
;
return
__add_to_environ
(
name
,
value
,
NULL
,
replac
e
);
}
/* 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
...
...
lib/snprintf.c
View file @
2db5c71
/*
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
...
...
lib/snprintf.h
View file @
2db5c71
/*
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 */
...
...
lib/vasprintf.c
View file @
2db5c71
/* 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 */
...
...
lib/xalloc.h
View file @
2db5c71
/* 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_ */
...
...
lib/xmalloc.c
View file @
2db5c71
/* 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
x
alloc_die
(
void
)
void
*
x
nmalloc
(
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
);
}
...
...
lib/xstrtol.c
View file @
2db5c71
/* 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
#if
ndef
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
;
...
...
lib/xstrtol.h
View file @
2db5c71
/* 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)
...
...
m4/getopt.m4
View file @
2db5c71
## $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], [:])
...
...
m4/regex.m4
View file @
2db5c71
#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 (®ex, 0, sizeof (regex));
[s = re_compile_pattern ("a[[:@:>@:]]b\n", 9, ®ex);]
/* 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 (®ex, 0, sizeof (regex));
s = re_compile_pattern ("{1", 2, ®ex);
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, ®ex);
memset (®ex, 0, sizeof (regex));
s = re_compile_pattern ("[[an\371]]*n", 7, ®ex);
if (s)
exit (1);
...
...
@@ -51,6 +67,16 @@ AC_DEFUN([jm_INCLUDED_REGEX],
if (re_match (®ex, "an", 2, 0, ®s) != 2)
exit (1);
memset (®ex, 0, sizeof (regex));
s = re_compile_pattern ("x", 1, ®ex);
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 (®ex, "wxy", 3, 2, -2, ®s) != 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)
])
...
...
mailbox/argp-ba.c
View file @
2db5c71
...
...
@@ -3,20 +3,19 @@
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
...
...
mailbox/argp-eexst.c
View file @
2db5c71
/* 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>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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"
...
...
mailbox/argp-fmtstream.c
View file @
2db5c71
/* 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>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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 */
...
...
mailbox/argp-fmtstream.h
View file @
2db5c71
/* 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>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
)
...
...
mailbox/argp-fs-xinl.c
View file @
2db5c71
/* 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>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
...
...
mailbox/argp-help.c
View file @
2db5c71
/* 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>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
in
line
in
t
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
));
mem
cpy
(
short_options
,
hol
->
short_options
,
hol_so_len
);
__memp
cpy
(
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
d
gettext here isn't quite right, since sorting will
have been done on the original; but documentation options
should be pretty rare anyway... */
__argp_fmtstream_puts
(
stream
,
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
);
...
...
mailbox/argp-namefrob.h
View file @
2db5c71
/* Name frobnication for compiling argp outside of glibc
Copyright (C) 1997, 200
1
Free Software Foundation, Inc.
Copyright (C) 1997, 200
3
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
...
...
mailbox/argp-parse.c
View file @
2db5c71
/* 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>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
);
...
...
mailbox/argp-pv.c
View file @
2db5c71
...
...
@@ -3,20 +3,19 @@
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
...
...
mailbox/argp-pvh.c
View file @
2db5c71
/* 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>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
;
...
...
mailbox/argp-xinl.c
View file @
2db5c71
/* Real definitions for extern inline functions in argp.h
Copyright (C) 1997, 1998, 200
1
Free Software Foundation, Inc.
Copyright (C) 1997, 1998, 200
4
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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. */
...
...
mailbox/getline.c
View file @
2db5c71
/* 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.
*/
#if
def
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"
#if
ndef 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
...
...
mailbox/getline.h
View file @
2db5c71
/* 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_ */
...
...
mailbox/getopt.c
View file @
2db5c71
/* 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. */
#if
def _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
;
#if
def _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. */
#if
def _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
;
...
...
mailbox/getopt1.c
View file @
2db5c71
/* 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
;
...
...
mailbox/md5.c
View file @
2db5c71
/*
* 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
;
}
...
...
mailbox/md5.h
View file @
2db5c71
#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
...
...
mailbox/regex.c
View file @
2db5c71
This diff could not be displayed because it is too large.
mailbox/strchrnul.c
View file @
2db5c71
/* 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.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
;
}
...
...
mailbox/strndup.c
View file @
2db5c71
/* 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
*
n
ouveau
=
malloc
(
len
+
1
);
char
*
n
ew
=
malloc
(
len
+
1
);
if
(
n
ouveau
==
NULL
)
if
(
n
ew
==
NULL
)
return
NULL
;
n
ouveau
[
len
]
=
'\0'
;
return
(
char
*
)
memcpy
(
nouveau
,
s
,
len
);
n
ew
[
len
]
=
'\0'
;
return
memcpy
(
new
,
s
,
len
);
}
#ifdef weak_alias
weak_alias
(
__strndup
,
strndup
)
#endif
...
...
mailbox/strnlen.c
View file @
2db5c71
/* 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.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
...
...
mailbox/strtok_r.c
View file @
2db5c71
/* 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.
Th
e 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.
Th
is 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.
Th
e GNU C Library
is distributed in the hope that it will be useful,
Th
is 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
...
...
Please
register
or
sign in
to post a comment