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