a5f80538340818436df56969eeabd4ff9f59b15a
[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->pidl(".tp_repr = py_talloc_default_repr,");
218         $self->deindent;
219         $self->pidl("};");
220
221         $self->pidl("");
222
223         my $py_fnname = "py_$name";
224         $self->pidl("static PyObject *$py_fnname(PyObject *self, PyObject *args)");
225         $self->pidl("{");
226         $self->indent;
227         $self->pidl("$cname *ret = talloc_zero(NULL, $cname);");
228         $self->pidl("return py_talloc_import(&$name\_ObjectType, ret);");
229         $self->deindent;
230         $self->pidl("}");
231         $self->pidl("");
232
233         return $py_fnname;
234 }
235
236 sub PythonFunction($$$)
237 {
238         my ($self, $fn, $iface) = @_;
239
240         $self->pidl("static PyObject *py_$fn->{NAME}(PyObject *self, PyObject *args)");
241         $self->pidl("{");
242         $self->indent;
243         $self->pidl("$iface\_InterfaceObject *iface = ($iface\_InterfaceObject *)self;");
244         $self->pidl("NTSTATUS status;");
245         $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
246         $self->pidl("struct $fn->{NAME} r;");
247         $self->pidl("PyObject *result;");
248         my $result_size = 0;
249
250         foreach my $e (@{$fn->{ELEMENTS}}) {
251                 if (grep(/in/,@{$e->{DIRECTION}})) {
252                         $self->pidl("PyObject *py_$e->{NAME};");
253                 }
254                 if (grep(/out/,@{$e->{DIRECTION}})) {
255                         $result_size++;
256                 }
257         }
258         if ($result_size > 0) {
259                 $self->pidl("");
260                 $self->pidl("ZERO_STRUCT(r.out);");
261         }
262         if ($fn->{RETURN_TYPE}) {
263                 $result_size++;
264         }
265
266         foreach my $e (@{$fn->{ELEMENTS}}) {
267                 if (grep(/in/,@{$e->{DIRECTION}})) {
268                         $self->ConvertObjectFromPython("mem_ctx", $e->{TYPE}, "py_$e->{NAME}", "r.in.$e->{NAME}");
269                 }
270         }
271         $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, &r);");
272         $self->handle_ntstatus("status", "NULL", "mem_ctx");
273
274         $self->pidl("result = PyTuple_New($result_size);");
275
276         my $i = 0;
277
278         foreach my $e (@{$fn->{ELEMENTS}}) {
279                 if (grep(/out/,@{$e->{DIRECTION}})) {
280                         $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($e->{TYPE}, "r.out.$e->{NAME}") . ");");
281
282                         $i++;
283                 }
284         }
285
286         if (defined($fn->{RETURN_TYPE})) {
287                 $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($fn->{RETURN_TYPE}, "r.out.result") . ");");
288         }
289
290         $self->pidl("talloc_free(mem_ctx);");
291         $self->pidl("return result;");
292         $self->deindent;
293         $self->pidl("}");
294         $self->pidl("");
295 }
296
297 sub handle_ntstatus($$$$)
298 {
299         my ($self, $var, $retval, $mem_ctx) = @_;
300
301         $self->pidl("if (NT_STATUS_IS_ERR($var)) {");
302         $self->indent;
303         $self->pidl("PyErr_SetString(PyExc_RuntimeError, nt_errstr($var));");
304         $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
305         $self->pidl("return $retval;");
306         $self->deindent;
307         $self->pidl("}");
308         $self->pidl("");
309 }
310
311 sub PythonType($$$)
312 {
313         my ($self, $d, $interface, $basename) = @_;
314
315         my $actual_ctype = $d;
316         if ($actual_ctype->{TYPE} eq "TYPEDEF") {
317                 $actual_ctype = $actual_ctype->{DATA};
318         }
319
320         if ($actual_ctype->{TYPE} eq "STRUCT") {
321                 my $py_fnname;
322                 if ($d->{TYPE} eq "STRUCT") {
323                         $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d);
324                 } else {
325                         $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d->{DATA});
326                 }
327
328                 my $fn_name = $d->{NAME};
329
330                 $fn_name =~ s/^$interface->{NAME}_//;
331                 $fn_name =~ s/^$basename\_//;
332
333                 $self->register_module_method($fn_name, $py_fnname, "METH_NOARGS", "NULL");
334         }
335
336         if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP") {
337                 $self->EnumAndBitmapConsts($d->{NAME}, $d);
338         }
339
340         if ($d->{TYPE} eq "TYPEDEF" and ($d->{DATA}->{TYPE} eq "ENUM" or $d->{DATA}->{TYPE} eq "BITMAP")) {
341                 $self->EnumAndBitmapConsts($d->{NAME}, $d->{DATA});
342         }
343
344         if ($actual_ctype->{TYPE} eq "UNION") {
345                 $self->pidl("PyObject *py_import_$d->{NAME}(int level, " .mapTypeName($d) . " *in)");
346                 $self->pidl("{");
347                 $self->indent;
348                 $self->FromUnionToPythonFunction($actual_ctype, "level", "in") if ($actual_ctype->{TYPE} eq "UNION");
349                 $self->deindent;
350                 $self->pidl("}");
351                 $self->pidl("");
352
353                 $self->pidl(mapTypeName($d) . " *py_export_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, PyObject *in)");
354                 $self->pidl("{");
355                 $self->indent;
356                 $self->FromPythonToUnionFunction($actual_ctype, mapTypeName($d), "level", "mem_ctx", "in") if ($actual_ctype->{TYPE} eq "UNION");
357                 $self->deindent;
358                 $self->pidl("}");
359                 $self->pidl("");
360         }
361 }
362
363 sub Interface($$$)
364 {
365         my($self,$interface,$basename) = @_;
366
367         $self->pidl_hdr("#ifndef _HEADER_PYTHON_$interface->{NAME}\n");
368         $self->pidl_hdr("#define _HEADER_PYTHON_$interface->{NAME}\n\n");
369
370         $self->pidl_hdr("\n");
371
372         $self->Const($_) foreach (@{$interface->{CONSTS}});
373
374         foreach my $d (@{$interface->{TYPES}}) {
375                 next if has_property($d, "nopython");
376
377                 $self->PythonType($d, $interface, $basename);
378         }
379
380         $self->pidl("staticforward PyTypeObject $interface->{NAME}_InterfaceType;");
381         $self->pidl("typedef struct {");
382         $self->indent;
383         $self->pidl("PyObject_HEAD");
384         $self->pidl("struct dcerpc_pipe *pipe;");
385         $self->deindent;
386         $self->pidl("} $interface->{NAME}_InterfaceObject;");
387
388         $self->pidl("");
389
390         foreach my $d (@{$interface->{FUNCTIONS}}) {
391                 next if not defined($d->{OPNUM});
392                 next if has_property($d, "nopython");
393
394                 $self->PythonFunction($d, $interface->{NAME});
395         }
396
397         $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
398         $self->indent;
399         foreach my $d (@{$interface->{FUNCTIONS}}) {
400                 next if not defined($d->{OPNUM});
401                 next if has_property($d, "nopython");
402
403                 my $fn_name = $d->{NAME};
404
405                 $fn_name =~ s/^$interface->{NAME}_//;
406
407                 $self->pidl("{ \"$fn_name\", (PyCFunction)py_$d->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
408         }
409         $self->pidl("{ NULL, NULL, 0, NULL }");
410         $self->deindent;
411         $self->pidl("};");
412         $self->pidl("");
413
414         $self->pidl("static void interface_$interface->{NAME}_dealloc(PyObject* self)");
415         $self->pidl("{");
416         $self->indent;
417         $self->pidl("$interface->{NAME}_InterfaceObject *interface = ($interface->{NAME}_InterfaceObject *)self;");
418         $self->pidl("talloc_free(interface->pipe);");
419         $self->pidl("PyObject_Del(self);");
420         $self->deindent;
421         $self->pidl("}");
422         $self->pidl("");
423
424         $self->pidl("static PyObject *interface_$interface->{NAME}_getattr(PyObject *obj, char *name)");
425         $self->pidl("{");
426         $self->indent;
427         $self->pidl("return Py_FindMethod(interface_$interface->{NAME}\_methods, obj, name);");
428         $self->deindent;
429         $self->pidl("}");
430
431         $self->pidl("");
432
433         $self->pidl("static PyTypeObject $interface->{NAME}_InterfaceType = {");
434         $self->indent;
435         $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
436         $self->pidl(".tp_name = \"$interface->{NAME}\",");
437         $self->pidl(".tp_basicsize = sizeof($interface->{NAME}_InterfaceObject),");
438         $self->pidl(".tp_dealloc = (destructor)interface_$interface->{NAME}_dealloc,");
439         $self->pidl(".tp_getattr = (getattrfunc)interface_$interface->{NAME}_getattr,");
440         $self->deindent;
441         $self->pidl("};");
442
443         $self->pidl("");
444
445         $self->register_module_method($interface->{NAME}, "interface_$interface->{NAME}", "METH_VARARGS|METH_KEYWORDS", "NULL");
446         $self->pidl("static PyObject *interface_$interface->{NAME}(PyObject *self, PyObject *args)");
447         $self->pidl("{");
448         $self->indent;
449         $self->pidl("$interface->{NAME}_InterfaceObject *ret;");
450         $self->pidl("const char *binding_string;");
451         $self->pidl("struct cli_credentials *credentials;");
452         $self->pidl("struct loadparm_context *lp_ctx;");
453         $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
454         $self->pidl("NTSTATUS status;");
455         $self->pidl("");
456
457         # FIXME: Arguments: binding string, credentials, loadparm context
458         $self->pidl("ret = PyObject_New($interface->{NAME}_InterfaceObject, &$interface->{NAME}_InterfaceType);");
459         $self->pidl("");
460
461         $self->pidl("status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, ");
462         $self->pidl("             &ndr_table_$interface->{NAME}, credentials, NULL, lp_ctx);");
463         $self->handle_ntstatus("status", "NULL", "mem_ctx");
464
465         $self->pidl("return (PyObject *)ret;");
466         $self->deindent;
467         $self->pidl("}");
468         
469         $self->pidl("");
470
471         $self->pidl_hdr("\n");
472         $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */\n");
473 }
474
475 sub register_module_method($$$$$)
476 {
477         my ($self, $fn_name, $pyfn_name, $flags, $doc) = @_;
478
479         push (@{$self->{module_methods}}, [$fn_name, $pyfn_name, $flags, $doc])
480 }
481
482 sub ConvertObjectFromPython($$$$$)
483 {
484         my ($self, $mem_ctx, $ctype, $cvar, $target) = @_;
485
486         die("undef type for $cvar") unless(defined($ctype));
487
488         if (ref($ctype) ne "HASH") {
489                 $ctype = getType($ctype);
490         }
491
492         if (ref($ctype) ne "HASH") {
493                 $self->pidl("$target = FIXME($cvar);");
494                 return;
495         }
496
497         my $actual_ctype = $ctype;
498         if ($ctype->{TYPE} eq "TYPEDEF") {
499                 $actual_ctype = $ctype->{DATA};
500         }
501
502         if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or 
503                 $actual_ctype->{TYPE} eq "SCALAR" and (
504                 expandAlias($actual_ctype->{NAME}) =~ /^(u?int[0-9]+|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong|udlongr)$/)) {
505                 $self->pidl("$target = PyInt_AsLong($cvar);");
506                 return;
507         }
508
509         if ($actual_ctype->{TYPE} eq "STRUCT") {
510                 $self->pidl("$target = py_talloc_get_type($cvar, " . mapTypeName($ctype) . ");");
511                 return;
512         }
513
514         if ($actual_ctype->{TYPE} eq "UNION") {
515                 $self->pidl("$target = py_export_$ctype->{NAME}($cvar);");
516                 return;
517         }
518
519         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "DATA_BLOB") {
520                 $self->pidl("$target = data_blob_talloc($mem_ctx, PyString_AsString($cvar), PyString_Size($cvar));");
521                 return;
522         }
523
524         if ($actual_ctype->{TYPE} eq "SCALAR" and 
525                 ($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")) {
526                 $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AsString($cvar));");
527                 return;
528         }
529
530         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
531                 $self->pidl("$target = FIXME($cvar);");
532                 return;
533                 }
534
535
536         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") {
537                 $self->pidl("$target = PyInt_AsLong($cvar);");
538                 return;
539         }
540
541         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") {
542                 $self->pidl("$target = PyInt_AsLong($cvar);");
543                 return;
544         }
545
546         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "string_array") {
547                 $self->pidl("$target = FIXME($cvar);");
548                 return;
549         }
550
551         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "pointer") {
552                 $self->pidl("$target = PyCObject_AsVoidPtr($cvar);");
553                 return;
554         }
555
556         die("unknown type ".mapTypeName($ctype) . ": $cvar");
557 }
558
559 sub ConvertScalarToPython($$$)
560 {
561         my ($self, $ctypename, $cvar) = @_;
562
563         die("expected string for $cvar, not $ctypename") if (ref($ctypename) eq "HASH");
564
565         $ctypename = expandAlias($ctypename);
566
567         if ($ctypename =~ /^(int|long|char|u?int[0-9]+|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) {
568                 return "PyInt_FromLong($cvar)";
569         }
570
571         if ($ctypename eq "DATA_BLOB") {
572                 return "PyString_FromStringAndSize($cvar->data, $cvar->length)";
573         }
574
575         if ($ctypename eq "NTSTATUS") {
576                 return "PyInt_FromLong(NT_STATUS_V($cvar))";
577         }
578
579         if ($ctypename eq "WERROR") {
580                 return "PyInt_FromLong(W_ERROR_V($cvar))";
581         }
582
583         if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) {
584                 return "PyString_FromString($cvar)";
585         }
586
587         if ($ctypename eq "string_array") { return "FIXME($cvar)"; }
588
589         if ($ctypename eq "ipv4address") { return "FIXME($cvar)"; }
590         if ($ctypename eq "pointer") {
591                 return "PyCObject_FromVoidPtr($cvar, talloc_free)";
592         }
593
594         die("Unknown scalar type $ctypename");
595 }
596
597 sub ConvertObjectToPython($$$)
598 {
599         my ($self, $ctype, $cvar) = @_;
600
601         die("undef type for $cvar") unless(defined($ctype));
602
603         if (ref($ctype) ne "HASH") {
604                 if (not hasType($ctype)) {
605                         if (ref($ctype) eq "HASH") {
606                                 return "py_import_$ctype->{TYPE}_$ctype->{NAME}($cvar)";
607                         } else {
608                                 return "py_import_$ctype($cvar)"; # best bet
609                         }
610                 }
611
612                 $ctype = getType($ctype);
613         }
614
615         my $actual_ctype = $ctype;
616         if ($ctype->{TYPE} eq "TYPEDEF") {
617                 $actual_ctype = $ctype->{DATA};
618         }
619
620         if ($actual_ctype->{TYPE} eq "ENUM") {
621                 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::enum_type_fn($actual_ctype), $cvar);
622         }
623
624         if ($actual_ctype->{TYPE} eq "BITMAP") {
625                 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::bitmap_type_fn($actual_ctype), $cvar);
626         }
627
628         if ($actual_ctype->{TYPE} eq "SCALAR") {
629                 return $self->ConvertScalarToPython($actual_ctype->{NAME}, $cvar);
630         }
631
632         if ($actual_ctype->{TYPE} eq "UNION") {
633                 return "py_import_$ctype->{NAME}($cvar)";
634         }
635
636         if ($actual_ctype->{TYPE} eq "STRUCT") {
637                 # FIXME: if $cvar is not a pointer, do a talloc_dup()
638                 return "py_talloc_import(&$ctype->{NAME}_ObjectType, $cvar)";
639         }
640
641         die("unknown type ".mapTypeName($ctype) . ": $cvar");
642 }
643
644 sub Parse($$$$$)
645 {
646     my($self,$basename,$ndr,$ndr_hdr,$hdr) = @_;
647     
648     my $py_hdr = $hdr;
649     $py_hdr =~ s/ndr_([^\/]+)$/py_$1/g;
650
651     $self->pidl_hdr("/* header auto-generated by pidl */\n\n");
652         
653     $self->pidl("
654 /* Python wrapper functions auto-generated by pidl */
655 #include \"includes.h\"
656 #include <Python.h>
657 #include \"librpc/rpc/dcerpc.h\"
658 #include \"scripting/python/pytalloc.h\"
659 #include \"$hdr\"
660 #include \"$ndr_hdr\"
661 #include \"$py_hdr\"
662
663 ");
664
665         foreach my $x (@$ndr) {
666             ($x->{TYPE} eq "INTERFACE") && $self->Interface($x, $basename);
667                 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}});
668         }
669         
670         $self->pidl("static PyMethodDef $basename\_methods[] = {");
671         $self->indent;
672         foreach (@{$self->{module_methods}}) {
673                 my ($fn_name, $pyfn_name, $flags, $doc) = @$_;
674                 $self->pidl("{ \"$fn_name\", (PyCFunction)$pyfn_name, $flags, $doc },");
675         }
676         
677         $self->pidl("{ NULL, NULL, 0, NULL }");
678         $self->deindent;
679         $self->pidl("};");
680
681         $self->pidl("");
682
683         $self->pidl("void init$basename(void)");
684         $self->pidl("{");
685         $self->indent;
686         $self->pidl("PyObject *m;");
687         $self->pidl("m = Py_InitModule(\"$basename\", $basename\_methods);");
688         foreach my $name (keys %{$self->{constants}}) {
689                 my $py_obj;
690                 my ($ctype, $cvar) = @{$self->{constants}->{$name}};
691                 if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) {
692                         $py_obj = "PyInt_FromLong($cvar)";
693                 } elsif ($cvar =~ /^".*"$/) {
694                         $py_obj = "PyString_FromString($cvar)";
695                 } else {
696                         $py_obj = $self->ConvertObjectToPython($ctype, $cvar);
697                 }
698
699                 $self->pidl("PyModule_AddObject(m, \"$name\", $py_obj);");
700         }
701         $self->deindent;
702         $self->pidl("}");
703     return ($self->{res_hdr}, $self->{res});
704 }
705
706 1;