bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

obstack_printf


From: Eric Blake
Subject: obstack_printf
Date: Fri, 13 Jun 2008 07:35:43 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080421 Thunderbird/2.0.0.14 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

More than a year ago, I proposed adding obstack_printf:

http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00188.html

Well, the time finally came where I'm ready to use it in m4, so here goes.

Tested on cygwin, which lacks native obstacks, and on glibc 2.3.4, where
obstack-printf-posix used the replacement (because of the x86 issue with
invalid bit patterns to isnanl) but obstack-printf deferred to the native
version.  I didn't bother making test-obstack-printf.c as extensive as
Bruno's other *printf tests, mainly because the module dependencies mean
that vasnprintf will provide the stress test of the libc printf.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEUEARECAAYFAkhSd68ACgkQ84KuGfSFAYA9HgCcDL7wNvq3S8Q0RNZ1A0d2RzSF
SsYAl2uoFntf0XW28GoGvvST3cGZ8Vc=
=aJz0
-----END PGP SIGNATURE-----
>From ad87d7005546a1a79ab90f47872f1fc8bdd40fb5 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 13 Jun 2008 06:40:53 -0600
Subject: [PATCH] Add obstack-printf and obstack-printf-posix modules.

* modules/obstack-printf: New file.
* modules/obstack-printf-posix: Likewise.
* MODULES.html.sh (Misc): Mention them.
* doc/glibc-functions/obstack_printf.texi (obstack_printf):
Likewise.
* doc/glibc-functions/obstack_vprintf.texi (obstack_vprintf):
Likewise.
* modules/stdio (Makefile.am): Accomodate new modules.
* m4/stdio_h.m4 (gl_STDIO_H_DEFAULTS): Likewise.
* lib/stdio.in.h (rpl_obstack_printf, rpl_obstack_vprintf):
Declare.
* lib/obstack_printf.c (obstack_printf, obstack_vprintf): New
functions.
* m4/obstack-printf.m4 (gl_OBSTACK_PRINTF)
(gl_REPLACE_OBSTACK_PRINTF): New macros
* m4/obstack-printf-posix.m4 (gl_OBSTACK_PRINTF_POSIX): Likewise.
* tests/test-obstack-printf.c: New file.
* modules/obstack-printf-tests: Likewise.
* modules/obstack-printf-posix-tests: Likewise.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                                |   23 ++++++
 MODULES.html.sh                          |    2 +
 doc/glibc-functions/obstack_printf.texi  |   58 +++++++++++++-
 doc/glibc-functions/obstack_vprintf.texi |   58 +++++++++++++-
 lib/obstack_printf.c                     |   92 ++++++++++++++++++++++
 lib/stdio.in.h                           |   20 +++++
 m4/obstack-printf-posix.m4               |   92 ++++++++++++++++++++++
 m4/obstack-printf.m4                     |   32 ++++++++
 m4/stdio_h.m4                            |    6 +-
 modules/obstack-printf                   |   27 +++++++
 modules/obstack-printf-posix             |   28 +++++++
 modules/obstack-printf-posix-tests       |    8 ++
 modules/obstack-printf-tests             |   13 +++
 modules/stdio                            |    4 +
 tests/test-obstack-printf.c              |  125 ++++++++++++++++++++++++++++++
 15 files changed, 577 insertions(+), 11 deletions(-)
 create mode 100644 lib/obstack_printf.c
 create mode 100644 m4/obstack-printf-posix.m4
 create mode 100644 m4/obstack-printf.m4
 create mode 100644 modules/obstack-printf
 create mode 100644 modules/obstack-printf-posix
 create mode 100644 modules/obstack-printf-posix-tests
 create mode 100644 modules/obstack-printf-tests
 create mode 100644 tests/test-obstack-printf.c

diff --git a/ChangeLog b/ChangeLog
index 38b642d..caaef9a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2008-06-13  Eric Blake  <address@hidden>
+
+       Add obstack-printf and obstack-printf-posix modules.
+       * modules/obstack-printf: New file.
+       * modules/obstack-printf-posix: Likewise.
+       * MODULES.html.sh (Misc): Mention them.
+       * doc/glibc-functions/obstack_printf.texi (obstack_printf):
+       Likewise.
+       * doc/glibc-functions/obstack_vprintf.texi (obstack_vprintf):
+       Likewise.
+       * modules/stdio (Makefile.am): Accomodate new modules.
+       * m4/stdio_h.m4 (gl_STDIO_H_DEFAULTS): Likewise.
+       * lib/stdio.in.h (rpl_obstack_printf, rpl_obstack_vprintf):
+       Declare.
+       * lib/obstack_printf.c (obstack_printf, obstack_vprintf): New
+       functions.
+       * m4/obstack-printf.m4 (gl_OBSTACK_PRINTF)
+       (gl_REPLACE_OBSTACK_PRINTF): New macros
+       * m4/obstack-printf-posix.m4 (gl_OBSTACK_PRINTF_POSIX): Likewise.
+       * tests/test-obstack-printf.c: New file.
+       * modules/obstack-printf-tests: Likewise.
+       * modules/obstack-printf-posix-tests: Likewise.
+
 2008-06-11  Bruno Haible  <address@hidden>
 
        * m4/open.m4 (gl_FUNC_OPEN): Add test against trailing slash bug.
diff --git a/MODULES.html.sh b/MODULES.html.sh
index d46cf68..f82e957 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1845,6 +1845,8 @@ func_all_modules ()
   func_module linebuffer
   func_module memxor
   func_module obstack
+  func_module obstack-printf
+  func_module obstack-printf-posix
   func_module hash-pjw
   func_module hash
   func_module readline
diff --git a/doc/glibc-functions/obstack_printf.texi 
b/doc/glibc-functions/obstack_printf.texi
index 53529c8..d039aee 100644
--- a/doc/glibc-functions/obstack_printf.texi
+++ b/doc/glibc-functions/obstack_printf.texi
@@ -2,15 +2,63 @@
 @subsection @code{obstack_printf}
 @findex obstack_printf
 
-Gnulib module: ---
+Gnulib module: obstack-printf or obstack-printf-posix
 
-Portability problems fixed by Gnulib:
+Portability problems fixed by either Gnulib module
address@hidden or @code{obstack-printf-posix}:
 @itemize
address@hidden
+This function is missing on all non-glibc platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 
6.5, OSF/1 5.1, Solaris 10, Cygwin, mingw, Interix 3.5, BeOS.
 @end itemize
 
-Portability problems not fixed by Gnulib:
+Portability problems fixed by Gnulib module @code{ostack-printf-posix}:
 @itemize
 @item
-This function is missing on all non-glibc platforms:
-MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 
6.5, OSF/1 5.1, Solaris 10, Cygwin, mingw, Interix 3.5, BeOS.
+This function does not support size specifiers as in C99 (@code{hh}, @code{ll},
address@hidden, @code{t}, @code{z}) on some platforms:
+AIX 5.1, HP-UX 11.23, IRIX 6.5, OSF/1 5.1, Solaris 9, Cygwin 2006, mingw, BeOS.
address@hidden
+printf of @samp{long double} numbers is unsupported on some platforms:
+mingw, BeOS.
address@hidden
+printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
+incorrect result on some platforms:
+AIX 5.2, OSF/1 5.1, Solaris 10, mingw.
address@hidden
+This function does not support the @samp{a} and @samp{A} directives on some
+platforms:
+glibc-2.3.6, MacOS X 10.3, NetBSD 3.0, OpenBSD 4.0, AIX 5.2, HP-UX 11, IRIX 
6.5, OSF/1 5.1, Solaris 10, Cygwin, mingw, BeOS.
address@hidden
+This function does not support the @samp{F} directive on some platforms:
+NetBSD 3.0, AIX 5.1, HP-UX 11.23, IRIX 6.5, OSF/1 5.1, Solaris 9, Cygwin, 
mingw, BeOS.
address@hidden
+This function does not support format directives that access arguments in an
+arbitrary order, such as @code{"%2$s"}, on some platforms:
+NetBSD 3.0, mingw, BeOS.
address@hidden
+This function doesn't support the @code{'} flag on some platforms:
+NetBSD 3.0, Cygwin 2006, mingw.
address@hidden
+This function behaves incorrectly when a @samp{-} flag and a negative width
+are specified together, on some platforms:
+HP-UX 10.20.
address@hidden
+printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
+with zeroes) on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 
10, Cygwin 2007, mingw.
address@hidden
+This function does not support precisions larger than 512 or 1024 in integer,
+floating-point and pointer output on some platforms:
+mingw, BeOS.
address@hidden
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
address@hidden
+This function does not fully support the @samp{n} directive on some platforms:
+HP-UX 11, mingw.
address@hidden itemize
+
+Portability problems not fixed by Gnulib:
address@hidden
 @end itemize
diff --git a/doc/glibc-functions/obstack_vprintf.texi 
b/doc/glibc-functions/obstack_vprintf.texi
index 0ae61a4..34775e3 100644
--- a/doc/glibc-functions/obstack_vprintf.texi
+++ b/doc/glibc-functions/obstack_vprintf.texi
@@ -2,15 +2,63 @@
 @subsection @code{obstack_vprintf}
 @findex obstack_vprintf
 
-Gnulib module: ---
+Gnulib module: obstack-printf or obstack-printf-posix
 
-Portability problems fixed by Gnulib:
+Portability problems fixed by either Gnulib module
address@hidden or @code{obstack-printf-posix}:
 @itemize
address@hidden
+This function is missing on all non-glibc platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 
6.5, OSF/1 5.1, Solaris 10, Cygwin, mingw, Interix 3.5, BeOS.
 @end itemize
 
-Portability problems not fixed by Gnulib:
+Portability problems fixed by Gnulib module @code{ostack-printf-posix}:
 @itemize
 @item
-This function is missing on all non-glibc platforms:
-MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 
6.5, OSF/1 5.1, Solaris 10, Cygwin, mingw, Interix 3.5, BeOS.
+This function does not support size specifiers as in C99 (@code{hh}, @code{ll},
address@hidden, @code{t}, @code{z}) on some platforms:
+AIX 5.1, HP-UX 11.23, IRIX 6.5, OSF/1 5.1, Solaris 9, Cygwin 2006, mingw, BeOS.
address@hidden
+printf of @samp{long double} numbers is unsupported on some platforms:
+mingw, BeOS.
address@hidden
+printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
+incorrect result on some platforms:
+AIX 5.2, OSF/1 5.1, Solaris 10, mingw.
address@hidden
+This function does not support the @samp{a} and @samp{A} directives on some
+platforms:
+glibc-2.3.6, MacOS X 10.3, NetBSD 3.0, OpenBSD 4.0, AIX 5.2, HP-UX 11, IRIX 
6.5, OSF/1 5.1, Solaris 10, Cygwin, mingw, BeOS.
address@hidden
+This function does not support the @samp{F} directive on some platforms:
+NetBSD 3.0, AIX 5.1, HP-UX 11.23, IRIX 6.5, OSF/1 5.1, Solaris 9, Cygwin, 
mingw, BeOS.
address@hidden
+This function does not support format directives that access arguments in an
+arbitrary order, such as @code{"%2$s"}, on some platforms:
+NetBSD 3.0, mingw, BeOS.
address@hidden
+This function doesn't support the @code{'} flag on some platforms:
+NetBSD 3.0, Cygwin 2006, mingw.
address@hidden
+This function behaves incorrectly when a @samp{-} flag and a negative width
+are specified together, on some platforms:
+HP-UX 10.20.
address@hidden
+printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
+with zeroes) on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 
10, Cygwin 2007, mingw.
address@hidden
+This function does not support precisions larger than 512 or 1024 in integer,
+floating-point and pointer output on some platforms:
+mingw, BeOS.
address@hidden
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
address@hidden
+This function does not fully support the @samp{n} directive on some platforms:
+HP-UX 11, mingw.
address@hidden itemize
+
+Portability problems not fixed by Gnulib:
address@hidden
 @end itemize
diff --git a/lib/obstack_printf.c b/lib/obstack_printf.c
new file mode 100644
index 0000000..f546f00
--- /dev/null
+++ b/lib/obstack_printf.c
@@ -0,0 +1,92 @@
+/* Formatted output to obstacks.
+   Copyright (C) 2008 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <stdio.h>
+
+#include "obstack.h"
+#include "vasnprintf.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* Grow an obstack with formatted output.  Return the number of bytes
+   added to OBS.  No trailing nul byte is added, and the object should
+   be closed with obstack_finish before use.
+
+   Upon memory allocation error, call obstack_alloc_failed_handler.
+   Upon other error, return -1.  */
+int
+obstack_printf (struct obstack *obs, const char *format, ...)
+{
+  va_list args;
+  int result;
+
+  va_start (args, format);
+  result = obstack_vprintf (obs, format, args);
+  va_end (args);
+  return result;
+}
+
+/* Grow an obstack with formatted output.  Return the number of bytes
+   added to OBS.  No trailing nul byte is added, and the object should
+   be closed with obstack_finish before use.
+
+   Upon memory allocation error, call obstack_alloc_failed_handler.
+   Upon other error, return -1.  */
+int
+obstack_vprintf (struct obstack *obs, const char *format, va_list args)
+{
+  /* If we are close to the end of the current obstack chunk, use a
+     stack-allocated buffer and copy, to reduce the likelihood of a
+     small-size malloc.  Otherwise, print directly into the
+     obstack.  */
+  const size_t cutoff = 1024;
+  char buf[cutoff];
+  char *base = obstack_next_free (obs);
+  size_t len = obstack_room (obs);
+  char *str;
+
+  if (len < cutoff)
+    {
+      base = buf;
+      len = cutoff;
+    }
+  str = vasnprintf (base, &len, format, args);
+  if (!str)
+    {
+      if (errno == ENOMEM)
+       obstack_alloc_failed_handler ();
+      return -1;
+    }
+  if (str == base && str != buf)
+    /* The output was already computed in place, but we need to
+       account for its size.  */
+    obstack_blank_fast (obs, len);
+  else
+    {
+      /* The output exceeded available obstack space or we used buf;
+        copy the resulting string.  */
+      obstack_grow (obs, str, len);
+      if (str != buf)
+       free (str);
+    }
+  return len;
+}
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 5fd27ff..3944955 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -212,6 +212,26 @@ extern int vsprintf (char *str, const char *format, 
va_list args)
 # endif
 #endif
 
+#if @GNULIB_OBSTACK_PRINTF@
+# if @REPLACE_OBSTACK_PRINTF@
+#  define obstack_printf rpl_osbtack_printf
+#  define obstack_vprintf rpl_obstack_vprintf
+# endif
+# if @REPLACE_OBSTACK_PRINTF@ || address@hidden@
+  struct obstack;
+  /* Grow an obstack with formatted output.  Return the number of
+     bytes added to OBS.  No trailing nul byte is added, and the
+     object should be closed with obstack_finish before use.  Upon
+     memory allocation error, call obstack_alloc_failed_handler.  Upon
+     other error, return -1.  */
+  extern int obstack_printf (struct obstack *obs, const char *format, ...)
+    __attribute__ ((__format__ (__printf__, 2, 3)));
+  extern int obstack_vprintf (struct obstack *obs, const char *format,
+                             va_list args)
+    __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#endif
+
 #if @GNULIB_FOPEN@
 # if @REPLACE_FOPEN@
 #  define fopen rpl_fopen
diff --git a/m4/obstack-printf-posix.m4 b/m4/obstack-printf-posix.m4
new file mode 100644
index 0000000..b5678b4
--- /dev/null
+++ b/m4/obstack-printf-posix.m4
@@ -0,0 +1,92 @@
+# obstack-printf-posix.m4 serial 1
+dnl Copyright (C) 2008 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_OBSTACK_PRINTF_POSIX],
+[
+  AC_REQUIRE([gl_PRINTF_SIZES_C99])
+  AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
+  AC_REQUIRE([gl_PRINTF_INFINITE])
+  AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_A])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_F])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_N])
+  AC_REQUIRE([gl_PRINTF_POSITIONS])
+  AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
+  AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
+  AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+  AC_REQUIRE([gl_PRINTF_PRECISION])
+  AC_REQUIRE([gl_PRINTF_ENOMEM])
+  gl_cv_func_obstack_printf_posix=no
+  case "$gl_cv_func_printf_sizes_c99" in
+    *yes)
+      case "$gl_cv_func_printf_long_double" in
+        *yes)
+          case "$gl_cv_func_printf_infinite" in
+            *yes)
+              case "$gl_cv_func_printf_infinite_long_double" in
+                *yes)
+                  case "$gl_cv_func_printf_directive_a" in
+                    *yes)
+                      case "$gl_cv_func_printf_directive_f" in
+                        *yes)
+                          case "$gl_cv_func_printf_directive_n" in
+                            *yes)
+                              case "$gl_cv_func_printf_positions" in
+                                *yes)
+                                  case "$gl_cv_func_printf_flag_grouping" in
+                                    *yes)
+                                      case 
"$gl_cv_func_printf_flag_leftadjust" in
+                                        *yes)
+                                          case "$gl_cv_func_printf_flag_zero" 
in
+                                            *yes)
+                                              case 
"$gl_cv_func_printf_precision" in
+                                                *yes)
+                                                  case 
"$gl_cv_func_printf_enomem" in
+                                                    *yes)
+                                                      # obstack_printf exists 
and is
+                                                      # already POSIX 
compliant.
+                                                      
gl_cv_func_obstack_printf_posix= yes
+                                                      ;;
+                                                   esac
+                                                  ;;
+                                              esac
+                                              ;;
+                                          esac
+                                          ;;
+                                      esac
+                                      ;;
+                                  esac
+                                  ;;
+                              esac
+                              ;;
+                          esac
+                          ;;
+                      esac
+                      ;;
+                  esac
+                  ;;
+              esac
+              ;;
+          esac
+          ;;
+      esac
+      ;;
+  esac
+  if test $gl_cv_func_obstack_printf_posix = no; then
+    gl_PREREQ_VASNPRINTF_LONG_DOUBLE
+    gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE
+    gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_A
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_F
+    gl_PREREQ_VASNPRINTF_FLAG_GROUPING
+    gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
+    gl_PREREQ_VASNPRINTF_FLAG_ZERO
+    gl_PREREQ_VASNPRINTF_PRECISION
+    gl_PREREQ_VASNPRINTF_ENOMEM
+    gl_REPLACE_VASNPRINTF
+    gl_REPLACE_OBSTACK_PRINTF
+  fi
+])
diff --git a/m4/obstack-printf.m4 b/m4/obstack-printf.m4
new file mode 100644
index 0000000..98860c2
--- /dev/null
+++ b/m4/obstack-printf.m4
@@ -0,0 +1,32 @@
+# obstack-printf.m4 serial 1
+dnl Copyright (C) 2008 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.
+
+dnl From Eric Blake.
+dnl Test whether obstack_printf() exists.  For now, we assume that
+dnl obstack_vprintf behaves identically, so we only test for one.
+
+AC_DEFUN([gl_FUNC_OBSTACK_PRINTF],
+[
+  AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+  AC_CHECK_FUNCS_ONCE([obstack_printf])
+  if test $ac_cv_func_obstack_printf = no ; then
+    gl_REPLACE_OBSTACK_PRINTF
+  fi
+
+  AC_CHECK_DECLS_ONCE([obstack_printf])
+  if test $ac_cv_have_decl_obstack_printf = no; then
+    HAVE_DECL_OBSTACK_PRINTF=0
+  fi
+])
+
+AC_DEFUN([gl_REPLACE_OBSTACK_PRINTF],
+[
+  AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+  AC_LIBOBJ([obstack_printf])
+  if test $ac_cv_func_obstack_printf = yes; then
+    REPLACE_OBSTACK_PRINTF=1
+  fi
+])
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
index fa262e3..4980f9e 100644
--- a/m4/stdio_h.m4
+++ b/m4/stdio_h.m4
@@ -1,4 +1,4 @@
-# stdio_h.m4 serial 10
+# stdio_h.m4 serial 11
 dnl Copyright (C) 2007-2008 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -21,6 +21,8 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS],
 [
   GNULIB_FPRINTF_POSIX=0;  AC_SUBST([GNULIB_FPRINTF_POSIX])
   GNULIB_PRINTF_POSIX=0;   AC_SUBST([GNULIB_PRINTF_POSIX])
+  GNULIB_OBSTACK_PRINTF=0; AC_SUBST([GNULIB_OBSTACK_PRINTF])
+  GNULIB_OBSTACK_PRINTF_POSIX=0;  AC_SUBST([GNULIB_OBSTACK_PRINTF_POSIX])
   GNULIB_SNPRINTF=0;       AC_SUBST([GNULIB_SNPRINTF])
   GNULIB_SPRINTF_POSIX=0;  AC_SUBST([GNULIB_SPRINTF_POSIX])
   GNULIB_VFPRINTF_POSIX=0; AC_SUBST([GNULIB_VFPRINTF_POSIX])
@@ -62,6 +64,8 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS],
   HAVE_DECL_GETDELIM=1;    AC_SUBST([HAVE_DECL_GETDELIM])
   HAVE_DECL_GETLINE=1;     AC_SUBST([HAVE_DECL_GETLINE])
   REPLACE_GETLINE=0;       AC_SUBST([REPLACE_GETLINE])
+  HAVE_DECL_OBSTACK_PRINTF=1;     AC_SUBST([HAVE_DECL_OBSTACK_PRINTF])
+  REPLACE_OBSTACK_PRINTF=0;       AC_SUBST([REPLACE_OBSTACK_PRINTF])
 ])
 
 dnl Code shared by fseeko and ftello.  Determine if large files are supported,
diff --git a/modules/obstack-printf b/modules/obstack-printf
new file mode 100644
index 0000000..44414b7
--- /dev/null
+++ b/modules/obstack-printf
@@ -0,0 +1,27 @@
+Description:
+Formatted printing into an obstack.
+
+Files:
+m4/obstack-printf.m4
+lib/obstack_printf.c
+
+Depends-on:
+obstack
+stdio
+vasnprintf
+
+configure.ac:
+gl_FUNC_OBSTACK_PRINTF
+gl_STDIO_MODULE_INDICATOR([obstack-printf])
+
+Makefile.am:
+
+Include:
+"obstack.h"
+<stdio.h>
+
+License:
+GPL
+
+Maintainer:
+Eric Blake
diff --git a/modules/obstack-printf-posix b/modules/obstack-printf-posix
new file mode 100644
index 0000000..e4c595b
--- /dev/null
+++ b/modules/obstack-printf-posix
@@ -0,0 +1,28 @@
+Description:
+POSIX formatted printing into an obstack.
+
+Files:
+m4/obstack-printf.m4
+m4/obstack-printf-posix.m4
+lib/obstack_printf.c
+
+Depends-on:
+obstack
+stdio
+vasnprintf-posix
+
+configure.ac:
+gl_FUNC_OBSTACK_PRINTF_POSIX
+gl_STDIO_MODULE_INDICATOR([obstack-printf-posix])
+
+Makefile.am:
+
+Include:
+"obstack.h"
+<stdio.h>
+
+License:
+GPL
+
+Maintainer:
+Eric Blake
diff --git a/modules/obstack-printf-posix-tests 
b/modules/obstack-printf-posix-tests
new file mode 100644
index 0000000..a5b1bc1
--- /dev/null
+++ b/modules/obstack-printf-posix-tests
@@ -0,0 +1,8 @@
+Files:
+
+Depends-on:
+obstack-printf-tests
+
+configure.ac:
+
+Makefile.am:
diff --git a/modules/obstack-printf-tests b/modules/obstack-printf-tests
new file mode 100644
index 0000000..c06be7d
--- /dev/null
+++ b/modules/obstack-printf-tests
@@ -0,0 +1,13 @@
+Files:
+tests/test-obstack-printf.c
+
+Depends-on:
+progname
+xalloc
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-obstack-printf
+check_PROGRAMS += test-obstack-printf
+test_obstack_printf_LDADD = $(LDADD) @LIBINTL@
diff --git a/modules/stdio b/modules/stdio
index d6a1549..91468d4 100644
--- a/modules/stdio
+++ b/modules/stdio
@@ -24,6 +24,8 @@ stdio.h: stdio.in.h
              -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \
              -e 's|@''GNULIB_FPRINTF_POSIX''@|$(GNULIB_FPRINTF_POSIX)|g' \
              -e 's|@''GNULIB_PRINTF_POSIX''@|$(GNULIB_PRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_OBSTACK_PRINTF''@|$(GNULIB_OBSTACK_PRINTF)|g' \
+             -e 
's|@''GNULIB_OBSTACK_PRINTF_POSIX''@|$(GNULIB_OBSTACK_PRINTF_POSIX)|g' \
              -e 's|@''GNULIB_SNPRINTF''@|$(GNULIB_SNPRINTF)|g' \
              -e 's|@''GNULIB_SPRINTF_POSIX''@|$(GNULIB_SPRINTF_POSIX)|g' \
              -e 's|@''GNULIB_VFPRINTF_POSIX''@|$(GNULIB_VFPRINTF_POSIX)|g' \
@@ -62,6 +64,8 @@ stdio.h: stdio.in.h
              -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \
              -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \
              -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \
+             -e 
's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \
+             -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \
              -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
              < $(srcdir)/stdio.in.h; \
        } > address@hidden
diff --git a/tests/test-obstack-printf.c b/tests/test-obstack-printf.c
new file mode 100644
index 0000000..fba7887
--- /dev/null
+++ b/tests/test-obstack-printf.c
@@ -0,0 +1,125 @@
+/* Test of obstack_printf() and obstack_vprintf() functions.
+   Copyright (C) 2008 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake <address@hidden>, 2008.  */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include "obstack.h"
+#include "xalloc.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+        {                                                                   \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          fflush (stderr);                                                  \
+          abort ();                                                         \
+        }                                                                   \
+    }                                                                       \
+  while (0)
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
+static void
+test_function (int (*my_obstack_printf) (struct obstack *, const char *, ...))
+{
+  struct obstack obs;
+  obstack_init (&obs);
+  /* In general, don't invoke obstack_* functions inside ASSERT, as
+     not all compilers can avoid multiple side effects.  */
+
+  /* Grow the obstack to near its boundary, then check that output
+     longer than the obstack free space grows the obstack.  */
+  {
+    char *base = obstack_base (&obs);
+    char *new_base;
+    int result;
+    int size;
+    int room = obstack_room (&obs) - 4;
+
+    obstack_blank_fast (&obs, room);
+    result = my_obstack_printf (&obs, "%d %s", 123, "456");
+    ASSERT (result == 7);
+    size = obstack_object_size (&obs);
+    ASSERT (result + room == size);
+    obstack_1grow (&obs, 0);
+    new_base = obstack_finish (&obs);
+    ASSERT (base != new_base);
+    ASSERT (strcmp (new_base + room, "123 456") == 0);
+  }
+
+  /* Check that strings shorter than the obstack free space don't
+     cause a reshuffling of the obstack.  */
+  {
+    char *base = obstack_base (&obs);
+    char *new_base;
+    int result;
+    int size;
+    int room = obstack_room (&obs);
+
+    ASSERT (8 < room);
+    result = my_obstack_printf (&obs, "%d %s", 123, "456");
+    ASSERT (result == 7);
+    size = obstack_object_size (&obs);
+    ASSERT (result == size);
+    new_base = obstack_base (&obs);
+    ASSERT (base == new_base);
+    ASSERT (strncmp (base, "123 456", result) == 0);
+  }
+
+  obstack_free (&obs, NULL);
+}
+
+static int
+my_obstack_printf (struct obstack *obs, const char *format, ...)
+{
+  va_list args;
+  int ret;
+
+  va_start (args, format);
+  ret = obstack_vprintf (obs, format, args);
+  va_end (args);
+  return ret;
+}
+
+static void
+test_obstack_vprintf ()
+{
+  test_function (my_obstack_printf);
+}
+
+static void
+test_obstack_printf ()
+{
+  test_function (obstack_printf);
+}
+
+int
+main (int argc, char *argv[])
+{
+  test_obstack_vprintf ();
+  test_obstack_printf ();
+  return 0;
+}
-- 
1.5.5.1


reply via email to

[Prev in Thread] Current Thread [Next in Thread]