diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 170 | ||||
-rw-r--r-- | src/H5private.h | 117 | ||||
-rw-r--r-- | src/H5system.c | 503 | ||||
-rw-r--r-- | src/H5win32defs.h | 58 |
4 files changed, 706 insertions, 142 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 444c884..bee531a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -611,6 +611,12 @@ set (H5_GENERATED_HEADERS ${HDF5_SRC_DIR}/H5overflow.h ) +set (H5_PUBLIC_GENERATED_HEADERS + ${HDF5_SRC_DIR}/H5Epubgen.h + ${HDF5_SRC_DIR}/H5version.h + ${HDF5_SRC_DIR}/H5overflow.h +) + option (HDF5_GENERATE_HEADERS "Rebuild Generated Files" ON) if (HDF5_GENERATE_HEADERS) set_source_files_properties(${H5_GENERATED_HEADERS} PROPERTIES GENERATED TRUE) @@ -649,11 +655,11 @@ endif () if (NOT EXISTS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c) add_executable (H5detect ${HDF5_SRC_DIR}/H5detect.c) - target_include_directories(H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") + target_include_directories (H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") target_compile_definitions(H5detect PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS}) TARGET_C_PROPERTIES (H5detect STATIC) target_link_libraries (H5detect - PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<PLATFORM_ID:Windows>:ws2_32.lib> + PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:MinGW>>:ws2_32.lib> PRIVATE $<$<PLATFORM_ID:Emscripten>:"-O0"> ) @@ -664,46 +670,96 @@ if (NOT EXISTS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c) ) add_custom_command ( OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c + ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 COMMAND ${HDF5_BATCH_CMD} ARGS ${HDF5_BINARY_DIR}/${HDF5_BATCH_H5DETECT_SCRIPT} + COMMAND ${CMAKE_COMMAND} + ARGS -E echo "Executed batch command to create H5Tinit.c" + COMMAND ${CMAKE_COMMAND} + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 DEPENDS H5detect WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} ) - set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c PROPERTIES GENERATED TRUE) + add_custom_target (gen_H5Tinit + COMMAND ${CMAKE_COMMAND} -P ${HDF5_SOURCE_DIR}/config/cmake/wait_H5Tinit.cmake + ) + if (BUILD_SHARED_LIBS) + add_custom_command ( + OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c + ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 + COMMAND ${CMAKE_COMMAND} + ARGS -E copy_if_different "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c" "${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c" + COMMAND ${CMAKE_COMMAND} + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 + DEPENDS gen_H5Tinit ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit_created + WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} + ) + set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE) + endif () else () add_custom_command ( OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c - COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR}$<TARGET_FILE:H5detect> + ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 + COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:H5detect> ARGS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c + COMMAND ${CMAKE_COMMAND} + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 DEPENDS H5detect WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} ) - set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c PROPERTIES GENERATED TRUE) + if (BUILD_SHARED_LIBS) + add_custom_command ( + OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c + ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 + COMMAND ${CMAKE_COMMAND} + ARGS -E copy_if_different "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c" "${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c" + COMMAND ${CMAKE_COMMAND} + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 + DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c + WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} + ) + set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE) + endif () endif () -endif () -if (BUILD_SHARED_LIBS) + set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c PROPERTIES GENERATED TRUE) +else () add_custom_command ( - OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c + OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 COMMAND ${CMAKE_COMMAND} - ARGS -E copy_if_different "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c" "${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c" + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c + WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} ) - set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE) + if (BUILD_SHARED_LIBS) + add_custom_command ( + OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 + COMMAND ${CMAKE_COMMAND} + ARGS -E copy_if_different "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c" "${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c" + COMMAND ${CMAKE_COMMAND} + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 + DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c + WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} + ) + set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE) + endif () endif () add_executable (H5make_libsettings ${HDF5_SRC_DIR}/H5make_libsettings.c) -target_include_directories(H5make_libsettings PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") +target_include_directories (H5make_libsettings PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") target_compile_definitions(H5make_libsettings PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS}) TARGET_C_PROPERTIES (H5make_libsettings STATIC) target_link_libraries (H5make_libsettings - PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<PLATFORM_ID:Windows>:ws2_32.lib> + PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:MinGW>>:ws2_32.lib> PRIVATE $<$<PLATFORM_ID:Emscripten>:"-O0"> ) add_custom_command ( OUTPUT ${HDF5_BINARY_DIR}/H5lib_settings.c - COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR}$<TARGET_FILE:H5make_libsettings> + ${HDF5_BINARY_DIR}/gen_SRCS.stamp2 + COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:H5make_libsettings> ARGS ${HDF5_BINARY_DIR}/H5lib_settings.c + COMMAND ${CMAKE_COMMAND} + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp2 DEPENDS H5make_libsettings WORKING_DIRECTORY ${HDF5_BINARY_DIR} ) @@ -711,9 +767,13 @@ set_source_files_properties (${HDF5_BINARY_DIR}/H5lib_settings.c PROPERTIES GENE if (BUILD_SHARED_LIBS) add_custom_command ( OUTPUT ${HDF5_BINARY_DIR}/shared/H5lib_settings.c + ${HDF5_BINARY_DIR}/shared/shared_gen_SRCS.stamp2 COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different "${HDF5_BINARY_DIR}/H5lib_settings.c" "${HDF5_BINARY_DIR}/shared/H5lib_settings.c" + COMMAND ${CMAKE_COMMAND} + ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp2 DEPENDS ${HDF5_BINARY_DIR}/H5lib_settings.c + WORKING_DIRECTORY ${HDF5_BINARY_DIR} ) set_source_files_properties (${HDF5_BINARY_DIR}/shared/H5lib_settings.c PROPERTIES GENERATED TRUE) endif () @@ -724,47 +784,49 @@ option (HDF5_ENABLE_DEBUG_APIS "Turn on extra debug output in all packages" OFF) #----------------------------------------------------------------------------- # Add H5Tinit source to build - generated by H5detect/CMake at configure time #----------------------------------------------------------------------------- -set (gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c ${HDF5_BINARY_DIR}/H5lib_settings.c) - -add_custom_target (gen_${HDF5_LIB_TARGET} ALL DEPENDS ${gen_SRCS}) -add_library (${HDF5_LIB_TARGET} STATIC ${common_SRCS} ${gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS}) -target_include_directories(${HDF5_LIB_TARGET} - PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>" - INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>" -) -target_compile_definitions(${HDF5_LIB_TARGET} - PUBLIC - ${HDF_EXTRA_C_FLAGS} - ${HDF_EXTRA_FLAGS} - $<IF:$<CONFIG:Debug>,DEBUG,NDEBUG> - PRIVATE - $<$<BOOL:${HDF5_ENABLE_TRACE}>:H5_DEBUG_API> # Enable tracing of the API - $<$<BOOL:${HDF5_ENABLE_DEBUG_APIS}>:H5Z_DEBUG;H5T_DEBUG;H5ST_DEBUG;H5S_DEBUG;H5O_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5F_DEBUG;H5D_DEBUG;H5B2_DEBUG;H5AC_DEBUG> -) -TARGET_C_PROPERTIES (${HDF5_LIB_TARGET} STATIC) -target_link_libraries (${HDF5_LIB_TARGET} - PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" - PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}> -) -set_global_variable (HDF5_LIBRARIES_TO_EXPORT ${HDF5_LIB_TARGET}) -H5_SET_LIB_OPTIONS (${HDF5_LIB_TARGET} ${HDF5_LIB_NAME} STATIC 0) -set_target_properties (${HDF5_LIB_TARGET} PROPERTIES FOLDER libraries) -add_dependencies (${HDF5_LIB_TARGET} gen_${HDF5_LIB_TARGET}) - -if (HDF5_ENABLE_DEBUG_APIS) - set_target_properties (${HDF5_LIB_TARGET} PROPERTIES - COMPILE_DEFINITIONS - "H5Z_DEBUG;H5VM_DEBUG;H5T_DEBUG;H5S_DEBUG;H5P_DEBUG;H5O_DEBUG;H5MM_DEBUG;H5MF_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5HG_DEBUG;H5G_DEBUG;H5F_DEBUG;H5E_DEBUG;H5D_DEBUG;H5B_DEBUG;H5AC_DEBUG" +if (NOT ONLY_SHARED_LIBS) + set (gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c ${HDF5_BINARY_DIR}/H5lib_settings.c) + add_custom_target (gen_${HDF5_LIB_TARGET} ALL DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp2) + + add_library (${HDF5_LIB_TARGET} STATIC ${common_SRCS} ${gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS}) + target_include_directories (${HDF5_LIB_TARGET} + PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>" + INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>" ) + target_compile_definitions(${HDF5_LIB_TARGET} + PUBLIC + ${HDF_EXTRA_C_FLAGS} + ${HDF_EXTRA_FLAGS} + $<IF:$<CONFIG:Debug>,DEBUG,NDEBUG> + PRIVATE + $<$<BOOL:${HDF5_ENABLE_TRACE}>:H5_DEBUG_API> # Enable tracing of the API + $<$<BOOL:${HDF5_ENABLE_DEBUG_APIS}>:H5Z_DEBUG;H5T_DEBUG;H5ST_DEBUG;H5S_DEBUG;H5O_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5F_DEBUG;H5D_DEBUG;H5B2_DEBUG;H5AC_DEBUG> + ) + TARGET_C_PROPERTIES (${HDF5_LIB_TARGET} STATIC) + target_link_libraries (${HDF5_LIB_TARGET} + PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" + PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}> + ) + set_global_variable (HDF5_LIBRARIES_TO_EXPORT ${HDF5_LIB_TARGET}) + H5_SET_LIB_OPTIONS (${HDF5_LIB_TARGET} ${HDF5_LIB_NAME} STATIC 0) + set_target_properties (${HDF5_LIB_TARGET} PROPERTIES FOLDER libraries) + add_dependencies (${HDF5_LIB_TARGET} gen_${HDF5_LIB_TARGET}) + + if (HDF5_ENABLE_DEBUG_APIS) + set_target_properties (${HDF5_LIB_TARGET} PROPERTIES + COMPILE_DEFINITIONS + "H5Z_DEBUG;H5VM_DEBUG;H5T_DEBUG;H5S_DEBUG;H5P_DEBUG;H5O_DEBUG;H5MM_DEBUG;H5MF_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5HG_DEBUG;H5G_DEBUG;H5F_DEBUG;H5E_DEBUG;H5D_DEBUG;H5B_DEBUG;H5AC_DEBUG" + ) + endif () + set (install_targets ${HDF5_LIB_TARGET}) endif () -set (install_targets ${HDF5_LIB_TARGET}) if (BUILD_SHARED_LIBS) set (shared_gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c ${HDF5_BINARY_DIR}/shared/H5lib_settings.c) + add_custom_target (gen_${HDF5_LIBSH_TARGET} ALL DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp2) - add_custom_target (gen_${HDF5_LIBSH_TARGET} ALL DEPENDS ${shared_gen_SRCS}) add_library (${HDF5_LIBSH_TARGET} SHARED ${common_SRCS} ${shared_gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS}) - target_include_directories(${HDF5_LIBSH_TARGET} + target_include_directories (${HDF5_LIBSH_TARGET} PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>" INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>" ) @@ -781,8 +843,8 @@ if (BUILD_SHARED_LIBS) ) TARGET_C_PROPERTIES (${HDF5_LIBSH_TARGET} SHARED) target_link_libraries (${HDF5_LIBSH_TARGET} - PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" - PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}> $<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:Threads::Threads> + PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:Threads::Threads> + PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}> ) set_global_variable (HDF5_LIBRARIES_TO_EXPORT "${HDF5_LIBRARIES_TO_EXPORT};${HDF5_LIBSH_TARGET}") H5_SET_LIB_OPTIONS (${HDF5_LIBSH_TARGET} ${HDF5_LIB_NAME} SHARED "LIB") @@ -805,7 +867,7 @@ if (NOT HDF5_INSTALL_NO_DEVELOPMENT) install ( FILES ${H5_PUBLIC_HEADERS} - ${H5_GENERATED_HEADERS} + ${H5_PUBLIC_GENERATED_HEADERS} ${HDF5_BINARY_DIR}/H5pubconf.h DESTINATION ${HDF5_INSTALL_INCLUDE_DIR} @@ -821,7 +883,9 @@ if (HDF5_EXPORTED_TARGETS) if (BUILD_SHARED_LIBS) INSTALL_TARGET_PDB (${HDF5_LIBSH_TARGET} ${HDF5_INSTALL_BIN_DIR} libraries) endif () - INSTALL_TARGET_PDB (${HDF5_LIB_TARGET} ${HDF5_INSTALL_BIN_DIR} libraries) + if (NOT ONLY_SHARED_LIBS) + INSTALL_TARGET_PDB (${HDF5_LIB_TARGET} ${HDF5_INSTALL_LIB_DIR} libraries) + endif () install ( TARGETS @@ -850,7 +914,9 @@ foreach (libs ${LINK_LIBS} ${LINK_COMP_LIBS}) set (_PKG_CONFIG_LIBS_PRIVATE "${_PKG_CONFIG_LIBS_PRIVATE} -l${libs}") endforeach () -set (_PKG_CONFIG_LIBS "${_PKG_CONFIG_LIBS} -l${HDF5_LIB_CORENAME}") +if (NOT ONLY_SHARED_LIBS) + set (_PKG_CONFIG_LIBS "${_PKG_CONFIG_LIBS} -l${HDF5_LIB_CORENAME}") +endif () if (BUILD_SHARED_LIBS) set (_PKG_CONFIG_SH_LIBS "${_PKG_CONFIG_SH_LIBS} -l${HDF5_LIB_CORENAME}") endif () diff --git a/src/H5private.h b/src/H5private.h index 85afab7..500aa43 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -126,7 +126,7 @@ /* * Unix ioctls. These are used by h5ls (and perhaps others) to determine a - * resonable output width. + * reasonable output width. */ #ifdef H5_HAVE_SYS_IOCTL_H # include <sys/ioctl.h> @@ -173,7 +173,7 @@ #endif #ifdef H5_HAVE_THREADSAFE -#include <process.h> /* For _beginthread() */ +#include <process.h> /* For _beginthread() */ #endif #include <windows.h> @@ -235,7 +235,6 @@ * color information down to the BEGIN_MPE_LOG macro (which should have a new * BEGIN_MPE_LOG_COLOR variant). -QAK */ - #define BEGIN_MPE_LOG \ if (H5_MPEinit_g){ \ sprintf(p_event_start, "start %s", FUNC); \ @@ -345,6 +344,9 @@ /* (from: http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2) */ # define POWER_OF_TWO(n) (!(n & (n - 1)) && n) +/* Raise an integer to a power of 2 */ +# define H5_EXP2(n) (1 << (n)) + /* * HDF Boolean type. */ @@ -465,6 +467,15 @@ # define H5_POSIX_MAX_IO_BYTES SSIZET_MAX #endif +/* POSIX I/O mode used as the third parameter to open/_open + * when creating a new file (O_CREAT is set). + */ +#if defined(H5_HAVE_WIN32_API) +# define H5_POSIX_CREATE_MODE_RW (_S_IREAD | _S_IWRITE) +#else +# define H5_POSIX_CREATE_MODE_RW 0666 +#endif + /* * A macro to portably increment enumerated types. */ @@ -480,7 +491,7 @@ #endif /* Double constant wrapper - * + * * Quiets gcc warnings from -Wunsuffixed-float-constants. * * This is a really annoying warning since the standard specifies that @@ -612,6 +623,9 @@ typedef struct { #ifndef HDatol #define HDatol(S) atol(S) #endif /* HDatol */ +#ifndef HDatoll + #define HDatoll(S) atoll(S) +#endif /* HDatol */ #ifndef HDbsearch #define HDbsearch(K,B,N,Z,F) bsearch(K,B,N,Z,F) #endif /* HDbsearch */ @@ -709,6 +723,9 @@ typedef struct { #ifndef HDexp #define HDexp(X) exp(X) #endif /* HDexp */ +#ifndef HDexp2 + #define HDexp2(X) exp2(X) +#endif /* HDexp2 */ #ifndef HDfabs #define HDfabs(X) fabs(X) #endif /* HDfabs */ @@ -956,6 +973,15 @@ typedef off_t h5_stat_size_t; #ifndef HDlink #define HDlink(OLD,NEW) link(OLD,NEW) #endif /* HDlink */ +#ifndef HDllround + #define HDllround(V) llround(V) +#endif /* HDround */ +#ifndef HDllroundf + #define HDllroundf(V) llroundf(V) +#endif /* HDllroundf */ +#ifndef HDllroundl + #define HDllroundl(V) llroundl(V) +#endif /* HDllroundl */ #ifndef HDlocaleconv #define HDlocaleconv() localeconv() #endif /* HDlocaleconv */ @@ -971,6 +997,15 @@ typedef off_t h5_stat_size_t; #ifndef HDlongjmp #define HDlongjmp(J,N) longjmp(J,N) #endif /* HDlongjmp */ +#ifndef HDlround + #define HDlround(V) lround(V) +#endif /* HDround */ +#ifndef HDlroundf + #define HDlroundf(V) lroundf(V) +#endif /* HDlroundf */ +#ifndef HDlroundl + #define HDlroundl(V) lroundl(V) +#endif /* HDroundl */ #ifndef HDlseek #define HDlseek(F,O,W) lseek(F,O,W) #endif /* HDlseek */ @@ -1020,12 +1055,11 @@ typedef off_t h5_stat_size_t; #ifndef HDmodf #define HDmodf(X,Y) modf(X,Y) #endif /* HDmodf */ +#ifndef HDnanosleep + #define HDnanosleep(N, O) nanosleep(N, O) +#endif /* HDnanosleep */ #ifndef HDopen - #ifdef _O_BINARY - #define HDopen(S,F,M) open(S,F|_O_BINARY,M) - #else - #define HDopen(S,F,M) open(S,F,M) - #endif + #define HDopen(F,...) open(F,__VA_ARGS__) #endif /* HDopen */ #ifndef HDopendir #define HDopendir(S) opendir(S) @@ -1110,10 +1144,22 @@ typedef off_t h5_stat_size_t; #ifndef HDrewinddir #define HDrewinddir(D) rewinddir(D) #endif /* HDrewinddir */ +#ifndef HDround + #define HDround(V) round(V) +#endif /* HDround */ +#ifndef HDroundf + #define HDroundf(V) roundf(V) +#endif /* HDroundf */ +#ifndef HDroundl + #define HDroundl(V) roundl(V) +#endif /* HDroundl */ #ifndef HDrmdir #define HDrmdir(S) rmdir(S) #endif /* HDrmdir */ /* scanf() variable arguments */ +#ifndef HDselect + #define HDselect(N,RD,WR,ER,T) select(N,RD,WR,ER,T) +#endif /* HDsetbuf */ #ifndef HDsetbuf #define HDsetbuf(F,S) setbuf(F,S) #endif /* HDsetbuf */ @@ -1212,8 +1258,9 @@ typedef off_t h5_stat_size_t; #define HDsrandom(S) srand(S) #endif /* HDsrandom */ #endif /* H5_HAVE_RAND_R */ -/* sscanf() variable arguments */ - +#ifndef HDsscanf + #define HDsscanf(S,FMT,...) sscanf(S,FMT,__VA_ARGS__) +#endif /* HDsscanf */ #ifndef HDstrcat #define HDstrcat(X,Y) strcat(X,Y) #endif /* HDstrcat */ @@ -1221,7 +1268,7 @@ typedef off_t h5_stat_size_t; #define HDstrchr(S,C) strchr(S,C) #endif /* HDstrchr */ #ifndef HDstrcmp - #define HDstrcmp(X,Y) strcmp(X,Y) + #define HDstrcmp(X,Y) strcmp(X,Y) #endif /* HDstrcmp */ #ifndef HDstrcasecmp #define HDstrcasecmp(X,Y) strcasecmp(X,Y) @@ -1271,6 +1318,9 @@ typedef off_t h5_stat_size_t; #ifndef HDstrtok #define HDstrtok(X,Y) strtok(X,Y) #endif /* HDstrtok */ +#ifndef HDstrtok_r + #define HDstrtok_r(X,Y,Z) strtok_r(X,Y,Z) +#endif /* HDstrtok */ #ifndef HDstrtol #define HDstrtol(S,R,N) strtol(S,R,N) #endif /* HDstrtol */ @@ -1373,6 +1423,9 @@ typedef off_t h5_stat_size_t; #ifndef HDva_arg #define HDva_arg(A,T) va_arg(A,T) #endif /* HDva_arg */ +#ifndef HDva_copy +#define HDva_copy(D,S) va_copy(D,S) +#endif /* HDva_copy */ #ifndef HDva_end #define HDva_end(A) va_end(A) #endif /* HDva_end */ @@ -1438,7 +1491,7 @@ extern char *strdup(const char *s); #define H5_CHECK_OVERFLOW(var, vartype, casttype) \ { \ casttype _tmp_overflow = (casttype)(var); \ - assert((var) == (vartype)_tmp_overflow); \ + HDassert((var) == (vartype)_tmp_overflow); \ } #else /* NDEBUG */ #define H5_CHECK_OVERFLOW(var, vartype, casttype) @@ -1452,7 +1505,7 @@ extern char *strdup(const char *s); { \ srctype _tmp_src = (srctype)(src); \ dsttype _tmp_dst = (dsttype)(_tmp_src); \ - assert(_tmp_src == (srctype)_tmp_dst); \ + HDassert(_tmp_src == (srctype)_tmp_dst); \ (dst) = _tmp_dst; \ } @@ -1463,8 +1516,8 @@ extern char *strdup(const char *s); { \ srctype _tmp_src = (srctype)(src); \ dsttype _tmp_dst = (dsttype)(_tmp_src); \ - assert(_tmp_src >= 0); \ - assert(_tmp_src == _tmp_dst); \ + HDassert(_tmp_src >= 0); \ + HDassert(_tmp_src == _tmp_dst); \ (dst) = _tmp_dst; \ } @@ -1475,8 +1528,8 @@ extern char *strdup(const char *s); { \ srctype _tmp_src = (srctype)(src); \ dsttype _tmp_dst = (dsttype)(_tmp_src); \ - assert(_tmp_dst >= 0); \ - assert(_tmp_src == (srctype)_tmp_dst); \ + HDassert(_tmp_dst >= 0); \ + HDassert(_tmp_src == (srctype)_tmp_dst); \ (dst) = _tmp_dst; \ } @@ -1484,8 +1537,8 @@ extern char *strdup(const char *s); { \ srctype _tmp_src = (srctype)(src); \ dsttype _tmp_dst = (dsttype)(_tmp_src); \ - assert(_tmp_src >= 0); \ - assert(_tmp_src == (srctype)_tmp_dst); \ + HDassert(_tmp_src >= 0); \ + HDassert(_tmp_src == (srctype)_tmp_dst); \ (dst) = _tmp_dst; \ } @@ -1606,19 +1659,16 @@ extern H5_debug_t H5_debug_g; extern char H5libhdf5_settings[]; /* embedded library information */ /*------------------------------------------------------------------------- - * Purpose: These macros are inserted automatically just after the - * FUNC_ENTER() macro of API functions and are used to trace - * application program execution. Unless H5_DEBUG_API has been - * defined they are no-ops. - * - * Arguments: R - Return type encoded as a string - * T - Argument types encoded as a string - * A0-An - Arguments. The number at the end of the macro name - * indicates the number of arguments. + * Purpose: These macros are inserted automatically just after the + * FUNC_ENTER() macro of API functions and are used to trace + * application program execution. Unless H5_DEBUG_API has been + * defined they are no-ops. * - * Programmer: Robb Matzke + * Arguments: R - Return type encoded as a string + * T - Argument types encoded as a string + * A0-An - Arguments. The number at the end of the macro name + * indicates the number of arguments. * - * Modifications: *------------------------------------------------------------------------- */ #ifdef H5_DEBUG_API @@ -2117,6 +2167,11 @@ H5_DLL uint32_t H5_checksum_lookup3(const void *data, size_t len, uint32_t initv H5_DLL uint32_t H5_checksum_metadata(const void *data, size_t len, uint32_t initval); H5_DLL uint32_t H5_hash_string(const char *str); +/* Time related routines */ +H5_DLL time_t H5_make_time(struct tm *tm); +H5_DLL void H5_nanosleep(uint64_t nanosec); +H5_DLL double H5_get_time(void); + /* Functions for building paths, etc. */ H5_DLL herr_t H5_build_extpath(const char *name, char **extpath /*out*/); H5_DLL herr_t H5_combine_path(const char *path1, const char *path2, char **full_name /*out*/); diff --git a/src/H5system.c b/src/H5system.c index 398ffee..d0c691d 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -71,7 +71,10 @@ /* Local Variables */ /*******************/ - +/* Track whether tzset routine was called */ +static hbool_t H5_ntzset = FALSE; + + /*------------------------------------------------------------------------- * Function: HDfprintf * @@ -93,12 +96,16 @@ * Programmer: Robb Matzke * Thursday, April 9, 1998 * - * Modifications: - * Robb Matzke, 1999-07-27 - * The `%a' format refers to an argument of `haddr_t' type - * instead of `haddr_t*' and the return value is correct. *------------------------------------------------------------------------- */ +/* Disable warning for "format not a string literal" here -QAK */ +/* + * This pragma only needs to surround the fprintf() calls with + * format_templ in the code below, but early (4.4.7, at least) gcc only + * allows diagnostic pragmas to be toggled outside of functions. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" int HDfprintf(FILE *stream, const char *fmt, ...) { @@ -119,7 +126,7 @@ HDfprintf(FILE *stream, const char *fmt, ...) HDassert(stream); HDassert(fmt); - va_start (ap, fmt); + HDva_start (ap, fmt); while (*fmt) { fwidth = prec = 0; zerofill = 0; @@ -168,7 +175,7 @@ HDfprintf(FILE *stream, const char *fmt, ...) s = rest; } /* end if */ else if ('*'==*s) { - fwidth = va_arg (ap, int); + fwidth = HDva_arg(ap, int); if(fwidth < 0) { leftjust = 1; fwidth = -fwidth; @@ -183,7 +190,7 @@ HDfprintf(FILE *stream, const char *fmt, ...) prec = (int)HDstrtol(s, &rest, 10); s = rest; } else if('*'==*s) { - prec = va_arg(ap, int); + prec = HDva_arg(ap, int); s++; } if(prec < 1) @@ -265,23 +272,22 @@ HDfprintf(FILE *stream, const char *fmt, ...) len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%s", modifier); HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%c", conv); - /* Conversion */ switch (conv) { case 'd': case 'i': if(!HDstrcmp(modifier, "h")) { - short x = (short)va_arg (ap, int); - n = fprintf (stream, format_templ, x); + short x = (short)HDva_arg(ap, int); + n = fprintf(stream, format_templ, x); } else if(!*modifier) { - int x = va_arg (ap, int); - n = fprintf (stream, format_templ, x); - } else if(!HDstrcmp (modifier, "l")) { - long x = va_arg (ap, long); - n = fprintf (stream, format_templ, x); + int x = HDva_arg(ap, int); + n = fprintf(stream, format_templ, x); + } else if(!HDstrcmp(modifier, "l")) { + long x = HDva_arg(ap, long); + n = fprintf(stream, format_templ, x); } else { - int64_t x = va_arg(ap, int64_t); - n = fprintf (stream, format_templ, x); + int64_t x = HDva_arg(ap, int64_t); + n = fprintf(stream, format_templ, x); } break; @@ -290,16 +296,16 @@ HDfprintf(FILE *stream, const char *fmt, ...) case 'x': case 'X': if(!HDstrcmp(modifier, "h")) { - unsigned short x = (unsigned short)va_arg (ap, unsigned int); + unsigned short x = (unsigned short)HDva_arg(ap, unsigned int); n = fprintf(stream, format_templ, x); } else if(!*modifier) { - unsigned int x = va_arg (ap, unsigned int); /*lint !e732 Loss of sign not really occuring */ + unsigned int x = HDva_arg(ap, unsigned int); n = fprintf(stream, format_templ, x); } else if(!HDstrcmp(modifier, "l")) { - unsigned long x = va_arg (ap, unsigned long); /*lint !e732 Loss of sign not really occuring */ + unsigned long x = HDva_arg(ap, unsigned long); n = fprintf(stream, format_templ, x); } else { - uint64_t x = va_arg(ap, uint64_t); /*lint !e732 Loss of sign not really occuring */ + uint64_t x = HDva_arg(ap, uint64_t); n = fprintf(stream, format_templ, x); } break; @@ -310,10 +316,10 @@ HDfprintf(FILE *stream, const char *fmt, ...) case 'g': case 'G': if(!HDstrcmp(modifier, "h")) { - float x = (float)va_arg(ap, double); - n = fprintf(stream, format_templ, x); + float x = (float)HDva_arg(ap, double); + n = fprintf(stream, format_templ, (double)x); } else if(!*modifier || !HDstrcmp(modifier, "l")) { - double x = va_arg(ap, double); + double x = HDva_arg(ap, double); n = fprintf(stream, format_templ, x); } else { /* @@ -321,10 +327,10 @@ HDfprintf(FILE *stream, const char *fmt, ...) * `double' are the same thing. */ #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE - long double x = va_arg(ap, long double); + long double x = HDva_arg(ap, long double); n = fprintf(stream, format_templ, x); #else - double x = va_arg(ap, double); + double x = HDva_arg(ap, double); n = fprintf(stream, format_templ, x); #endif } @@ -332,7 +338,7 @@ HDfprintf(FILE *stream, const char *fmt, ...) case 'a': { - haddr_t x = va_arg (ap, haddr_t); /*lint !e732 Loss of sign not really occuring */ + haddr_t x = HDva_arg(ap, haddr_t); if(H5F_addr_defined(x)) { len = 0; @@ -378,7 +384,7 @@ HDfprintf(FILE *stream, const char *fmt, ...) case 'c': { - char x = (char)va_arg(ap, int); + char x = (char)HDva_arg(ap, int); n = fprintf(stream, format_templ, x); } break; @@ -386,7 +392,7 @@ HDfprintf(FILE *stream, const char *fmt, ...) case 's': case 'p': { - char *x = va_arg(ap, char*); /*lint !e64 Type mismatch not really occuring */ + char *x = HDva_arg(ap, char*); n = fprintf(stream, format_templ, x); } break; @@ -398,10 +404,10 @@ HDfprintf(FILE *stream, const char *fmt, ...) case 't': { - htri_t tri_var = va_arg(ap, htri_t); + htri_t tri_var = HDva_arg(ap, htri_t); if(tri_var > 0) - fprintf (stream, "TRUE"); + fprintf(stream, "TRUE"); else if(!tri_var) fprintf(stream, "FALSE"); else @@ -422,11 +428,12 @@ HDfprintf(FILE *stream, const char *fmt, ...) nout++; } } - va_end(ap); + HDva_end(ap); return nout; } /* end HDfprintf() */ +#pragma GCC diagnostic pop + - /*------------------------------------------------------------------------- * Function: HDstrtoll * @@ -491,7 +498,8 @@ HDstrtoll(const char *s, const char **rest, int base) /* Optional minus or plus sign */ if ('+'==*s) { s++; - } else if ('-'==*s) { + } + else if ('-'==*s) { sign = -1; s++; } @@ -500,10 +508,12 @@ HDstrtoll(const char *s, const char **rest, int base) if (0==base && '0'==*s && ('x'==s[1] || 'X'==s[1])) { base = 16; s += 2; - } else if (0==base && '0'==*s) { + } + else if (0==base && '0'==*s) { base = 8; s++; - } else if (0==base) { + } + else if (0==base) { base = 10; } @@ -524,7 +534,8 @@ HDstrtoll(const char *s, const char **rest, int base) if (acc*base+digit < acc) { overflow = TRUE; - } else { + } + else { acc = acc*base + digit; } } @@ -535,7 +546,8 @@ HDstrtoll(const char *s, const char **rest, int base) if (overflow) { if (sign>0) { acc = ((uint64_t)1<<(8*sizeof(int64_t)-1))-1; - } else { + } + else { acc = (int64_t)((uint64_t)1<<(8*sizeof(int64_t)-1)); } errno = ERANGE; @@ -548,7 +560,7 @@ HDstrtoll(const char *s, const char **rest, int base) return acc; } /* end HDstrtoll() */ #endif - + /*------------------------------------------------------------------------- * Function: HDrand/HDsrand * @@ -585,6 +597,91 @@ void HDsrand(unsigned int seed) /*------------------------------------------------------------------------- + * Function: H5_make_time + * + * Purpose: Portability routine to abstract converting a 'tm' struct into + * a time_t value. + * + * Note: This is a little problematic because mktime() operates on + * local times. We convert to local time and then figure out the + * adjustment based on the local time zone and daylight savings + * setting. + * + * Return: Success: The value of timezone + * Failure: -1 + * + * Programmer: Quincey Koziol + * November 18, 2015 + * + *------------------------------------------------------------------------- + */ +time_t +H5_make_time(struct tm *tm) +{ + time_t the_time; /* The converted time */ +#if defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) /* VS 2015 */ + /* In gcc and in Visual Studio prior to VS 2015 'timezone' is a global + * variable declared in time.h. That variable was deprecated and in + * VS 2015 is removed, with _get_timezone replacing it. + */ + long timezone = 0; +#endif /* defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) */ + time_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(tm); + + /* Initialize timezone information */ + if(!H5_ntzset) { + HDtzset(); + H5_ntzset = TRUE; + } /* end if */ + + /* Perform base conversion */ + if((time_t)-1 == (the_time = HDmktime(tm))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCONVERT, FAIL, "badly formatted modification time message") + + /* Adjust for timezones */ +#if defined(H5_HAVE_TM_GMTOFF) + /* BSD-like systems */ + the_time += tm->tm_gmtoff; +#elif defined(H5_HAVE_TIMEZONE) +#if defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) /* VS 2015 */ + /* In gcc and in Visual Studio prior to VS 2015 'timezone' is a global + * variable declared in time.h. That variable was deprecated and in + * VS 2015 is removed, with _get_timezone replacing it. + */ + _get_timezone(&timezone); +#endif /* defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) */ + + the_time -= timezone - (tm->tm_isdst ? 3600 : 0); +#else + /* + * The catch-all. If we can't convert a character string universal + * coordinated time to a time_t value reliably then we can't decode the + * modification time message. This really isn't as bad as it sounds -- the + * only way a user can get the modification time is from our internal + * query routines, which can gracefully recover. + */ + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "unable to obtain local timezone information") +#endif + + /* Set return value */ + ret_value = the_time; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5_make_time() */ + +#ifdef H5_HAVE_WIN32_API + +/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosecond units */ +#define _W32_FT_OFFSET (116444736000000000ULL) + + +/*------------------------------------------------------------------------- * Function: Wgettimeofday * * Purpose: Wrapper function for gettimeofday on Windows systems @@ -605,11 +702,6 @@ void HDsrand(unsigned int seed) * *------------------------------------------------------------------------- */ -#ifdef H5_HAVE_VISUAL_STUDIO - -/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosecond units */ -#define _W32_FT_OFFSET (116444736000000000ULL) - int Wgettimeofday(struct timeval *tv, struct timezone *tz) { @@ -640,7 +732,7 @@ Wgettimeofday(struct timeval *tv, struct timezone *tz) return 0; } /* end Wgettimeofday() */ - + /*------------------------------------------------------------------------- * Function: Wsetenv * @@ -700,9 +792,9 @@ int c99_snprintf(char* str, size_t size, const char* format, ...) int count; va_list ap; - va_start(ap, format); + HDva_start(ap, format); count = c99_vsnprintf(str, size, format, ap); - va_end(ap); + HDva_end(ap); return count; } @@ -719,9 +811,204 @@ int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) return count; } -#endif + /*-------------------------------------------------------------------------- + * Function: Wnanosleep + * + * Purpose: Sleep for a given # of nanoseconds (Windows version) + * + * Return: SUCCEED/FAIL + * + * Programmer: Dana Robinson + * Fall 2016 + *-------------------------------------------------------------------------- + */ +int +Wnanosleep(const struct timespec *req, struct timespec *rem) +{ + /* XXX: Currently just a placeholder */ + return 0; + +} /* end Wnanosleep() */ + + +/*------------------------------------------------------------------------- + * Function: Wllround, Wllroundf, Wlround, Wlroundf, Wround, Wroundf + * + * Purpose: Wrapper function for round functions for use with VS2012 + * and earlier. + * + * Return: The rounded value that was passed in. + * + * Programmer: Dana Robinson + * December 2016 + * + *------------------------------------------------------------------------- + */ +long long +Wllround(double arg) +{ + return (long long)(arg < 0.0 ? HDceil(arg - 0.5) : HDfloor(arg + 0.5)); +} + +long long +Wllroundf(float arg) +{ + return (long long)(arg < 0.0F ? HDceil(arg - 0.5F) : HDfloor(arg + 0.5F)); +} + +long +Wlround(double arg) +{ + return (long)(arg < 0.0 ? HDceil(arg - 0.5) : HDfloor(arg + 0.5)); +} + +long +Wlroundf(float arg) +{ + return (long)(arg < 0.0F ? HDceil(arg - 0.5F) : HDfloor(arg + 0.5F)); +} + +double +Wround(double arg) +{ + return arg < 0.0 ? HDceil(arg - 0.5) : HDfloor(arg + 0.5); +} + +float +Wroundf(float arg) +{ + return (float)(arg < 0.0F ? HDceil(arg - 0.5F) : HDfloor(arg + 0.5F)); +} + +/*------------------------------------------------------------------------- +* Function: H5_get_utf16_str +* +* Purpose: Gets a UTF-16 string from an UTF-8 (or ASCII) string. +* +* Return: Success: A pointer to a UTF-16 string +* This must be freed by the caller using H5MM_xfree() +* Failure: NULL +* +* Programmer: Dana Robinson +* Spring 2019 +* +*------------------------------------------------------------------------- +*/ +const wchar_t * +H5_get_utf16_str(const char *s) +{ + int nwchars = -1; /* Length of the UTF-16 buffer */ + wchar_t *ret_s = NULL; /* UTF-16 version of the string */ + + /* Get the number of UTF-16 characters needed */ + if(0 == (nwchars = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0))) + goto error; + + /* Allocate a buffer for the UTF-16 string */ + if(NULL == (ret_s = (wchar_t *)H5MM_calloc(sizeof(wchar_t) * (size_t)nwchars))) + goto error; + + /* Convert the input UTF-8 string to UTF-16 */ + if(0 == MultiByteToWideChar(CP_UTF8, 0, s, -1, ret_s, nwchars)) + goto error; + + return ret_s; + +error: + if(ret_s) + H5MM_xfree((void *)ret_s); + return NULL; +} /* end H5_get_utf16_str() */ + +/*------------------------------------------------------------------------- + * Function: Wopen_utf8 + * + * Purpose: UTF-8 equivalent of open(2) for use on Windows. + * Converts a UTF-8 input path to UTF-16 and then opens the + * file via _wopen() under the hood + * + * Return: Success: A POSIX file descriptor + * Failure: -1 + * + * Programmer: Dana Robinson + * Spring 2019 + * + *------------------------------------------------------------------------- + */ +int +Wopen_utf8(const char *path, int oflag, ...) +{ + int fd = -1; /* POSIX file descriptor to be returned */ + wchar_t *wpath = NULL; /* UTF-16 version of the path */ + int pmode = 0; /* mode (optionally set via variable args) */ + + /* Convert the input UTF-8 path to UTF-16 */ + if(NULL == (wpath = H5_get_utf16_str(path))) + goto done; + + /* _O_BINARY must be set in Windows to avoid CR-LF <-> LF EOL + * transformations when performing I/O. Note that this will + * produce Unix-style text files, though. + */ + oflag |= _O_BINARY; + + /* Get the mode, if O_CREAT was specified */ + if(oflag & O_CREAT) { + va_list vl; + + HDva_start(vl, oflag); + pmode = HDva_arg(vl, int); + HDva_end(vl); + } + + /* Open the file */ + fd = _wopen(wpath, oflag, pmode); + +done: + if(wpath) + H5MM_xfree((void *)wpath); + + return fd; +} /* end Wopen_utf8() */ + +/*------------------------------------------------------------------------- + * Function: Wremove_utf8 + * + * Purpose: UTF-8 equivalent of remove(3) for use on Windows. + * Converts a UTF-8 input path to UTF-16 and then opens the + * file via _wremove() under the hood + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Dana Robinson + * Spring 2019 + * + *------------------------------------------------------------------------- + */ +int +Wremove_utf8(const char *path) +{ + wchar_t *wpath = NULL; /* UTF-16 version of the path */ + int ret; + + /* Convert the input UTF-8 path to UTF-16 */ + if(NULL == (wpath = H5_get_utf16_str(path))) + goto done; + + /* Open the file */ + ret = _wremove(wpath); + +done: + if(wpath) + H5MM_xfree((void *)wpath); + + return ret; +} /* end Wremove_utf8() */ + +#endif /* H5_HAVE_WIN32_API */ + - /*------------------------------------------------------------------------- * Function: H5_build_extpath * @@ -841,7 +1128,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5_build_extpath() */ - + /*-------------------------------------------------------------------------- * Function: H5_combine_path * @@ -864,13 +1151,13 @@ H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/) FUNC_ENTER_NOAPI_NOINIT - HDassert(path1); HDassert(path2); - path1_len = HDstrlen(path1); + if(path1) + path1_len = HDstrlen(path1); path2_len = HDstrlen(path2); - if(*path1 == '\0' || H5_CHECK_ABSOLUTE(path2)) { + if(path1 == NULL || *path1 == '\0' || H5_CHECK_ABSOLUTE(path2)) { /* If path1 is empty or path2 is absolute, simply use path2 */ if(NULL == (*full_name = (char *)H5MM_strdup(path2))) @@ -914,5 +1201,111 @@ H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5_combine_name() */ +} /* end H5_combine_path() */ + + +/*-------------------------------------------------------------------------- + * Function: H5_nanosleep + * + * Purpose: Sleep for a given # of nanoseconds + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * October 01, 2016 + *-------------------------------------------------------------------------- + */ +void +H5_nanosleep(uint64_t nanosec) +{ + struct timespec sleeptime; /* Struct to hold time to sleep */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Set up time to sleep */ + sleeptime.tv_sec = 0; + sleeptime.tv_nsec = (long)nanosec; + + HDnanosleep(&sleeptime, NULL); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5_nanosleep() */ + + +/*-------------------------------------------------------------------------- + * Function: H5_get_time + * + * Purpose: Get the current time, as the time of seconds after the UNIX epoch + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * October 05, 2016 + *-------------------------------------------------------------------------- + */ +double +H5_get_time(void) +{ +#ifdef H5_HAVE_GETTIMEOFDAY + struct timeval curr_time; +#endif /* H5_HAVE_GETTIMEOFDAY */ + double ret_value = (double)0.0f; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + +#ifdef H5_HAVE_GETTIMEOFDAY + HDgettimeofday(&curr_time, NULL); + + ret_value = (double)curr_time.tv_sec + ((double)curr_time.tv_usec / (double)1000000.0f); +#endif /* H5_HAVE_GETTIMEOFDAY */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5_get_time() */ + + +#ifdef H5_HAVE_WIN32_API + +#define H5_WIN32_ENV_VAR_BUFFER_SIZE 32767 + + +/*------------------------------------------------------------------------- + * Function: H5_expand_windows_env_vars() + * + * Purpose: Replaces windows environment variables of the form %foo% + * with user-specific values. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5_expand_windows_env_vars(char **env_var) +{ + long n_chars = 0; + char *temp_buf = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Allocate buffer for expanded environment variable string */ + if (NULL == (temp_buf = (char *)H5MM_calloc((size_t)H5_WIN32_ENV_VAR_BUFFER_SIZE))) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for expanded path") + + /* Expand the environment variable string */ + if ((n_chars = ExpandEnvironmentStringsA(*env_var, temp_buf, H5_WIN32_ENV_VAR_BUFFER_SIZE)) > H5_WIN32_ENV_VAR_BUFFER_SIZE) + HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "expanded path is too long") + + if (0 == n_chars) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "failed to expand path") + + *env_var = (char *)H5MM_xfree(*env_var); + *env_var = temp_buf; + +done: + if (FAIL == ret_value && temp_buf) + temp_buf = (char *)H5MM_xfree(temp_buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5_expand_windows_env_vars() */ +#endif /* H5_HAVE_WIN32_API */ diff --git a/src/H5win32defs.h b/src/H5win32defs.h index 080c206..479e620 100644 --- a/src/H5win32defs.h +++ b/src/H5win32defs.h @@ -34,6 +34,7 @@ typedef __int64 h5_stat_size_t; #define HDaccess(F,M) _access(F,M) #define HDchdir(S) _chdir(S) #define HDclose(F) _close(F) +#define HDcreat(S,M) Wopen_utf8(S,O_CREAT|O_TRUNC|O_RDWR,M) #define HDdup(F) _dup(F) #define HDfdopen(N,S) _fdopen(N,S) #define HDfileno(F) _fileno(F) @@ -45,18 +46,26 @@ typedef __int64 h5_stat_size_t; #define HDlseek(F,O,W) _lseeki64(F,O,W) #define HDlstat(S,B) _lstati64(S,B) #define HDmkdir(S,M) _mkdir(S) +#define HDnanosleep(N, O) Wnanosleep(N, O) #define HDoff_t __int64 -/* _O_BINARY must be set in Windows to avoid CR-LF <-> LF EOL - * transformations when performing I/O. + +/* Note that the variadic HDopen macro is using a VC++ extension + * where the comma is dropped if nothing is passed to the ellipsis. */ -#define HDopen(S,F,M) _open(S,F|_O_BINARY,M) +#ifndef H5_HAVE_MINGW +#define HDopen(S,F,...) Wopen_utf8(S,F,__VA_ARGS__) +#else +#define HDopen(S,F,...) Wopen_utf8(S,F,##__VA_ARGS__) +#endif /* H5_HAVE_MINGW */ #define HDread(F,M,Z) _read(F,M,Z) +#define HDremove(S) Wremove_utf8(S) #define HDrmdir(S) _rmdir(S) #define HDsetvbuf(F,S,M,Z) setvbuf(F,S,M,(Z>1?Z:2)) #define HDsleep(S) Sleep(S*1000) #define HDstat(S,B) _stati64(S,B) #define HDstrcasecmp(A,B) _stricmp(A,B) #define HDstrdup(S) _strdup(S) +#define HDstrtok_r(X,Y,Z) strtok_s(X,Y,Z) #define HDtzset() _tzset() #define HDunlink(S) _unlink(S) #define HDwrite(F,M,Z) _write(F,M,Z) @@ -70,6 +79,11 @@ typedef __int64 h5_stat_size_t; #ifndef H5_HAVE_STRTOULL #define HDstrtoull(S,R,N) _strtoui64(S,R,N) #endif /* H5_HAVE_STRTOULL */ + /* va_copy() does not exist on pre-2013 Visual Studio. Since va_lists are + * just pointers into the stack in those CRTs, the usual work-around + * is to just define the operation as a pointer copy. + */ + #define HDva_copy(D,S) ((D) = (S)) #endif /* MSC_VER < 1800 */ /* @@ -82,6 +96,25 @@ struct timezone { int tz_dsttime; }; +/* time.h before VS2015 does not include timespec */ +#if (_MSC_VER < 1900) +struct timespec +{ + time_t tv_sec; /* Seconds - >= 0 */ + long tv_nsec; /* Nanoseconds - [0, 999999999] */ +}; +#endif /* MSC_VER < 1900 */ + +/* The round functions do not exist in VS2012 and earlier */ +#if (_MSC_VER <= 1700) +#define HDllround(V) Wllround(V) +#define HDllroundf(V) Wllroundf(V) +#define HDlround(V) Wlround(V) +#define HDlroundf(V) Wlroundf(V) +#define HDround(V) Wround(V) +#define HDroundf(V) Wroundf(V) +#endif /* MSC_VER < 1700 */ + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -90,6 +123,23 @@ extern "C" { H5_DLL char* Wgetlogin(void); H5_DLL int c99_snprintf(char* str, size_t size, const char* format, ...); H5_DLL int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap); + H5_DLL int Wnanosleep(const struct timespec *req, struct timespec *rem); + H5_DLL herr_t H5_expand_windows_env_vars(char **env_var); + H5_DLL const wchar_t *H5_get_utf16_str(const char *s); + H5_DLL int Wopen_utf8(const char *path, int oflag, ...); + H5_DLL int Wremove_utf8(const char *path); + + /* Round functions only needed for VS2012 and earlier. + * They are always built to ensure they don't go stale and + * can be deleted (along with their #defines, above) when we + * drop VS2012 support. + */ + H5_DLL long long Wllround(double arg); + H5_DLL long long Wllroundf(float arg); + H5_DLL long Wlround(double arg); + H5_DLL long Wlroundf(float arg); + H5_DLL double Wround(double arg); + H5_DLL float Wroundf(float arg); #ifdef __cplusplus } #endif /* __cplusplus */ @@ -105,7 +155,7 @@ extern "C" { * is removed, with _get_timezone replacing it. */ #define HDget_timezone(V) _get_timezone(V); -#endif +#endif /* VS 2015 */ #endif /* H5_HAVE_VISUAL_STUDIO */ |