1 ###################################################
2 # create C header files for an IDL structure
3 # Copyright tridge@samba.org 2000
4 # Copyright jelmer@samba.org 2005
5 # released under the GNU GPL
7 package Parse::Pidl::Samba4::Header;
11 @EXPORT_OK = qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
14 use Parse::Pidl qw(fatal);
15 use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
16 use Parse::Pidl::Util qw(has_property is_constant unmake_str ParseExpr);
17 use Parse::Pidl::Samba4 qw(is_intree ElementStars ArrayBrackets choose_header);
19 use vars qw($VERSION);
25 sub pidl($) { $res .= shift; }
30 $res .="\t" foreach (1..$tab_depth);
34 #####################################################################
35 # parse a properties list
36 sub HeaderProperties($$)
38 my($props,$ignores) = @_;
41 foreach my $d (keys %{$props}) {
42 next if (grep(/^$d$/, @$ignores));
43 if($props->{$d} ne "1") {
44 $ret.= "$d($props->{$d}),";
51 pidl "/* [" . substr($ret, 0, -1) . "] */";
55 #####################################################################
56 # parse a structure element
62 if (has_property($element, "represent_as")) {
63 pidl mapTypeName($element->{PROPERTIES}->{represent_as})." ";
65 if (ref($element->{TYPE}) eq "HASH") {
66 HeaderType($element, $element->{TYPE}, $element->{TYPE}->{NAME});
68 HeaderType($element, $element->{TYPE}, "");
70 pidl " ".ElementStars($element);
72 pidl $element->{NAME};
73 pidl ArrayBrackets($element);
76 if (defined $element->{PROPERTIES}) {
77 HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
82 #####################################################################
84 sub HeaderStruct($$;$)
86 my($struct,$name,$tail) = @_;
88 pidl $tail if defined($tail) and not defined($struct->{ELEMENTS});
89 return if (not defined($struct->{ELEMENTS}));
93 foreach (@{$struct->{ELEMENTS}}) {
98 # some compilers can't handle empty structures
99 pidl tabs()."char _empty_;\n";
103 if (defined $struct->{PROPERTIES}) {
104 HeaderProperties($struct->{PROPERTIES}, []);
106 pidl $tail if defined($tail);
109 #####################################################################
113 my($enum,$name,$tail) = @_;
117 if (defined($enum->{ELEMENTS})) {
118 pidl "\n#ifndef USE_UINT_ENUMS\n";
121 foreach my $e (@{$enum->{ELEMENTS}}) {
123 unless ($first) { pidl ",\n"; }
126 @enum_els = split(/=/, $e);
127 if (@enum_els == 2) {
145 pidl " { __do_not_use_enum_$name=0x7FFFFFFF}\n";
146 foreach my $e (@{$enum->{ELEMENTS}}) {
150 if ($t =~ /(.*)=(.*)/) {
154 fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
155 unless ($without_val == 0);
160 fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
161 unless ($with_val == 0);
163 pidl "#define $name ( $value )\n";
167 pidl $tail if defined($tail);
170 #####################################################################
174 my($bitmap,$name) = @_;
176 return unless defined($bitmap->{ELEMENTS});
178 pidl "/* bitmap $name */\n";
179 pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
183 #####################################################################
185 sub HeaderUnion($$;$)
187 my($union,$name,$tail) = @_;
191 pidl $tail if defined($tail) and not defined($union->{ELEMENTS});
192 return if (not defined($union->{ELEMENTS}));
196 foreach my $e (@{$union->{ELEMENTS}}) {
197 if ($e->{TYPE} ne "EMPTY") {
198 if (! defined $done{$e->{NAME}}) {
201 $done{$e->{NAME}} = 1;
206 # sigh - some compilers don't like empty structures
207 pidl tabs()."int _dummy_element;\n";
212 if (defined $union->{PROPERTIES}) {
213 HeaderProperties($union->{PROPERTIES}, []);
215 pidl $tail if defined($tail);
218 #####################################################################
222 my($pipe,$name,$tail) = @_;
224 my $struct = $pipe->{DATA};
225 my $e = $struct->{ELEMENTS}[1];
227 pidl "struct $name;\n";
228 pidl "struct $struct->{NAME} {\n";
230 pidl tabs()."uint32_t count;\n";
231 pidl tabs().mapTypeName($e->{TYPE})." *array;\n";
235 if (defined $struct->{PROPERTIES}) {
236 HeaderProperties($struct->{PROPERTIES}, []);
239 pidl $tail if defined($tail);
242 #####################################################################
244 sub HeaderType($$$;$)
246 my($e,$data,$name,$tail) = @_;
247 if (ref($data) eq "HASH") {
248 ($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name, $tail);
249 ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
250 ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
251 ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
252 ($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail);
256 if (has_property($e, "charset")) {
259 pidl mapTypeName($e->{TYPE});
261 pidl $tail if defined($tail);
264 #####################################################################
266 sub HeaderTypedef($;$)
268 my($typedef,$tail) = @_;
269 # Don't print empty "enum foo;", since some compilers don't like it.
270 return if ($typedef->{DATA}->{TYPE} eq "ENUM" and not defined($typedef->{DATA}->{ELEMENTS}));
271 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}, $tail) if defined ($typedef->{DATA});
274 #####################################################################
279 if (!defined($const->{ARRAY_LEN}[0])) {
280 pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
282 pidl "#define $const->{NAME}\t $const->{VALUE}\n";
286 sub ElementDirection($)
290 return "inout" if (has_property($e, "in") and has_property($e, "out"));
291 return "in" if (has_property($e, "in"));
292 return "out" if (has_property($e, "out"));
296 #####################################################################
298 sub HeaderFunctionInOut($$)
302 return unless defined($fn->{ELEMENTS});
304 foreach my $e (@{$fn->{ELEMENTS}}) {
305 HeaderElement($e) if (ElementDirection($e) eq $prop);
309 #####################################################################
310 # determine if we need an "in" or "out" section
311 sub HeaderFunctionInOut_needed($$)
315 return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
317 return undef unless defined($fn->{ELEMENTS});
319 foreach my $e (@{$fn->{ELEMENTS}}) {
320 return 1 if (ElementDirection($e) eq $prop);
328 #####################################################################
330 sub HeaderFunction($)
334 return if ($headerstructs{$fn->{NAME}});
336 $headerstructs{$fn->{NAME}} = 1;
338 pidl "\nstruct $fn->{NAME} {\n";
342 if (HeaderFunctionInOut_needed($fn, "in") or
343 HeaderFunctionInOut_needed($fn, "inout")) {
344 pidl tabs()."struct {\n";
346 HeaderFunctionInOut($fn, "in");
347 HeaderFunctionInOut($fn, "inout");
349 pidl tabs()."} in;\n\n";
353 if (HeaderFunctionInOut_needed($fn, "out") or
354 HeaderFunctionInOut_needed($fn, "inout")) {
355 pidl tabs()."struct {\n";
357 HeaderFunctionInOut($fn, "out");
358 HeaderFunctionInOut($fn, "inout");
359 if (defined($fn->{RETURN_TYPE})) {
360 pidl tabs().mapTypeName($fn->{RETURN_TYPE}) . " result;\n";
363 pidl tabs()."} out;\n\n";
368 # sigh - some compilers don't like empty structures
369 pidl tabs()."int _dummy_element;\n";
379 foreach my $import (@imports) {
380 $import = unmake_str($import);
381 $import =~ s/\.idl$//;
382 pidl choose_header("librpc/gen_ndr/$import\.h", "gen_ndr/$import.h") . "\n";
389 foreach (@includes) {
390 pidl "#include $_\n";
394 #####################################################################
395 # parse the interface definitions
396 sub HeaderInterface($)
398 my($interface) = shift;
400 pidl "#ifndef _HEADER_$interface->{NAME}\n";
401 pidl "#define _HEADER_$interface->{NAME}\n\n";
403 foreach my $c (@{$interface->{CONSTS}}) {
407 foreach my $t (@{$interface->{TYPES}}) {
408 HeaderTypedef($t, ";\n\n") if ($t->{TYPE} eq "TYPEDEF");
409 HeaderStruct($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "STRUCT");
410 HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
411 HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
412 HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
413 HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE");
416 foreach my $fn (@{$interface->{FUNCTIONS}}) {
420 pidl "#endif /* _HEADER_$interface->{NAME} */\n";
427 pidl unmake_str($quote->{DATA}) . "\n";
430 #####################################################################
431 # parse a parsed IDL into a C header
439 pidl "/* header auto-generated by pidl */\n\n";
443 # work out a unique interface name
445 if ($_->{TYPE} eq "INTERFACE") {
446 $ifacename = $_->{NAME};
451 pidl "#ifndef _PIDL_HEADER_$ifacename\n";
452 pidl "#define _PIDL_HEADER_$ifacename\n\n";
455 pidl "#include <util/data_blob.h>\n";
457 pidl "#include <stdint.h>\n";
459 # FIXME: Include this only if NTSTATUS was actually used
460 pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
464 ($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
465 ($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
466 ($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
467 ($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
470 pidl "#endif /* _PIDL_HEADER_$ifacename */\n";
475 sub GenerateStructEnv($$)
480 foreach my $e (@{$x->{ELEMENTS}}) {
481 $env{$e->{NAME}} = "$v->$e->{NAME}";
489 sub EnvSubstituteValue($$)
493 # Substitute the value() values in the env
494 foreach my $e (@{$s->{ELEMENTS}}) {
495 next unless (defined(my $v = has_property($e, "value")));
497 $env->{$e->{NAME}} = ParseExpr($v, $env, $e);
503 sub GenerateFunctionInEnv($;$)
505 my ($fn, $base) = @_;
508 $base = "r->" unless defined($base);
510 foreach my $e (@{$fn->{ELEMENTS}}) {
511 if (grep (/in/, @{$e->{DIRECTION}})) {
512 $env{$e->{NAME}} = $base."in.$e->{NAME}";
519 sub GenerateFunctionOutEnv($;$)
521 my ($fn, $base) = @_;
524 $base = "r->" unless defined($base);
526 foreach my $e (@{$fn->{ELEMENTS}}) {
527 if (grep (/out/, @{$e->{DIRECTION}})) {
528 $env{$e->{NAME}} = $base."out.$e->{NAME}";
529 } elsif (grep (/in/, @{$e->{DIRECTION}})) {
530 $env{$e->{NAME}} = $base."in.$e->{NAME}";