diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-10-11 14:49:26 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-10-11 15:19:40 -0700 |
commit | 011c1d1c0766c65517ebd495465c99e86edb63ec (patch) | |
tree | 30d8f6a13235af90897c3223554871ef52225462 /lib/sh/snprintf.c | |
parent | 40cfaccf7b178b6239b5cd0013ef80b7ff8e503e (diff) | |
download | vyatta-bash-011c1d1c0766c65517ebd495465c99e86edb63ec.tar.gz vyatta-bash-011c1d1c0766c65517ebd495465c99e86edb63ec.zip |
Update to bash-4.1
Diffstat (limited to 'lib/sh/snprintf.c')
-rw-r--r-- | lib/sh/snprintf.c | 101 |
1 files changed, 69 insertions, 32 deletions
diff --git a/lib/sh/snprintf.c b/lib/sh/snprintf.c index 4a96474..d681b16 100644 --- a/lib/sh/snprintf.c +++ b/lib/sh/snprintf.c @@ -1,3 +1,5 @@ +/* snprintf - formatted output to strings, with bounds checking and allocation */ + /* build a test version with gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o @@ -7,21 +9,22 @@ Unix snprintf implementation. derived from inetutils/libinetutils/snprintf.c Version 1.1 - Copyright (C) 2001 Free Software Foundation, Inc. + Copyright (C) 2001,2006 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General License as published by - the Free Software Foundation; either version 2 of the License, or + Bash 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 3 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, + + Bash 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 License for more details. - - You should have received a copy of the GNU General License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see <http://www.gnu.org/licenses/>. Revision History: @@ -58,6 +61,15 @@ # include <config.h> #endif +/* GCC 4.2 on Snow Leopard doesn't like the snprintf prototype */ +#if defined(DEBUG) && !defined (MACOSX) +# undef HAVE_SNPRINTF +# undef HAVE_ASPRINTF + +# define HAVE_SNPRINTF 0 +# define HAVE_ASPRINTF 0 +#endif + #if defined(DRIVER) && !defined(HAVE_CONFIG_H) #define HAVE_LONG_LONG #define HAVE_LONG_DOUBLE @@ -74,7 +86,7 @@ #define intmax_t long #endif -#if !defined (HAVE_SNPRINTF) || !defined (HAVE_ASPRINTF) +#if !HAVE_SNPRINTF || !HAVE_ASPRINTF #include <bashtypes.h> @@ -291,6 +303,13 @@ static void dfallback __P((struct DATA *, const char *, const char *, double)); static char *groupnum __P((char *)); +#ifndef HAVE_ISINF_IN_LIBC +static int isinf __P((double)); +#endif +#ifndef HAVE_ISNAN_IN_LIBC +static int isnan __P((double)); +#endif + #ifdef DRIVER static void memory_error_and_abort (); static void *xmalloc __P((size_t)); @@ -401,7 +420,7 @@ static void xfree __P((void *)); } \ } while (0) -#if defined (HAVE_LOCALE_H) +#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV) # define GETLOCALEDATA(d, t, g) \ do \ { \ @@ -471,6 +490,8 @@ pow_10(n) 10^x ~= r * log_10(200) = 2; * log_10(250) = 2; + * + * NOTE: do not call this with r == 0 -- an infinite loop results. */ static int log_10(r) @@ -576,8 +597,11 @@ numtoa(number, base, precision, fract) { integral_part[0] = '0'; integral_part[1] = '\0'; - fraction_part[0] = '0'; - fraction_part[1] = '\0'; + /* The fractional part has to take the precision into account */ + for (ch = 0; ch < precision-1; ch++) + fraction_part[ch] = '0'; + fraction_part[ch] = '0'; + fraction_part[ch+1] = '\0'; if (fract) *fract = fraction_part; return integral_part; @@ -663,7 +687,8 @@ number(p, d, base) p->flags &= ~PF_ZEROPAD; sd = d; /* signed for ' ' padding in base 10 */ - flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; + flags = 0; + flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; if (*p->pf == 'X') flags |= FL_HEXUPPER; @@ -733,7 +758,7 @@ lnumber(p, d, base) p->flags &= ~PF_ZEROPAD; sd = d; /* signed for ' ' padding in base 10 */ - flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; + flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; if (*p->pf == 'X') flags |= FL_HEXUPPER; @@ -805,6 +830,7 @@ pointer(p, d) PUT_CHAR(*tmp, p); tmp++; } + PAD_LEFT(p); } @@ -972,11 +998,21 @@ floating(p, d) if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp))) tmp = t; + 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'; + if (tmp2[0] == '\0') + p->precision = 0; + } + /* calculate the padding. 1 for the dot */ p->width = p->width - ((d > 0. && p->justify == RIGHT) ? 1:0) - ((p->flags & PF_SPACE) ? 1:0) - - strlen(tmp) - p->precision - 1; + strlen(tmp) - p->precision - + ((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */ PAD_RIGHT(p); PUT_PLUS(d, p, 0.); PUT_SPACE(d, p, 0.); @@ -991,11 +1027,6 @@ floating(p, d) if (p->precision != 0 || (p->flags & PF_ALTFORM)) 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'; - for (; *tmp2; tmp2++) PUT_CHAR(*tmp2, p); /* the fraction */ @@ -1011,14 +1042,19 @@ exponent(p, d) char *tmp, *tmp2; int j, i; - if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)) + if (d != 0 && (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); + if (d == 0.) + j = 0; + else + { + 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', @@ -1076,6 +1112,7 @@ exponent(p, d) PUT_CHAR(*tmp, p); tmp++; } + PAD_LEFT(p); } #endif @@ -1358,7 +1395,7 @@ conv_break: STAR_ARGS(data); DEF_PREC(data); d = GETDOUBLE(data); - i = log_10(d); + i = (d != 0.) ? log_10(d) : -1; /* * for '%g|%G' ANSI: use f if exponent * is in the range or [-4,p] exclusively @@ -1614,7 +1651,7 @@ dfallback (data, fs, fe, d) } #endif /* FLOATING_POINT */ -#ifndef HAVE_SNPRINTF +#if !HAVE_SNPRINTF int #if defined (__STDC__) @@ -1664,7 +1701,7 @@ snprintf(string, length, format, va_alist) #endif /* HAVE_SNPRINTF */ -#ifndef HAVE_ASPRINTF +#if !HAVE_ASPRINTF int #if defined (__STDC__) @@ -1709,9 +1746,9 @@ asprintf(stringp, format, va_alist) return rval; } -#endif +#endif /* !HAVE_ASPRINTF */ -#endif +#endif /* !HAVE_SNPRINTF || !HAVE_ASPRINTF */ #ifdef DRIVER |