pidl/python: Work towards supporting more complex types (arrays, etc).
[ira/wip.git] / source / pidl / lib / Parse / Pidl / Samba4 / Python.pm
1 ###################################################
2 # Python function wrapper generator
3 # Copyright jelmer@samba.org 2007-2008
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 qw(hasType getType mapTypeName expandAlias);
13 use Parse::Pidl::Util qw(has_property ParseExpr);
14 use Parse::Pidl::CUtil qw(get_value_of get_pointer_to);
15
16 use vars qw($VERSION);
17 $VERSION = '0.01';
18
19 sub new($) {
20         my ($class) = @_;
21         my $self = { res => "", res_hdr => "", tabs => "", constants => {},
22                      module_methods => []};
23         bless($self, $class);
24 }
25
26 sub pidl_hdr ($$)
27 {
28         my $self = shift;
29         $self->{res_hdr} .= shift;
30 }
31
32 sub pidl($$)
33 {
34         my ($self, $d) = @_;
35         if ($d) {
36                 $self->{res} .= $self->{tabs};
37                 $self->{res} .= $d;
38         }
39         $self->{res} .= "\n";
40 }
41
42 sub indent($)
43 {
44         my ($self) = @_;
45         $self->{tabs} .= "\t";
46 }
47
48 sub deindent($)
49 {
50         my ($self) = @_;
51         $self->{tabs} = substr($self->{tabs}, 0, -1);
52 }
53
54 sub Import
55 {
56         my $self = shift;
57         my @imports = @_;
58         foreach (@imports) {
59                 s/\.idl\"$//;
60                 s/^\"//;
61                 $self->pidl_hdr("#include \"librpc/gen_ndr/py_$_\.h\"\n");
62         }
63 }
64
65 sub Const($$)
66 {
67     my ($self, $const) = @_;
68         $self->register_constant($const->{NAME}, $const->{DTYPE}, $const->{VALUE});
69 }
70
71 sub register_constant($$$$)
72 {
73         my ($self, $name, $type, $value) = @_;
74
75         $self->{constants}->{$name} = [$type, $value];
76 }
77
78 sub EnumAndBitmapConsts($$$)
79 {
80         my ($self, $name, $d) = @_;
81
82         return unless (defined($d->{ELEMENTS}));
83
84         foreach my $e (@{$d->{ELEMENTS}}) {
85                 $e =~ /^([A-Za-z0-9_]+)=(.*)$/;
86                 my $cname = $1;
87                 
88                 $self->register_constant($cname, $d, $cname);
89         }
90 }
91
92 sub FromUnionToPythonFunction($$$)
93 {
94         my ($self, $type, $switch, $name) = @_;
95
96         $self->pidl("switch ($switch) {");
97         $self->indent;
98
99         foreach my $e (@{$type->{ELEMENTS}}) {
100                 my $conv;
101                 
102                 if ($e->{NAME}) {
103                         $conv = $self->ConvertObjectToPython($e->{TYPE}, "$name->$e->{NAME}");
104                 } else {
105                         $conv = "Py_None";
106                 }
107                 if (defined($e->{CASE})) {
108                         $self->pidl("$e->{CASE}: return $conv;");
109                 } else {
110                         $self->pidl("default: return $conv;");
111                 }
112         }
113
114         $self->deindent;
115         $self->pidl("}");
116
117         $self->pidl("PyErr_SetString(PyExc_TypeError, \"unknown union level\");");
118         $self->pidl("return NULL;");
119 }
120
121 sub FromPythonToUnionFunction($$$$$)
122 {
123         my ($self, $type, $typename, $switch, $mem_ctx, $name) = @_;
124
125         my $has_default = 0;
126
127         $self->pidl("$typename *ret = talloc_zero($mem_ctx, $typename);");
128
129         $self->pidl("switch ($switch) {");
130         $self->indent;
131
132         foreach my $e (@{$type->{ELEMENTS}}) {
133                 if (defined($e->{CASE})) {
134                         $self->pidl("$e->{CASE}:");
135                 } else {
136                         $has_default = 1;
137                         $self->pidl("default:");
138                 }
139                 $self->indent;
140                 if ($e->{NAME}) {
141                         $self->ConvertObjectFromPython($mem_ctx, $e->{TYPE}, $name, "ret->$e->{NAME}");
142                 }
143                 $self->pidl("break;");
144                 $self->deindent;
145                 $self->pidl("");
146         }
147
148         if (!$has_default) {
149                 $self->pidl("default:");
150                 $self->indent;
151                 $self->pidl("PyErr_SetString(PyExc_TypeError, \"invalid union level value\");");
152                 $self->pidl("talloc_free(ret);");
153                 $self->pidl("ret = NULL;");
154                 $self->deindent;
155         }
156
157         $self->deindent;
158         $self->pidl("}");
159         $self->pidl("");
160         $self->pidl("return ret;");
161 }
162
163 sub PythonStruct($$$$)
164 {
165         my ($self, $name, $cname, $d) = @_;
166
167         $self->pidl("staticforward PyTypeObject $name\_ObjectType;");
168
169         $self->pidl("");
170
171         $self->pidl("static PyObject *py_$name\_getattr(PyObject *obj, char *name)");
172         $self->pidl("{");
173         $self->indent;
174         $self->pidl("$cname *object = py_talloc_get_type(obj, $cname);");
175         foreach my $e (@{$d->{ELEMENTS}}) {
176                 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
177                 my $varname = "object->$e->{NAME}";
178                 $self->indent;
179                 $self->pidl("return ".$self->ConvertObjectToPython($e->{TYPE}, $varname) . ";");
180                 $self->deindent;
181                 $self->pidl("}");
182         }
183         $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
184         $self->pidl("return NULL;");
185         $self->deindent;
186         $self->pidl("}");
187         $self->pidl("");
188
189         $self->pidl("static int py_$name\_setattr(PyObject *py_obj, char *name, PyObject *value)");
190         $self->pidl("{");
191         $self->indent;
192         $self->pidl("$cname *object = py_talloc_get_type(py_obj, $cname);");
193         foreach my $e (@{$d->{ELEMENTS}}) {
194                 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
195                 my $varname = "object->$e->{NAME}";
196                 $self->indent;
197                 $self->pidl("/* FIXME: talloc_free($varname) if necessary */");
198                 $self->ConvertObjectFromPython("mem_ctx", $e->{TYPE}, "value", $varname);
199                 $self->pidl("return 0;");
200                 $self->deindent;
201                 $self->pidl("}");
202         }
203         $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
204         $self->pidl("return -1;");
205         $self->deindent;
206         $self->pidl("}");
207         $self->pidl("");
208
209         $self->pidl("static PyTypeObject $name\_ObjectType = {");
210         $self->indent;
211         $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
212         $self->pidl(".tp_name = \"$name\",");
213         $self->pidl(".tp_basicsize = sizeof(py_talloc_Object),");
214         $self->pidl(".tp_dealloc = py_talloc_dealloc,");
215         $self->pidl(".tp_getattr = py_$name\_getattr,");
216         $self->pidl(".tp_setattr = py_$name\_setattr,");
217         $self->deindent;
218         $self->pidl("};");
219
220         $self->pidl("");
221
222         my $py_fnname = "py_$name";
223         $self->pidl("static PyObject *$py_fnname(PyObject *self, PyObject *args)");
224         $self->pidl("{");
225         $self->indent;
226         $self->pidl("$cname *ret = talloc_zero(NULL, $cname);");
227         $self->pidl("return py_talloc_import(&$name\_ObjectType, ret);");
228         $self->deindent;
229         $self->pidl("}");
230         $self->pidl("");
231
232         return $py_fnname;
233 }
234
235 sub PythonFunction($$$)
236 {
237         my ($self, $fn, $iface) = @_;
238
239         $self->pidl("static PyObject *py_$fn->{NAME}(PyObject *self, PyObject *args)");
240         $self->pidl("{");
241         $self->indent;
242         $self->pidl("$iface\_InterfaceObject *iface = ($iface\_InterfaceObject *)self;");
243         $self->pidl("NTSTATUS status;");
244         $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
245         $self->pidl("struct $fn->{NAME} r;");
246         $self->pidl("PyObject *result;");
247         my $result_size = 0;
248
249         foreach my $e (@{$fn->{ELEMENTS}}) {
250                 if (grep(/in/,@{$e->{DIRECTION}})) {
251                         $self->pidl("PyObject *py_$e->{NAME};");
252                 }
253                 if (grep(/out/,@{$e->{DIRECTION}})) {
254                         $result_size++;
255                 }
256         }
257         if ($result_size > 0) {
258                 $self->pidl("");
259                 $self->pidl("ZERO_STRUCT(r.out);");
260         }
261         if ($fn->{RETURN_TYPE}) {
262                 $result_size++;
263         }
264
265         foreach my $e (@{$fn->{ELEMENTS}}) {
266                 if (grep(/in/,@{$e->{DIRECTION}})) {
267                         $self->ConvertObjectFromPython("mem_ctx", $e->{TYPE}, "py_$e->{NAME}", "r.in.$e->{NAME}");
268                 }
269         }
270         $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, &r);");
271         $self->handle_ntstatus("status", "NULL", "mem_ctx");
272
273         $self->pidl("result = PyTuple_New($result_size);");
274
275         my $i = 0;
276
277         foreach my $e (@{$fn->{ELEMENTS}}) {
278                 if (grep(/out/,@{$e->{DIRECTION}})) {
279                         $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($e->{TYPE}, "r.out.$e->{NAME}") . ");");
280
281                         $i++;
282                 }
283         }
284
285         if (defined($fn->{RETURN_TYPE})) {
286                 $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($fn->{RETURN_TYPE}, "r.out.result") . ");");
287         }
288
289         $self->pidl("talloc_free(mem_ctx);");
290         $self->pidl("return result;");
291         $self->deindent;
292         $self->pidl("}");
293         $self->pidl("");
294 }
295
296 sub handle_ntstatus($$$$)
297 {
298         my ($self, $var, $retval, $mem_ctx) = @_;
299
300         $self->pidl("if (NT_STATUS_IS_ERR($var)) {");
301         $self->indent;
302         $self->pidl("PyErr_SetString(PyExc_RuntimeError, nt_errstr($var));");
303         $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
304         $self->pidl("return $retval;");
305         $self->deindent;
306         $self->pidl("}");
307         $self->pidl("");
308 }
309
310 sub PythonType($$$)
311 {
312         my ($self, $d, $interface, $basename) = @_;
313
314         my $actual_ctype = $d;
315         if ($actual_ctype->{TYPE} eq "TYPEDEF") {
316                 $actual_ctype = $actual_ctype->{DATA};
317         }
318
319         if ($actual_ctype->{TYPE} eq "STRUCT") {
320                 my $py_fnname;
321                 if ($d->{TYPE} eq "STRUCT") {
322                         $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d);
323                 } else {
324                         $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d->{DATA});
325                 }
326
327                 my $fn_name = $d->{NAME};
328
329                 $fn_name =~ s/^$interface->{NAME}_//;
330                 $fn_name =~ s/^$basename\_//;
331
332                 $self->register_module_method($fn_name, $py_fnname, "METH_NOARGS", "NULL");
333         }
334
335         if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP") {
336                 $self->EnumAndBitmapConsts($d->{NAME}, $d);
337         }
338
339         if ($d->{TYPE} eq "TYPEDEF" and ($d->{DATA}->{TYPE} eq "ENUM" or $d->{DATA}->{TYPE} eq "BITMAP")) {
340                 $self->EnumAndBitmapConsts($d->{NAME}, $d->{DATA});
341         }
342
343         if ($actual_ctype->{TYPE} eq "UNION") {
344                 $self->pidl("PyObject *py_import_$d->{NAME}(int level, " .mapTypeName($d) . " *in)");
345                 $self->pidl("{");
346                 $self->indent;
347                 $self->FromUnionToPythonFunction($actual_ctype, "level", "in") if ($actual_ctype->{TYPE} eq "UNION");
348                 $self->deindent;
349                 $self->pidl("}");
350                 $self->pidl("");
351
352                 $self->pidl(mapTypeName($d) . " *py_export_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, PyObject *in)");
353                 $self->pidl("{");
354                 $self->indent;
355                 $self->FromPythonToUnionFunction($actual_ctype, mapTypeName($d), "level", "mem_ctx", "in") if ($actual_ctype->{TYPE} eq "UNION");
356                 $self->deindent;
357                 $self->pidl("}");
358                 $self->pidl("");
359         }
360 }
361
362 sub Interface($$$)
363 {
364         my($self,$interface,$basename) = @_;
365
366         $self->pidl_hdr("#ifndef _HEADER_PYTHON_$interface->{NAME}\n");
367         $self->pidl_hdr("#define _HEADER_PYTHON_$interface->{NAME}\n\n");
368
369         $self->pidl_hdr("\n");
370
371         $self->Const($_) foreach (@{$interface->{CONSTS}});
372
373         foreach my $d (@{$interface->{TYPES}}) {
374                 next if has_property($d, "nopython");
375
376                 $self->PythonType($d, $interface, $basename);
377         }
378
379         $self->pidl("staticforward PyTypeObject $interface->{NAME}_InterfaceType;");
380         $self->pidl("typedef struct {");
381         $self->indent;
382         $self->pidl("PyObject_HEAD");
383         $self->pidl("struct dcerpc_pipe *pipe;");
384         $self->deindent;
385         $self->pidl("} $interface->{NAME}_InterfaceObject;");
386
387         $self->pidl("");
388
389         foreach my $d (@{$interface->{FUNCTIONS}}) {
390                 next if not defined($d->{OPNUM});
391                 next if has_property($d, "nopython");
392
393                 $self->PythonFunction($d, $interface->{NAME});
394         }
395
396         $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
397         $self->indent;
398         foreach my $d (@{$interface->{FUNCTIONS}}) {
399                 next if not defined($d->{OPNUM});
400                 next if has_property($d, "nopython");
401
402                 my $fn_name = $d->{NAME};
403
404                 $fn_name =~ s/^$interface->{NAME}_//;
405
406                 $self->pidl("{ \"$fn_name\", (PyCFunction)py_$d->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
407         }
408         $self->pidl("{ NULL, NULL, 0, NULL }");
409         $self->deindent;
410         $self->pidl("};");
411         $self->pidl("");
412
413         $self->pidl("static void interface_$interface->{NAME}_dealloc(PyObject* self)");
414         $self->pidl("{");
415         $self->indent;
416         $self->pidl("$interface->{NAME}_InterfaceObject *interface = ($interface->{NAME}_InterfaceObject *)self;");
417         $self->pidl("talloc_free(interface->pipe);");
418         $self->pidl("PyObject_Del(self);");
419         $self->deindent;
420         $self->pidl("}");
421         $self->pidl("");
422
423         $self->pidl("static PyObject *interface_$interface->{NAME}_getattr(PyObject *obj, char *name)");
424         $self->pidl("{");
425         $self->indent;
426         $self->pidl("return Py_FindMethod(interface_$interface->{NAME}\_methods, obj, name);");
427         $self->deindent;
428         $self->pidl("}");
429
430         $self->pidl("");
431
432         $self->pidl("static PyTypeObject $interface->{NAME}_InterfaceType = {");
433         $self->indent;
434         $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
435         $self->pidl(".tp_name = \"$interface->{NAME}\",");
436         $self->pidl(".tp_basicsize = sizeof($interface->{NAME}_InterfaceObject),");
437         $self->pidl(".tp_dealloc = (destructor)interface_$interface->{NAME}_dealloc,");
438         $self->pidl(".tp_getattr = (getattrfunc)interface_$interface->{NAME}_getattr,");
439         $self->deindent;
440         $self->pidl("};");
441
442         $self->pidl("");
443
444         $self->register_module_method($interface->{NAME}, "interface_$interface->{NAME}", "METH_VARARGS|METH_KEYWORDS", "NULL");
445         $self->pidl("static PyObject *interface_$interface->{NAME}(PyObject *self, PyObject *args)");
446         $self->pidl("{");
447         $self->indent;
448         $self->pidl("$interface->{NAME}_InterfaceObject *ret;");
449         $self->pidl("const char *binding_string;");
450         $self->pidl("struct cli_credentials *credentials;");
451         $self->pidl("struct loadparm_context *lp_ctx;");
452         $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
453         $self->pidl("NTSTATUS status;");
454         $self->pidl("");
455
456         # FIXME: Arguments: binding string, credentials, loadparm context
457         $self->pidl("ret = PyObject_New($interface->{NAME}_InterfaceObject, &$interface->{NAME}_InterfaceType);");
458         $self->pidl("");
459
460         $self->pidl("status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, ");
461         $self->pidl("             &ndr_table_$interface->{NAME}, credentials, NULL, lp_ctx);");
462         $self->handle_ntstatus("status", "NULL", "mem_ctx");
463
464         $self->pidl("return (PyObject *)ret;");
465         $self->deindent;
466         $self->pidl("}");
467         
468         $self->pidl("");
469
470         $self->pidl_hdr("\n");
471         $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */\n");
472 }
473
474 sub register_module_method($$$$$)
475 {
476         my ($self, $fn_name, $pyfn_name, $flags, $doc) = @_;
477
478         push (@{$self->{module_methods}}, [$fn_name, $pyfn_name, $flags, $doc])
479 }
480
481 sub ConvertObjectFromPython($$$$$)
482 {
483         my ($self, $mem_ctx, $ctype, $cvar, $target) = @_;
484
485         die("undef type for $cvar") unless(defined($ctype));
486
487         if (ref($ctype) ne "HASH") {
488                 $ctype = getType($ctype);
489         }
490
491         if (ref($ctype) ne "HASH") {
492                 $self->pidl("$target = FIXME($cvar);");
493                 return;
494         }
495
496         my $actual_ctype = $ctype;
497         if ($ctype->{TYPE} eq "TYPEDEF") {
498                 $actual_ctype = $ctype->{DATA};
499         }
500
501         if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or 
502                 $actual_ctype->{TYPE} eq "SCALAR" and (
503                 expandAlias($actual_ctype->{NAME}) =~ /^(u?int[0-9]+|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong|udlongr)$/)) {
504                 $self->pidl("$target = PyInt_AsLong($cvar);");
505                 return;
506         }
507
508         if ($actual_ctype->{TYPE} eq "STRUCT") {
509                 $self->pidl("$target = py_talloc_get_type($cvar, " . mapTypeName($ctype) . ");");
510                 return;
511         }
512
513         if ($actual_ctype->{TYPE} eq "UNION") {
514                 $self->pidl("$target = py_export_$ctype->{NAME}($cvar);");
515                 return;
516         }
517
518         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "DATA_BLOB") {
519                 $self->pidl("$target = data_blob_talloc($mem_ctx, PyString_AsString($cvar), PyString_Size($cvar));");
520                 return;
521         }
522
523         if ($actual_ctype->{TYPE} eq "SCALAR" and 
524                 ($actual_ctype->{NAME} eq "string" or $actual_ctype->{NAME} eq "nbt_string" or $actual_ctype->{NAME} eq "nbt_name" or $actual_ctype->{NAME} eq "wrepl_nbt_name")) {
525                 $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AsString($cvar));");
526                 return;
527         }
528
529         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
530                 $self->pidl("$target = FIXME($cvar);");
531                 return;
532                 }
533
534
535         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") {
536                 $self->pidl("$target = PyInt_AsLong($cvar);");
537                 return;
538         }
539
540         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") {
541                 $self->pidl("$target = PyInt_AsLong($cvar);");
542                 return;
543         }
544
545         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "string_array") {
546                 $self->pidl("$target = FIXME($cvar);");
547                 return;
548         }
549
550         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "pointer") {
551                 $self->pidl("$target = PyCObject_AsVoidPtr($cvar);");
552                 return;
553         }
554
555         die("unknown type ".mapTypeName($ctype) . ": $cvar");
556 }
557
558 sub ConvertScalarToPython($$$)
559 {
560         my ($self, $ctypename, $cvar) = @_;
561
562         $ctypename = expandAlias($ctypename);
563
564         if ($ctypename =~ /^(int|long|char|u?int[0-9]+|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) {
565                 return "PyInt_FromLong($cvar)";
566         }
567
568         if ($ctypename eq "DATA_BLOB") {
569                 return "PyString_FromStringAndSize($cvar->data, $cvar->length)";
570         }
571
572         if ($ctypename eq "NTSTATUS") {
573                 return "PyInt_FromLong(NT_STATUS_V($cvar))";
574         }
575
576         if ($ctypename eq "WERROR") {
577                 return "PyInt_FromLong(W_ERROR_V($cvar))";
578         }
579
580         if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) {
581                 return "PyString_FromString($cvar)";
582         }
583
584         if ($ctypename eq "string_array") { return "FIXME($cvar)"; }
585
586         if ($$ctypename eq "ipv4address") { return "FIXME($cvar)"; }
587         if ($ctypename eq "pointer") {
588                 return "PyCObject_FromVoidPtr($cvar, talloc_free)";
589         }
590
591         die("Unknown scalar type $ctypename");
592 }
593
594 sub ConvertObjectToPython($$$)
595 {
596         my ($self, $ctype, $cvar) = @_;
597
598         die("undef type for $cvar") unless(defined($ctype));
599
600         if (ref($ctype) ne "HASH") {
601                 if (not hasType($ctype)) {
602                         if (ref($ctype) eq "HASH") {
603                                 return "py_import_$ctype->{TYPE}_$ctype->{NAME}($cvar)";
604                         } else {
605                                 return "py_import_$ctype($cvar)"; # best bet
606                         }
607                 }
608
609                 $ctype = getType($ctype);
610         }
611
612         my $actual_ctype = $ctype;
613         if ($ctype->{TYPE} eq "TYPEDEF") {
614                 $actual_ctype = $ctype->{DATA};
615         }
616
617         if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or 
618                 ($actual_ctype->{TYPE} eq "SCALAR") {
619                 return $self->ConvertScalarToPython($actual_ctype->{NAME}, $cvar);
620         }
621
622         if ($actual_ctype->{TYPE} eq "UNION") {
623                 return "py_import_$ctype->{NAME}($cvar)";
624         }
625
626         if ($actual_ctype->{TYPE} eq "STRUCT") {
627                 # FIXME: if $cvar is not a pointer, do a talloc_dup()
628                 return "py_talloc_import(&$ctype->{NAME}_ObjectType, $cvar)";
629         }
630
631         die("unknown type ".mapTypeName($ctype) . ": $cvar");
632 }
633
634 sub Parse($$$$$)
635 {
636     my($self,$basename,$ndr,$ndr_hdr,$hdr) = @_;
637     
638     my $py_hdr = $hdr;
639     $py_hdr =~ s/ndr_([^\/]+)$/py_$1/g;
640
641     $self->pidl_hdr("/* header auto-generated by pidl */\n\n");
642         
643     $self->pidl("
644 /* Python wrapper functions auto-generated by pidl */
645 #include \"includes.h\"
646 #include <Python.h>
647 #include \"librpc/rpc/dcerpc.h\"
648 #include \"scripting/python/pytalloc.h\"
649 #include \"$hdr\"
650 #include \"$ndr_hdr\"
651 #include \"$py_hdr\"
652
653 ");
654
655         foreach my $x (@$ndr) {
656             ($x->{TYPE} eq "INTERFACE") && $self->Interface($x, $basename);
657                 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}});
658         }
659         
660         $self->pidl("static PyMethodDef $basename\_methods[] = {");
661         $self->indent;
662         foreach (@{$self->{module_methods}}) {
663                 my ($fn_name, $pyfn_name, $flags, $doc) = @$_;
664                 $self->pidl("{ \"$fn_name\", (PyCFunction)$pyfn_name, $flags, $doc },");
665         }
666         
667         $self->pidl("{ NULL, NULL, 0, NULL }");
668         $self->deindent;
669         $self->pidl("};");
670
671         $self->pidl("");
672
673         $self->pidl("void init$basename(void)");
674         $self->pidl("{");
675         $self->indent;
676         $self->pidl("PyObject *m;");
677         $self->pidl("m = Py_InitModule(\"$basename\", $basename\_methods);");
678         foreach (keys %{$self->{constants}}) {
679                 my $py_obj;
680                 my ($ctype, $cvar) = @{$self->{constants}->{$_}};
681                 if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) {
682                         $py_obj = "PyInt_FromLong($cvar)";
683                 } elsif ($cvar =~ /^".*"$/) {
684                         $py_obj = "PyString_FromString($cvar)";
685                 } else {
686                         $py_obj = $self->ConvertScalarToPython($ctype, $cvar);
687                 }
688
689                 $self->pidl("PyModule_AddObject(m, \"$_\", $py_obj);");
690         }
691         $self->deindent;
692         $self->pidl("}");
693     return ($self->{res_hdr}, $self->{res});
694 }
695
696 1;