1 ###################################################
2 # create C header files for an IDL structure
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
22 for (my($i)=0; $i < $tab_depth; $i++) {
27 #####################################################################
28 # parse a properties list
29 sub HeaderProperties($$)
37 foreach my $d (keys %{$props}) {
38 next if ($ignores->{$d});
39 if($props->{$d} ne "1") {
40 $ret.= "$d(" . $props->{$d} . "),";
47 pidl "/* [" . substr($ret, 0, -1) . "] */";
51 #####################################################################
52 # parse a structure element
57 if (defined $element->{PROPERTIES}) {
58 HeaderProperties($element->{PROPERTIES}, {"in" => 1, "out" => 1});
61 HeaderType($element, $element->{TYPE}, "");
63 if ($element->{POINTERS} &&
64 $element->{TYPE} ne "string") {
65 my($n) = $element->{POINTERS};
66 for (my($i)=$n; $i > 0; $i--) {
70 if (defined $element->{ARRAY_LEN} &&
71 !util::is_constant($element->{ARRAY_LEN}) &&
72 !$element->{POINTERS}) {
73 # conformant arrays are ugly! I choose to implement them with
74 # pointers instead of the [1] method
77 pidl "$element->{NAME}";
78 if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) {
79 pidl "[$element->{ARRAY_LEN}]";
84 #####################################################################
90 pidl "\nstruct $name {\n";
93 if (defined $struct->{ELEMENTS}) {
94 foreach my $e (@{$struct->{ELEMENTS}}) {
100 # some compilers can't handle empty structures
101 pidl "\tchar _empty_;\n";
107 #####################################################################
114 pidl "\nenum $name {\n";
116 my $els = \@{$enum->{ELEMENTS}};
117 foreach my $i (0 .. $#{$els}-1) {
124 my $e = ${$els}[$#{$els}];
127 if ($e !~ /^(.*?)\s*$/) {
128 die "Bad enum $name\n";
135 #####################################################################
142 pidl "\n/* bitmap $name */\n";
144 my $els = \@{$bitmap->{ELEMENTS}};
145 foreach my $i (0 .. $#{$els}) {
154 #####################################################################
162 if (defined $union->{PROPERTIES}) {
163 HeaderProperties($union->{PROPERTIES}, {});
165 pidl "\nunion $name {\n";
167 foreach my $e (@{$union->{ELEMENTS}}) {
168 if ($e->{TYPE} ne "EMPTY") {
169 if (! defined $done{$e->{NAME}}) {
172 $done{$e->{NAME}} = 1;
179 #####################################################################
186 if (ref($data) eq "HASH") {
187 ($data->{TYPE} eq "ENUM") &&
188 HeaderEnum($data, $name);
189 ($data->{TYPE} eq "BITMAP") &&
190 HeaderBitmap($data, $name);
191 ($data->{TYPE} eq "STRUCT") &&
192 HeaderStruct($data, $name);
193 ($data->{TYPE} eq "UNION") &&
194 HeaderUnion($data, $name);
199 if (my $t = typelist::getType($e->{TYPE})) {
203 if ($data =~ "string") {
205 } elsif (not defined($dt->{TYPE})) {
208 if ($dt->{TYPE} eq "ENUM") {
210 } elsif ($dt->{TYPE} eq "BITMAP") {
211 pidl util::bitmap_type_decl($dt);
212 } elsif ($dt->{TYPE} eq "SCALAR") {
213 pidl util::map_type($data);
214 } elsif ($dt->{TYPE} eq "UNION") {
216 } elsif ($dt->{TYPE} eq "STRUCT") {
219 print "Unknown data type type $dt->{TYPE}\n";
224 #####################################################################
228 my($typedef) = shift;
229 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
230 pidl ";\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP");
233 #####################################################################
234 # prototype a typedef
235 sub HeaderTypedefProto($)
239 if (needed::is_needed("ndr_size_$d->{NAME}")) {
240 if ($d->{DATA}{TYPE} eq "STRUCT") {
241 pidl "size_t ndr_size_$d->{NAME}(const struct $d->{NAME} *r, int flags);\n";
243 if ($d->{DATA}{TYPE} eq "UNION") {
244 pidl "size_t ndr_size_$d->{NAME}(const union $d->{NAME} *r, uint32_t level, int flags);\n";
248 return unless util::has_property($d, "public");
250 my $tf = NdrParser::get_typefamily($d->{DATA}{TYPE});
252 my $pull_args = $tf->{PULL_FN_ARGS}->($d);
253 my $push_args = $tf->{PUSH_FN_ARGS}->($d);
254 my $print_args = $tf->{PRINT_FN_ARGS}->($d);
255 pidl "NTSTATUS ndr_push_$d->{NAME}($push_args);\n";
256 pidl "NTSTATUS ndr_pull_$d->{NAME}($pull_args);\n";
257 if (!util::has_property($d, "noprint")) {
258 pidl "void ndr_print_$d->{NAME}($print_args);\n";
262 #####################################################################
267 if (!defined($const->{ARRAY_LEN})) {
268 pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
270 pidl "#define $const->{NAME}\t $const->{VALUE}\n";
274 #####################################################################
276 sub HeaderFunctionInOut($$)
281 foreach my $e (@{$fn->{ELEMENTS}}) {
282 if (util::has_property($e, $prop)) {
288 #####################################################################
289 # determine if we need an "in" or "out" section
290 sub HeaderFunctionInOut_needed($$)
295 if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
299 foreach my $e (@{$fn->{ELEMENTS}}) {
300 if (util::has_property($e, $prop)) {
309 #####################################################################
311 sub HeaderFunction($)
315 pidl "\nstruct $fn->{NAME} {\n";
319 if (HeaderFunctionInOut_needed($fn, "in")) {
323 HeaderFunctionInOut($fn, "in");
330 if (HeaderFunctionInOut_needed($fn, "out")) {
334 HeaderFunctionInOut($fn, "out");
335 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
337 pidl util::map_type($fn->{RETURN_TYPE}) . " result;\n";
346 # sigh - some compilers don't like empty structures
348 pidl "int _dummy_element;\n";
355 #####################################################################
356 # output prototypes for a IDL function
357 sub HeaderFnProto($$)
359 my $interface = shift;
361 my $name = $fn->{NAME};
363 pidl "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, struct $name *r);\n";
365 if (util::has_property($interface, "object")) {
366 pidl "NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r);\n";
368 pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
369 pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
375 #####################################################################
376 # generate vtable structure for DCOM interface
379 my $interface = shift;
380 pidl "struct dcom_$interface->{NAME}_vtable {\n";
381 if (defined($interface->{BASE})) {
382 pidl "\tstruct dcom_$interface->{BASE}\_vtable base;\n";
385 my $data = $interface->{DATA};
386 foreach my $d (@{$data}) {
387 pidl "\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $d->{NAME} *r);\n" if ($d->{TYPE} eq "FUNCTION");
393 #####################################################################
394 # parse the interface definitions
395 sub HeaderInterface($)
397 my($interface) = shift;
398 my($data) = $interface->{DATA};
402 pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n";
403 pidl "#define _HEADER_NDR_$interface->{NAME}\n\n";
405 if (defined $interface->{PROPERTIES}->{depends}) {
406 my @d = split / /, $interface->{PROPERTIES}->{depends};
408 pidl "#include \"librpc/gen_ndr/ndr_$i\.h\"\n";
412 if (defined $interface->{PROPERTIES}->{uuid}) {
413 my $name = uc $interface->{NAME};
414 pidl "#define DCERPC_$name\_UUID " .
415 util::make_str($interface->{PROPERTIES}->{uuid}) . "\n";
417 if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
418 pidl "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n";
420 pidl "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n";
422 if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; }
423 pidl "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n";
425 pidl "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
426 pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
429 foreach my $d (@{$data}) {
430 if ($d->{TYPE} eq "FUNCTION") {
431 my $u_name = uc $d->{NAME};
432 pidl "#define DCERPC_$u_name (";
434 if (defined($interface->{BASE})) {
435 pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
438 pidl sprintf("0x%02x", $count) . ")\n";
443 pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT (";
445 if (defined($interface->{BASE})) {
446 pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
451 foreach my $d (@{$data}) {
452 ($d->{TYPE} eq "CONST") &&
454 ($d->{TYPE} eq "TYPEDEF") &&
456 ($d->{TYPE} eq "TYPEDEF") &&
457 HeaderTypedefProto($d);
458 ($d->{TYPE} eq "FUNCTION") &&
460 ($d->{TYPE} eq "FUNCTION") &&
461 HeaderFnProto($interface, $d);
464 (util::has_property($interface, "object")) &&
465 HeaderVTable($interface);
467 pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
470 #####################################################################
471 # parse a parsed IDL into a C header
477 NdrParser::Load($idl);
480 pidl "/* header auto-generated by pidl */\n\n";
481 foreach my $x (@{$idl}) {
482 if ($x->{TYPE} eq "INTERFACE") {
483 needed::BuildNeeded($x);