r5345: Some more minor code readability fixes.
[Samba/gebeck_regimport.git] / source4 / build / pidl / header.pm
blob33e7d56208be59af5cb54238d7befd93ce069760
1 ###################################################
2 # create C header files for an IDL structure
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
6 package IdlHeader;
8 use strict;
9 use needed;
11 my($res);
12 my($tab_depth);
14 sub pidl ($)
16 $res .= shift;
19 sub tabs()
21 for (my($i)=0; $i < $tab_depth; $i++) {
22 pidl "\t";
26 #####################################################################
27 # parse a properties list
28 sub HeaderProperties($)
30 my($props) = shift;
32 return;
34 foreach my $d (@{$props}) {
35 if (ref($d) ne "HASH") {
36 pidl "/* [$d] */ ";
37 } else {
38 foreach my $k (keys %{$d}) {
39 pidl "/* [$k($d->{$k})] */ ";
45 #####################################################################
46 # parse a structure element
47 sub HeaderElement($)
49 my($element) = shift;
51 (defined $element->{PROPERTIES}) && HeaderProperties($element->{PROPERTIES});
52 pidl tabs();
53 HeaderType($element, $element->{TYPE}, "");
54 pidl " ";
55 if ($element->{POINTERS} &&
56 $element->{TYPE} ne "string") {
57 my($n) = $element->{POINTERS};
58 for (my($i)=$n; $i > 0; $i--) {
59 pidl "*";
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
67 pidl "*";
69 pidl "$element->{NAME}";
70 if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) {
71 pidl "[$element->{ARRAY_LEN}]";
73 pidl ";\n";
76 #####################################################################
77 # parse a struct
78 sub HeaderStruct($$)
80 my($struct) = shift;
81 my($name) = shift;
82 pidl "\nstruct $name {\n";
83 $tab_depth++;
84 my $el_count=0;
85 if (defined $struct->{ELEMENTS}) {
86 foreach my $e (@{$struct->{ELEMENTS}}) {
87 HeaderElement($e);
88 $el_count++;
91 if ($el_count == 0) {
92 # some compilers can't handle empty structures
93 pidl "\tchar _empty_;\n";
95 $tab_depth--;
96 pidl "}";
99 #####################################################################
100 # parse a enum
101 sub HeaderEnum($$)
103 my($enum) = shift;
104 my($name) = shift;
106 util::register_enum($enum, $name);
108 pidl "\nenum $name {\n";
109 $tab_depth++;
110 my $els = \@{$enum->{ELEMENTS}};
111 foreach my $i (0 .. $#{$els}-1) {
112 my $e = ${$els}[$i];
113 tabs();
114 chomp $e;
115 pidl "$e,\n";
118 my $e = ${$els}[$#{$els}];
119 tabs();
120 chomp $e;
121 if ($e !~ /^(.*?)\s*$/) {
122 die "Bad enum $name\n";
124 pidl "$1\n";
125 $tab_depth--;
126 pidl "}";
129 #####################################################################
130 # parse a bitmap
131 sub HeaderBitmap($$)
133 my($bitmap) = shift;
134 my($name) = shift;
136 util::register_bitmap($bitmap, $name);
138 pidl "\n/* bitmap $name */\n";
140 my $els = \@{$bitmap->{ELEMENTS}};
141 foreach my $i (0 .. $#{$els}) {
142 my $e = ${$els}[$i];
143 chomp $e;
144 pidl "#define $e\n";
147 pidl "\n";
150 #####################################################################
151 # parse a union
152 sub HeaderUnion($$)
154 my($union) = shift;
155 my($name) = shift;
156 my %done = ();
158 (defined $union->{PROPERTIES}) && HeaderProperties($union->{PROPERTIES});
159 pidl "\nunion $name {\n";
160 $tab_depth++;
161 foreach my $e (@{$union->{ELEMENTS}}) {
162 if ($e->{TYPE} ne "EMPTY") {
163 if (! defined $done{$e->{NAME}}) {
164 HeaderElement($e);
166 $done{$e->{NAME}} = 1;
169 $tab_depth--;
170 pidl "}";
173 #####################################################################
174 # parse a type
175 sub HeaderType($$$)
177 my $e = shift;
178 my($data) = shift;
179 my($name) = shift;
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);
189 return;
191 if ($data =~ "string") {
192 pidl "const char *";
193 } elsif (util::is_enum($e->{TYPE})) {
194 pidl "enum $data";
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")) {
201 pidl "union $data";
202 } else {
203 pidl "struct $data";
207 #####################################################################
208 # parse a declare
209 sub HeaderDeclare($)
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 #####################################################################
221 # parse a typedef
222 sub HeaderTypedef($)
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($)
233 my($d) = shift;
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")) {
245 return;
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 #####################################################################
283 # parse a const
284 sub HeaderConst($)
286 my($const) = shift;
287 if (!defined($const->{ARRAY_LEN})) {
288 pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
289 } else {
290 pidl "#define $const->{NAME}\t $const->{VALUE}\n";
294 #####################################################################
295 # parse a function
296 sub HeaderFunctionInOut($$)
298 my($fn) = shift;
299 my($prop) = shift;
301 foreach my $e (@{$fn->{ELEMENTS}}) {
302 if (util::has_property($e, $prop)) {
303 HeaderElement($e);
308 #####################################################################
309 # determine if we need an "in" or "out" section
310 sub HeaderFunctionInOut_needed($$)
312 my($fn) = shift;
313 my($prop) = shift;
315 if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
316 return 1;
319 foreach my $e (@{$fn->{ELEMENTS}}) {
320 if (util::has_property($e, $prop)) {
321 return 1;
325 return undef;
329 #####################################################################
330 # parse a function
331 sub HeaderFunction($)
333 my($fn) = shift;
335 pidl "\nstruct $fn->{NAME} {\n";
336 $tab_depth++;
337 my $needed = 0;
339 if (HeaderFunctionInOut_needed($fn, "in")) {
340 tabs();
341 pidl "struct {\n";
342 $tab_depth++;
343 HeaderFunctionInOut($fn, "in");
344 $tab_depth--;
345 tabs();
346 pidl "} in;\n\n";
347 $needed++;
350 if (HeaderFunctionInOut_needed($fn, "out")) {
351 tabs();
352 pidl "struct {\n";
353 $tab_depth++;
354 HeaderFunctionInOut($fn, "out");
355 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
356 tabs();
357 pidl util::map_type($fn->{RETURN_TYPE}) . " result;\n";
359 $tab_depth--;
360 tabs();
361 pidl "} out;\n\n";
362 $needed++;
365 if (! $needed) {
366 # sigh - some compilers don't like empty structures
367 tabs();
368 pidl "int _dummy_element;\n";
371 $tab_depth--;
372 pidl "};\n\n";
375 #####################################################################
376 # output prototypes for a IDL function
377 sub HeaderFnProto($$)
379 my $interface = shift;
380 my $fn = 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";
387 } else {
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";
391 pidl "\n";
395 #####################################################################
396 # generate vtable structure for DCOM interface
397 sub HeaderVTable($)
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");
409 pidl "};\n\n";
413 #####################################################################
414 # parse the interface definitions
415 sub HeaderInterface($)
417 my($interface) = shift;
418 my($data) = $interface->{DATA};
420 my $count = 0;
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};
427 foreach my $i (@d) {
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";
459 $count++;
463 pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT (";
465 if (defined($interface->{BASE})) {
466 pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
469 pidl "$count)\n\n";
471 foreach my $d (@{$data}) {
472 ($d->{TYPE} eq "CONST") &&
473 HeaderConst($d);
474 ($d->{TYPE} eq "DECLARE") &&
475 HeaderDeclare($d);
476 ($d->{TYPE} eq "TYPEDEF") &&
477 HeaderTypedef($d);
478 ($d->{TYPE} eq "TYPEDEF") &&
479 HeaderTypedefProto($d);
480 ($d->{TYPE} eq "FUNCTION") &&
481 HeaderFunction($d);
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
494 sub Parse($)
496 my($idl) = shift;
497 $tab_depth = 0;
499 $res = "";
500 pidl "/* header auto-generated by pidl */\n\n";
501 foreach my $x (@{$idl}) {
502 if ($x->{TYPE} eq "INTERFACE") {
503 needed::BuildNeeded($x);
504 HeaderInterface($x);
507 return $res;