これらのマクロは,特定のシステムヘッダファイルを調査します — それらが 存在しているか,そして場合によっては,特定のシンボルを宣言しているかを調 査します.
以下のヘッダファイルを調査します.最初に見つかった‘DIR’を定義してい るものに対して,リストアップされているCプリプロセッサマクロを定義します.
dirent.h HAVE_DIRENT_H
sys/ndir.h HAVE_SYS_NDIR_H
sys/dir.h HAVE_SYS_DIR_H
ndir.h HAVE_NDIR_H
ソースコード内のディレクトリライブラリの宣言は,以下のようにすべきでしょ う.
#if HAVE_DIRENT_H # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # if HAVE_SYS_NDIR_H # include <sys/ndir.h> # endif # if HAVE_SYS_DIR_H # include <sys/dir.h> # endif # if HAVE_NDIR_H # include <ndir.h> # endif #endif上記の宣言を使用している場合,プログラムは型を
struct direct
ではな くstruct dirent
として変数を宣言し,struct dirent
へのポイン タを渡すことによって,NAMLEN
マクロまでのディレクトリエントリ名の 長さにアクセスします.このマクロは,SCO Xenix dirとxライブラリも調査します.
sys/types.hが
major
,minor
,そしてmakedev
を定 義していないが,sys/mkdev.hが定義している場合,MAJOR_IN_MKDEV
を定義します.それ以外の場合で, sys/sysmacros.hが定義している場合は,MAJOR_IN_SYSMACROS
を 定義します.
sys/stat.hで定義されている
S_ISDIR
,S_ISREG
等のマク ロが正確に動作しない(間違った正の値を返す)場合,STAT_MACROS_BROKEN
を定義します.Tektronix UTekV,Amdahl UTS,そ してMotorola System V/88の場合がそうです.
stdbool.hが存在し,それがC99に準拠している場合,
HAVE_STDBOOL_H
を1に定義します.型_Bool
が定義されている場合,HAVE__BOOL
を1に定義します.C99の要求を満たすため,system.h には以下のコードを含めるべきです.#if HAVE_STDBOOL_H # include <stdbool.h> #else # if ! HAVE__BOOL # ifdef __cplusplus typedef bool _Bool; # else typedef unsigned char _Bool; # endif # endif # define bool _Bool # define false 0 # define true 1 # define __bool_true_false_are_defined 1 #endif
システムにANSI Cヘッダファイルが存在する場合,
STDC_HEADERS
を定義します.特にこのマクロは,stdlib.h, stdarg.h,string.h,そしてfloat.hを調査し,システム にそれらが存在している場合は,おそらくANSI Cヘッダーファイルの 残りも存在します.同様に,このマクロはstring.hがmemchr
を宣 言(他のmem
関数もおそらく存在)しているかどうか,stdlib.hがfree
を宣言(malloc
や他の関連する関数もおそらく存在)している かどうか,そして,ctype.hマクロが,ANSI Cが要求するハイ ビットセット文字でも動作するかどうかを調査します.GCCがあるシステムの多くはANSI Cヘッダファイルが存在していない ので,システムにANSI対応のヘッダファイル(そして,おそらくC ラ イブラリ関数) が存在していることを決定するために,
__STDC__
の代わ りにSTDC_HEADERS
を使用してください.ANSI Cヘッダが無いシステムには多くの変種が存在していて,そこで は,システムヘッダファイルが宣言しているものを正確に理解するより,使用す る関数を宣言する方がより容易でしょう.ANSIとBSDの関 数が混在しているシステムもあります.ほとんどANSIだが ‘memmove’が無いものもあります.BSD関数がstring.hや strings.h でマクロで定義されているものもあります.BSD関 数しか持っていないが string.hが存在するものもあります.メモリ関数 がmemory.hで定義されていて,string.hでも定義されているもの もあります.等々いろいろなシステムがあります.一つの文字列関数と一つのメ モリ関数を調査すれば恐らく十分です.ライブラリにANSIバージョン のものが存在する場合,他のものもほとんど存在します.以下を configure.acに書き込む場合を考えます.
AC_HEADER_STDC AC_CHECK_FUNCS(strchr memcpy)コード内に,以下のような宣言を使用することが可能です.
#if STDC_HEADERS # include <string.h> #else # if !HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr (), *strrchr (); # if !HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endifBSDとは異なる
memchr
,memset
,strtok
,また はstrspn
の様な関数を使用する場合,マクロは不十分でしょう.それぞ れの関数を実装する必要があります.(システムのCライブラリのものが,手動で 最適化されているかもしれないので)必要なときだけ実装を組み込む簡単な方法 として,例えばmemchr
を使用する場合は,それをmemchr.cに書き 込み,‘AC_REPLACE_FUNCS(memchr)’を使用することです.
sys/wait.hが存在して,POSIXと互換性がある場合,
HAVE_SYS_WAIT_H
を定義します.非互換性は,sys/wait.hが存在 しない場合や,ステータスの値を保存するため,int
の代わりに古い BSDのunion wait
使用する場合に生じます. sys/wait.hがPOSIXと互換性がない場合,それをインクルード する代わりに,それらの通常の解釈を用いてPOSIXのマクロを定義し てください.例えば以下のようにします.#include <sys/types.h> #if HAVE_SYS_WAIT_H # include <sys/wait.h> #endif #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif
unistd.hがPOSIXシステムに含まれている場合,
_POSIX_VERSION
が定義されます.unistd.hが無い場合,明らかに
POSIXシステムではありません.しかし,unistd.hを持つ
POSIXではないシステムもあります.
システムがPOSIXをサポートしているかどうか調査する方法は以下の ようにします.
#if HAVE_UNISTD_H # include <sys/types.h> # include <unistd.h> #endif #ifdef _POSIX_VERSION /* Code for POSIX systems. */ #endif
プログラムが,time.hとsys/time.hの両方をインクルードする可 能性がある場合,
TIME_WITH_SYS_TIME
を定義します.古いシステムでは, sys/time.hがtime.hをインクルードするものもありますが, time.hは複数回のインクルードに対して保護されていないので,プログ ラムで明示的に両方のファイルをインクルードすべきではありません.このマク ロは,例えば,struct tm
と同様,struct timeval
を使用するプ ログラムで役に立ちます.AC_CHECK_HEADERS(sys/time.h)
を使用して いることを調査可能にするHAVE_SYS_TIME_H
と一緒に使用するのが最善の 方法です.#if TIME_WITH_SYS_TIME # include <sys/time.h> # include <time.h> #else # if HAVE_SYS_TIME_H # include <sys/time.h> # else # include <time.h> # endif #endif