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 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 |
558 | { |
559 | const char *; |
560 | const char *const *; |
561 | size_t ; |
562 | const char *const *; |
563 | size_t ; |
564 | const char *; |
565 | } [] = |
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 (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 |
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 (s: "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 * |
669 | xstrndup (const char *s, size_t n) |
670 | { |
671 | size_t len = n; |
672 | char *new = malloc (size: 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 |
684 | xsystem (const char *cmd) |
685 | { |
686 | int status; |
687 | |
688 | status = system (command: 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 ** |
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 (template: macrofile); |
718 | if (fd == -1) |
719 | { |
720 | printf (format: "mkstemp failed: %m\n" ); |
721 | exit (1); |
722 | } |
723 | close (fd: fd); |
724 | |
725 | command = malloc (size: sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC) |
726 | + strlen (INC) + strlen (macrofile)); |
727 | |
728 | if (command == NULL) |
729 | { |
730 | puts (s: "No more memory." ); |
731 | exit (1); |
732 | } |
733 | |
734 | sprintf (command, fmt, "/dev/null" , CC, INC, CC, macrofile); |
735 | |
736 | if (xsystem (cmd: command)) |
737 | { |
738 | puts (s: "system() returned nonzero" ); |
739 | return NULL; |
740 | } |
741 | free (ptr: command); |
742 | input = fopen (macrofile, "r" ); |
743 | |
744 | if (input == NULL) |
745 | { |
746 | printf (format: "Could not read %s: " , macrofile); |
747 | perror (NULL); |
748 | return NULL; |
749 | } |
750 | |
751 | while (fgets (s: line, n: sizeof line, stream: input) != NULL) |
752 | { |
753 | char *start; |
754 | if (strlen (line) < 9 || line[7] != ' ') |
755 | { /* "#define A" */ |
756 | printf (format: "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 (ptr: result, size: result_max * sizeof (char **)); |
767 | if (result == NULL) |
768 | { |
769 | puts (s: "No more memory." ); |
770 | exit (1); |
771 | } |
772 | } |
773 | start = &line[8]; |
774 | result[result_len++] = xstrndup (s: start, n: 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 (s: result[result_len - 1]); |
782 | } |
783 | if (result_len == result_max) |
784 | { |
785 | result_max += 1; |
786 | result = realloc (ptr: result, size: result_max * sizeof (char **)); |
787 | if (result == NULL) |
788 | { |
789 | puts (s: "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 |
801 | (const struct 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 (format: "=== %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 (cmd: line)) |
822 | { |
823 | printf (format: "!! not available\n" ); |
824 | return 0; |
825 | } |
826 | } |
827 | |
828 | if (xsystem (cmd: command)) |
829 | { |
830 | puts (s: "system() returned nonzero" ); |
831 | result = 1; |
832 | } |
833 | input = fopen (macrofile, "r" ); |
834 | |
835 | if (input == NULL) |
836 | { |
837 | printf (format: "Could not read %s: " , macrofile); |
838 | perror (NULL); |
839 | return 1; |
840 | } |
841 | |
842 | while (fgets (s: line, n: sizeof line, stream: input) != NULL) |
843 | { |
844 | const char **ignore; |
845 | if (strlen (line) < 9 || line[7] != ' ') |
846 | { /* "#define A" */ |
847 | printf (format: "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 (format: "* 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 (format: "** macro `%s' not defined\n" , header->syms[i]); |
893 | |
894 | return result; |
895 | } |
896 | |