Added ability to turn on/off debug channels.
[wine.git] / tools / winapi / make_parser.pm
blob527ee66af7d3d49ebcd494238276b00dd07ff8ed
2 # Copyright 1999, 2000, 2001 Patrik Stridvall
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 package make_parser;
21 use strict;
23 use strict;
25 use setup qw($current_dir $wine_dir $winapi_dir $winapi_check_dir);
27 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
28 require Exporter;
30 @ISA = qw(Exporter);
31 @EXPORT = qw();
32 @EXPORT_OK = qw($directory $tool $file $line $message);
34 use vars qw($directory $tool $file $line $message);
36 use output qw($output);
37 use options qw($options);
39 ########################################################################
40 # global
41 ########################################################################
43 my $current;
44 my $function;
46 ########################################################################
47 # error
48 ########################################################################
50 sub error {
51 my $where = shift;
53 if(!defined($where)) {
54 $where = "";
57 my $context;
58 if($tool) {
59 $context = "$tool";
60 if($where) {
61 $context .= "<$where>";
63 } else {
64 if($where) {
65 $context = "<$where>";
66 } else {
67 $context = "<>";
71 if(defined($tool)) {
72 $output->write("$directory: $context: can't parse output: '$current'\n");
73 } else {
74 $output->write("$directory: $context: can't parse output: '$current'\n");
76 exit 1;
79 ########################################################################
80 # line
81 ########################################################################
83 sub line {
84 local $_ = shift;
86 $file = "";
87 $line = "";
88 $message = "";
90 $current = $_;
92 my ($new_tool, $read_files, $write_files, $remove_files) = command($_);
93 if(defined($new_tool)) {
94 $tool = $new_tool;
96 $function = "";
98 my $progress = "";
99 if($directory && $directory ne ".") {
100 $progress .= "$directory: ";
102 if($tool) {
103 $progress .= "$tool: ";
106 if($tool =~ /^cd|make$/) {
107 # Nothing
108 } elsif($tool =~ /^ld$/) {
109 foreach my $file (@{$read_files}) {
110 $output->lazy_progress("${progress}reading '$file'");
112 my $file = $$write_files[0];
113 $output->progress("$progress: writing '$file'");
114 } elsif($tool =~ /^rm$/) {
115 foreach my $file (@{$remove_files}) {
116 $output->lazy_progress("${progress}removing '$file'");
118 } else {
119 if($#$read_files >= 0) {
120 $progress .= "read[" . join(" ", @{$read_files}) . "]";
122 if($#$write_files >= 0) {
123 if($#$read_files >= 0) {
124 $progress .= ", ";
126 $progress .= "write[" . join(" ", @{$write_files}) . "]";
128 if($#$remove_files >= 0) {
129 if($#$read_files >= 0 || $#$write_files >= 0) {
130 $progress .= ", ";
132 $progress .= "remove[" . join(" ", @{$remove_files}) . "]";
135 $output->progress($progress);
138 return 0;
141 my $make = $options->make;
143 if(/^Wine build complete\.$/) {
144 # Nothing
145 } elsif(/^(.*?) is newer than (.*?), please rerun (.*?)\!$/) {
146 $message = "$_";
147 } elsif(/^(.*?) is older than (.*?), please rerun (.*?)$/) {
148 $message = "$_";
149 } elsif(/^\`(.*?)\' is up to date.$/) {
150 $tool = "make";
151 make_output($1, $_);
152 } elsif(s/^$make(?:\[(\d+)\])?:\s*//) {
153 $tool = "make";
154 make_output($1, $_);
155 } elsif(!defined($tool)) {
156 error("line");
157 } elsif($tool eq "make") {
158 make_output($1, $_);
159 } elsif($tool eq "bison" && /^conflicts:\s+\d+\s+shift\/reduce$/) {
160 # Nothing
161 } elsif($tool eq "gcc" && /^(?:In file included |\s*)from (.+?):(\d+)[,:]$/) {
162 # Nothing
163 } elsif($tool =~ /^gcc|ld$/ && s/^(.+?\.s?o)(?:\(.*?\))?:\s*//) {
164 $tool = "ld";
165 ld_output($1, $_)
166 } elsif($tool =~ /^gcc|ld$/ && s/^(.*?)ld:\s*//) {
167 $tool = "ld";
168 ld_output("", $_)
169 } elsif($tool =~ /^gcc|ld$/ && s/^collect2:\s*//) {
170 $tool = "ld";
171 ld_output("collect2", $_);
172 } elsif($tool eq "gcc" && s/^(.+?\.[chly]):\s*//) {
173 gcc_output($1, $_);
174 } elsif($tool eq "ld" && s/^(.+?\.c):(?:\d+:)?\s*//) {
175 ld_output($1, $_);
176 } elsif($tool eq "winebuild" && s/^(.+?\.spec):\s*//) {
177 winebuild_output($1, $_);
178 } elsif($tool eq "wmc" && s/^(.+?\.mc):\s*//) {
179 wmc_output($1, $_);
180 } elsif($tool eq "wrc" && s/^(.+?\.rc):\s*//) {
181 wrc_output($1, $_);
182 } elsif($tool eq "cd" && s/^\/bin\/sh:\s*cd:\s*//) {
183 parse_cd_output($_);
184 } elsif(/^\s*$/) {
185 # Nothing
186 } else {
187 error("line");
190 $file =~ s/^\.\///;
192 return 1;
195 ########################################################################
196 # make_output
197 ########################################################################
199 sub make_output {
200 my $level = shift;
201 local $_ = shift;
203 $file = "";
204 $message = "";
206 if(0) {
207 # Nothing
208 } elsif(/^\*\*\* \[(.*?)\] Error (\d+)$/) {
209 # Nothing
210 } elsif(/^\*\*\* Error code (\d+)$/) {
211 # Nothing
212 } elsif(/^\*\*\* Warning:\s+/) { #
213 if(/^File \`(.+?)\' has modification time in the future \((.+?) > \(.+?\)\)$/) {
214 # Nothing
215 } else {
216 error("make_output");
218 } elsif(/^\`(.*?)\' is up to date.$/) {
219 # Nothing
220 } elsif(/^\[(.*?)\] Error (\d+) \(ignored\)$/) {
221 # Nothing
222 } elsif(/^don\'t know how to make (.*?)\. Stop$/) {
223 $message = "$_";
224 } elsif(/^(Entering|Leaving) directory \`(.*?)\'$/) {
225 if($1 eq "Entering") {
226 $directory = $2;
227 } else {
228 $directory = "";
231 my @components;
232 foreach my $component (split(/\//, $directory)) {
233 if($component eq "wine") {
234 @components = ();
235 } else {
236 push @components, $component;
239 $directory = join("/", @components);
240 } elsif(/^(.*?) is older than (.*?), please rerun (.*?)\$/) {
241 # Nothing
242 } elsif(/^Nothing to be done for \`(.*?)\'\.$/) {
243 # Nothing
244 } elsif(s/^warning:\s+//) {
245 if(/^Clock skew detected. Your build may be incomplete.$/) {
246 # Nothing
247 } else {
248 error("make_output");
250 } elsif(/^Stop in (.*?)\.$/) {
251 # Nothing
252 } elsif(/^\s*$/) {
253 # Nothing
254 } else {
255 error("make_output");
260 ########################################################################
261 # command
262 ########################################################################
264 sub command {
265 local $_ = shift;
267 my $tool;
268 my $file;
269 my $read_files = ["<???>"];
270 my $write_files = ["<???>"];
271 my $remove_files = [];
273 s/^\s*(.*?)\s*$/$1/;
275 if(s/^\[\s+-d\s+(.*?)\s+\]\s+\|\|\s+//) {
276 # Nothing
279 if(s/^ar\s+//) {
280 $tool = "ar";
281 ($read_files, $write_files) = ar_command($_);
282 } elsif(s/^as\s+//) {
283 $tool = "as";
284 ($read_files, $write_files) = as_command($_);
285 } elsif(s/^bison\s+//) {
286 $tool = "bison";
287 ($read_files, $write_files) = bison_command($_);
288 } elsif(s/^cd\s+//) {
289 $tool = "cd";
290 ($read_files, $write_files) = cd_command($_);
291 } elsif(s/^flex\s+//) {
292 $tool = "flex";
293 ($read_files, $write_files) = flex_command($_);
294 } elsif(s/^for\s+//) {
295 $tool = "for";
296 ($read_files, $write_files) = for_command($_);
297 } elsif(s/^\/usr\/bin\/install\s+//) {
298 $tool = "install";
299 ($read_files, $write_files) = install_command($_);
300 } elsif(s/^ld\s+//) {
301 $tool = "ld";
302 ($read_files, $write_files) = ld_command($_);
303 } elsif(s/^\/sbin\/ldconfig\s+//) {
304 $tool = "ldconfig";
305 ($read_files, $write_files) = ldconfig_command();
306 } elsif(s/^gcc\s+//) {
307 $tool = "gcc";
308 ($read_files, $write_files) = gcc_command($_);
309 } elsif(s/^(?:(?:\.\.\/)+|\.\/)tools\/makedep\s+//) {
310 $tool = "makedep";
311 ($read_files, $write_files) = makedep_command($_);
312 } elsif(s/^mkdir\s+//) {
313 $tool = "mkdir";
314 ($read_files, $write_files) = mkdir_command($_);
315 } elsif(s/^ranlib\s+//) {
316 $tool = "ranlib";
317 ($read_files, $write_files) = ranlib_command($_);
318 } elsif(s/^rm\s+//) {
319 $tool = "rm";
320 ($read_files, $write_files, $remove_files) = rm_command($_);
321 } elsif(s/^sed\s+//) {
322 $tool = "sed";
323 ($read_files, $write_files) = sed_command($_);
324 } elsif(s/^strip\s+//) {
325 $tool = "sed";
326 ($read_files, $write_files) = strip_command($_);
327 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/winebuild\/winebuild\s+//) {
328 $tool = "winebuild";
329 ($read_files, $write_files) = winebuild_command($_);
330 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wmc\/wmc\s+//) {
331 $tool = "wmc";
332 ($read_files, $write_files) = wmc_command($_);
333 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wrc\/wrc\s+//) {
334 $tool = "wrc";
335 ($read_files, $write_files) = wrc_command($_);
338 return ($tool, $read_files, $write_files, $remove_files);
341 ########################################################################
342 # ar_command
343 ########################################################################
345 sub ar_command {
346 local $_ = shift;
348 my $read_files;
349 my $write_files;
351 if(/rc\s+(\S+)(\s+\S+)+$/) {
352 $write_files = [$1];
353 $read_files = $2;
354 $read_files =~ s/^\s*//;
355 $read_files = [split(/\s+/, $read_files)];
356 } else {
357 error("ar_command");
360 return ($read_files, $write_files);
363 ########################################################################
364 # as_command
365 ########################################################################
367 sub as_command {
368 local $_ = shift;
370 my $read_files;
371 my $write_files;
373 if(/-o\s+(\S+)\s+(\S+)$/) {
374 $write_files = [$1];
375 $read_files = [$2];
376 } else {
377 error("as_command");
380 return ($read_files, $write_files);
383 ########################################################################
384 # bision_command
385 ########################################################################
387 sub bison_command {
388 local $_ = shift;
390 return ([], []);
393 ########################################################################
394 # cd_command
395 ########################################################################
397 sub cd_command {
398 local $_ = shift;
400 return ([], []);
403 ########################################################################
404 # cd_output
405 ########################################################################
407 sub cd_output {
408 local $_ = shift;
410 if(/^(.*?): No such file or directory/) {
411 $message = "directory '$1' doesn't exist";
415 ########################################################################
416 # flex_command
417 ########################################################################
419 sub flex_command {
420 local $_ = shift;
422 return ([], []);
425 ########################################################################
426 # for_command
427 ########################################################################
429 sub for_command {
430 local $_ = shift;
432 return ([], []);
435 ########################################################################
436 # gcc_command
437 ########################################################################
439 sub gcc_command {
440 my $read_files;
441 my $write_files;
443 if(/-o\s+(\S+)\s+(\S+)$/) {
444 my $write_file = $1;
445 my $read_file = $2;
447 $write_file =~ s%^\./%%;
448 $read_file =~ s%^\./%%;
450 $write_files = [$write_file];
451 $read_files = [$read_file];
452 } elsif(/-o\s+(\S+)/) {
453 my $write_file = $1;
455 $write_file =~ s%^\./%%;
457 $write_files = [$write_file];
458 $read_files = ["<???>"];
459 } elsif(/^-shared.*?-o\s+(\S+)/) {
460 my $write_file = $1;
462 $write_file =~ s%^\./%%;
464 $write_files = [$write_file];
465 $read_files = ["<???>"];
466 } else {
467 error("gcc_command");
470 return ($read_files, $write_files);
473 ########################################################################
474 # gcc_output
475 ########################################################################
477 sub gcc_output {
478 $file = shift;
479 local $_ = shift;
481 if(s/^(\d+):\s+//) {
482 $line = $1;
483 if(s/^warning:\s+//) {
484 my $supress = 0;
486 if(0) {
487 # Nothing
488 } elsif(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) {
489 my $type = $2;
490 if($type =~ /^(?:
491 HACCEL|HACMDRIVER|HANDLE|HBITMAP|HBRUSH|HCALL|HCURSOR|HDC|HDRVR|HDESK|HDRAWDIB
492 HGDIOBJ|HKL|HGLOBAL|HIMC|HINSTANCE|HKEY|HLOCAL|
493 HMENU|HMIDISTRM|HMIDIIN|HMIDIOUT|HMIXER|HMIXEROBJ|HMMIO|HMODULE|
494 HLINE|HPEN|HPHONE|HPHONEAPP|
495 HRASCONN|HRGN|HRSRC|HWAVEIN|HWAVEOUT|HWINSTA|HWND|
496 SC_HANDLE|WSAEVENT|handle_t|pointer)$/x)
498 $supress = 1;
499 } else {
500 $supress = 0;
502 } elsif(/^\(near initialization for \`(.*?)\'\)$/) {
503 $supress = 0;
504 } elsif(/^\`(.*?)\' defined but not used$/) {
505 $supress = 0;
506 } elsif(/^\`(.*?)\' is not at beginning of declaration$/) {
507 $supress = 0;
508 } elsif(/^\`%x\' yields only last 2 digits of year in some locales$/) {
509 $supress = 1;
510 } elsif(/^assignment makes integer from pointer without a cast$/) {
511 $supress = 0;
512 } elsif(/^assignment makes pointer from integer without a cast$/) {
513 $supress = 0;
514 } elsif(/^assignment from incompatible pointer type$/) {
515 $supress = 0;
516 } elsif(/^cast from pointer to integer of different size$/) {
517 $supress = 0;
518 } elsif(/^comparison between pointer and integer$/) {
519 $supress = 0;
520 } elsif(/^comparison between signed and unsigned$/) {
521 $supress = 0;
522 } elsif(/^comparison of unsigned expression < 0 is always false$/) {
523 $supress = 0;
524 } elsif(/^comparison of unsigned expression >= 0 is always true$/) {
525 $supress = 0;
526 } elsif(/^conflicting types for built-in function \`(.*?)\'$/) {
527 $supress = 0;
528 } elsif(/^empty body in an if-statement$/) {
529 $supress = 0;
530 } elsif(/^empty body in an else-statement$/) {
531 $supress = 0;
532 } elsif(/^implicit declaration of function \`(.*?)\'$/) {
533 $supress = 0;
534 } elsif(/^initialization from incompatible pointer type$/) {
535 $supress = 0;
536 } elsif(/^initialization makes pointer from integer without a cast$/) {
537 $supress = 0;
538 } elsif(/^missing initializer$/) {
539 $supress = 0;
540 } elsif(/^ordered comparison of pointer with integer zero$/) {
541 $supress = 0;
542 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') from incompatible pointer type$/) {
543 my $arg = $1;
544 my $name = $2;
545 if(defined($name) && $name =~ /^GDI_AllocObject$/) {
546 $supress = 1;
547 } else {
548 $supress = 0;
550 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes integer from pointer without a cast$/) {
551 $supress = 0;
552 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes pointer from integer without a cast$/) {
553 $supress = 0;
554 } elsif(/^return makes integer from pointer without a cast$/) {
555 $supress = 0;
556 } elsif(/^return makes pointer from integer without a cast$/) {
557 $supress = 0;
558 } elsif(/^type of \`(.*?)\' defaults to \`(.*?)\'$/) {
559 $supress = 0;
560 } elsif(/^unused variable \`(.*?)\'$/) {
561 $supress = 0;
562 } elsif(!$options->pedantic) {
563 $supress = 0;
564 } else {
565 error("gcc_output");
568 if(!$supress) {
569 if($function) {
570 $message = "function $function: warning: $_";
571 } else {
572 $message = "warning: $_";
574 } else {
575 $message = "";
577 } elsif(/^\`(.*?)\' undeclared \(first use in this function\)$/) {
578 $message = "$_";
579 } elsif(/^\(Each undeclared identifier is reported only once$/) {
580 $message = "$_";
581 } elsif(/^conflicting types for \`(.*?)\'$/) {
582 $message = "$_";
583 } elsif(/^for each function it appears in.\)$/) {
584 $message = "$_";
585 } elsif(/^too many arguments to function$/) {
586 $message = "$_";
587 } elsif(/^previous declaration of \`(.*?)\'$/) {
588 $message = "$_";
589 } elsif(/^parse error before `(.*?)'$/) {
590 $message = "$_";
591 } elsif(!$options->pedantic) {
592 $message = "$_";
593 } else {
594 error("gcc_output");
596 } elsif(/^In function \`(.*?)\':$/) {
597 $function = $1;
598 } elsif(/^At top level:$/) {
599 $function = "";
600 } else {
601 error("gcc_output");
605 ########################################################################
606 # install_command
607 ########################################################################
609 sub install_command {
610 local $_ = shift;
612 return ([], []);
615 ########################################################################
616 # ld_command
617 ########################################################################
619 sub ld_command {
620 local $_ = shift;
622 my $read_files;
623 my $write_files;
625 if(/-r\s+(.*?)\s+-o\s+(\S+)$/) {
626 $write_files = [$2];
627 $read_files = [split(/\s+/, $1)];
628 } else {
629 error("ld_command");
632 return ($read_files, $write_files);
635 ########################################################################
636 # ld_output
637 ########################################################################
639 sub ld_output {
640 $file = shift;
641 local $_ = shift;
643 if(0) {
644 # Nothing
645 } elsif(/^In function \`(.*?)\':$/) {
646 $function = $1;
647 } elsif(/^more undefined references to \`(.*?)\' follow$/) {
648 # Nothing
649 } elsif(/^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
650 # Nothing
651 } elsif(/^undefined reference to \`(.*?)\'$/) {
652 # Nothing
653 } elsif(/^warning: (.*?)\(\) possibly used unsafely; consider using (.*?)\(\)$/) {
654 # Nothing
655 } elsif(/^warning: type and size of dynamic symbol \`(.*?)\' are not defined$/) {
656 $message = "$_";
657 } else {
658 $message = "$_";
662 ########################################################################
663 # ldconfig_command
664 ########################################################################
666 sub ldconfig_command {
667 local $_ = shift;
669 return ([], []);
672 ########################################################################
673 # makedep_command
674 ########################################################################
676 sub makedep_command {
677 local $_ = shift;
679 return ([], []);
682 ########################################################################
683 # mkdir_command
684 ########################################################################
686 sub mkdir_command {
687 local $_ = shift;
689 return ([], []);
692 ########################################################################
693 # ranlib_command
694 ########################################################################
696 sub ranlib_command {
697 local $_ = shift;
699 my $read_files;
700 my $write_files;
702 $read_files = [split(/\s+/)];
703 $write_files = [];
705 return ($read_files, $write_files);
708 ########################################################################
709 # rm_command
710 ########################################################################
712 sub rm_command {
713 local $_ = shift;
714 s/^-f\s*//;
715 return ([], [], [split(/\s+/, $_)]);
718 ########################################################################
719 # sed_command
720 ########################################################################
722 sub sed_command {
723 local $_ = shift;
725 return ([], []);
728 ########################################################################
729 # strip_command
730 ########################################################################
732 sub strip_command {
733 local $_ = shift;
735 return ([], []);
738 ########################################################################
739 # winebuild_command
740 ########################################################################
742 sub winebuild_command {
743 local $_ = shift;
745 return ([], []);
748 ########################################################################
749 # winebuild_output
750 ########################################################################
752 sub winebuild_output {
753 $file = shift;
754 local $_ = shift;
756 $message = $_;
759 ########################################################################
760 # wmc_command
761 ########################################################################
763 sub wmc_command {
764 local $_ = shift;
766 my $read_files;
767 my $write_files;
769 if(/\s+(\S+)$/) {
770 my $mc_file = $1;
772 my $rc_file = $mc_file;
773 $rc_file =~ s/\.mc$/.rc/;
775 $write_files = [$rc_file];
776 $read_files = [$mc_file];
777 } else {
778 error("wmc_command");
781 return ($read_files, $write_files);
784 ########################################################################
785 # wmc_output
786 ########################################################################
788 sub wmc_output {
789 $file = shift;
790 local $_ = shift;
793 ########################################################################
794 # wrc_command
795 ########################################################################
797 sub wrc_command {
798 local $_ = shift;
800 my $read_files;
801 my $write_files;
803 if(/\s+(\S+)$/) {
804 my $rc_file = $1;
806 my $o_file = $rc_file;
807 $o_file =~ s/\.rc$/.o/;
809 $write_files = [$o_file];
810 $read_files = [$rc_file];
811 } else {
812 error("wrc_command");
815 return ($read_files, $write_files);
818 ########################################################################
819 # wrc_output
820 ########################################################################
822 sub wrc_output {
823 $file = shift;
824 local $_ = shift;