widl: Fix handling of [local] functions without [call_as].
[wine] / tools / winapi / preprocessor.pm
1 #
2 # Copyright 1999, 2000, 2001 Patrik Stridvall
3 #
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.
8 #
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.
13 #
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
17 #
18
19 package preprocessor;
20
21 use strict;
22
23 sub new($) {
24     my $proto = shift;
25     my $class = ref($proto) || $proto;
26     my $self  = {};
27     bless ($self, $class);
28
29     my $state = \%{$self->{STATE}};
30     my $stack = \@{$self->{STACK}};
31     my $include_found = \${$self->{INCLUDE_FOUND}};
32     my $conditional_found = \${$self->{CONDITIONAL_FOUND}};
33
34     $$include_found = shift;
35     $$conditional_found = shift;
36
37     return $self;
38 }
39
40 sub include($$) {
41     my $self = shift;
42     my $include_found = \${$self->{INCLUDE_FOUND}};
43
44     my $argument = shift;
45
46     &$$include_found($argument);
47 }
48
49 sub define($$) {
50     my $self = shift;
51     my $state = \%{$self->{STATE}};
52     my $conditional_found = \${$self->{CONDITIONAL_FOUND}};
53
54     my $name = shift;
55
56     $$state{$name} = "def";
57
58     &$$conditional_found($name);
59 }
60
61 sub undefine($$) {
62     my $self = shift;
63     my $state = \%{$self->{STATE}};
64     my $conditional_found = \${$self->{CONDITIONAL_FOUND}};
65
66     my $name = shift;
67
68     $$state{$name} = "undef";
69
70     &$$conditional_found($name);
71 }
72
73 sub begin_if($$$) {
74     my $self = shift;
75     my $state = \%{$self->{STATE}};
76     my $stack = \@{$self->{STACK}};
77
78     my $directive = shift;
79     local $_ = shift;
80
81     while(!/^$/) {
82         if(/^0\s*\&\&/s) {
83             $_ = "0";
84         } elsif(/^1\s*\|\|/s) {
85             $_ = "1";
86         }
87
88         if (/^(!\s*)?defined\s*\(\s*(\w+)\s*\)\s*(?:(\&\&|\|\|)\s*)?/s ||
89             /^(!\s*)?defined\s*(\w+)\s*(?:(\&\&|\|\|)\s*)?/s)
90         {
91             $_ = $';
92
93             my $sign = $1;
94             my $var = $2;
95
96             if (defined($sign) && $sign eq "!") {
97                 $self->undefine($var);
98                 push @$stack, $var;
99             } else {
100                 $self->define($var);
101                 push @$stack, $var;
102             }
103         } elsif (/^(!\s*)?(\w+)\s*(?:(<|<=|==|!=|>=|>|\+|\-|\*\/)\s*(\w+)\s*)?(?:(\&\&|\|\|)\s*)?/s) {
104             $_ = $';
105
106             my $sign = $1;
107             my $var = $2;
108
109             if (defined($sign) && $sign eq "!") {
110                 $self->undefine($var);
111                 push @$stack, $var;
112             } else {
113                 $self->define($var);
114                 push @$stack, $var;
115             }
116         } elsif(/^(!\s*)?\(/s) {
117             $_ = "";
118         } else {
119             print "*** Can't parse '#$directive $_' ***\n";
120             $_ = "";
121         }
122     }
123 }
124
125 sub else_if($$) {
126     my $self = shift;
127     my $state = \%{$self->{STATE}};
128     my $stack = \@{$self->{STACK}};
129
130     my $argument = shift;
131
132     $self->end_if;
133
134     if(defined($argument)) {
135         $self->begin_if("elif", $argument);
136     }
137 }
138
139 sub end_if($) {
140     my $self = shift;
141     my $state = \%{$self->{STATE}};
142     my $stack = \@{$self->{STACK}};
143
144     my $macro = pop @$stack;
145     delete $$state{$macro} if defined($macro);
146 }
147
148 sub directive($$$) {
149     my $self = shift;
150     my $state = \%{$self->{STATE}};
151     my $stack = \@{$self->{STACK}};
152
153     my $directive = shift;
154     my $argument = shift;
155
156     local $_ = $directive;
157     if(/^if$/) {
158         $self->begin_if("if",$argument);
159     } elsif(/^ifdef$/) {
160         $self->begin_if("if", "defined($argument)");
161     } elsif(/^ifndef$/) {
162         $self->begin_if("if", "!defined($argument)");
163         push @$stack, $argument;
164     } elsif(/^elif$/) {
165         $self->else_if($argument);
166     } elsif(/^else$/) {
167         $self->else_if;
168     } elsif(/^endif$/) {
169         $self->end_if;
170     } elsif(/^include/) {
171         $self->include($argument);
172     }
173 }
174
175 sub is_def($$) {
176     my $self = shift;
177     my $state = \%{$self->{STATE}};
178
179     my $name = shift;
180
181     my $status = $$state{$name};
182
183     return defined($status) && $status eq "def";
184 }
185
186 sub is_undef($$) {
187     my $self = shift;
188     my $state = \%{$self->{STATE}};
189
190     my $name = shift;
191
192     my $status = $$state{$name};
193
194     return defined($status) && $status eq "undef";
195 }
196
197 sub is_unknown($$) {
198     my $self = shift;
199     my $state = \%{$self->{STATE}};
200
201     my $name = shift;
202
203     my $status = $$state{$name};
204
205     return !defined($status);
206 }
207
208 1;