mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-08-05 17:52:30 +02:00
Imported from ../bash-2.05b.tar.gz.
This commit is contained in:
+494
-99
@@ -47,9 +47,7 @@
|
||||
* Currently doesn't handle (and bash/readline doesn't use):
|
||||
* *M$ width, precision specifications
|
||||
* %N$ numbered argument conversions
|
||||
* inf, nan floating values (could use isinf(), isnan())
|
||||
* `,', `'' flags
|
||||
* `C', `S' conversions
|
||||
* inf, nan floating values imperfect (if isinf(), isnan() not in libc)
|
||||
* support for `F' is imperfect, since underlying printf may not handle it
|
||||
*/
|
||||
|
||||
@@ -65,10 +63,12 @@
|
||||
#ifdef __linux__
|
||||
#define HAVE_PRINTF_A_FORMAT
|
||||
#endif
|
||||
#define HAVE_ISINF_IN_LIBC
|
||||
#define PREFER_STDARG
|
||||
#define HAVE_STRINGIZE
|
||||
#define HAVE_LIMITS_H
|
||||
#define HAVE_STDDEF_H
|
||||
#define HAVE_LOCALE_H
|
||||
#define intmax_t long
|
||||
#endif
|
||||
|
||||
@@ -96,12 +96,18 @@
|
||||
#endif
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
# include <float.h> /* for manifest constants */
|
||||
# include <stdio.h> /* for sprintf */
|
||||
#endif
|
||||
|
||||
#include <typemax.h>
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#include "stdc.h"
|
||||
#include <shmbutil.h>
|
||||
|
||||
#ifndef DRIVER
|
||||
# include "shell.h"
|
||||
@@ -114,6 +120,10 @@ extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
|
||||
extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
|
||||
#endif
|
||||
|
||||
#ifndef FREE
|
||||
# define FREE(x) if (x) free (x)
|
||||
#endif
|
||||
|
||||
/* Bound on length of the string representing an integer value of type T.
|
||||
Subtract one for the sign bit if T is signed;
|
||||
302 / 1000 is log10 (2) rounded up;
|
||||
@@ -130,7 +140,7 @@ extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
|
||||
#define PF_ZEROPAD 0x00008 /* 0 */
|
||||
#define PF_PLUS 0x00010 /* + */
|
||||
#define PF_SPACE 0x00020 /* ' ' */
|
||||
#define PF_COMMA 0x00040 /* , */
|
||||
#define PF_THOUSANDS 0x00040 /* ' */
|
||||
|
||||
#define PF_DOT 0x00080 /* `.precision' */
|
||||
#define PF_STAR_P 0x00100 /* `*' after precision */
|
||||
@@ -158,6 +168,10 @@ extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
|
||||
|
||||
static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
|
||||
|
||||
static int decpoint;
|
||||
static int thoussep;
|
||||
static char *grouping;
|
||||
|
||||
/*
|
||||
* For the FLOATING POINT FORMAT :
|
||||
* the challenge was finding a way to
|
||||
@@ -196,25 +210,27 @@ static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
|
||||
|
||||
#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
|
||||
|
||||
#define GETARG(type) (va_arg(args, type))
|
||||
|
||||
/* Macros that do proper sign extension and handle length modifiers. Used
|
||||
for the integer conversion specifiers. */
|
||||
#define GETSIGNED(p) \
|
||||
(((p)->flags & PF_LONGINT) \
|
||||
? va_arg(args, long) \
|
||||
: (((p)->flags & PF_SHORTINT) ? (long)(short)va_arg(args, int) \
|
||||
: (long)va_arg(args, int)))
|
||||
? GETARG (long) \
|
||||
: (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \
|
||||
: (long)GETARG (int)))
|
||||
|
||||
#define GETUNSIGNED(p) \
|
||||
(((p)->flags & PF_LONGINT) \
|
||||
? va_arg(args, unsigned long) \
|
||||
: (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)va_arg(args, int) \
|
||||
: (unsigned long)va_arg(args, unsigned int)))
|
||||
? GETARG (unsigned long) \
|
||||
: (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \
|
||||
: (unsigned long)GETARG (unsigned int)))
|
||||
|
||||
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
#define GETLDOUBLE(p) va_arg(args, long double)
|
||||
#define GETLDOUBLE(p) GETARG (long double)
|
||||
#endif
|
||||
#define GETDOUBLE(p) va_arg(args, double)
|
||||
#define GETDOUBLE(p) GETARG (double)
|
||||
|
||||
#define SET_SIZE_FLAGS(p, type) \
|
||||
if (sizeof (type) > sizeof (int)) \
|
||||
@@ -271,6 +287,8 @@ static void ldfallback __P((struct DATA *, const char *, const char *, long doub
|
||||
static void dfallback __P((struct DATA *, const char *, const char *, double));
|
||||
#endif
|
||||
|
||||
static char *groupnum __P((char *));
|
||||
|
||||
#ifdef DRIVER
|
||||
static void memory_error_and_abort ();
|
||||
static void *xmalloc __P((size_t));
|
||||
@@ -317,6 +335,20 @@ static void xfree __P((void *));
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Output a string. P->WIDTH has already been adjusted for padding. */
|
||||
#define PUT_STRING(string, len, p) \
|
||||
do \
|
||||
{ \
|
||||
PAD_RIGHT (p); \
|
||||
while ((len)-- > 0) \
|
||||
{ \
|
||||
PUT_CHAR (*(string), (p)); \
|
||||
(string)++; \
|
||||
} \
|
||||
PAD_LEFT (p); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define PUT_PLUS(d, p, zero) \
|
||||
if ((d) > zero && (p)->justify == RIGHT) \
|
||||
PUT_CHAR('+', p)
|
||||
@@ -340,9 +372,34 @@ static void xfree __P((void *));
|
||||
/* if width and prec. in the args */
|
||||
#define STAR_ARGS(p) \
|
||||
if ((p)->flags & PF_STAR_W) \
|
||||
(p)->width = va_arg(args, int); \
|
||||
(p)->width = GETARG (int); \
|
||||
if ((p)->flags & PF_STAR_P) \
|
||||
(p)->precision = va_arg(args, int)
|
||||
(p)->precision = GETARG (int)
|
||||
|
||||
#if defined (HAVE_LOCALE_H)
|
||||
# define GETLOCALEDATA(d, t, g) \
|
||||
do \
|
||||
{ \
|
||||
struct lconv *lv; \
|
||||
if ((d) == 0) { \
|
||||
(d) = '.'; (t) = -1; (g) = 0; /* defaults */ \
|
||||
lv = localeconv(); \
|
||||
if (lv) \
|
||||
{ \
|
||||
if (lv->decimal_point && lv->decimal_point[0]) \
|
||||
(d) = lv->decimal_point[0]; \
|
||||
if (lv->thousands_sep && lv->thousands_sep[0]) \
|
||||
(t) = lv->thousands_sep[0]; \
|
||||
(g) = lv->grouping ? lv->grouping : ""; \
|
||||
if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (0);
|
||||
#else
|
||||
# define GETLOCALEDATA(d, t, g) \
|
||||
( (d) = '.', (t) = ',', g = "\003" )
|
||||
#endif
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
/*
|
||||
@@ -496,6 +553,8 @@ numtoa(number, base, precision, fract)
|
||||
integral_part[1] = '\0';
|
||||
fraction_part[0] = '0';
|
||||
fraction_part[1] = '\0';
|
||||
if (fract)
|
||||
*fract = fraction_part;
|
||||
return integral_part;
|
||||
}
|
||||
|
||||
@@ -570,7 +629,7 @@ number(p, d, base)
|
||||
unsigned long d;
|
||||
int base;
|
||||
{
|
||||
char *tmp;
|
||||
char *tmp, *t;
|
||||
long sd;
|
||||
int flags;
|
||||
|
||||
@@ -580,6 +639,14 @@ number(p, d, base)
|
||||
flags |= FL_HEXUPPER;
|
||||
|
||||
tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
|
||||
t = 0;
|
||||
if ((p->flags & PF_THOUSANDS))
|
||||
{
|
||||
GETLOCALEDATA(decpoint, thoussep, grouping);
|
||||
if (grouping && (t = groupnum (tmp)))
|
||||
tmp = t;
|
||||
}
|
||||
|
||||
p->width -= strlen(tmp);
|
||||
PAD_RIGHT(p);
|
||||
|
||||
@@ -609,6 +676,7 @@ number(p, d, base)
|
||||
}
|
||||
|
||||
PAD_LEFT(p);
|
||||
FREE (t);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
@@ -621,7 +689,7 @@ lnumber(p, d, base)
|
||||
unsigned long long d;
|
||||
int base;
|
||||
{
|
||||
char *tmp;
|
||||
char *tmp, *t;
|
||||
long long sd;
|
||||
int flags;
|
||||
|
||||
@@ -631,6 +699,14 @@ lnumber(p, d, base)
|
||||
flags |= FL_HEXUPPER;
|
||||
|
||||
tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
|
||||
t = 0;
|
||||
if ((p->flags & PF_THOUSANDS))
|
||||
{
|
||||
GETLOCALEDATA(decpoint, thoussep, grouping);
|
||||
if (grouping && (t = groupnum (tmp)))
|
||||
tmp = t;
|
||||
}
|
||||
|
||||
p->width -= strlen(tmp);
|
||||
PAD_RIGHT(p);
|
||||
|
||||
@@ -660,6 +736,7 @@ lnumber(p, d, base)
|
||||
}
|
||||
|
||||
PAD_LEFT(p);
|
||||
FREE (t);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -692,34 +769,162 @@ strings(p, tmp)
|
||||
struct DATA *p;
|
||||
char *tmp;
|
||||
{
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
i = strlen(tmp);
|
||||
len = 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);
|
||||
len = (len < p->precision ? len : p->precision);
|
||||
p->width -= len;
|
||||
|
||||
PUT_STRING (tmp, len, p);
|
||||
}
|
||||
|
||||
#if HANDLE_MULTIBYTE
|
||||
/* %ls wide-character strings */
|
||||
static void
|
||||
wstrings(p, tmp)
|
||||
struct DATA *p;
|
||||
wchar_t *tmp;
|
||||
{
|
||||
size_t len;
|
||||
mbstate_t mbs;
|
||||
char *os;
|
||||
const wchar_t *ws;
|
||||
|
||||
memset (&mbs, '\0', sizeof (mbstate_t));
|
||||
ws = (const wchar_t *)tmp;
|
||||
|
||||
os = (char *)NULL;
|
||||
if (p->precision != NOT_FOUND)
|
||||
{
|
||||
os = (char *)xmalloc (p->precision + 1);
|
||||
len = wcsrtombs (os, &ws, p->precision, &mbs);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = wcsrtombs (NULL, &ws, 0, &mbs);
|
||||
if (len != (size_t)-1)
|
||||
{
|
||||
memset (&mbs, '\0', sizeof (mbstate_t));
|
||||
os = (char *)xmalloc (len + 1);
|
||||
(void)wcsrtombs (os, &ws, len + 1, &mbs);
|
||||
}
|
||||
}
|
||||
if (len == (size_t)-1)
|
||||
{
|
||||
/* invalid multibyte sequence; bail now. */
|
||||
FREE (os);
|
||||
return;
|
||||
}
|
||||
|
||||
p->width -= len;
|
||||
PUT_STRING (os, len, p);
|
||||
free (os);
|
||||
}
|
||||
|
||||
static void
|
||||
wchars (p, wc)
|
||||
struct DATA *p;
|
||||
wint_t wc;
|
||||
{
|
||||
char *lbuf, *l;
|
||||
mbstate_t mbs;
|
||||
size_t len;
|
||||
|
||||
lbuf = (char *)malloc (MB_CUR_MAX+1);
|
||||
if (lbuf == 0)
|
||||
return;
|
||||
memset (&mbs, '\0', sizeof (mbstate_t));
|
||||
len = wcrtomb (lbuf, wc, &mbs);
|
||||
if (len == (size_t)-1)
|
||||
/* conversion failed; bail now. */
|
||||
return;
|
||||
p->width -= len;
|
||||
l = lbuf;
|
||||
PUT_STRING (l, len, p);
|
||||
free (lbuf);
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
|
||||
#ifndef HAVE_ISINF_IN_LIBC
|
||||
/* Half-assed versions, since we don't want to link with libm. */
|
||||
static int
|
||||
isinf(d)
|
||||
double d;
|
||||
{
|
||||
#ifdef DBL_MAX
|
||||
if (d < DBL_MIN)
|
||||
return -1;
|
||||
else if (d > DBL_MAX)
|
||||
return 1;
|
||||
else
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
isnan(d)
|
||||
double d;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
|
||||
(mode == 2) we check for NaN. This does the necessary printing. Returns
|
||||
1 if Inf or Nan, 0 if not. */
|
||||
static int
|
||||
chkinfnan(p, d, mode)
|
||||
struct DATA *p;
|
||||
double d;
|
||||
int mode; /* == 1 for inf, == 2 for nan */
|
||||
{
|
||||
int i;
|
||||
char *tmp;
|
||||
char *big, *small;
|
||||
|
||||
i = (mode == 1) ? isinf(d) : isnan(d);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
big = (mode == 1) ? "INF" : "NAN";
|
||||
small = (mode == 1) ? "inf" : "nan";
|
||||
|
||||
tmp = (*p->pf == 'F' || *p->pf == 'G' || *p->pf == 'E') ? big : small;
|
||||
|
||||
if (i < 0)
|
||||
PUT_CHAR('-', p);
|
||||
|
||||
while (*tmp)
|
||||
{
|
||||
PUT_CHAR (*tmp, p);
|
||||
tmp++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* %f %F %g %G floating point representation */
|
||||
static void
|
||||
floating(p, d)
|
||||
struct DATA *p;
|
||||
double d;
|
||||
{
|
||||
char *tmp, *tmp2;
|
||||
char *tmp, *tmp2, *t;
|
||||
int i;
|
||||
|
||||
if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
|
||||
return; /* already printed nan or inf */
|
||||
|
||||
GETLOCALEDATA(decpoint, thoussep, grouping);
|
||||
DEF_PREC(p);
|
||||
d = ROUND(d, p);
|
||||
tmp = dtoa(d, p->precision, &tmp2);
|
||||
t = 0;
|
||||
if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
|
||||
tmp = t;
|
||||
|
||||
/* calculate the padding. 1 for the dot */
|
||||
p->width = p->width -
|
||||
((d > 0. && p->justify == RIGHT) ? 1:0) -
|
||||
@@ -728,17 +933,22 @@ floating(p, d)
|
||||
PAD_RIGHT(p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
PUT_SPACE(d, p, 0.);
|
||||
|
||||
while (*tmp)
|
||||
{ /* the integral */
|
||||
PUT_CHAR(*tmp, p);
|
||||
tmp++;
|
||||
}
|
||||
FREE (t);
|
||||
|
||||
if (p->precision != 0 || (p->flags & PF_ALTFORM))
|
||||
PUT_CHAR('.', p); /* put the '.' */
|
||||
PUT_CHAR(decpoint, p); /* put the '.' */
|
||||
|
||||
if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
|
||||
/* smash the trailing zeros unless altform */
|
||||
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
|
||||
tmp2[i] = '\0';
|
||||
tmp2[i] = '\0';
|
||||
|
||||
for (; *tmp2; tmp2++)
|
||||
PUT_CHAR(*tmp2, p); /* the fraction */
|
||||
|
||||
@@ -752,69 +962,55 @@ exponent(p, d)
|
||||
double d;
|
||||
{
|
||||
char *tmp, *tmp2;
|
||||
int j, i, nsig, ndig;
|
||||
int j, i;
|
||||
|
||||
if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
|
||||
return; /* already printed nan or inf */
|
||||
|
||||
GETLOCALEDATA(decpoint, thoussep, grouping);
|
||||
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 '+|-', 2 for 'exp' */
|
||||
/* calculate how much padding need */
|
||||
p->width = p->width -
|
||||
((d > 0. && p->justify == RIGHT) ? 1:0) -
|
||||
((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
|
||||
|
||||
PAD_RIGHT(p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
PUT_SPACE(d, p, 0.);
|
||||
/*
|
||||
* When supplied %g or %G, an optional precision is the number of
|
||||
* significant digits to print.
|
||||
*
|
||||
* nsig = number of significant digits we've printed (leading zeros are
|
||||
* never significant)
|
||||
* ndig = if non-zero, max number of significant digits to print (only
|
||||
* applicable to %g/%G)
|
||||
*/
|
||||
nsig = ndig = 0;
|
||||
if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_DOT))
|
||||
ndig = (p->precision == 0) ? 1 : p->precision;
|
||||
|
||||
while (*tmp)
|
||||
{
|
||||
PUT_CHAR(*tmp, p);
|
||||
tmp++;
|
||||
if (ndig && (++nsig >= ndig))
|
||||
break;
|
||||
}
|
||||
|
||||
if ((p->precision != 0 || (p->flags & PF_ALTFORM)) && (ndig == 0 || nsig < ndig))
|
||||
PUT_CHAR('.', p); /* the '.' */
|
||||
if (p->precision != 0 || (p->flags & PF_ALTFORM))
|
||||
PUT_CHAR(decpoint, p); /* the '.' */
|
||||
|
||||
if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
|
||||
/* smash the trailing zeros unless altform */
|
||||
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
|
||||
tmp2[i] = '\0';
|
||||
tmp2[i] = '\0';
|
||||
|
||||
for (; *tmp2; tmp2++)
|
||||
{
|
||||
if (ndig && (nsig++ >= ndig))
|
||||
break;
|
||||
PUT_CHAR(*tmp2, p); /* the fraction */
|
||||
}
|
||||
PUT_CHAR(*tmp2, p); /* the fraction */
|
||||
|
||||
/* the exponent put the 'e|E' */
|
||||
if (*p->pf == 'g' || *p->pf == 'e')
|
||||
{
|
||||
PUT_CHAR('e', p);
|
||||
}
|
||||
PUT_CHAR('e', p);
|
||||
else
|
||||
PUT_CHAR('E', p);
|
||||
PUT_CHAR('E', p);
|
||||
|
||||
/* the sign of the exp */
|
||||
if (j > 0)
|
||||
{
|
||||
PUT_CHAR('+', p);
|
||||
}
|
||||
PUT_CHAR('+', p);
|
||||
else
|
||||
{
|
||||
PUT_CHAR('-', p);
|
||||
@@ -825,9 +1021,7 @@ exponent(p, d)
|
||||
/* pad out to at least two spaces. pad with `0' if the exponent is a
|
||||
single digit. */
|
||||
if (j <= 9)
|
||||
{
|
||||
PUT_CHAR('0', p);
|
||||
}
|
||||
PUT_CHAR('0', p);
|
||||
|
||||
/* the exponent */
|
||||
while (*tmp)
|
||||
@@ -839,6 +1033,69 @@ exponent(p, d)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return a new string with the digits in S grouped according to the locale's
|
||||
grouping info and thousands separator. If no grouping should be performed,
|
||||
this returns NULL; the caller needs to check for it. */
|
||||
static char *
|
||||
groupnum (s)
|
||||
char *s;
|
||||
{
|
||||
char *se, *ret, *re, *g;
|
||||
int len, slen;
|
||||
|
||||
if (grouping == 0 || *grouping <= 0 || *grouping == CHAR_MAX)
|
||||
return ((char *)NULL);
|
||||
|
||||
/* find min grouping to size returned string */
|
||||
for (len = *grouping, g = grouping; *g; g++)
|
||||
if (*g > 0 && *g < len)
|
||||
len = *g;
|
||||
|
||||
slen = strlen (s);
|
||||
len = slen / len + 1;
|
||||
ret = (char *)xmalloc (slen + len + 1);
|
||||
re = ret + slen + len;
|
||||
*re = '\0';
|
||||
|
||||
g = grouping;
|
||||
se = s + slen;
|
||||
len = *g;
|
||||
|
||||
while (se > s)
|
||||
{
|
||||
*--re = *--se;
|
||||
|
||||
/* handle `-' inserted by numtoa() and the fmtu* family here. */
|
||||
if (se > s && se[-1] == '-')
|
||||
continue;
|
||||
|
||||
/* begin new group. */
|
||||
if (--len == 0 && se > s)
|
||||
{
|
||||
*--re = thoussep;
|
||||
len = *++g; /* was g++, but that uses first char twice (glibc bug, too) */
|
||||
if (*g == '\0')
|
||||
len = *--g; /* use previous grouping */
|
||||
else if (*g == CHAR_MAX)
|
||||
{
|
||||
do
|
||||
*--re = *--se;
|
||||
while (se > s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (re > ret)
|
||||
#ifdef HAVE_MEMMOVE
|
||||
memmove (ret, re, strlen (re) + 1);
|
||||
#else
|
||||
strcpy (ret, re);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize the conversion specifiers */
|
||||
static void
|
||||
init_conv_flag (p)
|
||||
@@ -887,18 +1144,26 @@ vsnprintf_internal(data, string, length, format, args)
|
||||
#endif
|
||||
int state, i, c, n;
|
||||
char *s;
|
||||
#if HANDLE_MULTIBYTE
|
||||
wchar_t *ws;
|
||||
wint_t wc;
|
||||
#endif
|
||||
const char *convstart;
|
||||
|
||||
/* Sanity check, the string must be > 1. C99 actually says that LENGTH
|
||||
can be zero here, in the case of snprintf/vsnprintf (it's never 0 in
|
||||
the case of asprintf/vasprintf), and the return value is the number
|
||||
/* Sanity check, the string length must be >= 0. C99 actually says that
|
||||
LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
|
||||
0 in the case of asprintf/vasprintf), and the return value is the number
|
||||
of characters that would have been written. */
|
||||
if (length < 1)
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
if (format == 0)
|
||||
return 0;
|
||||
|
||||
/* Reset these for each call because the locale might have changed. */
|
||||
decpoint = thoussep = 0;
|
||||
grouping = 0;
|
||||
|
||||
for (; c = *(data->pf); data->pf++)
|
||||
{
|
||||
if (c != '%')
|
||||
@@ -966,8 +1231,8 @@ vsnprintf_internal(data, string, length, format, args)
|
||||
data->flags |= PF_PLUS;
|
||||
data->justify = RIGHT;
|
||||
continue;
|
||||
case ',':
|
||||
data->flags |= PF_COMMA; /* not implemented yet */
|
||||
case '\'':
|
||||
data->flags |= PF_THOUSANDS;
|
||||
continue;
|
||||
|
||||
case '1': case '2': case '3':
|
||||
@@ -1043,9 +1308,18 @@ conv_break:
|
||||
* else use %e|%E
|
||||
*/
|
||||
if (-4 < i && i < data->precision)
|
||||
floating(data, d);
|
||||
{
|
||||
/* reset precision */
|
||||
data->precision -= i + 1;
|
||||
floating(data, d);
|
||||
}
|
||||
else
|
||||
exponent(data, d);
|
||||
{
|
||||
/* reduce precision by 1 because of leading digit before
|
||||
decimal point in e format. */
|
||||
data->precision--;
|
||||
exponent(data, d);
|
||||
}
|
||||
state = 0;
|
||||
break;
|
||||
case 'e':
|
||||
@@ -1073,7 +1347,7 @@ conv_break:
|
||||
#ifdef HAVE_LONG_LONG
|
||||
if (data->flags & PF_LONGLONG)
|
||||
{
|
||||
ull = va_arg(args, unsigned long long);
|
||||
ull = GETARG (unsigned long long);
|
||||
lnumber(data, ull, 10);
|
||||
}
|
||||
else
|
||||
@@ -1093,7 +1367,7 @@ conv_break:
|
||||
#ifdef HAVE_LONG_LONG
|
||||
if (data->flags & PF_LONGLONG)
|
||||
{
|
||||
ull = va_arg(args, long long);
|
||||
ull = GETARG (long long);
|
||||
lnumber(data, ull, 10);
|
||||
}
|
||||
else
|
||||
@@ -1109,7 +1383,7 @@ conv_break:
|
||||
#ifdef HAVE_LONG_LONG
|
||||
if (data->flags & PF_LONGLONG)
|
||||
{
|
||||
ull = va_arg(args, unsigned long long);
|
||||
ull = GETARG (unsigned long long);
|
||||
lnumber(data, ull, 8);
|
||||
}
|
||||
else
|
||||
@@ -1126,7 +1400,7 @@ conv_break:
|
||||
#ifdef HAVE_LONG_LONG
|
||||
if (data->flags & PF_LONGLONG)
|
||||
{
|
||||
ull = va_arg(args, unsigned long long);
|
||||
ull = GETARG (unsigned long long);
|
||||
lnumber(data, ull, 16);
|
||||
}
|
||||
else
|
||||
@@ -1139,33 +1413,64 @@ conv_break:
|
||||
break;
|
||||
case 'p':
|
||||
STAR_ARGS(data);
|
||||
ul = (unsigned long)va_arg(args, void *);
|
||||
ul = (unsigned long)GETARG (void *);
|
||||
pointer(data, ul);
|
||||
state = 0;
|
||||
break;
|
||||
#if HANDLE_MULTIBYTE
|
||||
case 'C':
|
||||
data->flags |= PF_LONGINT;
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
case 'c': /* character */
|
||||
ul = va_arg(args, int);
|
||||
PUT_CHAR(ul, data);
|
||||
STAR_ARGS(data);
|
||||
#if HANDLE_MULTIBYTE
|
||||
if (data->flags & PF_LONGINT)
|
||||
{
|
||||
wc = GETARG (wint_t);
|
||||
wchars (data, wc);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ul = GETARG (int);
|
||||
PUT_CHAR(ul, data);
|
||||
}
|
||||
state = 0;
|
||||
break;
|
||||
#if HANDLE_MULTIBYTE
|
||||
case 'S':
|
||||
data->flags |= PF_LONGINT;
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
case 's': /* string */
|
||||
STAR_ARGS(data);
|
||||
s = va_arg(args, char *);
|
||||
strings(data, s);
|
||||
#if HANDLE_MULTIBYTE
|
||||
if (data->flags & PF_LONGINT)
|
||||
{
|
||||
ws = GETARG (wchar_t *);
|
||||
wstrings (data, ws);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
s = GETARG (char *);
|
||||
strings(data, s);
|
||||
}
|
||||
state = 0;
|
||||
break;
|
||||
case 'n':
|
||||
#ifdef HAVE_LONG_LONG
|
||||
if (data->flags & PF_LONGLONG)
|
||||
*(va_arg(args, long long *)) = data->counter;
|
||||
*(GETARG (long long *)) = data->counter;
|
||||
else
|
||||
#endif
|
||||
if (data->flags & PF_LONGINT)
|
||||
*(va_arg(args, long *)) = data->counter;
|
||||
*(GETARG (long *)) = data->counter;
|
||||
else if (data->flags & PF_SHORTINT)
|
||||
*(va_arg(args, short *)) = data->counter;
|
||||
*(GETARG (short *)) = data->counter;
|
||||
else
|
||||
*(va_arg(args, int *)) = data->counter;
|
||||
*(GETARG (int *)) = data->counter;
|
||||
state = 0;
|
||||
break;
|
||||
case '%': /* nothing just % */
|
||||
@@ -1201,7 +1506,7 @@ ldfallback (data, fs, fe, ld)
|
||||
char fmtbuf[FALLBACK_FMTSIZE], *obuf;
|
||||
int fl;
|
||||
|
||||
obuf = xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
|
||||
obuf = (char *)xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
|
||||
fl = fe - fs + 1;
|
||||
strncpy (fmtbuf, fs, fl);
|
||||
fmtbuf[fl] = '\0';
|
||||
@@ -1248,6 +1553,8 @@ vsnprintf(string, length, format, args)
|
||||
{
|
||||
struct DATA data;
|
||||
|
||||
if (string == 0 && length != 0)
|
||||
return 0;
|
||||
init_data (&data, string, length, format, PFM_SN);
|
||||
return (vsnprintf_internal(&data, string, length, format, args));
|
||||
}
|
||||
@@ -1267,12 +1574,10 @@ snprintf(string, length, format, va_alist)
|
||||
int rval;
|
||||
va_list args;
|
||||
|
||||
#if defined(PREFER_STDARG)
|
||||
va_start(args, format);
|
||||
#else
|
||||
va_start(args);
|
||||
#endif
|
||||
SH_VA_START(args, format);
|
||||
|
||||
if (string == 0 && length != 0)
|
||||
return 0;
|
||||
init_data (&data, string, length, format, PFM_SN);
|
||||
rval = vsnprintf_internal (&data, string, length, format, args);
|
||||
|
||||
@@ -1319,11 +1624,7 @@ asprintf(stringp, format, va_alist)
|
||||
int rval;
|
||||
va_list args;
|
||||
|
||||
#if defined(PREFER_STDARG)
|
||||
va_start(args, format);
|
||||
#else
|
||||
va_start(args);
|
||||
#endif
|
||||
SH_VA_START(args, format);
|
||||
|
||||
rval = vasprintf (stringp, format, args);
|
||||
|
||||
@@ -1378,10 +1679,6 @@ xfree(x)
|
||||
free (x);
|
||||
}
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
# include <float.h>
|
||||
#endif
|
||||
|
||||
/* set of small tests for snprintf() */
|
||||
main()
|
||||
{
|
||||
@@ -1389,6 +1686,18 @@ main()
|
||||
char *h;
|
||||
int i, si, ai;
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
si = snprintf((char *)NULL, 0, "abcde\n");
|
||||
printf("snprintf returns %d with NULL first argument and size of 0\n", si);
|
||||
si = snprintf(holder, 0, "abcde\n");
|
||||
printf("snprintf returns %d with non-NULL first argument and size of 0\n", si);
|
||||
si = snprintf((char *)NULL, 16, "abcde\n");
|
||||
printf("snprintf returns %d with NULL first argument and non-zero size\n", si);
|
||||
|
||||
/*
|
||||
printf("Suite of test for snprintf:\n");
|
||||
printf("a_format\n");
|
||||
@@ -1660,6 +1969,92 @@ main()
|
||||
printf ("<%d> <%s>\n", si, holder);
|
||||
printf ("<%d> <%s>\n\n", ai, h);
|
||||
|
||||
/* huh? */
|
||||
printf("/%%g/, 421.2345\n");
|
||||
snprintf(holder, sizeof holder, "/%g/\n", 421.2345);
|
||||
asprintf(&h, "/%g/\n", 421.2345);
|
||||
printf("/%g/\n", 421.2345);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%g/, 4214.2345\n");
|
||||
snprintf(holder, sizeof holder, "/%g/\n", 4214.2345);
|
||||
asprintf(&h, "/%g/\n", 4214.2345);
|
||||
printf("/%g/\n", 4214.2345);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%.5g/, 4214.2345\n");
|
||||
snprintf(holder, sizeof holder, "/%.5g/\n", 4214.2345);
|
||||
asprintf(&h, "/%.5g/\n", 4214.2345);
|
||||
printf("/%.5g/\n", 4214.2345);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%.4g/, 4214.2345\n");
|
||||
snprintf(holder, sizeof holder, "/%.4g/\n", 4214.2345);
|
||||
asprintf(&h, "/%.4g/\n", 4214.2345);
|
||||
printf("/%.4g/\n", 4214.2345);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%'ld %%'ld/, 12345, 1234567\n");
|
||||
snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 12345, 1234567);
|
||||
asprintf(&h, "/%'ld %'ld/\n", 12345, 1234567);
|
||||
printf("/%'ld %'ld/\n", 12345, 1234567);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%'ld %%'ld/, 336, 3336\n");
|
||||
snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 336, 3336);
|
||||
asprintf(&h, "/%'ld %'ld/\n", 336, 3336);
|
||||
printf("/%'ld %'ld/\n", 336, 3336);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%'ld %%'ld/, -42786, -142786\n");
|
||||
snprintf(holder, sizeof holder, "/%'ld %'ld/\n", -42786, -142786);
|
||||
asprintf(&h, "/%'ld %'ld/\n", -42786, -142786);
|
||||
printf("/%'ld %'ld/\n", -42786, -142786);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
|
||||
snprintf(holder, sizeof holder, "/%'f %'f/\n", 421.2345, 421234.56789);
|
||||
asprintf(&h, "/%'f %'f/\n", 421.2345, 421234.56789);
|
||||
printf("/%'f %'f/\n", 421.2345, 421234.56789);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
|
||||
snprintf(holder, sizeof holder, "/%'f %'f/\n", -421.2345, -421234.56789);
|
||||
asprintf(&h, "/%'f %'f/\n", -421.2345, -421234.56789);
|
||||
printf("/%'f %'f/\n", -421.2345, -421234.56789);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
|
||||
snprintf(holder, sizeof holder, "/%'g %'g/\n", 421.2345, 421234.56789);
|
||||
asprintf(&h, "/%'g %'g/\n", 421.2345, 421234.56789);
|
||||
printf("/%'g %'g/\n", 421.2345, 421234.56789);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
|
||||
snprintf(holder, sizeof holder, "/%'g %'g/\n", -421.2345, -421234.56789);
|
||||
asprintf(&h, "/%'g %'g/\n", -421.2345, -421234.56789);
|
||||
printf("/%'g %'g/\n", -421.2345, -421234.56789);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
#endif
|
||||
|
||||
printf("/%%'g/, 4213455.8392\n");
|
||||
snprintf(holder, sizeof holder, "/%'g/\n", 4213455.8392);
|
||||
asprintf(&h, "/%'g/\n", 4213455.8392);
|
||||
printf("/%'g/\n", 4213455.8392);
|
||||
printf("%s", holder);
|
||||
printf("%s\n", h);
|
||||
|
||||
exit (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user