diff --git a/lib/alloca.in.h b/lib/alloca.in.h index d5664b6..6606984 100644 --- a/lib/alloca.in.h +++ b/lib/alloca.in.h @@ -51,6 +51,8 @@ extern "C" void *_alloca (unsigned short); # pragma intrinsic (_alloca) # define alloca _alloca +# elif defined __MVS__ +# include # else # include # ifdef __cplusplus diff --git a/lib/c-ctype.c b/lib/c-ctype.c index 6635d34..bbc543f 100644 --- a/lib/c-ctype.c +++ b/lib/c-ctype.c @@ -17,16 +17,54 @@ along with this program; if not, see . */ #include +/* On z/OS with EBCDIC, we punt and just use the system functions. + IBM created this mess; let them deal with it. + + Note that if we are not building with -D_ALL_SOURCE, then isascii() + interprets its input as an ASCII codepoint, even in an EBCDIC build. + + Also, the z/OS ctype functions do not handle negative-valued chars + at all (especially helpful when signed EBCDIC 'A' == -63), so we + adjust their arguments accordingly. */ +#if defined __MVS__ && !C_CTYPE_ASCII +# ifndef _ALL_SOURCE +# error "Please compile me with -D_ALL_SOURCE, or else isascii() will not work correctly with EBCDIC input." +# endif +# include +# define USE_SYSTEM_CTYPE +# define SYSTEM_CTYPE_CHAR(C) ((C) & 0xff) +#endif + /* Specification. */ #define NO_C_CTYPE_MACROS #include "c-ctype.h" +/* In EBCDIC, literal chars like 'A' may be represented by a signed + negative (-63) as well as unsigned positive (193) value. If we are + comparing a char integer value to a literal, then we want the + former to be on the same side of the "fence" as the latter. */ +#if C_CTYPE_ASCII +# define CHAR_LITERAL(C) (C) +#elif 'A' < 0 +# define CHAR_LITERAL(C) ((C) >= 128 && (C) < 256 ? (C) - 256 : (C)) +#else +# define CHAR_LITERAL(C) ((C) >= -128 && (C) < 0 ? (C) + 256 : (C)) +#endif + /* The function isascii is not locale dependent. Its use in EBCDIC is questionable. */ bool c_isascii (int c) { +#if C_CTYPE_ASCII return (c >= 0x00 && c <= 0x7f); +#elif defined USE_SYSTEM_CTYPE + /* On z/OS, the ctype functions return zero or non-zero, + not necessarily 0 or 1. */ + return isascii (SYSTEM_CTYPE_CHAR (c)) != 0; +#else +# error "No suitable implementation for c_isascii()" +#endif } bool @@ -42,8 +80,8 @@ c_isalnum (int c) || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); #endif -#else - switch (c) +#else /* Non-consecutive alphanumerics */ + switch (CHAR_LITERAL (c)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -74,7 +112,7 @@ c_isalpha (int c) return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); #endif #else - switch (c) + switch (CHAR_LITERAL (c)) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': @@ -104,8 +142,10 @@ c_iscntrl (int c) { #if C_CTYPE_ASCII return ((c & ~0x1f) == 0 || c == 0x7f); +#elif defined USE_SYSTEM_CTYPE + return iscntrl(SYSTEM_CTYPE_CHAR (c)) != 0; #else - switch (c) + switch (CHAR_LITERAL (c)) { case ' ': case '!': case '"': case '#': case '$': case '%': case '&': case '\'': case '(': case ')': case '*': case '+': @@ -137,9 +177,9 @@ bool c_isdigit (int c) { #if C_CTYPE_CONSECUTIVE_DIGITS - return (c >= '0' && c <= '9'); + return (CHAR_LITERAL (c) >= '0' && CHAR_LITERAL (c) <= '9'); #else - switch (c) + switch (CHAR_LITERAL (c)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -156,7 +196,7 @@ c_islower (int c) #if C_CTYPE_CONSECUTIVE_LOWERCASE return (c >= 'a' && c <= 'z'); #else - switch (c) + switch (CHAR_LITERAL (c)) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': @@ -175,8 +215,10 @@ c_isgraph (int c) { #if C_CTYPE_ASCII return (c >= '!' && c <= '~'); +#elif defined USE_SYSTEM_CTYPE + return isgraph(SYSTEM_CTYPE_CHAR (c)) != 0; #else - switch (c) + switch (CHAR_LITERAL (c)) { case '!': case '"': case '#': case '$': case '%': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': @@ -209,8 +251,10 @@ c_isprint (int c) { #if C_CTYPE_ASCII return (c >= ' ' && c <= '~'); +#elif defined USE_SYSTEM_CTYPE + return isprint(SYSTEM_CTYPE_CHAR (c)) != 0; #else - switch (c) + switch (CHAR_LITERAL (c)) { case ' ': case '!': case '"': case '#': case '$': case '%': case '&': case '\'': case '(': case ')': case '*': case '+': @@ -245,8 +289,10 @@ c_ispunct (int c) return ((c >= '!' && c <= '~') && !((c >= '0' && c <= '9') || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'))); +#elif defined USE_SYSTEM_CTYPE + return ispunct(SYSTEM_CTYPE_CHAR (c)) != 0; #else - switch (c) + switch (CHAR_LITERAL (c)) { case '!': case '"': case '#': case '$': case '%': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': @@ -275,7 +321,7 @@ c_isupper (int c) #if C_CTYPE_CONSECUTIVE_UPPERCASE return (c >= 'A' && c <= 'Z'); #else - switch (c) + switch (CHAR_LITERAL (c)) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': @@ -303,7 +349,7 @@ c_isxdigit (int c) || (c >= 'a' && c <= 'f')); #endif #else - switch (c) + switch (CHAR_LITERAL (c)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -322,7 +368,7 @@ c_tolower (int c) #if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c); #else - switch (c) + switch (CHAR_LITERAL (c)) { case 'A': return 'a'; case 'B': return 'b'; @@ -361,7 +407,7 @@ c_toupper (int c) #if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE return (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c); #else - switch (c) + switch (CHAR_LITERAL (c)) { case 'a': return 'A'; case 'b': return 'B'; diff --git a/lib/c-ctype.h b/lib/c-ctype.h index d622973..d94f526 100644 --- a/lib/c-ctype.h +++ b/lib/c-ctype.h @@ -141,11 +141,13 @@ extern int c_toupper (int c) _GL_ATTRIBUTE_CONST; /* ASCII optimizations. */ +#ifdef C_CTYPE_ASCII #undef c_isascii #define c_isascii(c) \ ({ int __c = (c); \ (__c >= 0x00 && __c <= 0x7f); \ }) +#endif #if C_CTYPE_CONSECUTIVE_DIGITS \ && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE diff --git a/lib/fnmatch.c b/lib/fnmatch.c index a607672..58754fa 100644 --- a/lib/fnmatch.c +++ b/lib/fnmatch.c @@ -22,7 +22,7 @@ # define _GNU_SOURCE 1 #endif -#if ! defined __builtin_expect && __GNUC__ < 3 +#if ! defined __builtin_expect && defined __GNUC__ && __GNUC__ < 3 # define __builtin_expect(expr, expected) (expr) #endif diff --git a/lib/get-rusage-as.c b/lib/get-rusage-as.c index 2bad20a..4db1596 100644 --- a/lib/get-rusage-as.c +++ b/lib/get-rusage-as.c @@ -355,7 +355,7 @@ get_rusage_as_via_iterator (void) uintptr_t get_rusage_as (void) { -#if (defined __APPLE__ && defined __MACH__) || defined _AIX || defined __CYGWIN__ /* Mac OS X, AIX, Cygwin */ +#if (defined __APPLE__ && defined __MACH__) || defined _AIX || defined __CYGWIN__ || defined __MVS__ /* Mac OS X, AIX, Cygwin, z/OS */ /* get_rusage_as_via_setrlimit() does not work. Prefer get_rusage_as_via_iterator(). */ return get_rusage_as_via_iterator (); diff --git a/lib/glob.c b/lib/glob.c index ed49a9d..9fd6482 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -144,7 +144,9 @@ # define __stat64(fname, buf) stat (fname, buf) # define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag) # define struct_stat64 struct stat -# define __alloca alloca +# ifndef __MVS__ +# define __alloca alloca +# endif # define __readdir readdir # define __glob_pattern_p glob_pattern_p #endif /* _LIBC */ diff --git a/lib/glthread/thread.c b/lib/glthread/thread.c index d4e2921..28a2797 100644 --- a/lib/glthread/thread.c +++ b/lib/glthread/thread.c @@ -33,7 +33,7 @@ #include -#ifdef PTW32_VERSION +#if defined(PTW32_VERSION) || defined(__MVS__) const gl_thread_t gl_null_thread /* = { .p = NULL } */; diff --git a/lib/glthread/thread.h b/lib/glthread/thread.h index 2febe34..01ec45b 100644 --- a/lib/glthread/thread.h +++ b/lib/glthread/thread.h @@ -172,6 +172,15 @@ typedef pthread_t gl_thread_t; # define gl_thread_self_pointer() \ (pthread_in_use () ? pthread_self ().p : NULL) extern const gl_thread_t gl_null_thread; +# elif defined(__MVS__) + /* On IBM z/OS, pthread_t is a struct with an 8-byte '__' field. + The first three bytes of this field appear to uniquely identify a + pthread_t, though not necessarily representing a pointer. */ +# define gl_thread_self() \ + (pthread_in_use () ? pthread_self () : gl_null_thread) +# define gl_thread_self_pointer() \ + (pthread_in_use () ? *((void **) pthread_self ().__) : NULL) +extern const gl_thread_t gl_null_thread; # else # define gl_thread_self() \ (pthread_in_use () ? pthread_self () : (pthread_t) NULL) diff --git a/lib/math.in.h b/lib/math.in.h index 62a089a..59293fd 100644 --- a/lib/math.in.h +++ b/lib/math.in.h @@ -406,6 +406,7 @@ _GL_WARN_ON_USE (ceilf, "ceilf is unportable - " #if @GNULIB_CEIL@ # if @REPLACE_CEIL@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ceil # define ceil rpl_ceil # endif _GL_FUNCDECL_RPL (ceil, double, (double x)); @@ -753,6 +754,7 @@ _GL_WARN_ON_USE (floorf, "floorf is unportable - " #if @GNULIB_FLOOR@ # if @REPLACE_FLOOR@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef floor # define floor rpl_floor # endif _GL_FUNCDECL_RPL (floor, double, (double x)); @@ -973,6 +975,7 @@ _GL_WARN_ON_USE (frexpf, "frexpf is unportable - " #if @GNULIB_FREXP@ # if @REPLACE_FREXP@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef frexp # define frexp rpl_frexp # endif _GL_FUNCDECL_RPL (frexp, double, (double x, int *expptr) _GL_ARG_NONNULL ((2))); @@ -1958,6 +1961,7 @@ _GL_WARN_ON_USE (tanhf, "tanhf is unportable - " #if @GNULIB_TRUNCF@ # if @REPLACE_TRUNCF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef truncf # define truncf rpl_truncf # endif _GL_FUNCDECL_RPL (truncf, float, (float x)); @@ -1980,6 +1984,7 @@ _GL_WARN_ON_USE (truncf, "truncf is unportable - " #if @GNULIB_TRUNC@ # if @REPLACE_TRUNC@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef trunc # define trunc rpl_trunc # endif _GL_FUNCDECL_RPL (trunc, double, (double x)); diff --git a/lib/ptsname_r.c b/lib/ptsname_r.c index faa33fb..809388a 100644 --- a/lib/ptsname_r.c +++ b/lib/ptsname_r.c @@ -34,6 +34,11 @@ # define _PATH_DEV "/dev/" # endif +# undef __set_errno +# undef __stat +# undef __ttyname_r +# undef __ptsname_r + # define __set_errno(e) errno = (e) # define __isatty isatty # define __stat stat diff --git a/lib/regex.h b/lib/regex.h index 6f3bae3..64d7a43 100644 --- a/lib/regex.h +++ b/lib/regex.h @@ -23,6 +23,12 @@ #include +/* IBM z/OS uses -D__string=1 as an inclusion guard. */ +#if defined(__MVS__) && defined(__string) +# undef __string +# define __string __string +#endif + /* Allow the use in C++ code. */ #ifdef __cplusplus extern "C" { diff --git a/lib/string.in.h b/lib/string.in.h index b3356bb..6359ea3 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -44,6 +44,12 @@ #ifndef address@hidden@_STRING_H #define address@hidden@_STRING_H +/* IBM z/OS uses -D__string=1 as an inclusion guard. */ +#if defined(__MVS__) && defined(__string) +# undef __string +# define __string __string +#endif + /* NetBSD 5.0 mis-defines NULL. */ #include diff --git a/lib/strtod.c b/lib/strtod.c index 9fd0170..09bc76a 100644 --- a/lib/strtod.c +++ b/lib/strtod.c @@ -239,7 +239,13 @@ strtod (const char *nptr, char **endptr) if (*s == '0' && c_tolower (s[1]) == 'x') { if (! c_isxdigit (s[2 + (s[2] == '.')])) - end = s + 1; + { + end = s + 1; + + /* strtod() on z/OS is confused by "0x". */ + if (errno == ERANGE) + errno = 0; + } else if (end <= s + 2) { num = parse_number (s + 2, 16, 2, 4, 'p', &endbuf); @@ -321,7 +327,7 @@ strtod (const char *nptr, char **endptr) better to use the underlying implementation's result, since a nice implementation populates the bits of the NaN according to interpreting n-char-sequence as a hexadecimal number. */ - if (s != end) + if (s != end || !isnand(num)) num = NAN; errno = saved_errno; } diff --git a/m4/fclose.m4 b/m4/fclose.m4 index 6bd1ad8..92ba457 100644 --- a/m4/fclose.m4 +++ b/m4/fclose.m4 @@ -17,4 +17,8 @@ AC_DEFUN([gl_FUNC_FCLOSE], if test $REPLACE_CLOSE = 1; then REPLACE_FCLOSE=1 fi + + case "$host" in + *-ibm-openedition) REPLACE_FCLOSE=1 ;; + esac ]) diff --git a/m4/strstr.m4 b/m4/strstr.m4 index 040c0b9..e623e28 100644 --- a/m4/strstr.m4 +++ b/m4/strstr.m4 @@ -79,6 +79,11 @@ static void quit (int sig) { exit (sig + 128); } char *needle = (char *) malloc (m + 2); /* Failure to compile this test due to missing alarm is okay, since all such platforms (mingw) also have quadratic strstr. */ +#ifdef __MVS__ + /* Except for z/OS, which does not deliver signals while strstr() + is running (thanks to restrictions on its LE runtime). */ + return 1; +#endif signal (SIGALRM, quit); alarm (5); /* Check for quadratic performance. */ diff --git a/m4/wchar_h.m4 b/m4/wchar_h.m4 index 9d1b0f8..35ece60 100644 --- a/m4/wchar_h.m4 +++ b/m4/wchar_h.m4 @@ -81,8 +81,14 @@ AC_DEFUN([gl_WCHAR_H_INLINE_OK], extern int zero (void); int main () { return zero(); } ]])]) + dnl Do not rename the object file from conftest.$ac_objext to + dnl conftest1.$ac_objext, as this will cause the link to fail on + dnl z/OS when using the XPLINK object format (due to duplicate + dnl CSECT names). Instead, we temporarily redefine $ac_compile so + dnl that the object file has the latter name from the start. + save_ac_compile="$ac_compile" + ac_compile=`echo "$save_ac_compile" | sed s/conftest/conftest1/` if AC_TRY_EVAL([ac_compile]); then - mv conftest.$ac_objext conftest1.$ac_objext AC_LANG_CONFTEST([ AC_LANG_SOURCE([[#define wcstod renamed_wcstod /* Tru64 with Desktop Toolkit C has a bug: must be included before @@ -95,8 +101,9 @@ int main () { return zero(); } #include int zero (void) { return 0; } ]])]) + dnl See note above about renaming object files. + ac_compile=`echo "$save_ac_compile" | sed s/conftest/conftest2/` if AC_TRY_EVAL([ac_compile]); then - mv conftest.$ac_objext conftest2.$ac_objext if $CC -o conftest$ac_exeext $CFLAGS $LDFLAGS conftest1.$ac_objext conftest2.$ac_objext $LIBS >&AS_MESSAGE_LOG_FD 2>&1; then : else @@ -104,6 +111,7 @@ int zero (void) { return 0; } fi fi fi + ac_compile="$save_ac_compile" rm -f conftest1.$ac_objext conftest2.$ac_objext conftest$ac_exeext ]) if test $gl_cv_header_wchar_h_correct_inline = no; then diff --git a/tests/infinity.h b/tests/infinity.h index 45c30bd..4e8a755 100644 --- a/tests/infinity.h +++ b/tests/infinity.h @@ -17,8 +17,9 @@ /* Infinityf () returns a 'float' +Infinity. */ -/* The Microsoft MSVC 9 compiler chokes on the expression 1.0f / 0.0f. */ -#if defined _MSC_VER +/* The Microsoft MSVC 9 compiler chokes on the expression 1.0f / 0.0f. + The IBM XL C compiler on z/OS complains. */ +#if defined _MSC_VER || (defined __MVS__ && defined __IBMC__) static float Infinityf () { @@ -32,8 +33,9 @@ Infinityf () /* Infinityd () returns a 'double' +Infinity. */ -/* The Microsoft MSVC 9 compiler chokes on the expression 1.0 / 0.0. */ -#if defined _MSC_VER +/* The Microsoft MSVC 9 compiler chokes on the expression 1.0 / 0.0. + The IBM XL C compiler on z/OS complains. */ +#if defined _MSC_VER || (defined __MVS__ && defined __IBMC__) static double Infinityd () { @@ -47,9 +49,10 @@ Infinityd () /* Infinityl () returns a 'long double' +Infinity. */ -/* The Microsoft MSVC 9 compiler chokes on the expression 1.0L / 0.0L. */ -#if defined _MSC_VER -static double +/* The Microsoft MSVC 9 compiler chokes on the expression 1.0L / 0.0L. + The IBM XL C compiler on z/OS complains. */ +#if defined _MSC_VER || (defined __MVS__ && defined __IBMC__) +static long double Infinityl () { static long double zero = 0.0L; diff --git a/tests/nan.h b/tests/nan.h index 9f6819c..10b393e 100644 --- a/tests/nan.h +++ b/tests/nan.h @@ -15,11 +15,18 @@ along with this program. If not, see . */ +/* IBM z/OS supports both hexadecimal and IEEE floating-point formats. The + former does not support NaN and its isnan() implementation returns zero + for all values. */ +#if defined __MVS__ && defined __IBMC__ && !defined __BFP__ +# error "NaN is not supported with IBM's hexadecimal floating-point format; please re-compile with -qfloat=ieee" +#endif + /* NaNf () returns a 'float' not-a-number. */ /* The Compaq (ex-DEC) C 6.4 compiler and the Microsoft MSVC 9 compiler choke - on the expression 0.0 / 0.0. */ -#if defined __DECC || defined _MSC_VER + on the expression 0.0 / 0.0. The IBM XL C compiler on z/OS complains. */ +#if defined __DECC || defined _MSC_VER || (defined __MVS__ && defined __IBMC__) static float NaNf () { @@ -34,8 +41,8 @@ NaNf () /* NaNd () returns a 'double' not-a-number. */ /* The Compaq (ex-DEC) C 6.4 compiler and the Microsoft MSVC 9 compiler choke - on the expression 0.0 / 0.0. */ -#if defined __DECC || defined _MSC_VER + on the expression 0.0 / 0.0. The IBM XL C compiler on z/OS complains. */ +#if defined __DECC || defined _MSC_VER || (defined __MVS__ && defined __IBMC__) static double NaNd () { @@ -51,14 +58,15 @@ NaNd () /* On Irix 6.5, gcc 3.4.3 can't compute compile-time NaN, and needs the runtime type conversion. - The Microsoft MSVC 9 compiler chokes on the expression 0.0L / 0.0L. */ + The Microsoft MSVC 9 compiler chokes on the expression 0.0L / 0.0L. + The IBM XL C compiler on z/OS complains. */ #ifdef __sgi static long double NaNl () { double zero = 0.0; return zero / zero; } -#elif defined _MSC_VER +#elif defined _MSC_VER || (defined __MVS__ && defined __IBMC__) static long double NaNl () { diff --git a/tests/test-c-ctype.c b/tests/test-c-ctype.c index 81fe936..f7a2e39 100644 --- a/tests/test-c-ctype.c +++ b/tests/test-c-ctype.c @@ -24,6 +24,12 @@ #include "macros.h" +#if 'A' < 0 +# define CHAR_LITERAL(C) ((C) >= 128 && (C) < 256 ? (C) - 256 : (C)) +#else +# define CHAR_LITERAL(C) ((C) >= -128 && (C) < 0 ? (C) + 256 : (C)) +#endif + static void test_all (void) { @@ -31,9 +37,11 @@ test_all (void) for (c = -0x80; c < 0x100; c++) { +#ifdef C_CTYPE_ASCII ASSERT (c_isascii (c) == (c >= 0 && c < 0x80)); +#endif - switch (c) + switch (CHAR_LITERAL (c)) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': @@ -54,7 +62,7 @@ test_all (void) break; } - switch (c) + switch (CHAR_LITERAL (c)) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': @@ -73,7 +81,7 @@ test_all (void) break; } - switch (c) + switch (CHAR_LITERAL (c)) { case '\t': case ' ': ASSERT (c_isblank (c) == 1); @@ -83,9 +91,13 @@ test_all (void) break; } +#ifdef C_CTYPE_ASCII ASSERT (c_iscntrl (c) == ((c >= 0 && c < 0x20) || c == 0x7f)); +#else + ASSERT (!! c_iscntrl (c) == !! iscntrl (c & 0xff)); +#endif - switch (c) + switch (CHAR_LITERAL (c)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -96,7 +108,7 @@ test_all (void) break; } - switch (c) + switch (CHAR_LITERAL (c)) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': @@ -110,13 +122,27 @@ test_all (void) break; } +#ifdef C_CTYPE_ASCII ASSERT (c_isgraph (c) == ((c >= 0x20 && c < 0x7f) && c != ' ')); +#else + ASSERT (!! c_isgraph (c) == !! isgraph (c & 0xff)); +#endif +#ifdef C_CTYPE_ASCII ASSERT (c_isprint (c) == (c >= 0x20 && c < 0x7f)); +#else + ASSERT (!! c_isprint (c) == !! isprint (c & 0xff)); +#endif +#ifdef C_CTYPE_ASCII ASSERT (c_ispunct (c) == (c_isgraph (c) && !c_isalnum (c))); +#else + /* EBCDIC contains characters like accented letters, which fail + the above test. */ + ASSERT (!! c_ispunct (c) == !! ispunct (c & 0xff)); +#endif - switch (c) + switch (CHAR_LITERAL (c)) { case ' ': case '\t': case '\n': case '\v': case '\f': case '\r': ASSERT (c_isspace (c) == 1); @@ -126,7 +152,7 @@ test_all (void) break; } - switch (c) + switch (CHAR_LITERAL (c)) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': @@ -140,7 +166,7 @@ test_all (void) break; } - switch (c) + switch (CHAR_LITERAL (c)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -153,7 +179,7 @@ test_all (void) break; } - switch (c) + switch (CHAR_LITERAL (c)) { case 'A': ASSERT (c_tolower (c) == 'a'); diff --git a/tests/test-c-strcasecmp.c b/tests/test-c-strcasecmp.c index f7f6b43..47feac8 100644 --- a/tests/test-c-strcasecmp.c +++ b/tests/test-c-strcasecmp.c @@ -19,6 +19,7 @@ #include #include "c-strcase.h" +#include "c-ctype.h" #include #include @@ -57,9 +58,11 @@ main (int argc, char *argv[]) ASSERT (c_strcasecmp ("\303\266zg\303\274r", "\303\226ZG\303\234R") > 0); /* özgür */ ASSERT (c_strcasecmp ("\303\226ZG\303\234R", "\303\266zg\303\274r") < 0); /* özgür */ +#if C_CTYPE_ASCII /* This test shows how strings of different size cannot compare equal. */ ASSERT (c_strcasecmp ("turkish", "TURK\304\260SH") < 0); ASSERT (c_strcasecmp ("TURK\304\260SH", "turkish") > 0); +#endif return 0; } diff --git a/tests/test-c-strncasecmp.c b/tests/test-c-strncasecmp.c index 4027b5b..20c64e3 100644 --- a/tests/test-c-strncasecmp.c +++ b/tests/test-c-strncasecmp.c @@ -19,6 +19,7 @@ #include #include "c-strcase.h" +#include "c-ctype.h" #include #include @@ -71,9 +72,11 @@ main (int argc, char *argv[]) ASSERT (c_strncasecmp ("\303\266zg\303\274r", "\303\226ZG\303\234R", 99) > 0); /* özgür */ ASSERT (c_strncasecmp ("\303\226ZG\303\234R", "\303\266zg\303\274r", 99) < 0); /* özgür */ +#if C_CTYPE_ASCII /* This test shows how strings of different size cannot compare equal. */ ASSERT (c_strncasecmp ("turkish", "TURK\304\260SH", 7) < 0); ASSERT (c_strncasecmp ("TURK\304\260SH", "turkish", 7) > 0); +#endif return 0; } diff --git a/tests/test-canonicalize-lgpl.c b/tests/test-canonicalize-lgpl.c index 12d2bb0..49c0221 100644 --- a/tests/test-canonicalize-lgpl.c +++ b/tests/test-canonicalize-lgpl.c @@ -191,12 +191,16 @@ main (void) ASSERT (result2); ASSERT (stat ("/", &st1) == 0); ASSERT (stat ("//", &st2) == 0); + /* On IBM z/OS, "/" and "//" are distinct, yet they both have + st_dev == st_ino == 1. */ +#ifndef __MVS__ if (SAME_INODE (st1, st2)) { ASSERT (strcmp (result1, "/") == 0); ASSERT (strcmp (result2, "/") == 0); } else +#endif { ASSERT (strcmp (result1, "//") == 0); ASSERT (strcmp (result2, "//") == 0); diff --git a/tests/test-iconv-utf.c b/tests/test-iconv-utf.c index c1589f6..547e859 100644 --- a/tests/test-iconv-utf.c +++ b/tests/test-iconv-utf.c @@ -27,20 +27,39 @@ #include "macros.h" +/* If we're compiling on an EBCDIC-based system, we need the test strings + to remain in ASCII. */ +#if 'A' != 0x41 && defined(__IBMC__) +# pragma convert("ISO8859-1") +# define CONVERT_ENABLED +#endif + +/* The text is "Japanese (日本語) [\U0001D50D\U0001D51E\U0001D52D]". */ + +const char test_utf8_string[] = "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; + +const char test_utf16be_string[] = "\000J\000a\000p\000a\000n\000e\000s\000e\000 \000(\145\345\147\054\212\236\000)\000 \000[\330\065\335\015\330\065\335\036\330\065\335\055\000]"; + +const char test_utf16le_string[] = "J\000a\000p\000a\000n\000e\000s\000e\000 \000(\000\345\145\054\147\236\212)\000 \000[\000\065\330\015\335\065\330\036\335\065\330\055\335]\000"; + +const char test_utf32be_string[] = "\000\000\000J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\145\345\000\000\147\054\000\000\212\236\000\000\000)\000\000\000 \000\000\000[\000\001\325\015\000\001\325\036\000\001\325\055\000\000\000]"; + +const char test_utf32le_string[] = "J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\000\345\145\000\000\054\147\000\000\236\212\000\000)\000\000\000 \000\000\000[\000\000\000\015\325\001\000\036\325\001\000\055\325\001\000]\000\000\000"; + +#ifdef CONVERT_ENABLED +# pragma convert(pop) +#endif + int main () { #if HAVE_ICONV /* Assume that iconv() supports at least the encoding UTF-8. */ - /* The text is "Japanese (日本語) [\U0001D50D\U0001D51E\U0001D52D]". */ - /* Test conversion from UTF-8 to UTF-16BE with no errors. */ { - static const char input[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; - static const char expected[] = - "\000J\000a\000p\000a\000n\000e\000s\000e\000 \000(\145\345\147\054\212\236\000)\000 \000[\330\065\335\015\330\065\335\036\330\065\335\055\000]"; +#define input test_utf8_string +#define expected test_utf16be_string iconv_t cd; char buf[100]; const char *inptr; @@ -64,14 +83,15 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } /* Test conversion from UTF-8 to UTF-16LE with no errors. */ { - static const char input[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; - static const char expected[] = - "J\000a\000p\000a\000n\000e\000s\000e\000 \000(\000\345\145\054\147\236\212)\000 \000[\000\065\330\015\335\065\330\036\335\065\330\055\335]\000"; +#define input test_utf8_string +#define expected test_utf16le_string iconv_t cd; char buf[100]; const char *inptr; @@ -95,14 +115,15 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } /* Test conversion from UTF-8 to UTF-32BE with no errors. */ { - static const char input[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; - static const char expected[] = - "\000\000\000J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\145\345\000\000\147\054\000\000\212\236\000\000\000)\000\000\000 \000\000\000[\000\001\325\015\000\001\325\036\000\001\325\055\000\000\000]"; +#define input test_utf8_string +#define expected test_utf32be_string iconv_t cd; char buf[100]; const char *inptr; @@ -126,14 +147,15 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } /* Test conversion from UTF-8 to UTF-32LE with no errors. */ { - static const char input[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; - static const char expected[] = - "J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\000\345\145\000\000\054\147\000\000\236\212\000\000)\000\000\000 \000\000\000[\000\000\000\015\325\001\000\036\325\001\000\055\325\001\000]\000\000\000"; +#define input test_utf8_string +#define expected test_utf32le_string iconv_t cd; char buf[100]; const char *inptr; @@ -157,14 +179,15 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } /* Test conversion from UTF-16BE to UTF-8 with no errors. */ { - static const char input[] = - "\000J\000a\000p\000a\000n\000e\000s\000e\000 \000(\145\345\147\054\212\236\000)\000 \000[\330\065\335\015\330\065\335\036\330\065\335\055\000]"; - static const char expected[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; +#define input test_utf16be_string +#define expected test_utf8_string iconv_t cd; char buf[100]; const char *inptr; @@ -188,14 +211,15 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } /* Test conversion from UTF-16LE to UTF-8 with no errors. */ { - static const char input[] = - "J\000a\000p\000a\000n\000e\000s\000e\000 \000(\000\345\145\054\147\236\212)\000 \000[\000\065\330\015\335\065\330\036\335\065\330\055\335]\000"; - static const char expected[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; +#define input test_utf16le_string +#define expected test_utf8_string iconv_t cd; char buf[100]; const char *inptr; @@ -219,14 +243,15 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } /* Test conversion from UTF-32BE to UTF-8 with no errors. */ { - static const char input[] = - "\000\000\000J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\145\345\000\000\147\054\000\000\212\236\000\000\000)\000\000\000 \000\000\000[\000\001\325\015\000\001\325\036\000\001\325\055\000\000\000]"; - static const char expected[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; +#define input test_utf32be_string +#define expected test_utf8_string iconv_t cd; char buf[100]; const char *inptr; @@ -250,14 +275,15 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } /* Test conversion from UTF-32LE to UTF-8 with no errors. */ { - static const char input[] = - "J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\000\345\145\000\000\054\147\000\000\236\212\000\000)\000\000\000 \000\000\000[\000\000\000\015\325\001\000\036\325\001\000\055\325\001\000]\000\000\000"; - static const char expected[] = - "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]"; +#define input test_utf32le_string +#define expected test_utf8_string iconv_t cd; char buf[100]; const char *inptr; @@ -281,6 +307,9 @@ main () ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0); ASSERT (iconv_close (cd) == 0); + +#undef input +#undef expected } #endif diff --git a/tests/test-iconv.c b/tests/test-iconv.c index ed715bd..a64c6dd 100644 --- a/tests/test-iconv.c +++ b/tests/test-iconv.c @@ -44,8 +44,14 @@ main () #if HAVE_ICONV /* Assume that iconv() supports at least the encodings ASCII, ISO-8859-1, and UTF-8. */ - iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); - iconv_t cd_utf8_to_88591 = iconv_open ("ISO-8859-1", "UTF-8"); + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO8859-1"); + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + +#if defined __MVS__ && defined __IBMC__ + /* String literals below are in ASCII, not EBCDIC. */ +# pragma convert("ISO8859-1") +# define CONVERT_ENABLED +#endif ASSERT (cd_88591_to_utf8 != (iconv_t)(-1)); ASSERT (cd_utf8_to_88591 != (iconv_t)(-1)); @@ -142,7 +148,12 @@ main () iconv_close (cd_88591_to_utf8); iconv_close (cd_utf8_to_88591); + +#ifdef CONVERT_ENABLED +# pragma convert(pop) #endif +#endif /* HAVE_ICONV */ + return 0; } diff --git a/tests/test-nonblocking-pipe.h b/tests/test-nonblocking-pipe.h index 5b3646e..01c992c 100644 --- a/tests/test-nonblocking-pipe.h +++ b/tests/test-nonblocking-pipe.h @@ -31,10 +31,11 @@ OSF/1 >= 262145 Solaris <= 7 >= 10241 Solaris >= 8 >= 20481 + z/OS >= 131073 Cygwin >= 65537 native Windows >= 4097 (depends on the _pipe argument) */ -#if defined __osf__ || (defined __linux__ && (defined __ia64__ || defined __mips__)) +#if defined __MVS__ || defined __osf__ || (defined __linux__ && (defined __ia64__ || defined __mips__)) # define PIPE_DATA_BLOCK_SIZE 270000 #elif defined __linux__ && defined __sparc__ # define PIPE_DATA_BLOCK_SIZE 140000 diff --git a/tests/test-nonblocking-reader.h b/tests/test-nonblocking-reader.h index 8cba131..d8eaa32 100644 --- a/tests/test-nonblocking-reader.h +++ b/tests/test-nonblocking-reader.h @@ -110,7 +110,7 @@ full_read_from_nonblocking_fd (size_t fd, void *buf, size_t count) ASSERT (spent_time < 0.5); if (ret < 0) { - ASSERT (saved_errno == EAGAIN); + ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK); usleep (SMALL_DELAY); } else diff --git a/tests/test-nonblocking-writer.h b/tests/test-nonblocking-writer.h index 0ecf996..ff148dc 100644 --- a/tests/test-nonblocking-writer.h +++ b/tests/test-nonblocking-writer.h @@ -124,7 +124,7 @@ main_writer_loop (int test, size_t data_block_size, int fd, (long) ret, dbgstrerror (ret < 0, saved_errno)); if (ret < 0 && bytes_written >= data_block_size) { - ASSERT (saved_errno == EAGAIN); + ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK); ASSERT (spent_time < 0.5); break; } @@ -133,7 +133,7 @@ main_writer_loop (int test, size_t data_block_size, int fd, ASSERT (spent_time < 0.5); if (ret < 0) { - ASSERT (saved_errno == EAGAIN); + ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK); usleep (SMALL_DELAY); } else @@ -165,7 +165,7 @@ main_writer_loop (int test, size_t data_block_size, int fd, ASSERT (spent_time < 0.5); if (ret < 0) { - ASSERT (saved_errno == EAGAIN); + ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK); usleep (SMALL_DELAY); } else diff --git a/tests/test-sigpipe.sh b/tests/test-sigpipe.sh index bc2baf2..6cf3242 100755 --- a/tests/test-sigpipe.sh +++ b/tests/test-sigpipe.sh @@ -21,7 +21,7 @@ fi # Test signal's behaviour when a handler is installed. tmpfiles="$tmpfiles t-sigpipeC.tmp" -./test-sigpipe${EXEEXT} B 2> t-sigpipeC.tmp | head -1 > /dev/null +./test-sigpipe${EXEEXT} C 2> t-sigpipeC.tmp | head -1 > /dev/null if test -s t-sigpipeC.tmp; then LC_ALL=C tr -d '\r' < t-sigpipeC.tmp rm -fr $tmpfiles; exit 1 diff --git a/tests/test-wcwidth.c b/tests/test-wcwidth.c index 9fad785..fdbecc3 100644 --- a/tests/test-wcwidth.c +++ b/tests/test-wcwidth.c @@ -26,6 +26,7 @@ SIGNATURE_CHECK (wcwidth, int, (wchar_t)); #include #include +#include "c-ctype.h" #include "localcharset.h" #include "macros.h" @@ -34,9 +35,11 @@ main () { wchar_t wc; +#ifdef C_CTYPE_ASCII /* Test width of ASCII characters. */ for (wc = 0x20; wc < 0x7F; wc++) ASSERT (wcwidth (wc) == 1); +#endif /* Switch to an UTF-8 locale. */ if (setlocale (LC_ALL, "fr_FR.UTF-8") != NULL