diff options
Diffstat (limited to 'src/H5system.c')
-rw-r--r-- | src/H5system.c | 1107 |
1 files changed, 426 insertions, 681 deletions
diff --git a/src/H5system.c b/src/H5system.c index e2747f4..56110ea 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -6,7 +6,7 @@ * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * distribution tree, or in https://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -25,47 +25,40 @@ /****************/ /* Module Setup */ /****************/ - +#include "H5module.h" /* This source code file is part of the H5 module */ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Fprivate.h" /* File access */ -#include "H5MMprivate.h" /* Memory management */ - +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File access */ +#include "H5MMprivate.h" /* Memory management */ /****************/ /* Local Macros */ /****************/ - /******************/ /* Local Typedefs */ /******************/ - /********************/ /* Package Typedefs */ /********************/ - /********************/ /* Local Prototypes */ /********************/ - /*********************/ /* Package Variables */ /*********************/ - /*****************************/ /* Library Private Variables */ /*****************************/ - /*******************/ /* Local Variables */ /*******************/ @@ -73,381 +66,36 @@ /* Track whether tzset routine was called */ static hbool_t H5_ntzset = FALSE; - -/*------------------------------------------------------------------------- - * Function: HDfprintf - * - * Purpose: Prints the optional arguments under the control of the format - * string FMT to the stream STREAM. This function takes the - * same format as fprintf(3c) with a few added features: - * - * The conversion modifier `H' refers to the size of an - * `hsize_t' or `hssize_t' type. For instance, "0x%018Hx" - * prints an `hsize_t' value as a hex number right justified and - * zero filled in an 18-character field. - * - * The conversion 'a' refers to an haddr_t type. - * - * The conversion 't' refers to an htri_t type. - * - * Return: Success: Number of characters printed - * - * Failure: -1 - * - * Programmer: Robb Matzke - * Thursday, April 9, 1998 - * - *------------------------------------------------------------------------- - */ -/* 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. +#ifndef H5_HAVE_VASPRINTF +/* HDvasprintf provides vasprintf-like function on targets where it is + * unavailable. */ -H5_GCC_DIAG_OFF(format-nonliteral) int -HDfprintf(FILE *stream, const char *fmt, ...) +HDvasprintf(char **bufp, const char *fmt, va_list _ap) { - int n=0, nout = 0; - int fwidth, prec; - int zerofill; - int leftjust; - int plussign; - int ldspace; - int prefix; - char modifier[8]; - int conv; - char *rest, format_templ[128]; - int len; - const char *s; - va_list ap; - - HDassert(stream); - HDassert(fmt); - - HDva_start (ap, fmt); - while (*fmt) { - fwidth = prec = 0; - zerofill = 0; - leftjust = 0; - plussign = 0; - prefix = 0; - ldspace = 0; - modifier[0] = '\0'; - - if ('%'==fmt[0] && '%'==fmt[1]) { - HDputc ('%', stream); - fmt += 2; - nout++; - } else if ('%'==fmt[0]) { - s = fmt + 1; - - /* Flags */ - while(HDstrchr("-+ #", *s)) { - switch(*s) { - case '-': - leftjust = 1; - break; - - case '+': - plussign = 1; - break; - - case ' ': - ldspace = 1; - break; - - case '#': - prefix = 1; - break; - - default: - HDassert(0 && "Unknown format flag"); - } /* end switch */ /*lint !e744 Switch statement doesn't _need_ default */ - s++; - } /* end while */ - - /* Field width */ - if(HDisdigit(*s)) { - zerofill = ('0' == *s); - fwidth = (int)HDstrtol (s, &rest, 10); - s = rest; - } /* end if */ - else if ('*'==*s) { - fwidth = HDva_arg(ap, int); - if(fwidth < 0) { - leftjust = 1; - fwidth = -fwidth; - } - s++; - } - - /* Precision */ - if('.'==*s) { - s++; - if(HDisdigit(*s)) { - prec = (int)HDstrtol(s, &rest, 10); - s = rest; - } else if('*'==*s) { - prec = HDva_arg(ap, int); - s++; - } - if(prec < 1) - prec = 1; - } - - /* Extra type modifiers */ - if(HDstrchr("zZHhlqLI", *s)) { - switch(*s) { - /*lint --e{506} Don't issue warnings about constant value booleans */ - /*lint --e{774} Don't issue warnings boolean within 'if' always evaluates false/true */ - case 'H': - if(sizeof(hsize_t) < sizeof(long)) - modifier[0] = '\0'; - else if(sizeof(hsize_t) == sizeof(long)) { - HDstrncpy(modifier, "l", sizeof(modifier)); - modifier[sizeof(modifier) - 1] = '\0'; - } /* end if */ - else { - HDstrncpy(modifier, H5_PRINTF_LL_WIDTH, sizeof(modifier)); - modifier[sizeof(modifier) - 1] = '\0'; - } /* end else */ - break; - - case 'Z': - case 'z': - if(sizeof(size_t) < sizeof(long)) - modifier[0] = '\0'; - else if(sizeof(size_t) == sizeof(long)) { - HDstrncpy(modifier, "l", sizeof(modifier)); - modifier[sizeof(modifier) - 1] = '\0'; - } /* end if */ - else { - HDstrncpy(modifier, H5_PRINTF_LL_WIDTH, sizeof(modifier)); - modifier[sizeof(modifier) - 1] = '\0'; - } /* end else */ - break; - - default: - /* Handle 'I64' modifier for Microsoft's "__int64" type */ - if(*s=='I' && *(s+1)=='6' && *(s+2)=='4') { - modifier[0] = *s; - modifier[1] = *(s+1); - modifier[2] = *(s+2); - modifier[3] = '\0'; - s += 2; /* Increment over 'I6', the '4' is taken care of below */ - } /* end if */ - else { - /* Handle 'll' for long long types */ - if(*s=='l' && *(s+1)=='l') { - modifier[0] = *s; - modifier[1] = *s; - modifier[2] = '\0'; - s++; /* Increment over first 'l', second is taken care of below */ - } /* end if */ - else { - modifier[0] = *s; - modifier[1] = '\0'; - } /* end else */ - } /* end else */ - break; - } - s++; - } - - /* Conversion */ - conv = *s++; - - /* Create the format template */ - len = 0; - len += HDsnprintf(format_templ, (sizeof(format_templ) - (size_t)(len + 1)), "%%%s%s%s%s%s", (leftjust ? "-" : ""), - (plussign ? "+" : ""), (ldspace ? " " : ""), - (prefix ? "#" : ""), (zerofill ? "0" : "")); - if(fwidth > 0) - len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%d", fwidth); - if(prec > 0) - len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), ".%d", prec); - if(*modifier) - 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)HDva_arg(ap, int); - n = fprintf(stream, format_templ, x); - } else if(!*modifier) { - 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 = HDva_arg(ap, int64_t); - n = fprintf(stream, format_templ, x); - } - break; - - case 'o': - case 'u': - case 'x': - case 'X': - if(!HDstrcmp(modifier, "h")) { - unsigned short x = (unsigned short)HDva_arg(ap, unsigned int); - n = fprintf(stream, format_templ, x); - } else if(!*modifier) { - unsigned int x = HDva_arg(ap, unsigned int); - n = fprintf(stream, format_templ, x); - } else if(!HDstrcmp(modifier, "l")) { - unsigned long x = HDva_arg(ap, unsigned long); - n = fprintf(stream, format_templ, x); - } else { - uint64_t x = HDva_arg(ap, uint64_t); - n = fprintf(stream, format_templ, x); - } - break; - - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - if(!HDstrcmp(modifier, "h")) { - float x = (float)HDva_arg(ap, double); - n = fprintf(stream, format_templ, (double)x); - } else if(!*modifier || !HDstrcmp(modifier, "l")) { - double x = HDva_arg(ap, double); - n = fprintf(stream, format_templ, x); - } else { - /* - * Some compilers complain when `long double' and - * `double' are the same thing. - */ -#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE - long double x = HDva_arg(ap, long double); - n = fprintf(stream, format_templ, x); -#else - double x = HDva_arg(ap, double); - n = fprintf(stream, format_templ, x); -#endif - } - break; - - case 'a': - { - haddr_t x = HDva_arg(ap, haddr_t); - - if(H5F_addr_defined(x)) { - len = 0; - len += HDsnprintf(format_templ, (sizeof(format_templ) - (size_t)(len + 1)), "%%%s%s%s%s%s", - (leftjust ? "-" : ""), (plussign ? "+" : ""), - (ldspace ? " " : ""), (prefix ? "#" : ""), - (zerofill ? "0" : "")); - if(fwidth > 0) - len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%d", fwidth); - - /*lint --e{506} Don't issue warnings about constant value booleans */ - /*lint --e{774} Don't issue warnings boolean within 'if' always evaluates false/true */ - if(sizeof(x) == H5_SIZEOF_INT) { - HDstrncat(format_templ, "u", (sizeof(format_templ) - (size_t)(len + 1))); - len++; - } /* end if */ - else if(sizeof(x) == H5_SIZEOF_LONG) { - HDstrncat(format_templ, "lu", (sizeof(format_templ) - (size_t)(len + 1))); - len++; - } /* end if */ - else if(sizeof(x) == H5_SIZEOF_LONG_LONG) { - HDstrncat(format_templ, H5_PRINTF_LL_WIDTH, (sizeof(format_templ) - (size_t)(len + 1))); - len += (int)sizeof(H5_PRINTF_LL_WIDTH); - HDstrncat(format_templ, "u", (sizeof(format_templ) - (size_t)(len + 1))); - len++; - } - n = fprintf(stream, format_templ, x); - } else { - len = 0; - HDstrncpy(format_templ, "%", (sizeof(format_templ) - (size_t)(len + 1))); - len++; - if(leftjust) { - HDstrncat(format_templ, "-", (sizeof(format_templ) - (size_t)(len + 1))); - len++; - } /* end if */ - if(fwidth) - len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%d", fwidth); - HDstrncat(format_templ, "s", (sizeof(format_templ) - (size_t)(len + 1))); - n = fprintf(stream, format_templ, "UNDEF"); - } - } - break; - - case 'c': - { - char x = (char)HDva_arg(ap, int); - n = fprintf(stream, format_templ, x); - } - break; - - case 's': - case 'p': - { - char *x = HDva_arg(ap, char*); - n = fprintf(stream, format_templ, x); - } - break; - - case 'n': - format_templ[HDstrlen(format_templ) - 1] = 'u'; - n = fprintf(stream, format_templ, nout); - break; - - case 't': - { - htri_t tri_var = HDva_arg(ap, htri_t); - - if(tri_var > 0) - n = fprintf(stream, "TRUE"); - else if(!tri_var) - n = fprintf(stream, "FALSE"); - else - n = fprintf(stream, "FAIL(%d)", (int)tri_var); - } - break; - - case 'T': /* Elapsed time, in seconds */ - { - double seconds = HDva_arg(ap, double); - char *time_string = H5_timer_get_time_string(seconds); - - if(time_string) { - n = fprintf(stream, format_templ, time_string); - HDfree(time_string); - } /* end if */ - else - n = fprintf(stream, format_templ, "(error)"); - } - break; - - default: - HDfputs(format_templ, stream); - n = (int)HDstrlen(format_templ); - break; - } - nout += n; - fmt = s; - } else { - HDputc(*fmt, stream); - fmt++; - nout++; + char * buf; /* buffer to receive formatted string */ + size_t bufsz; /* size of buffer to allocate */ + + for (bufsz = 32; (buf = HDmalloc(bufsz)) != NULL;) { + int ret; + va_list ap; + + HDva_copy(ap, _ap); + ret = HDvsnprintf(buf, bufsz, fmt, ap); + va_end(ap); + if (ret >= 0 && (size_t)ret < bufsz) { + *bufp = buf; + return ret; } + HDfree(buf); + if (ret < 0) + return ret; + bufsz = (size_t)ret + 1; } - HDva_end(ap); - return nout; -} /* end HDfprintf() */ -H5_GCC_DIAG_ON(format-nonliteral) + return -1; +} +#endif /* H5_HAVE_VASPRINTF */ - /*------------------------------------------------------------------------- * Function: HDstrtoll * @@ -494,61 +142,61 @@ H5_GCC_DIAG_ON(format-nonliteral) int64_t HDstrtoll(const char *s, const char **rest, int base) { - int64_t sign=1, acc=0; - hbool_t overflow = FALSE; + int64_t sign = 1, acc = 0; + hbool_t overflow = FALSE; errno = 0; - if (!s || (base && (base<2 || base>36))) { + if (!s || (base && (base < 2 || base > 36))) { if (rest) *rest = s; return 0; } /* Skip white space */ - while (HDisspace (*s)) s++; + while (HDisspace(*s)) + s++; /* Optional minus or plus sign */ - if ('+'==*s) { + if ('+' == *s) { s++; } - else if ('-'==*s) { + else if ('-' == *s) { sign = -1; s++; } /* Zero base prefix */ - if (0==base && '0'==*s && ('x'==s[1] || 'X'==s[1])) { + 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; } /* Digits */ - while ((base<=10 && *s>='0' && *s<'0'+base) || - (base>10 && ((*s>='0' && *s<='9') || - (*s>='a' && *s<'a'+base-10) || - (*s>='A' && *s<'A'+base-10)))) { + while ((base <= 10 && *s >= '0' && *s < '0' + base) || + (base > 10 && ((*s >= '0' && *s <= '9') || (*s >= 'a' && *s < 'a' + base - 10) || + (*s >= 'A' && *s < 'A' + base - 10)))) { if (!overflow) { int64_t digit = 0; - if (*s>='0' && *s<='9') + if (*s >= '0' && *s <= '9') digit = *s - '0'; - else if (*s>='a' && *s<='z') - digit = (*s-'a')+10; + else if (*s >= 'a' && *s <= 'z') + digit = (*s - 'a') + 10; else - digit = (*s-'A')+10; + digit = (*s - 'A') + 10; - if (acc*base+digit < acc) { + if (acc * base + digit < acc) { overflow = TRUE; } else { - acc = acc*base + digit; + acc = acc * base + digit; } } s++; @@ -556,11 +204,11 @@ HDstrtoll(const char *s, const char **rest, int base) /* Overflow */ if (overflow) { - if (sign>0) { - acc = ((uint64_t)1<<(8*sizeof(int64_t)-1))-1; + if (sign > 0) { + acc = ((uint64_t)1 << (8 * sizeof(int64_t) - 1)) - 1; } else { - acc = (int64_t)((uint64_t)1<<(8*sizeof(int64_t)-1)); + acc = (int64_t)((uint64_t)1 << (8 * sizeof(int64_t) - 1)); } errno = ERANGE; } @@ -572,7 +220,7 @@ HDstrtoll(const char *s, const char **rest, int base) return acc; } /* end HDstrtoll() */ #endif - + /*------------------------------------------------------------------------- * Function: HDrand/HDsrand * @@ -596,19 +244,19 @@ HDstrtoll(const char *s, const char **rest, int base) static unsigned int g_seed = 42; -int HDrand(void) +int +HDrand(void) { return rand_r(&g_seed); } -void HDsrand(unsigned int seed) +void +HDsrand(unsigned int seed) { g_seed = seed; } #endif /* H5_HAVE_RAND_R */ - - /*------------------------------------------------------------------------- * Function: Pflock * @@ -625,26 +273,27 @@ void HDsrand(unsigned int seed) */ #ifdef H5_HAVE_FCNTL int -Pflock(int fd, int operation) { +Pflock(int fd, int operation) +{ - struct flock flk; + struct flock flk; /* Set the lock type */ - if(operation & LOCK_UN) + if (operation & LOCK_UN) flk.l_type = F_UNLCK; - else if(operation & LOCK_SH) + else if (operation & LOCK_SH) flk.l_type = F_RDLCK; else flk.l_type = F_WRLCK; /* Set the other flock struct values */ flk.l_whence = SEEK_SET; - flk.l_start = 0; - flk.l_len = 0; /* to EOF */ - flk.l_pid = 0; /* not used with set */ + flk.l_start = 0; + flk.l_len = 0; /* to EOF */ + flk.l_pid = 0; /* not used with set */ /* Lock or unlock */ - if(HDfcntl(fd, F_SETLK, &flk) < 0) + if (HDfcntl(fd, F_SETLK, &flk) < 0) return -1; return 0; @@ -652,7 +301,6 @@ Pflock(int fd, int operation) { } /* end Pflock() */ #endif /* H5_HAVE_FCNTL */ - /*------------------------------------------------------------------------- * Function: Nflock * @@ -664,12 +312,12 @@ Pflock(int fd, int operation) { *------------------------------------------------------------------------- */ int H5_ATTR_CONST -Nflock(int H5_ATTR_UNUSED fd, int H5_ATTR_UNUSED operation) { +Nflock(int H5_ATTR_UNUSED fd, int H5_ATTR_UNUSED operation) +{ /* just succeed */ return 0; } /* end Nflock() */ - /*------------------------------------------------------------------------- * Function: H5_make_time * @@ -692,15 +340,15 @@ Nflock(int H5_ATTR_UNUSED fd, int H5_ATTR_UNUSED operation) { 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 */ + 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 */ +#endif /* defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) */ + time_t ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -708,21 +356,21 @@ H5_make_time(struct tm *tm) HDassert(tm); /* Initialize timezone information */ - if(!H5_ntzset) { + if (!H5_ntzset) { HDtzset(); H5_ntzset = TRUE; } /* end if */ /* Perform base conversion */ - if((time_t)-1 == (the_time = HDmktime(tm))) + if ((time_t)-1 == (the_time = HDmktime(tm))) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCONVERT, FAIL, "badly formatted modification time message") - /* Adjust for timezones */ + /* 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 */ +#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. @@ -754,7 +402,6 @@ done: /* Offset between 1/1/1601 and 1/1/1970 in 100 nanosecond units */ #define _W32_FT_OFFSET (116444736000000000ULL) - /*------------------------------------------------------------------------- * Function: Wgettimeofday * @@ -779,34 +426,33 @@ done: int Wgettimeofday(struct timeval *tv, struct timezone *tz) { - union { - unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ - FILETIME ft; - } _now; + union { + unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } _now; static int tzsetflag; - if(tv) { - GetSystemTimeAsFileTime (&_now.ft); - tv->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL ); - tv->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL); + if (tv) { + GetSystemTimeAsFileTime(&_now.ft); + tv->tv_usec = (long)((_now.ns100 / 10ULL) % 1000000ULL); + tv->tv_sec = (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL); } - if(tz) { - if(!tzsetflag) { + if (tz) { + if (!tzsetflag) { _tzset(); tzsetflag = 1; } tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; + tz->tz_dsttime = _daylight; } - /* Always return 0 as per Open Group Base Specifications Issue 6. - Do not set errno on error. */ - return 0; + /* Always return 0 as per Open Group Base Specifications Issue 6. + Do not set errno on error. */ + return 0; } /* end Wgettimeofday() */ - /*------------------------------------------------------------------------- * Function: Wsetenv * @@ -825,14 +471,14 @@ Wgettimeofday(struct timeval *tv, struct timezone *tz) int Wsetenv(const char *name, const char *value, int overwrite) { - size_t bufsize; + size_t bufsize; errno_t err; /* If we're not overwriting, check if the environment variable exists. * If it does (i.e.: the required buffer size to store the variable's * value is non-zero), then return an error code. */ - if(!overwrite) { + if (!overwrite) { err = getenv_s(&bufsize, NULL, 0, name); if (err || bufsize) return (int)err; @@ -841,11 +487,10 @@ 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 - /*------------------------------------------------------------------------- * Function: H5_get_win32_times * @@ -864,25 +509,25 @@ Wsetenv(const char *name, const char *value, int overwrite) int H5_get_win32_times(H5_timevals_t *tvs /*in,out*/) { - static HANDLE process_handle; - ULARGE_INTEGER kernel_start; - ULARGE_INTEGER user_start; - FILETIME KernelTime; - FILETIME UserTime; - FILETIME CreationTime; - FILETIME ExitTime; - LARGE_INTEGER counts_start; + static HANDLE process_handle; + ULARGE_INTEGER kernel_start; + ULARGE_INTEGER user_start; + FILETIME KernelTime; + FILETIME UserTime; + FILETIME CreationTime; + FILETIME ExitTime; + LARGE_INTEGER counts_start; static LARGE_INTEGER counts_freq; - static hbool_t is_initialized = FALSE; - BOOL err; + static hbool_t is_initialized = FALSE; + BOOL err; HDassert(tvs); - if(!is_initialized) { + if (!is_initialized) { /* NOTE: This is just a pseudo handle and does not need to be closed. */ process_handle = GetCurrentProcess(); - err = QueryPerformanceFrequency(&counts_freq); - if(0 == err) + err = QueryPerformanceFrequency(&counts_freq); + if (0 == err) return -1; is_initialized = TRUE; } /* end if */ @@ -891,28 +536,27 @@ H5_get_win32_times(H5_timevals_t *tvs /*in,out*/) * System and user times * *************************/ - err = GetProcessTimes(process_handle, &CreationTime, &ExitTime, &KernelTime, - &UserTime); - if(0 == err) + err = GetProcessTimes(process_handle, &CreationTime, &ExitTime, &KernelTime, &UserTime); + if (0 == err) return -1; /* The 1.0E7 factor seems strange but it's due to the clock * ticking in 100 ns increments. */ kernel_start.HighPart = KernelTime.dwHighDateTime; - kernel_start.LowPart = KernelTime.dwLowDateTime; - tvs->system = (double)(kernel_start.QuadPart / 1.0E7F); + kernel_start.LowPart = KernelTime.dwLowDateTime; + tvs->system = (double)(kernel_start.QuadPart / 1.0E7F); user_start.HighPart = UserTime.dwHighDateTime; - user_start.LowPart = UserTime.dwLowDateTime; - tvs->user = (double)(user_start.QuadPart / 1.0E7F); + user_start.LowPart = UserTime.dwLowDateTime; + tvs->user = (double)(user_start.QuadPart / 1.0E7F); /**************** * Elapsed time * ****************/ err = QueryPerformanceCounter(&counts_start); - if(0 == err) + if (0 == err) return -1; tvs->elapsed = (double)(counts_start.QuadPart) / (double)counts_freq.QuadPart; @@ -924,45 +568,19 @@ H5_get_win32_times(H5_timevals_t *tvs /*in,out*/) #define WloginBuffer_count 256 static char Wlogin_buffer[WloginBuffer_count]; - -char* +char * Wgetlogin(void) { -#ifdef H5_HAVE_WINSOCK2_H - long bufferCount = WloginBuffer_count; - if (GetUserName(Wlogin_buffer, &bufferCount) == 0) +#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; } -int c99_snprintf(char* str, size_t size, const char* format, ...) -{ - int count; - va_list ap; - - HDva_start(ap, format); - count = c99_vsnprintf(str, size, format, ap); - HDva_end(ap); - - return count; -} - -int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - - /*------------------------------------------------------------------------- * Function: Wflock * @@ -974,151 +592,85 @@ int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) *------------------------------------------------------------------------- */ int -Wflock(int H5_ATTR_UNUSED fd, int H5_ATTR_UNUSED operation) { - -/* This is a no-op while we implement a Win32 VFD */ -#if 0 -int -Wflock(int fd, int operation) { +Wflock(int fd, int operation) +{ - HANDLE hFile; - DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; - DWORD dwReserved = 0; - /* MAXDWORD for entire file */ - DWORD nNumberOfBytesToLockLow = MAXDWORD; - DWORD nNumberOfBytesToLockHigh = MAXDWORD; - /* Must initialize OVERLAPPED struct */ - OVERLAPPED overlapped = {0}; + HANDLE hFile; + DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; + DWORD dwReserved = 0; + /* MAXDWORD locks the entire file */ + DWORD nNumberOfBytesToLockLow = MAXDWORD; + DWORD nNumberOfBytesToLockHigh = MAXDWORD; + /* Must initialize OVERLAPPED struct */ + OVERLAPPED overlapped = {0}; /* Get Windows HANDLE */ - hFile = _get_osfhandle(fd); + if (INVALID_HANDLE_VALUE == (hFile = (HANDLE)_get_osfhandle(fd))) + return -1; /* Convert to Windows flags */ - if(operation & LOCK_EX) + if (operation & LOCK_EX) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; /* Lock or unlock */ - if(operation & LOCK_UN) - if(0 == UnlockFileEx(hFile, dwReserved, nNumberOfBytesToLockLow, - nNumberOfBytesToLockHigh, &overlapped)) - return -1; - else - if(0 == LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow, - nNumberOfBytesToLockHigh, &overlapped)) + if (operation & LOCK_UN) { + if (0 == + UnlockFileEx(hFile, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, &overlapped)) { + /* Attempting to unlock an already unlocked file will fail and this can happen + * in H5Fstart_swmr_write(). For now, just ignore the "error" (error code: 0x9e / 158). + */ + if (GetLastError() != 158) + return -1; + } + } + else { + if (0 == LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, + &overlapped)) return -1; -#endif /* 0 */ - return 0; -} /* end Wflock() */ - + } - /*-------------------------------------------------------------------------- - * 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 Wflock() */ -} /* end Wnanosleep() */ - - /*------------------------------------------------------------------------- - * Function: Wllround, Wllroundf, Wlround, Wlroundf, Wround, Wroundf + * Function: H5_get_utf16_str * - * Purpose: Wrapper function for round functions for use with VS2012 - * and earlier. + * Purpose: Gets a UTF-16 string from an UTF-8 (or ASCII) string. * - * Return: The rounded value that was passed in. + * Return: Success: A pointer to a UTF-16 string + * This must be freed by the caller using H5MM_xfree() + * Failure: NULL * * Programmer: Dana Robinson - * December 2016 + * Spring 2019 * *------------------------------------------------------------------------- */ -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 * +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 */ + 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))) + 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))) + 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)) + if (0 == MultiByteToWideChar(CP_UTF8, 0, s, -1, ret_s, nwchars)) goto error; return ret_s; error: - if(ret_s) + if (ret_s) H5MM_xfree((void *)ret_s); return NULL; -} /* end H5_get_utf16_str() */ +} /* end H5_get_utf16_str() */ /*------------------------------------------------------------------------- * Function: Wopen_utf8 @@ -1138,22 +690,22 @@ error: 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) */ + 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))) + 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. - */ + * 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) { + if (oflag & O_CREAT) { va_list vl; HDva_start(vl, oflag); @@ -1165,11 +717,11 @@ Wopen_utf8(const char *path, int oflag, ...) fd = _wopen(wpath, oflag, pmode); done: - if(wpath) + if (wpath) H5MM_xfree((void *)wpath); return fd; -} /* end Wopen_utf8() */ +} /* end Wopen_utf8() */ /*------------------------------------------------------------------------- * Function: Wremove_utf8 @@ -1189,26 +741,25 @@ done: int Wremove_utf8(const char *path) { - wchar_t *wpath = NULL; /* UTF-16 version of the path */ - int ret; + wchar_t *wpath = NULL; /* UTF-16 version of the path */ + int ret = -1; /* Convert the input UTF-8 path to UTF-16 */ - if(NULL == (wpath = H5_get_utf16_str(path))) + if (NULL == (wpath = H5_get_utf16_str(path))) goto done; /* Open the file */ ret = _wremove(wpath); done: - if(wpath) + if (wpath) H5MM_xfree((void *)wpath); return ret; -} /* end Wremove_utf8() */ +} /* end Wremove_utf8() */ #endif /* H5_HAVE_WIN32_API */ - /*------------------------------------------------------------------------- * Function: H5_build_extpath * @@ -1225,15 +776,15 @@ done: * *------------------------------------------------------------------------- */ -#define MAX_PATH_LEN 1024 +#define MAX_PATH_LEN 1024 herr_t H5_build_extpath(const char *name, char **extpath /*out*/) { - char *full_path = NULL; /* Pointer to the full path, as built or passed in */ - char *cwdpath = NULL; /* Pointer to the current working directory path */ - char *new_name = NULL; /* Pointer to the name of the file */ - herr_t ret_value = SUCCEED; /* Return value */ + char * full_path = NULL; /* Pointer to the full path, as built or passed in */ + char * cwdpath = NULL; /* Pointer to the current working directory path */ + char * new_name = NULL; /* Pointer to the name of the file */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -1248,19 +799,19 @@ H5_build_extpath(const char *name, char **extpath /*out*/) * Unix: name[0] is a "/" * Windows: name[0-2] is "<drive letter>:\" or "<drive-letter>:/" */ - if(H5_CHECK_ABSOLUTE(name)) { - if(NULL == (full_path = (char *)H5MM_strdup(name))) + if (H5_CHECK_ABSOLUTE(name)) { + if (NULL == (full_path = (char *)H5MM_strdup(name))) HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed") - } /* end if */ + } /* end if */ else { /* relative pathname */ - char *retcwd; + char * retcwd; size_t name_len; - int drive; + int drive; - if(NULL == (cwdpath = (char *)H5MM_malloc(MAX_PATH_LEN))) + if (NULL == (cwdpath = (char *)H5MM_malloc(MAX_PATH_LEN))) HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed") name_len = HDstrlen(name) + 1; - if(NULL == (new_name = (char *)H5MM_malloc(name_len))) + if (NULL == (new_name = (char *)H5MM_malloc(name_len))) HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed") /* @@ -1268,17 +819,17 @@ H5_build_extpath(const char *name, char **extpath /*out*/) * Get current working directory on the drive specified in NAME * Unix: does not apply */ - if(H5_CHECK_ABS_DRIVE(name)) { - drive = HDtoupper(name[0]) - 'A' + 1; + if (H5_CHECK_ABS_DRIVE(name)) { + drive = HDtoupper(name[0]) - 'A' + 1; retcwd = HDgetdcwd(drive, cwdpath, MAX_PATH_LEN); HDstrncpy(new_name, &name[2], name_len); } /* end if */ - /* - * Windows: name[0] is a '/' or '\' - * Get current drive - * Unix: does not apply - */ - else if(H5_CHECK_ABS_PATH(name) && (0 != (drive = HDgetdrive()))) { + /* + * Windows: name[0] is a '/' or '\' + * Get current drive + * Unix: does not apply + */ + else if (H5_CHECK_ABS_PATH(name) && (0 != (drive = HDgetdrive()))) { HDsnprintf(cwdpath, MAX_PATH_LEN, "%c:%c", (drive + 'A' - 1), name[0]); retcwd = cwdpath; HDstrncpy(new_name, &name[1], name_len); @@ -1289,7 +840,7 @@ H5_build_extpath(const char *name, char **extpath /*out*/) HDstrncpy(new_name, name, name_len); } /* end if */ - if(retcwd != NULL) { + if (retcwd != NULL) { size_t cwdlen; size_t path_len; @@ -1298,37 +849,36 @@ H5_build_extpath(const char *name, char **extpath /*out*/) HDassert(cwdlen); HDassert(new_name); path_len = cwdlen + HDstrlen(new_name) + 2; - if(NULL == (full_path = (char *)H5MM_malloc(path_len))) + if (NULL == (full_path = (char *)H5MM_malloc(path_len))) HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed") HDstrncpy(full_path, cwdpath, cwdlen + 1); - if(!H5_CHECK_DELIMITER(cwdpath[cwdlen - 1])) + if (!H5_CHECK_DELIMITER(cwdpath[cwdlen - 1])) HDstrncat(full_path, H5_DIR_SEPS, HDstrlen(H5_DIR_SEPS)); HDstrncat(full_path, new_name, HDstrlen(new_name)); } /* end if */ - } /* end else */ + } /* end else */ /* strip out the last component (the file name itself) from the path */ - if(full_path) { + if (full_path) { char *ptr = NULL; H5_GET_LAST_DELIMITER(full_path, ptr) HDassert(ptr); - *++ptr = '\0'; + *++ptr = '\0'; *extpath = full_path; } /* end if */ done: /* Release resources */ - if(cwdpath) + if (cwdpath) H5MM_xfree(cwdpath); - if(new_name) + if (new_name) H5MM_xfree(new_name); FUNC_LEAVE_NOAPI(ret_value) } /* end H5_build_extpath() */ - /*-------------------------------------------------------------------------- * Function: H5_combine_path * @@ -1343,35 +893,35 @@ done: *-------------------------------------------------------------------------- */ herr_t -H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/) +H5_combine_path(const char *path1, const char *path2, char **full_name /*out*/) { - size_t path1_len; /* length of path1 */ - size_t path2_len; /* length of path2 */ - herr_t ret_value = SUCCEED; /* Return value */ + size_t path1_len = 0; /* length of path1 */ + size_t path2_len; /* length of path2 */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT HDassert(path2); - if(path1) + if (path1) path1_len = HDstrlen(path1); path2_len = HDstrlen(path2); - if(path1 == NULL || *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))) + if (NULL == (*full_name = (char *)H5MM_strdup(path2))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") } /* end if */ - else if(H5_CHECK_ABS_PATH(path2)) { + else if (H5_CHECK_ABS_PATH(path2)) { /* On windows path2 is a path absolute name */ if (H5_CHECK_ABSOLUTE(path1) || H5_CHECK_ABS_DRIVE(path1)) { /* path1 is absolute or drive absolute and path2 is path absolute. * Use the drive letter of path1 + path2 */ - if(NULL == (*full_name = (char *)H5MM_malloc(path2_len + 3))) + if (NULL == (*full_name = (char *)H5MM_malloc(path2_len + 3))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate path2 buffer") HDsnprintf(*full_name, (path2_len + 3), "%c:%s", path1[0], path2); } /* end if */ @@ -1380,7 +930,7 @@ H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/) * path1 does not have a drive letter (i.e. is "a\b" or "\a\b"). * Use path2. */ - if(NULL == (*full_name = (char *)H5MM_strdup(path2))) + if (NULL == (*full_name = (char *)H5MM_strdup(path2))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") } /* end else */ @@ -1391,11 +941,14 @@ H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/) * Allocate a buffer to hold path1 + path2 + possibly the delimiter * + terminating null byte */ - if(NULL == (*full_name = (char *)H5MM_malloc(path1_len + path2_len + 2 + 2))) /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */ + if (NULL == + (*full_name = (char *)H5MM_malloc(path1_len + path2_len + 2 + + 2))) /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer") /* Compose the full file name */ - HDsnprintf(*full_name, (path1_len + path2_len + 2 + 2), "%s%s%s", path1, /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */ + HDsnprintf(*full_name, (path1_len + path2_len + 2 + 2), "%s%s%s", + path1, /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */ (H5_CHECK_DELIMITER(path1[path1_len - 1]) ? "" : H5_DIR_SEPS), path2); } /* end else */ @@ -1403,39 +956,67 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5_combine_path() */ - /*-------------------------------------------------------------------------- * Function: H5_nanosleep * * Purpose: Sleep for a given # of nanoseconds * - * Return: SUCCEED/FAIL + * Note that commodity hardware is probably going to have a + * resolution of milliseconds, not nanoseconds. * - * Programmer: Quincey Koziol - * October 01, 2016 + * Return: void *-------------------------------------------------------------------------- */ 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; +#ifdef H5_HAVE_WIN32_API + DWORD dwMilliseconds = (DWORD)HDceil(nanosec / 1.0e6); + DWORD ignore; - HDnanosleep(&sleeptime, NULL); + /* Windows can't sleep at a ns resolution. Best we can do is ~1 ms. We + * don't care about the return value since the second parameter + * (bAlertable) is FALSE, so it will always be zero. + */ + ignore = SleepEx(dwMilliseconds, FALSE); + +#else + + const uint64_t nanosec_per_sec = 1000 * 1000 * 1000; + struct timespec sleeptime; /* Struct to hold time to sleep */ + + /* Set up time to sleep + * + * Assuming ILP32 or LP64 or wider architecture, (long)operand + * satisfies 0 <= operand < nanosec_per_sec < LONG_MAX. + * + * It's harder to be sure that we don't overflow time_t. + */ + sleeptime.tv_sec = (time_t)(nanosec / nanosec_per_sec); + sleeptime.tv_nsec = (long)(nanosec % nanosec_per_sec); + + /* Sleep for up to `sleeptime` and, in the event of an interruption, + * save the unslept time back to `sleeptime`. + */ + while (HDnanosleep(&sleeptime, &sleeptime) == -1) { + /* If we were just interrupted, sleep for the remaining time. + * Otherwise, the error was essentially impossible, so just stop + * sleeping. + */ + if (errno != EINTR) + break; + } +#endif FUNC_LEAVE_NOAPI_VOID } /* end H5_nanosleep() */ #ifdef H5_HAVE_WIN32_API -#define H5_WIN32_ENV_VAR_BUFFER_SIZE 32767 +#define H5_WIN32_ENV_VAR_BUFFER_SIZE 32767 - /*------------------------------------------------------------------------- * Function: H5_expand_windows_env_vars() * @@ -1449,9 +1030,9 @@ H5_nanosleep(uint64_t nanosec) 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 */ + long n_chars = 0; + char * temp_buf = NULL; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -1460,7 +1041,8 @@ H5_expand_windows_env_vars(char **env_var) 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) + 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) @@ -1477,3 +1059,166 @@ done: } /* 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; +} |