Okay, I've split my changes into a set of patches, attached. These
patches are orthogonal and may be applied in any order:
gnulib-zos-ascii.patch: When in a non-ASCII environment, disable tests
that assume ASCII.
gnulib-zos-charset.patch: Added appropriately conditional #pragmas so
that the test strings in test-iconv-utf.c are correctly interpreted in
ASCII instead of EBCDIC (i.e. 'J' == 0x4A and not 0xD1). This issue
could be addressed in a more portable way by simply rewriting all the
ASCII literal characters as octal escapes, but then you would lose the
partial readability that the strings have now. Also, iconv_open() on
z/OS does not recognize "ISO-8859-1", but "ISO8859-1" works.
gnulib-zos-configure.patch: Changes to the Autoconf M4 code to support
z/OS. Note that fclose() is broken in a different way on z/OS than it is
on other systems, thus the special-case in fclose.m4.
gnulib-zos-cpp.patch: General preprocessor-level changes to
support z/OS.
gnulib-zos-errno.patch: Accommodate z/OS errno code preferences. (I
believe this should still be within spec; IBM is good at following the
letter if not the spirit of such things.)
gnulib-zos-pthread.patch: Rudimentary gl_thread support for z/OS.
gnulib-zos-regex-argname.patch: "__string" is not a good name to use as
an identifier on this system. A better fix would be to use a different
name (why not just "s"?), provided this can be pushed to upstream glibc.
gnulib-zos-strtod.patch: Address a couple quirks in the z/OS
implementation of strtod().
--Daniel
--
Daniel Richard G. || [email protected]
My ASCII-art .sig got a bad case of Times New Roman.
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-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
diff --git a/tests/test-iconv-utf.c b/tests/test-iconv-utf.c
index c1589f6..a769bee 100644
--- a/tests/test-iconv-utf.c
+++ b/tests/test-iconv-utf.c
@@ -27,20 +27,38 @@
#include "macros.h"
+/* If compiling on an EBCDIC system, keep the test strings in ASCII. */
+#if defined __IBMC__ && 'A' != 0x41
+# 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 +82,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 +114,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 +146,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 +178,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 +210,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 +242,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 +274,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 +306,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/m4/fclose.m4 b/m4/fclose.m4
index 6bd1ad8..e939d30 100644
--- a/m4/fclose.m4
+++ b/m4/fclose.m4
@@ -1,4 +1,4 @@
-# fclose.m4 serial 6
+# fclose.m4 serial 7
dnl Copyright (C) 2008-2015 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -7,6 +7,7 @@ dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_FCLOSE],
[
AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
gl_FUNC_FFLUSH_STDIN
if test $gl_cv_func_fflush_stdin != yes; then
@@ -17,4 +18,8 @@ AC_DEFUN([gl_FUNC_FCLOSE],
if test $REPLACE_CLOSE = 1; then
REPLACE_FCLOSE=1
fi
+
+ case "$host_os" in
+ openedition) REPLACE_FCLOSE=1 ;;
+ esac
])
diff --git a/m4/strstr.m4 b/m4/strstr.m4
index 040c0b9..e3e528d 100644
--- a/m4/strstr.m4
+++ b/m4/strstr.m4
@@ -1,4 +1,4 @@
-# strstr.m4 serial 16
+# strstr.m4 serial 17
dnl Copyright (C) 2008-2015 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -67,6 +67,12 @@ AC_DEFUN([gl_FUNC_STRSTR],
AC_CACHE_CHECK([whether strstr works in linear time],
[gl_cv_func_strstr_linear],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#ifdef __MVS__
+/* z/OS does not deliver signals while strstr() is running (thanks to
+ restrictions on its LE runtime), which prevents us from limiting the
+ running time of this test. */
+# error "This test does not work properly on z/OS"
+#endif
#include <signal.h> /* for signal */
#include <string.h> /* for strstr */
#include <stdlib.h> /* for malloc */
diff --git a/m4/wchar_h.m4 b/m4/wchar_h.m4
index 9d1b0f8..c926c4b 100644
--- a/m4/wchar_h.m4
+++ b/m4/wchar_h.m4
@@ -7,7 +7,7 @@ dnl with or without modifications, as long as this notice is preserved.
dnl Written by Eric Blake.
-# wchar_h.m4 serial 39
+# wchar_h.m4 serial 40
AC_DEFUN([gl_WCHAR_H],
[
@@ -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, 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/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/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/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/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-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-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/lib/glthread/thread.c b/lib/glthread/thread.c
index d4e2921..5923ea2 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..36a9521 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/regex.h b/lib/regex.h
index 6f3bae3..21fc00c 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..fa438a4 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..9dc6eeb 100644
--- a/lib/strtod.c
+++ b/lib/strtod.c
@@ -239,7 +239,12 @@ 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 returns ERANGE for "0x". */
+ errno = 0;
+ }
else if (end <= s + 2)
{
num = parse_number (s + 2, 16, 2, 4, 'p', &endbuf);
@@ -321,7 +326,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 || num == num)
num = NAN;
errno = saved_errno;
}