[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: obstack_printf
From: |
Bruno Haible |
Subject: |
Re: obstack_printf |
Date: |
Sat, 14 Jun 2008 09:33:08 +0200 |
User-agent: |
KMail/1.5.4 |
Eric Blake wrote:
> 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.
The obligatory proofreading and nitpicking:
1) This C code
const size_t cutoff = 1024;
char buf[cutoff];
is understood only by gcc, Tru64 cc, IRIX cc. It fails to compile on other C
compilers:
Solaris, Sun C 5.0:
cc -O -DHAVE_CONFIG_H -I. -I.. -g -c obstack_printf.c
"obstack_printf.c", line 62: integral constant expression expected
HP-UX, "cc -Ae":
cc: "obstack_printf.c", line 62: error 1502: Array size must be a constant
expression.
AIX, "xlc -D_ALL_SOURCE":
"obstack_printf.c", line 62.12: 1506-195 (S) Integral constant expression with
a value greater than zero is required.
The fix is to define the array size either as a macro or as an enum value.
2) You test for the declaration of the function in <stdio.h>. Good. But in order
to minimize the danger inherent in redeclaration of a system function, it's
better
to let <stdio.h> declare the function by itself: Define _GNU_SOURCE.
3) gl_FUNC_OBSTACK_PRINTF_POSIX assumes that if the *printf family of functions
is POSIX compliant, obstack_printf exists as well. Pretty daring :-) To fix
this, I looked at snprintf-posix.m4.
4) In the "Include" section of the module description, I find it confusing to
mention "obstack.h" before <stdio.h>. It suggests that "obstack.h" should be
included before <stdio.h>. This is not the case; actually, one does not need
to include "obstack.h" at all if a forward declaration
struct obstack;
is present.
5) What do you mean by this comment in tests/test-obstack-printf.c ?
/* In general, don't invoke obstack_* functions inside ASSERT, as
not all compilers can avoid multiple side effects. */
The ASSERT macro is ours, not the system's one. What can go wrong regarding
"multiple side effects"?
Here's the proposed fix:
2008-06-14 Bruno Haible <address@hidden>
* lib/obstack_printf.c (obstack_vprintf): Define the stack-allocated
array size as a macro.
* m4/obstack-printf.m4 (gl_FUNC_OBSTACK_PRINTF): Require
AC_USE_SYSTEM_EXTENSIONS.
* m4/obstack-printf-posix.m4 (gl_FUNC_OBSTACK_PRINTF_POSIX): Likewise.
Test whether the obstack_printf function actually exists.
* modules/obstack-printf (Depends-on): Add extensions.
(Include): Remove obstack.h.
* modules/obstack-printf-posix (Depends-on): Add extensions.
(Include): Remove obstack.h.
*** lib/obstack_printf.c.orig 2008-06-14 09:05:52.000000000 +0200
--- lib/obstack_printf.c 2008-06-14 08:43:36.000000000 +0200
***************
*** 58,73 ****
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)
--- 58,73 ----
stack-allocated buffer and copy, to reduce the likelihood of a
small-size malloc. Otherwise, print directly into the
obstack. */
! #define 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)
***************
*** 89,92 ****
--- 89,93 ----
free (str);
}
return len;
+ #undef CUTOFF
}
*** m4/obstack-printf.m4.orig 2008-06-14 09:05:52.000000000 +0200
--- m4/obstack-printf.m4 2008-06-14 08:12:56.000000000 +0200
***************
*** 1,4 ****
! # 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,
--- 1,4 ----
! # obstack-printf.m4 serial 2
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,
***************
*** 10,15 ****
--- 10,18 ----
AC_DEFUN([gl_FUNC_OBSTACK_PRINTF],
[
+ dnl Persuade glibc <stdio.h> to declare obstack_printf(), obstack_vprintf().
+ AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
AC_REQUIRE([gl_STDIO_H_DEFAULTS])
AC_CHECK_FUNCS_ONCE([obstack_printf])
if test $ac_cv_func_obstack_printf = no ; then
*** m4/obstack-printf-posix.m4.orig 2008-06-14 09:05:52.000000000 +0200
--- m4/obstack-printf-posix.m4 2008-06-14 08:24:19.000000000 +0200
***************
*** 1,4 ****
! # 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,
--- 1,4 ----
! # obstack-printf-posix.m4 serial 2
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,
***************
*** 6,11 ****
--- 6,14 ----
AC_DEFUN([gl_FUNC_OBSTACK_PRINTF_POSIX],
[
+ dnl Persuade glibc <stdio.h> to declare obstack_printf(), obstack_vprintf().
+ AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
AC_REQUIRE([gl_PRINTF_SIZES_C99])
AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
AC_REQUIRE([gl_PRINTF_INFINITE])
***************
*** 20,80 ****
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
--- 23,86 ----
AC_REQUIRE([gl_PRINTF_PRECISION])
AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_obstack_printf_posix=no
! AC_CHECK_FUNCS_ONCE([obstack_printf])
! if test $ac_cv_func_obstack_printf = yes ; then
! 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
! fi
if test $gl_cv_func_obstack_printf_posix = no; then
gl_PREREQ_VASNPRINTF_LONG_DOUBLE
gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE
*** modules/obstack-printf.orig 2008-06-14 09:05:52.000000000 +0200
--- modules/obstack-printf 2008-06-14 08:16:19.000000000 +0200
***************
*** 9,14 ****
--- 9,15 ----
obstack
stdio
vasnprintf
+ extensions
configure.ac:
gl_FUNC_OBSTACK_PRINTF
***************
*** 17,23 ****
Makefile.am:
Include:
- "obstack.h"
<stdio.h>
License:
--- 18,23 ----
*** modules/obstack-printf-posix.orig 2008-06-14 09:05:52.000000000 +0200
--- modules/obstack-printf-posix 2008-06-14 08:16:23.000000000 +0200
***************
*** 10,15 ****
--- 10,16 ----
obstack
stdio
vasnprintf-posix
+ extensions
configure.ac:
gl_FUNC_OBSTACK_PRINTF_POSIX
***************
*** 18,24 ****
Makefile.am:
Include:
- "obstack.h"
<stdio.h>
License:
--- 19,24 ----