1 ###################################################
2 # check that a parsed IDL file is valid
3 # Copyright tridge@samba.org 2003
4 # released under the GNU GPL
11 #####################################################################
12 # signal a fatal validation error
17 die("$pos->{FILE}:$pos->{LINE}:$s\n");
24 warn ("$pos->{FILE}:$pos->{LINE}:warning:$s\n");
31 if ($e->{PARENT} && $e->{PARENT}->{NAME}) {
32 return "$e->{PARENT}->{NAME}.$e->{NAME}";
35 if ($e->{PARENT} && $e->{PARENT}->{PARENT}->{NAME}) {
36 return "$e->{PARENT}->{PARENT}->{NAME}.$e->{NAME}";
40 return "$e->{PARENT}->{NAME}.$e->{NAME}";
51 "pointer_default" => {},
52 "pointer_default_top" => {},
89 "nodiscriminant" => {},
95 "subcontext_size" => {},
116 #####################################################################
117 # check for unknown properties
118 sub ValidProperties($)
122 return unless defined $e->{PROPERTIES};
124 foreach my $key (keys %{$e->{PROPERTIES}}) {
125 if (not defined $property_list{$key}) {
126 fatal($e, el_name($e) . ": unknown property '$key'\n");
131 #####################################################################
139 if (util::has_property($e, "ptr")) {
140 fatal($e, el_name($e) . " : pidl does not support full NDR pointers yet\n");
143 # Check whether switches are used correctly.
144 if (my $switch = util::has_property($e, "switch_is")) {
145 my $e2 = util::find_sibling($e, $switch);
146 my $type = typelist::getType($e->{TYPE});
148 if (defined($type) and $type->{DATA}->{TYPE} ne "UNION") {
149 fatal($e, el_name($e) . ": switch_is() used on non-union type $e->{TYPE} which is a $type->{DATA}->{TYPE}");
152 if (!util::has_property($type, "nodiscriminant") and defined($e2)) {
153 my $discriminator_type = util::has_property($type, "switch_type");
154 $discriminator_type = "uint32" unless defined ($discriminator_type);
156 if ($e2->{TYPE} ne $discriminator_type) {
157 print el_name($e) . ": Warning: switch_is() is of type $e2->{TYPE}, while discriminator type for union $type->{NAME} is $discriminator_type\n";
162 if (defined (util::has_property($e, "subcontext_size")) and not defined(util::has_property($e, "subcontext"))) {
163 fatal($e, el_name($e) . " : subcontext_size() on non-subcontext element");
166 if (defined (util::has_property($e, "compression")) and not defined(util::has_property($e, "subcontext"))) {
167 fatal($e, el_name($e) . " : compression() on non-subcontext element");
170 if (defined (util::has_property($e, "obfuscation")) and not defined(util::has_property($e, "subcontext"))) {
171 fatal($e, el_name($e) . " : obfuscation() on non-subcontext element");
174 if (!$e->{POINTERS} && (
175 util::has_property($e, "ptr") or
176 util::has_property($e, "unique") or
177 util::has_property($e, "relative") or
178 util::has_property($e, "ref"))) {
179 fatal($e, el_name($e) . " : pointer properties on non-pointer element\n");
183 #####################################################################
189 ValidProperties($struct);
191 foreach my $e (@{$struct->{ELEMENTS}}) {
192 $e->{PARENT} = $struct;
197 #####################################################################
203 ValidProperties($union);
205 if (util::has_property($union->{PARENT}, "nodiscriminant") and util::has_property($union->{PARENT}, "switch_type")) {
206 fatal($union->{PARENT}, $union->{PARENT}->{NAME} . ": switch_type() on union without discriminant");
209 foreach my $e (@{$union->{ELEMENTS}}) {
210 $e->{PARENT} = $union;
212 if (defined($e->{PROPERTIES}->{default}) and
213 defined($e->{PROPERTIES}->{case})) {
214 fatal $e, "Union member $e->{NAME} can not have both default and case properties!\n";
217 unless (defined ($e->{PROPERTIES}->{default}) or
218 defined ($e->{PROPERTIES}->{case})) {
219 fatal $e, "Union member $e->{NAME} must have default or case property\n";
222 if (util::has_property($e, "ref")) {
223 fatal($e, el_name($e) . " : embedded ref pointers are not supported yet\n");
231 #####################################################################
235 my($typedef) = shift;
236 my $data = $typedef->{DATA};
238 ValidProperties($typedef);
240 $data->{PARENT} = $typedef;
242 if (ref($data) eq "HASH") {
243 if ($data->{TYPE} eq "STRUCT") {
247 if ($data->{TYPE} eq "UNION") {
253 #####################################################################
259 ValidProperties($fn);
261 foreach my $e (@{$fn->{ELEMENTS}}) {
263 if (util::has_property($e, "ref") && !$e->{POINTERS}) {
264 fatal $e, "[ref] variables must be pointers ($fn->{NAME}/$e->{NAME})\n";
270 #####################################################################
271 # parse the interface definitions
272 sub ValidInterface($)
274 my($interface) = shift;
275 my($data) = $interface->{DATA};
277 ValidProperties($interface);
279 if (util::has_property($interface, "pointer_default") &&
280 $interface->{PROPERTIES}->{pointer_default} eq "ptr") {
281 fatal $interface, "Full pointers are not supported yet\n";
284 if (util::has_property($interface, "object")) {
285 if (util::has_property($interface, "version") &&
286 $interface->{PROPERTIES}->{version} != 0) {
287 fatal $interface, "Object interfaces must have version 0.0 ($interface->{NAME})\n";
290 if (!defined($interface->{BASE}) &&
291 not ($interface->{NAME} eq "IUnknown")) {
292 fatal $interface, "Object interfaces must all derive from IUnknown ($interface->{NAME})\n";
296 foreach my $d (@{$data}) {
297 ($d->{TYPE} eq "TYPEDEF") &&
299 ($d->{TYPE} eq "FUNCTION") &&
305 #####################################################################
306 # parse a parsed IDL into a C header
311 foreach my $x (@{$idl}) {
312 ($x->{TYPE} eq "INTERFACE") &&