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