diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5.c | 220 | ||||
-rw-r--r-- | src/H5mpi.c | 2 | ||||
-rw-r--r-- | src/H5private.h | 70 | ||||
-rw-r--r-- | src/H5public.h | 26 | ||||
-rw-r--r-- | src/H5system.c | 170 |
5 files changed, 383 insertions, 105 deletions
@@ -63,6 +63,10 @@ hbool_t H5_PKG_INIT_VAR = FALSE; /* Library Private Variables */ /*****************************/ +/* Library incompatible release versions */ +const unsigned VERS_RELEASE_EXCEPTIONS[] = {0}; +const unsigned VERS_RELEASE_EXCEPTIONS_SIZE = 0; + /* statically initialize block for pthread_once call used in initializing */ /* the first global mutex */ #ifdef H5_HAVE_THREADSAFE @@ -264,13 +268,13 @@ done: } /* end H5_init_library() */ /*------------------------------------------------------------------------- - * Function: H5_term_library + * Function: H5_term_library * - * Purpose: Terminate interfaces in a well-defined order due to - * dependencies among the interfaces, then terminate - * library-specific data. + * Purpose: Terminate interfaces in a well-defined order due to + * dependencies among the interfaces, then terminate + * library-specific data. * - * Return: void + * Return: void * *------------------------------------------------------------------------- */ @@ -456,22 +460,22 @@ done: } /* end H5_term_library() */ /*------------------------------------------------------------------------- - * Function: H5dont_atexit + * Function: H5dont_atexit * - * Purpose: Indicates that the library is not to clean up after itself - * when the application exits by calling exit() or returning - * from main(). This function must be called before any other - * HDF5 function or constant is used or it will have no effect. + * Purpose: Indicates that the library is not to clean up after itself + * when the application exits by calling exit() or returning + * from main(). This function must be called before any other + * HDF5 function or constant is used or it will have no effect. * - * If this function is used then certain memory buffers will not - * be de-allocated nor will open files be flushed automatically. - * The application may still call H5close() explicitly to - * accomplish these things. + * If this function is used then certain memory buffers will not + * be de-allocated nor will open files be flushed automatically. + * The application may still call H5close() explicitly to + * accomplish these things. * - * Return: Success: non-negative + * Return: Success: non-negative * - * Failure: negative if this function is called more than - * once or if it is called too late. + * Failure: negative if this function is called more than + * once or if it is called too late. * *------------------------------------------------------------------------- */ @@ -492,19 +496,19 @@ H5dont_atexit(void) } /* end H5dont_atexit() */ /*------------------------------------------------------------------------- - * Function: H5garbage_collect + * Function: H5garbage_collect * - * Purpose: Walks through all the garbage collection routines for the - * library, which are supposed to free any unused memory they have - * allocated. + * Purpose: Walks through all the garbage collection routines for the + * library, which are supposed to free any unused memory they have + * allocated. * * These should probably be registered dynamically in a linked list of * functions to call, but there aren't that many right now, so we * hard-wire them... * - * Return: Success: non-negative + * Return: Success: non-negative * - * Failure: negative + * Failure: negative * *------------------------------------------------------------------------- */ @@ -525,9 +529,9 @@ done: } /* end H5garbage_collect() */ /*------------------------------------------------------------------------- - * Function: H5set_free_list_limits + * Function: H5set_free_list_limits * - * Purpose: Sets limits on the different kinds of free lists. Setting a value + * Purpose: Sets limits on the different kinds of free lists. Setting a value * of -1 for a limit means no limit of that type. These limits are global * for the entire library. Each "global" limit only applies to free lists * of that type, so if an application sets a limit of 1 MB on each of the @@ -545,9 +549,9 @@ done: * int blk_global_lim; IN: The limit on all "block" free list memory used * int blk_list_lim; IN: The limit on memory used in each "block" free list * - * Return: Success: non-negative + * Return: Success: non-negative * - * Failure: negative + * Failure: negative * *------------------------------------------------------------------------- */ @@ -571,11 +575,11 @@ done: } /* end H5set_free_list_limits() */ /*------------------------------------------------------------------------- - * Function: H5get_free_list_sizes + * Function: H5get_free_list_sizes * - * Purpose: Gets the current size of the different kinds of free lists that - * the library uses to manage memory. The free list sizes can be set with - * H5set_free_list_limits and garbage collected with H5garbage_collect. + * Purpose: Gets the current size of the different kinds of free lists that + * the library uses to manage memory. The free list sizes can be set with + * H5set_free_list_limits and garbage collected with H5garbage_collect. * These lists are global for the entire library. * * Parameters: @@ -584,8 +588,8 @@ done: * size_t *blk_size; OUT: The current size of all "block" free list memory used * size_t *fac_size; OUT: The current size of all "factory" free list memory used * - * Return: Success: non-negative - * Failure: negative + * Return: Success: non-negative + * Failure: negative * * Programmer: Quincey Koziol * Friday, March 6, 2020 @@ -609,23 +613,23 @@ done: } /* end H5get_free_list_sizes() */ /*------------------------------------------------------------------------- - * Function: H5get_alloc_stats + * Function: H5get_alloc_stats * - * Purpose: Gets the memory allocation statistics for the library, if the - * --enable-memory-alloc-sanity-check option was given when building the + * Purpose: Gets the memory allocation statistics for the library, if the + * --enable-memory-alloc-sanity-check option was given when building the * library. Applications can check whether this option was enabled by - * detecting if the 'H5_MEMORY_ALLOC_SANITY_CHECK' macro is defined. This - * option is enabled by default for debug builds of the library and - * disabled by default for non-debug builds. If the option is not enabled, - * all the values returned with be 0. These statistics are global for the - * entire library, but don't include allocations from chunked dataset I/O - * filters or non-native VOL connectors. + * detecting if the 'H5_MEMORY_ALLOC_SANITY_CHECK' macro is defined. This + * option is enabled by default for debug builds of the library and + * disabled by default for non-debug builds. If the option is not enabled, + * all the values returned with be 0. These statistics are global for the + * entire library, but don't include allocations from chunked dataset I/O + * filters or non-native VOL connectors. * * Parameters: * H5_alloc_stats_t *stats; OUT: Memory allocation statistics * - * Return: Success: non-negative - * Failure: negative + * Return: Success: non-negative + * Failure: negative * * Programmer: Quincey Koziol * Saturday, March 7, 2020 @@ -758,12 +762,12 @@ H5__debug_mask(const char *s) #ifdef H5_HAVE_PARALLEL /*------------------------------------------------------------------------- - * Function: H5__mpi_delete_cb + * Function: H5__mpi_delete_cb * - * Purpose: Callback attribute on MPI_COMM_SELF to terminate the HDF5 + * Purpose: Callback attribute on MPI_COMM_SELF to terminate the HDF5 * library when the communicator is destroyed, i.e. on MPI_Finalize. * - * Return: MPI_SUCCESS + * Return: MPI_SUCCESS * *------------------------------------------------------------------------- */ @@ -777,18 +781,18 @@ H5__mpi_delete_cb(MPI_Comm H5_ATTR_UNUSED comm, int H5_ATTR_UNUSED keyval, void #endif /*H5_HAVE_PARALLEL*/ /*------------------------------------------------------------------------- - * Function: H5get_libversion + * Function: H5get_libversion * - * Purpose: Returns the library version numbers through arguments. MAJNUM - * will be the major revision number of the library, MINNUM the - * minor revision number, and RELNUM the release revision number. + * Purpose: Returns the library version numbers through arguments. MAJNUM + * will be the major revision number of the library, MINNUM the + * minor revision number, and RELNUM the release revision number. * - * Note: When printing an HDF5 version number it should be printed as + * Note: When printing an HDF5 version number it should be printed as * - * printf("%u.%u.%u", maj, min, rel) or - * printf("version %u.%u release %u", maj, min, rel) + * printf("%u.%u.%u", maj, min, rel) or + * printf("version %u.%u release %u", maj, min, rel) * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ @@ -813,17 +817,20 @@ done: } /* end H5get_libversion() */ /*------------------------------------------------------------------------- - * Function: H5check_version + * Function: H5check_version * - * Purpose: Verifies that the arguments match the version numbers - * compiled into the library. This function is intended to be - * called from user to verify that the versions of header files - * compiled into the application match the version of the hdf5 - * library. + * Purpose: Verifies that the arguments match the version numbers + * compiled into the library. This function is intended to be + * called from user to verify that the versions of header files + * compiled into the application match the version of the hdf5 + * library. + * Within major.minor.release version, the expectation + * is that all release versions are compatible, exceptions to + * this rule must be added to the VERS_RELEASE_EXCEPTIONS list. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: abort() + * Failure: abort() * *------------------------------------------------------------------------- */ @@ -836,6 +843,15 @@ done: "linked with a different version of static or shared HDF5 library.\n" \ "You should recompile the application or check your shared library related\n" \ "settings such as 'LD_LIBRARY_PATH'.\n" +#define RELEASE_MISMATCH_WARNING \ + "Warning! ***HDF5 library release mismatched error***\n" \ + "The HDF5 header files used to compile this application are not compatible with\n" \ + "the version used by the HDF5 library to which this application is linked.\n" \ + "Data corruption or segmentation faults may occur if the application continues.\n" \ + "This can happen when an application was compiled by one version of HDF5 but\n" \ + "linked with an incompatible version of static or shared HDF5 library.\n" \ + "You should recompile the application or check your shared library related\n" \ + "settings such as 'LD_LIBRARY_PATH'.\n" herr_t H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) @@ -864,7 +880,11 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) disable_version_check = (unsigned int)HDstrtol(s, NULL, 0); } - if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum || H5_VERS_RELEASE != relnum) { + /* H5_VERS_MAJOR and H5_VERS_MINOR must match */ + /* Cast relnum to int to avoid warning for unsigned < 0 comparison + * in first release versions */ + if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum || H5_VERS_RELEASE > (int)relnum) { + switch (disable_version_check) { case 0: HDfprintf(stderr, "%s%s", version_mismatch_warning, @@ -899,7 +919,51 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) break; } /* end switch */ - } /* end if */ + } /* end if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum || H5_VERS_RELEASE > relnum) */ + + /* H5_VERS_RELEASE should be compatible, we will only add checks for exceptions */ + if (H5_VERS_RELEASE != relnum) { + for (unsigned i = 0; i < VERS_RELEASE_EXCEPTIONS_SIZE; i++) { + /* Check for incompatible headers or incompatible library */ + if (VERS_RELEASE_EXCEPTIONS[i] == relnum || VERS_RELEASE_EXCEPTIONS[i] == H5_VERS_RELEASE) { + switch (disable_version_check) { + case 0: + HDfprintf( + stderr, "%s%s", version_mismatch_warning, + "You can, at your own risk, disable this warning by setting the environment\n" + "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n" + "Setting it to 2 or higher will suppress the warning messages totally.\n"); + /* Mention the versions we are referring to */ + HDfprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, + relnum, (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, + (unsigned)H5_VERS_RELEASE); + + /* Bail out now. */ + HDfputs("Bye...\n", stderr); + HDabort(); + case 1: + /* continue with a warning */ + /* Note that the warning message is embedded in the format string.*/ + HDfprintf(stderr, + "%s'HDF5_DISABLE_VERSION_CHECK' " + "environment variable is set to %d, application will\n" + "continue at your own risk.\n", + version_mismatch_warning, disable_version_check); + /* Mention the versions we are referring to */ + HDfprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, + relnum, (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, + (unsigned)H5_VERS_RELEASE); + break; + default: + /* 2 or higher: continue silently */ + break; + } /* end switch */ + + } /* end if */ + + } /* end for */ + + } /* end if (H5_VERS_RELEASE != relnum) */ /* Indicate that the version check has been performed */ checked = 1; @@ -944,7 +1008,7 @@ done: * is failing inexplicably, then try calling this function * first. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ @@ -965,9 +1029,9 @@ done: /*------------------------------------------------------------------------- * Function: H5close * - * Purpose: Terminate the library and release all resources. + * Purpose: Terminate the library and release all resources. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ @@ -988,9 +1052,9 @@ H5close(void) } /* end H5close() */ /*------------------------------------------------------------------------- - * Function: H5allocate_memory + * Function: H5allocate_memory * - * Purpose: Allocate a memory buffer with the semantics of malloc(). + * Purpose: Allocate a memory buffer with the semantics of malloc(). * * NOTE: This function is intended for use with filter * plugins so that all allocation and free operations @@ -1028,9 +1092,9 @@ H5allocate_memory(size_t size, hbool_t clear) } /* end H5allocate_memory() */ /*------------------------------------------------------------------------- - * Function: H5resize_memory + * Function: H5resize_memory * - * Purpose: Resize a memory buffer with the semantics of realloc(). + * Purpose: Resize a memory buffer with the semantics of realloc(). * * NOTE: This function is intended for use with filter * plugins so that all allocation and free operations @@ -1065,14 +1129,14 @@ H5resize_memory(void *mem, size_t size) } /* end H5resize_memory() */ /*------------------------------------------------------------------------- - * Function: H5free_memory + * Function: H5free_memory * - * Purpose: Frees memory allocated by the library that it is the user's + * Purpose: Frees memory allocated by the library that it is the user's * responsibility to free. Ensures that the same library * that was used to allocate the memory frees it. Passing * NULL pointers is allowed. * - * Return: SUCCEED/FAIL + * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ @@ -1089,12 +1153,12 @@ H5free_memory(void *mem) } /* end H5free_memory() */ /*------------------------------------------------------------------------- - * Function: H5is_library_threadsafe + * Function: H5is_library_threadsafe * - * Purpose: Checks to see if the library was built with thread-safety + * Purpose: Checks to see if the library was built with thread-safety * enabled. * - * Return: SUCCEED/FAIL + * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ diff --git a/src/H5mpi.c b/src/H5mpi.c index 9749721..4a8aa44 100644 --- a/src/H5mpi.c +++ b/src/H5mpi.c @@ -523,7 +523,7 @@ H5_mpio_create_large_type(hsize_t num_elements, MPI_Aint stride_bytes, MPI_Datat MPI_Type_get_extent(old_type, &unused_lb_arg, &old_extent); } - /* Set up the arguments for MPI_Type_struct constructor */ + /* Set up the arguments for MPI_Type_create_struct() */ type[0] = outer_type; type[1] = leftover_type; block_len[0] = 1; diff --git a/src/H5private.h b/src/H5private.h index 808c2ce..1fd95dc 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -31,19 +31,19 @@ #include <errno.h> #include <fcntl.h> #include <float.h> -#include <limits.h> #include <math.h> #include <signal.h> -#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* POSIX headers */ +#ifdef H5_HAVE_SYS_TIME_H +#include <sys/time.h> +#endif #ifdef H5_HAVE_UNISTD_H #include <pwd.h> #include <unistd.h> -#include <sys/types.h> #include <sys/wait.h> #endif @@ -130,22 +130,21 @@ #define H5_DEFAULT_VOL H5VL_NATIVE #ifdef H5_HAVE_WIN32_API + /* The following two defines must be before any windows headers are included */ #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */ #define NOGDI /* Exclude Graphic Display Interface macros */ -#ifdef H5_HAVE_WINSOCK2_H -#include <winsock2.h> -#endif +#include <windows.h> + +#include <direct.h> /* For _getcwd() */ +#include <io.h> /* POSIX I/O */ +#include <winsock2.h> /* For GetUserName() */ #ifdef H5_HAVE_THREADSAFE #include <process.h> /* For _beginthread() */ #endif -#include <windows.h> -#include <direct.h> /* For _getcwd() */ -#include <io.h> /* POSIX I/O */ - #endif /*H5_HAVE_WIN32_API*/ #ifndef F_OK @@ -2524,6 +2523,57 @@ H5_DLL double H5_get_time(void); 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*/); +/* getopt(3) equivalent that papers over the lack of long options on BSD + * and lack of Windows support. + */ +H5_DLLVAR int H5_opterr; /* get_option prints errors if this is on */ +H5_DLLVAR int H5_optind; /* token pointer */ +H5_DLLVAR const char *H5_optarg; /* flag argument (or value) */ + +enum h5_arg_level { + no_arg = 0, /* doesn't take an argument */ + require_arg, /* requires an argument */ + optional_arg /* argument is optional */ +}; + +/* + * get_option determines which options are specified on the command line and + * returns a pointer to any arguments possibly associated with the option in + * the ``H5_optarg'' variable. get_option returns the shortname equivalent of + * the option. The long options are specified in the following way: + * + * struct h5_long_options foo[] = { + * { "filename", require_arg, 'f' }, + * { "append", no_arg, 'a' }, + * { "width", require_arg, 'w' }, + * { NULL, 0, 0 } + * }; + * + * Long named options can have arguments specified as either: + * + * ``--param=arg'' or ``--param arg'' + * + * Short named options can have arguments specified as either: + * + * ``-w80'' or ``-w 80'' + * + * and can have more than one short named option specified at one time: + * + * -aw80 + * + * in which case those options which expect an argument need to come at the + * end. + */ +struct h5_long_options { + const char * name; /* Name of the long option */ + enum h5_arg_level has_arg; /* Whether we should look for an arg */ + char shortval; /* The shortname equivalent of long arg + * this gets returned from get_option + */ +}; + +H5_DLL int H5_get_option(int argc, const char **argv, const char *opt, const struct h5_long_options *l_opt); + #ifdef H5_HAVE_PARALLEL /* Generic MPI functions */ H5_DLL hsize_t H5_mpi_set_bigio_count(hsize_t new_count); diff --git a/src/H5public.h b/src/H5public.h index 30d297e..495af6f 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -35,22 +35,23 @@ #include <features.h> /* For setting POSIX, BSD, etc. compatibility */ #endif -#ifdef H5_HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#include <limits.h> /* For H5T_NATIVE_CHAR defn in H5Tpublic.h */ -#include <stdarg.h> /* For variadic functions in H5VLpublic.h */ - -#include <stdint.h> /* For C9x types */ - +/* C library header files for things that appear in HDF5 public headers */ #ifdef __cplusplus #define __STDC_FORMAT_MACROS #endif -#include <inttypes.h> /* C99/POSIX.1 header for uint64_t, PRIu64 */ - -#ifdef H5_HAVE_STDDEF_H +#include <inttypes.h> +#include <limits.h> +#include <stdarg.h> +#include <stdbool.h> #include <stddef.h> +#include <stdint.h> + +/* Unlike most sys/ headers, which are POSIX-only, sys/types.h is avaible + * on Windows, though it doesn't necessarily contain all the POSIX types + * we need for HDF5 (e.g. ssize_t). + */ +#ifdef H5_HAVE_SYS_TYPES_H +#include <sys/types.h> #endif #ifdef H5_HAVE_PARALLEL @@ -214,7 +215,6 @@ typedef int herr_t; * } * \endcode */ -#include <stdbool.h> typedef bool hbool_t; typedef int htri_t; diff --git a/src/H5system.c b/src/H5system.c index 4aae743..56110ea 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -487,7 +487,7 @@ Wsetenv(const char *name, const char *value, int overwrite) return (int)_putenv_s(name, value); } /* end Wsetenv() */ -#ifdef H5_HAVE_WINSOCK2_H +#ifdef H5_HAVE_WIN32_API #pragma comment(lib, "advapi32.lib") #endif @@ -572,12 +572,12 @@ char * Wgetlogin(void) { -#ifdef H5_HAVE_WINSOCK2_H +#ifdef H5_HAVE_WIN32_API DWORD bufferCount = WloginBuffer_count; if (GetUserName(Wlogin_buffer, &bufferCount) != 0) return (Wlogin_buffer); else -#endif /* H5_HAVE_WINSOCK2_H */ +#endif return NULL; } @@ -1058,3 +1058,167 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5_expand_windows_env_vars() */ #endif /* H5_HAVE_WIN32_API */ + +/* Global variables */ +int H5_opterr = 1; /* Get_option prints errors if this is on */ +int H5_optind = 1; /* Token pointer */ +const char *H5_optarg; /* Flag argument (or value) */ + +/*------------------------------------------------------------------------- + * Function: H5_get_option + * + * Purpose: Determine the command-line options a user specified. We can + * accept both short and long type command-lines. + * + * Return: Success: The short valued "name" of the command line + * parameter or EOF if there are no more + * parameters to process. + * + * Failure: A question mark. + *------------------------------------------------------------------------- + */ +int +H5_get_option(int argc, const char **argv, const char *opts, const struct h5_long_options *l_opts) +{ + static int sp = 1; /* character index in current token */ + int optopt = '?'; /* option character passed back to user */ + + if (sp == 1) { + /* check for more flag-like tokens */ + if (H5_optind >= argc || argv[H5_optind][0] != '-' || argv[H5_optind][1] == '\0') { + return EOF; + } + else if (HDstrcmp(argv[H5_optind], "--") == 0) { + H5_optind++; + return EOF; + } + } + + if (sp == 1 && argv[H5_optind][0] == '-' && argv[H5_optind][1] == '-') { + /* long command line option */ + int i; + const char ch = '='; + char * arg = HDstrdup(&argv[H5_optind][2]); + size_t arg_len = 0; + + H5_optarg = strchr(&argv[H5_optind][2], ch); + arg_len = HDstrlen(&argv[H5_optind][2]); + if (H5_optarg) { + arg_len -= HDstrlen(H5_optarg); + H5_optarg++; /* skip the equal sign */ + } + arg[arg_len] = 0; + + for (i = 0; l_opts && l_opts[i].name; i++) { + if (HDstrcmp(arg, l_opts[i].name) == 0) { + /* we've found a matching long command line flag */ + optopt = l_opts[i].shortval; + + if (l_opts[i].has_arg != no_arg) { + if (H5_optarg == NULL) { + if (l_opts[i].has_arg != optional_arg) { + if (H5_optind < (argc - 1)) + if (argv[H5_optind + 1][0] != '-') + H5_optarg = argv[++H5_optind]; + } + else if (l_opts[i].has_arg == require_arg) { + if (H5_opterr) + HDfprintf(stderr, "%s: option required for \"--%s\" flag\n", argv[0], arg); + + optopt = '?'; + } + } + } + else { + if (H5_optarg) { + if (H5_opterr) + HDfprintf(stderr, "%s: no option required for \"%s\" flag\n", argv[0], arg); + + optopt = '?'; + } + } + break; + } + } + + if (l_opts[i].name == NULL) { + /* exhausted all of the l_opts we have and still didn't match */ + if (H5_opterr) + HDfprintf(stderr, "%s: unknown option \"%s\"\n", argv[0], arg); + + optopt = '?'; + } + + H5_optind++; + sp = 1; + + HDfree(arg); + } + else { + register char *cp; /* pointer into current token */ + + /* short command line option */ + optopt = argv[H5_optind][sp]; + + if (optopt == ':' || (cp = HDstrchr(opts, optopt)) == 0) { + if (H5_opterr) + HDfprintf(stderr, "%s: unknown option \"%c\"\n", argv[0], optopt); + + /* if no chars left in this token, move to next token */ + if (argv[H5_optind][++sp] == '\0') { + H5_optind++; + sp = 1; + } + return '?'; + } + + if (*++cp == ':') { + /* if a value is expected, get it */ + if (argv[H5_optind][sp + 1] != '\0') { + /* flag value is rest of current token */ + H5_optarg = &argv[H5_optind++][sp + 1]; + } + else if (++H5_optind >= argc) { + if (H5_opterr) + HDfprintf(stderr, "%s: value expected for option \"%c\"\n", argv[0], optopt); + + optopt = '?'; + } + else { + /* flag value is next token */ + H5_optarg = argv[H5_optind++]; + } + + sp = 1; + } + /* wildcard argument */ + else if (*cp == '*') { + /* check the next argument */ + H5_optind++; + /* we do have an extra argument, check if not last */ + if ((H5_optind + 1) < argc) { + if (argv[H5_optind][0] != '-') { + H5_optarg = argv[H5_optind++]; + } + else { + H5_optarg = NULL; + } + } + else { + H5_optarg = NULL; + } + } + else { + /* set up to look at next char in token, next time */ + if (argv[H5_optind][++sp] == '\0') { + /* no more in current token, so setup next token */ + H5_optind++; + sp = 1; + } + H5_optarg = NULL; + } + } + + /* return the current flag character found */ + return optopt; +} |