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;
12 @EXPORT_OK = qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
15 use Parse::Pidl qw(fatal);
16 use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
17 use Parse::Pidl::Util qw(has_property is_constant unmake_str ParseExpr);
18 use Parse::Pidl::Samba4 qw(is_intree ElementStars ArrayBrackets choose_header);
20 use vars qw($VERSION);
26 sub pidl($) { $res .= shift; }
31 $res .="\t" foreach (1..$tab_depth);
35 #####################################################################
36 # parse a properties list
37 sub HeaderProperties($$)
39 my($props,$ignores) = @_;
42 foreach my $d (keys %{$props}) {
43 next if (grep(/^$d$/, @$ignores));
44 if($props->{$d} ne "1") {
45 $ret.= "$d($props->{$d}),";
52 pidl "/* [" . substr($ret, 0, -1) . "] */";
56 #####################################################################
57 # parse a structure element
63 if (has_property($element, "represent_as")) {
64 pidl mapTypeName($element->{PROPERTIES}->{represent_as})." ";
66 if (ref($element->{TYPE}) eq "HASH") {
67 HeaderType($element, $element->{TYPE}, $element->{TYPE}->{NAME});
69 HeaderType($element, $element->{TYPE}, "");
71 pidl " ".ElementStars($element);
73 pidl $element->{NAME};
74 pidl ArrayBrackets($element);
77 if (defined $element->{PROPERTIES}) {
78 HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
83 #####################################################################
85 sub HeaderStruct($$;$)
87 my($struct,$name,$tail) = @_;
89 pidl $tail if defined($tail) and not defined($struct->{ELEMENTS});
90 return if (not defined($struct->{ELEMENTS}));
94 foreach (@{$struct->{ELEMENTS}}) {
99 # some compilers can't handle empty structures
100 pidl tabs()."char _empty_;\n";
104 if (defined $struct->{PROPERTIES}) {
105 HeaderProperties($struct->{PROPERTIES}, []);
107 pidl $tail if defined($tail);
110 #####################################################################
114 my($enum,$name,$tail) = @_;
118 if (defined($enum->{ELEMENTS})) {
119 pidl "\n#ifndef USE_UINT_ENUMS\n";
122 foreach my $e (@{$enum->{ELEMENTS}}) {
124 unless ($first) { pidl ",\n"; }
127 @enum_els = split(/=/, $e);
128 if (@enum_els == 2) {
146 pidl " { __donnot_use_enum_$name=0x7FFFFFFF}\n";
147 foreach my $e (@{$enum->{ELEMENTS}}) {
151 if ($t =~ /(.*)=(.*)/) {
155 fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
156 unless ($without_val == 0);
161 fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
162 unless ($with_val == 0);
164 pidl "#define $name ( $value )\n";
168 pidl $tail if defined($tail);
171 #####################################################################
175 my($bitmap,$name) = @_;
177 return unless defined($bitmap->{ELEMENTS});
179 pidl "/* bitmap $name */\n";
180 pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
184 #####################################################################
186 sub HeaderUnion($$;$)
188 my($union,$name,$tail) = @_;
192 pidl $tail if defined($tail) and not defined($union->{ELEMENTS});
193 return if (not defined($union->{ELEMENTS}));
197 foreach my $e (@{$union->{ELEMENTS}}) {
198 if ($e->{TYPE} ne "EMPTY") {
199 if (! defined $done{$e->{NAME}}) {
202 $done{$e->{NAME}} = 1;
207 # sigh - some compilers don't like empty structures
208 pidl tabs()."int _dummy_element;\n";
213 if (defined $union->{PROPERTIES}) {
214 HeaderProperties($union->{PROPERTIES}, []);
216 pidl $tail if defined($tail);
219 #####################################################################
221 sub HeaderType($$$;$)
223 my($e,$data,$name,$tail) = @_;
224 if (ref($data) eq "HASH") {
225 ($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name, $tail);
226 ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
227 ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
228 ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
232 if (has_property($e, "charset")) {
235 pidl mapTypeName($e->{TYPE});
237 pidl $tail if defined($tail);
240 #####################################################################
242 sub HeaderTypedef($;$)
244 my($typedef,$tail) = @_;
245 # Don't print empty "enum foo;", since some compilers don't like it.
246 return if ($typedef->{DATA}->{TYPE} eq "ENUM" and not defined($typedef->{DATA}->{ELEMENTS}));
247 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}, $tail) if defined ($typedef->{DATA});
250 #####################################################################
255 if (!defined($const->{ARRAY_LEN}[0])) {
256 pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
258 pidl "#define $const->{NAME}\t $const->{VALUE}\n";
262 sub ElementDirection($)
266 return "inout" if (has_property($e, "in") and has_property($e, "out"));
267 return "in" if (has_property($e, "in"));
268 return "out" if (has_property($e, "out"));
272 #####################################################################
274 sub HeaderFunctionInOut($$)
278 return unless defined($fn->{ELEMENTS});
280 foreach my $e (@{$fn->{ELEMENTS}}) {
281 HeaderElement($e) if (ElementDirection($e) eq $prop);
285 #####################################################################
286 # determine if we need an "in" or "out" section
287 sub HeaderFunctionInOut_needed($$)
291 return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
293 return undef unless defined($fn->{ELEMENTS});
295 foreach my $e (@{$fn->{ELEMENTS}}) {
296 return 1 if (ElementDirection($e) eq $prop);
304 #####################################################################
306 sub HeaderFunction($)
310 return if ($headerstructs{$fn->{NAME}});
312 $headerstructs{$fn->{NAME}} = 1;
314 pidl "\nstruct $fn->{NAME} {\n";
318 if (HeaderFunctionInOut_needed($fn, "in") or
319 HeaderFunctionInOut_needed($fn, "inout")) {
320 pidl tabs()."struct {\n";
322 HeaderFunctionInOut($fn, "in");
323 HeaderFunctionInOut($fn, "inout");
325 pidl tabs()."} in;\n\n";
329 if (HeaderFunctionInOut_needed($fn, "out") or
330 HeaderFunctionInOut_needed($fn, "inout")) {
331 pidl tabs()."struct {\n";
333 HeaderFunctionInOut($fn, "out");
334 HeaderFunctionInOut($fn, "inout");
335 if (defined($fn->{RETURN_TYPE})) {
336 pidl tabs().mapTypeName($fn->{RETURN_TYPE}) . " result;\n";
339 pidl tabs()."} out;\n\n";
344 # sigh - some compilers don't like empty structures
345 pidl tabs()."int _dummy_element;\n";
355 foreach my $import (@imports) {
356 $import = unmake_str($import);
357 $import =~ s/\.idl$//;
358 pidl choose_header("librpc/gen_ndr/$import\.h", "gen_ndr/$import.h") . "\n";
365 foreach (@includes) {
366 pidl "#include $_\n";
370 #####################################################################
371 # parse the interface definitions
372 sub HeaderInterface($)
374 my($interface) = shift;
376 pidl "#ifndef _HEADER_$interface->{NAME}\n";
377 pidl "#define _HEADER_$interface->{NAME}\n\n";
379 foreach my $c (@{$interface->{CONSTS}}) {
383 foreach my $t (@{$interface->{TYPES}}) {
384 HeaderTypedef($t, ";\n\n") if ($t->{TYPE} eq "TYPEDEF");
385 HeaderStruct($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "STRUCT");
386 HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
387 HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
388 HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
391 foreach my $fn (@{$interface->{FUNCTIONS}}) {
395 pidl "#endif /* _HEADER_$interface->{NAME} */\n";
402 pidl unmake_str($quote->{DATA}) . "\n";
405 #####################################################################
406 # parse a parsed IDL into a C header
414 pidl "/* header auto-generated by pidl */\n\n";
416 pidl "#include <util/data_blob.h>\n";
418 pidl "#include <stdint.h>\n";
420 # FIXME: Include this only if NTSTATUS was actually used
421 pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
425 ($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
426 ($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
427 ($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
428 ($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
434 sub GenerateStructEnv($$)
439 foreach my $e (@{$x->{ELEMENTS}}) {
440 $env{$e->{NAME}} = "$v->$e->{NAME}";
448 sub EnvSubstituteValue($$)
452 # Substitute the value() values in the env
453 foreach my $e (@{$s->{ELEMENTS}}) {
454 next unless (defined(my $v = has_property($e, "value")));
456 $env->{$e->{NAME}} = ParseExpr($v, $env, $e);
462 sub GenerateFunctionInEnv($;$)
464 my ($fn, $base) = @_;
467 $base = "r->" unless defined($base);
469 foreach my $e (@{$fn->{ELEMENTS}}) {
470 if (grep (/in/, @{$e->{DIRECTION}})) {
471 $env{$e->{NAME}} = $base."in.$e->{NAME}";
478 sub GenerateFunctionOutEnv($;$)
480 my ($fn, $base) = @_;
483 $base = "r->" unless defined($base);
485 foreach my $e (@{$fn->{ELEMENTS}}) {
486 if (grep (/out/, @{$e->{DIRECTION}})) {
487 $env{$e->{NAME}} = $base."out.$e->{NAME}";
488 } elsif (grep (/in/, @{$e->{DIRECTION}})) {
489 $env{$e->{NAME}} = $base."in.$e->{NAME}";