bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* [PATCH] IBM z/OS + EBCDIC support
@ 2015-09-22  2:28 Daniel Richard G.
  2015-09-22 15:23 ` Eric Blake
                   ` (2 more replies)
  0 siblings, 3 replies; 49+ messages in thread
From: Daniel Richard G. @ 2015-09-22  2:28 UTC (permalink / raw)
  To: bug-gnulib

[-- Attachment #1: Type: text/plain, Size: 8000 bytes --]

Hello list,

The attached patch, against Git master, addresses numerous
incompatibilities in Gnulib with IBM z/OS (a mainframe operating system)
and the EBCDIC encoding.

With my changes, Gnulib builds successfully, and most of the tests
succeed. The remaining failures are as follows.

These appear to expose bugs in the system implementation, and have been
reported to IBM. (A few others have already received APAR fixes):

    FAIL: test-fdopendir
    FAIL: test-getopt
    FAIL: test-mbsrtowcs1.sh

A number of floating-point tests appear to be in the same boat. These
failure modes have yet to be evaluated:

    FAIL: test-fma2
    FAIL: test-fmaf2
    FAIL: test-fmodl-ieee
    FAIL: test-isinf
    FAIL: test-isnan
    FAIL: test-isnanl-nolibm
    FAIL: test-isnanl
    FAIL: test-ldexpf
    FAIL: test-remainderl-ieee
    FAIL: test-truncl-ieee

These require more investigation and/or discussion on this list:

    FAIL: test-perror.sh
    FAIL: test-poll
    FAIL: test-select-in.sh
    FAIL: test-select-out.sh
    FAIL: test-sigpipe.sh
    FAIL: test-symlink
    FAIL: test-symlinkat

One more issue for now: In order to build Gnulib on this system, it is
necessary to use a compiler wrapper script, due to the inexplicably
broken way xlc handles #include paths. I recently submitted some changes
to Gawk to work around this (look in the feature/zOS-try2 branch,
m4/arch.m4 file; search for "zos-cc"). It's possible that a similar
workaround will need to be bundled here.


In any event, below is a walk-through of my changes in the patch.
Comments and questions are welcome.


+++ lib/alloca.in.h

* z/OS has the alloca() definitions in stdlib.h.

+++ lib/c-ctype.c

* Implementing ctype functions that support EBCDIC from scratch is not
  feasible, not least because there isn't even one specific EBCDIC
  variant that should be targeted. So I just call through to the system
  routines, while ensuring that the compile-time environment is set
  correctly, and working around the system routines' input-range issues
  with signed chars.

* In EBCDIC, normal chars like 'A' occur in the upper half of the 8-bit
  range. This interferes with the idiom of using "switch (c)" and then
  "case 'A':" et al. because c can have two distinct values (-63 and
  193) that should match to 'A'.

  My fix, then, is a macro which converts the input codepoint to the
  range that will match literal chars, when necessary. (Obviously, in
  ASCII, it's a no-op.) Any takers on a better name for this macro than
  CHAR_LITERAL()?

+++ lib/c-ctype.h

* Ensure that ASCII optimizations are applied only when building in
  ASCII.

+++ lib/fnmatch.c

* Fixed an error from __GNUC__ not being defined.

+++ lib/get-rusage-as.c

* Added z/OS awareness.

+++ lib/glob.c

* Avoid this #define on z/OS, because...

    $ grep alloca /usr/include/stdlib.h
            #ifndef alloca
              #define alloca(x) __alloca(x)
                #pragma linkage(__alloca,builtin)
                void *__alloca(unsigned int x);

+++ lib/glthread/thread.c

* Added z/OS awareness. pthread_t does not have a .p field on z/OS, but
  this does otherwise seem to apply.

  For what it's worth, this is pthread_t, from /usr/include/sys/types.h:

          typedef struct {
                     char __[0x08];
          } pthread_t;

+++ lib/glthread/thread.h

* Best guess at a gl_thread implementation for z/OS.

+++ lib/math.in.h

* The system defines these functions as macros, and the compiler did not
  like seeing them redefined.

+++ lib/ptsname_r.c

* Likewise.

+++ lib/regex.h

* Ensure that "__string" does not expand to "1" when it is used as a
  formal parameter name.

+++ lib/string.in.h

* Likewise.

+++ lib/strtod.c

* The system strtod() sets ERANGE for some reason when parsing "0x".

* It also returns a value of 0.0 for "nan()".

+++ m4/fclose.m4

* This system has a broken fclose(); without this bit, the test-fclose
  test fails:

    $ ./test-fclose
    /path/to/gltests/test-fclose.c:74: assertion 'lseek (fd, 0, SEEK_CUR) == 3' failed
    CEE5207E The signal SIGABRT was received.
    ABORT instruction

  However, the existing conditions didn't enable it, so I added a
  host-platform check.

+++ m4/strstr.m4

* The IBM runtime sucks; signal delivery is delayed until strstr()
  exits, so this test results in a hang that can only be SIGKILL'ed.

+++ m4/wchar_h.m4

* The linker on this system cares way too much about the object file's
  original name.

  Slightly longer explanation: In 64-bit builds, the toolchain uses the
  XPLINK object format (as opposed to GOFF for 31-bit builds). XPLINK
  has the notion of CSECTs, and these are named. By default, the main
  code CSECT is named after the source-file basename. If the linker
  encounters two CSECTs with the same name, it will consider them to be
  duplicates, and discard one---even if they contain completely
  orthogonal definitions.

  This can be worked around by specifying the CSECT names explicitly
  with -qcsect=foobaz (using different values of "foobaz" for the two
  files), but IMO it is easier just to compile the two source files for
  these tests from differently-named source files in the first place.

+++ tests/infinity.h

* xlc doesn't like constant div-by-zero expressions.

+++ tests/nan.h

* z/OS, in addition to supporting IEEE floating-point, also supports an
  older "hexadecimal" format that does not support NaN. Bomb out if this
  is in use.

+++ tests/test-c-ctype.c

* We need the same CHAR_LITERAL() hack here as in c-ctype.c.

+++ tests/test-c-strcasecmp.c

* In EBCDIC-1047, the tests

    ASSERT (c_strcasecmp ("turkish", "TURK\304\260SH") < 0);
    ASSERT (c_strcasecmp ("TURK\304\260SH", "turkish") > 0);

  are actually

    ASSERT (c_strcasecmp ("turkish", "TURKD¬SH") < 0);
    ASSERT (c_strcasecmp ("TURKD¬SH", "turkish") > 0);

  which, of course, fail.

+++ tests/test-c-strncasecmp.c

* Likewise.

+++ tests/test-canonicalize-lgpl.c

* Addressed a strange z/OS corner case. This system has
  DOUBLE_SLASH_IS_DISTINCT_ROOT, yet the dev/ino numbers are the same.

+++ tests/test-iconv-utf.c

* When compiling in (normal) EBCDIC mode on z/OS, the compiler
  translates char and string literals to EBCDIC. (Numerical escapes like
  "\346" are not remapped.) This messes up the test, because the input
  strings are supposed to have their literal characters represented in
  ASCII. So I moved all the input strings to the top of the file, added
  an appropriate compiler #pragma to change the conversion behavior, and
  modified the tests to refer to these.

  (Note that a #define would not work for the input strings, because the
  text is converted at the point of use, not the point of definition.)

+++ tests/test-iconv.c

* The system iconv implementation does not recognize "ISO-8859-1", but
  it does recognize "ISO8859-1".

* Similar issue with converting input strings. (This leaves open the
  possibility that any ASSERT() failures will be reported in ISO 8859-1,
  not EBCDIC, thus resulting in gibberish on the user's terminal. But I
  kept the changes to the minimum needed to get this test to pass. I can
  do the full nine yards if desired.)

+++ tests/test-nonblocking-pipe.h

* Added z/OS awareness. (I tested this and found that exact
  boundary value; the test fails with 131072.)

+++ tests/test-nonblocking-reader.h

* Nonblocking read() returns EWOULDBLOCK on this system.

+++ tests/test-nonblocking-writer.h

* Nonblocking write() returns EWOULDBLOCK on this system.

+++ tests/test-sigpipe.sh

* Fixed an apparent typo.

+++ tests/test-wcwidth.c

* Only run ASCII-specific tests in ASCII mode.


--Daniel


-- 
Daniel Richard G. || skunk@iSKUNK.ORG
My ASCII-art .sig got a bad case of Times New Roman.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gnulib-zos-v1.patch --]
[-- Type: text/x-patch; name="gnulib-zos-v1.patch", Size: 37481 bytes --]

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 <stdlib.h>
 # else
 #  include <stddef.h>
 #  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 <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
+/* 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 <ctype.h>
+# 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 <pthread.h>
 
-#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 <sys/types.h>
 
+/* 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 _@GUARD_PREFIX@_STRING_H
 #define _@GUARD_PREFIX@_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 <stddef.h>
 
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: <stdio.h> must be included before
@@ -95,8 +101,9 @@ int main () { return zero(); }
 #include <wchar.h>
 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 <http://www.gnu.org/licenses/>.  */
 
 
+/* 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 <config.h>
 
 #include "c-strcase.h"
+#include "c-ctype.h"
 
 #include <locale.h>
 #include <string.h>
@@ -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 <config.h>
 
 #include "c-strcase.h"
+#include "c-ctype.h"
 
 #include <locale.h>
 #include <string.h>
@@ -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 <locale.h>
 #include <string.h>
 
+#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

^ permalink raw reply related	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2020-01-22  6:41 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-22  2:28 [PATCH] IBM z/OS + EBCDIC support Daniel Richard G.
2015-09-22 15:23 ` Eric Blake
2015-09-22 19:27   ` Daniel Richard G.
2015-09-22 20:00     ` Paul Eggert
2015-09-22 20:08       ` Eric Blake
2015-09-22 20:51         ` Daniel Richard G.
2015-09-22 19:32 ` Paul Eggert
2015-09-22 19:46   ` Paul Eggert
2015-09-22 20:37   ` Daniel Richard G.
2015-09-22 22:03     ` Paul Eggert
2015-09-22 23:44       ` Daniel Richard G.
2015-09-23  2:02         ` Paul Eggert
2015-09-23  6:58           ` Daniel Richard G.
2015-09-23 19:05             ` Paul Eggert
2015-09-23 19:29             ` Paul Eggert
2015-09-23 21:57               ` Daniel Richard G.
2015-09-25  7:29                 ` Paul Eggert
2015-09-26  0:25                   ` Daniel Richard G.
2015-09-26  2:49                     ` Paul Eggert
2015-09-26  4:39                       ` Daniel Richard G.
2015-09-26 16:08                         ` Ben Pfaff
2015-09-27  6:31                           ` Daniel Richard G.
2015-09-27  6:59                             ` Paul Eggert
2015-09-28  2:09                               ` Daniel Richard G.
2015-10-15  4:49                               ` Daniel Richard G.
2016-08-18  0:47                                 ` Paul Eggert
2016-08-18  8:24                                   ` Daniel Richard G.
2016-08-18  8:53                                     ` Paul Eggert
2016-08-19  8:20                                       ` Daniel Richard G.
2016-08-19 11:03                                         ` Bruno Haible
2016-08-19 19:28                                         ` Paul Eggert
2016-08-19 20:38                                           ` Daniel Richard G.
2019-12-19  4:57                                 ` z/OS configure triple Bruno Haible
2019-12-20  0:22                                   ` Daniel Richard G.
2019-12-20  6:29                                     ` Bruno Haible
2019-12-19  5:16                                 ` z/OS, iconv, and charset aliases Bruno Haible
2019-12-19  5:21                                   ` Bruno Haible
2019-12-20  4:38                                   ` Daniel Richard G.
2019-12-20  8:19                                     ` Bruno Haible
2019-12-20 18:23                                       ` Daniel Richard G.
2019-12-21  5:49                                         ` z/OS, iconv, and gperf Bruno Haible
2020-01-09  5:48                                           ` Daniel Richard G.
2020-01-19 21:52                                             ` Bruno Haible
2020-01-19 21:59                                             ` Bruno Haible
2020-01-19 22:32                                               ` Daniel Richard G.
2020-01-20  0:13                                                 ` Bruno Haible
2020-01-22  6:38                                                   ` Daniel Richard G.
2015-09-22 19:50 ` [PATCH] IBM z/OS + EBCDIC support Paul Eggert
2015-09-22 20:47   ` Daniel Richard G.

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).