Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 15 additions & 19 deletions src/silo/silo_f.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ DBPUTMSP_FC (int *dbid, FCD_DB name, int *lname, FCD_DB matname, int *lmatname,

*status = DBPutMatspecies(dbfile, nm, mnm, *nmat, nmatspec,
speclist, dims, *ndims, *nspecies_mf,
species_mf, mix_speclist, *mixlen,
FPTR(species_mf), FPTR(mix_speclist), *mixlen,
*datatype, optlist);

FREE(nm);
Expand Down Expand Up @@ -1412,7 +1412,7 @@ DBPUTFL_FC (int *dbid, FCD_DB name, int *lname, int *nfaces, int *ndims,
nodelist, *lnodelist, *origin,
FPTR(zoneno),
shapesize, shapecnt, *nshapes,
types, typelist, *ntypes);
FPTR(types), FPTR(typelist), *ntypes);

FREE(nm);

Expand Down Expand Up @@ -2485,7 +2485,8 @@ DBPUTQV1_FC (int *dbid, FCD_DB name,

dbfile = (DBfile *) DBFortranAccessPointer(*dbid);

*status = DBPutQuadvar1(dbfile, nm, mnm, var, dims, *ndims, mixvar,
*status = DBPutQuadvar1(dbfile, nm, mnm, var, dims, *ndims,
*mixlen==0?NULL:mixvar,
*mixlen, *datatype, *centering, optlist);

FREE(nm);
Expand Down Expand Up @@ -2612,7 +2613,7 @@ DBPUTQV_FC (int *dbid, FCD_DB vname, int *lvname, FCD_DB mname, int *lmname,
} else {
API_ERROR("vars", E_BADARGS);
}
if ((*(int *)mixvar) != DB_F77NULL) {
if (mixlen > 0) {
/* Now convert the Fortran data array into a C array of data */
cmixvar = (void **)malloc(sizeof(void*) * (*nvars));
/* Make pointers to Fortran address in vars array */
Expand Down Expand Up @@ -2895,8 +2896,8 @@ DBPUTUV1_FC (int *dbid, FCD_DB name,

dbfile = (DBfile *) DBFortranAccessPointer(*dbid);

*status = DBPutUcdvar1(dbfile, nm, mnm, var, *nels, mixvar, *mixlen,
*datatype, *centering, optlist);
*status = DBPutUcdvar1(dbfile, nm, mnm, var, *nels, mixlen==0?NULL:mixvar,
*mixlen, *datatype, *centering, optlist);

FREE(nm);
FREE(mnm);
Expand Down Expand Up @@ -4249,22 +4250,17 @@ DBGETQV1_FC (int *dbid, FCD_DB varname, int *lvarname, void *var, int *dims,
*ndims = qv->ndims;
*centering = (qv->align[0] == 0.) ? DB_NODECENT : DB_ZONECENT;
*datatype = qv->datatype;
*mixlen = qv->mixlen;
for (i = 0; i < qv->ndims; i++)
dims[i] = qv->dims[i];

/*------------------------------------------------------------
* If there was mixed data, copy that too.
*
* Kludge city!!! I'm assuming name of mixed component is
* 'varname_mix'. This info should be kept in DBquadvar
* somewhere.
*-----------------------------------------------------------*/
if ((*(int *)mixvar) != DB_F77NULL) {
strcpy(tmpstr, varnm);
strcat(tmpstr, "_mix");

*mixlen = DBGetVarLength(dbfile, tmpstr);
DBReadVar(dbfile, tmpstr, mixvar);
/*------------------------------
* Copy the mixed vals of quad
* var into the supplied space.
*-----------------------------*/
if (qv->mixlen > 0 && (FPTR(mixvar))) {
nbytes = qv->mixlen * db_GetMachDataSize(qv->datatype);
memcpy(mixvar, qv->mixvals[0], nbytes);
}

DBFreeQuadvar(qv);
Expand Down
14 changes: 5 additions & 9 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -738,14 +738,10 @@ if(SILO_ENABLE_SILOCK AND NOT WIN32)
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/testsilock
${silo_test_output_dir})
add_test(NAME testsilock
COMMAND ${CMAKE_COMMAND} -E env
"${silo_test_output_dir}/testsilock")
add_test(NAME testsilock COMMAND "${silo_test_output_dir}/testsilock")
set_tests_properties(onehex PROPERTIES DEPENDS testsilock RESOURCE_LOCK onehex.silo)
if(SILO_ENABLE_HDF5 AND HDF5_FOUND)
add_test(NAME testsilock-hdf5
COMMAND ${CMAKE_COMMAND} -E env
"${silo_test_output_dir}/testsilock" DB_HDF5)
add_test(NAME testsilock-hdf5 COMMAND "${silo_test_output_dir}/testsilock" DB_HDF5)
set_tests_properties(onehex-hdf5 PROPERTIES DEPENDS testsilock-hdf5)
set_tests_properties(testsilock-hdf5 PROPERTIES DEPENDS testsilock RESOURCE_LOCK onehex.silo)
endif()
Expand Down Expand Up @@ -786,7 +782,7 @@ if(SILO_ENABLE_PYTHON_MODULE AND Python_EXECUTABLE)
set_tests_properties(test-write-py-hdf5 PROPERTIES DEPENDS sami-hdf5 REQUIRED_FILES sami.silo)
set_tests_properties(test-write-py-hdf5 PROPERTIES RESOURCE_LOCK "sami.silo")
set_tests_properties(test-write-py-hdf5 PROPERTIES LABELS "python;hdf5")
add_test(NAME test-scale-quadvar-hdf5 COMMAND ${CMAKE_COMMAND} -E env "${silo_test_output_dir}/test_scale_quadvar")
add_test(NAME test-scale-quadvar-hdf5 COMMAND "${silo_test_output_dir}/test_scale_quadvar")
set_tests_properties(test-scale-quadvar-hdf5 PROPERTIES SKIP_RETURN_CODE ${_silo_test_skip_retval}
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:SiloPy>${_envvar_path_sep}$ENV{PYTHONPATH};LD_PRELOAD=${SILO_LIBASAN_PATH}:${SILO_LIBUBSAN_PATH};ASAN_OPTIONS=detect_leaks=0;SILO_TEST_SKIP_RETURN_CODE=${_silo_test_skip_retval}")
set_tests_properties(test-scale-quadvar-hdf5 PROPERTIES LABELS "python;hdf5")
Expand Down Expand Up @@ -816,14 +812,14 @@ if(SILO_ENABLE_PYTHON_MODULE AND Python_EXECUTABLE)
set_tests_properties(multi_test-reset-hdf5 test-read-py-hdf5 PROPERTIES REQUIRED_FILES "multi_ucd3d.h5;multi_rect3d.h5")
endif()

add_test(NAME testonehex COMMAND ${CMAKE_COMMAND} -E env "${silo_test_output_dir}/testonehex" DB_PDB)
add_test(NAME testonehex COMMAND "${silo_test_output_dir}/testonehex" DB_PDB)
set_tests_properties(testonehex PROPERTIES DEPENDS onehex)
set_tests_properties(testonehex PROPERTIES ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:SiloPy>${_envvar_path_sep}$ENV{PYTHONPATH};LD_PRELOAD=${SILO_LIBASAN_PATH}:${SILO_LIBUBSAN_PATH};ASAN_OPTIONS=detect_leaks=0")
set_tests_properties(testonehex PROPERTIES LABELS "python")
set_tests_properties(testonehex onehex PROPERTIES RESOURCE_LOCK "onehex.silo")

if(SILO_ENABLE_HDF5 AND HDF5_FOUND)
add_test(NAME testonehex-hdf5 COMMAND ${CMAKE_COMMAND} -E env "${silo_test_output_dir}/testonehex" DB_HDF5)
add_test(NAME testonehex-hdf5 COMMAND "${silo_test_output_dir}/testonehex" DB_HDF5)
set_tests_properties(testonehex-hdf5 PROPERTIES DEPENDS "onehex-hdf5;testonehex")
set_tests_properties(testonehex-hdf5 PROPERTIES ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:SiloPy>${_envvar_path_sep}$ENV{PYTHONPATH};LD_PRELOAD=${SILO_LIBASAN_PATH}:${SILO_LIBUBSAN_PATH};ASAN_OPTIONS=detect_leaks=0")
set_tests_properties(testonehex-hdf5 PROPERTIES LABELS "python;hdf5")
Expand Down
202 changes: 202 additions & 0 deletions tests/dbf77null.f
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
C***********************************************************************
C Copyright (C) 1994-2026 Lawrence Livermore National Security, LLC.
C LLNL-CODE-425250.
C All rights reserved.
C
C This file is part of Silo. For details, see silo.llnl.gov.
C***********************************************************************
C
C Purpose
C
C Exercise the DB_F77NULL convention in Silo's Fortran interface.
C
C In particular, verify
C
C 1. DB_F77NULL may be supplied for an absent mixed-data array.
C 2. DB_F77NULL may be supplied for optional facelist arrays.
C 3. A legitimate INTEGER mixed-data array whose first value is
C -99 is not mistaken for DB_F77NULL.
C
C Case 3 intentionally demonstrates why a wrapper must not blindly
C apply FPTR() to a nullable data array when another argument (such
C as mixlen) can unambiguously say whether the array is present.
C
C ChatGPT via Mark C. Miller, Thu Aug 27 20:24:53 PDT 2026
C***********************************************************************

program f77null

implicit none
include "silo.inc"

integer dbid, err, driver, nargs, errmode
integer status, nerrors
integer dims(1), vdims(1)
integer ivar(1), mixvar(1)
integer rvar(1), rmixvar(1), rdims(1)
integer rndims, rmixlen, rdatatype, rcentering
integer nodelist(2), shapesize(1), shapecnt(1)
character*256 cloption
real x(2)

errmode = DB_NONE
driver = DB_PDB
nargs = iargc()
if (nargs .gt. 0) then
call getarg(1, cloption)
if (cloption .eq. "DB_HDF5") driver = DB_HDF5
if (cloption .eq. "show-all-errors") then
errmode = DB_ALL_AND_DRVR
endif
endif

status = dbshowerrors(errmode)

nerrors = 0

C...Create a tiny 1-D quad mesh.

x(1) = 0.0
x(2) = 1.0
dims(1) = 2

err = dbcreate("dbf77null.silo", 12, DB_CLOBBER, DB_LOCAL,
. "DB_F77NULL regression test", 26,
. driver, dbid)
if (err .ne. 0) then
print *, "dbcreate failed"
stop 1
endif

status = 0
err = dbputqm(dbid, "mesh", 4,
. "X", 1, DB_F77NULLSTRING, 0,
. DB_F77NULLSTRING, 0,
. x, DB_F77NULL, DB_F77NULL,
. dims, 1, DB_FLOAT, DB_COLLINEAR,
. DB_F77NULL, status)
if (err .ne. 0 .or. status .lt. 0) then
print *, "dbputqm failed"
nerrors = nerrors + 1
endif

C...A scalar zone-centered variable with no mixed data.

vdims(1) = 1
ivar(1) = 17

status = 0
err = dbputqv1(dbid, "nomix", 5, "mesh", 4,
. ivar, vdims, 1, DB_F77NULL, 0,
. DB_INT, DB_ZONECENT, DB_F77NULL, status)
if (err .ne. 0 .or. status .lt. 0) then
print *, "dbputqv1 with DB_F77NULL mixvar failed"
nerrors = nerrors + 1
endif

C...Now provide real mixed data whose first value happens to equal the
C...DB_F77NULL magic integer value. This is legitimate data and must
C...NOT be converted to a C NULL pointer.
C...
C...A wrapper of the form FPTR(mixvar) gets this wrong because FPTR
C...examines the first INTEGER value. For DBPutQuadvar1, mixlen already
C...tells the wrapper whether mixvar is present, so the safer conversion
C...is conceptually: *mixlen == 0 ? NULL : mixvar

mixvar(1) = -99

status = 0
err = dbputqv1(dbid, "minus99", 7, "mesh", 4,
. ivar, vdims, 1, mixvar, 1,
. DB_INT, DB_ZONECENT, DB_F77NULL, status)
if (err .ne. 0 .or. status .lt. 0) then
print *, "dbputqv1 rejected legitimate mixvar(1)=-99"
nerrors = nerrors + 1
endif

C...Exercise DB_F77NULL for optional facelist arrays.

nodelist(1) = 0
nodelist(2) = 1
shapesize(1) = 2
shapecnt(1) = 1

status = 0
err = dbputfl(dbid, "fl", 2, 1, 2,
. nodelist, 2, 0, DB_F77NULL,
. shapesize, shapecnt, 1,
. DB_F77NULL, DB_F77NULL, 0, status)
if (err .ne. 0 .or. status .lt. 0) then
print *, "dbputfl with DB_F77NULL optional arrays failed"
nerrors = nerrors + 1
endif

err = dbclose(dbid)
if (err .ne. 0) then
print *, "dbclose failed"
nerrors = nerrors + 1
endif

C...Read the -99 mixed data back.

err = dbopen("dbf77null.silo", 12, driver, DB_READ, dbid)
if (err .ne. 0) then
print *, "dbopen failed"
stop 1
endif

rvar(1) = 0
rmixvar(1) = 0
rdims(1) = 0
rndims = 0
rmixlen = 0
rdatatype = 0
rcentering = 0

err = dbgetqv1(dbid, "minus99", 7, rvar, rdims, rndims,
. rmixvar, rmixlen, rdatatype, rcentering)
if (err .ne. 0) then
print *, "dbgetqv1(minus99) failed"
nerrors = nerrors + 1
else
if (rmixlen .ne. 1) then
print *, "wrong mixlen; expected 1, got ", rmixlen
nerrors = nerrors + 1
endif
if (rmixvar(1) .ne. -99) then
print *, "wrong mixed value; expected -99, got ",
. rmixvar(1)
nerrors = nerrors + 1
endif
endif

C...Also exercise DB_F77NULL on the output side of dbgetqv1.

rvar(1) = 0
rdims(1) = 0
rndims = 0
rmixlen = 0
rdatatype = 0
rcentering = 0

err = dbgetqv1(dbid, "nomix", 5, rvar, rdims, rndims,
. DB_F77NULL, rmixlen, rdatatype, rcentering)
if (err .ne. 0) then
print *, "dbgetqv1 with DB_F77NULL mixvar failed"
nerrors = nerrors + 1
endif

err = dbclose(dbid)
if (err .ne. 0) then
print *, "final dbclose failed"
nerrors = nerrors + 1
endif

if (nerrors .ne. 0) then
print *, "DB_F77NULL regression test failed:", nerrors
stop 1
endif

print *, "DB_F77NULL regression test passed"
stop
end
7 changes: 7 additions & 0 deletions tests/test_scale_quadvar
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ fi
# Use python module to create data with no special features
#
env PYTHONPATH=$(dirname $silo_pyso) $pycmd $scale_quadvar_py 1>/dev/null 2>&1
py_status=$?
if [ -n "$SILO_TEST_SKIP_RETURN_CODE" ] && [ "$py_status" -eq "$SILO_TEST_SKIP_RETURN_CODE" ]; then
exit $SILO_TEST_SKIP_RETURN_CODE
fi
if [ "$py_status" -ne 0 ]; then
exit "$py_status"
fi

#
# Now, run browser and make sure we don't get any errors in the diff
Expand Down
Loading