r5443: Fix HeaderProperties(). Not re-enabling yet because I don't know why it
[Samba/gebeck_regimport.git] / source4 / build / pidl / header.pm
blobd450886604f7c6e7c375dc685f95314088783874
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;
31 my($ignores) = shift;
32 my $ret = "";
34 return;
36 foreach my $d (keys %{$props}) {
37 next if ($ignores->{$d});
38 if($props->{$d} ne "1") {
39 $ret.= "$d(" . $props->{$d} . "),";
40 } else {
41 $ret.="$d,";
45 if ($ret) {
46 pidl "/* [" . substr($ret, 0, -1) . "] */";
50 #####################################################################
51 # parse a structure element
52 sub HeaderElement($)
54 my($element) = shift;
56 if (defined $element->{PROPERTIES}) {
57 HeaderProperties($element->{PROPERTIES}, {"in" => 1, "out" => 1});
59 pidl tabs();
60 HeaderType($element, $element->{TYPE}, "");
61 pidl " ";
62 if ($element->{POINTERS} &&
63 $element->{TYPE} ne "string") {
64 my($n) = $element->{POINTERS};
65 for (my($i)=$n; $i > 0; $i--) {
66 pidl "*";
69 if (defined $element->{ARRAY_LEN} &&
70 !util::is_constant($element->{ARRAY_LEN}) &&
71 !$element->{POINTERS}) {
72 # conformant arrays are ugly! I choose to implement them with
73 # pointers instead of the [1] method
74 pidl "*";
76 pidl "$element->{NAME}";
77 if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) {
78 pidl "[$element->{ARRAY_LEN}]";
80 pidl ";\n";
83 #####################################################################
84 # parse a struct
85 sub HeaderStruct($$)
87 my($struct) = shift;
88 my($name) = shift;
89 pidl "\nstruct $name {\n";
90 $tab_depth++;
91 my $el_count=0;
92 if (defined $struct->{ELEMENTS}) {
93 foreach my $e (@{$struct->{ELEMENTS}}) {
94 HeaderElement($e);
95 $el_count++;
98 if ($el_count == 0) {
99 # some compilers can't handle empty structures
100 pidl "\tchar _empty_;\n";
102 $tab_depth--;
103 pidl "}";
106 #####################################################################
107 # parse a enum
108 sub HeaderEnum($$)
110 my($enum) = shift;
111 my($name) = shift;
113 pidl "\nenum $name {\n";
114 $tab_depth++;
115 my $els = \@{$enum->{ELEMENTS}};
116 foreach my $i (0 .. $#{$els}-1) {
117 my $e = ${$els}[$i];
118 tabs();
119 chomp $e;
120 pidl "$e,\n";
123 my $e = ${$els}[$#{$els}];
124 tabs();
125 chomp $e;
126 if ($e !~ /^(.*?)\s*$/) {
127 die "Bad enum $name\n";
129 pidl "$1\n";
130 $tab_depth--;
131 pidl "}";
134 #####################################################################
135 # parse a bitmap
136 sub HeaderBitmap($$)
138 my($bitmap) = shift;
139 my($name) = shift;
141 pidl "\n/* bitmap $name */\n";
143 my $els = \@{$bitmap->{ELEMENTS}};
144 foreach my $i (0 .. $#{$els}) {
145 my $e = ${$els}[$i];
146 chomp $e;
147 pidl "#define $e\n";
150 pidl "\n";
153 #####################################################################
154 # parse a union
155 sub HeaderUnion($$)
157 my($union) = shift;
158 my($name) = shift;
159 my %done = ();
161 if (defined $union->{PROPERTIES}) {
162 HeaderProperties($union->{PROPERTIES}, {});
164 pidl "\nunion $name {\n";
165 $tab_depth++;
166 foreach my $e (@{$union->{ELEMENTS}}) {
167 if ($e->{TYPE} ne "EMPTY") {
168 if (! defined $done{$e->{NAME}}) {
169 HeaderElement($e);
171 $done{$e->{NAME}} = 1;
174 $tab_depth--;
175 pidl "}";
178 #####################################################################
179 # parse a type
180 sub HeaderType($$$)
182 my $e = shift;
183 my($data) = shift;
184 my($name) = shift;
185 if (ref($data) eq "HASH") {
186 ($data->{TYPE} eq "ENUM") &&
187 HeaderEnum($data, $name);
188 ($data->{TYPE} eq "BITMAP") &&
189 HeaderBitmap($data, $name);
190 ($data->{TYPE} eq "STRUCT") &&
191 HeaderStruct($data, $name);
192 ($data->{TYPE} eq "UNION") &&
193 HeaderUnion($data, $name);
194 return;
197 my $dt;
198 if (my $t = NdrParser::get_typedef($e->{TYPE})) {
199 $dt = $t->{DATA};
202 if ($data =~ "string") {
203 pidl "const char *";
204 } elsif (not defined($dt->{TYPE})) {
205 pidl "struct $data";
206 } else {
207 if ($dt->{TYPE} eq "ENUM") {
208 pidl "enum $data";
209 } elsif ($dt->{TYPE} eq "BITMAP") {
210 pidl util::bitmap_type_decl($dt);
211 } elsif ($dt->{TYPE} eq "SCALAR") {
212 pidl util::map_type($data);
213 } elsif ($dt->{TYPE} eq "UNION") {
214 pidl "union $data";
215 } elsif ($dt->{TYPE} eq "STRUCT") {
216 pidl "struct $data";
217 } else {
218 print "Unknown data type type $dt->{TYPE}\n";
223 #####################################################################
224 # parse a typedef
225 sub HeaderTypedef($)
227 my($typedef) = shift;
228 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
229 pidl ";\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP");
232 #####################################################################
233 # prototype a typedef
234 sub HeaderTypedefProto($)
236 my($d) = shift;
238 if (needed::is_needed("ndr_size_$d->{NAME}")) {
239 if ($d->{DATA}{TYPE} eq "STRUCT") {
240 pidl "size_t ndr_size_$d->{NAME}(const struct $d->{NAME} *r, int flags);\n";
242 if ($d->{DATA}{TYPE} eq "UNION") {
243 pidl "size_t ndr_size_$d->{NAME}(const union $d->{NAME} *r, uint32_t level, int flags);\n";
247 return unless util::has_property($d, "public");
249 my $tf = NdrParser::get_typefamily($d->{DATA}{TYPE});
251 my $pull_args = $tf->{PULL_FN_ARGS}->($d);
252 my $push_args = $tf->{PUSH_FN_ARGS}->($d);
253 my $print_args = $tf->{PRINT_FN_ARGS}->($d);
254 pidl "NTSTATUS ndr_push_$d->{NAME}($push_args);\n";
255 pidl "NTSTATUS ndr_pull_$d->{NAME}($pull_args);\n";
256 if (!util::has_property($d, "noprint")) {
257 pidl "void ndr_print_$d->{NAME}($print_args);\n";
261 #####################################################################
262 # parse a const
263 sub HeaderConst($)
265 my($const) = shift;
266 if (!defined($const->{ARRAY_LEN})) {
267 pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
268 } else {
269 pidl "#define $const->{NAME}\t $const->{VALUE}\n";
273 #####################################################################
274 # parse a function
275 sub HeaderFunctionInOut($$)
277 my($fn) = shift;
278 my($prop) = shift;
280 foreach my $e (@{$fn->{ELEMENTS}}) {
281 if (util::has_property($e, $prop)) {
282 HeaderElement($e);
287 #####################################################################
288 # determine if we need an "in" or "out" section
289 sub HeaderFunctionInOut_needed($$)
291 my($fn) = shift;
292 my($prop) = shift;
294 if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
295 return 1;
298 foreach my $e (@{$fn->{ELEMENTS}}) {
299 if (util::has_property($e, $prop)) {
300 return 1;
304 return undef;
308 #####################################################################
309 # parse a function
310 sub HeaderFunction($)
312 my($fn) = shift;
314 pidl "\nstruct $fn->{NAME} {\n";
315 $tab_depth++;
316 my $needed = 0;
318 if (HeaderFunctionInOut_needed($fn, "in")) {
319 tabs();
320 pidl "struct {\n";
321 $tab_depth++;
322 HeaderFunctionInOut($fn, "in");
323 $tab_depth--;
324 tabs();
325 pidl "} in;\n\n";
326 $needed++;
329 if (HeaderFunctionInOut_needed($fn, "out")) {
330 tabs();
331 pidl "struct {\n";
332 $tab_depth++;
333 HeaderFunctionInOut($fn, "out");
334 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
335 tabs();
336 pidl util::map_type($fn->{RETURN_TYPE}) . " result;\n";
338 $tab_depth--;
339 tabs();
340 pidl "} out;\n\n";
341 $needed++;
344 if (! $needed) {
345 # sigh - some compilers don't like empty structures
346 tabs();
347 pidl "int _dummy_element;\n";
350 $tab_depth--;
351 pidl "};\n\n";
354 #####################################################################
355 # output prototypes for a IDL function
356 sub HeaderFnProto($$)
358 my $interface = shift;
359 my $fn = shift;
360 my $name = $fn->{NAME};
362 pidl "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, struct $name *r);\n";
364 if (util::has_property($interface, "object")) {
365 pidl "NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r);\n";
366 } else {
367 pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
368 pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
370 pidl "\n";
374 #####################################################################
375 # generate vtable structure for DCOM interface
376 sub HeaderVTable($)
378 my $interface = shift;
379 pidl "struct dcom_$interface->{NAME}_vtable {\n";
380 if (defined($interface->{BASE})) {
381 pidl "\tstruct dcom_$interface->{BASE}\_vtable base;\n";
384 my $data = $interface->{DATA};
385 foreach my $d (@{$data}) {
386 pidl "\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $d->{NAME} *r);\n" if ($d->{TYPE} eq "FUNCTION");
388 pidl "};\n\n";
392 #####################################################################
393 # parse the interface definitions
394 sub HeaderInterface($)
396 my($interface) = shift;
397 my($data) = $interface->{DATA};
399 my $count = 0;
401 pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n";
402 pidl "#define _HEADER_NDR_$interface->{NAME}\n\n";
404 if (defined $interface->{PROPERTIES}->{depends}) {
405 my @d = split / /, $interface->{PROPERTIES}->{depends};
406 foreach my $i (@d) {
407 pidl "#include \"librpc/gen_ndr/ndr_$i\.h\"\n";
411 if (defined $interface->{PROPERTIES}->{uuid}) {
412 my $name = uc $interface->{NAME};
413 pidl "#define DCERPC_$name\_UUID " .
414 util::make_str($interface->{PROPERTIES}->{uuid}) . "\n";
416 if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
417 pidl "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n";
419 pidl "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n";
421 if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; }
422 pidl "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n";
424 pidl "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
425 pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
428 foreach my $d (@{$data}) {
429 if ($d->{TYPE} eq "FUNCTION") {
430 my $u_name = uc $d->{NAME};
431 pidl "#define DCERPC_$u_name (";
433 if (defined($interface->{BASE})) {
434 pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
437 pidl sprintf("0x%02x", $count) . ")\n";
438 $count++;
442 pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT (";
444 if (defined($interface->{BASE})) {
445 pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
448 pidl "$count)\n\n";
450 foreach my $d (@{$data}) {
451 ($d->{TYPE} eq "CONST") &&
452 HeaderConst($d);
453 ($d->{TYPE} eq "TYPEDEF") &&
454 HeaderTypedef($d);
455 ($d->{TYPE} eq "TYPEDEF") &&
456 HeaderTypedefProto($d);
457 ($d->{TYPE} eq "FUNCTION") &&
458 HeaderFunction($d);
459 ($d->{TYPE} eq "FUNCTION") &&
460 HeaderFnProto($interface, $d);
463 (util::has_property($interface, "object")) &&
464 HeaderVTable($interface);
466 pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
469 #####################################################################
470 # parse a parsed IDL into a C header
471 sub Parse($)
473 my($idl) = shift;
474 $tab_depth = 0;
476 NdrParser::Load($idl);
478 $res = "";
479 pidl "/* header auto-generated by pidl */\n\n";
480 foreach my $x (@{$idl}) {
481 if ($x->{TYPE} eq "INTERFACE") {
482 needed::BuildNeeded($x);
483 HeaderInterface($x);
486 return $res;