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 #####################################################################
101 util::register_enum($enum, $name);
103 $res .= "\nenum $name {\n";
105 my $els = \@{$enum->{ELEMENTS}};
106 foreach my $i (0 .. $#{$els}-1) {
113 my $e = ${$els}[$#{$els}];
116 if ($e !~ /^(.*?)\s*$/) {
117 die "Bad enum $name\n";
124 #####################################################################
131 util::register_bitmap($bitmap, $name);
133 $res .= "\n/* bitmap $name */\n";
135 my $els = \@{$bitmap->{ELEMENTS}};
136 foreach my $i (0 .. $#{$els}) {
139 $res .= "#define $e\n";
145 #####################################################################
153 (defined $union->{PROPERTIES}) && HeaderProperties($union->{PROPERTIES});
154 $res .= "\nunion $name {\n";
156 foreach my $e (@{$union->{DATA}}) {
157 if ($e->{TYPE} eq "UNION_ELEMENT") {
158 if (! defined $done{$e->{DATA}->{NAME}}) {
159 HeaderElement($e->{DATA});
161 $done{$e->{DATA}->{NAME}} = 1;
168 #####################################################################
175 if (ref($data) eq "HASH") {
176 ($data->{TYPE} eq "ENUM") &&
177 HeaderEnum($data, $name);
178 ($data->{TYPE} eq "BITMAP") &&
179 HeaderBitmap($data, $name);
180 ($data->{TYPE} eq "STRUCT") &&
181 HeaderStruct($data, $name);
182 ($data->{TYPE} eq "UNION") &&
183 HeaderUnion($data, $name);
186 if ($data =~ "string") {
187 $res .= "const char *";
188 } elsif (util::is_enum($e->{TYPE})) {
189 $res .= "enum $data";
190 } elsif (util::is_bitmap($e->{TYPE})) {
191 my $bitmap = util::get_bitmap($e->{TYPE});
192 $res .= util::bitmap_type_decl($bitmap);
193 } elsif (util::is_scalar_type($data)) {
194 $res .= util::map_type($data);
195 } elsif (util::has_property($e, "switch_is")) {
196 $res .= "union $data";
198 $res .= "struct $data";
202 #####################################################################
206 my($declare) = shift;
208 if ($declare->{DATA}->{TYPE} eq "ENUM") {
209 util::register_enum($declare, $declare->{NAME});
210 } elsif ($declare->{DATA}->{TYPE} eq "BITMAP") {
211 util::register_bitmap($declare, $declare->{NAME});
215 #####################################################################
219 my($typedef) = shift;
220 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
221 $res .= ";\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP");
224 #####################################################################
225 # prototype a typedef
226 sub HeaderTypedefProto($)
230 if (needed::is_needed("ndr_size_$d->{NAME}")) {
231 if ($d->{DATA}{TYPE} eq "STRUCT") {
232 $res .= "size_t ndr_size_$d->{NAME}(const struct $d->{NAME} *r, int flags);\n";
234 if ($d->{DATA}{TYPE} eq "UNION") {
235 $res .= "size_t ndr_size_$d->{NAME}(const union $d->{NAME} *r, uint32_t level, int flags);\n";
239 if (!util::has_property($d, "public")) {
243 if ($d->{DATA}{TYPE} eq "STRUCT") {
244 $res .= "NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $d->{NAME} *r);\n";
245 $res .= "NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $d->{NAME} *r);\n";
246 if (!util::has_property($d, "noprint")) {
247 $res .= "void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, struct $d->{NAME} *r);\n";
251 if ($d->{DATA}{TYPE} eq "UNION") {
252 $res .= "NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, int ndr_flags, int level, union $d->{NAME} *r);\n";
253 $res .= "NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, int level, union $d->{NAME} *r);\n";
254 if (!util::has_property($d, "noprint")) {
255 $res .= "void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, int level, union $d->{NAME} *r);\n";
259 if ($d->{DATA}{TYPE} eq "ENUM") {
260 $res .= "NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, enum $d->{NAME} r);\n";
261 $res .= "NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, enum $d->{NAME} *r);\n";
262 if (!util::has_property($d, "noprint")) {
263 $res .= "void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, enum $d->{NAME} r);\n";
267 if ($d->{DATA}{TYPE} eq "BITMAP") {
268 my $type_decl = util::bitmap_type_decl($d->{DATA});
269 $res .= "NTSTATUS ndr_push_$d->{NAME}(struct ndr_push *ndr, $type_decl r);\n";
270 $res .= "NTSTATUS ndr_pull_$d->{NAME}(struct ndr_pull *ndr, $type_decl *r);\n";
271 if (!util::has_property($d, "noprint")) {
272 $res .= "void ndr_print_$d->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r);\n";
277 #####################################################################
282 if (!defined($const->{ARRAY_LEN})) {
283 $res .= "#define $const->{NAME}\t( $const->{VALUE} )\n";
285 $res .= "#define $const->{NAME}\t $const->{VALUE}\n";
289 #####################################################################
291 sub HeaderFunctionInOut($$)
296 foreach my $e (@{$fn->{DATA}}) {
297 if (util::has_property($e, $prop)) {
303 #####################################################################
304 # determine if we need an "in" or "out" section
305 sub HeaderFunctionInOut_needed($$)
310 if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
314 foreach my $e (@{$fn->{DATA}}) {
315 if (util::has_property($e, $prop)) {
324 #####################################################################
326 sub HeaderFunction($)
330 $res .= "\nstruct $fn->{NAME} {\n";
334 if (HeaderFunctionInOut_needed($fn, "in")) {
336 $res .= "struct {\n";
338 HeaderFunctionInOut($fn, "in");
345 if (HeaderFunctionInOut_needed($fn, "out")) {
347 $res .= "struct {\n";
349 HeaderFunctionInOut($fn, "out");
350 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
352 $res .= util::map_type($fn->{RETURN_TYPE}) . " result;\n";
356 $res .= "} out;\n\n";
361 # sigh - some compilers don't like empty structures
363 $res .= "int _dummy_element;\n";
370 #####################################################################
371 # output prototypes for a IDL function
372 sub HeaderFnProto($$)
374 my $interface = shift;
376 my $name = $fn->{NAME};
378 $res .= "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, struct $name *r);\n";
380 if (util::has_property($interface, "object")) {
381 $res .= "NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r);\n";
383 $res .= "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
384 $res .= "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
390 #####################################################################
391 # generate vtable structure for DCOM interface
394 my $interface = shift;
395 $res .= "struct dcom_$interface->{NAME}_vtable {\n";
396 if (defined($interface->{BASE})) {
397 $res .= "\tstruct dcom_$interface->{BASE}\_vtable base;\n";
400 my $data = $interface->{DATA};
401 foreach my $d (@{$data}) {
402 $res .= "\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $d->{NAME} *r);\n" if ($d->{TYPE} eq "FUNCTION");
408 #####################################################################
409 # parse the interface definitions
410 sub HeaderInterface($)
412 my($interface) = shift;
413 my($data) = $interface->{DATA};
417 $res .= "#ifndef _HEADER_NDR_$interface->{NAME}\n";
418 $res .= "#define _HEADER_NDR_$interface->{NAME}\n\n";
420 if (defined $interface->{PROPERTIES}->{depends}) {
421 my @d = split / /, $interface->{PROPERTIES}->{depends};
423 $res .= "#include \"librpc/gen_ndr/ndr_$i\.h\"\n";
427 if (defined $interface->{PROPERTIES}->{uuid}) {
428 my $name = uc $interface->{NAME};
429 $res .= "#define DCERPC_$name\_UUID " .
430 util::make_str($interface->{PROPERTIES}->{uuid}) . "\n";
432 if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
433 $res .= "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n";
435 $res .= "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n";
437 if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; }
438 $res .= "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n";
440 $res .= "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
441 $res .= "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
444 foreach my $d (@{$data}) {
445 if ($d->{TYPE} eq "FUNCTION") {
446 my $u_name = uc $d->{NAME};
447 $res .= "#define DCERPC_$u_name (";
449 if (defined($interface->{BASE})) {
450 $res .= "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
453 $res .= sprintf("0x%02x", $count) . ")\n";
458 $res .= "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT (";
460 if (defined($interface->{BASE})) {
461 $res .= "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
464 $res .= "$count)\n\n";
466 foreach my $d (@{$data}) {
467 ($d->{TYPE} eq "CONST") &&
469 ($d->{TYPE} eq "DECLARE") &&
471 ($d->{TYPE} eq "TYPEDEF") &&
473 ($d->{TYPE} eq "TYPEDEF") &&
474 HeaderTypedefProto($d);
475 ($d->{TYPE} eq "FUNCTION") &&
477 ($d->{TYPE} eq "FUNCTION") &&
478 HeaderFnProto($interface, $d);
481 (util::has_property($interface, "object")) &&
482 HeaderVTable($interface);
484 $res .= "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
487 #####################################################################
488 # parse a parsed IDL into a C header
494 $res = "/* header auto-generated by pidl */\n\n";
495 foreach my $x (@{$idl}) {
496 if ($x->{TYPE} eq "INTERFACE") {
497 needed::BuildNeeded($x);