1 ###################################################
2 # create C header files for an IDL structure
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
16 for (my($i)=0; $i < $tab_depth; $i++) {
21 #####################################################################
22 # parse a properties list
23 sub HeaderProperties($)
29 foreach my $d (@{$props}) {
30 if (ref($d) ne "HASH") {
31 $res .= "/* [$d] */ ";
33 foreach my $k (keys %{$d}) {
34 $res .= "/* [$k($d->{$k})] */ ";
40 #####################################################################
41 # parse a structure element
46 (defined $element->{PROPERTIES}) && HeaderProperties($element->{PROPERTIES});
48 HeaderType($element, $element->{TYPE}, "");
50 if ($element->{POINTERS} &&
51 $element->{TYPE} ne "string") {
52 my($n) = $element->{POINTERS};
53 for (my($i)=$n; $i > 0; $i--) {
57 if (defined $element->{ARRAY_LEN} &&
58 !util::is_constant($element->{ARRAY_LEN}) &&
59 !$element->{POINTERS}) {
60 # conformant arrays are ugly! I choose to implement them with
61 # pointers instead of the [1] method
64 $res .= "$element->{NAME}";
65 if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) {
66 $res .= "[$element->{ARRAY_LEN}]";
71 #####################################################################
77 $res .= "\nstruct $name {\n";
80 if (defined $struct->{ELEMENTS}) {
81 foreach my $e (@{$struct->{ELEMENTS}}) {
87 # some compilers can't handle empty structures
88 $res .= "\tchar _empty_;\n";
94 #####################################################################
100 $res .= "\nenum $name {\n";
102 my $els = \@{$enum->{ELEMENTS}};
103 foreach my $i (0 .. $#{$els}-1) {
110 my $e = ${$els}[$#{$els}];
113 if ($e !~ /^(.*?)\s*$/) {
114 die "Bad enum $name\n";
122 #####################################################################
130 (defined $union->{PROPERTIES}) && HeaderProperties($union->{PROPERTIES});
131 $res .= "\nunion $name {\n";
133 foreach my $e (@{$union->{DATA}}) {
134 if ($e->{TYPE} eq "UNION_ELEMENT") {
135 if (! defined $done{$e->{DATA}->{NAME}}) {
136 HeaderElement($e->{DATA});
138 $done{$e->{DATA}->{NAME}} = 1;
145 #####################################################################
152 if (ref($data) eq "HASH") {
153 ($data->{TYPE} eq "ENUM") &&
154 HeaderEnum($data, $name);
155 ($data->{TYPE} eq "STRUCT") &&
156 HeaderStruct($data, $name);
157 ($data->{TYPE} eq "UNION") &&
158 HeaderUnion($data, $name);
161 if ($data =~ "string") {
162 $res .= "const char *";
163 } elsif (util::is_scalar_type($data)) {
165 } elsif (util::has_property($e, "switch_is")) {
166 $res .= "union $data";
168 $res .= "struct $data";
172 #####################################################################
176 my($typedef) = shift;
177 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
181 #####################################################################
182 # prototype a typedef
183 sub HeaderTypedefProto($)
186 if (!util::has_property($d->{DATA}, "public")) {
190 if ($d->{DATA}{TYPE} eq "STRUCT") {
191 $res .= "NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *, int , struct $d->{NAME} *);\n";
192 $res .= "NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *, int , struct $d->{NAME} *);\n";
193 if (!util::has_property($d->{DATA}, "noprint")) {
194 $res .= "void ndr_print_$d->{NAME}(struct ndr_print *, const char *, struct $d->{NAME} *);\n";
197 if (needed::is_needed("ndr_size_$d->{NAME}")) {
198 $res .= "size_t ndr_size_$d->{NAME}(int , struct $d->{NAME} *, int );\n";
201 if ($d->{DATA}{TYPE} eq "UNION") {
202 $res .= "NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *, int, int, union $d->{NAME} *);\n";
203 $res .= "NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *, int, int, union $d->{NAME} *);\n";
204 if (!util::has_property($d->{DATA}, "noprint")) {
205 $res .= "void ndr_print_$d->{NAME}(struct ndr_print *, const char *, int, union $d->{NAME} *);\n";
210 #####################################################################
215 $res .= "#define $const->{NAME}\t( $const->{VALUE} )\n";
218 #####################################################################
220 sub HeaderFunctionInOut($$)
225 foreach my $e (@{$fn->{DATA}}) {
226 if (util::has_property($e, $prop)) {
232 #####################################################################
233 # determine if we need an "in" or "out" section
234 sub HeaderFunctionInOut_needed($$)
239 if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
243 foreach my $e (@{$fn->{DATA}}) {
244 if (util::has_property($e, $prop)) {
253 #####################################################################
255 sub HeaderFunction($)
259 $res .= "\nstruct $fn->{NAME} {\n";
263 if (HeaderFunctionInOut_needed($fn, "in")) {
265 $res .= "struct {\n";
267 HeaderFunctionInOut($fn, "in");
274 if (HeaderFunctionInOut_needed($fn, "out")) {
276 $res .= "struct {\n";
278 HeaderFunctionInOut($fn, "out");
279 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
281 $res .= "$fn->{RETURN_TYPE} result;\n";
285 $res .= "} out;\n\n";
290 # sigh - some compilers don't like empty structures
292 $res .= "int _dummy_element;\n";
299 #####################################################################
300 # output prototypes for a IDL function
304 my $name = $fn->{NAME};
306 my $firstarg = "dcerpc_pipe";
307 if (util::has_property($fn, "object")) {
308 $firstarg = "dcom_interface";
311 $res .= "void ndr_print_$name(struct ndr_print *, const char *, int, struct $name *);\n";
312 $res .= "struct rpc_request *dcerpc_$name\_send(struct $firstarg *, TALLOC_CTX *, struct $name *);\n";
313 $res .= "NTSTATUS dcerpc_$name(struct $firstarg *, TALLOC_CTX *, struct $name *);\n";
317 #####################################################################
318 # parse the interface definitions
319 sub HeaderInterface($)
321 my($interface) = shift;
322 my($data) = $interface->{DATA};
326 $res .= "#ifndef _HEADER_NDR_$interface->{NAME}\n";
327 $res .= "#define _HEADER_NDR_$interface->{NAME}\n\n";
329 if (defined $interface->{PROPERTIES}->{depends}) {
330 my @d = split / /, $interface->{PROPERTIES}->{depends};
332 $res .= "#include \"librpc/gen_ndr/ndr_$i\.h\"\n";
336 if (defined $interface->{PROPERTIES}->{uuid}) {
337 my $name = uc $interface->{NAME};
338 $res .= "#define DCERPC_$name\_UUID " .
339 util::make_str($interface->{PROPERTIES}->{uuid}) . "\n";
341 if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
342 $res .= "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n";
344 $res .= "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n";
346 if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; }
347 $res .= "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n";
349 $res .= "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
350 $res .= "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
353 $count = $interface->{INHERITED_FUNCTIONS};
354 foreach my $d (@{$data}) {
355 if ($d->{TYPE} eq "FUNCTION") {
356 my $u_name = uc $d->{NAME};
357 $res .= "#define DCERPC_$u_name " . sprintf("0x%02x", $count) . "\n";
364 foreach my $d (@{$data}) {
365 ($d->{TYPE} eq "CONST") &&
367 ($d->{TYPE} eq "TYPEDEF") &&
369 ($d->{TYPE} eq "TYPEDEF") &&
370 HeaderTypedefProto($d);
371 ($d->{TYPE} eq "FUNCTION") &&
373 ($d->{TYPE} eq "FUNCTION") &&
377 $res .= "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
380 #####################################################################
381 # parse a parsed IDL into a C header
387 $res = "/* header auto-generated by pidl */\n\n";
388 foreach my $x (@{$idl}) {
389 if ($x->{TYPE} eq "INTERFACE") {
390 needed::BuildNeeded($x);