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}}) {
123
unless ($first) { pidl ",\n"; }
136
pidl " { __donnot_use_enum_$name=0x7FFFFFFF}\n";
137
foreach my $e (@{$enum->{ELEMENTS}}) {
141
if ($t =~ /(.*)=(.*)/) {
145
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
146
unless ($without_val == 0);
151
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
152
unless ($with_val == 0);
154
pidl "#define $name ( $value )\n";
158
pidl $tail if defined($tail);
161
#####################################################################
165
my($bitmap,$name) = @_;
167
return unless defined($bitmap->{ELEMENTS});
169
pidl "/* bitmap $name */\n";
170
pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
174
#####################################################################
176
sub HeaderUnion($$;$)
178
my($union,$name,$tail) = @_;
182
pidl $tail if defined($tail) and not defined($union->{ELEMENTS});
183
return if (not defined($union->{ELEMENTS}));
187
foreach my $e (@{$union->{ELEMENTS}}) {
188
if ($e->{TYPE} ne "EMPTY") {
189
if (! defined $done{$e->{NAME}}) {
192
$done{$e->{NAME}} = 1;
197
# sigh - some compilers don't like empty structures
198
pidl tabs()."int _dummy_element;\n";
203
if (defined $union->{PROPERTIES}) {
204
HeaderProperties($union->{PROPERTIES}, []);
206
pidl $tail if defined($tail);
209
#####################################################################
211
sub HeaderType($$$;$)
213
my($e,$data,$name,$tail) = @_;
214
if (ref($data) eq "HASH") {
215
($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name, $tail);
216
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
217
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
218
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
222
if (has_property($e, "charset")) {
225
pidl mapTypeName($e->{TYPE});
227
pidl $tail if defined($tail);
230
#####################################################################
232
sub HeaderTypedef($;$)
234
my($typedef,$tail) = @_;
235
# Don't print empty "enum foo;", since some compilers don't like it.
236
return if ($typedef->{DATA}->{TYPE} eq "ENUM" and not defined($typedef->{DATA}->{ELEMENTS}));
237
HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}, $tail) if defined ($typedef->{DATA});
240
#####################################################################
245
if (!defined($const->{ARRAY_LEN}[0])) {
246
pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
248
pidl "#define $const->{NAME}\t $const->{VALUE}\n";
252
sub ElementDirection($)
256
return "inout" if (has_property($e, "in") and has_property($e, "out"));
257
return "in" if (has_property($e, "in"));
258
return "out" if (has_property($e, "out"));
262
#####################################################################
264
sub HeaderFunctionInOut($$)
268
return unless defined($fn->{ELEMENTS});
270
foreach my $e (@{$fn->{ELEMENTS}}) {
271
HeaderElement($e) if (ElementDirection($e) eq $prop);
275
#####################################################################
276
# determine if we need an "in" or "out" section
277
sub HeaderFunctionInOut_needed($$)
281
return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
283
return undef unless defined($fn->{ELEMENTS});
285
foreach my $e (@{$fn->{ELEMENTS}}) {
286
return 1 if (ElementDirection($e) eq $prop);
294
#####################################################################
296
sub HeaderFunction($)
300
return if ($headerstructs{$fn->{NAME}});
302
$headerstructs{$fn->{NAME}} = 1;
304
pidl "\nstruct $fn->{NAME} {\n";
308
if (HeaderFunctionInOut_needed($fn, "in") or
309
HeaderFunctionInOut_needed($fn, "inout")) {
310
pidl tabs()."struct {\n";
312
HeaderFunctionInOut($fn, "in");
313
HeaderFunctionInOut($fn, "inout");
315
pidl tabs()."} in;\n\n";
319
if (HeaderFunctionInOut_needed($fn, "out") or
320
HeaderFunctionInOut_needed($fn, "inout")) {
321
pidl tabs()."struct {\n";
323
HeaderFunctionInOut($fn, "out");
324
HeaderFunctionInOut($fn, "inout");
325
if (defined($fn->{RETURN_TYPE})) {
326
pidl tabs().mapTypeName($fn->{RETURN_TYPE}) . " result;\n";
329
pidl tabs()."} out;\n\n";
334
# sigh - some compilers don't like empty structures
335
pidl tabs()."int _dummy_element;\n";
345
foreach my $import (@imports) {
346
$import = unmake_str($import);
347
$import =~ s/\.idl$//;
348
pidl choose_header("librpc/gen_ndr/$import\.h", "gen_ndr/$import.h") . "\n";
355
foreach (@includes) {
356
pidl "#include $_\n";
360
#####################################################################
361
# parse the interface definitions
362
sub HeaderInterface($)
364
my($interface) = shift;
366
pidl "#ifndef _HEADER_$interface->{NAME}\n";
367
pidl "#define _HEADER_$interface->{NAME}\n\n";
369
foreach my $c (@{$interface->{CONSTS}}) {
373
foreach my $t (@{$interface->{TYPES}}) {
374
HeaderTypedef($t, ";\n\n") if ($t->{TYPE} eq "TYPEDEF");
375
HeaderStruct($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "STRUCT");
376
HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
377
HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
378
HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
381
foreach my $fn (@{$interface->{FUNCTIONS}}) {
385
pidl "#endif /* _HEADER_$interface->{NAME} */\n";
392
pidl unmake_str($quote->{DATA}) . "\n";
395
#####################################################################
396
# parse a parsed IDL into a C header
404
pidl "/* header auto-generated by pidl */\n\n";
406
pidl "#include <util/data_blob.h>\n";
408
pidl "#include <stdint.h>\n";
410
# FIXME: Include this only if NTSTATUS was actually used
411
pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
415
($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
416
($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
417
($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
418
($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
424
sub GenerateStructEnv($$)
429
foreach my $e (@{$x->{ELEMENTS}}) {
430
$env{$e->{NAME}} = "$v->$e->{NAME}";
438
sub EnvSubstituteValue($$)
442
# Substitute the value() values in the env
443
foreach my $e (@{$s->{ELEMENTS}}) {
444
next unless (defined(my $v = has_property($e, "value")));
446
$env->{$e->{NAME}} = ParseExpr($v, $env, $e);
452
sub GenerateFunctionInEnv($;$)
454
my ($fn, $base) = @_;
457
$base = "r->" unless defined($base);
459
foreach my $e (@{$fn->{ELEMENTS}}) {
460
if (grep (/in/, @{$e->{DIRECTION}})) {
461
$env{$e->{NAME}} = $base."in.$e->{NAME}";
468
sub GenerateFunctionOutEnv($;$)
470
my ($fn, $base) = @_;
473
$base = "r->" unless defined($base);
475
foreach my $e (@{$fn->{ELEMENTS}}) {
476
if (grep (/out/, @{$e->{DIRECTION}})) {
477
$env{$e->{NAME}} = $base."out.$e->{NAME}";
478
} elsif (grep (/in/, @{$e->{DIRECTION}})) {
479
$env{$e->{NAME}} = $base."in.$e->{NAME}";