Back to index

glibc  2.9
annexc.c
Go to the documentation of this file.
00001 /* Copyright (C) 1998, 2000, 2002, 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <ctype.h>
00020 #include <fnmatch.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <signal.h>
00026 #include <sys/wait.h>
00027 
00028 #define HEADER_MAX          256
00029 
00030 static const char *macrofile;
00031 
00032 /* <aio.h>.  */
00033 static const char *const aio_syms[] =
00034 {
00035   "AIO_ALLDONE", "AIO_CANCELED", "AIO_NOTCANCELED", "LIO_NOP", "LIO_NOWAIT",
00036   "LIO_READ", "LIO_WAIT", "LIO_WRITE",
00037   /* From <fcntl.h>.  */
00038   "FD_CLOEXEC", "F_DUPFD", "F_GETFD", "F_GETFL", "F_GETLK", "F_RDLCK",
00039   "F_SETFD", "F_SETFL", "F_SETLK", "F_SETLKW", "F_UNLCK", "F_WRLCK",
00040   "O_ACCMODE", "O_APPEND", "O_CREAT", "O_DSYNC", "O_EXCL", "O_NOCTTY",
00041   "O_NONBLOCK", "O_RDONLY", "O_RDWR", "O_RSYNC", "O_SYNC", "O_TRUNC",
00042   "O_WRONLY",
00043   /* From <signal.h>.  */
00044   "SA_NOCLDSTOP", "SA_SIGINFO", "SIGABRT", "SIGALRM", "SIGBUS", "SIGCHLD",
00045   "SIGCONT", "SIGEV_NONE", "SIGEV_SIGNAL", "SIGEV_SIGNAL", "SIGEV_THREAD",
00046   "SIGFPE", "SIGHUP", "SIGILL", "SIGINT", "SIGKILL", "SIGPIPE", "SIGQUIT",
00047   "SIGRTMAX", "SIGRTMIN", "SIGSEGV", "SIGSTOP", "SIGTERM", "SIGTSTP",
00048   "SIGTTIN", "SIGTTOU", "SIGUSR1", "SIGUSR2", "SIG_BLOCK", "SIG_DFL",
00049   "SIG_ERR", "SIG_IGN", "SIG_SETMASK", "SIG_UNBLOCK", "SI_ASYNCIO",
00050   "SI_MESGQ", "SI_QUEUE", "SI_TIMER", "SI_USER"
00051 };
00052 static const char *const aio_maybe[] =
00053 {
00054   "aio_cancel", "aio_error", "aio_fsync", "aio_read", "aio_return",
00055   "aio_suspend", "aio_write", "lio_listio",
00056   /* From <fcntl.h>.  */
00057   "creat", "fcntl", "open", "SEEK_CUR", "SEEK_END", "SEEK_SET", "S_IRGRP",
00058   "S_IROTH", "S_IRUSR", "S_IRWXG", "S_IRWXO", "S_IRWXU", "S_ISBLK",
00059   "S_ISCHR", "S_ISDIR", "S_ISFIFO", "S_ISGID", "S_ISREG", "S_ISUID",
00060   "S_IWGRP", "S_IWOTH", "S_IWUSR", "S_IXGRP", "S_IXOTH", "S_IXUSR",
00061   /* From <signal.h>.  */
00062   "kill", "raise", "sigaction", "sigaddset", "sigdelset", "sigemptyset",
00063   "sigfillset", "sigismember", "signal", "sigpending", "sigprocmask",
00064   "sigqueue", "sigsuspend", "sigtimedwait", "sigwait", "sigwaitinfo"
00065 };
00066 
00067 /* <assert.h>.  */
00068 static const char *const assert_syms[] =
00069 {
00070   "assert"
00071 };
00072 static const char *const assert_maybe[] =
00073 {
00074 };
00075 
00076 /* <ctype.h>.   */
00077 static const char *const ctype_syms[] =
00078 {
00079 };
00080 static const char *const ctype_maybe[] =
00081 {
00082   "isalnum", "isalpha", "iscntrl", "isdigit", "isgraph", "islower",
00083   "isprint", "ispunct", "isspace", "isupper", "isxdigit", "tolower",
00084   "toupper"
00085 };
00086 
00087 /* <dirent.h>.  */
00088 static const char *const dirent_syms[] =
00089 {
00090 };
00091 static const char *const dirent_maybe[] =
00092 {
00093   "closedir", "opendir", "readdir", "readdir_r", "rewinddir"
00094 };
00095 
00096 /* <errno.h>.  */
00097 static const char *const errno_syms[] =
00098 {
00099   "E2BIG", "EACCES", "EAGAIN", "EBADF", "EBADMSG", "EBUSY", "ECANCELED",
00100   "ECHILD", "EDEADLK", "EDOM", "EEXIST", "EFAULT", "EFBIG", "EINPROGRESS",
00101   "EINTR", "EINVAL", "EIO", "EISDIR", "EMFILE", "EMLINK", "EMSGSIZE",
00102   "ENAMETOOLONG", "ENFILE", "ENODEV", "ENOENT", "ENOEXEC", "ENOLCK",
00103   "ENOMEM", "ENOSPC", "ENOSYS", "ENOTDIR", "ENOTEMPTY", "ENOTSUP",
00104   "ENOTTY", "ENXIO", "EPERM", "EPIPE", "ERANGE", "EROFS", "ESPIPE",
00105   "ESRCH", "ETIMEDOUT", "EXDEV"
00106 };
00107 static const char *const errno_maybe[] =
00108 {
00109   "errno", "E*"
00110 };
00111 
00112 /* <fcntl.h>.  */
00113 static const char *const fcntl_syms[] =
00114 {
00115   "FD_CLOEXEC", "F_DUPFD", "F_GETFD", "F_GETFL", "F_GETLK", "F_RDLCK",
00116   "F_SETFD", "F_SETFL", "F_SETLK", "F_SETLKW", "F_UNLCK", "F_WRLCK",
00117   "O_ACCMODE", "O_APPEND", "O_CREAT", "O_DSYNC", "O_EXCL", "O_NOCTTY",
00118   "O_NONBLOCK", "O_RDONLY", "O_RDWR", "O_RSYNC", "O_SYNC", "O_TRUNC",
00119   "O_WRONLY"
00120 };
00121 static const char *const fcntl_maybe[] =
00122 {
00123   "creat", "fcntl", "open", "SEEK_CUR", "SEEK_END", "SEEK_SET", "S_IRGRP",
00124   "S_IROTH", "S_IRUSR", "S_IRWXG", "S_IRWXO", "S_IRWXU", "S_ISBLK",
00125   "S_ISCHR", "S_ISDIR", "S_ISFIFO", "S_ISGID", "S_ISREG", "S_ISUID",
00126   "S_IWGRP", "S_IWOTH", "S_IWUSR", "S_IXGRP", "S_IXOTH", "S_IXUSR"
00127 };
00128 
00129 /* <float.h>.  */
00130 static const char *const float_syms[] =
00131 {
00132   "DBL_DIG", "DBL_EPSILON", "DBL_MANT_DIG", "DBL_MAX", "DBL_MAX_10_EXP",
00133   "DBL_MAX_EXP", "DBL_MIN", "DBL_MIN_10_EXP", "DBL_MIN_EXP", "FLT_DIG",
00134   "FLT_EPSILON", "FLT_MANT_DIG", "FLT_MAX", "FLT_MAX_10_EXP", "FLT_MAX_EXP",
00135   "FLT_MIN", "FLT_MIN_10_EXP", "FLT_MIN_EXP", "FLT_RADIX", "FLT_ROUNDS",
00136   "LDBL_DIG", "LDBL_EPSILON", "LDBL_MANT_DIG", "LDBL_MAX", "LDBL_MAX_10_EXP",
00137   "LDBL_MAX_EXP", "LDBL_MIN", "LDBL_MIN_10_EXP", "LDBL_MIN_EXP"
00138 };
00139 static const char *const float_maybe[] =
00140 {
00141 };
00142 
00143 /* <grp.h>.  */
00144 static const char *const grp_syms[] =
00145 {
00146 };
00147 static const char *const grp_maybe[] =
00148 {
00149   "getgrgid", "getgrgid_r", "getgrnam", "getgrnam_r"
00150 };
00151 
00152 /* <limits.h>.  */
00153 static const char *const limits_syms[] =
00154 {
00155   "_POSIX_AIO_LISTIO_MAX", "_POSIX_AIO_MAX", "_POSIX_ARG_MAX",
00156   "_POSIX_CHILD_MAX", "_POSIX_CLOCKRES_MAX", "_POSIX_DELAYTIMER_MAX",
00157   "_POSIX_LINK_MAX", "_POSIX_LOGIN_NAME_MAX", "_POSIX_MAX_CANON",
00158   "_POSIX_MAX_INPUT", "_POSIX_MQ_OPEN_MAX", "_POSIX_MQ_PRIO_MAX",
00159   "_POSIX_NAME_MAX", "_POSIX_NGROUPS_MAX", "_POSIX_OPEN_MAX",
00160   "_POSIX_PATH_MAX", "_POSIX_PIPE_BUF", "_POSIX_RTSIG_MAX",
00161   "_POSIX_SEM_NSEMS_MAX", "_POSIX_SEM_VALUE_MAX", "_POSIX_SIGQUEUE_MAX",
00162   "_POSIX_SSIZE_MAX", "_POSIX_STREAM_MAX",
00163   "_POSIX_THREAD_DESTRUCTOR_ITERATIONS", "_POSIX_THREAD_KEYS_MAX",
00164   "_POSIX_THREAD_THREADS_MAX", "_POSIX_TIMER_MAX", "_POSIX_TTY_NAME_MAX",
00165   "_POSIX_TZNAME_MAX", "_POSIX_THREAD_DESTRUCTOR_ITERATIONS",
00166   "CHAR_BIT", "CHAR_MAX", "CHAR_MIN", "INT_MAX", "INT_MIN", "LONG_MAX",
00167   "LONG_MIN", "MB_LEN_MAX", "NGROUPS_MAX", "PAGESIZE", "SCHAR_MAX",
00168   "SCHAR_MIN", "SHRT_MAX", "SHRT_MIN", "UCHAR_MAX", "UINT_MAX",
00169   "ULONG_MAX", "USHRT_MAX"
00170 };
00171 static const char *const limits_maybe[] =
00172 {
00173   "AIO_LISTIO_MAX", "AIO_MAX", "ARG_MAX", "CHILD_MAX", "DELAYTIMER_MAX",
00174   "LINK_MAX", "LOGIN_NAME_MAX", "LONG_MAX", "LONG_MIN", "MAX_CANON",
00175   "MAX_INPUT", "MQ_OPEN_MAX", "MQ_PRIO_MAX", "NAME_MAX", "OPEN_MAX",
00176   "PATH_MAX", "PIPE_BUF", "RTSIG_MAX", "PTHREAD_DESTRUCTOR_ITERATIONS",
00177   "PTHREAD_KEYS_MAX", "PTHREAD_STACK_MIN", "PTHREAD_THREADS_MAX"
00178 };
00179 
00180 /* <locale.h>.  */
00181 static const char *const locale_syms[] =
00182 {
00183   "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC",
00184   "LC_TIME", "NULL"
00185 };
00186 static const char *const locale_maybe[] =
00187 {
00188   "LC_*", "localeconv", "setlocale"
00189 };
00190 
00191 /* <math.h>.  */
00192 static const char *const math_syms[] =
00193 {
00194   "HUGE_VAL"
00195 };
00196 static const char *const math_maybe[] =
00197 {
00198   "acos", "asin", "atan2", "atan", "ceil", "cos", "cosh", "exp",
00199   "fabs", "floor", "fmod", "frexp", "ldexp", "log10", "log", "modf",
00200   "pow", "sin", "sinh", "sqrt", "tan", "tanh",
00201   "acosf", "asinf", "atan2f", "atanf", "ceilf", "cosf", "coshf", "expf",
00202   "fabsf", "floorf", "fmodf", "frexpf", "ldexpf", "log10f", "logf", "modff",
00203   "powf", "sinf", "sinhf", "sqrtf", "tanf", "tanhf",
00204   "acosl", "asinl", "atan2l", "atanl", "ceill", "cosl", "coshl", "expl",
00205   "fabsl", "floorl", "fmodl", "frexpl", "ldexpl", "log10l", "logl", "modfl",
00206   "powl", "sinl", "sinhl", "sqrtl", "tanl", "tanhl"
00207 };
00208 
00209 /* <mqueue.h>.  */
00210 static const char *const mqueue_syms[] =
00211 {
00212 };
00213 static const char *const mqueue_maybe[] =
00214 {
00215   "mq_close", "mq_getattr", "mq_notify", "mq_open", "mq_receive",
00216   "mq_send", "mq_setattr", "mq_unlink"
00217 };
00218 
00219 /* <pthread.h>.  */
00220 static const char *const pthread_syms[] =
00221 {
00222   "PTHREAD_CANCELED", "PTHREAD_CANCEL_ASYNCHRONOUS",
00223   "PTHREAD_CANCEL_DEFERRED", "PTHREAD_CANCEL_DISABLE", "PTHREAD_CANCEL_ENABLE",
00224   "PTHREAD_COND_INITIALIZER", "PTHREAD_CREATE_DETACHED",
00225   "PTHREAD_CREATE_JOINABLE", "PTHREAD_EXPLICIT_SCHED",
00226   "PTHREAD_INHERIT_SCHED", "PTHREAD_MUTEX_INITIALIZER",
00227   "PTHREAD_ONCE_INIT", "PTHREAD_PRIO_INHERIT", "PTHREAD_PRIO_NONE",
00228   "PTHREAD_PRIO_PROTECT", "PTHREAD_PROCESS_PRIVATE",
00229   "PTHREAD_PROCESS_SHARED", "PTHREAD_SCOPE_PROCESS", "PTHREAD_SCOPE_SYSTEM",
00230   /* These come from <sched.h>.  */
00231   "SCHED_FIFO", "SCHED_OTHER", "SCHED_RR",
00232   /* These come from <time.h>.  */
00233   "CLK_TCK", "CLOCKS_PER_SEC", "CLOCK_REALTIME", "NULL", "TIMER_ABSTIME"
00234 };
00235 static const char *const pthread_maybe[] =
00236 {
00237   "pthread_atfork", "pthread_attr_destroy", "pthread_attr_getdetachstate",
00238   "pthread_attr_getinheritsched", "pthread_attr_getschedparam",
00239   "pthread_attr_getschedpolicy", "pthread_attr_getscope",
00240   "pthread_attr_getstackaddr", "pthread_attr_getstacksize",
00241   "pthread_attr_init", "pthread_attr_setdetachstate",
00242   "pthread_attr_setinheritsched", "pthread_attr_setschedparam",
00243   "pthread_attr_setschedpolicy", "pthread_attr_setscope",
00244   "pthread_attr_setstackaddr", "pthread_attr_setstacksize",
00245   "pthread_cleanup_pop", "pthread_cleanup_push", "pthread_cond_broadcast",
00246   "pthread_cond_destroy", "pthread_cond_init", "pthread_cond_signal",
00247   "pthread_cond_timedwait", "pthread_cond_wait", "pthread_condattr_destroy",
00248   "pthread_condattr_getpshared", "pthread_condattr_init",
00249   "pthread_condattr_setpshared", "pthread_create", "pthread_detach",
00250   "pthread_equal", "pthread_exit", "pthread_getspecific", "pthread_join",
00251   "pthread_key_create", "pthread_key_destroy", "pthread_kill",
00252   "pthread_mutex_destroy", "pthread_mutex_getprioceiling",
00253   "pthread_mutex_init", "pthread_mutex_lock", "pthread_mutex_setprioceiling",
00254   "pthread_mutex_trylock", "pthread_mutex_unlock", "pthread_mutexattr_destroy",
00255   "pthread_mutexattr_getprioceiling", "pthread_mutexattr_getprotocol",
00256   "pthread_mutexattr_getpshared", "pthread_mutexattr_init",
00257   "pthread_mutexattr_setprioceiling", "pthread_mutexattr_setprotocol",
00258   "pthread_mutexattr_setpshared", "pthread_once", "pthread_self",
00259   "pthread_setcancelstate", "pthread_setcanceltype", "pthread_setspecific",
00260   "pthread_sigmask", "pthread_testcancel"
00261   /* These come from <sched.h>.  */
00262   "sched_get_priority_max", "sched_get_priority_min",
00263   "sched_get_rr_interval", "sched_getparam", "sched_getscheduler",
00264   "sched_setparam", "sched_setscheduler", "sched_yield",
00265   /* These come from <time.h>.  */
00266   "asctime", "asctime_r", "clock", "clock_getres", "clock_gettime",
00267   "clock_settime", "ctime", "ctime_r", "difftime", "gmtime", "gmtime_r",
00268   "localtime", "localtime_r", "mktime", "nanosleep", "strftime", "time",
00269   "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime",
00270   "timer_settime", "tzset"
00271 };
00272 
00273 /* <pwd.h>.  */
00274 static const char *const pwd_syms[] =
00275 {
00276 };
00277 static const char *const pwd_maybe[] =
00278 {
00279   "getpwnam", "getpwnam_r", "getpwuid", "getpwuid_r"
00280 };
00281 
00282 /* <sched.h>.  */
00283 static const char *const sched_syms[] =
00284 {
00285   "SCHED_FIFO", "SCHED_OTHER", "SCHED_RR",
00286 };
00287 static const char *const sched_maybe[] =
00288 {
00289   "sched_get_priority_max", "sched_get_priority_min",
00290   "sched_get_rr_interval", "sched_getparam", "sched_getscheduler",
00291   "sched_setparam", "sched_setscheduler", "sched_yield",
00292   /* These come from <time.h>.  */
00293   "CLK_TCK", "CLOCKS_PER_SEC", "CLOCK_REALTIME", "NULL", "TIMER_ABSTIME"
00294   "asctime", "asctime_r", "clock", "clock_getres", "clock_gettime",
00295   "clock_settime", "ctime", "ctime_r", "difftime", "gmtime", "gmtime_r",
00296   "localtime", "localtime_r", "mktime", "nanosleep", "strftime", "time",
00297   "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime",
00298   "timer_settime", "tzset"
00299 };
00300 
00301 /* <semaphore.h>.  */
00302 static const char *const semaphore_syms[] =
00303 {
00304 };
00305 static const char *const semaphore_maybe[] =
00306 {
00307   "sem_close", "sem_destroy", "sem_getvalue", "sem_init", "sem_open",
00308   "sen_post", "sem_trywait", "sem_unlink", "sem_wait"
00309 };
00310 
00311 /* <setjmp.h>.  */
00312 static const char *const setjmp_syms[] =
00313 {
00314 };
00315 static const char *const setjmp_maybe[] =
00316 {
00317   "longjmp", "setjmp", "siglongjmp", "sigsetjmp"
00318 };
00319 
00320 /* <signal.h>.  */
00321 static const char *const signal_syms[] =
00322 {
00323   "SA_NOCLDSTOP", "SA_SIGINFO", "SIGABRT", "SIGALRM", "SIGBUS", "SIGCHLD",
00324   "SIGCONT", "SIGEV_NONE", "SIGEV_SIGNAL", "SIGEV_THREAD",
00325   "SIGFPE", "SIGHUP", "SIGILL", "SIGINT", "SIGKILL", "SIGPIPE", "SIGQUIT",
00326   "SIGRTMAX", "SIGRTMIN", "SIGSEGV", "SIGSTOP", "SIGTERM", "SIGTSTP",
00327   "SIGTTIN", "SIGTTOU", "SIGUSR1", "SIGUSR2", "SIG_BLOCK", "SIG_DFL",
00328   "SIG_ERR", "SIG_IGN", "SIG_SETMASK", "SIG_UNBLOCK", "SI_ASYNCIO",
00329   "SI_MESGQ", "SI_QUEUE", "SI_TIMER", "SI_USER"
00330 };
00331 static const char *const signal_maybe[] =
00332 {
00333   "kill", "raise", "sigaction", "sigaddset", "sigdelset", "sigemptyset",
00334   "sigfillset", "sigismember", "signal", "sigpending", "sigprocmask",
00335   "sigqueue", "sigsuspend", "sigtimedwait", "sigwait", "sigwaitinfo"
00336 };
00337 
00338 /* <stdarg.h>.  */
00339 static const char *const stdarg_syms[] =
00340 {
00341   "va_arg", "va_end", "va_start"
00342 };
00343 static const char *const stdarg_maybe[] =
00344 {
00345   "va_list"
00346 };
00347 
00348 /* <stddef.h>.  */
00349 static const char *const stddef_syms[] =
00350 {
00351   "NULL", "offsetof"
00352 };
00353 static const char *const stddef_maybe[] =
00354 {
00355 };
00356 
00357 /* <stdio.h>.  */
00358 static const char *const stdio_syms[] =
00359 {
00360   "BUFSIZ", "EOF", "FILENAME_MAX", "FOPEN_MAX", "L_ctermid", "L_cuserid",
00361   "L_tmpnam", "NULL", "SEEK_CUR", "SEEK_END", "SEEK_SET", "STREAM_MAX",
00362   "TMP_MAX", "stderr", "stdin", "stdout", "_IOFBF", "_IOLBF", "_IONBF"
00363 };
00364 static const char *const stdio_maybe[] =
00365 {
00366   "clearerr", "fclose", "fdopen", "feof", "ferror", "fflush", "fgetc",
00367   "fgetpos", "fgets", "fileno", "flockfile", "fopen", "fprintf", "fputc",
00368   "fputs", "fread", "freopen", "fscanf", "fseek", "fsetpos", "ftell",
00369   "ftrylockfile", "funlockfile", "fwrite", "getc", "getchar",
00370   "getchar_unlocked", "getc_unlocked", "gets", "perror", "printf", "putc",
00371   "putchar", "putchar_unlocked", "putc_unlocked", "puts", "remove", "rename",
00372   "rewind", "scanf", "setbuf", "setvbuf", "sprintf", "sscanf", "tmpfile",
00373   "tmpnam", "ungetc", "vfprintf", "vprintf", "vsprintf"
00374 };
00375 
00376 /* <stdlib.h>.  */
00377 static const char *const stdlib_syms[] =
00378 {
00379   "EXIT_FAILURE", "EXIT_SUCCESS", "MB_CUR_MAX", "NULL", "RAND_MAX"
00380 };
00381 static const char *const stdlib_maybe[] =
00382 {
00383   "abort", "abs", "atexit", "atof", "atoi", "atol", "bsearch", "calloc",
00384   "div", "exit", "free", "getenv", "labs", "ldiv", "malloc", "mblen",
00385   "mbstowcs", "mbtowc", "qsort", "rand", "rand_r", "realloc", "srand",
00386   "strtod", "strtol", "strtoul", "system", "wcstombs", "wctomb"
00387 };
00388 
00389 /* <string.h>.  */
00390 static const char *const string_syms[] =
00391 {
00392   "NULL"
00393 };
00394 static const char *const string_maybe[] =
00395 {
00396   "memchr", "memcmp", "memcpy", "memmove", "memset", "strcat", "strchr",
00397   "strcmp", "strcoll", "strcpy", "strcspn", "strerror", "strlen",
00398   "strncat", "strncmp", "strncpy", "strpbrk", "strrchr", "strspn",
00399   "strstr", "strtok", "strtok_r", "strxfrm"
00400 };
00401 
00402 /* <sys/mman.h>.  */
00403 static const char *const mman_syms[] =
00404 {
00405   "MAP_FAILED", "MAP_FIXED", "MAP_PRIVATE", "MAP_SHARED", "MCL_CURRENT",
00406   "MCL_FUTURE", "MS_ASYNC", "MS_INVALIDATE", "MS_SYNC", "PROT_EXEC",
00407   "PROT_NONE", "PROT_READ", "PROT_WRITE"
00408 };
00409 static const char *const mman_maybe[] =
00410 {
00411   "mlock", "mlockall", "mmap", "mprotect", "msync", "munlock", "munlockall",
00412   "munmap", "shm_open", "shm_unlock"
00413 };
00414 
00415 /* <sys/stat.h>.  */
00416 static const char *const stat_syms[] =
00417 {
00418   "S_IRGRP", "S_IROTH", "S_IRUSR", "S_IRWXG", "S_IRWXO", "S_IRWXU",
00419   "S_ISBLK", "S_ISCHR", "S_ISDIR", "S_ISFIFO", "S_ISGID", "S_ISREG",
00420   "S_ISUID", "S_IWGRP", "S_IWOTH", "S_IWUSR", "S_IXGRP", "S_IXOTH",
00421   "S_IXUSR", "S_TYPEISMQ", "S_TYPEISSEM", "S_TYPEISSHM"
00422 };
00423 static const char *const stat_maybe[] =
00424 {
00425   "chmod", "fchmod", "fstat", "mkdir", "mkfifo", "stat", "umask"
00426 };
00427 
00428 /* <sys/times.h>.  */
00429 static const char *const times_syms[] =
00430 {
00431 };
00432 static const char *const times_maybe[] =
00433 {
00434   "times"
00435 };
00436 
00437 /* <sys/types.h>.  */
00438 static const char *const types_syms[] =
00439 {
00440 };
00441 static const char *const types_maybe[] =
00442 {
00443 };
00444 
00445 /* <sys/utsname.h>.  */
00446 static const char *const utsname_syms[] =
00447 {
00448 };
00449 static const char *const utsname_maybe[] =
00450 {
00451   "uname"
00452 };
00453 
00454 /* <sys/wait.h>.  */
00455 static const char *const wait_syms[] =
00456 {
00457   "WEXITSTATUS", "WIFEXITED", "WIFSIGNALED", "WIFSTOPPED", "WNOHANG",
00458   "WSTOPSIG", "WTERMSIG", "WUNTRACED"
00459 };
00460 static const char *const wait_maybe[] =
00461 {
00462   "wait", "waitpid"
00463 };
00464 
00465 /* <termios.h>.  */
00466 static const char *const termios_syms[] =
00467 {
00468   "B0", "B110", "B1200", "B134", "B150", "B1800", "B19200", "B200", "B2400",
00469   "B300", "B38400", "B4800", "B50", "B600", "B75", "B9600", "BRKINT", "CLOCAL",
00470   "CREAD", "CS5", "CS6", "CS7", "CS8", "CSIZE", "CSTOPN", "ECHO", "ECHOE",
00471   "ECHOK", "ECHONL", "HUPCL", "ICANON", "ICRNL", "IEXTEN", "IGNBRK", "IGNCR",
00472   "IGNPAR", "INCLR", "INPCK", "ISIG", "ISTRIP", "IXOFF", "IXON", "NCCS",
00473   "NOFLSH", "OPOST", "PARENB", "PARMRK", "PARODD", "TCIFLUSH", "TCIOFF",
00474   "TCIOFLUSH", "TCOFLUSH", "TCOOFF", "TCOON", "TCSADRAIN", "TCSAFLUSH",
00475   "TCSANOW", "TOSTOP", "VEOF", "VEOL", "VERASE", "VINTR", "VKILL", "VMIN",
00476   "VQUIT", "VSTART", "VSTOP", "VSUSP", "VTIME"
00477 };
00478 static const char *const termios_maybe[] =
00479 {
00480   "cfgetispeed", "cfgetospeed", "cfsetispeed", "cfsetospeed", "tcdrain",
00481   "tcflow", "tcflush", "tcgetattr", "tcsendbrk", "tcsetattr"
00482 };
00483 
00484 /* <time.h>.  */
00485 static const char *const time_syms[] =
00486 {
00487   "CLK_TCK", "CLOCKS_PER_SEC", "CLOCK_REALTIME", "NULL", "TIMER_ABSTIME"
00488 };
00489 static const char *const time_maybe[] =
00490 {
00491   "asctime", "asctime_r", "clock", "clock_getres", "clock_gettime",
00492   "clock_settime", "ctime", "ctime_r", "difftime", "gmtime", "gmtime_r",
00493   "localtime", "localtime_r", "mktime", "nanosleep", "strftime", "time",
00494   "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime",
00495   "timer_settime", "tzset"
00496 };
00497 
00498 /* <unistd.h>.  */
00499 static const char *const unistd_syms[] =
00500 {
00501   "F_OK", "NULL", "R_OK", "SEEK_CUR", "SEEK_END", "SEEK_SET", "STDERR_FILENO",
00502   "STDIN_FILENO", "STDOUT_FILENO", "W_OK", "X_OK",
00503   "_PC_ASYNC_IO", "_PC_CHOWN_RESTRICTED", "_PC_LINK_MAX", "_PC_MAX_CANON",
00504   "_PC_MAX_INPUT", "_PC_NAME_MAX", "_PC_NO_TRUNC", "_PC_PATH_MAX",
00505   "_PC_PIPE_BUF", "_PC_PRIO_IO", "_PC_SYNC_IO", "_PC_VDISABLE",
00506   "_SC_AIO_LISTIO_MAX", "_SC_AIO_MAX", "_SC_AIO_PRIO_DELTA_MAX",
00507   "_SC_ARG_MAX", "_SC_ASYNCHRONOUS_IO", "_SC_CHILD_MAX", "_SC_CLK_TCK",
00508   "_SC_DELAYTIMER_MAX", "_SC_FSYNC", "_SC_GETGR_R_SIZE_MAX",
00509   "_SC_GETPW_R_SIZE_MAX", "_SC_JOB_CONTROL", "_SC_LOGIN_NAME_MAX",
00510   "_SC_MAPPED_FILES", "_SC_MEMLOCK", "_SC_MEMLOCK_RANGE",
00511   "_SC_MEMORY_PROTECTION", "_SC_MESSAGE_PASSING", "_SC_MQ_OPEN_MAX",
00512   "_SC_MQ_PRIO_MAX", "_SC_NGROUPS_MAX", "_SC_OPEN_MAX", "_SC_PAGESIZE",
00513   "_SC_PRIORITIZED_IO", "_SC_PRIORITY_SCHEDULING", "_SC_REALTIME_SIGNALS",
00514   "_SC_RTSIG_MAX", "_SC_SAVED_IDS", "_SC_SEMAPHORES", "_SC_SEM_NSEMS_MAX",
00515   "_SC_SEM_VALUE_MAX", "_SC_SHARED_MEMORY_OBJECTS", "_SC_SIGQUEUE_MAX",
00516   "_SC_STREAM_MAX", "_SC_SYNCHRONIZED_IO", "_SC_THREADS",
00517   "_SC_THREAD_ATTR_STACKADDR", "_SC_THREAD_ATTR_STACKSIZE",
00518   "_SC_THREAD_DESTRUCTOR_ITERATIONS", "_SC_THREAD_PRIO_INHERIT",
00519   "_SC_THREAD_PRIORITY_SCHEDULING", "_SC_THREAD_PRIO_PROTECT",
00520   "_SC_THREAD_PROCESS_SHARED", "_SC_THREAD_SAFE_FUNCTIONS",
00521   "_SC_THREAD_STACK_MIN", "_SC_THREAD_THREADS_MAX", "_SC_TIMERS",
00522   "_SC_TIMER_MAX", "_SC_TTY_NAME_MAX", "_SC_TZNAME_MAX", "_SC_VERSION"
00523 };
00524 static const char *const unistd_maybe[] =
00525 {
00526   "_POSIX_ASYNCHRONOUS_IO", "_POSIX_ASYNC_IO", "_POSIX_CHOWN_RESTRICTED",
00527   "_POSIX_FSYNC", "_POSIX_JOB_CONTROL", "_POSIX_MAPPED_FILES",
00528   "_POSIX_MEMLOCK", "_POSIX_MEMLOCK_RANGE", "_MEMORY_PROTECTION",
00529   "_POSIX_MESSAGE_PASSING", "_POSIX_NO_TRUNC", "_POSIX_PRIORITIZED_IO",
00530   "_POSIX_PRIORITY_SCHEDULING", "_POSIX_PRIO_IO", "_POSIX_REATIME_SIGNALS",
00531   "_POSIX_SAVED_IDS", "_POSIX_SEMAPHORES", "_POSIX_SHARED_MEMORY_OBJECTS",
00532   "_POSIX_SYNCHRONIZED_IO", "_POSIX_SYNC_IO", "_POSIX_THREADS",
00533   "_POSIX_THREAD_ATTR_STACKADDR", "_POSIX_THREAD_ATTR_STACKSIZE",
00534   "_POSIX_THREAD_PRIO_INHERIT", "_POSIX_THREAD_PRIO_PROTECT",
00535   "_POSIX_THREAD_PROCESS_SHARED", "_POSIX_THREAD_SAFE_FUNCTIONS",
00536   "_POSIX_THREAD_PRIORITY_SCHEDULING", "_POSIX_TIMERS",
00537   "_POSIX_VDISABLE", "_POSIX_VERSION",
00538   "_exit", "access", "alarm", "chdir", "chown", "close", "ctermid", "cuserid",
00539   "dup2", "dup", "execl", "execle", "execlp", "execv", "execve", "execvp",
00540   "fdatasync", "fork", "fpathconf", "fsync", "ftruncate", "getcwd", "getegid",
00541   "geteuid", "getgid", "getgroups", "getlogin", "getlogin_r", "getpgrp",
00542   "getpid", "getppid", "getuid", "isatty", "link", "lseek", "pathconf",
00543   "pause", "pipe", "read", "rmdir", "setgid", "setgpid", "setsid", "setuid",
00544   "sleep", "sleep", "sysconf", "tcgetpgrp", "tcsetpgrp", "ttyname",
00545   "ttyname_r", "unlink", "write"
00546 };
00547 
00548 /* <utime.h>.  */
00549 static const char *const utime_syms[] =
00550 {
00551 };
00552 static const char *const utime_maybe[] =
00553 {
00554   "utime"
00555 };
00556 
00557 
00558 static struct header
00559 {
00560   const char *name;
00561   const char *const *syms;
00562   size_t nsyms;
00563   const char *const *maybe;
00564   size_t nmaybe;
00565   const char *subset;
00566 } headers[] =
00567 {
00568 #define H(n) \
00569   { #n ".h", n##_syms, sizeof (n##_syms) / sizeof (n##_syms[0]), \
00570     n##_maybe, sizeof (n##_maybe) / sizeof (n##_maybe[0]), NULL }
00571 #define Hc(n, s) \
00572   { #n ".h", n##_syms, sizeof (n##_syms) / sizeof (n##_syms[0]), \
00573     n##_maybe, sizeof (n##_maybe) / sizeof (n##_maybe[0]), s }
00574 #define Hs(n) \
00575   { "sys/" #n ".h", n##_syms, sizeof (n##_syms) / sizeof (n##_syms[0]), \
00576     n##_maybe, sizeof (n##_maybe) / sizeof (n##_maybe[0]), NULL }
00577   H(aio),
00578   H(assert),
00579   H(ctype),
00580   H(dirent),
00581   H(errno),
00582   H(fcntl),
00583   H(float),
00584   H(grp),
00585   H(limits),
00586   H(locale),
00587   H(math),
00588   Hc(mqueue, "_POSIX_MESSAGE_PASSING"),
00589   H(pthread),
00590   H(pwd),
00591   H(sched),
00592   H(semaphore),
00593   H(setjmp),
00594   H(signal),
00595   H(stdarg),
00596   H(stddef),
00597   H(stdio),
00598   H(stdlib),
00599   H(string),
00600   Hs(mman),
00601   Hs(stat),
00602   Hs(times),
00603   Hs(types),
00604   Hs(utsname),
00605   Hs(wait),
00606   H(termios),
00607   H(time),
00608   H(unistd),
00609   H(utime)
00610 };
00611 
00612 #define NUMBER_OF_HEADERS              (sizeof headers / sizeof *headers)
00613 
00614 
00615 /* Format string to build command to invoke compiler.  */
00616 static const char fmt[] = "\
00617 echo \"#include <%s>\" |\
00618 %s -E -dM -D_POSIX_SOURCE %s \
00619 -isystem `%s --print-prog-name=include` - > %s";
00620 
00621 static const char testfmt[] = "\
00622 echo \"#include <unistd.h>\n#if !defined %s || %s == -1\n#error not defined\n#endif\n\" |\
00623 %s -E -dM -D_POSIX_SOURCE %s \
00624 -isystem `%s --print-prog-name=include` - 2> /dev/null > %s";
00625 
00626 
00627 /* The compiler we use (given on the command line).  */
00628 const char *CC;
00629 /* The -I parameters for CC to find all headers.  */
00630 const char *INC;
00631 
00632 static char *xstrndup (const char *, size_t);
00633 static const char **get_null_defines (void);
00634 static int check_header (const struct header *, const char **);
00635 static int xsystem (const char *);
00636 
00637 int
00638 main (int argc, char *argv[])
00639 {
00640   int h;
00641   int result = 0;
00642   const char **ignore_list;
00643 
00644   CC = argc > 1 ? argv[1] : "gcc";
00645   INC = argc > 2 ? argv[2] : "";
00646 
00647   if (system (NULL) == 0)
00648     {
00649       puts ("Sorry, no command processor.");
00650       return EXIT_FAILURE;
00651     }
00652 
00653   /* First get list of symbols which are defined by the compiler.  */
00654   ignore_list = get_null_defines ();
00655 
00656   fputs ("Tested files:\n", stdout);
00657 
00658   for (h = 0; h < NUMBER_OF_HEADERS; ++h)
00659     result |= check_header (&headers[h], ignore_list);
00660 
00661   /* The test suite should return errors but for now this is not
00662      practical.  Give a warning and ask the user to correct the bugs.  */
00663   return result;
00664 }
00665 
00666 
00667 static char *
00668 xstrndup (const char *s, size_t n)
00669 {
00670   size_t len = n;
00671   char *new = malloc (len + 1);
00672 
00673   if (new == NULL)
00674     return NULL;
00675 
00676   new[len] = '\0';
00677   return memcpy (new, s, len);
00678 }
00679 
00680 
00681 /* Like system but propagate interrupt and quit signals.  */
00682 int
00683 xsystem (const char *cmd)
00684 {
00685   int status;
00686 
00687   status = system (cmd);
00688   if (status != -1)
00689     {
00690       if (WIFSIGNALED (status))
00691        {
00692          if (WTERMSIG (status) == SIGINT || WTERMSIG (status) == SIGQUIT)
00693            raise (WTERMSIG (status));
00694        }
00695       else if (WIFEXITED (status))
00696        {
00697          if (WEXITSTATUS (status) == SIGINT + 128
00698              || WEXITSTATUS (status) == SIGQUIT + 128)
00699            raise (WEXITSTATUS (status) - 128);
00700        }
00701     }
00702   return status;
00703 }
00704 
00705 
00706 static const char **
00707 get_null_defines (void)
00708 {
00709   char line[BUFSIZ], *command;
00710   char **result = NULL;
00711   size_t result_len = 0;
00712   size_t result_max = 0;
00713   FILE *input;
00714   int first = 1;
00715 
00716   macrofile = tmpnam (NULL);
00717 
00718   command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC)
00719                   + strlen (INC) + strlen (macrofile));
00720 
00721   if (command == NULL)
00722     {
00723       puts ("No more memory.");
00724       exit (1);
00725     }
00726 
00727   sprintf (command, fmt, "/dev/null", CC, INC, CC, macrofile);
00728 
00729   if (xsystem (command))
00730     {
00731       puts ("system() returned nonzero");
00732       return NULL;
00733     }
00734   free (command);
00735   input = fopen (macrofile, "r");
00736 
00737   if (input == NULL)
00738     {
00739       printf ("Could not read %s: ", macrofile);
00740       perror (NULL);
00741       return NULL;
00742     }
00743 
00744   while (fgets (line, sizeof line, input) != NULL)
00745     {
00746       char *start;
00747       if (strlen (line) < 9 || line[7] != ' ')
00748        { /* "#define A" */
00749          printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
00750                 line);
00751          continue;
00752        }
00753       if (line[8] == '_')
00754        /* It's a safe identifier.  */
00755        continue;
00756       if (result_len == result_max)
00757        {
00758          result_max += 10;
00759          result = realloc (result, result_max * sizeof (char **));
00760          if (result == NULL)
00761            {
00762              puts ("No more memory.");
00763              exit (1);
00764            }
00765        }
00766       start = &line[8];
00767       result[result_len++] = xstrndup (start, strcspn (start, " ("));
00768 
00769       if (first)
00770        {
00771          fputs ("The following identifiers will be ignored since the compiler defines them\nby default:\n", stdout);
00772          first = 0;
00773        }
00774       puts (result[result_len - 1]);
00775     }
00776   if (result_len == result_max)
00777     {
00778       result_max += 1;
00779       result = realloc (result, result_max * sizeof (char **));
00780       if (result == NULL)
00781        {
00782          puts ("No more memory.");
00783          exit (1);
00784        }
00785     }
00786   result[result_len] = NULL;
00787   fclose (input);
00788   remove (macrofile);
00789 
00790   return (const char **) result;
00791 }
00792 
00793 
00794 static int
00795 check_header (const struct header *header, const char **except)
00796 {
00797   char line[BUFSIZ], command[sizeof fmt + strlen (header->name)
00798                           + 2 * strlen (CC)
00799                           + strlen (INC) + strlen (macrofile)];
00800   FILE *input;
00801   int result = 0;
00802   int found[header->nsyms];
00803   int i;
00804 
00805   memset (found, '\0', header->nsyms * sizeof (int));
00806 
00807   printf ("=== %s ===\n", header->name);
00808   sprintf (command, fmt, header->name, CC, INC, CC, macrofile);
00809 
00810   /* First see whether this subset is supported at all.  */
00811   if (header->subset != NULL)
00812     {
00813       sprintf (line, testfmt, header->subset, header->subset, CC, INC, CC,
00814               macrofile);
00815       if (xsystem (line))
00816        {
00817          printf ("!! not available\n");
00818          return 0;
00819        }
00820     }
00821 
00822   if (xsystem (command))
00823     {
00824       puts ("system() returned nonzero");
00825       result = 1;
00826     }
00827   input = fopen (macrofile, "r");
00828 
00829   if (input == NULL)
00830     {
00831       printf ("Could not read %s: ", macrofile);
00832       perror (NULL);
00833       return 1;
00834     }
00835 
00836   while (fgets (line, sizeof line, input) != NULL)
00837     {
00838       const char **ignore;
00839       if (strlen (line) < 9 || line[7] != ' ')
00840        { /* "#define A" */
00841          printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
00842                 line);
00843          result = 1;
00844          continue;
00845        }
00846 
00847       /* Find next char after the macro identifier; this can be either
00848         a space or an open parenthesis.  */
00849       line[8 + strcspn (&line[8], " (")] = '\0';
00850 
00851       /* Now check whether it's one of the required macros.  */
00852       for (i = 0; i < header->nsyms; ++i)
00853        if (!strcmp (&line[8], header->syms[i]))
00854          break;
00855       if (i < header->nsyms)
00856        {
00857          found[i] = 1;
00858          continue;
00859        }
00860 
00861       /* Symbols starting with "_" are ok.  */
00862       if (line[8] == '_')
00863        continue;
00864 
00865       /* Maybe one of the symbols which are always defined.  */
00866       for (ignore = except; *ignore != NULL; ++ignore)
00867        if (! strcmp (&line[8], *ignore))
00868          break;
00869       if (*ignore != NULL)
00870        continue;
00871 
00872       /* Otherwise the symbol better should match one of the following.  */
00873       for (i = 0; i < header->nmaybe; ++i)
00874        if (fnmatch (header->maybe[i], &line[8], 0) == 0)
00875          break;
00876       if (i < header->nmaybe)
00877        continue;
00878 
00879       printf ("*  invalid macro `%s'\n", &line[8]);
00880       result |= 1;
00881     }
00882   fclose (input);
00883   remove (macrofile);
00884 
00885   for (i = 0; i < header->nsyms; ++i)
00886     if (found[i] == 0)
00887       printf ("** macro `%s' not defined\n", header->syms[i]);
00888 
00889   return result;
00890 }