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;
10 use Parse::Pidl qw(fatal);
11 use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
12 use Parse::Pidl::Util qw(has_property is_constant);
13 use Parse::Pidl::NDR qw(GetNextLevel);
14 use Parse::Pidl::Samba4 qw(is_intree);
16 use vars qw($VERSION);
22 sub pidl($) { $res .= shift; }
27 $res .="\t" foreach (1..$tab_depth);
31 #####################################################################
32 # parse a properties list
33 sub HeaderProperties($$)
35 my($props,$ignores) = @_;
38 foreach my $d (keys %{$props}) {
39 next if (grep(/^$d$/, @$ignores));
40 if($props->{$d} ne "1") {
41 $ret.= "$d($props->{$d}),";
48 pidl "/* [" . substr($ret, 0, -1) . "] */";
52 #####################################################################
53 # parse a structure element
59 if (has_property($element, "represent_as")) {
60 pidl mapTypeName($element->{PROPERTIES}->{represent_as})." ";
62 if (ref($element->{TYPE}) eq "HASH") {
63 HeaderType($element, $element->{TYPE}, $element->{TYPE}->{NAME});
65 HeaderType($element, $element->{TYPE}, "");
69 foreach my $l (@{$element->{LEVELS}}) {
70 next unless ($l->{TYPE} eq "POINTER");
72 my $nl = GetNextLevel($element, $l);
73 next if (defined($nl) and $nl->{TYPE} eq "ARRAY");
78 $numstar-- if (scalar_is_reference($element->{TYPE}));
80 foreach my $l (@{$element->{LEVELS}}) {
81 next unless ($l->{TYPE} eq "ARRAY");
82 next if ($l->{IS_FIXED}) and
83 not has_property($element, "charset");
86 pidl "*" foreach (1..$numstar);
88 pidl $element->{NAME};
89 foreach my $l (@{$element->{LEVELS}}) {
90 next unless ($l->{TYPE} eq "ARRAY");
91 next unless ($l->{IS_FIXED} and
92 not has_property($element, "charset"));
93 pidl "[$l->{SIZE_IS}]";
97 if (defined $element->{PROPERTIES}) {
98 HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
103 #####################################################################
107 my($struct,$name) = @_;
109 return if (not defined($struct->{ELEMENTS}));
113 foreach (@{$struct->{ELEMENTS}}) {
117 if ($el_count == 0) {
118 # some compilers can't handle empty structures
119 pidl tabs()."char _empty_;\n";
123 if (defined $struct->{PROPERTIES}) {
124 HeaderProperties($struct->{PROPERTIES}, []);
128 #####################################################################
132 my($enum,$name) = @_;
135 pidl "#ifndef USE_UINT_ENUMS\n";
136 pidl "enum $name {\n";
138 if (defined($enum->{ELEMENTS})) {
139 foreach my $e (@{$enum->{ELEMENTS}}) {
140 unless ($first) { pidl ",\n"; }
151 pidl "enum $name { __donnot_use_enum_$name=0x7FFFFFFF}\n";
154 if (defined($enum->{ELEMENTS})) {
155 foreach my $e (@{$enum->{ELEMENTS}}) {
159 if ($t =~ /(.*)=(.*)/) {
163 fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
164 unless ($without_val == 0);
169 fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
170 unless ($with_val == 0);
172 pidl "#define $name ( $value )\n";
178 #####################################################################
182 my($bitmap,$name) = @_;
184 return unless defined($bitmap->{ELEMENTS});
186 pidl "/* bitmap $name */\n";
187 pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
191 #####################################################################
195 my($union,$name) = @_;
199 return if (not defined($union->{ELEMENTS}));
202 foreach my $e (@{$union->{ELEMENTS}}) {
203 if ($e->{TYPE} ne "EMPTY") {
204 if (! defined $done{$e->{NAME}}) {
207 $done{$e->{NAME}} = 1;
213 if (defined $union->{PROPERTIES}) {
214 HeaderProperties($union->{PROPERTIES}, []);
218 #####################################################################
222 my($e,$data,$name) = @_;
223 if (ref($data) eq "HASH") {
224 ($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name);
225 ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
226 ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name);
227 ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name);
231 if (has_property($e, "charset")) {
234 pidl mapTypeName($e->{TYPE});
238 #####################################################################
242 my($typedef) = shift;
243 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
246 #####################################################################
251 if (!defined($const->{ARRAY_LEN}[0])) {
252 pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
254 pidl "#define $const->{NAME}\t $const->{VALUE}\n";
258 sub ElementDirection($)
262 return "inout" if (has_property($e, "in") and has_property($e, "out"));
263 return "in" if (has_property($e, "in"));
264 return "out" if (has_property($e, "out"));
268 #####################################################################
270 sub HeaderFunctionInOut($$)
274 return unless defined($fn->{ELEMENTS});
276 foreach my $e (@{$fn->{ELEMENTS}}) {
277 HeaderElement($e) if (ElementDirection($e) eq $prop);
281 #####################################################################
282 # determine if we need an "in" or "out" section
283 sub HeaderFunctionInOut_needed($$)
287 return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
289 return undef unless defined($fn->{ELEMENTS});
291 foreach my $e (@{$fn->{ELEMENTS}}) {
292 return 1 if (ElementDirection($e) eq $prop);
300 #####################################################################
302 sub HeaderFunction($)
306 return if ($headerstructs{$fn->{NAME}});
308 $headerstructs{$fn->{NAME}} = 1;
310 pidl "\nstruct $fn->{NAME} {\n";
314 if (HeaderFunctionInOut_needed($fn, "in") or
315 HeaderFunctionInOut_needed($fn, "inout")) {
316 pidl tabs()."struct {\n";
318 HeaderFunctionInOut($fn, "in");
319 HeaderFunctionInOut($fn, "inout");
321 pidl tabs()."} in;\n\n";
325 if (HeaderFunctionInOut_needed($fn, "out") or
326 HeaderFunctionInOut_needed($fn, "inout")) {
327 pidl tabs()."struct {\n";
329 HeaderFunctionInOut($fn, "out");
330 HeaderFunctionInOut($fn, "inout");
331 if (defined($fn->{RETURN_TYPE})) {
332 pidl tabs().mapTypeName($fn->{RETURN_TYPE}) . " result;\n";
335 pidl tabs()."} out;\n\n";
340 # sigh - some compilers don't like empty structures
341 pidl tabs()."int _dummy_element;\n";
354 pidl "#include \"librpc/gen_ndr/$_\.h\"\n";
361 foreach (@includes) {
362 pidl "#include $_\n";
366 #####################################################################
367 # parse the interface definitions
368 sub HeaderInterface($)
370 my($interface) = shift;
372 pidl "#ifndef _HEADER_$interface->{NAME}\n";
373 pidl "#define _HEADER_$interface->{NAME}\n\n";
375 foreach my $c (@{$interface->{CONSTS}}) {
379 foreach my $t (@{$interface->{TYPES}}) {
380 HeaderTypedef($t) if ($t->{TYPE} eq "TYPEDEF");
381 HeaderStruct($t, $t->{NAME}) if ($t->{TYPE} eq "STRUCT");
382 HeaderUnion($t, $t->{NAME}) if ($t->{TYPE} eq "UNION");
383 HeaderEnum($t, $t->{NAME}) if ($t->{TYPE} eq "ENUM");
384 HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
385 pidl ";\n\n" if ($t->{TYPE} eq "BITMAP" or
386 $t->{TYPE} eq "STRUCT" or
387 $t->{TYPE} eq "TYPEDEF" or
388 $t->{TYPE} eq "UNION" or
389 $t->{TYPE} eq "ENUM");
392 foreach my $fn (@{$interface->{FUNCTIONS}}) {
396 pidl "#endif /* _HEADER_$interface->{NAME} */\n";
399 #####################################################################
400 # parse a parsed IDL into a C header
408 pidl "/* header auto-generated by pidl */\n\n";
410 pidl "#include <core.h>\n";
412 pidl "#include <stdint.h>\n";
416 ($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
417 ($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
418 ($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});