A few bug fixes.
[wine] / tools / winapi / make_parser.pm
1 package make_parser;
2
3 use strict;
4
5 use strict;
6
7 use setup qw($current_dir $wine_dir $winapi_dir $winapi_check_dir);
8
9 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
10 require Exporter;
11
12 @ISA = qw(Exporter);
13 @EXPORT = qw();
14 @EXPORT_OK = qw($directory $tool $file $line $message);
15
16 use vars qw($directory $tool $file $line $message);
17
18 use output qw($output);
19 use options qw($options);
20
21 ########################################################################
22 # global
23 ########################################################################
24
25 my $current; 
26 my $function;
27
28 ########################################################################
29 # error
30 ########################################################################
31
32 sub error {
33     if(defined($tool)) {
34         $output->write("make_filter: $tool: can't parse output: '$current'\n");
35     } else {
36         $output->write("make_filter: <>: can't parse output: '$current'\n");
37     }
38     exit 1;
39 }
40
41 ########################################################################
42 # line
43 ########################################################################
44
45 sub line {
46     local $_ = shift;
47
48     $file = "";
49     $line = "";
50     $message = "";
51
52     $current = $_;
53
54     my ($new_tool, $read_files, $write_files, $remove_files) = command($_);
55     if(defined($new_tool)) {
56         $tool = $new_tool;
57
58         $function = "";
59
60         if($tool =~ /^cd|make$/) {
61             # Nothing
62         } elsif($tool =~ /^ld$/) {
63             foreach my $file (@{$read_files}) {
64                 $output->lazy_progress("$directory: ld: reading '$file'");
65             }
66             my $file = $$write_files[0];
67             $output->progress("$directory: ld: writing '$file'");
68         } elsif($tool =~ /^rm$/) {
69             foreach my $file (@{$remove_files}) {
70                 $output->lazy_progress("$directory: rm: removing '$file'");
71             }
72         } else {
73             my $progress = "$directory: $tool: ";
74             if($#$read_files >= 0) {
75                 $progress .= "read[" . join(" ", @{$read_files}) . "]";
76             }
77             if($#$write_files >= 0) {
78                 if($#$read_files >= 0) {
79                     $progress .= ", ";
80                 }              
81                 $progress .= "write[" . join(" ", @{$write_files}) . "]";
82             }
83             if($#$remove_files >= 0) {
84                 if($#$read_files >= 0 || $#$write_files >= 0) {
85                     $progress .= ", ";
86                 }              
87                 $progress .= "remove[" . join(" ", @{$remove_files}) . "]";
88             }
89             
90             $output->progress($progress);
91         }
92         return 0;
93     }
94
95     if(/^Wine build complete\.$/) {
96         # Nothing
97     } elsif(/^(.*?) is newer than (.*?), please rerun (.*?)\!$/) {
98         $message = "$_";
99     } elsif(/^(.*?) is older than (.*?), please rerun (.*?)$/) {
100         $message = "$_";
101     } elsif(s/^make(?:\[(\d+)\])?:\s*//) {
102         $tool = "make";
103         make_output($1, $_);
104     } elsif(!defined($tool)) {
105         error();
106     } elsif($tool eq "bison" && /^conflicts:\s+\d+\s+shift\/reduce$/) {
107         # Nothing
108     } elsif($tool eq "gcc" && /^In file included from (.+?):(\d+):$/) {
109         # Nothing
110     } elsif($tool =~ /^gcc|ld$/ && s/^(.+?\.o(?:\(.*?\))?):\s*//) {
111         ld_output($1, $_)
112     } elsif($tool eq "gcc" && s/^(.+?\.[chly]):\s*//) {
113         gcc_output($1, $_);
114     } elsif($tool eq "winebuild" && s/^(.+?\.spec):\s*//) {
115         winebuild_output($1, $_);
116     } elsif($tool eq "wmc" && s/^(.+?\.mc):\s*//) {
117         wmc_output($1, $_);
118     } elsif($tool eq "wrc" && s/^(.+?\.rc):\s*//) {
119         wrc_output($1, $_);
120     } elsif($tool eq "cd" && s/^\/bin\/sh:\s*cd:\s*//) {
121         parse_cd_output($_);
122     } else {
123         error();
124     }
125     
126     $file =~ s/^\.\///;
127
128     return 1;
129 }
130
131 ########################################################################
132 # make_output
133 ########################################################################
134
135 sub make_output {
136     my $level = shift;
137     local $_ = shift;
138
139     $file = "";
140     $message = "";
141
142     if(0) {
143         # Nothing
144     } elsif(/^\*\*\* \[(.*?)\] Error (\d+)$/) {
145         $message = "$_";
146     } elsif(/^\*\*\* Warning:\s+/) { # 
147         if(/^File \`(.+?)\' has modification time in the future \((.+?) > \(.+?\)\)$/) {
148             # Nothing
149         } else {
150             error();
151         }
152     } elsif(/^\`(.*?)\' is up to date.$/) {
153         # Nothing
154     } elsif(/^\[(.*?)\] Error (\d+) \(ignored\)$/) {
155         # Nothing
156     } elsif(/^(Entering|Leaving) directory \`(.*?)\'$/) {
157         if($1 eq "Entering") {
158             $directory = $2;
159         } else {
160             $directory = "";
161         }
162
163         my @components;
164         foreach my $component (split(/\//, $directory)) {
165             if($component eq "wine") {
166                 @components = ();
167             } else {
168                 push @components, $component;
169             }
170         }
171         $directory = join("/", @components);
172     } elsif(/^(.*?) is older than (.*?), please rerun (.*?)\$/) {
173         # Nothing
174     } elsif(/^Nothing to be done for \`(.*?)\'\.$/) {
175         # Nothing
176     } elsif(s/^warning:\s+//) {
177         if(/^Clock skew detected.  Your build may be incomplete.$/) {
178             # Nothing
179         } else {
180             error();
181         }
182     } else {
183         error();
184     }
185
186 }
187
188 ########################################################################
189 # command
190 ########################################################################
191
192 sub command {
193     local $_ = shift;
194
195     my $tool;
196     my $file;
197     my $read_files = ["<???>"];
198     my $write_files = ["<???>"];
199     my $remove_files = [];
200
201     s/^\s*(.*?)\s*$/$1/;
202
203     if(s/^\[\s+-d\s+(.*?)\s+\]\s+\|\|\s+//) {
204         # Nothing
205     }
206
207     if(s/^ar\s*//) {
208         $tool = "ar";
209         ($read_files, $write_files) = ar_command($_);
210     } elsif(s/^as\s*//) {
211         $tool = "as";
212         ($read_files, $write_files) = as_command($_);
213     } elsif(s/^bison\s*//) {
214         $tool = "bison";
215         ($read_files, $write_files) = bison_command($_);
216     } elsif(s/^cd\s*//) {
217         $tool = "cd";
218         ($read_files, $write_files) = cd_command($_);
219     } elsif(s/^flex\s*//) {
220         $tool = "flex";
221         ($read_files, $write_files) = flex_command($_);
222     } elsif(s/^for\s*//) {
223         $tool = "for";
224         ($read_files, $write_files) = for_command($_);
225     } elsif(s/^\/usr\/bin\/install\s*//) {
226         $tool = "install";
227         ($read_files, $write_files) = install_command($_);
228     } elsif(s/^ld\s*//) {
229         $tool = "ld";
230         ($read_files, $write_files) = ld_command($_);
231     } elsif(s/^\/sbin\/ldconfig\s*//) {
232         $tool = "ldconfig";
233         ($read_files, $write_files) = ldconfig_command();
234     } elsif(s/^gcc\s*//) {
235         $tool = "gcc";
236         ($read_files, $write_files) = gcc_command($_);
237     } elsif(s/^(?:(?:\.\.\/)+|\.\/)tools\/makedep\s*//) {
238         $tool = "makedep";
239         ($read_files, $write_files) = makedep_command($_);
240     } elsif(s/^mkdir\s*//) {
241         $tool = "mkdir";
242         ($read_files, $write_files) = mkdir_command($_);
243     } elsif(s/^ranlib\s*//) {
244         $tool = "ranlib";
245         ($read_files, $write_files) = ranlib_command($_);
246     } elsif(s/^rm\s*//) {
247         $tool = "rm";
248         ($read_files, $write_files, $remove_files) = rm_command($_);
249     } elsif(s/^sed\s*//) {
250         $tool = "sed";
251         ($read_files, $write_files) = sed_command($_);
252     } elsif(s/^strip\s*//) {
253         $tool = "sed";
254         ($read_files, $write_files) = strip_command($_);
255     } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/winebuild\/winebuild\s*//) {
256         $tool = "winebuild";
257         ($read_files, $write_files) = winebuild_command($_);
258     } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wmc\/wmc\s*//) {
259         $tool = "wmc";
260         ($read_files, $write_files) = wmc_command($_);
261     } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wrc\/wrc\s*//) {
262         $tool = "wrc";
263         ($read_files, $write_files) = wrc_command($_);
264     }
265
266     return ($tool, $read_files, $write_files, $remove_files);
267 }
268
269 ########################################################################
270 # ar_command
271 ########################################################################
272
273 sub ar_command {
274     local $_ = shift;
275
276     my $read_files;
277     my $write_files;
278
279     if(/rc\s+(\S+)(\s+\S+)+$/) {
280         $write_files = [$1];
281         $read_files = $2;
282         $read_files =~ s/^\s*//;
283         $read_files = [split(/\s+/, $read_files)];
284     } else {
285         error();
286     }
287
288     return ($read_files, $write_files);
289 }
290
291 ########################################################################
292 # as_command
293 ########################################################################
294
295 sub as_command {
296     local $_ = shift;
297
298     my $read_files;
299     my $write_files;
300
301     if(/-o\s+(\S+)\s+(\S+)$/) {
302         $write_files = [$1];
303         $read_files = [$2];
304     } else {
305         error();
306     }
307
308     return ($read_files, $write_files);
309 }
310
311 ########################################################################
312 # bision_command
313 ########################################################################
314
315 sub bison_command {
316     local $_ = shift;
317
318     return ([], []);
319 }
320
321 ########################################################################
322 # cd_command
323 ########################################################################
324
325 sub cd_command {
326     local $_ = shift;
327
328     return ([], []);
329 }
330
331 ########################################################################
332 # cd_output
333 ########################################################################
334
335 sub cd_output {
336     local $_ = shift;
337
338     if(/^(.*?): No such file or directory/) {
339         $message = "directory '$1' doesn't exist";
340     }
341 }
342
343 ########################################################################
344 # flex_command
345 ########################################################################
346
347 sub flex_command {
348     local $_ = shift;
349
350     return ([], []);
351 }
352
353 ########################################################################
354 # for_command
355 ########################################################################
356
357 sub for_command {
358     local $_ = shift;
359
360     return ([], []);
361 }
362
363 ########################################################################
364 # gcc_command
365 ########################################################################
366
367 sub gcc_command {
368     my $read_files;
369     my $write_files;
370
371     if(/-o\s+(\S+)\s+(\S+)$/) {
372         $write_files = [$1];
373         $read_files = [$2];
374     } elsif(/-o\s+(\S+)/) {
375         $write_files = [$1];
376         $read_files = ["<???>"];
377     } elsif(/^-shared.*?-o\s+(\S+)/) {
378         $write_files = [$1];
379         $read_files = ["<???>"];
380     } else {
381         error();
382     }
383
384     return ($read_files, $write_files);
385 }
386
387 ########################################################################
388 # gcc_output
389 ########################################################################
390
391 sub gcc_output {
392     $file = shift;
393     local $_ = shift;
394
395     if(s/^(\d+):\s+//) {
396         $line = $1;
397         if(s/^warning:\s+//) {
398             my $supress = 0;
399
400             if(0) {
401                 # Nothing
402             } elsif(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) {
403                 $supress = 0;
404             } elsif(/^\(near initialization for \`(.*?)\'\)$/) {
405                 $supress = 0;
406             } elsif(/^\`(.*?)\' defined but not used$/) {
407                 $supress = 0;
408             } elsif(/^\`(.*?)\' is not at beginning of declaration$/) {
409                 $supress = 0;
410             } elsif(/^\`%x\' yields only last 2 digits of year in some locales$/) {
411                 $supress = 1;
412             } elsif(/^assignment makes integer from pointer without a cast$/) {
413                 $supress = 0;
414             } elsif(/^assignment makes pointer from integer without a cast$/) {
415                 $supress = 0;
416             } elsif(/^assignment from incompatible pointer type$/) {
417                 $supress = 0;
418             } elsif(/^cast from pointer to integer of different size$/) {
419                 $supress = 0;
420             } elsif(/^comparison between pointer and integer$/) {
421                 $supress = 0;
422             } elsif(/^comparison between signed and unsigned$/) {
423                 $supress = 0;
424             } elsif(/^comparison of unsigned expression < 0 is always false$/) {
425                 $supress = 0;
426             } elsif(/^comparison of unsigned expression >= 0 is always true$/) {
427                 $supress = 0;
428             } elsif(/^conflicting types for built-in function \`(.*?)\'$/) {
429                 $supress = 0;
430             } elsif(/^empty body in an if-statement$/) {
431                 $supress = 0;
432             } elsif(/^empty body in an else-statement$/) {
433                 $supress = 0;
434             } elsif(/^implicit declaration of function \`(.*?)\'$/) {
435                 $supress = 0;
436             } elsif(/^initialization from incompatible pointer type$/) {
437                 $supress = 0;
438             } elsif(/^initialization makes pointer from integer without a cast$/) {
439                 $supress = 0;
440             } elsif(/^missing initializer$/) {
441                 $supress = 0;
442             } elsif(/^ordered comparison of pointer with integer zero$/) {
443                 $supress = 0;
444             } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') from incompatible pointer type$/) {
445                 $supress = 0;
446             } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes integer from pointer without a cast$/) {
447                 $supress = 0;
448             } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes pointer from integer without a cast$/) {
449                 $supress = 0;
450             } elsif(/^return makes integer from pointer without a cast$/) {
451                 $supress = 0;
452             } elsif(/^return makes pointer from integer without a cast$/) {
453                 $supress = 0;
454             } elsif(/^type of \`(.*?)\' defaults to \`(.*?)\'$/) {
455                 $supress = 0;
456             } elsif(/^unused variable \`(.*?)\'$/) {
457                 $supress = 0;
458             } elsif(!$options->pedantic) {
459                 $supress = 0;
460             } else {
461                 error();
462             }
463
464             if(!$supress) {
465                 if($function) {
466                     $message = "function $function: $_";
467                 } else {
468                     $message = "$_";
469                 }
470             } else {
471                 $message = "";
472             }
473         } elsif(/^\`(.*?)\' undeclared \(first use in this function\)$/) {
474             $message = "$_";
475         } elsif(/^\(Each undeclared identifier is reported only once$/) {
476             $message = "$_";
477         } elsif(/^conflicting types for \`(.*?)\'$/) {
478             $message = "$_";
479         } elsif(/^for each function it appears in.\)$/) {
480             $message = "$_";
481         } elsif(/^too many arguments to function$/) {
482             $message = "$_";
483         } elsif(/^previous declaration of \`(.*?)\'$/) {
484             $message = "$_";
485         } elsif(/^parse error before `(.*?)'$/) {
486             $message = "$_";
487         } elsif(!$options->pedantic) {
488             $message = "$_";
489         } else {
490             error();
491         }
492     } elsif(/^In function \`(.*?)\':$/) {
493         $function = $1;
494     } elsif(/^At top level:$/) {
495         $function = "";
496     } else {
497         error();
498     }
499 }
500
501 ########################################################################
502 # install_command
503 ########################################################################
504
505 sub install_command {
506     local $_ = shift;
507
508     return ([], []);
509 }
510
511 ########################################################################
512 # ld_command
513 ########################################################################
514
515 sub ld_command {
516     local $_ = shift;
517
518     my $read_files;
519     my $write_files;
520
521     if(/-r\s+(.*?)\s+-o\s+(\S+)$/) {
522         $write_files = [$2];
523         $read_files = [split(/\s+/, $1)];
524     } else {
525         error();
526     }
527
528     return ($read_files, $write_files);
529 }
530
531 ########################################################################
532 # ld_output
533 ########################################################################
534
535 sub ld_output {
536     $file = shift;
537     local $_ = shift;
538
539     if(/^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
540         # nothing
541     }
542 }
543
544 ########################################################################
545 # ldconfig_command
546 ########################################################################
547
548 sub ldconfig_command {
549     local $_ = shift;
550
551     return ([], []);
552 }
553
554 ########################################################################
555 # makedep_command
556 ########################################################################
557
558 sub makedep_command {
559     local $_ = shift;
560
561     return ([], []);
562 }
563
564 ########################################################################
565 # mkdir_command
566 ########################################################################
567
568 sub mkdir_command {
569     local $_ = shift;
570
571     return ([], []);
572 }
573
574 ########################################################################
575 # ranlib_command
576 ########################################################################
577
578 sub ranlib_command {
579     local $_ = shift;
580
581     my $read_files;
582     my $write_files;
583
584     $read_files = [split(/\s+/)];
585     $write_files = [];
586
587     return ($read_files, $write_files);
588 }
589
590 ########################################################################
591 # rm_command
592 ########################################################################
593
594 sub rm_command {
595     local $_ = shift;
596     s/^-f\s*//;
597     return ([], [], [split(/\s+/, $_)]);
598 }
599
600 ########################################################################
601 # sed_command
602 ########################################################################
603
604 sub sed_command {
605     local $_ = shift;
606
607     return ([], []);
608 }
609
610 ########################################################################
611 # strip_command
612 ########################################################################
613
614 sub strip_command {
615     local $_ = shift;
616
617     return ([], []);
618 }
619
620 ########################################################################
621 # winebuild_command
622 ########################################################################
623
624 sub winebuild_command {
625     local $_ = shift;
626
627     return ([], []);
628 }
629
630 ########################################################################
631 # winebuild_output
632 ########################################################################
633
634 sub winebuild_output {
635     $file = shift;
636     local $_ = shift;
637
638     $message = $_;
639 }
640
641 ########################################################################
642 # wmc_command
643 ########################################################################
644
645 sub wmc_command {
646     local $_ = shift;
647
648     my $read_files;
649     my $write_files;
650
651     if(/\s+(\S+)$/) {
652         my $mc_file = $1;
653
654         my $rc_file = $mc_file;
655         $rc_file =~ s/\.mc$/.rc/;
656
657         $write_files = [$rc_file];
658         $read_files = [$mc_file];
659     } else {
660         error();
661     }
662
663     return ($read_files, $write_files);
664 }
665
666 ########################################################################
667 # wmc_output
668 ########################################################################
669
670 sub wmc_output {
671     $file = shift;
672     local $_ = shift;
673 }
674
675 ########################################################################
676 # wrc_command
677 ########################################################################
678
679 sub wrc_command {
680     local $_ = shift;
681
682     my $read_files;
683     my $write_files;
684
685     if(/\s+(\S+)$/) {
686         my $rc_file = $1;
687
688         my $o_file = $rc_file;
689         $o_file =~ s/\.rc$/.o/;
690
691         $write_files = [$o_file];
692         $read_files = [$rc_file];
693     } else {
694         error();
695     }
696
697     return ($read_files, $write_files);
698 }
699
700 ########################################################################
701 # wrc_output
702 ########################################################################
703
704 sub wrc_output {
705     $file = shift;
706     local $_ = shift;
707 }
708
709 1;