af37a1b8dbad8980ff15e695f85025ac21114bc2
[samba.git] / source / build / 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 typelist;
7
8 use strict;
9
10 my %typedefs = ();
11
12 sub addType($)
13 {
14         my $t = shift;
15         $typedefs{$t->{NAME}} = $t;
16 }
17
18 sub getType($)
19 {
20         my $t = shift;
21         return undef unless(defined($typedefs{$t}));
22         return $typedefs{$t};
23 }
24
25 sub typeIs($$)
26 {
27         my $t = shift;
28         my $tt = shift;
29
30         return 1 if (hasType($t) and getType($t)->{DATA}->{TYPE} eq $tt);
31         return 0;
32 }
33
34 sub hasType($)
35 {
36         my $t = shift;
37         return 1 if defined($typedefs{$t});
38         return 0;
39 }
40
41 sub RegisterPrimitives()
42 {
43         my @primitives = (
44                 "char", "int8", "uint8", "short", "wchar_t", 
45                 "int16", "uint16", "long", "int32", "uint32", 
46                 "dlong", "udlong", "udlongr", "NTTIME", "NTTIME_1sec", 
47                 "time_t", "DATA_BLOB", "error_status_t", "WERROR", 
48                 "NTSTATUS", "boolean32", "unsigned32", "ipv4address", 
49                 "hyper", "NTTIME_hyper");
50                 
51         foreach my $k (@primitives) {
52                 $typedefs{$k} = {
53                         NAME => $k,
54                         TYPE => "TYPEDEF",
55                         DATA => {
56                                 TYPE => "SCALAR",
57                                 NAME => $k
58                         }
59                 };
60         }
61 }
62
63 sub enum_type_fn($)
64 {
65         my $enum = shift;
66         if (util::has_property($enum->{PARENT}, "enum8bit")) {
67                 return "uint8";
68         } elsif (util::has_property($enum->{PARENT}, "v1_enum")) {
69                 return "uint32";
70         }
71         return "uint16";
72 }
73
74 sub bitmap_type_fn($)
75 {
76         my $bitmap = shift;
77
78         if (util::has_property($bitmap, "bitmap8bit")) {
79                 return "uint8";
80         } elsif (util::has_property($bitmap, "bitmap16bit")) {
81                 return "uint16";
82         } elsif (util::has_property($bitmap, "bitmap64bit")) {
83                 return "uint64";
84         }
85         return "uint32";
86 }
87
88 # provide mappings between IDL base types and types in our headers
89 my %scalar_type_mappings = 
90     (
91      "int8"         => "int8_t",
92      "uint8"        => "uint8_t",
93      "short"        => "int16_t",
94      "wchar_t"      => "uint16_t",
95      "int16"        => "int16_t",
96      "uint16"       => "uint16_t",
97      "int32"        => "int32_t",
98      "uint32"       => "uint32_t",
99      "int64"        => "int64_t",
100      "uint64"       => "uint64_t",
101      "dlong"        => "int64_t",
102      "udlong"       => "uint64_t",
103      "udlongr"      => "uint64_t",
104      "hyper"        => "uint64_t",
105      "NTTIME_1sec"  => "NTTIME",
106      "NTTIME_hyper" => "NTTIME",
107      "ipv4address"  => "const char *",
108      "nbt_string"   => "const char *"
109      );
110
111 # map from a IDL type to a C header type
112 sub mapScalarType($)
113 {
114         my $name = shift;
115         if (my $ret = $scalar_type_mappings{$name}) {
116                 return $ret;
117         }
118         return $name;
119 }
120
121 sub mapType($)
122 {
123         my $e = shift;
124         my $dt;
125
126         return "const char *" if ($e->{TYPE} =~ "string");
127
128         if ($e->{TYPE} eq "ENUM" or $e->{TYPE} eq "BITMAP") {
129                 $dt = getType($e->{PARENT}->{NAME});
130         }
131         
132         unless ($dt or $dt = getType($e->{TYPE})) {
133                 # Best guess
134                 return "struct $e->{TYPE}";
135         }
136         return mapScalarType($e->{TYPE}) if ($dt->{DATA}->{TYPE} eq "SCALAR");
137         return "enum $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "ENUM");
138         return "struct $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "STRUCT");
139         return "struct $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "INTERFACE");
140         return "union $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "UNION");
141         return mapScalarType(bitmap_type_fn($dt->{DATA})) if ($dt->{DATA}->{TYPE} eq "BITMAP");
142
143         die("Unknown type $dt->{DATA}->{TYPE}");
144 }
145
146 sub LoadIdl($)
147 {
148         my $idl = shift;
149
150         foreach my $x (@{$idl}) {
151                 next if $x->{TYPE} ne "INTERFACE";
152
153                 # DCOM interfaces can be types as well
154                 addType({
155                         NAME => $x->{NAME},
156                         TYPE => "TYPEDEF",
157                         DATA => $x
158                         }) if (util::has_property($x, "object"));
159
160                 foreach my $y (@{$x->{DATA}}) {
161                         addType($y) if (
162                                 $y->{TYPE} eq "TYPEDEF" 
163                          or $y->{TYPE} eq "DECLARE");
164                 }
165         }
166 }
167
168 RegisterPrimitives();
169
170
171 1;