Set docstrings from helpstring attribute where possible.
[jelmer/samba4-debian.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 resolveType getType mapTypeName expandAlias);
13 use Parse::Pidl::Util qw(has_property ParseExpr);
14 use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
15 use Parse::Pidl::CUtil qw(get_value_of get_pointer_to);
16 use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
17
18 use vars qw($VERSION);
19 $VERSION = '0.01';
20
21 sub new($) {
22         my ($class) = @_;
23         my $self = { res => "", res_hdr => "", tabs => "", constants => {},
24                      module_methods => []};
25         bless($self, $class);
26 }
27
28 sub pidl_hdr ($$)
29 {
30         my $self = shift;
31         $self->{res_hdr} .= shift;
32 }
33
34 sub pidl($$)
35 {
36         my ($self, $d) = @_;
37         if ($d) {
38                 $self->{res} .= $self->{tabs};
39                 $self->{res} .= $d;
40         }
41         $self->{res} .= "\n";
42 }
43
44 sub indent($)
45 {
46         my ($self) = @_;
47         $self->{tabs} .= "\t";
48 }
49
50 sub deindent($)
51 {
52         my ($self) = @_;
53         $self->{tabs} = substr($self->{tabs}, 0, -1);
54 }
55
56 sub Import
57 {
58         my $self = shift;
59         my @imports = @_;
60         foreach (@imports) {
61                 s/\.idl\"$//;
62                 s/^\"//;
63                 $self->pidl_hdr("#include \"librpc/gen_ndr/py_$_\.h\"\n");
64         }
65 }
66
67 sub Const($$)
68 {
69     my ($self, $const) = @_;
70         $self->register_constant($const->{NAME}, $const->{DTYPE}, $const->{VALUE});
71 }
72
73 sub register_constant($$$$)
74 {
75         my ($self, $name, $type, $value) = @_;
76
77         $self->{constants}->{$name} = [$type, $value];
78 }
79
80 sub EnumAndBitmapConsts($$$)
81 {
82         my ($self, $name, $d) = @_;
83
84         return unless (defined($d->{ELEMENTS}));
85
86         foreach my $e (@{$d->{ELEMENTS}}) {
87                 $e =~ /^([A-Za-z0-9_]+)/;
88                 my $cname = $1;
89                 
90                 $self->register_constant($cname, $d, $cname);
91         }
92 }
93
94 sub FromUnionToPythonFunction($$$$)
95 {
96         my ($self, $mem_ctx, $type, $switch, $name) = @_;
97
98         $self->pidl("PyObject *ret;");
99         $self->pidl("");
100
101         $self->pidl("switch ($switch) {");
102         $self->indent;
103
104         foreach my $e (@{$type->{ELEMENTS}}) {
105                 $self->pidl("$e->{CASE}:");
106
107                 $self->indent;
108
109                 if ($e->{NAME}) {
110                         $self->ConvertObjectToPython($mem_ctx, {}, $e, "$name->$e->{NAME}", "ret");
111                 } else {
112                         $self->pidl("ret = Py_None;");
113                 }
114
115                 $self->pidl("return ret;");
116                 $self->pidl("");
117
118                 $self->deindent;
119         }
120
121         $self->deindent;
122         $self->pidl("}");
123
124         $self->pidl("PyErr_SetString(PyExc_TypeError, \"unknown union level\");");
125         $self->pidl("return NULL;");
126 }
127
128 sub FromPythonToUnionFunction($$$$$)
129 {
130         my ($self, $type, $typename, $switch, $mem_ctx, $name) = @_;
131
132         my $has_default = 0;
133
134         $self->pidl("$typename *ret = talloc_zero($mem_ctx, $typename);");
135
136         $self->pidl("switch ($switch) {");
137         $self->indent;
138
139         foreach my $e (@{$type->{ELEMENTS}}) {
140                 $self->pidl("$e->{CASE}:");
141                 if ($e->{CASE} eq "default") { $has_default = 1; }
142                 $self->indent;
143                 if ($e->{NAME}) {
144                         $self->ConvertObjectFromPython({}, $mem_ctx, $e, $name, "ret->$e->{NAME}", "talloc_free(ret); return NULL;");
145                 }
146                 $self->pidl("break;");
147                 $self->deindent;
148                 $self->pidl("");
149         }
150
151         if (!$has_default) {
152                 $self->pidl("default:");
153                 $self->indent;
154                 $self->pidl("PyErr_SetString(PyExc_TypeError, \"invalid union level value\");");
155                 $self->pidl("talloc_free(ret);");
156                 $self->pidl("ret = NULL;");
157                 $self->deindent;
158         }
159
160         $self->deindent;
161         $self->pidl("}");
162         $self->pidl("");
163         $self->pidl("return ret;");
164 }
165
166 sub PythonStruct($$$$)
167 {
168         my ($self, $name, $cname, $d) = @_;
169
170         my $env = GenerateStructEnv($d, "object");
171
172         $self->pidl("");
173
174         $self->pidl("static PyObject *py_$name\_getattr(PyObject *obj, char *name)");
175         $self->pidl("{");
176         $self->indent;
177         if ($#{$d->{ELEMENTS}} > -1) {
178                 $self->pidl("$cname *object = py_talloc_get_ptr(obj);");
179                 foreach my $e (@{$d->{ELEMENTS}}) {
180                         $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
181                         my $varname = "object->$e->{NAME}";
182                         $self->indent;
183                         $self->pidl("PyObject *py_$e->{NAME};");
184                         $self->ConvertObjectToPython("py_talloc_get_mem_ctx(obj)", $env, $e, $varname, "py_$e->{NAME}");
185                         $self->pidl("return py_$e->{NAME};");
186                         $self->deindent;
187                         $self->pidl("}");
188                 }
189         }
190         $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
191         $self->pidl("return NULL;");
192         $self->deindent;
193         $self->pidl("}");
194         $self->pidl("");
195
196         $self->pidl("static int py_$name\_setattr(PyObject *py_obj, char *name, PyObject *value)");
197         $self->pidl("{");
198         $self->indent;
199         if ($#{$d->{ELEMENTS}} > -1) {
200                 $self->pidl("$cname *object = py_talloc_get_ptr(py_obj);");
201                 my $mem_ctx = "py_talloc_get_mem_ctx(py_obj)";
202                 foreach my $e (@{$d->{ELEMENTS}}) {
203                         $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
204                         my $varname = "object->$e->{NAME}";
205                         $self->indent;
206                         my $l = $e->{LEVELS}[0];
207                         my $nl = GetNextLevel($e, $l);
208                         if ($l->{TYPE} eq "POINTER" and 
209                                 not ($nl->{TYPE} eq "ARRAY" and ($nl->{IS_FIXED} or is_charset_array($e, $nl))) and
210                                 not ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE}))) {
211                                 $self->pidl("talloc_free($varname);");
212                         }
213                         $self->ConvertObjectFromPython($env, $mem_ctx, $e, "value", $varname, "return -1;");
214                         $self->pidl("return 0;");
215                         $self->deindent;
216                         $self->pidl("}");
217                 }
218         }
219         $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
220         $self->pidl("return -1;");
221         $self->deindent;
222         $self->pidl("}");
223         $self->pidl("");
224
225         $self->pidl_hdr("PyAPI_DATA(PyTypeObject) $name\_Type;\n");
226         $self->pidl_hdr("#define $name\_Check(op) PyObject_TypeCheck(op, &$name\_Type)\n");
227         $self->pidl_hdr("#define $name\_CheckExact(op) ((op)->ob_type == &$name\_Type)\n");
228         $self->pidl_hdr("\n");
229         my $docstring = $self->DocString($d, $name);
230         $self->pidl("PyTypeObject $name\_Type = {");
231         $self->indent;
232         $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
233         $self->pidl(".tp_name = \"$name\",");
234         $self->pidl(".tp_basicsize = sizeof(py_talloc_Object),");
235         $self->pidl(".tp_dealloc = py_talloc_dealloc,");
236         $self->pidl(".tp_getattr = py_$name\_getattr,");
237         $self->pidl(".tp_setattr = py_$name\_setattr,");
238         $self->pidl(".tp_repr = py_talloc_default_repr,");
239         $self->pidl(".tp_doc = $docstring,");
240         $self->deindent;
241         $self->pidl("};");
242
243         $self->pidl("");
244
245         my $py_fnname = "py_$name";
246         $self->pidl("static PyObject *$py_fnname(PyObject *self, PyObject *args)");
247         $self->pidl("{");
248         $self->indent;
249         $self->pidl("$cname *ret = talloc_zero(NULL, $cname);");
250         $self->pidl("return py_talloc_import(&$name\_Type, ret);");
251         $self->deindent;
252         $self->pidl("}");
253         $self->pidl("");
254
255         return ($py_fnname, "NULL");
256 }
257
258 sub PythonFunction($$$)
259 {
260         my ($self, $fn, $iface) = @_;
261
262         my $docstring = $self->DocString($fn, $fn->{NAME});
263
264         my $fnname = "py_$fn->{NAME}";
265
266         $self->pidl("static PyObject *$fnname(PyObject *self, PyObject *args, PyObject *kwargs)");
267         $self->pidl("{");
268         $self->indent;
269         $self->pidl("$iface\_InterfaceObject *iface = ($iface\_InterfaceObject *)self;");
270         $self->pidl("NTSTATUS status;");
271         $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
272         $self->pidl("struct $fn->{NAME} *r = talloc_zero(mem_ctx, struct $fn->{NAME});");
273         $self->pidl("PyObject *result = Py_None;");
274         
275         my $env = GenerateFunctionInEnv($fn, "r->");
276         my $result_size = 0;
277
278         my $args_format = "";
279         my $args_string = "";
280         my $args_names = "";
281
282         foreach my $e (@{$fn->{ELEMENTS}}) {
283                 $self->pidl("PyObject *py_$e->{NAME};");
284                 if (grep(/out/,@{$e->{DIRECTION}})) {
285                         $result_size++;
286                 }
287                 if (grep(/in/,@{$e->{DIRECTION}})) {
288                         $args_format .= "O";
289                         $args_string .= ", &py_$e->{NAME}";
290                         $args_names .= "\"$e->{NAME}\", ";
291                 }
292         }
293         $self->pidl("const char *kwnames[] = {");
294         $self->indent;
295         $self->pidl($args_names . "NULL");
296         $self->deindent;
297         $self->pidl("};");
298
299         $self->pidl("");
300         $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"$args_format:$fn->{NAME}\", discard_const_p(char *, kwnames)$args_string)) {");
301         $self->indent;
302         $self->pidl("return NULL;");
303         $self->deindent;
304         $self->pidl("}");
305
306         if ($fn->{RETURN_TYPE}) {
307                 $result_size++ unless ($fn->{RETURN_TYPE} eq "WERROR" or $fn->{RETURN_TYPE} eq "NTSTATUS");
308         }
309
310         foreach my $e (@{$fn->{ELEMENTS}}) {
311                 if (grep(/in/,@{$e->{DIRECTION}})) {
312                         $self->ConvertObjectFromPython($env, "mem_ctx", $e, "py_$e->{NAME}", "r->in.$e->{NAME}", "talloc_free(mem_ctx); return NULL;");
313                 }
314         }
315         $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, r);");
316         $self->handle_ntstatus("status", "NULL", "mem_ctx");
317
318         $env = GenerateFunctionOutEnv($fn, "r->");
319         my $i = 0;
320
321         if ($result_size > 1) {
322                 $self->pidl("result = PyTuple_New($result_size);");
323         }
324
325         foreach my $e (@{$fn->{ELEMENTS}}) {
326                 my $py_name = "py_$e->{NAME}";
327                 if (grep(/out/,@{$e->{DIRECTION}})) {
328                         $self->ConvertObjectToPython("r", $env, $e, "r->out.$e->{NAME}", $py_name);
329                         if ($result_size > 1) {
330                                 $self->pidl("PyTuple_SetItem(result, $i, $py_name);");
331                                 $i++;
332                         } else {
333                                 $self->pidl("result = $py_name;");
334                         }
335                 }
336         }
337
338         if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") {
339                 $self->handle_ntstatus("r->out.result", "NULL", "mem_ctx");
340         } elsif (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "WERROR") {
341                 $self->handle_werror("r->out.result", "NULL", "mem_ctx");
342         } elsif (defined($fn->{RETURN_TYPE})) {
343                 my $conv = $self->ConvertObjectToPythonData("r", $fn->{RETURN_TYPE}, "r->out.result");
344                 if ($result_size > 1) {
345                         $self->pidl("PyTuple_SetItem(result, $i, $conv);");
346                 } else {
347                         $self->pidl("result = $conv;");
348                 }
349         }
350
351         $self->pidl("talloc_free(mem_ctx);");
352         $self->pidl("return result;");
353         $self->deindent;
354         $self->pidl("}");
355         $self->pidl("");
356
357         return ($fnname, $docstring);
358 }
359
360 sub handle_werror($$$$)
361 {
362         my ($self, $var, $retval, $mem_ctx) = @_;
363
364         $self->pidl("if (!W_ERROR_IS_OK($var)) {");
365         $self->indent;
366         $self->pidl("PyErr_SetString(PyExc_RuntimeError, win_errstr($var));");
367         $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
368         $self->pidl("return $retval;");
369         $self->deindent;
370         $self->pidl("}");
371         $self->pidl("");
372 }
373
374 sub handle_ntstatus($$$$)
375 {
376         my ($self, $var, $retval, $mem_ctx) = @_;
377
378         $self->pidl("if (NT_STATUS_IS_ERR($var)) {");
379         $self->indent;
380         $self->pidl("PyErr_SetString(PyExc_RuntimeError, nt_errstr($var));");
381         $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
382         $self->pidl("return $retval;");
383         $self->deindent;
384         $self->pidl("}");
385         $self->pidl("");
386 }
387
388 sub PythonType($$$)
389 {
390         my ($self, $d, $interface, $basename) = @_;
391
392         my $actual_ctype = $d;
393         if ($actual_ctype->{TYPE} eq "TYPEDEF") {
394                 $actual_ctype = $actual_ctype->{DATA};
395         }
396
397         if ($actual_ctype->{TYPE} eq "STRUCT") {
398                 my ($py_fnname, $py_fndocstring);
399                 if ($d->{TYPE} eq "STRUCT") {
400                         ($py_fnname, $py_fndocstring) = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d);
401                 } else {
402                         ($py_fnname, $py_fndocstring) = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d->{DATA});
403                 }
404
405                 my $fn_name = $d->{NAME};
406
407                 $fn_name =~ s/^$interface->{NAME}_//;
408                 $fn_name =~ s/^$basename\_//;
409
410                 $self->register_module_method($fn_name, $py_fnname, "METH_NOARGS", $py_fndocstring);
411         }
412
413         if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP") {
414                 $self->EnumAndBitmapConsts($d->{NAME}, $d);
415         }
416
417         if ($d->{TYPE} eq "TYPEDEF" and ($d->{DATA}->{TYPE} eq "ENUM" or $d->{DATA}->{TYPE} eq "BITMAP")) {
418                 $self->EnumAndBitmapConsts($d->{NAME}, $d->{DATA});
419         }
420
421         if ($actual_ctype->{TYPE} eq "UNION" and defined($actual_ctype->{ELEMENTS})) {
422                 $self->pidl("PyObject *py_import_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, " .mapTypeName($d) . " *in)");
423                 $self->pidl("{");
424                 $self->indent;
425                 $self->FromUnionToPythonFunction("mem_ctx", $actual_ctype, "level", "in") if ($actual_ctype->{TYPE} eq "UNION");
426                 $self->deindent;
427                 $self->pidl("}");
428                 $self->pidl("");
429
430                 $self->pidl(mapTypeName($d) . " *py_export_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, PyObject *in)");
431                 $self->pidl("{");
432                 $self->indent;
433                 $self->FromPythonToUnionFunction($actual_ctype, mapTypeName($d), "level", "mem_ctx", "in") if ($actual_ctype->{TYPE} eq "UNION");
434                 $self->deindent;
435                 $self->pidl("}");
436                 $self->pidl("");
437         }
438 }
439
440 sub DocString($$$)
441 {
442         my ($self, $d, $name) = @_;
443         if (has_property($d, "helpstring")) {
444                 my $docstring = "py_doc_$name";
445                 $self->pidl("static const char ".$docstring."[] = ".has_property($d, "helpstring").";");
446                 return $docstring;
447         }
448
449         return "NULL";
450 }
451
452 sub Interface($$$)
453 {
454         my($self,$interface,$basename) = @_;
455
456         $self->pidl_hdr("#ifndef _HEADER_PYTHON_$interface->{NAME}\n");
457         $self->pidl_hdr("#define _HEADER_PYTHON_$interface->{NAME}\n\n");
458
459         $self->pidl_hdr("\n");
460
461         $self->Const($_) foreach (@{$interface->{CONSTS}});
462
463         foreach my $d (@{$interface->{TYPES}}) {
464                 next if has_property($d, "nopython");
465
466                 $self->PythonType($d, $interface, $basename);
467         }
468
469         if (defined $interface->{PROPERTIES}->{uuid}) {
470                 $self->pidl_hdr("PyAPI_DATA(PyTypeObject) $interface->{NAME}_InterfaceType;\n");
471                 $self->pidl("typedef struct {");
472                 $self->indent;
473                 $self->pidl("PyObject_HEAD");
474                 $self->pidl("struct dcerpc_pipe *pipe;");
475                 $self->deindent;
476                 $self->pidl("} $interface->{NAME}_InterfaceObject;");
477
478                 $self->pidl("");
479
480                 my @fns = ();
481
482                 foreach my $d (@{$interface->{FUNCTIONS}}) {
483                         next if not defined($d->{OPNUM});
484                         next if has_property($d, "nopython");
485
486                         my ($fnname, $fndocstring) = $self->PythonFunction($d, $interface->{NAME});
487
488                         push (@fns, [$fnname, $fndocstring]);
489                 }
490
491                 $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
492                 $self->indent;
493                 foreach my $d (@fns) {
494                         my ($c_fn, $docstring) = @$d;
495                         my $fn_name = $c_fn;
496
497                         $fn_name =~ s/^$interface->{NAME}_//;
498                         $fn_name =~ s/^$basename\_//;
499
500                         $self->pidl("{ \"$fn_name\", (PyCFunction)$c_fn, METH_VARARGS|METH_KEYWORDS, $docstring },");
501                 }
502                 $self->pidl("{ NULL, NULL, 0, NULL }");
503                 $self->deindent;
504                 $self->pidl("};");
505                 $self->pidl("");
506
507                 $self->pidl("static void interface_$interface->{NAME}_dealloc(PyObject* self)");
508                 $self->pidl("{");
509                 $self->indent;
510                 $self->pidl("$interface->{NAME}_InterfaceObject *interface = ($interface->{NAME}_InterfaceObject *)self;");
511                 $self->pidl("talloc_free(interface->pipe);");
512                 $self->pidl("PyObject_Del(self);");
513                 $self->deindent;
514                 $self->pidl("}");
515                 $self->pidl("");
516
517                 $self->pidl("static PyObject *interface_$interface->{NAME}_getattr(PyObject *obj, char *name)");
518                 $self->pidl("{");
519                 $self->indent;
520                 $self->pidl("return Py_FindMethod(interface_$interface->{NAME}\_methods, obj, name);");
521                 $self->deindent;
522                 $self->pidl("}");
523
524                 $self->pidl("");
525
526                 my $docstring = $self->DocString($interface, $interface->{NAME});
527                 $self->pidl("PyTypeObject $interface->{NAME}_InterfaceType = {");
528                 $self->indent;
529                 $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
530                 $self->pidl(".tp_name = \"$interface->{NAME}\",");
531                 $self->pidl(".tp_basicsize = sizeof($interface->{NAME}_InterfaceObject),");
532                 $self->pidl(".tp_dealloc = interface_$interface->{NAME}_dealloc,");
533                 $self->pidl(".tp_getattr = interface_$interface->{NAME}_getattr,");
534                 $self->pidl(".tp_doc = $docstring,");
535                 $self->deindent;
536                 $self->pidl("};");
537
538                 $self->pidl("");
539
540                 $self->register_module_method($interface->{NAME}, "interface_$interface->{NAME}", "METH_VARARGS|METH_KEYWORDS", "\"$interface->{NAME}(binding, lp_ctx, credentials)\\nConnect to the $interface->{NAME} interface\"");
541                 $self->pidl("static PyObject *interface_$interface->{NAME}(PyObject *self, PyObject *args, PyObject *kwargs)");
542                 $self->pidl("{");
543                 $self->indent;
544                 $self->pidl("$interface->{NAME}_InterfaceObject *ret;");
545                 $self->pidl("const char *binding_string;");
546                 $self->pidl("struct cli_credentials *credentials;");
547                 $self->pidl("struct loadparm_context *lp_ctx = NULL;");
548                 $self->pidl("PyObject *py_lp_ctx = NULL, *py_credentials = Py_None;");
549                 $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
550                 $self->pidl("NTSTATUS status;");
551                 $self->pidl("");
552                 $self->pidl("const char *kwnames[] = {");
553                 $self->indent;
554                 $self->pidl("\"binding\", \"lp_ctx\", \"credentials\", NULL");
555                 $self->deindent;
556                 $self->pidl("};");
557                 $self->pidl("extern struct loadparm_context *lp_from_py_object(PyObject *py_obj);");
558                 $self->pidl("extern struct cli_credentials *cli_credentials_from_py_object(PyObject *py_obj);");
559                 $self->pidl("");
560                 $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"sO|O:$interface->{NAME}\", discard_const_p(char *, kwnames), &binding_string, &py_lp_ctx, &py_credentials)) {");
561                 $self->indent;
562                 $self->pidl("return NULL;");
563                 $self->deindent;
564                 $self->pidl("}");
565                 $self->pidl("");
566                 $self->pidl("if (py_lp_ctx != NULL) {");
567                 $self->indent;
568                 $self->pidl("lp_ctx = lp_from_py_object(py_lp_ctx);");
569                 $self->pidl("if (lp_ctx == NULL) {");
570                 $self->indent;
571                 $self->pidl("PyErr_SetString(PyExc_TypeError, \"Expected loadparm context\");");
572                 $self->pidl("return NULL;");
573                 $self->deindent;
574                 $self->pidl("}");
575                 $self->deindent;
576                 $self->pidl("}");
577                 $self->pidl("");
578
579                 $self->pidl("credentials = cli_credentials_from_py_object(py_credentials);");
580                 $self->pidl("if (credentials == NULL) {");
581                 $self->indent;
582                 $self->pidl("PyErr_SetString(PyExc_TypeError, \"Expected credentials\");");
583                 $self->pidl("return NULL;");
584                 $self->deindent;
585                 $self->pidl("}");
586
587                 $self->pidl("ret = PyObject_New($interface->{NAME}_InterfaceObject, &$interface->{NAME}_InterfaceType);");
588                 $self->pidl("");
589
590                 $self->pidl("status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, ");
591                 $self->pidl("             &ndr_table_$interface->{NAME}, credentials, NULL, lp_ctx);");
592                 $self->handle_ntstatus("status", "NULL", "mem_ctx");
593
594                 $self->pidl("ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;");
595
596                 $self->pidl("return (PyObject *)ret;");
597                 $self->deindent;
598                 $self->pidl("}");
599                 
600                 $self->pidl("");
601         }
602
603         $self->pidl_hdr("\n");
604         $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */\n");
605 }
606
607 sub register_module_method($$$$$)
608 {
609         my ($self, $fn_name, $pyfn_name, $flags, $doc) = @_;
610
611         push (@{$self->{module_methods}}, [$fn_name, $pyfn_name, $flags, $doc])
612 }
613
614 sub assign($$$)
615 {
616         my ($self, $dest, $src) = @_;
617         if ($dest =~ /^\&/) {
618                 $self->pidl("memcpy($dest, $src, sizeof(" . get_value_of($dest) . "));");
619         } else {
620                 $self->pidl("$dest = $src;");
621         }
622 }
623
624 sub ConvertObjectFromPythonData($$$$$$)
625 {
626         my ($self, $mem_ctx, $cvar, $ctype, $target, $fail) = @_;
627
628         die("undef type for $cvar") unless(defined($ctype));
629
630         $ctype = resolveType($ctype);
631
632         my $actual_ctype = $ctype;
633         if ($ctype->{TYPE} eq "TYPEDEF") {
634                 $actual_ctype = $ctype->{DATA};
635         }
636
637         if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or 
638                 $actual_ctype->{TYPE} eq "SCALAR" and (
639                 expandAlias($actual_ctype->{NAME}) =~ /^(u?int[0-9]*|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong|udlongr)$/)) {
640                 $self->pidl("PY_CHECK_TYPE(PyInt, $cvar, $fail);");
641                 $self->pidl("$target = PyInt_AsLong($cvar);");
642                 return;
643         }
644
645         if ($actual_ctype->{TYPE} eq "STRUCT") {
646                 $self->pidl("PY_CHECK_TYPE($ctype->{NAME}, $cvar, $fail);");
647                 $self->assign($target, "py_talloc_get_ptr($cvar)");
648                 return;
649         }
650
651         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "DATA_BLOB") {
652                 $self->pidl("$target = data_blob_talloc($mem_ctx, PyString_AsString($cvar), PyString_Size($cvar));");
653                 return;
654         }
655
656         if ($actual_ctype->{TYPE} eq "SCALAR" and 
657                 ($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")) {
658                 $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AsString($cvar));");
659                 return;
660         }
661
662         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
663                 $self->pidl("$target = PyString_AsString($cvar);");
664                 return;
665                 }
666
667
668         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") {
669                 $self->pidl("$target = NT_STATUS(PyInt_AsLong($cvar));");
670                 return;
671         }
672
673         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") {
674                 $self->pidl("$target = W_ERROR(PyInt_AsLong($cvar));");
675                 return;
676         }
677
678         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "string_array") {
679                 $self->pidl("$target = PyCObject_AsVoidPtr($cvar);");
680                 return;
681         }
682
683         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "pointer") {
684                 $self->assign($target, "PyCObject_AsVoidPtr($cvar)");
685                 return;
686         }
687
688         die("unknown type ".mapTypeName($ctype) . ": $cvar");
689
690 }
691
692 sub ConvertObjectFromPythonLevel($$$$$$$$)
693 {
694         my ($self, $env, $mem_ctx, $py_var, $e, $l, $var_name, $fail) = @_;
695         my $nl = GetNextLevel($e, $l);
696
697         if ($l->{TYPE} eq "POINTER") {
698                 if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
699                         $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail);
700                         return;
701                 }
702                 if ($l->{POINTER_TYPE} ne "ref") {
703                         $self->pidl("if ($py_var == Py_None) {");
704                         $self->indent;
705                         $self->pidl("$var_name = NULL;");
706                         $self->deindent;
707                         $self->pidl("} else {");
708                         $self->indent;
709                 }
710                 $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);");
711                 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, get_value_of($var_name), $fail);
712                 if ($l->{POINTER_TYPE} ne "ref") {
713                         $self->deindent;
714                         $self->pidl("}");
715                 }
716         } elsif ($l->{TYPE} eq "ARRAY") {
717                 my $pl = GetPrevLevel($e, $l);
718                 if ($pl && $pl->{TYPE} eq "POINTER") {
719                         $var_name = get_pointer_to($var_name);
720                 }
721
722                 if (is_charset_array($e, $l)) {
723                         $self->pidl("PY_CHECK_TYPE(PyUnicode, $py_var, $fail);");
724                         # FIXME: Use Unix charset setting rather than utf-8
725                         $self->pidl($var_name . " = PyString_AsString(PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\"));");
726                 } else {
727                         my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}";
728                         $self->pidl("PY_CHECK_TYPE(PyList, $py_var, $fail);");
729                         $self->pidl("{");
730                         $self->indent;
731                         $self->pidl("int $counter;");
732                         if (!$l->{IS_FIXED}) {
733                                 $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_Size($py_var));");
734                         }
735                         $self->pidl("for ($counter = 0; $counter < PyList_Size($py_var); $counter++) {");
736                         $self->indent;
737                         $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GetItem($py_var, $counter)", $e, GetNextLevel($e, $l), $var_name."[$counter]", $fail);
738                         $self->deindent;
739                         $self->pidl("}");
740                         $self->deindent;
741                         $self->pidl("}");
742                 }
743         } elsif ($l->{TYPE} eq "DATA") {
744
745                 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE})) {
746                         $var_name = get_pointer_to($var_name);
747                 }
748                 $self->ConvertObjectFromPythonData($mem_ctx, $py_var, $l->{DATA_TYPE}, $var_name, $fail);
749         } elsif ($l->{TYPE} eq "SWITCH") {
750                 $var_name = get_pointer_to($var_name);
751                 my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e);
752                 $self->assign($var_name, "py_export_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $py_var)");
753         } elsif ($l->{TYPE} eq "SUBCONTEXT") {
754                 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, GetNextLevel($e, $l), $var_name, $fail);
755         } else {
756                 die("unknown level type $l->{TYPE}");
757         }
758 }
759
760 sub ConvertObjectFromPython($$$$$$$)
761 {
762         my ($self, $env, $mem_ctx, $ctype, $cvar, $target, $fail) = @_;
763
764         $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $cvar, $ctype, $ctype->{LEVELS}[0], $target, $fail);
765 }
766
767 sub ConvertScalarToPython($$$)
768 {
769         my ($self, $ctypename, $cvar) = @_;
770
771         die("expected string for $cvar, not $ctypename") if (ref($ctypename) eq "HASH");
772
773         $ctypename = expandAlias($ctypename);
774
775         if ($ctypename =~ /^(char|u?int[0-9]*|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) {
776                 return "PyInt_FromLong($cvar)";
777         }
778
779         if ($ctypename eq "DATA_BLOB") {
780                 return "PyString_FromStringAndSize((char *)($cvar).data, ($cvar).length)";
781         }
782
783         if ($ctypename eq "NTSTATUS") {
784                 return "PyInt_FromLong(NT_STATUS_V($cvar))";
785         }
786
787         if ($ctypename eq "WERROR") {
788                 return "PyInt_FromLong(W_ERROR_V($cvar))";
789         }
790
791         if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) {
792                 return "PyString_FromString($cvar)";
793         }
794
795         # Not yet supported
796         if ($ctypename eq "string_array") { return "PyCObject_FromVoidPtr($cvar)"; }
797         if ($ctypename eq "ipv4address") { return "PyString_FromString($cvar)"; }
798         if ($ctypename eq "pointer") {
799                 return "PyCObject_FromVoidPtr($cvar, talloc_free)";
800         }
801
802         die("Unknown scalar type $ctypename");
803 }
804
805 sub ConvertObjectToPythonData($$$$$)
806 {
807         my ($self, $mem_ctx, $ctype, $cvar) = @_;
808
809         die("undef type for $cvar") unless(defined($ctype));
810
811         $ctype = resolveType($ctype);
812
813         my $actual_ctype = $ctype;
814         if ($ctype->{TYPE} eq "TYPEDEF") {
815                 $actual_ctype = $ctype->{DATA};
816         } 
817         
818         if ($actual_ctype->{TYPE} eq "ENUM") {
819                 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::enum_type_fn($actual_ctype), $cvar);
820         } elsif ($actual_ctype->{TYPE} eq "BITMAP") {
821                 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::bitmap_type_fn($actual_ctype), $cvar);
822         } elsif ($actual_ctype->{TYPE} eq "SCALAR") {
823                 return $self->ConvertScalarToPython($actual_ctype->{NAME}, $cvar);
824         } elsif ($actual_ctype->{TYPE} eq "STRUCT") {
825                 return "py_talloc_import_ex(&$ctype->{NAME}_Type, $mem_ctx, $cvar)";
826         }
827
828         die("unknown type ".mapTypeName($ctype) . ": $cvar");
829 }
830
831 sub ConvertObjectToPythonLevel($$$$$)
832 {
833         my ($self, $mem_ctx, $env, $e, $l, $var_name, $py_var) = @_;
834         my $nl = GetNextLevel($e, $l);
835
836         if ($l->{TYPE} eq "POINTER") {
837                 if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
838                         $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name, $py_var);
839                         return;
840                 }
841                 if ($l->{POINTER_TYPE} ne "ref") {
842                         $self->pidl("if ($var_name == NULL) {");
843                         $self->indent;
844                         $self->pidl("$py_var = Py_None;");
845                         $self->deindent;
846                         $self->pidl("} else {");
847                         $self->indent;
848                 }
849                 $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, get_value_of($var_name), $py_var);
850                 if ($l->{POINTER_TYPE} ne "ref") {
851                         $self->deindent;
852                         $self->pidl("}");
853                 }
854         } elsif ($l->{TYPE} eq "ARRAY") {
855                 if (is_charset_array($e, $l)) {
856                         $var_name = get_pointer_to($var_name);
857                         # FIXME: Use Unix charset setting rather than utf-8
858                         $self->pidl("$py_var = PyUnicode_Decode($var_name, strlen($var_name), \"utf-8\", \"ignore\");");
859                 } else {
860                         my $pl = GetPrevLevel($e, $l);
861                         if ($pl && $pl->{TYPE} eq "POINTER") {
862                                 $var_name = get_pointer_to($var_name);
863                         }
864
865                         die("No SIZE_IS for array $var_name") unless (defined($l->{SIZE_IS}));
866                         my $length = $l->{SIZE_IS};
867                         if (defined($l->{LENGTH_IS})) {
868                                 $length = $l->{LENGTH_IS};
869                         }
870
871                         $length = ParseExpr($length, $env, $e);
872                         $self->pidl("$py_var = PyList_New($length);");
873                         $self->pidl("{");
874                         $self->indent;
875                         my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}";
876                         $self->pidl("int $counter;");
877                         $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
878                         $self->indent;
879                         my $member_var = "py_$e->{NAME}_$l->{LEVEL_INDEX}";
880                         $self->pidl("PyObject *$member_var;");
881                         $self->ConvertObjectToPythonLevel($var_name, $env, $e, GetNextLevel($e, $l), $var_name."[$counter]", $member_var);
882                         $self->pidl("PyList_SetItem($py_var, $counter, $member_var);");
883                         $self->deindent;
884                         $self->pidl("}");
885                         $self->deindent;
886                         $self->pidl("}");
887                 }
888         } elsif ($l->{TYPE} eq "SWITCH") {
889                 $var_name = get_pointer_to($var_name);
890                 my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e);
891                 $self->pidl("$py_var = py_import_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $var_name);");
892         } elsif ($l->{TYPE} eq "DATA") {
893                 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE})) {
894                         $var_name = get_pointer_to($var_name);
895                 }
896                 my $conv = $self->ConvertObjectToPythonData($mem_ctx, $l->{DATA_TYPE}, $var_name);
897                 $self->pidl("$py_var = $conv;");
898         } elsif ($l->{TYPE} eq "SUBCONTEXT") {
899                 $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, GetNextLevel($e, $l), $var_name, $py_var);
900         } else {
901                 die("Unknown level type $l->{TYPE} $var_name");
902         }
903 }
904
905 sub ConvertObjectToPython($$$$$$)
906 {
907         my ($self, $mem_ctx, $env, $ctype, $cvar, $py_var) = @_;
908
909         $self->ConvertObjectToPythonLevel($mem_ctx, $env, $ctype, $ctype->{LEVELS}[0], $cvar, $py_var);
910 }
911
912 sub Parse($$$$$)
913 {
914     my($self,$basename,$ndr,$ndr_hdr,$hdr) = @_;
915     
916     my $py_hdr = $hdr;
917     $py_hdr =~ s/ndr_([^\/]+)$/py_$1/g;
918
919     $self->pidl_hdr("/* header auto-generated by pidl */\n\n");
920         
921     $self->pidl("
922 /* Python wrapper functions auto-generated by pidl */
923 #include \"includes.h\"
924 #include <Python.h>
925 #include \"librpc/rpc/dcerpc.h\"
926 #include \"scripting/python/pytalloc.h\"
927 #include \"scripting/python/pyrpc.h\"
928 #include \"$hdr\"
929 #include \"$ndr_hdr\"
930 #include \"$py_hdr\"
931
932 ");
933
934         foreach my $x (@$ndr) {
935                 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}});
936             ($x->{TYPE} eq "INTERFACE") && $self->Interface($x, $basename);
937         }
938         
939         $self->pidl("static PyMethodDef $basename\_methods[] = {");
940         $self->indent;
941         foreach (@{$self->{module_methods}}) {
942                 my ($fn_name, $pyfn_name, $flags, $doc) = @$_;
943                 $self->pidl("{ \"$fn_name\", (PyCFunction)$pyfn_name, $flags, $doc },");
944         }
945         
946         $self->pidl("{ NULL, NULL, 0, NULL }");
947         $self->deindent;
948         $self->pidl("};");
949
950         $self->pidl("");
951
952         $self->pidl("void init$basename(void)");
953         $self->pidl("{");
954         $self->indent;
955         $self->pidl("PyObject *m;");
956         $self->pidl("m = Py_InitModule3(\"$basename\", $basename\_methods, \"$basename DCE/RPC interface\");");
957         foreach my $name (keys %{$self->{constants}}) {
958                 my $py_obj;
959                 my ($ctype, $cvar) = @{$self->{constants}->{$name}};
960                 if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) {
961                         $py_obj = "PyInt_FromLong($cvar)";
962                 } elsif ($cvar =~ /^".*"$/) {
963                         $py_obj = "PyString_FromString($cvar)";
964                 } else {
965                         $py_obj = $self->ConvertObjectToPythonData("NULL", expandAlias($ctype), $cvar);
966                 }
967
968                 $self->pidl("PyModule_AddObject(m, \"$name\", $py_obj);");
969         }
970         $self->deindent;
971         $self->pidl("}");
972     return ($self->{res_hdr}, $self->{res});
973 }
974
975 1;