7e2ded1ff7f04d4f44439197698cff4c76f96b44
[ira/wip.git] / source / pidl / lib / Parse / Pidl / Samba4 / Python.pm
1 ###################################################
2 # Python function wrapper generator
3 # Copyright jelmer@samba.org 2007
4 # released under the GNU GPL
5
6 package Parse::Pidl::Samba4::Python;
7
8 use Exporter;
9 @ISA = qw(Exporter);
10
11 use strict;
12 use Parse::Pidl::Typelist;
13 use Parse::Pidl::Util qw(has_property ParseExpr);
14
15 use vars qw($VERSION);
16 $VERSION = '0.01';
17
18 sub new($) {
19         my ($class) = @_;
20         my $self = { res => "", res_hdr => "", tabs => "", constants => {}};
21         bless($self, $class);
22 }
23
24 sub pidl_hdr ($$)
25 {
26         my $self = shift;
27         $self->{res_hdr} .= shift;
28 }
29
30 sub pidl($$)
31 {
32         my ($self, $d) = @_;
33         if ($d) {
34                 $self->{res} .= $self->{tabs};
35                 $self->{res} .= $d;
36         }
37         $self->{res} .= "\n";
38 }
39
40 sub indent($)
41 {
42         my ($self) = @_;
43         $self->{tabs} .= "\t";
44 }
45
46 sub deindent($)
47 {
48         my ($self) = @_;
49         $self->{tabs} = substr($self->{tabs}, 0, -1);
50 }
51
52 sub Import
53 {
54         my $self = shift;
55         my @imports = @_;
56         foreach (@imports) {
57                 s/\.idl\"$//;
58                 s/^\"//;
59                 $self->pidl_hdr("#include \"librpc/gen_ndr/py_$_\.h\"\n");
60         }
61 }
62
63 sub Const($$)
64 {
65     my ($self, $const) = @_;
66     $self->{constants}->{$const->{NAME}} = [$const->{DATA}->{TYPE}, $const->{VALUE}];
67 }
68
69 sub FromTypeToPythonFunction($$)
70 {
71         my ($self, $type) = @_;
72
73         #FIXME
74 }
75
76 sub FromPythonToTypeFunction($$)
77 {
78         my ($self, $type) = @_;
79
80         #FIXME
81 }
82
83 sub TypeConstructor($$)
84 {
85         my ($self, $type) = @_;
86
87         $self->pidl("static PyObject *py_$type->{NAME}(PyObject *self, PyObject *args)");
88         $self->pidl("{");
89         $self->indent;
90         #FIXME
91
92         $self->pidl("return Py_None;");
93         $self->deindent;
94         $self->pidl("}");
95         $self->pidl("");
96 }
97
98 sub PythonFunction($$$)
99 {
100         my ($self, $fn, $iface) = @_;
101
102         $self->pidl("static PyObject *py_$fn->{NAME}(PyObject *self, PyObject *args)");
103         $self->pidl("{");
104         $self->indent;
105         $self->pidl("$iface\_InterfaceObject *iface = ($iface\_InterfaceObject *)self;");
106         $self->pidl("NTSTATUS status;");
107         $self->pidl("");
108         # FIXME
109         $self->handle_ntstatus("status", "NULL");
110         $self->pidl("return Py_None;");
111         $self->deindent;
112         $self->pidl("}");
113         $self->pidl("");
114 }
115
116 sub handle_ntstatus($$$)
117 {
118         my ($self, $var, $retval) = @_;
119
120         $self->pidl("if (NT_STATUS_IS_ERR($var)) {");
121         $self->indent;
122         $self->pidl("PyErr_SetString(PyExc_RuntimeError, nt_errstr($var));");
123         $self->pidl("return $retval;");
124         $self->deindent;
125         $self->pidl("}");
126         $self->pidl("");
127 }
128
129 sub Interface($$)
130 {
131         my($self,$interface) = @_;
132
133         $self->pidl_hdr("#ifndef _HEADER_PYTHON_$interface->{NAME}\n");
134         $self->pidl_hdr("#define _HEADER_PYTHON_$interface->{NAME}\n\n");
135
136         $self->pidl_hdr("\n");
137
138         $self->Const($_) foreach (@{$interface->{CONSTS}});
139
140         foreach (@{$interface->{TYPES}}) {
141                 $self->FromTypeToPythonFunction($_);    
142                 $self->FromPythonToTypeFunction($_);    
143                 $self->TypeConstructor($_);
144         }
145
146         $self->pidl("staticforward PyTypeObject $interface->{NAME}_InterfaceType;");
147         $self->pidl("typedef struct {");
148         $self->indent;
149         $self->pidl("PyObject_HEAD");
150         $self->pidl("struct dcerpc_pipe *pipe;");
151         $self->deindent;
152         $self->pidl("} $interface->{NAME}_InterfaceObject;");
153
154         $self->pidl("");
155
156         foreach my $d (@{$interface->{FUNCTIONS}}) {
157                 next if not defined($d->{OPNUM});
158                 next if has_property($d, "nopython");
159
160                 $self->PythonFunction($d, $interface->{NAME});
161         }
162
163         $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
164         $self->indent;
165         foreach my $d (@{$interface->{FUNCTIONS}}) {
166                 next if not defined($d->{OPNUM});
167                 next if has_property($d, "nopython");
168
169                 my $fn_name = $d->{NAME};
170
171                 $fn_name =~ s/^$interface->{NAME}_//;
172
173                 $self->pidl("{ (char *)\"$fn_name\", (PyCFunction)py_$d->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
174         }
175         $self->pidl("{ NULL, NULL, 0, NULL }");
176         $self->deindent;
177         $self->pidl("};");
178         $self->pidl("");
179
180         $self->pidl("static void interface_$interface->{NAME}_dealloc(PyObject* self)");
181         $self->pidl("{");
182         $self->indent;
183         $self->pidl("$interface->{NAME}_InterfaceObject *interface = ($interface->{NAME}_InterfaceObject *)self;");
184         $self->pidl("talloc_free(interface->pipe);");
185         $self->pidl("PyObject_Del(self);");
186         $self->deindent;
187         $self->pidl("}");
188         $self->pidl("");
189
190         $self->pidl("static PyObject *interface_$interface->{NAME}_getattr(PyTypeObject *obj, char *name)");
191         $self->pidl("{");
192         $self->indent;
193         $self->pidl("return Py_FindMethod(interface_$interface->{NAME}\_methods, (PyObject *)obj, name);");
194         $self->deindent;
195         $self->pidl("}");
196
197         $self->pidl("");
198
199         $self->pidl("static PyTypeObject $interface->{NAME}_InterfaceType = {");
200         $self->indent;
201         $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
202         $self->pidl(".tp_name = \"$interface->{NAME}\",");
203         $self->pidl(".tp_basicsize = sizeof($interface->{NAME}_InterfaceObject),");
204         $self->pidl(".tp_dealloc = interface_$interface->{NAME}_dealloc,");
205         $self->pidl(".tp_getattr = interface_$interface->{NAME}_getattr,");
206         $self->deindent;
207         $self->pidl("};");
208
209         $self->pidl("");
210
211         $self->pidl("static PyObject *interface_$interface->{NAME}(PyObject *self, PyObject *args)");
212         $self->pidl("{");
213         $self->indent;
214         $self->pidl("$interface->{NAME}_InterfaceObject *ret;");
215         $self->pidl("const char *binding_string;");
216         $self->pidl("struct cli_credentials *credentials;");
217         $self->pidl("struct loadparm_context *lp_ctx;");
218         $self->pidl("NTSTATUS status;");
219         $self->pidl("");
220
221         # FIXME: Arguments: binding string, credentials, loadparm context
222         $self->pidl("ret = PyObject_New($interface->{NAME}_InterfaceObject, &$interface->{NAME}_InterfaceType);");
223         $self->pidl("");
224
225         $self->pidl("status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, ");
226         $self->pidl("             &ndr_table_$interface->{NAME}, credentials, NULL, lp_ctx);");
227         $self->handle_ntstatus("status", "NULL");
228
229         $self->pidl("return (PyObject *)ret;");
230         $self->deindent;
231         $self->pidl("}");
232         
233         $self->pidl("");
234
235         $self->pidl_hdr("\n");
236         $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */\n");
237 }
238
239 sub Parse($$$$)
240 {
241     my($self,$basename,$ndr,$hdr) = @_;
242     
243     my $py_hdr = $hdr;
244     $py_hdr =~ s/ndr_([^\/]+)$/py_$1/g;
245
246     $self->pidl_hdr("/* header auto-generated by pidl */\n\n");
247         
248     $self->pidl("
249 /* Python wrapper functions auto-generated by pidl */
250 #include \"includes.h\"
251 #include <Python.h>
252 #include \"librpc/rpc/dcerpc.h\"
253 #include \"$hdr\"
254 #include \"$py_hdr\"
255
256 ");
257
258         foreach my $x (@$ndr) {
259             ($x->{TYPE} eq "INTERFACE") && $self->Interface($x);
260                 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}});
261         }
262         
263         $self->pidl("static PyMethodDef $basename\_methods[] = {");
264         $self->indent;
265         foreach my $x (@$ndr) {
266             next if ($x->{TYPE} ne "INTERFACE");
267                 $self->pidl("{ (char *)\"$x->{NAME}\", (PyCFunction)interface_$x->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
268
269                 foreach my $d (@{$x->{TYPES}}) {
270                         next if has_property($d, "nopython");
271                         next if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP");
272
273                         my $fn_name = $d->{NAME};
274
275                         $fn_name =~ s/^$x->{NAME}_//;
276                         $fn_name =~ s/^$basename\_//;
277
278                         $self->pidl("{ (char *)\"$fn_name\", (PyCFunction)py_$d->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
279                 }
280         }
281         
282         $self->pidl("{ NULL, NULL, 0, NULL }");
283         $self->deindent;
284         $self->pidl("};");
285
286         $self->pidl("");
287
288         $self->pidl("void init$basename(void)");
289         $self->pidl("{");
290         $self->indent;
291         $self->pidl("PyObject *m;");
292         $self->pidl("m = Py_InitModule((char *)\"$basename\", $basename\_methods);");
293         foreach (keys %{$self->{constants}}) {
294                 # FIXME: Handle non-string constants
295                 $self->pidl("PyModule_AddObject(m, \"$_\", PyString_FromString(" . $self->{constants}->{$_}->[1] . "));");
296         }
297         $self->deindent;
298         $self->pidl("}");
299     return ($self->{res_hdr}, $self->{res});
300 }
301
302 1;