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