wined3d: Color keying emulation.
[wine/multimedia.git] / tools / winapi / make_parser.pm
blob6f7e6a4d12ab3639653d2ff3a64fc95eae51f4f6
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 package make_parser;
21 use strict;
23 use setup qw($current_dir $wine_dir $winapi_dir);
25 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
26 require Exporter;
28 @ISA = qw(Exporter);
29 @EXPORT = qw();
30 @EXPORT_OK = qw($directory $tool $file $line $message);
32 use vars qw($directory $tool $file $line $message);
34 use output qw($output);
35 use options qw($options);
38 #sub command($);
39 #sub gcc_output($$);
40 #sub ld_output($$);
41 #sub make_output($$);
42 #sub winebuild_output($$);
43 #sub wmc_output($$);
44 #sub wrc_output($$);
47 ########################################################################
48 # global
49 ########################################################################
51 my $current;
52 my $function;
54 ########################################################################
55 # error
56 ########################################################################
58 sub error($) {
59 my $where = shift;
61 if(!defined($where)) {
62 $where = "";
65 my $context;
66 if($tool) {
67 $context = "$tool";
68 if($where) {
69 $context .= "<$where>";
71 } else {
72 if($where) {
73 $context = "<$where>";
74 } else {
75 $context = "<>";
79 if(defined($tool)) {
80 $output->write("$directory: $context: can't parse output: '$current'\n");
81 } else {
82 $output->write("$directory: $context: can't parse output: '$current'\n");
84 exit 1;
87 ########################################################################
88 # make_output
89 ########################################################################
91 sub make_output($$) {
92 my $level = shift;
93 local $_ = shift;
95 $file = "";
96 $message = "";
98 if(0) {
99 # Nothing
100 } elsif(/^\*\*\* \[(.*?)\] Error (\d+)$/) {
101 # Nothing
102 } elsif(/^\*\*\* Error code (\d+)$/) {
103 # Nothing
104 } elsif(/^\*\*\* Warning:\s+/) { #
105 if(/^File \`(.+?)\' has modification time in the future \((.+?) > \(.+?\)\)$/) {
106 # Nothing
107 } else {
108 error("make_output");
110 } elsif(/^\`(.*?)\' is up to date.$/) {
111 # Nothing
112 } elsif(/^\[(.*?)\] Error (\d+) \(ignored\)$/) {
113 # Nothing
114 } elsif(/^don\'t know how to make (.*?)\. Stop$/) {
115 $message = "$_";
116 } elsif(/^(Entering|Leaving) directory \`(.*?)\'$/) {
117 if($1 eq "Entering") {
118 $directory = $2;
119 } else {
120 $directory = "";
123 my @components;
124 foreach my $component (split(/\//, $directory)) {
125 if($component eq "wine") {
126 @components = ();
127 } else {
128 push @components, $component;
131 $directory = join("/", @components);
132 } elsif(/^(.*?) is older than (.*?), please rerun (.*?)\$/) {
133 # Nothing
134 } elsif(/^Nothing to be done for \`(.*?)\'\.$/) {
135 # Nothing
136 } elsif(s/^warning:\s+//) {
137 if(/^Clock skew detected. Your build may be incomplete.$/) {
138 # Nothing
139 } else {
140 error("make_output");
142 } elsif(/^Stop in (.*?)\.$/) {
143 # Nothing
144 } elsif(/^\s*$/) {
145 # Nothing
146 } else {
147 error("make_output");
152 ########################################################################
153 # ar_command
154 ########################################################################
156 sub ar_command($) {
157 local $_ = shift;
159 my $read_files;
160 my $write_files;
162 if(/rc\s+(\S+)(\s+\S+)+$/) {
163 $write_files = [$1];
164 $read_files = $2;
165 $read_files =~ s/^\s*//;
166 $read_files = [split(/\s+/, $read_files)];
167 } else {
168 error("ar_command");
171 return ($read_files, $write_files);
174 ########################################################################
175 # as_command
176 ########################################################################
178 sub as_command($) {
179 local $_ = shift;
181 my $read_files;
182 my $write_files;
184 if(/-o\s+(\S+)\s+(\S+)$/) {
185 $write_files = [$1];
186 $read_files = [$2];
187 } else {
188 error("as_command");
191 return ($read_files, $write_files);
194 ########################################################################
195 # bision_command
196 ########################################################################
198 sub bison_command($) {
199 local $_ = shift;
201 return ([], []);
204 ########################################################################
205 # cd_command
206 ########################################################################
208 sub cd_command($) {
209 local $_ = shift;
211 return ([], []);
214 ########################################################################
215 # cd_output
216 ########################################################################
218 sub cd_output($) {
219 local $_ = shift;
221 if(/^(.*?): No such file or directory/) {
222 $message = "directory '$1' doesn't exist";
226 ########################################################################
227 # flex_command
228 ########################################################################
230 sub flex_command($) {
231 local $_ = shift;
233 return ([], []);
236 ########################################################################
237 # for_command
238 ########################################################################
240 sub for_command($) {
241 local $_ = shift;
243 return ([], []);
246 ########################################################################
247 # gcc_command
248 ########################################################################
250 sub gcc_command($) {
251 my $read_files;
252 my $write_files;
254 if(/-o\s+(\S+)\s+(\S+)$/) {
255 my $write_file = $1;
256 my $read_file = $2;
258 $write_file =~ s%^\./%%;
259 $read_file =~ s%^\./%%;
261 $write_files = [$write_file];
262 $read_files = [$read_file];
263 } elsif(/-o\s+(\S+)/) {
264 my $write_file = $1;
266 $write_file =~ s%^\./%%;
268 $write_files = [$write_file];
269 $read_files = ["<???>"];
270 } elsif(/^-shared.*?-o\s+(\S+)/) {
271 my $write_file = $1;
273 $write_file =~ s%^\./%%;
275 $write_files = [$write_file];
276 $read_files = ["<???>"];
277 } else {
278 error("gcc_command");
281 return ($read_files, $write_files);
284 ########################################################################
285 # gcc_output
286 ########################################################################
288 sub gcc_output($$) {
289 $file = shift;
290 local $_ = shift;
292 if(s/^(\d+):\s+//) {
293 $line = $1;
294 if(s/^warning:\s+//) {
295 my $suppress = 0;
297 if(0) {
298 # Nothing
299 } elsif(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) {
300 my $type = $2;
301 if($type =~ /^(?:
302 HACCEL|HACMDRIVER|HANDLE|HBITMAP|HBRUSH|HCALL|HCURSOR|HDC|HDRVR|HDESK|HDRAWDIB
303 HGDIOBJ|HKL|HGLOBAL|HIMC|HINSTANCE|HKEY|HLOCAL|
304 HMENU|HMIDISTRM|HMIDIIN|HMIDIOUT|HMIXER|HMIXEROBJ|HMMIO|HMODULE|
305 HLINE|HPEN|HPHONE|HPHONEAPP|
306 HRASCONN|HRGN|HRSRC|HWAVEIN|HWAVEOUT|HWINSTA|HWND|
307 SC_HANDLE|WSAEVENT|handle_t|pointer)$/x)
309 $suppress = 1;
310 } else {
311 $suppress = 0;
313 } elsif(/^\(near initialization for \`(.*?)\'\)$/) {
314 $suppress = 0;
315 } elsif(/^\`(.*?)\' defined but not used$/) {
316 $suppress = 0;
317 } elsif(/^\`(.*?)\' is not at beginning of declaration$/) {
318 $suppress = 0;
319 } elsif(/^\`%x\' yields only last 2 digits of year in some locales$/) {
320 $suppress = 1;
321 } elsif(/^assignment makes integer from pointer without a cast$/) {
322 $suppress = 0;
323 } elsif(/^assignment makes pointer from integer without a cast$/) {
324 $suppress = 0;
325 } elsif(/^assignment from incompatible pointer type$/) {
326 $suppress = 0;
327 } elsif(/^cast from pointer to integer of different size$/) {
328 $suppress = 0;
329 } elsif(/^comparison between pointer and integer$/) {
330 $suppress = 0;
331 } elsif(/^comparison between signed and unsigned$/) {
332 $suppress = 0;
333 } elsif(/^comparison of unsigned expression < 0 is always false$/) {
334 $suppress = 0;
335 } elsif(/^comparison of unsigned expression >= 0 is always true$/) {
336 $suppress = 0;
337 } elsif(/^conflicting types for built-in function \`(.*?)\'$/) {
338 $suppress = 0;
339 } elsif(/^empty body in an if-statement$/) {
340 $suppress = 0;
341 } elsif(/^empty body in an else-statement$/) {
342 $suppress = 0;
343 } elsif(/^implicit declaration of function \`(.*?)\'$/) {
344 $suppress = 0;
345 } elsif(/^initialization from incompatible pointer type$/) {
346 $suppress = 0;
347 } elsif(/^initialization makes pointer from integer without a cast$/) {
348 $suppress = 0;
349 } elsif(/^missing initializer$/) {
350 $suppress = 0;
351 } elsif(/^ordered comparison of pointer with integer zero$/) {
352 $suppress = 0;
353 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') from incompatible pointer type$/) {
354 my $arg = $1;
355 my $name = $2;
356 if(defined($name) && $name =~ /^GDI_AllocObject$/) {
357 $suppress = 1;
358 } else {
359 $suppress = 0;
361 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes integer from pointer without a cast$/) {
362 $suppress = 0;
363 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes pointer from integer without a cast$/) {
364 $suppress = 0;
365 } elsif(/^return makes integer from pointer without a cast$/) {
366 $suppress = 0;
367 } elsif(/^return makes pointer from integer without a cast$/) {
368 $suppress = 0;
369 } elsif(/^type of \`(.*?)\' defaults to \`(.*?)\'$/) {
370 $suppress = 0;
371 } elsif(/^unused variable \`(.*?)\'$/) {
372 $suppress = 0;
373 } elsif(!$options->pedantic) {
374 $suppress = 0;
375 } else {
376 error("gcc_output");
379 if(!$suppress) {
380 if($function) {
381 $message = "function $function: warning: $_";
382 } else {
383 $message = "warning: $_";
385 } else {
386 $message = "";
388 } elsif(/^\`(.*?)\' undeclared \(first use in this function\)$/) {
389 $message = "$_";
390 } elsif(/^\(Each undeclared identifier is reported only once$/) {
391 $message = "$_";
392 } elsif(/^conflicting types for \`(.*?)\'$/) {
393 $message = "$_";
394 } elsif(/^for each function it appears in.\)$/) {
395 $message = "$_";
396 } elsif(/^too many arguments to function$/) {
397 $message = "$_";
398 } elsif(/^previous declaration of \`(.*?)\'$/) {
399 $message = "$_";
400 } elsif(/^parse error before `(.*?)'$/) {
401 $message = "$_";
402 } elsif(!$options->pedantic) {
403 $message = "$_";
404 } else {
405 error("gcc_output");
407 } elsif(/^In function \`(.*?)\':$/) {
408 $function = $1;
409 } elsif(/^At top level:$/) {
410 $function = "";
411 } else {
412 error("gcc_output");
416 ########################################################################
417 # install_command
418 ########################################################################
420 sub install_command($) {
421 local $_ = shift;
423 return ([], []);
426 ########################################################################
427 # ld_command
428 ########################################################################
430 sub ld_command($) {
431 local $_ = shift;
433 my $read_files;
434 my $write_files;
436 if(/-r\s+(.*?)\s+-o\s+(\S+)$/) {
437 $write_files = [$2];
438 $read_files = [split(/\s+/, $1)];
439 } else {
440 error("ld_command");
443 return ($read_files, $write_files);
446 ########################################################################
447 # ld_output
448 ########################################################################
450 sub ld_output($$) {
451 $file = shift;
452 local $_ = shift;
454 if(0) {
455 # Nothing
456 } elsif(/^In function \`(.*?)\':$/) {
457 $function = $1;
458 } elsif(/^more undefined references to \`(.*?)\' follow$/) {
459 # Nothing
460 } elsif(/^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
461 # Nothing
462 } elsif(/^undefined reference to \`(.*?)\'$/) {
463 # Nothing
464 } elsif(/^warning: (.*?)\(\) possibly used unsafely; consider using (.*?)\(\)$/) {
465 # Nothing
466 } elsif(/^warning: type and size of dynamic symbol \`(.*?)\' are not defined$/) {
467 $message = "$_";
468 } else {
469 $message = "$_";
473 ########################################################################
474 # ldconfig_command
475 ########################################################################
477 sub ldconfig_command($) {
478 local $_ = shift;
480 return ([], []);
483 ########################################################################
484 # makedep_command
485 ########################################################################
487 sub makedep_command($) {
488 local $_ = shift;
490 return ([], []);
493 ########################################################################
494 # mkdir_command
495 ########################################################################
497 sub mkdir_command($) {
498 local $_ = shift;
500 return ([], []);
503 ########################################################################
504 # ranlib_command
505 ########################################################################
507 sub ranlib_command($) {
508 local $_ = shift;
510 my $read_files;
511 my $write_files;
513 $read_files = [split(/\s+/)];
514 $write_files = [];
516 return ($read_files, $write_files);
519 ########################################################################
520 # rm_command
521 ########################################################################
523 sub rm_command($) {
524 local $_ = shift;
525 s/^-f\s*//;
526 return ([], [], [split(/\s+/, $_)]);
529 ########################################################################
530 # sed_command
531 ########################################################################
533 sub sed_command($) {
534 local $_ = shift;
536 return ([], []);
539 ########################################################################
540 # strip_command
541 ########################################################################
543 sub strip_command($) {
544 local $_ = shift;
546 return ([], []);
549 ########################################################################
550 # winebuild_command
551 ########################################################################
553 sub winebuild_command($) {
554 local $_ = shift;
556 return ([], []);
559 ########################################################################
560 # winebuild_output
561 ########################################################################
563 sub winebuild_output($$) {
564 $file = shift;
565 local $_ = shift;
567 $message = $_;
570 ########################################################################
571 # wmc_command
572 ########################################################################
574 sub wmc_command($) {
575 local $_ = shift;
577 my $read_files;
578 my $write_files;
580 if(/\s+(\S+)$/) {
581 my $mc_file = $1;
583 my $rc_file = $mc_file;
584 $rc_file =~ s/\.mc$/.rc/;
586 $write_files = [$rc_file];
587 $read_files = [$mc_file];
588 } else {
589 error("wmc_command");
592 return ($read_files, $write_files);
595 ########################################################################
596 # wmc_output
597 ########################################################################
599 sub wmc_output($$) {
600 $file = shift;
601 local $_ = shift;
604 ########################################################################
605 # wrc_command
606 ########################################################################
608 sub wrc_command($) {
609 local $_ = shift;
611 my $read_files;
612 my $write_files;
614 if(/\s+(\S+)$/) {
615 my $rc_file = $1;
617 my $o_file = $rc_file;
618 $o_file =~ s/\.rc$/.o/;
620 $write_files = [$o_file];
621 $read_files = [$rc_file];
622 } else {
623 error("wrc_command");
626 return ($read_files, $write_files);
629 ########################################################################
630 # wrc_output
631 ########################################################################
633 sub wrc_output($$) {
634 $file = shift;
635 local $_ = shift;
638 ########################################################################
639 # command
640 ########################################################################
642 sub command($) {
643 local $_ = shift;
645 my $tool;
646 my $file;
647 my $read_files = ["<???>"];
648 my $write_files = ["<???>"];
649 my $remove_files = [];
651 s/^\s*(.*?)\s*$/$1/;
653 if(s/^\[\s+-d\s+(.*?)\s+\]\s+\|\|\s+//) {
654 # Nothing
657 if(s/^ar\s+//) {
658 $tool = "ar";
659 ($read_files, $write_files) = ar_command($_);
660 } elsif(s/^as\s+//) {
661 $tool = "as";
662 ($read_files, $write_files) = as_command($_);
663 } elsif(s/^bison\s+//) {
664 $tool = "bison";
665 ($read_files, $write_files) = bison_command($_);
666 } elsif(s/^cd\s+//) {
667 $tool = "cd";
668 ($read_files, $write_files) = cd_command($_);
669 } elsif(s/^flex\s+//) {
670 $tool = "flex";
671 ($read_files, $write_files) = flex_command($_);
672 } elsif(s/^for\s+//) {
673 $tool = "for";
674 ($read_files, $write_files) = for_command($_);
675 } elsif(s/^\/usr\/bin\/install\s+//) {
676 $tool = "install";
677 ($read_files, $write_files) = install_command($_);
678 } elsif(s/^ld\s+//) {
679 $tool = "ld";
680 ($read_files, $write_files) = ld_command($_);
681 } elsif(s/^\/sbin\/ldconfig\s+//) {
682 $tool = "ldconfig";
683 ($read_files, $write_files) = ldconfig_command();
684 } elsif(s/^gcc\s+//) {
685 $tool = "gcc";
686 ($read_files, $write_files) = gcc_command($_);
687 } elsif(s/^(?:(?:\.\.\/)+|\.\/)tools\/makedep\s+//) {
688 $tool = "makedep";
689 ($read_files, $write_files) = makedep_command($_);
690 } elsif(s/^mkdir\s+//) {
691 $tool = "mkdir";
692 ($read_files, $write_files) = mkdir_command($_);
693 } elsif(s/^ranlib\s+//) {
694 $tool = "ranlib";
695 ($read_files, $write_files) = ranlib_command($_);
696 } elsif(s/^rm\s+//) {
697 $tool = "rm";
698 ($read_files, $write_files, $remove_files) = rm_command($_);
699 } elsif(s/^sed\s+//) {
700 $tool = "sed";
701 ($read_files, $write_files) = sed_command($_);
702 } elsif(s/^strip\s+//) {
703 $tool = "sed";
704 ($read_files, $write_files) = strip_command($_);
705 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/winebuild\/winebuild\s+//) {
706 $tool = "winebuild";
707 ($read_files, $write_files) = winebuild_command($_);
708 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wmc\/wmc\s+//) {
709 $tool = "wmc";
710 ($read_files, $write_files) = wmc_command($_);
711 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wrc\/wrc\s+//) {
712 $tool = "wrc";
713 ($read_files, $write_files) = wrc_command($_);
716 return ($tool, $read_files, $write_files, $remove_files);
719 ########################################################################
720 # line
721 ########################################################################
723 sub line($) {
724 local $_ = shift;
726 $file = "";
727 $line = "";
728 $message = "";
730 $current = $_;
732 my ($new_tool, $read_files, $write_files, $remove_files) = command($_);
733 if(defined($new_tool)) {
734 $tool = $new_tool;
736 $function = "";
738 my $progress = "";
739 if($directory && $directory ne ".") {
740 $progress .= "$directory: ";
742 if($tool) {
743 $progress .= "$tool: ";
746 if($tool =~ /^(?:cd|make)$/) {
747 # Nothing
748 } elsif($tool eq "ld"/) {
749 foreach my $file (@{$read_files}) {
750 $output->lazy_progress("${progress}reading '$file'");
752 my $file = $$write_files[0];
753 $output->progress("$progress: writing '$file'");
754 } elsif($tool eq "rm") {
755 foreach my $file (@{$remove_files}) {
756 $output->lazy_progress("${progress}removing '$file'");
758 } else {
759 if($#$read_files >= 0) {
760 $progress .= "read[" . join(" ", @{$read_files}) . "]";
762 if($#$write_files >= 0) {
763 if($#$read_files >= 0) {
764 $progress .= ", ";
766 $progress .= "write[" . join(" ", @{$write_files}) . "]";
768 if($#$remove_files >= 0) {
769 if($#$read_files >= 0 || $#$write_files >= 0) {
770 $progress .= ", ";
772 $progress .= "remove[" . join(" ", @{$remove_files}) . "]";
775 $output->progress($progress);
778 return 0;
781 my $make = $options->make;
783 if(/^Wine build complete\.$/) {
784 # Nothing
785 } elsif(/^(.*?) is newer than (.*?), please rerun (.*?)\!$/) {
786 $message = "$_";
787 } elsif(/^(.*?) is older than (.*?), please rerun (.*?)$/) {
788 $message = "$_";
789 } elsif(/^\`(.*?)\' is up to date.$/) {
790 $tool = "make";
791 make_output($1, $_);
792 } elsif(s/^$make(?:\[(\d+)\])?:\s*//) {
793 $tool = "make";
794 make_output($1, $_);
795 } elsif(!defined($tool)) {
796 error("line");
797 } elsif($tool eq "make") {
798 make_output($1, $_);
799 } elsif($tool eq "bison" && /^conflicts:\s+\d+\s+shift\/reduce$/) {
800 # Nothing
801 } elsif($tool eq "gcc" && /^(?:In file included |\s*)from (.+?):(\d+)[,:]$/) {
802 # Nothing
803 } elsif($tool =~ /^(?:gcc|ld)$/ && s/^(.+?\.s?o)(?:\(.*?\))?:\s*//) {
804 $tool = "ld";
805 ld_output($1, $_)
806 } elsif($tool =~ /^(?:gcc|ld)$/ && s/^(.*?)ld:\s*//) {
807 $tool = "ld";
808 ld_output("", $_)
809 } elsif($tool =~ /^(?:gcc|ld)$/ && s/^collect2:\s*//) {
810 $tool = "ld";
811 ld_output("collect2", $_);
812 } elsif($tool eq "gcc" && s/^(.+?\.[chly]):\s*//) {
813 gcc_output($1, $_);
814 } elsif($tool eq "ld" && s/^(.+?\.c):(?:\d+:)?\s*//) {
815 ld_output($1, $_);
816 } elsif($tool eq "winebuild" && s/^(.+?\.spec):\s*//) {
817 winebuild_output($1, $_);
818 } elsif($tool eq "wmc" && s/^(.+?\.mc):\s*//) {
819 wmc_output($1, $_);
820 } elsif($tool eq "wrc" && s/^(.+?\.rc):\s*//) {
821 wrc_output($1, $_);
822 } elsif($tool eq "cd" && s/^\/bin\/sh:\s*cd:\s*//) {
823 parse_cd_output($_);
824 } elsif(/^\s*$/) {
825 # Nothing
826 } else {
827 error("line");
830 $file =~ s/^\.\///;
832 return 1;