r2298: Convert to and from string parameters.
[samba.git] / source4 / build / pidl / swig.pm
1 ###################################################
2 # Samba4 parser generator for swig wrappers
3 # Copyright tpot@samba.org 2004
4 # released under the GNU GPL
5
6 package IdlSwig;
7
8 use strict;
9 use Data::Dumper;
10
11 my($res);
12 my($name);
13
14 sub DebugElement($)
15 {
16     my($e) = shift;
17     my($result) = "";
18
19     $result .= "\t// $e->{TYPE} $e->{NAME} ";
20
21     $result .= "(scalar) " 
22         if util::is_scalar_type($e->{TYPE});
23
24     $result .= "pointers=$e->{POINTERS} " 
25         if $e->{POINTERS} > 0;
26
27     my($size_is) = util::has_property($e, "size_is");
28     $result .= "size_is=" . $size_is . " " if $size_is;
29
30     my($length_is) = util::has_property($e, "length_is");
31     $result .= "length_is=" . $length_is . " " if $length_is;
32
33     $result .= "array_len=" . $e->{ARRAY_LEN} . " " if $e->{ARRAY_LEN};
34
35     $result .= "\n";
36
37     return $result;
38 }
39
40 sub XFromPython($$)
41 {
42     my($e) = shift;
43     my($prefix) = shift;
44     my($result) = "";
45     my($obj) = "PyDict_GetItem(obj, PyString_FromString(\"$e->{NAME}\"))";
46
47     # Special cases
48
49     if (($e->{TYPE} eq "policy_handle" || $e->{TYPE} eq "string") && $e->{POINTERS} == 1) {
50         $result .= "\ts->$prefix$e->{NAME} = $e->{TYPE}_from_python($obj);\n";
51         return $result;
52     }
53
54     if ($e->{TYPE} eq "string" && $e->{POINTERS} == 1) {
55         $result .= "\ts->$prefix$e->{NAME} = policy_handle_from_python($obj);\n";
56         return $result;
57     }
58
59     # Generate conversion for element
60     
61     if (util::is_scalar_type($e->{TYPE})) {
62         if ($e->{POINTERS} == 0) {
63             if ($e->{ARRAY_LEN}) {
64                 # pointer to scalar with array len property
65                 $result .= DebugElement($e);
66             } else {
67                 $result .= "\ts->$prefix$e->{NAME} = $e->{TYPE}_from_python($obj);\n";
68             }
69         } else {
70             # Pointer to scalar
71             $result .= DebugElement($e);
72         }
73     } else {
74         # Non-scalar type
75         $result .= DebugElement($e);
76     }
77
78     return $result;
79 }
80
81 sub XToPython($$)
82 {
83     my($e) = shift;
84     my($prefix) = shift;
85     my($result) = "";
86
87     # Special cases
88
89     if ($e->{TYPE} eq "policy_handle" && $e->{POINTERS} == 1) {
90         $result .= "\tPyDict_SetItem(obj, PyString_FromString(\"$e->{NAME}\"), policy_handle_to_python(s->$prefix$e->{NAME}));\n";
91         return $result;
92     }
93
94     if ($e->{TYPE} eq "string" && $e->{POINTERS} == 1) {
95         $result .= "\tPyDict_SetItem(obj, PyString_FromString(\"$e->{NAME}\"), string_to_python(s->$prefix$e->{NAME}));\n";
96         return $result;
97     }
98
99     # Generate conversion for element
100
101     if (util::is_scalar_type($e->{TYPE})) {
102         if ($e->{POINTERS} == 0) {
103             if ($e->{ARRAY_LEN}) {
104                 # pointer to scalar with array len property
105                 $result .= DebugElement($e);
106             } else {
107                 $result .= "\tPyDict_SetItem(obj, PyString_FromString(\"$e->{NAME}\"), $e->{TYPE}_to_python(s->$prefix$e->{NAME}));\n";
108             }
109         } else {
110             # Pointer to scalar
111             $result .= DebugElement($e);
112         }
113     } else {
114         # Non-scalar type
115         $result .= DebugElement($e);
116     }
117
118     return $result;
119 }
120
121 sub ParseFunction($)
122 {
123     my($fn) = shift;
124
125     $res .= "%{\n\n";
126
127     $res .= "/* Convert Python dict to struct $fn->{NAME}.in */\n\n";
128
129     $res .= "int $fn->{NAME}_from_python(TALLOC_CTX *mem_ctx, struct $fn->{NAME} *s, PyObject *obj)\n";
130     $res .= "{\n";
131
132     foreach my $e (@{$fn->{DATA}}) {
133         $res .= XFromPython($e, "in.") if util::has_property($e, "in")
134     }
135
136     $res .= "\n";
137     $res .= "\treturn True;\n";
138     $res .= "}\n\n";
139
140     $res .= "/* Convert struct $fn->{NAME}.out to Python dict */\n\n";
141
142     $res .= "int $fn->{NAME}_to_python(TALLOC_CTX *mem_ctx, PyObject *obj, struct $fn->{NAME} *s)\n";
143     $res .= "{\n";
144
145     foreach my $e (@{$fn->{DATA}}) {
146         $res .= XToPython($e, "out.") if util::has_property($e, "out")
147     }
148
149     $res .= "\n";
150     $res .= "\treturn True;\n";
151     $res .= "}\n\n";
152
153     $res .= "%}\n\n";
154
155     # Input typemap
156
157     $res .= "%typemap(in) struct $fn->{NAME} * (struct $fn->{NAME} temp) {\n";
158     $res .= "\tTALLOC_CTX *mem_ctx = talloc_init(\"typemap(int) $fn->{NAME}\");\n\n";
159     $res .= "\t$fn->{NAME}_from_python(mem_ctx, &temp, \$input);\n";
160     $res .= "\t\$1 = &temp;\n";
161     $res .= "}\n\n";
162
163     # Output typemap
164
165     $res .= "%typemap(argout) struct $fn->{NAME} * {\n";
166     $res .= "\tTALLOC_CTX *mem_ctx = talloc_init(\"typemap(argout) $fn->{NAME}\");\n\n";
167     $res .= "\tlong status = PyLong_AsLong(resultobj);\n";
168     $res .= "\tPyObject *dict;\n";
169     $res .= "\n";
170     $res .= "\tif (status != 0) {\n";
171     $res .= "\t\tset_ntstatus_exception(status);\n";
172     $res .= "\t\treturn NULL;\n";
173     $res .= "\t}\n";
174     $res .= "\n";
175     $res .= "\tdict = PyDict_New();\n";
176
177     $res .= "\t$fn->{NAME}_to_python(mem_ctx, dict, \$1);\n";
178
179     $res .= "\tresultobj = dict;\n";
180     $res .= "}\n\n";
181
182     # Function definitions
183
184     $res .= "%rename($fn->{NAME}) dcerpc_$fn->{NAME};\n";
185     $res .= "$fn->{RETURN_TYPE} dcerpc_$fn->{NAME}(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $fn->{NAME} *r);\n\n";
186 }
187
188 sub ParseStruct($)
189 {
190     my($s) = shift;
191
192     $res .= "%{\n\n";
193     $res .= "/* Convert Python dict to struct $s->{NAME} */\n\n";
194     
195     $res .= "int python_to_$s->{NAME}(TALLOC_CTX *mem_ctx, struct $s->{NAME} *s, PyObject *obj)\n";
196     $res .= "{\n";
197
198     foreach my $e (@{$s->{DATA}{ELEMENTS}}) {
199         $res .= XFromPython($e, "");
200     }
201
202     $res .= "\n";
203     $res .= "\treturn TRUE;\n";
204     $res .= "}\n\n";
205
206     $res .= "/* Convert struct $s->{NAME} to Python dict */\n\n";
207
208     $res .= "int $s->{NAME}_to_python(TALLOC_CTX *mem_ctx, PyObject *obj, struct $s->{NAME} *s)\n";
209     $res .= "{\n";
210
211     foreach my $e (@{$s->{DATA}{ELEMENTS}}) {
212         $res .= XToPython($e, "");
213     }
214
215     $res .= "\n";
216     $res .= "\treturn TRUE;\n";
217     $res .= "}\n";
218
219     $res .= "\n%}\n\n";    
220 }
221
222 sub ParseTypedef($)
223 {
224     my($t) = shift;
225
226     foreach my $e ($t) {
227         ($e->{DATA}{TYPE} eq "STRUCT") && ParseStruct($e);
228     }
229 }
230
231 sub ParseInheritedData($)
232 {
233     my($data) = shift;
234
235     foreach my $e (@{$data}) {
236         ($e->{TYPE} eq "FUNCTION") && ParseFunction($e);
237         ($e->{TYPE} eq "TYPEDEF") && ParseTypedef($e);
238     }
239 }
240
241 sub ParseHeader($)
242 {
243     my($hdr) = shift;
244
245     $name = $hdr->{NAME};
246     $res .= "#define DCERPC_" . uc($name) . "_UUID \"$hdr->{PROPERTIES}->{uuid}\"\n";
247     $res .= "const int DCERPC_" . uc($name) . "_VERSION = " . $hdr->{PROPERTIES}->{version} . ";\n";
248     $res .= "#define DCERPC_" . uc($name) . "_NAME \"" . $name . "\"\n";
249     $res .= "\n";
250
251     ParseInheritedData($hdr->{INHERITED_DATA});    
252 }
253
254 sub Parse($)
255 {
256     my($idl) = shift;
257
258     $res = "/* auto-generated by pidl */\n\n";
259
260     foreach my $x (@{$idl}) {
261         ($x->{TYPE} eq "INTERFACE") && ParseHeader($x);
262     }
263
264     return $res;
265 }
266
267 1;