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