diff --git a/.gitignore b/.gitignore index 1d5b8b37de..9d1fd87ebd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ ctest.c ctest64.c nc_test/test_get.c nc_test/test_put.c +nc_test/test_read.c +nc_test/test_write.c ##### # End ignored generated files. diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a61ac597b..555991da94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -984,14 +984,14 @@ IF(ENABLE_PNETCDF) FIND_LIBRARY(PNETCDF NAMES pnetcdf) FIND_PATH(PNETCDF_INCLUDE_DIR pnetcdf.h) IF(NOT PNETCDF) - MESSAGE(STATUS "Cannot find PNetCDF library. Disabling PNetCDF support.") + MESSAGE(STATUS "Cannot find PnetCDF library. Disabling PnetCDF support.") SET(USE_PNETCDF OFF CACHE BOOL "") ELSE(NOT PNETCDF) SET(USE_PARALLEL ON CACHE BOOL "") - # Check PNetCDF version. Must be >= 1.6.0 + # Check PnetCDF version. Must be >= 1.6.0 set(pnetcdf_h "${PNETCDF_INCLUDE_DIR}/pnetcdf.h" ) - message(STATUS "PNetCDF include file ${pnetcdf_h} will be searched for version") + message(STATUS "PnetCDF include file ${pnetcdf_h} will be searched for version") file(STRINGS "${pnetcdf_h}" pnetcdf_major_string REGEX "^#define PNETCDF_VERSION_MAJOR") string(REGEX REPLACE "[^0-9]" "" pnetcdf_major "${pnetcdf_major_string}") file(STRINGS "${pnetcdf_h}" pnetcdf_minor_string REGEX "^#define PNETCDF_VERSION_MINOR") @@ -999,7 +999,7 @@ IF(ENABLE_PNETCDF) file(STRINGS "${pnetcdf_h}" pnetcdf_sub_string REGEX "^#define PNETCDF_VERSION_SUB") string(REGEX REPLACE "[^0-9]" "" pnetcdf_sub "${pnetcdf_sub_string}") set(pnetcdf_version "${pnetcdf_major}.${pnetcdf_minor}.${pnetcdf_sub}") - message(STATUS "Found PNetCDF version ${pnetcdf_version}") + message(STATUS "Found PnetCDF version ${pnetcdf_version}") if(${pnetcdf_version} VERSION_GREATER "1.6.0") SET(STATUS_PNETCDF "ON") @@ -1008,13 +1008,66 @@ IF(ENABLE_PNETCDF) # pnetcdf => parallel SET(STATUS_PARALLEL ON) SET(USE_PARALLEL ON) - MESSAGE(STATUS "Using PNetCDF Library: ${PNETCDF}") + MESSAGE(STATUS "Using PnetCDF Library: ${PNETCDF}") ELSE() - MESSAGE(WARNING "ENABLE_PNETCDF requires version 1.6.1 or later; found version ${pnetcdf_version}. PNetCDF is disabled") + MESSAGE(WARNING "ENABLE_PNETCDF requires version 1.6.1 or later; found version ${pnetcdf_version}. PnetCDF is disabled") ENDIF() ENDIF(NOT PNETCDF) ENDIF() +# Options to enable use of fill values for elements casuing NC_ERANGE +SET(STATUS_ERANGE_FILL "ON") +OPTION(ENABLE_ERANGE_FILL "Enable use of fill value when out-of-range type conversion causes NC_ERANGE error." ON) +IF(NOT ENABLE_ERANGE_FILL) + SET(STATUS_ERANGE_FILL "OFF") +ENDIF() + +# Options to use a more relaxed coordinate argument boundary check +SET(STATUS_RELAX_COORD_BOUND "OFF") +OPTION(ENABLE_RELAX_COORD_BOUND "Enable a more relaxed boundary error check NC_EINVALCOORDS to allow coordinate start argument equal to dimension size when argument count is zero." OFF) +IF(ENABLE_RELAX_COORD_BOUND) + SET(STATUS_RELAX_COORD_BOUND "ON") +ENDIF() + +# check and conform with PnetCDF settings on ERANGE_FILL and RELAX_COORD_BOUND +IF(STATUS_PNETCDF) + file(STRINGS "${pnetcdf_h}" enable_erange_fill_pnetcdf REGEX "^#define PNETCDF_ERANGE_FILL") + string(REGEX REPLACE "[^0-9]" "" erange_fill_pnetcdf "${enable_erange_fill_pnetcdf}") + IF("x${erange_fill_pnetcdf}" STREQUAL "x1") + IF(NOT STATUS_ERANGE_FILL) + MESSAGE(WARNING "Enable erange-fill to conform with PnetCDF setting") + SET(STATUS_ERANGE_FILL "ON") + ENDIF() + ELSE() + IF(STATUS_ERANGE_FILL) + MESSAGE(WARNING "Disable erange-fill to conform with PnetCDF setting") + SET(STATUS_ERANGE_FILL "OFF") + ENDIF() + ENDIF() + file(STRINGS "${pnetcdf_h}" relax_coord_bound_pnetcdf REGEX "^#define PNETCDF_RELAX_COORD_BOUND") + string(REGEX REPLACE "[^0-9]" "" relax_coord_bound "${relax_coord_bound_pnetcdf}") + IF("x${relax_coord_bound}" STREQUAL "x1") + IF(NOT STATUS_RELAX_COORD_BOUND) + MESSAGE(WARNING "Enable relax-coord-bound to conform with PnetCDF setting") + SET(STATUS_RELAX_COORD_BOUND "ON") + ENDIF() + ELSE() + IF(STATUS_RELAX_COORD_BOUND) + MESSAGE(WARNING "Disable relax-coord-bound to conform with PnetCDF setting") + SET(STATUS_RELAX_COORD_BOUND "OFF") + ENDIF() + ENDIF() +ENDIF() + +IF(STATUS_ERANGE_FILL) + SET(M4FLAGS "-DERANGE_FILL" CACHE STRING "") +ENDIF() + +IF(STATUS_RELAX_COORD_BOUND) + MESSAGE(STATUS "Enabling a more relatexed check for NC_EINVALCOORDS") + ADD_DEFINITIONS(-DRELAX_COORD_BOUND) +ENDIF() + # Enable Parallel Tests. OPTION(ENABLE_PARALLEL_TESTS "Enable Parallel IO Tests. Ignored if netCDF4 is not enabled, or if there is no parallel I/O Support." ${USE_PARALLEL}) IF(ENABLE_PARALLEL_TESTS AND USE_PARALLEL) @@ -1242,9 +1295,13 @@ ENDIF(SIZEOF_PTRDIFF_T) # __int64 is used on Windows for large file support. CHECK_TYPE_SIZE("__int64" SIZEOF___INT_64) -CHECK_TYPE_SIZE("uchar" SIZEOF_UCHAR) CHECK_TYPE_SIZE("int64_t" SIZEOF_INT64_T) CHECK_TYPE_SIZE("uint64_t" SIZEOF_UINT64_T) +CHECK_TYPE_SIZE("unsigned char" SIZEOF_UCHAR) +CHECK_TYPE_SIZE("unsigned short int" SIZEOF_USHORT) +CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT) +CHECK_TYPE_SIZE("long long" SIZEOF_LONGLONG) +CHECK_TYPE_SIZE("unsigned long long" SIZEOF_ULONGLONG) # On windows systems, we redefine off_t as __int64 # to enable LFS. This is true on 32 and 64 bit system.s @@ -1338,7 +1395,7 @@ IF(HAVE_M4) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${filename}.c COMMAND ${NC_M4} - ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${filename}.m4 > ${CMAKE_CURRENT_SOURCE_DIR}/${filename}.c + ARGS ${M4FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/${filename}.m4 > ${CMAKE_CURRENT_SOURCE_DIR}/${filename}.c VERBATIM ) ENDIF(HAVE_M4) @@ -1806,6 +1863,7 @@ is_enabled(USE_DAP HAS_DAP) is_enabled(USE_DISKLESS HAS_DISKLESS) is_enabled(USE_MMAP HAS_MMAP) is_enabled(JNA HAS_JNA) +is_enabled(STATUS_RELAX_COORD_BOUND RELAX_COORD_BOUND) # Generate file from template. CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/libnetcdf.settings.in" diff --git a/Makefile.am b/Makefile.am index c1e9613257..8a18e9b43b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -128,6 +128,7 @@ settings_DATA=libnetcdf.settings #### MM4= ./nc_test/test_put ./nc_test/test_get \ + ./nc_test/test_write ./nc_test/test_read \ ./libsrc/netcdf ./libsrc/putget ./libsrc/ncx \ ./libsrc/t_ncxx ./libsrc/attr diff --git a/acinclude.m4 b/acinclude.m4 index b88246a154..2040f45d2c 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -749,3 +749,25 @@ esac ])# AX_C_FLOAT_WORDS_BIGENDIAN +dnl Find the full path of a header file +dnl +dnl UD_CHECK_HEADER_PATH(file, [action-if-found], [action-if-not-found]) +dnl Example: +dnl UD_CHECK_HEADER_PATH([math.h]) +dnl AC_MSG_NOTICE([ac_cv_header_path_math_h=$ac_cv_header_path_math_h]) +dnl +dnl +AC_DEFUN([UD_CHECK_HEADER_PATH], +[ + AS_VAR_PUSHDEF([ac_Path], [ac_cv_header_path_$1])dnl + AC_CACHE_CHECK( + [for full path of header file $1], [ac_Path], + [AC_PREPROC_IFELSE( + [AC_LANG_PROGRAM([[#include <$1>]])], + [AS_VAR_SET([ac_Path], [`sed -n '/\.h"/s/.*"\(.*\)".*/\1/p' conftest.i | grep -m 1 $1`])], + [AC_MSG_RESULT([not found])] + )]) + AS_VAR_SET_IF([ac_Path], [$2], [$3]) + AS_VAR_POPDEF([ac_Path])dnl +]) + diff --git a/configure.ac b/configure.ac index 875c9f5eb5..338c4ab018 100644 --- a/configure.ac +++ b/configure.ac @@ -858,6 +858,13 @@ AC_CHECK_SIZEOF(size_t) $SLEEPCMD AC_CHECK_SIZEOF(unsigned long long) +$SLEEPCMD +if test "$ac_cv_type_uchar" = yes ; then + AC_CHECK_SIZEOF(uchar) +else + AC_CHECK_SIZEOF(unsigned char) +fi + $SLEEPCMD if test "$ac_cv_type_ushort" = yes ; then AC_CHECK_SIZEOF(ushort) @@ -1079,6 +1086,83 @@ if test "x$enable_parallel" = xyes; then AC_DEFINE([USE_PARALLEL], [1], [if true, pnetcdf or parallel netcdf-4 is in use]) fi +AC_ARG_ENABLE([erange_fill], + [AS_HELP_STRING([--disable-erange-fill], + [Disable use of fill value when out-of-range type + conversion causes NC_ERANGE error. @<:@default: enabled@:>@])], + [enable_erange_fill=${enableval}], [enable_erange_fill=yes] +) + +AC_ARG_ENABLE([relax-coord-bound], + [AS_HELP_STRING([--enable-relax-coord-bound], + [Enable a more relaxed boundary error check NC_EINVALCOORDS + to allow coordinate start argument equal to dimension size + when argument count is zero. @<:@default: disabled@:>@])], + [enable_relax_coord_bound=${enableval}], [enable_relax_coord_bound=no] +) + +# check PnetCDF's settings on enable_erange_fill and relax_coord_bound +if test "x$enable_pnetcdf" = xyes; then + UD_CHECK_HEADER_PATH([pnetcdf.h]) + + AC_MSG_CHECKING([if erange-fill is enabled in PnetCDF]) + erange_fill_pnetcdf=`grep PNETCDF_ERANGE_FILL ${ac_cv_header_path_pnetcdf_h}` + if test "x$erange_fill_pnetcdf" = x; then + erange_fill_pnetcdf=no + else + erange_fill_pnetcdf=`echo ${erange_fill_pnetcdf} | cut -d' ' -f3` + if test "x$coord_bound_pnetcdf" = x0; then + enable_erange_fill_pnetcdf=no + else + enable_erange_fill_pnetcdf=yes + fi + fi + AC_MSG_NOTICE([$enable_erange_fill_pnetcdf]) + if test "$enable_erange_fill" != "$enable_erange_fill_pnetcdf"; then + if test "$enable_erange_fill_pnetcdf" = yes; then + AC_MSG_WARN([Enable erange-fill to conform with PnetCDF setting]) + else + AC_MSG_WARN([Disable erange-fill to conform with PnetCDF setting]) + fi + enable_erange_fill=$enable_erange_fill_pnetcdf + fi + + AC_MSG_CHECKING([if relax-coord-bound is enabled in PnetCDF]) + relax_coord_bound_pnetcdf=`grep PNETCDF_RELAX_COORD_BOUND ${ac_cv_header_path_pnetcdf_h}` + if test "x$relax_coord_bound_pnetcdf" = x; then + relax_coord_bound_pnetcdf=no + else + coord_bound_pnetcdf=`echo ${relax_coord_bound_pnetcdf} | cut -d' ' -f3` + if test "x$coord_bound_pnetcdf" = x0; then + relax_coord_bound_pnetcdf=no + else + relax_coord_bound_pnetcdf=yes + fi + fi + AC_MSG_NOTICE([$relax_coord_bound_pnetcdf]) + if test "$enable_relax_coord_bound" != "$relax_coord_bound_pnetcdf"; then + if test "$relax_coord_bound_pnetcdf" = yes; then + AC_MSG_WARN([Enable relax-coord-bound to conform with PnetCDF setting]) + else + AC_MSG_WARN([Disable relax-coord-bound to conform with PnetCDF setting]) + fi + enable_relax_coord_bound=$relax_coord_bound_pnetcdf + fi +fi + +if test "x$enable_erange_fill" = xyes ; then + if test "x$M4FLAGS" = x ; then + M4FLAGS="-DERANGE_FILL" + else + M4FLAGS="$M4FLAGS -DERANGE_FILL" + fi +fi +AC_SUBST(M4FLAGS) + +if test "x$enable_relax_coord_bound" = xyes; then + AC_DEFINE([RELAX_COORD_BOUND], [1], [if true, NC_EINVALCOORDS check is more relaxed]) +fi + # Check for downloading/building fortran via postinstall script. if test "x$enable_remote_fortran_bootstrap" = xyes; then AC_DEFINE([BUILD_FORTRAN], 1, [If true, will attempt to download and build netcdf-fortran.]) @@ -1246,6 +1330,7 @@ AC_SUBST(HAS_PARALLEL4,[$enable_parallel4]) AC_SUBST(HAS_DISKLESS,[$enable_diskless]) AC_SUBST(HAS_MMAP,[$enable_mmap]) AC_SUBST(HAS_JNA,[$enable_jna]) +AC_SUBST(RELAX_COORD_BOUND,[$enable_relax_coord_bound]) # Include some specifics for netcdf on windows. #AH_VERBATIM([_WIN32_STRICMP], diff --git a/include/nc.h b/include/nc.h index aa597c9c36..2275c0e867 100644 --- a/include/nc.h +++ b/include/nc.h @@ -38,11 +38,7 @@ typedef struct NC { typedef struct { /* all xdr'd */ size_t nchars; -#ifdef __arm__ - signed char *cp; -#else char *cp; -#endif } NC_string; @@ -55,17 +51,10 @@ free_NC_string(NC_string *ncstrp); extern int NC_check_name(const char *name); -#ifdef __arm__ -extern NC_string * -new_NC_string(size_t slen, const signed char *str); -extern int -set_NC_string(NC_string *ncstrp, const signed char *str); -#else extern NC_string * new_NC_string(size_t slen, const char *str); extern int set_NC_string(NC_string *ncstrp, const char *str); -#endif /* End defined in string.c */ diff --git a/include/nc3internal.h b/include/nc3internal.h index a9b2d8124f..c98098e34c 100644 --- a/include/nc3internal.h +++ b/include/nc3internal.h @@ -389,6 +389,12 @@ NC_sync(NC3_INFO* ncp); extern int NC_calcsize(const NC3_INFO* ncp, off_t *filesizep); +extern int +NC3_inq_default_fill_value(int xtype, void *fillp); + +extern int +NC3_inq_var_fill(const NC_var *varp, void *fill_value); + /* End defined in nc.c */ /* Begin defined in v1hpg.c */ diff --git a/libdispatch/dstring.c b/libdispatch/dstring.c index 37aa67825b..1f407e9183 100644 --- a/libdispatch/dstring.c +++ b/libdispatch/dstring.c @@ -228,13 +228,8 @@ NC_check_name(const char *name) NC_new_string(count, str) */ -#ifdef __arm__ -NC_string * -new_NC_string(size_t slen, const signed char *str) -#else NC_string * new_NC_string(size_t slen, const char *str) -#endif { NC_string *ncstrp; size_t sz = M_RNDUP(sizeof(NC_string)) + slen + 1; @@ -269,13 +264,8 @@ new_NC_string(size_t slen, const char *str) NC_re_string() */ -#ifdef __arm__ - int - set_NC_string(NC_string *ncstrp, const signed char *str) -#else int set_NC_string(NC_string *ncstrp, const char *str) -#endif { size_t slen; diff --git a/libdispatch/dvarget.c b/libdispatch/dvarget.c index 6db41494a9..30291d7b29 100644 --- a/libdispatch/dvarget.c +++ b/libdispatch/dvarget.c @@ -143,6 +143,7 @@ NCDEFAULT_get_vars(int ncid, int varid, const size_t * start, NC* ncp; int memtypelen; size_t vartypelen; + size_t nels; char* value = (char*)value0; size_t numrecs; size_t varshape[NC_MAX_VAR_DIMS]; @@ -200,9 +201,18 @@ NCDEFAULT_get_vars(int ncid, int varid, const size_t * start, /* Do various checks and fixups on start/edges/stride */ simplestride = 1; /* assume so */ + nels = 1; for(i=0;i dimlen) return NC_EINVALCOORDS; +#else + if (mystart[i] >= dimlen) return NC_EINVALCOORDS; +#endif if(edges == NULL) { if(i == 0 && isrecvar) myedges[i] = numrecs - start[i]; @@ -210,23 +220,23 @@ NCDEFAULT_get_vars(int ncid, int varid, const size_t * start, myedges[i] = varshape[i] - mystart[i]; } else myedges[i] = edges[i]; - if(myedges[i] == 0) - return NC_NOERR; /* cannot read anything */ +#ifdef RELAX_COORD_BOUND + if (mystart[i] == dimlen && myedges[i] > 0) return NC_EINVALCOORDS; +#endif + /* myedges is unsigned, never < 0 */ + if(mystart[i] + myedges[i] > dimlen) + return NC_EEDGE; mystride[i] = (stride == NULL ? 1 : stride[i]); if(mystride[i] <= 0 /* cast needed for braindead systems with signed size_t */ || ((unsigned long) mystride[i] >= X_INT_MAX)) return NC_ESTRIDE; if(mystride[i] != 1) simplestride = 0; - /* illegal value checks */ - dimlen = (i == 0 && isrecvar ? numrecs : varshape[i]); - /* mystart is unsigned, never < 0 */ - if(mystart[i] >= dimlen) - return NC_EINVALCOORDS; - /* myedges is unsigned, never < 0 */ - if(mystart[i] + myedges[i] > dimlen) - return NC_EEDGE; + if(myedges[i] == 0) + nels = 0; } + if(nels == 0) + return NC_NOERR; /* cannot read anything */ if(simplestride) { return NC_get_vara(ncid, varid, mystart, myedges, value, memtype); } @@ -376,17 +386,26 @@ NCDEFAULT_get_varm(int ncid, int varid, const size_t *start, mymap = mystride + varndims; /* - * Initialize I/O parameters. + * Check start, edges */ for (idim = maxidim; idim >= 0; --idim) { + size_t dimlen = + idim == 0 && isrecvar + ? numrecs + : varshape[idim]; + mystart[idim] = start != NULL ? start[idim] : 0; - if (edges != NULL && edges[idim] == 0) +#ifdef RELAX_COORD_BOUND + if (mystart[idim] > dimlen) +#else + if (mystart[idim] >= dimlen) +#endif { - status = NC_NOERR; /* read/write no data */ + status = NC_EINVALCOORDS; goto done; } @@ -405,6 +424,33 @@ NCDEFAULT_get_varm(int ncid, int varid, const size_t *start, myedges[idim] = varshape[idim] - mystart[idim]; #endif +#ifdef RELAX_COORD_BOUND + if (mystart[idim] == dimlen && myedges[idim] > 0) + { + status = NC_EINVALCOORDS; + goto done; + } +#endif + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + } + + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + if (edges != NULL && edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + mystride[idim] = stride != NULL ? stride[idim] : 1; @@ -430,30 +476,6 @@ NCDEFAULT_get_varm(int ncid, int varid, const size_t *start, stop[idim] = (mystart[idim] + myedges[idim] * (size_t)mystride[idim]); } - /* - * Check start, edges - */ - for (idim = maxidim; idim >= 0; --idim) - { - size_t dimlen = - idim == 0 && isrecvar - ? numrecs - : varshape[idim]; - if (mystart[idim] >= dimlen) - { - status = NC_EINVALCOORDS; - goto done; - } - - if (mystart[idim] + myedges[idim] > dimlen) - { - status = NC_EEDGE; - goto done; - } - - } - - /* Lower body */ /* * As an optimization, adjust I/O parameters when the fastest diff --git a/libdispatch/dvarput.c b/libdispatch/dvarput.c index 59e071bc76..27b3ea9f2e 100644 --- a/libdispatch/dvarput.c +++ b/libdispatch/dvarput.c @@ -128,6 +128,7 @@ NCDEFAULT_put_vars(int ncid, int varid, const size_t * start, nc_type vartype = NC_NAT; NC* ncp; size_t vartypelen; + size_t nels; int memtypelen; const char* value = (const char*)value0; size_t numrecs; @@ -193,9 +194,26 @@ NCDEFAULT_put_vars(int ncid, int varid, const size_t * start, /* Do various checks and fixups on start/edges/stride */ isstride1 = 1; /* assume so */ + nels = 1; for(i=0;i dimlen) return NC_EINVALCOORDS; +#else + if (mystart[i] >= dimlen) return NC_EINVALCOORDS; +#endif + } if(edges == NULL) { #if 0 if(i == 0 && isrecvar) @@ -208,31 +226,27 @@ NCDEFAULT_put_vars(int ncid, int varid, const size_t * start, myedges[i] = varshape[i] - mystart[i]; } else myedges[i] = edges[i]; - if(myedges[i] == 0) - return NC_NOERR; /* cannot write anything */ +#ifdef RELAX_COORD_BOUND + if(!is_recdim[i]) { + if (mystart[i] == dimlen && myedges[i] > 0) + return NC_EINVALCOORDS; + } +#endif + if(!is_recdim[i]) { + /* myediges is unsigned, will never be < 0 */ + if(mystart[i] + myedges[i] > dimlen) + return NC_EEDGE; + } mystride[i] = (stride == NULL ? 1 : stride[i]); if(mystride[i] <= 0 /* cast needed for braindead systems with signed size_t */ || ((unsigned long) mystride[i] >= X_INT_MAX)) return NC_ESTRIDE; if(mystride[i] != 1) isstride1 = 0; - /* illegal value checks */ -#if 0 - dimlen = (i == 0 && isrecvar ? numrecs : varshape[i]); - if(i == 0 && isrecvar) {/*do nothing*/} -#else - dimlen = varshape[i]; - if(is_recdim[i]) {/*do nothing*/} -#endif - else { - /* mystart is unsigned, will never be < 0 */ - if(mystart[i] > dimlen) - return NC_EINVALCOORDS; - /* myediges is unsigned, will never be < 0 */ - if(mystart[i] + myedges[i] > dimlen) - return NC_EEDGE; - } + nels *= myedges[i]; } + if(nels == 0) + return NC_NOERR; /* cannot write anything */ if(isstride1) { return NC_put_vara(ncid, varid, mystart, myedges, value, memtype); } @@ -384,7 +398,7 @@ NCDEFAULT_put_varm( mymap = mystride + varndims; /* - * Initialize I/O parameters. + * Check start, edges */ for (idim = maxidim; idim >= 0; --idim) { @@ -392,17 +406,44 @@ NCDEFAULT_put_varm( ? start[idim] : 0; + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && isrecvar + ? numrecs - mystart[idim] + : varshape[idim] - mystart[idim]; + } + + for (idim = isrecvar; idim <= maxidim; ++idim) + { +#ifdef RELAX_COORD_BOUND + if (mystart[idim] > varshape[idim] || + (mystart[idim] == varshape[idim] && myedges[idim] > 0)) +#else + if (mystart[idim] >= varshape[idim]) +#endif + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > varshape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { if (edges != NULL && edges[idim] == 0) { status = NC_NOERR; /* read/write no data */ goto done; } - myedges[idim] = edges != NULL - ? edges[idim] - : idim == 0 && isrecvar - ? numrecs - mystart[idim] - : varshape[idim] - mystart[idim]; mystride[idim] = stride != NULL ? stride[idim] : 1; @@ -417,23 +458,6 @@ NCDEFAULT_put_varm( stop[idim] = mystart[idim] + myedges[idim] * (size_t)mystride[idim]; } - /* - * Check start, edges - */ - for (idim = isrecvar; idim < maxidim; ++idim) - { - if (mystart[idim] > varshape[idim]) - { - status = NC_EINVALCOORDS; - goto done; - } - if (mystart[idim] + myedges[idim] > varshape[idim]) - { - status = NC_EEDGE; - goto done; - } - } - /* Lower body */ /* * As an optimization, adjust I/O parameters when the fastest diff --git a/libnetcdf.settings.in b/libnetcdf.settings.in index 5d7f5e0a87..af534d859f 100644 --- a/libnetcdf.settings.in +++ b/libnetcdf.settings.in @@ -28,7 +28,7 @@ NetCDF-2 API: @HAS_NC2@ HDF4 Support: @HAS_HDF4@ NetCDF-4 API: @HAS_NC4@ NC-4 Parallel Support: @HAS_PARALLEL4@ -PNetCDF Support: @HAS_PNETCDF@ +PnetCDF Support: @HAS_PNETCDF@ DAP Support: @HAS_DAP@ Diskless Support: @HAS_DISKLESS@ MMap Support: @HAS_MMAP@ diff --git a/libsrc/attr.m4 b/libsrc/attr.m4 index 3d6c0d6e78..18d05e1403 100644 --- a/libsrc/attr.m4 +++ b/libsrc/attr.m4 @@ -398,6 +398,9 @@ NC_lookupattr(int ncid, if(ncap == NULL) return NC_ENOTVAR; + if(name == NULL) + return NC_EBADNAME; + tmp = NC_findattr(ncap, name); if(tmp == NULL) return NC_ENOTATT; @@ -634,31 +637,31 @@ dnl define(`XNCX_PAD_PUTN',dnl `dnl static int -ncx_pad_putn_I$1(void **xpp, size_t nelems, const $1 *tp, nc_type type) +ncx_pad_putn_I$1(void **xpp, size_t nelems, const $1 *tp, nc_type type, void *fillp) { switch(type) { case NC_CHAR: return NC_ECHAR; case NC_BYTE: - return ncx_pad_putn_schar_$1(xpp, nelems, tp); + return ncx_pad_putn_schar_$1(xpp, nelems, tp, fillp); case NC_SHORT: - return ncx_pad_putn_short_$1(xpp, nelems, tp); + return ncx_pad_putn_short_$1(xpp, nelems, tp, fillp); case NC_INT: - return ncx_putn_int_$1(xpp, nelems, tp); + return ncx_putn_int_$1(xpp, nelems, tp, fillp); case NC_FLOAT: - return ncx_putn_float_$1(xpp, nelems, tp); + return ncx_putn_float_$1(xpp, nelems, tp, fillp); case NC_DOUBLE: - return ncx_putn_double_$1(xpp, nelems, tp); + return ncx_putn_double_$1(xpp, nelems, tp, fillp); case NC_UBYTE: - return ncx_pad_putn_uchar_$1(xpp, nelems, tp); + return ncx_pad_putn_uchar_$1(xpp, nelems, tp, fillp); case NC_USHORT: - return ncx_putn_ushort_$1(xpp, nelems, tp); + return ncx_putn_ushort_$1(xpp, nelems, tp, fillp); case NC_UINT: - return ncx_putn_uint_$1(xpp, nelems, tp); + return ncx_putn_uint_$1(xpp, nelems, tp, fillp); case NC_INT64: - return ncx_putn_longlong_$1(xpp, nelems, tp); + return ncx_putn_longlong_$1(xpp, nelems, tp, fillp); case NC_UINT64: - return ncx_putn_ulonglong_$1(xpp, nelems, tp); + return ncx_putn_ulonglong_$1(xpp, nelems, tp, fillp); default: assert("ncx_pad_putn_I$1 invalid type" == 0); } @@ -743,31 +746,31 @@ XNCX_PAD_GETN(ulonglong) /* Common dispatcher for put cases */ static int dispatchput(void **xpp, size_t nelems, const void* tp, - nc_type atype, nc_type memtype) + nc_type atype, nc_type memtype, void *fillp) { switch (memtype) { case NC_CHAR: return ncx_pad_putn_text(xpp,nelems, (char *)tp); case NC_BYTE: - return ncx_pad_putn_Ischar(xpp, nelems, (schar*)tp, atype); + return ncx_pad_putn_Ischar(xpp, nelems, (schar*)tp, atype, fillp); case NC_SHORT: - return ncx_pad_putn_Ishort(xpp, nelems, (short*)tp, atype); + return ncx_pad_putn_Ishort(xpp, nelems, (short*)tp, atype, fillp); case NC_INT: - return ncx_pad_putn_Iint(xpp, nelems, (int*)tp, atype); + return ncx_pad_putn_Iint(xpp, nelems, (int*)tp, atype, fillp); case NC_FLOAT: - return ncx_pad_putn_Ifloat(xpp, nelems, (float*)tp, atype); + return ncx_pad_putn_Ifloat(xpp, nelems, (float*)tp, atype, fillp); case NC_DOUBLE: - return ncx_pad_putn_Idouble(xpp, nelems, (double*)tp, atype); + return ncx_pad_putn_Idouble(xpp, nelems, (double*)tp, atype, fillp); case NC_UBYTE: /*Synthetic*/ - return ncx_pad_putn_Iuchar(xpp,nelems, (uchar *)tp, atype); + return ncx_pad_putn_Iuchar(xpp,nelems, (uchar *)tp, atype, fillp); case NC_INT64: - return ncx_pad_putn_Ilonglong(xpp, nelems, (longlong*)tp, atype); + return ncx_pad_putn_Ilonglong(xpp, nelems, (longlong*)tp, atype, fillp); case NC_USHORT: - return ncx_pad_putn_Iushort(xpp, nelems, (ushort*)tp, atype); + return ncx_pad_putn_Iushort(xpp, nelems, (ushort*)tp, atype, fillp); case NC_UINT: - return ncx_pad_putn_Iuint(xpp, nelems, (uint*)tp, atype); + return ncx_pad_putn_Iuint(xpp, nelems, (uint*)tp, atype, fillp); case NC_UINT64: - return ncx_pad_putn_Iulonglong(xpp, nelems, (ulonglong*)tp, atype); + return ncx_pad_putn_Iulonglong(xpp, nelems, (ulonglong*)tp, atype, fillp); case NC_NAT: return NC_EBADTYPE; default: @@ -793,6 +796,7 @@ NC3_put_att( NC_attr **attrpp; NC_attr *old = NULL; NC_attr *attrp; + unsigned char fill[8]; /* fill value in internal representation */ status = NC_check_id(ncid, &nc); if(status != NC_NOERR) @@ -806,6 +810,10 @@ NC3_put_att( if(ncap == NULL) return NC_ENOTVAR; + if (name == NULL) + return NC_EBADNAME; + + /* check NC_EBADTYPE */ status = nc3_cktype(nc->mode, type); if(status != NC_NOERR) return status; @@ -828,6 +836,9 @@ NC3_put_att( /* 4 cases: exists X indef */ + status = NC3_inq_default_fill_value(type, &fill); + if (status != NC_NOERR) return status; + if(attrpp != NULL) { /* name in use */ if(!NC_indef(ncp)) { const size_t xsz = ncx_len_NC_attrV(type, nelems); @@ -842,7 +853,13 @@ NC3_put_att( if(nelems != 0) { void *xp = attrp->xvalue; - status = dispatchput(&xp, nelems, (const void*)value, type, memtype); + /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */ + if (!fIsSet(ncp->flags,NC_64BIT_DATA) && type == NC_BYTE && memtype == NC_UBYTE) { + status = NC3_inq_default_fill_value(NC_UBYTE, &fill); + if (status != NC_NOERR) return status; + status = dispatchput(&xp, nelems, value, memtype, memtype, &fill); + } else + status = dispatchput(&xp, nelems, value, type, memtype, &fill); } set_NC_hdirty(ncp); @@ -874,7 +891,13 @@ NC3_put_att( if(nelems != 0) { void *xp = attrp->xvalue; - status = dispatchput(&xp, nelems, (const void*)value, type, memtype); + /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */ + if (!fIsSet(ncp->flags,NC_64BIT_DATA) && type == NC_BYTE && memtype == NC_UBYTE) { + status = NC3_inq_default_fill_value(NC_UBYTE, &fill); + if (status != NC_NOERR) return status; + status = dispatchput(&xp, nelems, value, memtype, memtype, &fill); + } else + status = dispatchput(&xp, nelems, value, type, memtype, &fill); } if(attrpp != NULL) { @@ -904,9 +927,16 @@ NC3_get_att( nc_type memtype) { int status; + NC *nc; + NC3_INFO* ncp; NC_attr *attrp; const void *xp; + status = NC_check_id(ncid, &nc); + if(status != NC_NOERR) + return status; + ncp = NC3_DATA(nc); + status = NC_lookupattr(ncid, varid, name, &attrp); if(status != NC_NOERR) return status; @@ -922,7 +952,7 @@ NC3_get_att( xp = attrp->xvalue; switch (memtype) { case NC_CHAR: - return ncx_pad_getn_text(&xp, attrp->nelems , (char *)value); + return ncx_pad_getn_text(&xp, attrp->nelems, (char *)value); case NC_BYTE: return ncx_pad_getn_Ischar(&xp,attrp->nelems,(schar*)value,attrp->type); case NC_SHORT: @@ -936,14 +966,17 @@ NC3_get_att( case NC_INT64: return ncx_pad_getn_Ilonglong(&xp,attrp->nelems,(longlong*)value,attrp->type); case NC_UBYTE: /* Synthetic */ - return ncx_pad_getn_Iuchar(&xp, attrp->nelems , (uchar *)value, attrp->type); + /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */ + if (!fIsSet(ncp->flags,NC_64BIT_DATA) && attrp->type == NC_BYTE) + return ncx_pad_getn_Iuchar(&xp, attrp->nelems, (uchar *)value, NC_UBYTE); + else + return ncx_pad_getn_Iuchar(&xp, attrp->nelems, (uchar *)value, attrp->type); case NC_USHORT: return ncx_pad_getn_Iushort(&xp,attrp->nelems,(ushort*)value,attrp->type); case NC_UINT: return ncx_pad_getn_Iuint(&xp,attrp->nelems,(uint*)value,attrp->type); case NC_UINT64: return ncx_pad_getn_Iulonglong(&xp,attrp->nelems,(ulonglong*)value,attrp->type); - case NC_NAT: return NC_EBADTYPE; default: @@ -952,3 +985,4 @@ NC3_get_att( status = NC_EBADTYPE; return status; } + diff --git a/libsrc/nc3internal.c b/libsrc/nc3internal.c index 13e83ced41..cb98a94d92 100644 --- a/libsrc/nc3internal.c +++ b/libsrc/nc3internal.c @@ -351,9 +351,9 @@ read_numrecs(NC3_INFO *ncp) return status; if (fIsSet(ncp->flags, NC_64BIT_DATA)) { - long long tmp=0; - status = ncx_get_int64(&xp, &tmp); - new_nrecs = tmp; + unsigned long long tmp=0; + status = ncx_get_uint64(&xp, &tmp); + new_nrecs = (size_t)tmp; } else status = ncx_get_size_t(&xp, &new_nrecs); @@ -394,7 +394,7 @@ write_numrecs(NC3_INFO *ncp) { const size_t nrecs = NC_get_numrecs(ncp); if (fIsSet(ncp->flags, NC_64BIT_DATA)) - status = ncx_put_int64(&xp, nrecs); + status = ncx_put_uint64(&xp, (unsigned long long)nrecs); else status = ncx_put_size_t(&xp, &nrecs); } @@ -1724,3 +1724,95 @@ nc_delete(const char * path) { return nc_delete_mp(path, 0); } + +/*----< NC3_inq_default_fill_value() >---------------------------------------*/ +/* copy the default fill value to the memory space pointed by fillp */ +int +NC3_inq_default_fill_value(int xtype, void *fillp) +{ + if (fillp == NULL) return NC_NOERR; + + switch(xtype) { + case NC_CHAR : *(char*)fillp = NC_FILL_CHAR; break; + case NC_BYTE : *(signed char*)fillp = NC_FILL_BYTE; break; + case NC_SHORT : *(short*)fillp = NC_FILL_SHORT; break; + case NC_INT : *(int*)fillp = NC_FILL_INT; break; + case NC_FLOAT : *(float*)fillp = NC_FILL_FLOAT; break; + case NC_DOUBLE : *(double*)fillp = NC_FILL_DOUBLE; break; + case NC_UBYTE : *(unsigned char*)fillp = NC_FILL_UBYTE; break; + case NC_USHORT : *(unsigned short*)fillp = NC_FILL_USHORT; break; + case NC_UINT : *(unsigned int*)fillp = NC_FILL_UINT; break; + case NC_INT64 : *(long long*)fillp = NC_FILL_INT64; break; + case NC_UINT64 : *(unsigned long long*)fillp = NC_FILL_UINT64; break; + default : return NC_EBADTYPE; + } + return NC_NOERR; +} + + +/*----< NC3_inq_var_fill() >-------------------------------------------------*/ +/* inquire the fill value of a variable */ +int +NC3_inq_var_fill(const NC_var *varp, void *fill_value) +{ + NC_attr **attrpp = NULL; + + if (fill_value == NULL) return NC_EINVAL; + + /* + * find fill value + */ + attrpp = NC_findattr(&varp->attrs, _FillValue); + if ( attrpp != NULL ) { + /* User defined fill value */ + if ( (*attrpp)->type != varp->type || (*attrpp)->nelems != 1 ) + return NC_EBADTYPE; + + const void *xp = (*attrpp)->xvalue; + /* value stored in xvalue is in external representation, may need byte-swap */ + switch(varp->type) { + case NC_CHAR: return ncx_getn_text (&xp, 1, (char*)fill_value); + case NC_BYTE: return ncx_getn_schar_schar (&xp, 1, (signed char*)fill_value); + case NC_UBYTE: return ncx_getn_uchar_uchar (&xp, 1, (unsigned char*)fill_value); + case NC_SHORT: return ncx_getn_short_short (&xp, 1, (short*)fill_value); + case NC_USHORT: return ncx_getn_ushort_ushort (&xp, 1, (unsigned short*)fill_value); + case NC_INT: return ncx_getn_int_int (&xp, 1, (int*)fill_value); + case NC_UINT: return ncx_getn_uint_uint (&xp, 1, (unsigned int*)fill_value); + case NC_FLOAT: return ncx_getn_float_float (&xp, 1, (float*)fill_value); + case NC_DOUBLE: return ncx_getn_double_double (&xp, 1, (double*)fill_value); + case NC_INT64: return ncx_getn_longlong_longlong (&xp, 1, (long long*)fill_value); + case NC_UINT64: return ncx_getn_ulonglong_ulonglong(&xp, 1, (unsigned long long*)fill_value); + default: return NC_EBADTYPE; + } + } + else { + /* use the default */ + switch(varp->type){ + case NC_CHAR: *(char *)fill_value = NC_FILL_CHAR; + break; + case NC_BYTE: *(signed char *)fill_value = NC_FILL_BYTE; + break; + case NC_SHORT: *(short *)fill_value = NC_FILL_SHORT; + break; + case NC_INT: *(int *)fill_value = NC_FILL_INT; + break; + case NC_UBYTE: *(unsigned char *)fill_value = NC_FILL_UBYTE; + break; + case NC_USHORT: *(unsigned short *)fill_value = NC_FILL_USHORT; + break; + case NC_UINT: *(unsigned int *)fill_value = NC_FILL_UINT; + break; + case NC_INT64: *(long long *)fill_value = NC_FILL_INT64; + break; + case NC_UINT64: *(unsigned long long *)fill_value = NC_FILL_UINT64; + break; + case NC_FLOAT: *(float *)fill_value = NC_FILL_FLOAT; + break; + case NC_DOUBLE: *(double *)fill_value = NC_FILL_DOUBLE; + break; + default: + return NC_EINVAL; + } + } + return NC_NOERR; +} diff --git a/libsrc/ncx.h b/libsrc/ncx.h index dc1c89ca50..bf3c1f26c2 100644 --- a/libsrc/ncx.h +++ b/libsrc/ncx.h @@ -231,19 +231,19 @@ extern int ncx_get_schar_double(const void *xp, double *ip); extern int -ncx_put_schar_schar(void *xp, const schar *ip); +ncx_put_schar_schar(void *xp, const schar *ip, void *fillp); extern int -ncx_put_schar_uchar(void *xp, const uchar *ip); +ncx_put_schar_uchar(void *xp, const uchar *ip, void *fillp); extern int -ncx_put_schar_short(void *xp, const short *ip); +ncx_put_schar_short(void *xp, const short *ip, void *fillp); extern int -ncx_put_schar_int(void *xp, const int *ip); +ncx_put_schar_int(void *xp, const int *ip, void *fillp); extern int -ncx_put_schar_long(void *xp, const long *ip); +ncx_put_schar_long(void *xp, const long *ip, void *fillp); extern int -ncx_put_schar_float(void *xp, const float *ip); +ncx_put_schar_float(void *xp, const float *ip, void *fillp); extern int -ncx_put_schar_double(void *xp, const double *ip); +ncx_put_schar_double(void *xp, const double *ip, void *fillp); #endif /* @@ -275,8 +275,17 @@ ncx_put_int32(void **xpp, const int ip); extern int ncx_put_int64(void **xpp, const long long ip); +extern int +ncx_get_uint32(const void **xpp, unsigned int *ip); +extern int +ncx_get_uint64(const void **xpp, unsigned long long *ip); +extern int +ncx_put_uint32(void **xpp, const unsigned int ip); +extern int +ncx_put_uint64(void **xpp, const unsigned long long ip); + extern int ncx_get_int_int(const void *xp, int *ip); -extern int ncx_put_int_int(void *xp, const int *ip); +extern int ncx_put_int_int(void *xp, const int *ip, void *fillp); /* * Aggregate numeric conversion functions. @@ -366,50 +375,50 @@ extern int ncx_pad_getn_schar_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_schar_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_schar_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_schar_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_schar_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_schar_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_schar_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_schar_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_schar_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_schar_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_schar_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_schar_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_schar_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_schar_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_schar_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_schar_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_schar_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_schar_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_schar_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_schar_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_schar_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_schar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_schar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); extern int -ncx_pad_putn_schar_schar (void **xpp, size_t nelems, const schar *ip); +ncx_pad_putn_schar_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_pad_putn_schar_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_pad_putn_schar_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_pad_putn_schar_short (void **xpp, size_t nelems, const short *ip); +ncx_pad_putn_schar_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_pad_putn_schar_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_pad_putn_schar_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_pad_putn_schar_int (void **xpp, size_t nelems, const int *ip); +ncx_pad_putn_schar_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_pad_putn_schar_uint (void **xpp, size_t nelems, const uint *ip); +ncx_pad_putn_schar_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_pad_putn_schar_long (void **xpp, size_t nelems, const long *ip); +ncx_pad_putn_schar_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_pad_putn_schar_float (void **xpp, size_t nelems, const float *ip); +ncx_pad_putn_schar_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *ip); +ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_pad_putn_schar_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_pad_putn_schar_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_pad_putn_schar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_pad_putn_schar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- uchar ----------------------------------------------------------------*/ extern int @@ -459,50 +468,50 @@ extern int ncx_pad_getn_uchar_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_uchar_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_uchar_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_uchar_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_uchar_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_uchar_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_uchar_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_uchar_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_uchar_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_uchar_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_uchar_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_uchar_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_uchar_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_uchar_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_uchar_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_uchar_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_uchar_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_uchar_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_uchar_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_uchar_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_uchar_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_uchar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_uchar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); extern int -ncx_pad_putn_uchar_schar (void **xpp, size_t nelems, const schar *ip); +ncx_pad_putn_uchar_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_pad_putn_uchar_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_pad_putn_uchar_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_pad_putn_uchar_short (void **xpp, size_t nelems, const short *ip); +ncx_pad_putn_uchar_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_pad_putn_uchar_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_pad_putn_uchar_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_pad_putn_uchar_int (void **xpp, size_t nelems, const int *ip); +ncx_pad_putn_uchar_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_pad_putn_uchar_uint (void **xpp, size_t nelems, const uint *ip); +ncx_pad_putn_uchar_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_pad_putn_uchar_long (void **xpp, size_t nelems, const long *ip); +ncx_pad_putn_uchar_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_pad_putn_uchar_float (void **xpp, size_t nelems, const float *ip); +ncx_pad_putn_uchar_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_pad_putn_uchar_double(void **xpp, size_t nelems, const double *ip); +ncx_pad_putn_uchar_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_pad_putn_uchar_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_pad_putn_uchar_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_pad_putn_uchar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_pad_putn_uchar_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- short ----------------------------------------------------------------*/ extern int @@ -552,50 +561,50 @@ extern int ncx_pad_getn_short_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_short_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_short_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_short_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_short_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_short_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_short_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_short_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_short_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_short_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_short_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_short_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_short_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_short_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_short_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_short_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_short_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_short_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_short_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_short_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_short_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_short_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_short_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); extern int -ncx_pad_putn_short_schar (void **xpp, size_t nelems, const schar *ip); +ncx_pad_putn_short_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_pad_putn_short_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_pad_putn_short_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_pad_putn_short_short (void **xpp, size_t nelems, const short *ip); +ncx_pad_putn_short_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_pad_putn_short_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_pad_putn_short_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_pad_putn_short_int (void **xpp, size_t nelems, const int *ip); +ncx_pad_putn_short_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_pad_putn_short_uint (void **xpp, size_t nelems, const uint *ip); +ncx_pad_putn_short_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_pad_putn_short_long (void **xpp, size_t nelems, const long *ip); +ncx_pad_putn_short_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_pad_putn_short_float (void **xpp, size_t nelems, const float *ip); +ncx_pad_putn_short_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *ip); +ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_pad_putn_short_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_pad_putn_short_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_pad_putn_short_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_pad_putn_short_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- ushort ---------------------------------------------------------------*/ extern int @@ -645,50 +654,50 @@ extern int ncx_pad_getn_ushort_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_ushort_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_ushort_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_ushort_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_ushort_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_ushort_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_ushort_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_ushort_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_ushort_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_ushort_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_ushort_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_ushort_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_ushort_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_ushort_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_ushort_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_ushort_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_ushort_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_ushort_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_ushort_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_ushort_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_ushort_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_ushort_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_ushort_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); extern int -ncx_pad_putn_ushort_schar (void **xpp, size_t nelems, const schar *ip); +ncx_pad_putn_ushort_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_pad_putn_ushort_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_pad_putn_ushort_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_pad_putn_ushort_short (void **xpp, size_t nelems, const short *ip); +ncx_pad_putn_ushort_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_pad_putn_ushort_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_pad_putn_ushort_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_pad_putn_ushort_int (void **xpp, size_t nelems, const int *ip); +ncx_pad_putn_ushort_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_pad_putn_ushort_uint (void **xpp, size_t nelems, const uint *ip); +ncx_pad_putn_ushort_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_pad_putn_ushort_long (void **xpp, size_t nelems, const long *ip); +ncx_pad_putn_ushort_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_pad_putn_ushort_float (void **xpp, size_t nelems, const float *ip); +ncx_pad_putn_ushort_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_pad_putn_ushort_double(void **xpp, size_t nelems, const double *ip); +ncx_pad_putn_ushort_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_pad_putn_ushort_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_pad_putn_ushort_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_pad_putn_ushort_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_pad_putn_ushort_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- int ------------------------------------------------------------------*/ extern int @@ -717,29 +726,29 @@ extern int ncx_getn_int_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_int_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_int_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_int_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_int_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_int_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_int_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_int_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_int_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_int_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_int_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_int_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_int_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_int_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_int_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_long_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_long_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_int_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_int_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_int_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_int_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_int_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_int_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_int_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_int_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- uint -----------------------------------------------------------------*/ extern int @@ -768,29 +777,29 @@ extern int ncx_getn_uint_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_uint_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_uint_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_uint_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_uint_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_uint_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_uint_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_uint_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_uint_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_uint_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_uint_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_uint_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_uint_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_uint_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_uint_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_long_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_long_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_uint_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_uint_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_uint_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_uint_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_uint_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_uint_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_uint_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_uint_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- float ----------------------------------------------------------------*/ extern int @@ -817,27 +826,27 @@ extern int ncx_getn_float_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_float_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_float_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_float_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_float_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_float_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_float_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_float_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_float_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_float_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_float_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_float_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_float_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_float_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_float_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_float_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_float_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_float_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_float_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_float_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_float_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_float_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_float_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- double ---------------------------------------------------------------*/ extern int @@ -864,27 +873,27 @@ extern int ncx_getn_double_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_double_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_double_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_double_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_double_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_double_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_double_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_double_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_double_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_double_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_double_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_double_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_double_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_double_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_double_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_double_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_double_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_double_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_double_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_double_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_double_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_double_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_double_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- longlong ----------------------------------------------------------------*/ extern int @@ -911,27 +920,27 @@ extern int ncx_getn_longlong_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_longlong_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_longlong_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_longlong_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_longlong_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_longlong_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_longlong_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_longlong_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_longlong_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_longlong_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_longlong_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_longlong_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_longlong_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_longlong_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_longlong_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_longlong_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_longlong_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_longlong_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_longlong_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_longlong_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_longlong_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_longlong_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_longlong_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /*---- ulonglong ---------------------------------------------------------------*/ extern int @@ -958,27 +967,27 @@ extern int ncx_getn_ulonglong_ulonglong(const void **xpp, size_t nelems, ulonglong *ip); extern int -ncx_putn_ulonglong_schar (void **xpp, size_t nelems, const schar *ip); +ncx_putn_ulonglong_schar (void **xpp, size_t nelems, const schar *ip, void *fillp); extern int -ncx_putn_ulonglong_uchar (void **xpp, size_t nelems, const uchar *ip); +ncx_putn_ulonglong_uchar (void **xpp, size_t nelems, const uchar *ip, void *fillp); extern int -ncx_putn_ulonglong_short (void **xpp, size_t nelems, const short *ip); +ncx_putn_ulonglong_short (void **xpp, size_t nelems, const short *ip, void *fillp); extern int -ncx_putn_ulonglong_ushort(void **xpp, size_t nelems, const ushort *ip); +ncx_putn_ulonglong_ushort(void **xpp, size_t nelems, const ushort *ip, void *fillp); extern int -ncx_putn_ulonglong_int (void **xpp, size_t nelems, const int *ip); +ncx_putn_ulonglong_int (void **xpp, size_t nelems, const int *ip, void *fillp); extern int -ncx_putn_ulonglong_uint (void **xpp, size_t nelems, const uint *ip); +ncx_putn_ulonglong_uint (void **xpp, size_t nelems, const uint *ip, void *fillp); extern int -ncx_putn_ulonglong_long (void **xpp, size_t nelems, const long *ip); +ncx_putn_ulonglong_long (void **xpp, size_t nelems, const long *ip, void *fillp); extern int -ncx_putn_ulonglong_float (void **xpp, size_t nelems, const float *ip); +ncx_putn_ulonglong_float (void **xpp, size_t nelems, const float *ip, void *fillp); extern int -ncx_putn_ulonglong_double(void **xpp, size_t nelems, const double *ip); +ncx_putn_ulonglong_double(void **xpp, size_t nelems, const double *ip, void *fillp); extern int -ncx_putn_ulonglong_longlong (void **xpp, size_t nelems, const longlong *ip); +ncx_putn_ulonglong_longlong (void **xpp, size_t nelems, const longlong *ip, void *fillp); extern int -ncx_putn_ulonglong_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); +ncx_putn_ulonglong_ulonglong(void **xpp, size_t nelems, const ulonglong *ip, void *fillp); /* @@ -986,21 +995,6 @@ ncx_putn_ulonglong_ulonglong(void **xpp, size_t nelems, const ulonglong *ip); */ /* read ASCII characters */ -#ifdef __arm__ - -extern int -ncx_getn_text(const void **xpp, size_t nchars, signed char *cp); -extern int -ncx_pad_getn_text(const void **xpp, size_t nchars, signed char *cp); - -/* write ASCII characters */ -extern int -ncx_putn_text(void **xpp, size_t nchars, const signed char *cp); -extern int -ncx_pad_putn_text(void **xpp, size_t nchars, const signed char *cp); - -#else // ifdef __arm__ - extern int ncx_getn_text(const void **xpp, size_t nchars, char *cp); extern int @@ -1012,7 +1006,6 @@ ncx_putn_text(void **xpp, size_t nchars, const char *cp); extern int ncx_pad_putn_text(void **xpp, size_t nchars, const char *cp); -#endif //ifdef __arm__ /* for symmetry */ #define ncx_getn_char_char(xpp, nelems, fillp) ncx_getn_text(xpp, nelems, fillp) diff --git a/libsrc/ncx.m4 b/libsrc/ncx.m4 index 2abf546e6c..39cfaf8e41 100644 --- a/libsrc/ncx.m4 +++ b/libsrc/ncx.m4 @@ -1,50 +1,124 @@ +dnl Process this m4 file to produce 'C' language file. dnl -dnl sjl: this version of ncx.m4 has SX-specific optimisations as per -dnl Harveys mods to earlier versions. However, I have removed -dnl support for FLOAT2 and attempted to tidy up the mods to -dnl reduce the complexity a bit -dnl -dnl This is m4 source. -dnl Process using m4 to produce 'C' language file. +dnl This file is supposed to be the same as PnetCDF's ncx.m4 dnl dnl If you see this line, you can ignore the next one. /* Do not edit this file. It is produced from the corresponding .m4 source */ dnl /* - * Copyright 1996, University Corporation for Atmospheric Research - * See netcdf/COPYRIGHT file for copying and redistribution conditions. - * - * This file contains some routines derived from code - * which is copyrighted by Sun Microsystems, Inc. - * The "#ifdef vax" versions of - * ncx_put_float_float() - * ncx_get_float_float() - * ncx_put_double_double() - * ncx_get_double_double() - * ncx_putn_float_float() - * ncx_getn_float_float() - * ncx_putn_double_double() - * ncx_getn_double_double() - * are derived from xdr_float() and xdr_double() routines - * in the freely available, copyrighted Sun RPCSRC 3.9 - * distribution, xdr_float.c. - * Our "value added" is that these are always memory to memory, - * they handle IEEE subnormals properly, and their "n" versions - * operate speedily on arrays. + * Copyright (C) 2014, Northwestern University and Argonne National Laboratory + * See COPYRIGHT notice in top-level directory. */ -/* $Id: ncx.m4 2795 2014-10-27 23:12:51Z wkliao $ */ +/* $Id: ncx.m4 2601 2016-11-07 04:54:42Z wkliao $ */ -/* - * An external data representation interface. - */ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +dnl +dnl If the m4 macro "ERANGE_FILL" is defined, the I/O to data elements +dnl that cause NC_ERANGE will be filled with the NC default fill values. +dnl + +define(`SKIP_LOOP', `ifdef(`ERANGE_FILL', `$1++; $2++; continue;')') -#pragma GCC diagnostic ignored "-Wdeprecated" +dnl +dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF +dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types +dnl (MPI_Offset vs. size_t), and function name substrings for external data +dnl types. +dnl + +ifdef(`PNETCDF',` +`#'if HAVE_CONFIG_H +`#'include +`#'endif') -#include "ncx.h" -#include "nc3dispatch.h" +#include +#include #include #include +ifdef(`PNETCDF',` +`#'include "ncx.h" +`#'include "macro.h"',` +`#'pragma GCC diagnostic ignored "-Wdeprecated" +`#'include "ncx.h" +`#'include "nc3dispatch.h"') + +define(`IntType', `ifdef(`PNETCDF', `MPI_Offset', `size_t')')dnl +define(`APIPrefix',`ifdef(`PNETCDF', `ncmpi', `nc')')dnl +define(`NC_TYPE', `ifdef(`PNETCDF', `ifelse( +`$1', `schar', `NC_BYTE',dnl +`$1', `uchar', `NC_UBYTE',dnl +`$1', `short', `NC_SHORT',dnl +`$1', `ushort', `NC_USHORT',dnl +`$1', `int', `NC_INT',dnl +`$1', `uint', `NC_UINT',dnl +`$1', `float', `NC_FLOAT',dnl +`$1', `double', `NC_DOUBLE',dnl +`$1', `int64', `NC_INT64',dnl +`$1', `uint64', `NC_UINT64')',dnl +`ifelse( +`$1', `int64', `longlong',dnl +`$1', `uint64', `ulonglong',dnl +`$1')')')dnl + +ifdef(`PNETCDF',,`define(`DEBUG_RETURN_ERROR',`return $1;')') +ifdef(`PNETCDF',,`define(`DEBUG_ASSIGN_ERROR',`$1 = $2;')') + +#ifdef HAVE_INTTYPES_H +#include /* uint16_t, uint32_t, uint64_t */ +#elif defined(HAVE_STDINT_H) +#include /* uint16_t, uint32_t, uint64_t */ +#endif + +dnl +dnl *fillp is the fill value in internal representation +dnl +define(`FillValue', `ifdef(`ERANGE_FILL', `ifelse( +`$1', `schar', `if (fillp != NULL) memcpy($2, fillp, 1);',dnl +`$1', `uchar', `if (fillp != NULL) memcpy($2, fillp, 1);',dnl +`$1', `short', `if (fillp != NULL) memcpy($2, fillp, 2);',dnl +`$1', `ushort', `if (fillp != NULL) memcpy($2, fillp, 2);',dnl +`$1', `int', `if (fillp != NULL) memcpy($2, fillp, 4);',dnl +`$1', `uint', `if (fillp != NULL) memcpy($2, fillp, 4);',dnl +`$1', `long', `if (fillp != NULL) memcpy($2, fillp, SIZEOF_LONG);', dnl +`$1', `ulong', `if (fillp != NULL) memcpy($2, fillp, SIZEOF_ULONG);',dnl +`$1', `float', `if (fillp != NULL) memcpy($2, fillp, 4);',dnl +`$1', `double', `if (fillp != NULL) memcpy($2, fillp, 8);',dnl +`$1', `longlong', `if (fillp != NULL) memcpy($2, fillp, 8);',dnl +`$1', `int64', `if (fillp != NULL) memcpy($2, fillp, 8);',dnl +`$1', `ulonglong', `if (fillp != NULL) memcpy($2, fillp, 8);',dnl +`$1', `uint64', `if (fillp != NULL) memcpy($2, fillp, 8);')')')dnl + +dnl +dnl +define(`FillDefaultValue', `ifelse( +`$1', `schar', `NC_FILL_BYTE', +`$1', `uchar', `NC_FILL_UBYTE', +`$1', `short', `NC_FILL_SHORT', +`$1', `ushort', `NC_FILL_USHORT', +`$1', `int', `NC_FILL_INT', +`$1', `uint', `NC_FILL_UINT', +`$1', `long', `NC_FILL_INT', +`$1', `ulong', `NC_FILL_UINT', +`$1', `float', `NC_FILL_FLOAT', +`$1', `double', `NC_FILL_DOUBLE', +`$1', `longlong', `NC_FILL_INT64', +`$1', `int64', `NC_FILL_INT64', +`$1', `ulonglong', `NC_FILL_UINT64', +`$1', `uint64', `NC_FILL_UINT64')')dnl + +/* + * The only error code returned from subroutines in this file is NC_ERANGE, + * if errors are detected. + */ + +/* + * An external data representation interface. + */ + /* alias poorly named limits.h macros */ #define SHORT_MAX SHRT_MAX #define SHORT_MIN SHRT_MIN @@ -92,14 +166,66 @@ dnl #define Min(a,b) ((a) < (b) ? (a) : (b)) #define Max(a,b) ((a) > (b) ? (a) : (b)) +#ifndef SIZEOF_UCHAR +#ifdef SIZEOF_UNSIGNED_CHAR +#define SIZEOF_UCHAR SIZEOF_UNSIGNED_CHAR +#else +#error "unknown SIZEOF_UCHAR" +#endif +#endif + #ifndef SIZEOF_USHORT +#ifdef SIZEOF_UNSIGNED_SHORT_INT #define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT_INT +#elif defined(SIZEOF_UNSIGNED_SHORT) +#define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT +#else +#error "unknown SIZEOF_USHORT" +#endif #endif + #ifndef SIZEOF_UINT +#ifdef SIZEOF_UNSIGNED_INT #define SIZEOF_UINT SIZEOF_UNSIGNED_INT +#else +#error "unknown SIZEOF_UINT" +#endif +#endif + +#ifndef SIZEOF_LONGLONG +#ifdef SIZEOF_LONG_LONG +#define SIZEOF_LONGLONG SIZEOF_LONG_LONG +#else +#error "unknown SIZEOF_LONGLONG" +#endif +#endif + +#ifndef SIZEOF_INT64 +#ifdef SIZEOF_LONG_LONG +#define SIZEOF_INT64 SIZEOF_LONG_LONG +#elif defined(SIZEOF_LONGLONG) +#define SIZEOF_INT64 SIZEOF_LONGLONG +#else +#error "unknown SIZEOF_INT64" +#endif +#endif + +#ifndef SIZEOF_ULONGLONG +#ifdef SIZEOF_UNSIGNED_LONG_LONG +#define SIZEOF_ULONGLONG SIZEOF_UNSIGNED_LONG_LONG +#else +#error "unknown SIZEOF_ULONGLONG" +#endif +#endif + +#ifndef SIZEOF_UINT64 +#ifdef SIZEOF_UNSIGNED_LONG_LONG +#define SIZEOF_UINT64 SIZEOF_UNSIGNED_LONG_LONG +#elif defined(SIZEOF_ULONGLONG) +#define SIZEOF_UINT64 SIZEOF_ULONGLONG +#else +#error "unknown SIZEOF_UINT64" #endif -#ifndef SIZEOF_ULONG_LONG -#define SIZEOF_ULONG_LONG SIZEOF_UNSIGNED_LONG_LONG #endif /* @@ -113,7 +239,7 @@ dnl # define X_FLOAT_MIN (-X_FLOAT_MAX) #endif -#if _SX /* NEC SUPER UX */ +#if defined(_SX) && _SX != 0 /* NEC SUPER UX */ #define LOOPCNT 256 /* must be no longer than hardware vector length */ #if _INT64 #undef INT_MAX /* workaround cpp bug */ @@ -140,34 +266,52 @@ static const char nada[X_ALIGN] = {0, 0, 0, 0}; #ifndef WORDS_BIGENDIAN /* LITTLE_ENDIAN: DEC and intel */ /* - * Routines to convert to BIGENDIAN. - * Optimize the swapn?b() and swap?b() routines aggressivly. + * Routines to convert to BIG ENDIAN. + * Optimize the swapn?b() and swap?b() routines aggressively. */ #define SWAP2(a) ( (((a) & 0xff) << 8) | \ - (((a) >> 8) & 0xff) ) + (((a) >> 8) & 0xff) ) #define SWAP4(a) ( ((a) << 24) | \ - (((a) << 8) & 0x00ff0000) | \ - (((a) >> 8) & 0x0000ff00) | \ - (((a) >> 24) & 0x000000ff) ) - - -static void -swapn2b(void *dst, const void *src, size_t nn) -{ + (((a) << 8) & 0x00ff0000) | \ + (((a) >> 8) & 0x0000ff00) | \ + (((a) >> 24) & 0x000000ff) ) + +#define SWAP8(a) ( (((a) & 0x00000000000000FFULL) << 56) | \ + (((a) & 0x000000000000FF00ULL) << 40) | \ + (((a) & 0x0000000000FF0000ULL) << 24) | \ + (((a) & 0x00000000FF000000ULL) << 8) | \ + (((a) & 0x000000FF00000000ULL) >> 8) | \ + (((a) & 0x0000FF0000000000ULL) >> 24) | \ + (((a) & 0x00FF000000000000ULL) >> 40) | \ + (((a) & 0xFF00000000000000ULL) >> 56) ) + + +inline static void +swapn2b(void *dst, const void *src, IntType nn) +{ + /* it is OK if dst == src */ + int i; + uint16_t *op = (uint16_t*) dst; + uint16_t *ip = (uint16_t*) src; + for (i=0; i 0) * { * *op++ = *(++ip); * *op++ = *(ip++ -1); * } */ - while(nn > 3) + while (nn > 3) { *op++ = *(++ip); *op++ = *(ip++ -1); @@ -179,35 +323,90 @@ swapn2b(void *dst, const void *src, size_t nn) *op++ = *(ip++ -1); nn -= 4; } - while(nn-- > 0) + while (nn-- > 0) { *op++ = *(++ip); *op++ = *(ip++ -1); } +#endif } # ifndef vax -void +inline static void swap4b(void *dst, const void *src) { - uint32_t* op32 = (uint32_t*)(dst); + + /* copy over, make the below swap in-place */ + uint32_t tmp = *(uint32_t*)src; + tmp = SWAP4(tmp); + memcpy(dst, &tmp, 4); + + /* Codes below will cause "break strict-aliasing rules" in gcc + uint32_t *op = (uint32_t*)dst; + *op = *(uint32_t*)src; + *op = SWAP4(*op); + */ + + /* Below are copied from netCDF-4. + * See https://bugtracking.unidata.ucar.edu/browse/NCF-338 + * Quote "One issue we are wrestling with is how compilers optimize this + * code. For some reason, we are actually needing to add an artificial + * move to a 4 byte space to get it to work. I think what is happening is + * that the optimizer is bit shifting within a double, which is incorrect. + * The following code actually does work correctly. + * This is in Linux land, gcc. + * + * However, the above in-place byte-swap does not appear affected by this. + */ +#if 0 + uint32_t *ip = (uint32_t*)src; + uint32_t tempOut; /* cannot use pointer when gcc O2 optimizer is used */ + tempOut = SWAP4(*ip); + + *(float *)dst = *(float *)(&tempOut); +#endif + + /* OLD implementation that results in four load and four store CPU + instructions + char *op = dst; + const char *ip = src; + op[0] = ip[3]; + op[1] = ip[2]; + op[2] = ip[1]; + op[3] = ip[0]; + */ + + /* + uint32_t* op32 = (uint32_t*)(dst); const uint32_t* ip32 = (const uint32_t*)(src); *op32 = (((*ip32) ) << 24) | (((*ip32) & 0x0000ff00u) << 8) | (((*ip32) & 0x00ff0000u) >> 8) | (((*ip32) ) >> 24); + +*/ } # endif /* !vax */ -static void -swapn4b(void *dst, const void *src, size_t nn) +inline static void +swapn4b(void *dst, const void *src, IntType nn) { + int i; + uint32_t *op = (uint32_t*) dst; + uint32_t *ip = (uint32_t*) src; + for (i=0; i 0) * { * op[0] = ip[3]; * op[1] = ip[2]; @@ -217,7 +416,7 @@ swapn4b(void *dst, const void *src, size_t nn) * ip += 4; * } */ - while(nn > 3) + while (nn > 3) { op[0] = ip[3]; op[1] = ip[2]; @@ -239,7 +438,7 @@ swapn4b(void *dst, const void *src, size_t nn) ip += 16; nn -= 4; } - while(nn-- > 0) + while (nn-- > 0) { op[0] = ip[3]; op[1] = ip[2]; @@ -248,12 +447,29 @@ swapn4b(void *dst, const void *src, size_t nn) op += 4; ip += 4; } +#endif } # ifndef vax -static void +inline static void swap8b(void *dst, const void *src) { +#ifdef FLOAT_WORDS_BIGENDIAN + /* copy over, make the below swap in-place */ + *(uint64_t*)dst = *(uint64_t*)src; + + uint32_t *op = (uint32_t*)dst; + *op = SWAP4(*op); + op = (uint32_t*)((char*)dst+4); + *op = SWAP4(*op); +#else + uint64_t *op = (uint64_t*)dst; + /* copy over, make the below swap in-place */ + *op = *(uint64_t*)src; + *op = SWAP8(*op); +#endif + +#if 0 char *op = dst; const char *ip = src; # ifndef FLOAT_WORDS_BIGENDIAN @@ -274,19 +490,44 @@ swap8b(void *dst, const void *src) op[5] = ip[6]; op[6] = ip[5]; op[7] = ip[4]; -# endif +#endif +#endif } # endif /* !vax */ # ifndef vax -static void -swapn8b(void *dst, const void *src, size_t nn) -{ +inline static void +swapn8b(void *dst, const void *src, IntType nn) +{ +#ifdef FLOAT_WORDS_BIGENDIAN + int i; + uint64_t *dst_p = (uint64_t*) dst; + uint64_t *src_p = (uint64_t*) src; + for (i=0; i 0) * { * op[0] = ip[7]; * op[1] = ip[6]; @@ -301,7 +542,7 @@ swapn8b(void *dst, const void *src, size_t nn) * } */ # ifndef FLOAT_WORDS_BIGENDIAN - while(nn > 1) + while (nn > 1) { op[0] = ip[7]; op[1] = ip[6]; @@ -323,7 +564,7 @@ swapn8b(void *dst, const void *src, size_t nn) ip += 16; nn -= 2; } - while(nn-- != 0) + while (nn-- > 0) { op[0] = ip[7]; op[1] = ip[6]; @@ -337,7 +578,7 @@ swapn8b(void *dst, const void *src, size_t nn) ip += 8; } # else - while(nn-- != 0) + while (nn-- > 0) { op[0] = ip[3]; op[1] = ip[2]; @@ -350,7 +591,8 @@ swapn8b(void *dst, const void *src, size_t nn) op += 8; ip += 8; } -# endif +#endif +#endif } # endif /* !vax */ @@ -376,57 +618,37 @@ define(`Xmin', ``X_'Upcase($1)`_MIN'')dnl define(`IXmax', ``IX_'Upcase($1)`_MAX'')dnl dnl define(`Fmin', `ifelse(index(`$1',`u'), 0, `0', `(double)Imin($1)')')dnl -define(`Dmin', `ifelse(index(`$1',`u'), 0, `0', `Imin($1)')')dnl +define(`Dmin', `ifelse(index(`$1',`u'), 0, `0', `(double)Imin($1)')')dnl define(`FXmin', `ifelse(index(`$1',`u'), 0, `0', `(double)Xmin($1)')')dnl define(`DXmin', `ifelse(index(`$1',`u'), 0, `0', `Xmin($1)')')dnl -dnl -dnl For GET APIs: -dnl check for negative xx if xp is signed && ip is unsigned -dnl Don't check for negative xx if xp is signed && ip is signed -dnl Don't check for negative xx if xp is unsigned -dnl -define(`GETI_CheckNeg', `ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, ` if (xx < 0) return NC_ERANGE; /* because ip is unsigned */')')')dnl - -dnl -dnl For PUT APIs: -dnl check for negative ip if xp is unsigned && ip is signed -dnl Don't check for negative ip if xp is unsigned && ip is unsigned -dnl Don't check for negative ip if xp is signed -dnl -define(`PUTI_CheckNeg', `ifelse(index(`$1',`u'), 0, `ifelse(index(`$2',`u'), 0, , ` if (*ip < 0) return NC_ERANGE; /* because xp is unsigned */')')')dnl +define(`Cast_Signed2Unsigned', + `ifelse(index(`$1',`u'), 0, + `ifelse(index(`$2',`u'), 0, , `(signed)')')')dnl dnl -dnl For GET APIs and either $1 and $2 is float or double: +dnl For GET APIs boundary check dnl define(`GETF_CheckBND', -`ifelse(`$1', `double', ` if(xx > Upcase($2)_MAX || xx < Dmin($2)) return NC_ERANGE;', - `ifelse(`$1', `float', `ifelse(`$2', `double',,` if(xx > (double)Upcase($2)_MAX || xx < Fmin($2)) return NC_ERANGE;')')'dnl -)') - -dnl -dnl For PUT APIs and either $1 and $2 is float or double: -dnl -define(`PUTF_CheckBND', -`ifelse(`$2', `double', ` if(*ip > Xmax($1) || *ip < DXmin($1)) return NC_ERANGE;', - `ifelse(`$2', `float', ` if(*ip > (double)Xmax($1) || *ip < FXmin($1)) return NC_ERANGE;')'dnl -)') - -dnl -dnl For GET APIs and $1 and $2 are not float or double -dnl -define(`GETI_CheckBND', -``#'if IXmax($1) > Imax($2) - if (xx > Imax($2)'`ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, , ` || xx < Imin($2)')')'`) return NC_ERANGE;' -`#'endif) - -dnl -dnl For PUT APIs and $1 and $2 are not float or double -dnl -define(`PUTI_CheckBND', -``#'if IXmax($1) < Imax($2) - if (*ip > IXmax($1)'`ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, , ` || *ip < Xmin($1)')')'`) return NC_ERANGE;' -`#'endif) +`if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) { + ifdef(`ERANGE_FILL',`*ip = FillDefaultValue($1);') + DEBUG_RETURN_ERROR(NC_ERANGE) + } + *ip = ($1)xx;')dnl + +dnl +dnl For GET APIs boudnary check for when $1 is either 'longlong' or 'ulonglong' +dnl +define(`GETF_CheckBND2', + `ifelse(index(`$1',`u'), 0, +`if (xx == Upcase($1)_MAX) *ip = Upcase($1)_MAX;',dnl for unsigned type +`if (xx == Upcase($1)_MAX) *ip = Upcase($1)_MAX; + else if (xx == Upcase($1)_MIN) *ip = Upcase($1)_MIN;') + else if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) { + ifdef(`ERANGE_FILL',`*ip = FillDefaultValue($1);') + DEBUG_RETURN_ERROR(NC_ERANGE) + } + else *ip = ($1)xx;') /* * Primitive numeric conversion functions. @@ -438,13 +660,19 @@ dnl NCX_GET1F(xtype, itype) for floating-point types dnl define(`NCX_GET1F',dnl `dnl -int -ncx_get_$1_$2(const void *xp, $2 *ip) +static int +APIPrefix`x_get_'NC_TYPE($1)_$2(const void *xp, $2 *ip) { ix_$1 xx; get_ix_$1(xp, &xx); - *ip = ($2) xx; -GETF_CheckBND($1, $2) + ifelse(`$1', `float', `ifelse(`$2', `longlong', GETF_CheckBND2($2), + `$2', `ulonglong', GETF_CheckBND2($2), + `$2', `double', `*ip = ($2)xx;', + GETF_CheckBND($2))', + `$1', `double', `ifelse(`$2', `longlong', GETF_CheckBND2($2), + `$2', `ulonglong', GETF_CheckBND2($2), + GETF_CheckBND($2))', + `*ip = ($2)xx;') return NC_NOERR; } ')dnl @@ -455,23 +683,41 @@ dnl NCX_GET1I(xtype, itype, isComptable) for integral types dnl define(`NCX_GET1I',dnl `dnl -int -ncx_get_$1_$2(const void *xp, $2 *ip) +static int +APIPrefix`x_get_'NC_TYPE($1)_$2(const void *xp, $2 *ip) { + int err=NC_NOERR; ifelse(`$3', `1', ``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX - get_ix_$1(xp, (ix_$1 *)ip); - return NC_NOERR; + get_ix_$1(xp, (ix_$1 *)ip); `#'else ')dnl - ix_$1 xx; - get_ix_$1(xp, &xx); - *ip = ($2) xx; -GETI_CheckBND($1, $2) -GETI_CheckNeg($1, $2) -ifelse(`$3', `1', ``#'endif + ix_$1 xx; + get_ix_$1(xp, &xx); + +`#'if IXmax($1) > Imax($2) + if (xx > Imax($2)'`ifelse(index(`$1',`u'), 0, , + index(`$2',`u'), 0, , + ` || xx < Imin($2)')'`) { +ifdef(`ERANGE_FILL',`dnl + *ip = FillDefaultValue($2); + DEBUG_RETURN_ERROR(NC_ERANGE)',` + DEBUG_ASSIGN_ERROR(err, NC_ERANGE)') + }' +`#'endif + +`ifelse(index(`$1',`u'), 0, , index(`$2',`u'), 0,`dnl + if (xx < 0) { +ifdef(`ERANGE_FILL',`dnl + *ip = FillDefaultValue($2); + DEBUG_RETURN_ERROR(NC_ERANGE)',` + DEBUG_ASSIGN_ERROR(err, NC_ERANGE)') /* because ip is unsigned */ + }')'dnl + + *ip = ($2) xx; +`ifelse(`$3', `1', ``#'endif ')dnl - return NC_NOERR; + return err; } ')dnl @@ -481,13 +727,24 @@ dnl NCX_PUT1F(xtype, itype) for floating-point types dnl define(`NCX_PUT1F',dnl `dnl -int -ncx_put_$1_$2(void *xp, const $2 *ip) +static int +APIPrefix`x_put_'NC_TYPE($1)_$2(void *xp, const $2 *ip, void *fillp) { - ix_$1 xx = (ix_$1)*ip; - put_ix_$1(xp, &xx); -PUTF_CheckBND($1, $2) - return NC_NOERR; + int err=NC_NOERR; + ix_$1 xx = FillDefaultValue($1); + + ifelse(`$2', `double', `if (*ip > Xmax($1) || *ip < DXmin($1)) { + FillValue($1, &xx) + DEBUG_ASSIGN_ERROR(err, NC_ERANGE) + } ifdef(`ERANGE_FILL',`else')', + `$2', `float', `if (*ip > (double)Xmax($1) || *ip < FXmin($1)) { + FillValue($1, &xx) + DEBUG_ASSIGN_ERROR(err, NC_ERANGE) + } ifdef(`ERANGE_FILL',`else')') + xx = (ix_$1)*ip; + + put_ix_$1(xp, &xx); + return err; } ')dnl @@ -497,22 +754,37 @@ dnl NCX_PUT1I(xtype, itype, isComptable) for integral types dnl define(`NCX_PUT1I',dnl `dnl -int -ncx_put_$1_$2(void *xp, const $2 *ip) +static int +APIPrefix`x_put_'NC_TYPE($1)_$2(void *xp, const $2 *ip, void *fillp) { + int err=NC_NOERR; ifelse(`$3', `1', ``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX - put_ix_$1(xp, (const ix_$1 *)ip); - return NC_NOERR; + put_ix_$1(xp, (const ix_$1 *)ip); `#'else ')dnl - ix_$1 xx = (ix_$1)*ip; - put_ix_$1(xp, &xx); -PUTI_CheckBND($1, $2) -PUTI_CheckNeg($1, $2) + ix_$1 xx = FillDefaultValue($1); + +`#'if IXmax($1) < Imax($2) + if (*ip > IXmax($1)'`ifelse(index(`$1',`u'), 0, , + index(`$2',`u'), 0, , + ` || *ip < Xmin($1)')'`) { + FillValue($1, &xx) + DEBUG_ASSIGN_ERROR(err, NC_ERANGE) + } ifdef(`ERANGE_FILL',`else') +`#'endif +ifelse(index(`$1',`u'), 0, `ifelse(index(`$2',`u'), 0, ,`dnl + if (*ip < 0) { + FillValue($1, &xx) + DEBUG_ASSIGN_ERROR(err, NC_ERANGE) /* because xp is unsigned */ + } ifdef(`ERANGE_FILL',`else') +')')dnl + xx = (ix_$1)*ip; + + put_ix_$1(xp, &xx); ifelse(`$3', `1', ``#'endif ')dnl - return NC_NOERR; + return err; } ')dnl @@ -522,7 +794,7 @@ ifelse(`$3', `1', ``#'endif /* We don't implement any x_schar and x_uchar primitives. */ -/* x_short -------------------------------------------------------------------*/ +/* external NC_SHORT --------------------------------------------------------*/ #if SHORT_MAX == X_SHORT_MAX typedef short ix_short; @@ -538,7 +810,7 @@ typedef long ix_short; #define IX_SHORT_MAX LONG_MAX #elif LLONG_MAX >= X_SHORT_MAX typedef long long ix_short; -#define SIZEOF_IX_SHORT SIZEOF_LONG_LONG +#define SIZEOF_IX_SHORT SIZEOF_LONGLONG #define IX_SHORT_MAX LLONG_MAX #else #error "ix_short implementation" @@ -548,50 +820,51 @@ static void get_ix_short(const void *xp, ix_short *ip) { const uchar *cp = (const uchar *) xp; - *ip = *cp++ << 8; + *ip = (ix_short)(*cp++ << 8); #if SIZEOF_IX_SHORT > X_SIZEOF_SHORT - if(*ip & 0x8000) + if (*ip & 0x8000) { /* extern is negative */ *ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */ } #endif - *ip |= *cp; + *ip = (ix_short)(*ip | *cp); } static void put_ix_short(void *xp, const ix_short *ip) { uchar *cp = (uchar *) xp; - *cp++ = (*ip) >> 8; - *cp = (*ip) & 0xff; -} - -static NCX_GET1I(short, schar, 0) -static NCX_GET1I(short, short, 1) -static NCX_GET1I(short, int, 1) -static NCX_GET1I(short, longlong, 1) -static NCX_GET1I(short, ushort, 0) -static NCX_GET1I(short, uchar, 0) -static NCX_GET1I(short, uint, 0) -static NCX_GET1I(short, ulonglong, 0) -static NCX_GET1F(short, float) -static NCX_GET1F(short, double) + *cp++ = (uchar)((*ip) >> 8); + *cp = (uchar)((*ip) & 0xff); +} + +NCX_GET1I(short, schar, 0) +NCX_GET1I(short, short, 1) +NCX_GET1I(short, int, 1) +NCX_GET1I(short, long, 1) +NCX_GET1I(short, longlong, 1) +NCX_GET1I(short, ushort, 0) +NCX_GET1I(short, uchar, 0) +NCX_GET1I(short, uint, 0) +NCX_GET1I(short, ulonglong, 0) +NCX_GET1F(short, float) +NCX_GET1F(short, double) static int -ncx_put_short_schar(void *xp, const schar *ip) +APIPrefix`x_put_'NC_TYPE(short)_schar(void *xp, const schar *ip, void *fillp) { uchar *cp = (uchar *) xp; - if(*ip & 0x80) + if (*ip & 0x80) *cp++ = 0xff; else *cp++ = 0; - *cp = (uchar)(signed)*ip; + *cp = (uchar)*ip; return NC_NOERR; } static int -ncx_put_short_uchar(void *xp, const uchar *ip) +APIPrefix`x_put_'NC_TYPE(short)_uchar(void *xp, const uchar *ip, void *fillp) { uchar *cp = (uchar *) xp; *cp++ = 0; @@ -599,16 +872,17 @@ ncx_put_short_uchar(void *xp, const uchar *ip) return NC_NOERR; } -static NCX_PUT1I(short, short, 1) -static NCX_PUT1I(short, int, 1) -static NCX_PUT1I(short, longlong, 1) -static NCX_PUT1I(short, ushort, 0) -static NCX_PUT1I(short, uint, 0) -static NCX_PUT1I(short, ulonglong, 0) -static NCX_PUT1F(short, float) -static NCX_PUT1F(short, double) +NCX_PUT1I(short, short, 1) +NCX_PUT1I(short, int, 1) +NCX_PUT1I(short, long, 1) +NCX_PUT1I(short, longlong, 1) +NCX_PUT1I(short, ushort, 0) +NCX_PUT1I(short, uint, 0) +NCX_PUT1I(short, ulonglong, 0) +NCX_PUT1F(short, float) +NCX_PUT1F(short, double) -/* x_ushort ------------------------------------------------------------------*/ +/* external NC_USHORT -------------------------------------------------------*/ #if USHORT_MAX == X_USHORT_MAX typedef unsigned short ix_ushort; @@ -624,7 +898,7 @@ typedef unsigned long ix_ushort; #define IX_USHORT_MAX ULONG_MAX #elif ULLONG_MAX >= X_USHORT_MAX typedef unsigned long long ix_ushort; -#define SIZEOF_IX_USHORT SIZEOF_ULONG_LONG +#define SIZEOF_IX_USHORT SIZEOF_ULONGLONG #define IX_USHORT_MAX ULLONG_MAX #else #error "ix_ushort implementation" @@ -634,52 +908,64 @@ static void get_ix_ushort(const void *xp, ix_ushort *ip) { const uchar *cp = (const uchar *) xp; - *ip = *cp++ << 8; + *ip = (ix_ushort)(*cp++ << 8); #if SIZEOF_IX_SHORT > X_SIZEOF_SHORT - if(*ip & 0x8000) + if (*ip & 0x8000) { /* extern is negative */ *ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */ } #endif - *ip |= *cp; + *ip = (ix_ushort)(*ip | *cp); } static void put_ix_ushort(void *xp, const ix_ushort *ip) { uchar *cp = (uchar *) xp; - *cp++ = (*ip) >> 8; - *cp = (*ip) & 0xff; -} - -static NCX_GET1I(ushort, schar, 0) -static NCX_GET1I(ushort, short, 0) -static NCX_GET1I(ushort, int, 0) -static NCX_GET1I(ushort, longlong, 0) -static NCX_GET1I(ushort, ushort, 1) -static NCX_GET1I(ushort, uchar, 1) -static NCX_GET1I(ushort, uint, 1) -static NCX_GET1I(ushort, ulonglong, 1) -static NCX_GET1F(ushort, float) -static NCX_GET1F(ushort, double) + *cp++ = (uchar)((*ip) >> 8); + *cp = (uchar)((*ip) & 0xff); +} + +NCX_GET1I(ushort, schar, 0) +NCX_GET1I(ushort, short, 0) +NCX_GET1I(ushort, int, 0) +NCX_GET1I(ushort, long, 0) +NCX_GET1I(ushort, longlong, 0) +NCX_GET1I(ushort, ushort, 1) +NCX_GET1I(ushort, uchar, 1) +NCX_GET1I(ushort, uint, 1) +NCX_GET1I(ushort, ulonglong, 1) +NCX_GET1F(ushort, float) +NCX_GET1F(ushort, double) static int -ncx_put_ushort_schar(void *xp, const schar *ip) +APIPrefix`x_put_'NC_TYPE(ushort)_schar(void *xp, const schar *ip, void *fillp) { - uchar *cp = (uchar *) xp; - if(*ip & 0x80) - *cp++ = 0xff; - else - *cp++ = 0; - *cp = (uchar)(signed)*ip; - if (*ip < 0) return NC_ERANGE; + int err=NC_NOERR; + uchar *cp; + if (*ip < 0) { +ifdef(`ERANGE_FILL', `dnl + if (fillp != NULL) memcpy(xp, fillp, 2); +#ifndef WORDS_BIGENDIAN + swapn2b(xp, xp, 1); +#endif + DEBUG_RETURN_ERROR(NC_ERANGE)',`dnl + DEBUG_ASSIGN_ERROR(err, NC_ERANGE)') + } - return NC_NOERR; + cp = (uchar *) xp; + if (*ip & 0x80) + *cp++ = 0xff; + else + *cp++ = 0; + *cp = (uchar)*ip; + + return err; } static int -ncx_put_ushort_uchar(void *xp, const uchar *ip) +APIPrefix`x_put_'NC_TYPE(ushort)_uchar(void *xp, const uchar *ip, void *fillp) { uchar *cp = (uchar *) xp; *cp++ = 0; @@ -687,16 +973,17 @@ ncx_put_ushort_uchar(void *xp, const uchar *ip) return NC_NOERR; } -static NCX_PUT1I(ushort, short, 0) -static NCX_PUT1I(ushort, int, 0) -static NCX_PUT1I(ushort, longlong, 0) -static NCX_PUT1I(ushort, ushort, 1) -static NCX_PUT1I(ushort, uint, 1) -static NCX_PUT1I(ushort, ulonglong, 1) -static NCX_PUT1F(ushort, float) -static NCX_PUT1F(ushort, double) +NCX_PUT1I(ushort, short, 0) +NCX_PUT1I(ushort, int, 0) +NCX_PUT1I(ushort, long, 0) +NCX_PUT1I(ushort, longlong, 0) +NCX_PUT1I(ushort, ushort, 1) +NCX_PUT1I(ushort, uint, 1) +NCX_PUT1I(ushort, ulonglong, 1) +NCX_PUT1F(ushort, float) +NCX_PUT1F(ushort, double) -/* x_int ---------------------------------------------------------------------*/ +/* external NC_INT ----------------------------------------------------------*/ #if SHORT_MAX == X_INT_MAX typedef short ix_int; @@ -722,7 +1009,7 @@ get_ix_int(const void *xp, ix_int *ip) *ip = *cp++ << 24; #if SIZEOF_IX_INT > X_SIZEOF_INT - if(*ip & 0x80000000) + if (*ip & 0x80000000) { /* extern is negative */ *ip |= (~(0xffffffff)); /* N.B. Assumes "twos complement" */ @@ -738,28 +1025,31 @@ put_ix_int(void *xp, const ix_int *ip) { uchar *cp = (uchar *) xp; - *cp++ = (*ip) >> 24; - *cp++ = ((*ip) & 0x00ff0000) >> 16; - *cp++ = ((*ip) & 0x0000ff00) >> 8; - *cp = ((*ip) & 0x000000ff); + *cp++ = (uchar)( (*ip) >> 24); + *cp++ = (uchar)(((*ip) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*ip) & 0x0000ff00) >> 8); + *cp = (uchar)( (*ip) & 0x000000ff); } -static NCX_GET1I(int, schar, 0) -static NCX_GET1I(int, short, 1) - NCX_GET1I(int, int, 1) -static NCX_GET1I(int, longlong, 1) -static NCX_GET1I(int, ushort, 0) -static NCX_GET1I(int, uchar, 0) -static NCX_GET1I(int, uint, 0) -static NCX_GET1I(int, ulonglong, 0) -static NCX_GET1F(int, float) -static NCX_GET1F(int, double) +#if X_SIZEOF_INT != SIZEOF_INT +NCX_GET1I(int, int, 1) +#endif +NCX_GET1I(int, schar, 0) +NCX_GET1I(int, short, 1) +NCX_GET1I(int, long, 1) +NCX_GET1I(int, longlong, 1) +NCX_GET1I(int, ushort, 0) +NCX_GET1I(int, uchar, 0) +NCX_GET1I(int, uint, 0) +NCX_GET1I(int, ulonglong, 0) +NCX_GET1F(int, float) +NCX_GET1F(int, double) static int -ncx_put_int_schar(void *xp, const schar *ip) +APIPrefix`x_put_'NC_TYPE(int)_schar(void *xp, const schar *ip, void *fillp) { uchar *cp = (uchar *) xp; - if(*ip & 0x80) + if (*ip & 0x80) { *cp++ = 0xff; *cp++ = 0xff; @@ -771,12 +1061,12 @@ ncx_put_int_schar(void *xp, const schar *ip) *cp++ = 0x00; *cp++ = 0x00; } - *cp = (uchar)(signed)*ip; + *cp = (uchar)*ip; return NC_NOERR; } static int -ncx_put_int_uchar(void *xp, const uchar *ip) +APIPrefix`x_put_'NC_TYPE(int)_uchar(void *xp, const uchar *ip, void *fillp) { uchar *cp = (uchar *) xp; *cp++ = 0x00; @@ -786,17 +1076,20 @@ ncx_put_int_uchar(void *xp, const uchar *ip) return NC_NOERR; } -static NCX_PUT1I(int, short, 1) - NCX_PUT1I(int, int, 1) -static NCX_PUT1I(int, longlong, 1) -static NCX_PUT1I(int, ushort, 0) -static NCX_PUT1I(int, uint, 0) -static NCX_PUT1I(int, ulonglong, 0) -static NCX_PUT1F(int, float) -static NCX_PUT1F(int, double) +#if X_SIZEOF_INT != SIZEOF_INT +NCX_PUT1I(int, int, 1) +#endif +NCX_PUT1I(int, short, 1) +NCX_PUT1I(int, long, 1) +NCX_PUT1I(int, longlong, 1) +NCX_PUT1I(int, ushort, 0) +NCX_PUT1I(int, uint, 0) +NCX_PUT1I(int, ulonglong, 0) +NCX_PUT1F(int, float) +NCX_PUT1F(int, double) -/* x_uint --------------------------------------------------------------------*/ +/* external NC_UINT ---------------------------------------------------------*/ #if USHORT_MAX == X_UINT_MAX typedef ushort ix_uint; @@ -820,10 +1113,10 @@ get_ix_uint(const void *xp, ix_uint *ip) { const uchar *cp = (const uchar *) xp; - *ip = *cp++ << 24; - *ip |= (*cp++ << 16); - *ip |= (*cp++ << 8); - *ip |= *cp; + *ip = (ix_uint)(*cp++ << 24); + *ip = (ix_uint)(*ip | (ix_uint)(*cp++ << 16)); + *ip = (ix_uint)(*ip | (ix_uint)(*cp++ << 8)); + *ip = (ix_uint)(*ip | *cp); } static void @@ -831,42 +1124,51 @@ put_ix_uint(void *xp, const ix_uint *ip) { uchar *cp = (uchar *) xp; - *cp++ = (*ip) >> 24; - *cp++ = ((*ip) & 0x00ff0000) >> 16; - *cp++ = ((*ip) & 0x0000ff00) >> 8; - *cp = ((*ip) & 0x000000ff); + *cp++ = (uchar)((*ip) >> 24); + *cp++ = (uchar)(((*ip) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*ip) & 0x0000ff00) >> 8); + *cp = (uchar)( (*ip) & 0x000000ff); } #if X_SIZEOF_UINT != SIZEOF_UINT -static NCX_GET1I(uint, uint, 1) +NCX_GET1I(uint, uint, 1) #endif -static NCX_GET1I(uint, schar, 0) -static NCX_GET1I(uint, short, 0) -static NCX_GET1I(uint, int, 0) -static NCX_GET1I(uint, longlong, 0) -static NCX_GET1I(uint, ushort, 1) -static NCX_GET1I(uint, uchar, 1) -static NCX_GET1I(uint, ulonglong, 1) -static NCX_GET1F(uint, float) -static NCX_GET1F(uint, double) +NCX_GET1I(uint, schar, 0) +NCX_GET1I(uint, short, 0) +NCX_GET1I(uint, int, 0) +NCX_GET1I(uint, long, 0) +NCX_GET1I(uint, longlong, 0) +NCX_GET1I(uint, ushort, 1) +NCX_GET1I(uint, uchar, 1) +NCX_GET1I(uint, ulonglong, 1) +NCX_GET1F(uint, float) +NCX_GET1F(uint, double) static int -ncx_put_uint_schar(void *xp, const schar *ip) +APIPrefix`x_put_'NC_TYPE(uint)_schar(void *xp, const schar *ip, void *fillp) { - uchar *cp = (uchar *) xp; - *cp++ = 0x00; - *cp++ = 0x00; - *cp++ = 0x00; - *cp = (uchar)(signed)*ip; + uchar *cp; + if (*ip < 0) { +ifdef(`ERANGE_FILL', `dnl + if (fillp != NULL) memcpy(xp, fillp, 4); +#ifndef WORDS_BIGENDIAN + swapn4b(xp, xp, 1); +#endif') + DEBUG_RETURN_ERROR(NC_ERANGE) + } - if (*ip < 0) return NC_ERANGE; + cp = (uchar *) xp; + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; + *cp = (uchar)*ip; - return NC_NOERR; + return NC_NOERR; } static int -ncx_put_uint_uchar(void *xp, const uchar *ip) +APIPrefix`x_put_'NC_TYPE(uint)_uchar(void *xp, const uchar *ip, void *fillp) { uchar *cp = (uchar *) xp; *cp++ = 0x00; @@ -877,32 +1179,34 @@ ncx_put_uint_uchar(void *xp, const uchar *ip) } #if X_SIZEOF_UINT != SIZEOF_UINT -static NCX_PUT1I(uint, uint, 1) +NCX_PUT1I(uint, uint, 1) #endif -static NCX_PUT1I(uint, short, 0) -static NCX_PUT1I(uint, int, 0) -static NCX_PUT1I(uint, longlong, 0) -static NCX_PUT1I(uint, ushort, 1) -static NCX_PUT1I(uint, ulonglong, 1) -static NCX_PUT1F(uint, float) -static NCX_PUT1F(uint, double) +NCX_PUT1I(uint, short, 0) +NCX_PUT1I(uint, int, 0) +NCX_PUT1I(uint, long, 0) +NCX_PUT1I(uint, longlong, 0) +NCX_PUT1I(uint, ushort, 1) +NCX_PUT1I(uint, ulonglong, 1) +NCX_PUT1F(uint, float) +NCX_PUT1F(uint, double) + -/* x_float -------------------------------------------------------------------*/ +/* external NC_FLOAT --------------------------------------------------------*/ #if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) -static void +inline static void get_ix_float(const void *xp, float *ip) { #ifdef WORDS_BIGENDIAN - (void) memcpy(ip, xp, sizeof(float)); + (void) memcpy(ip, xp, SIZEOF_FLOAT); #else swap4b(ip, xp); #endif } -static void +inline static void put_ix_float(void *xp, const float *ip) { #ifdef WORDS_BIGENDIAN @@ -912,7 +1216,7 @@ put_ix_float(void *xp, const float *ip) #endif } -#elif vax +#elif defined(vax) && vax != 0 /* What IEEE single precision floating point looks like on a Vax */ struct ieee_single { @@ -961,7 +1265,7 @@ define(`GET_VAX_DFLOAT_Body',dnl switch(exp) { case 0 : /* ieee subnormal */ - if(isp->mant_hi == min.ieee.mant_hi + if (isp->mant_hi == min.ieee.mant_hi && isp->mant_lo_hi == min.ieee.mant_lo_hi && isp->mant_lo_lo == min.ieee.mant_lo_lo) { @@ -973,7 +1277,7 @@ define(`GET_VAX_DFLOAT_Body',dnl | isp->mant_lo_hi << 8 | isp->mant_lo_lo; unsigned tmp = mantissa >> 20; - if(tmp >= 4) { + if (tmp >= 4) { vsp->exp = 2; } else if (tmp >= 2) { vsp->exp = 1; @@ -1036,8 +1340,8 @@ define(`PUT_VAX_DFLOAT_Body',dnl } break; case 0xff : /* max.s.exp */ - if( vsp->mantissa2 == max.s.mantissa2 - && vsp->mantissa1 == max.s.mantissa1) + if (vsp->mantissa2 == max.s.mantissa2 && + vsp->mantissa1 == max.s.mantissa1) { /* map largest vax float to ieee infinity */ *isp = max.ieee; @@ -1127,11 +1431,11 @@ define(`GET_IX_FLOAT_Body',dnl `dnl cray_single *csp = (cray_single *) ip; - if(isp->exp == 0) + if (isp->exp == 0) { /* ieee subnormal */ *ip = (double)isp->mant; - if(isp->mant != 0) + if (isp->mant != 0) { csp->exp -= (ieee_single_bias + 22); } @@ -1156,13 +1460,13 @@ define(`PUT_IX_FLOAT_Body',dnl isp->sign = csp->sign; - if(ieee_exp >= 0xff) + if (ieee_exp >= 0xff) { /* NC_ERANGE => ieee Inf */ isp->exp = 0xff; isp->mant = 0x0; } - else if(ieee_exp > 0) + else if (ieee_exp > 0) { /* normal ieee representation */ isp->exp = ieee_exp; @@ -1171,7 +1475,7 @@ define(`PUT_IX_FLOAT_Body',dnl isp->mant = (((csp->mant << 1) & 0xffffffffffff) >> (48 - 23)); } - else if(ieee_exp > -23) + else if (ieee_exp > -23) { /* ieee subnormal, right shift */ const int rshift = (48 - 23 - ieee_exp); @@ -1179,7 +1483,7 @@ define(`PUT_IX_FLOAT_Body',dnl isp->mant = csp->mant >> rshift; #if 0 - if(csp->mant & (1 << (rshift -1))) + if (csp->mant & (1 << (rshift -1))) { /* round up */ isp->mant++; @@ -1200,7 +1504,7 @@ static void get_ix_float(const void *xp, float *ip) { - if(word_align(xp) == 0) + if (word_align(xp) == 0) { const ieee_single_hi *isp = (const ieee_single_hi *) xp; GET_IX_FLOAT_Body @@ -1215,7 +1519,7 @@ GET_IX_FLOAT_Body static void put_ix_float(void *xp, const float *ip) { - if(word_align(xp) == 0) + if (word_align(xp) == 0) { ieee_single_hi *isp = (ieee_single_hi*)xp; PUT_IX_FLOAT_Body @@ -1235,10 +1539,10 @@ get_ix_float(const void *xp, float *ip) ieee_double *idp = (ieee_double *) ip; - if(word_align(xp) == 0) + if (word_align(xp) == 0) { const ieee_single_hi *isp = (const ieee_single_hi *) xp; - if(isp->exp == 0 && isp->mant == 0) + if (isp->exp == 0 && isp->mant == 0) { idp->exp = 0; idp->mant = 0; @@ -1253,7 +1557,7 @@ get_ix_float(const void *xp, float *ip) else { const ieee_single_lo *isp = (const ieee_single_lo *) xp; - if(isp->exp == 0 && isp->mant == 0) + if (isp->exp == 0 && isp->mant == 0) { idp->exp = 0; idp->mant = 0; @@ -1271,10 +1575,10 @@ static void put_ix_float(void *xp, const float *ip) { const ieee_double *idp = (const ieee_double *) ip; - if(word_align(xp) == 0) + if (word_align(xp) == 0) { ieee_single_hi *isp = (ieee_single_hi*)xp; - if(idp->exp > (ieee_double_bias - ieee_single_bias)) + if (idp->exp > (ieee_double_bias - ieee_single_bias)) isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias); else isp->exp = 0; @@ -1284,7 +1588,7 @@ put_ix_float(void *xp, const float *ip) else { ieee_single_lo *isp = (ieee_single_lo*)xp; - if(idp->exp > (ieee_double_bias - ieee_single_bias)) + if (idp->exp > (ieee_double_bias - ieee_single_bias)) isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias); else isp->exp = 0; @@ -1300,7 +1604,7 @@ put_ix_float(void *xp, const float *ip) #if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT) static int -ncx_get_float_float(const void *xp, float *ip) +APIPrefix`x_get_'NC_TYPE(float)_float(const void *xp, float *ip, void *fillp) { /* TODO */ get_ix_float(xp, ip); @@ -1310,41 +1614,49 @@ ncx_get_float_float(const void *xp, float *ip) #define ix_float float -static NCX_GET1F(float, schar) -static NCX_GET1F(float, short) -static NCX_GET1F(float, int) -static NCX_GET1F(float, double) -static NCX_GET1F(float, longlong) -static NCX_GET1F(float, uchar) -static NCX_GET1F(float, ushort) -static NCX_GET1F(float, uint) -static NCX_GET1F(float, ulonglong) +NCX_GET1F(float, schar) +NCX_GET1F(float, short) +NCX_GET1F(float, int) +NCX_GET1F(float, long) +NCX_GET1F(float, double) +NCX_GET1F(float, longlong) +NCX_GET1F(float, uchar) +NCX_GET1F(float, ushort) +NCX_GET1F(float, uint) +NCX_GET1F(float, ulonglong) #if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT) static int -ncx_put_float_float(void *xp, const float *ip) +APIPrefix`x_put_'NC_TYPE(float)_float(void *xp, const float *ip, void *fillp) { - put_ix_float(xp, ip); + int err=NC_NOERR; + float *_ip=ip; #ifdef NO_IEEE_FLOAT - if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) - return NC_ERANGE; + ifdef(`ERANGE_FILL',`float tmp;') + if (*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) { + FillValue(float, &tmp) + ifdef(`ERANGE_FILL',`_ip = &tmp;') + DEBUG_ASSIGN_ERROR(err, NC_ERANGE) + } #endif - return NC_NOERR; + put_ix_float(xp, _ip); + return err; } #endif -static NCX_PUT1F(float, schar) -static NCX_PUT1F(float, short) -static NCX_PUT1F(float, int) -static NCX_PUT1F(float, double) -static NCX_PUT1F(float, longlong) -static NCX_PUT1F(float, uchar) -static NCX_PUT1F(float, ushort) -static NCX_PUT1F(float, uint) -static NCX_PUT1F(float, ulonglong) +NCX_PUT1F(float, schar) +NCX_PUT1F(float, short) +NCX_PUT1F(float, int) +NCX_PUT1F(float, long) +NCX_PUT1F(float, double) +NCX_PUT1F(float, longlong) +NCX_PUT1F(float, uchar) +NCX_PUT1F(float, ushort) +NCX_PUT1F(float, uint) +NCX_PUT1F(float, ulonglong) -/* x_double ------------------------------------------------------------------*/ +/* external NC_DOUBLE -------------------------------------------------------*/ #if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) @@ -1352,7 +1664,7 @@ static void get_ix_double(const void *xp, double *ip) { #ifdef WORDS_BIGENDIAN - (void) memcpy(ip, xp, sizeof(double)); + (void) memcpy(ip, xp, SIZEOF_DOUBLE); #else swap8b(ip, xp); #endif @@ -1368,7 +1680,7 @@ put_ix_double(void *xp, const double *ip) #endif } -#elif vax +#elif defined(vax) && vax != 0 /* What IEEE double precision floating point looks like on a Vax */ struct ieee_double { @@ -1502,14 +1814,14 @@ define(`PUT_VAX_DDOUBLE_Body',dnl unsigned mant_hi = (vdp->mantissa1 << 13) | (vdp->mantissa2 >> 3); - if((vdp->mantissa4 & 7) > 4) + if ((vdp->mantissa4 & 7) > 4) { /* round up */ mant_lo++; - if(mant_lo == 0) + if (mant_lo == 0) { mant_hi++; - if(mant_hi > 0xffffff) + if (mant_hi > 0xffffff) { mant_hi = 0; exp++; @@ -1543,11 +1855,11 @@ get_ix_double(const void *xp, double *ip) const ieee_double *idp = (const ieee_double *) xp; cray_single *csp = (cray_single *) ip; - if(idp->exp == 0) + if (idp->exp == 0) { /* ieee subnormal */ *ip = (double)idp->mant; - if(idp->mant != 0) + if (idp->mant != 0) { csp->exp -= (ieee_double_bias + 51); } @@ -1571,13 +1883,13 @@ put_ix_double(void *xp, const double *ip) idp->sign = csp->sign; - if(ieee_exp >= 0x7ff) + if (ieee_exp >= 0x7ff) { /* NC_ERANGE => ieee Inf */ idp->exp = 0x7ff; idp->mant = 0x0; } - else if(ieee_exp > 0) + else if (ieee_exp > 0) { /* normal ieee representation */ idp->exp = ieee_exp; @@ -1586,14 +1898,14 @@ put_ix_double(void *xp, const double *ip) idp->mant = (((csp->mant << 1) & 0xffffffffffff) << (52 - 48)); } - else if(ieee_exp >= (-(52 -48))) + else if (ieee_exp >= (-(52 -48))) { /* ieee subnormal, left shift */ const int lshift = (52 - 48) + ieee_exp; idp->mant = csp->mant << lshift; idp->exp = 0; } - else if(ieee_exp >= -52) + else if (ieee_exp >= -52) { /* ieee subnormal, right shift */ const int rshift = (- (52 - 48) - ieee_exp); @@ -1601,7 +1913,7 @@ put_ix_double(void *xp, const double *ip) idp->mant = csp->mant >> rshift; #if 0 - if(csp->mant & (1 << (rshift -1))) + if (csp->mant & (1 << (rshift -1))) { /* round up */ idp->mant++; @@ -1623,47 +1935,36 @@ put_ix_double(void *xp, const double *ip) #define ix_double double -static NCX_GET1F(double, schar) -static NCX_GET1F(double, short) -static NCX_GET1F(double, int) -static NCX_GET1F(double, longlong) -static NCX_GET1F(double, uchar) -static NCX_GET1F(double, ushort) -static NCX_GET1F(double, uint) - -int -ncx_get_double_ulonglong(const void *xp, unsigned long long *ip) -{ - double xx; - get_ix_double(xp, &xx); - *ip = (unsigned long long) xx; - if(xx > ULONG_LONG_MAX || xx < 0) - return NC_ERANGE; - return NC_NOERR; -} +NCX_GET1F(double, schar) +NCX_GET1F(double, short) +NCX_GET1F(double, int) +NCX_GET1F(double, long) +NCX_GET1F(double, longlong) +NCX_GET1F(double, uchar) +NCX_GET1F(double, ushort) +NCX_GET1F(double, uint) +NCX_GET1F(double, ulonglong) static int -ncx_get_double_float(const void *xp, float *ip) +APIPrefix`x_get_'NC_TYPE(double)_float(const void *xp, float *ip) { - double xx; - get_ix_double(xp, &xx); - if(xx > FLT_MAX) - { - *ip = FLT_MAX; - return NC_ERANGE; - } - if(xx < (-FLT_MAX)) - { - *ip = (-FLT_MAX); - return NC_ERANGE; - } - *ip = (float) xx; - return NC_NOERR; + double xx; + get_ix_double(xp, &xx); + if (xx > FLT_MAX) { + ifdef(`ERANGE_FILL', `*ip = NC_FILL_FLOAT;', `*ip = FLT_MAX;') + DEBUG_RETURN_ERROR(NC_ERANGE) + } + if (xx < (-FLT_MAX)) { + ifdef(`ERANGE_FILL', `*ip = NC_FILL_FLOAT;', `*ip = (-FLT_MAX);') + DEBUG_RETURN_ERROR(NC_ERANGE) + } + *ip = (float) xx; + return NC_NOERR; } #if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE || defined(NO_IEEE_FLOAT) static int -ncx_get_double_double(const void *xp, double *ip) +APIPrefix`x_get_'NC_TYPE(double)_double(const void *xp, double *ip, void *fillp) { /* TODO */ get_ix_double(xp, ip); @@ -1671,182 +1972,208 @@ ncx_get_double_double(const void *xp, double *ip) } #endif -static NCX_PUT1F(double, schar) -static NCX_PUT1F(double, uchar) -static NCX_PUT1F(double, short) -static NCX_PUT1F(double, ushort) -static NCX_PUT1F(double, int) -static NCX_PUT1F(double, uint) -static NCX_PUT1F(double, longlong) -static NCX_PUT1F(double, ulonglong) +NCX_PUT1F(double, schar) +NCX_PUT1F(double, uchar) +NCX_PUT1F(double, short) +NCX_PUT1F(double, ushort) +NCX_PUT1F(double, int) +NCX_PUT1F(double, long) +NCX_PUT1F(double, uint) +NCX_PUT1F(double, longlong) +NCX_PUT1F(double, ulonglong) static int -ncx_put_double_float(void *xp, const float *ip) +APIPrefix`x_put_'NC_TYPE(double)_float(void *xp, const float *ip, void *fillp) { - double xx = (double) *ip; - put_ix_double(xp, &xx); -#if 1 /* TODO: figure this out */ - if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) - return NC_ERANGE; + int err=NC_NOERR; + double xx = FillDefaultValue(double); +#if 1 /* TODO: figure this out (if condition below will never be true)*/ + if ((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) { + FillValue(double, &xx) + DEBUG_ASSIGN_ERROR(err, NC_ERANGE) + } ifdef(`ERANGE_FILL',`else') #endif - return NC_NOERR; + xx = (double) *ip; + + put_ix_double(xp, &xx); + return err; } #if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE || defined(NO_IEEE_FLOAT) static int -ncx_put_double_double(void *xp, const double *ip) +APIPrefix`x_put_'NC_TYPE(double)_double(void *xp, const double *ip, void *fillp) { - put_ix_double(xp, ip); + int err=NC_NOERR; + double *_ip = ip; #ifdef NO_IEEE_FLOAT - if(*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN) - return NC_ERANGE; + ifdef(`ERANGE_FILL',`double tmp=NC_FILL_DOUBLE;') + if (*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN) { + FillValue(double, &tmp) + ifdef(`ERANGE_FILL',`_ip = &tmp;') + DEBUG_ASSIGN_ERROR(err, NC_ERANGE) + } #endif - return NC_NOERR; + put_ix_double(xp, _ip); + return err; } #endif -/* x_longlong ---------------------------------------------------------------------*/ +/* external NC_INT64 --------------------------------------------------------*/ -#if SHORT_MAX == X_LONGLONG_MAX -typedef short ix_longlong; -#define SIZEOF_IX_LONGLONG SIZEOF_SHORT -#define IX_LONGLONG_MAX SHORT_MAX -#elif LONG_LONG_MAX >= X_LONGLONG_MAX -typedef longlong ix_longlong; -#define SIZEOF_IX_LONGLONG SIZEOF_LONGLONG -#define IX_LONGLONG_MAX LONG_LONG_MAX -#elif LONG_MAX >= X_LONGLONG_MAX -typedef long ix_longlong; -#define SIZEOF_IX_LONGLONG SIZEOF_LONG -#define IX_LONGLONG_MAX LONG_MAX +#if SHORT_MAX == X_INT64_MAX +typedef short ix_int64; +#define SIZEOF_IX_INT64 SIZEOF_SHORT +#define IX_INT64_MAX SHORT_MAX +#elif LONG_LONG_MAX >= X_INT64_MAX +typedef longlong ix_int64; +#define SIZEOF_IX_INT64 SIZEOF_LONGLONG +#define IX_INT64_MAX LONG_LONG_MAX +#elif LONG_MAX >= X_INT64_MAX +typedef long ix_int64; +#define SIZEOF_IX_INT64 SIZEOF_LONG +#define IX_INT64_MAX LONG_MAX #else -#error "ix_longlong implementation" +#error "ix_int64 implementation" #endif static void -get_ix_longlong(const void *xp, ix_longlong *ip) +get_ix_int64(const void *xp, ix_int64 *ip) { const uchar *cp = (const uchar *) xp; - *ip = ((long long)(*cp++) << 56); - *ip |= ((long long)(*cp++) << 48); - *ip |= ((long long)(*cp++) << 40); - *ip |= ((long long)(*cp++) << 32); - *ip |= ((long long)(*cp++) << 24); - *ip |= ((long long)(*cp++) << 16); - *ip |= ((long long)(*cp++) << 8); - *ip |= (long long)*cp; + *ip = ((ix_int64)(*cp++) << 56); + *ip |= ((ix_int64)(*cp++) << 48); + *ip |= ((ix_int64)(*cp++) << 40); + *ip |= ((ix_int64)(*cp++) << 32); + *ip |= ((ix_int64)(*cp++) << 24); + *ip |= ((ix_int64)(*cp++) << 16); + *ip |= ((ix_int64)(*cp++) << 8); + *ip |= (ix_int64)*cp; } static void -put_ix_longlong(void *xp, const ix_longlong *ip) +put_ix_int64(void *xp, const ix_int64 *ip) { uchar *cp = (uchar *) xp; - *cp++ = (*ip) >> 56; - *cp++ = ((*ip) & 0x00ff000000000000LL) >> 48; - *cp++ = ((*ip) & 0x0000ff0000000000LL) >> 40; - *cp++ = ((*ip) & 0x000000ff00000000LL) >> 32; - *cp++ = ((*ip) & 0x00000000ff000000LL) >> 24; - *cp++ = ((*ip) & 0x0000000000ff0000LL) >> 16; - *cp++ = ((*ip) & 0x000000000000ff00LL) >> 8; - *cp = ((*ip) & 0x00000000000000ffLL); -} - -static NCX_GET1I(longlong, schar, 0) -static NCX_GET1I(longlong, short, 1) -static NCX_GET1I(longlong, int, 1) -static NCX_GET1I(longlong, longlong, 1) -static NCX_GET1I(longlong, ushort, 0) -static NCX_GET1I(longlong, uchar, 0) -static NCX_GET1I(longlong, uint, 0) -static NCX_GET1I(longlong, ulonglong, 0) -static NCX_GET1F(longlong, float) -static NCX_GET1F(longlong, double) - -static NCX_PUT1I(longlong, schar, 0) -static NCX_PUT1I(longlong, short, 1) -static NCX_PUT1I(longlong, int, 1) -static NCX_PUT1I(longlong, longlong, 1) -static NCX_PUT1I(longlong, ushort, 0) -static NCX_PUT1I(longlong, uchar, 0) -static NCX_PUT1I(longlong, uint, 0) -static NCX_PUT1I(longlong, ulonglong, 0) -static NCX_PUT1F(longlong, float) -static NCX_PUT1F(longlong, double) - -/* x_ulonglong --------------------------------------------------------------------*/ - -#if USHORT_MAX == X_ULONGLONG_MAX -typedef ushort ix_ulonglong; -#define SIZEOF_IX_ULONGLONG SIZEOF_USHORT -#define IX_ULONGLONG_MAX USHORT_MAX -#elif ULONG_LONG_MAX >= X_ULONGLONG_MAX -typedef ulonglong ix_ulonglong; -#define SIZEOF_IX_ULONGLONG SIZEOF_ULONGLONG -#define IX_ULONGLONG_MAX ULONG_LONG_MAX -#elif ULONG_MAX >= X_ULONGLONG_MAX -typedef ulong ix_ulonglong; -#define SIZEOF_IX_ULONGLONG SIZEOF_ULONG -#define IX_ULONGLONG_MAX ULONG_MAX + *cp++ = (uchar)((*ip) >> 56); + *cp++ = (uchar)(((*ip) & 0x00ff000000000000LL) >> 48); + *cp++ = (uchar)(((*ip) & 0x0000ff0000000000LL) >> 40); + *cp++ = (uchar)(((*ip) & 0x000000ff00000000LL) >> 32); + *cp++ = (uchar)(((*ip) & 0x00000000ff000000LL) >> 24); + *cp++ = (uchar)(((*ip) & 0x0000000000ff0000LL) >> 16); + *cp++ = (uchar)(((*ip) & 0x000000000000ff00LL) >> 8); + *cp = (uchar)( (*ip) & 0x00000000000000ffLL); +} + +#if X_SIZEOF_INT64 != SIZEOF_LONGLONG +NCX_GET1I(int64, longlong, 1) +#endif +NCX_GET1I(int64, schar, 0) +NCX_GET1I(int64, short, 1) +NCX_GET1I(int64, int, 1) +NCX_GET1I(int64, long, 1) +NCX_GET1I(int64, ushort, 0) +NCX_GET1I(int64, uchar, 0) +NCX_GET1I(int64, uint, 0) +NCX_GET1I(int64, ulonglong, 0) +NCX_GET1F(int64, float) +NCX_GET1F(int64, double) + +#if X_SIZEOF_INT64 != SIZEOF_LONGLONG +NCX_PUT1I(int64, longlong, 1) +#endif +NCX_PUT1I(int64, schar, 0) +NCX_PUT1I(int64, short, 1) +NCX_PUT1I(int64, int, 1) +NCX_PUT1I(int64, long, 1) +NCX_PUT1I(int64, ushort, 0) +NCX_PUT1I(int64, uchar, 0) +NCX_PUT1I(int64, uint, 0) +NCX_PUT1I(int64, ulonglong, 0) +NCX_PUT1F(int64, float) +NCX_PUT1F(int64, double) + + +/* external NC_UINT64 -------------------------------------------------------*/ + +#if USHORT_MAX == X_UINT64_MAX +typedef ushort ix_uint64; +#define SIZEOF_IX_UINT64 SIZEOF_USHORT +#define IX_UINT64_MAX USHORT_MAX +#elif ULONG_LONG_MAX >= X_UINT64_MAX +typedef ulonglong ix_uint64; +#define SIZEOF_IX_UINT64 SIZEOF_ULONGLONG +#define IX_UINT64_MAX ULONG_LONG_MAX +#elif ULONG_MAX >= X_UINT64_MAX +typedef ulong ix_uint64; +#define SIZEOF_IX_UINT64 SIZEOF_ULONG +#define IX_UINT64_MAX ULONG_MAX #else -#error "ix_ulonglong implementation" +#error "ix_uint64 implementation" #endif static void -get_ix_ulonglong(const void *xp, ix_ulonglong *ip) +get_ix_uint64(const void *xp, ix_uint64 *ip) { const uchar *cp = (const uchar *) xp; - *ip = ((unsigned long long)(*cp++) << 56); - *ip |= ((unsigned long long)(*cp++) << 48); - *ip |= ((unsigned long long)(*cp++) << 40); - *ip |= ((unsigned long long)(*cp++) << 32); - *ip |= ((unsigned long long)(*cp++) << 24); - *ip |= ((unsigned long long)(*cp++) << 16); - *ip |= ((unsigned long long)(*cp++) << 8); - *ip |= (unsigned long long)*cp; + *ip = ((ix_uint64)(*cp++) << 56); + *ip |= ((ix_uint64)(*cp++) << 48); + *ip |= ((ix_uint64)(*cp++) << 40); + *ip |= ((ix_uint64)(*cp++) << 32); + *ip |= ((ix_uint64)(*cp++) << 24); + *ip |= ((ix_uint64)(*cp++) << 16); + *ip |= ((ix_uint64)(*cp++) << 8); + *ip |= (ix_uint64)*cp; } static void -put_ix_ulonglong(void *xp, const ix_ulonglong *ip) +put_ix_uint64(void *xp, const ix_uint64 *ip) { uchar *cp = (uchar *) xp; - *cp++ = (*ip) >> 56; - *cp++ = ((*ip) & 0x00ff000000000000ULL) >> 48; - *cp++ = ((*ip) & 0x0000ff0000000000ULL) >> 40; - *cp++ = ((*ip) & 0x000000ff00000000ULL) >> 32; - *cp++ = ((*ip) & 0x00000000ff000000ULL) >> 24; - *cp++ = ((*ip) & 0x0000000000ff0000ULL) >> 16; - *cp++ = ((*ip) & 0x000000000000ff00ULL) >> 8; - *cp = ((*ip) & 0x00000000000000ffULL); -} - -static NCX_GET1I(ulonglong, schar, 0) -static NCX_GET1I(ulonglong, short, 0) -static NCX_GET1I(ulonglong, int, 0) -static NCX_GET1I(ulonglong, longlong, 0) -static NCX_GET1I(ulonglong, ushort, 1) -static NCX_GET1I(ulonglong, uchar, 1) -static NCX_GET1I(ulonglong, uint, 1) -static NCX_GET1I(ulonglong, ulonglong, 1) -static NCX_GET1F(ulonglong, float) -static NCX_GET1F(ulonglong, double) - -static NCX_PUT1I(ulonglong, schar, 0) -static NCX_PUT1I(ulonglong, short, 0) -static NCX_PUT1I(ulonglong, int, 0) -static NCX_PUT1I(ulonglong, longlong, 0) -static NCX_PUT1I(ulonglong, uchar, 1) -static NCX_PUT1I(ulonglong, ushort, 1) -static NCX_PUT1I(ulonglong, uint, 1) -static NCX_PUT1I(ulonglong, ulonglong, 1) -static NCX_PUT1F(ulonglong, float) -static NCX_PUT1F(ulonglong, double) + *cp++ = (uchar)((*ip) >> 56); + *cp++ = (uchar)(((*ip) & 0x00ff000000000000ULL) >> 48); + *cp++ = (uchar)(((*ip) & 0x0000ff0000000000ULL) >> 40); + *cp++ = (uchar)(((*ip) & 0x000000ff00000000ULL) >> 32); + *cp++ = (uchar)(((*ip) & 0x00000000ff000000ULL) >> 24); + *cp++ = (uchar)(((*ip) & 0x0000000000ff0000ULL) >> 16); + *cp++ = (uchar)(((*ip) & 0x000000000000ff00ULL) >> 8); + *cp = (uchar)( (*ip) & 0x00000000000000ffULL); +} + +#if X_SIZEOF_UINT64 != SIZEOF_ULONGLONG +NCX_GET1I(uint64, ulonglong, 1) +#endif +NCX_GET1I(uint64, schar, 0) +NCX_GET1I(uint64, short, 0) +NCX_GET1I(uint64, int, 0) +NCX_GET1I(uint64, long, 0) +NCX_GET1I(uint64, longlong, 0) +NCX_GET1I(uint64, ushort, 1) +NCX_GET1I(uint64, uchar, 1) +NCX_GET1I(uint64, uint, 1) +NCX_GET1F(uint64, float) +NCX_GET1F(uint64, double) + +#if X_SIZEOF_UINT64 != SIZEOF_ULONGLONG +NCX_PUT1I(uint64, ulonglong, 1) +#endif +NCX_PUT1I(uint64, schar, 0) +NCX_PUT1I(uint64, short, 0) +NCX_PUT1I(uint64, int, 0) +NCX_PUT1I(uint64, long, 0) +NCX_PUT1I(uint64, longlong, 0) +NCX_PUT1I(uint64, uchar, 1) +NCX_PUT1I(uint64, ushort, 1) +NCX_PUT1I(uint64, uint, 1) +NCX_PUT1F(uint64, float) +NCX_PUT1F(uint64, double) + /* x_size_t */ @@ -1856,7 +2183,7 @@ static NCX_PUT1F(ulonglong, double) #endif int -ncx_put_size_t(void **xpp, const size_t *ulp) +APIPrefix`x_put_size_t'(void **xpp, const size_t *ulp) { /* similar to put_ix_int() */ uchar *cp = (uchar *) *xpp; @@ -1872,14 +2199,14 @@ ncx_put_size_t(void **xpp, const size_t *ulp) } int -ncx_get_size_t(const void **xpp, size_t *ulp) +APIPrefix`x_get_size_t'(const void **xpp, size_t *ulp) { /* similar to get_ix_int */ const uchar *cp = (const uchar *) *xpp; - *ulp = (unsigned)(*cp++ << 24); - *ulp |= (*cp++ << 16); - *ulp |= (*cp++ << 8); + *ulp = (size_t)(*cp++ << 24); + *ulp |= (size_t)(*cp++ << 16); + *ulp |= (size_t)(*cp++ << 8); *ulp |= *cp; *xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_SIZE_T); @@ -1889,18 +2216,19 @@ ncx_get_size_t(const void **xpp, size_t *ulp) /* x_off_t */ int -ncx_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t) +APIPrefix`x_put_off_t'(void **xpp, const off_t *lp, size_t sizeof_off_t) { - /* similar to put_ix_int() */ - uchar *cp = (uchar *) *xpp; - /* No negative offsets stored in netcdf */ + /* No negative offsets stored in netcdf */ if (*lp < 0) { /* Assume this is an overflow of a 32-bit int... */ - return NC_ERANGE; + DEBUG_RETURN_ERROR(NC_ERANGE) } assert(sizeof_off_t == 4 || sizeof_off_t == 8); + /* similar to put_ix_int() */ + uchar *cp = (uchar *) *xpp; + if (sizeof_off_t == 4) { *cp++ = (uchar) ((*lp) >> 24); *cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16); @@ -1920,13 +2248,13 @@ ncx_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t) *cp = (uchar)( (*lp) & 0x000000ff); #else *cp++ = (uchar) ((*lp) >> 56); - *cp++ = (uchar)(((*lp) & 0x00ff000000000000ULL) >> 48); - *cp++ = (uchar)(((*lp) & 0x0000ff0000000000ULL) >> 40); - *cp++ = (uchar)(((*lp) & 0x000000ff00000000ULL) >> 32); - *cp++ = (uchar)(((*lp) & 0x00000000ff000000ULL) >> 24); - *cp++ = (uchar)(((*lp) & 0x0000000000ff0000ULL) >> 16); - *cp++ = (uchar)(((*lp) & 0x000000000000ff00ULL) >> 8); - *cp = (uchar)( (*lp) & 0x00000000000000ffULL); + *cp++ = (uchar)(((*lp) & 0x00ff000000000000LL) >> 48); + *cp++ = (uchar)(((*lp) & 0x0000ff0000000000LL) >> 40); + *cp++ = (uchar)(((*lp) & 0x000000ff00000000LL) >> 32); + *cp++ = (uchar)(((*lp) & 0x00000000ff000000LL) >> 24); + *cp++ = (uchar)(((*lp) & 0x0000000000ff0000LL) >> 16); + *cp++ = (uchar)(((*lp) & 0x000000000000ff00LL) >> 8); + *cp = (uchar)( (*lp) & 0x00000000000000ffLL); #endif } *xpp = (void *)((char *)(*xpp) + sizeof_off_t); @@ -1934,7 +2262,7 @@ ncx_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t) } int -ncx_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t) +APIPrefix`x_get_off_t'(const void **xpp, off_t *lp, size_t sizeof_off_t) { /* similar to get_ix_int() */ const uchar *cp = (const uchar *) *xpp; @@ -1959,7 +2287,7 @@ ncx_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t) * on this system. Set an error code and return. */ if (*lp != 0) { - return NC_ERANGE; + DEBUG_RETURN_ERROR(NC_ERANGE) } *lp = ((off_t)(*cp++) << 24); @@ -1973,7 +2301,7 @@ ncx_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t) * than 2^32 which is not allowed, but is not caught * by the previous check */ - return NC_ERANGE; + DEBUG_RETURN_ERROR(NC_ERANGE) } #else *lp = ((off_t)(*cp++) << 56); @@ -1990,62 +2318,68 @@ ncx_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t) return NC_NOERR; } -/*----< ncx_get_int32() >--------------------------------------------------*/ +/*----< APIPrefix`x_get_uint32'() >------------------------------------------*/ int -ncx_get_int32(const void **xpp, - int *ip) +APIPrefix`x_get_uint32'(const void **xpp, uint *ip) { +#ifdef WORDS_BIGENDIAN + /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on + * some system, such as HPUX */ + (void) memcpy(ip, *xpp, SIZEOF_UINT); +#else const uchar *cp = (const uchar *) *xpp; - /* cannot call swap4b(), as lp is 8-byte */ - *ip = (*cp++ << 24); - *ip |= (*cp++ << 16); - *ip |= (*cp++ << 8); - *ip |= *cp; - + *ip = (uint)(*cp++ << 24); + *ip = (uint)(*ip | (uint)(*cp++ << 16)); + *ip = (uint)(*ip | (uint)(*cp++ << 8)); + *ip = (uint)(*ip | *cp); +#endif /* advance *xpp 4 bytes */ *xpp = (void *)((const char *)(*xpp) + 4); return NC_NOERR; } -/*----< ncx_get_int64() >-------------------------------------------------*/ +/*----< APIPrefix`x_get_uint64'() >------------------------------------------*/ int -ncx_get_int64(const void **xpp, - long long *llp) +APIPrefix`x_get_uint64'(const void **xpp, unsigned long long *ullp) { +#ifdef WORDS_BIGENDIAN + /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on + * some system, such as HPUX */ + (void) memcpy(ullp, *xpp, SIZEOF_UINT64); +#else const uchar *cp = (const uchar *) *xpp; - /* below is the same as calling swap8b(llp, *xpp) */ - *llp = ((long long)(*cp++) << 56); - *llp |= ((long long)(*cp++) << 48); - *llp |= ((long long)(*cp++) << 40); - *llp |= ((long long)(*cp++) << 32); - *llp |= ((long long)(*cp++) << 24); - *llp |= ((long long)(*cp++) << 16); - *llp |= ((long long)(*cp++) << 8); - *llp |= (long long)*cp; - + /* below is the same as calling swap8b(ullp, *xpp) */ + *ullp = (unsigned long long)(*cp++) << 56; + *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 48); + *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 40); + *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 32); + *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 24); + *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 16); + *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 8); + *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp)); +#endif /* advance *xpp 8 bytes */ *xpp = (void *)((const char *)(*xpp) + 8); return NC_NOERR; } -/*---< ncx_put_int32() >-----------------------------------------------------*/ -/* copy the contents of lp (a signed 32-bit integer) to xpp in Big Endian +/*---< APIPrefix`x_put_uint32'() >-------------------------------------------*/ +/* copy the contents of ip (an unsigned 32-bit integer) to xpp in Big Endian * form and advance *xpp 4 bytes */ int -ncx_put_int32(void **xpp, - const int ip) +APIPrefix`x_put_uint32'(void **xpp, const unsigned int ip) { #ifdef WORDS_BIGENDIAN - int *ptr = (int*) (*xpp); /* typecast to 4-byte integer */ - *ptr = ip; + /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on + * some system, such as HPUX */ + (void) memcpy(*xpp, &ip, X_SIZEOF_UINT); #else /* bitwise shifts below are to produce an integer in Big Endian */ - /* cannot call swap4b(), as lp is 8-byte */ uchar *cp = (uchar *) *xpp; *cp++ = (uchar)((ip & 0xff000000) >> 24); *cp++ = (uchar)((ip & 0x00ff0000) >> 16); @@ -2058,28 +2392,28 @@ ncx_put_int32(void **xpp, return NC_NOERR; } -/*---< ncx_put_int64() >-----------------------------------------------------*/ -/* copy the contents of lp (a signed 64-bit integer) to xpp in Big Endian +/*---< APIPrefix`x_put_uint64'() >-------------------------------------------*/ +/* copy the contents of ip (an unsigned 64-bit integer) to xpp in Big Endian * form and advance *xpp 8 bytes */ int -ncx_put_int64(void **xpp, - const long long ip) +APIPrefix`x_put_uint64'(void **xpp, const unsigned long long ip) { #ifdef WORDS_BIGENDIAN - long long *ptr = (long long*) (*xpp); /* typecast to 8-byte integer */ - *ptr = ip; + /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on + * some system, such as HPUX */ + (void) memcpy(*xpp, &ip, X_SIZEOF_UINT64); #else uchar *cp = (uchar *) *xpp; /* below is the same as calling swap8b(*xpp, &ip) */ - *cp++ = (uchar)((ip & 0xff00000000000000ULL) >> 56); - *cp++ = (uchar)((ip & 0x00ff000000000000ULL) >> 48); - *cp++ = (uchar)((ip & 0x0000ff0000000000ULL) >> 40); - *cp++ = (uchar)((ip & 0x000000ff00000000ULL) >> 32); - *cp++ = (uchar)((ip & 0x00000000ff000000ULL) >> 24); - *cp++ = (uchar)((ip & 0x0000000000ff0000ULL) >> 16); - *cp++ = (uchar)((ip & 0x000000000000ff00ULL) >> 8); - *cp = (uchar)( ip & 0x00000000000000ffULL); + *cp++ = (uchar) (ip >> 56); + *cp++ = (uchar)((ip & 0x00ff000000000000LL) >> 48); + *cp++ = (uchar)((ip & 0x0000ff0000000000LL) >> 40); + *cp++ = (uchar)((ip & 0x000000ff00000000LL) >> 32); + *cp++ = (uchar)((ip & 0x00000000ff000000LL) >> 24); + *cp++ = (uchar)((ip & 0x0000000000ff0000LL) >> 16); + *cp++ = (uchar)((ip & 0x000000000000ff00LL) >> 8); + *cp = (uchar) (ip & 0x00000000000000ffLL); #endif /* advance *xpp 8 bytes */ *xpp = (void *)((char *)(*xpp) + 8); @@ -2092,8 +2426,8 @@ ncx_put_int64(void **xpp, * Aggregate numeric conversion functions. */ dnl -define(`GETN_CheckBND', `ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, `|| xp[i] < 0', `|| xp[i] < Imin($2)')')')dnl -define(`PUTN_CheckBND', `ifelse(index(`$2',`u'), 0, , `ifelse(index(`$1',`u'), 0, `|| tp[i] < 0', `|| tp[i] < Xmin($1)')')')dnl +define(`GETN_CheckBND', `ifelse(index(`$1',`u'), 0, , index(`$2',`u'), 0, `|| xp[i] < 0', `|| xp[i] < Imin($2)')')dnl +define(`PUTN_CheckBND', `ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| tp[i] < 0', `|| tp[i] < Xmin($1)')')dnl dnl dnl dnl dnl @@ -2102,8 +2436,8 @@ dnl NCX_GETN_Byte_Body (body for one byte types on diagonal) dnl define(`NCX_GETN_Byte_Body',dnl `dnl - (void) memcpy(tp, *xpp, nelems); - *xpp = (void *)((schar *)(*xpp) + nelems); + (void) memcpy(tp, *xpp, (size_t)nelems); + *xpp = (void *)((char *)(*xpp) + nelems); return NC_NOERR; ')dnl dnl dnl dnl @@ -2112,99 +2446,86 @@ dnl NCX_PAD_GETN_Byte_body (body for one byte types on diagonal) dnl define(`NCX_PAD_GETN_Byte_Body',dnl `dnl - size_t rndup = nelems % X_ALIGN; + IntType rndup = nelems % X_ALIGN; - if(rndup) + if (rndup) rndup = X_ALIGN - rndup; - (void) memcpy(tp, *xpp, nelems); + (void) memcpy(tp, *xpp, (size_t)nelems); *xpp = (void *)((char *)(*xpp) + nelems + rndup); return NC_NOERR; ')dnl dnl dnl dnl dnl -dnl NCX_GETN_CHAR(Type) +dnl NCX_GETN_BYTE(xtype, itype) dnl -define(`NCX_GETN_CHAR',dnl +define(`NCX_GETN_BYTE',dnl `dnl int -ncx_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp) +APIPrefix`x_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp) { - int status = NC_NOERR; - $1 *xp = ($1 *)(*xpp); + int status = NC_NOERR; + $1 *xp = ($1 *)(*xpp); - while(nelems-- != 0) - { -ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, ` if (*xp < 0) status = NC_ERANGE;')') - *tp++ = *xp++; - } + while (nelems-- != 0) { + ifelse(index(`$1',`u'), 0, , + index(`$2',`u'), 0, ` + if (*xp < 0) { + ifdef(`ERANGE_FILL',`*tp = FillDefaultValue($2);') + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because tp is unsigned */ + SKIP_LOOP(xp, tp) + }')dnl - *xpp = (const void *)xp; - return status; + *tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++); /* type cast from $1 to $2 */ + } + + *xpp = (const void *)xp; + return status; } ')dnl dnl dnl dnl dnl -dnl NCX_PAD_GETN_CHAR(Type) +dnl NCX_PAD_GETN_BYTE(xtype, itype) dnl -define(`NCX_PAD_GETN_CHAR',dnl +define(`NCX_PAD_GETN_BYTE',dnl `dnl int -ncx_pad_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp) +APIPrefix`x_pad_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp) { - int status = NC_NOERR; - size_t rndup = nelems % X_ALIGN; - $1 *xp = ($1 *) *xpp; + int status = NC_NOERR; + IntType rndup = nelems % X_ALIGN; + $1 *xp = ($1 *) *xpp; - if(rndup) - rndup = X_ALIGN - rndup; + if (rndup) + rndup = X_ALIGN - rndup; - while(nelems-- != 0) - { -ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, ` if (*xp < 0) status = NC_ERANGE;')') - *tp++ = *xp++; - } - - *xpp = (void *)(xp + rndup); - return status; -} -')dnl -dnl dnl dnl -dnl -dnl NCX_GETNo(XType, Type) deprecated -dnl -define(`NCX_GETNo',dnl -`dnl -int -ncx_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp) -{ - const char *xp = (const char *) *xpp; - int status = NC_NOERR; - $1 xx; + while (nelems-- != 0) { + ifelse(index(`$1',`u'), 0, , + index(`$2',`u'), 0, ` + if (*xp < 0) { + ifdef(`ERANGE_FILL', `*tp = FillDefaultValue($2);') + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because tp is unsigned */ + SKIP_LOOP(xp, tp) + }')dnl - for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++) - { - const int lstatus = ncx_get_$1_$1(xp, &xx); - *tp = ($2)xx; - if(lstatus != NC_NOERR) - status = lstatus; - } + *tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++); /* type cast from $1 to $2 */ + } - *xpp = (const void *)xp; - return status; + *xpp = (void *)(xp + rndup); + return status; } ')dnl dnl dnl dnl dnl -dnl NCX_GETN(XType, Type, condition) +dnl NCX_GETN(xtype, itype) dnl define(`NCX_GETN',dnl `dnl int -ncx_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp) +APIPrefix`x_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp) { -`#'if _SX && Xsizeof($1) == Isizeof($1) +`#'if defined(_SX) && _SX != 0 && Xsizeof($1) == Isizeof($1) /* basic algorithm is: * - ensure sane alignment of input data @@ -2227,7 +2548,7 @@ ncx_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp) for (j=0; j Xmax($1) ifelse(index(`$2',`u'), 0, , `ifelse(index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')')) - status = NC_ERANGE; - *xp++ = ($1) (signed)*tp++; - } + while (nelems-- != 0) { + if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')) { + FillValue($1, xp) + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) + SKIP_LOOP(xp, tp) + } + *xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */ + } - *xpp = (void *)xp; - return status; + *xpp = (void *)xp; + return status; } ')dnl dnl dnl dnl dnl -dnl NCX_PAD_PUTN_CHAR(xtype, ttype) +dnl NCX_PAD_PUTN_BYTE(xtype, ttype) dnl -define(`NCX_PAD_PUTN_CHAR',dnl +define(`NCX_PAD_PUTN_BYTE',dnl `dnl int -ncx_pad_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp) +APIPrefix`x_pad_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp) { - int status = NC_NOERR; - size_t rndup = nelems % X_ALIGN; - $1 *xp = ($1 *) *xpp; - - if(rndup) - rndup = X_ALIGN - rndup; + int status = NC_NOERR; + IntType rndup = nelems % X_ALIGN; + $1 *xp = ($1 *) *xpp; - while(nelems-- != 0) - { - if(*tp > Xmax($1) ifelse(index(`$2',`u'), 0, , `ifelse(index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')')) - status = NC_ERANGE; - *xp++ = ($1) (signed) *tp++; - } + if (rndup) rndup = X_ALIGN - rndup; + while (nelems-- != 0) { + if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')) { + FillValue($1, xp) + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) + SKIP_LOOP(xp, tp) + } + *xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */ + } - if(rndup) - { - (void) memcpy(xp, nada, rndup); - xp += rndup; - } - - *xpp = (void *)xp; - return status; -} -')dnl -dnl dnl dnl -dnl -dnl NCX_PUTNo(XType, Type) deprecated -dnl -define(`NCX_PUTNo',dnl -`dnl -int -ncx_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp) -{ - char *xp = (char *) *xpp; - int status = NC_NOERR; - $1 xx; - for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++) - { - xx = ($1) *tp; - { - int lstatus = ncx_put_$1_$1(xp, &xx); - if(lstatus != NC_NOERR) - status = lstatus; - } - } + if (rndup) { + (void) memcpy(xp, nada, (size_t)rndup); + xp += rndup; + } - *xpp = (void *)xp; - return status; + *xpp = (void *)xp; + return status; } ')dnl dnl dnl dnl dnl -dnl NCX_PUTN(XType, Type, condition) +dnl NCX_PUTN(xtype, itype) dnl define(`NCX_PUTN',dnl `dnl int -ncx_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp) +APIPrefix`x_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp) { -`#'if _SX && Xsizeof($1) == Isizeof($1) +`#'if defined(_SX) && _SX != 0 && Xsizeof($1) == Isizeof($1) /* basic algorithm is: * - ensure sane alignment of output data @@ -2433,7 +2730,7 @@ ncx_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp) $1 *xp; ifelse( $1$2, intfloat,dnl `dnl - double d; /* special case for ncx_putn_int_float */ + double d; /* special case for APIPrefix`x_putn_int_float' */ ')dnl int nrange = 0; /* number of range errors */ int realign = 0; /* "do we need to fix input data alignment?" */ @@ -2472,7 +2769,7 @@ ifelse( $1$2, intfloat,dnl } /* copy workspace back if necessary */ if (realign) { - memcpy(*xpp, tmp, ni*Xsizeof($1)); + memcpy(*xpp, tmp, (size_t)*ni*Xsizeof($1)); xp = ($1 *) *xpp; } /* update xpp and tp */ @@ -2489,8 +2786,8 @@ ifelse( $1$2, intfloat,dnl for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++) { - int lstatus = ncx_put_$1_$2(xp, tp); - if(lstatus != NC_NOERR) + int lstatus = APIPrefix`x_put_'NC_TYPE($1)_$2(xp, tp, fillp); + if (status == NC_NOERR) /* report the first encountered error */ status = lstatus; } @@ -2506,23 +2803,23 @@ dnl define(`NCX_PAD_PUTN_SHORT',dnl `dnl int -ncx_pad_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp) +APIPrefix`x_pad_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp) { - const size_t rndup = nelems % 2; + const IntType rndup = nelems % X_SIZEOF_SHORT; char *xp = (char *) *xpp; int status = NC_NOERR; for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++) { - int lstatus = ncx_put_$1_$2(xp, tp); - if(lstatus != NC_NOERR) + int lstatus = APIPrefix`x_put_'NC_TYPE($1)_$2(xp, tp, fillp); + if (status == NC_NOERR) /* report the first encountered error */ status = lstatus; } - if(rndup != 0) + if (rndup != 0) { - (void) memcpy(xp, nada, Xsizeof($1)); + (void) memcpy(xp, nada, (size_t)(Xsizeof($1))); xp += Xsizeof($1); } @@ -2539,186 +2836,237 @@ dnl dnl dnl /* schar ---------------------------------------------------------------------*/ -dnl NCX_GETN_CHAR(schar, schar) -int -ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) -{ - NCX_GETN_Byte_Body -} -dnl NCX_GETN_CHAR(schar, uchar) +dnl NCX_GETN_BYTE(schar, schar) int -ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) +APIPrefix`x_getn_'NC_TYPE(schar)_schar(const void **xpp, IntType nelems, schar *tp) { NCX_GETN_Byte_Body } -NCX_GETN_CHAR(schar, short) -NCX_GETN_CHAR(schar, int) -NCX_GETN_CHAR(schar, float) -NCX_GETN_CHAR(schar, double) -NCX_GETN_CHAR(schar, longlong) -NCX_GETN_CHAR(schar, ushort) -NCX_GETN_CHAR(schar, uint) -NCX_GETN_CHAR(schar, ulonglong) +NCX_GETN_BYTE(schar, uchar) +NCX_GETN_BYTE(schar, short) +NCX_GETN_BYTE(schar, int) +NCX_GETN_BYTE(schar, long) +NCX_GETN_BYTE(schar, float) +NCX_GETN_BYTE(schar, double) +NCX_GETN_BYTE(schar, longlong) +NCX_GETN_BYTE(schar, ushort) +NCX_GETN_BYTE(schar, uint) +NCX_GETN_BYTE(schar, ulonglong) -dnl NCX_PAD_GETN_CHAR(schar, schar) +dnl NCX_PAD_GETN_BYTE(schar, schar) int -ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) +APIPrefix`x_pad_getn_'NC_TYPE(schar)_schar(const void **xpp, IntType nelems, schar *tp) { NCX_PAD_GETN_Byte_Body } -dnl NCX_PAD_GETN_CHAR(schar, uchar) -int -ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) -{ - NCX_PAD_GETN_Byte_Body -} -NCX_PAD_GETN_CHAR(schar, short) -NCX_PAD_GETN_CHAR(schar, int) -NCX_PAD_GETN_CHAR(schar, float) -NCX_PAD_GETN_CHAR(schar, double) -NCX_PAD_GETN_CHAR(schar, longlong) -NCX_PAD_GETN_CHAR(schar, ushort) -NCX_PAD_GETN_CHAR(schar, uint) -NCX_PAD_GETN_CHAR(schar, ulonglong) +NCX_PAD_GETN_BYTE(schar, uchar) +NCX_PAD_GETN_BYTE(schar, short) +NCX_PAD_GETN_BYTE(schar, int) +NCX_PAD_GETN_BYTE(schar, long) +NCX_PAD_GETN_BYTE(schar, float) +NCX_PAD_GETN_BYTE(schar, double) +NCX_PAD_GETN_BYTE(schar, longlong) +NCX_PAD_GETN_BYTE(schar, ushort) +NCX_PAD_GETN_BYTE(schar, uint) +NCX_PAD_GETN_BYTE(schar, ulonglong) -dnl NCX_PUTN_CHAR(schar, schar) -int -ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) -{ - NCX_PUTN_Byte_Body -} -dnl NCX_PUTN_CHAR(schar, uchar) +dnl NCX_PUTN_BYTE(schar, schar) int -ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +APIPrefix`x_putn_'NC_TYPE(schar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp) { NCX_PUTN_Byte_Body } -NCX_PUTN_CHAR(schar, short) -NCX_PUTN_CHAR(schar, int) -NCX_PUTN_CHAR(schar, float) -NCX_PUTN_CHAR(schar, double) -NCX_PUTN_CHAR(schar, longlong) -NCX_PUTN_CHAR(schar, ushort) -NCX_PUTN_CHAR(schar, uint) -NCX_PUTN_CHAR(schar, ulonglong) +NCX_PUTN_BYTE(schar, uchar) +NCX_PUTN_BYTE(schar, short) +NCX_PUTN_BYTE(schar, int) +NCX_PUTN_BYTE(schar, long) +NCX_PUTN_BYTE(schar, float) +NCX_PUTN_BYTE(schar, double) +NCX_PUTN_BYTE(schar, longlong) +NCX_PUTN_BYTE(schar, ushort) +NCX_PUTN_BYTE(schar, uint) +NCX_PUTN_BYTE(schar, ulonglong) -dnl NCX_PAD_PUTN_CHAR(schar, schar) -int -ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) -{ - NCX_PAD_PUTN_Byte_Body -} -dnl NCX_PAD_PUTN_CHAR(schar, uchar) +dnl NCX_PAD_PUTN_BYTE(schar, schar) int -ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +APIPrefix`x_pad_putn_'NC_TYPE(schar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp) { NCX_PAD_PUTN_Byte_Body } -NCX_PAD_PUTN_CHAR(schar, short) -NCX_PAD_PUTN_CHAR(schar, int) -NCX_PAD_PUTN_CHAR(schar, float) -NCX_PAD_PUTN_CHAR(schar, double) -NCX_PAD_PUTN_CHAR(schar, longlong) -NCX_PAD_PUTN_CHAR(schar, ushort) -NCX_PAD_PUTN_CHAR(schar, uint) -NCX_PAD_PUTN_CHAR(schar, ulonglong) +NCX_PAD_PUTN_BYTE(schar, uchar) +NCX_PAD_PUTN_BYTE(schar, short) +NCX_PAD_PUTN_BYTE(schar, int) +NCX_PAD_PUTN_BYTE(schar, long) +NCX_PAD_PUTN_BYTE(schar, float) +NCX_PAD_PUTN_BYTE(schar, double) +NCX_PAD_PUTN_BYTE(schar, longlong) +NCX_PAD_PUTN_BYTE(schar, ushort) +NCX_PAD_PUTN_BYTE(schar, uint) +NCX_PAD_PUTN_BYTE(schar, ulonglong) /* uchar ---------------------------------------------------------------------*/ dnl -dnl NCX_GETN_CHAR(uchar, schar) +dnl NCX_GETN_BYTE(uchar, schar) int -ncx_getn_uchar_schar(const void **xpp, size_t nelems, schar *tp) +APIPrefix`x_getn_'NC_TYPE(uchar)_schar(const void **xpp, IntType nelems, schar *tp) { - NCX_GETN_Byte_Body + int status = NC_NOERR; + uchar *xp = (uchar *)(*xpp); + + while (nelems-- != 0) { + if (*xp > SCHAR_MAX) { + *tp = NC_FILL_BYTE; + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) + SKIP_LOOP(xp, tp) + } + *tp++ = (schar) *xp++; /* type cast from uchar to schar */ + } + + *xpp = (const void *)xp; + return status; } -dnl NCX_GETN_CHAR(uchar, uchar) +dnl NCX_GETN_BYTE(uchar, uchar) int -ncx_getn_uchar_uchar(const void **xpp, size_t nelems, uchar *tp) +APIPrefix`x_getn_'NC_TYPE(uchar)_uchar(const void **xpp, IntType nelems, uchar *tp) { NCX_GETN_Byte_Body } -NCX_GETN_CHAR(uchar, short) -NCX_GETN_CHAR(uchar, int) -NCX_GETN_CHAR(uchar, float) -NCX_GETN_CHAR(uchar, double) -NCX_GETN_CHAR(uchar, longlong) -NCX_GETN_CHAR(uchar, ushort) -NCX_GETN_CHAR(uchar, uint) -NCX_GETN_CHAR(uchar, ulonglong) +NCX_GETN_BYTE(uchar, short) +NCX_GETN_BYTE(uchar, int) +NCX_GETN_BYTE(uchar, long) +NCX_GETN_BYTE(uchar, float) +NCX_GETN_BYTE(uchar, double) +NCX_GETN_BYTE(uchar, longlong) +NCX_GETN_BYTE(uchar, ushort) +NCX_GETN_BYTE(uchar, uint) +NCX_GETN_BYTE(uchar, ulonglong) + +dnl NCX_PAD_GETN_BYTE(uchar, schar) +int +APIPrefix`x_pad_getn_'NC_TYPE(uchar)_schar(const void **xpp, IntType nelems, schar *tp) +{ + int status = NC_NOERR; + IntType rndup = nelems % X_ALIGN; + uchar *xp = (uchar *) *xpp; + + if (rndup) rndup = X_ALIGN - rndup; + + while (nelems-- != 0) { + if (*xp > SCHAR_MAX) { + *tp = NC_FILL_BYTE; + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) + SKIP_LOOP(xp, tp) + } + *tp++ = (schar) *xp++; /* type cast from uchar to schar */ + } -dnl NCX_PAD_GETN_CHAR(uchar, schar) -int -ncx_pad_getn_uchar_schar(const void **xpp, size_t nelems, schar *tp) -{ - NCX_PAD_GETN_Byte_Body + *xpp = (void *)(xp + rndup); + return status; } -dnl NCX_PAD_GETN_CHAR(uchar, uchar) +dnl NCX_PAD_GETN_BYTE(uchar, uchar) int -ncx_pad_getn_uchar_uchar(const void **xpp, size_t nelems, uchar *tp) +APIPrefix`x_pad_getn_'NC_TYPE(uchar)_uchar(const void **xpp, IntType nelems, uchar *tp) { NCX_PAD_GETN_Byte_Body } -NCX_PAD_GETN_CHAR(uchar, short) -NCX_PAD_GETN_CHAR(uchar, int) -NCX_PAD_GETN_CHAR(uchar, float) -NCX_PAD_GETN_CHAR(uchar, double) -NCX_PAD_GETN_CHAR(uchar, longlong) -NCX_PAD_GETN_CHAR(uchar, ushort) -NCX_PAD_GETN_CHAR(uchar, uint) -NCX_PAD_GETN_CHAR(uchar, ulonglong) +NCX_PAD_GETN_BYTE(uchar, short) +NCX_PAD_GETN_BYTE(uchar, int) +NCX_PAD_GETN_BYTE(uchar, long) +NCX_PAD_GETN_BYTE(uchar, float) +NCX_PAD_GETN_BYTE(uchar, double) +NCX_PAD_GETN_BYTE(uchar, longlong) +NCX_PAD_GETN_BYTE(uchar, ushort) +NCX_PAD_GETN_BYTE(uchar, uint) +NCX_PAD_GETN_BYTE(uchar, ulonglong) + +dnl NCX_PUTN_BYTE(uchar, schar) +int +APIPrefix`x_putn_'NC_TYPE(uchar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp) +{ + int status = NC_NOERR; + uchar *xp = (uchar *) *xpp; + + while (nelems-- != 0) { + if (*tp < 0) { + FillValue(uchar, xp) + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) + SKIP_LOOP(xp, tp) + } + *xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */ + } -dnl NCX_PUTN_CHAR(uchar, schar) -int -ncx_putn_uchar_schar(void **xpp, size_t nelems, const schar *tp) -{ - NCX_PUTN_Byte_Body + *xpp = (void *)xp; + return status; } -dnl NCX_PUTN_CHAR(uchar, uchar) +dnl NCX_PUTN_BYTE(uchar, uchar) int -ncx_putn_uchar_uchar(void **xpp, size_t nelems, const uchar *tp) +APIPrefix`x_putn_'NC_TYPE(uchar)_uchar(void **xpp, IntType nelems, const uchar *tp, void *fillp) { NCX_PUTN_Byte_Body } -NCX_PUTN_CHAR(uchar, short) -NCX_PUTN_CHAR(uchar, int) -NCX_PUTN_CHAR(uchar, float) -NCX_PUTN_CHAR(uchar, double) -NCX_PUTN_CHAR(uchar, longlong) -NCX_PUTN_CHAR(uchar, ushort) -NCX_PUTN_CHAR(uchar, uint) -NCX_PUTN_CHAR(uchar, ulonglong) +NCX_PUTN_BYTE(uchar, short) +NCX_PUTN_BYTE(uchar, int) +NCX_PUTN_BYTE(uchar, long) +NCX_PUTN_BYTE(uchar, float) +NCX_PUTN_BYTE(uchar, double) +NCX_PUTN_BYTE(uchar, longlong) +NCX_PUTN_BYTE(uchar, ushort) +NCX_PUTN_BYTE(uchar, uint) +NCX_PUTN_BYTE(uchar, ulonglong) + +dnl NCX_PAD_PUTN_BYTE(uchar, schar) +int +APIPrefix`x_pad_putn_'NC_TYPE(uchar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp) +{ + int status = NC_NOERR; + IntType rndup = nelems % X_ALIGN; + uchar *xp = (uchar *) *xpp; + + if (rndup) rndup = X_ALIGN - rndup; + + while (nelems-- != 0) { + if (*tp < 0) { + FillValue(uchar, xp) + DEBUG_ASSIGN_ERROR(status, NC_ERANGE) + SKIP_LOOP(xp, tp) + } + *xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */ + } -dnl NCX_PAD_PUTN_UCHAR(uchar, schar) -int -ncx_pad_putn_uchar_schar(void **xpp, size_t nelems, const schar *tp) -{ - NCX_PAD_PUTN_Byte_Body + if (rndup) { + (void) memcpy(xp, nada, (size_t)rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; } dnl NCX_PAD_PUTN_UCHAR(uchar, uchar) int -ncx_pad_putn_uchar_uchar(void **xpp, size_t nelems, const uchar *tp) +APIPrefix`x_pad_putn_'NC_TYPE(uchar)_uchar(void **xpp, IntType nelems, const uchar *tp, void *fillp) { NCX_PAD_PUTN_Byte_Body } -NCX_PAD_PUTN_CHAR(uchar, short) -NCX_PAD_PUTN_CHAR(uchar, int) -NCX_PAD_PUTN_CHAR(uchar, float) -NCX_PAD_PUTN_CHAR(uchar, double) -NCX_PAD_PUTN_CHAR(uchar, longlong) -NCX_PAD_PUTN_CHAR(uchar, ushort) -NCX_PAD_PUTN_CHAR(uchar, uint) -NCX_PAD_PUTN_CHAR(uchar, ulonglong) +NCX_PAD_PUTN_BYTE(uchar, short) +NCX_PAD_PUTN_BYTE(uchar, int) +NCX_PAD_PUTN_BYTE(uchar, long) +NCX_PAD_PUTN_BYTE(uchar, float) +NCX_PAD_PUTN_BYTE(uchar, double) +NCX_PAD_PUTN_BYTE(uchar, longlong) +NCX_PAD_PUTN_BYTE(uchar, ushort) +NCX_PAD_PUTN_BYTE(uchar, uint) +NCX_PAD_PUTN_BYTE(uchar, ulonglong) /* short ---------------------------------------------------------------------*/ #if X_SIZEOF_SHORT == SIZEOF_SHORT /* optimized version */ int -ncx_getn_short_short(const void **xpp, size_t nelems, short *tp) +APIPrefix`x_getn_'NC_TYPE(short)_short(const void **xpp, IntType nelems, short *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(short)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_SHORT); # else swapn2b(tp, *xpp, nelems); # endif @@ -2730,6 +3078,7 @@ NCX_GETN(short, short) #endif NCX_GETN(short, schar) NCX_GETN(short, int) +NCX_GETN(short, long) NCX_GETN(short, float) NCX_GETN(short, double) NCX_GETN(short, longlong) @@ -2742,6 +3091,7 @@ NCX_PAD_GETN_SHORT(short, schar) NCX_PAD_GETN_SHORT(short, uchar) NCX_PAD_GETN_SHORT(short, short) NCX_PAD_GETN_SHORT(short, int) +NCX_PAD_GETN_SHORT(short, long) NCX_PAD_GETN_SHORT(short, float) NCX_PAD_GETN_SHORT(short, double) NCX_PAD_GETN_SHORT(short, uint) @@ -2752,10 +3102,10 @@ NCX_PAD_GETN_SHORT(short, ushort) #if X_SIZEOF_SHORT == SIZEOF_SHORT /* optimized version */ int -ncx_putn_short_short(void **xpp, size_t nelems, const short *tp) +APIPrefix`x_putn_'NC_TYPE(short)_short(void **xpp, IntType nelems, const short *tp, void *fillp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_SHORT); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_SHORT); # else swapn2b(*xpp, tp, nelems); # endif @@ -2767,6 +3117,7 @@ NCX_PUTN(short, short) #endif NCX_PUTN(short, schar) NCX_PUTN(short, int) +NCX_PUTN(short, long) NCX_PUTN(short, float) NCX_PUTN(short, double) NCX_PUTN(short, longlong) @@ -2779,6 +3130,7 @@ NCX_PAD_PUTN_SHORT(short, schar) NCX_PAD_PUTN_SHORT(short, uchar) NCX_PAD_PUTN_SHORT(short, short) NCX_PAD_PUTN_SHORT(short, int) +NCX_PAD_PUTN_SHORT(short, long) NCX_PAD_PUTN_SHORT(short, float) NCX_PAD_PUTN_SHORT(short, double) NCX_PAD_PUTN_SHORT(short, uint) @@ -2792,10 +3144,10 @@ NCX_PAD_PUTN_SHORT(short, ushort) #if X_SIZEOF_USHORT == SIZEOF_USHORT /* optimized version */ int -ncx_getn_ushort_ushort(const void **xpp, size_t nelems, unsigned short *tp) +APIPrefix`x_getn_'NC_TYPE(ushort)_ushort(const void **xpp, IntType nelems, unsigned short *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(unsigned short)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_USHORT); # else swapn2b(tp, *xpp, nelems); # endif @@ -2808,6 +3160,7 @@ NCX_GETN(ushort, ushort) NCX_GETN(ushort, schar) NCX_GETN(ushort, short) NCX_GETN(ushort, int) +NCX_GETN(ushort, long) NCX_GETN(ushort, float) NCX_GETN(ushort, double) NCX_GETN(ushort, longlong) @@ -2816,23 +3169,24 @@ NCX_GETN(ushort, uint) NCX_GETN(ushort, ulonglong) NCX_PAD_GETN_SHORT(ushort, schar) -NCX_PAD_GETN_SHORT(ushort, uchar) NCX_PAD_GETN_SHORT(ushort, short) -NCX_PAD_GETN_SHORT(ushort, ushort) NCX_PAD_GETN_SHORT(ushort, int) -NCX_PAD_GETN_SHORT(ushort, uint) +NCX_PAD_GETN_SHORT(ushort, long) NCX_PAD_GETN_SHORT(ushort, float) NCX_PAD_GETN_SHORT(ushort, double) +NCX_PAD_GETN_SHORT(ushort, uchar) +NCX_PAD_GETN_SHORT(ushort, ushort) +NCX_PAD_GETN_SHORT(ushort, uint) NCX_PAD_GETN_SHORT(ushort, longlong) NCX_PAD_GETN_SHORT(ushort, ulonglong) #if X_SIZEOF_USHORT == SIZEOF_USHORT /* optimized version */ int -ncx_putn_ushort_ushort(void **xpp, size_t nelems, const unsigned short *tp) +APIPrefix`x_putn_'NC_TYPE(ushort)_ushort(void **xpp, IntType nelems, const unsigned short *tp, void *fillp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_USHORT); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_USHORT); # else swapn2b(*xpp, tp, nelems); # endif @@ -2845,6 +3199,7 @@ NCX_PUTN(ushort, ushort) NCX_PUTN(ushort, schar) NCX_PUTN(ushort, short) NCX_PUTN(ushort, int) +NCX_PUTN(ushort, long) NCX_PUTN(ushort, float) NCX_PUTN(ushort, double) NCX_PUTN(ushort, longlong) @@ -2856,6 +3211,7 @@ NCX_PAD_PUTN_SHORT(ushort, schar) NCX_PAD_PUTN_SHORT(ushort, uchar) NCX_PAD_PUTN_SHORT(ushort, short) NCX_PAD_PUTN_SHORT(ushort, int) +NCX_PAD_PUTN_SHORT(ushort, long) NCX_PAD_PUTN_SHORT(ushort, float) NCX_PAD_PUTN_SHORT(ushort, double) NCX_PAD_PUTN_SHORT(ushort, uint) @@ -2869,10 +3225,10 @@ NCX_PAD_PUTN_SHORT(ushort, ushort) #if X_SIZEOF_INT == SIZEOF_INT /* optimized version */ int -ncx_getn_int_int(const void **xpp, size_t nelems, int *tp) +APIPrefix`x_getn_'NC_TYPE(int)_int(const void **xpp, IntType nelems, int *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(int)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_INT); # else swapn4b(tp, *xpp, nelems); # endif @@ -2884,6 +3240,7 @@ NCX_GETN(int, int) #endif NCX_GETN(int, schar) NCX_GETN(int, short) +NCX_GETN(int, long) NCX_GETN(int, float) NCX_GETN(int, double) NCX_GETN(int, longlong) @@ -2895,10 +3252,10 @@ NCX_GETN(int, ulonglong) #if X_SIZEOF_INT == SIZEOF_INT /* optimized version */ int -ncx_putn_int_int(void **xpp, size_t nelems, const int *tp) +APIPrefix`x_putn_'NC_TYPE(int)_int(void **xpp, IntType nelems, const int *tp, void *fillp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT); # else swapn4b(*xpp, tp, nelems); # endif @@ -2910,6 +3267,7 @@ NCX_PUTN(int, int) #endif NCX_PUTN(int, schar) NCX_PUTN(int, short) +NCX_PUTN(int, long) NCX_PUTN(int, float) NCX_PUTN(int, double) NCX_PUTN(int, longlong) @@ -2923,10 +3281,10 @@ NCX_PUTN(int, ulonglong) #if X_SIZEOF_UINT == SIZEOF_UINT /* optimized version */ int -ncx_getn_uint_uint(const void **xpp, size_t nelems, unsigned int *tp) +APIPrefix`x_getn_'NC_TYPE(uint)_uint(const void **xpp, IntType nelems, unsigned int *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(uint)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UINT); # else swapn4b(tp, *xpp, nelems); # endif @@ -2939,6 +3297,7 @@ NCX_GETN(uint, uint) NCX_GETN(uint, schar) NCX_GETN(uint, short) NCX_GETN(uint, int) +NCX_GETN(uint, long) NCX_GETN(uint, float) NCX_GETN(uint, double) NCX_GETN(uint, longlong) @@ -2949,10 +3308,10 @@ NCX_GETN(uint, ulonglong) #if X_SIZEOF_UINT == SIZEOF_UINT /* optimized version */ int -ncx_putn_uint_uint(void **xpp, size_t nelems, const unsigned int *tp) +APIPrefix`x_putn_'NC_TYPE(uint)_uint(void **xpp, IntType nelems, const unsigned int *tp, void *fillp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_UINT); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT); # else swapn4b(*xpp, tp, nelems); # endif @@ -2965,6 +3324,7 @@ NCX_PUTN(uint, uint) NCX_PUTN(uint, schar) NCX_PUTN(uint, short) NCX_PUTN(uint, int) +NCX_PUTN(uint, long) NCX_PUTN(uint, float) NCX_PUTN(uint, double) NCX_PUTN(uint, longlong) @@ -2978,23 +3338,23 @@ NCX_PUTN(uint, ulonglong) #if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) /* optimized version */ int -ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) +APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nelems, float *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(float)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_FLOAT); # else swapn4b(tp, *xpp, nelems); # endif *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_FLOAT); return NC_NOERR; } -#elif vax +#elif defined(vax) && vax != 0 int -ncx_getn_float_float(const void **xpp, size_t nfloats, float *ip) +APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nfloats, float *ip) { float *const end = ip + nfloats; - while(ip < end) + while (ip < end) { GET_VAX_DFLOAT_Body(`(*xpp)') @@ -3005,15 +3365,15 @@ GET_VAX_DFLOAT_Body(`(*xpp)') } #else int -ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) +APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nelems, float *tp) { const char *xp = *xpp; int status = NC_NOERR; for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) { - const int lstatus = ncx_get_float_float(xp, tp); - if(lstatus != NC_NOERR) + const int lstatus = APIPrefix`x_get_'NC_TYPE(float)_float(xp, tp, fillp); + if (status == NC_NOERR) /* report the first encountered error */ status = lstatus; } @@ -3025,6 +3385,7 @@ ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) NCX_GETN(float, schar) NCX_GETN(float, short) NCX_GETN(float, int) +NCX_GETN(float, long) NCX_GETN(float, double) NCX_GETN(float, longlong) NCX_GETN(float, ushort) @@ -3032,45 +3393,38 @@ NCX_GETN(float, uchar) NCX_GETN(float, uint) NCX_GETN(float, ulonglong) +int +APIPrefix`x_putn_'NC_TYPE(float)_float(void **xpp, IntType nelems, const float *tp, void *fillp) #if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) /* optimized version */ -int -ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_FLOAT); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_FLOAT); # else swapn4b(*xpp, tp, nelems); # endif *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_FLOAT); return NC_NOERR; } -#elif vax -int -ncx_putn_float_float(void **xpp, size_t nfloats, const float *ip) +#elif defined(vax) && vax != 0 { - const float *const end = ip + nfloats; - - while(ip < end) - { -PUT_VAX_DFLOAT_Body(`(*xpp)') + const float *const end = tp + nelems; - ip++; + while (tp < end) { + PUT_VAX_DFLOAT_Body(`(*xpp)') + tp++; *xpp = (char *)(*xpp) + X_SIZEOF_FLOAT; } return NC_NOERR; } #else -int -ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) { char *xp = *xpp; int status = NC_NOERR; - for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) - { - int lstatus = ncx_put_float_float(xp, tp); - if(lstatus != NC_NOERR) + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) { + int lstatus = APIPrefix`x_put_'NC_TYPE(float)_float(xp, tp, fillp); + if (status == NC_NOERR) /* report the first encountered error */ status = lstatus; } @@ -3081,6 +3435,7 @@ ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) NCX_PUTN(float, schar) NCX_PUTN(float, short) NCX_PUTN(float, int) +NCX_PUTN(float, long) NCX_PUTN(float, double) NCX_PUTN(float, longlong) NCX_PUTN(float, uchar) @@ -3093,23 +3448,23 @@ NCX_PUTN(float, ulonglong) #if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) /* optimized version */ int -ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType nelems, double *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(double)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_DOUBLE); # else swapn8b(tp, *xpp, nelems); # endif *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); return NC_NOERR; } -#elif vax +#elif defined(vax) && vax != 0 int -ncx_getn_double_double(const void **xpp, size_t ndoubles, double *ip) +APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType ndoubles, double *ip) { double *const end = ip + ndoubles; - while(ip < end) + while (ip < end) { GET_VAX_DDOUBLE_Body(`(*xpp)') ip++; @@ -3120,15 +3475,15 @@ GET_VAX_DDOUBLE_Body(`(*xpp)') /* vax */ #else int -ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType nelems, double *tp) { const char *xp = *xpp; int status = NC_NOERR; for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) { - const int lstatus = ncx_get_double_double(xp, tp); - if(lstatus != NC_NOERR) + const int lstatus = APIPrefix`x_get_'NC_TYPE(double)_double(xp, tp, fillp); + if (status == NC_NOERR) /* report the first encountered error */ status = lstatus; } @@ -3139,6 +3494,7 @@ ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) NCX_GETN(double, schar) NCX_GETN(double, short) NCX_GETN(double, int) +NCX_GETN(double, long) NCX_GETN(double, float) NCX_GETN(double, longlong) NCX_GETN(double, uchar) @@ -3149,23 +3505,23 @@ NCX_GETN(double, ulonglong) #if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) /* optimized version */ int -ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType nelems, const double *tp, void *fillp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_DOUBLE); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_DOUBLE); # else swapn8b(*xpp, tp, nelems); # endif *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); return NC_NOERR; } -#elif vax +#elif defined(vax) && vax != 0 int -ncx_putn_double_double(void **xpp, size_t ndoubles, const double *ip) +APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType ndoubles, const double *ip, void *fillp) { const double *const end = ip + ndoubles; - while(ip < end) + while (ip < end) { PUT_VAX_DDOUBLE_Body(`(*xpp)') ip++; @@ -3176,15 +3532,15 @@ PUT_VAX_DDOUBLE_Body(`(*xpp)') /* vax */ #else int -ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType nelems, const double *tp, void *fillp) { char *xp = *xpp; int status = NC_NOERR; for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) { - int lstatus = ncx_put_double_double(xp, tp); - if(lstatus != NC_NOERR) + int lstatus = APIPrefix`x_put_'NC_TYPE(double)_double(xp, tp, fillp); + if (status == NC_NOERR) /* report the first encountered error */ status = lstatus; } @@ -3195,6 +3551,7 @@ ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) NCX_PUTN(double, schar) NCX_PUTN(double, short) NCX_PUTN(double, int) +NCX_PUTN(double, long) NCX_PUTN(double, float) NCX_PUTN(double, longlong) NCX_PUTN(double, uchar) @@ -3203,113 +3560,117 @@ NCX_PUTN(double, uint) NCX_PUTN(double, ulonglong) -/* longlong -----------------------------------------------------------------------*/ +/* longlong ------------------------------------------------------------------*/ -#if X_SIZEOF_LONGLONG == SIZEOF_LONGLONG +#if X_SIZEOF_INT64 == SIZEOF_LONGLONG /* optimized version */ int -ncx_getn_longlong_longlong(const void **xpp, size_t nelems, long long *tp) +APIPrefix`x_getn_'NC_TYPE(int64)_longlong(const void **xpp, IntType nelems, long long *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(long long)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_LONG_LONG); # else swapn8b(tp, *xpp, nelems); # endif - *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_LONGLONG); + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT64); return NC_NOERR; } #else -NCX_GETN(longlong, longlong) -#endif -NCX_GETN(longlong, schar) -NCX_GETN(longlong, short) -NCX_GETN(longlong, int) -NCX_GETN(longlong, float) -NCX_GETN(longlong, double) -NCX_GETN(longlong, uchar) -NCX_GETN(longlong, ushort) -NCX_GETN(longlong, uint) -NCX_GETN(longlong, ulonglong) - -#if X_SIZEOF_LONGLONG == SIZEOF_LONGLONG +NCX_GETN(int64, longlong) +#endif +NCX_GETN(int64, schar) +NCX_GETN(int64, short) +NCX_GETN(int64, int) +NCX_GETN(int64, long) +NCX_GETN(int64, float) +NCX_GETN(int64, double) +NCX_GETN(int64, uchar) +NCX_GETN(int64, ushort) +NCX_GETN(int64, uint) +NCX_GETN(int64, ulonglong) + +#if X_SIZEOF_INT64 == SIZEOF_LONGLONG /* optimized version */ int -ncx_putn_longlong_longlong(void **xpp, size_t nelems, const long long *tp) +APIPrefix`x_putn_'NC_TYPE(int64)_longlong(void **xpp, IntType nelems, const long long *tp, void *fillp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_LONGLONG); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT64); # else swapn8b(*xpp, tp, nelems); # endif - *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_LONGLONG); + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT64); return NC_NOERR; } #else -NCX_PUTN(longlong, longlong) -#endif -NCX_PUTN(longlong, schar) -NCX_PUTN(longlong, short) -NCX_PUTN(longlong, int) -NCX_PUTN(longlong, float) -NCX_PUTN(longlong, double) -NCX_PUTN(longlong, uchar) -NCX_PUTN(longlong, ushort) -NCX_PUTN(longlong, uint) -NCX_PUTN(longlong, ulonglong) - -/* ulonglong ----------------------------------------------------------------------*/ - -#if X_SIZEOF_ULONGLONG == SIZEOF_ULONGLONG +NCX_PUTN(int64, longlong) +#endif +NCX_PUTN(int64, schar) +NCX_PUTN(int64, short) +NCX_PUTN(int64, int) +NCX_PUTN(int64, long) +NCX_PUTN(int64, float) +NCX_PUTN(int64, double) +NCX_PUTN(int64, uchar) +NCX_PUTN(int64, ushort) +NCX_PUTN(int64, uint) +NCX_PUTN(int64, ulonglong) + +/* uint64 --------------------------------------------------------------------*/ + +#if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG /* optimized version */ int -ncx_getn_ulonglong_ulonglong(const void **xpp, size_t nelems, unsigned long long *tp) +APIPrefix`x_getn_'NC_TYPE(uint64)_ulonglong(const void **xpp, IntType nelems, unsigned long long *tp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(tp, *xpp, nelems * sizeof(unsigned long long)); + (void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UNSIGNED_LONG_LONG); # else swapn8b(tp, *xpp, nelems); # endif - *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_ULONGLONG); + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_UINT64); return NC_NOERR; } #else -NCX_GETN(ulonglong, ulonglong) -#endif -NCX_GETN(ulonglong, schar) -NCX_GETN(ulonglong, short) -NCX_GETN(ulonglong, int) -NCX_GETN(ulonglong, float) -NCX_GETN(ulonglong, double) -NCX_GETN(ulonglong, longlong) -NCX_GETN(ulonglong, uchar) -NCX_GETN(ulonglong, ushort) -NCX_GETN(ulonglong, uint) - -#if X_SIZEOF_ULONGLONG == SIZEOF_ULONGLONG +NCX_GETN(uint64, ulonglong) +#endif +NCX_GETN(uint64, schar) +NCX_GETN(uint64, short) +NCX_GETN(uint64, int) +NCX_GETN(uint64, long) +NCX_GETN(uint64, float) +NCX_GETN(uint64, double) +NCX_GETN(uint64, longlong) +NCX_GETN(uint64, uchar) +NCX_GETN(uint64, ushort) +NCX_GETN(uint64, uint) + +#if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG /* optimized version */ int -ncx_putn_ulonglong_ulonglong(void **xpp, size_t nelems, const unsigned long long *tp) +APIPrefix`x_putn_'NC_TYPE(uint64)_ulonglong(void **xpp, IntType nelems, const unsigned long long *tp, void *fillp) { #ifdef WORDS_BIGENDIAN - (void) memcpy(*xpp, tp, nelems * X_SIZEOF_ULONGLONG); + (void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT64); # else swapn8b(*xpp, tp, nelems); # endif - *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_ULONGLONG); + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_UINT64); return NC_NOERR; } #else -NCX_PUTN(ulonglong, ulonglong) +NCX_PUTN(uint64, ulonglong) #endif -NCX_PUTN(ulonglong, schar) -NCX_PUTN(ulonglong, short) -NCX_PUTN(ulonglong, int) -NCX_PUTN(ulonglong, float) -NCX_PUTN(ulonglong, double) -NCX_PUTN(ulonglong, longlong) -NCX_PUTN(ulonglong, uchar) -NCX_PUTN(ulonglong, ushort) -NCX_PUTN(ulonglong, uint) +NCX_PUTN(uint64, schar) +NCX_PUTN(uint64, short) +NCX_PUTN(uint64, int) +NCX_PUTN(uint64, long) +NCX_PUTN(uint64, float) +NCX_PUTN(uint64, double) +NCX_PUTN(uint64, longlong) +NCX_PUTN(uint64, uchar) +NCX_PUTN(uint64, ushort) +NCX_PUTN(uint64, uint) /* @@ -3317,45 +3678,27 @@ NCX_PUTN(ulonglong, uint) */ /* text */ -#ifdef __arm__ -int -ncx_getn_text(const void **xpp, size_t nelems, signed char *tp) -#else + int -ncx_getn_text(const void **xpp, size_t nelems, char *tp) -#endif +APIPrefix`x_getn_text'(const void **xpp, IntType nelems, char *tp) { NCX_GETN_Byte_Body } -#ifdef __arm__ -int -ncx_pad_getn_text(const void **xpp, size_t nelems, signed char *tp) -#else int -ncx_pad_getn_text(const void **xpp, size_t nelems, char *tp) -#endif +APIPrefix`x_pad_getn_text'(const void **xpp, IntType nelems, char *tp) { NCX_PAD_GETN_Byte_Body } -#ifdef __arm__ -int ncx_putn_text(void **xpp, size_t nelems, const signed char *tp) -#else int -ncx_putn_text(void **xpp, size_t nelems, const char *tp) -#endif +APIPrefix`x_putn_text'(void **xpp, IntType nelems, const char *tp) { NCX_PUTN_Byte_Body } -#ifdef __arm__ -int -ncx_pad_putn_text(void **xpp, size_t nelems, const signed char *tp) -#else int -ncx_pad_putn_text(void **xpp, size_t nelems, const char *tp) -#endif +APIPrefix`x_pad_putn_text'(void **xpp, IntType nelems, const char *tp) { NCX_PAD_PUTN_Byte_Body } @@ -3364,25 +3707,25 @@ NCX_PAD_PUTN_Byte_Body /* opaque */ int -ncx_getn_void(const void **xpp, size_t nelems, void *tp) +APIPrefix`x_getn_void'(const void **xpp, IntType nelems, void *tp) { NCX_GETN_Byte_Body } int -ncx_pad_getn_void(const void **xpp, size_t nelems, void *tp) +APIPrefix`x_pad_getn_void'(const void **xpp, IntType nelems, void *tp) { NCX_PAD_GETN_Byte_Body } int -ncx_putn_void(void **xpp, size_t nelems, const void *tp) +APIPrefix`x_putn_void'(void **xpp, IntType nelems, const void *tp) { NCX_PUTN_Byte_Body } int -ncx_pad_putn_void(void **xpp, size_t nelems, const void *tp) +APIPrefix`x_pad_putn_void'(void **xpp, IntType nelems, const void *tp) { NCX_PAD_PUTN_Byte_Body } diff --git a/libsrc/putget.m4 b/libsrc/putget.m4 index e35174453b..8dfc0d4e63 100644 --- a/libsrc/putget.m4 +++ b/libsrc/putget.m4 @@ -101,7 +101,7 @@ NC_fill_$2( *vp++ = $4; } } - return ncx_putn_$2_$1(xpp, nelems, fillp); + return ncx_putn_$2_$1(xpp, nelems, fillp ifelse(`$1',`char',,`,NULL')); } ')dnl @@ -541,7 +541,11 @@ NCcoordck(NC3_INFO* ncp, const NC_var *varp, const size_t *coord) { if(*coord > X_UINT_MAX) /* rkr: bug fix from previous X_INT_MAX */ return NC_EINVALCOORDS; /* sanity check */ +#ifdef RELAX_COORD_BOUND + if(NC_readonly(ncp) && *coord > NC_get_numrecs(ncp)) +#else if(NC_readonly(ncp) && *coord >= NC_get_numrecs(ncp)) +#endif { if(!NC_doNsync(ncp)) return NC_EINVALCOORDS; @@ -551,7 +555,11 @@ NCcoordck(NC3_INFO* ncp, const NC_var *varp, const size_t *coord) const int status = read_numrecs(ncp); if(status != NC_NOERR) return status; +#ifdef RELAX_COORD_BOUND + if(*coord > NC_get_numrecs(ncp)) +#else if(*coord >= NC_get_numrecs(ncp)) +#endif return NC_EINVALCOORDS; } } @@ -578,7 +586,11 @@ fprintf(stderr," NCcoordck: ip %p, *ip %ld, up %p, *up %lu\n", #endif /* CDEBUG */ /* cast needed for braindead systems with signed size_t */ +#ifdef RELAX_COORD_BOUND + if((unsigned long) *ip > (unsigned long) *up ) +#else if((unsigned long) *ip >= (unsigned long) *up ) +#endif return NC_EINVALCOORDS; } @@ -602,6 +614,11 @@ NCedgeck(const NC3_INFO* ncp, const NC_var *varp, if(IS_RECVAR(varp)) { +#ifdef RELAX_COORD_BOUND + if (NC_readonly(ncp) && + (start[0] == NC_get_numrecs(ncp) && edges[0] > 0)) + return(NC_EINVALCOORDS); +#endif start++; edges++; shp++; @@ -609,6 +626,10 @@ NCedgeck(const NC3_INFO* ncp, const NC_var *varp, for(; start < end; start++, edges++, shp++) { +#ifdef RELAX_COORD_BOUND + if ((unsigned long) *start == *shp && *edges > 0) + return(NC_EINVALCOORDS); +#endif /* cast needed for braindead systems with signed size_t */ if((unsigned long) *edges > *shp || (unsigned long) *start + (unsigned long) *edges > *shp) @@ -680,12 +701,16 @@ putNCvx_$1_$2(NC3_INFO* ncp, const NC_var *varp, size_t remaining = varp->xsz * nelems; int status = NC_NOERR; void *xp; + void *fillp; if(nelems == 0) return NC_NOERR; assert(value != NULL); + fillp = malloc(varp->xsz); + status = NC3_inq_var_fill(varp, fillp); + for(;;) { size_t extent = MIN(remaining, ncp->chunk); @@ -696,7 +721,7 @@ putNCvx_$1_$2(NC3_INFO* ncp, const NC_var *varp, if(lstatus != NC_NOERR) return lstatus; - lstatus = ncx_putn_$1_$2(&xp, nput, value); + lstatus = ncx_putn_$1_$2(&xp, nput, value ifelse(`$1',`char',,`,fillp')); if(lstatus != NC_NOERR && status == NC_NOERR) { /* not fatal to the loop */ @@ -709,10 +734,11 @@ putNCvx_$1_$2(NC3_INFO* ncp, const NC_var *varp, remaining -= extent; if(remaining == 0) break; /* normal loop exit */ - offset += extent; + offset += (off_t)extent; value += nput; } + free(fillp); return status; } @@ -868,7 +894,7 @@ getNCvx_$1_$2(const NC3_INFO* ncp, const NC_var *varp, remaining -= extent; if(remaining == 0) break; /* normal loop exit */ - offset += extent; + offset += (off_t)extent; value += nget; } @@ -1168,14 +1194,18 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, #ifndef __CHAR_UNSIGNED__ return getNCvx_char_char(ncp,varp,start,nelems,(char*)value); #else - return getNCvx_schar_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_schar_schar(ncp,varp,start,nelems,value); #endif break; case CASE(NC_BYTE,NC_BYTE): - return getNCvx_schar_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_schar_schar(ncp,varp,start,nelems, (schar*)value); break; case CASE(NC_BYTE,NC_UBYTE): - return getNCvx_schar_uchar(ncp,varp,start,nelems,(unsigned char*)value); + if (fIsSet(ncp->flags,NC_64BIT_DATA)) + return getNCvx_schar_uchar(ncp,varp,start,nelems,(unsigned char*)value); + else + /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */ + return getNCvx_uchar_uchar(ncp,varp,start,nelems,(unsigned char*)value); break; case CASE(NC_BYTE,NC_SHORT): return getNCvx_schar_short(ncp,varp,start,nelems,(short*)value); @@ -1202,7 +1232,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, return getNCvx_schar_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_SHORT,NC_BYTE): - return getNCvx_short_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_short_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_SHORT,NC_UBYTE): return getNCvx_short_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1233,7 +1263,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, break; case CASE(NC_INT,NC_BYTE): - return getNCvx_int_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_int_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_INT,NC_UBYTE): return getNCvx_int_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1264,7 +1294,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, break; case CASE(NC_FLOAT,NC_BYTE): - return getNCvx_float_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_float_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_FLOAT,NC_UBYTE): return getNCvx_float_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1295,7 +1325,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, break; case CASE(NC_DOUBLE,NC_BYTE): - return getNCvx_double_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_double_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_DOUBLE,NC_UBYTE): return getNCvx_double_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1329,7 +1359,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, return getNCvx_uchar_uchar(ncp,varp,start,nelems,(unsigned char*)value); break; case CASE(NC_UBYTE,NC_BYTE): - return getNCvx_uchar_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_uchar_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_UBYTE,NC_SHORT): return getNCvx_uchar_short(ncp,varp,start,nelems,(short*)value); @@ -1357,7 +1387,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, break; case CASE(NC_USHORT,NC_BYTE): - return getNCvx_ushort_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_ushort_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_USHORT,NC_UBYTE): return getNCvx_ushort_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1388,7 +1418,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, break; case CASE(NC_UINT,NC_BYTE): - return getNCvx_uint_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_uint_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_UINT,NC_UBYTE): return getNCvx_uint_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1419,7 +1449,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, break; case CASE(NC_INT64,NC_BYTE): - return getNCvx_longlong_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_longlong_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_INT64,NC_UBYTE): return getNCvx_longlong_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1450,7 +1480,7 @@ readNCv(const NC3_INFO* ncp, const NC_var* varp, const size_t* start, break; case CASE(NC_UINT64,NC_BYTE): - return getNCvx_ulonglong_schar(ncp,varp,start,nelems,(signed char*)value); + return getNCvx_ulonglong_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_UINT64,NC_UBYTE): return getNCvx_ulonglong_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1500,10 +1530,14 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_char_char(ncp,varp,start,nelems,(char*)value); break; case CASE(NC_BYTE,NC_BYTE): - return putNCvx_schar_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_schar_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_BYTE,NC_UBYTE): - return putNCvx_schar_uchar(ncp,varp,start,nelems,(unsigned char*)value); + if (fIsSet(ncp->flags,NC_64BIT_DATA)) + return putNCvx_schar_uchar(ncp,varp,start,nelems,(unsigned char*)value); + else + /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */ + return putNCvx_uchar_uchar(ncp,varp,start,nelems,(unsigned char*)value); break; case CASE(NC_BYTE,NC_SHORT): return putNCvx_schar_short(ncp,varp,start,nelems,(short*)value); @@ -1530,7 +1564,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_schar_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_SHORT,NC_BYTE): - return putNCvx_short_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_short_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_SHORT,NC_UBYTE): return putNCvx_short_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1560,7 +1594,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_short_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_INT,NC_BYTE): - return putNCvx_int_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_int_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_INT,NC_UBYTE): return putNCvx_int_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1590,7 +1624,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_int_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_FLOAT,NC_BYTE): - return putNCvx_float_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_float_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_FLOAT,NC_UBYTE): return putNCvx_float_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1620,7 +1654,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_float_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_DOUBLE,NC_BYTE): - return putNCvx_double_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_double_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_DOUBLE,NC_UBYTE): return putNCvx_double_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1653,7 +1687,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_uchar_uchar(ncp,varp,start,nelems,(unsigned char*)value); break; case CASE(NC_UBYTE,NC_BYTE): - return putNCvx_uchar_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_uchar_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_UBYTE,NC_SHORT): return putNCvx_uchar_short(ncp,varp,start,nelems,(short*)value); @@ -1680,7 +1714,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_uchar_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_USHORT,NC_BYTE): - return putNCvx_ushort_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_ushort_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_USHORT,NC_UBYTE): return putNCvx_ushort_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1710,7 +1744,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_ushort_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_UINT,NC_BYTE): - return putNCvx_uint_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_uint_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_UINT,NC_UBYTE): return putNCvx_uint_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1740,7 +1774,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_uint_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_INT64,NC_BYTE): - return putNCvx_longlong_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_longlong_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_INT64,NC_UBYTE): return putNCvx_longlong_uchar(ncp,varp,start,nelems,(unsigned char*)value); @@ -1770,7 +1804,7 @@ writeNCv(NC3_INFO* ncp, const NC_var* varp, const size_t* start, return putNCvx_longlong_ushort(ncp,varp,start,nelems,(unsigned short*)value); break; case CASE(NC_UINT64,NC_BYTE): - return putNCvx_ulonglong_schar(ncp,varp,start,nelems,(signed char*)value); + return putNCvx_ulonglong_schar(ncp,varp,start,nelems,(schar*)value); break; case CASE(NC_UINT64,NC_UBYTE): return putNCvx_ulonglong_uchar(ncp,varp,start,nelems,(unsigned char*)value); diff --git a/libsrc/v1hpg.c b/libsrc/v1hpg.c index afdeb519a3..488ef73e11 100644 --- a/libsrc/v1hpg.c +++ b/libsrc/v1hpg.c @@ -85,11 +85,7 @@ fault_v1hs(v1hs *gsp, size_t extent) if(gsp->base != NULL) { -#ifdef __arm__ const ptrdiff_t incr = (signed char *)gsp->pos - (signed char *)gsp->base; -#else - const ptrdiff_t incr = (char *)gsp->pos - (char *)gsp->base; -#endif status = rel_v1hs(gsp); if(status) return status; @@ -107,11 +103,7 @@ fault_v1hs(v1hs *gsp, size_t extent) gsp->pos = gsp->base; -#ifdef __arm__ gsp->end = (signed char *)gsp->base + gsp->extent; -#else - gsp->end = (char *)gsp->base + gsp->extent; -#endif return NC_NOERR; } @@ -128,13 +120,8 @@ fprintf(stderr, "nextread %lu, remaining %lu\n", (unsigned long)nextread, (unsigned long)((char *)gsp->end - (char *)gsp->pos)); #endif -#ifdef __arm__ if((signed char *)gsp->pos + nextread <= (signed char *)gsp->end) return NC_NOERR; -#else - if((char *)gsp->pos + nextread <= (char *)gsp->end) - return NC_NOERR; -#endif return fault_v1hs(gsp, nextread); } @@ -150,10 +137,12 @@ v1h_put_size_t(v1hs *psp, const size_t *sp) status = check_v1hs(psp, X_SIZEOF_INT64); else status = check_v1hs(psp, X_SIZEOF_SIZE_T); - if(status != NC_NOERR) + if(status != NC_NOERR) return status; - if (psp->version == 5) - return ncx_put_int64(&psp->pos, *sp); + if (psp->version == 5) { + unsigned long long tmp = (unsigned long long) (*sp); + return ncx_put_uint64(&psp->pos, tmp); + } else return ncx_put_size_t(&psp->pos, sp); } @@ -167,11 +156,11 @@ v1h_get_size_t(v1hs *gsp, size_t *sp) status = check_v1hs(gsp, X_SIZEOF_INT64); else status = check_v1hs(gsp, X_SIZEOF_SIZE_T); - if(status != NC_NOERR) + if(status != NC_NOERR) return status; if (gsp->version == 5) { - long long tmp=0; - status = ncx_get_int64((const void **)(&gsp->pos), &tmp); + unsigned long long tmp=0; + status = ncx_get_uint64((const void **)(&gsp->pos), &tmp); *sp = (size_t)tmp; return status; } @@ -187,18 +176,10 @@ v1h_get_size_t(v1hs *gsp, size_t *sp) static int v1h_put_nc_type(v1hs *psp, const nc_type *typep) { - const int itype = (int) *typep; - int status = check_v1hs(psp, X_SIZEOF_INT); - if(status != NC_NOERR) - return status; - status = ncx_put_int_int(psp->pos, &itype); - -#ifdef __arm__ - psp->pos = (void *)((signed char *)psp->pos + X_SIZEOF_INT); -#else - psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT); -#endif - + const unsigned int itype = (unsigned int) *typep; + int status = check_v1hs(psp, X_SIZEOF_INT); + if(status != NC_NOERR) return status; + status = ncx_put_uint32(&psp->pos, itype); return status; } @@ -207,16 +188,10 @@ v1h_put_nc_type(v1hs *psp, const nc_type *typep) static int v1h_get_nc_type(v1hs *gsp, nc_type *typep) { - int type = 0; - int status = check_v1hs(gsp, X_SIZEOF_INT); - if(status != NC_NOERR) - return status; - status = ncx_get_int_int(gsp->pos, &type); -#ifdef __arm__ - gsp->pos = (void *)((signed char *)gsp->pos + X_SIZEOF_INT); -#else - gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT); -#endif + unsigned int type = 0; + int status = check_v1hs(gsp, X_SIZEOF_INT); + if(status != NC_NOERR) return status; + status = ncx_get_uint32((const void**)(&gsp->pos), &type); if(status != NC_NOERR) return status; @@ -248,16 +223,10 @@ v1h_get_nc_type(v1hs *gsp, nc_type *typep) static int v1h_put_NCtype(v1hs *psp, NCtype type) { - const int itype = (int) type; - int status = check_v1hs(psp, X_SIZEOF_INT); - if(status != NC_NOERR) - return status; - status = ncx_put_int_int(psp->pos, &itype); -#ifdef __arm__ - psp->pos = (void *)((signed char *)psp->pos + X_SIZEOF_INT); -#else - psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT); -#endif + const unsigned int itype = (unsigned int) type; + int status = check_v1hs(psp, X_SIZEOF_INT); + if(status != NC_NOERR) return status; + status = ncx_put_uint32(&psp->pos, itype); return status; } @@ -265,21 +234,13 @@ v1h_put_NCtype(v1hs *psp, NCtype type) static int v1h_get_NCtype(v1hs *gsp, NCtype *typep) { - int type = 0; - int status = check_v1hs(gsp, X_SIZEOF_INT); - if(status != NC_NOERR) - return status; - status = ncx_get_int_int(gsp->pos, &type); - -#ifdef __arm__ - gsp->pos = (void *)((signed char *)gsp->pos + X_SIZEOF_INT); -#else - gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT); -#endif - if(status != NC_NOERR) - return status; - /* else */ - *typep = (NCtype) type; + unsigned int type = 0; + int status = check_v1hs(gsp, X_SIZEOF_INT); + if(status != NC_NOERR) return status; + status = ncx_get_uint32((const void**)(&gsp->pos), &type); + if(status != NC_NOERR) return status; + /* else */ + *typep = (NCtype) type; return NC_NOERR; } @@ -340,11 +301,11 @@ static int v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp) { int status; - size_t nchars = 0; + size_t padding, nchars = 0; NC_string *ncstrp; status = v1h_get_size_t(gsp, &nchars); - if(status != NC_NOERR) + if(status != NC_NOERR) return status; ncstrp = new_NC_string(nchars, NULL); @@ -353,7 +314,6 @@ v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp) return NC_ENOMEM; } - #if 0 /* assert(ncstrp->nchars == nchars || ncstrp->nchars - nchars < X_ALIGN); */ assert(ncstrp->nchars % X_ALIGN == 0); @@ -362,22 +322,33 @@ v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp) status = check_v1hs(gsp, _RNDUP(ncstrp->nchars, X_ALIGN)); #endif - if(status != NC_NOERR) + if(status != NC_NOERR) goto unwind_alloc; status = ncx_pad_getn_text((const void **)(&gsp->pos), nchars, ncstrp->cp); - if(status != NC_NOERR) + if(status != NC_NOERR) goto unwind_alloc; + padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN) + - X_SIZEOF_CHAR * ncstrp->nchars; + if (padding > 0) { + /* CDF specification: Header padding uses null (\x00) bytes. */ + char pad[X_ALIGN-1]; + memset(pad, 0, X_ALIGN-1); + if (memcmp((char*)gsp->pos-padding, pad, padding) != 0) { + free_NC_string(ncstrp); + return NC_EINVAL; + } + } + *ncstrpp = ncstrp; - return NC_NOERR; + return NC_NOERR; unwind_alloc: free_NC_string(ncstrp); return status; - } /* End NC_string */ @@ -614,6 +585,28 @@ ncx_len_NC_attr(const NC_attr *attrp, int version) #undef MIN #define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn)) +/*----< ncmpix_len_nctype() >------------------------------------------------*/ +/* return the length of external data type */ +static int +ncmpix_len_nctype(nc_type type) { + switch(type) { + case NC_BYTE: + case NC_CHAR: + case NC_UBYTE: return X_SIZEOF_CHAR; + case NC_SHORT: return X_SIZEOF_SHORT; + case NC_USHORT: return X_SIZEOF_USHORT; + case NC_INT: return X_SIZEOF_INT; + case NC_UINT: return X_SIZEOF_UINT; + case NC_FLOAT: return X_SIZEOF_FLOAT; + case NC_DOUBLE: return X_SIZEOF_DOUBLE; + case NC_INT64: return X_SIZEOF_INT64; + case NC_UINT64: return X_SIZEOF_UINT64; + default: fprintf(stderr,"ncmpix_len_nctype bad type %d\n",type); + assert(0); + } + return 0; +} + /* * Put the values of an attribute * The loop is necessary since attrp->nelems @@ -626,7 +619,7 @@ v1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp) const size_t perchunk = psp->extent; size_t remaining = attrp->xsz; void *value = attrp->xvalue; - size_t nbytes; + size_t nbytes, padding; assert(psp->extent % X_ALIGN == 0); @@ -634,23 +627,24 @@ v1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp) nbytes = MIN(perchunk, remaining); status = check_v1hs(psp, nbytes); - if(status != NC_NOERR) + if(status != NC_NOERR) return status; (void) memcpy(psp->pos, value, nbytes); -#ifdef __arm__ psp->pos = (void *)((signed char *)psp->pos + nbytes); value = (void *)((signed char *)value + nbytes); -#else - psp->pos = (void *)((char *)psp->pos + nbytes); - value = (void *)((char *)value + nbytes); -#endif - remaining -= nbytes; + remaining -= nbytes; } while(remaining != 0); - return NC_NOERR; + padding = attrp->xsz - ncmpix_len_nctype(attrp->type) * attrp->nelems; + if (padding > 0) { + /* CDF specification: Header padding uses null (\x00) bytes. */ + memset((char*)psp->pos-padding, 0, padding); + } + + return NC_NOERR; } /* Write a NC_attr to the header */ @@ -691,29 +685,33 @@ v1h_get_NC_attrV(v1hs *gsp, NC_attr *attrp) const size_t perchunk = gsp->extent; size_t remaining = attrp->xsz; void *value = attrp->xvalue; - size_t nget; + size_t nget, padding; do { nget = MIN(perchunk, remaining); status = check_v1hs(gsp, nget); - if(status != NC_NOERR) + if(status != NC_NOERR) return status; (void) memcpy(value, gsp->pos, nget); -#ifdef __arm__ gsp->pos = (void *)((signed char *)gsp->pos + nget); value = (void *)((signed char *)value + nget); -#else - gsp->pos = (void *)((char *)gsp->pos + nget); - value = (void *)((char *)value + nget); -#endif - remaining -= nget; + remaining -= nget; } while(remaining != 0); - return NC_NOERR; + padding = attrp->xsz - ncmpix_len_nctype(attrp->type) * attrp->nelems; + if (padding > 0) { + /* CDF specification: Header padding uses null (\x00) bytes. */ + char pad[X_ALIGN-1]; + memset(pad, 0, X_ALIGN-1); + if (memcmp((char*)gsp->pos-padding, pad, (size_t)padding) != 0) + return NC_EINVAL; + } + + return NC_NOERR; } @@ -939,7 +937,7 @@ v1h_put_NC_var(v1hs *psp, const NC_var *varp) if(status != NC_NOERR) return status; status = ncx_putn_longlong_int(&psp->pos, - varp->ndims, varp->dimids); + varp->ndims, varp->dimids, NULL); if(status != NC_NOERR) return status; } @@ -948,7 +946,7 @@ v1h_put_NC_var(v1hs *psp, const NC_var *varp) if(status != NC_NOERR) return status; status = ncx_putn_int_int(&psp->pos, - varp->ndims, varp->dimids); + varp->ndims, varp->dimids, NULL); if(status != NC_NOERR) return status; } @@ -1345,21 +1343,23 @@ ncx_put_NC(const NC3_INFO* ncp, void **xpp, off_t offset, size_t extent) } if (ps.version == 5) - status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic5), ncmagic5); + status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic5), ncmagic5, NULL); else if (ps.version == 2) - status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic), ncmagic); + status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic), ncmagic, NULL); else - status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic1), ncmagic1); - if(status != NC_NOERR) + status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic1), ncmagic1, NULL); + if(status != NC_NOERR) goto release; { const size_t nrecs = NC_get_numrecs(ncp); - if (ps.version == 5) - status = ncx_put_int64(&ps.pos, nrecs); + if (ps.version == 5) { + unsigned long long tmp = (unsigned long long) nrecs; + status = ncx_put_uint64(&ps.pos, tmp); + } else status = ncx_put_size_t(&ps.pos, &nrecs); - if(status != NC_NOERR) + if(status != NC_NOERR) goto release; } @@ -1486,8 +1486,8 @@ nc_get_NC(NC3_INFO* ncp) { size_t nrecs = 0; if (gs.version == 5) { - long long tmp = 0; - status = ncx_get_int64((const void **)(&gs.pos), &tmp); + unsigned long long tmp = 0; + status = ncx_get_uint64((const void **)(&gs.pos), &tmp); nrecs = (size_t)tmp; } else @@ -1497,11 +1497,8 @@ nc_get_NC(NC3_INFO* ncp) NC_set_numrecs(ncp, nrecs); } -#ifdef __arm__ assert((signed char *)gs.pos < (signed char *)gs.end); -#else - assert((char *)gs.pos < (char *)gs.end); -#endif + status = v1h_get_NC_dimarray(&gs, &ncp->dims); if(status != NC_NOERR) goto unwind_get; diff --git a/libsrc4/nc4attr.c b/libsrc4/nc4attr.c index 5f5188b08a..9c2bdde928 100644 --- a/libsrc4/nc4attr.c +++ b/libsrc4/nc4attr.c @@ -55,6 +55,18 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name, if (!(grp = nc4_rec_find_grp(h5->root_grp, (ncid & GRP_ID_MASK)))) BAIL(NC_EBADGRPID); + /* Check varid */ + if (varid != NC_GLOBAL) { + if (varid < 0 || varid >= grp->vars.nelems) + return NC_ENOTVAR; + if (grp->vars.value[varid] == NULL) + return NC_ENOTVAR; + assert(grp->vars.value[varid]->varid == varid); + } + + if (name == NULL) + BAIL(NC_EBADNAME); + /* Normalize name. */ if ((retval = nc4_normalize_name(name, norm_name))) BAIL(retval); @@ -221,18 +233,8 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, int i; int res; - if (!name) - return NC_EBADNAME; assert(nc && NC4_DATA(nc)); - LOG((1, "nc4_put_att: ncid 0x%x varid %d name %s " - "file_type %d mem_type %d len %d", ncid, varid, - name, file_type, mem_type, len)); - - /* If len is not zero, then there must be some data. */ - if (len && !data) - return NC_EINVAL; - /* Find info for this file and group, and set pointer to each. */ h5 = NC4_DATA(nc); if (!(grp = nc4_rec_find_grp(h5->root_grp, (ncid & GRP_ID_MASK)))) @@ -242,19 +244,6 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, if (h5->no_write) return NC_EPERM; - /* Check and normalize the name. */ - if ((retval = nc4_check_name(name, norm_name))) - return retval; - - if(nc->ext_ncid == ncid && varid == NC_GLOBAL) { - const char** sp; - for(sp = NC_RESERVED_SPECIAL_LIST;*sp;sp++) { - if(strcmp(name,*sp)==0) { - return NC_ENOTATT; /* Not settable */ - } - } - } - /* Find att, if it exists. */ if (varid == NC_GLOBAL) attlist = &grp->att; @@ -268,10 +257,34 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, assert(var->varid == varid); } + if (!name) + return NC_EBADNAME; + + /* Check and normalize the name. */ + if ((retval = nc4_check_name(name, norm_name))) + return retval; + + if(nc->ext_ncid == ncid && varid == NC_GLOBAL) { + const char** sp; + for(sp = NC_RESERVED_SPECIAL_LIST;*sp;sp++) { + if(strcmp(name,*sp)==0) { + return NC_ENOTATT; /* Not settable */ + } + } + } + for (att = *attlist; att; att = att->l.next) if (!strcmp(att->name, norm_name)) break; + /* If len is not zero, then there must be some data. */ + if (len && !data) + return NC_EINVAL; + + LOG((1, "nc4_put_att: ncid 0x%x varid %d name %s " + "file_type %d mem_type %d len %d", ncid, varid, + name, file_type, mem_type, len)); + if (!att) { /* If this is a new att, require define mode. */ @@ -821,12 +834,6 @@ nc4_put_att_tc(int ncid, int varid, const char *name, nc_type file_type, NC *nc; NC_HDF5_FILE_INFO_T *h5; - if (!name || strlen(name) > NC_MAX_NAME) - return NC_EBADNAME; - - LOG((3, "nc4_put_att_tc: ncid 0x%x varid %d name %s file_type %d " - "mem_type %d len %d", ncid, varid, name, file_type, mem_type, len)); - /* The length needs to be positive (cast needed for braindead systems with signed size_t). */ if((unsigned long) len > X_INT_MAX) @@ -840,6 +847,26 @@ nc4_put_att_tc(int ncid, int varid, const char *name, nc_type file_type, h5 = NC4_DATA(nc); assert(h5); + /* Check varid */ + if (varid != NC_GLOBAL) { + /* Find info for this file and group, and set pointer to each. */ + NC_GRP_INFO_T *grp; + if (!(grp = nc4_rec_find_grp(h5->root_grp, (ncid & GRP_ID_MASK)))) + return NC_EBADGRPID; + + if (varid < 0 || varid >= grp->vars.nelems) + return NC_ENOTVAR; + if (grp->vars.value[varid] == NULL) + return NC_ENOTVAR; + assert(grp->vars.value[varid]->varid == varid); + } + + if (!name || strlen(name) > NC_MAX_NAME) + return NC_EBADNAME; + + LOG((3, "nc4_put_att_tc: ncid 0x%x varid %d name %s file_type %d " + "mem_type %d len %d", ncid, varid, name, file_type, mem_type, len)); + if(nc->ext_ncid == ncid && varid == NC_GLOBAL) { const char** reserved = NC_RESERVED_ATT_LIST; for(;*reserved;reserved++) { diff --git a/libsrc4/nc4hdf.c b/libsrc4/nc4hdf.c index 1889973341..99b5a25aab 100644 --- a/libsrc4/nc4hdf.c +++ b/libsrc4/nc4hdf.c @@ -632,8 +632,12 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp, assert(dim && dim->dimid == var->dimids[d2]); if (!dim->unlimited) { +#ifdef RELAX_COORD_BOUND if (start[d2] > (hssize_t)fdims[d2] || (start[d2] == (hssize_t)fdims[d2] && count[d2] > 0)) +#else + if (start[d2] >= (hssize_t)fdims[d2]) +#endif BAIL_QUIET(NC_EINVALCOORDS); if (start[d2] + count[d2] > fdims[d2]) BAIL_QUIET(NC_EEDGE); @@ -965,8 +969,12 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, BAIL(retval); /* Check for out of bound requests. */ +#ifdef RELAX_COORD_BOUND if (start[d2] > (hssize_t)ulen || (start[d2] == (hssize_t)ulen && count[d2] > 0)) +#else + if (start[d2] >= (hssize_t)ulen && ulen > 0) +#endif BAIL_QUIET(NC_EINVALCOORDS); if (start[d2] + count[d2] > ulen) BAIL_QUIET(NC_EEDGE); @@ -989,8 +997,12 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, else { /* Check for out of bound requests. */ +#ifdef RELAX_COORD_BOUND if (start[d2] > (hssize_t)fdims[d2] || (start[d2] == (hssize_t)fdims[d2] && count[d2] > 0)) +#else + if (start[d2] >= (hssize_t)fdims[d2]) +#endif BAIL_QUIET(NC_EINVALCOORDS); if (start[d2] + count[d2] > fdims[d2]) BAIL_QUIET(NC_EEDGE); diff --git a/libsrcp/ncpdispatch.c b/libsrcp/ncpdispatch.c index a4e8c3ef27..19b2d31a2a 100644 --- a/libsrcp/ncpdispatch.c +++ b/libsrcp/ncpdispatch.c @@ -189,7 +189,7 @@ NCP__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree, size_t assert(nc5); /* causes implicitly defined warning; may be because of old installed pnetcdf? */ -#if 0 +#if 1 /* In PnetCDF ncmpi__enddef() is only implemented in v1.5.0 and later */ status = ncmpi__enddef(nc->int_ncid, mpi_h_minfree, mpi_v_align, mpi_v_minfree, mpi_r_align); @@ -441,6 +441,7 @@ NCP_get_att( if(status != NC_NOERR) return status; status = NCP_inq_att(ncid,varid,name,&xtype,NULL); + if(status != NC_NOERR) return status; if(memtype == NC_NAT) memtype = xtype; @@ -487,6 +488,14 @@ NCP_put_att( int status; MPI_Offset mpilen; + /* check if ncid is valid */ + status = NC_check_id(ncid, &nc); + if(status != NC_NOERR) return status; + + /* check if varid is valid */ + status = ncmpi_inq_varnatts(nc->int_ncid, varid, NULL); + if (status != NC_NOERR) return status; + if (!name || (strlen(name) > NC_MAX_NAME)) return NC_EBADNAME; @@ -495,9 +504,6 @@ NCP_put_att( if(((unsigned long) len) > X_INT_MAX) return NC_EINVAL; - status = NC_check_id(ncid, &nc); - if(status != NC_NOERR) return status; - mpilen = len; switch (memtype) { diff --git a/nc_test/CMakeLists.txt b/nc_test/CMakeLists.txt index f46ac171f4..54d003b73c 100644 --- a/nc_test/CMakeLists.txt +++ b/nc_test/CMakeLists.txt @@ -1,6 +1,6 @@ INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) -SET (nc_test_m4_SOURCES test_get test_put) +SET (nc_test_m4_SOURCES test_get test_put test_read test_write) FOREACH (F ${nc_test_m4_SOURCES}) GEN_m4(${F}) ENDFOREACH() @@ -93,5 +93,5 @@ ENDIF() ## Specify files to be distributed by 'make dist' FILE(GLOB CUR_EXTRA_DIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.h ${CMAKE_CURRENT_SOURCE_DIR}/*.sh) SET(CUR_EXTRA_DIST ${CUR_EXTRA_DIST} CMakeLists.txt Makefile.am) -SET(CUR_EXTRA_DIST ${CUR_EXTRA_DIST} test_get.m4 test_put.m4 ref_tst_diskless2.cdl) +SET(CUR_EXTRA_DIST ${CUR_EXTRA_DIST} test_get.m4 test_put.m4 test_read.m4 test_write.m4 ref_tst_diskless2.cdl) ADD_EXTRA_DIST("${CUR_EXTRA_DIST}") diff --git a/nc_test/Makefile.am b/nc_test/Makefile.am index 2423829096..11a37780c6 100644 --- a/nc_test/Makefile.am +++ b/nc_test/Makefile.am @@ -92,7 +92,8 @@ endif # USE_VALGRIND_TESTS # Distribute the .c files so that m4 isn't required on the users # machine. EXTRA_DIST = test_get.m4 test_put.m4 run_valgrind_tests.sh \ -run_diskless.sh run_diskless2.sh run_mmap.sh run_pnetcdf_test.sh +run_diskless.sh run_diskless2.sh run_mmap.sh run_pnetcdf_test.sh \ +test_read.m4 test_write.m4 # ref_tst_diskless2.cdl is for diff comparison and to produce tst_diskless2.c EXTRA_DIST += ref_tst_diskless2.cdl CMakeLists.txt diff --git a/nc_test/error.c b/nc_test/error.c index e9668de7d0..2d502ca0e5 100644 --- a/nc_test/error.c +++ b/nc_test/error.c @@ -59,7 +59,7 @@ ifFail(const int expr, const int line, const char *file) * "architecture" of this program. */ void -print_n_size_t(size_t nelems, const size_t *array) +print_n_size_t(int nelems, const size_t *array) { fprintf(stderr, "["); while(nelems-- > 0) diff --git a/nc_test/error.h b/nc_test/error.h index 7ed8fdfcd0..f8ccf3b062 100644 --- a/nc_test/error.h +++ b/nc_test/error.h @@ -24,10 +24,11 @@ __attribute__ ((format (printf, 1, 2))) extern int ifFail(const int expr, const int line, const char *file); extern void -print_n_size_t(size_t nelems, const size_t *array); +print_n_size_t(int nelems, const size_t *array); #ifdef __cplusplus } #endif #define IF(EXPR) if (ifFail(EXPR, __LINE__, __FILE__)) +#define ELSE_NOK else {nok++;} diff --git a/nc_test/nc_test.c b/nc_test/nc_test.c index 5e779e3bbd..f4c27e4ac1 100644 --- a/nc_test/nc_test.c +++ b/nc_test/nc_test.c @@ -35,11 +35,11 @@ char dim_name[NDIMS][3]; size_t dim_len[NDIMS]; char var_name[NVARS][2+MAX_RANK]; nc_type var_type[NVARS]; -size_t var_rank[NVARS]; +int var_rank[NVARS]; int var_dimid[NVARS][MAX_RANK]; size_t var_shape[NVARS][MAX_RANK]; size_t var_nels[NVARS]; -size_t var_natts[NVARS]; +int var_natts[NVARS]; char att_name[NVARS][MAX_NATTS][2]; char gatt_name[NGATTS][3]; nc_type att_type[NVARS][NGATTS]; @@ -156,7 +156,7 @@ main(int argc, char *argv[]) /* Initialize global variables defining test file */ init_gvars(); - /* Write the test file, needed for the read-only tests below. */ + /* Write the test file, needed for the read-only tests below. */ write_file(testfile); /* delete any existing scratch netCDF file */ @@ -355,6 +355,8 @@ main(int argc, char *argv[]) NC_TEST(nc_copy_att); NC_TEST(nc_rename_att); NC_TEST(nc_del_att); + NC_TEST(nc_against_pnetcdf); + /* keep below the last test, as it changes the default file format */ NC_TEST(nc_set_default_format); } diff --git a/nc_test/test_get.m4 b/nc_test/test_get.m4 index 5b792be125..49b46a81c1 100644 --- a/nc_test/test_get.m4 +++ b/nc_test/test_get.m4 @@ -1,18 +1,71 @@ dnl This is m4 source. dnl Process using m4 to produce 'C' language file. dnl +dnl This file is supposed to be the same as PnetCDF's test_get.m4 +dnl dnl If you see this line, you can ignore the next one. /* Do not edit this file. It is produced from the corresponding .m4 source */ dnl -/********************************************************************* - * Copyright 1996, UCAR/Unidata - * See netcdf/COPYRIGHT file for copying and redistribution conditions. - * $Id: test_get.m4 2785 2014-10-26 05:21:20Z wkliao $ - *********************************************************************/ - -#ifdef USE_PARALLEL -#include +/* + * Copyright (C) 2003, Northwestern University and Argonne National Laboratory + * See COPYRIGHT notice in top-level directory. + */ +/* $Id: test_get.m4 2630 2016-11-17 06:35:10Z wkliao $ */ + +dnl +dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF +dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types +dnl (MPI_Offset vs. size_t), and function name substrings for external data +dnl types. +dnl + +#include "tests.h" + +ifdef(`PNETCDF',,`dnl +#ifdef USE_PNETCDF +#include +#ifndef PNETCDF_VERSION_MAJOR +#error("PNETCDF_VERSION_MAJOR is not defined in pnetcdf.h") +#endif +#ifndef PNETCDF_VERSION_MINOR +#error("PNETCDF_VERSION_MAJOR is not defined in pnetcdf.h") #endif +#endif') + +define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl + +define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl +define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl +define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_get_$1',`test_nc_get_$1')')dnl +define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl + +define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, &ncid)', `file_open($1, $2, &ncid)')')dnl + +define(`VarArgs', `ifdef(`PNETCDF',`int numVars',`void')')dnl +define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts,int numVars',`void')')dnl + +define(`GetVar1',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl +define(`GetVar', `ifdef(`PNETCDF',`ncmpi_get_var_$1_all', `nc_get_var_$1')')dnl +define(`GetVara',`ifdef(`PNETCDF',`ncmpi_get_vara_$1_all',`nc_get_vara_$1')')dnl +define(`GetVars',`ifdef(`PNETCDF',`ncmpi_get_vars_$1_all',`nc_get_vars_$1')')dnl +define(`GetVarm',`ifdef(`PNETCDF',`ncmpi_get_varm_$1_all',`nc_get_varm_$1')')dnl +define(`GetAtt', `ifdef(`PNETCDF',`ncmpi_get_att_$1',`nc_get_att_$1')')dnl + +define(`PNETCDF_CHECK_ERANGE',`dnl +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,` +`#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)')', + `$1',`schar',`ifdef(`PNETCDF',,` +`#'if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7 + else if (cdf_format < NC_FORMAT_CDF5) { +`#'else')') + else { +ifelse(`$1',`schar',`ifdef(`PNETCDF',,``#'endif')') + IF (err != NC_ERANGE) + EXPECT_ERR(NC_ERANGE, err) + ELSE_NOK + } +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')')' +)dnl undefine(`index')dnl dnl dnl dnl @@ -33,94 +86,146 @@ dnl define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl dnl -#include "tests.h" +define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dnl +define(`CheckRange',`ifelse(`$1',`text', `1', `($2 >= $1_min && $2 <= $1_max)')')dnl +define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl +define(`CheckNumRange',`ifelse(`$1',`text', `1',`inRange3(cdf_format, $2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl dnl TEST_NC_GET_VAR1(TYPE) dnl define(`TEST_NC_GET_VAR1',dnl `dnl -void -test_nc_get_var1_$1(void) +int +TestFunc(var1)_$1(VarArgs) { - int ncid; - int i; - int j; - int err; - int nok = 0; /* count of valid comparisons */ - size_t index[MAX_RANK]; - double expect; + int i, err, ncid, cdf_format; + int nok = 0; /* count of valid comparisons */ int canConvert; /* Both text or both numeric */ - $1 value; + IntType j, index[MAX_RANK]; + double expect; + $1 value[1]; + + err = FileOpen(testfile, NC_NOWRITE); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = GetVar1($1)(BAD_ID, 0, NULL, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = GetVar1($1)(ncid, BAD_VARID, NULL, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - for (j = 0; j < var_rank[i]; j++) - index[j] = 0; - err = nc_get_var1_$1(BAD_ID, i, index, &value); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + /* check if can detect a bad file ID */ + err = GetVar1($1)(BAD_ID, i, NULL, value); IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_var1_$1(ncid, BAD_VARID, index, &value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - index[j] = var_shape[i][j]; - err = nc_get_var1_$1(ncid, i, index, &value); - if(!canConvert) { - IF(err != NC_ECHAR) - error("conversion: status = %d", err); - } else IF (err != NC_EINVALCOORDS) - error("bad index: status = %d", err); - index[j] = 0; - } - for (j = 0; j < var_nels[i]; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase 1"); - expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1) ); - if (var_rank[i] == 0 && i%2 ) - err = nc_get_var1_$1(ncid, i, NULL, &value); - else - err = nc_get_var1_$1(ncid, i, index, &value); + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = GetVar1($1)(ncid, i, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) + } + else if (var_rank[i] == 0) { + index[0] = 0; + expect = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect, var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect)) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>7)')') + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')') + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK +')dnl + + /* test NC_EINVALCOORDS */ + for (j = 0; j < var_rank[i]; j++) index[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + index[j] = var_shape[i][j]; /* out of boundary check */ + err = GetVar1($1)(ncid, i, index, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } else IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + index[j] = 0; + } + + /* check if the contents are supposed to be */ + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + /* when file is created the variable contents are generated by + * hash functions */ + expect = hash4(cdf_format, var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + err = GetVar1($1)(ncid, i, index, value); if (canConvert) { - if (inRange3(expect,var_type[i], NCT_ITYPE($1))) { - if (expect >= $1_min && expect <= $1_max) { - IF (err) { - error("%s", nc_strerror(err)); - } else { - IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) { - error("expected: %G, got: %G", expect, - (double) value); - } else { - nok++; - } - } - } else { - IF (err != NC_ERANGE) - error("Range error: status = %d", err); - } + if (inRange3(cdf_format, expect,var_type[i], NCT_ITYPE($1))) { + if (CheckRange($1, expect)) { + IF (err != NC_NOERR) { + EXPECT_ERR(NC_NOERR, err) + } else { + ifelse(`$1', `uchar', ` + /* in put_vars(), API _put_vara_double() is used to + * write the NC_BYTE variables to files. In this + * case, NC_BYTE variables are treated as signed + * for CDF-1 and 2 formats. Thus, we must skip the + * equal test below for uchar. + */ + if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect > schar_max) continue;') + IF (!equal((double)value[0], expect, var_type[i], NCT_ITYPE($1))) { + error("expected: %G, got: %G", expect, (double)value[0]); + } + ELSE_NOK + } + } + PNETCDF_CHECK_ERANGE($1) } else { - IF (err != 0 && err != NC_ERANGE) - error("OK or Range error: status = %d", err); - } - } else { - IF (err != NC_ECHAR) - error("wrong type: status = %d", err); - } - } + IF (err != NC_NOERR && err != NC_ERANGE) + EXPECT_ERR(NC_NOERR or NC_ERANGE, err) + } + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; } ')dnl TEST_NC_GET_VAR1(text) -TEST_NC_GET_VAR1(uchar) TEST_NC_GET_VAR1(schar) +TEST_NC_GET_VAR1(uchar) TEST_NC_GET_VAR1(short) TEST_NC_GET_VAR1(int) TEST_NC_GET_VAR1(long) @@ -136,94 +241,107 @@ dnl TEST_NC_GET_VAR(TYPE) dnl define(`TEST_NC_GET_VAR',dnl `dnl -void -test_nc_get_var_$1(void) +int +TestFunc(var)_$1(VarArgs) { - int ncid; - int i; - int j; - int err; - int allInExtRange; /* all values within external range? */ - int allInIntRange; /* all values within internal range? */ - int nels; - int nok = 0; /* count of valid comparisons */ - size_t index[MAX_RANK]; + int i, err, ncid, cdf_format; + int allInExtRange; /* all values within range of external data type */ + int allInIntRange; /* all values within range of internal data type */ + int nok = 0; /* count of valid comparisons */ int canConvert; /* Both text or both numeric */ - $1 value[MAX_NELS]; + IntType j, index[MAX_RANK]; double expect[MAX_NELS]; + $1 value[MAX_NELS]; + + err = FileOpen(testfile, NC_NOWRITE); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = GetVar($1)(BAD_ID, 0, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = GetVar($1)(ncid, BAD_VARID, value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); - err = nc_get_var_$1(BAD_ID, i, value); + + /* check if can detect a bad file ID */ + err = GetVar($1)(BAD_ID, i, value); IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_var_$1(ncid, BAD_VARID, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - nels *= var_shape[i][j]; - } - allInExtRange = allInIntRange = 1; - for (j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase 1"); - expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1)); - if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) { - allInIntRange = allInIntRange && expect[j] >= $1_min - && expect[j] <= $1_max; - } else { - allInExtRange = 0; - } - } - err = nc_get_var_$1(ncid, i, value); - if (canConvert) { - if (allInExtRange) { - if (allInIntRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("Range error: status = %d", err); - } - } else { - IF (err != 0 && err != NC_ERANGE) - error("OK or Range error: status = %d", err); - } - for (j = 0; j < nels; j++) { - if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) - && expect[j] >= $1_min && expect[j] <= $1_max) { - IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){ - error("value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("element number: %d ", j); - error("expect: %g", expect[j]); - error("got: %g", (double) value[j]); - } - } else { - nok++; - } - } - } - } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); - } + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + + allInExtRange = allInIntRange = 1; + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + expect[j] = hash4(cdf_format, var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[j],var_type[i], NCT_ITYPE($1))) { + IfCheckTextChar($1, var_type[i]) + allInIntRange &= CheckRange($1,expect[j]); + } else + allInExtRange = 0; + } + err = GetVar($1)(ncid, i, value); + if (canConvert) { + if (allInExtRange) { + if (allInIntRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + } + PNETCDF_CHECK_ERANGE($1) + } else { + IF (err != NC_NOERR && err != NC_ERANGE) + EXPECT_ERR(NC_NOERR or NC_ERANGE, err) + } + for (j = 0; j < var_nels[i]; j++) { + if (CheckNumRange($1, expect[j], var_type[i])) { + ifelse(`$1', `uchar', ` + /* in put_vars(), API _put_vara_double() is used to + * write the NC_BYTE variables to files. In this + * case, NC_BYTE variables are treated as signed + * for CDF-1 and 2 formats. Thus, we must skip the + * equal test below for uchar. + */ + if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;') + IF (!equal((double)value[j],expect[j],var_type[i],NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("var_type: %s, ", s_nc_type(var_type[i])); + error("element number: %d, ", j); + error("expect: %g, ", expect[j]); + error("got: %g", (double) value[j]); + } + } + ELSE_NOK + } + } + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; } ')dnl @@ -245,160 +363,245 @@ dnl TEST_NC_GET_VARA(TYPE) dnl define(`TEST_NC_GET_VARA',dnl `dnl -void -test_nc_get_vara_$1(void) +int +TestFunc(vara)_$1(VarArgs) { - int ncid; - int d; - int i; - int j; - int k; - int err; - int allInExtRange; /* all values within external range? */ - int allInIntRange; /* all values within internal range? */ - int nels; - int nslabs; - int nok = 0; /* count of valid comparisons */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t mid[MAX_RANK]; + int i, k, err, nslabs, ncid, cdf_format; + int allInExtRange; /* all values within external range? */ + int allInIntRange; /* all values within internal range? */ + int nok = 0; /* count of valid comparisons */ int canConvert; /* Both text or both numeric */ - $1 value[MAX_NELS]; + IntType j; + IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK], mid[MAX_RANK]; double expect[MAX_NELS]; + $1 value[MAX_NELS]; + + err = FileOpen(testfile, NC_NOWRITE); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err)); + + err = GetVara($1)(BAD_ID, 0, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + err = GetVara($1)(ncid, BAD_VARID, NULL, NULL, value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - } - err = nc_get_vara_$1(BAD_ID, i, start, edge, value); + + /* check if can detect a bad file ID */ + err = GetVara($1)(BAD_ID, i, NULL, NULL, value); IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_vara_$1(ncid, BAD_VARID, start, edge, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - start[j] = var_shape[i][j]; - err = nc_get_vara_$1(ncid, i, start, edge, value); - IF (canConvert && err != NC_EINVALCOORDS) - error("bad index: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_get_vara_$1(ncid, i, start, edge, value); - IF (canConvert && err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - } - /* Check non-scalars for correct error returned even when */ - /* there is nothing to get (edge[j]==0) */ - if(var_rank[i] > 0) { - for (j = 0; j < var_rank[i]; j++) { - edge[j] = 0; - } - err = nc_get_vara_$1(BAD_ID, i, start, edge, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_vara_$1(ncid, BAD_VARID, start, edge, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_get_vara_$1(ncid, i, start, edge, value); - if (canConvert) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ECHAR) - error("wrong type: status = %d", err); - } - for (j = 0; j < var_rank[i]; j++) { - edge[j] = 1; - } - } /* Choose a random point dividing each dim into 2 parts */ - /* get 2^rank (nslabs) slabs so defined */ + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + } + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = GetVara($1)(ncid, i, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + else if (var_rank[i] == 0) { + index[0] = 0; + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>7)')') + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')') + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = GetVara($1)(ncid, i, start, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + else if (var_rank[i] == 0) { + index[0] = 0; + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) + } + else IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; /* causes NC_EINVALCOORDS */ + err = GetVara($1)(ncid, i, start, edge, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + start[j] = 0; + continue; + } + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + start[j] = 0; + edge[j] = var_shape[i][j] + 1; /* causes NC_EEDGE */ + err = GetVara($1)(ncid, i, start, edge, value); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + edge[j] = 1; + } + /* Check non-scalars for correct error returned even when there is + * nothing to get (edge[*]==0) */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_rank[i] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = GetVara($1)(ncid, i, start, edge, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + start[j] = 0; + continue; + } +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + start[j] = var_shape[i][j]+1; /* should cause NC_EINVALCOORDS */ + err = GetVara($1)(ncid, i, start, edge, value); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + start[j] = 0; + } + + err = GetVara($1)(ncid, i, start, edge, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + } else if (var_rank[i] == 0) { + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>7)')') + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')') + } else { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ nslabs = 1; for (j = 0; j < var_rank[i]; j++) { mid[j] = roll( var_shape[i][j] ); nslabs *= 2; } - /* bits of k determine whether to get lower or upper part of dim */ + /* bits of k determine whether to get lower or upper part of dim */ for (k = 0; k < nslabs; k++) { - nels = 1; + IntType nels = 1; for (j = 0; j < var_rank[i]; j++) { if ((k >> j) & 1) { start[j] = 0; edge[j] = mid[j]; - }else{ + } else { start[j] = mid[j]; edge[j] = var_shape[i][j] - mid[j]; } nels *= edge[j]; } - allInExtRange = allInIntRange = 1; + allInExtRange = allInIntRange = 1; for (j = 0; j < nels; j++) { + int d; err = toMixedBase(j, var_rank[i], edge, index); - IF (err) - error("error in toMixedBase 1"); + IF (err != 0) error("error in toMixedBase"); for (d = 0; d < var_rank[i]; d++) index[d] += start[d]; - expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1)); - if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) { - allInIntRange = allInIntRange && expect[j] >= $1_min - && expect[j] <= $1_max; - } else { - allInExtRange = 0; - } - } - if (var_rank[i] == 0 && i%2) - err = nc_get_vara_$1(ncid, i, NULL, NULL, value); - else - err = nc_get_vara_$1(ncid, i, start, edge, value); + expect[j] = hash4(cdf_format, var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) { + IfCheckTextChar($1, var_type[i]) + allInIntRange &= CheckRange($1,expect[j]); + } else + allInExtRange = 0; + } + err = GetVara($1)(ncid, i, start, edge, value); if (canConvert) { - if (allInExtRange) { - if (allInIntRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("Range error: status = %d", err); - } - } else { - IF (err != 0 && err != NC_ERANGE) - error("OK or Range error: status = %d", err); - } - for (j = 0; j < nels; j++) { - if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) - && expect[j] >= $1_min && expect[j] <= $1_max) { - IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){ - error("value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("element number: %d ", j); - error("expect: %g", expect[j]); - error("got: %g", (double) value[j]); - } - } else { - nok++; - } - } - } + if (allInExtRange) { + if (allInIntRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + } + PNETCDF_CHECK_ERANGE($1) + } else { + IF (err != NC_NOERR && err != NC_ERANGE) + EXPECT_ERR(NC_NOERR or NC_ERANGE, err) + } + for (j = 0; j < nels; j++) { + if (CheckNumRange($1, expect[j], var_type[i])) { + ifelse(`$1', `uchar', ` + /* in put_vars(), API _put_vara_double() is used to + * write the NC_BYTE variables to files. In this + * case, NC_BYTE variables are treated as signed + * for CDF-1 and 2 formats. Thus, we must skip the + * equal test below for uchar. + */ + if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;') + IF (!equal((double)value[j],expect[j],var_type[i],NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("var_type: %s, ", s_nc_type(var_type[i])); + error("element number: %d, ", j); + error("expect: %g, ", expect[j]); + error("got: %g", (double) value[j]); + } + } + ELSE_NOK + } + } } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) } } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; } ')dnl @@ -420,178 +623,283 @@ dnl TEST_NC_GET_VARS(TYPE) dnl define(`TEST_NC_GET_VARS',dnl `dnl -void -test_nc_get_vars_$1(void) +int +TestFunc(vars)_$1(VarArgs) { - int ncid; - int d; - int i; - int j; - int k; - int m; - int err; - int allInExtRange; /* all values within external range? */ - int allInIntRange; /* all values within internal range? */ - int nels; - int nslabs; - int nstarts; /* number of different starts */ - int nok = 0; /* count of valid comparisons */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t index2[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; + int i, k, d, err, nslabs, ncid, cdf_format; + int allInExtRange; /* all values within external range? */ + int allInIntRange; /* all values within internal range? */ + PTRDType nstarts; /* number of different starts */ + int nok = 0; /* count of valid comparisons */ int canConvert; /* Both text or both numeric */ - $1 value[MAX_NELS]; + IntType j, m, nels; + IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK]; + IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType stride[MAX_RANK]; double expect[MAX_NELS]; + $1 value[MAX_NELS]; + + err = FileOpen(testfile, NC_NOWRITE); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err)); + + err = GetVars($1)(BAD_ID, 0, NULL, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + err = GetVars($1)(ncid, BAD_VARID, NULL, NULL, NULL, value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); + + /* check if can detect a bad file ID */ + err = GetVars($1)(BAD_ID, i, NULL, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + for (j = 0; j < var_rank[i]; j++) { start[j] = 0; edge[j] = 1; stride[j] = 1; } - err = nc_get_vars_$1(BAD_ID, i, start, edge, stride, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_vars_$1(ncid, BAD_VARID, start, edge, stride, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = GetVars($1)(ncid, i, NULL, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + else if (var_rank[i] == 0) { + index[0] = 0; + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = GetVars($1)(ncid, i, start, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + else if (var_rank[i] == 0) { + index[0] = 0; + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) + } + else IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ for (j = 0; j < var_rank[i]; j++) { start[j] = var_shape[i][j]; - err = nc_get_vars_$1(ncid, i, start, edge, stride, value); - if(!canConvert) { - IF (err != NC_ECHAR) - error("conversion: status = %d", err); - } else { + err = GetVars($1)(ncid, i, start, edge, stride, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + start[j] = 0; + continue; + } IF (err != NC_EINVALCOORDS) - error("bad index: status = %d", err); + EXPECT_ERR(NC_EINVALCOORDS, err) start[j] = 0; edge[j] = var_shape[i][j] + 1; - err = nc_get_vars_$1(ncid, i, start, edge, stride, value); + err = GetVars($1)(ncid, i, start, edge, stride, value); IF (err != NC_EEDGE) - error("bad edge: status = %d", err); + EXPECT_ERR(NC_EEDGE, err) edge[j] = 1; stride[j] = 0; - err = nc_get_vars_$1(ncid, i, start, edge, stride, value); + err = GetVars($1)(ncid, i, start, edge, stride, value); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + stride[j] = 1; + } + + /* Check non-scalars for correct error returned even when there is + * nothing to get (edge[j]==0) */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = GetVars($1)(ncid, i, start, edge, stride, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + start[j] = 0; + continue; + } +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + start[j] = var_shape[i][j]+1; /* should cause NC_EINVALCOORDS */ + err = GetVars($1)(ncid, i, start, edge, stride, value); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + start[j] = 0; +ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=7)') + stride[j] = 0; + err = GetVars($1)(ncid, i, start, edge, stride, value); IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); + EXPECT_ERR(NC_ESTRIDE, err) stride[j] = 1; - } +ifdef(`PNETCDF',,``#'endif') } - /* Choose a random point dividing each dim into 2 parts */ - /* get 2^rank (nslabs) slabs so defined */ + + err = GetVars($1)(ncid, i, start, edge, stride, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + } else if (var_rank[i] == 0) { + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>7)')') + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')') + } else { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ nslabs = 1; for (j = 0; j < var_rank[i]; j++) { mid[j] = roll( var_shape[i][j] ); nslabs *= 2; } - /* bits of k determine whether to get lower or upper part of dim */ - /* choose random stride from 1 to edge */ + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ for (k = 0; k < nslabs; k++) { nstarts = 1; for (j = 0; j < var_rank[i]; j++) { if ((k >> j) & 1) { start[j] = 0; edge[j] = mid[j]; - }else{ + } else { start[j] = mid[j]; edge[j] = var_shape[i][j] - mid[j]; } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; nstarts *= stride[j]; } for (m = 0; m < nstarts; m++) { err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); + IF (err != 0) error("error in toMixedBase"); nels = 1; for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + count[j] = 1 + (edge[j]-index[j]-1) / (IntType)stride[j]; nels *= count[j]; index[j] += start[j]; } - /* Random choice of forward or backward */ + /* Random choice of forward or backward */ /* TODO if ( roll(2) ) { for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; + index[j] += (count[j] - 1) * (IntType)stride[j]; stride[j] = -stride[j]; } } */ - allInExtRange = allInIntRange = 1; - for (j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], count, index2); - IF (err) - error("error in toMixedBase 1"); - for (d = 0; d < var_rank[i]; d++) - index2[d] = index[d] + index2[d] * stride[d]; - expect[j] = hash4(var_type[i], var_rank[i], index2, - NCT_ITYPE($1)); - if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) { - allInIntRange = allInIntRange && expect[j] >= $1_min - && expect[j] <= $1_max; - } else { - allInExtRange = 0; - } - } - if (var_rank[i] == 0 && i%2 ) - err = nc_get_vars_$1(ncid, i, NULL, NULL, NULL, value); - else - err = nc_get_vars_$1(ncid, i, index, count, stride, value); - if (canConvert) { - if (allInExtRange) { - if (allInIntRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("Range error: status = %d", err); - } - } else { - IF (err != 0 && err != NC_ERANGE) - error("OK or Range error: status = %d", err); - } - for (j = 0; j < nels; j++) { - if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) - && expect[j] >= $1_min && expect[j] <= $1_max) { - IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){ - error("value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("element number: %d ", j); + allInExtRange = allInIntRange = 1; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err != 0) error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * (IntType)stride[d]; + expect[j] = hash4(cdf_format, var_type[i], var_rank[i], + index2, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) { + IfCheckTextChar($1, var_type[i]) + allInIntRange &= CheckRange($1,expect[j]); + } else + allInExtRange = 0; + } + err = GetVars($1)(ncid, i, index, count, stride, value); + if (canConvert) { + if (allInExtRange) { + if (allInIntRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + } + PNETCDF_CHECK_ERANGE($1) + } else { + IF (err != NC_NOERR && err != NC_ERANGE) + EXPECT_ERR(NC_NOERR or NC_ERANGE, err) + } + for (j = 0; j < nels; j++) { + if (CheckNumRange($1, expect[j], var_type[i])) { + ifelse(`$1', `uchar', ` + /* in put_vars(), API _put_vara_double() is used to + * write the NC_BYTE variables to files. In this + * case, NC_BYTE variables are treated as signed + * for CDF-1 and 2 formats. Thus, we must skip the + * equal test below for uchar. + */ + if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;') + IF (!equal((double)value[j],expect[j],var_type[i], NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("var_type: %s, ", s_nc_type(var_type[i])); + error("element number: %d, ", j); error("expect: %g, ", expect[j]); - error("got: %g", (double) value[j]); - } - } else { - nok++; - } - } - } - } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); - } - } - } + error("got: %g", (double) value[j]); + } + } + ELSE_NOK + } + } + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + } + } + } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; } ')dnl @@ -613,186 +921,288 @@ dnl TEST_NC_GET_VARM(TYPE) dnl define(`TEST_NC_GET_VARM',dnl `dnl -void -test_nc_get_varm_$1(void) +int +TestFunc(varm)_$1(VarArgs) { - int ncid; - int d; - int i; - int j; - int k; - int m; - int err; - int allInExtRange; /* all values within external range? */ - int allInIntRange; /* all values within internal range? */ - int nels; - int nslabs; - int nstarts; /* number of different starts */ - int nok = 0; /* count of valid comparisons */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t index2[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; - ptrdiff_t imap[MAX_RANK]; + int i, k, d, err, nslabs, ncid, cdf_format; + int allInExtRange; /* all values within external range? */ + int allInIntRange; /* all values within internal range? */ + PTRDType nstarts; /* number of different starts */ + int nok = 0; /* count of valid comparisons */ int canConvert; /* Both text or both numeric */ - $1 value[MAX_NELS]; + IntType j, m, nels; + IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK]; + IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType stride[MAX_RANK], imap[MAX_RANK]; double expect[MAX_NELS]; + $1 value[MAX_NELS]; + + err = FileOpen(testfile, NC_NOWRITE); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err)); + + err = GetVarm($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + err = GetVarm($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); + + /* check if can detect a bad file ID */ + err = GetVars($1)(BAD_ID, i, NULL, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + for (j = 0; j < var_rank[i]; j++) { start[j] = 0; edge[j] = 1; stride[j] = 1; imap[j] = 1; } - err = nc_get_varm_$1(BAD_ID, i, start, edge, stride, imap, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_varm_$1(ncid, BAD_VARID, start, edge, stride, imap, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = GetVarm($1)(ncid, i, NULL, NULL, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + else if (var_rank[i] == 0) { + index[0] = 0; + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = GetVarm($1)(ncid, i, start, NULL, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + else if (var_rank[i] == 0) { + index[0] = 0; + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) + } + else IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ for (j = 0; j < var_rank[i]; j++) { start[j] = var_shape[i][j]; - err = nc_get_varm_$1(ncid, i, start, edge, stride, imap, value); - if(!canConvert) { - IF (err != NC_ECHAR) - error("conversion: status = %d", err); - } else { - IF (err != NC_EINVALCOORDS) - error("bad index: status = %d", err); + err = GetVarm($1)(ncid, i, start, edge, stride, imap, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + continue; + } + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) start[j] = 0; edge[j] = var_shape[i][j] + 1; - err = nc_get_varm_$1(ncid, i, start, edge, stride, imap, value); + err = GetVarm($1)(ncid, i, start, edge, stride, imap, value); IF (err != NC_EEDGE) - error("bad edge: status = %d", err); + EXPECT_ERR(NC_EEDGE, err) edge[j] = 1; stride[j] = 0; - err = nc_get_varm_$1(ncid, i, start, edge, stride, imap, value); + err = GetVarm($1)(ncid, i, start, edge, stride, imap, value); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + stride[j] = 1; + } + + /* Check non-scalars for correct error returned even when there is + * nothing to get (edge[j]==0) */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = GetVarm($1)(ncid, i, start, edge, stride, imap, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + start[j] = 0; + continue; + } +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + start[j] = var_shape[i][j]+1; /* should cause NC_EINVALCOORDS */ + err = GetVarm($1)(ncid, i, start, edge, stride, imap, value); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + start[j] = 0; +ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=7)') + stride[j] = 0; + err = GetVarm($1)(ncid, i, start, edge, stride, imap, value); IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); + EXPECT_ERR(NC_ESTRIDE, err) stride[j] = 1; - } +ifdef(`PNETCDF',,``#'endif') + } + + err = GetVarm($1)(ncid, i, start, edge, stride, imap, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + } else if (var_rank[i] == 0) { + expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) && + CheckRange($1, expect[0])) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>7)')') + else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err) +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')') + } else { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) } - /* Choose a random point dividing each dim into 2 parts */ - /* get 2^rank (nslabs) slabs so defined */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ nslabs = 1; for (j = 0; j < var_rank[i]; j++) { mid[j] = roll( var_shape[i][j] ); nslabs *= 2; } - /* bits of k determine whether to get lower or upper part of dim */ - /* choose random stride from 1 to edge */ + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ for (k = 0; k < nslabs; k++) { nstarts = 1; for (j = 0; j < var_rank[i]; j++) { if ((k >> j) & 1) { start[j] = 0; edge[j] = mid[j]; - }else{ + } else { start[j] = mid[j]; edge[j] = var_shape[i][j] - mid[j]; } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; nstarts *= stride[j]; } for (m = 0; m < nstarts; m++) { err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); + IF (err != 0) error("error in toMixedBase"); nels = 1; for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + count[j] = 1 + (edge[j]-index[j]-1) / (IntType)stride[j]; nels *= count[j]; index[j] += start[j]; } - /* Random choice of forward or backward */ + /* Random choice of forward or backward */ /* TODO - if ( roll(2) ) { - for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; - stride[j] = -stride[j]; - } - } + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * (IntType)stride[j]; + stride[j] = -stride[j]; + } + } */ - if (var_rank[i] > 0) { - j = var_rank[i] - 1; - imap[j] = 1; - for (; j > 0; j--) - imap[j-1] = imap[j] * count[j]; - } + if (var_rank[i] > 0) { + int jj = var_rank[i] - 1; + imap[jj] = 1; + for (; jj > 0; jj--) + imap[jj-1] = imap[jj] * (PTRDType)count[jj]; + } allInExtRange = allInIntRange = 1; for (j = 0; j < nels; j++) { err = toMixedBase(j, var_rank[i], count, index2); - IF (err) - error("error in toMixedBase 1"); + IF (err != 0) error("error in toMixedBase"); for (d = 0; d < var_rank[i]; d++) - index2[d] = index[d] + index2[d] * stride[d]; - expect[j] = hash4(var_type[i], var_rank[i], index2, - NCT_ITYPE($1)); - if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) { - allInIntRange = allInIntRange && expect[j] >= $1_min - && expect[j] <= $1_max; - } else { + index2[d] = index[d] + index2[d] * (IntType)stride[d]; + expect[j] = hash4(cdf_format, var_type[i], var_rank[i], + index2, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) { + IfCheckTextChar($1, var_type[i]) + allInIntRange &= CheckRange($1,expect[j]); + } else allInExtRange = 0; - } } - if (var_rank[i] == 0 && i%2 ) - err = nc_get_varm_$1(ncid,i,NULL,NULL,NULL,NULL,value); - else - err = nc_get_varm_$1(ncid,i,index,count,stride,imap,value); + err = GetVarm($1)(ncid,i,index,count,stride,imap,value); if (canConvert) { if (allInExtRange) { if (allInIntRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("Range error: status = %d", err); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) } + PNETCDF_CHECK_ERANGE($1) } else { - IF (err != 0 && err != NC_ERANGE) - error("OK or Range error: status = %d", err); + IF (err != NC_NOERR && err != NC_ERANGE) + EXPECT_ERR(NC_NOERR or NC_ERANGE, err) } for (j = 0; j < nels; j++) { - if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) - && expect[j] >= $1_min - && expect[j] <= $1_max) { - IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){ + if (CheckNumRange($1, expect[j], var_type[i])) { + ifelse(`$1', `uchar', ` + /* in put_vars(), API _put_vara_double() is used to + * write the NC_BYTE variables to files. In this + * case, NC_BYTE variables are treated as signed + * for CDF-1 and 2 formats. Thus, we must skip the + * equal test below for uchar. + */ + if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;') + IF (!equal((double)value[j],expect[j],var_type[i], NCT_ITYPE($1))){ error("value read not that expected"); if (verbose) { error("\n"); error("varid: %d, ", i); error("var_name: %s, ", var_name[i]); - error("element number: %d ", j); + error("var_type: %s, ", s_nc_type(var_type[i])); + error("element number: %d, ", j); error("expect: %g, ", expect[j]); error("got: %g", (double) value[j]); } - } else { - nok++; } + ELSE_NOK } } } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) } } } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; } ')dnl @@ -814,90 +1224,129 @@ dnl TEST_NC_GET_ATT(TYPE) dnl define(`TEST_NC_GET_ATT',dnl `dnl -void -test_nc_get_att_$1(void) +int +TestFunc(att)_$1(AttVarArgs) { - int ncid; - int i; - int j; - size_t k; - int err; + int i, j, err, ncid, cdf_format; + IntType k; int allInExtRange; int allInIntRange; int canConvert; /* Both text or both numeric */ - $1 value[MAX_NELS]; + int nok = 0; /* count of valid comparisons */ double expect[MAX_NELS]; - int nok = 0; /* count of valid comparisons */ + $1 value[MAX_NELS]; + + err = FileOpen(testfile, NC_NOWRITE); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err)); - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); + err = GetAtt($1)(BAD_ID, 0, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + err = GetAtt($1)(ncid, BAD_VARID, NULL, value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK for (i = -1; i < numVars; i++) { for (j = 0; j < NATTS(i); j++) { - canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - err = nc_get_att_$1(BAD_ID, i, ATT_NAME(i,j), value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_get_att_$1(ncid, i, "noSuch", value); - IF (err != NC_ENOTATT) - error("Bad attribute name: status = %d", err); - allInExtRange = allInIntRange = 1; + canConvert = (ATT_TYPE(i,j) == NC_CHAR) CheckText($1); + + err = GetAtt($1)(ncid, BAD_VARID, ATT_NAME(i,j), value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + +ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>7)') + /* check if can detect a bad name */ + err = GetAtt($1)(ncid, i, NULL, NULL); + IF (err != NC_EBADNAME) + EXPECT_ERR(NC_EBADNAME, err) + ELSE_NOK +ifdef(`PNETCDF',,``#'endif') + + err = GetAtt($1)(ncid, i, "noSuch", value); + IF (err != NC_ENOTATT) + EXPECT_ERR(NC_ENOTATT, err) + ELSE_NOK + + allInExtRange = allInIntRange = 1; for (k = 0; k < ATT_LEN(i,j); k++) { - expect[k] = hash4(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); - if (inRange3(expect[k],ATT_TYPE(i,j),NCT_ITYPE($1))) { - allInIntRange = allInIntRange && expect[k] >= $1_min - && expect[k] <= $1_max; + expect[k] = hash4(cdf_format, ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[k],ATT_TYPE(i,j),NCT_ITYPE($1))) { + /* netCDF specification make a special case for type + * conversion between uchar and scahr: do not check for + * range error. See + * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion + */ + IfCheckTextChar($1, ATT_TYPE(i,j)) + ifelse(`$1',`uchar', `if (cdf_format > NC_FORMAT_64BIT_OFFSET || (cdf_format < NC_FORMAT_CDF5 && ATT_TYPE(i,j) != NC_BYTE))') + allInIntRange &= CheckRange($1,expect[k]); } else { allInExtRange = 0; } - } - err = nc_get_att_$1(ncid, i, ATT_NAME(i,j), value); + } + err = GetAtt($1)(ncid, i, ATT_NAME(i,j), value); if (canConvert || ATT_LEN(i,j) == 0) { if (allInExtRange) { if (allInIntRange) { - IF (err) - error("%s", nc_strerror(err)); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>7)')') } else { IF (err != NC_ERANGE) - error("Range error: status = %d", err); + EXPECT_ERR(NC_ERANGE, err) +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')') } } else { - IF (err != 0 && err != NC_ERANGE) - error("OK or Range error: status = %d", err); + IF (err != NC_NOERR && err != NC_ERANGE) + EXPECT_ERR(NC_NOERR or NC_ERANGE, err) } - for (k = 0; k < ATT_LEN(i,j); k++) { - if (inRange3(expect[k],ATT_TYPE(i,j),NCT_ITYPE($1)) - && expect[k] >= $1_min && expect[k] <= $1_max) { - IF (!equal(value[k],expect[k],ATT_TYPE(i,j), NCT_ITYPE($1))){ - error("value read not that expected"); + for (k = 0; k < ATT_LEN(i,j); k++) { + if (CheckNumRange($1, expect[k], ATT_TYPE(i,j))) { + ifelse(`$1', `uchar', ` + /* in put_vars(), API _put_vara_double() is used to + * write the NC_BYTE variables to files. In this + * case, NC_BYTE variables are treated as signed + * for CDF-1 and 2 formats. Thus, we must skip the + * equal test below for uchar. + */ + if (cdf_format < NC_FORMAT_CDF5 && ATT_TYPE(i,j) == NC_BYTE && expect[k] > schar_max) continue;') + IF (!equal((double)value[k],expect[k],ATT_TYPE(i,j), NCT_ITYPE($1))){ + error("value read not that expected"); if (verbose) { error("\n"); error("varid: %d, ", i); + if (i == -1) + error("var_type: GLOBAL, "); + else + error("var_name: %s var_type: %s, ", var_name[i],s_nc_type(var_type[i])); error("att_name: %s, ", ATT_NAME(i,j)); - error("element number: %d ", k); - error("expect: %g", expect[k]); + error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j))); + error("element number: %d, ", k); + error("expect: %g, ", expect[k]); error("got: %g", (double) value[k]); } - } else { - nok++; + } else { + nok++; } - } - } - } else { - IF (err != NC_ECHAR) - error("wrong type: status = %d", err); - } - } + } + } + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + } + } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; } ')dnl diff --git a/nc_test/test_get_p5.m4 b/nc_test/test_get_p5.m4 index 91b09e9a1a..dd2066daa8 100644 --- a/nc_test/test_get_p5.m4 +++ b/nc_test/test_get_p5.m4 @@ -82,7 +82,7 @@ test_nc_get_var1_$1(void) err = toMixedBase(j, var_rank[i], var_shape[i], index); IF (err) error("error in toMixedBase 1"); - expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1) ); + expect = hash4(cdf_format, var_type[i], var_rank[i], index, NCT_ITYPE($1)); if (var_rank[i] == 0 && i%2 ) err = nc_get_var1_$1(ncid, i, NULL, &value); else @@ -182,7 +182,7 @@ test_nc_get_var_$1(void) err = toMixedBase(j, var_rank[i], var_shape[i], index); IF (err) error("error in toMixedBase 1"); - expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1)); + expect[j] = hash4(cdf_format,var_type[i], var_rank[i], index, NCT_ITYPE($1)); if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) { allInIntRange = allInIntRange && expect[j] >= $1_min && expect[j] <= $1_max; @@ -366,7 +366,7 @@ test_nc_get_vara_$1(void) error("error in toMixedBase 1"); for (d = 0; d < var_rank[i]; d++) index[d] += start[d]; - expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1)); + expect[j] = hash4(cdf_format,var_type[i], var_rank[i], index, NCT_ITYPE($1)); if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) { allInIntRange = allInIntRange && expect[j] >= $1_min && expect[j] <= $1_max; @@ -560,7 +560,7 @@ test_nc_get_vars_$1(void) error("error in toMixedBase 1"); for (d = 0; d < var_rank[i]; d++) index2[d] = index[d] + index2[d] * stride[d]; - expect[j] = hash4(var_type[i], var_rank[i], index2, + expect[j] = hash4(cdf_format,var_type[i], var_rank[i], index2, NCT_ITYPE($1)); if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) { allInIntRange = allInIntRange && expect[j] >= $1_min @@ -766,7 +766,7 @@ test_nc_get_varm_$1(void) error("error in toMixedBase 1"); for (d = 0; d < var_rank[i]; d++) index2[d] = index[d] + index2[d] * stride[d]; - expect[j] = hash4(var_type[i], var_rank[i], index2, + expect[j] = hash4(cdf_format,var_type[i], var_rank[i], index2, NCT_ITYPE($1)); if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) { allInIntRange = allInIntRange && expect[j] >= $1_min @@ -881,7 +881,7 @@ test_nc_get_att_$1(void) error("Bad attribute name: status = %d", err); allInExtRange = allInIntRange = 1; for (k = 0; k < ATT_LEN(i,j); k++) { - expect[k] = hash4(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); + expect[k] = hash4(cdf_format,ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); if (inRange3(expect[k],ATT_TYPE(i,j),NCT_ITYPE($1))) { allInIntRange = allInIntRange && expect[k] >= $1_min && expect[k] <= $1_max; diff --git a/nc_test/test_put.m4 b/nc_test/test_put.m4 index 32601f5aa0..6b702487e6 100644 --- a/nc_test/test_put.m4 +++ b/nc_test/test_put.m4 @@ -1,18 +1,75 @@ dnl This is m4 source. dnl Process using m4 to produce 'C' language file. dnl +dnl This file is supposed to be the same as PnetCDF's test_put.m4 +dnl dnl If you see this line, you can ignore the next one. /* Do not edit this file. It is produced from the corresponding .m4 source */ dnl -/********************************************************************* - * Copyright 1996, UCAR/Unidata - * See netcdf/COPYRIGHT file for copying and redistribution conditions. - * $Id: test_put.m4 2785 2014-10-26 05:21:20Z wkliao $ - *********************************************************************/ - -#ifdef USE_PARALLEL -#include +/* + * Copyright (C) 2003, Northwestern University and Argonne National Laboratory + * See COPYRIGHT notice in top-level directory. + */ +/* $Id: test_put.m4 2655 2016-11-25 21:03:48Z wkliao $ */ + +dnl +dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF +dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types +dnl (MPI_Offset vs. size_t), and function name substrings for external data +dnl types. +dnl + +#include "tests.h" + +ifdef(`PNETCDF',,`dnl +#ifdef USE_PNETCDF +#include +#ifndef PNETCDF_VERSION_MAJOR +#error("PNETCDF_VERSION_MAJOR is not defined in pnetcdf.h") +#endif +#ifndef PNETCDF_VERSION_MINOR +#error("PNETCDF_VERSION_MAJOR is not defined in pnetcdf.h") #endif +#endif') + +define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl + +define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl +define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl +define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_put_$1',`test_nc_put_$1')')dnl +define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl + +define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, &ncid)', `file_open($1, $2, &ncid)')')dnl +define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, &ncid)', `file_create($1, $2, &ncid)')')dnl +define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl + +define(`VarArgs', `ifdef(`PNETCDF',`int numVars',`void')')dnl +define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts,int numVars',`void')')dnl + +define(`PutVar1',`ifdef(`PNETCDF',`ncmpi_put_var1_$1_all',`nc_put_var1_$1')')dnl +define(`PutVar', `ifdef(`PNETCDF',`ncmpi_put_var_$1_all', `nc_put_var_$1')')dnl +define(`PutVara',`ifdef(`PNETCDF',`ncmpi_put_vara_$1_all',`nc_put_vara_$1')')dnl +define(`PutVars',`ifdef(`PNETCDF',`ncmpi_put_vars_$1_all',`nc_put_vars_$1')')dnl +define(`PutVarm',`ifdef(`PNETCDF',`ncmpi_put_varm_$1_all',`nc_put_varm_$1')')dnl +define(`PutAtt', `ifdef(`PNETCDF',`ncmpi_put_att_$1',`nc_put_att_$1')')dnl +define(`GetVar1',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl +define(`DefVars',`ifdef(`PNETCDF',`def_vars($1,$2)',`def_vars($1)')')dnl + +define(`PNETCDF_CHECK_ERANGE',`dnl +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,` +`#'if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)')', + `$1',`schar',`ifdef(`PNETCDF',,` +`#'if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7 + else if (cdf_format < NC_FORMAT_CDF5) { +`#'else')') + else { +ifelse(`$1',`schar',`ifdef(`PNETCDF',,``#'endif')') + IF (err != NC_ERANGE) + EXPECT_ERR(NC_ERANGE, err) + ELSE_NOK + } +ifelse(`$1',`uchar',`ifdef(`PNETCDF',,``#'endif')')' +)dnl undefine(`index')dnl dnl dnl dnl @@ -30,10 +87,22 @@ dnl dnl dnl dnl dnl NCT_ITYPE(type) dnl -define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl +define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl +define(`NC_TYPE', ``NC_'Upcase($1)')dnl +define(`X_MIN', ``X_'Upcase($1)_MIN')dnl +define(`X_MAX', ``X_'Upcase($1)_MAX')dnl dnl -#include "tests.h" +define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dnl +define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl +define(`CheckNumRange', + `ifelse(`$1',`text', `1', + `inRange3(cdf_format, (double)$2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl +define(`CheckRange', + `ifelse(`$1',`text', `0', `($2 >= $1_min && $2 <= $1_max)')')dnl +define(`CheckRange3', + `ifelse(`$1',`text', `1', + `inRange3(cdf_format, (double)$2,$3,NCT_ITYPE($1))')')dnl dnl HASH(TYPE) dnl @@ -42,18 +111,20 @@ define(`HASH',dnl /* * ensure hash value within range for internal TYPE */ -static -double -hash_$1( - const nc_type type, - const int rank, - const size_t *index, - const nct_itype itype) +$1 +hash_$1(const int cdf_format, + const nc_type type, + const int rank, + const IntType *index, + const nct_itype itype) { - const double min = $1_min; - const double max = $1_max; + double value; - return MAX(min, MIN(max, hash4( type, rank, index, itype))); + value = hash4(cdf_format, type, rank, index, itype); + ifelse(`$1',`text',`return (text)value;',` + if (value > $1_max) return $1_max; + else if (value < $1_min) return $1_min; + else return ($1)value;') } ')dnl @@ -75,88 +146,92 @@ dnl CHECK_VARS(TYPE) dnl define(`CHECK_VARS',dnl `dnl -/* +/* * check all vars in file which are (text/numeric) compatible with TYPE */ -static -void -check_vars_$1(const char *filename) +int +check_vars_$1(const char *filename, int numVars) { - int ncid; /* netCDF id */ - size_t index[MAX_RANK]; - int err; /* status */ - int d; - int i; - size_t j; - $1 value; - nc_type datatype; - int ndims; + int i, d, err, ncid, cdf_format, ndims; + int canConvert; /* Both text or both numeric */ + int nok = 0; /* count of valid comparisons */ int dimids[MAX_RANK]; - double expect; + nc_type datatype; char name[NC_MAX_NAME]; - size_t length; - int canConvert; /* Both text or both numeric */ - int nok = 0; /* count of valid comparisons */ + IntType j, length, index[MAX_RANK]; + double expect; + $1 value; + + err = FileOpen(filename, NC_NOWRITE); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); - err = file_open(filename, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err)); for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - if (canConvert) { - err = nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL); - IF (err) - error("nc_inq_var: %s", nc_strerror(err)); - IF (strcmp(name, var_name[i]) != 0) - error("Unexpected var_name"); - IF (datatype != var_type[i]) - error("Unexpected type"); - IF (ndims != var_rank[i]) - error("Unexpected rank"); - for (j = 0; j < ndims; j++) { - err = nc_inq_dim(ncid, dimids[j], 0, &length); - IF (err) - error("nc_inq_dim: %s", nc_strerror(err)); - IF (length != var_shape[i][j]) - error("Unexpected shape"); - } - for (j = 0; j < var_nels[i]; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase 2"); - expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1)); - err = nc_get_var1_$1(ncid, i, index, &value); - if (inRange3(expect,datatype,NCT_ITYPE($1))) { - if (expect >= $1_min && expect <= $1_max) { - IF (err) { - error("nc_get_var1_$1: %s", nc_strerror(err)); - } else { - IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) { - error("Var value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("index:"); - for (d = 0; d < var_rank[i]; d++) - error(" %d", index[d]); - error(", expect: %g, ", expect); - error("got: %g", (double) value); - } - } else { - ++nok; - } - } - } - } - } - } + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + if (!canConvert) continue; + + err = APIFunc(inq_var)(ncid, i, name, &datatype, &ndims, dimids, NULL); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + IF (strcmp(name, var_name[i]) != 0) + error("Unexpected var_name"); + IF (datatype != var_type[i]) + error("Unexpected type"); + IF (ndims != var_rank[i]) + error("Unexpected rank"); + for (j = 0; j < ndims; j++) { + err = APIFunc(inq_dim)(ncid, dimids[j], 0, &length); + IF (err != NC_NOERR) + error("inq_dim: %s", APIFunc(strerror)(err)); + IF (length != var_shape[i][j]) + error("Unexpected shape"); + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + expect = hash4(cdf_format, var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + err = GetVar1($1)(ncid, i, index, &value); + if (CheckNumRange($1, expect, datatype)) { + IF (err != NC_NOERR) { + error("GetVar1($1): %s", APIFunc(strerror)(err)); + } else { + ifelse(`$1', `uchar', ` + /* In put_vars(), PutVara(double)() is used to write + * variables of type NC_BYTE to files. For uchar APIs, + * NC_BYTE variables are treated as unsigned for CDF-1 and 2 + * formats. Thus, we skip the equal test for out-of-bound + * values below for uchar APIs. + */ + if (cdf_format < NC_FORMAT_CDF5 && + var_type[i] == NC_BYTE && expect > schar_max) + continue;') + IF (!equal((double)value,expect,var_type[i],NCT_ITYPE($1))){ + error("Var value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("var_type: %s, ", s_nc_type(var_type[i])); + error("index:"); + for (d = 0; d < var_rank[i]; d++) + error(" %d", index[d]); + error(", expect: %g, ", expect); + error("got: %g", (double) value); + } + } else { + ++nok; + } + } + } + } } - err = nc_close (ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; } ')dnl @@ -174,83 +249,96 @@ CHECK_VARS(longlong) CHECK_VARS(ulonglong) -dnl CHECK_ATTS(TYPE) numeric only +dnl CHECK_ATTS(TYPE) dnl define(`CHECK_ATTS',dnl `dnl -/* - * check all attributes in file which are (text/numeric) compatible with TYPE - * ignore any attributes containing values outside range of TYPE +/* + * for _text tests, check all attributes in file which are of text type + * Note no NC_ERANGE check for text attributes as text is not convertible to + * any other numerical data types (i.e. NC_ECHAR) + * + * for other tests, check all numerical attributes in file against values + * outside range of type $1 */ -static -void -check_atts_$1(int ncid) +int +check_atts_$1(int ncid, int numGatts, int numVars) { - int err; /* status */ - int i; - int j; - size_t k; - $1 value[MAX_NELS]; + int i, j, cdf_format, err; + int canConvert; /* Both text or both numeric */ + int nok = 0; /* count of valid comparisons */ + IntType k, length; nc_type datatype; + IntType nInExtRange; /* number values within external range */ + IntType nInIntRange; /* number values within internal range */ double expect[MAX_NELS]; - size_t length; - size_t nInExtRange; /* number values within external range */ - size_t nInIntRange; /* number values within internal range */ - int canConvert; /* Both text or both numeric */ - int nok = 0; /* count of valid comparisons */ + $1 value[MAX_NELS]; + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) + error("inq_format: %s", APIFunc(strerror)(err)); for (i = -1; i < numVars; i++) { for (j = 0; j < NATTS(i); j++) { - canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - if (canConvert) { - err = nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length); - IF (err) - error("nc_inq_att: %s", nc_strerror(err)); - IF (datatype != ATT_TYPE(i,j)) - error("nc_inq_att: unexpected type"); - IF (length != ATT_LEN(i,j)) - error("nc_inq_att: unexpected length"); - assert(length <= MAX_NELS); - nInIntRange = nInExtRange = 0; - for (k = 0; k < length; k++) { - expect[k] = hash4( datatype, -1, &k, NCT_ITYPE($1)); - if (inRange3(expect[k], datatype, NCT_ITYPE($1))) { - ++nInExtRange; - if (expect[k] >= $1_min && expect[k] <= $1_max) - ++nInIntRange; - } - } - err = nc_get_att_$1(ncid, i, ATT_NAME(i,j), value); - if (nInExtRange == length && nInIntRange == length) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != 0 && err != NC_ERANGE) - error("OK or Range error: status = %d", err); + canConvert = (ATT_TYPE(i,j) == NC_CHAR) CheckText($1); + if (!canConvert) continue; + + err = APIFunc(inq_att)(ncid, i, ATT_NAME(i,j), &datatype, &length); + IF (err != NC_NOERR) + error("inq_att: %s", APIFunc(strerror)(err)); + IF (datatype != ATT_TYPE(i,j)) + error("inq_att: unexpected type"); + IF (length != ATT_LEN(i,j)) + error("inq_att: unexpected length"); + assert(length <= MAX_NELS); + nInIntRange = nInExtRange = 0; + for (k = 0; k < length; k++) { + expect[k] = hash4(cdf_format, datatype, -1, &k, NCT_ITYPE($1)); + if (inRange3(cdf_format, expect[k], datatype, NCT_ITYPE($1))) { + ++nInExtRange; + if (CheckRange($1, expect[k])) + ++nInIntRange; } - for (k = 0; k < length; k++) { - if (inRange3(expect[k],datatype,NCT_ITYPE($1)) - && expect[k] >= $1_min && expect[k] <= $1_max) { - IF (!equal(value[k],expect[k],datatype,NCT_ITYPE($1))) { - error("att. value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("att_name: %s, ", ATT_NAME(i,j)); - error("element number: %d ", k); - error("expect: %g, ", expect[k]); - error("got: %g", (double) value[k]); - } - } else { - nok++; + } + err = APIFunc(get_att_$1)(ncid, i, ATT_NAME(i,j), value); + if (nInExtRange == length && nInIntRange == length) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + } else { + IF (err != NC_NOERR && err != NC_ERANGE) + EXPECT_ERR(NC_NOERR or NC_ERANGE, err) + } + for (k = 0; k < length; k++) { + if (CheckNumRange($1, expect[k], datatype)) { + ifelse(`$1', `uchar', ` + /* In put_vars(), PutVara(double)() is used to write + * variables of type NC_BYTE to files. For uchar APIs, + * NC_BYTE variables are treated as unsigned for CDF-1 and 2 + * formats. Thus, we skip the equal test for out-of-bound + * values below for uchar APIs. + */ + if (cdf_format < NC_FORMAT_CDF5 && + ATT_TYPE(i,j) == NC_BYTE && expect[k] > schar_max) + continue;') + IF (!equal((double)value[k],expect[k],datatype,NCT_ITYPE($1))) { + error("att. value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("att_name: %s, ", ATT_NAME(i,j)); + error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j))); + error("element number: %d ", k); + error("expect: %g, ", expect[k]); + error("got: %g", (double) value[k]); } + } else { + nok++; } } - } + } } } - - print_nok(nok); + return nok; } ')dnl @@ -272,98 +360,123 @@ dnl TEST_NC_PUT_VAR1(TYPE) dnl define(`TEST_NC_PUT_VAR1',dnl `dnl -void -test_nc_put_var1_$1(void) +int +TestFunc(var1)_$1(VarArgs) { - int ncid; - int i; - int j; - int err; - size_t index[MAX_RANK]; - int canConvert; /* Both text or both numeric */ - $1 value = 5; /* any value would do - only for error cases */ - - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; + int i, err, ncid, cdf_format, nok=0; + int canConvert; /* Both text or both numeric */ + IntType j, index[MAX_RANK]; + $1 value[1]; + + err = FileCreate(scratch, NC_CLOBBER); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; } + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) + error("inq_format: %s", APIFunc(strerror)(err)); + def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); + DefVars(ncid, numVars); -#ifdef USE_PNETCDF - { - int format; - nc_inq_format_extended(ncid, &format, NULL); - if (format == NC_FORMATX_PNETCDF) { - for (i = 0; i < numVars; i++) { - err = nc_var_par_access(ncid, i, NC_COLLECTIVE); - IF (err) - error("nc_var_par_access: %s", nc_strerror(err)); - } - } - } -#endif + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVar1($1)(BAD_ID, 0, NULL, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVar1($1)(ncid, BAD_VARID, NULL, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - for (j = 0; j < var_rank[i]; j++) - index[j] = 0; - err = nc_put_var1_$1(BAD_ID, i, index, &value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_var1_$1(ncid, BAD_VARID, index, &value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + value[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVar1($1)(BAD_ID, i, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVar1($1)(ncid, i, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) + } + else if (var_rank[i] == 0) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK +')dnl + + /* test NC_EINVALCOORDS */ + for (j = 0; j < var_rank[i]; j++) index[j] = 0; + for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - index[j] = var_shape[i][j]; - err = nc_put_var1_$1(ncid, i, index, &value); - IF (canConvert && err != NC_EINVALCOORDS) - error("bad index: status = %d", err); - index[j] = 0; - } + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + index[j] = var_shape[i][j]; /* out of boundary check */ + err = PutVar1($1)(ncid, i, index, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + index[j] = 0; + continue; + } + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + index[j] = 0; } + for (j = 0; j < var_nels[i]; j++) { err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase 1"); - value = hash_$1( var_type[i], var_rank[i], index, NCT_ITYPE($1)); - if (var_rank[i] == 0 && i%2 == 0) - err = nc_put_var1_$1(ncid, i, NULL, &value); - else - err = nc_put_var1_$1(ncid, i, index, &value); - if (canConvert) { - if (inRange3(value, var_type[i],NCT_ITYPE($1))) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) { - error("Range error: status = %d", err); - error("\n\t\tfor type %s value %.17e %ld", - s_nc_type(var_type[i]), - (double)value, (long)value); - } - } - } else { - IF (err != NC_ECHAR) - error("wrong type: status = %d", err); + IF (err != 0) error("error in toMixedBase"); + value[0] = hash_$1(cdf_format, var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + err = PutVar1($1)(ncid, i, index, value); + if (canConvert) { + if (CheckRange3($1, value[0], var_type[i])) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } + PNETCDF_CHECK_ERANGE($1) + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK } } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); - check_vars_$1(scratch); + nok += check_vars_$1(scratch, numVars); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("delete file %s failed", scratch); + return nok; } ')dnl @@ -385,141 +498,139 @@ dnl TEST_NC_PUT_VAR(TYPE) dnl define(`TEST_NC_PUT_VAR',dnl `dnl -void -test_nc_put_var_$1(void) +int +TestFunc(var)_$1(VarArgs) { - int ncid; - int varid; - int i; - int j; - int err; - int nels; - size_t index[MAX_RANK]; - int canConvert; /* Both text or both numeric */ - int allInExtRange; /* all values within external range? */ + int i, err, ncid, varid, cdf_format, nok=0; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + IntType j, index[MAX_RANK]; $1 value[MAX_NELS]; - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; + err = FileCreate(scratch, NC_CLOBBER); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; } + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) + error("inq_format: %s", APIFunc(strerror)(err)); + def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); + DefVars(ncid, numVars); -#ifdef USE_PNETCDF - { - int format; - nc_inq_format_extended(ncid, &format, NULL); - if (format == NC_FORMATX_PNETCDF) { - for (i = 0; i < numVars; i++) { - err = nc_var_par_access(ncid, i, NC_COLLECTIVE); - IF (err) - error("nc_var_par_access: %s", nc_strerror(err)); - } - } - } -#endif + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVar($1)(BAD_ID, 0, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVar($1)(ncid, BAD_VARID, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); - err = nc_put_var_$1(BAD_ID, i, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_var_$1(ncid, BAD_VARID, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - nels *= var_shape[i][j]; - } - for (allInExtRange = 1, j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase 1"); - value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1)); - allInExtRange = allInExtRange - && inRange3(value[j], var_type[i], NCT_ITYPE($1)); - } - err = nc_put_var_$1(ncid, i, value); - if (canConvert) { - if (allInExtRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE && var_dimid[i][0] != RECDIM) - error("range error: status = %d", err); - } - } else { /* should flag wrong type even if nothing to write */ - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); - } + + if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */ + + value[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVar($1)(BAD_ID, i, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + + for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + value[j]= hash_$1(cdf_format,var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + IfCheckTextChar($1, var_type[i]) + allInExtRange &= inRange3(cdf_format, (double)value[j], + var_type[i], NCT_ITYPE($1)); + } + err = PutVar($1)(ncid, i, value); + if (canConvert) { + if (allInExtRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } + PNETCDF_CHECK_ERANGE($1) + } else { /* should flag wrong type even if nothing to write */ + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } } - /* Preceding has written nothing for record variables, now try */ - /* again with more than 0 records */ + /* Preceding has written nothing for record variables, now try */ + /* again with more than 0 records */ - /* Write record number NRECS to force writing of preceding records */ - /* Assumes variable cr is char vector with UNLIMITED dimension */ - err = nc_inq_varid(ncid, "cr", &varid); - IF (err) - error("nc_inq_varid: %s", nc_strerror(err)); + /* Write record number NRECS to force writing of preceding records */ + /* Assumes variable cr is char vector with UNLIMITED dimension */ + err = APIFunc(inq_varid)(ncid, "cr", &varid); + IF (err != NC_NOERR) + error("inq_varid: %s", APIFunc(strerror)(err)); index[0] = NRECS-1; - err = nc_put_var1_text(ncid, varid, index, "x"); - IF (err) - error("nc_put_var1_text: %s", nc_strerror(err)); + err = PutVar1(text)(ncid, varid, index, "x"); + IF (err != NC_NOERR) + error("put_var1_text: %s", APIFunc(strerror)(err)); for (i = 0; i < numVars; i++) { - if (var_dimid[i][0] == RECDIM) { /* only test record variables here */ - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - err = nc_put_var_$1(BAD_ID, i, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - nels *= var_shape[i][j]; - } - for (allInExtRange = 1, j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase 1"); - value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1)); - allInExtRange = allInExtRange - && inRange3(value[j], var_type[i], NCT_ITYPE($1)); - } - err = nc_put_var_$1(ncid, i, value); - if (canConvert) { - if (allInExtRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("range error: status = %d", err); - } - } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); - } + if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */ + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + + for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + value[j]= hash_$1(cdf_format,var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + IfCheckTextChar($1, var_type[i]) + allInExtRange &= inRange3(cdf_format, (double)value[j], + var_type[i], NCT_ITYPE($1)); + } + err = PutVar($1)(ncid, i, value); + if (canConvert) { + if (allInExtRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } else { + IF (err != NC_ERANGE) + EXPECT_ERR(NC_ERANGE, err) + ELSE_NOK + } + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); - check_vars_$1(scratch); + nok += check_vars_$1(scratch, numVars); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("delete file %s failed", scratch); + return nok; } ')dnl @@ -541,155 +652,206 @@ dnl TEST_NC_PUT_VARA(TYPE) dnl define(`TEST_NC_PUT_VARA',dnl `dnl -void -test_nc_put_vara_$1(void) +int +TestFunc(vara)_$1(VarArgs) { - int ncid; - int d; - int i; - int j; - int k; - int err; - int nslabs; - int nels; - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t index[MAX_RANK]; - int canConvert; /* Both text or both numeric */ - int allInExtRange; /* all values within external range? */ + int i, k, d, err, nslabs, ncid, cdf_format, nok=0; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + IntType j, nels; + IntType start[MAX_RANK], edge[MAX_RANK]; + IntType mid[MAX_RANK], index[MAX_RANK]; $1 value[MAX_NELS]; - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; + err = FileCreate(scratch, NC_CLOBBER); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; } + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) + error("inq_format: %s", APIFunc(strerror)(err)); + def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); + DefVars(ncid, numVars); -#ifdef USE_PNETCDF - { - int format; - nc_inq_format_extended(ncid, &format, NULL); - if (format == NC_FORMATX_PNETCDF) { - for (i = 0; i < numVars; i++) { - err = nc_var_par_access(ncid, i, NC_COLLECTIVE); - IF (err) - error("nc_var_par_access: %s", nc_strerror(err)); - } - } - } -#endif + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVara($1)(BAD_ID, 0, NULL, NULL, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVara($1)(ncid, BAD_VARID, NULL, NULL, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK - value[0] = 0; for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); + + value[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVara($1)(BAD_ID, i, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + for (j = 0; j < var_rank[i]; j++) { start[j] = 0; edge[j] = 1; - } - err = nc_put_vara_$1(BAD_ID, i, start, edge, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_vara_$1(ncid, BAD_VARID, start, edge, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - start[j] = var_shape[i][j]; - err = nc_put_vara_$1(ncid, i, start, edge, value); - IF (canConvert && err != NC_EINVALCOORDS) - error("bad start: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_put_vara_$1(ncid, i, start, edge, value); - IF (canConvert && err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - } } -/* wkliao: this test below of put_vara is redundant and incorrectly uses the - value[] set from the previously iteration. There is no such test - in put_vars and put_varm. - - err = nc_put_vara_$1(ncid, i, start, edge, value); - if (canConvert) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ECHAR) - error("wrong type: status = %d", err); +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVara($1)(ncid, i, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) } -*/ + else if (var_rank[i] == 0) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = PutVara($1)(ncid, i, start, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) + } + else if (var_rank[i] == 0) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVara($1)(ncid, i, start, edge, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + start[j] = 0; + continue; + } + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = PutVara($1)(ncid, i, start, edge, value); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDG, err) + ELSE_NOK edge[j] = 1; - } + } - /* Choose a random point dividing each dim into 2 parts */ - /* Put 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { + /* Check correct error returned when nothing to put, when edge[*]==0 */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVara($1)(ncid, i, start, edge, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + start[j] = 0; + continue; + } +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = PutVara($1)(ncid, i, start, edge, value); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + /* Choose a random point dividing each dim into 2 parts */ + /* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to put lower or upper part of dim */ - for (k = 0; k < nslabs; k++) { - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - nels *= edge[j]; - } + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + for (k = 0; k < nslabs; k++) { + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + } else { + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + nels *= edge[j]; + } + for (allInExtRange = 1, j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], edge, index); - IF (err) - error("error in toMixedBase 1"); - for (d = 0; d < var_rank[i]; d++) - index[d] += start[d]; - value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1)); - allInExtRange = allInExtRange - && inRange3(value[j], var_type[i], NCT_ITYPE($1)); - } - if (var_rank[i] == 0 && i%2 == 0) - err = nc_put_vara_$1(ncid, i, NULL, NULL, value); - else - err = nc_put_vara_$1(ncid, i, start, edge, value); - if (canConvert) { - if (allInExtRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("range error: status = %d", err); - } - } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); + err = toMixedBase(j, var_rank[i], edge, index); + IF (err != 0) error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index[d] += start[d]; + value[j]= hash_$1(cdf_format,var_type[i], var_rank[i], index, + NCT_ITYPE($1)); + IfCheckTextChar($1, var_type[i]) + allInExtRange &= inRange3(cdf_format, (double)value[j], + var_type[i], NCT_ITYPE($1)); + } + err = PutVara($1)(ncid, i, start, edge, value); + if (canConvert) { + if (allInExtRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } + PNETCDF_CHECK_ERANGE($1) + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK } } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); - check_vars_$1(scratch); + nok += check_vars_$1(scratch, numVars); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("delete file %s failed", scratch); + return nok; } ')dnl @@ -711,176 +873,235 @@ dnl TEST_NC_PUT_VARS(TYPE) dnl define(`TEST_NC_PUT_VARS',dnl `dnl -void -test_nc_put_vars_$1(void) +int +TestFunc(vars)_$1(VarArgs) { - int ncid; - int d; - int i; - int j; - int k; - int m; - int err; - int nels; - int nslabs; - int nstarts; /* number of different starts */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t index2[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; - int canConvert; /* Both text or both numeric */ - int allInExtRange; /* all values within external range? */ + int i, k, d, err, nslabs, ncid, cdf_format, nok=0; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + IntType j, m, nels; + IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK]; + IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType nstarts; /* number of different starts */ + PTRDType stride[MAX_RANK]; $1 value[MAX_NELS]; - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; + err = FileCreate(scratch, NC_CLOBBER); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; } + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) + error("inq_format: %s", APIFunc(strerror)(err)); + def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); + DefVars(ncid, numVars); -#ifdef USE_PNETCDF - { - int format; - nc_inq_format_extended(ncid, &format, NULL); - if (format == NC_FORMATX_PNETCDF) { - for (i = 0; i < numVars; i++) { - err = nc_var_par_access(ncid, i, NC_COLLECTIVE); - IF (err) - error("nc_var_par_access: %s", nc_strerror(err)); + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVars($1)(BAD_ID, 0, NULL, NULL, NULL, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVars($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + value[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVars($1)(BAD_ID, i, NULL, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; } - } - } +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVars($1)(ncid, i, NULL, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) + } + else if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = PutVars($1)(ncid, i, start, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) + } + else if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; /* out of boundary check */ + err = PutVars($1)(ncid, i, start, edge, stride, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + start[j] = 0; + continue; + } + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = PutVars($1)(ncid, i, start, edge, stride, value); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK + edge[j] = 1; + stride[j] = 0; + err = PutVars($1)(ncid, i, start, edge, stride, value); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + ELSE_NOK + stride[j] = 1; + } + /* Check correct error returned even when nothing to put */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVars($1)(ncid, i, start, edge, stride, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + start[j] = 0; + continue; + } +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) #endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = PutVars($1)(ncid, i, start, edge, stride, value); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; - for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - stride[j] = 1; - } - err = nc_put_vars_$1(BAD_ID, i, start, edge, stride, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_vars_$1(ncid, BAD_VARID, start, edge, stride, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - start[j] = var_shape[i][j] + 1; - err = nc_put_vars_$1(ncid, i, start, edge, stride, value); - if(!canConvert) { - IF(err != NC_ECHAR) - error("conversion: status = %d", err); - } else { - IF(err != NC_EINVALCOORDS) - error("bad start: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_put_vars_$1(ncid, i, start, edge, stride, value); - IF (err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - stride[j] = 0; - err = nc_put_vars_$1(ncid, i, start, edge, stride, value); - IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); - stride[j] = 1; - } - } - } - /* Choose a random point dividing each dim into 2 parts */ - /* Put 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { - mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to put lower or upper part of dim */ - /* choose random stride from 1 to edge */ - for (k = 0; k < nslabs; k++) { - nstarts = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; - nstarts *= stride[j]; - } - for (m = 0; m < nstarts; m++) { - err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; - nels *= count[j]; - index[j] += start[j]; - } - /* Random choice of forward or backward */ + /* Choose a random point dividing each dim into 2 parts */ + /* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + } else { + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err != 0) error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ /* TODO - if ( roll(2) ) { - for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; - stride[j] = -stride[j]; - } - } + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * (IntType)stride[j]; + stride[j] = -stride[j]; + } + } */ - for (allInExtRange = 1, j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], count, index2); - IF (err) - error("error in toMixedBase"); - for (d = 0; d < var_rank[i]; d++) - index2[d] = index[d] + index2[d] * stride[d]; - value[j] = hash_$1(var_type[i], var_rank[i], index2, - NCT_ITYPE($1)); - allInExtRange = allInExtRange - && inRange3(value[j], var_type[i], NCT_ITYPE($1)); - } - if (var_rank[i] == 0 && i%2 == 0) - err = nc_put_vars_$1(ncid, i, NULL, NULL, stride, value); - else - err = nc_put_vars_$1(ncid, i, index, count, stride, value); - if (canConvert) { - if (allInExtRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("range error: status = %d", err); - } - } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); - } - } - } + for (allInExtRange = 1, j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err != 0) error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * (IntType)stride[d]; + value[j] = hash_$1(cdf_format,var_type[i], var_rank[i], + index2, NCT_ITYPE($1)); + IfCheckTextChar($1, var_type[i]) + allInExtRange &= inRange3(cdf_format, (double)value[j], + var_type[i], NCT_ITYPE($1)); + } + err = PutVars($1)(ncid, i, index, count, stride, value); + if (canConvert) { + if (allInExtRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } + PNETCDF_CHECK_ERANGE($1) + } else { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + } + } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); - check_vars_$1(scratch); + nok += check_vars_$1(scratch, numVars); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("delete file %s failed", scratch); + return nok; } ')dnl @@ -902,184 +1123,243 @@ dnl TEST_NC_PUT_VARM(TYPE) dnl define(`TEST_NC_PUT_VARM',dnl `dnl -void -test_nc_put_varm_$1(void) +int +TestFunc(varm)_$1(VarArgs) { - int ncid; - int d; - int i; - int j; - int k; - int m; - int err; - int nels; - int nslabs; - int nstarts; /* number of different starts */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t index2[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; - ptrdiff_t imap[MAX_RANK]; - int canConvert; /* Both text or both numeric */ - int allInExtRange; /* all values within external range? */ + int i, k, d, err, nslabs, ncid, cdf_format, nok=0; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + IntType j, m, nels; + IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK]; + IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType nstarts; /* number of different starts */ + PTRDType stride[MAX_RANK], imap[MAX_RANK]; $1 value[MAX_NELS]; - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; + err = FileCreate(scratch, NC_CLOBBER); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; } + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) + error("inq_format: %s", APIFunc(strerror)(err)); + def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); + DefVars(ncid, numVars); -#ifdef USE_PNETCDF - { - int format; - nc_inq_format_extended(ncid, &format, NULL); - if (format == NC_FORMATX_PNETCDF) { - for (i = 0; i < numVars; i++) { - err = nc_var_par_access(ncid, i, NC_COLLECTIVE); - IF (err) - error("nc_var_par_access: %s", nc_strerror(err)); + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVarm($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVarm($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + value[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVarm($1)(BAD_ID, i, NULL, NULL, NULL, NULL, value); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + canConvert = (var_type[i] == NC_CHAR) CheckText($1); + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + imap[j] = 1; } - } - } + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVarm($1)(ncid, i, NULL, NULL, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) + } + else if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = PutVarm($1)(ncid, i, start, NULL, NULL, NULL, value); + if (!canConvert) { + IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err) + } + else if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; /* out of boundary check */ + err = PutVarm($1)(ncid, i, start, edge, stride, imap, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + start[j] = 0; + continue; + } + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = PutVarm($1)(ncid, i, start, edge, stride, imap, value); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK + edge[j] = 1; + stride[j] = 0; + err = PutVarm($1)(ncid, i, start, edge, stride, imap, value); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + ELSE_NOK + stride[j] = 1; + } + /* Check correct error returned when nothing to put, i.e. edge[*]==0 */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVarm($1)(ncid, i, start, edge, stride, imap, value); + if (!canConvert) { + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + start[j] = 0; + continue; + } +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) #endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = PutVarm($1)(ncid, i, start, edge, stride, imap, value); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; - for (i = 0; i < numVars; i++) { - canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - stride[j] = 1; - imap[j] = 1; - } - err = nc_put_varm_$1(BAD_ID, i, start, edge, stride, imap, value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_varm_$1(ncid, BAD_VARID, start, edge, stride, imap, value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - start[j] = var_shape[i][j] + 1; - err = nc_put_varm_$1(ncid, i, start, edge, stride, imap, value); - if (!canConvert) { - IF(err != NC_ECHAR) - error("conversion: status = %d", err); - } else { - IF (err != NC_EINVALCOORDS) - error("bad start: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_put_varm_$1(ncid, i, start, edge, stride, imap, value); - IF (err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - stride[j] = 0; - err = nc_put_varm_$1(ncid, i, start, edge, stride, imap, value); - IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); - stride[j] = 1; - } - } - } - /* Choose a random point dividing each dim into 2 parts */ - /* Put 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { - mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to put lower or upper part of dim */ - /* choose random stride from 1 to edge */ - for (k = 0; k < nslabs; k++) { - nstarts = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; - nstarts *= stride[j]; - } + /* Choose a random point dividing each dim into 2 parts */ + /* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + } else { + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; + nstarts *= stride[j]; + } for (m = 0; m < nstarts; m++) { err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); + IF (err != 0) error("error in toMixedBase"); nels = 1; for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j]; nels *= count[j]; index[j] += start[j]; } - /* Random choice of forward or backward */ + /* Random choice of forward or backward */ /* TODO if ( roll(2) ) { for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; + index[j] += (count[j] - 1) * (IntType)stride[j]; stride[j] = -stride[j]; } } */ if (var_rank[i] > 0) { - j = var_rank[i] - 1; - imap[j] = 1; - for (; j > 0; j--) - imap[j-1] = imap[j] * count[j]; + int jj = var_rank[i] - 1; + imap[jj] = 1; + for (; jj > 0; jj--) + imap[jj-1] = imap[jj] * (PTRDType)count[jj]; } for (allInExtRange = 1, j = 0; j < nels; j++) { err = toMixedBase(j, var_rank[i], count, index2); - IF (err) - error("error in toMixedBase"); + IF (err != 0) error("error in toMixedBase"); for (d = 0; d < var_rank[i]; d++) - index2[d] = index[d] + index2[d] * stride[d]; - value[j] = hash_$1(var_type[i], var_rank[i], index2, - NCT_ITYPE($1)); - allInExtRange = allInExtRange - && inRange3(value[j], var_type[i], NCT_ITYPE($1)); + index2[d] = index[d] + index2[d] * (IntType)stride[d]; + value[j] = hash_$1(cdf_format,var_type[i], var_rank[i], + index2, NCT_ITYPE($1)); + IfCheckTextChar($1, var_type[i]) + allInExtRange &= inRange3(cdf_format, (double)value[j], + var_type[i], NCT_ITYPE($1)); } - if (var_rank[i] == 0 && i%2 == 0) - err = nc_put_varm_$1(ncid,i,NULL,NULL,NULL,NULL,value); - else - err = nc_put_varm_$1(ncid,i,index,count,stride,imap,value); + err = PutVarm($1)(ncid,i,index,count,stride,imap,value); if (canConvert) { if (allInExtRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("range error: status = %d", err); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK } + PNETCDF_CHECK_ERANGE($1) } else { - IF (nels > 0 && err != NC_ECHAR) - error("wrong type: status = %d", err); - } - } - } + IF (err != NC_ECHAR) + EXPECT_ERR(NC_ECHAR, err) + ELSE_NOK + } + } + } } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); - check_vars_$1(scratch); + nok += check_vars_$1(scratch, numVars); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("delete file %s failed", scratch); + return nok; } ')dnl @@ -1097,64 +1377,73 @@ TEST_NC_PUT_VARM(longlong) TEST_NC_PUT_VARM(ulonglong) -void -test_nc_put_att_text(void) +int +TestFunc(att)_text(AttVarArgs) { - int ncid; - int i; - int j; - size_t k; - int err; + int i, j, err, ncid, nok=0; + IntType k; text value[MAX_NELS]; - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; + err = FileCreate(scratch, NC_NOCLOBBER); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; } def_dims(ncid); - def_vars(ncid); + DefVars(ncid, numVars); + + /* check if can detect a bad file ID */ + err = PutAtt(text)(BAD_ID, 0, NULL, 0, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutAtt(text)(ncid, BAD_VARID, NULL, 0, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK { - const char *const tval = "value for bad name"; - const size_t tval_len = strlen(tval); - - err = nc_put_att_text(ncid, 0, "", tval_len, tval); - IF (err != NC_EBADNAME) - error("should be NC_EBADNAME: status = %d", err); + const char *const tval = "value for bad name"; + const IntType tval_len = (IntType)strlen(tval); + + err = PutAtt(text)(ncid, 0, "", tval_len, tval); + IF (err != NC_EBADNAME) + EXPECT_ERR(NC_EBADNAME, err) + ELSE_NOK } for (i = -1; i < numVars; i++) { for (j = 0; j < NATTS(i); j++) { if (ATT_TYPE(i,j) == NC_CHAR) { - assert(ATT_LEN(i,j) <= MAX_NELS); - err = nc_put_att_text(BAD_ID, i, ATT_NAME(i,j), ATT_LEN(i,j), - value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_att_text(ncid, BAD_VARID, ATT_NAME(i,j), - ATT_LEN(i,j), value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (k = 0; k < ATT_LEN(i,j); k++) { - value[k] = hash(ATT_TYPE(i,j), -1, &k); - } - err = nc_put_att_text(ncid, i, ATT_NAME(i,j), - ATT_LEN(i,j), value); - IF (err) { - error("%s", nc_strerror(err)); - } - } + assert(ATT_LEN(i,j) <= MAX_NELS); + + err = PutAtt(text)(ncid, BAD_VARID, ATT_NAME(i,j), ATT_LEN(i,j), value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + for (k = 0; k < ATT_LEN(i,j); k++) { + double dtmp = hash(ATT_TYPE(i,j), -1, &k); + value[k] = (text)dtmp; + } + err = PutAtt(text)(ncid, i, ATT_NAME(i,j), ATT_LEN(i,j), value); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } } } - check_atts_text(ncid); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); + nok += check_atts_text(ncid, numGatts, numVars); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("delete file %s failed", scratch); + return nok; } @@ -1162,67 +1451,85 @@ dnl TEST_NC_PUT_ATT(TYPE) numeric only dnl define(`TEST_NC_PUT_ATT',dnl `dnl -void -test_nc_put_att_$1(void) +int +TestFunc(att)_$1(AttVarArgs) { - int ncid; - int i; - int j; - size_t k; - int err; - $1 value[MAX_NELS]; + int i, j, err, ncid, cdf_format, nok=0; int allInExtRange; /* all values within external range? */ + IntType k; + $1 value[MAX_NELS]; - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; + err = FileCreate(scratch, NC_NOCLOBBER); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; } + + err = APIFunc(inq_format)(ncid, &cdf_format); + IF (err != NC_NOERR) + error("inq_format: %s", APIFunc(strerror)(err)); + def_dims(ncid); - def_vars(ncid); + DefVars(ncid, numVars); + + /* check if can detect a bad file ID */ + err = PutAtt($1)(BAD_ID, 0, NULL, 0, 0, NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutAtt($1)(ncid, BAD_VARID, NULL, 0, 0, NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK for (i = -1; i < numVars; i++) { for (j = 0; j < NATTS(i); j++) { if (!(ATT_TYPE(i,j) == NC_CHAR)) { - assert(ATT_LEN(i,j) <= MAX_NELS); - err = nc_put_att_$1(BAD_ID, i, ATT_NAME(i,j), ATT_TYPE(i,j), - ATT_LEN(i,j), value); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), - ATT_TYPE(i,j), ATT_LEN(i,j), value); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_put_att_$1(ncid, i, ATT_NAME(i,j), BAD_TYPE, - ATT_LEN(i,j), value); - IF (err != NC_EBADTYPE) - error("bad type: status = %d", err); - for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) { - value[k] = hash_$1(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); - allInExtRange = allInExtRange - && inRange3(value[k], ATT_TYPE(i,j), NCT_ITYPE($1)); - } - err = nc_put_att_$1(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), - ATT_LEN(i,j), value); - if (allInExtRange) { - IF (err) - error("%s", nc_strerror(err)); - } else { - IF (err != NC_ERANGE) - error("range error: status = %d", err); - } - } + assert(ATT_LEN(i,j) <= MAX_NELS); + + err = PutAtt($1)(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + /* check if can detect a bad name */ + err = PutAtt($1)(ncid, i, NULL, 0, 0, NULL); + IF (err != NC_EBADNAME) + EXPECT_ERR(NC_EBADNAME, err) + ELSE_NOK + + err = PutAtt($1)(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value); + IF (err != NC_EBADTYPE) + EXPECT_ERR(NC_EBADTYPE, err) + ELSE_NOK + + for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) { + value[k] = hash_$1(cdf_format,ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); + IfCheckTextChar($1, ATT_TYPE(i,j)) + allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_ITYPE($1)); + } + err = PutAtt($1)(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value); + if (allInExtRange) { + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } + PNETCDF_CHECK_ERANGE($1) + } } } - check_atts_$1(ncid); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); + nok += check_atts_$1(ncid, numGatts, numVars); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("delete file %s failed", scratch); + return nok; } ')dnl diff --git a/nc_test/test_read.c b/nc_test/test_read.c deleted file mode 100644 index 96edad9589..0000000000 --- a/nc_test/test_read.c +++ /dev/null @@ -1,1613 +0,0 @@ -/********************************************************************* - * Copyright 1996, UCAR/Unidata - * See netcdf/COPYRIGHT file for copying and redistribution conditions. - * $Id: test_read.c 2792 2014-10-27 06:02:59Z wkliao $ - *********************************************************************/ - -#include "tests.h" - -/* - * Test nc_strerror. - * Try on a bad error status. - * Test for each defined error status. - */ -void -test_nc_strerror(void) -{ - int i; - const char *message; - - static const struct { - int status; - const char *msg; - } ncerrs[] = { - {NC_NOERR, "No error"}, - {NC_EBADID, "NetCDF: Not a valid ID"}, - {NC_ENFILE, "NetCDF: Too many files open"}, - {NC_EEXIST, "NetCDF: File exists && NC_NOCLOBBER"}, - {NC_EINVAL, "NetCDF: Invalid argument"}, - {NC_EPERM, "NetCDF: Write to read only"}, - {NC_ENOTINDEFINE, "NetCDF: Operation not allowed in data mode"}, - {NC_EINDEFINE, "NetCDF: Operation not allowed in define mode"}, - {NC_EINVALCOORDS, "NetCDF: Index exceeds dimension bound"}, - {NC_EMAXDIMS, "NetCDF: NC_MAX_DIMS exceeded"}, - {NC_ENAMEINUSE, "NetCDF: String match to name in use"}, - {NC_ENOTATT, "NetCDF: Attribute not found"}, - {NC_EMAXATTS, "NetCDF: NC_MAX_ATTRS exceeded"}, - {NC_EBADTYPE, "NetCDF: Not a valid data type or _FillValue type mismatch"}, - {NC_EBADDIM, "NetCDF: Invalid dimension ID or name"}, - {NC_EUNLIMPOS, "NetCDF: NC_UNLIMITED in the wrong index"}, - {NC_EMAXVARS, "NetCDF: NC_MAX_VARS exceeded"}, - {NC_ENOTVAR, "NetCDF: Variable not found"}, - {NC_EGLOBAL, "NetCDF: Action prohibited on NC_GLOBAL varid"}, - {NC_ENOTNC, "NetCDF: Unknown file format"}, - {NC_ESTS, "NetCDF: In Fortran, string too short"}, - {NC_EMAXNAME, "NetCDF: NC_MAX_NAME exceeded"}, - {NC_EUNLIMIT, "NetCDF: NC_UNLIMITED size already in use"}, - {NC_ENORECVARS, "NetCDF: nc_rec op when there are no record vars"}, - {NC_ECHAR, "NetCDF: Attempt to convert between text & numbers"}, - {NC_EEDGE, "NetCDF: Start+count exceeds dimension bound"}, - {NC_ESTRIDE, "NetCDF: Illegal stride"}, - {NC_EBADNAME, "NetCDF: Name contains illegal characters"}, - {NC_ERANGE, "NetCDF: Numeric conversion not representable"}, - {NC_ENOMEM, "NetCDF: Memory allocation (malloc) failure"}, - {NC_EVARSIZE, "NetCDF: One or more variable sizes violate format constraints"}, - {NC_EDIMSIZE, "NetCDF: Invalid dimension size"} - }; - - /* Try on a bad error status */ - /* Dmh: allow trailing extra info */ - message = nc_strerror(-666);/* should fail */ - IF (strncmp(message, "Unknown Error", strlen("Unknown Error")) != 0) - error("nc_strerror on bad error status returned: %s", message); - - /* Try on each legitimate error status */ - /* Dmh: allow trailing extra info */ - for (i=0; i> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - nels *= edge[j]; - } - if (var_rank[i] == 0 && i%2 ) - err = nc_get_vara(ncid, i, NULL, NULL, buf); - else - err = nc_get_vara(ncid, i, start, edge, buf); - IF (err) { - error("%s", nc_strerror(err)); - } else { - for (j = 0; j < nels; j++) { - p = (char *) buf; - p += j * nctypelen(var_type[i]); - err = nc2dbl( var_type[i], p, & got ); - IF (err) - error("error in nc2dbl"); - err = toMixedBase(j, var_rank[i], edge, index); - IF (err) - error("error in toMixedBase 1"); - for (d = 0; d < var_rank[i]; d++) - index[d] += start[d]; - expect = hash(var_type[i], var_rank[i], index); - if (inRange(expect,var_type[i])) { - IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { - error("value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("element number: %d ", j); - error("expect: %g", expect); - error("got: %g", got); - } - } else { - nok++; - } - } - } - } - } - } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); -} - - -/* - * Test nc_get_vars - * Choose a random point dividing each dim into 2 parts - * Get 2^rank (nslabs) slabs so defined - * Each get overwrites buffer, so check after each get. - */ -void -test_nc_get_vars(void) -{ - int ncid; - int d; - int i; - int j; - int k; - int m; - int err; - int nels; - int nslabs; - int nstarts; /* number of different starts */ - int nok = 0; /* total count of valid comparisons */ - int n; /* count of valid comparisons within var */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t index2[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; - double buf[MAX_NELS]; /* (void *) buffer */ - char *p; /* (void *) pointer */ - double expect; - double got; - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - for (i = 0; i < numVars; i++) { - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - stride[j] = 1; - } - err = nc_get_vars(BAD_ID, i, start, edge, stride, buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_vars(ncid, BAD_VARID, start, edge, stride, buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - start[j] = var_shape[i][j]; - err = nc_get_vars(ncid, i, start, edge, stride, buf); - IF (err != NC_EINVALCOORDS) - error("bad index: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_get_vars(ncid, i, start, edge, stride, buf); - IF (err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - stride[j] = 0; - err = nc_get_vars(ncid, i, start, edge, stride, buf); - IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); - stride[j] = 1; - } - /* Choose a random point dividing each dim into 2 parts */ - /* get 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { - mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to get lower or upper part of dim */ - /* choose random stride from 1 to edge */ - n = 0; - for (k = 0; k < nslabs; k++) { - nstarts = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; - nstarts *= stride[j]; - } - for (m = 0; m < nstarts; m++) { - err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; - nels *= count[j]; - index[j] += start[j]; - } - /* Random choice of forward or backward */ -/* TODO - if ( roll(2) ) { - for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; - stride[j] = -stride[j]; - } - } - */ - if (var_rank[i] == 0 && i%2 ) - err = nc_get_vars(ncid, i, NULL, NULL, NULL, buf); - else - err = nc_get_vars(ncid, i, index, count, stride, buf); - IF (err) { - error("%s", nc_strerror(err)); - } else { - for (j = 0; j < nels; j++) { - p = (char *) buf; - p += j * nctypelen(var_type[i]); - err = nc2dbl( var_type[i], p, & got ); - IF (err) - error("error in nc2dbl"); - err = toMixedBase(j, var_rank[i], count, index2); - IF (err) - error("error in toMixedBase 1"); - for (d = 0; d < var_rank[i]; d++) - index2[d] = index[d] + index2[d] * stride[d]; - expect = hash(var_type[i], var_rank[i], index2); - if (inRange(expect,var_type[i])) { - IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { - error("value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("element number: %d ", j); - error("expect: %g, ", expect); - error("got: %g ", got); - } - } else { - nok++; - } - } - n++; - } - } - } - } - IF (n != var_nels[i]) { - error("count != nels"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("count: %d, ", n); - error("nels: %d ", var_nels[i]); - } - } - } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); -} - - -/* - * Test nc_get_varm - * Choose a random point dividing each dim into 2 parts - * Get 2^rank (nslabs) slabs so defined - * Choose random stride from 1 to edge - * Buffer should end up being bit image of external variable. - * So all gets for a variable store in different elements of buffer - */ -void -test_nc_get_varm(void) -{ - int ncid; - int i; - int j; - int k; - int m; - int err; - int nslabs; - int nstarts; /* number of different starts */ - int nok = 0; /* total count of valid comparisons */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; - ptrdiff_t imap[MAX_RANK]; - ptrdiff_t imap2[MAX_RANK]; - double buf[MAX_NELS]; /* (void *) buffer */ - char *p; /* (void *) pointer */ - double expect; - double got; - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - for (i = 0; i < numVars; i++) { - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - stride[j] = 1; - } - if (var_rank[i] > 0) { - j = var_rank[i] - 1; - /* imap[j] = nctypelen(var_type[i]); in bytes */ - imap[j] = 1; /* in numbers of elements */ - for (; j > 0; j--) - imap[j-1] = imap[j] * var_shape[i][j]; - } - err = nc_get_varm(BAD_ID, i, start, edge, stride, imap, buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_varm(ncid, BAD_VARID, start, edge, stride, imap, buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - start[j] = var_shape[i][j]; - err = nc_get_varm(ncid, i, start, edge, stride, imap, buf); - IF (err != NC_EINVALCOORDS) - error("bad index: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_get_varm(ncid, i, start, edge, stride, imap, buf); - IF (err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - stride[j] = 0; - err = nc_get_varm(ncid, i, start, edge, stride, imap, buf); - IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); - stride[j] = 1; - } - /* Choose a random point dividing each dim into 2 parts */ - /* get 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { - mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to get lower or upper part of dim */ - /* choose random stride from 1 to edge */ - for (k = 0; k < nslabs; k++) { - nstarts = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; - imap2[j] = imap[j] * sstride[j]; - nstarts *= stride[j]; - } - for (m = 0; m < nstarts; m++) { - if (var_rank[i] == 0 && i%2 ) { - err = nc_get_varm(ncid, i, NULL, NULL, NULL, NULL, buf); - } else { - err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); - for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; - index[j] += start[j]; - } - /* Random choice of forward or backward */ -/* TODO - if ( roll(2) ) { - for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; - stride[j] = -stride[j]; - } - } - */ - j = fromMixedBase(var_rank[i], index, var_shape[i]); - p = (char *) buf + j * nctypelen(var_type[i]); - err = nc_get_varm(ncid, i, index, count, stride, imap2, p); - } - IF (err) - error("%s", nc_strerror(err)); - } - } - p = (char *) buf; - for (j = 0; j < var_nels[i]; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase"); - expect = hash( var_type[i], var_rank[i], index); - err = nc2dbl( var_type[i], p, & got ); - IF (err) - error("error in nc2dbl"); - if (inRange(expect,var_type[i])) { - IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { - error("value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", var_name[i]); - error("element number: %d ", j); - error("expect: %g, ", expect); - error("got: %g ", got); - } - } else { - nok++; - } - } - p += nctypelen(var_type[i]); - } - } - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); -} - - -void -test_nc_get_att(void) -{ - int ncid; - int i; - int j; - size_t k; - int err; - double buf[MAX_NELS]; /* (void *) buffer */ - signed char *p; /* (void *) pointer */ - double expect; - double got; - int nok = 0; /* count of valid comparisons */ - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - for (j = 0; j < NATTS(i); j++) { - err = nc_get_att(BAD_ID, i, ATT_NAME(i,j), buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_get_att(ncid, BAD_VARID, ATT_NAME(i,j), buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_get_att(ncid, i, "noSuch", buf); - IF (err != NC_ENOTATT) - error("Bad attribute name: status = %d", err); - err = nc_get_att(ncid, i, ATT_NAME(i,j), buf); - IF (err) { - error("%s", nc_strerror(err)); - } else { - for (k = 0; k < ATT_LEN(i,j); k++) { - expect = hash(ATT_TYPE(i,j), -1, &k ); - p = (signed char *) buf; - p += k * nctypelen(ATT_TYPE(i,j)); - err = nc2dbl( ATT_TYPE(i,j), p, &got ); - IF (err) - error("error in nc2dbl"); - if (inRange(expect,ATT_TYPE(i,j))) { - IF (!equal(got,expect,ATT_TYPE(i,j),NCT_DOUBLE)) { - error("value read not that expected"); - if (verbose) { - error("\n"); - error("varid: %d, ", i); - error("var_name: %s, ", - i >= 0 ? var_name[i] : "Global"); - error("att_name: %s, ", ATT_NAME(i,j)); - error("element number: %d\n", k); - error("expect: %-23.16e\n", expect); - error(" got: %-23.16e", got); - } - } else { - nok++; - } - } - } - } - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - print_nok(nok); -} - - -void -test_nc_inq_att(void) -{ - int ncid; - int i; - int j; - int err; - nc_type t; - size_t n; - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - for (j = 0; j < NATTS(i); j++) { - err = nc_inq_att(BAD_ID, i, ATT_NAME(i,j), &t, &n); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_inq_att(ncid, BAD_VARID, ATT_NAME(i,j), &t, &n); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_inq_att(ncid, i, "noSuch", &t, &n); - IF (err != NC_ENOTATT) - error("Bad attribute name: status = %d", err); - err = nc_inq_att(ncid, i, ATT_NAME(i,j), &t, &n); - IF (err) { - error("%s", nc_strerror(err)); - } else { - IF (t != ATT_TYPE(i,j)) - error("type not that expected"); - IF (n != ATT_LEN(i,j)) - error("length not that expected"); - } - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); -} - - -void -test_nc_inq_attlen(void) -{ - int ncid; - int i; - int j; - int err; - size_t len; - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - err = nc_inq_attlen(ncid, i, "noSuch", &len); - IF (err != NC_ENOTATT) - error("Bad attribute name: status = %d", err); - for (j = 0; j < NATTS(i); j++) { - err = nc_inq_attlen(BAD_ID, i, ATT_NAME(i,j), &len); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_inq_attlen(ncid, BAD_VARID, ATT_NAME(i,j), &len); - IF (err != NC_ENOTVAR) - error("bad varid: status = %d", err); - err = nc_inq_attlen(ncid, i, ATT_NAME(i,j), &len); - IF (err) { - error("%s", nc_strerror(err)); - } else { - IF (len != ATT_LEN(i,j)) - error("len not that expected"); - } - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); -} - - -void -test_nc_inq_atttype(void) -{ - int ncid; - int i; - int j; - int err; - nc_type datatype; - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - err = nc_inq_atttype(ncid, i, "noSuch", &datatype); - IF (err != NC_ENOTATT) - error("Bad attribute name: status = %d", err); - for (j = 0; j < NATTS(i); j++) { - err = nc_inq_atttype(BAD_ID, i, ATT_NAME(i,j), &datatype); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_inq_atttype(ncid, BAD_VARID, ATT_NAME(i,j), &datatype); - IF (err != NC_ENOTVAR) - error("bad varid: status = %d", err); - err = nc_inq_atttype(ncid, i, ATT_NAME(i,j), &datatype); - IF (err) { - error("%s", nc_strerror(err)); - } else { - IF (datatype != ATT_TYPE(i,j)) - error("type not that expected"); - } - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); -} - - -void -test_nc_inq_attname(void) -{ - int ncid; - int i; - int j; - int err; - char name[NC_MAX_NAME]; - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - err = nc_inq_attname(ncid, i, BAD_ATTNUM, name); - IF (err != NC_ENOTATT) - error("Bad attribute number: status = %d", err); - err = nc_inq_attname(ncid, i, NATTS(i), name); - IF (err != NC_ENOTATT) - error("Bad attribute number: status = %d", err); - for (j = 0; j < NATTS(i); j++) { - err = nc_inq_attname(BAD_ID, i, j, name); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_inq_attname(ncid, BAD_VARID, j, name); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_inq_attname(ncid, i, j, name); - IF (err) { - error("%s", nc_strerror(err)); - } else { - IF (strcmp(ATT_NAME(i,j), name) != 0) - error("name not that expected"); - } - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); -} - - -void -test_nc_inq_attid(void) -{ - int ncid; - int i; - int j; - int err; - int attnum; - - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - err = nc_inq_attid(ncid, i, "noSuch", &attnum); - IF (err != NC_ENOTATT) - error("Bad attribute name: status = %d", err); - for (j = 0; j < NATTS(i); j++) { - err = nc_inq_attid(BAD_ID, i, ATT_NAME(i,j), &attnum); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_inq_attid(ncid, BAD_VARID, ATT_NAME(i,j), &attnum); - IF (err != NC_ENOTVAR) - error("bad varid: status = %d", err); - err = nc_inq_attid(ncid, i, ATT_NAME(i,j), &attnum); - IF (err) { - error("%s", nc_strerror(err)); - } else { - IF (attnum != j) - error("attnum not that expected"); - } - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); -} diff --git a/nc_test/test_read.m4 b/nc_test/test_read.m4 new file mode 100644 index 0000000000..1160c2123b --- /dev/null +++ b/nc_test/test_read.m4 @@ -0,0 +1,2039 @@ +dnl This is m4 source. +dnl Process using m4 to produce 'C' language file. +dnl +dnl This file is supposed to be the same as PnetCDF's test_read.m4 +dnl +dnl If you see this line, you can ignore the next one. +/* Do not edit this file. It is produced from the corresponding .m4 source */ +dnl +/* + * Copyright (C) 2003, Northwestern University and Argonne National Laboratory + * See COPYRIGHT notice in top-level directory. + */ +/* $Id: test_read.m4 2640 2016-11-18 21:08:08Z wkliao $ */ + +dnl +dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF +dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types +dnl (MPI_Offset vs. size_t), and function name substrings for external data +dnl types. +dnl + +#include /* open() */ +#include /* open() */ +#include /* open() */ +#include /* unlink(), write() */ +#include /* errno, strerror() */ + +#include "tests.h" + +define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl + +define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl +define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl +define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_$1',`test_nc_$1')')dnl +define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl + +define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, $3)', `file_open($1, $2, $3)')')dnl +define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, $3)', `file_create($1, $2, $3)')')dnl +define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl + +define(`VarArgs', `ifdef(`PNETCDF',`int numVars',`void')')dnl +define(`AttArgs', `ifdef(`PNETCDF',`int numGatts',`void')')dnl +define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts, int numVars',`void')')dnl + +define(`GetVar1', `ifdef(`PNETCDF',`ncmpi_get_var1_all($1,$2,$3,$4,$5,$6)', `nc_get_var1($1,$2,$3,$4)')')dnl +define(`GetVar', `ifdef(`PNETCDF',`ncmpi_get_var_all( $1,$2,$3,$4,$5)', `nc_get_var( $1,$2,$3)')')dnl +define(`GetVara', `ifdef(`PNETCDF',`ncmpi_get_vara_all($1,$2,$3,$4,$5,$6,$7)', `nc_get_vara($1,$2,$3,$4,$5)')')dnl +define(`GetVars', `ifdef(`PNETCDF',`ncmpi_get_vars_all($1,$2,$3,$4,$5,$6,$7,$8)', `nc_get_vars($1,$2,$3,$4,$5,$6)')')dnl +define(`GetVarm', `ifdef(`PNETCDF',`ncmpi_get_varm_all($1,$2,$3,$4,$5,$6,$7,$8,$9)', `nc_get_varm($1,$2,$3,$4,$5,$6,$7)')')dnl + +/* + * Test APIFunc(strerror). + * Try on a bad error status. + * Test for each defined error status. + */ +int +TestFunc(strerror)(void) +{ + int i; + const char *message, *expected_msg; + int nok=0; + + static const struct { + int status; + const char *msg; + } ncerrs[] = { + {NC_NOERR, "No error"}, + {NC_EBADID, "NetCDF: Not a valid ID"}, + {NC_ENFILE, "NetCDF: Too many files open"}, + {NC_EEXIST, "NetCDF: File exists && NC_NOCLOBBER"}, + {NC_EINVAL, "NetCDF: Invalid argument"}, + {NC_EPERM, "NetCDF: Write to read only"}, + {NC_ENOTINDEFINE, "NetCDF: Operation not allowed in data mode"}, + {NC_EINDEFINE, "NetCDF: Operation not allowed in define mode"}, + {NC_EINVALCOORDS, "NetCDF: Index exceeds dimension bound"}, + {NC_EMAXDIMS, "NetCDF: NC_MAX_DIMS exceeded"}, + {NC_ENAMEINUSE, "NetCDF: String match to name in use"}, + {NC_ENOTATT, "NetCDF: Attribute not found"}, + {NC_EMAXATTS, "NetCDF: NC_MAX_ATTRS exceeded"}, + {NC_EBADTYPE, "NetCDF: Not a valid data type or _FillValue type mismatch"}, + {NC_EBADDIM, "NetCDF: Invalid dimension ID or name"}, + {NC_EUNLIMPOS, "NetCDF: NC_UNLIMITED in the wrong index"}, + {NC_EMAXVARS, "NetCDF: NC_MAX_VARS exceeded"}, + {NC_ENOTVAR, "NetCDF: Variable not found"}, + {NC_EGLOBAL, "NetCDF: Action prohibited on NC_GLOBAL varid"}, + {NC_ENOTNC, "NetCDF: Unknown file format"}, + {NC_ESTS, "NetCDF: In Fortran, string too short"}, + {NC_EMAXNAME, "NetCDF: NC_MAX_NAME exceeded"}, + {NC_EUNLIMIT, "NetCDF: NC_UNLIMITED size already in use"}, + {NC_ENORECVARS, "NetCDF: nc_rec op when there are no record vars"}, + {NC_ECHAR, "NetCDF: Attempt to convert between text & numbers"}, + {NC_EEDGE, "NetCDF: Start+count exceeds dimension bound"}, + {NC_ESTRIDE, "NetCDF: Illegal stride"}, + {NC_EBADNAME, "NetCDF: Name contains illegal characters"}, + {NC_ERANGE, "NetCDF: Numeric conversion not representable"}, + {NC_ENOMEM, "NetCDF: Memory allocation (malloc) failure"}, + {NC_EVARSIZE, "NetCDF: One or more variable sizes violate format constraints"}, + {NC_EDIMSIZE, "NetCDF: Invalid dimension size"} + }; + + /* Try on a bad error status */ + message = APIFunc(strerror)(-666);/* should fail */ + expected_msg = "Unknown Error"; + IF (strncmp(message, expected_msg, strlen(expected_msg)) != 0) + error("APIFunc(strerror) on bad error status returned: %s", message); + ELSE_NOK + + /* Try on each legitimate error status */ + for (i=0; i= 0); + close(fd); + } + + /* Open a file that is not a netCDF file. */ + err = FileOpen(NOT_NC_FILE, NC_NOWRITE, &ncid); /* should fail */ + IF (err != NC_ENOTNC) + error("expecting NC_ENOTNC or NC_EFILE but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* delete the not-nc file */ + unlink(NOT_NC_FILE); +#endif + + /* Open a netCDF file in read-only mode, check that write fails */ + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(redef)(ncid); /* should fail */ + IF (err != NC_EPERM) + error("expecting NC_EPERM but got %s", nc_err_code_name(err)); + /* Opened OK, see if can open again and get a different netCDF ID */ + err = FileOpen(testfile, NC_NOWRITE, &ncid2); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + else { + APIFunc(close)(ncid2); + nok++; + } + IF (ncid2 == ncid) + error("netCDF IDs for first and second open calls should differ"); + + ifdef(`PNETCDF', `if (! read_only)') + { /* tests using netCDF scratch file */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncid2); + IF (err != NC_NOERR) + error("create: %s", APIFunc(strerror)(err)); + else + APIFunc(close)(ncid2); + err = FileOpen(scratch, NC_WRITE, &ncid2); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + else { + APIFunc(close)(ncid2); + nok++; + } + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +/* + * Test APIFunc(close). + * Try to close a netCDF file twice, check whether second close fails. + * Try on bad handle, check error return. + * Try in define mode and data mode. + */ +int +TestFunc(close)(void) +{ + int ncid, nok=0; + int err = FileOpen(testfile, NC_NOWRITE, &ncid); + + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + /* Close a netCDF file twice, second time should fail */ + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* Try with a bad netCDF ID */ + err = APIFunc(close)(BAD_ID);/* should fail */ + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* Close in data mode */ + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close in data mode failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + + ifdef(`PNETCDF', `if (! read_only)') + { /* tests using netCDF scratch file */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) + error("create: %s", APIFunc(strerror)(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close in define mode: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + } + return nok; +} + + +/* + * Test APIFunc(inq) + * Try on bad handle, check error return. + * Try in data mode, check returned values. + * Try asking for subsets of info. + * If in writable section of tests, + * Try in define mode, after adding an unlimited dimension, variable. + * On exit, any open netCDF files are closed. + */ +int +TestFunc(inq)(AttVarArgs) +{ + int ncid; + int ndims; /* number of dimensions */ + int nvars; /* number of variables */ + int ngatts; /* number of global attributes */ + int recdim; /* id of unlimited dimension */ + int err; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + /* Try on bad handle */ + err = APIFunc(inq)(BAD_ID, 0, 0, 0, 0); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, &recdim); + IF (err != NC_NOERR) + error("inq: %s", APIFunc(strerror)(err)); + else IF (ndims != NDIMS) + error("inq: wrong number of dimensions returned, %d", ndims); + else IF (nvars != numVars) + error("inq: wrong number of variables returned, %d", nvars); + else IF (ngatts != numGatts) + error("inq: wrong number of global atts returned, %d", ngatts); + else IF (recdim != RECDIM) + error("inq: wrong record dimension ID returned, %d", recdim); + ELSE_NOK + + /* Inguire for no info (useless, but should still work) */ + err = APIFunc(inq)(ncid, 0, 0, 0, 0); + IF (err != NC_NOERR) + error("inq for no info failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + + /* Inguire for subsets of info */ + ngatts = numGatts - 1; /* wipe out previous correct value */ + err = APIFunc(inq)(ncid, 0, 0, &ngatts, 0); + IF (err != NC_NOERR) + error("inq for one item failed: %s", APIFunc(strerror)(err)); + else IF (ngatts != numGatts) + error("inq subset: wrong number of global atts returned, %d", ngatts); + ELSE_NOK + ndims = NDIMS - 1; + nvars = numVars - 1; + err = APIFunc(inq)(ncid, &ndims, &nvars, 0, 0); + IF (err != NC_NOERR) + error("inq for two items failed: %s", APIFunc(strerror)(err)); + else IF (ndims != NDIMS) + error("inq subset: wrong number of dimensions returned, %d", ndims); + else IF (nvars != numVars) + error("inq subset: wrong number of variables returned, %d", nvars); + ELSE_NOK + + ifdef(`PNETCDF', `if (! read_only)') + { /* tests using netCDF scratch file */ + int ncid2; /* for scratch netCDF dataset */ + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid2); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + } else { /* add dim, var, gatt, check inq */ + int ndims0; + int nvars0; + int ngatts0; + int recdim0; + err = APIFunc(enddef)(ncid2); /* enter data mode */ + err = APIFunc(inq)(ncid2, &ndims0, &nvars0, &ngatts0, &recdim0); + IF (err != NC_NOERR) + error("inq: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(redef)(ncid2); /* enter define mode */ + /* Check that inquire still works in define mode */ + err = APIFunc(inq)(ncid2, &ndims, &nvars, &ngatts, &recdim); + IF (err != NC_NOERR) + error("inq in define mode: %s", APIFunc(strerror)(err)); + else IF (ndims != ndims0) + error("inq in define mode: ndims wrong, %d", ndims); + else IF (nvars != nvars0) + error("inq in define mode: nvars wrong, %d", nvars); + else IF (ngatts != ngatts0) + error("inq in define mode: ngatts wrong, %d", ngatts); + else IF (recdim != recdim0) + error("inq in define mode: recdim wrong, %d", recdim); + ELSE_NOK + + { + int did, vid; + /* Add dim, var, global att */ + err = APIFunc(def_dim)(ncid2, "inqd", 1L, &did); + IF (err != NC_NOERR) + error("def_dim: %s", APIFunc(strerror)(err)); + err = APIFunc(def_var)(ncid2, "inqv", NC_FLOAT, 0, 0, &vid); + IF (err != NC_NOERR) + error("def_var: %s", APIFunc(strerror)(err)); + } + err = APIFunc(put_att_text)(ncid2, NC_GLOBAL, "inqa", 1+strlen("stuff"), + "stuff"); + IF (err != NC_NOERR) + error("put_att_text: %s", APIFunc(strerror)(err)); + + /* Make sure APIFunc(inq) sees the additions while in define mode */ + err = APIFunc(inq)(ncid2, &ndims, &nvars, &ngatts, &recdim); + IF (err != NC_NOERR) + error("inq in define mode: %s", APIFunc(strerror)(err)); + else IF (ndims != ndims0 + 1) + error("inq in define mode: ndims wrong, %d", ndims); + else IF (nvars != nvars0 + 1) + error("inq in define mode: nvars wrong, %d", nvars); + else IF (ngatts != ngatts0 + 1) + error("inq in define mode: ngatts wrong, %d", ngatts); + ELSE_NOK + err = APIFunc(enddef)(ncid2); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* Make sure APIFunc(inq) stills sees additions in data mode */ + err = APIFunc(inq)(ncid2, &ndims, &nvars, &ngatts, &recdim); + IF (err != NC_NOERR) + error("inq failed in data mode: %s", APIFunc(strerror)(err)); + else IF (ndims != ndims0 + 1) + error("inq in define mode: ndims wrong, %d", ndims); + else IF (nvars != nvars0 + 1) + error("inq in define mode: nvars wrong, %d", nvars); + else IF (ngatts != ngatts0 + 1) + error("inq in define mode: ngatts wrong, %d", ngatts); + ELSE_NOK + APIFunc(close)(ncid2); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_natts)(AttArgs) +{ + int ncid; + int ngatts; /* number of global attributes */ + int err, nok=0; + + err = APIFunc(inq_natts)(BAD_ID, &ngatts); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_natts)(ncid, &ngatts); + IF (err != NC_NOERR) + error("inq_natts: %s", APIFunc(strerror)(err)); + else IF (ngatts != numGatts) + error("inq_natts: wrong number of global atts returned, %d", ngatts); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_ndims)(void) +{ + int ncid; + int ndims; + int err; + int nok=0; + + err = APIFunc(inq_ndims)(BAD_ID, &ndims); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_ndims)(ncid, &ndims); + IF (err != NC_NOERR) + error("inq_ndims: %s", APIFunc(strerror)(err)); + else IF (ndims != NDIMS) + error("inq_ndims: wrong number returned, %d", ndims); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_nvars)(VarArgs) +{ + int ncid; + int nvars; + int err; + int nok=0; + + err = APIFunc(inq_nvars)(BAD_ID, &nvars); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_nvars)(ncid, &nvars); + IF (err != NC_NOERR) + error("inq_nvars: %s", APIFunc(strerror)(err)); + else IF (nvars != numVars) + error("inq_nvars: wrong number returned, %d", nvars); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_unlimdim)(void) +{ + int ncid; + int unlimdim; + int err; + int nok=0; + + err = APIFunc(inq_unlimdim)(BAD_ID, &unlimdim); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_unlimdim)(ncid, &unlimdim); + IF (err != NC_NOERR) + error("inq_unlimdim: %s", APIFunc(strerror)(err)); + else IF (unlimdim != RECDIM) + error("inq_unlimdim: wrong number returned, %d", unlimdim); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_dimid)(void) +{ + int ncid; + int dimid; + int i; + int err; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_dimid)(ncid, "noSuch", &dimid); + IF (err != NC_EBADDIM) + error("expecting NC_EBADDIM but got %s", nc_err_code_name(err)); + ELSE_NOK + for (i = 0; i < NDIMS; i++) { + err = APIFunc(inq_dimid)(BAD_ID, dim_name[i], &dimid); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_dimid)(ncid, dim_name[i], &dimid); + IF (err != NC_NOERR) + error("inq_dimid: %s", APIFunc(strerror)(err)); + else IF (dimid != i) + error("expected %d, got %d", i, dimid); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_dim)(void) +{ + int ncid; + int i; + int err; + char name[NC_MAX_NAME]; + IntType length; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < NDIMS; i++) { + err = APIFunc(inq_dim)(BAD_ID, i, name, &length); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_dim)(ncid, BAD_DIMID, name, &length); + IF (err != NC_EBADDIM) + error("expecting NC_EBADDIM but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_dim)(ncid, i, 0, 0); + IF (err != NC_NOERR) + error("inq_dim: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(inq_dim)(ncid, i, name, &length); + IF (err != NC_NOERR) + error("inq_dim: %s", APIFunc(strerror)(err)); + else IF (strcmp(dim_name[i],name)) + error("name expected: %s, got: %s",dim_name[i],name); + else IF (dim_len[i] != length) + error("size expected: %d, got: %d",dim_len[i],length); + ELSE_NOK + err = APIFunc(inq_dim)(ncid, i, name, 0); + IF (err != NC_NOERR) + error("inq_dim: %s", APIFunc(strerror)(err)); + else IF (strcmp(dim_name[i],name)) + error("name expected: %s, got: %s",dim_name[i],name); + ELSE_NOK + err = APIFunc(inq_dim)(ncid, i, 0, &length); + IF (err != NC_NOERR) + error("inq_dim: %s", APIFunc(strerror)(err)); + else IF (dim_len[i] != length) + error("size expected: %d, got: %d",dim_len[i],length); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_dimlen)(void) +{ + int ncid; + int i; + int err; + IntType length; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < NDIMS; i++) { + err = APIFunc(inq_dimlen)(BAD_ID, i, &length); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_dimlen)(ncid, BAD_DIMID, &length); + IF (err != NC_EBADDIM) + error("expecting NC_EBADDIM but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_dimlen)(ncid, i, &length); + IF (err != NC_NOERR) + error("inq_dimlen: %s", APIFunc(strerror)(err)); + else IF (dim_len[i] != length) + error("size expected: %d, got: %d",dim_len[i],length); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_dimname)(void) +{ + int ncid; + int i; + int err; + char name[NC_MAX_NAME]; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < NDIMS; i++) { + err = APIFunc(inq_dimname)(BAD_ID, i, name); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_dimname)(ncid, BAD_DIMID, name); + IF (err != NC_EBADDIM) + error("expecting NC_EBADDIM but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_dimname)(ncid, i, name); + IF (err != NC_NOERR) + error("inq_dimname: %s", APIFunc(strerror)(err)); + else IF (strcmp(dim_name[i],name)) + error("name expected: %s, got: %s",dim_name[i],name); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_varid)(VarArgs) +{ + int ncid; + int varid; + int i; + int err; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + err = APIFunc(inq_varid)(ncid, "noSuch", &varid); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + + for (i = 0; i < numVars; i++) { + err = APIFunc(inq_varid)(BAD_ID, var_name[i], &varid); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_varid)(ncid, var_name[i], &varid); + IF (err != NC_NOERR) + error("inq_varid: %s", APIFunc(strerror)(err)); + else IF (varid != i) + error("expected %d, got %d", i, varid); + ELSE_NOK + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_var)(VarArgs) +{ + int ncid; + int i; + int err; + char name[NC_MAX_NAME]; + nc_type datatype; + int ndims; + int dimids[MAX_RANK]; + int natts; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < numVars; i++) { + err = APIFunc(inq_var)(BAD_ID, i, name, &datatype, &ndims, dimids, &natts); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_var)(ncid,BAD_VARID,name,&datatype,&ndims,dimids,&natts); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_var)(ncid, i, 0, 0, 0, 0, 0); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(inq_var)(ncid, i, name, &datatype, &ndims, dimids, &natts); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + else IF (strcmp(var_name[i],name)) + error("name expected: %s, got: %s",var_name[i],name); + else IF (var_type[i] != datatype) + error("type expected: %d, got: %d",var_type[i],datatype); + else IF (var_rank[i] != ndims) + error("ndims expected: %d, got: %d",var_rank[i],ndims); + else IF (!int_vec_eq(var_dimid[i],dimids,ndims)) + error("unexpected dimid"); + else IF (var_natts[i] != natts) + error("natts expected: %d, got: %d",var_natts[i],natts); + ELSE_NOK + err = APIFunc(inq_var)(ncid, i, name, 0, 0, 0, 0); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + else IF (strcmp(var_name[i],name)) + error("name expected: %s, got: %s",var_name[i],name); + ELSE_NOK + err = APIFunc(inq_var)(ncid, i, 0, &datatype, 0, 0, 0); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + else IF (var_type[i] != datatype) + error("type expected: %d, got: %d",var_type[i],datatype); + ELSE_NOK + err = APIFunc(inq_var)(ncid, i, 0, 0, &ndims, 0, 0); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + else IF (var_rank[i] != ndims) + error("ndims expected: %d, got: %d",var_rank[i],ndims); + ELSE_NOK + err = APIFunc(inq_var)(ncid, i, 0, 0, 0, dimids, 0); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + else IF (!int_vec_eq(var_dimid[i],dimids,ndims)) + error("unexpected dimid"); + ELSE_NOK + err = APIFunc(inq_var)(ncid, i, 0, 0, 0, 0, &natts); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + else IF (var_natts[i] != natts) + error("natts expected: %d, got: %d",var_natts[i],natts); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_vardimid)(VarArgs) +{ + int ncid; + int i; + int err; + int dimids[MAX_RANK]; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < numVars; i++) { + err = APIFunc(inq_vardimid)(BAD_ID, i, dimids); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_vardimid)(ncid, BAD_VARID, dimids); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_vardimid)(ncid, i, dimids); + IF (err != NC_NOERR) + error("inq_vardimid: %s", APIFunc(strerror)(err)); + else IF (!int_vec_eq(var_dimid[i], dimids, var_rank[i])) + error("unexpected dimid"); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_varname)(VarArgs) +{ + int ncid; + int i; + int err; + char name[NC_MAX_NAME]; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < numVars; i++) { + err = APIFunc(inq_varname)(BAD_ID, i, name); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + nok++; + err = APIFunc(inq_varname)(ncid, BAD_VARID, name); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_varname)(ncid, i, name); + IF (err != NC_NOERR) + error("inq_varname: %s", APIFunc(strerror)(err)); + else IF (strcmp(var_name[i],name)) + error("name expected: %s, got: %s",var_name[i],name); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_varnatts)(AttVarArgs) +{ + int ncid; + int i; + int err; + int natts; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = -1; i < numVars; i++) { + err = APIFunc(inq_varnatts)(BAD_ID, i, &natts); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_varnatts)(ncid, BAD_VARID, &natts); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_varnatts)(ncid, VARID(i), &natts); + IF (err != NC_NOERR) + error("inq_varnatts: %s", APIFunc(strerror)(err)); + else IF (NATTS(i) != natts) + error("natts expected: %d, got: %d",NATTS(i),natts); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_varndims)(VarArgs) +{ + int ncid; + int i; + int err; + int ndims; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < numVars; i++) { + err = APIFunc(inq_varndims)(BAD_ID, i, &ndims); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_varndims)(ncid, BAD_VARID, &ndims); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_varndims)(ncid, i, &ndims); + IF (err != NC_NOERR) + error("inq_varndims: %s", APIFunc(strerror)(err)); + else IF (var_rank[i] != ndims) + error("ndims expected: %d, got: %d",var_rank[i],ndims); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_vartype)(VarArgs) +{ + int ncid; + int i; + int err; + nc_type datatype; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < numVars; i++) { + err = APIFunc(inq_vartype)(BAD_ID, i, &datatype); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_vartype)(ncid, BAD_VARID, &datatype); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_vartype)(ncid, i, &datatype); + IF (err != NC_NOERR) + error("inq_vartype: %s", APIFunc(strerror)(err)); + else IF (var_type[i] != datatype) + error("type expected: %d, got: %d", var_type[i], datatype); + ELSE_NOK + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +/* + * Test GetVar1 + */ +int +TestFunc(get_var1)(VarArgs) +{ + int ncid; + int i; + int err; + double expect; + int nok = 0; /* count of valid comparisons */ + double buf[1]; /* (void *) buffer */ + double value[1]; + IntType j, index[MAX_RANK]; + ifdef(`PNETCDF', `MPI_Datatype datatype;') + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = GetVar1(BAD_ID, 0, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err) + + /* check if can detect a bad variable ID */ + err = GetVar1(ncid, BAD_VARID, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err) + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + /* check if can detect a bad file ID */ + err = GetVar1(BAD_ID, i, NULL, value, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + +ifdef(`PNETCDF',`dnl + err = GetVar1(ncid, i, NULL, value, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK +')dnl + + /* test NC_EINVALCOORDS */ + for (j = 0; j < var_rank[i]; j++) { + index[j] = var_shape[i][j]; + err = GetVar1(ncid, i, index, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + index[j] = 0; + } + err = GetVar1(ncid, i, index, value, 1, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + + /* check if the contents are supposed to be */ + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + expect = hash( var_type[i], var_rank[i], index ); + err = GetVar1(ncid, i, index, buf, 1, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + err = nc2dbl( var_type[i], buf, &value[0]); + IF (err) + error("error in nc2dbl"); + if (inRange(expect,var_type[i])) { + IF (!equal2(value[0],expect,var_type[i])) + error("expected: %G, got: %G", expect, value[0]); + ELSE_NOK + } + } + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +/* + * Test GetVara + * Choose a random point dividing each dim into 2 parts + * Get 2^rank (nslabs) slabs so defined + * Each get overwrites buffer, so check after each get. + */ +int +TestFunc(get_vara)(VarArgs) +{ + int ncid, d, i, k, err, nslabs; + int nok = 0; /* count of valid comparisons */ + IntType j, nels; + IntType start[MAX_RANK]; + IntType edge[MAX_RANK]; + IntType index[MAX_RANK]; + IntType mid[MAX_RANK]; + ifdef(`PNETCDF', `MPI_Datatype datatype;') + double buf[MAX_NELS]; /* (void *) buffer */ + double expect; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = GetVara(BAD_ID, 0, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err) + + /* check if can detect a bad variable ID */ + err = GetVara(ncid, BAD_VARID, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err) + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + /* check if can detect a bad file ID */ + err = GetVara(BAD_ID, i, NULL, NULL, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + } + +ifdef(`PNETCDF',`dnl + err = GetVara(ncid, i, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + err = GetVara(ncid, i, start, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* test NC_EINVALCOORDS, first when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + index[j] = var_shape[i][j]; + err = GetVara(ncid, i, index, edge, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + index[j] = 0; + edge[j] = var_shape[i][j] + 1; /* edge error check */ + err = GetVara(ncid, i, start, edge, buf, 1, datatype); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK + edge[j] = 1; + } + + /* Check non-scalars for correct error returned even when there is + * nothing to get (edge[j]==0) */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = GetVara(ncid, i, start, edge, buf, 0, datatype); +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = GetVara(ncid, i, start, edge, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + err = GetVara(ncid, i, start, edge, buf, 1, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + for (k = 0; k < nslabs; k++) { + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + nels *= edge[j]; + } + err = GetVara(ncid, i, start, edge, buf, nels, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + + for (j = 0; j < nels; j++) { + double got; + char *p = (char *) buf; + p += j * (IntType)nctypelen(var_type[i]); + err = nc2dbl( var_type[i], p, & got ); + IF (err) error("error in nc2dbl"); + err = toMixedBase(j, var_rank[i], edge, index); + IF (err != 0) error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index[d] += start[d]; + expect = hash(var_type[i], var_rank[i], index); + if (inRange(expect,var_type[i])) { + IF (!equal2(got,expect,var_type[i])) { + error("buf read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g", expect); + error("got: %g", got); + } + } + } + } + } + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +/* + * Test GetVars + * Choose a random point dividing each dim into 2 parts + * Get 2^rank (nslabs) slabs so defined + * Each get overwrites buffer, so check after each get. + */ +int +TestFunc(get_vars)(VarArgs) +{ + int ncid; + int d; + int i; + int k; + int err; + int nslabs; + PTRDType nstarts; /* number of different starts */ + int nok = 0; /* total count of valid comparisons */ + int n; /* count of valid comparisons within var */ + IntType j, m, nels; + IntType start[MAX_RANK]; + IntType edge[MAX_RANK]; + IntType index[MAX_RANK]; + IntType index2[MAX_RANK]; + IntType mid[MAX_RANK]; + IntType count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType stride[MAX_RANK]; + ifdef(`PNETCDF', `MPI_Datatype datatype;') + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double expect; + double got; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = GetVars(BAD_ID, 0, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err) + + /* check if can detect a bad variable ID */ + err = GetVars(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err) + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + /* check if can detect a bad file ID */ + err = GetVars(BAD_ID, i, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + +ifdef(`PNETCDF',`dnl + err = GetVars(ncid, i, NULL, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + err = GetVars(ncid, i, start, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* test NC_EINVALCOORDS, first when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; + err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK + edge[j] = 1; + stride[j] = 0; + err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + ELSE_NOK + stride[j] = 1; + } + /* Check non-scalars for correct error returned even when there is + * nothing to get (edge[j]==0) */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = GetVars(ncid, i, start, edge, stride, buf, 0, datatype); +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ + n = 0; + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err != 0) error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * (IntType)stride[j]; + stride[j] = -stride[j]; + } + } + */ + err = GetVars(ncid, i, index, count, stride, buf, nels, datatype); + IF (err != NC_NOERR) + error("%s", APIFunc(strerror)(err)); + ELSE_NOK + + for (j = 0; j < nels; j++) { + p = (char *) buf; + p += j * (IntType)nctypelen(var_type[i]); + err = nc2dbl( var_type[i], p, & got ); + IF (err != NC_NOERR) + error("error in nc2dbl"); + err = toMixedBase(j, var_rank[i], count, index2); + IF (err != 0) error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * (IntType)stride[d]; + expect = hash(var_type[i], var_rank[i], index2); + if (inRange(expect,var_type[i])) { + IF (!equal2(got,expect,var_type[i])) { + error("buf read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g, ", expect); + error("got: %g ", got); + } + } + ELSE_NOK + } + n++; + } + } + } + IF (n != var_nels[i]) { + error("count != nels"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("count: %d, ", n); + error("nels: %d ", var_nels[i]); + } + } + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +/* + * Test GetVarm + * Choose a random point dividing each dim into 2 parts + * Get 2^rank (nslabs) slabs so defined + * Choose random stride from 1 to edge + * Buffer should end up being bit image of external variable. + * So all gets for a variable store in different elements of buffer + */ +int +TestFunc(get_varm)(VarArgs) +{ + int ncid; + int i; + int k; + int err; + int nslabs; + PTRDType nstarts; /* number of different starts */ + int nok = 0; /* total count of valid comparisons */ + IntType j, m, nels; + IntType start[MAX_RANK]; + IntType edge[MAX_RANK]; + IntType index[MAX_RANK]; + IntType mid[MAX_RANK]; + IntType count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType stride[MAX_RANK]; + PTRDType imap[MAX_RANK]; + PTRDType imap2[MAX_RANK]; + ifdef(`PNETCDF', `MPI_Datatype datatype;') + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double expect; + double got; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = GetVarm(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err) + + /* check if can detect a bad variable ID */ + err = GetVarm(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err) + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + /* check if can detect a bad file ID */ + err = GetVarm(BAD_ID, i, NULL, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + imap[j] = 1; + } + +ifdef(`PNETCDF',`dnl + err = GetVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + err = GetVarm(ncid, i, start, NULL, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* test NC_EINVALCOORDS, first when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; + err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDGE, err) + ELSE_NOK + edge[j] = 1; + stride[j] = 0; + err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + ELSE_NOK + stride[j] = 1; + } + /* Check non-scalars for correct error returned even when there is + * nothing to get (edge[j]==0) */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = GetVarm(ncid, i, start, edge, stride, imap, buf, 0, datatype); +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + + if (var_rank[i] > 0) { + int jj = var_rank[i] - 1; + /* imap[jj] = nctypelen(var_type[i]); */ + imap[jj] = 1; /* in numbers of elements */ + for (; jj > 0; jj--) + imap[jj-1] = imap[jj] * (PTRDType)var_shape[i][jj]; + } + + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; + imap2[j] = imap[j] * stride[j]; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + if (var_rank[i] == 0 && i%2 ) { + err = GetVarm(ncid, i, NULL, NULL, NULL, NULL, buf, var_nels[i], datatype); + } else { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err != 0) error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j]; + index[j] += start[j]; + nels *= count[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * (IntType)stride[j]; + stride[j] = -stride[j]; + } + } + */ + j = fromMixedBase(var_rank[i], index, var_shape[i]); + p = (char *) buf + j * (IntType)nctypelen(var_type[i]); + err = GetVarm(ncid, i, index, count, stride, imap2, p, nels, datatype); + } + IF (err != NC_NOERR) + error("%s", APIFunc(strerror)(err)); + ELSE_NOK + } + } + p = (char *) buf; + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + expect = hash( var_type[i], var_rank[i], index); + err = nc2dbl( var_type[i], p, & got ); + IF (err != NC_NOERR) + error("error in nc2dbl"); + if (inRange(expect,var_type[i])) { + IF (!equal2(got,expect,var_type[i])) { + error("buf read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g, ", expect); + error("got: %g ", got); + } + } + ELSE_NOK + } + p += nctypelen(var_type[i]); + } + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(get_att)(AttVarArgs) +{ + int ncid; + int i; + int j; + IntType k; + int err; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double expect; + double got; + int nok = 0; /* count of valid comparisons */ + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + for (j = 0; j < NATTS(i); j++) { + err = APIFunc(get_att)(BAD_ID, i, ATT_NAME(i,j), buf); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(get_att)(ncid, BAD_VARID, ATT_NAME(i,j), buf); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(get_att)(ncid, i, "noSuch", buf); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(get_att)(ncid, i, ATT_NAME(i,j), buf); + IF (err != NC_NOERR) { + error("%s", APIFunc(strerror)(err)); + } else { + nok++; + for (k = 0; k < ATT_LEN(i,j); k++) { + expect = hash(ATT_TYPE(i,j), -1, &k); + p = (char *) buf; + p += k * (IntType)nctypelen(ATT_TYPE(i,j)); + err = nc2dbl( ATT_TYPE(i,j), p, &got ); + IF (err != NC_NOERR) + error("error in nc2dbl"); + if (inRange(expect,ATT_TYPE(i,j))) { + IF (!equal2(got,expect,ATT_TYPE(i,j))) { + error("buf read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", + i >= 0 ? var_name[i] : "Global"); + error("att_name: %s, ", ATT_NAME(i,j)); + error("element number: %d\n", k); + error("expect: %-23.16e\n", expect); + error(" got: %-23.16e", got); + } + } + } + } + } + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_att)(AttVarArgs) +{ + int ncid; + int i; + int j; + int err; + nc_type t; + IntType n; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + for (j = 0; j < NATTS(i); j++) { + err = APIFunc(inq_att)(BAD_ID, i, ATT_NAME(i,j), &t, &n); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_att)(ncid, BAD_VARID, ATT_NAME(i,j), &t, &n); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_att)(ncid, i, "noSuch", &t, &n); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_att)(ncid, i, ATT_NAME(i,j), &t, &n); + IF (err != NC_NOERR) { + error("%s", APIFunc(strerror)(err)); + } else { + IF (t != ATT_TYPE(i,j)) + error("type not that expected"); + ELSE_NOK + IF (n != ATT_LEN(i,j)) + error("length not that expected"); + ELSE_NOK + } + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_attlen)(AttVarArgs) +{ + int ncid; + int i; + int j; + int err; + IntType len; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + err = APIFunc(inq_attlen)(ncid, i, "noSuch", &len); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + for (j = 0; j < NATTS(i); j++) { + err = APIFunc(inq_attlen)(BAD_ID, i, ATT_NAME(i,j), &len); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_attlen)(ncid, BAD_VARID, ATT_NAME(i,j), &len); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_attlen)(ncid, i, ATT_NAME(i,j), &len); + IF (err != NC_NOERR) { + error("%s", APIFunc(strerror)(err)); + } else { + IF (len != ATT_LEN(i,j)) + error("len not that expected"); + ELSE_NOK + } + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_atttype)(AttVarArgs) +{ + int ncid; + int i; + int j; + int err; + nc_type datatype; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + err = APIFunc(inq_atttype)(ncid, i, "noSuch", &datatype); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + for (j = 0; j < NATTS(i); j++) { + err = APIFunc(inq_atttype)(BAD_ID, i, ATT_NAME(i,j), &datatype); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_atttype)(ncid, BAD_VARID, ATT_NAME(i,j), &datatype); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_atttype)(ncid, i, ATT_NAME(i,j), &datatype); + IF (err != NC_NOERR) { + error("%s", APIFunc(strerror)(err)); + } else { + IF (datatype != ATT_TYPE(i,j)) + error("type not that expected"); + ELSE_NOK + } + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_attname)(AttVarArgs) +{ + int ncid; + int i; + int j; + int err; + char name[NC_MAX_NAME]; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + err = APIFunc(inq_attname)(ncid, i, BAD_ATTNUM, name); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_attname)(ncid, i, NATTS(i), name); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + for (j = 0; j < NATTS(i); j++) { + err = APIFunc(inq_attname)(BAD_ID, i, j, name); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_attname)(ncid, BAD_VARID, j, name); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_attname)(ncid, i, j, name); + IF (err != NC_NOERR) { + error("%s", APIFunc(strerror)(err)); + } else { + IF (strcmp(ATT_NAME(i,j), name) != 0) + error("name not that expected"); + ELSE_NOK + } + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + + +int +TestFunc(inq_attid)(AttVarArgs) +{ + int ncid; + int i; + int j; + int err; + int attnum; + int nok=0; + + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + err = APIFunc(inq_attid)(ncid, i, "noSuch", &attnum); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + for (j = 0; j < NATTS(i); j++) { + err = APIFunc(inq_attid)(BAD_ID, i, ATT_NAME(i,j), &attnum); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_attid)(ncid, BAD_VARID, ATT_NAME(i,j), &attnum); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(inq_attid)(ncid, i, ATT_NAME(i,j), &attnum); + IF (err != NC_NOERR) { + error("%s", APIFunc(strerror)(err)); + } else { + IF (attnum != j) + error("attnum not that expected"); + ELSE_NOK + } + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + return nok; +} + diff --git a/nc_test/test_write.c b/nc_test/test_write.c deleted file mode 100644 index a5fd5607e0..0000000000 --- a/nc_test/test_write.c +++ /dev/null @@ -1,2076 +0,0 @@ -/********************************************************************* - * Copyright 1996, UCAR/Unidata - * See netcdf/COPYRIGHT file for copying and redistribution conditions. - * $Id: test_write.c 2796 2014-10-28 03:40:29Z wkliao $ - *********************************************************************/ - -#include "tests.h" -#include "math.h" -#include /* For FILE stuff. */ - -/* - * Test nc_create - * For mode in NC_NOCLOBBER, NC_CLOBBER do: - * create netcdf file 'scratch.nc' with no data, close it - * test that it can be opened, do nc_inq to check nvars = 0, etc. - * Try again in NC_NOCLOBBER mode, check error return - * On exit, delete this file - */ -void -test_nc_create(void) -{ - int clobber; /* 0 for NC_NOCLOBBER, 1 for NC_CLOBBER */ - int err; - int ncid; - int ndims; /* number of dimensions */ - int nvars; /* number of variables */ - int ngatts; /* number of global attributes */ - int recdim; /* id of unlimited dimension */ - - for (clobber = 0; clobber < 2; clobber++) { - int cmode = clobber ? NC_CLOBBER : NC_NOCLOBBER; - err = file_create(scratch, cmode, &ncid); - IF (err) - error("nc_create: %s", nc_strerror(err)); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = file_open(scratch, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = nc_inq(ncid, &ndims, &nvars, &ngatts, &recdim); - IF (err) - error("nc_inq: %s", nc_strerror(err)); - else IF (ndims != 0) - error("nc_inq: wrong number of dimensions returned, %d", ndims); - else IF (nvars != 0) - error("nc_inq: wrong number of variables returned, %d", nvars); - else IF (ngatts != 0) - error("nc_inq: wrong number of global atts returned, %d", ngatts); - else IF (recdim != -1) - error("nc_inq: wrong record dimension ID returned, %d", recdim); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - } - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err != NC_EEXIST) - error("attempt to overwrite file: status = %d", err); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_redef - * (In fact also tests nc_enddef - called from test_nc_enddef) - * BAD_ID - * attempt redef (error) & enddef on read-only file - * create file, define dims & vars. - * attempt put var (error) - * attempt redef (error) & enddef. - * put vars - * attempt def new dims (error) - * redef - * def new dims, vars. - * put atts - * enddef - * put vars - * close - * check file: vars & atts - * check reopening with NC_WRITE and adding new dims, atts, vars - */ -void -test_nc_redef(void) -{ - int ncid; /* netcdf id */ - /* used to force effective test of ncio->move() in redef */ - size_t sizehint = 8192; - int dimid; /* dimension id */ - int varid; /* variable id */ - int varid1; /* variable id */ - int err; - const char * title = "Not funny"; - double var; - char name[NC_MAX_NAME]; - size_t length; - int fmt_variant1, fmt_variant2; - - /* BAD_ID tests */ - err = nc_redef(BAD_ID); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_enddef(BAD_ID); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - - /* read-only tests */ - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = nc_redef(ncid); - IF (err != NC_EPERM) - error("nc_redef in NC_NOWRITE mode: status = %d", err); - err = nc_enddef(ncid); - IF (err != NC_ENOTINDEFINE) - error("nc_redef in NC_NOWRITE mode: status = %d", err); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - /* tests using scratch file */ - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - /* limit for ncio implementations which have infinite chunksize */ - if(sizehint > 32768) - sizehint = 16384; - def_dims(ncid); - def_vars(ncid); - put_atts(ncid); - err = nc_inq_varid(ncid, "d", &varid); - IF (err) - error("nc_inq_varid: %s", nc_strerror(err)); - var = 1.0; - err = nc_put_var1_double(ncid, varid, NULL, &var); - IF (err != NC_EINDEFINE) - error("nc_put_var... in define mode: status = %d", err); - err = nc_redef(ncid); - IF (err != NC_EINDEFINE) - error("nc_redef in define mode: status = %d", err); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - put_vars(ncid); - err = nc_def_dim(ncid, "abc", sizehint, &dimid); - IF (err != NC_ENOTINDEFINE) - error("nc_def_dim in define mode: status = %d", err); - err = nc_redef(ncid); - IF (err) - error("nc_redef: %s", nc_strerror(err)); -#if 0 - err = nc_set_fill(ncid, NC_NOFILL, NULL); - IF (err) - error("nc_set_fill: %s", nc_strerror(err)); -#endif - err = nc_def_dim(ncid, "abc", sizehint, &dimid); - IF (err) - error("nc_def_dim: %s", nc_strerror(err)); - err = nc_def_var(ncid, "abcScalar", NC_INT, 0, NULL, &varid); - IF (err) - error("nc_def_var: %s", nc_strerror(err)); - err = nc_def_var(ncid, "abc", NC_INT, 1, &dimid, &varid1); - IF (err) - error("nc_def_var: %s", nc_strerror(err)); - { - int dimids[NDIMS +1]; - int ii = 0; - for(ii = 0; ii < NDIMS; ii++) - dimids[ii] = ii; - dimids[NDIMS] = dimid; - err = nc_def_var(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1); - IF (err) - error("nc_def_var: %s", nc_strerror(err)); - } - err = nc_put_att_text(ncid, NC_GLOBAL, "title", 1+strlen(title), title); - IF (err) - error("nc_put_att_text: %s", nc_strerror(err)); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - var = 1.0; - err = nc_put_var1_double(ncid, varid, NULL, &var); - IF (err) - error("nc_put_var1_double: %s", nc_strerror(err)); - err = nc_inq_format(ncid, &fmt_variant1); - IF (err) - error("nc_inq_format: %s", nc_strerror(err)); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - /* check scratch file written as expected */ - check_file(scratch); /* checks all except "abc" stuff added above */ - - IF ((err = file_open(scratch, NC_NOWRITE, &ncid))) - error("nc_open: %s", nc_strerror(err)); - IF ((err = nc_inq_dim(ncid, dimid, name, &length))) - error("nc_inq_dim: %s", nc_strerror(err)); - IF (strcmp(name, "abc") != 0) - error("Unexpected dim name"); - IF (length != sizehint) - error("Unexpected dim length"); - IF ((err = nc_get_var1_double(ncid, varid, NULL, &var))) - error("nc_get_var1_double: %s", nc_strerror(err)); - IF (var != 1.0) - error("nc_get_var1_double: unexpected value"); - IF ((err = nc_close(ncid))) - error("nc_close: %s", nc_strerror(err)); - - /* open scratch file for writing, add another dim, var, att, then check */ - IF ((err = file_open(scratch, NC_WRITE, &ncid))) - error("nc_open: %s", nc_strerror(err)); - IF ((err = nc_redef(ncid))) - error("nc_redef: %s", nc_strerror(err)); - IF ((err = nc_def_dim(ncid, "def", sizehint, &dimid))) - error("nc_def_dim: %s", nc_strerror(err)); - IF ((err = nc_def_var(ncid, "defScalar", NC_INT, 0, NULL, &varid))) - error("nc_def_var: %s", nc_strerror(err)); - IF ((err = nc_def_var(ncid, "def", NC_INT, 1, &dimid, &varid1))) - error("nc_def_var: %s", nc_strerror(err)); - IF ((err = nc_put_att_text(ncid, NC_GLOBAL, "Credits", 1+strlen("Thanks!"), "Thanks!"))) - error("nc_put_att_text: %s", nc_strerror(err)); - IF ((err = nc_enddef(ncid))) - error("nc_enddef: %s", nc_strerror(err)); - var = 2.0; - IF ((err = nc_put_var1_double(ncid, varid, NULL, &var))) - error("nc_put_var1_double: %s", nc_strerror(err)); - IF ((err = nc_close(ncid))) - error("nc_close: %s", nc_strerror(err)); - - /* check scratch file written as expected */ - check_file(scratch); - - err = file_open(scratch, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = nc_inq_dim(ncid, dimid, name, &length); - IF (err) - error("nc_inq_dim: %s", nc_strerror(err)); - IF (strcmp(name, "def") != 0) - error("Unexpected dim name"); - IF (length != sizehint) - error("Unexpected dim length"); - err = nc_get_var1_double(ncid, varid, NULL, &var); - IF (err) - error("nc_get_var1_double: %s", nc_strerror(err)); - IF (var != 2.0) - error("nc_get_var1_double: unexpected value"); - /* make sure format variant hasn't changed from when created */ - err = nc_inq_format(ncid, &fmt_variant2); - IF (err) - error("nc_inq_format: %s", nc_strerror(err)); - IF (fmt_variant1 != fmt_variant2) - error("nc_enddef changed format variant"); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_enddef - * Simply calls test_nc_redef which tests both nc_redef & nc_enddef - */ -void -test_nc_enddef(void) -{ - test_nc_redef(); -} - - -/* - * Test nc_sync - * try with bad handle, check error - * try in define mode, check error - * try writing with one handle, reading with another on same netCDF - */ -void -test_nc_sync(void) -{ - int ncidw; /* netcdf id for writing */ - int ncidr; /* netcdf id for reading */ - int err; - - /* BAD_ID test */ - err = nc_sync(BAD_ID); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - - /* create scratch file & try nc_sync in define mode */ - err = file_create(scratch, NC_NOCLOBBER, &ncidw); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - err = nc_sync(ncidw); - IF (err != NC_EINDEFINE) - error("nc_sync called in define mode: status = %d", err); - - /* write using same handle */ - def_dims(ncidw); - def_vars(ncidw); - put_atts(ncidw); - err = nc_enddef(ncidw); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - put_vars(ncidw); - err = nc_sync(ncidw); - IF (err) - error("nc_sync of ncidw failed: %s", nc_strerror(err)); - - /* open another handle, nc_sync, read (check) */ - err = file_open(scratch, NC_NOWRITE, &ncidr); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = nc_sync(ncidr); - IF (err) - error("nc_sync of ncidr failed: %s", nc_strerror(err)); - check_dims(ncidr); - check_atts(ncidr); - check_vars(ncidr); - - /* close both handles */ - err = nc_close(ncidr); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = nc_close(ncidw); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_abort - * try with bad handle, check error - * try in define mode before anything written, check that file was deleted - * try after nc_enddef, nc_redef, define new dims, vars, atts - * try after writing variable - */ -void -test_nc_abort(void) -{ - int ncid; /* netcdf id */ - int err; - int ndims; - int nvars; - int ngatts; - - /* BAD_ID test */ - err = nc_abort(BAD_ID); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - - /* create scratch file & try nc_abort in define mode */ - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - put_atts(ncid); - err = nc_abort(ncid); - IF (err) - error("nc_abort of ncid failed: %s", nc_strerror(err)); - err = nc_close(ncid); /* should already be closed */ - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = remove(scratch); /* should already be deleted */ - IF (!err) - error("file %s should not exist", scratch); - - /* - * create scratch file - * do nc_enddef & nc_redef - * define new dims, vars, atts - * try nc_abort: should restore previous state (no dims, vars, atts) - */ - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - err = nc_redef(ncid); - IF (err) - error("nc_redef: %s", nc_strerror(err)); - def_dims(ncid); - def_vars(ncid); - put_atts(ncid); - err = nc_abort(ncid); - IF (err) - error("nc_abort of ncid failed: %s", nc_strerror(err)); - err = nc_close(ncid); /* should already be closed */ - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = file_open(scratch, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = nc_inq (ncid, &ndims, &nvars, &ngatts, NULL); - IF (err) - error("nc_inq: %s", nc_strerror(err)); - IF (ndims != 0) - error("ndims should be 0"); - IF (nvars != 0) - error("nvars should be 0"); - IF (ngatts != 0) - error("ngatts should be 0"); - err = nc_close (ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - /* try nc_abort in data mode - should just close */ - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - put_atts(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - put_vars(ncid); - err = nc_abort(ncid); - IF (err) - error("nc_abort of ncid failed: %s", nc_strerror(err)); - err = nc_close(ncid); /* should already be closed */ - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - check_file(scratch); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_def_dim - * try with bad netCDF handle, check error - * try in data mode, check error - * check that returned id is one more than previous id - * try adding same dimension twice, check error - * try with illegal sizes, check error - * make sure unlimited size works, shows up in nc_inq_unlimdim - * try to define a second unlimited dimension, check error - */ -void -test_nc_def_dim(void) -{ - int ncid; - int err; /* status */ - int i; - int dimid; /* dimension id */ - size_t length; - - /* BAD_ID test */ - err = nc_def_dim(BAD_ID, "abc", 8, &dimid); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - - /* data mode test */ - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - err = nc_def_dim(ncid, "abc", 8, &dimid); - IF (err != NC_ENOTINDEFINE) - error("bad ncid: status = %d", err); - - /* define-mode tests: unlimited dim */ - err = nc_redef(ncid); - IF (err) - error("nc_redef: %s", nc_strerror(err)); - err = nc_def_dim(ncid, dim_name[0], NC_UNLIMITED, &dimid); - IF (err) - error("nc_def_dim: %s", nc_strerror(err)); - IF (dimid != 0) - error("Unexpected dimid"); - err = nc_inq_unlimdim(ncid, &dimid); - IF (err) - error("nc_inq_unlimdim: %s", nc_strerror(err)); - IF (dimid != 0) - error("Unexpected recdim"); - err = nc_inq_dimlen(ncid, dimid, &length); - IF (err) - error("nc_inq_dimlen: %s", nc_strerror(err)); - IF (length != 0) - error("Unexpected length"); - err = nc_def_dim(ncid, "abc", NC_UNLIMITED, &dimid); - IF (err != NC_EUNLIMIT) - error("2nd unlimited dimension: status = %d", err); - /* define-mode tests: remaining dims */ - for (i = 1; i < NDIMS; i++) { - err = nc_def_dim(ncid, dim_name[i-1], dim_len[i], &dimid); - IF (err != NC_ENAMEINUSE) - error("duplicate name: status = %d", err); - err = nc_def_dim(ncid, BAD_NAME, dim_len[i], &dimid); - IF (err != NC_EBADNAME) - error("bad name: status = %d", err); - /* Fix: dmh 11/4/2011: works only if sizeof(long) > 4 */ - if(sizeof(long) > 4) { - err = nc_def_dim(ncid, dim_name[i], NC_UNLIMITED-1, &dimid); - IF (err != NC_EDIMSIZE) - error("bad size: status = %d", err); - } - err = nc_def_dim(ncid, dim_name[i], dim_len[i], &dimid); - IF (err) - error("nc_def_dim: %s", nc_strerror(err)); - IF (dimid != i) - error("Unexpected dimid"); - } - - /* Following just to expand unlimited dim */ - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - put_vars(ncid); - - /* Check all dims */ - check_dims(ncid); - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_rename_dim - * try with bad netCDF handle, check error - * check that proper rename worked with nc_inq_dim - * try renaming to existing dimension name, check error - * try with bad dimension handle, check error - */ -void -test_nc_rename_dim(void) -{ - int ncid; - int err; /* status */ - char name[NC_MAX_NAME]; - - /* BAD_ID test */ - err = nc_rename_dim(BAD_ID, 0, "abc"); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - - /* main tests */ - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - err = nc_rename_dim(ncid, BAD_DIMID, "abc"); - IF (err != NC_EBADDIM) - error("bad dimid: status = %d", err); - err = nc_rename_dim(ncid, 2, "abc"); - IF (err) - error("nc_rename_dim: %s", nc_strerror(err)); - err = nc_inq_dimname(ncid, 2, name); - IF (err) - error("nc_inq_dimname: %s", nc_strerror(err)); - IF (strcmp(name, "abc") != 0) - error("Unexpected name: %s", name); - err = nc_rename_dim(ncid, 0, "abc"); - IF (err != NC_ENAMEINUSE) - error("duplicate name: status = %d", err); - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_def_var - * try with bad netCDF handle, check error - * try with bad name, check error - * scalar tests: - * check that proper define worked with nc_inq_var - * try redefining an existing variable, check error - * try with bad datatype, check error - * try with bad number of dimensions, check error - * try in data mode, check error - * check that returned id is one more than previous id - * try with bad dimension ids, check error - */ -void -test_nc_def_var(void) -{ - int ncid; - int varid; - int err; /* status */ - int i; - int ndims; - int natts; - char name[NC_MAX_NAME]; - int dimids[MAX_RANK]; - nc_type datatype; - - /* BAD_ID test */ - err = nc_def_var(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - - /* scalar tests */ - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - err = nc_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid); - IF (err) - error("nc_def_var: %s", nc_strerror(err)); - err = nc_inq_var(ncid, varid, name, &datatype, &ndims, dimids, &natts); - IF (err) - error("nc_inq_var: %s", nc_strerror(err)); - IF (strcmp(name, "abc") != 0) - error("Unexpected name: %s", name); - IF (datatype != NC_SHORT) - error("Unexpected datatype"); - IF (ndims != 0) - error("Unexpected rank"); - err = nc_def_var(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid); - IF (err != NC_EBADNAME) - error("bad name: status = %d", err); - err = nc_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid); - IF (err != NC_ENAMEINUSE) - error("duplicate name: status = %d", err); - err = nc_def_var(ncid, "ABC", BAD_TYPE, -1, dimids, &varid); - IF (err != NC_EBADTYPE) - error("bad type: status = %d", err); - err = nc_def_var(ncid, "ABC", NC_SHORT, -1, dimids, &varid); - IF (err != NC_EINVAL) - error("bad rank: status = %d", err); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - err = nc_def_var(ncid, "ABC", NC_SHORT, 0, dimids, &varid); - IF (err != NC_ENOTINDEFINE) - error("nc_def_var called in data mode: status = %d", err); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); - - /* general tests using global vars */ - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - for (i = 0; i < numVars; i++) { - err = nc_def_var(ncid, var_name[i], var_type[i], var_rank[i], - var_dimid[i], &varid); - IF (err) - error("nc_def_var: %s", nc_strerror(err)); - IF (varid != i) - error("Unexpected varid"); - } - - /* try bad dim ids */ - dimids[0] = BAD_DIMID; - err = nc_def_var(ncid, "abc", NC_SHORT, 1, dimids, &varid); - IF (err != NC_EBADDIM) - error("bad dim ids: status = %d", err); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_put_var1 - */ -void -test_nc_put_var1(void) -{ - int ncid; - int i; - int j; - int err; - size_t index[MAX_RANK]; - double value; - double buf[1]; /* (void *) buffer */ - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - - for (i = 0; i < numVars; i++) { - for (j = 0; j < var_rank[i]; j++) - index[j] = 0; - err = nc_put_var1(BAD_ID, i, index, buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_var1(ncid, BAD_VARID, index, buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - index[j] = var_shape[i][j]; - err = nc_put_var1(ncid, i, index, buf); - IF (err != NC_EINVALCOORDS) - error("bad index: status = %d", err); - index[j] = 0; - } - } - for (j = 0; j < var_nels[i]; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase"); - value = hash( var_type[i], var_rank[i], index); - if (inRange(value, var_type[i])) { - err = dbl2nc(value, var_type[i], buf); - IF (err) - error("error in dbl2nc"); - if (var_rank[i] == 0 && i%2 == 0) - err = nc_put_var1(ncid, i, NULL, buf); - else - err = nc_put_var1(ncid, i, index, buf); - IF (err) - error("%s", nc_strerror(err)); - } - } - } - - check_vars(ncid); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_put_vara - * Choose a random point dividing each dim into 2 parts - * Put 2^rank (nslabs) slabs so defined - * Redefine buffer for each put. - * At end check all variables using check_vars - */ -void -test_nc_put_vara(void) -{ - int ncid; - int d; - int i; - int j; - int k; - int err; - int nels; - int nslabs; - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t mid[MAX_RANK]; - double buf[MAX_NELS]; /* (void *) buffer */ - char *p; /* (void *) pointer */ - double value; - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - - for (i = 0; i < numVars; i++) { - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - } - err = nc_put_vara(BAD_ID, i, start, edge, buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_vara(ncid, BAD_VARID, start, edge, buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - start[j] = var_shape[i][j]; - err = nc_put_vara(ncid, i, start, edge, buf); - IF (err != NC_EINVALCOORDS) - error("bad index: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_put_vara(ncid, i, start, edge, buf); - IF (err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - } - } - /* Choose a random point dividing each dim into 2 parts */ - /* put 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { - mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to put lower or upper part of dim */ - for (k = 0; k < nslabs; k++) { - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - nels *= edge[j]; - } - p = (char *) buf; - for (j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], edge, index); - IF (err) - error("error in toMixedBase"); - for (d = 0; d < var_rank[i]; d++) - index[d] += start[d]; - value = hash( var_type[i], var_rank[i], index); - if (!inRange(value, var_type[i])) - value = 0; - err = dbl2nc(value, var_type[i], p); - IF (err) - error("error in dbl2nc"); - p += nctypelen(var_type[i]); - } - if (var_rank[i] == 0 && i%2 == 0) - err = nc_put_vara(ncid, i, NULL, NULL, buf); - else - err = nc_put_vara(ncid, i, start, edge, buf); - IF (err) { - error("%s", nc_strerror(err)); - } - } - } - - check_vars(ncid); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_put_vars - * Choose a random point dividing each dim into 2 parts - * Put 2^rank (nslabs) slabs so defined - * Choose random stride from 1 to edge - * Redefine buffer for each put. - * At end check all variables using check_vars - */ -void -test_nc_put_vars(void) -{ - int ncid; - int d; - int i; - int j; - int k; - int m; - int err; - int nels; - int nslabs; - int nstarts; /* number of different starts */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t index2[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; - double buf[MAX_NELS]; /* (void *) buffer */ - char *p; /* (void *) pointer */ - double value; - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - - for (i = 0; i < numVars; i++) { - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - stride[j] = 1; - } - err = nc_put_vars(BAD_ID, i, start, edge, stride, buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_vars(ncid, BAD_VARID, start, edge, stride, buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - start[j] = var_shape[i][j]; - err = nc_put_vars(ncid, i, start, edge, stride, buf); - IF (err != NC_EINVALCOORDS && err != NC_EEDGE) - error("bad index: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_put_vars(ncid, i, start, edge, stride, buf); - IF (err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - stride[j] = 0; - err = nc_put_vars(ncid, i, start, edge, stride, buf); - IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); - stride[j] = 1; - } - } - /* Choose a random point dividing each dim into 2 parts */ - /* put 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { - mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to put lower or upper part of dim */ - /* choose random stride from 1 to edge */ - for (k = 0; k < nslabs; k++) { - nstarts = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; - nstarts *= stride[j]; - } - for (m = 0; m < nstarts; m++) { - err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); - nels = 1; - for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; - nels *= count[j]; - index[j] += start[j]; - } - /* Random choice of forward or backward */ -/* TODO - if ( roll(2) ) { - for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; - stride[j] = -stride[j]; - } - } - */ - p = (char *) buf; - for (j = 0; j < nels; j++) { - err = toMixedBase(j, var_rank[i], count, index2); - IF (err) - error("error in toMixedBase"); - for (d = 0; d < var_rank[i]; d++) - index2[d] = index[d] + index2[d] * stride[d]; - value = hash( var_type[i], var_rank[i], index2); - if (!inRange(value, var_type[i])) - value = 0; - err = dbl2nc(value, var_type[i], p); - IF (err) - error("error in dbl2nc"); - p += nctypelen(var_type[i]); - } - if (var_rank[i] == 0 && i%2 == 0) - err = nc_put_vars(ncid, i, NULL, NULL, NULL, buf); - else - err = nc_put_vars(ncid, i, index, count, stride, buf); - IF (err) { - error("%s", nc_strerror(err)); - } - } - } - } - - check_vars(ncid); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_put_varm - * Choose a random point dividing each dim into 2 parts - * Put 2^rank (nslabs) slabs so defined - * Choose random stride from 1 to edge - * Buffer is bit image of whole external variable. - * So all puts for a variable put different elements of buffer - * At end check all variables using check_vars - */ -void -test_nc_put_varm(void) -{ - int ncid; - int i; - int j; - int k; - int m; - int err; - int nslabs; - int nstarts; /* number of different starts */ - size_t start[MAX_RANK]; - size_t edge[MAX_RANK]; - size_t index[MAX_RANK]; - size_t mid[MAX_RANK]; - size_t count[MAX_RANK]; - size_t sstride[MAX_RANK]; - ptrdiff_t stride[MAX_RANK]; - ptrdiff_t imap[MAX_RANK]; - ptrdiff_t imap2[MAX_RANK]; - double buf[MAX_NELS]; /* (void *) buffer */ - char *p; /* (void *) pointer */ - double value; - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - - for (i = 0; i < numVars; i++) { - assert(var_rank[i] <= MAX_RANK); - assert(var_nels[i] <= MAX_NELS); - for (j = 0; j < var_rank[i]; j++) { - start[j] = 0; - edge[j] = 1; - stride[j] = 1; - } - if (var_rank[i] > 0) { - j = var_rank[i] - 1; - // imap[j] = nctypelen(var_type[i]); /* in bytes */ - imap[j] = 1; /* in numbers of elements */ - for (; j > 0; j--) - imap[j-1] = imap[j] * var_shape[i][j]; - } - p = (char *) buf; - for (j = 0; j < var_nels[i]; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase"); - value = hash( var_type[i], var_rank[i], index); - if (!inRange(value, var_type[i])) - value = 0; - err = dbl2nc(value, var_type[i], p); - IF (err) - error("error in dbl2nc"); - p += nctypelen(var_type[i]); - } - err = nc_put_varm(BAD_ID, i, start, edge, stride, imap, buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_varm(ncid, BAD_VARID, start, edge, stride, imap, buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - for (j = 0; j < var_rank[i]; j++) { - if (var_dimid[i][j] > 0) { /* skip record dim */ - start[j] = var_shape[i][j]; - err = nc_put_varm(ncid, i, start, edge, stride, imap, buf); - IF (err != NC_EINVALCOORDS && err != NC_EEDGE) - error("bad index: status = %d", err); - start[j] = 0; - edge[j] = var_shape[i][j] + 1; - err = nc_put_varm(ncid, i, start, edge, stride, imap, buf); - IF (err != NC_EEDGE) - error("bad edge: status = %d", err); - edge[j] = 1; - stride[j] = 0; - err = nc_put_varm(ncid, i, start, edge, stride, imap, buf); - IF (err != NC_ESTRIDE) - error("bad stride: status = %d", err); - stride[j] = 1; - } - } - /* Choose a random point dividing each dim into 2 parts */ - /* put 2^rank (nslabs) slabs so defined */ - nslabs = 1; - for (j = 0; j < var_rank[i]; j++) { - mid[j] = roll( var_shape[i][j] ); - nslabs *= 2; - } - /* bits of k determine whether to put lower or upper part of dim */ - /* choose random stride from 1 to edge */ - for (k = 0; k < nslabs; k++) { - nstarts = 1; - for (j = 0; j < var_rank[i]; j++) { - if ((k >> j) & 1) { - start[j] = 0; - edge[j] = mid[j]; - }else{ - start[j] = mid[j]; - edge[j] = var_shape[i][j] - mid[j]; - } - sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; - imap2[j] = imap[j] * sstride[j]; - nstarts *= stride[j]; - } - for (m = 0; m < nstarts; m++) { - if (var_rank[i] == 0 && i%2 == 0) { - err = nc_put_varm(ncid, i, NULL, NULL, NULL, NULL, buf); - } else { - err = toMixedBase(m, var_rank[i], sstride, index); - IF (err) - error("error in toMixedBase"); - for (j = 0; j < var_rank[i]; j++) { - count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; - index[j] += start[j]; - } - /* Random choice of forward or backward */ -/* TODO - if ( roll(2) ) { - for (j = 0; j < var_rank[i]; j++) { - index[j] += (count[j] - 1) * stride[j]; - stride[j] = -stride[j]; - } - } - */ - j = fromMixedBase(var_rank[i], index, var_shape[i]); - p = (char *) buf + j * nctypelen(var_type[i]); - err = nc_put_varm(ncid, i, index, count, stride, imap2, p); - } - IF (err) { - error("%s", nc_strerror(err)); - } - } - } - } - - check_vars(ncid); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_rename_var - * try with bad netCDF handle, check error - * try with bad variable handle, check error - * try renaming to existing variable name, check error - * check that proper rename worked with nc_inq_varid - * try in data mode, check error - */ -void -test_nc_rename_var(void) -{ - int ncid; - int varid; - int err; - int i; - char name[NC_MAX_NAME]; - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - err = nc_rename_var(ncid, BAD_VARID, "newName"); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - def_dims(ncid); - def_vars(ncid); - - /* Prefix "new_" to each name */ - for (i = 0; i < numVars; i++) { - err = nc_rename_var(BAD_ID, i, "newName"); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_rename_var(ncid, i, var_name[numVars-1]); - IF (err != NC_ENAMEINUSE) - error("duplicate name: status = %d", err); - (void) strcpy(name, "new_"); - (void) strcat(name, var_name[i]); - err = nc_rename_var(ncid, i, name); - IF (err) - error("nc_rename_var: %s", nc_strerror(err)); - err = nc_inq_varid(ncid, name, &varid); - IF (err) - error("nc_inq_varid: %s", nc_strerror(err)); - IF (varid != i) - error("Unexpected varid"); - } - - /* Change to data mode */ - /* Try making names even longer. Then restore original names */ - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - for (i = 0; i < numVars; i++) { - (void) strcpy(name, "even_longer_"); - (void) strcat(name, var_name[i]); - err = nc_rename_var(ncid, i, name); - IF (err != NC_ENOTINDEFINE) - error("longer name in data mode: status = %d", err); - err = nc_rename_var(ncid, i, var_name[i]); - IF (err) - error("nc_rename_var: %s", nc_strerror(err)); - err = nc_inq_varid(ncid, var_name[i], &varid); - IF (err) - error("nc_inq_varid: %s", nc_strerror(err)); - IF (varid != i) - error("Unexpected varid"); - } - - put_vars(ncid); - check_vars(ncid); - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -void -test_nc_put_att(void) -{ - int ncid; - int varid; - int i; - int j; - size_t k; - int err; - double buf[MAX_NELS]; /* (void *) buffer */ - char *p; /* (void *) pointer */ - char *name; /* of att */ - nc_type datatype; /* of att */ - size_t length; /* of att */ - double value; - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - - for (i = -1; i < numVars; i++) { - varid = VARID(i); - for (j = 0; j < NATTS(i); j++) { - name = ATT_NAME(i,j); - datatype = ATT_TYPE(i,j); - length = ATT_LEN(i,j); - err = nc_put_att(BAD_ID, varid, name, datatype, length, buf); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_put_att(ncid, varid, BAD_NAME, datatype, length, buf); - IF (err != NC_EBADNAME) - error("bad name: status = %d", err); - err = nc_put_att(ncid, BAD_VARID, name, datatype, length, buf); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_put_att(ncid, varid, name, BAD_TYPE, length, buf); - IF (err != NC_EBADTYPE) - error("bad type: status = %d", err); - p = (char *) buf; - for (k = 0; k < length; k++) { - value = hash(datatype, -1, &k ); - if (!inRange(value, datatype)) - value = 0; - err = dbl2nc(value, datatype, p); - IF (err) - error("error in dbl2nc"); - p += nctypelen(datatype); - } - err = nc_put_att(ncid, varid, name, datatype, length, buf); - IF (err) { - error("%s", nc_strerror(err)); - } - } - } - - check_atts(ncid); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_copy_att - * try with bad source or target netCDF handles, check error - * try with bad source or target variable handle, check error - * try with nonexisting attribute, check error - * check that NC_GLOBAL variable for source or target works - * check that new attribute put works with target in define mode - * check that old attribute put works with target in data mode - * check that changing type and length of an attribute work OK - * try with same ncid for source and target, different variables - * try with same ncid for source and target, same variable - */ -void -test_nc_copy_att(void) -{ - int ncid_in; - int ncid_out; - int varid; - int err; - int i; - int j; - char *name; /* of att */ - nc_type datatype; /* of att */ - size_t length; /* of att */ - char value; - - err = file_open(testfile, NC_NOWRITE, &ncid_in); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = file_create(scratch, NC_NOCLOBBER, &ncid_out); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid_out); - def_vars(ncid_out); - - for (i = -1; i < numVars; i++) { - varid = VARID(i); - for (j = 0; j < NATTS(i); j++) { - name = ATT_NAME(i,j); - err = nc_copy_att(ncid_in, BAD_VARID, name, ncid_out, varid); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_copy_att(ncid_in, varid, name, ncid_out, BAD_VARID); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - err = nc_copy_att(BAD_ID, varid, name, ncid_out, varid); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_copy_att(ncid_in, varid, name, BAD_ID, varid); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_copy_att(ncid_in, varid, "noSuch", ncid_out, varid); - IF (err != NC_ENOTATT) - error("bad attname: status = %d", err); - err = nc_copy_att(ncid_in, varid, name, ncid_out, varid); - IF (err) - error("nc_copy_att: %s", nc_strerror(err)); - err = nc_copy_att(ncid_out, varid, name, ncid_out, varid); - IF (err) - error("source = target: %s", nc_strerror(err)); - } - } - - err = nc_close(ncid_in); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - /* Close scratch. Reopen & check attributes */ - err = nc_close(ncid_out); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = file_open(scratch, NC_WRITE, &ncid_out); - IF (err) - error("nc_open: %s", nc_strerror(err)); - check_atts(ncid_out); - - /* - * change to define mode - * define single char. global att. ':a' with value 'A' - * This will be used as source for following copies - */ - err = nc_redef(ncid_out); - IF (err) - error("nc_redef: %s", nc_strerror(err)); - err = nc_put_att_text(ncid_out, NC_GLOBAL, "a", 1, "A"); - IF (err) - error("nc_put_att_text: %s", nc_strerror(err)); - - /* - * change to data mode - * Use scratch as both source & dest. - * try copy to existing att. change type & decrease length - * rename 1st existing att of each var (if any) 'a' - * if this att. exists them copy ':a' to it - */ - err = nc_enddef(ncid_out); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - for (i = 0; i < numVars; i++) { - if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) { - err = nc_rename_att(ncid_out, i, att_name[i][0], "a"); - IF (err) - error("nc_rename_att: %s", nc_strerror(err)); - err = nc_copy_att(ncid_out, NC_GLOBAL, "a", ncid_out, i); - IF (err) - error("nc_copy_att: %s", nc_strerror(err)); - } - } - err = nc_close(ncid_out); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - /* Reopen & check */ - err = file_open(scratch, NC_WRITE, &ncid_out); - IF (err) - error("nc_open: %s", nc_strerror(err)); - for (i = 0; i < numVars; i++) { - if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) { - err = nc_inq_att(ncid_out, i, "a", &datatype, &length); - IF (err) - error("nc_inq_att: %s", nc_strerror(err)); - IF (datatype != NC_CHAR) - error("Unexpected type"); - IF (length != 1) - error("Unexpected length"); - err = nc_get_att_text(ncid_out, i, "a", &value); - IF (err) - error("nc_get_att_text: %s", nc_strerror(err)); - IF (value != 'A') - error("Unexpected value"); - } - } - - err = nc_close(ncid_out); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_rename_att - * try with bad netCDF handle, check error - * try with bad variable handle, check error - * try with nonexisting att name, check error - * try renaming to existing att name, check error - * check that proper rename worked with nc_inq_attid - * try in data mode, check error - */ -void -test_nc_rename_att(void) -{ - int ncid; - int varid; - int err; - int i; - int j; - size_t k; - int attnum; - char *attname; - char name[NC_MAX_NAME]; - char oldname[NC_MAX_NAME]; - char newname[NC_MAX_NAME]; - int nok = 0; /* count of valid comparisons */ - nc_type datatype; - nc_type atttype; - size_t length; - size_t attlength; - signed char text[MAX_NELS]; - double value[MAX_NELS]; - double expect; - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - err = nc_rename_att(ncid, BAD_VARID, "abc", "newName"); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - def_dims(ncid); - def_vars(ncid); - put_atts(ncid); - - for (i = -1; i < numVars; i++) { - varid = VARID(i); - for (j = 0; j < NATTS(i); j++) { - attname = ATT_NAME(i,j); - err = nc_rename_att(BAD_ID, varid, attname, "newName"); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_rename_att(ncid, varid, "noSuch", "newName"); - IF (err != NC_ENOTATT) - error("bad attname: status = %d", err); - (void) strcpy(newname, "new_"); - (void) strcat(newname, attname); - err = nc_rename_att(ncid, varid, attname, newname); - IF (err) - error("nc_rename_att: %s", nc_strerror(err)); - err = nc_inq_attid(ncid, varid, newname, &attnum); - IF (err) - error("nc_inq_attid: %s", nc_strerror(err)); - IF (attnum != j) - error("Unexpected attnum"); - } - } - - /* Close. Reopen & check */ - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = file_open(scratch, NC_WRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - varid = VARID(i); - for (j = 0; j < NATTS(i); j++) { - attname = ATT_NAME(i,j); - atttype = ATT_TYPE(i,j); - attlength = ATT_LEN(i,j); - (void) strcpy(newname, "new_"); - (void) strcat(newname, attname); - err = nc_inq_attname(ncid, varid, j, name); - IF (err) - error("nc_inq_attname: %s", nc_strerror(err)); - IF (strcmp(name, newname) != 0) - error("nc_inq_attname: unexpected name"); - err = nc_inq_att(ncid, varid, name, &datatype, &length); - IF (err) - error("nc_inq_att: %s", nc_strerror(err)); - IF (datatype != atttype) - error("nc_inq_att: unexpected type"); - IF (length != attlength) - error("nc_inq_att: unexpected length"); - if (datatype == NC_CHAR) { - err = nc_get_att_text(ncid, varid, name, text); - IF (err) - error("nc_get_att_text: %s", nc_strerror(err)); - for (k = 0; k < attlength; k++) { - expect = hash(datatype, -1, &k); - IF (text[k] != expect) { - error("nc_get_att_text: unexpected value"); - } else { - nok++; - } - } - } else { - err = nc_get_att_double(ncid, varid, name, value); - IF (err) - error("nc_get_att_double: %s", nc_strerror(err)); - for (k = 0; k < attlength; k++) { - expect = hash(datatype, -1, &k); - if (inRange(expect, datatype)) { - IF (!equal(value[k],expect,datatype,NCT_DOUBLE)) { - error("nc_get_att_double: unexpected value"); - } else { - nok++; - } - } - } - } - } - } - print_nok(nok); - - /* Now in data mode */ - /* Try making names even longer. Then restore original names */ - - for (i = -1; i < numVars; i++) { - varid = VARID(i); - for (j = 0; j < NATTS(i); j++) { - attname = ATT_NAME(i,j); - (void) strcpy(oldname, "new_"); - (void) strcat(oldname, attname); - (void) strcpy(newname, "even_longer_"); - (void) strcat(newname, attname); - err = nc_rename_att(ncid, varid, oldname, newname); - IF (err != NC_ENOTINDEFINE) - error("longer name in data mode: status = %d", err); - err = nc_rename_att(ncid, varid, oldname, attname); - IF (err) - error("nc_rename_att: %s", nc_strerror(err)); - err = nc_inq_attid(ncid, varid, attname, &attnum); - IF (err) - error("nc_inq_attid: %s", nc_strerror(err)); - IF (attnum != j) - error("Unexpected attnum"); - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_del_att - * try with bad netCDF handle, check error - * try with bad variable handle, check error - * try with nonexisting att name, check error - * check that proper delete worked using: - * nc_inq_attid, nc_inq_natts, nc_inq_varnatts - */ -void -test_nc_del_att(void) -{ - int ncid; - int err; - int i; - int j; - int attnum; - int natts; - int numatts; - int varid; - char *name; /* of att */ - - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - err = nc_del_att(ncid, BAD_VARID, "abc"); - IF (err != NC_ENOTVAR) - error("bad var id: status = %d", err); - def_dims(ncid); - def_vars(ncid); - put_atts(ncid); - - for (i = -1; i < numVars; i++) { - varid = VARID(i); - numatts = NATTS(i); - for (j = 0; j < numatts; j++) { - name = ATT_NAME(i,j); - err = nc_del_att(BAD_ID, varid, name); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - err = nc_del_att(ncid, varid, "noSuch"); - IF (err != NC_ENOTATT) - error("bad attname: status = %d", err); - err = nc_del_att(ncid, varid, name); - IF (err) - error("nc_del_att: %s", nc_strerror(err)); - err = nc_inq_attid(ncid, varid, name, &attnum); - IF (err != NC_ENOTATT) - error("bad attname: status = %d", err); - if (i < 0) { - err = nc_inq_natts(ncid, &natts); - IF (err) - error("nc_inq_natts: %s", nc_strerror(err)); - IF (natts != numatts-j-1) - error("natts: expected %d, got %d", numatts-j-1, natts); - } - err = nc_inq_varnatts(ncid, varid, &natts); - IF (err) - error("nc_inq_varnatts: %s", nc_strerror(err)); - IF (natts != numatts-j-1) - error("natts: expected %d, got %d", numatts-j-1, natts); - } - } - - /* Close. Reopen & check no attributes left */ - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = file_open(scratch, NC_WRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = nc_inq_natts(ncid, &natts); - IF (err) - error("nc_inq_natts: %s", nc_strerror(err)); - IF (natts != 0) - error("natts: expected %d, got %d", 0, natts); - for (i = -1; i < numVars; i++) { - varid = VARID(i); - err = nc_inq_varnatts(ncid, varid, &natts); - IF (err) - error("nc_inq_natts: %s", nc_strerror(err)); - IF (natts != 0) - error("natts: expected %d, got %d", 0, natts); - } - - /* restore attributes. change to data mode. try to delete */ - err = nc_redef(ncid); - IF (err) - error("nc_redef: %s", nc_strerror(err)); - put_atts(ncid); - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - - for (i = -1; i < numVars; i++) { - varid = VARID(i); - numatts = NATTS(i); - for (j = 0; j < numatts; j++) { - name = ATT_NAME(i,j); - err = nc_del_att(ncid, varid, name); - IF (err != NC_ENOTINDEFINE) - error("in data mode: status = %d", err); - } - } - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - - -/* - * Test nc_set_fill - * try with bad netCDF handle, check error - * try in read-only mode, check error - * try with bad new_fillmode, check error - * try in data mode, check error - * check that proper set to NC_FILL works for record & non-record variables - * (note that it is not possible to test NC_NOFILL mode!) - * close file & create again for test using attribute _FillValue - */ -void -test_nc_set_fill(void) -{ - int ncid; - int varid; - int err; - int i; - int j; - int old_fillmode; - int nok = 0; /* count of valid comparisons */ - char text = 0; - double value = 0; - double fill; - size_t index[MAX_RANK]; - - /* bad ncid */ - err = nc_set_fill(BAD_ID, NC_NOFILL, &old_fillmode); - IF (err != NC_EBADID) - error("bad ncid: status = %d", err); - - /* try in read-only mode */ - err = file_open(testfile, NC_NOWRITE, &ncid); - IF (err) - error("nc_open: %s", nc_strerror(err)); - err = nc_set_fill(ncid, NC_NOFILL, &old_fillmode); - IF (err != NC_EPERM) - error("read-only: status = %d", err); - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - - /* create scratch */ - err = file_create(scratch, NC_NOCLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - - /* BAD_FILLMODE */ - err = nc_set_fill(ncid, BAD_FILLMODE, &old_fillmode); - IF (err != NC_EINVAL) - error("bad fillmode: status = %d", err); - - /* proper calls */ - err = nc_set_fill(ncid, NC_NOFILL, &old_fillmode); - IF (err) - error("nc_set_fill: %s", nc_strerror(err)); - IF (old_fillmode != NC_FILL) - error("Unexpected old fill mode: %d", old_fillmode); - err = nc_set_fill(ncid, NC_FILL, &old_fillmode); - IF (err) - error("nc_set_fill: %s", nc_strerror(err)); - IF (old_fillmode != NC_NOFILL) - error("Unexpected old fill mode: %d", old_fillmode); - - /* define dims & vars */ - def_dims(ncid); - def_vars(ncid); - - /* Change to data mode. Set fillmode again */ - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - err = nc_set_fill(ncid, NC_FILL, &old_fillmode); - IF (err) - error("nc_set_fill: %s", nc_strerror(err)); - IF (old_fillmode != NC_FILL) - error("Unexpected old fill mode: %d", old_fillmode); - - /* Write record number NRECS to force writing of preceding records */ - /* Assumes variable cr is char vector with UNLIMITED dimension */ - err = nc_inq_varid(ncid, "cr", &varid); - IF (err) - error("nc_inq_varid: %s", nc_strerror(err)); - index[0] = NRECS; - err = nc_put_var1_text(ncid, varid, index, &text); - IF (err) - error("nc_put_var1_text: %s", nc_strerror(err)); - - /* get all variables & check all values equal default fill */ - for (i = 0; i < numVars; i++) { - switch (var_type[i]) { - case NC_CHAR: fill = NC_FILL_CHAR; break; - case NC_BYTE: fill = NC_FILL_BYTE; break; - case NC_SHORT: fill = NC_FILL_SHORT; break; - case NC_INT: fill = NC_FILL_INT; break; - case NC_FLOAT: fill = NC_FILL_FLOAT; break; - case NC_DOUBLE: fill = NC_FILL_DOUBLE; break; - default: assert(0); - } - for (j = 0; j < var_nels[i]; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase"); - if (var_type[i] == NC_CHAR) { - err = nc_get_var1_text(ncid, i, index, &text); - IF (err) - error("nc_get_var1_text failed: %s", nc_strerror(err)); - value = text; - } else { - err = nc_get_var1_double(ncid, i, index, &value); - IF (err) - error("nc_get_var1_double failed: %s", nc_strerror(err)); - } - IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON) - error("\n\t\tValue expected: %-23.17e,\n\t\t read: %-23.17e\n", - fill, value); - else - nok++; - } - } - - /* close scratch & create again for test using attribute _FillValue */ - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = file_create(scratch, NC_CLOBBER, &ncid); - IF (err) { - error("nc_create: %s", nc_strerror(err)); - return; - } - def_dims(ncid); - def_vars(ncid); - - /* set _FillValue = 42 for all vars */ - text = fill = 42; - for (i = 0; i < numVars; i++) { - if (var_type[i] == NC_CHAR) { - err = nc_put_att_text(ncid, i, "_FillValue", 1, &text); - IF (err) - error("nc_put_att_text: %s", nc_strerror(err)); - } else { - err = nc_put_att_double(ncid, i, "_FillValue",var_type[i],1,&fill); - IF (err) - error("nc_put_att_double: %s", nc_strerror(err)); - } - } - - /* data mode. write records */ - err = nc_enddef(ncid); - IF (err) - error("nc_enddef: %s", nc_strerror(err)); - index[0] = NRECS; - err = nc_put_var1_text(ncid, varid, index, &text); - IF (err) - error("nc_put_var1_text: %s", nc_strerror(err)); - - /* get all variables & check all values equal 42 */ - for (i = 0; i < numVars; i++) { - for (j = 0; j < var_nels[i]; j++) { - err = toMixedBase(j, var_rank[i], var_shape[i], index); - IF (err) - error("error in toMixedBase"); - if (var_type[i] == NC_CHAR) { - err = nc_get_var1_text(ncid, i, index, &text); - IF (err) - error("nc_get_var1_text failed: %s", nc_strerror(err)); - value = text; - } else { - err = nc_get_var1_double(ncid, i, index, &value); - IF (err) - error("nc_get_var1_double failed: %s", nc_strerror(err)); - } - IF (value != fill) - error(" Value expected: %g, read: %g\n", fill, value); - else - nok++; - } - } - print_nok(nok); - - err = nc_close(ncid); - IF (err) - error("nc_close: %s", nc_strerror(err)); - err = remove(scratch); - IF (err) - error("remove of %s failed", scratch); -} - -/* This function gets the version of a netCDF file, 1 is for netCDF - classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format, - 5 for 64-bit data format (CDF-5). -*/ -#define MAGIC_NUM_LEN 4 -static -int -nc_get_file_version(char *path, int *version) -{ - FILE *fp; - char magic[MAGIC_NUM_LEN]; - - /* Need two valid pointers - check for NULL. */ - if (!version || !path) - return NC_EINVAL; - - /* Figure out if this is a netcdf or hdf5 file. */ - if (!(fp = fopen(path, "r")) || - fread(magic, MAGIC_NUM_LEN, 1, fp) != 1) { - fclose(fp); - return errno; - } - fclose(fp); - if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0) - { - if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC || - magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT_OFFSET || - magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF5) - *version = magic[MAGIC_NUM_LEN-1]; - else - return NC_ENOTNC; - } - /* tomorrow, tomorrow, I love you tomorrow, you're always a day - away! */ - /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F') - *version = 3;*/ - return NC_NOERR; -} - -/* - * Test nc_set_default_format - * try with bad default format - * try with NULL old_formatp - * try in data mode, check error - * check that proper set to NC_FILL works for record & non-record variables - * (note that it is not possible to test NC_NOFILL mode!) - * close file & create again for test using attribute _FillValue - */ -void -test_nc_set_default_format(void) -{ - int ncid; - int err; - int i; - int version; - int old_format; - - /* bad format */ - err = nc_set_default_format(BAD_DEFAULT_FORMAT, &old_format); - IF (err != NC_EINVAL) - error("bad default format: status = %d", err); - - /* NULL old_formatp */ - err = nc_set_default_format(NC_FORMAT_64BIT_OFFSET, NULL); - IF (err) - error("null old_fortmatp: status = %d", err); - - /* Cycle through available formats. */ - for(i=NC_FORMAT_CLASSIC; i /* open() */ +#include /* open() */ +#include /* open() */ +#include /* read() */ + +#include "tests.h" +#include "math.h" + +define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl + +define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl +define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl +define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_$1',`test_nc_$1')')dnl +define(`APIFunc', `ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl + +define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, $3)', `file_open($1, $2, $3)')')dnl +define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, $3)', `file_create($1, $2, $3)')')dnl +define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl + +define(`Def_Vars', `ifdef(`PNETCDF',`def_vars($1,$2)',`def_vars($1)')')dnl +define(`Put_Atts', `ifdef(`PNETCDF',`put_atts($1,$2,$3)',`put_atts($1)')')dnl +define(`Put_Vars', `ifdef(`PNETCDF',`put_vars($1,$2)',`put_vars($1)')')dnl +define(`Check_File',`ifdef(`PNETCDF',`check_file($1,$2,$3)',`check_file($1)')')dnl +define(`Check_Atts',`ifdef(`PNETCDF',`check_atts($1,$2,$3)',`check_atts($1)')')dnl +define(`Check_Vars',`ifdef(`PNETCDF',`check_vars($1,$2)',`check_vars($1)')')dnl +define(`VarArgs', `ifdef(`PNETCDF',`int numVars',`void')')dnl +define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts, int numVars',`void')')dnl + +define(`GetVar1TYPE',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl +define(`PutVar1TYPE',`ifdef(`PNETCDF',`ncmpi_put_var1_$1_all',`nc_put_var1_$1')')dnl + +define(`PutVar1', `ifdef(`PNETCDF',`ncmpi_put_var1_all($1,$2,$3,$4,$5,$6)', `nc_put_var1($1,$2,$3,$4)')')dnl +define(`PutVar', `ifdef(`PNETCDF',`ncmpi_put_var_all( $1,$2,$3,$4,$5)', `nc_put_var( $1,$2,$3)')')dnl +define(`PutVara', `ifdef(`PNETCDF',`ncmpi_put_vara_all($1,$2,$3,$4,$5,$6,$7)', `nc_put_vara($1,$2,$3,$4,$5)')')dnl +define(`PutVars', `ifdef(`PNETCDF',`ncmpi_put_vars_all($1,$2,$3,$4,$5,$6,$7,$8)', `nc_put_vars($1,$2,$3,$4,$5,$6)')')dnl +define(`PutVarm', `ifdef(`PNETCDF',`ncmpi_put_varm_all($1,$2,$3,$4,$5,$6,$7,$8,$9)', `nc_put_varm($1,$2,$3,$4,$5,$6,$7)')')dnl + + +/* + * Test APIFunc(create) + * For mode in NC_NOCLOBBER, NC_CLOBBER do: + * create netcdf file 'scratch.nc' with no data, close it + * test that it can be opened, do APIFunc(inq) to check nvars = 0, etc. + * Try again in NC_NOCLOBBER mode, check error return + * On exit, delete this file + */ +int +TestFunc(create)(void) +{ + int clobber; /* 0 for NC_NOCLOBBER, 1 for NC_CLOBBER */ + int err; + int ncid; + int ndims; /* number of dimensions */ + int nvars; /* number of variables */ + int ngatts; /* number of global attributes */ + int recdim; /* id of unlimited dimension */ + int nok=0; + + for (clobber = 0; clobber < 2; clobber++) { + err = FileCreate(scratch, clobber ? NC_CLOBBER : NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) + error("create: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileOpen(scratch, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, &recdim); + IF (err != NC_NOERR) + error("inq: %s", APIFunc(strerror)(err)); + else IF (ndims != 0) + error("inq: wrong number of dimensions returned, %d", ndims); + else IF (nvars != 0) + error("inq: wrong number of variables returned, %d", nvars); + else IF (ngatts != 0) + error("inq: wrong number of global atts returned, %d", ngatts); + else IF (recdim != -1) + error("inq: wrong record dimension ID returned, %d", recdim); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + } + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_EEXIST) + error("expecting NC_EEXIST but got %s", nc_err_code_name(err)); + ELSE_NOK + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(redef) + * (In fact also tests APIFunc(enddef) - called from TestFunc(enddef)) + * BAD_ID + * attempt redef (error) & enddef on read-only file + * create file, define dims & vars. + * attempt put var (error) + * attempt redef (error) & enddef. + * put vars + * attempt def new dims (error) + * redef + * def new dims, vars. + * put atts + * enddef + * put vars + * close + * check file: vars & atts + * check reopening with NC_WRITE and adding new dims, atts, vars + */ +int +TestFunc(redef)(AttVarArgs) +{ + int ncid; /* netcdf id */ + /* used to force effective test of ncio->move() in redef */ + IntType sizehint = 8192; + int dimid; /* dimension id */ + int varid; /* variable id */ + int varid1; /* variable id */ + int nok=0, err; + const char * title = "Not funny"; + double var; + char name[NC_MAX_NAME]; + IntType length; + int fmt_variant1, fmt_variant2; + + /* BAD_ID tests */ + err = APIFunc(redef)(BAD_ID); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(enddef)(BAD_ID); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* read-only tests */ + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(redef)(ncid); + IF (err != NC_EPERM) + error("expecting NC_EPERM but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(enddef)(ncid); + IF (err != NC_ENOTINDEFINE) + error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + /* tests using scratch file */ +ifdef(`PNETCDF',`dnl + err = FileCreate(scratch, NC_NOCLOBBER, &ncid);',`dnl + err = file__create(scratch, NC_NOCLOBBER, 0, &sizehint, &ncid);') + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } +ifdef(`PNETCDF',,`dnl + /* limit for ncio implementations which have infinite chunksize */ + if(sizehint > 32768) sizehint = 16384;') + def_dims(ncid); + Def_Vars(ncid, numVars); + Put_Atts(ncid, numGatts, numVars); + err = APIFunc(inq_varid)(ncid, "d", &varid); + IF (err != NC_NOERR) + error("inq_varid: %s", APIFunc(strerror)(err)); + var = 1.0; + +ifdef(`PNETCDF', ` + err = ncmpi_begin_indep_data(ncid); + IF (err != NC_EINDEFINE) + error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));')dnl + + err = PutVar1TYPE(double)(ncid, varid, NULL, &var); + IF (err != NC_EINDEFINE) + error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err)); + +ifdef(`PNETCDF', ` + err = ncmpi_end_indep_data(ncid); + IF (err != NC_ENOTINDEP) + error("expecting NC_ENOTINDEP but got %s", nc_err_code_name(err));')dnl + + err = APIFunc(redef)(ncid); + IF (err != NC_EINDEFINE) + error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + ELSE_NOK + Put_Vars(ncid, numVars); + err = APIFunc(def_dim)(ncid, "abc", sizehint, &dimid); + IF (err != NC_ENOTINDEFINE) + error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err)); + err = APIFunc(redef)(ncid); + IF (err != NC_NOERR) + error("redef: %s", APIFunc(strerror)(err)); + ELSE_NOK + + err = APIFunc(set_fill)(ncid, NC_NOFILL, NULL); + IF (err != NC_NOERR) + error("set_fill: %s", APIFunc(strerror)(err)); + + err = APIFunc(def_dim)(ncid, "abc", sizehint, &dimid); + IF (err != NC_NOERR) + error("def_dim: %s", APIFunc(strerror)(err)); + err = APIFunc(def_var)(ncid, "abcScalar", NC_INT, 0, NULL, &varid); + IF (err != NC_NOERR) + error("def_var: %s", APIFunc(strerror)(err)); + err = APIFunc(def_var)(ncid, "abc", NC_INT, 1, &dimid, &varid1); + IF (err != NC_NOERR) + error("def_var: %s", APIFunc(strerror)(err)); + { + int dimids[NDIMS +1]; + int ii = 0; + for(ii = 0; ii < NDIMS; ii++) dimids[ii] = ii; + dimids[NDIMS] = dimid; + err = APIFunc(def_var)(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1); + IF (err != NC_NOERR) + error("def_var: %s", APIFunc(strerror)(err)); + } + err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "title", 1+strlen(title), title); + IF (err != NC_NOERR) + error("put_att_text: %s", APIFunc(strerror)(err)); + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + ELSE_NOK + var = 1.0; + +ifdef(`PNETCDF', ` + err = ncmpi_end_indep_data(ncid); + IF (err != NC_ENOTINDEP) + error("expecting NC_ENOTINDEP but got %s", nc_err_code_name(err));')dnl + + err = PutVar1TYPE(double)(ncid, varid, NULL, &var); + IF (err != NC_NOERR) + error("put_var1_double: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_format)(ncid, &fmt_variant1); + IF (err) + error("inq_format: %s", APIFunc(strerror)(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + /* check scratch file written as expected */ + Check_File(scratch, numGatts, numVars); /* checks all except "abc" stuff added above */ + + IF ((err = FileOpen(scratch, NC_NOWRITE, &ncid))) + error("open: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(inq_dim)(ncid, dimid, name, &length))) + error("inq_dim: %s", APIFunc(strerror)(err)); + IF (strcmp(name, "abc") != 0) + error("Unexpected dim name"); + IF (length != sizehint) + error("Unexpected dim length"); + IF ((err = GetVar1TYPE(double)(ncid, varid, NULL, &var))) + error("get_var1_double: %s", APIFunc(strerror)(err)); + IF (var != 1.0) + error("get_var1_double: unexpected value"); + IF ((err = APIFunc(close)(ncid))) + error("close: %s", APIFunc(strerror)(err)); + + /* open scratch file for writing, add another dim, var, att, then check */ + IF ((err = FileOpen(scratch, NC_WRITE, &ncid))) + error("open: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(redef)(ncid))) + error("redef: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(def_dim)(ncid, "def", sizehint, &dimid))) + error("def_dim: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(def_var)(ncid, "defScalar", NC_INT, 0, NULL, &varid))) + error("def_var: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(def_var)(ncid, "def", NC_INT, 1, &dimid, &varid1))) + error("def_var: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "Credits", 1+strlen("Thanks!"), "Thanks!"))) + error("put_att_text: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(enddef)(ncid))) + error("enddef: %s", APIFunc(strerror)(err)); + var = 2.0; + IF ((err = PutVar1TYPE(double)(ncid, varid, NULL, &var))) + error("put_var1_double: %s", APIFunc(strerror)(err)); + IF ((err = APIFunc(close)(ncid))) + error("close: %s", APIFunc(strerror)(err)); + + /* check scratch file written as expected */ + Check_File(scratch, numGatts, numVars); + + err = FileOpen(scratch, NC_NOWRITE, &ncid); + IF (err) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_dim)(ncid, dimid, name, &length); + IF (err) + error("inq_dim: %s", APIFunc(strerror)(err)); + IF (strcmp(name, "def") != 0) + error("Unexpected dim name"); + IF (length != sizehint) + error("Unexpected dim length"); + err = GetVar1TYPE(double)(ncid, varid, NULL, &var); + IF (err) + error("get_var1_double: %s", APIFunc(strerror)(err)); + IF (var != 2.0) + error("get_var1_double: unexpected value"); + /* make sure format variant hasn't changed from when created */ + err = APIFunc(inq_format)(ncid, &fmt_variant2); + IF (err) + error("inq_format: %s", APIFunc(strerror)(err)); + IF (fmt_variant1 != fmt_variant2) + error("enddef changed format variant"); + err = APIFunc(close)(ncid); + IF (err) + error("close: %s", APIFunc(strerror)(err)); + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(enddef) + * Simply calls TestFunc(redef) which tests both APIFunc(redef) & APIFunc(enddef) + */ +int +TestFunc(enddef)(AttVarArgs) +{ + ifdef(`PNETCDF', + `return test_ncmpi_redef(numGatts, numVars);', + `return test_nc_redef();') +} + + +/* + * Test APIFunc(sync) + * try with bad handle, check error + * try in define mode, check error + * try writing with one handle, reading with another on same netCDF + */ +int +TestFunc(sync)(AttVarArgs) +{ + int ncidw; /* netcdf id for writing */ + int ncidr; /* netcdf id for reading */ + int nok=0, err; + + /* BAD_ID test */ + err = APIFunc(sync)(BAD_ID); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* create scratch file & try APIFunc(sync) in define mode */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncidw); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + err = APIFunc(sync)(ncidw); + IF (err != NC_EINDEFINE) + error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* write using same handle */ + def_dims(ncidw); + Def_Vars(ncidw, numVars); + Put_Atts(ncidw, numGatts, numVars); + err = APIFunc(enddef)(ncidw); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + Put_Vars(ncidw, numVars); + err = APIFunc(sync)(ncidw); + IF (err != NC_NOERR) + error("sync of ncidw failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + + /* open another handle, APIFunc(sync), read (check) */ + err = FileOpen(scratch, NC_NOWRITE, &ncidr); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(sync)(ncidr); + IF (err != NC_NOERR) + error("sync of ncidr failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + check_dims(ncidr); + Check_Atts(ncidr, numGatts, numVars); + Check_Vars(ncidr, numVars); + + /* close both handles */ + err = APIFunc(close)(ncidr); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = APIFunc(close)(ncidw); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(abort) + * try with bad handle, check error + * try in define mode before anything written, check that file was deleted + * try after APIFunc(enddef), APIFunc(redef), define new dims, vars, atts + * try after writing variable + */ +int +TestFunc(abort)(AttVarArgs) +{ + int ncid; /* netcdf id */ + int err; + int ndims; + int nvars; + int ngatts; + int nok=0; + + /* BAD_ID test */ + err = APIFunc(abort)(BAD_ID); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* create scratch file & try APIFunc(abort) in define mode */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + def_dims(ncid); + Def_Vars(ncid, numVars); + Put_Atts(ncid, numGatts, numVars); + err = APIFunc(abort)(ncid); + IF (err != NC_NOERR) + error("abort of ncid failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(close)(ncid); /* should already be closed */ + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + err = FileDelete(scratch, info); /* should already be deleted */ +ifdef(`PNETCDF', + `IF (err != NC_ENOENT && err != NC_EFILE) + error("expecting NC_ENOENT or NC_EFILE but got %s", nc_err_code_name(err));', + `IF (err != ENOENT && err != NC_EIO) + error("expecting ENOENT or NC_EIO but got %s", nc_err_code_name(err));')dnl + + /* + * create scratch file + * do APIFunc(enddef) & APIFunc(redef) + * define new dims, vars, atts + * try APIFunc(abort): should restore previous state (no dims, vars, atts) + */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + err = APIFunc(redef)(ncid); + IF (err != NC_NOERR) + error("redef: %s", APIFunc(strerror)(err)); + def_dims(ncid); + Def_Vars(ncid, numVars); + Put_Atts(ncid, numGatts, numVars); + err = APIFunc(abort)(ncid); + IF (err != NC_NOERR) + error("abort of ncid failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(close)(ncid); /* should already be closed */ + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + err = FileOpen(scratch, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, NULL); + IF (err != NC_NOERR) + error("inq: %s", APIFunc(strerror)(err)); + IF (ndims != 0) + error("ndims should be 0"); + IF (nvars != 0) + error("nvars should be 0"); + IF (ngatts != 0) + error("ngatts should be 0"); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + /* try APIFunc(abort) in data mode - should just close */ + err = FileCreate(scratch, NC_CLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + def_dims(ncid); + Def_Vars(ncid, numVars); + Put_Atts(ncid, numGatts, numVars); + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + Put_Vars(ncid, numVars); + err = APIFunc(abort)(ncid); + IF (err != NC_NOERR) + error("abort of ncid failed: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(close)(ncid); /* should already be closed */ + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + Check_File(scratch, numGatts, numVars); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(def_dim) + * try with bad netCDF handle, check error + * try in data mode, check error + * check that returned id is one more than previous id + * try adding same dimension twice, check error + * try with illegal sizes, check error + * make sure unlimited size works, shows up in APIFunc(inq_unlimdim) + * try to define a second unlimited dimension, check error + */ +int +TestFunc(def_dim)(VarArgs) +{ + int ncid; + int err; /* status */ + int i, nok=0; + int dimid; /* dimension id */ + IntType length; + + /* BAD_ID test */ + err = APIFunc(def_dim)(BAD_ID, "abc", 8, &dimid); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* data mode test */ + err = FileCreate(scratch, NC_CLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + err = APIFunc(def_dim)(ncid, "abc", 8, &dimid); + IF (err != NC_ENOTINDEFINE) + error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* define-mode tests: unlimited dim */ + err = APIFunc(redef)(ncid); + IF (err != NC_NOERR) + error("redef: %s", APIFunc(strerror)(err)); + err = APIFunc(def_dim)(ncid, dim_name[0], NC_UNLIMITED, &dimid); + IF (err != NC_NOERR) + error("def_dim: %s", APIFunc(strerror)(err)); + ELSE_NOK + IF (dimid != 0) + error("Unexpected dimid"); + ELSE_NOK + err = APIFunc(inq_unlimdim)(ncid, &dimid); + IF (err != NC_NOERR) + error("inq_unlimdim: %s", APIFunc(strerror)(err)); + IF (dimid != 0) + error("Unexpected recdim"); + err = APIFunc(inq_dimlen)(ncid, dimid, &length); + IF (length != 0) + error("Unexpected length"); + err = APIFunc(def_dim)(ncid, "abc", NC_UNLIMITED, &dimid); + IF (err != NC_EUNLIMIT) + error("expecting NC_EUNLIMIT but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* define-mode tests: remaining dims */ + for (i = 1; i < NDIMS; i++) { + err = APIFunc(def_dim)(ncid, dim_name[i-1], dim_len[i], &dimid); + IF (err != NC_ENAMEINUSE) + error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(def_dim)(ncid, BAD_NAME, dim_len[i], &dimid); + IF (err != NC_EBADNAME) + error("expecting NC_EBADNAME but got %s", nc_err_code_name(err)); + ELSE_NOK +ifdef(`PNETCDF', ,`if(sizeof(long) > 4) /* Fix: dmh 11/4/2011: works only if sizeof(long) > 4 */') + { + err = APIFunc(def_dim)(ncid, dim_name[i], (IntType)(NC_UNLIMITED-1), &dimid); + IF (err != NC_EDIMSIZE) + error("expecting NC_EDIMSIZE but got %s", nc_err_code_name(err)); + ELSE_NOK + } + err = APIFunc(def_dim)(ncid, dim_name[i], dim_len[i], &dimid); + IF (err != NC_NOERR) + error("def_dim: %s", APIFunc(strerror)(err)); + ELSE_NOK + IF (dimid != i) + error("Unexpected dimid"); + } + + /* Following just to expand unlimited dim */ + Def_Vars(ncid, numVars); + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + Put_Vars(ncid, numVars); + + /* Check all dims */ + check_dims(ncid); + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(rename_dim) + * try with bad netCDF handle, check error + * check that proper rename worked with APIFunc(inq_dim) + * try renaming to existing dimension name, check error + * try with bad dimension handle, check error + */ +int +TestFunc(rename_dim)(void) +{ + int ncid; + int err, nok=0; /* status */ + char name[NC_MAX_NAME]; + + /* BAD_ID test */ + err = APIFunc(rename_dim)(BAD_ID, 0, "abc"); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* main tests */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + def_dims(ncid); + err = APIFunc(rename_dim)(ncid, BAD_DIMID, "abc"); + IF (err != NC_EBADDIM) + error("expecting NC_EBADDIM but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(rename_dim)(ncid, 2, "abc"); + IF (err != NC_NOERR) + error("rename_dim: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(inq_dimname)(ncid, 2, name); + IF (strcmp(name, "abc") != 0) + error("Unexpected name: %s", name); + err = APIFunc(rename_dim)(ncid, 0, "abc"); + IF (err != NC_ENAMEINUSE) + error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err)); + ELSE_NOK + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(def_var) + * try with bad netCDF handle, check error + * try with bad name, check error + * scalar tests: + * check that proper define worked with APIFunc(inq_var) + * try redefining an existing variable, check error + * try with bad datatype, check error + * try with bad number of dimensions, check error + * try in data mode, check error + * check that returned id is one more than previous id + * try with bad dimension ids, check error + */ +int +TestFunc(def_var)(VarArgs) +{ + int ncid; + int varid; + int err, nok=0; /* status */ + int i; + int ndims; + int natts; + char name[NC_MAX_NAME]; + int dimids[MAX_RANK]; + nc_type datatype; + + /* BAD_ID test */ + err = APIFunc(def_var)(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* scalar tests */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 0, NULL, &varid); + IF (err != NC_NOERR) + error("def_var: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(inq_var)(ncid, varid, name, &datatype, &ndims, dimids, &natts); + IF (err != NC_NOERR) + error("inq_var: %s", APIFunc(strerror)(err)); + IF (strcmp(name, "abc") != 0) + error("Unexpected name: %s", name); + IF (datatype != NC_SHORT) + error("Unexpected datatype"); + IF (ndims != 0) + error("Unexpected rank"); + err = APIFunc(def_var)(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid); + IF (err != NC_EBADNAME) + error("expecting NC_EBADNAME but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 0, NULL, &varid); + IF (err != NC_ENAMEINUSE) + error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(def_var)(ncid, "ABC", BAD_TYPE, -1, dimids, &varid); + IF (err != NC_EBADTYPE) + error("expecting NC_EBADTYPE but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(def_var)(ncid, "ABC", NC_SHORT, -1, dimids, &varid); + IF (err != NC_EINVAL) + error("expecting NC_EINVAL but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + err = APIFunc(def_var)(ncid, "ABC", NC_SHORT, 0, dimids, &varid); + IF (err != NC_ENOTINDEFINE) + error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + + /* general tests using global vars */ + err = FileCreate(scratch, NC_CLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + def_dims(ncid); + for (i = 0; i < numVars; i++) { + err = APIFunc(def_var)(ncid, var_name[i], var_type[i], var_rank[i], + var_dimid[i], &varid); + IF (err != NC_NOERR) + error("def_var: %s", APIFunc(strerror)(err)); + ELSE_NOK + IF (varid != i) + error("Unexpected varid"); + ELSE_NOK + } + + /* try bad dim ids */ + dimids[0] = BAD_DIMID; + err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 1, dimids, &varid); + IF (err != NC_EBADDIM) + error("expecting NC_EBADDIM but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test PutVar1 + */ +int +TestFunc(put_var1)(VarArgs) +{ + int i, err, ncid, nok=0; + IntType j, index[MAX_RANK]; + double value[1]; + double buf[1]; /* (void *) buffer */ + ifdef(`PNETCDF', `MPI_Datatype datatype;') + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + + def_dims(ncid); + Def_Vars(ncid, numVars); + + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVar1(BAD_ID, 0, NULL, NULL, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVar1(ncid, BAD_VARID, NULL, NULL, 1, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + value[0] = 5; /* reset to a value within bounds */ + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVar1(ncid, i, NULL, value, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK +')dnl + + /* test NC_EINVALCOORDS */ + for (j = 0; j < var_rank[i]; j++) index[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + index[j] = var_shape[i][j]; /* out of boundary check */ + err = PutVar1(ncid, i, index, value, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + index[j] = 0; + } + + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + value[0] = hash(var_type[i], var_rank[i], index); + if (inRange(value[0], var_type[i])) { + err = dbl2nc(value[0], var_type[i], buf); + IF (err != NC_NOERR) + error("error in dbl2nc var:%s type:%s", + var_name[i],s_nc_type(var_type[i])); + err = PutVar1(ncid, i, index, buf, 1, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } + } + } + + Check_Vars(ncid, numVars); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test PutVara + * Choose a random point dividing each dim into 2 parts + * Put 2^rank (nslabs) slabs so defined + * Redefine buffer for each put. + * At end check all variables using Check_Vars + */ +int +TestFunc(put_vara)(VarArgs) +{ + int d, i, k, err, nslabs, ncid, nok=0; + IntType j, nels; + IntType start[MAX_RANK]; + IntType edge[MAX_RANK]; + IntType index[MAX_RANK]; + IntType mid[MAX_RANK]; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double value; + ifdef(`PNETCDF', `MPI_Datatype datatype;') + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + + def_dims(ncid); + Def_Vars(ncid, numVars); + + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVara(BAD_ID, 0, start, edge, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVara(ncid, BAD_VARID, start, edge, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + buf[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVara(BAD_ID, i, start, edge, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + } + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVara(ncid, i, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = PutVara(ncid, i, start, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVara(ncid, i, start, edge, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = PutVara(ncid, i, start, edge, buf, 1, datatype); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDG, err) + ELSE_NOK + edge[j] = 1; + } + /* Check correct error returned when nothing to put, when edge[*]==0 */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVara(ncid, i, start, edge, buf, 0, datatype); +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = PutVara(ncid, i, start, edge, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + /* Choose a random point dividing each dim into 2 parts */ + /* put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + for (k = 0; k < nslabs; k++) { + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + nels *= edge[j]; + } + p = (char *) buf; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], edge, index); + IF (err != 0) error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index[d] += start[d]; + value = hash(var_type[i], var_rank[i], index); + if (!inRange(value, var_type[i])) + value = 0; + err = dbl2nc(value, var_type[i], p); + IF (err != NC_NOERR) + error("error in dbl2nc"); + p += nctypelen(var_type[i]); + } + err = PutVara(ncid, i, start, edge, buf, nels, datatype); + IF (err != NC_NOERR) + error("%s", APIFunc(strerror)(err)); + ELSE_NOK + } + } + + Check_Vars(ncid, numVars); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test PutVars + * Choose a random point dividing each dim into 2 parts + * Put 2^rank (nslabs) slabs so defined + * Choose random stride from 1 to edge + * Redefine buffer for each put. + * At end check all variables using Check_Vars + */ +int +TestFunc(put_vars)(VarArgs) +{ + int ncid, d, i, k, err, nslabs, nok=0; + PTRDType nstarts; /* number of different starts */ + IntType j, m, nels; + IntType start[MAX_RANK]; + IntType edge[MAX_RANK]; + IntType index[MAX_RANK]; + IntType index2[MAX_RANK]; + IntType mid[MAX_RANK]; + IntType count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType stride[MAX_RANK]; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double value; + ifdef(`PNETCDF', `MPI_Datatype datatype;') + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + + def_dims(ncid); + Def_Vars(ncid, numVars); + + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVars(BAD_ID, 0, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVars(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + buf[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVars(BAD_ID, i, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVars(ncid, i, NULL, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = PutVars(ncid, i, start, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == 0) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; /* edge error check */ + err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDG, err) + ELSE_NOK + edge[j] = 1; + stride[j] = 0; /* strided edge error check */ + err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + ELSE_NOK + stride[j] = 1; + } + /* Check correct error returned even when nothing to put */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == 0) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVars(ncid, i, start, edge, stride, buf, 0, datatype); +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + /* Choose a random point dividing each dim into 2 parts */ + /* put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err != 0) error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * (IntType)stride[j]; + stride[j] = -stride[j]; + } + } + */ + p = (char *) buf; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err != 0) error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * (IntType)stride[d]; + value = hash(var_type[i], var_rank[i], index2); + if (!inRange(value, var_type[i])) + value = 0; + err = dbl2nc(value, var_type[i], p); + IF (err != NC_NOERR) + error("error in dbl2nc"); + p += nctypelen(var_type[i]); + } + err = PutVars(ncid, i, index, count, stride, buf, nels, datatype); + IF (err != NC_NOERR) + EXPECT_ERR(NC_NOERR, err) + ELSE_NOK + } + } + } + + Check_Vars(ncid, numVars); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test PutVarm + * Choose a random point dividing each dim into 2 parts + * Put 2^rank (nslabs) slabs so defined + * Choose random stride from 1 to edge + * Buffer is bit image of whole external variable. + * So all puts for a variable put different elements of buffer + * At end check all variables using Check_Vars + */ +int +TestFunc(put_varm)(VarArgs) +{ + int ncid, nok=0; + int i; + int k; + int err; + int nslabs; + IntType j, m; + PTRDType nstarts; /* number of different starts */ + IntType start[MAX_RANK]; + IntType edge[MAX_RANK]; + IntType index[MAX_RANK]; + IntType mid[MAX_RANK]; + IntType count[MAX_RANK]; + IntType sstride[MAX_RANK]; + PTRDType stride[MAX_RANK]; + PTRDType imap[MAX_RANK]; + PTRDType imap2[MAX_RANK]; + ifdef(`PNETCDF', `IntType bufcount;') + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double value; + ifdef(`PNETCDF', `MPI_Datatype datatype;') + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + + def_dims(ncid); + Def_Vars(ncid, numVars); + + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + /* check if can detect a bad file ID */ + err = PutVarm(NC_EBADID, 0, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + /* check if can detect a bad variable ID */ + err = PutVarm(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL); + IF (err != NC_ENOTVAR) + EXPECT_ERR(NC_ENOTVAR, err) + ELSE_NOK + + for (i = 0; i < numVars; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + + buf[0] = 5; /* reset to a value within bounds */ + + /* check if can detect a bad file ID */ + err = PutVarm(BAD_ID, i, NULL, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL); + IF (err != NC_EBADID) + EXPECT_ERR(NC_EBADID, err) + ELSE_NOK + + ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);') + + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + imap[j] = 1; + } + +ifdef(`PNETCDF',`dnl + /* for non-scalar variables, argument start cannot be NULL */ + err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { /* scalar variable */ + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EINVALCOORDS) { + EXPECT_ERR(NC_EINVALCOORDS, err) + } + ELSE_NOK + + /* for non-scalar variables, argument count cannot be NULL */ + err = PutVarm(ncid, i, start, NULL, NULL, NULL, buf, 1, datatype); + if (var_rank[i] == 0) { + IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err) + } + else IF (err != NC_EEDGE) { + EXPECT_ERR(NC_EEDGE, err) + } + ELSE_NOK +')dnl + + /* first test when edge[*] > 0 */ + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == 0) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + edge[j] = var_shape[i][j] + 1; /* edge error check */ + err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_EEDGE) + EXPECT_ERR(NC_EEDG, err) + ELSE_NOK + edge[j] = 1; + stride[j] = 0; /* strided edge error check */ + err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_ESTRIDE) + EXPECT_ERR(NC_ESTRIDE, err) + ELSE_NOK + stride[j] = 1; + } + /* Check correct error returned even when nothing to put */ + for (j = 0; j < var_rank[i]; j++) edge[j] = 0; + + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] == 0) continue; /* skip record dim */ + start[j] = var_shape[i][j]; + err = PutVarm(ncid, i, start, edge, stride, imap, buf, 0, datatype); +#ifdef RELAX_COORD_BOUND + IF (err != NC_NOERR) /* allowed when edge[j]==0 */ + EXPECT_ERR(NC_NOERR, err) +#else + IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */ + EXPECT_ERR(NC_EINVALCOORDS, err) +#endif + ELSE_NOK + start[j] = var_shape[i][j]+1; /* out of boundary check */ + err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype); + IF (err != NC_EINVALCOORDS) + EXPECT_ERR(NC_EINVALCOORDS, err) + ELSE_NOK + start[j] = 0; + } + for (j = 0; j < var_rank[i]; j++) edge[j] = 1; + + if (var_rank[i] > 0) { + int jj = var_rank[i] - 1; + imap[jj] = nctypelen(var_type[i]); /* netCDF considers imap in bytes */ + imap[jj] = 1; /* PnetCDF considers imap in elements */ + for (; jj > 0; jj--) + imap[jj-1] = imap[jj] * (PTRDType)var_shape[i][jj]; + } + p = (char *) buf; + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + value = hash(var_type[i], var_rank[i], index); + if (!inRange(value, var_type[i])) + value = 0; + err = dbl2nc(value, var_type[i], p); + IF (err != NC_NOERR) + error("error in dbl2nc"); + p += nctypelen(var_type[i]); + } + + /* Choose a random point dividing each dim into 2 parts */ + /* put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + stride[j] = (PTRDType)sstride[j]; + imap2[j] = imap[j] * (PTRDType)sstride[j]; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + if (var_rank[i] == 0 && i%2 == 0) { + err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype); + } else { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err != 0) error("error in toMixedBase"); + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * (IntType)stride[j]; + stride[j] = -stride[j]; + } + } + */ + j = fromMixedBase(var_rank[i], index, var_shape[i]); + p = (char *) buf + (int)j * nctypelen(var_type[i]); + ifdef(`PNETCDF', `for (bufcount=1,j=0; j 0 && ATT_LEN(i,j) > 0) { + err = APIFunc(rename_att)(ncid_out, i, att_name[i][0], "a"); + IF (err != NC_NOERR) + error("rename_att: %s", APIFunc(strerror)(err)); + err = APIFunc(copy_att)(ncid_out, NC_GLOBAL, "a", ncid_out, i); + IF (err != NC_NOERR) + error("copy_att: %s", APIFunc(strerror)(err)); + ELSE_NOK + } + } + err = APIFunc(close)(ncid_out); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + /* Reopen & check */ + err = FileOpen(scratch, NC_WRITE, &ncid_out); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + for (i = 0; i < numVars; i++) { + if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) { + err = APIFunc(inq_att)(ncid_out, i, "a", &datatype, &length); + IF (err != NC_NOERR) + error("inq_att: %s", APIFunc(strerror)(err)); + IF (datatype != NC_CHAR) + error("Unexpected type"); + IF (length != 1) + error("Unexpected length"); + err = APIFunc(get_att_text)(ncid_out, i, "a", &value); + IF (err != NC_NOERR) + error("get_att_text: %s", APIFunc(strerror)(err)); + IF (value != 'A') + error("Unexpected value"); + } + } + + err = APIFunc(close)(ncid_out); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(rename_att) + * try with bad netCDF handle, check error + * try with bad variable handle, check error + * try with nonexisting att name, check error + * try renaming to existing att name, check error + * check that proper rename worked with APIFunc(inq_attid) + * try in data mode, check error + */ +int +TestFunc(rename_att)(AttVarArgs) +{ + int ncid; + int varid; + int err; + int i; + int j; + IntType k; + int attnum; + char *attname; + char name[NC_MAX_NAME]; + char oldname[NC_MAX_NAME]; + char newname[NC_MAX_NAME]; + int nok = 0; /* count of valid comparisons */ + nc_type datatype; + nc_type atttype; + IntType length; + IntType attlength; + char text[MAX_NELS]; + double value[MAX_NELS]; + double expect; + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + err = APIFunc(rename_att)(ncid, BAD_VARID, "abc", "newName"); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + def_dims(ncid); + Def_Vars(ncid, numVars); + Put_Atts(ncid, numGatts, numVars); + + for (i = -1; i < numVars; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + attname = ATT_NAME(i,j); + err = APIFunc(rename_att)(BAD_ID, varid, attname, "newName"); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(rename_att)(ncid, varid, "noSuch", "newName"); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + strcpy(newname, "new_"); + strcat(newname, attname); + err = APIFunc(rename_att)(ncid, varid, attname, newname); + IF (err != NC_NOERR) + error("rename_att: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(inq_attid)(ncid, varid, newname, &attnum); + IF (err != NC_NOERR) + error("inq_attid: %s", APIFunc(strerror)(err)); + IF (attnum != j) + error("Unexpected attnum"); + } + } + + /* Close. Reopen & check */ + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileOpen(scratch, NC_WRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + attname = ATT_NAME(i,j); + atttype = ATT_TYPE(i,j); + attlength = ATT_LEN(i,j); + strcpy(newname, "new_"); + strcat(newname, attname); + err = APIFunc(inq_attname)(ncid, varid, j, name); + IF (err != NC_NOERR) + error("inq_attname: %s", APIFunc(strerror)(err)); + IF (strcmp(name, newname) != 0) + error("inq_attname: unexpected name"); + err = APIFunc(inq_att)(ncid, varid, name, &datatype, &length); + IF (err != NC_NOERR) + error("inq_att: %s", APIFunc(strerror)(err)); + IF (datatype != atttype) + error("inq_att: unexpected type"); + IF (length != attlength) + error("inq_att: unexpected length"); + if (datatype == NC_CHAR) { + err = APIFunc(get_att_text)(ncid, varid, name, text); + IF (err != NC_NOERR) + error("get_att_text: %s", APIFunc(strerror)(err)); + for (k = 0; k < attlength; k++) { + expect = hash(datatype, -1, &k); + IF (text[k] != (char)expect) + error("get_att_text: unexpected value"); + } + } else { + err = APIFunc(get_att_double)(ncid, varid, name, value); + IF (err != NC_NOERR) + error("get_att_double: %s", APIFunc(strerror)(err)); + for (k = 0; k < attlength; k++) { + expect = hash(datatype, -1, &k); + if (inRange(expect, datatype)) { + IF (!equal(value[k],expect,datatype,NCT_DOUBLE)) + error("get_att_double: unexpected value"); + } + } + } + } + } + + /* Now in data mode */ + /* Try making names even longer. Then restore original names */ + + for (i = -1; i < numVars; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + attname = ATT_NAME(i,j); + strcpy(oldname, "new_"); + strcat(oldname, attname); + strcpy(newname, "even_longer_"); + strcat(newname, attname); + err = APIFunc(rename_att)(ncid, varid, oldname, newname); + IF (err != NC_ENOTINDEFINE) + error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(rename_att)(ncid, varid, oldname, attname); + IF (err != NC_NOERR) + error("rename_att: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(inq_attid)(ncid, varid, attname, &attnum); + IF (err != NC_NOERR) + error("inq_attid: %s", APIFunc(strerror)(err)); + IF (attnum != j) + error("Unexpected attnum"); + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(del_att) + * try with bad netCDF handle, check error + * try with bad variable handle, check error + * try with nonexisting att name, check error + * check that proper delete worked using: + * APIFunc(inq_attid), APIFunc(inq_natts), APIFunc(inq_varnatts) + */ +int +TestFunc(del_att)(AttVarArgs) +{ + int ncid; + int err, nok=0; + int i; + int j; + int attnum; + int natts; + int numatts; + int varid; + char *name; /* of att */ + + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + err = APIFunc(del_att)(ncid, BAD_VARID, "abc"); + IF (err != NC_ENOTVAR) + error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err)); + ELSE_NOK + def_dims(ncid); + Def_Vars(ncid, numVars); + Put_Atts(ncid, numGatts, numVars); + + for (i = -1; i < numVars; i++) { + varid = VARID(i); + numatts = NATTS(i); + for (j = 0; j < numatts; j++) { + name = ATT_NAME(i,j); + err = APIFunc(del_att)(BAD_ID, varid, name); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(del_att)(ncid, varid, "noSuch"); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + ELSE_NOK + err = APIFunc(del_att)(ncid, varid, name); + IF (err != NC_NOERR) + error("del_att: %s", APIFunc(strerror)(err)); + ELSE_NOK + err = APIFunc(inq_attid)(ncid, varid, name, &attnum); + IF (err != NC_ENOTATT) + error("expecting NC_ENOTATT but got %s", nc_err_code_name(err)); + if (i < 0) { + err = APIFunc(inq_natts)(ncid, &natts); + IF (err != NC_NOERR) + error("inq_natts: %s", APIFunc(strerror)(err)); + IF (natts != numatts-j-1) + error("natts: expected %d, got %d", numatts-j-1, natts); + } + err = APIFunc(inq_varnatts)(ncid, varid, &natts); + IF (err != NC_NOERR) + error("inq_natts: %s", APIFunc(strerror)(err)); + IF (natts != numatts-j-1) + error("natts: expected %d, got %d", numatts-j-1, natts); + } + } + + /* Close. Reopen & check no attributes left */ + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileOpen(scratch, NC_WRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(inq_natts)(ncid, &natts); + IF (err != NC_NOERR) + error("inq_natts: %s", APIFunc(strerror)(err)); + IF (natts != 0) + error("natts: expected %d, got %d", 0, natts); + for (i = -1; i < numVars; i++) { + varid = VARID(i); + err = APIFunc(inq_varnatts)(ncid, varid, &natts); + IF (err != NC_NOERR) + error("inq_natts: %s", APIFunc(strerror)(err)); + IF (natts != 0) + error("natts: expected %d, got %d", 0, natts); + } + + /* restore attributes. change to data mode. try to delete */ + err = APIFunc(redef)(ncid); + IF (err != NC_NOERR) + error("redef: %s", APIFunc(strerror)(err)); + Put_Atts(ncid, numGatts, numVars); + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + + for (i = -1; i < numVars; i++) { + varid = VARID(i); + numatts = NATTS(i); + for (j = 0; j < numatts; j++) { + name = ATT_NAME(i,j); + err = APIFunc(del_att)(ncid, varid, name); + IF (err != NC_ENOTINDEFINE) + error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err)); + ELSE_NOK + } + } + + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + return nok; +} + + +/* + * Test APIFunc(set_fill) + * try with bad netCDF handle, check error + * try in read-only mode, check error + * try with bad new_fillmode, check error + * try in data mode, check error + * check that proper set to NC_FILL works for record & non-record variables + * (note that it is not possible to test NC_NOFILL mode!) + * close file & create again for test using attribute _FillValue + */ +int +TestFunc(set_fill)(VarArgs) +{ + int ncid; + int varid; + int err; + int i; + IntType j; + int old_fillmode; + int nok = 0; /* count of valid comparisons */ + char text = 0; + double value = 0; + double fill; + IntType index[MAX_RANK]; + + /* bad ncid */ + err = APIFunc(set_fill)(BAD_ID, NC_NOFILL, &old_fillmode); + IF (err != NC_EBADID) + error("expecting NC_EBADID but got %s", nc_err_code_name(err)); + + /* try in read-only mode */ + err = FileOpen(testfile, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) + error("open: %s", APIFunc(strerror)(err)); + err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode); + IF (err != NC_EPERM) + error("expecting NC_EPERM but got %s", nc_err_code_name(err)); + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + + /* create scratch */ + err = FileCreate(scratch, NC_NOCLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + + /* BAD_FILLMODE */ + err = APIFunc(set_fill)(ncid, BAD_FILLMODE, &old_fillmode); + IF (err != NC_EINVAL) + error("expecting NC_EINVAL but got %s", nc_err_code_name(err)); + + /* proper calls */ + err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode); + IF (err != NC_NOERR) + error("set_fill: %s", APIFunc(strerror)(err)); + IF (old_fillmode != NC_NOFILL) + error("Unexpected old fill mode: %d", old_fillmode); + err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode); + IF (err != NC_NOERR) + error("set_fill: %s", APIFunc(strerror)(err)); + IF (old_fillmode != NC_NOFILL) + error("Unexpected old fill mode: %d", old_fillmode); + + /* define dims & vars */ + def_dims(ncid); + Def_Vars(ncid, numVars); + + /* Change to data mode. Set fillmode again */ + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode); +ifdef(`PNETCDF', + `IF (err != NC_ENOTINDEFINE) + error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));', + `IF (err) + error("nc_set_fill: %s", nc_strerror(err)); + IF (old_fillmode != NC_FILL) + error("Unexpected old fill mode: %d", old_fillmode);')dnl + + /* Write record number NRECS to force writing of preceding records */ + /* Assumes variable cr is char vector with UNLIMITED dimension */ + err = APIFunc(inq_varid)(ncid, "cr", &varid); + IF (err != NC_NOERR) + error("inq_varid: %s", APIFunc(strerror)(err)); + index[0] = NRECS; + +ifdef(`PNETCDF', ` + for (i=0; i<=index[0]; i++) + err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl + + err = PutVar1TYPE(text)(ncid, varid, index, &text); + IF (err != NC_NOERR) + error("put_var1_text_all: %s", APIFunc(strerror)(err)); + + /* get all variables & check all values equal default fill */ + for (i = 0; i < numVars; i++) { + ifdef(`PNETCDF', `if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */') + switch (var_type[i]) { + case NC_CHAR: fill = (double)NC_FILL_CHAR; break; + case NC_BYTE: fill = (double)NC_FILL_BYTE; break; + case NC_SHORT: fill = (double)NC_FILL_SHORT; break; + case NC_INT: fill = (double)NC_FILL_INT; break; + case NC_FLOAT: fill = (double)NC_FILL_FLOAT; break; + case NC_DOUBLE: fill = (double)NC_FILL_DOUBLE; break; + case NC_UBYTE: fill = (double)NC_FILL_UBYTE; break; + case NC_USHORT: fill = (double)NC_FILL_USHORT; break; + case NC_UINT: fill = (double)NC_FILL_UINT; break; + case NC_INT64: fill = (double)NC_FILL_INT64; break; + case NC_UINT64: fill = (double)NC_FILL_UINT64; break; + default: assert(0); + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + if (var_type[i] == NC_CHAR) { + err = GetVar1TYPE(text)(ncid, i, index, &text); + IF (err != NC_NOERR) + error("get_var1_text_all failed: %s", APIFunc(strerror)(err)); + value = text; + } else { + err = GetVar1TYPE(double)(ncid, i, index, &value); + IF (err != NC_NOERR) + error("get_var1_double_all failed: %s", APIFunc(strerror)(err)); + } + IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON) + error("\n\t\t%s Value expected: %-23.17e,\n\t\t read: %-23.17e\n", + var_name[i],fill, value); + ELSE_NOK + } + } + + /* close scratch & create again for test using attribute _FillValue */ + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileCreate(scratch, NC_CLOBBER, &ncid); + IF (err != NC_NOERR) { + error("create: %s", APIFunc(strerror)(err)); + return nok; + } + def_dims(ncid); + Def_Vars(ncid, numVars); + + /* set _FillValue = 42 for all vars */ + fill = 42; + text = 42; + for (i = 0; i < numVars; i++) { + if (var_type[i] == NC_CHAR) { + err = APIFunc(put_att_text)(ncid, i, "_FillValue", 1, &text); + IF (err != NC_NOERR) + error("put_att_text: %s", APIFunc(strerror)(err)); + } else { + err = APIFunc(put_att_double)(ncid, i, "_FillValue",var_type[i],1,&fill); + IF (err != NC_NOERR) + error("put_att_double: %s", APIFunc(strerror)(err)); + } + } + + /* data mode. write records */ + err = APIFunc(enddef)(ncid); + IF (err != NC_NOERR) + error("enddef: %s", APIFunc(strerror)(err)); + index[0] = NRECS; + +ifdef(`PNETCDF', ` + for (i=0; i<=index[0]; i++) + err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl + + err = PutVar1TYPE(text)(ncid, varid, index, &text); + IF (err != NC_NOERR) + error("put_var1_text_all: %s", APIFunc(strerror)(err)); + + /* get all variables & check all values equal 42 */ + for (i = 0; i < numVars; i++) { + if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */ + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err != 0) error("error in toMixedBase"); + if (var_type[i] == NC_CHAR) { + err = GetVar1TYPE(text)(ncid, i, index, &text); + IF (err != NC_NOERR) + error("get_var1_text_all failed: %s", APIFunc(strerror)(err)); + value = text; + } else { + err = GetVar1TYPE(double)(ncid, i, index, &value); + IF (err != NC_NOERR) + error("get_var1_double_all failed: %s", APIFunc(strerror)(err)); + } + IF (value != fill) + error(" %s Value expected: %g, read: %g\n", var_name[i],fill, value); + ELSE_NOK + } + } + err = APIFunc(close)(ncid); + IF (err != NC_NOERR) + error("close: %s", APIFunc(strerror)(err)); + err = FileDelete(scratch, info); + IF (err != NC_NOERR) + error("remove of %s failed", scratch); + + return nok; +} + + +/* This function gets the version of a netCDF file, 1 is for netCDF + classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format, + 5 for 64-bit data format (CDF-5). +*/ +#define MAGIC_NUM_LEN 4 +static +int +APIFunc(get_file_version)(char *path, int *version) +{ + int fd; + ssize_t read_len; + char magic[MAGIC_NUM_LEN]; + + /* Need two valid pointers - check for NULL. */ + if (!version || !path) + return NC_EINVAL; + + /* Figure out if this is a netcdf or hdf5 file. */ + fd = open(path, O_RDONLY, 0600); + if (fd == -1) return errno; + + read_len = read(fd, magic, MAGIC_NUM_LEN); + if (-1 == close(fd)) return errno; + + if (read_len == -1) + return errno; + + if (read_len != MAGIC_NUM_LEN) { + printf("Error: reading NC magic string unexpected short read\n"); + return 0; + } + + if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0) { + if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC || + magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT_OFFSET || + magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF5) + *version = magic[MAGIC_NUM_LEN-1]; + else + return NC_ENOTNC; + } + /* tomorrow, tomorrow, I love you tomorrow, you're always a day + away! */ + /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F') + *version = 3;*/ + return NC_NOERR; +} + +/* + * Test APIFunc(set_default_format) + * try with bad default format + * try with NULL old_formatp + * try in data mode, check error + * check that proper set to NC_FILL works for record & non-record variables + * (note that it is not possible to test NC_NOFILL mode!) + * close file & create again for test using attribute _FillValue + */ +int +TestFunc(set_default_format)(void) +{ + int ncid, nok=0; + int err; + int i; + int version=1; + int old_format; + + /* bad format */ + err = APIFunc(set_default_format)(BAD_DEFAULT_FORMAT, &old_format); + IF (err != NC_EINVAL) + error("expecting NC_EINVAL but got %s", nc_err_code_name(err)); + ELSE_NOK + + /* NULL old_formatp */ + err = APIFunc(set_default_format)(NC_FORMAT_64BIT_OFFSET, NULL); + IF (err != NC_NOERR) + error("null old_fortmatp: status = %d", err); + ELSE_NOK + + /* Cycle through available formats. */ + for(i=NC_FORMAT_CLASSIC; i #endif -typedef signed char text; +typedef char text; typedef signed char schar; #ifndef HAVE_USHORT @@ -243,11 +242,11 @@ extern char dim_name[NDIMS][3]; extern size_t dim_len[NDIMS]; extern char var_name[NVARS][2+MAX_RANK]; extern nc_type var_type[NVARS]; -extern size_t var_rank[NVARS]; +extern int var_rank[NVARS]; extern int var_dimid[NVARS][MAX_RANK]; extern size_t var_shape[NVARS][MAX_RANK]; extern size_t var_nels[NVARS]; -extern size_t var_natts[NVARS]; +extern int var_natts[NVARS]; extern char att_name[NVARS][MAX_NATTS][2]; extern char gatt_name[NGATTS][3]; extern nc_type att_type[NVARS][NGATTS]; @@ -267,220 +266,221 @@ extern size_t gatt_len[NGATTS]; extern const char *s_nc_type(nc_type); -extern void test_nc_strerror(void); -extern void test_nc_open(void); -extern void test_nc_close(void); - -extern void test_nc_inq(void); -extern void test_nc_inq_natts(void); -extern void test_nc_inq_ndims(void); -extern void test_nc_inq_nvars(void); -extern void test_nc_inq_unlimdim(void); - -extern void test_nc_inq_dimid(void); -extern void test_nc_inq_dim(void); -extern void test_nc_inq_dimlen(void); -extern void test_nc_inq_dimname(void); - -extern void test_nc_inq_varid(void); -extern void test_nc_inq_vardimid(void); -extern void test_nc_inq_varname(void); -extern void test_nc_inq_varnatts(void); -extern void test_nc_inq_varndims(void); -extern void test_nc_inq_vartype(void); -extern void test_nc_inq_var(void); - -extern void test_nc_get_var_double(void); -extern void test_nc_get_var_float(void); -extern void test_nc_get_var_int(void); -extern void test_nc_get_var_long(void); -extern void test_nc_get_var_schar(void); -extern void test_nc_get_var_short(void); -extern void test_nc_get_var_text(void); -extern void test_nc_get_var_uchar(void); -extern void test_nc_get_var(void); -extern void test_nc_get_var_ushort(void); -extern void test_nc_get_var_uint(void); -extern void test_nc_get_var_longlong(void); -extern void test_nc_get_var_ulonglong(void); - -extern void test_nc_get_var1_double(void); -extern void test_nc_get_var1_float(void); -extern void test_nc_get_var1_int(void); -extern void test_nc_get_var1_long(void); -extern void test_nc_get_var1_schar(void); -extern void test_nc_get_var1_short(void); -extern void test_nc_get_var1_text(void); -extern void test_nc_get_var1_uchar(void); -extern void test_nc_get_var1(void); -extern void test_nc_get_var1_ushort(void); -extern void test_nc_get_var1_uint(void); -extern void test_nc_get_var1_longlong(void); -extern void test_nc_get_var1_ulonglong(void); - -extern void test_nc_get_vara_double(void); -extern void test_nc_get_vara_float(void); -extern void test_nc_get_vara_int(void); -extern void test_nc_get_vara_long(void); -extern void test_nc_get_vara_schar(void); -extern void test_nc_get_vara_short(void); -extern void test_nc_get_vara_text(void); -extern void test_nc_get_vara_uchar(void); -extern void test_nc_get_vara(void); -extern void test_nc_get_vara_ushort(void); -extern void test_nc_get_vara_uint(void); -extern void test_nc_get_vara_longlong(void); -extern void test_nc_get_vara_ulonglong(void); - -extern void test_nc_get_vars(void); -extern void test_nc_get_vars_double(void); -extern void test_nc_get_vars_float(void); -extern void test_nc_get_vars_int(void); -extern void test_nc_get_vars_long(void); -extern void test_nc_get_vars_schar(void); -extern void test_nc_get_vars_short(void); -extern void test_nc_get_vars_text(void); -extern void test_nc_get_vars_uchar(void); -extern void test_nc_get_vars(void); -extern void test_nc_get_vars_ushort(void); -extern void test_nc_get_vars_uint(void); -extern void test_nc_get_vars_longlong(void); -extern void test_nc_get_vars_ulonglong(void); - -extern void test_nc_get_varm(void); -extern void test_nc_get_varm_double(void); -extern void test_nc_get_varm_float(void); -extern void test_nc_get_varm_int(void); -extern void test_nc_get_varm_long(void); -extern void test_nc_get_varm_schar(void); -extern void test_nc_get_varm_short(void); -extern void test_nc_get_varm_text(void); -extern void test_nc_get_varm_uchar(void); -extern void test_nc_get_varm(void); -extern void test_nc_get_varm_ushort(void); -extern void test_nc_get_varm_uint(void); -extern void test_nc_get_varm_longlong(void); -extern void test_nc_get_varm_ulonglong(void); - -extern void test_nc_get_att(void); -extern void test_nc_get_att_double(void); -extern void test_nc_get_att_float(void); -extern void test_nc_get_att_int(void); -extern void test_nc_get_att_long(void); -extern void test_nc_get_att_schar(void); -extern void test_nc_get_att_short(void); -extern void test_nc_get_att_text(void); -extern void test_nc_get_att_uchar(void); -extern void test_nc_get_att_ushort(void); -extern void test_nc_get_att_uint(void); -extern void test_nc_get_att_longlong(void); -extern void test_nc_get_att_ulonglong(void); - -extern void test_nc_put_att(void); -extern void test_nc_put_var_double(void); -extern void test_nc_put_var_float(void); -extern void test_nc_put_var_int(void); -extern void test_nc_put_var_long(void); -extern void test_nc_put_var_schar(void); -extern void test_nc_put_var_short(void); -extern void test_nc_put_var_text(void); -extern void test_nc_put_var_uchar(void); -extern void test_nc_put_var(void); -extern void test_nc_put_var_ushort(void); -extern void test_nc_put_var_uint(void); -extern void test_nc_put_var_longlong(void); -extern void test_nc_put_var_ulonglong(void); - -extern void test_nc_put_var1_double(void); -extern void test_nc_put_var1_float(void); -extern void test_nc_put_var1_int(void); -extern void test_nc_put_var1_long(void); -extern void test_nc_put_var1_schar(void); -extern void test_nc_put_var1_short(void); -extern void test_nc_put_var1_text(void); -extern void test_nc_put_var1_uchar(void); -extern void test_nc_put_var1(void); -extern void test_nc_put_var1_ushort(void); -extern void test_nc_put_var1_uint(void); -extern void test_nc_put_var1_longlong(void); -extern void test_nc_put_var1_ulonglong(void); - -extern void test_nc_put_vara_double(void); -extern void test_nc_put_vara_float(void); -extern void test_nc_put_vara_int(void); -extern void test_nc_put_vara_long(void); -extern void test_nc_put_vara_schar(void); -extern void test_nc_put_vara_short(void); -extern void test_nc_put_vara_text(void); -extern void test_nc_put_vara_uchar(void); -extern void test_nc_put_vara(void); -extern void test_nc_put_vara_ushort(void); -extern void test_nc_put_vara_uint(void); -extern void test_nc_put_vara_longlong(void); -extern void test_nc_put_vara_ulonglong(void); - -extern void test_nc_put_vars_double(void); -extern void test_nc_put_vars_float(void); -extern void test_nc_put_vars_int(void); -extern void test_nc_put_vars_long(void); -extern void test_nc_put_vars_schar(void); -extern void test_nc_put_vars_short(void); -extern void test_nc_put_vars_text(void); -extern void test_nc_put_vars_uchar(void); -extern void test_nc_put_vars(void); -extern void test_nc_put_vars_ushort(void); -extern void test_nc_put_vars_uint(void); -extern void test_nc_put_vars_longlong(void); -extern void test_nc_put_vars_ulonglong(void); - -extern void test_nc_put_varm_double(void); -extern void test_nc_put_varm_float(void); -extern void test_nc_put_varm_int(void); -extern void test_nc_put_varm_long(void); -extern void test_nc_put_varm_schar(void); -extern void test_nc_put_varm_short(void); -extern void test_nc_put_varm_text(void); -extern void test_nc_put_varm_uchar(void); -extern void test_nc_put_varm(void); -extern void test_nc_put_varm_ushort(void); -extern void test_nc_put_varm_uint(void); -extern void test_nc_put_varm_longlong(void); -extern void test_nc_put_varm_ulonglong(void); - -extern void test_nc_put_att_double(void); -extern void test_nc_put_att_float(void); -extern void test_nc_put_att_int(void); -extern void test_nc_put_att_long(void); -extern void test_nc_put_att_schar(void); -extern void test_nc_put_att_short(void); -extern void test_nc_put_att_text(void); -extern void test_nc_put_att_uchar(void); -extern void test_nc_put_att_ushort(void); -extern void test_nc_put_att_uint(void); -extern void test_nc_put_att_longlong(void); -extern void test_nc_put_att_ulonglong(void); - -extern void test_nc_create(void); -extern void test_nc_redef(void); -extern void test_nc_enddef(void); -extern void test_nc_sync(void); -extern void test_nc_abort(void); -extern void test_nc_def_dim(void); -extern void test_nc_rename_dim(void); -extern void test_nc_def_var(void); -extern void test_nc_rename_var(void); -extern void test_nc_copy_att(void); - -extern void test_nc_inq_att(void); -extern void test_nc_inq_attname(void); -extern void test_nc_inq_attid(void); -extern void test_nc_inq_attlen(void); -extern void test_nc_inq_atttype(void); - -extern void test_nc_rename_att(void); -extern void test_nc_del_att(void); -extern void test_nc_set_fill(void); -extern void test_nc_set_default_format(void); +extern int test_nc_strerror(void); +extern int test_nc_open(void); +extern int test_nc_close(void); + +extern int test_nc_inq(void); +extern int test_nc_inq_natts(void); +extern int test_nc_inq_ndims(void); +extern int test_nc_inq_nvars(void); +extern int test_nc_inq_unlimdim(void); + +extern int test_nc_inq_dimid(void); +extern int test_nc_inq_dim(void); +extern int test_nc_inq_dimlen(void); +extern int test_nc_inq_dimname(void); + +extern int test_nc_inq_varid(void); +extern int test_nc_inq_vardimid(void); +extern int test_nc_inq_varname(void); +extern int test_nc_inq_varnatts(void); +extern int test_nc_inq_varndims(void); +extern int test_nc_inq_vartype(void); +extern int test_nc_inq_var(void); + +extern int test_nc_get_var_double(void); +extern int test_nc_get_var_float(void); +extern int test_nc_get_var_int(void); +extern int test_nc_get_var_long(void); +extern int test_nc_get_var_schar(void); +extern int test_nc_get_var_short(void); +extern int test_nc_get_var_text(void); +extern int test_nc_get_var_uchar(void); +extern int test_nc_get_var(void); +extern int test_nc_get_var_ushort(void); +extern int test_nc_get_var_uint(void); +extern int test_nc_get_var_longlong(void); +extern int test_nc_get_var_ulonglong(void); + +extern int test_nc_get_var1_double(void); +extern int test_nc_get_var1_float(void); +extern int test_nc_get_var1_int(void); +extern int test_nc_get_var1_long(void); +extern int test_nc_get_var1_schar(void); +extern int test_nc_get_var1_short(void); +extern int test_nc_get_var1_text(void); +extern int test_nc_get_var1_uchar(void); +extern int test_nc_get_var1(void); +extern int test_nc_get_var1_ushort(void); +extern int test_nc_get_var1_uint(void); +extern int test_nc_get_var1_longlong(void); +extern int test_nc_get_var1_ulonglong(void); + +extern int test_nc_get_vara_double(void); +extern int test_nc_get_vara_float(void); +extern int test_nc_get_vara_int(void); +extern int test_nc_get_vara_long(void); +extern int test_nc_get_vara_schar(void); +extern int test_nc_get_vara_short(void); +extern int test_nc_get_vara_text(void); +extern int test_nc_get_vara_uchar(void); +extern int test_nc_get_vara(void); +extern int test_nc_get_vara_ushort(void); +extern int test_nc_get_vara_uint(void); +extern int test_nc_get_vara_longlong(void); +extern int test_nc_get_vara_ulonglong(void); + +extern int test_nc_get_vars(void); +extern int test_nc_get_vars_double(void); +extern int test_nc_get_vars_float(void); +extern int test_nc_get_vars_int(void); +extern int test_nc_get_vars_long(void); +extern int test_nc_get_vars_schar(void); +extern int test_nc_get_vars_short(void); +extern int test_nc_get_vars_text(void); +extern int test_nc_get_vars_uchar(void); +extern int test_nc_get_vars(void); +extern int test_nc_get_vars_ushort(void); +extern int test_nc_get_vars_uint(void); +extern int test_nc_get_vars_longlong(void); +extern int test_nc_get_vars_ulonglong(void); + +extern int test_nc_get_varm(void); +extern int test_nc_get_varm_double(void); +extern int test_nc_get_varm_float(void); +extern int test_nc_get_varm_int(void); +extern int test_nc_get_varm_long(void); +extern int test_nc_get_varm_schar(void); +extern int test_nc_get_varm_short(void); +extern int test_nc_get_varm_text(void); +extern int test_nc_get_varm_uchar(void); +extern int test_nc_get_varm(void); +extern int test_nc_get_varm_ushort(void); +extern int test_nc_get_varm_uint(void); +extern int test_nc_get_varm_longlong(void); +extern int test_nc_get_varm_ulonglong(void); + +extern int test_nc_get_att(void); +extern int test_nc_get_att_double(void); +extern int test_nc_get_att_float(void); +extern int test_nc_get_att_int(void); +extern int test_nc_get_att_long(void); +extern int test_nc_get_att_schar(void); +extern int test_nc_get_att_short(void); +extern int test_nc_get_att_text(void); +extern int test_nc_get_att_uchar(void); +extern int test_nc_get_att_ushort(void); +extern int test_nc_get_att_uint(void); +extern int test_nc_get_att_longlong(void); +extern int test_nc_get_att_ulonglong(void); + +extern int test_nc_put_att(void); +extern int test_nc_put_var_double(void); +extern int test_nc_put_var_float(void); +extern int test_nc_put_var_int(void); +extern int test_nc_put_var_long(void); +extern int test_nc_put_var_schar(void); +extern int test_nc_put_var_short(void); +extern int test_nc_put_var_text(void); +extern int test_nc_put_var_uchar(void); +extern int test_nc_put_var(void); +extern int test_nc_put_var_ushort(void); +extern int test_nc_put_var_uint(void); +extern int test_nc_put_var_longlong(void); +extern int test_nc_put_var_ulonglong(void); + +extern int test_nc_put_var1_double(void); +extern int test_nc_put_var1_float(void); +extern int test_nc_put_var1_int(void); +extern int test_nc_put_var1_long(void); +extern int test_nc_put_var1_schar(void); +extern int test_nc_put_var1_short(void); +extern int test_nc_put_var1_text(void); +extern int test_nc_put_var1_uchar(void); +extern int test_nc_put_var1(void); +extern int test_nc_put_var1_ushort(void); +extern int test_nc_put_var1_uint(void); +extern int test_nc_put_var1_longlong(void); +extern int test_nc_put_var1_ulonglong(void); + +extern int test_nc_put_vara_double(void); +extern int test_nc_put_vara_float(void); +extern int test_nc_put_vara_int(void); +extern int test_nc_put_vara_long(void); +extern int test_nc_put_vara_schar(void); +extern int test_nc_put_vara_short(void); +extern int test_nc_put_vara_text(void); +extern int test_nc_put_vara_uchar(void); +extern int test_nc_put_vara(void); +extern int test_nc_put_vara_ushort(void); +extern int test_nc_put_vara_uint(void); +extern int test_nc_put_vara_longlong(void); +extern int test_nc_put_vara_ulonglong(void); + +extern int test_nc_put_vars_double(void); +extern int test_nc_put_vars_float(void); +extern int test_nc_put_vars_int(void); +extern int test_nc_put_vars_long(void); +extern int test_nc_put_vars_schar(void); +extern int test_nc_put_vars_short(void); +extern int test_nc_put_vars_text(void); +extern int test_nc_put_vars_uchar(void); +extern int test_nc_put_vars(void); +extern int test_nc_put_vars_ushort(void); +extern int test_nc_put_vars_uint(void); +extern int test_nc_put_vars_longlong(void); +extern int test_nc_put_vars_ulonglong(void); + +extern int test_nc_put_varm_double(void); +extern int test_nc_put_varm_float(void); +extern int test_nc_put_varm_int(void); +extern int test_nc_put_varm_long(void); +extern int test_nc_put_varm_schar(void); +extern int test_nc_put_varm_short(void); +extern int test_nc_put_varm_text(void); +extern int test_nc_put_varm_uchar(void); +extern int test_nc_put_varm(void); +extern int test_nc_put_varm_ushort(void); +extern int test_nc_put_varm_uint(void); +extern int test_nc_put_varm_longlong(void); +extern int test_nc_put_varm_ulonglong(void); + +extern int test_nc_put_att_double(void); +extern int test_nc_put_att_float(void); +extern int test_nc_put_att_int(void); +extern int test_nc_put_att_long(void); +extern int test_nc_put_att_schar(void); +extern int test_nc_put_att_short(void); +extern int test_nc_put_att_text(void); +extern int test_nc_put_att_uchar(void); +extern int test_nc_put_att_ushort(void); +extern int test_nc_put_att_uint(void); +extern int test_nc_put_att_longlong(void); +extern int test_nc_put_att_ulonglong(void); + +extern int test_nc_create(void); +extern int test_nc_redef(void); +extern int test_nc_enddef(void); +extern int test_nc_sync(void); +extern int test_nc_abort(void); +extern int test_nc_def_dim(void); +extern int test_nc_rename_dim(void); +extern int test_nc_def_var(void); +extern int test_nc_rename_var(void); +extern int test_nc_copy_att(void); + +extern int test_nc_inq_att(void); +extern int test_nc_inq_attname(void); +extern int test_nc_inq_attid(void); +extern int test_nc_inq_attlen(void); +extern int test_nc_inq_atttype(void); + +extern int test_nc_rename_att(void); +extern int test_nc_del_att(void); +extern int test_nc_set_fill(void); +extern int test_nc_set_default_format(void); +extern int test_nc_against_pnetcdf(void); void print_nok(int nok); @@ -508,26 +508,28 @@ typedef enum { #define NCT_ULONGLONG NCT_UINT64 } nct_itype; -int inRange3(const double value, const nc_type datatype, const nct_itype itype); +int inRange3(const int cdf_format, const double value, const nc_type datatype, const nct_itype itype); int equal(const double x, const double y, nc_type extType, nct_itype itype); +int equal2(const double x, const double y, nc_type extType); + int int_vec_eq(const int *v1, const int *v2, const int n); -int roll( int n ); +size_t roll( size_t n ); int toMixedBase( size_t number, /* number to be converted to mixed base */ - size_t length, - const size_t base[], /* dimensioned [length], base[0] ignored */ - size_t result[]); /* dimensioned [length] */ + int length, + const size_t base[], /* dimensioned [length], base[0] ignored */ + size_t result[]); /* dimensioned [length] */ size_t fromMixedBase( - size_t length, + int length, size_t number[], /* dimensioned [length] */ - size_t base[]); /* dimensioned [length], base[0] ignored */ + size_t base[]); /* dimensioned [length], base[0] ignored */ int nc2dbl ( const nc_type datatype, const void *p, double *result); @@ -536,6 +538,7 @@ int dbl2nc ( const double d, const nc_type datatype, void *p); double hash( const nc_type type, const int rank, const size_t *index ); double hash4( + const int cdf_format, const nc_type type, const int rank, const size_t *index, @@ -563,8 +566,12 @@ void check_file(char *filename); int file_create(const char *filename, int cmode, int *ncid); +int file__create(const char *filename, int cmode, size_t initialsz, size_t *bufrsizehintp, int *ncid); + int file_open(const char *filename, int omode, int *ncid); +char* nc_err_code_name(int err); + #ifdef __cplusplus } #endif diff --git a/nc_test/tst_atts3.c b/nc_test/tst_atts3.c index 3855e01fed..e5ffc25d3f 100644 --- a/nc_test/tst_atts3.c +++ b/nc_test/tst_atts3.c @@ -136,7 +136,7 @@ main(int argc, char **argv) signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE}; unsigned char uchar_in[ATT_LEN]; short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT}; - int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000}; + int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 127, 100000}; float float_in[ATT_LEN], float_out[ATT_LEN] = {-0.5, 0.25, 0.125}; double double_in[ATT_LEN], double_out[ATT_LEN] = {-0.25, .5, 0.125}; long long longlong_in[ATT_LEN] = {-1LL, -1LL, -1LL}; @@ -211,8 +211,10 @@ main(int argc, char **argv) * supported C types. though the conversion may encounter * out-of-range values */ if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_INT_NAME, uchar_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) + for (i = 0; i < ATT_LEN; i++) { + if (i == 0 || i == 2) continue; if (uchar_in[i] != (unsigned char) int_out[i]) ERR; + } /* This was bug NCF-171: on 32-bit platforms, bad values returned */ if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT_NAME, longlong_in)) ERR; @@ -346,8 +348,10 @@ main(int argc, char **argv) for (i = 0; i < ATT_LEN; i++) if (short_in[i] != short_out[i]) ERR; if (nc_get_att_short(ncid, NC_GLOBAL, ATT_INT_NAME, short_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) + for (i = 0; i < ATT_LEN; i++) { + if (i == 0 || i == 2) continue; if (short_in[i] != (short) int_out[i]) ERR; + } if (nc_get_att_short(ncid, NC_GLOBAL, ATT_FLOAT_NAME, short_in)) ERR; for (i = 0; i < ATT_LEN; i++) if (short_in[i] != (short) float_out[i]) ERR; @@ -360,11 +364,15 @@ main(int argc, char **argv) for (i = 0; i < ATT_LEN; i++) if (schar_in[i] != schar_out[i]) ERR; if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) + for (i = 0; i < ATT_LEN; i++) { + if (i == 0 || i == 2) continue; if (schar_in[i] != (signed char) short_out[i]) ERR; + } if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) + for (i = 0; i < ATT_LEN; i++) { + if (i == 0 || i == 2) continue; if (schar_in[i] != (signed char) int_out[i]) ERR; + } if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR; for (i = 0; i < ATT_LEN; i++) if (schar_in[i] != (signed char) float_out[i]) ERR; @@ -373,22 +381,25 @@ main(int argc, char **argv) if (schar_in[i] != (signed char) double_out[i]) ERR; /* Read all atts (except text) as uchar. */ - /* Shouldn't this get an NC_ERANGE error for storing -128 into an unsigned char? Possible bug ... */ if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, uchar_in)) ERR; for (i = 0; i < ATT_LEN; i++) if (uchar_in[i] != (unsigned char) schar_out[i]) ERR; if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_SHORT_NAME, uchar_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) - if (uchar_in[i] != (unsigned char) short_out[i]) ERR; if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_INT_NAME, uchar_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) + for (i = 0; i < ATT_LEN; i++) { + if (i == 0 || i == 2) continue; if (uchar_in[i] != (unsigned char) int_out[i]) ERR; + } if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, uchar_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) + for (i = 0; i < ATT_LEN; i++) { + if (i == 0) continue; if (uchar_in[i] != (unsigned char) float_out[i]) ERR; + } if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, uchar_in) != NC_ERANGE) ERR; - for (i = 0; i < ATT_LEN; i++) + for (i = 0; i < ATT_LEN; i++) { + if (i == 0) continue; if (uchar_in[i] != (unsigned char) double_out[i]) ERR; + } /* Read all atts (except text) into long long variable. */ if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_SCHAR_NAME, longlong_in)) ERR; diff --git a/nc_test/tst_small.c b/nc_test/tst_small.c index 9d4791ea3e..750baf5a66 100644 --- a/nc_test/tst_small.c +++ b/nc_test/tst_small.c @@ -104,6 +104,7 @@ test_small_atts(const char *testfile) { /* Create null-terminated text string of correct length. */ strncpy(att, source, t); + att[t] = '\0'; /* Create a file with one attribute. */ if (file_create(testfile, NC_CLOBBER, &ncid)) ERR; diff --git a/nc_test/util.c b/nc_test/util.c index 25f0b82343..d7c58d1ae2 100644 --- a/nc_test/util.c +++ b/nc_test/util.c @@ -4,8 +4,9 @@ * $Id: util.c 2792 2014-10-27 06:02:59Z wkliao $ *********************************************************************/ +#include /* floor() */ #include "tests.h" -#include + void print_nok(int nok) { @@ -17,11 +18,9 @@ print_nok(int nok) /* Is value within external type range? */ int -inRange(const double value, const nc_type datatype) +inRange(const double value, const nc_type xtype) { - double min, max; - - switch (datatype) { + switch (xtype) { case NC_CHAR: return value >= X_CHAR_MIN && value <= X_CHAR_MAX; case NC_BYTE: return value >= X_BYTE_MIN && value <= X_BYTE_MAX; case NC_SHORT: return value >= X_SHORT_MIN && value <= X_SHORT_MAX; @@ -34,46 +33,39 @@ inRange(const double value, const nc_type datatype) case NC_INT64: return value >= X_INT64_MIN && value <= X_INT64_MAX; case NC_UINT64: return value >= 0 && value <= X_UINT64_MAX; default: assert(0); + return(0); } - return value >= min && value <= max; -} - -static int -inRange_uchar(const double value, const nc_type datatype) -{ - if (datatype == NC_BYTE) { - return(value >= 0 && value <= 255); - } - /* else */ - return inRange(value, datatype); } static int -inRange_schar(const double value, const nc_type datatype) +inRange_uchar(const int cdf_format, + const double value, + const nc_type xtype) { - /* check value of type datatype if within schar range */ + /* check value of type xtype if within uchar range */ - if (datatype == NC_UBYTE) { + if (cdf_format < NC_FORMAT_CDF5 && xtype == NC_BYTE) { /* netCDF specification make a special case for type conversion between * uchar and scahr: do not check for range error. See - * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion + * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion */ - return(value >= X_CHAR_MIN && value <= X_CHAR_MAX); + return(value >= 0 && value <= 255); + /* this is to ensure value is within the range of uchar */ } /* else */ - return inRange(value, datatype); + return inRange(value, xtype); } static int -inRange_float(const double value, const nc_type datatype) +inRange_float(const double value, const nc_type xtype) { double min, max; - switch (datatype) { - case NC_CHAR: min = X_CHAR_MIN; max = X_CHAR_MAX; break; - case NC_BYTE: min = X_BYTE_MIN; max = X_BYTE_MAX; break; + switch (xtype) { + case NC_CHAR: min = X_CHAR_MIN; max = X_CHAR_MAX; break; + case NC_BYTE: min = X_BYTE_MIN; max = X_BYTE_MAX; break; case NC_SHORT: min = X_SHORT_MIN; max = X_SHORT_MAX; break; - case NC_INT: min = X_INT_MIN; max = X_INT_MAX; break; + case NC_INT: min = X_INT_MIN; max = X_INT_MAX; break; case NC_FLOAT: if(FLT_MAX < X_FLOAT_MAX) { min = (-FLT_MAX); @@ -101,7 +93,7 @@ inRange_float(const double value, const nc_type datatype) } if(!( value >= min && value <= max)) { #if 0 /* DEBUG */ - if(datatype == NC_FLOAT) { + if(xtype == NC_FLOAT) { fprintf(stderr, "\n"); fprintf(stderr, "min % .17e\n", min); fprintf(stderr, "value % .17e\n", value); @@ -113,7 +105,7 @@ inRange_float(const double value, const nc_type datatype) #if FLT_MANT_DIG != DBL_MANT_DIG /* else */ { - const float fvalue = value; + const float fvalue = (float)value; return fvalue >= min && fvalue <= max; } #else @@ -122,24 +114,37 @@ inRange_float(const double value, const nc_type datatype) } /* wrapper for inRange to handle special NC_BYTE/uchar adjustment */ +/* this function checks whether "value" to be casted to type "itype" is + * within the range of external "xtype". + */ int -inRange3( - const double value, - const nc_type datatype, - const nct_itype itype) +inRange3(const int cdf_format, + const double value, + const nc_type xtype, + const nct_itype itype) { + /* netCDF specification make a special case for type conversion between + * uchar and NC_BYTE: do not check for range error. See + * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion + * The _uchar and _schar functions were introduced in netCDF-3 to eliminate + * an ambiguity, and support both signed and unsigned byte data. In + * netCDF-2, whether the external NC_BYTE type represented signed or + * unsigned values was left up to the user. In netcdf-3, we treat NC_BYTE + * as signed for the purposes of conversion to short, int, long, float, or + * double. (Of course, no conversion takes place when the internal type is + * signed char.) In the _uchar functions, we treat NC_BYTE as if it were + * unsigned. Thus, no NC_ERANGE error can occur converting between NC_BYTE + * and unsigned char. + */ switch (itype) { - case NCT_SCHAR: - case NCT_CHAR: - return inRange_schar(value, datatype); - case NCT_UCHAR: - return inRange_uchar(value, datatype); - case NCT_FLOAT: - return inRange_float(value, datatype); - default: - break; + case NCT_UCHAR: + return inRange_uchar(cdf_format, value, xtype); + case NCT_FLOAT: + return inRange_float(value, xtype); + default: + break; } - return inRange(value, datatype); + return inRange(value, xtype); } @@ -148,17 +153,51 @@ inRange3( * Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON. */ int -equal( - const double x, - const double y, - nc_type extType, /* external data type */ - nct_itype itype) +equal(const double x, + const double y, + nc_type xtype, /* external data type */ + nct_itype itype) { const double flt_epsilon = 1.19209290E-07; const double dbl_epsilon = 2.2204460492503131E-16; double epsilon; - epsilon = extType == NC_FLOAT || itype == NCT_FLOAT ? flt_epsilon : dbl_epsilon; + epsilon = xtype == NC_FLOAT || + itype == NCT_FLOAT ? flt_epsilon : dbl_epsilon; + + if (xtype == NC_CHAR && itype == NCT_TEXT) { + /* because in-memory data type char can be signed or unsigned, + * type cast the value from external NC_CHAR before the comparison + */ + char x2 = (char) x; + char y2 = (char) y; + return ABS(x2-y2) <= epsilon * MAX( ABS(x2), ABS(y2)); + } + + return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y)); +} + +/* this function is for the APIs without itype, i.e. xtype == itype */ +int +equal2(const double x, + const double y, + nc_type xtype) /* external data type */ +{ + const double flt_epsilon = 1.19209290E-07; + const double dbl_epsilon = 2.2204460492503131E-16; + double epsilon; + + epsilon = xtype == NC_FLOAT ? flt_epsilon : dbl_epsilon; + + if (xtype == NC_CHAR) { + /* because in-memory data type char can be signed or unsigned, + * type cast the value from external NC_CHAR before the comparison + */ + char x2 = (char) x; + char y2 = (char) y; + return ABS(x2-y2) <= epsilon * MAX( ABS(x2), ABS(y2)); + } + return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y)); } @@ -177,9 +216,9 @@ int_vec_eq(const int *v1, const int *v2, const int n) * Generate random integer from 0 to n-1 * Like throwing an n-sided dice marked 0, 1, 2, ..., n-1 */ -int roll( int n ) +size_t roll( size_t n ) { - int r; + size_t r; do /* @@ -189,7 +228,7 @@ int roll( int n ) * We don't use RAND_MAX here because not all compilation * environments define it (e.g. gcc(1) under SunOS 4.1.4). */ - r = ((rand() % 32768) / 32767.0) * (n - 1) + 0.5; + r = (size_t)(((rand() % 32768) / 32767.0) * (n - 1) + 0.5); while (r >= n); return r; @@ -209,16 +248,15 @@ int roll( int n ) int toMixedBase( size_t number, /* number to be converted to mixed base */ - size_t length, + int length, const size_t base[], /* dimensioned [length], base[0] ignored */ size_t result[]) /* dimensioned [length] */ { - size_t i; + int i; if (length > 0) { for (i = length - 1; i > 0; i--) { - if (base[i] == 0) - return 1; + if (base[i] == 0) return 1; result[i] = number % base[i]; number = number / base[i]; } @@ -238,10 +276,9 @@ toMixedBase( * Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado */ size_t -fromMixedBase( - size_t length, - size_t number[], /* dimensioned [length] */ - size_t base[]) /* dimensioned [length], base[0] ignored */ +fromMixedBase(int length, + size_t number[], /* dimensioned [length] */ + size_t base[]) /* dimensioned [length], base[0] ignored */ { size_t i; size_t result = 0; @@ -257,30 +294,30 @@ fromMixedBase( /* Convert any nc_type to double */ -int nc2dbl ( const nc_type datatype, const void *p, double *result) +int nc2dbl ( const nc_type xtype, const void *p, double *result) { if ( ! p ) return 2; if ( ! result ) return 3; - switch (datatype) { - case NC_BYTE: *result = *((signed char *) p); break; - case NC_CHAR: *result = *((signed char *) p); break; - case NC_SHORT: *result = *((short *) p); break; + switch (xtype) { + case NC_CHAR: *result = *((char *) p); break; + case NC_BYTE: *result = *((signed char *) p); break; + case NC_UBYTE: *result = *((unsigned char *) p); break; + case NC_SHORT: *result = *((short *) p); break; + case NC_USHORT: *result = *((unsigned short *) p); break; case NC_INT: #if INT_MAX >= X_INT_MAX *result = *((int *) p); break; #else *result = *((long *) p); break; #endif - case NC_FLOAT: *result = *((float *) p); break; - case NC_DOUBLE: *result = *((double *) p); break; - case NC_UBYTE: *result = *((unsigned char *) p); break; - case NC_USHORT: *result = *((unsigned short *) p); break; case NC_UINT: #if UINT_MAX >= X_UINT_MAX *result = *((unsigned int *) p); break; #else *result = *((unsigned long *) p); break; #endif + case NC_FLOAT: *result = *((float *) p); break; + case NC_DOUBLE: *result = *((double *) p); break; case NC_INT64: *result = *((long long *) p); break; case NC_UINT64: *result = *((unsigned long long *) p); break; default: return 1; @@ -290,83 +327,86 @@ int nc2dbl ( const nc_type datatype, const void *p, double *result) /* Convert double to any nc_type */ -int dbl2nc ( const double d, const nc_type datatype, void *p) +int dbl2nc ( const double d, const nc_type xtype, void *p) { double r; /* rounded value */ - if (p) { - switch (datatype) { - case NC_BYTE: - r = floor(0.5+d); - if ( r < schar_min || r > schar_max ) return 2; - *((signed char *) p) = r; - break; - case NC_CHAR: - r = floor(0.5+d); - if ( r < text_min || r > text_max ) return 2; -#ifndef __CHAR_UNSIGNED__ - *((char *) p) = r; -#else - *((signed char*) p) = r; -#endif - break; - case NC_SHORT: - r = floor(0.5+d); - if ( r < short_min || r > short_max ) return 2; - *((short *) p) = r; - break; - case NC_INT: - r = floor(0.5+d); - if ( r < long_min || r > long_max ) return 2; -#if INT_MAX >= X_INT_MAX - *((int *) p) = r; + if (p == NULL) return 1; + switch (xtype) { + case NC_CHAR: + r = floor(0.5+d); + /* d is obtained from hash() which may be set to X_CHAR_MIN (0) + * or X_CHAR_MAX (255). When in-memory data type char is signed + * (i.e. ranged from -128 to 127), we should still allow a type + * cast a unsigned value > 127 to a signed char without + * reporting it as a range error. + */ + if ( r < X_CHAR_MIN || r > X_CHAR_MAX ) return 2; +#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0 + *((signed char*) p) = (signed char)r; #else - *((long *) p) = r; + *((char *) p) = (char)r; #endif - break; - case NC_FLOAT: - if ( fabs(d) > float_max ) return 2; - *((float *) p) = d; - break; - case NC_DOUBLE: - *((double *) p) = d; - break; + break; + case NC_BYTE: + r = floor(0.5+d); + if ( r < schar_min || r > schar_max ) return 2; + *((signed char *) p) = (signed char)r; + break; case NC_UBYTE: r = floor(0.5+d); if ( r < 0.0 || r > uchar_max ) return 2; - *((unsigned char *) p) = r; + *((unsigned char *) p) = (unsigned char)r; + break; + case NC_SHORT: + r = floor(0.5+d); + if ( r < short_min || r > short_max ) return 2; + *((short *) p) = (short)r; break; case NC_USHORT: r = floor(0.5+d); if ( r < 0.0 || r > ushort_max ) return 2; - *((unsigned short *) p) = r; + *((unsigned short *) p) = (unsigned short)r; + break; + case NC_INT: + r = floor(0.5+d); + if ( r < long_min || r > long_max ) return 2; +#if INT_MAX >= X_INT_MAX + *((int *) p) = (int)r; +#else + *((long *) p) = (long)r; +#endif break; case NC_UINT: r = floor(0.5+d); if ( r < 0.0 || r > uint_max ) return 2; #if UINT_MAX >= X_UINT_MAX - *((unsigned int *) p) = r; + *((unsigned int *) p) = (unsigned int)r; #else - *((unsigned long *) p) = r; + *((unsigned long *) p) = (unsigned long)r; #endif break; + case NC_FLOAT: + if ( fabs(d) > float_max ) return 2; + *((float *) p) = (float)d; + break; + case NC_DOUBLE: + *((double *) p) = (double)d; + break; case NC_INT64: r = floor(0.5+d); if ( r < int64_min || r > int64_max ) return 2; - *((long long *) p) = r; + *((long long *) p) = (long long)r; break; case NC_UINT64: r = floor(0.5+d); if ( r < 0.0 || r > uint64_max ) return 2; - *((unsigned long long *) p) = r; + *((unsigned long long *) p) = (unsigned long long)r; break; - default: - return 1; - } - return 0; - } else { - return 1; + default: + return 1; } + return 0; } #define FUZZ (1.19209290E-07) @@ -374,7 +414,7 @@ int dbl2nc ( const double d, const nc_type datatype, void *p) #ifdef USE_EXTREME_NUMBERS /* Generate data values as function of type, rank (-1 for attribute), index */ double -hash( const nc_type type, const int rank, const size_t *index ) +hash( const nc_type xtype, const int rank, const size_t *index ) { double base; double result; @@ -385,11 +425,11 @@ hash( const nc_type type, const int rank, const size_t *index ) if (abs(rank) == 1 && index[0] <= 3) { switch (index[0]) { case 0: - switch (type) { + switch (xtype) { case NC_CHAR: return X_CHAR_MIN; case NC_BYTE: return X_BYTE_MIN; case NC_SHORT: return X_SHORT_MIN; - case NC_INT: return X_INT_MIN; + case NC_INT: return X_INT_MIN; case NC_FLOAT: return X_FLOAT_MIN; case NC_DOUBLE: return X_DOUBLE_MIN; case NC_UBYTE: return 0; @@ -401,11 +441,11 @@ hash( const nc_type type, const int rank, const size_t *index ) default: assert(0); } case 1: - switch (type) { + switch (xtype) { case NC_CHAR: return X_CHAR_MAX; case NC_BYTE: return X_BYTE_MAX; case NC_SHORT: return X_SHORT_MAX; - case NC_INT: return X_INT_MAX; + case NC_INT: return X_INT_MAX; case NC_FLOAT: return X_FLOAT_MAX; case NC_DOUBLE: return X_DOUBLE_MAX; case NC_UBYTE: return X_UCHAR_MAX; @@ -418,11 +458,11 @@ hash( const nc_type type, const int rank, const size_t *index ) default: assert(0); } case 2: - switch (type) { + switch (xtype) { case NC_CHAR: return 'A'; case NC_BYTE: return X_BYTE_MIN-1.0; case NC_SHORT: return X_SHORT_MIN-1.0; - case NC_INT: return X_INT_MIN-1.0; + case NC_INT: return X_INT_MIN-1.0; case NC_FLOAT: return X_FLOAT_MIN * (1.0 + FUZZ); case NC_DOUBLE: return -1.0; case NC_UBYTE: return -1.0; @@ -433,11 +473,11 @@ hash( const nc_type type, const int rank, const size_t *index ) default: assert(0); } case 3: - switch (type) { + switch (xtype) { case NC_CHAR: return 'Z'; case NC_BYTE: return X_BYTE_MAX+1.0; case NC_SHORT: return X_SHORT_MAX+1.0; - case NC_INT: return X_INT_MAX+1.0; + case NC_INT: return X_INT_MAX+1.0; case NC_FLOAT: return X_FLOAT_MAX * (1.0 + FUZZ); case NC_DOUBLE: return 1.0; case NC_UBYTE: return X_UCHAR_MAX +1.0; @@ -449,12 +489,12 @@ hash( const nc_type type, const int rank, const size_t *index ) } } } else { - switch (type) { - case NC_CHAR: base = 2; break; - case NC_BYTE: base = -2; break; - case NC_SHORT: base = -5; break; - case NC_INT: base = -20; break; - case NC_FLOAT: base = -9; break; + switch (xtype) { + case NC_CHAR: base = 2; break; + case NC_BYTE: base = -2; break; + case NC_SHORT: base = -5; break; + case NC_INT: base = -20; break; + case NC_FLOAT: base = -9; break; case NC_DOUBLE: base = -10; break; /* not sure what right values are */ @@ -479,7 +519,7 @@ hash( const nc_type type, const int rank, const size_t *index ) /* Generate data values as function of type, rank (-1 for attribute), index */ double -hash( const nc_type type, const int rank, const size_t *index ) +hash( const nc_type xtype, const int rank, const size_t *index ) { double base; double result; @@ -490,7 +530,7 @@ hash( const nc_type type, const int rank, const size_t *index ) if (abs(rank) == 1 && index[0] <= 3) { switch (index[0]) { case 0: - switch (type) { + switch (xtype) { case NC_CHAR: return X_CHAR_MIN; case NC_BYTE: return X_BYTE_MIN; case NC_SHORT: return SANE_SHORT; @@ -506,7 +546,7 @@ hash( const nc_type type, const int rank, const size_t *index ) default: assert(0); } case 1: - switch (type) { + switch (xtype) { case NC_CHAR: return X_CHAR_MAX; case NC_BYTE: return X_BYTE_MAX; case NC_SHORT: return SANE_SHORT; @@ -523,7 +563,7 @@ hash( const nc_type type, const int rank, const size_t *index ) default: assert(0); } case 2: - switch (type) { + switch (xtype) { case NC_CHAR: return 'A'; case NC_BYTE: return X_BYTE_MIN-1.0; case NC_SHORT: return SANE_SHORT-1.0; @@ -538,7 +578,7 @@ hash( const nc_type type, const int rank, const size_t *index ) default: assert(0); } case 3: - switch (type) { + switch (xtype) { case NC_CHAR: return 'Z'; case NC_BYTE: return X_BYTE_MAX+1.0; case NC_SHORT: return SANE_SHORT+1.0; @@ -554,7 +594,7 @@ hash( const nc_type type, const int rank, const size_t *index ) } } } else { - switch (type) { + switch (xtype) { case NC_CHAR: base = 2; break; case NC_BYTE: base = -2; break; case NC_SHORT: base = -5; break; @@ -579,17 +619,34 @@ hash( const nc_type type, const int rank, const size_t *index ) #endif /* wrapper for hash to handle special NC_BYTE/uchar adjustment */ double -hash4( - const nc_type type, - const int rank, - const size_t *index, - const nct_itype itype) +hash4(const int cdf_format, + const nc_type xtype, + const int rank, + const size_t *index, + const nct_itype itype) { double result; - result = hash( type, rank, index ); - if (itype == NCT_UCHAR && type == NC_BYTE && result >= -128 && result < 0) + result = hash( xtype, rank, index ); + + /* netCDF specification make a special case for type conversion between + * uchar and NC_BYTE: do not check for range error. See + * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion + * The _uchar and _schar functions were introduced in netCDF-3 to eliminate + * an ambiguity, and support both signed and unsigned byte data. In + * netCDF-2, whether the external NC_BYTE type represented signed or + * unsigned values was left up to the user. In netcdf-3, we treat NC_BYTE + * as signed for the purposes of conversion to short, int, long, float, or + * double. (Of course, no conversion takes place when the internal type is + * signed char.) In the _uchar functions, we treat NC_BYTE as if it were + * unsigned. Thus, no NC_ERANGE error can occur converting between NC_BYTE + * and unsigned char. + */ + if (cdf_format < NC_FORMAT_CDF5 && + itype == NCT_UCHAR && xtype == NC_BYTE && + result >= -128 && result < 0) result += 256; + return result; } @@ -641,7 +698,7 @@ init_gatts(const char *type_letter) } static size_t -product(size_t nn, const size_t *sp) +product(int nn, const size_t *sp) { size_t result = 1; while(nn-- > 0) @@ -669,7 +726,7 @@ init_gvars (void) */ const char digit[] = "r123456789"; - size_t rank; + int rank; int vn; /* var number */ int xtype; /* index of type */ int an; /* attribute number */ @@ -685,7 +742,7 @@ init_gvars (void) { /* number variables of a type and rank */ const size_t nvars = product(rank, max_dim_len); - int jj; + size_t jj; for (jj = 0; jj < nvars; jj++) { @@ -781,13 +838,13 @@ put_atts(int ncid) int j; /* index of attribute */ int allInRange; double att[MAX_NELS]; - signed char catt[MAX_NELS]; + char catt[MAX_NELS]; for (i = -1; i < numVars; i++) { for (j = 0; j < NATTS(i); j++) { if (ATT_TYPE(i,j) == NC_CHAR) { for (k = 0; k < ATT_LEN(i,j); k++) { - catt[k] = hash(ATT_TYPE(i,j), -1, &k); + catt[k] = (char) hash(ATT_TYPE(i,j), -1, &k); } err = nc_put_att_text(ncid, i, ATT_NAME(i,j), ATT_LEN(i,j), catt); @@ -822,7 +879,7 @@ put_vars(int ncid) int i; size_t j; double value[MAX_NELS]; - signed char text[MAX_NELS]; + char text[MAX_NELS]; int allInRange; for (j = 0; j < MAX_RANK; j++) @@ -832,7 +889,7 @@ put_vars(int ncid) err = toMixedBase(j, var_rank[i], var_shape[i], index); IF (err) error("toMixedBase"); if (var_name[i][0] == 'c') { - text[j] = hash(var_type[i], var_rank[i], index); + text[j] = (char) hash(var_type[i], var_rank[i], index); } else { value[j] = hash(var_type[i], var_rank[i], index); allInRange = allInRange && inRange(value[j], var_type[i]); @@ -922,28 +979,23 @@ void check_vars(int ncid) { size_t index[MAX_RANK]; - int err; /* status */ - int i; + char text, name[NC_MAX_NAME]; + int i, err; /* status */ size_t j; - signed char text; - double value; - nc_type datatype; - int ndims; - int dimids[MAX_RANK]; - int isChar; - double expect; - char name[NC_MAX_NAME]; - size_t length; int nok = 0; /* count of valid comparisons */ + int isChar, ndims, dimids[MAX_RANK]; + double value, expect; + nc_type xtype; + size_t length; for (i = 0; i < numVars; i++) { isChar = var_type[i] == NC_CHAR; - err = nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL); + err = nc_inq_var(ncid, i, name, &xtype, &ndims, dimids, NULL); IF (err) error("nc_inq_var: %s", nc_strerror(err)); IF (strcmp(name, var_name[i]) != 0) error("Unexpected var_name"); - IF (datatype != var_type[i]) + IF (xtype != var_type[i]) error("Unexpected type"); IF (ndims != var_rank[i]) error("Unexpected rank"); @@ -960,18 +1012,14 @@ check_vars(int ncid) error("error in toMixedBase 2"); expect = hash( var_type[i], var_rank[i], index ); if (isChar) { - err = nc_get_var1_text(ncid, i, index, &text); - IF (err) + err = nc_get_var1_text(ncid, i, index, &text); + IF (err) error("nc_get_var1_text: %s", nc_strerror(err)); - IF (text != expect) { - error("Var %s value read 0x%02x not that expected 0x%02x ", - var_name[i], text, (char)expect); - print_n_size_t(var_rank[i], index); + IF (text != (char)expect) { + error("Var %s [%lu] value read %hhd not that expected %g ", + var_name[i], j, text, expect); + print_n_size_t(var_rank[i], index); } else { -#if 0 - print("\nOk %s ", var_name[i]); - print_n_size_t(var_rank[i], index); -#endif nok++; } } else { @@ -981,16 +1029,10 @@ check_vars(int ncid) error("nc_get_var1_double: %s", nc_strerror(err)); } else { IF (!equal(value,expect,var_type[i], NCT_DOUBLE)) { - value = 0; - err = nc_get_var1_double(ncid, i, index, &value); - error("Var %s value read % 12.5e not that expected % 12.7e ", - var_name[i], value, expect); + error("Var %s [%lu] value read %g not that expected %g ", + var_name[i], j, value, expect); print_n_size_t(var_rank[i], index); } else { -#if 0 - print("\nOk %s ", var_name[i]); - print_n_size_t(var_rank[i], index); -#endif nok++; } } @@ -1012,10 +1054,10 @@ check_atts(int ncid) int i; int j; size_t k; - nc_type datatype; + nc_type xtype; char name[NC_MAX_NAME]; size_t length; - signed char text[MAX_NELS]; + char text[MAX_NELS]; double value[MAX_NELS]; double expect; int nok = 0; /* count of valid comparisons */ @@ -1027,28 +1069,29 @@ check_atts(int ncid) error("nc_inq_attname: %s", nc_strerror(err)); IF (strcmp(name, ATT_NAME(i,j)) != 0) error("nc_inq_attname: unexpected name"); - err = nc_inq_att(ncid, i, name, &datatype, &length); + err = nc_inq_att(ncid, i, name, &xtype, &length); IF (err) error("nc_inq_att: %s", nc_strerror(err)); - IF (datatype != ATT_TYPE(i,j)) + IF (xtype != ATT_TYPE(i,j)) error("nc_inq_att: unexpected type"); IF (length != ATT_LEN(i,j)) error("nc_inq_att: unexpected length"); - if (datatype == NC_CHAR) { + if (xtype == NC_CHAR) { err = nc_get_att_text(ncid, i, name, text); IF (err) error("nc_get_att_text: %s", nc_strerror(err)); for (k = 0; k < ATT_LEN(i,j); k++) { - IF (text[k] != hash(datatype, -1, &k)) { + expect = hash(xtype, -1, &k); + IF (text[k] != (char)expect) { error("nc_get_att_text: unexpected value"); - } else { - nok++; - } + } else { + nok++; + } } } else { err = nc_get_att_double(ncid, i, name, value); for (k = 0; k < ATT_LEN(i,j); k++) { - expect = hash(datatype, -1, &k); + expect = hash(xtype, -1, &k); if (inRange(expect,ATT_TYPE(i,j))) { IF (err) error("nc_get_att_double: %s", nc_strerror(err)); @@ -1088,9 +1131,9 @@ check_file(char *filename) /* TODO: Maybe this function belongs in the netcdf library. */ const char * -s_nc_type(nc_type type) +s_nc_type(nc_type xtype) { - switch((int)type){ + switch((int)xtype){ case NC_CHAR: return "NC_CHAR"; case NC_BYTE: return "NC_BYTE"; case NC_UBYTE: return "NC_UBYTE"; @@ -1111,13 +1154,13 @@ int file_create(const char *filename, int cmode, int *ncid) { int err; +#ifdef USE_PNETCDF /* get the default file format */ int default_format; nc_set_default_format(NC_FORMAT_CLASSIC, &default_format); /* set it back to the default */ nc_set_default_format(default_format, NULL); -#ifdef USE_PNETCDF if (default_format == NC_FORMAT_CLASSIC || default_format == NC_FORMAT_64BIT_OFFSET || default_format == NC_FORMAT_64BIT_DATA) @@ -1129,17 +1172,43 @@ int file_create(const char *filename, int cmode, int *ncid) return err; } -int file_open(const char *filename, int omode, int *ncid) +int file__create(const char *filename, + int cmode, + size_t initialsz, + size_t *bufrsizehintp, + int *ncid) { int err; +#ifdef USE_PNETCDF /* get the default file format */ int default_format; err = nc_set_default_format(NC_FORMAT_CLASSIC, &default_format); /* set it back to the default */ err = nc_set_default_format(default_format, NULL); + if (default_format == NC_FORMAT_CLASSIC || + default_format == NC_FORMAT_64BIT_OFFSET || + default_format == NC_FORMAT_64BIT_DATA) + err = nc_create_par(filename, cmode|NC_PNETCDF, MPI_COMM_WORLD, MPI_INFO_NULL, ncid); + else +#endif + err = nc__create(filename, cmode, initialsz, bufrsizehintp, ncid); + + return err; +} + +int file_open(const char *filename, int omode, int *ncid) +{ + int err; + #ifdef USE_PNETCDF + /* get the default file format */ + int default_format; + err = nc_set_default_format(NC_FORMAT_CLASSIC, &default_format); + /* set it back to the default */ + err = nc_set_default_format(default_format, NULL); + if (default_format == NC_FORMAT_CLASSIC || default_format == NC_FORMAT_64BIT_OFFSET || default_format == NC_FORMAT_64BIT_DATA) @@ -1150,3 +1219,241 @@ int file_open(const char *filename, int omode, int *ncid) return err; } + + +#ifdef USE_PNETCDF +#include /* to include PnetCDF error codes */ +#endif + +char* nc_err_code_name(int err) +{ + static char unknown_str[32]; + + if (err > 0) { /* system error */ + const char *cp = (const char *) strerror(err); + if (cp == NULL) + sprintf(unknown_str,"Unknown error code %d",err); + else + sprintf(unknown_str,"Error code %d (%s)",err,cp); + return unknown_str; + } + + switch (err) { + case (NC_NOERR): return "NC_NOERR"; + case (NC_EBADID): return "NC_EBADID"; + case (NC_ENFILE): return "NC_ENFILE"; + case (NC_EEXIST): return "NC_EEXIST"; + case (NC_EINVAL): return "NC_EINVAL"; + case (NC_EPERM): return "NC_EPERM"; + case (NC_ENOTINDEFINE): return "NC_ENOTINDEFINE"; + case (NC_EINDEFINE): return "NC_EINDEFINE"; + case (NC_EINVALCOORDS): return "NC_EINVALCOORDS"; + case (NC_EMAXDIMS): return "NC_EMAXDIMS"; + case (NC_ENAMEINUSE): return "NC_ENAMEINUSE"; + case (NC_ENOTATT): return "NC_ENOTATT"; + case (NC_EMAXATTS): return "NC_EMAXATTS"; + case (NC_EBADTYPE): return "NC_EBADTYPE"; + case (NC_EBADDIM): return "NC_EBADDIM"; + case (NC_EUNLIMPOS): return "NC_EUNLIMPOS"; + case (NC_EMAXVARS): return "NC_EMAXVARS"; + case (NC_ENOTVAR): return "NC_ENOTVAR"; + case (NC_EGLOBAL): return "NC_EGLOBAL"; + case (NC_ENOTNC): return "NC_ENOTNC"; + case (NC_ESTS): return "NC_ESTS"; + case (NC_EMAXNAME): return "NC_EMAXNAME"; + case (NC_EUNLIMIT): return "NC_EUNLIMIT"; + case (NC_ENORECVARS): return "NC_ENORECVARS"; + case (NC_ECHAR): return "NC_ECHAR"; + case (NC_EEDGE): return "NC_EEDGE"; + case (NC_ESTRIDE): return "NC_ESTRIDE"; + case (NC_EBADNAME): return "NC_EBADNAME"; + case (NC_ERANGE): return "NC_ERANGE"; + case (NC_ENOMEM): return "NC_ENOMEM"; + case (NC_EVARSIZE): return "NC_EVARSIZE"; + case (NC_EDIMSIZE): return "NC_EDIMSIZE"; + case (NC_ETRUNC): return "NC_ETRUNC"; + case (NC_EAXISTYPE): return "NC_EAXISTYPE"; + case (NC_EDAP): return "NC_EDAP"; + case (NC_ECURL): return "NC_ECURL"; + case (NC_EIO): return "NC_EIO"; + case (NC_ENODATA): return "NC_ENODATA"; + case (NC_EDAPSVC): return "NC_EDAPSVC"; + case (NC_EDAS): return "NC_EDAS"; + case (NC_EDDS): return "NC_EDDS"; + case (NC_EDATADDS): return "NC_EDATADDS"; + case (NC_EDAPURL): return "NC_EDAPURL"; + case (NC_EDAPCONSTRAINT): return "NC_EDAPCONSTRAINT"; + case (NC_ETRANSLATION): return "NC_ETRANSLATION"; + case (NC_EACCESS): return "NC_EACCESS"; + case (NC_EAUTH): return "NC_EAUTH"; + case (NC_ENOTFOUND): return "NC_ENOTFOUND"; + case (NC_ECANTREMOVE): return "NC_ECANTREMOVE"; + case (NC_EHDFERR): return "NC_EHDFERR"; + case (NC_ECANTREAD): return "NC_ECANTREAD"; + case (NC_ECANTWRITE): return "NC_ECANTWRITE"; + case (NC_ECANTCREATE): return "NC_ECANTCREATE"; + case (NC_EFILEMETA): return "NC_EFILEMETA"; + case (NC_EDIMMETA): return "NC_EDIMMETA"; + case (NC_EATTMETA): return "NC_EATTMETA"; + case (NC_EVARMETA): return "NC_EVARMETA"; + case (NC_ENOCOMPOUND): return "NC_ENOCOMPOUND"; + case (NC_EATTEXISTS): return "NC_EATTEXISTS"; + case (NC_ENOTNC4): return "NC_ENOTNC4"; + case (NC_ESTRICTNC3): return "NC_ESTRICTNC3"; + case (NC_ENOTNC3): return "NC_ENOTNC3"; + case (NC_ENOPAR): return "NC_ENOPAR"; + case (NC_EPARINIT): return "NC_EPARINIT"; + case (NC_EBADGRPID): return "NC_EBADGRPID"; + case (NC_EBADTYPID): return "NC_EBADTYPID"; + case (NC_ETYPDEFINED): return "NC_ETYPDEFINED"; + case (NC_EBADFIELD): return "NC_EBADFIELD"; + case (NC_EBADCLASS): return "NC_EBADCLASS"; + case (NC_EMAPTYPE): return "NC_EMAPTYPE"; + case (NC_ELATEFILL): return "NC_ELATEFILL"; + case (NC_ELATEDEF): return "NC_ELATEDEF"; + case (NC_EDIMSCALE): return "NC_EDIMSCALE"; + case (NC_ENOGRP): return "NC_ENOGRP"; + case (NC_ESTORAGE): return "NC_ESTORAGE"; + case (NC_EBADCHUNK): return "NC_EBADCHUNK"; + case (NC_ENOTBUILT): return "NC_ENOTBUILT"; + case (NC_EDISKLESS): return "NC_EDISKLESS"; + case (NC_ECANTEXTEND): return "NC_ECANTEXTEND"; + case (NC_EMPI): return "NC_EMPI"; + // case (NC_EURL): return "NC_EURL"; + // case (NC_ECONSTRAINT): return "NC_ECONSTRAINT"; +#ifdef USE_PNETCDF + case (NC_ESMALL): return "NC_ESMALL"; + case (NC_ENOTINDEP): return "NC_ENOTINDEP"; + case (NC_EINDEP): return "NC_EINDEP"; + case (NC_EFILE): return "NC_EFILE"; + case (NC_EREAD): return "NC_EREAD"; + case (NC_EWRITE): return "NC_EWRITE"; + case (NC_EOFILE): return "NC_EOFILE"; + case (NC_EMULTITYPES): return "NC_EMULTITYPES"; + case (NC_EIOMISMATCH): return "NC_EIOMISMATCH"; + case (NC_ENEGATIVECNT): return "NC_ENEGATIVECNT"; + case (NC_EUNSPTETYPE): return "NC_EUNSPTETYPE"; + case (NC_EINVAL_REQUEST): return "NC_EINVAL_REQUEST"; + case (NC_EAINT_TOO_SMALL): return "NC_EAINT_TOO_SMALL"; + case (NC_ENOENT): return "NC_ENOENT"; +#ifdef NC_EMULTIDEFINE + case (NC_EMULTIDEFINE): return "NC_EMULTIDEFINE"; +#endif +#if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=3 + case (NC_ENOTSUPPORT): return "NC_ENOTSUPPORT"; + case (NC_ENULLBUF): return "NC_ENULLBUF"; + case (NC_EPREVATTACHBUF): return "NC_EPREVATTACHBUF"; + case (NC_ENULLABUF): return "NC_ENULLABUF"; + case (NC_EPENDINGBPUT): return "NC_EPENDINGBPUT"; + case (NC_EINSUFFBUF): return "NC_EINSUFFBUF"; +#endif +#if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=4 + case (NC_EINTOVERFLOW): return "NC_EINTOVERFLOW"; + case (NC_EMULTIDEFINE_OMODE): return "NC_EMULTIDEFINE_OMODE"; + case (NC_EMULTIDEFINE_DIM_NUM): return "NC_EMULTIDEFINE_DIM_NUM"; + case (NC_EMULTIDEFINE_DIM_SIZE): return "NC_EMULTIDEFINE_DIM_SIZE"; + case (NC_EMULTIDEFINE_DIM_NAME): return "NC_EMULTIDEFINE_DIM_NAME"; + case (NC_EMULTIDEFINE_VAR_NUM): return "NC_EMULTIDEFINE_VAR_NUM"; + case (NC_EMULTIDEFINE_VAR_NAME): return "NC_EMULTIDEFINE_VAR_NAME"; + case (NC_EMULTIDEFINE_VAR_NDIMS): return "NC_EMULTIDEFINE_VAR_NDIMS"; + case (NC_EMULTIDEFINE_VAR_DIMIDS): return "NC_EMULTIDEFINE_VAR_DIMIDS"; + case (NC_EMULTIDEFINE_VAR_TYPE): return "NC_EMULTIDEFINE_VAR_TYPE"; + case (NC_EMULTIDEFINE_VAR_LEN): return "NC_EMULTIDEFINE_VAR_LEN"; + case (NC_EMULTIDEFINE_NUMRECS): return "NC_EMULTIDEFINE_NUMRECS"; + case (NC_EMULTIDEFINE_VAR_BEGIN): return "NC_EMULTIDEFINE_VAR_BEGIN"; + case (NC_EMULTIDEFINE_ATTR_NUM): return "NC_EMULTIDEFINE_ATTR_NUM"; + case (NC_EMULTIDEFINE_ATTR_SIZE): return "NC_EMULTIDEFINE_ATTR_SIZE"; + case (NC_EMULTIDEFINE_ATTR_NAME): return "NC_EMULTIDEFINE_ATTR_NAME"; + case (NC_EMULTIDEFINE_ATTR_TYPE): return "NC_EMULTIDEFINE_ATTR_TYPE"; + case (NC_EMULTIDEFINE_ATTR_LEN): return "NC_EMULTIDEFINE_ATTR_LEN"; + case (NC_EMULTIDEFINE_ATTR_VAL): return "NC_EMULTIDEFINE_ATTR_VAL"; +#endif +#if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=5 + case (NC_ENOTENABLED): return "NC_ENOTENABLED"; + case (NC_EBAD_FILE): return "NC_EBAD_FILE"; + case (NC_ENO_SPACE): return "NC_ENO_SPACE"; + case (NC_EQUOTA): return "NC_EQUOTA"; + case (NC_EMULTIDEFINE_FNC_ARGS): return "NC_EMULTIDEFINE_FNC_ARGS"; +#endif +#if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=6 + case (NC_EINVAL_CMODE): return "NC_EINVAL_CMODE"; + case (NC_ENULLSTART): return "NC_ENULLSTART"; + case (NC_ENULLCOUNT): return "NC_ENULLCOUNT"; + case (NC_ETYPESIZE_MISMATCH): return "NC_ETYPESIZE_MISMATCH"; + case (NC_ETYPESIZE): return "NC_ETYPESIZE"; + case (NC_ETYPE_MISMATCH): return "NC_ETYPE_MISMATCH"; + case (NC_ESTRICTCDF2): return "NC_ESTRICTCDF2"; +#endif +#if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=7 + case (NC_ENOTRECVAR): return "NC_ENOTRECVAR"; + case (NC_ENOTFILL): return "NC_ENOTFILL"; + case (NC_EMULTIDEFINE_FILL_MODE): return "NC_EMULTIDEFINE_FILL_MODE"; + case (NC_EMULTIDEFINE_VAR_FILL_MODE): return "NC_EMULTIDEFINE_VAR_FILL_MODE"; + case (NC_EMULTIDEFINE_VAR_FILL_VALUE): return "NC_EMULTIDEFINE_VAR_FILL_VALUE"; +#endif +#if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=8 + case (NC_EPENDING): return "NC_EPENDING"; + case (NC_EINVAL_OMODE): return "NC_EINVAL_OMODE"; + case (NC_EMULTIDEFINE_CMODE): return "NC_EMULTIDEFINE_CMODE"; +#endif +#endif + default: + sprintf(unknown_str,"Unknown code %d",err); + } + return unknown_str; +} + + +int +test_nc_against_pnetcdf(void) +{ +#ifdef USE_PNETCDF + int ncid; /* netCDF id */ + int err; /* status */ + + /* Using netCDF library to create file */ + err = nc_create(scratch, NC_CLOBBER, &ncid); + IF (err != NC_NOERR) error("nc_create: %s", nc_strerror(err)); + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + err = nc_enddef(ncid); + IF (err != NC_NOERR) error("nc_enddef: %s", nc_strerror(err)); + put_vars(ncid); + err = nc_close (ncid); + IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err)); + + /* Using PnetCDF library to check file */ + err = nc_open_par(scratch, NC_NOWRITE|NC_PNETCDF, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid); + IF (err != NC_NOERR) error("nc_open_par: %s", nc_strerror(err)); + check_dims(ncid); + check_vars(ncid); + check_atts(ncid); + err = nc_close (ncid); + IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err)); + + /* Using PnetCDF library to create file */ + err = nc_create_par(scratch, NC_PNETCDF, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid); + IF (err != NC_NOERR) error("nc_create_par: %s", nc_strerror(err)); + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + err = nc_enddef(ncid); + IF (err != NC_NOERR) error("nc_enddef: %s", nc_strerror(err)); + put_vars(ncid); + err = nc_close (ncid); + IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err)); + + /* Using NetCDF library to check file */ + err = nc_open(scratch, NC_NOWRITE, &ncid); + IF (err != NC_NOERR) error("nc_open: %s", nc_strerror(err)); + check_dims(ncid); + check_vars(ncid); + check_atts(ncid); + err = nc_close (ncid); + IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err)); + err = nc_delete(scratch); + IF (err != NC_NOERR) error("remove of %s failed", scratch); +#endif + return 1; +} diff --git a/nc_test4/tst_converts.c b/nc_test4/tst_converts.c index e0e3deb464..183da06de0 100644 --- a/nc_test4/tst_converts.c +++ b/nc_test4/tst_converts.c @@ -70,8 +70,12 @@ create_file(int format, unsigned char *uchar_out) if (nc_def_var(ncid, VAR1_NAME, NC_BYTE, 1, dimids, &varid)) ERR; if (nc_enddef(ncid)) ERR; retval = nc_put_var_uchar(ncid, varid, uchar_out); - if ((format != NC_FORMAT_NETCDF4) && retval) ERR; - if ((format == NC_FORMAT_NETCDF4) && (retval != NC_ERANGE)) ERR; + if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_64BIT_DATA) + { + if (retval != NC_ERANGE) ERR; + } + else if (retval != NC_NOERR) ERR; + if (nc_close(ncid)) ERR; return NC_NOERR; } @@ -105,7 +109,7 @@ check_file(int format, unsigned char *uchar_out) * because range errors are not generated for byte type * conversions. */ res = nc_get_var_uchar(ncid, 0, uchar_in); - if (format == NC_FORMAT_NETCDF4) + if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_64BIT_DATA) { if (res != NC_ERANGE) ERR; } diff --git a/nc_test4/tst_files.c b/nc_test4/tst_files.c index 5b949a9bec..1fe342c805 100644 --- a/nc_test4/tst_files.c +++ b/nc_test4/tst_files.c @@ -502,8 +502,11 @@ test_redef(int format) /* Add att. */ ret = nc_put_att_uchar(ncid, NC_GLOBAL, REDEF_ATT3_NAME, NC_BYTE, 1, &uchar_out); - if (format != NC_FORMAT_NETCDF4 && ret) ERR; - else if (format == NC_FORMAT_NETCDF4 && ret != NC_ERANGE) ERR; + if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_64BIT_DATA) + { + if (ret != NC_ERANGE) ERR; + } + else if (ret) ERR; /* Check it out. */ if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; @@ -539,7 +542,7 @@ test_redef(int format) if (nc_get_att_int(ncid, NC_GLOBAL, REDEF_ATT2_NAME, &int_in)) ERR; if (int_in != short_out) ERR; ret = nc_get_att_uchar(ncid, NC_GLOBAL, REDEF_ATT3_NAME, &uchar_in); - if (format == NC_FORMAT_NETCDF4) + if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_64BIT_DATA) { if (ret != NC_ERANGE) ERR; } diff --git a/ncdump/Makefile.am b/ncdump/Makefile.am index b8bec73a84..c117eb0a12 100644 --- a/ncdump/Makefile.am +++ b/ncdump/Makefile.am @@ -121,7 +121,10 @@ tst_ncf213.cdl tst_ncf213.nc tst_h_scalar.cdl tst_h_scalar.nc \ tst_mud4_chars.cdl tst_mud4_chars.nc \ inttags.nc inttags4.nc tst_inttags.cdl tst_inttags4.cdl \ tst_dimsize_classic.nc tst_dimsize_64offset.nc tst_dimsize_64data.nc \ -nc4_fileinfo.nc hdf5_fileinfo.hdf +nc4_fileinfo.nc hdf5_fileinfo.hdf \ +ref_hdf5_compat1.nc ref_hdf5_compat2.nc ref_hdf5_compat3.nc \ +ref_tst_compounds.nc ref_tst_dims.nc ref_tst_interops4.nc \ +ref_tst_xplatform2_1.nc ref_tst_xplatform2_2.nc # These files all have to be included with the distribution. EXTRA_DIST = run_tests.sh tst_64bit.sh tst_output.sh test0.cdl \ @@ -158,3 +161,6 @@ tst_ncgen4_diff.sh tst_ncgen4_cycle.sh ref_ctest.c ref_ctest64.c CLEANFILES += results/*.nc results/*.dmp results/*.dmp2 tmp*.cdl tst_bug324.nc DISTCLEANFILES = results + +clean-local: + -rm -rf results