diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-03-05 11:23:38 +0000 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-03-05 11:23:38 +0000 |
commit | c1c8d2fe18e19f109db0730c39197931a21d8f1f (patch) | |
tree | f9229e84d865a8bba6fdbf19509ea113f4f85f30 /lgl | |
parent | 9d39932d4ddeab2de8a08c2a22f9e8050bddca5a (diff) | |
download | gnutls-c1c8d2fe18e19f109db0730c39197931a21d8f1f.tar.gz |
Updaet.
Diffstat (limited to 'lgl')
-rw-r--r-- | lgl/m4/gnulib-comp.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/time_r.m4 | 3 | ||||
-rw-r--r-- | lgl/m4/vasnprintf.m4 | 30 | ||||
-rw-r--r-- | lgl/m4/vasprintf.m4 | 24 | ||||
-rw-r--r-- | lgl/time_.h | 2 | ||||
-rw-r--r-- | lgl/vasnprintf.c | 499 | ||||
-rw-r--r-- | lgl/vasnprintf.h | 6 | ||||
-rw-r--r-- | lgl/vasprintf.h | 10 |
8 files changed, 553 insertions, 23 deletions
diff --git a/lgl/m4/gnulib-comp.m4 b/lgl/m4/gnulib-comp.m4 index 362af5989e..5442a06ee5 100644 --- a/lgl/m4/gnulib-comp.m4 +++ b/lgl/m4/gnulib-comp.m4 @@ -69,7 +69,7 @@ AC_DEFUN([lgl_INIT], gl_GC_SHA1 gl_MODULE_INDICATOR([gc-sha1]) dnl you must add AM_GNU_GETTEXT([external]) or similar to configure.ac. - AM_GNU_GETTEXT_VERSION([0.15]) + AM_GNU_GETTEXT_VERSION([0.16.1]) gl_MD2 gl_FUNC_MEMMEM gl_STRING_MODULE_INDICATOR([memmem]) diff --git a/lgl/m4/time_r.m4 b/lgl/m4/time_r.m4 index a4e016f819..dbb6396607 100644 --- a/lgl/m4/time_r.m4 +++ b/lgl/m4/time_r.m4 @@ -9,7 +9,10 @@ dnl Written by Paul Eggert. AC_DEFUN([gl_TIME_R], [ + dnl Persuade glibc and Solaris <time.h> to declare localtime_r. AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS]) AC_REQUIRE([AC_C_RESTRICT]) AC_CACHE_CHECK([whether localtime_r is compatible with its POSIX signature], diff --git a/lgl/m4/vasnprintf.m4 b/lgl/m4/vasnprintf.m4 index 72c9a13e2f..e7b51dc413 100644 --- a/lgl/m4/vasnprintf.m4 +++ b/lgl/m4/vasnprintf.m4 @@ -1,5 +1,5 @@ -# vasnprintf.m4 serial 7 -dnl Copyright (C) 2002-2004, 2006 Free Software Foundation, Inc. +# vasnprintf.m4 serial 8 +dnl Copyright (C) 2002-2004, 2006-2007 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. @@ -7,18 +7,28 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_FUNC_VASNPRINTF], [ AC_REQUIRE([gl_EOVERFLOW]) - AC_REPLACE_FUNCS(vasnprintf) + AC_CHECK_FUNCS([vasnprintf]) if test $ac_cv_func_vasnprintf = no; then - AC_LIBOBJ(printf-args) - AC_LIBOBJ(printf-parse) - AC_LIBOBJ(asnprintf) - gl_PREREQ_PRINTF_ARGS - gl_PREREQ_PRINTF_PARSE - gl_PREREQ_VASNPRINTF - gl_PREREQ_ASNPRINTF + gl_REPLACE_VASNPRINTF fi ]) +AC_DEFUN([gl_REPLACE_VASNPRINTF], +[ + AC_LIBOBJ([vasnprintf]) + AC_LIBOBJ([printf-args]) + AC_LIBOBJ([printf-parse]) + AC_LIBOBJ([asnprintf]) + if test $ac_cv_func_vasnprintf = yes; then + AC_DEFINE([REPLACE_VASNPRINTF], 1, + [Define if vasnprintf exists but is overridden by gnulib.]) + fi + gl_PREREQ_PRINTF_ARGS + gl_PREREQ_PRINTF_PARSE + gl_PREREQ_VASNPRINTF + gl_PREREQ_ASNPRINTF +]) + # Prequisites of lib/printf-args.h, lib/printf-args.c. AC_DEFUN([gl_PREREQ_PRINTF_ARGS], [ diff --git a/lgl/m4/vasprintf.m4 b/lgl/m4/vasprintf.m4 index 18ca6327b5..0f4c12374f 100644 --- a/lgl/m4/vasprintf.m4 +++ b/lgl/m4/vasprintf.m4 @@ -1,20 +1,30 @@ -# vasprintf.m4 serial 2 -dnl Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc. +# vasprintf.m4 serial 3 +dnl Copyright (C) 2002-2003, 2006-2007 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. AC_DEFUN([gl_FUNC_VASPRINTF], [ - AC_REPLACE_FUNCS(vasprintf) + AC_CHECK_FUNCS([vasprintf]) if test $ac_cv_func_vasprintf = no; then - AC_LIBOBJ(asprintf) - gl_PREREQ_VASPRINTF_H - gl_PREREQ_VASPRINTF - gl_PREREQ_ASPRINTF + gl_REPLACE_VASPRINTF fi ]) +AC_DEFUN([gl_REPLACE_VASPRINTF], +[ + AC_LIBOBJ([vasprintf]) + AC_LIBOBJ([asprintf]) + if test $ac_cv_func_vasprintf = yes; then + AC_DEFINE([REPLACE_VASPRINTF], 1, + [Define if vasprintf exists but is overridden by gnulib.]) + fi + gl_PREREQ_VASPRINTF_H + gl_PREREQ_VASPRINTF + gl_PREREQ_ASPRINTF +]) + # Prerequisites of lib/vasprintf.h. AC_DEFUN([gl_PREREQ_VASPRINTF_H], [ diff --git a/lgl/time_.h b/lgl/time_.h index b4709bf85f..7b0c6014cd 100644 --- a/lgl/time_.h +++ b/lgl/time_.h @@ -86,7 +86,7 @@ char *strptime (char const *restrict __buf, char const *restrict __format, time_t timegm (struct tm *__tm); #endif -/* Encourage applications to avoid unsafe functions that can overrrun +/* Encourage applications to avoid unsafe functions that can overrun buffers when given outlandish struct tm values. Portable applications should use strftime (or even sprintf) instead. */ # if GNULIB_PORTCHECK diff --git a/lgl/vasnprintf.c b/lgl/vasnprintf.c index 8e5c8c39f5..15b426b875 100644 --- a/lgl/vasnprintf.c +++ b/lgl/vasnprintf.c @@ -49,6 +49,15 @@ /* Checked size_t computations. */ #include "xsize.h" +#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL +# include "isnan.h" +# include "isnanl.h" +# if HAVE_LONG_DOUBLE +# include "printf-frexp.h" +# include "printf-frexpl.h" +# endif +#endif + #if HAVE_WCHAR_T # if HAVE_WCSLEN # define local_wcslen wcslen @@ -257,6 +266,474 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar abort (); } } +#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL + else if (dp->conversion == 'a' || dp->conversion == 'A') + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; + int has_width; + size_t width; + int has_precision; + size_t precision; + size_t tmp_length; + CHAR_T tmpbuf[700]; + CHAR_T *tmp; + CHAR_T *pad_ptr; + CHAR_T *p; + + has_width = 0; + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = (unsigned int) (-arg); + } + else + width = arg; + } + else + { + const CHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + has_width = 1; + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const CHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + /* Allocate a temporary buffer of sufficient size. */ +# if HAVE_LONG_DOUBLE + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) ((LDBL_DIG + 1) + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + tmp_length = + (unsigned int) ((DBL_DIG + 1) + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + + if (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (CHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } + + pad_ptr = NULL; + p = tmp; +# if HAVE_LONG_DOUBLE + if (type == TYPE_LONGDOUBLE) + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + + if (isnanl (arg)) + { + if (dp->conversion == 'A') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + + if (arg < 0.0L) + { + sign = -1; + arg = -arg; + } + else if (arg == 0.0L) + { + /* Distinguish 0.0L and -0.0L. */ + static long double plus_zero = 0.0L; + long double arg_mem = arg; + if (memcmp (&plus_zero, &arg_mem, sizeof (long double)) != 0) + { + sign = -1; + arg = -arg; + } + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0L && arg + arg == arg) + { + if (dp->conversion == 'A') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { + int exponent; + long double mantissa; + + if (arg > 0.0L) + mantissa = printf_frexpl (arg, &exponent); + else + { + exponent = 0; + mantissa = 0.0L; + } + + if (has_precision + && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1) + { + /* Round the mantissa. */ + long double tail = mantissa; + size_t q; + + for (q = precision; ; q--) + { + int digit = (int) tail; + tail -= digit; + if (q == 0) + { + if (digit & 1 ? tail >= 0.5L : tail > 0.5L) + tail = 1 - tail; + else + tail = - tail; + break; + } + tail *= 16.0L; + } + if (tail != 0.0L) + for (q = precision; q > 0; q--) + tail *= 0.0625L; + mantissa += tail; + } + + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + { + int digit; + + digit = (int) mantissa; + mantissa -= digit; + *p++ = '0' + digit; + if ((flags & FLAG_ALT) + || mantissa > 0.0L || precision > 0) + { + *p++ = '.'; + /* This loop terminates because we assume + that FLT_RADIX is a power of 2. */ + while (mantissa > 0.0L) + { + mantissa *= 16.0L; + digit = (int) mantissa; + mantissa -= digit; + *p++ = digit + + (digit < 10 + ? '0' + : dp->conversion - 10); + if (precision > 0) + precision--; + } + while (precision > 0) + { + *p++ = '0'; + precision--; + } + } + } + *p++ = dp->conversion - 'A' + 'P'; +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } +# else + sprintf (p, "%+d", exponent); +# endif + while (*p != '\0') + p++; + } + } + } + else +# endif + { + double arg = a.arg[dp->arg_index].a.a_double; + + if (isnan (arg)) + { + if (dp->conversion == 'A') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + + if (arg < 0.0) + { + sign = -1; + arg = -arg; + } + else if (arg == 0.0) + { + /* Distinguish 0.0 and -0.0. */ + static double plus_zero = 0.0; + double arg_mem = arg; + if (memcmp (&plus_zero, &arg_mem, sizeof (double)) != 0) + { + sign = -1; + arg = -arg; + } + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0 && arg + arg == arg) + { + if (dp->conversion == 'A') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { + int exponent; + double mantissa; + + if (arg > 0.0) + mantissa = printf_frexp (arg, &exponent); + else + { + exponent = 0; + mantissa = 0.0; + } + + if (has_precision + && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1) + { + /* Round the mantissa. */ + double tail = mantissa; + size_t q; + + for (q = precision; ; q--) + { + int digit = (int) tail; + tail -= digit; + if (q == 0) + { + if (digit & 1 ? tail >= 0.5 : tail > 0.5) + tail = 1 - tail; + else + tail = - tail; + break; + } + tail *= 16.0; + } + if (tail != 0.0) + for (q = precision; q > 0; q--) + tail *= 0.0625; + mantissa += tail; + } + + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + { + int digit; + + digit = (int) mantissa; + mantissa -= digit; + *p++ = '0' + digit; + if ((flags & FLAG_ALT) + || mantissa > 0.0 || precision > 0) + { + *p++ = '.'; + /* This loop terminates because we assume + that FLT_RADIX is a power of 2. */ + while (mantissa > 0.0) + { + mantissa *= 16.0; + digit = (int) mantissa; + mantissa -= digit; + *p++ = digit + + (digit < 10 + ? '0' + : dp->conversion - 10); + if (precision > 0) + precision--; + } + while (precision > 0) + { + *p++ = '0'; + precision--; + } + } + } + *p++ = dp->conversion - 'A' + 'P'; +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } +# else + sprintf (p, "%+d", exponent); +# endif + while (*p != '\0') + p++; + } + } + } + /* The generated string now extends from tmp to p, with the + zero padding insertion point being at pad_ptr. */ + if (has_width && p - tmp < width) + { + size_t pad = width - (p - tmp); + CHAR_T *end = p + pad; + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + CHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + CHAR_T *q = end; + + while (p > tmp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + + p = end; + } + + { + size_t count = p - tmp; + + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); + + /* Make room for the result. */ + if (count >= allocated - length) + { + size_t n = xsum (length, count); + + ENSURE_ALLOCATION (n); + } + + /* Append the result. */ + memcpy (result + length, tmp, count * sizeof (CHAR_T)); + if (tmp != tmpbuf) + free (tmp); + length += count; + } + } +#endif else { arg_type type = a.arg[dp->arg_index].type; @@ -430,12 +907,32 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar break; case 'e': case 'E': case 'g': case 'G': - case 'a': case 'A': tmp_length = 12; /* sign, decimal point, exponent etc. */ tmp_length = xsum (tmp_length, precision); break; + case 'a': case 'A': +# if HAVE_LONG_DOUBLE + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + tmp_length = + (unsigned int) (DBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + break; + case 'c': # if HAVE_WINT_T && !WIDE_CHAR_VERSION if (type == TYPE_WIDE_CHAR) diff --git a/lgl/vasnprintf.h b/lgl/vasnprintf.h index 3ed5714471..f2a035b61a 100644 --- a/lgl/vasnprintf.h +++ b/lgl/vasnprintf.h @@ -1,5 +1,5 @@ /* vsprintf with automatic memory allocation. - Copyright (C) 2002-2004 Free Software Foundation, Inc. + Copyright (C) 2002-2004, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -65,6 +65,10 @@ extern "C" { free (output); } */ +#if REPLACE_VASNPRINTF +# define asnprintf rpl_asnprintf +# define vasnprintf rpl_vasnprintf +#endif extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) __attribute__ ((__format__ (__printf__, 3, 4))); extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) diff --git a/lgl/vasprintf.h b/lgl/vasprintf.h index b7a7ac87f9..37e7e47e62 100644 --- a/lgl/vasprintf.h +++ b/lgl/vasprintf.h @@ -1,5 +1,5 @@ /* vsprintf with automatic memory allocation. - Copyright (C) 2002-2003 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -23,7 +23,9 @@ /* Get asprintf(), vasprintf() declarations. */ #include <stdio.h> -#else +#endif + +#if !HAVE_VASPRINTF || REPLACE_VASPRINTF /* Get va_list. */ #include <stdarg.h> @@ -49,6 +51,10 @@ extern "C" { If the memory allocation succeeds, store the address of the string in *RESULT and return the number of resulting bytes, excluding the trailing NUL. Upon memory allocation error, or some other error, return -1. */ +#if REPLACE_VASPRINTF +# define asprintf rpl_asprintf +# define vasprintf rpl_vasprintf +#endif extern int asprintf (char **result, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); extern int vasprintf (char **result, const char *format, va_list args) |