1 ###################################################
2 # create C header files for an IDL structure
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
21 for (my($i)=0; $i < $tab_depth; $i++) {
26 #####################################################################
27 # parse a properties list
28 sub HeaderProperties
($)
34 foreach my $d (@
{$props}) {
35 if (ref($d) ne "HASH") {
38 foreach my $k (keys %{$d}) {
39 pidl
"/* [$k($d->{$k})] */ ";
45 #####################################################################
46 # parse a structure element
51 (defined $element->{PROPERTIES
}) && HeaderProperties
($element->{PROPERTIES
});
53 HeaderType
($element, $element->{TYPE
}, "");
55 if ($element->{POINTERS
} &&
56 $element->{TYPE
} ne "string") {
57 my($n) = $element->{POINTERS
};
58 for (my($i)=$n; $i > 0; $i--) {
62 if (defined $element->{ARRAY_LEN
} &&
63 !util
::is_constant
($element->{ARRAY_LEN
}) &&
64 !$element->{POINTERS
}) {
65 # conformant arrays are ugly! I choose to implement them with
66 # pointers instead of the [1] method
69 pidl
"$element->{NAME}";
70 if (defined $element->{ARRAY_LEN
} && util
::is_constant
($element->{ARRAY_LEN
})) {
71 pidl
"[$element->{ARRAY_LEN}]";
76 #####################################################################
82 pidl
"\nstruct $name {\n";
85 if (defined $struct->{ELEMENTS
}) {
86 foreach my $e (@
{$struct->{ELEMENTS
}}) {
92 # some compilers can't handle empty structures
93 pidl
"\tchar _empty_;\n";
99 #####################################################################
106 util
::register_enum
($enum, $name);
108 pidl
"\nenum $name {\n";
110 my $els = \@
{$enum->{ELEMENTS
}};
111 foreach my $i (0 .. $#{$els}-1) {
118 my $e = ${$els}[$#{$els}];
121 if ($e !~ /^(.*?)\s*$/) {
122 die "Bad enum $name\n";
129 #####################################################################
136 util
::register_bitmap
($bitmap, $name);
138 pidl
"\n/* bitmap $name */\n";
140 my $els = \@
{$bitmap->{ELEMENTS
}};
141 foreach my $i (0 .. $#{$els}) {
150 #####################################################################
158 (defined $union->{PROPERTIES
}) && HeaderProperties
($union->{PROPERTIES
});
159 pidl
"\nunion $name {\n";
161 foreach my $e (@
{$union->{ELEMENTS
}}) {
162 if ($e->{TYPE
} ne "EMPTY") {
163 if (! defined $done{$e->{NAME
}}) {
166 $done{$e->{NAME
}} = 1;
173 #####################################################################
180 if (ref($data) eq "HASH") {
181 ($data->{TYPE
} eq "ENUM") &&
182 HeaderEnum
($data, $name);
183 ($data->{TYPE
} eq "BITMAP") &&
184 HeaderBitmap
($data, $name);
185 ($data->{TYPE
} eq "STRUCT") &&
186 HeaderStruct
($data, $name);
187 ($data->{TYPE
} eq "UNION") &&
188 HeaderUnion
($data, $name);
191 if ($data =~ "string") {
193 } elsif (util
::is_enum
($e->{TYPE
})) {
195 } elsif (util
::is_bitmap
($e->{TYPE
})) {
196 my $bitmap = util
::get_bitmap
($e->{TYPE
});
197 pidl util
::bitmap_type_decl
($bitmap);
198 } elsif (NdrParser
::is_scalar_type
($data)) {
199 pidl util
::map_type
($data);
200 } elsif (util
::has_property
($e, "switch_is")) {
207 #####################################################################
211 my($declare) = shift;
213 if ($declare->{DATA
}->{TYPE
} eq "ENUM") {
214 util
::register_enum
($declare, $declare->{NAME
});
215 } elsif ($declare->{DATA
}->{TYPE
} eq "BITMAP") {
216 util
::register_bitmap
($declare, $declare->{NAME
});
220 #####################################################################
224 my($typedef) = shift;
225 HeaderType
($typedef, $typedef->{DATA
}, $typedef->{NAME
});
226 pidl
";\n" unless ($typedef->{DATA
}->{TYPE
} eq "BITMAP");
229 #####################################################################
230 # prototype a typedef
231 sub HeaderTypedefProto
($)
235 if (needed
::is_needed
("ndr_size_$d->{NAME}")) {
236 if ($d->{DATA
}{TYPE
} eq "STRUCT") {
237 pidl
"size_t ndr_size_$d->{NAME}(const struct $d->{NAME} *r, int flags);\n";
239 if ($d->{DATA
}{TYPE
} eq "UNION") {
240 pidl
"size_t ndr_size_$d->{NAME}(const union $d->{NAME} *r, uint32_t level, int flags);\n";
244 if (!util
::has_property
($d, "public")) {
248 if ($d->{DATA
}{TYPE
} eq "STRUCT") {
249 pidl
"NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $d->{NAME} *r);\n";
250 pidl
"NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $d->{NAME} *r);\n";
251 if (!util
::has_property
($d, "noprint")) {
252 pidl
"void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, struct $d->{NAME} *r);\n";
256 if ($d->{DATA
}{TYPE
} eq "UNION") {
257 pidl
"NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, int ndr_flags, int level, union $d->{NAME} *r);\n";
258 pidl
"NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, int level, union $d->{NAME} *r);\n";
259 if (!util
::has_property
($d, "noprint")) {
260 pidl
"void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, int level, union $d->{NAME} *r);\n";
264 if ($d->{DATA
}{TYPE
} eq "ENUM") {
265 pidl
"NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, int ndr_flags, enum $d->{NAME} r);\n";
266 pidl
"NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, enum $d->{NAME} *r);\n";
267 if (!util
::has_property
($d, "noprint")) {
268 pidl
"void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, enum $d->{NAME} r);\n";
272 if ($d->{DATA
}{TYPE
} eq "BITMAP") {
273 my $type_decl = util
::bitmap_type_decl
($d->{DATA
});
274 pidl
"NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, int ndr_flags, $type_decl r);\n";
275 pidl
"NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, $type_decl *r);\n";
276 if (!util
::has_property
($d, "noprint")) {
277 pidl
"void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r);\n";
282 #####################################################################
287 if (!defined($const->{ARRAY_LEN
})) {
288 pidl
"#define $const->{NAME}\t( $const->{VALUE} )\n";
290 pidl
"#define $const->{NAME}\t $const->{VALUE}\n";
294 #####################################################################
296 sub HeaderFunctionInOut
($$)
301 foreach my $e (@
{$fn->{ELEMENTS
}}) {
302 if (util
::has_property
($e, $prop)) {
308 #####################################################################
309 # determine if we need an "in" or "out" section
310 sub HeaderFunctionInOut_needed
($$)
315 if ($prop eq "out" && $fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
319 foreach my $e (@
{$fn->{ELEMENTS
}}) {
320 if (util
::has_property
($e, $prop)) {
329 #####################################################################
331 sub HeaderFunction
($)
335 pidl
"\nstruct $fn->{NAME} {\n";
339 if (HeaderFunctionInOut_needed
($fn, "in")) {
343 HeaderFunctionInOut
($fn, "in");
350 if (HeaderFunctionInOut_needed
($fn, "out")) {
354 HeaderFunctionInOut
($fn, "out");
355 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
357 pidl util
::map_type
($fn->{RETURN_TYPE
}) . " result;\n";
366 # sigh - some compilers don't like empty structures
368 pidl
"int _dummy_element;\n";
375 #####################################################################
376 # output prototypes for a IDL function
377 sub HeaderFnProto
($$)
379 my $interface = shift;
381 my $name = $fn->{NAME
};
383 pidl
"void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, struct $name *r);\n";
385 if (util
::has_property
($interface, "object")) {
386 pidl
"NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r);\n";
388 pidl
"NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
389 pidl
"struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
395 #####################################################################
396 # generate vtable structure for DCOM interface
399 my $interface = shift;
400 pidl
"struct dcom_$interface->{NAME}_vtable {\n";
401 if (defined($interface->{BASE
})) {
402 pidl
"\tstruct dcom_$interface->{BASE}\_vtable base;\n";
405 my $data = $interface->{DATA
};
406 foreach my $d (@
{$data}) {
407 pidl
"\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $d->{NAME} *r);\n" if ($d->{TYPE
} eq "FUNCTION");
413 #####################################################################
414 # parse the interface definitions
415 sub HeaderInterface
($)
417 my($interface) = shift;
418 my($data) = $interface->{DATA
};
422 pidl
"#ifndef _HEADER_NDR_$interface->{NAME}\n";
423 pidl
"#define _HEADER_NDR_$interface->{NAME}\n\n";
425 if (defined $interface->{PROPERTIES
}->{depends
}) {
426 my @d = split / /, $interface->{PROPERTIES
}->{depends
};
428 pidl
"#include \"librpc/gen_ndr/ndr_$i\.h\"\n";
432 if (defined $interface->{PROPERTIES
}->{uuid
}) {
433 my $name = uc $interface->{NAME
};
434 pidl
"#define DCERPC_$name\_UUID " .
435 util
::make_str
($interface->{PROPERTIES
}->{uuid
}) . "\n";
437 if(!defined $interface->{PROPERTIES
}->{version
}) { $interface->{PROPERTIES
}->{version
} = "0.0"; }
438 pidl
"#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n";
440 pidl
"#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n";
442 if(!defined $interface->{PROPERTIES
}->{helpstring
}) { $interface->{PROPERTIES
}->{helpstring
} = "NULL"; }
443 pidl
"#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n";
445 pidl
"\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
446 pidl
"NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
449 foreach my $d (@
{$data}) {
450 if ($d->{TYPE
} eq "FUNCTION") {
451 my $u_name = uc $d->{NAME
};
452 pidl
"#define DCERPC_$u_name (";
454 if (defined($interface->{BASE
})) {
455 pidl
"DCERPC_" . uc $interface->{BASE
} . "_CALL_COUNT + ";
458 pidl
sprintf("0x%02x", $count) . ")\n";
463 pidl
"\n#define DCERPC_" . uc $interface->{NAME
} . "_CALL_COUNT (";
465 if (defined($interface->{BASE
})) {
466 pidl
"DCERPC_" . uc $interface->{BASE
} . "_CALL_COUNT + ";
471 foreach my $d (@
{$data}) {
472 ($d->{TYPE
} eq "CONST") &&
474 ($d->{TYPE
} eq "DECLARE") &&
476 ($d->{TYPE
} eq "TYPEDEF") &&
478 ($d->{TYPE
} eq "TYPEDEF") &&
479 HeaderTypedefProto
($d);
480 ($d->{TYPE
} eq "FUNCTION") &&
482 ($d->{TYPE
} eq "FUNCTION") &&
483 HeaderFnProto
($interface, $d);
486 (util
::has_property
($interface, "object")) &&
487 HeaderVTable
($interface);
489 pidl
"#endif /* _HEADER_NDR_$interface->{NAME} */\n";
492 #####################################################################
493 # parse a parsed IDL into a C header
500 pidl
"/* header auto-generated by pidl */\n\n";
501 foreach my $x (@
{$idl}) {
502 if ($x->{TYPE
} eq "INTERFACE") {
503 needed
::BuildNeeded
($x);