r8806: Move data representation-independent data into seperate header
[sfrench/samba-autobuild/.git] / source4 / build / pidl / Parse / Pidl / Samba / Header.pm
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
6
7 package Parse::Pidl::Samba::Header;
8
9 use strict;
10 use Parse::Pidl::Typelist qw(mapType);
11 use Parse::Pidl::Util qw(has_property is_constant);
12 use Parse::Pidl::NDR qw(GetNextLevel GetPrevLevel);
13
14 my($res);
15 my($tab_depth);
16
17 sub pidl ($)
18 {
19         $res .= shift;
20 }
21
22 sub tabs()
23 {
24         my $res = "";
25         $res .="\t" foreach (1..$tab_depth);
26         return $res;
27 }
28
29 #####################################################################
30 # parse a properties list
31 sub HeaderProperties($$)
32 {
33     my($props,$ignores) = @_;
34         my $ret = "";
35
36     foreach my $d (keys %{$props}) {
37                 next if (grep(/^$d$/, @$ignores));
38                 if($props->{$d} ne "1") {
39                         $ret.= "$d($props->{$d}),";
40                 } else {
41                         $ret.="$d,";
42                 }
43         }
44
45         if ($ret) {
46                 pidl "/* [" . substr($ret, 0, -1) . "] */";
47         }
48 }
49
50 #####################################################################
51 # parse a structure element
52 sub HeaderElement($)
53 {
54         my($element) = shift;
55
56         pidl tabs();
57         HeaderType($element, $element->{TYPE}, "");
58         pidl " ";
59         my $numstar = $element->{POINTERS};
60         foreach (@{$element->{ARRAY_LEN}})
61         {
62                 next if is_constant($_);
63                 $numstar++;
64         }
65         $numstar-- if ($element->{TYPE} eq "string");
66         pidl "*" foreach (1..$numstar);
67         pidl $element->{NAME};
68         foreach (@{$element->{ARRAY_LEN}}) {
69                 next unless is_constant($_);
70                 pidl "[$_]";
71         }
72
73         pidl ";";
74         if (defined $element->{PROPERTIES}) {
75                 HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
76         }
77         pidl "\n";
78 }
79
80 #####################################################################
81 # parse a struct
82 sub HeaderStruct($$)
83 {
84     my($struct,$name) = @_;
85         pidl "struct $name {\n";
86     $tab_depth++;
87     my $el_count=0;
88     if (defined $struct->{ELEMENTS}) {
89                 foreach my $e (@{$struct->{ELEMENTS}}) {
90                     HeaderElement($e);
91                     $el_count++;
92                 }
93     }
94     if ($el_count == 0) {
95             # some compilers can't handle empty structures
96             pidl tabs()."char _empty_;\n";
97     }
98     $tab_depth--;
99     pidl tabs()."}";
100         if (defined $struct->{PROPERTIES}) {
101                 HeaderProperties($struct->{PROPERTIES}, []);
102         }
103 }
104
105 #####################################################################
106 # parse a enum
107 sub HeaderEnum($$)
108 {
109     my($enum,$name) = @_;
110     my $first = 1;
111
112     if (not Parse::Pidl::Util::useUintEnums()) {
113         pidl "enum $name {\n";
114         $tab_depth++;
115         foreach my $e (@{$enum->{ELEMENTS}}) {
116             unless ($first) { pidl ",\n"; }
117             $first = 0;
118             pidl tabs();
119             pidl $e;
120         }
121         pidl "\n";
122         $tab_depth--;
123         pidl "}";
124     } else {
125         my $count = 0;
126         pidl "enum $name { __donnot_use_enum_$name=0x7FFFFFFF};\n";
127         my $with_val = 0;
128         my $without_val = 0;
129         foreach my $e (@{$enum->{ELEMENTS}}) {
130             my $t = "$e";
131             my $name;
132             my $value;
133             if ($t =~ /(.*)=(.*)/) {
134                 $name = $1;
135                 $value = $2;
136                 $with_val = 1;
137                 die ("you can't mix enum member with values and without values when using --uint-enums!")
138                         unless ($without_val == 0);
139             } else {
140                 $name = $t;
141                 $value = $count++;
142                 $without_val = 1;
143                 die ("you can't mix enum member with values and without values when using --uint-enums!")
144                         unless ($with_val == 0);
145             }
146             pidl "#define $name ( $value )\n";
147         }
148         pidl "\n";
149     }
150 }
151
152 #####################################################################
153 # parse a bitmap
154 sub HeaderBitmap($$)
155 {
156     my($bitmap,$name) = @_;
157
158     pidl "/* bitmap $name */\n";
159     pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
160     pidl "\n";
161 }
162
163 #####################################################################
164 # parse a union
165 sub HeaderUnion($$)
166 {
167         my($union,$name) = @_;
168         my %done = ();
169
170         pidl "union $name {\n";
171         $tab_depth++;
172         foreach my $e (@{$union->{ELEMENTS}}) {
173                 if ($e->{TYPE} ne "EMPTY") {
174                         if (! defined $done{$e->{NAME}}) {
175                                 HeaderElement($e);
176                         }
177                         $done{$e->{NAME}} = 1;
178                 }
179         }
180         $tab_depth--;
181         pidl "}";
182
183         if (defined $union->{PROPERTIES}) {
184                 HeaderProperties($union->{PROPERTIES}, []);
185         }
186 }
187
188 #####################################################################
189 # parse a type
190 sub HeaderType($$$)
191 {
192         my($e,$data,$name) = @_;
193         if (ref($data) eq "HASH") {
194                 ($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name);
195                 ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
196                 ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name);
197                 ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name);
198                 return;
199         }
200
201         if (has_property($e, "charset")) {
202                 pidl "const char";
203         } else {
204                 pidl mapType($e->{TYPE});
205         }
206 }
207
208 #####################################################################
209 # parse a typedef
210 sub HeaderTypedef($)
211 {
212     my($typedef) = shift;
213     HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
214     pidl ";\n\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP");
215 }
216
217 #####################################################################
218 # parse a const
219 sub HeaderConst($)
220 {
221     my($const) = shift;
222     if (!defined($const->{ARRAY_LEN}[0])) {
223         pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
224     } else {
225         pidl "#define $const->{NAME}\t $const->{VALUE}\n";
226     }
227 }
228
229 #####################################################################
230 # parse a function
231 sub HeaderFunctionInOut($$)
232 {
233     my($fn,$prop) = @_;
234
235     foreach my $e (@{$fn->{ELEMENTS}}) {
236             if (has_property($e, $prop)) {
237                     HeaderElement($e);
238             }
239     }
240 }
241
242 #####################################################################
243 # determine if we need an "in" or "out" section
244 sub HeaderFunctionInOut_needed($$)
245 {
246     my($fn,$prop) = @_;
247
248     return 1 if ($prop eq "out" && $fn->{RETURN_TYPE} ne "void");
249
250     foreach (@{$fn->{ELEMENTS}}) {
251             return 1 if (has_property($_, $prop));
252     }
253
254     return undef;
255 }
256
257 my %headerstructs = ();
258
259 #####################################################################
260 # parse a function
261 sub HeaderFunction($)
262 {
263     my($fn) = shift;
264
265     return if ($headerstructs{$fn->{NAME}});
266
267     $headerstructs{$fn->{NAME}} = 1;
268
269     pidl "\nstruct $fn->{NAME} {\n";
270     $tab_depth++;
271     my $needed = 0;
272
273     if (HeaderFunctionInOut_needed($fn, "in")) {
274             pidl tabs()."struct {\n";
275             $tab_depth++;
276             HeaderFunctionInOut($fn, "in");
277             $tab_depth--;
278             pidl tabs()."} in;\n\n";
279             $needed++;
280     }
281
282     if (HeaderFunctionInOut_needed($fn, "out")) {
283             pidl tabs()."struct {\n";
284             $tab_depth++;
285             HeaderFunctionInOut($fn, "out");
286             if ($fn->{RETURN_TYPE} ne "void") {
287                     pidl tabs().mapType($fn->{RETURN_TYPE}) . " result;\n";
288             }
289             $tab_depth--;
290             pidl tabs()."} out;\n\n";
291             $needed++;
292     }
293
294     if (! $needed) {
295             # sigh - some compilers don't like empty structures
296             pidl tabs()."int _dummy_element;\n";
297     }
298
299     $tab_depth--;
300     pidl "};\n\n";
301 }
302
303 #####################################################################
304 # parse the interface definitions
305 sub HeaderInterface($)
306 {
307         my($interface) = shift;
308
309         my $count = 0;
310
311         pidl "#ifndef _HEADER_$interface->{NAME}\n";
312         pidl "#define _HEADER_$interface->{NAME}\n\n";
313
314         if (defined $interface->{PROPERTIES}->{depends}) {
315                 my @d = split / /, $interface->{PROPERTIES}->{depends};
316                 foreach my $i (@d) {
317                         pidl "#include \"librpc/gen_ndr/$i\.h\"\n";
318                 }
319         }
320
321         foreach my $d (@{$interface->{DATA}}) {
322                 next if ($d->{TYPE} ne "CONST");
323                 HeaderConst($d);
324         }
325
326         foreach my $d (@{$interface->{DATA}}) {
327                 next if ($d->{TYPE} ne "TYPEDEF");
328                 HeaderTypedef($d);
329         }
330
331         foreach my $d (@{$interface->{DATA}}) {
332                 next if ($d->{TYPE} ne "FUNCTION");
333                 HeaderFunction($d);
334         }
335
336         pidl "#endif /* _HEADER_$interface->{NAME} */\n";
337 }
338
339 #####################################################################
340 # parse a parsed IDL into a C header
341 sub Parse($)
342 {
343     my($idl) = shift;
344     $tab_depth = 0;
345
346         $res = "";
347     pidl "/* header auto-generated by pidl */\n\n";
348     foreach my $x (@{$idl}) {
349             ($x->{TYPE} eq "INTERFACE") && HeaderInterface($x);
350     }
351     return $res;
352 }
353
354 1;