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 @headers = ('unistd.h');
27 # These are the ISO C99 keywords.
28 @keywords = ('auto', 'break', 'case', 'char', 'const', 'continue', 'default',
29 'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto',
30 'if', 'inline', 'int', 'long', 'register', 'restrict', 'return',
31 'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
32 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while');
34 # These are symbols which are known to pollute the namespace.
35 @knownproblems = ('unix', 'linux', 'i386');
37 # Some headers need a bit more attention.
38 $mustprepend{'regex.h'} = "#include <sys/types.h>\n";
39 $mustprepend{'wordexp.h'} = "#include <stddef.h>\n";
41 # Make a hash table from this information.
42 while ($#keywords >= 0) {
43 $iskeyword{pop (@keywords)} = 1;
46 # Make a hash table from the known problems.
47 while ($#knownproblems >= 0) {
48 $isknown{pop (@knownproblems)} = 1;
67 my($pattern, $string) = @_;
68 my($strlen) = length ($string);
71 if (substr ($pattern, 0, 1) eq '*') {
72 my($patlen) = length ($pattern) - 1;
73 $res = ($strlen >= $patlen
74 && substr ($pattern, -$patlen, $patlen) eq substr ($string, -$patlen, $patlen));
75 } elsif (substr ($pattern, -1, 1) eq '*') {
76 my($patlen) = length ($pattern) - 1;
77 $res = ($strlen >= $patlen
78 && substr ($pattern, 0, $patlen) eq substr ($string, 0, $patlen));
80 $res = $pattern eq $string;
88 my($fnamebase, $msg, $errmsg, $skip) = @_;
99 $ret = system "$CC $CFLAGS -c $fnamebase.c -o $fnamebase.o > $fnamebase.out 2>&1";
103 printf (" $errmsg Compiler message:\n");
110 if ($verbose > 1 && -s "$fnamebase.out") {
111 # We print all warnings issued.
115 if ($printlog != 0) {
116 printf (" " . "-" x 71 . "\n");
117 open (MESSAGE, "< $fnamebase.out");
122 printf (" " . "-" x 71 . "\n");
125 unlink "$fnamebase.c";
126 unlink "$fnamebase.o";
127 unlink "$fnamebase.out";
135 my($fnamebase, $msg, $errmsg, $skip) = @_;
146 $ret = system "$CC $CFLAGS -o $fnamebase $fnamebase.c > $fnamebase.out 2>&1";
150 printf (" $errmsg Compiler message:\n");
156 # Now run the program. If the exit code is not zero something is wrong.
157 $result = system "$fnamebase > $fnamebase.out2 2>&1";
160 if ($verbose > 1 && -s "$fnamebase.out") {
161 # We print all warnings issued.
163 system "cat $fnamebase.out2 >> $fnamebase.out";
168 unlink "$fnamebase.out";
169 rename "$fnamebase.out2", "$fnamebase.out";
172 if ($printlog != 0) {
173 printf (" " . "-" x 71 . "\n");
174 open (MESSAGE, "< $fnamebase.out");
179 printf (" " . "-" x 71 . "\n");
183 unlink "$fnamebase.c";
184 unlink "$fnamebase.o";
185 unlink "$fnamebase.out";
186 unlink "$fnamebase.out2";
193 my($token, @allow) = @_;
196 return if ($token =~ /^[0-9_]/ || $iskeyword{$token});
198 for ($idx = 0; $idx <= $#allow; ++$idx) {
199 return if (poorfnmatch ($allow[$idx], $token));
202 if ($isknown{$token}) {
207 printf ("FAIL\n " . "-" x 72 . "\n");
209 printf (" Namespace violation: \"%s\"\n", $token);
215 my($h, $fnamebase, @allow) = @_;
219 # Generate a program to get the contents of this header.
220 open (TESTFILE, ">$fnamebase.c");
221 print TESTFILE "#include <$h>\n";
226 open (CONTENT, "$CC $CFLAGS -E $fnamebase.c -P -Wp,-dN | sed -e '/^# [1-9]/d' -e '/^[[:space:]]*\$/d' |");
227 loop: while (<CONTENT>) {
228 next loop if (/^#undef /);
230 if (/^#define (.*)/) {
231 newtoken ($1, @allow);
233 # We have to tokenize the line.
236 my($len) = length ($str);
238 foreach $token (split(/[^a-zA-Z0-9_]/, $str)) {
240 newtoken ($token, @allow);
246 unlink "$fnamebase.c";
248 printf (" " . "-" x 72 . "\n");
250 } elsif ($nknown > 0) {
251 printf ("EXPECTED FAILURES\n");
259 while ($#headers >= 0) {
260 my($h) = pop (@headers);
263 my($fnamebase) = "$tmpdir/$hf-test";
266 my(@allowheader) = ();
267 my($prepend) = $mustprepend{$h};
269 printf ("Testing <$h>\n");
270 printf ("----------" . "-" x length ($h) . "\n");
272 # Generate a program to test for the availability of this header.
273 open (TESTFILE, ">$fnamebase.c");
274 print TESTFILE "$prepend";
275 print TESTFILE "#include <$h>\n";
278 $missing = compiletest ($fnamebase, "Checking whether <$h> is available",
279 "Header <$h> not available", 0);
283 open (CONTROL, "$CC -E -D$dialect - < data/$h-data |");
284 control: while (<CONTROL>) {
286 next control if (/^#/);
287 next control if (/^[ ]*$/);
289 if (/^element *({([^}]*)}|([^{ ]*)) *({([^}]*)}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
290 my($struct) = "$2$3";
296 # Remember that this name is allowed.
297 push @allow, $member;
299 # Generate a program to test for the availability of this member.
300 open (TESTFILE, ">$fnamebase.c");
301 print TESTFILE "$prepend";
302 print TESTFILE "#include <$h>\n";
303 print TESTFILE "$struct a;\n";
304 print TESTFILE "$struct b;\n";
305 print TESTFILE "extern void xyzzy (__typeof__ (&b.$member), __typeof__ (&a.$member), unsigned);\n";
306 print TESTFILE "void foobarbaz (void) {\n";
307 print TESTFILE " xyzzy (&a.$member, &b.$member, sizeof (a.$member));\n";
308 print TESTFILE "}\n";
311 $res = compiletest ($fnamebase, "Testing for member $member",
312 "Member \"$member\" not available.", $res);
315 # Test the types of the members.
316 open (TESTFILE, ">$fnamebase.c");
317 print TESTFILE "$prepend";
318 print TESTFILE "#include <$h>\n";
319 print TESTFILE "$struct a;\n";
320 print TESTFILE "extern $type b$rest;\n";
321 print TESTFILE "extern __typeof__ (a.$member) b;\n";
324 compiletest ($fnamebase, "Testing for type of member $member",
325 "Member \"$member\" does not have the correct type.", $res);
326 } elsif (/^constant *([a-zA-Z0-9_]*) ([>=<]+) ([A-Za-z0-9_]*)/) {
332 # Remember that this name is allowed.
335 # Generate a program to test for the availability of this constant.
336 open (TESTFILE, ">$fnamebase.c");
337 print TESTFILE "$prepend";
338 print TESTFILE "#include <$h>\n";
339 print TESTFILE "__typeof__ ($const) a = $const;\n";
342 $res = compiletest ($fnamebase, "Testing for constant $const",
343 "Constant \"$const\" not available.", $res);
346 # Generate a program to test for the value of this constant.
347 open (TESTFILE, ">$fnamebase.c");
348 print TESTFILE "$prepend";
349 print TESTFILE "#include <$h>\n";
350 # Negate the value since 0 means ok
351 print TESTFILE "int main (void) { return !($const $op $value); }\n";
354 $res = runtest ($fnamebase, "Testing for value of constant $const",
355 "Constant \"$const\" has not the right value.", $res);
357 } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
363 # Remember that this name is allowed.
366 # Generate a program to test for the availability of this constant.
367 open (TESTFILE, ">$fnamebase.c");
368 print TESTFILE "$prepend";
369 print TESTFILE "#include <$h>\n";
370 print TESTFILE "__typeof__ ($const) a = $const;\n";
373 $res = compiletest ($fnamebase, "Testing for constant $const",
374 "Constant \"$const\" not available.", $res);
376 # Test the types of the members.
377 open (TESTFILE, ">$fnamebase.c");
378 print TESTFILE "$prepend";
379 print TESTFILE "#include <$h>\n";
380 print TESTFILE "__typeof__ (($type) 0) a;\n";
381 print TESTFILE "extern __typeof__ ($const) a;\n";
384 compiletest ($fnamebase, "Testing for type of constant $const",
385 "Constant \"$const\" does not have the correct type.",
389 # Generate a program to test for the value of this constant.
390 open (TESTFILE, ">$fnamebase.c");
391 print TESTFILE "$prepend";
392 print TESTFILE "#include <$h>\n";
393 print TESTFILE "int main (void) { return $const != $value; }\n";
396 $res = runtest ($fnamebase, "Testing for value of constant $const",
397 "Constant \"$const\" has not the right value.", $res);
399 } elsif (/^constant *([a-zA-Z0-9_]*) *([A-Za-z0-9_]*)?/) {
404 # Remember that this name is allowed.
407 # Generate a program to test for the availability of this constant.
408 open (TESTFILE, ">$fnamebase.c");
409 print TESTFILE "$prepend";
410 print TESTFILE "#include <$h>\n";
411 print TESTFILE "__typeof__ ($const) a = $const;\n";
414 $res = compiletest ($fnamebase, "Testing for constant $const",
415 "Constant \"$const\" not available.", $res);
418 # Generate a program to test for the value of this constant.
419 open (TESTFILE, ">$fnamebase.c");
420 print TESTFILE "$prepend";
421 print TESTFILE "#include <$h>\n";
422 print TESTFILE "int main (void) { return $const != $value; }\n";
425 $res = runtest ($fnamebase, "Testing for value of constant $const",
426 "Constant \"$const\" has not the right value.", $res);
428 } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
434 # Remember that this name is allowed.
437 # Generate a program to test for the availability of this constant.
438 open (TESTFILE, ">$fnamebase.c");
439 print TESTFILE "$prepend";
440 print TESTFILE "#include <$h>\n";
441 print TESTFILE "__typeof__ ($const) a = $const;\n";
444 $res = compiletest ($fnamebase, "Testing for constant $const",
445 "Constant \"$const\" not available.", $res);
447 # Test the types of the members.
448 open (TESTFILE, ">$fnamebase.c");
449 print TESTFILE "$prepend";
450 print TESTFILE "#include <$h>\n";
451 print TESTFILE "__typeof__ (($type) 0) a;\n";
452 print TESTFILE "extern __typeof__ ($const) a;\n";
455 compiletest ($fnamebase, "Testing for type of constant $const",
456 "Constant \"$const\" does not have the correct type.",
460 # Generate a program to test for the value of this constant.
461 open (TESTFILE, ">$fnamebase.c");
462 print TESTFILE "$prepend";
463 print TESTFILE "#include <$h>\n";
464 print TESTFILE "int main (void) { return $const != $value; }\n";
467 $res = runtest ($fnamebase, "Testing for value of constant $const",
468 "Constant \"$const\" has not the right value.", $res);
470 } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) {
473 # Remember that this name is allowed.
474 if ($type =~ /^struct *(.*)/) {
476 } elsif ($type =~ /^union *(.*)/) {
482 # Remember that this name is allowed.
485 # Generate a program to test for the availability of this constant.
486 open (TESTFILE, ">$fnamebase.c");
487 print TESTFILE "$prepend";
488 print TESTFILE "#include <$h>\n";
489 print TESTFILE "$type *a;\n";
492 compiletest ($fnamebase, "Testing for type $type",
493 "Type \"$type\" not available.", $missing);
494 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
495 my($rettype) = "$2$3";
500 # Remember that this name is allowed.
503 # Generate a program to test for availability of this function.
504 open (TESTFILE, ">$fnamebase.c");
505 print TESTFILE "$prepend";
506 print TESTFILE "#include <$h>\n";
507 # print TESTFILE "#undef $fname\n";
508 print TESTFILE "$rettype (*(*foobarbaz) $args = $fname;\n";
511 $res = compiletest ($fnamebase, "Test availability of function $fname",
512 "Function \"$fname\" is not available.", $res);
514 # Generate a program to test for the type of this function.
515 open (TESTFILE, ">$fnamebase.c");
516 print TESTFILE "$prepend";
517 print TESTFILE "#include <$h>\n";
518 # print TESTFILE "#undef $fname\n";
519 print TESTFILE "extern $rettype (*(*foobarbaz) $args;\n";
520 print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
523 compiletest ($fnamebase, "Test for type of function $fname",
524 "Function \"$fname\" has incorrect type.", $res);
525 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
526 my($rettype) = "$2$3";
531 # Remember that this name is allowed.
534 # Generate a program to test for availability of this function.
535 open (TESTFILE, ">$fnamebase.c");
536 print TESTFILE "$prepend";
537 print TESTFILE "#include <$h>\n";
538 # print TESTFILE "#undef $fname\n";
539 print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n";
542 $res = compiletest ($fnamebase, "Test availability of function $fname",
543 "Function \"$fname\" is not available.", $res);
545 # Generate a program to test for the type of this function.
546 open (TESTFILE, ">$fnamebase.c");
547 print TESTFILE "$prepend";
548 print TESTFILE "#include <$h>\n";
549 # print TESTFILE "#undef $fname\n";
550 print TESTFILE "extern $rettype (*foobarbaz) $args;\n";
551 print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
554 compiletest ($fnamebase, "Test for type of function $fname",
555 "Function \"$fname\" has incorrect type.", $res);
556 } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
561 # Remember that this name is allowed.
564 # Generate a program to test for availability of this function.
565 open (TESTFILE, ">$fnamebase.c");
566 print TESTFILE "$prepend";
567 print TESTFILE "#include <$h>\n";
568 # print TESTFILE "#undef $fname\n";
569 print TESTFILE "$type *foobarbaz = &$vname;\n";
572 $res = compiletest ($fnamebase, "Test availability of variable $vname",
573 "Variable \"$vname\" is not available.", $res);
575 # Generate a program to test for the type of this function.
576 open (TESTFILE, ">$fnamebase.c");
577 print TESTFILE "$prepend";
578 print TESTFILE "#include <$h>\n";
579 # print TESTFILE "#undef $fname\n";
580 print TESTFILE "extern $type $vname;\n";
583 compiletest ($fnamebase, "Test for type of variable $fname",
584 "Variable \"$vname\" has incorrect type.", $res);
585 } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
586 my($rettype) = "$2$3";
591 # Remember that this name is allowed.
594 # Generate a program to test for availability of this function.
595 open (TESTFILE, ">$fnamebase.c");
596 print TESTFILE "$prepend";
597 print TESTFILE "#include <$h>\n";
598 print TESTFILE "#ifndef $fname\n";
599 print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n";
600 print TESTFILE "#endif\n";
603 $res = compiletest ($fnamebase, "Test availability of function $fname",
604 "Function \"$fname\" is not available.", $res);
606 # Generate a program to test for the type of this function.
607 open (TESTFILE, ">$fnamebase.c");
608 print TESTFILE "$prepend";
609 print TESTFILE "#include <$h>\n";
610 print TESTFILE "#ifndef $fname\n";
611 print TESTFILE "extern $rettype (*foobarbaz) $args;\n";
612 print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
613 print TESTFILE "#endif\n";
616 compiletest ($fnamebase, "Test for type of function $fname",
617 "Function \"$fname\" has incorrect type.", $res);
618 } elsif (/^macro-str *([^ ]*)\s*(\".*\")/) {
619 # The above regex doesn't handle a \" in a string.
624 # Remember that this name is allowed.
627 # Generate a program to test for availability of this macro.
628 open (TESTFILE, ">$fnamebase.c");
629 print TESTFILE "$prepend";
630 print TESTFILE "#include <$h>\n";
631 print TESTFILE "#ifndef $macro\n";
632 print TESTFILE "# error \"Macro $macro not defined\"\n";
633 print TESTFILE "#endif\n";
636 compiletest ($fnamebase, "Test availability of macro $macro",
637 "Macro \"$macro\" is not available.", $missing);
639 # Generate a program to test for the value of this macro.
640 open (TESTFILE, ">$fnamebase.c");
641 print TESTFILE "$prepend";
642 print TESTFILE "#include <$h>\n";
643 # We can't include <string.h> here.
644 print TESTFILE "extern int (strcmp)(const char *, const char *);\n";
645 print TESTFILE "int main (void) { return strcmp ($macro, $string) != 0;}\n";
648 $res = runtest ($fnamebase, "Testing for value of macro $macro",
649 "Macro \"$macro\" has not the right value.", $res);
650 } elsif (/^macro *([^ ]*)/) {
653 # Remember that this name is allowed.
656 # Generate a program to test for availability of this macro.
657 open (TESTFILE, ">$fnamebase.c");
658 print TESTFILE "$prepend";
659 print TESTFILE "#include <$h>\n";
660 print TESTFILE "#ifndef $macro\n";
661 print TESTFILE "# error \"Macro $macro not defined\"\n";
662 print TESTFILE "#endif\n";
665 compiletest ($fnamebase, "Test availability of macro $macro",
666 "Macro \"$macro\" is not available.", $missing);
667 } elsif (/^allow-header *(.*)/) {
669 push @allowheader, $pattern;
671 } elsif (/^allow *(.*)/) {
673 push @allow, $pattern;
676 # printf ("line is `%s'\n", $_);
684 # Read the data files for the header files which are allowed to be included.
685 while ($#allowheader >= 0) {
686 my($ah) = pop @allowheader;
688 open (ALLOW, "$CC -E -D$dialect - < data/$ah-data |");
689 acontrol: while (<ALLOW>) {
690 next acontrol if (/^#/);
691 next acontrol if (/^[ ]*$/);
693 if (/^element *({([^}]*)}|([^ ]*)) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
695 } elsif (/^constant *([a-zA-Z0-9_]*) *([A-Za-z0-9_]*)?/) {
697 } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
699 } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) {
702 # Remember that this name is allowed.
703 if ($type =~ /^struct *(.*)/) {
705 } elsif ($type =~ /^union *(.*)/) {
710 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
712 } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
714 } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
716 } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
718 } elsif (/^macro *([^ ]*)/) {
720 } elsif (/^allow *(.*)/) {
722 } elsif (/^allow-header *(.*)/) {
723 # XXX We should have a test for recursive dependencies here.
724 push @allowheader, $1;
730 # Now check the namespace.
731 printf (" Checking the namespace of \"%s\"... ", $h);
736 checknamespace ($h, $fnamebase, @allow);
742 printf "-" x 76 . "\n";
743 printf (" Total number of tests : %4d\n", $total);
745 printf (" Number of known failures: %4d (", $known);
746 $percent = ($known * 100) / $total;
747 if ($percent < 1.0) {
750 printf ("%3d%%)\n", $percent);
753 printf (" Number of failed tests : %4d (", $errors);
754 $percent = ($errors * 100) / $total;
755 if ($percent < 1.0) {
758 printf ("%3d%%)\n", $percent);
761 printf (" Number of skipped tests : %4d (", $skipped);
762 $percent = ($skipped * 100) / $total;
763 if ($percent < 1.0) {
766 printf ("%3d%%)\n", $percent);