Update.
[platform/upstream/glibc.git] / conform / conformtest.pl
1 #! /usr/bin/perl
2
3 $CC = "gcc";
4 $CFLAGS = "-I. '-D__attribute__(x)=' -D_XOPEN_SOURCE=500";
5
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", "langinfo.h", "iso646.h",
20             "inttypes.h", "iconv.h", "grp.h", "glob.h", "ftw.h", "fnmatch.h",
21             "fmtmsg.h", "float.h", "fcntl.h", "errno.h", "dlfcn.h", "dirent.h",
22             "ctype.h", "cpio.h", "assert.h", "arpa/inet.h", "aio.h");
23
24 # These are the ISO C99 keywords.
25 @keywords = ('auto', 'break', 'case', 'char', 'const', 'continue', 'default',
26              'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto',
27              'if', 'inline', 'int', 'long', 'register', 'restrict', 'return',
28              'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
29              'typedef', 'union', 'unsigned', 'void', 'volatile', 'while');
30
31 # Some headers need a bit more attention.
32 $mustprepend{'regex.h'} = "#include <sys/types.h>\n";
33
34 # Make an hash table from this information.
35 while ($#keywords) {
36   $iskeyword{pop (@keywords)} = 1;
37 }
38
39 $tmpdir = "/tmp";
40
41 $verbose = 1;
42
43 $total = 0;
44 $skipped = 0;
45 $errors = 0;
46
47 #$dialect = "ISO";
48 #$dialect = "POSIX";
49 #$dialect = "XPG3";
50 #$dialect = "XPG4";
51 $dialect = "UNIX98";
52
53
54 sub poorfnmatch {
55   my($pattern, $string) = @_;
56   my($strlen) = length ($string);
57   my($res);
58
59   if (substr ($pattern, 0, 1) eq '*') {
60     my($patlen) = length ($pattern) - 1;
61     $res = ($strlen >= $patlen
62             && substr ($pattern, -$patlen, $patlen) eq substr ($string, -$patlen, $patlen));
63   } elsif (substr ($pattern, -1, 1) eq '*') {
64     my($patlen) = length ($pattern) - 1;
65     $res = ($strlen >= $patlen
66             && substr ($pattern, 0, $patlen) eq substr ($string, 0, $patlen));
67   } else {
68     $res = $pattern eq $string;
69   }
70   return $res;
71 }
72
73
74 sub compiletest
75 {
76   my($fnamebase, $msg, $errmsg, $skip) = @_;
77   my($result) = $skip;
78   my($printlog) = 0;
79
80   ++$total;
81   printf ("  $msg...");
82
83   if ($skip != 0) {
84     ++$skipped;
85     printf (" SKIP\n");
86   } else {
87     $ret = system "$CC $CFLAGS -c $fnamebase.c -o $fnamebase.o > $fnamebase.out 2>&1";
88     if ($ret != 0) {
89       printf (" FAIL\n");
90       if ($verbose != 0) {
91         printf ("    $errmsg  Compiler message:\n");
92         $printlog = 1;
93       }
94       ++$errors;
95       $result = 1;
96     } else {
97       printf (" OK\n");
98       if ($verbose > 1 && -s "$fnamebase.out") {
99         # We print all warnings issued.
100         $printlog = 1;
101       }
102     }
103     if ($printlog != 0) {
104       printf ("    " . "-" x 71 . "\n");
105       open (MESSAGE, "< $fnamebase.out");
106       while (<MESSAGE>) {
107         printf ("    %s", $_);
108       }
109       close (MESSAGE);
110       printf ("    " . "-" x 71 . "\n");
111     }
112   }
113   unlink "$fnamebase.c";
114   unlink "$fnamebase.o";
115   unlink "$fnamebase.out";
116
117   $result;
118 }
119
120
121 sub runtest
122 {
123   my($fnamebase, $msg, $errmsg, $skip) = @_;
124   my($result) = $skip;
125   my($printlog) = 0;
126
127   ++$total;
128   printf ("  $msg...");
129
130   if ($skip != 0) {
131     ++$skipped;
132     printf (" SKIP\n");
133   } else {
134     $ret = system "$CC $CFLAGS -o $fnamebase $fnamebase.c > $fnamebase.out 2>&1";
135     if ($ret != 0) {
136       printf (" FAIL\n");
137       if ($verbose != 0) {
138         printf ("    $errmsg  Compiler message:\n");
139         $printlog = 1;
140       }
141       ++$errors;
142       $result = 1;
143     } else {
144       # Now run the program.  If the exit code is not zero something is wrong.
145       $result = system "$fnamebase > $fnamebase.out2 2>&1";
146       if ($result == 0) {
147         printf (" OK\n");
148         if ($verbose > 1 && -s "$fnamebase.out") {
149           # We print all warnings issued.
150           $printlog = 1;
151           system "cat $fnamebase.out2 >> $fnamebase.out";
152         }
153       } else {
154         printf (" FAIL\n");
155         $printlog = 1;
156         unlink "$fnamebase.out";
157         rename "$fnamebase.out2", "$fnamebase.out";
158       }
159     }
160     if ($printlog != 0) {
161       printf ("    " . "-" x 71 . "\n");
162       open (MESSAGE, "< $fnamebase.out");
163       while (<MESSAGE>) {
164         printf ("    %s", $_);
165       }
166       close (MESSAGE);
167       printf ("    " . "-" x 71 . "\n");
168     }
169   }
170   unlink "$fnamebase";
171   unlink "$fnamebase.c";
172   unlink "$fnamebase.o";
173   unlink "$fnamebase.out";
174   unlink "$fnamebase.out2";
175
176   $result;
177 }
178
179
180 sub newtoken {
181   my($token, $nerrors, @allow) = @_;
182   my($idx);
183
184   if ($token =~ /^[0-9_]/ || $iskeyword{$token}) {
185     return $nerrors;
186   }
187
188   for ($idx = 0; $idx <= $#allow; ++$idx) {
189     if (poorfnmatch ($allow[$idx], $token)) {
190       return $nerrors;
191     }
192   }
193
194   ++$nerrors;
195   if ($nerrors == 1) {
196     printf ("FAIL\n    " . "-" x 72 . "\n");
197   }
198   printf ("    Namespace violation: \"%s\"\n", $token);
199   return $nerrors;
200 }
201
202
203 sub checknamespace {
204   my($h, $fnamebase, @allow) = @_;
205   my($nerrors) = 0;
206
207   ++$total;
208
209   # Generate a program to get the contents of this header.
210   open (TESTFILE, ">$fnamebase.c");
211   print TESTFILE "#include <$h>\n";
212   close (TESTFILE);
213
214   open (CONTENT, "$CC $CFLAGS -E $fnamebase.c -Wp,-dN | sed -e '/^# [1-9]/d' -e '/^[[:space:]]*\$/d' |");
215   while (<CONTENT>) {
216     chop;
217     if (/^#define (.*)/) {
218       $nerrors = newtoken ($1, $nerrors, @allow);
219     } else {
220       # We have to tokenize the line.
221       my($str) = $_;
222       my($index) = 0;
223       my($len) = length ($str);
224
225       foreach $token (split(/[^a-zA-Z0-9_]/, $str)) {
226         if ($token ne "") {
227           $nerrors = newtoken ($token, $nerrors, @allow);
228         }
229       }
230     }
231   }
232   close (CONTENT);
233   unlink "$fnamebase.c";
234   if ($nerrors != 0) {
235     printf ("    " . "-" x 72 . "\n");
236     ++$errors;
237   } else {
238     printf ("OK\n");
239   }
240 }
241
242
243 while ($#headers >= 0) {
244   my($h) = pop (@headers);
245   my($hf) = $h;
246   $hf =~ s|/|-|;
247   my($fnamebase) = "$tmpdir/$hf-test";
248   my($missing);
249   my(@allow) = ();
250   my(@allowheader) = ();
251   my($prepend) = $mustprepend{$h};
252
253   printf ("Testing <$h>\n");
254   printf ("----------" . "-" x length ($h) . "\n");
255
256   # Generate a program to test for the availability of this header.
257   open (TESTFILE, ">$fnamebase.c");
258   print TESTFILE "$prepend";
259   print TESTFILE "#include <$h>\n";
260   close (TESTFILE);
261
262   $missing = compiletest ($fnamebase, "Checking whether <$h> is available",
263                           "Header <$h> not available", 0);
264
265   printf ("\n");
266
267   open (CONTROL, "$CC -E -D$dialect - < data/$h-data |");
268   control: while (<CONTROL>) {
269     chop;
270     next control if (/^#/);
271     next control if (/^[        ]*$/);
272
273     if (/^element *({([^}]*)}|([^ ]*)) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
274       my($struct) = "$2$3";
275       my($type) = "$5$6";
276       my($member) = "$7";
277       my($rest) = "$8";
278       my($res) = $missing;
279
280       # Remember that this name is allowed.
281       push @allow, $member;
282
283       # Generate a program to test for the availability of this member.
284       open (TESTFILE, ">$fnamebase.c");
285       print TESTFILE "$prepend";
286       print TESTFILE "#include <$h>\n";
287       print TESTFILE "$struct a;\n";
288       print TESTFILE "$struct b;\n";
289       print TESTFILE "extern void xyzzy (__typeof__ (&b.$member), __typeof__ (&a.$member), unsigned);\n";
290       print TESTFILE "void foobarbaz (void) {\n";
291       print TESTFILE "  xyzzy (&a.$member, &b.$member, sizeof (a.$member));\n";
292       print TESTFILE "}\n";
293       close (TESTFILE);
294
295       $res = compiletest ($fnamebase, "Testing for member $member",
296                           "Member \"$member\" not available.", $res);
297
298
299       # Test the types of the members.
300       open (TESTFILE, ">$fnamebase.c");
301       print TESTFILE "$prepend";
302       print TESTFILE "#include <$h>\n";
303       print TESTFILE "$struct a;\n";
304       print TESTFILE "extern $type b$rest;\n";
305       print TESTFILE "extern __typeof__ (a.$member) b;\n";
306       close (TESTFILE);
307
308       compiletest ($fnamebase, "Testing for type of member $member",
309                    "Member \"$member\" does not have the correct type.", $res);
310     } elsif (/^constant *([a-zA-Z0-9_]*) *([A-Za-z0-9_]*)?/) {
311       my($const) = $1;
312       my($value) = $2;
313       my($res) = $missing;
314
315       # Remember that this name is allowed.
316       push @allow, $const;
317
318       # Generate a program to test for the availability of this constant.
319       open (TESTFILE, ">$fnamebase.c");
320       print TESTFILE "$prepend";
321       print TESTFILE "#include <$h>\n";
322       print TESTFILE "__typeof__ ($const) a = $const;\n";
323       close (TESTFILE);
324
325       $res = compiletest ($fnamebase, "Testing for constant $const",
326                           "Constant \"$const\" not available.", $res);
327
328       if ($value ne "") {
329         # Generate a program to test for the value of this constant.
330         open (TESTFILE, ">$fnamebase.c");
331         print TESTFILE "$prepend";
332         print TESTFILE "#include <$h>\n";
333         print TESTFILE "int main (void) { return $const != $value; }\n";
334         close (TESTFILE);
335
336         $res = runtest ($fnamebase, "Testing for value of constant $const",
337                         "Constant \"$const\" has not the right value.", $res);
338       }
339     } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
340       my($const) = $1;
341       my($type) = "$3$4";
342       my($value) = $5;
343       my($res) = $missing;
344
345       # Remember that this name is allowed.
346       push @allow, $const;
347
348       # Generate a program to test for the availability of this constant.
349       open (TESTFILE, ">$fnamebase.c");
350       print TESTFILE "$prepend";
351       print TESTFILE "#include <$h>\n";
352       print TESTFILE "__typeof__ ($const) a = $const;\n";
353       close (TESTFILE);
354
355       $res = compiletest ($fnamebase, "Testing for constant $const",
356                           "Constant \"$const\" not available.", $res);
357
358       # Test the types of the members.
359       open (TESTFILE, ">$fnamebase.c");
360       print TESTFILE "$prepend";
361       print TESTFILE "#include <$h>\n";
362       print TESTFILE "__typeof__ (($type) 0) a;\n";
363       print TESTFILE "extern __typeof__ ($const) a;\n";
364       close (TESTFILE);
365
366       compiletest ($fnamebase, "Testing for type of constant $const",
367                    "Constant \"$const\" does not have the correct type.",
368                    $res);
369
370       if ($value ne "") {
371         # Generate a program to test for the value of this constant.
372         open (TESTFILE, ">$fnamebase.c");
373         print TESTFILE "$prepend";
374         print TESTFILE "#include <$h>\n";
375         print TESTFILE "int main (void) { return $const != $value; }\n";
376         close (TESTFILE);
377
378         $res = runtest ($fnamebase, "Testing for value of constant $const",
379                         "Constant \"$const\" has not the right value.", $res);
380       }
381     } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) {
382       my($type) = "$2$3";
383
384       # Remember that this name is allowed.
385       if ($type =~ /^struct *(.*)/) {
386         push @allow, $1;
387       } elsif ($type =~ /^union *(.*)/) {
388         push @allow, $1;
389       } else {
390         push @allow, $type;
391       }
392
393       # Remember that this name is allowed.
394       push @allow, $type;
395
396       # Generate a program to test for the availability of this constant.
397       open (TESTFILE, ">$fnamebase.c");
398       print TESTFILE "$prepend";
399       print TESTFILE "#include <$h>\n";
400       print TESTFILE "$type *a;\n";
401       close (TESTFILE);
402
403       compiletest ($fnamebase, "Testing for type $type",
404                    "Type \"$type\" not available.", $missing);
405     } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
406       my($rettype) = "$2$3";
407       my($fname) = "$4";
408       my($args) = "$5";
409       my($res) = $missing;
410
411       # Remember that this name is allowed.
412       push @allow, $fname;
413
414       # Generate a program to test for availability of this function.
415       open (TESTFILE, ">$fnamebase.c");
416       print TESTFILE "$prepend";
417       print TESTFILE "#include <$h>\n";
418       # print TESTFILE "#undef $fname\n";
419       print TESTFILE "$rettype (*(*foobarbaz) $args = $fname;\n";
420       close (TESTFILE);
421
422       $res = compiletest ($fnamebase, "Test availability of function $fname",
423                           "Function \"$fname\" is not available.", $res);
424
425       # Generate a program to test for the type of this function.
426       open (TESTFILE, ">$fnamebase.c");
427       print TESTFILE "$prepend";
428       print TESTFILE "#include <$h>\n";
429       # print TESTFILE "#undef $fname\n";
430       print TESTFILE "extern $rettype (*(*foobarbaz) $args;\n";
431       print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
432       close (TESTFILE);
433
434       compiletest ($fnamebase, "Test for type of function $fname",
435                    "Function \"$fname\" has incorrect type.", $res);
436     } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
437       my($rettype) = "$2$3";
438       my($fname) = "$4";
439       my($args) = "$5";
440       my($res) = $missing;
441
442       # Remember that this name is allowed.
443       push @allow, $fname;
444
445       # Generate a program to test for availability of this function.
446       open (TESTFILE, ">$fnamebase.c");
447       print TESTFILE "$prepend";
448       print TESTFILE "#include <$h>\n";
449       # print TESTFILE "#undef $fname\n";
450       print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n";
451       close (TESTFILE);
452
453       $res = compiletest ($fnamebase, "Test availability of function $fname",
454                           "Function \"$fname\" is not available.", $res);
455
456       # Generate a program to test for the type of this function.
457       open (TESTFILE, ">$fnamebase.c");
458       print TESTFILE "$prepend";
459       print TESTFILE "#include <$h>\n";
460       # print TESTFILE "#undef $fname\n";
461       print TESTFILE "extern $rettype (*foobarbaz) $args;\n";
462       print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
463       close (TESTFILE);
464
465       compiletest ($fnamebase, "Test for type of function $fname",
466                    "Function \"$fname\" has incorrect type.", $res);
467     } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
468       my($type) = "$2$3";
469       my($vname) = "$4";
470       my($res) = $missing;
471
472       # Remember that this name is allowed.
473       push @allow, $vname;
474
475       # Generate a program to test for availability of this function.
476       open (TESTFILE, ">$fnamebase.c");
477       print TESTFILE "$prepend";
478       print TESTFILE "#include <$h>\n";
479       # print TESTFILE "#undef $fname\n";
480       print TESTFILE "$type *foobarbaz = &$vname;\n";
481       close (TESTFILE);
482
483       $res = compiletest ($fnamebase, "Test availability of variable $vname",
484                           "Variable \"$vname\" is not available.", $res);
485
486       # Generate a program to test for the type of this function.
487       open (TESTFILE, ">$fnamebase.c");
488       print TESTFILE "$prepend";
489       print TESTFILE "#include <$h>\n";
490       # print TESTFILE "#undef $fname\n";
491       print TESTFILE "extern $type $vname;\n";
492       close (TESTFILE);
493
494       compiletest ($fnamebase, "Test for type of variable $fname",
495                    "Variable \"$vname\" has incorrect type.", $res);
496     } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
497       my($rettype) = "$2$3";
498       my($fname) = "$4";
499       my($args) = "$5";
500       my($res) = $missing;
501
502       # Remember that this name is allowed.
503       push @allow, $fname;
504
505       # Generate a program to test for availability of this function.
506       open (TESTFILE, ">$fnamebase.c");
507       print TESTFILE "$prepend";
508       print TESTFILE "#include <$h>\n";
509       print TESTFILE "#ifndef $fname\n";
510       print TESTFILE "$rettype (*foobarbaz) $args = $fname;\n";
511       print TESTFILE "#endif\n";
512       close (TESTFILE);
513
514       $res = compiletest ($fnamebase, "Test availability of function $fname",
515                           "Function \"$fname\" is not available.", $res);
516
517       # Generate a program to test for the type of this function.
518       open (TESTFILE, ">$fnamebase.c");
519       print TESTFILE "$prepend";
520       print TESTFILE "#include <$h>\n";
521       print TESTFILE "#ifndef $fname\n";
522       print TESTFILE "extern $rettype (*foobarbaz) $args;\n";
523       print TESTFILE "extern __typeof__ (&$fname) foobarbaz;\n";
524       print TESTFILE "#endif\n";
525       close (TESTFILE);
526
527       compiletest ($fnamebase, "Test for type of function $fname",
528                    "Function \"$fname\" has incorrect type.", $res);
529     } elsif (/^macro *([^       ]*)/) {
530       my($macro) = "$1";
531
532       # Remember that this name is allowed.
533       push @allow, $macro;
534
535       # Generate a program to test for availability of this macro.
536       open (TESTFILE, ">$fnamebase.c");
537       print TESTFILE "$prepend";
538       print TESTFILE "#include <$h>\n";
539       print TESTFILE "#ifndef $macro\n";
540       print TESTFILE "# error \"Macro $macro not defined\"\n";
541       print TESTFILE "#endif\n";
542       close (TESTFILE);
543
544       compiletest ($fnamebase, "Test availability of macro $macro",
545                    "Macro \"$macro\" is not available.", $missing);
546     } elsif (/^allow *(.*)/) {
547       my($pattern) = $1;
548       push @allow, $pattern;
549       next control;
550     } elsif (/^allow-header *(.*)/) {
551       my($pattern) = $1;
552       push @allowheader, $pattern;
553       next control;
554     } else {
555       # printf ("line is `%s'\n", $_);
556       next control;
557     }
558
559     printf ("\n");
560   }
561   close (CONTROL);
562
563   # Read the data files for the header files which are allowed to be included.
564   while ($#allowheader >= 0) {
565     my($ah) = pop @allowheader;
566
567     open (ALLOW, "$CC -E -D$dialect - < data/$ah-data |");
568     acontrol: while (<ALLOW>) {
569       next acontrol if (/^#/);
570       next acontrol if (/^[     ]*$/);
571
572       if (/^element *({([^}]*)}|([^ ]*)) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
573         push @allow, $7;
574       } elsif (/^constant *([a-zA-Z0-9_]*) *([A-Za-z0-9_]*)?/) {
575         push @allow, $1;
576       } elsif (/^typed-constant *([a-zA-Z0-9_]*) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*)?/) {
577         push @allow, 1;
578       } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) {
579         my($type) = "$2$3";
580
581         # Remember that this name is allowed.
582         if ($type =~ /^struct *(.*)/) {
583           push @allow, $1;
584         } elsif ($type =~ /^union *(.*)/) {
585           push @allow, $1;
586         } else {
587           push @allow, $type;
588         }
589       } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
590         push @allow, $4;
591       } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
592         push @allow, $4;
593       } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
594         push @allow, $4;
595       } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
596         push @allow, $4;
597       } elsif (/^macro *([^     ]*)/) {
598         push @allow, $1;
599       } elsif (/^allow *(.*)/) {
600         push @allow, $1;
601       } elsif (/^allow-header *(.*)/) {
602         push @allowheader, $1;
603       }
604     }
605     close (ALLOW);
606   }
607
608   # Now check the namespace.
609   printf ("  Checking the namespace of \"%s\"... ", $h);
610   if ($missing) {
611     ++$skipped;
612     printf ("SKIP\n");
613   } else {
614     checknamespace ($h, $fnamebase, @allow);
615   }
616
617   printf ("\n\n");
618 }
619
620 printf "-" x 76 . "\n";
621 printf ("  Total number of tests  : %4d\n", $total);
622 printf ("  Number of failed tests : %4d (%3d%%)\n", $errors, ($errors * 100) / $total);
623 printf ("  Number of skipped tests: %4d (%3d%%)\n", $skipped, ($skipped * 100) / $total);
624
625 exit $errors != 0;