autoconf: Function Portability
1
1 5.5.1 Portability of C Functions
1 --------------------------------
1
1 Most usual functions can either be missing, or be buggy, or be limited
1 on some architectures. This section tries to make an inventory of these
1 portability issues. By definition, this list always requires
1 additions. A much more complete list is maintained by the Gnulib
DONTPRINTYET 1 project (⇒Gnulib), covering *noteCurrent Posix Functions:
DONTPRINTYET 1DONTPRINTYET 1 project (⇒Gnulib), covering ⇒Current Posix Functions
(gnulib)Function Substitutes, *noteLegacy Functions: (gnulib)Legacy
DONTPRINTYET 1DONTPRINTYET 1DONTPRINTYET 1 project (⇒Gnulib), covering ⇒Current Posix Functions
(gnulib)Function Substitutes, ⇒Legacy Functions (gnulib)Legacy
Function Substitutes, and *noteGlibc Functions: (gnulib)Glibc Function
1DONTPRINTYET 1DONTPRINTYET 1DONTPRINTYET 1 project (⇒Gnulib), covering ⇒Current Posix Functions
(gnulib)Function Substitutes, ⇒Legacy Functions (gnulib)Legacy
Function Substitutes, and ⇒Glibc Functions (gnulib)Glibc Function
Substitutes. Please help us keep the gnulib list as complete as
1 possible.
1
1 `exit'
1 On ancient hosts, `exit' returned `int'. This is because `exit'
1 predates `void', and there was a long tradition of it returning
1 `int'.
1
1 On current hosts, the problem more likely is that `exit' is not
1 declared, due to C++ problems of some sort or another. For this
1 reason we suggest that test programs not invoke `exit', but return
1 from `main' instead.
1
1 `free'
1 The C standard says a call `free (NULL)' does nothing, but some
1 old systems don't support this (e.g., NextStep).
1
1 `isinf'
1 `isnan'
1 The C99 standard says that `isinf' and `isnan' are macros. On
1 some systems just macros are available (e.g., HP-UX and Solaris
1 10), on some systems both macros and functions (e.g., glibc
1 2.3.2), and on some systems only functions (e.g., IRIX 6 and
1 Solaris 9). In some cases these functions are declared in
1 nonstandard headers like `<sunmath.h>' and defined in non-default
1 libraries like `-lm' or `-lsunmath'.
1
1 The C99 `isinf' and `isnan' macros work correctly with `long
1 double' arguments, but pre-C99 systems that use functions
1 typically assume `double' arguments. On such a system, `isinf'
1 incorrectly returns true for a finite `long double' argument that
1 is outside the range of `double'.
1
1 The best workaround for these issues is to use gnulib modules
1 `isinf' and `isnan' (⇒Gnulib). But a lighter weight
1 solution involves code like the following.
1
1 #include <math.h>
1
1 #ifndef isnan
1 # define isnan(x) \
1 (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
1 : sizeof (x) == sizeof (double) ? isnan_d (x) \
1 : isnan_f (x))
1 static inline int isnan_f (float x) { return x != x; }
1 static inline int isnan_d (double x) { return x != x; }
1 static inline int isnan_ld (long double x) { return x != x; }
1 #endif
1
1 #ifndef isinf
1 # define isinf(x) \
1 (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
1 : sizeof (x) == sizeof (double) ? isinf_d (x) \
1 : isinf_f (x))
1 static inline int isinf_f (float x)
1 { return !isnan (x) && isnan (x - x); }
1 static inline int isinf_d (double x)
1 { return !isnan (x) && isnan (x - x); }
1 static inline int isinf_ld (long double x)
1 { return !isnan (x) && isnan (x - x); }
1 #endif
1
1 Use `AC_C_INLINE' (⇒C Compiler) so that this code works on
1 compilers that lack the `inline' keyword. Some optimizing
1 compilers mishandle these definitions, but systems with that bug
1 typically have many other floating point corner-case compliance
1 problems anyway, so it's probably not worth worrying about.
1
1 `malloc'
1 The C standard says a call `malloc (0)' is implementation
1 dependent. It can return either `NULL' or a new non-null pointer.
1 The latter is more common (e.g., the GNU C Library) but is by no
1 means universal. `AC_FUNC_MALLOC' can be used to insist on
1 non-`NULL' (⇒Particular Functions).
1
1 `putenv'
1 Posix prefers `setenv' to `putenv'; among other things, `putenv'
1 is not required of all Posix implementations, but `setenv' is.
1
1 Posix specifies that `putenv' puts the given string directly in
1 `environ', but some systems make a copy of it instead (e.g., glibc
1 2.0, or BSD). And when a copy is made, `unsetenv' might not free
1 it, causing a memory leak (e.g., FreeBSD 4).
1
1 On some systems `putenv ("FOO")' removes `FOO' from the
1 environment, but this is not standard usage and it dumps core on
1 some systems (e.g., AIX).
1
1 On MinGW, a call `putenv ("FOO=")' removes `FOO' from the
1 environment, rather than inserting it with an empty value.
1
1 `realloc'
1 The C standard says a call `realloc (NULL, size)' is equivalent to
1 `malloc (size)', but some old systems don't support this (e.g.,
1 NextStep).
1
1 `signal' handler
1 Normally `signal' takes a handler function with a return type of
1 `void', but some old systems required `int' instead. Any actual
1 `int' value returned is not used; this is only a difference in the
1 function prototype demanded.
1
1 All systems we know of in current use return `void'. The `int'
1 was to support K&R C, where of course `void' is not available.
1 The obsolete macro `AC_TYPE_SIGNAL' (⇒AC_TYPE_SIGNAL) can
1 be used to establish the correct type in all cases.
1
1 In most cases, it is more robust to use `sigaction' when it is
1 available, rather than `signal'.
1
1 `snprintf'
1 The C99 standard says that if the output array isn't big enough
1 and if no other errors occur, `snprintf' and `vsnprintf' truncate
1 the output and return the number of bytes that ought to have been
1 produced. Some older systems return the truncated length (e.g.,
1 GNU C Library 2.0.x or IRIX 6.5), some a negative value (e.g.,
1 earlier GNU C Library versions), and some the buffer length
1 without truncation (e.g., 32-bit Solaris 7). Also, some buggy
1 older systems ignore the length and overrun the buffer (e.g.,
1 64-bit Solaris 7).
1
1 `sprintf'
1 The C standard says `sprintf' and `vsprintf' return the number of
1 bytes written. On some ancient systems (SunOS 4 for instance)
1 they return the buffer pointer instead, but these no longer need
1 to be worried about.
1
1 `sscanf'
1 On various old systems, e.g., HP-UX 9, `sscanf' requires that its
1 input string be writable (though it doesn't actually change it).
1 This can be a problem when using `gcc' since it normally puts
11 constant strings in read-only memory (⇒Incompatibilities of
GCC (gcc)Incompatibilities.). Apparently in some cases even
1 having format strings read-only can be a problem.
1
1 `strerror_r'
1 Posix specifies that `strerror_r' returns an `int', but many
1 systems (e.g., GNU C Library version 2.2.4) provide a different
1 version returning a `char *'. `AC_FUNC_STRERROR_R' can detect
1 which is in use (⇒Particular Functions).
1
1 `strnlen'
1 AIX 4.3 provides a broken version which produces the following
1 results:
1
1 strnlen ("foobar", 0) = 0
1 strnlen ("foobar", 1) = 3
1 strnlen ("foobar", 2) = 2
1 strnlen ("foobar", 3) = 1
1 strnlen ("foobar", 4) = 0
1 strnlen ("foobar", 5) = 6
1 strnlen ("foobar", 6) = 6
1 strnlen ("foobar", 7) = 6
1 strnlen ("foobar", 8) = 6
1 strnlen ("foobar", 9) = 6
1
1 `sysconf'
1 `_SC_PAGESIZE' is standard, but some older systems (e.g., HP-UX 9)
1 have `_SC_PAGE_SIZE' instead. This can be tested with `#ifdef'.
1
1 `unlink'
1 The Posix spec says that `unlink' causes the given file to be
1 removed only after there are no more open file handles for it.
1 Some non-Posix hosts have trouble with this requirement, though,
1 and some DOS variants even corrupt the file system.
1
1 `unsetenv'
1 On MinGW, `unsetenv' is not available, but a variable `FOO' can be
1 removed with a call `putenv ("FOO=")', as described under `putenv'
1 above.
1
1 `va_copy'
1 The C99 standard provides `va_copy' for copying `va_list'
1 variables. It may be available in older environments too, though
1 possibly as `__va_copy' (e.g., `gcc' in strict pre-C99 mode).
1 These can be tested with `#ifdef'. A fallback to `memcpy (&dst,
1 &src, sizeof (va_list))' gives maximum portability.
1
1 `va_list'
1 `va_list' is not necessarily just a pointer. It can be a `struct'
1 (e.g., `gcc' on Alpha), which means `NULL' is not portable. Or it
1 can be an array (e.g., `gcc' in some PowerPC configurations),
1 which means as a function parameter it can be effectively
1 call-by-reference and library routines might modify the value back
1 in the caller (e.g., `vsnprintf' in the GNU C Library 2.1).
1
1 Signed `>>'
1 Normally the C `>>' right shift of a signed type replicates the
1 high bit, giving a so-called "arithmetic" shift. But care should
1 be taken since Standard C doesn't require that behavior. On those
1 few processors without a native arithmetic shift (for instance Cray
1 vector systems) zero bits may be shifted in, the same as a shift
1 of an unsigned type.
1
1 Integer `/'
1 C divides signed integers by truncating their quotient toward zero,
1 yielding the same result as Fortran. However, before C99 the
1 standard allowed C implementations to take the floor or ceiling of
1 the quotient in some cases. Hardly any implementations took
1 advantage of this freedom, though, and it's probably not worth
1 worrying about this issue nowadays.
1