* io/Versions (__dup2, __pipe): Added to GLIBC_2.0 for
[kopensolaris-gnu/glibc.git] / posix / annexc.c
1 /* Copyright (C) 1998 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the GNU C Library; see the file COPYING.LIB.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 #include <ctype.h>
20 #include <fnmatch.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <signal.h>
26 #include <sys/wait.h>
27
28 #define TMPFILE             "/tmp/macros"
29 #define HEADER_MAX          256
30
31 /* <aio.h>.  */
32 static const char *const aio_syms[] =
33 {
34   "AIO_ALLDONE", "AIO_CANCELED", "AIO_NOTCANCELED", "LIO_NOP", "LIO_NOWAIT",
35   "LIO_READ", "LIO_WAIT", "LIO_WRITE",
36   /* From <fcntl.h>.  */
37   "FD_CLOEXEC", "F_DUPFD", "F_GETFD", "F_GETFL", "F_GETLK", "F_RDLCK",
38   "F_SETFD", "F_SETFL", "F_SETLK", "F_SETLKW", "F_UNLCK", "F_WRLCK",
39   "O_ACCMODE", "O_APPEND", "O_CREAT", "O_DSYNC", "O_EXCL", "O_NOCTTY",
40   "O_NONBLOCK", "O_RDONLY", "O_RDWR", "O_RSYNC", "O_SYNC", "O_TRUNC",
41   "O_WRONLY",
42   /* From <signal.h>.  */
43   "SA_NOCLDSTOP", "SA_SIGINFO", "SIGABRT", "SIGALRM", "SIGBUS", "SIGCHLD",
44   "SIGCONT", "SIGEV_NONE", "SIGEV_SIGNAL", "SIGEV_SIGNAL", "SIGEV_THREAD",
45   "SIGFPE", "SIGHUP", "SIGILL", "SIGINT", "SIGKILL", "SIGPIPE", "SIGQUIT",
46   "SIGRTMAX", "SIGRTMIN", "SIGSEGV", "SIGSTOP", "SIGTERM", "SIGTSTP",
47   "SIGTTIN", "SIGTTOU", "SIGUSR1", "SIGUSR2", "SIG_BLOCK", "SIG_DFL",
48   "SIG_ERR", "SIG_IGN", "SIG_SETMASK", "SIG_UNBLOCK", "SI_ASYNCIO",
49   "SI_MESGQ", "SI_QUEUE", "SI_TIMER", "SI_USER"
50 };
51 static const char *const aio_maybe[] =
52 {
53   "aio_cancel", "aio_error", "aio_fsync", "aio_read", "aio_return",
54   "aio_suspend", "aio_write", "lio_listio",
55   /* From <fcntl.h>.  */
56   "creat", "fcntl", "open", "SEEK_CUR", "SEEK_END", "SEEK_SET", "S_IRGRP",
57   "S_IROTH", "S_IRUSR", "S_IRWXG", "S_IRWXO", "S_IRWXU", "S_ISBLK",
58   "S_ISCHR", "S_ISDIR", "S_ISFIFO", "S_ISGID", "S_ISREG", "S_ISUID",
59   "S_IWGRP", "S_IWOTH", "S_IWUSR", "S_IXGRP", "S_IXOTH", "S_IXUSR",
60   /* From <signal.h>.  */
61   "kill", "raise", "sigaction", "sigaddset", "sigdelset", "sigemptyset",
62   "sigfillset", "sigismember", "signal", "sigpending", "sigprocmask",
63   "sigqueue", "sigsuspend", "sigtimedwait", "sigwait", "sigwaitinfo"
64 };
65
66 /* <assert.h>.  */
67 static const char *const assert_syms[] =
68 {
69   "assert"
70 };
71 static const char *const assert_maybe[] =
72 {
73 };
74
75 /* <ctype.h>.   */
76 static const char *const ctype_syms[] =
77 {
78 };
79 static const char *const ctype_maybe[] =
80 {
81   "isalnum", "isalpha", "iscntrl", "isdigit", "isgraph", "islower",
82   "isprint", "ispunct", "isspace", "isupper", "isxdigit", "tolower",
83   "toupper"
84 };
85
86 /* <dirent.h>.  */
87 static const char *const dirent_syms[] =
88 {
89 };
90 static const char *const dirent_maybe[] =
91 {
92   "closedir", "opendir", "readdir", "readdir_r", "rewinddir"
93 };
94
95 /* <errno.h>.  */
96 static const char *const errno_syms[] =
97 {
98   "E2BIG", "EACCES", "EAGAIN", "EBADF", "EBADMSG", "EBUSY", "ECANCELED",
99   "ECHILD", "EDEADLK", "EDOM", "EEXIST", "EFAULT", "EFBIG", "EINPROGRESS",
100   "EINTR", "EINVAL", "EIO", "EISDIR", "EMFILE", "EMLINK", "EMSGSIZE",
101   "ENAMETOOLONG", "ENFILE", "ENODEV", "ENOENT", "ENOEXEC", "ENOLCK",
102   "ENOMEM", "ENOSPC", "ENOSYS", "ENOTDIR", "ENOTEMPTY", "ENOTSUP",
103   "ENOTTY", "ENXIO", "EPERM", "EPIPE", "ERANGE", "EROFS", "ESPIPE",
104   "ESRCH", "ETIMEDOUT", "EXDEV"
105 };
106 static const char *const errno_maybe[] =
107 {
108   "errno", "E*"
109 };
110
111 /* <fcntl.h>.  */
112 static const char *const fcntl_syms[] =
113 {
114   "FD_CLOEXEC", "F_DUPFD", "F_GETFD", "F_GETFL", "F_GETLK", "F_RDLCK",
115   "F_SETFD", "F_SETFL", "F_SETLK", "F_SETLKW", "F_UNLCK", "F_WRLCK",
116   "O_ACCMODE", "O_APPEND", "O_CREAT", "O_DSYNC", "O_EXCL", "O_NOCTTY",
117   "O_NONBLOCK", "O_RDONLY", "O_RDWR", "O_RSYNC", "O_SYNC", "O_TRUNC",
118   "O_WRONLY"
119 };
120 static const char *const fcntl_maybe[] =
121 {
122   "creat", "fcntl", "open", "SEEK_CUR", "SEEK_END", "SEEK_SET", "S_IRGRP",
123   "S_IROTH", "S_IRUSR", "S_IRWXG", "S_IRWXO", "S_IRWXU", "S_ISBLK",
124   "S_ISCHR", "S_ISDIR", "S_ISFIFO", "S_ISGID", "S_ISREG", "S_ISUID",
125   "S_IWGRP", "S_IWOTH", "S_IWUSR", "S_IXGRP", "S_IXOTH", "S_IXUSR"
126 };
127
128 /* <float.h>.  */
129 static const char *const float_syms[] =
130 {
131   "DBL_DIG", "DBL_EPSILON", "DBL_MANT_DIG", "DBL_MAX", "DBL_MAX_10_EXP",
132   "DBL_MAX_EXP", "DBL_MIN", "DBL_MIN_10_EXP", "DBL_MIN_EXP", "FLT_DIG",
133   "FLT_EPSILON", "FLT_MANT_DIG", "FLT_MAX", "FLT_MAX_10_EXP", "FLT_MAX_EXP",
134   "FLT_MIN", "FLT_MIN_10_EXP", "FLT_MIN_EXP", "FLT_RADIX", "FLT_ROUNDS",
135   "LDBL_DIG", "LDBL_EPSILON", "LDBL_MANT_DIG", "LDBL_MAX", "LDBL_MAX_10_EXP",
136   "LDBL_MAX_EXP", "LDBL_MIN", "LDBL_MIN_10_EXP", "LDBL_MIN_EXP"
137 };
138 static const char *const float_maybe[] =
139 {
140 };
141
142 /* <grp.h>.  */
143 static const char *const grp_syms[] =
144 {
145 };
146 static const char *const grp_maybe[] =
147 {
148   "getgrgid", "getgrgid_r", "getgrnam", "getgrnam_r"
149 };
150
151 /* <limits.h>.  */
152 static const char *const limits_syms[] =
153 {
154   "_POSIX_AIO_LISTIO_MAX", "_POSIX_AIO_MAX", "_POSIX_ARG_MAX",
155   "_POSIX_CHILD_MAX", "_POSIX_CLOCKRES_MAX", "_POSIX_DELAYTIMER_MAX",
156   "_POSIX_LINK_MAX", "_POSIX_LOGIN_NAME_MAX", "_POSIX_MAX_CANON",
157   "_POSIX_MAX_INPUT", "_POSIX_MQ_OPEN_MAX", "_POSIX_MQ_PRIO_MAX",
158   "_POSIX_NAME_MAX", "_POSIX_NGROUPS_MAX", "_POSIX_OPEN_MAX",
159   "_POSIX_PATH_MAX", "_POSIX_PIPE_BUF", "_POSIX_RTSIG_MAX",
160   "_POSIX_SEM_NSEMS_MAX", "_POSIX_SEM_VALUE_MAX", "_POSIX_SIGQUEUE_MAX",
161   "_POSIX_SSIZE_MAX", "_POSIX_STREAM_MAX",
162   "_POSIX_THREAD_DESTRUCTOR_ITERATIONS", "_POSIX_THREAD_KEYS_MAX",
163   "_POSIX_THREAD_THREADS_MAX", "_POSIX_TIMER_MAX", "_POSIX_TTY_NAME_MAX",
164   "_POSIX_TZNAME_MAX", "_POSIX_THREAD_DESTRUCTOR_ITERATIONS",
165   "CHAR_BIT", "CHAR_MAX", "CHAR_MIN", "INT_MAX", "INT_MIN", "LONG_MAX",
166   "LONG_MIN", "MB_LEN_MAX", "NGROUPS_MAX", "PAGESIZE", "SCHAR_MAX",
167   "SCHAR_MIN", "SHRT_MAX", "SHRT_MIN", "UCHAR_MAX", "UINT_MAX",
168   "ULONG_MAX", "USHRT_MAX"
169 };
170 static const char *const limits_maybe[] =
171 {
172   "AIO_LISTIO_MAX", "AIO_MAX", "ARG_MAX", "CHILD_MAX", "DELAYTIMER_MAX",
173   "LINK_MAX", "LOGIN_NAME_MAX", "LONG_MAX", "LONG_MIN", "MAX_CANON",
174   "MAX_INPUT", "MQ_OPEN_MAX", "MQ_PRIO_MAX", "NAME_MAX", "OPEN_MAX",
175   "PATH_MAX", "PIPE_BUF", "RTSIG_MAX", "PTHREAD_DESTRUCTOR_ITERATIONS",
176   "PTHREAD_KEYS_MAX", "PTHREAD_STACK_MIN", "PTHREAD_THREADS_MAX"
177 };
178
179 /* <locale.h>.  */
180 static const char *const locale_syms[] =
181 {
182   "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC",
183   "LC_TIME", "NULL"
184 };
185 static const char *const locale_maybe[] =
186 {
187   "LC_*", "localeconv", "setlocale"
188 };
189
190 /* <math.h>.  */
191 static const char *const math_syms[] =
192 {
193   "HUGE_VAL"
194 };
195 static const char *const math_maybe[] =
196 {
197   "acos", "asin", "atan2", "atan", "ceil", "cos", "cosh", "exp",
198   "fabs", "floor", "fmod", "frexp", "ldexp", "log10", "log", "modf",
199   "pow", "sin", "sinh", "sqrt", "tan", "tanh",
200   "acosf", "asinf", "atan2f", "atanf", "ceilf", "cosf", "coshf", "expf",
201   "fabsf", "floorf", "fmodf", "frexpf", "ldexpf", "log10f", "logf", "modff",
202   "powf", "sinf", "sinhf", "sqrtf", "tanf", "tanhf",
203   "acosl", "asinl", "atan2l", "atanl", "ceill", "cosl", "coshl", "expl",
204   "fabsl", "floorl", "fmodl", "frexpl", "ldexpl", "log10l", "logl", "modfl",
205   "powl", "sinl", "sinhl", "sqrtl", "tanl", "tanhl"
206 };
207
208 /* <mqueue.h>.  */
209 static const char *const mqueue_syms[] =
210 {
211 };
212 static const char *const mqueue_maybe[] =
213 {
214   "mq_close", "mq_getattr", "mq_notify", "mq_open", "mq_receive",
215   "mq_send", "mq_setattr", "mq_unlink"
216 };
217
218 /* <pthread.h>.  */
219 static const char *const pthread_syms[] =
220 {
221   "PTHREAD_CANCELED", "PTHREAD_CANCEL_ASYNCHRONOUS",
222   "PTHREAD_CANCEL_DEFERRED", "PTHREAD_CANCEL_DISABLE", "PTHREAD_CANCEL_ENABLE",
223   "PTHREAD_COND_INITIALIZER", "PTHREAD_CREATE_DETACHED",
224   "PTHREAD_CREATE_JOINABLE", "PTHREAD_EXPLICIT_SCHED",
225   "PTHREAD_INHERIT_SCHED", "PTHREAD_MUTEX_INITIALIZER",
226   "PTHREAD_ONCE_INIT", "PTHREAD_PRIO_INHERIT", "PTHREAD_PRIO_NONE",
227   "PTHREAD_PRIO_PROTECT", "PTHREAD_PROCESS_PRIVATE",
228   "PTHREAD_PROCESS_SHARED", "PTHREAD_SCOPE_PROCESS", "PTHREAD_SCOPE_SYSTEM",
229   /* These come from <sched.h>.  */
230   "SCHED_FIFO", "SCHED_OTHER", "SCHED_RR",
231   /* These come from <time.h>.  */
232   "CLK_TCK", "CLOCKS_PER_SEC", "CLOCK_REALTIME", "NULL", "TIMER_ABSTIME"
233 };
234 static const char *const pthread_maybe[] =
235 {
236   "pthread_atfork", "pthread_attr_destroy", "pthread_attr_getdetachstate",
237   "pthread_attr_getinheritsched", "pthread_attr_getschedparam",
238   "pthread_attr_getschedpolicy", "pthread_attr_getscope",
239   "pthread_attr_getstackaddr", "pthread_attr_getstacksize",
240   "pthread_attr_init", "pthread_attr_setdetachstate",
241   "pthread_attr_setinheritsched", "pthread_attr_setschedparam",
242   "pthread_attr_setschedpolicy", "pthread_attr_setscope",
243   "pthread_attr_setstackaddr", "pthread_attr_setstacksize",
244   "pthread_cleanup_pop", "pthread_cleanup_push", "pthread_cond_broadcast",
245   "pthread_cond_destroy", "pthread_cond_init", "pthread_cond_signal",
246   "pthread_cond_timedwait", "pthread_cond_wait", "pthread_condattr_destroy",
247   "pthread_condattr_getpshared", "pthread_condattr_init",
248   "pthread_condattr_setpshared", "pthread_create", "pthread_detach",
249   "pthread_equal", "pthread_exit", "pthread_getspecific", "pthread_join",
250   "pthread_key_create", "pthread_key_destroy", "pthread_kill",
251   "pthread_mutex_destroy", "pthread_mutex_getprioceiling",
252   "pthread_mutex_init", "pthread_mutex_lock", "pthread_mutex_setprioceiling",
253   "pthread_mutex_trylock", "pthread_mutex_unlock", "pthread_mutexattr_destroy",
254   "pthread_mutexattr_getprioceiling", "pthread_mutexattr_getprotocol",
255   "pthread_mutexattr_getpshared", "pthread_mutexattr_init",
256   "pthread_mutexattr_setprioceiling", "pthread_mutexattr_setprotocol",
257   "pthread_mutexattr_setpshared", "pthread_once", "pthread_self",
258   "pthread_setcancelstate", "pthread_setcanceltype", "pthread_setspecific",
259   "pthread_sigmask", "pthread_testcancel"
260   /* These come from <sched.h>.  */
261   "sched_get_priority_max", "sched_get_priority_min",
262   "sched_get_rr_interval", "sched_getparam", "sched_getscheduler",
263   "sched_setparam", "sched_setscheduler", "sched_yield",
264   /* These come from <time.h>.  */
265   "asctime", "asctime_r", "clock", "clock_getres", "clock_gettime",
266   "clock_settime", "ctime", "ctime_r", "difftime", "gmtime", "gmtime_r",
267   "localtime", "localtime_r", "mktime", "nanosleep", "strftime", "time",
268   "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime",
269   "timer_settime", "tzset"
270 };
271
272 /* <pwd.h>.  */
273 static const char *const pwd_syms[] =
274 {
275 };
276 static const char *const pwd_maybe[] =
277 {
278   "getpwnam", "getpwnam_r", "getpwuid", "getpwuid_r"
279 };
280
281 /* <sched.h>.  */
282 static const char *const sched_syms[] =
283 {
284   "SCHED_FIFO", "SCHED_OTHER", "SCHED_RR",
285 };
286 static const char *const sched_maybe[] =
287 {
288   "sched_get_priority_max", "sched_get_priority_min",
289   "sched_get_rr_interval", "sched_getparam", "sched_getscheduler",
290   "sched_setparam", "sched_setscheduler", "sched_yield",
291   /* These come from <time.h>.  */
292   "CLK_TCK", "CLOCKS_PER_SEC", "CLOCK_REALTIME", "NULL", "TIMER_ABSTIME"
293   "asctime", "asctime_r", "clock", "clock_getres", "clock_gettime",
294   "clock_settime", "ctime", "ctime_r", "difftime", "gmtime", "gmtime_r",
295   "localtime", "localtime_r", "mktime", "nanosleep", "strftime", "time",
296   "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime",
297   "timer_settime", "tzset"
298 };
299
300 /* <semaphore.h>.  */
301 static const char *const semaphore_syms[] =
302 {
303 };
304 static const char *const semaphore_maybe[] =
305 {
306   "sem_close", "sem_destroy", "sem_getvalue", "sem_init", "sem_open",
307   "sen_post", "sem_trywait", "sem_unlink", "sem_wait"
308 };
309
310 /* <setjmp.h>.  */
311 static const char *const setjmp_syms[] =
312 {
313 };
314 static const char *const setjmp_maybe[] =
315 {
316   "longjmp", "setjmp", "siglongjmp", "sigsetjmp"
317 };
318
319 /* <signal.h>.  */
320 static const char *const signal_syms[] =
321 {
322   "SA_NOCLDSTOP", "SA_SIGINFO", "SIGABRT", "SIGALRM", "SIGBUS", "SIGCHLD",
323   "SIGCONT", "SIGEV_NONE", "SIGEV_SIGNAL", "SIGEV_THREAD",
324   "SIGFPE", "SIGHUP", "SIGILL", "SIGINT", "SIGKILL", "SIGPIPE", "SIGQUIT",
325   "SIGRTMAX", "SIGRTMIN", "SIGSEGV", "SIGSTOP", "SIGTERM", "SIGTSTP",
326   "SIGTTIN", "SIGTTOU", "SIGUSR1", "SIGUSR2", "SIG_BLOCK", "SIG_DFL",
327   "SIG_ERR", "SIG_IGN", "SIG_SETMASK", "SIG_UNBLOCK", "SI_ASYNCIO",
328   "SI_MESGQ", "SI_QUEUE", "SI_TIMER", "SI_USER"
329 };
330 static const char *const signal_maybe[] =
331 {
332   "kill", "raise", "sigaction", "sigaddset", "sigdelset", "sigemptyset",
333   "sigfillset", "sigismember", "signal", "sigpending", "sigprocmask",
334   "sigqueue", "sigsuspend", "sigtimedwait", "sigwait", "sigwaitinfo"
335 };
336
337 /* <stdarg.h>.  */
338 static const char *const stdarg_syms[] =
339 {
340   "va_arg", "va_end", "va_start"
341 };
342 static const char *const stdarg_maybe[] =
343 {
344   "va_list"
345 };
346
347 /* <stddef.h>.  */
348 static const char *const stddef_syms[] =
349 {
350   "NULL", "offsetof"
351 };
352 static const char *const stddef_maybe[] =
353 {
354 };
355
356 /* <stdio.h>.  */
357 static const char *const stdio_syms[] =
358 {
359   "BUFSIZ", "EOF", "FILENAME_MAX", "FOPEN_MAX", "L_ctermid", "L_cuserid",
360   "L_tmpnam", "NULL", "SEEK_CUR", "SEEK_END", "SEEK_SET", "STREAM_MAX",
361   "TMP_MAX", "stderr", "stdin", "stdout", "_IOFBF", "_IOLBF", "_IONBF"
362 };
363 static const char *const stdio_maybe[] =
364 {
365   "clearerr", "fclose", "fdopen", "feof", "ferror", "fflush", "fgetc",
366   "fgetpos", "fgets", "fileno", "flockfile", "fopen", "fprintf", "fputc",
367   "fputs", "fread", "freopen", "fscanf", "fseek", "fsetpos", "ftell",
368   "ftrylockfile", "funlockfile", "fwrite", "getc", "getchar",
369   "getchar_unlocked", "getc_unlocked", "gets", "perror", "printf", "putc",
370   "putchar", "putchar_unlocked", "putc_unlocked", "puts", "remove", "rename",
371   "rewind", "scanf", "setbuf", "setvbuf", "sprintf", "sscanf", "tmpfile",
372   "tmpnam", "ungetc", "vfprintf", "vprintf", "vsprintf"
373 };
374
375 /* <stdlib.h>.  */
376 static const char *const stdlib_syms[] =
377 {
378   "EXIT_FAILURE", "EXIT_SUCCESS", "MB_CUR_MAX", "NULL", "RAND_MAX"
379 };
380 static const char *const stdlib_maybe[] =
381 {
382   "abort", "abs", "atexit", "atof", "atoi", "atol", "bsearch", "calloc",
383   "div", "exit", "free", "getenv", "labs", "ldiv", "malloc", "mblen",
384   "mbstowcs", "mbtowc", "qsort", "rand", "rand_r", "realloc", "srand",
385   "strtod", "strtol", "strtoul", "system", "wcstombs", "wctomb"
386 };
387
388 /* <string.h>.  */
389 static const char *const string_syms[] =
390 {
391   "NULL"
392 };
393 static const char *const string_maybe[] =
394 {
395   "memchr", "memcmp", "memcpy", "memmove", "memset", "strcat", "strchr",
396   "strcmp", "strcoll", "strcpy", "strcspn", "strerror", "strlen",
397   "strncat", "strncmp", "strncpy", "strpbrk", "strrchr", "strspn",
398   "strstr", "strtok", "strtok_r", "strxfrm"
399 };
400
401 /* <sys/mman.h>.  */
402 static const char *const mman_syms[] =
403 {
404   "MAP_FAILED", "MAP_FIXED", "MAP_PRIVATE", "MAP_SHARED", "MCL_CURRENT",
405   "MCL_FUTURE", "MS_ASYNC", "MS_INVALIDATE", "MS_SYNC", "PROT_EXEC",
406   "PROT_NONE", "PROT_READ", "PROT_WRITE"
407 };
408 static const char *const mman_maybe[] =
409 {
410   "mlock", "mlockall", "mmap", "mprotect", "msync", "munlock", "munlockall",
411   "munmap", "shm_open", "shm_unlock"
412 };
413
414 /* <sys/stat.h>.  */
415 static const char *const stat_syms[] =
416 {
417   "S_IRGRP", "S_IROTH", "S_IRUSR", "S_IRWXG", "S_IRWXO", "S_IRWXU",
418   "S_ISBLK", "S_ISCHR", "S_ISDIR", "S_ISFIFO", "S_ISGID", "S_ISREG",
419   "S_ISUID", "S_IWGRP", "S_IWOTH", "S_IWUSR", "S_IXGRP", "S_IXOTH",
420   "S_IXUSR", "S_TYPEISMQ", "S_TYPEISSEM", "S_TYPEISSHM"
421 };
422 static const char *const stat_maybe[] =
423 {
424   "chmod", "fchmod", "fstat", "mkdir", "mkfifo", "stat", "umask"
425 };
426
427 /* <sys/times.h>.  */
428 static const char *const times_syms[] =
429 {
430 };
431 static const char *const times_maybe[] =
432 {
433   "times"
434 };
435
436 /* <sys/types.h>.  */
437 static const char *const types_syms[] =
438 {
439 };
440 static const char *const types_maybe[] =
441 {
442 };
443
444 /* <sys/utsname.h>.  */
445 static const char *const utsname_syms[] =
446 {
447 };
448 static const char *const utsname_maybe[] =
449 {
450   "uname"
451 };
452
453 /* <sys/wait.h>.  */
454 static const char *const wait_syms[] =
455 {
456   "WEXITSTATUS", "WIFEXITED", "WIFSIGNALED", "WIFSTOPPED", "WNOHANG",
457   "WSTOPSIG", "WTERMSIG", "WUNTRACED"
458 };
459 static const char *const wait_maybe[] =
460 {
461   "wait", "waitpid"
462 };
463
464 /* <termios.h>.  */
465 static const char *const termios_syms[] =
466 {
467   "B0", "B110", "B1200", "B134", "B150", "B1800", "B19200", "B200", "B2400",
468   "B300", "B38400", "B4800", "B50", "B600", "B75", "B9600", "BRKINT", "CLOCAL",
469   "CREAD", "CS5", "CS6", "CS7", "CS8", "CSIZE", "CSTOPN", "ECHO", "ECHOE",
470   "ECHOK", "ECHONL", "HUPCL", "ICANON", "ICRNL", "IEXTEN", "IGNBRK", "IGNCR",
471   "IGNPAR", "INCLR", "INPCK", "ISIG", "ISTRIP", "IXOFF", "IXON", "NCCS",
472   "NOFLSH", "OPOST", "PARENB", "PARMRK", "PARODD", "TCIFLUSH", "TCIOFF",
473   "TCIOFLUSH", "TCOFLUSH", "TCOOFF", "TCOON", "TCSADRAIN", "TCSAFLUSH",
474   "TCSANOW", "TOSTOP", "VEOF", "VEOL", "VERASE", "VINTR", "VKILL", "VMIN",
475   "VQUIT", "VSTART", "VSTOP", "VSUSP", "VTIME"
476 };
477 static const char *const termios_maybe[] =
478 {
479   "cfgetispeed", "cfgetospeed", "cfsetispeed", "cfsetospeed", "tcdrain",
480   "tcflow", "tcflush", "tcgetattr", "tcsendbrk", "tcsetattr"
481 };
482
483 /* <time.h>.  */
484 static const char *const time_syms[] =
485 {
486   "CLK_TCK", "CLOCKS_PER_SEC", "CLOCK_REALTIME", "NULL", "TIMER_ABSTIME"
487 };
488 static const char *const time_maybe[] =
489 {
490   "asctime", "asctime_r", "clock", "clock_getres", "clock_gettime",
491   "clock_settime", "ctime", "ctime_r", "difftime", "gmtime", "gmtime_r",
492   "localtime", "localtime_r", "mktime", "nanosleep", "strftime", "time",
493   "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime",
494   "timer_settime", "tzset"
495 };
496
497 /* <unistd.h>.  */
498 static const char *const unistd_syms[] =
499 {
500   "F_OK", "NULL", "R_OK", "SEEK_CUR", "SEEK_END", "SEEK_SET", "STDERR_FILENO",
501   "STDIN_FILENO", "STDOUT_FILENO", "W_OK", "X_OK",
502   "_PC_ASYNC_IO", "_PC_CHOWN_RESTRICTED", "_PC_LINK_MAX", "_PC_MAX_CANON",
503   "_PC_MAX_INPUT", "_PC_NAME_MAX", "_PC_NO_TRUNC", "_PC_PATH_MAX",
504   "_PC_PIPE_BUF", "_PC_PRIO_IO", "_PC_SYNC_IO", "_PC_VDISABLE",
505   "_SC_AIO_LISTIO_MAX", "_SC_AIO_MAX", "_SC_AIO_PRIO_DELTA_MAX",
506   "_SC_ARG_MAX", "_SC_ASYNCHRONOUS_IO", "_SC_CHILD_MAX", "_SC_CLK_TCK",
507   "_SC_DELAYTIMER_MAX", "_SC_FSYNC", "_SC_GETGR_R_SIZE_MAX",
508   "_SC_GETPW_R_SIZE_MAX", "_SC_JOB_CONTROL", "_SC_LOGIN_NAME_MAX",
509   "_SC_MAPPED_FILES", "_SC_MEMLOCK", "_SC_MEMLOCK_RANGE",
510   "_SC_MEMORY_PROTECTION", "_SC_MESSAGE_PASSING", "_SC_MQ_OPEN_MAX",
511   "_SC_MQ_PRIO_MAX", "_SC_NGROUPS_MAX", "_SC_OPEN_MAX", "_SC_PAGESIZE",
512   "_SC_PRIORITIZED_IO", "_SC_PRIORITY_SCHEDULING", "_SC_REALTIME_SIGNALS",
513   "_SC_RTSIG_MAX", "_SC_SAVED_IDS", "_SC_SEMAPHORES", "_SC_SEM_NSEMS_MAX",
514   "_SC_SEM_VALUE_MAX", "_SC_SHARED_MEMORY_OBJECTS", "_SC_SIGQUEUE_MAX",
515   "_SC_STREAM_MAX", "_SC_SYNCHRONIZED_IO", "_SC_THREADS",
516   "_SC_THREAD_ATTR_STACKADDR", "_SC_THREAD_ATTR_STACKSIZE",
517   "_SC_THREAD_DESTRUCTOR_ITERATIONS", "_SC_THREAD_PRIO_INHERIT",
518   "_SC_THREAD_PRIORITY_SCHEDULING", "_SC_THREAD_PRIO_PROTECT",
519   "_SC_THREAD_PROCESS_SHARED", "_SC_THREAD_SAFE_FUNCTIONS",
520   "_SC_THREAD_STACK_MIN", "_SC_THREAD_THREADS_MAX", "_SC_TIMERS",
521   "_SC_TIMER_MAX", "_SC_TTY_NAME_MAX", "_SC_TZNAME_MAX", "_SC_VERSION"
522 };
523 static const char *const unistd_maybe[] =
524 {
525   "_POSIX_ASYNCHRONOUS_IO", "_POSIX_ASYNC_IO", "_POSIX_CHOWN_RESTRICTED",
526   "_POSIX_FSYNC", "_POSIX_JOB_CONTROL", "_POSIX_MAPPED_FILES",
527   "_POSIX_MEMLOCK", "_POSIX_MEMLOCK_RANGE", "_MEMORY_PROTECTION",
528   "_POSIX_MESSAGE_PASSING", "_POSIX_NO_TRUNC", "_POSIX_PRIORITIZED_IO",
529   "_POSIX_PRIORITY_SCHEDULING", "_POSIX_PRIO_IO", "_POSIX_REATIME_SIGNALS",
530   "_POSIX_SAVED_IDS", "_POSIX_SEMAPHORES", "_POSIX_SHARED_MEMORY_OBJECTS",
531   "_POSIX_SYNCHRONIZED_IO", "_POSIX_SYNC_IO", "_POSIX_THREADS",
532   "_POSIX_THREAD_ATTR_STACKADDR", "_POSIX_THREAD_ATTR_STACKSIZE",
533   "_POSIX_THREAD_PRIO_INHERIT", "_POSIX_THREAD_PRIO_PROTECT",
534   "_POSIX_THREAD_PROCESS_SHARED", "_POSIX_THREAD_SAFE_FUNCTIONS",
535   "_POSIX_THREAD_PRIORITY_SCHEDULING", "_POSIX_TIMERS",
536   "_POSIX_VDISABLE", "_POSIX_VERSION",
537   "_exit", "access", "alarm", "chdir", "chown", "close", "ctermid", "cuserid",
538   "dup2", "dup", "execl", "execle", "execlp", "execv", "execve", "execvp",
539   "fdatasync", "fork", "fpathconf", "fsync", "ftruncate", "getcwd", "getegid",
540   "geteuid", "getgid", "getgroups", "getlogin", "getlogin_r", "getpgrp",
541   "getpid", "getppid", "getuid", "isatty", "link", "lseek", "pathconf",
542   "pause", "pipe", "read", "rmdir", "setgid", "setgpid", "setsid", "setuid",
543   "sleep", "sleep", "sysconf", "tcgetpgrp", "tcsetpgrp", "ttyname",
544   "ttyname_r", "unlink", "write"
545 };
546
547 /* <utime.h>.  */
548 static const char *const utime_syms[] =
549 {
550 };
551 static const char *const utime_maybe[] =
552 {
553   "utime"
554 };
555
556
557 static struct header
558 {
559   const char *name;
560   const char *const *syms;
561   size_t nsyms;
562   const char *const *maybe;
563   size_t nmaybe;
564   const char *subset;
565 } headers[] =
566 {
567 #define H(n) \
568   { #n ".h", n##_syms, sizeof (n##_syms) / sizeof (n##_syms[0]), \
569     n##_maybe, sizeof (n##_maybe) / sizeof (n##_maybe[0]), NULL }
570 #define Hc(n, s) \
571   { #n ".h", n##_syms, sizeof (n##_syms) / sizeof (n##_syms[0]), \
572     n##_maybe, sizeof (n##_maybe) / sizeof (n##_maybe[0]), s }
573 #define Hs(n) \
574   { "sys/" #n ".h", n##_syms, sizeof (n##_syms) / sizeof (n##_syms[0]), \
575     n##_maybe, sizeof (n##_maybe) / sizeof (n##_maybe[0]), NULL }
576   H(aio),
577   H(assert),
578   H(ctype),
579   H(dirent),
580   H(errno),
581   H(fcntl),
582   H(float),
583   H(grp),
584   H(limits),
585   H(locale),
586   H(math),
587   Hc(mqueue, "_POSIX_MESSAGE_PASSING"),
588   H(pthread),
589   H(pwd),
590   H(sched),
591   H(semaphore),
592   H(setjmp),
593   H(signal),
594   H(stdarg),
595   H(stddef),
596   H(stdio),
597   H(stdlib),
598   H(string),
599   Hs(mman),
600   Hs(stat),
601   Hs(times),
602   Hs(types),
603   Hs(utsname),
604   Hs(wait),
605   H(termios),
606   H(time),
607   H(unistd),
608   H(utime)
609 };
610
611 #define NUMBER_OF_HEADERS              (sizeof headers / sizeof *headers)
612
613
614 /* Format string to build command to invoke compiler.  */
615 static const char fmt[] = "\
616 echo \"#include <%s>\" |\
617 %s -E -dM -D_POSIX_SOURCE -D_LIBC %s \
618 -isystem `%s --print-prog-name=include` - > %s";
619
620 static const char testfmt[] = "\
621 echo \"#include <unistd.h>\n#ifndef %s\n#error not defined\n#endif\n\" |\
622 %s -E -dM -D_POSIX_SOURCE -D_LIBC %s \
623 -isystem `%s --print-prog-name=include` - 2> /dev/null > %s";
624
625
626 /* The compiler we use (given on the command line).  */
627 const char *CC;
628 /* The -I parameters for CC to find all headers.  */
629 const char *INC;
630
631 static char *xstrndup (const char *, size_t);
632 static const char **get_null_defines (void);
633 static int check_header (const struct header *, const char **);
634 static int xsystem (const char *);
635
636 int
637 main (int argc, char *argv[])
638 {
639   int h;
640   int result = 0;
641   const char **ignore_list;
642
643   CC = argc > 1 ? argv[1] : "gcc";
644   INC = argc > 2 ? argv[2] : "";
645
646   if (system (NULL) == 0)
647     {
648       puts ("Sorry, no command processor.");
649       return EXIT_FAILURE;
650     }
651
652   /* First get list of symbols which are defined by the compiler.  */
653   ignore_list = get_null_defines ();
654
655   fputs ("Tested files:\n", stdout);
656
657   for (h = 0; h < NUMBER_OF_HEADERS; ++h)
658     result |= check_header (&headers[h], ignore_list);
659
660   /* The test suite should return errors but for now this is not
661      practical.  Give a warning and ask the user to correct the bugs.  */
662   return result;
663 }
664
665
666 static char *
667 xstrndup (const char *s, size_t n)
668 {
669   size_t len = n;
670   char *new = malloc (len + 1);
671
672   if (new == NULL)
673     return NULL;
674
675   new[len] = '\0';
676   return memcpy (new, s, len);
677 }
678
679
680 /* Like system but propagate interrupt and quit signals.  */
681 int
682 xsystem (const char *cmd)
683 {
684   int status;
685
686   status = system (cmd);
687   if (status != -1)
688     {
689       if (WIFSIGNALED (status))
690         {
691           if (WTERMSIG (status) == SIGINT || WTERMSIG (status) == SIGQUIT)
692             raise (WTERMSIG (status));
693         }
694       else if (WIFEXITED (status))
695         {
696           if (WEXITSTATUS (status) == SIGINT + 128
697               || WEXITSTATUS (status) == SIGQUIT + 128)
698             raise (WEXITSTATUS (status) - 128);
699         }
700     }
701   return status;
702 }
703
704
705 static const char **
706 get_null_defines (void)
707 {
708   char line[BUFSIZ], *command;
709   char **result = NULL;
710   size_t result_len = 0;
711   size_t result_max = 0;
712   FILE *input;
713   int first = 1;
714
715   command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC)
716                     + strlen (INC) + strlen (TMPFILE));
717
718   if (command == NULL)
719     {
720       puts ("No more memory.");
721       exit (1);
722     }
723
724   sprintf (command, fmt, "/dev/null", CC, INC, CC, TMPFILE);
725
726   if (xsystem (command))
727     {
728       puts ("system() returned nonzero");
729       return NULL;
730     }
731   free (command);
732   input = fopen (TMPFILE, "r");
733
734   if (input == NULL)
735     {
736       printf ("Could not read %s: ", TMPFILE);
737       perror (NULL);
738       return NULL;
739     }
740
741   while (fgets (line, sizeof line, input) != NULL)
742     {
743       char *start;
744       if (strlen (line) < 9 || line[7] != ' ')
745         { /* "#define A" */
746           printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
747                   line);
748           continue;
749         }
750       if (line[8] == '_')
751         /* It's a safe identifier.  */
752         continue;
753       if (result_len == result_max)
754         {
755           result_max += 10;
756           result = realloc (result, result_max * sizeof (char **));
757           if (result == NULL)
758             {
759               puts ("No more memory.");
760               exit (1);
761             }
762         }
763       start = &line[8];
764       result[result_len++] = xstrndup (start, strcspn (start, " ("));
765
766       if (first)
767         {
768           fputs ("The following identifiers will be ignored since the compiler defines them\nby default:\n", stdout);
769           first = 0;
770         }
771       puts (result[result_len - 1]);
772     }
773   if (result_len == result_max)
774     {
775       result_max += 1;
776       result = realloc (result, result_max * sizeof (char **));
777       if (result == NULL)
778         {
779           puts ("No more memory.");
780           exit (1);
781         }
782     }
783   result[result_len] = NULL;
784   fclose (input);
785   remove (TMPFILE);
786
787   return (const char **) result;
788 }
789
790
791 static int
792 check_header (const struct header *header, const char **except)
793 {
794   char line[BUFSIZ], *command;
795   FILE *input;
796   int result = 0;
797   int found[header->nsyms];
798   int i;
799
800   memset (found, '\0', header->nsyms * sizeof (int));
801   command = alloca (sizeof fmt + strlen (header->name) + 2 * strlen (CC)
802                     + strlen (INC) + strlen (TMPFILE));
803
804
805   if (command == NULL)
806     {
807       puts ("No more memory.");
808       exit (1);
809     }
810
811   printf ("=== %s ===\n", header->name);
812   sprintf (command, fmt, header->name, CC, INC, CC, TMPFILE);
813
814   /* First see whether this subset is supported at all.  */
815   if (header->subset != NULL)
816     {
817       sprintf (line, testfmt, header->subset, CC, INC, CC, TMPFILE);
818       if (xsystem (line))
819         {
820           printf ("!! not available\n");
821           return 0;
822         }
823     }
824
825   if (xsystem (command))
826     {
827       puts ("system() returned nonzero");
828       result = 1;
829     }
830   input = fopen (TMPFILE, "r");
831
832   if (input == NULL)
833     {
834       printf ("Could not read %s: ", TMPFILE);
835       perror (NULL);
836       return 1;
837     }
838
839   while (fgets (line, sizeof line, input) != NULL)
840     {
841       const char **ignore;
842       if (strlen (line) < 9 || line[7] != ' ')
843         { /* "#define A" */
844           printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
845                   line);
846           result = 1;
847           continue;
848         }
849
850       /* Find next char after the macro identifier; this can be either
851          a space or an open parenthesis.  */
852       line[8 + strcspn (&line[8], " (")] = '\0';
853
854       /* Now check whether it's one of the required macros.  */
855       for (i = 0; i < header->nsyms; ++i)
856         if (!strcmp (&line[8], header->syms[i]))
857           break;
858       if (i < header->nsyms)
859         {
860           found[i] = 1;
861           continue;
862         }
863
864       /* Symbols starting with "_" are ok.  */
865       if (line[8] == '_')
866         continue;
867
868       /* Maybe one of the symbols which are always defined.  */
869       for (ignore = except; *ignore != NULL; ++ignore)
870         if (! strcmp (&line[8], *ignore))
871           break;
872       if (*ignore != NULL)
873         continue;
874
875       /* Otherwise the symbol better should match one of the following.  */
876       for (i = 0; i < header->nmaybe; ++i)
877         if (fnmatch (header->maybe[i], &line[8], 0) == 0)
878           break;
879       if (i < header->nmaybe)
880         continue;
881
882       printf ("*  invalid macro `%s'\n", &line[8]);
883       result |= 1;
884     }
885   fclose (input);
886   remove (TMPFILE);
887
888   for (i = 0; i < header->nsyms; ++i)
889     if (found[i] == 0)
890       printf ("** macro `%s' not defined\n", header->syms[i]);
891
892   return result;
893 }