f7d383d29752469e9b742a04da26cf49430c12ce
[samba.git] / source / build / pidl / eparser.pm
1 ###################################################
2 # parser generator for IDL structures
3 # Copyright tpot@samba.org 2001
4 # Copyright tridge@samba.org 2000
5 # released under the GNU GPL
6
7 package IdlEParser;
8
9 use strict;
10 use dump;
11 use Data::Dumper;
12
13 my($name);
14
15 sub ParamSimpleNdrType($)
16 {
17     my($p) = shift;
18     my($res);
19
20     $res .= "\toffset = dissect_ndr_$p->{TYPE}(tvb, offset, pinfo, tree, drep, hf_$p->{NAME}, NULL);\n";
21
22     return $res;
23 }
24
25 sub ParamPolicyHandle($)
26 {
27     my($p) = shift;
28     my($res);
29
30     $res .= "\toffset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep, hf_policy_hnd, NULL, NULL, FALSE, FALSE);\n";
31
32     return $res;
33 }
34
35 my %param_handlers = (
36                       'uint16' => \&ParamSimpleNdrType,
37                       'uint32' => \&ParamSimpleNdrType,
38                       'policy_handle' => \&ParamPolicyHandle,
39                       );
40
41 #####################################################################
42 # parse a function
43 sub ParseParameter($)
44
45     my($p) = shift;
46     my($res);
47
48     if (defined($param_handlers{$p->{TYPE}})) {
49         $res .= &{$param_handlers{$p->{TYPE}}}($p);
50         return $res;
51     }
52
53     $res .= "\t/* Unhandled IDL type '$p->{TYPE}' in $p->{PARENT}->{NAME} */\n";
54
55     return $res;
56     # exit(1);
57 }
58
59 #####################################################################
60 # parse a function
61 sub ParseFunction($)
62
63     my($f) = shift;
64     my($res);
65
66     $res .= "/*\n\n";
67     $res .= IdlDump::DumpFunction($f);
68     $res .= "*/\n\n";
69
70     # Request function
71
72     $res .= "static int\n";
73     $res .= "$f->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n";
74     $res .= "{\n";
75
76     my($d);
77     foreach $d (@{$f->{DATA}}) {
78         $res .= ParseParameter($d), if defined($d->{PROPERTIES}{in});
79     }
80
81     $res .= "\treturn offset;\n";
82     $res .= "}\n\n";
83
84     # Response function
85
86     $res .= "static int\n";
87     $res .= "$f->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n";
88     $res .= "{\n";
89
90     foreach $d (@{$f->{DATA}}) {
91         $res .= ParseParameter($d), if defined($d->{PROPERTIES}{out});
92     }
93
94     $res .= "\n";
95     $res .= "\treturn offset;\n";
96     $res .= "}\n\n";
97
98     return $res;
99 }
100
101 #####################################################################
102 # parse the interface definitions
103 sub Pass2Interface($)
104 {
105     my($interface) = shift;
106     my($data) = $interface->{DATA};
107     my($res) = "";
108
109     foreach my $d (@{$data}) {
110         $res .= ParseFunction($d), if $d->{TYPE} eq "FUNCTION";
111     }
112
113     return $res;
114 }
115
116 #####################################################################
117 # Pass 1: Stuff required before structs and functions
118
119 sub Pass1ModuleHeader($)
120 {
121     my($d) = shift;
122     my($res) = "";
123
124     $res .= << "EOF";
125 #ifdef HAVE_CONFIG_H
126 #include "config.h"
127 #endif
128
129 #include "packet-dcerpc.h"
130 #include "packet-dcerpc-nt.h"
131
132 EOF
133
134     # UUID
135
136     if ($d->{TYPE} eq "MODULEHEADER" and defined($d->{PROPERTIES}->{uuid})) {
137         my $uuid = $d->{PROPERTIES}->{uuid};
138         $res .= "static e_uuid_t uuid_dcerpc_$name = {\n";
139         $res .= "\t0x" . substr($uuid, 0, 8);
140         $res .= ", 0x" . substr($uuid, 9, 4);
141         $res .= ", 0x" . substr($uuid, 14, 4) . ",\n";
142         $res .= "\t{ 0x" . substr($uuid, 19, 2);
143         $res .= ", 0x" . substr($uuid, 21, 2);
144         $res .= ", 0x" . substr($uuid, 24, 2);
145         $res .= ", 0x" . substr($uuid, 26, 2);
146         $res .= ", 0x" . substr($uuid, 28, 2);
147         $res .= ", 0x" . substr($uuid, 30, 2);
148         $res .= ", 0x" . substr($uuid, 32, 2);
149         $res .= ", 0x" . substr($uuid, 34, 2) . " }\n";
150         $res .= "};\n\n";
151         
152         $res .= "static guint16 ver_dcerpc_samr = " . 
153             $d->{PROPERTIES}->{version} . ";\n\n";
154     }
155
156     return $res;
157 }
158
159 sub Pass1Interface($)
160 {
161     my($interface) = shift;
162     my($res) = "";
163
164     $res .= << "EOF";
165 static int proto_dcerpc_$name = -1;
166
167 static int hf_${name}_opnum = -1;
168 static int hf_${name}_rc = -1;
169 static int hf_policy_hnd = -1;
170
171 static gint ett_dcerpc_$name = -1;
172
173 EOF
174
175     my %p = ();
176
177     foreach my $fn (@{$interface->{DATA}}) {
178         next, if $fn->{TYPE} ne "FUNCTION";
179         foreach my $args ($fn->{DATA}) {
180             foreach my $params (@{$args}) {
181                 $res .= "static int hf_$params->{NAME} = -1;\n",
182                     if not defined $p{$params->{NAME}};
183                 $p{$params->{NAME}} = 1;
184             }
185         }
186     }
187
188     $res .= "\n";
189
190     return $res;
191 }
192
193 #####################################################################
194 # Pass 3: trailing stuff
195
196 sub Pass3Interface($)
197 {
198     my($interface) = shift;
199     my($res) = "";
200
201     $res .= "static dcerpc_sub_dissector dcerpc_${name}_dissectors[] = {\n";
202
203     my $num = 0;
204
205     foreach my $d (@{$interface->{DATA}}) {
206         if ($d->{TYPE} eq "FUNCTION") {
207             # Strip module name from function name, if present
208             my $n = $d->{NAME};
209             $n = substr($d->{NAME}, length($name) + 1),
210                 if $name eq substr($d->{NAME}, 0, length($name));
211
212             $res .= "\t{ $num, \"$n\",\n";
213             $res .= "\t\t$d->{NAME}_rqst,\n";
214             $res .= "\t\t$d->{NAME}_resp },\n";
215             $num++;
216         }
217     }
218
219     $res .= "};\n\n";
220
221     return $res;
222 }
223
224 #####################################################################
225 # parse a parsed IDL structure back into an IDL file
226 sub Parse($)
227 {
228     my($idl) = shift;
229     my($res) = "/* parser auto-generated by pidl */\n\n";
230     my($d);
231
232     # Pass 0: set module name
233
234     foreach $d (@{$idl}) {
235         $name = $d->{NAME}, if ($d->{TYPE} eq "INTERFACE");
236     }
237
238     # Pass 1: header stuff
239
240     foreach $d (@{$idl}) {
241         $res .= Pass1ModuleHeader($d), if $d->{TYPE} eq "MODULEHEADER";
242         $res .= Pass1Interface($d), if $d->{TYPE} eq "INTERFACE";
243     }
244
245     # Pass 2: typedefs and functions
246
247     foreach $d (@{$idl}) {
248         $res .= Pass2Interface($d), if $d->{TYPE} eq "INTERFACE";
249     }
250
251     # Pass 3: trailing stuff
252
253     foreach $d (@{$idl}) {
254         $res .= Pass3Interface($d), if $d->{TYPE} eq "INTERFACE";
255     }
256
257     $res .= << "EOF";
258 void
259 proto_reg_handoff_dcerpc_$name(void)
260 {
261         dcerpc_init_uuid(proto_dcerpc_$name, ett_dcerpc_$name, 
262                          &uuid_dcerpc_$name, ver_dcerpc_$name, 
263                          dcerpc_${name}_dissectors, hf_${name}_opnum);
264 }
265 EOF
266
267     return $res;
268 }
269
270 1;