]>
Commit | Line | Data |
---|---|---|
48d0341c | 1 | #!/usr/bin/perl |
da1067a9 | 2 | |
24f4f825 | 3 | use GlibcConform; |
ad4f2ebf | 4 | use Getopt::Long; |
f095bb72 | 5 | use POSIX; |
ad4f2ebf | 6 | |
8149f976 | 7 | $standard = "XOPEN2K8"; |
da1067a9 | 8 | $CC = "gcc"; |
8149f976 | 9 | $tmpdir = "/tmp"; |
31341567 | 10 | GetOptions ('headers=s' => \@headers, 'standard=s' => \$standard, |
8149f976 | 11 | 'flags=s' => \$flags, 'cc=s' => \$CC, 'tmpdir=s' => \$tmpdir); |
ad4f2ebf | 12 | @headers = split(/,/,join(',',@headers)); |
da1067a9 UD |
13 | |
14 | # List of the headers we are testing. | |
ad4f2ebf UD |
15 | if (@headers == ()) { |
16 | @headers = ("wordexp.h", "wctype.h", "wchar.h", "varargs.h", "utmpx.h", | |
31341567 UD |
17 | "utime.h", "unistd.h", "ulimit.h", "ucontext.h", "uchar.h", |
18 | "time.h", "tgmath.h", "termios.h", "tar.h", "sys/wait.h", | |
19 | "sys/utsname.h", "sys/un.h", "sys/uio.h", "sys/types.h", | |
20 | "sys/times.h", "sys/timeb.h", "sys/time.h", "sys/statvfs.h", | |
21 | "sys/stat.h", "sys/socket.h", "sys/shm.h", "sys/sem.h", | |
22 | "sys/select.h", "sys/resource.h", "sys/msg.h", "sys/mman.h", | |
23 | "sys/ipc.h", "syslog.h", "stropts.h", "strings.h", "string.h", | |
05bcf62a JM |
24 | "stdnoreturn.h", "stdlib.h", "stdio.h", "stdint.h", "stddef.h", |
25 | "stdbool.h", "stdarg.h", "stdalign.h", "spawn.h", "signal.h", | |
26 | "setjmp.h", "semaphore.h", "search.h", "sched.h", "regex.h", | |
27 | "pwd.h", "pthread.h", "poll.h", "nl_types.h", "netinet/tcp.h", | |
28 | "netinet/in.h", "net/if.h", "netdb.h", "ndbm.h", "mqueue.h", | |
29 | "monetary.h", "math.h", "locale.h", "libgen.h", "limits.h", | |
30 | "langinfo.h", "iso646.h", "inttypes.h", "iconv.h", "grp.h", | |
31 | "glob.h", "ftw.h", "fnmatch.h", "fmtmsg.h", "float.h", "fenv.h", | |
32 | "fcntl.h", "errno.h", "dlfcn.h", "dirent.h", "ctype.h", "cpio.h", | |
33 | "complex.h", "assert.h", "arpa/inet.h", "aio.h"); | |
ad4f2ebf UD |
34 | } |
35 | ||
c9140a62 JM |
36 | $CFLAGS_namespace = "$flags -fno-builtin $CFLAGS{$standard} -D_ISOMAC"; |
37 | $CFLAGS = "$CFLAGS_namespace '-D__attribute__(x)='"; | |
31341567 | 38 | |
4efeffc1 UD |
39 | # Check standard name for validity. |
40 | die "unknown standard \"$standard\"" if ($CFLAGS{$standard} eq ""); | |
41 | ||
42 | # if ($standard ne "XOPEN2K8" && $standard ne "POSIX2008") { | |
43 | # # Some headers need a bit more attention. At least with XPG7 | |
44 | # # all headers should be self-contained. | |
45 | # $mustprepend{'inttypes.h'} = "#include <stddef.h>\n"; | |
46 | # $mustprepend{'glob.h'} = "#include <sys/types.h>\n"; | |
47 | # $mustprepend{'grp.h'} = "#include <sys/types.h>\n"; | |
48 | # $mustprepend{'regex.h'} = "#include <sys/types.h>\n"; | |
49 | # $mustprepend{'pwd.h'} = "#include <sys/types.h>\n"; | |
50 | # $mustprepend{'sched.h'} = "#include <sys/types.h>\n"; | |
51 | # $mustprepend{'signal.h'} = "#include <pthread.h>\n#include <sys/types.h>\n"; | |
52 | # $mustprepend{'stdio.h'} = "#include <sys/types.h>\n"; | |
53 | # $mustprepend{'sys/stat.h'} = "#include <sys/types.h>\n"; | |
54 | # $mustprepend{'wchar.h'} = "#include <stdarg.h>\n"; | |
55 | # $mustprepend{'wordexp.h'} = "#include <stddef.h>\n"; | |
56 | # } | |
57 | ||
9af0bf29 | 58 | # These are the ISO C90 keywords. |
4efeffc1 UD |
59 | @keywords = ('auto', 'break', 'case', 'char', 'const', 'continue', 'default', |
60 | 'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', | |
9af0bf29 | 61 | 'if', 'int', 'long', 'register', 'return', |
4efeffc1 UD |
62 | 'short', 'signed', 'sizeof', 'static', 'struct', 'switch', |
63 | 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'); | |
9af0bf29 JM |
64 | if ($CFLAGS{$standard} =~ /-std=(c99|c1x)/) { |
65 | push (@keywords, 'inline', 'restrict'); | |
66 | } | |
77faa354 | 67 | |
7287c36d UD |
68 | # Make a hash table from this information. |
69 | while ($#keywords >= 0) { | |
da1067a9 UD |
70 | $iskeyword{pop (@keywords)} = 1; |
71 | } | |
72 | ||
da1067a9 UD |
73 | $verbose = 1; |
74 | ||
75 | $total = 0; | |
76 | $skipped = 0; | |
77 | $errors = 0; | |
5675961d JM |
78 | $xerrors = 0; |
79 | ||
80 | sub note_error { | |
81 | my($xfail) = @_; | |
82 | if ($xfail) { | |
83 | $xerrors++; | |
84 | printf ("Ignoring this failure.\n"); | |
85 | } else { | |
86 | $errors++; | |
87 | } | |
88 | } | |
da1067a9 | 89 | |
da1067a9 UD |
90 | |
91 | sub poorfnmatch { | |
92 | my($pattern, $string) = @_; | |
93 | my($strlen) = length ($string); | |
94 | my($res); | |
95 | ||
96 | if (substr ($pattern, 0, 1) eq '*') { | |
97 | my($patlen) = length ($pattern) - 1; | |
98 | $res = ($strlen >= $patlen | |
99 | && substr ($pattern, -$patlen, $patlen) eq substr ($string, -$patlen, $patlen)); | |
100 | } elsif (substr ($pattern, -1, 1) eq '*') { | |
31341567 UD |
101 | if (substr ($pattern, -2, 1) eq ']') { |
102 | my($patlen) = index ($pattern, '['); | |
103 | my($range) = substr ($pattern, $patlen + 1, -2); | |
104 | $res = ($strlen > $patlen | |
105 | && substr ($pattern, 0, $patlen) eq substr ($string, 0, $patlen) | |
106 | && index ($range, substr ($string, $patlen, 1)) != -1); | |
107 | } else { | |
108 | my($patlen) = length ($pattern) - 1; | |
109 | $res = ($strlen >= $patlen | |
110 | && substr ($pattern, 0, $patlen) eq substr ($string, 0, $patlen)); | |
111 | } | |
da1067a9 UD |
112 | } else { |
113 | $res = $pattern eq $string; | |
114 | } | |
115 | return $res; | |
116 | } | |
117 | ||
118 | ||
119 | sub compiletest | |
120 | { | |
5675961d | 121 | my($fnamebase, $msg, $errmsg, $skip, $optional, $xfail) = @_; |
da1067a9 UD |
122 | my($result) = $skip; |
123 | my($printlog) = 0; | |
124 | ||
125 | ++$total; | |
126 | printf (" $msg..."); | |
127 | ||
128 | if ($skip != 0) { | |
129 | ++$skipped; | |
130 | printf (" SKIP\n"); | |
131 | } else { | |
31341567 | 132 | $ret = system "$CC $CFLAGS -c $fnamebase.c -o $fnamebase.o > $fnamebase.out 2>&1"; |
da1067a9 | 133 | if ($ret != 0) { |
2eba94b2 UD |
134 | if ($optional != 0) { |
135 | printf (" $errmsg\n"); | |
136 | $result = 1; | |
137 | } else { | |
138 | printf (" FAIL\n"); | |
139 | if ($verbose != 0) { | |
140 | printf (" $errmsg Compiler message:\n"); | |
141 | $printlog = 1; | |
142 | } | |
5675961d | 143 | note_error($xfail); |
2eba94b2 | 144 | $result = 1; |
da1067a9 | 145 | } |
da1067a9 UD |
146 | } else { |
147 | printf (" OK\n"); | |
148 | if ($verbose > 1 && -s "$fnamebase.out") { | |
149 | # We print all warnings issued. | |
150 | $printlog = 1; | |
151 | } | |
152 | } | |
153 | if ($printlog != 0) { | |
154 | printf (" " . "-" x 71 . "\n"); | |
155 | open (MESSAGE, "< $fnamebase.out"); | |
156 | while (<MESSAGE>) { | |
157 | printf (" %s", $_); | |
158 | } | |
159 | close (MESSAGE); | |
160 | printf (" " . "-" x 71 . "\n"); | |
161 | } | |
162 | } | |
163 | unlink "$fnamebase.c"; | |
164 | unlink "$fnamebase.o"; | |
165 | unlink "$fnamebase.out"; | |
166 | ||
167 | $result; | |
168 | } | |
169 | ||
170 | ||
171 | sub runtest | |
172 | { | |
5675961d | 173 | my($fnamebase, $msg, $errmsg, $skip, $xfail) = @_; |
da1067a9 UD |
174 | my($result) = $skip; |
175 | my($printlog) = 0; | |
176 | ||
177 | ++$total; | |
178 | printf (" $msg..."); | |
179 | ||
180 | if ($skip != 0) { | |
181 | ++$skipped; | |
182 | printf (" SKIP\n"); | |
183 | } else { | |
31341567 | 184 | $ret = system "$CC $CFLAGS -o $fnamebase $fnamebase.c > $fnamebase.out 2>&1"; |
da1067a9 UD |
185 | if ($ret != 0) { |
186 | printf (" FAIL\n"); | |
187 | if ($verbose != 0) { | |
188 | printf (" $errmsg Compiler message:\n"); | |
189 | $printlog = 1; | |
190 | } | |
5675961d | 191 | note_error($xfail); |
da1067a9 UD |
192 | $result = 1; |
193 | } else { | |
194 | # Now run the program. If the exit code is not zero something is wrong. | |
195 | $result = system "$fnamebase > $fnamebase.out2 2>&1"; | |
196 | if ($result == 0) { | |
197 | printf (" OK\n"); | |
198 | if ($verbose > 1 && -s "$fnamebase.out") { | |
199 | # We print all warnings issued. | |
200 | $printlog = 1; | |
201 | system "cat $fnamebase.out2 >> $fnamebase.out"; | |
202 | } | |
203 | } else { | |
204 | printf (" FAIL\n"); | |
5675961d | 205 | note_error($xfail); |
da1067a9 UD |
206 | $printlog = 1; |
207 | unlink "$fnamebase.out"; | |
208 | rename "$fnamebase.out2", "$fnamebase.out"; | |
209 | } | |
210 | } | |
211 | if ($printlog != 0) { | |
212 | printf (" " . "-" x 71 . "\n"); | |
213 | open (MESSAGE, "< $fnamebase.out"); | |
214 | while (<MESSAGE>) { | |
215 | printf (" %s", $_); | |
216 | } | |
217 | close (MESSAGE); | |
218 | printf (" " . "-" x 71 . "\n"); | |
219 | } | |
220 | } | |
221 | unlink "$fnamebase"; | |
222 | unlink "$fnamebase.c"; | |
223 | unlink "$fnamebase.o"; | |
224 | unlink "$fnamebase.out"; | |
225 | unlink "$fnamebase.out2"; | |
226 | ||
227 | $result; | |
228 | } | |
229 | ||
230 | ||
231 | sub newtoken { | |
7287c36d | 232 | my($token, @allow) = @_; |
da1067a9 UD |
233 | my($idx); |
234 | ||
7287c36d | 235 | return if ($token =~ /^[0-9_]/ || $iskeyword{$token}); |
8ce9ea0c | 236 | |
da1067a9 | 237 | for ($idx = 0; $idx <= $#allow; ++$idx) { |
7287c36d | 238 | return if (poorfnmatch ($allow[$idx], $token)); |
da1067a9 | 239 | } |
b92a20b5 JM |
240 | |
241 | $errors{$token} = 1; | |
9c777dfe UD |
242 | } |
243 | ||
244 | ||
245 | sub removetoken { | |
246 | my($token) = @_; | |
247 | my($idx); | |
248 | ||
249 | return if ($token =~ /^[0-9_]/ || $iskeyword{$token}); | |
250 | ||
251 | if (exists $errors{$token}) { | |
252 | undef $errors{$token}; | |
da1067a9 | 253 | } |
da1067a9 UD |
254 | } |
255 | ||
256 | ||
257 | sub checknamespace { | |
258 | my($h, $fnamebase, @allow) = @_; | |
da1067a9 UD |
259 | |
260 | ++$total; | |
261 | ||
262 | # Generate a program to get the contents of this header. | |
263 | open (TESTFILE, ">$fnamebase.c"); | |
264 | print TESTFILE "#include <$h>\n"; | |
265 | close (TESTFILE); | |
266 | ||
9c777dfe | 267 | undef %errors; |
c9140a62 | 268 | open (CONTENT, "$CC $CFLAGS_namespace -E $fnamebase.c -P -Wp,-dN | sed -e '/^# [1-9]/d' -e '/^[[:space:]]*\$/d' |"); |
19533127 | 269 | loop: while (<CONTENT>) { |
da1067a9 UD |
270 | chop; |
271 | if (/^#define (.*)/) { | |
7287c36d | 272 | newtoken ($1, @allow); |
9c777dfe UD |
273 | } elsif (/^#undef (.*)/) { |
274 | removetoken ($1); | |
da1067a9 UD |
275 | } else { |
276 | # We have to tokenize the line. | |
277 | my($str) = $_; | |
da1067a9 | 278 | |
fddb8742 | 279 | $str =~ s/"[^"]*"//g; |
da1067a9 UD |
280 | foreach $token (split(/[^a-zA-Z0-9_]/, $str)) { |
281 | if ($token ne "") { | |
7287c36d | 282 | newtoken ($token, @allow); |
da1067a9 UD |
283 | } |
284 | } | |
285 | } | |
286 | } | |
287 | close (CONTENT); | |
288 | unlink "$fnamebase.c"; | |
9c777dfe UD |
289 | $realerror = 0; |
290 | if ($#errors != 0) { | |
d9022567 RM |
291 | # Sort the output list so it's easier to compare results with diff. |
292 | foreach $f (sort keys(%errors)) { | |
9c777dfe UD |
293 | if ($errors{$f} == 1) { |
294 | if ($realerror == 0) { | |
295 | printf ("FAIL\n " . "-" x 72 . "\n"); | |
296 | $realerror = 1; | |
297 | ++$errors; | |
298 | } | |
299 | printf (" Namespace violation: \"%s\"\n", $f); | |
300 | } | |
301 | } | |
302 | printf (" " . "-" x 72 . "\n") if ($realerror != 0); | |
303 | } | |
304 | ||
305 | if ($realerror == 0) { | |
31341567 | 306 | printf ("OK\n"); |
da1067a9 UD |
307 | } |
308 | } | |
309 | ||
310 | ||
311 | while ($#headers >= 0) { | |
312 | my($h) = pop (@headers); | |
bba09d23 UD |
313 | my($hf) = $h; |
314 | $hf =~ s|/|-|; | |
315 | my($fnamebase) = "$tmpdir/$hf-test"; | |
31341567 | 316 | my($missing) = 1; |
da1067a9 | 317 | my(@allow) = (); |
0ed99ce4 | 318 | my(@allowheader) = (); |
9d48fef0 | 319 | my(%seenheader) = (); |
77faa354 | 320 | my($prepend) = $mustprepend{$h}; |
31341567 | 321 | my($test_exist) = 1; |
da1067a9 UD |
322 | |
323 | printf ("Testing <$h>\n"); | |
324 | printf ("----------" . "-" x length ($h) . "\n"); | |
325 | ||
aebe1003 | 326 | open (CONTROL, "$CC -E -D$standard -std=c99 -x c data/$h-data |"); |
da1067a9 UD |
327 | control: while (<CONTROL>) { |
328 | chop; | |
329 | next control if (/^#/); | |
20d49639 | 330 | next control if (/^[ ]*$/); |
da1067a9 | 331 | |
31341567 UD |
332 | if ($test_exist) { |
333 | $test_exist = 0; | |
334 | # Generate a program to test for the availability of this header. | |
335 | open (TESTFILE, ">$fnamebase.c"); | |
336 | print TESTFILE "$prepend"; | |
337 | print TESTFILE "#include <$h>\n"; | |
338 | close (TESTFILE); | |
339 | ||
340 | $missing = compiletest ($fnamebase, "Checking whether <$h> is available", | |
5675961d | 341 | "Header <$h> not available", 0, 0, 0); |
31341567 UD |
342 | printf ("\n"); |
343 | last control if ($missing); | |
344 | } | |
345 | ||
5675961d JM |
346 | my($xfail) = 0; |
347 | if (/^xfail-/) { | |
348 | s/^xfail-//; | |
349 | $xfail = 1; | |
350 | } | |
d22956c9 JM |
351 | my($optional) = 0; |
352 | if (/^optional-/) { | |
353 | s/^optional-//; | |
354 | $optional = 1; | |
355 | } | |
7287c36d | 356 | if (/^element *({([^}]*)}|([^{ ]*)) *({([^}]*)}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/) { |
da1067a9 UD |
357 | my($struct) = "$2$3"; |
358 | my($type) = "$5$6"; | |
359 | my($member) = "$7"; | |
360 | my($rest) = "$8"; | |
361 | my($res) = $missing; | |
362 | ||
363 | # Remember that this name is allowed. | |
364 | push @allow, $member; | |
365 | ||
366 | # Generate a program to test for the availability of this member. | |
367 | open (TESTFILE, ">$fnamebase.c"); | |
77faa354 | 368 | print TESTFILE "$prepend"; |
da1067a9 UD |
369 | print TESTFILE "#include <$h>\n"; |
370 | print TESTFILE "$struct a;\n"; | |
371 | print TESTFILE "$struct b;\n"; | |
372 | print TESTFILE "extern void xyzzy (__typeof__ (&b.$member), __typeof__ (&a.$member), unsigned);\n"; | |
373 | print TESTFILE "void foobarbaz (void) {\n"; | |
374 | print TESTFILE " xyzzy (&a.$member, &b.$member, sizeof (a.$member));\n"; | |
375 | print TESTFILE "}\n"; | |
376 | close (TESTFILE); | |
377 | ||
378 | $res = compiletest ($fnamebase, "Testing for member $member", | |
d22956c9 JM |
379 | ($optional |
380 | ? "NOT AVAILABLE." | |
381 | : "Member \"$member\" not available."), $res, | |
5675961d | 382 | $optional, $xfail); |
da238298 | 383 | |
d22956c9 | 384 | if ($res == 0 || $missing != 0 || !$optional) { |
da238298 UD |
385 | # Test the types of the members. |
386 | open (TESTFILE, ">$fnamebase.c"); | |
387 | print TESTFILE "$prepend"; | |
388 | print TESTFILE "#include <$h>\n"; | |
389 | print TESTFILE "$struct a;\n"; | |
390 | print TESTFILE "extern $type b$rest;\n"; | |
391 | print TESTFILE "extern __typeof__ (a.$member) b;\n"; | |
392 | close (TESTFILE); | |
393 | ||
394 | compiletest ($fnamebase, "Testing for type of member $member", | |
395 | "Member \"$member\" does not have the correct type.", | |
5675961d | 396 | $res, 0, $xfail); |
da238298 | 397 | } |
a00f522a | 398 | } elsif (/^(macro|constant|macro-constant|macro-int-constant) +([a-zA-Z0-9_]*) *(?:{([^}]*)} *)?(?:([>=<!]+) ([A-Za-z0-9_\\'-]*))?/) { |
aafc49b3 JM |
399 | my($symbol_type) = $1; |
400 | my($symbol) = $2; | |
401 | my($type) = $3; | |
402 | my($op) = $4; | |
403 | my($value) = $5; | |
20d49639 | 404 | my($res) = $missing; |
aafc49b3 JM |
405 | my($mres) = $missing; |
406 | my($cres) = $missing; | |
20d49639 AJ |
407 | |
408 | # Remember that this name is allowed. | |
aafc49b3 | 409 | push @allow, $symbol; |
20d49639 | 410 | |
aafc49b3 JM |
411 | if ($symbol_type =~ /macro/) { |
412 | # Generate a program to test for availability of this macro. | |
413 | open (TESTFILE, ">$fnamebase.c"); | |
414 | print TESTFILE "$prepend"; | |
415 | print TESTFILE "#include <$h>\n"; | |
416 | print TESTFILE "#ifndef $symbol\n"; | |
417 | print TESTFILE "# error \"Macro $symbol not defined\"\n"; | |
418 | print TESTFILE "#endif\n"; | |
419 | close (TESTFILE); | |
20d49639 | 420 | |
aafc49b3 JM |
421 | $mres = compiletest ($fnamebase, "Test availability of macro $symbol", |
422 | ($optional | |
423 | ? "NOT PRESENT" | |
424 | : "Macro \"$symbol\" is not available."), $res, | |
5675961d | 425 | $optional, $xfail); |
aafc49b3 JM |
426 | } |
427 | ||
428 | if ($symbol_type =~ /constant/) { | |
429 | # Generate a program to test for the availability of this constant. | |
430 | open (TESTFILE, ">$fnamebase.c"); | |
431 | print TESTFILE "$prepend"; | |
432 | print TESTFILE "#include <$h>\n"; | |
433 | print TESTFILE "__typeof__ ($symbol) a = $symbol;\n"; | |
434 | close (TESTFILE); | |
435 | ||
436 | $cres = compiletest ($fnamebase, "Testing for constant $symbol", | |
437 | ($optional | |
438 | ? "NOT PRESENT" | |
439 | : "Constant \"$symbol\" not available."), $res, | |
5675961d | 440 | $optional, $xfail); |
aafc49b3 JM |
441 | } |
442 | ||
443 | $res = $res || $mres || $cres; | |
20d49639 | 444 | |
661f8cf0 JM |
445 | if ($symbol_type eq "macro-int-constant" && ($res == 0 || !$optional)) { |
446 | # Test that the symbol is usable in #if. | |
447 | open (TESTFILE, ">$fnamebase.c"); | |
448 | print TESTFILE "$prepend"; | |
449 | print TESTFILE "#include <$h>\n"; | |
450 | print TESTFILE "#if $symbol < 0\n"; | |
451 | print TESTFILE "# define conformtest_negative 1\n"; | |
452 | my($s) = "0"; | |
453 | for (my $i = 0; $i < 63; $i++) { | |
454 | print TESTFILE "# if $symbol & (1LL << $i)\n"; | |
455 | print TESTFILE "# define conformtest_bit_$i 0LL\n"; | |
456 | print TESTFILE "# else\n"; | |
457 | print TESTFILE "# define conformtest_bit_$i (1LL << $i)\n"; | |
458 | print TESTFILE "# endif\n"; | |
459 | $s .= "|conformtest_bit_$i"; | |
460 | } | |
461 | print TESTFILE "# define conformtest_value ~($s)\n"; | |
462 | print TESTFILE "#else\n"; | |
463 | print TESTFILE "# define conformtest_negative 0\n"; | |
464 | $s = "0"; | |
465 | for (my $i = 0; $i < 64; $i++) { | |
466 | print TESTFILE "# if $symbol & (1ULL << $i)\n"; | |
467 | print TESTFILE "# define conformtest_bit_$i (1ULL << $i)\n"; | |
468 | print TESTFILE "# else\n"; | |
469 | print TESTFILE "# define conformtest_bit_$i 0ULL\n"; | |
470 | print TESTFILE "# endif\n"; | |
471 | $s .= "|conformtest_bit_$i"; | |
472 | } | |
473 | print TESTFILE "# define conformtest_value ($s)\n"; | |
474 | print TESTFILE "#endif\n"; | |
475 | print TESTFILE "int main (void) { return !((($symbol < 0) == conformtest_negative) && ($symbol == conformtest_value)); }\n"; | |
476 | close (TESTFILE); | |
477 | ||
478 | runtest ($fnamebase, "Testing for #if usability of symbol $symbol", | |
5675961d | 479 | "Symbol \"$symbol\" not usable in #if.", $res, $xfail); |
661f8cf0 JM |
480 | } |
481 | ||
f2d922fe | 482 | if (defined ($type) && ($res == 0 || !$optional)) { |
aafc49b3 | 483 | # Test the type of the symbol. |
20d49639 AJ |
484 | open (TESTFILE, ">$fnamebase.c"); |
485 | print TESTFILE "$prepend"; | |
486 | print TESTFILE "#include <$h>\n"; | |
ee74b9cb JM |
487 | if ($type =~ /^promoted:/) { |
488 | $type =~ s/^promoted://; | |
489 | print TESTFILE "__typeof__ (($type) 0 + ($type) 0) a;\n"; | |
490 | } else { | |
491 | print TESTFILE "__typeof__ (($type) 0) a;\n"; | |
492 | } | |
aafc49b3 | 493 | print TESTFILE "extern __typeof__ ($symbol) a;\n"; |
20d49639 AJ |
494 | close (TESTFILE); |
495 | ||
aafc49b3 JM |
496 | compiletest ($fnamebase, "Testing for type of symbol $symbol", |
497 | "Symbol \"$symbol\" does not have the correct type.", | |
5675961d | 498 | $res, 0, $xfail); |
20d49639 | 499 | } |
20d49639 | 500 | |
f2d922fe | 501 | if (defined ($op) && ($res == 0 || !$optional)) { |
aafc49b3 | 502 | # Generate a program to test for the value of this symbol. |
8ce9ea0c UD |
503 | open (TESTFILE, ">$fnamebase.c"); |
504 | print TESTFILE "$prepend"; | |
505 | print TESTFILE "#include <$h>\n"; | |
f2d922fe | 506 | # Negate the value since 0 means ok |
aafc49b3 | 507 | print TESTFILE "int main (void) { return !($symbol $op $value); }\n"; |
8ce9ea0c UD |
508 | close (TESTFILE); |
509 | ||
aafc49b3 | 510 | $res = runtest ($fnamebase, "Testing for value of symbol $symbol", |
5675961d JM |
511 | "Symbol \"$symbol\" has not the right value.", $res, |
512 | $xfail); | |
8ce9ea0c | 513 | } |
31341567 | 514 | } elsif (/^symbol *([a-zA-Z0-9_]*) *([A-Za-z0-9_-]*)?/) { |
257abbe2 UD |
515 | my($symbol) = $1; |
516 | my($value) = $2; | |
517 | my($res) = $missing; | |
518 | ||
519 | # Remember that this name is allowed. | |
520 | push @allow, $symbol; | |
521 | ||
522 | # Generate a program to test for the availability of this constant. | |
523 | open (TESTFILE, ">$fnamebase.c"); | |
524 | print TESTFILE "$prepend"; | |
525 | print TESTFILE "#include <$h>\n"; | |
526 | print TESTFILE "void foobarbaz (void) {\n"; | |
527 | print TESTFILE "__typeof__ ($symbol) a = $symbol;\n"; | |
528 | print TESTFILE "}\n"; | |
529 | close (TESTFILE); | |
530 | ||
531 | $res = compiletest ($fnamebase, "Testing for symbol $symbol", | |
5675961d | 532 | "Symbol \"$symbol\" not available.", $res, 0, $xfail); |
257abbe2 UD |
533 | |
534 | if ($value ne "") { | |
535 | # Generate a program to test for the value of this constant. | |
536 | open (TESTFILE, ">$fnamebase.c"); | |
537 | print TESTFILE "$prepend"; | |
538 | print TESTFILE "#include <$h>\n"; | |
539 | print TESTFILE "int main (void) { return $symbol != $value; }\n"; | |
540 | close (TESTFILE); | |
541 | ||
542 | $res = runtest ($fnamebase, "Testing for value of symbol $symbol", | |
5675961d JM |
543 | "Symbol \"$symbol\" has not the right value.", $res, |
544 | $xfail); | |
257abbe2 | 545 | } |
da1067a9 UD |
546 | } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) { |
547 | my($type) = "$2$3"; | |
2ff458eb | 548 | my($maybe_opaque) = 0; |
da1067a9 UD |
549 | |
550 | # Remember that this name is allowed. | |
551 | if ($type =~ /^struct *(.*)/) { | |
552 | push @allow, $1; | |
553 | } elsif ($type =~ /^union *(.*)/) { | |
554 | push @allow, $1; | |
555 | } else { | |
556 | push @allow, $type; | |
2ff458eb | 557 | $maybe_opaque = 1; |
da1067a9 UD |
558 | } |
559 | ||
3bf3d361 | 560 | # Generate a program to test for the availability of this type. |
da1067a9 | 561 | open (TESTFILE, ">$fnamebase.c"); |
5d916713 | 562 | print TESTFILE "$prepend"; |
da1067a9 | 563 | print TESTFILE "#include <$h>\n"; |
2ff458eb UD |
564 | if ($maybe_opaque == 1) { |
565 | print TESTFILE "$type *a;\n"; | |
566 | } else { | |
567 | print TESTFILE "$type a;\n"; | |
568 | } | |
da1067a9 UD |
569 | close (TESTFILE); |
570 | ||
f095bb72 | 571 | compiletest ($fnamebase, "Testing for type $type", |
d22956c9 JM |
572 | ($optional |
573 | ? "NOT AVAILABLE" | |
5675961d JM |
574 | : "Type \"$type\" not available."), $missing, $optional, |
575 | $xfail); | |
f095bb72 UD |
576 | } elsif (/^tag *({([^}]*)|([a-zA-Z0-9_]*))/) { |
577 | my($type) = "$2$3"; | |
578 | ||
579 | # Remember that this name is allowed. | |
580 | if ($type =~ /^struct *(.*)/) { | |
581 | push @allow, $1; | |
582 | } elsif ($type =~ /^union *(.*)/) { | |
583 | push @allow, $1; | |
584 | } else { | |
585 | push @allow, $type; | |
586 | } | |
587 | ||
588 | # Generate a program to test for the availability of this type. | |
589 | open (TESTFILE, ">$fnamebase.c"); | |
590 | print TESTFILE "$prepend"; | |
591 | print TESTFILE "#include <$h>\n"; | |
592 | print TESTFILE "$type;\n"; | |
593 | close (TESTFILE); | |
594 | ||
da1067a9 | 595 | compiletest ($fnamebase, "Testing for type $type", |
5675961d | 596 | "Type \"$type\" not available.", $missing, 0, $xfail); |
d22956c9 | 597 | } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) { |
2ff458eb UD |
598 | my($rettype) = "$2$3"; |
599 | my($fname) = "$4"; | |
600 | my($args) = "$5"; | |
601 | my($res) = $missing; | |
602 | ||
603 | # Remember that this name is allowed. | |
604 | push @allow, $fname; | |
605 | ||
606 | # Generate a program to test for availability of this function. | |
607 | open (TESTFILE, ">$fnamebase.c"); | |
608 | print TESTFILE "$prepend"; | |
609 | print TESTFILE "#include <$h>\n"; | |
610 | # print TESTFILE "#undef $fname\n"; | |
611 | print TESTFILE "$rettype (*(*foobarbaz) $args = $fname;\n"; | |
612 | close (TESTFILE); | |
613 | ||
614 | $res = compiletest ($fnamebase, "Test availability of function $fname", | |
d22956c9 JM |
615 | ($optional |
616 | ? "NOT AVAILABLE" | |
617 | : "Function \"$fname\" is not available."), $res, | |
5675961d | 618 | $optional, $xfail); |
2ff458eb | 619 | |
d22956c9 | 620 | if ($res == 0 || $missing == 1 || !$optional) { |
2ff458eb UD |
621 | # Generate a program to test for the type of this function. |
622 | open (TESTFILE, ">$fnamebase.c"); | |
623 | print TESTFILE "$prepend"; | |
624 | print TESTFILE "#include <$h>\n"; | |
625 | # print TESTFILE "#undef $fname\n"; | |
626 | print TESTFILE "extern $rettype (*(*foobarbaz) $args;\n"; | |
627 | print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n"; | |
628 | close (TESTFILE); | |
629 | ||
630 | compiletest ($fnamebase, "Test for type of function $fname", | |
5675961d JM |
631 | "Function \"$fname\" has incorrect type.", $res, 0, |
632 | $xfail); | |
2ff458eb | 633 | } |
d22956c9 | 634 | } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { |
2ff458eb UD |
635 | my($rettype) = "$2$3"; |
636 | my($fname) = "$4"; | |
637 | my($args) = "$5"; | |
638 | my($res) = $missing; | |
639 | ||
640 | # Remember that this name is allowed. | |
641 | push @allow, $fname; | |
642 | ||
643 | # Generate a program to test for availability of this function. | |
644 | open (TESTFILE, ">$fnamebase.c"); | |
645 | print TESTFILE "$prepend"; | |
646 | print TESTFILE "#include <$h>\n"; | |
647 | # print TESTFILE "#undef $fname\n"; | |
648 | print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n"; | |
649 | close (TESTFILE); | |
650 | ||
651 | $res = compiletest ($fnamebase, "Test availability of function $fname", | |
d22956c9 JM |
652 | ($optional |
653 | ? "NOT AVAILABLE" | |
654 | : "Function \"$fname\" is not available."), $res, | |
5675961d | 655 | $optional, $xfail); |
2ff458eb | 656 | |
d22956c9 | 657 | if ($res == 0 || $missing != 0 || !$optional) { |
2ff458eb UD |
658 | # Generate a program to test for the type of this function. |
659 | open (TESTFILE, ">$fnamebase.c"); | |
660 | print TESTFILE "$prepend"; | |
661 | print TESTFILE "#include <$h>\n"; | |
662 | # print TESTFILE "#undef $fname\n"; | |
663 | print TESTFILE "extern $rettype (*foobarbaz) $args;\n"; | |
664 | print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n"; | |
665 | close (TESTFILE); | |
666 | ||
667 | compiletest ($fnamebase, "Test for type of function $fname", | |
5675961d JM |
668 | "Function \"$fname\" has incorrect type.", $res, 0, |
669 | $xfail); | |
2ff458eb | 670 | } |
73b6bffc | 671 | } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) *(.*)/) { |
8ce9ea0c UD |
672 | my($type) = "$2$3"; |
673 | my($vname) = "$4"; | |
73b6bffc | 674 | my($rest) = "$5"; |
8ce9ea0c UD |
675 | my($res) = $missing; |
676 | ||
677 | # Remember that this name is allowed. | |
678 | push @allow, $vname; | |
679 | ||
680 | # Generate a program to test for availability of this function. | |
681 | open (TESTFILE, ">$fnamebase.c"); | |
682 | print TESTFILE "$prepend"; | |
683 | print TESTFILE "#include <$h>\n"; | |
684 | # print TESTFILE "#undef $fname\n"; | |
73b6bffc UD |
685 | print TESTFILE "typedef $type xyzzy$rest;\n"; |
686 | print TESTFILE "$xyzzy *foobarbaz = &$vname;\n"; | |
8ce9ea0c UD |
687 | close (TESTFILE); |
688 | ||
689 | $res = compiletest ($fnamebase, "Test availability of variable $vname", | |
5675961d JM |
690 | "Variable \"$vname\" is not available.", $res, 0, |
691 | $xfail); | |
8ce9ea0c UD |
692 | |
693 | # Generate a program to test for the type of this function. | |
694 | open (TESTFILE, ">$fnamebase.c"); | |
695 | print TESTFILE "$prepend"; | |
696 | print TESTFILE "#include <$h>\n"; | |
697 | # print TESTFILE "#undef $fname\n"; | |
73b6bffc | 698 | print TESTFILE "extern $type $vname$rest;\n"; |
8ce9ea0c UD |
699 | close (TESTFILE); |
700 | ||
701 | compiletest ($fnamebase, "Test for type of variable $fname", | |
5675961d | 702 | "Variable \"$vname\" has incorrect type.", $res, 0, $xfail); |
8ce9ea0c UD |
703 | } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { |
704 | my($rettype) = "$2$3"; | |
705 | my($fname) = "$4"; | |
706 | my($args) = "$5"; | |
707 | my($res) = $missing; | |
708 | ||
709 | # Remember that this name is allowed. | |
710 | push @allow, $fname; | |
711 | ||
712 | # Generate a program to test for availability of this function. | |
713 | open (TESTFILE, ">$fnamebase.c"); | |
714 | print TESTFILE "$prepend"; | |
715 | print TESTFILE "#include <$h>\n"; | |
716 | print TESTFILE "#ifndef $fname\n"; | |
717 | print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n"; | |
718 | print TESTFILE "#endif\n"; | |
719 | close (TESTFILE); | |
720 | ||
31341567 | 721 | $res = compiletest ($fnamebase, "Test availability of macro $fname", |
5675961d JM |
722 | "Function \"$fname\" is not available.", $res, 0, |
723 | $xfail); | |
8ce9ea0c UD |
724 | |
725 | # Generate a program to test for the type of this function. | |
726 | open (TESTFILE, ">$fnamebase.c"); | |
727 | print TESTFILE "$prepend"; | |
728 | print TESTFILE "#include <$h>\n"; | |
729 | print TESTFILE "#ifndef $fname\n"; | |
730 | print TESTFILE "extern $rettype (*foobarbaz) $args;\n"; | |
731 | print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n"; | |
732 | print TESTFILE "#endif\n"; | |
733 | close (TESTFILE); | |
734 | ||
31341567 | 735 | compiletest ($fnamebase, "Test for type of macro $fname", |
5675961d | 736 | "Function \"$fname\" has incorrect type.", $res, 0, $xfail); |
7cc9fcf4 | 737 | } elsif (/^macro-str *([^ ]*) *(\".*\")/) { |
20d49639 AJ |
738 | # The above regex doesn't handle a \" in a string. |
739 | my($macro) = "$1"; | |
740 | my($string) = "$2"; | |
741 | my($res) = $missing; | |
742 | ||
743 | # Remember that this name is allowed. | |
744 | push @allow, $macro; | |
745 | ||
746 | # Generate a program to test for availability of this macro. | |
747 | open (TESTFILE, ">$fnamebase.c"); | |
748 | print TESTFILE "$prepend"; | |
749 | print TESTFILE "#include <$h>\n"; | |
750 | print TESTFILE "#ifndef $macro\n"; | |
751 | print TESTFILE "# error \"Macro $macro not defined\"\n"; | |
752 | print TESTFILE "#endif\n"; | |
753 | close (TESTFILE); | |
754 | ||
755 | compiletest ($fnamebase, "Test availability of macro $macro", | |
5675961d | 756 | "Macro \"$macro\" is not available.", $missing, 0, $xfail); |
20d49639 AJ |
757 | |
758 | # Generate a program to test for the value of this macro. | |
759 | open (TESTFILE, ">$fnamebase.c"); | |
760 | print TESTFILE "$prepend"; | |
761 | print TESTFILE "#include <$h>\n"; | |
762 | # We can't include <string.h> here. | |
763 | print TESTFILE "extern int (strcmp)(const char *, const char *);\n"; | |
7cc9fcf4 | 764 | print TESTFILE "int main (void) { return (strcmp) ($macro, $string) != 0;}\n"; |
20d49639 AJ |
765 | close (TESTFILE); |
766 | ||
767 | $res = runtest ($fnamebase, "Testing for value of macro $macro", | |
5675961d JM |
768 | "Macro \"$macro\" has not the right value.", $res, |
769 | $xfail); | |
0ed99ce4 UD |
770 | } elsif (/^allow-header *(.*)/) { |
771 | my($pattern) = $1; | |
9d48fef0 UD |
772 | if ($seenheader{$pattern} != 1) { |
773 | push @allowheader, $pattern; | |
774 | $seenheader{$pattern} = 1; | |
775 | } | |
0ed99ce4 | 776 | next control; |
d753ffef UD |
777 | } elsif (/^allow *(.*)/) { |
778 | my($pattern) = $1; | |
779 | push @allow, $pattern; | |
780 | next control; | |
da1067a9 UD |
781 | } else { |
782 | # printf ("line is `%s'\n", $_); | |
783 | next control; | |
784 | } | |
785 | ||
786 | printf ("\n"); | |
787 | } | |
788 | close (CONTROL); | |
789 | ||
0ed99ce4 UD |
790 | # Read the data files for the header files which are allowed to be included. |
791 | while ($#allowheader >= 0) { | |
792 | my($ah) = pop @allowheader; | |
793 | ||
05bcf62a | 794 | open (ALLOW, "$CC -E -D$standard -x c data/$ah-data |"); |
0ed99ce4 | 795 | acontrol: while (<ALLOW>) { |
505cf2c0 | 796 | chop; |
0ed99ce4 | 797 | next acontrol if (/^#/); |
20d49639 | 798 | next acontrol if (/^[ ]*$/); |
0ed99ce4 | 799 | |
5675961d JM |
800 | s/^xfail-//; |
801 | s/^optional-//; | |
0ed99ce4 UD |
802 | if (/^element *({([^}]*)}|([^ ]*)) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) { |
803 | push @allow, $7; | |
661f8cf0 | 804 | } elsif (/^(macro|constant|macro-constant|macro-int-constant) +([a-zA-Z0-9_]*) *(?:{([^}]*)} *)?(?:([>=<!]+) ([A-Za-z0-9_-]*))?/) { |
b92a20b5 | 805 | push @allow, $2; |
a9625ea9 UD |
806 | } elsif (/^(type|tag) *({([^}]*)|([a-zA-Z0-9_]*))/) { |
807 | my($type) = "$3$4"; | |
0ed99ce4 UD |
808 | |
809 | # Remember that this name is allowed. | |
810 | if ($type =~ /^struct *(.*)/) { | |
811 | push @allow, $1; | |
812 | } elsif ($type =~ /^union *(.*)/) { | |
813 | push @allow, $1; | |
814 | } else { | |
815 | push @allow, $type; | |
816 | } | |
817 | } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) { | |
818 | push @allow, $4; | |
819 | } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { | |
820 | push @allow, $4; | |
821 | } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) { | |
822 | push @allow, $4; | |
823 | } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { | |
824 | push @allow, $4; | |
39c33b6c JM |
825 | } elsif (/^symbol *([a-zA-Z0-9_]*) *([A-Za-z0-9_-]*)?/) { |
826 | push @allow, $1; | |
0ed99ce4 | 827 | } elsif (/^allow-header *(.*)/) { |
9d48fef0 UD |
828 | if ($seenheader{$1} != 1) { |
829 | push @allowheader, $1; | |
830 | $seenheader{$1} = 1; | |
831 | } | |
bec7805d UD |
832 | } elsif (/^allow *(.*)/) { |
833 | push @allow, $1; | |
0ed99ce4 UD |
834 | } |
835 | } | |
836 | close (ALLOW); | |
837 | } | |
838 | ||
31341567 UD |
839 | if ($test_exist) { |
840 | printf (" Not defined\n"); | |
da1067a9 | 841 | } else { |
31341567 UD |
842 | # Now check the namespace. |
843 | printf (" Checking the namespace of \"%s\"... ", $h); | |
844 | if ($missing) { | |
845 | ++$skipped; | |
846 | printf ("SKIP\n"); | |
847 | } else { | |
848 | checknamespace ($h, $fnamebase, @allow); | |
849 | } | |
da1067a9 UD |
850 | } |
851 | ||
852 | printf ("\n\n"); | |
853 | } | |
854 | ||
855 | printf "-" x 76 . "\n"; | |
7287c36d UD |
856 | printf (" Total number of tests : %4d\n", $total); |
857 | ||
7287c36d UD |
858 | printf (" Number of failed tests : %4d (", $errors); |
859 | $percent = ($errors * 100) / $total; | |
6b3e8333 | 860 | if ($errors > 0 && $percent < 1.0) { |
7287c36d UD |
861 | printf (" <1%%)\n"); |
862 | } else { | |
863 | printf ("%3d%%)\n", $percent); | |
864 | } | |
865 | ||
5675961d JM |
866 | printf (" Number of xfailed tests : %4d (", $xerrors); |
867 | $percent = ($xerrors * 100) / $total; | |
868 | if ($xerrors > 0 && $percent < 1.0) { | |
869 | printf (" <1%%)\n"); | |
870 | } else { | |
871 | printf ("%3d%%)\n", $percent); | |
872 | } | |
873 | ||
7287c36d UD |
874 | printf (" Number of skipped tests : %4d (", $skipped); |
875 | $percent = ($skipped * 100) / $total; | |
6b3e8333 | 876 | if ($skipped > 0 && $percent < 1.0) { |
7287c36d UD |
877 | printf (" <1%%)\n"); |
878 | } else { | |
879 | printf ("%3d%%)\n", $percent); | |
880 | } | |
da1067a9 UD |
881 | |
882 | exit $errors != 0; | |
31341567 UD |
883 | # Local Variables: |
884 | # perl-indent-level: 2 | |
885 | # End: |