[svn-r9861] Purpose:

Bug fix

Description:
    Add detect vasprintf() routine and use it instead of vsnprintf() when
formatting error descriptions if it's available.

    Added configure test to detect "broken" vsnprintf() implementations which
don't return the correct number of character for strings that are too long to
fit into the buffer provided (currently a problem on the SGIs and probably the
HP).

    Re-wrote error formatting code in H5Epush_stack() to handle broken
vsnprintf() implementations, etc.

Platforms tested:
    IRIX64 6.5 (modi4)
    h5committest
This commit is contained in:
Quincey Koziol 2005-01-23 22:26:37 -05:00
parent d363f95d6d
commit 563a8dd140
5 changed files with 222 additions and 3 deletions

153
configure vendored
View File

@ -30855,7 +30855,7 @@ done
for ac_func in signal snprintf vsnprintf strdup system waitpid
for ac_func in signal snprintf vasprintf strdup system waitpid
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
@ -30931,6 +30931,157 @@ fi
done
for ac_func in vsnprintf
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
if eval "test \"\${$as_ac_var+set}\" = set"; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func (); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char $ac_func ();
char (*f) ();
#ifdef F77_DUMMY_MAIN
# ifdef __cplusplus
extern "C"
# endif
int F77_DUMMY_MAIN() { return 1; }
#endif
int
main ()
{
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
f = $ac_func;
#endif
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
if test `eval echo '${'$as_ac_var'}'` = yes; then
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
echo "$as_me:$LINENO: checking if vsnprintf returns correct value" >&5
echo $ECHO_N "checking if vsnprintf returns correct value... $ECHO_C" >&6
if test "${hdf5_cv_vsnprintf_works+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test "$cross_compiling" = yes; then
{ { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5
echo "$as_me: error: cannot run test program while cross compiling" >&2;}
{ (exit 1); exit 1; }; }
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
#include "confdefs.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
int test_vsnprintf(const char *fmt,...)
{
va_list ap;
char *s = malloc(16);
int ret;
va_start(ap, fmt);
ret=vsnprintf(s,16,"%s",ap);
va_end(ap);
return(ret==15 ? 1 : 0);
}
int main(void)
{
exit(test_vsnprintf("%s","A string that is longer than 16 characters"));
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && { ac_try='./conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
hdf5_cv_vsnprintf_works=yes
else
echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
( exit $ac_status )
hdf5_cv_vsnprintf_works=no
fi
rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
if test ${hdf5_cv_vsnprintf_works} = "yes"; then
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
cat >>confdefs.h <<\_ACEOF
#define VSNPRINTF_WORKS 1
_ACEOF
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi
fi
done
echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
if test "${ac_cv_prog_cc_stdc+set}" = set; then

View File

@ -1644,7 +1644,51 @@ dnl Check for functions.
dnl
AC_CHECK_FUNCS(fork frexpf frexpl gethostname getpwuid getrusage)
AC_CHECK_FUNCS(BSDgettimeofday longjmp setsysinfo sigaction)
AC_CHECK_FUNCS(signal snprintf vsnprintf strdup system waitpid)
AC_CHECK_FUNCS(signal snprintf vasprintf strdup system waitpid)
dnl Check for vsnprintf() separately, so we can detect situations where it
dnl doesn't return the correct size for formatted strings that are too large
dnl for the buffer provided
AC_CHECK_FUNCS(vsnprintf,
dnl Check if vsnprintf() returns correct size for strings that don't fit
dnl into the size allowed. If vsnprintf() works correctly on this platform,
dnl it should return a value larger than 15 for the test below
AC_MSG_CHECKING([if vsnprintf returns correct value])
AC_CACHE_VAL([hdf5_cv_vsnprintf_works],
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
int test_vsnprintf(const char *fmt,...)
{
va_list ap;
char *s = malloc(16);
int ret;
va_start(ap, fmt);
ret=vsnprintf(s,16,"%s",ap);
va_end(ap);
return(ret==15 ? 1 : 0);
}
int main(void)
{
exit(test_vsnprintf("%s","A string that is longer than 16 characters"));
}
],[hdf5_cv_vsnprintf_works=yes],[hdf5_cv_vsnprintf_works=no],))
if test ${hdf5_cv_vsnprintf_works} = "yes"; then
AC_MSG_RESULT([yes])
AC_DEFINE([VSNPRINTF_WORKS], [1],
[Define if vsnprintf() returns the correct value for formatted strings that don't fit into size allowed])
else
AC_MSG_RESULT([no])
fi
,)
dnl ----------------------------------------------------------------------
dnl Check compiler characteristics

View File

@ -1513,13 +1513,24 @@ H5Epush_stack(hid_t err_stack, const char *file, const char *func, unsigned line
/* Format the description */
va_start(ap, fmt);
#ifdef H5_HAVE_VASPRINTF
/* Use the vasprintf() routine, since it does what we're trying to do below */
if(HDvasprintf(&tmp,fmt,ap)<0)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
#else /* H5_HAVE_VASPRINTF */
/* Allocate space for the formatted description buffer */
tmp_len=128;
if((tmp=H5MM_malloc((size_t)tmp_len))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* If the description doesn't fit into the initial buffer size, allocate more space and try again */
while((desc_len=HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap))>tmp_len) {
while((desc_len=HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap))
#ifdef H5_VSNPRINTF_WORKS
>
#else /* H5_VSNPRINTF_WORKS */
>=
#endif /* H5_VSNPRINTF_WORKS */
(tmp_len-1)) {
/* shutdown & restart the va_list */
va_end(ap);
va_start(ap, fmt);
@ -1528,10 +1539,15 @@ H5Epush_stack(hid_t err_stack, const char *file, const char *func, unsigned line
H5MM_xfree(tmp);
/* Allocate a description of the appropriate length */
#ifdef H5_VSNPRINTF_WORKS
tmp_len = desc_len+1;
#else /* H5_VSNPRINTF_WORKS */
tmp_len = 2 * desc_len;
#endif /* H5_VSNPRINTF_WORKS */
if((tmp=H5MM_malloc((size_t)tmp_len))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
} /* end while */
#endif /* H5_HAVE_VASPRINTF */
va_end(ap);

View File

@ -366,6 +366,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
@ -553,6 +556,10 @@
correct precision. */
#undef ULLONG_TO_LDOUBLE_PRECISION_WORKS
/* Define if vsnprintf() returns the correct value for formatted strings that
don't fit into size allowed */
#undef VSNPRINTF_WORKS
/* Define if the HDF5 v1.6 compatibility functions are to be compiled in */
#undef WANT_H5_V1_6_COMPAT

View File

@ -838,6 +838,7 @@ H5_DLL int64_t HDstrtoll (const char *s, const char **rest, int base);
#define HDva_arg(A,T) va_arg(A,T)
#define HDva_end(A) va_end(A)
#define HDva_start(A,P) va_start(A,P)
#define HDvasprintf(RET,FMT,A) vasprintf(RET,FMT,A)
#define HDvfprintf(F,FMT,A) vfprintf(F,FMT,A)
#define HDvprintf(FMT,A) vprintf(FMT,A)
#define HDvsprintf(S,FMT,A) vsprintf(S,FMT,A)