1 /* Copyright (C) 1998-2022 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 Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18 #include <ctype.h>
19 #include <fnmatch.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <sys/wait.h>
26
27 #define HEADER_MAX 256
28
29 static char macrofile[] = "/tmp/annexc.XXXXXX";
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 %s \
618 -isystem `%s --print-prog-name=include` - > %s";
619
620 static const char testfmt[] = "\
621 echo \"#include <unistd.h>\n#if !defined %s || %s == -1\n#error not defined\n#endif\n\" |\
622 %s -E -dM -D_POSIX_SOURCE %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
main(int argc,char * argv[])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 remove (macrofile);
661
662 /* The test suite should return errors but for now this is not
663 practical. Give a warning and ask the user to correct the bugs. */
664 return result;
665 }
666
667
668 static char *
xstrndup(const char * s,size_t n)669 xstrndup (const char *s, size_t n)
670 {
671 size_t len = n;
672 char *new = malloc (len + 1);
673
674 if (new == NULL)
675 return NULL;
676
677 new[len] = '\0';
678 return memcpy (new, s, len);
679 }
680
681
682 /* Like system but propagate interrupt and quit signals. */
683 int
xsystem(const char * cmd)684 xsystem (const char *cmd)
685 {
686 int status;
687
688 status = system (cmd);
689 if (status != -1)
690 {
691 if (WIFSIGNALED (status))
692 {
693 if (WTERMSIG (status) == SIGINT || WTERMSIG (status) == SIGQUIT)
694 raise (WTERMSIG (status));
695 }
696 else if (WIFEXITED (status))
697 {
698 if (WEXITSTATUS (status) == SIGINT + 128
699 || WEXITSTATUS (status) == SIGQUIT + 128)
700 raise (WEXITSTATUS (status) - 128);
701 }
702 }
703 return status;
704 }
705
706
707 static const char **
get_null_defines(void)708 get_null_defines (void)
709 {
710 char line[BUFSIZ], *command;
711 char **result = NULL;
712 size_t result_len = 0;
713 size_t result_max = 0;
714 FILE *input;
715 int first = 1;
716
717 int fd = mkstemp (macrofile);
718 if (fd == -1)
719 {
720 printf ("mkstemp failed: %m\n");
721 exit (1);
722 }
723 close (fd);
724
725 command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC)
726 + strlen (INC) + strlen (macrofile));
727
728 if (command == NULL)
729 {
730 puts ("No more memory.");
731 exit (1);
732 }
733
734 sprintf (command, fmt, "/dev/null", CC, INC, CC, macrofile);
735
736 if (xsystem (command))
737 {
738 puts ("system() returned nonzero");
739 return NULL;
740 }
741 free (command);
742 input = fopen (macrofile, "r");
743
744 if (input == NULL)
745 {
746 printf ("Could not read %s: ", macrofile);
747 perror (NULL);
748 return NULL;
749 }
750
751 while (fgets (line, sizeof line, input) != NULL)
752 {
753 char *start;
754 if (strlen (line) < 9 || line[7] != ' ')
755 { /* "#define A" */
756 printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
757 line);
758 continue;
759 }
760 if (line[8] == '_')
761 /* It's a safe identifier. */
762 continue;
763 if (result_len == result_max)
764 {
765 result_max += 10;
766 result = realloc (result, result_max * sizeof (char **));
767 if (result == NULL)
768 {
769 puts ("No more memory.");
770 exit (1);
771 }
772 }
773 start = &line[8];
774 result[result_len++] = xstrndup (start, strcspn (start, " ("));
775
776 if (first)
777 {
778 fputs ("The following identifiers will be ignored since the compiler defines them\nby default:\n", stdout);
779 first = 0;
780 }
781 puts (result[result_len - 1]);
782 }
783 if (result_len == result_max)
784 {
785 result_max += 1;
786 result = realloc (result, result_max * sizeof (char **));
787 if (result == NULL)
788 {
789 puts ("No more memory.");
790 exit (1);
791 }
792 }
793 result[result_len] = NULL;
794 fclose (input);
795
796 return (const char **) result;
797 }
798
799
800 static int
check_header(const struct header * header,const char ** except)801 check_header (const struct header *header, const char **except)
802 {
803 char line[BUFSIZ], command[sizeof fmt + strlen (header->name)
804 + 2 * strlen (CC)
805 + strlen (INC) + strlen (macrofile)];
806 FILE *input;
807 int result = 0;
808 int found[header->nsyms];
809 int i;
810
811 memset (found, '\0', header->nsyms * sizeof (int));
812
813 printf ("=== %s ===\n", header->name);
814 sprintf (command, fmt, header->name, CC, INC, CC, macrofile);
815
816 /* First see whether this subset is supported at all. */
817 if (header->subset != NULL)
818 {
819 sprintf (line, testfmt, header->subset, header->subset, CC, INC, CC,
820 macrofile);
821 if (xsystem (line))
822 {
823 printf ("!! not available\n");
824 return 0;
825 }
826 }
827
828 if (xsystem (command))
829 {
830 puts ("system() returned nonzero");
831 result = 1;
832 }
833 input = fopen (macrofile, "r");
834
835 if (input == NULL)
836 {
837 printf ("Could not read %s: ", macrofile);
838 perror (NULL);
839 return 1;
840 }
841
842 while (fgets (line, sizeof line, input) != NULL)
843 {
844 const char **ignore;
845 if (strlen (line) < 9 || line[7] != ' ')
846 { /* "#define A" */
847 printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
848 line);
849 result = 1;
850 continue;
851 }
852
853 /* Find next char after the macro identifier; this can be either
854 a space or an open parenthesis. */
855 line[8 + strcspn (&line[8], " (")] = '\0';
856
857 /* Now check whether it's one of the required macros. */
858 for (i = 0; i < header->nsyms; ++i)
859 if (!strcmp (&line[8], header->syms[i]))
860 break;
861 if (i < header->nsyms)
862 {
863 found[i] = 1;
864 continue;
865 }
866
867 /* Symbols starting with "_" are ok. */
868 if (line[8] == '_')
869 continue;
870
871 /* Maybe one of the symbols which are always defined. */
872 for (ignore = except; *ignore != NULL; ++ignore)
873 if (! strcmp (&line[8], *ignore))
874 break;
875 if (*ignore != NULL)
876 continue;
877
878 /* Otherwise the symbol better should match one of the following. */
879 for (i = 0; i < header->nmaybe; ++i)
880 if (fnmatch (header->maybe[i], &line[8], 0) == 0)
881 break;
882 if (i < header->nmaybe)
883 continue;
884
885 printf ("* invalid macro `%s'\n", &line[8]);
886 result |= 1;
887 }
888 fclose (input);
889
890 for (i = 0; i < header->nsyms; ++i)
891 if (found[i] == 0)
892 printf ("** macro `%s' not defined\n", header->syms[i]);
893
894 return result;
895 }
896