pidl: Avoid accidently filling in empty body for types without body.
[ira/wip.git] / source / pidl / lib / Parse / Pidl / Typelist.pm
1 ###################################################
2 # Samba4 parser generator for IDL structures
3 # Copyright jelmer@samba.org 2005
4 # released under the GNU GPL
5
6 package Parse::Pidl::Typelist;
7
8 require Exporter;
9 @ISA = qw(Exporter);
10 @EXPORT_OK = qw(hasType getType mapTypeName scalar_is_reference expandAlias
11                             mapScalarType addType typeIs is_scalar enum_type_fn
12                                 bitmap_type_fn mapType typeHasBody
13 );
14 use vars qw($VERSION);
15 $VERSION = '0.01';
16
17 use Parse::Pidl::Util qw(has_property);
18 use strict;
19
20 my %types = ();
21
22 my @reference_scalars = (
23         "string", "string_array", "nbt_string", 
24         "wrepl_nbt_name", "ipv4address"
25 );
26
27 # a list of known scalar types
28 my %scalars = (
29         "void"          => "void",
30         "char"          => "char",
31         "int8"          => "int8_t",
32         "uint8"         => "uint8_t",
33         "int16"         => "int16_t",
34         "uint16"        => "uint16_t",
35         "int32"         => "int32_t",
36         "uint32"        => "uint32_t",
37         "hyper"         => "uint64_t",
38         "dlong"         => "int64_t",
39         "udlong"        => "uint64_t",
40         "udlongr"       => "uint64_t",
41         "pointer"       => "void*",
42         "DATA_BLOB"     => "DATA_BLOB",
43         "string"        => "const char *",
44         "string_array"  => "const char **",
45         "time_t"        => "time_t",
46         "NTTIME"        => "NTTIME",
47         "NTTIME_1sec"   => "NTTIME",
48         "NTTIME_hyper"  => "NTTIME",
49         "WERROR"        => "WERROR",
50         "NTSTATUS"      => "NTSTATUS",
51         "COMRESULT" => "COMRESULT",
52         "nbt_string"    => "const char *",
53         "wrepl_nbt_name"=> "struct nbt_name *",
54         "ipv4address"   => "const char *",
55 );
56
57 my %aliases = (
58         "error_status_t" => "uint32",
59         "boolean8" => "uint8",
60         "boolean32" => "uint32",
61         "DWORD" => "uint32",
62         "int" => "int32",
63         "WORD" => "uint16",
64         "char" => "uint8",
65         "long" => "int32",
66         "short" => "int16",
67         "HYPER_T" => "hyper",
68         "HRESULT" => "COMRESULT",
69 );
70
71 sub expandAlias($)
72 {
73         my $name = shift;
74
75         return $aliases{$name} if defined($aliases{$name});
76
77         return $name;
78 }
79
80 # map from a IDL type to a C header type
81 sub mapScalarType($)
82 {
83         my $name = shift;
84
85         # it's a bug when a type is not in the list
86         # of known scalars or has no mapping
87         return $scalars{$name} if defined($scalars{$name});
88
89         die("Unknown scalar type $name");
90 }
91
92 sub addType($)
93 {
94         my $t = shift;
95         $types{$t->{NAME}} = $t;
96 }
97
98 sub getType($)
99 {
100         my $t = shift;
101         return ($t) if (ref($t) eq "HASH" and not defined($t->{NAME}));
102         return undef if not hasType($t);
103         return $types{$t->{NAME}} if (ref($t) eq "HASH");
104         return $types{$t};
105 }
106
107 sub typeIs($$)
108 {
109         my ($t,$tt) = @_;
110         
111         if (ref($t) eq "HASH") {
112                 return 1 if ($t->{TYPE} eq $tt);
113                 return 0;
114         }
115         return 1 if (hasType($t) and getType($t)->{TYPE} eq "TYPEDEF" and 
116                          getType($t)->{DATA}->{TYPE} eq $tt);
117         return 0;
118 }
119
120 sub hasType($)
121 {
122         my $t = shift;
123         if (ref($t) eq "HASH") {
124                 return 1 if (not defined($t->{NAME}));
125                 return 1 if (defined($types{$t->{NAME}}) and 
126                         $types{$t->{NAME}}->{TYPE} eq $t->{TYPE});
127                 return 0;
128         }
129         return 1 if defined($types{$t});
130         return 0;
131 }
132
133 sub is_scalar($)
134 {
135         sub is_scalar($);
136         my $type = shift;
137
138         return 1 if (ref($type) eq "HASH" and 
139                 ($type->{TYPE} eq "SCALAR" or $type->{TYPE} eq "ENUM" or 
140                  $type->{TYPE} eq "BITMAP"));
141
142         if (my $dt = getType($type)) {
143                 return is_scalar($dt->{DATA}) if ($dt->{TYPE} eq "TYPEDEF");
144                 return 1 if ($dt->{TYPE} eq "SCALAR" or $dt->{TYPE} eq "ENUM" or 
145                                  $dt->{TYPE} eq "BITMAP");
146         }
147
148         return 0;
149 }
150
151 sub scalar_is_reference($)
152 {
153         my $name = shift;
154
155         return 1 if (grep(/^$name$/, @reference_scalars));
156         return 0;
157 }
158
159 sub RegisterScalars()
160 {
161         foreach (keys %scalars) {
162                 addType({
163                         NAME => $_,
164                         TYPE => "TYPEDEF",
165                         DATA => {
166                                 TYPE => "SCALAR",
167                                 NAME => $_
168                         }
169                 }
170                 );
171         }
172 }
173
174 sub enum_type_fn($)
175 {
176         my $enum = shift;
177         $enum->{TYPE} eq "ENUM" or die("not an enum");
178
179         # for typedef enum { } we need to check $enum->{PARENT}
180         if (has_property($enum, "enum8bit")) {
181                 return "uint8";
182         } elsif (has_property($enum, "enum16bit")) {
183                 return "uint16";
184         } elsif (has_property($enum, "v1_enum")) {
185                 return "uint32";
186         } elsif (has_property($enum->{PARENT}, "enum8bit")) {
187                 return "uint8";
188         } elsif (has_property($enum->{PARENT}, "enum16bit")) {
189                 return "uint16";
190         } elsif (has_property($enum->{PARENT}, "v1_enum")) {
191                 return "uint32";
192         }
193         return "uint16";
194 }
195
196 sub bitmap_type_fn($)
197 {
198         my $bitmap = shift;
199
200         $bitmap->{TYPE} eq "BITMAP" or die("not a bitmap");
201
202         if (has_property($bitmap, "bitmap8bit")) {
203                 return "uint8";
204         } elsif (has_property($bitmap, "bitmap16bit")) {
205                 return "uint16";
206         } elsif (has_property($bitmap, "bitmap64bit")) {
207                 return "hyper";
208         }
209         return "uint32";
210 }
211
212 sub typeHasBody($)
213 {
214         sub typeHasBody($);
215         my ($e) = @_;
216
217         if ($e->{TYPE} eq "TYPEDEF") {
218                 return 0 unless(defined($e->{DATA}));
219                 return typeHasBody($e->{DATA});
220         }
221
222         return defined($e->{ELEMENTS});
223 }
224
225 sub mapType($$)
226 {
227         sub mapType($$);
228         my ($t, $n) = @_;
229
230         return mapType($t->{DATA}, $n) if ($t->{TYPE} eq "TYPEDEF");
231         return mapScalarType($n) if ($t->{TYPE} eq "SCALAR");
232         return "enum $n" if ($t->{TYPE} eq "ENUM");
233         return "struct $n" if ($t->{TYPE} eq "STRUCT");
234         return "union $n" if ($t->{TYPE} eq "UNION");
235         return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
236         die("Unknown type $t->{TYPE}");
237 }
238
239 sub mapTypeName($)
240 {
241         my $t = shift;
242         return "void" unless defined($t);
243         my $dt;
244         $t = expandAlias($t);
245
246         unless ($dt or ($dt = getType($t))) {
247                 # Best guess
248                 return "struct $t";
249         }
250
251         return mapType($dt, $dt->{NAME});
252 }
253
254 sub LoadIdl($)
255 {
256         my ($idl) = @_;
257
258         foreach my $x (@{$idl}) {
259                 next if $x->{TYPE} ne "INTERFACE";
260
261                 foreach my $y (@{$x->{DATA}}) {
262                         addType($y) if (
263                                 $y->{TYPE} eq "TYPEDEF" 
264                                  or $y->{TYPE} eq "UNION"
265                                  or $y->{TYPE} eq "STRUCT"
266                          or $y->{TYPE} eq "ENUM"
267                          or $y->{TYPE} eq "BITMAP");
268                 }
269         }
270 }
271
272 sub GenerateTypeLib()
273 {
274         return Parse::Pidl::Util::MyDumper(\%types);
275 }
276
277 RegisterScalars();
278
279 1;