* 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 <ebb9@byu.net>
+2008-06-13 Eric Blake <ebb9@byu.net>
+
+ 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 <bruno@clisp.org>
* m4/open.m4 (gl_FUNC_OPEN): Add test against trailing slash bug.
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
@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
+@code{obstack-printf} or @code{obstack-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.
@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},
+@code{j}, @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.
+@item
+printf of @samp{long double} numbers is unsupported on some platforms:
+mingw, BeOS.
+@item
+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.
+@item
+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.
+@item
+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.
+@item
+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.
+@item
+This function doesn't support the @code{'} flag on some platforms:
+NetBSD 3.0, Cygwin 2006, mingw.
+@item
+This function behaves incorrectly when a @samp{-} flag and a negative width
+are specified together, on some platforms:
+HP-UX 10.20.
+@item
+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.
+@item
+This function does not support precisions larger than 512 or 1024 in integer,
+floating-point and pointer output on some platforms:
+mingw, BeOS.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
+@item
+This function does not fully support the @samp{n} directive on some platforms:
+HP-UX 11, mingw.
+@end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
@end itemize
@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
+@code{obstack-printf} or @code{obstack-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.
@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},
+@code{j}, @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.
+@item
+printf of @samp{long double} numbers is unsupported on some platforms:
+mingw, BeOS.
+@item
+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.
+@item
+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.
+@item
+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.
+@item
+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.
+@item
+This function doesn't support the @code{'} flag on some platforms:
+NetBSD 3.0, Cygwin 2006, mingw.
+@item
+This function behaves incorrectly when a @samp{-} flag and a negative width
+are specified together, on some platforms:
+HP-UX 10.20.
+@item
+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.
+@item
+This function does not support precisions larger than 512 or 1024 in integer,
+floating-point and pointer output on some platforms:
+mingw, BeOS.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
+@item
+This function does not fully support the @samp{n} directive on some platforms:
+HP-UX 11, mingw.
+@end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
@end itemize
--- /dev/null
+/* 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;
+}
# 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@ || !@HAVE_DECL_OBSTACK_PRINTF@
+ 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
--- /dev/null
+# 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
+])
--- /dev/null
+# 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
+])
-# 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,
[
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])
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,
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+Files:
+
+Depends-on:
+obstack-printf-tests
+
+configure.ac:
+
+Makefile.am:
--- /dev/null
+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@
-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' \
-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; \
} > $@-t
--- /dev/null
+/* 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 <ebb9@byu.net>, 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;
+}