mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-01-18 15:15:56 +08:00
[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:
parent
d363f95d6d
commit
563a8dd140
153
configure
vendored
153
configure
vendored
@ -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
|
||||
|
46
configure.in
46
configure.in
@ -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
|
||||
|
18
src/H5E.c
18
src/H5E.c
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user