7. Header Files

Many useful system header files are in different places in different systems, or they define different symbols. We will assume henceforth that the application has been developed on a BSD-like Unix and must be ported to a System V-like Unix or VMS or a Unix-like system with header files that comply with the Standard.

In the following sections, we show how to handle the most simple cases that arise in practice. Some of the code that appears below was derived from the header file Xos.h which is part of the X Window System distributed by MIT. We have added changes, e.g., to support VMS.

Many header files are unprotected in many systems, notably those derived from BSD version 4.2 and earlier. By "unprotected" we mean that an attempt to include a header file more than once will either cause compilation errors (e.g., due to recursive or nested includes) or, in some implementations, warnings from the preprocessor stating that symbols are being redefined. It is good practice to protect header files.

7.1. ctype.h

ctype.h provides almost the same functionality on all systems, except that some symbols must be renamed.

#ifdef SYSV
#  define  _ctype_  _ctype
#  define  toupper  _toupper
#  define  tolower  _tolower
#endif

Under Sys V, toupper and tolower are also defined and will check the validity of their arguments and perform the conversion only if necessary. Under BSD-derived systems, one must normally remember to check the validity of the arguments. The following solution might be acceptable to most:

#ifdef SYSV
#  define  TOUPPER(c)  toupper(c)
#else /* !SYSV */
#  define  TOUPPER(c)  (islower(c)?toupper(c):(c))
#endif

The definitions in <ctype.h> are not portable across character sets.

7.2. fcntl.h and sys/file.h

Many files that a BSD-like system expects to find in the sys directory are placed in /usr/include in System V. Other systems, such as VMS, do not even have a sys directory. (9)

The symbols used in the open function call are defined in different header files in the two types of systems:

#ifdef  SYSV
#  include <fcntl.h>
#else
#  include <sys/file.h>
#endif

In some systems, e.g., BSD 4.3 and SunOS, it does not make a difference which one is used because both define the O_xxxx symbols.

7.3. errno.h

The semantics of the error number may differ from one system to another and the list may differ as well (e.g., BSD systems have more error numbers than System V). Some systems, e.g., SunOS, define the global symbol errno which will hold the last error detected by the run-time library. This symbol is not declared in most systems, although it is required by the Standard that such a symbol be defined (see section 4.1.3 of the Standard [13]). It is, of course, available in all Unix implementations.

The most portable way to print error messages is to use perror.

7.4. math.h

System V has more definitions in this header file than BSD-like systems. The corresponding library has more functions as well. This header file is unprotected under VMS and Cray, and in that case we must do it ourselves:

#if defined(CRAY) || defined(VMS)
#  ifndef  __MATH__
#    define  __MATH__
#    include <math.h>
#  endif
#endif

7.5. strings.h vs. string.h

Some systems cannot be treated as System V or BSD, but are really special cases, as one can see in the following:

#ifdef  SYSV
#  ifndef SYSV_STRINGS
#    define  SYSV_STRINGS
#  endif
#endif

#ifdef _STDH_ /* ANSI C Standard header files */ # ifndef SYSV_STRINGS # define SYSV_STRINGS # endif #endif

#ifdef macII # ifndef SYSV_STRINGS # define SYSV_STRINGS # endif #endif

#ifdef vms # ifndef SYSV_STRINGS # define SYSV_STRINGS # endif #endif

#ifdef SYSV_STRINGS # include <string.h> # define index strchr # define rindex strrchr #else # include <strings.h> #endif

As one can easily observe, System V-like Unix systems use different names for index and rindex and place them in different header files. Although VMS supports better System V features, it must be treated as a special case.

7.6. time.h and types.h

When using time.h, one must also include types.h. The following code does the trick:

#ifdef macII
#  include <time.h>   /* on a Mac II we need this one as well */
#endif

#ifdef  SYSV
#  include <time.h>
#else
#  ifdef vms
#    include <time.h>
#  else
#    ifdef CRAY
#      ifndef __TYPES__   /* it is not protected under CRAY */
#        define __TYPES__
#        include <sys/types.h>
#      endif
#    else
#      include <sys/types.h>
#    endif /* of ifdef CRAY */
#    include <sys/time.h>
#  endif  /* of ifdef vms  */
#endif

The above is not sufficient in order for the code to be portable since the structure that defines time values is not the same in all systems. Different systems have vary in the way time_t values are represented. The Standard, for instance, only requires that it be an arithmetic type. Recognizing this difficulty, the Standard defines a function called difftime to compute the difference between two time values of type time_t, and mktime which takes a string and produces a value of type time_t.

7.7. varargs.h vs. stdarg.h

In some systems the definitions in both header files are contradictory. For instance, the following will produce compilation errors, e.g., under VMS:

#include <varargs.h>
#include <stdio.h>

This is because <stdio.h> includes <stdarg.h> which in turn redefines all the symbols (va_start, va_end, etc.) in <varargs.h>. This is incorrect behavior because Standard header files should not include other Standard header files. Furthermore, the method used in <varargs.h> for defining variadic functions is incompatible with the Standard (see section 11.2.3 for more information on variadic functions).

The solution we adopt is to always include <varargs.h> last and not to define in the same module both functions that use <varargs.h> and functions that use the ellipsis notation.

7.8. sys/wait.h

This one is lacking in some systems (e.g., Altos and Xenix). HP-UX does define it but one must use macros to access the fields of the wait struct, instead of using the names of the fields. The wait struct uses bit-fields and if the platform does not define it one must do it oneself and care must be taken with respect to byte ordering (see Byte ordering in section 11.1).


9. Under VMS, since a path such as <sys/file.h> will evaluate to sys:file.h, it is sufficient to equate the logical name sys to sys$library.


upcontents previousUnix Flavors: System V and BSD nextRun-time Library