]>
Commit | Line | Data |
---|---|---|
688903eb | 1 | /* Copyright (C) 1998-2018 Free Software Foundation, Inc. |
4959e310 UD |
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 | |
41bdb6e2 AJ |
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. | |
4959e310 UD |
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 | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
4959e310 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
4959e310 UD |
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> | |
999b2f6b UD |
24 | #include <signal.h> |
25 | #include <sys/wait.h> | |
4959e310 | 26 | |
4959e310 UD |
27 | #define HEADER_MAX 256 |
28 | ||
5c112f1b | 29 | static char macrofile[] = "/tmp/annexc.XXXXXX"; |
c891b2df | 30 | |
4959e310 UD |
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 | { | |
bb967344 | 98 | "E2BIG", "EACCES", "EAGAIN", "EBADF", "EBADMSG", "EBUSY", "ECANCELED", |
4959e310 UD |
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", | |
3f62b69a UD |
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" | |
4959e310 UD |
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", | |
bb967344 | 323 | "SIGCONT", "SIGEV_NONE", "SIGEV_SIGNAL", "SIGEV_THREAD", |
4959e310 UD |
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 | { | |
3f62b69a | 340 | "va_arg", "va_end", "va_start" |
4959e310 UD |
341 | }; |
342 | static const char *const stdarg_maybe[] = | |
343 | { | |
3f62b69a | 344 | "va_list" |
4959e310 UD |
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 | { | |
3f62b69a UD |
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" | |
4959e310 UD |
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", | |
bb967344 UD |
405 | "MCL_FUTURE", "MS_ASYNC", "MS_INVALIDATE", "MS_SYNC", "PROT_EXEC", |
406 | "PROT_NONE", "PROT_READ", "PROT_WRITE" | |
4959e310 UD |
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>\" |\ | |
d7e82198 | 617 | %s -E -dM -D_POSIX_SOURCE %s \ |
4959e310 UD |
618 | -isystem `%s --print-prog-name=include` - > %s"; |
619 | ||
620 | static const char testfmt[] = "\ | |
b4f48b41 | 621 | echo \"#include <unistd.h>\n#if !defined %s || %s == -1\n#error not defined\n#endif\n\" |\ |
d7e82198 | 622 | %s -E -dM -D_POSIX_SOURCE %s \ |
4959e310 UD |
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 **); | |
999b2f6b | 634 | static int xsystem (const char *); |
4959e310 UD |
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 | ||
5c112f1b JM |
660 | remove (macrofile); |
661 | ||
4959e310 UD |
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 * | |
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 | ||
999b2f6b UD |
682 | /* Like system but propagate interrupt and quit signals. */ |
683 | int | |
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 | ||
4959e310 UD |
707 | static const char ** |
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 | ||
5c112f1b JM |
717 | int fd = mkstemp (macrofile); |
718 | if (fd == -1) | |
719 | { | |
720 | printf ("mkstemp failed: %m\n"); | |
721 | exit (1); | |
722 | } | |
723 | close (fd); | |
c891b2df | 724 | |
4959e310 | 725 | command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC) |
c891b2df | 726 | + strlen (INC) + strlen (macrofile)); |
4959e310 UD |
727 | |
728 | if (command == NULL) | |
729 | { | |
730 | puts ("No more memory."); | |
731 | exit (1); | |
732 | } | |
733 | ||
c891b2df | 734 | sprintf (command, fmt, "/dev/null", CC, INC, CC, macrofile); |
4959e310 | 735 | |
999b2f6b | 736 | if (xsystem (command)) |
4959e310 UD |
737 | { |
738 | puts ("system() returned nonzero"); | |
739 | return NULL; | |
740 | } | |
741 | free (command); | |
c891b2df | 742 | input = fopen (macrofile, "r"); |
4959e310 UD |
743 | |
744 | if (input == NULL) | |
745 | { | |
c891b2df | 746 | printf ("Could not read %s: ", macrofile); |
4959e310 UD |
747 | perror (NULL); |
748 | return NULL; | |
749 | } | |
750 | ||
751 | while (fgets (line, sizeof line, input) != NULL) | |
752 | { | |
8eaaffde | 753 | char *start; |
4959e310 UD |
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]; | |
8eaaffde | 774 | result[result_len++] = xstrndup (start, strcspn (start, " (")); |
4959e310 UD |
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); | |
4959e310 UD |
795 | |
796 | return (const char **) result; | |
797 | } | |
798 | ||
799 | ||
800 | static int | |
801 | check_header (const struct header *header, const char **except) | |
802 | { | |
db2f05ba RM |
803 | char line[BUFSIZ], command[sizeof fmt + strlen (header->name) |
804 | + 2 * strlen (CC) | |
805 | + strlen (INC) + strlen (macrofile)]; | |
4959e310 UD |
806 | FILE *input; |
807 | int result = 0; | |
808 | int found[header->nsyms]; | |
809 | int i; | |
810 | ||
811 | memset (found, '\0', header->nsyms * sizeof (int)); | |
4959e310 UD |
812 | |
813 | printf ("=== %s ===\n", header->name); | |
c891b2df | 814 | sprintf (command, fmt, header->name, CC, INC, CC, macrofile); |
4959e310 UD |
815 | |
816 | /* First see whether this subset is supported at all. */ | |
817 | if (header->subset != NULL) | |
818 | { | |
b4f48b41 | 819 | sprintf (line, testfmt, header->subset, header->subset, CC, INC, CC, |
c891b2df | 820 | macrofile); |
999b2f6b | 821 | if (xsystem (line)) |
4959e310 UD |
822 | { |
823 | printf ("!! not available\n"); | |
824 | return 0; | |
825 | } | |
826 | } | |
827 | ||
999b2f6b | 828 | if (xsystem (command)) |
4959e310 UD |
829 | { |
830 | puts ("system() returned nonzero"); | |
831 | result = 1; | |
832 | } | |
c891b2df | 833 | input = fopen (macrofile, "r"); |
4959e310 UD |
834 | |
835 | if (input == NULL) | |
836 | { | |
c891b2df | 837 | printf ("Could not read %s: ", macrofile); |
4959e310 UD |
838 | perror (NULL); |
839 | return 1; | |
840 | } | |
841 | ||
842 | while (fgets (line, sizeof line, input) != NULL) | |
843 | { | |
4959e310 UD |
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 | ||
8eaaffde UD |
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 | ||
4959e310 UD |
857 | /* Now check whether it's one of the required macros. */ |
858 | for (i = 0; i < header->nsyms; ++i) | |
8eaaffde | 859 | if (!strcmp (&line[8], header->syms[i])) |
4959e310 UD |
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 | ||
4959e310 UD |
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); | |
4959e310 UD |
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 | } |