wineps: Don't use CDECL for private functions.
[wine.git] / tools / winapi / make_parser.pm
blob2f5788df88289a1558a116a1bcf3f51cc00ac3b7
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;
22 use warnings 'all';
24 use setup qw($current_dir $wine_dir $winapi_dir);
26 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
27 require Exporter;
29 @ISA = qw(Exporter);
30 @EXPORT = qw();
31 @EXPORT_OK = qw($directory $tool $file $line $message);
33 use vars qw($directory $tool $file $line $message);
35 use output qw($output);
36 use options qw($options);
39 #sub command($);
40 #sub gcc_output($$);
41 #sub ld_output($$);
42 #sub make_output($$);
43 #sub winebuild_output($$);
44 #sub wmc_output($$);
45 #sub wrc_output($$);
48 ########################################################################
49 # global
50 ########################################################################
52 my $current;
53 my $function;
55 ########################################################################
56 # error
57 ########################################################################
59 sub error($) {
60 my $where = shift;
62 if(!defined($where)) {
63 $where = "";
66 my $context;
67 if($tool) {
68 $context = "$tool";
69 if($where) {
70 $context .= "<$where>";
72 } else {
73 if($where) {
74 $context = "<$where>";
75 } else {
76 $context = "<>";
80 if(defined($tool)) {
81 $output->write("$directory: $context: can't parse output: '$current'\n");
82 } else {
83 $output->write("$directory: $context: can't parse output: '$current'\n");
85 exit 1;
88 ########################################################################
89 # make_output
90 ########################################################################
92 sub make_output($$) {
93 my $level = shift;
94 local $_ = shift;
96 $file = "";
97 $message = "";
99 if(/^\*\*\* \[(.*?)\] Error (\d+)$/) {
100 # Nothing
101 } elsif(/^\*\*\* Error code (\d+)$/) {
102 # Nothing
103 } elsif(/^\*\*\* Warning:\s+/) { #
104 if(/^File \`(.+?)\' has modification time in the future \((.+?) > \(.+?\)\)$/) {
105 # Nothing
106 } else {
107 error("make_output");
109 } elsif(/^\`(.*?)\' is up to date.$/) {
110 # Nothing
111 } elsif(/^\[(.*?)\] Error (\d+) \(ignored\)$/) {
112 # Nothing
113 } elsif(/^don\'t know how to make (.*?)\. Stop$/) {
114 $message = "$_";
115 } elsif(/^(Entering|Leaving) directory \`(.*?)\'$/) {
116 if($1 eq "Entering") {
117 $directory = $2;
118 } else {
119 $directory = "";
122 my @components;
123 foreach my $component (split(/\//, $directory)) {
124 if($component eq "wine") {
125 @components = ();
126 } else {
127 push @components, $component;
130 $directory = join("/", @components);
131 } elsif(/^(.*?) is older than (.*?), please rerun (.*?)\$/) {
132 # Nothing
133 } elsif(/^Nothing to be done for \`(.*?)\'\.$/) {
134 # Nothing
135 } elsif(s/^warning:\s+//) {
136 if(/^Clock skew detected. Your build may be incomplete.$/) {
137 # Nothing
138 } else {
139 error("make_output");
141 } elsif(/^Stop in (.*?)\.$/) {
142 # Nothing
143 } elsif(/^\s*$/) {
144 # Nothing
145 } else {
146 error("make_output");
151 ########################################################################
152 # ar_command
153 ########################################################################
155 sub ar_command($) {
156 local $_ = shift;
158 my $read_files;
159 my $write_files;
161 if(/rc\s+(\S+)(\s+\S+)+$/) {
162 $write_files = [$1];
163 $read_files = $2;
164 $read_files =~ s/^\s*//;
165 $read_files = [split(/\s+/, $read_files)];
166 } else {
167 error("ar_command");
170 return ($read_files, $write_files);
173 ########################################################################
174 # as_command
175 ########################################################################
177 sub as_command($) {
178 local $_ = shift;
180 my $read_files;
181 my $write_files;
183 if(/-o\s+(\S+)\s+(\S+)$/) {
184 $write_files = [$1];
185 $read_files = [$2];
186 } else {
187 error("as_command");
190 return ($read_files, $write_files);
193 ########################################################################
194 # bision_command
195 ########################################################################
197 sub bison_command($) {
198 local $_ = shift;
200 return ([], []);
203 ########################################################################
204 # cd_command
205 ########################################################################
207 sub cd_command($) {
208 local $_ = shift;
210 return ([], []);
213 ########################################################################
214 # cd_output
215 ########################################################################
217 sub cd_output($) {
218 local $_ = shift;
220 if(/^(.*?): No such file or directory/) {
221 $message = "directory '$1' doesn't exist";
225 ########################################################################
226 # flex_command
227 ########################################################################
229 sub flex_command($) {
230 local $_ = shift;
232 return ([], []);
235 ########################################################################
236 # for_command
237 ########################################################################
239 sub for_command($) {
240 local $_ = shift;
242 return ([], []);
245 ########################################################################
246 # gcc_command
247 ########################################################################
249 sub gcc_command($) {
250 my $read_files;
251 my $write_files;
253 if(/-o\s+(\S+)\s+(\S+)$/) {
254 my $write_file = $1;
255 my $read_file = $2;
257 $write_file =~ s%^\./%%;
258 $read_file =~ s%^\./%%;
260 $write_files = [$write_file];
261 $read_files = [$read_file];
262 } elsif(/-o\s+(\S+)/) {
263 my $write_file = $1;
265 $write_file =~ s%^\./%%;
267 $write_files = [$write_file];
268 $read_files = ["<???>"];
269 } elsif(/^-shared.*?-o\s+(\S+)/) {
270 my $write_file = $1;
272 $write_file =~ s%^\./%%;
274 $write_files = [$write_file];
275 $read_files = ["<???>"];
276 } else {
277 error("gcc_command");
280 return ($read_files, $write_files);
283 ########################################################################
284 # gcc_output
285 ########################################################################
287 sub gcc_output($$) {
288 $file = shift;
289 local $_ = shift;
291 if(s/^(\d+):\s+//) {
292 $line = $1;
293 if(s/^warning:\s+//) {
294 my $suppress = 0;
296 if(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) {
297 my $type = $2;
298 if($type =~ /^(?:
299 HACCEL|HACMDRIVER|HANDLE|HBITMAP|HBRUSH|HCALL|HCURSOR|HDC|HDRVR|HDESK|HDRAWDIB
300 HGDIOBJ|HKL|HGLOBAL|HIMC|HINSTANCE|HKEY|HLOCAL|
301 HMENU|HMIDISTRM|HMIDIIN|HMIDIOUT|HMIXER|HMIXEROBJ|HMMIO|HMODULE|
302 HLINE|HPEN|HPHONE|HPHONEAPP|
303 HRASCONN|HRGN|HRSRC|HWAVEIN|HWAVEOUT|HWINSTA|HWND|
304 SC_HANDLE|WSAEVENT|handle_t|pointer)$/x)
306 $suppress = 1;
307 } else {
308 $suppress = 0;
310 } elsif(/^\(near initialization for \`(.*?)\'\)$/) {
311 $suppress = 0;
312 } elsif(/^\`(.*?)\' defined but not used$/) {
313 $suppress = 0;
314 } elsif(/^\`(.*?)\' is not at beginning of declaration$/) {
315 $suppress = 0;
316 } elsif(/^\`%x\' yields only last 2 digits of year in some locales$/) {
317 $suppress = 1;
318 } elsif(/^assignment makes integer from pointer without a cast$/) {
319 $suppress = 0;
320 } elsif(/^assignment makes pointer from integer without a cast$/) {
321 $suppress = 0;
322 } elsif(/^assignment from incompatible pointer type$/) {
323 $suppress = 0;
324 } elsif(/^cast from pointer to integer of different size$/) {
325 $suppress = 0;
326 } elsif(/^comparison between pointer and integer$/) {
327 $suppress = 0;
328 } elsif(/^comparison between signed and unsigned$/) {
329 $suppress = 0;
330 } elsif(/^comparison of unsigned expression < 0 is always false$/) {
331 $suppress = 0;
332 } elsif(/^comparison of unsigned expression >= 0 is always true$/) {
333 $suppress = 0;
334 } elsif(/^conflicting types for built-in function \`(.*?)\'$/) {
335 $suppress = 0;
336 } elsif(/^empty body in an if-statement$/) {
337 $suppress = 0;
338 } elsif(/^empty body in an else-statement$/) {
339 $suppress = 0;
340 } elsif(/^implicit declaration of function \`(.*?)\'$/) {
341 $suppress = 0;
342 } elsif(/^initialization from incompatible pointer type$/) {
343 $suppress = 0;
344 } elsif(/^initialization makes pointer from integer without a cast$/) {
345 $suppress = 0;
346 } elsif(/^missing initializer$/) {
347 $suppress = 0;
348 } elsif(/^ordered comparison of pointer with integer zero$/) {
349 $suppress = 0;
350 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') from incompatible pointer type$/) {
351 $suppress = 0;
352 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes integer from pointer without a cast$/) {
353 $suppress = 0;
354 } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes pointer from integer without a cast$/) {
355 $suppress = 0;
356 } elsif(/^return makes integer from pointer without a cast$/) {
357 $suppress = 0;
358 } elsif(/^return makes pointer from integer without a cast$/) {
359 $suppress = 0;
360 } elsif(/^type of \`(.*?)\' defaults to \`(.*?)\'$/) {
361 $suppress = 0;
362 } elsif(/^unused variable \`(.*?)\'$/) {
363 $suppress = 0;
364 } elsif(!$options->pedantic) {
365 $suppress = 0;
366 } else {
367 error("gcc_output");
370 if(!$suppress) {
371 if($function) {
372 $message = "function $function: warning: $_";
373 } else {
374 $message = "warning: $_";
376 } else {
377 $message = "";
379 } elsif(/^\`(.*?)\' undeclared \(first use in this function\)$/) {
380 $message = "$_";
381 } elsif(/^\(Each undeclared identifier is reported only once$/) {
382 $message = "$_";
383 } elsif(/^conflicting types for \`(.*?)\'$/) {
384 $message = "$_";
385 } elsif(/^for each function it appears in.\)$/) {
386 $message = "$_";
387 } elsif(/^too many arguments to function$/) {
388 $message = "$_";
389 } elsif(/^previous declaration of \`(.*?)\'$/) {
390 $message = "$_";
391 } elsif(/^parse error before `(.*?)'$/) {
392 $message = "$_";
393 } elsif(!$options->pedantic) {
394 $message = "$_";
395 } else {
396 error("gcc_output");
398 } elsif(/^In function \`(.*?)\':$/) {
399 $function = $1;
400 } elsif(/^At top level:$/) {
401 $function = "";
402 } else {
403 error("gcc_output");
407 ########################################################################
408 # install_command
409 ########################################################################
411 sub install_command($) {
412 local $_ = shift;
414 return ([], []);
417 ########################################################################
418 # ld_command
419 ########################################################################
421 sub ld_command($) {
422 local $_ = shift;
424 my $read_files;
425 my $write_files;
427 if(/-r\s+(.*?)\s+-o\s+(\S+)$/) {
428 $write_files = [$2];
429 $read_files = [split(/\s+/, $1)];
430 } else {
431 error("ld_command");
434 return ($read_files, $write_files);
437 ########################################################################
438 # ld_output
439 ########################################################################
441 sub ld_output($$) {
442 $file = shift;
443 local $_ = shift;
445 if(/^In function \`(.*?)\':$/) {
446 $function = $1;
447 } elsif(/^more undefined references to \`(.*?)\' follow$/) {
448 # Nothing
449 } elsif(/^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
450 # Nothing
451 } elsif(/^undefined reference to \`(.*?)\'$/) {
452 # Nothing
453 } elsif(/^warning: (.*?)\(\) possibly used unsafely; consider using (.*?)\(\)$/) {
454 # Nothing
455 } elsif(/^warning: type and size of dynamic symbol \`(.*?)\' are not defined$/) {
456 $message = "$_";
457 } else {
458 $message = "$_";
462 ########################################################################
463 # ldconfig_command
464 ########################################################################
466 sub ldconfig_command($) {
467 local $_ = shift;
469 return ([], []);
472 ########################################################################
473 # makedep_command
474 ########################################################################
476 sub makedep_command($) {
477 local $_ = shift;
479 return ([], []);
482 ########################################################################
483 # mkdir_command
484 ########################################################################
486 sub mkdir_command($) {
487 local $_ = shift;
489 return ([], []);
492 ########################################################################
493 # ranlib_command
494 ########################################################################
496 sub ranlib_command($) {
497 local $_ = shift;
499 my $read_files;
500 my $write_files;
502 $read_files = [split(/\s+/)];
503 $write_files = [];
505 return ($read_files, $write_files);
508 ########################################################################
509 # rm_command
510 ########################################################################
512 sub rm_command($) {
513 local $_ = shift;
514 s/^-f\s*//;
515 return ([], [], [split(/\s+/, $_)]);
518 ########################################################################
519 # sed_command
520 ########################################################################
522 sub sed_command($) {
523 local $_ = shift;
525 return ([], []);
528 ########################################################################
529 # strip_command
530 ########################################################################
532 sub strip_command($) {
533 local $_ = shift;
535 return ([], []);
538 ########################################################################
539 # winebuild_command
540 ########################################################################
542 sub winebuild_command($) {
543 local $_ = shift;
545 return ([], []);
548 ########################################################################
549 # winebuild_output
550 ########################################################################
552 sub winebuild_output($$) {
553 $file = shift;
554 local $_ = shift;
556 $message = $_;
559 ########################################################################
560 # wmc_command
561 ########################################################################
563 sub wmc_command($) {
564 local $_ = shift;
566 my $read_files;
567 my $write_files;
569 if(/\s+(\S+)$/) {
570 my $mc_file = $1;
572 my $rc_file = $mc_file;
573 $rc_file =~ s/\.mc$/.rc/;
575 $write_files = [$rc_file];
576 $read_files = [$mc_file];
577 } else {
578 error("wmc_command");
581 return ($read_files, $write_files);
584 ########################################################################
585 # wmc_output
586 ########################################################################
588 sub wmc_output($$) {
589 $file = shift;
590 local $_ = shift;
593 ########################################################################
594 # wrc_command
595 ########################################################################
597 sub wrc_command($) {
598 local $_ = shift;
600 my $read_files;
601 my $write_files;
603 if(/\s+(\S+)$/) {
604 my $rc_file = $1;
606 my $o_file = $rc_file;
607 $o_file =~ s/\.rc$/.o/;
609 $write_files = [$o_file];
610 $read_files = [$rc_file];
611 } else {
612 error("wrc_command");
615 return ($read_files, $write_files);
618 ########################################################################
619 # wrc_output
620 ########################################################################
622 sub wrc_output($$) {
623 $file = shift;
624 local $_ = shift;
627 ########################################################################
628 # command
629 ########################################################################
631 sub command($) {
632 local $_ = shift;
634 my $tool;
635 my $file;
636 my $read_files = ["<???>"];
637 my $write_files = ["<???>"];
638 my $remove_files = [];
640 s/^\s*(.*?)\s*$/$1/;
642 if(s/^\[\s+-d\s+(.*?)\s+\]\s+\|\|\s+//) {
643 # Nothing
646 if(s/^ar\s+//) {
647 $tool = "ar";
648 ($read_files, $write_files) = ar_command($_);
649 } elsif(s/^as\s+//) {
650 $tool = "as";
651 ($read_files, $write_files) = as_command($_);
652 } elsif(s/^bison\s+//) {
653 $tool = "bison";
654 ($read_files, $write_files) = bison_command($_);
655 } elsif(s/^cd\s+//) {
656 $tool = "cd";
657 ($read_files, $write_files) = cd_command($_);
658 } elsif(s/^flex\s+//) {
659 $tool = "flex";
660 ($read_files, $write_files) = flex_command($_);
661 } elsif(s/^for\s+//) {
662 $tool = "for";
663 ($read_files, $write_files) = for_command($_);
664 } elsif(s/^\/usr\/bin\/install\s+//) {
665 $tool = "install";
666 ($read_files, $write_files) = install_command($_);
667 } elsif(s/^ld\s+//) {
668 $tool = "ld";
669 ($read_files, $write_files) = ld_command($_);
670 } elsif(s/^\/sbin\/ldconfig\s+//) {
671 $tool = "ldconfig";
672 ($read_files, $write_files) = ldconfig_command();
673 } elsif(s/^gcc\s+//) {
674 $tool = "gcc";
675 ($read_files, $write_files) = gcc_command($_);
676 } elsif(s/^(?:(?:\.\.\/)+|\.\/)tools\/makedep\s+//) {
677 $tool = "makedep";
678 ($read_files, $write_files) = makedep_command($_);
679 } elsif(s/^mkdir\s+//) {
680 $tool = "mkdir";
681 ($read_files, $write_files) = mkdir_command($_);
682 } elsif(s/^ranlib\s+//) {
683 $tool = "ranlib";
684 ($read_files, $write_files) = ranlib_command($_);
685 } elsif(s/^rm\s+//) {
686 $tool = "rm";
687 ($read_files, $write_files, $remove_files) = rm_command($_);
688 } elsif(s/^sed\s+//) {
689 $tool = "sed";
690 ($read_files, $write_files) = sed_command($_);
691 } elsif(s/^strip\s+//) {
692 $tool = "sed";
693 ($read_files, $write_files) = strip_command($_);
694 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/winebuild\/winebuild\s+//) {
695 $tool = "winebuild";
696 ($read_files, $write_files) = winebuild_command($_);
697 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wmc\/wmc\s+//) {
698 $tool = "wmc";
699 ($read_files, $write_files) = wmc_command($_);
700 } elsif(s/^LD_LIBRARY_PATH="(?:(?:\.\.\/)*unicode)?:\$LD_LIBRARY_PATH"\s+(?:\.\.\/)*tools\/wrc\/wrc\s+//) {
701 $tool = "wrc";
702 ($read_files, $write_files) = wrc_command($_);
705 return ($tool, $read_files, $write_files, $remove_files);
708 ########################################################################
709 # line
710 ########################################################################
712 sub line($) {
713 local $_ = shift;
715 $file = "";
716 $line = "";
717 $message = "";
719 $current = $_;
721 my ($new_tool, $read_files, $write_files, $remove_files) = command($_);
722 if(defined($new_tool)) {
723 $tool = $new_tool;
725 $function = "";
727 my $progress = "";
728 if($directory && $directory ne ".") {
729 $progress .= "$directory: ";
731 if($tool) {
732 $progress .= "$tool: ";
735 if($tool =~ /^(?:cd|make)$/) {
736 # Nothing
737 } elsif($tool eq "ld"/) {
738 foreach my $file (@{$read_files}) {
739 $output->lazy_progress("${progress}reading '$file'");
741 my $file = $$write_files[0];
742 $output->progress("$progress: writing '$file'");
743 } elsif($tool eq "rm") {
744 foreach my $file (@{$remove_files}) {
745 $output->lazy_progress("${progress}removing '$file'");
747 } else {
748 if($#$read_files >= 0) {
749 $progress .= "read[" . join(" ", @{$read_files}) . "]";
751 if($#$write_files >= 0) {
752 if($#$read_files >= 0) {
753 $progress .= ", ";
755 $progress .= "write[" . join(" ", @{$write_files}) . "]";
757 if($#$remove_files >= 0) {
758 if($#$read_files >= 0 || $#$write_files >= 0) {
759 $progress .= ", ";
761 $progress .= "remove[" . join(" ", @{$remove_files}) . "]";
764 $output->progress($progress);
767 return 0;
770 my $make = $options->make;
772 if(/^Wine build complete\.$/) {
773 # Nothing
774 } elsif(/^(.*?) is newer than (.*?), please rerun (.*?)\!$/) {
775 $message = "$_";
776 } elsif(/^(.*?) is older than (.*?), please rerun (.*?)$/) {
777 $message = "$_";
778 } elsif(/^\`(.*?)\' is up to date.$/) {
779 $tool = "make";
780 make_output($1, $_);
781 } elsif(s/^$make(?:\[(\d+)\])?:\s*//) {
782 $tool = "make";
783 make_output($1, $_);
784 } elsif(!defined($tool)) {
785 error("line");
786 } elsif($tool eq "make") {
787 make_output($1, $_);
788 } elsif($tool eq "bison" && /^conflicts:\s+\d+\s+shift\/reduce$/) {
789 # Nothing
790 } elsif($tool eq "gcc" && /^(?:In file included |\s*)from (.+?):(\d+)[,:]$/) {
791 # Nothing
792 } elsif($tool =~ /^(?:gcc|ld)$/ && s/^(.+?\.s?o)(?:\(.*?\))?:\s*//) {
793 $tool = "ld";
794 ld_output($1, $_)
795 } elsif($tool =~ /^(?:gcc|ld)$/ && s/^(.*?)ld:\s*//) {
796 $tool = "ld";
797 ld_output("", $_)
798 } elsif($tool =~ /^(?:gcc|ld)$/ && s/^collect2:\s*//) {
799 $tool = "ld";
800 ld_output("collect2", $_);
801 } elsif($tool eq "gcc" && s/^(.+?\.[chly]):\s*//) {
802 gcc_output($1, $_);
803 } elsif($tool eq "ld" && s/^(.+?\.c):(?:\d+:)?\s*//) {
804 ld_output($1, $_);
805 } elsif($tool eq "winebuild" && s/^(.+?\.spec):\s*//) {
806 winebuild_output($1, $_);
807 } elsif($tool eq "wmc" && s/^(.+?\.mc):\s*//) {
808 wmc_output($1, $_);
809 } elsif($tool eq "wrc" && s/^(.+?\.rc):\s*//) {
810 wrc_output($1, $_);
811 } elsif($tool eq "cd" && s/^\/bin\/sh:\s*cd:\s*//) {
812 parse_cd_output($_);
813 } elsif(/^\s*$/) {
814 # Nothing
815 } else {
816 error("line");
819 $file =~ s/^\.\///;
821 return 1;