4 $CFLAGS = "-I. '-D__attribute__(x)=' -D_XOPEN_SOURCE=600";
6 # List of the headers we are testing.
7 @headers = ("wordexp.h", "wctype.h", "wchar.h", "varargs.h", "utmpx.h",
8 "utime.h", "unistd.h", "ulimit.h", "ucontext.h", "time.h",
9 "termios.h", "tar.h", "sys/wait.h", "sys/utsname.h", "sys/un.h",
10 "sys/uio.h", "sys/types.h", "sys/times.h", "sys/timeb.h",
11 "sys/time.h", "sys/statvfs.h", "sys/stat.h", "sys/socket.h",
12 "sys/shm.h", "sys/sem.h", "sys/resource.h", "sys/msg.h",
13 "sys/mman.h", "sys/ipc.h", "syslog.h", "stropts.h", "strings.h",
14 "string.h", "stdlib.h", "stdio.h", "stddef.h", "stdarg.h",
15 "spawn.h", "signal.h", "setjmp.h", "semaphore.h",
16 "search.h", "sched.h", "regex.h", "pwd.h", "pthread.h",
17 "poll.h", "nl_types.h", "netinet/tcp.h", "netinet/in.h",
18 "net/if.h", "netdb.h", "ndbm.h", "mqueue.h", "monetary.h",
19 "math.h", "locale.h", "libgen.h", "limits.h", "langinfo.h",
20 "iso646.h", "inttypes.h", "iconv.h", "grp.h", "glob.h", "ftw.h",
21 "fnmatch.h", "fmtmsg.h", "float.h", "fcntl.h", "errno.h",
22 "dlfcn.h", "dirent.h", "ctype.h", "cpio.h", "assert.h",
23 "arpa/inet.h", "aio.h");
25 # These are the ISO C99 keywords.
26 @keywords = ('auto', 'break', 'case', 'char', 'const', 'continue', 'default',
27 'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto',
28 'if', 'inline', 'int', 'long', 'register', 'restrict', 'return',
29 'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
30 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while');
32 # These are symbols which are known to pollute the namespace.
33 @knownproblems = ('unix', 'linux', 'i386');
35 # Some headers need a bit more attention.
36 $mustprepend{'regex.h'} = "#include <sys/types.h>\n";
37 $mustprepend{'wordexp.h'} = "#include <stddef.h>\n";
39 # Make a hash table from this information.
40 while ($#keywords >= 0) {
41 $iskeyword{pop (@keywords)} = 1;
44 # Make a hash table from the known problems.
45 while ($#knownproblems >= 0) {
46 $isknown{pop (@knownproblems)} = 1;
65 my($pattern, $string) = @_;
66 my($strlen) = length ($string);
69 if (substr ($pattern, 0, 1) eq '*') {
70 my($patlen) = length ($pattern) - 1;
71 $res = ($strlen >= $patlen
72 && substr ($pattern, -$patlen, $patlen) eq substr ($string, -$patlen, $patlen));
73 } elsif (substr ($pattern, -1, 1) eq '*') {
74 my($patlen) = length ($pattern) - 1;
75 $res = ($strlen >= $patlen
76 && substr ($pattern, 0, $patlen) eq substr ($string, 0, $patlen));
78 $res = $pattern eq $string;
86 my($fnamebase, $msg, $errmsg, $skip) = @_;
97 $ret = system "$CC $CFLAGS -c $fnamebase.c -o $fnamebase.o > $fnamebase.out 2>&1";
101 printf (" $errmsg Compiler message:\n");
108 if ($verbose > 1 && -s "$fnamebase.out") {
109 # We print all warnings issued.
113 if ($printlog != 0) {
114 printf (" " . "-" x 71 . "\n");
115 open (MESSAGE, "< $fnamebase.out");
120 printf (" " . "-" x 71 . "\n");
123 unlink "$fnamebase.c";
124 unlink "$fnamebase.o";
125 unlink "$fnamebase.out";
133 my($fnamebase, $msg, $errmsg, $skip) = @_;
144 $ret = system "$CC $CFLAGS -o $fnamebase $fnamebase.c > $fnamebase.out 2>&1";
148 printf (" $errmsg Compiler message:\n");
154 # Now run the program. If the exit code is not zero something is wrong.
155 $result = system "$fnamebase > $fnamebase.out2 2>&1";
158 if ($verbose > 1 && -s "$fnamebase.out") {
159 # We print all warnings issued.
161 system "cat $fnamebase.out2 >> $fnamebase.out";
166 unlink "$fnamebase.out";
167 rename "$fnamebase.out2", "$fnamebase.out";
170 if ($printlog != 0) {
171 printf (" " . "-" x 71 . "\n");
172 open (MESSAGE, "< $fnamebase.out");
177 printf (" " . "-" x 71 . "\n");
181 unlink "$fnamebase.c";
182 unlink "$fnamebase.o";
183 unlink "$fnamebase.out";
184 unlink "$fnamebase.out2";
191 my($token, @allow) = @_;
194 return if ($token =~ /^[0-9_]/ || $iskeyword{$token});
196 for ($idx = 0; $idx <= $#allow; ++$idx) {
197 return if (poorfnmatch ($allow[$idx], $token));
200 if ($isknown{$token}) {
205 printf ("FAIL\n " . "-" x 72 . "\n");
207 printf (" Namespace violation: \"%s\"\n", $token);
213 my($h, $fnamebase, @allow) = @_;
217 # Generate a program to get the contents of this header.
218 open (TESTFILE, ">$fnamebase.c");
219 print TESTFILE "#include <$h>\n";
224 open (CONTENT, "$CC $CFLAGS -E $fnamebase.c -P -Wp,-dN | sed -e '/^# [1-9]/d' -e '/^[[:space:]]*\$/d' |");
225 loop: while (<CONTENT>) {
226 next loop if (/^#undef /);
228 if (/^#define (.*)/) {
229 newtoken ($1, @allow);
231 # We have to tokenize the line.
234 my($len) = length ($str);
236 foreach $token (split(/[^a-zA-Z0-9_]/, $str)) {
238 newtoken ($token, @allow);
244 unlink "$fnamebase.c";
246 printf (" " . "-" x 72 . "\n");
248 } elsif ($nknown > 0) {
249 printf ("EXPECTED FAILURES\n");
257 while ($#headers >= 0) {
258 my($h) = pop (@headers);
261 my($fnamebase) = "$tmpdir/$hf-test";
264 my(@allowheader) = ();
265 my($prepend) = $mustprepend{$h};
267 printf ("Testing <$h>\n");
268 printf ("----------" . "-" x length ($h) . "\n");
270 # Generate a program to test for the availability of this header.
271 open (TESTFILE, ">$fnamebase.c");
272 print TESTFILE "$prepend";
273 print TESTFILE "#include <$h>\n";
276 $missing = compiletest ($fnamebase, "Checking whether <$h> is available",
277 "Header <$h> not available", 0);
281 open (CONTROL, "$CC -E -D$dialect - < data/$h-data |");
282 control: while (<CONTROL>) {
284 next control if (/^#/);
285 next control if (/^[ ]*$/);
287 if (/^element *({([^}]*)}|([^{ ]*)) *({([^}]*)}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
288 my($struct) = "$2$3";
294 # Remember that this name is allowed.
295 push @allow, $member;
297 # Generate a program to test for the availability of this member.
298 open (TESTFILE, ">$fnamebase.c");
299 print TESTFILE "$prepend";
300 print TESTFILE "#include <$h>\n";
301 print TESTFILE "$struct a;\n";
302 print TESTFILE "$struct b;\n";
303 print TESTFILE "extern void xyzzy (__typeof__ (&b.$member), __typeof__ (&a.$member), unsigned);\n";
304 print TESTFILE "void foobarbaz (void) {\n";
305 print TESTFILE " xyzzy (&a.$member, &b.$member, sizeof (a.$member));\n";
306 print TESTFILE "}\n";
309 $res = compiletest ($fnamebase, "Testing for member $member",
310 "Member \"$member\" not available.", $res);
313 # Test the types of the members.
314 open (TESTFILE, ">$fnamebase.c");
315 print TESTFILE "$prepend";
316 print TESTFILE "#include <$h>\n";
317 print TESTFILE "$struct a;\n";
318 print TESTFILE "extern $type b$rest;\n";
319 print TESTFILE "extern __typeof__ (a.$member) b;\n";
322 compiletest ($fnamebase, "Testing for type of member $member",
323 "Member \"$member\" does not have the correct type.", $res);
324 } elsif (/^constant *([a-zA-Z0-9_]*) ([>=<]+) ([A-Za-z0-9_]*)/) {
330 # Remember that this name is allowed.
333 # Generate a program to test for the availability of this constant.
334 open (TESTFILE, ">$fnamebase.c");
335 print TESTFILE "$prepend";
336 print TESTFILE "#include <$h>\n";
337 print TESTFILE "__typeof__ ($const) a = $const;\n";
340 $res = compiletest ($fnamebase, "Testing for constant $const",
341 "Constant \"$const\" not available.", $res);
344 # Generate a program to test for the value of this constant.
345 open (TESTFILE, ">$fnamebase.c");
346 print TESTFILE "$prepend";
347 print TESTFILE "#include <$h>\n";
348 # Negate the value since 0 means ok
349 print TESTFILE "int main (void) { return !($const $op $value); }\n";
352 $res = runtest ($fnamebase, "Testing for value of constant $const",
353 "Constant \"$const\" has not the right value.", $res);
355 } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
361 # Remember that this name is allowed.
364 # Generate a program to test for the availability of this constant.
365 open (TESTFILE, ">$fnamebase.c");
366 print TESTFILE "$prepend";
367 print TESTFILE "#include <$h>\n";
368 print TESTFILE "__typeof__ ($const) a = $const;\n";
371 $res = compiletest ($fnamebase, "Testing for constant $const",
372 "Constant \"$const\" not available.", $res);
374 # Test the types of the members.
375 open (TESTFILE, ">$fnamebase.c");
376 print TESTFILE "$prepend";
377 print TESTFILE "#include <$h>\n";
378 print TESTFILE "__typeof__ (($type) 0) a;\n";
379 print TESTFILE "extern __typeof__ ($const) a;\n";
382 compiletest ($fnamebase, "Testing for type of constant $const",
383 "Constant \"$const\" does not have the correct type.",
387 # Generate a program to test for the value of this constant.
388 open (TESTFILE, ">$fnamebase.c");
389 print TESTFILE "$prepend";
390 print TESTFILE "#include <$h>\n";
391 print TESTFILE "int main (void) { return $const != $value; }\n";
394 $res = runtest ($fnamebase, "Testing for value of constant $const",
395 "Constant \"$const\" has not the right value.", $res);
397 } elsif (/^constant *([a-zA-Z0-9_]*) *([A-Za-z0-9_]*)?/) {
402 # Remember that this name is allowed.
405 # Generate a program to test for the availability of this constant.
406 open (TESTFILE, ">$fnamebase.c");
407 print TESTFILE "$prepend";
408 print TESTFILE "#include <$h>\n";
409 print TESTFILE "__typeof__ ($const) a = $const;\n";
412 $res = compiletest ($fnamebase, "Testing for constant $const",
413 "Constant \"$const\" not available.", $res);
416 # Generate a program to test for the value of this constant.
417 open (TESTFILE, ">$fnamebase.c");
418 print TESTFILE "$prepend";
419 print TESTFILE "#include <$h>\n";
420 print TESTFILE "int main (void) { return $const != $value; }\n";
423 $res = runtest ($fnamebase, "Testing for value of constant $const",
424 "Constant \"$const\" has not the right value.", $res);
426 } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
432 # Remember that this name is allowed.
435 # Generate a program to test for the availability of this constant.
436 open (TESTFILE, ">$fnamebase.c");
437 print TESTFILE "$prepend";
438 print TESTFILE "#include <$h>\n";
439 print TESTFILE "__typeof__ ($const) a = $const;\n";
442 $res = compiletest ($fnamebase, "Testing for constant $const",
443 "Constant \"$const\" not available.", $res);
445 # Test the types of the members.
446 open (TESTFILE, ">$fnamebase.c");
447 print TESTFILE "$prepend";
448 print TESTFILE "#include <$h>\n";
449 print TESTFILE "__typeof__ (($type) 0) a;\n";
450 print TESTFILE "extern __typeof__ ($const) a;\n";
453 compiletest ($fnamebase, "Testing for type of constant $const",
454 "Constant \"$const\" does not have the correct type.",
458 # Generate a program to test for the value of this constant.
459 open (TESTFILE, ">$fnamebase.c");
460 print TESTFILE "$prepend";
461 print TESTFILE "#include <$h>\n";
462 print TESTFILE "int main (void) { return $const != $value; }\n";
465 $res = runtest ($fnamebase, "Testing for value of constant $const",
466 "Constant \"$const\" has not the right value.", $res);
468 } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) {
471 # Remember that this name is allowed.
472 if ($type =~ /^struct *(.*)/) {
474 } elsif ($type =~ /^union *(.*)/) {
480 # Remember that this name is allowed.
483 # Generate a program to test for the availability of this constant.
484 open (TESTFILE, ">$fnamebase.c");
485 print TESTFILE "$prepend";
486 print TESTFILE "#include <$h>\n";
487 print TESTFILE "$type *a;\n";
490 compiletest ($fnamebase, "Testing for type $type",
491 "Type \"$type\" not available.", $missing);
492 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
493 my($rettype) = "$2$3";
498 # Remember that this name is allowed.
501 # Generate a program to test for availability of this function.
502 open (TESTFILE, ">$fnamebase.c");
503 print TESTFILE "$prepend";
504 print TESTFILE "#include <$h>\n";
505 # print TESTFILE "#undef $fname\n";
506 print TESTFILE "$rettype (*(*foobarbaz) $args = $fname;\n";
509 $res = compiletest ($fnamebase, "Test availability of function $fname",
510 "Function \"$fname\" is not available.", $res);
512 # Generate a program to test for the type of this function.
513 open (TESTFILE, ">$fnamebase.c");
514 print TESTFILE "$prepend";
515 print TESTFILE "#include <$h>\n";
516 # print TESTFILE "#undef $fname\n";
517 print TESTFILE "extern $rettype (*(*foobarbaz) $args;\n";
518 print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
521 compiletest ($fnamebase, "Test for type of function $fname",
522 "Function \"$fname\" has incorrect type.", $res);
523 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
524 my($rettype) = "$2$3";
529 # Remember that this name is allowed.
532 # Generate a program to test for availability of this function.
533 open (TESTFILE, ">$fnamebase.c");
534 print TESTFILE "$prepend";
535 print TESTFILE "#include <$h>\n";
536 # print TESTFILE "#undef $fname\n";
537 print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n";
540 $res = compiletest ($fnamebase, "Test availability of function $fname",
541 "Function \"$fname\" is not available.", $res);
543 # Generate a program to test for the type of this function.
544 open (TESTFILE, ">$fnamebase.c");
545 print TESTFILE "$prepend";
546 print TESTFILE "#include <$h>\n";
547 # print TESTFILE "#undef $fname\n";
548 print TESTFILE "extern $rettype (*foobarbaz) $args;\n";
549 print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
552 compiletest ($fnamebase, "Test for type of function $fname",
553 "Function \"$fname\" has incorrect type.", $res);
554 } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
559 # Remember that this name is allowed.
562 # Generate a program to test for availability of this function.
563 open (TESTFILE, ">$fnamebase.c");
564 print TESTFILE "$prepend";
565 print TESTFILE "#include <$h>\n";
566 # print TESTFILE "#undef $fname\n";
567 print TESTFILE "$type *foobarbaz = &$vname;\n";
570 $res = compiletest ($fnamebase, "Test availability of variable $vname",
571 "Variable \"$vname\" is not available.", $res);
573 # Generate a program to test for the type of this function.
574 open (TESTFILE, ">$fnamebase.c");
575 print TESTFILE "$prepend";
576 print TESTFILE "#include <$h>\n";
577 # print TESTFILE "#undef $fname\n";
578 print TESTFILE "extern $type $vname;\n";
581 compiletest ($fnamebase, "Test for type of variable $fname",
582 "Variable \"$vname\" has incorrect type.", $res);
583 } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
584 my($rettype) = "$2$3";
589 # Remember that this name is allowed.
592 # Generate a program to test for availability of this function.
593 open (TESTFILE, ">$fnamebase.c");
594 print TESTFILE "$prepend";
595 print TESTFILE "#include <$h>\n";
596 print TESTFILE "#ifndef $fname\n";
597 print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n";
598 print TESTFILE "#endif\n";
601 $res = compiletest ($fnamebase, "Test availability of function $fname",
602 "Function \"$fname\" is not available.", $res);
604 # Generate a program to test for the type of this function.
605 open (TESTFILE, ">$fnamebase.c");
606 print TESTFILE "$prepend";
607 print TESTFILE "#include <$h>\n";
608 print TESTFILE "#ifndef $fname\n";
609 print TESTFILE "extern $rettype (*foobarbaz) $args;\n";
610 print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
611 print TESTFILE "#endif\n";
614 compiletest ($fnamebase, "Test for type of function $fname",
615 "Function \"$fname\" has incorrect type.", $res);
616 } elsif (/^macro-str *([^ ]*)\s*(\".*\")/) {
617 # The above regex doesn't handle a \" in a string.
622 # Remember that this name is allowed.
625 # Generate a program to test for availability of this macro.
626 open (TESTFILE, ">$fnamebase.c");
627 print TESTFILE "$prepend";
628 print TESTFILE "#include <$h>\n";
629 print TESTFILE "#ifndef $macro\n";
630 print TESTFILE "# error \"Macro $macro not defined\"\n";
631 print TESTFILE "#endif\n";
634 compiletest ($fnamebase, "Test availability of macro $macro",
635 "Macro \"$macro\" is not available.", $missing);
637 # Generate a program to test for the value of this macro.
638 open (TESTFILE, ">$fnamebase.c");
639 print TESTFILE "$prepend";
640 print TESTFILE "#include <$h>\n";
641 # We can't include <string.h> here.
642 print TESTFILE "extern int (strcmp)(const char *, const char *);\n";
643 print TESTFILE "int main (void) { return strcmp ($macro, $string) != 0;}\n";
646 $res = runtest ($fnamebase, "Testing for value of macro $macro",
647 "Macro \"$macro\" has not the right value.", $res);
648 } elsif (/^macro *([^ ]*)/) {
651 # Remember that this name is allowed.
654 # Generate a program to test for availability of this macro.
655 open (TESTFILE, ">$fnamebase.c");
656 print TESTFILE "$prepend";
657 print TESTFILE "#include <$h>\n";
658 print TESTFILE "#ifndef $macro\n";
659 print TESTFILE "# error \"Macro $macro not defined\"\n";
660 print TESTFILE "#endif\n";
663 compiletest ($fnamebase, "Test availability of macro $macro",
664 "Macro \"$macro\" is not available.", $missing);
665 } elsif (/^allow-header *(.*)/) {
667 push @allowheader, $pattern;
669 } elsif (/^allow *(.*)/) {
671 push @allow, $pattern;
674 # printf ("line is `%s'\n", $_);
682 # Read the data files for the header files which are allowed to be included.
683 while ($#allowheader >= 0) {
684 my($ah) = pop @allowheader;
686 open (ALLOW, "$CC -E -D$dialect - < data/$ah-data |");
687 acontrol: while (<ALLOW>) {
688 next acontrol if (/^#/);
689 next acontrol if (/^[ ]*$/);
691 if (/^element *({([^}]*)}|([^ ]*)) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
693 } elsif (/^constant *([a-zA-Z0-9_]*) *([A-Za-z0-9_]*)?/) {
695 } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
697 } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) {
700 # Remember that this name is allowed.
701 if ($type =~ /^struct *(.*)/) {
703 } elsif ($type =~ /^union *(.*)/) {
708 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
710 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
712 } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
714 } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
716 } elsif (/^macro *([^ ]*)/) {
718 } elsif (/^allow *(.*)/) {
720 } elsif (/^allow-header *(.*)/) {
721 # XXX We should have a test for recursive dependencies here.
722 push @allowheader, $1;
728 # Now check the namespace.
729 printf (" Checking the namespace of \"%s\"... ", $h);
734 checknamespace ($h, $fnamebase, @allow);
740 printf "-" x 76 . "\n";
741 printf (" Total number of tests : %4d\n", $total);
743 printf (" Number of known failures: %4d (", $known);
744 $percent = ($known * 100) / $total;
745 if ($known > 0 && $percent < 1.0) {
748 printf ("%3d%%)\n", $percent);
751 printf (" Number of failed tests : %4d (", $errors);
752 $percent = ($errors * 100) / $total;
753 if ($errors > 0 && $percent < 1.0) {
756 printf ("%3d%%)\n", $percent);
759 printf (" Number of skipped tests : %4d (", $skipped);
760 $percent = ($skipped * 100) / $total;
761 if ($skipped > 0 && $percent < 1.0) {
764 printf ("%3d%%)\n", $percent);