1################################################### 2# Python function wrapper generator 3# Copyright jelmer@samba.org 2007-2008 4# released under the GNU GPL 5 6package Parse::Pidl::Samba4::Python; 7 8use Exporter; 9@ISA = qw(Exporter); 10 11use strict; 12use Parse::Pidl qw(warning fatal error); 13use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias); 14use Parse::Pidl::Util qw(has_property ParseExpr unmake_str); 15use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array); 16use Parse::Pidl::CUtil qw(get_value_of get_pointer_to); 17use Parse::Pidl::Samba4 qw(ArrayDynamicallyAllocated); 18use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv); 19 20use vars qw($VERSION); 21$VERSION = '0.01'; 22 23sub new($) { 24 my ($class) = @_; 25 my $self = { res => "", res_hdr => "", tabs => "", constants => {}, 26 module_methods => [], module_objects => [], ready_types => [], 27 module_imports => [], type_imports => {}, 28 patch_type_calls => [], readycode => [] }; 29 bless($self, $class); 30} 31 32sub pidl_hdr ($$) 33{ 34 my $self = shift; 35 $self->{res_hdr} .= shift; 36} 37 38sub pidl($$) 39{ 40 my ($self, $d) = @_; 41 if ($d) { 42 if ((!($d =~ /^#/))) { 43 $self->{res} .= $self->{tabs}; 44 } 45 $self->{res} .= $d; 46 } 47 $self->{res} .= "\n"; 48} 49 50sub indent($) 51{ 52 my ($self) = @_; 53 $self->{tabs} .= "\t"; 54} 55 56sub deindent($) 57{ 58 my ($self) = @_; 59 $self->{tabs} = substr($self->{tabs}, 0, -1); 60} 61 62sub PrettifyTypeName($$) 63{ 64 my ($name, $basename) = @_; 65 66 $name =~ s/^$basename\_//; 67 68 return $name; 69} 70 71sub Import 72{ 73 my $self = shift; 74 my @imports = @_; 75 foreach (@imports) { 76 $_ = unmake_str($_); 77 s/\.idl$//; 78 $self->pidl_hdr("#include \"librpc/gen_ndr/$_\.h\"\n"); 79 $self->register_module_import($_); 80 } 81} 82 83sub Const($$) 84{ 85 my ($self, $const) = @_; 86 $self->register_constant($const->{NAME}, $const->{DTYPE}, $const->{VALUE}); 87} 88 89sub register_constant($$$$) 90{ 91 my ($self, $name, $type, $value) = @_; 92 93 $self->{constants}->{$name} = [$type, $value]; 94} 95 96sub EnumAndBitmapConsts($$$) 97{ 98 my ($self, $name, $d) = @_; 99 100 return unless (defined($d->{ELEMENTS})); 101 102 foreach my $e (@{$d->{ELEMENTS}}) { 103 $e =~ /^([A-Za-z0-9_]+)/; 104 my $cname = $1; 105 106 $self->register_constant($cname, $d, $cname); 107 } 108} 109 110sub FromUnionToPythonFunction($$$$) 111{ 112 my ($self, $mem_ctx, $type, $switch, $name) = @_; 113 114 $self->pidl("PyObject *ret;"); 115 $self->pidl(""); 116 117 $self->pidl("switch ($switch) {"); 118 $self->indent; 119 120 foreach my $e (@{$type->{ELEMENTS}}) { 121 $self->pidl("$e->{CASE}:"); 122 123 $self->indent; 124 125 if ($e->{NAME}) { 126 $self->ConvertObjectToPython($mem_ctx, {}, $e, "$name->$e->{NAME}", "ret", "return NULL;"); 127 } else { 128 $self->pidl("ret = Py_None;"); 129 } 130 131 $self->pidl("return ret;"); 132 $self->pidl(""); 133 134 $self->deindent; 135 } 136 137 $self->deindent; 138 $self->pidl("}"); 139 140 $self->pidl("PyErr_SetString(PyExc_TypeError, \"unknown union level\");"); 141 $self->pidl("return NULL;"); 142} 143 144sub FromPythonToUnionFunction($$$$$) 145{ 146 my ($self, $type, $typename, $switch, $mem_ctx, $name) = @_; 147 148 my $has_default = 0; 149 150 $self->pidl("$typename *ret = talloc_zero($mem_ctx, $typename);"); 151 152 $self->pidl("switch ($switch) {"); 153 $self->indent; 154 155 foreach my $e (@{$type->{ELEMENTS}}) { 156 $self->pidl("$e->{CASE}:"); 157 if ($e->{CASE} eq "default") { $has_default = 1; } 158 $self->indent; 159 if ($e->{NAME}) { 160 $self->ConvertObjectFromPython({}, $mem_ctx, $e, $name, "ret->$e->{NAME}", "talloc_free(ret); return NULL;"); 161 } 162 $self->pidl("break;"); 163 $self->deindent; 164 $self->pidl(""); 165 } 166 167 if (!$has_default) { 168 $self->pidl("default:"); 169 $self->indent; 170 $self->pidl("PyErr_SetString(PyExc_TypeError, \"invalid union level value\");"); 171 $self->pidl("talloc_free(ret);"); 172 $self->pidl("ret = NULL;"); 173 $self->deindent; 174 } 175 176 $self->deindent; 177 $self->pidl("}"); 178 $self->pidl(""); 179 $self->pidl("return ret;"); 180} 181 182sub PythonStruct($$$$$$) 183{ 184 my ($self, $modulename, $prettyname, $name, $cname, $d) = @_; 185 186 my $env = GenerateStructEnv($d, "object"); 187 188 $self->pidl(""); 189 190 my $getsetters = "NULL"; 191 192 if ($#{$d->{ELEMENTS}} > -1) { 193 foreach my $e (@{$d->{ELEMENTS}}) { 194 my $varname = "object->$e->{NAME}"; 195 $self->pidl("static PyObject *py_$name\_get_$e->{NAME}(PyObject *obj, void *closure)"); 196 $self->pidl("{"); 197 $self->indent; 198 $self->pidl("$cname *object = ($cname *)py_talloc_get_ptr(obj);"); 199 $self->pidl("PyObject *py_$e->{NAME};"); 200 $self->ConvertObjectToPython("py_talloc_get_mem_ctx(obj)", $env, $e, $varname, "py_$e->{NAME}", "return NULL;"); 201 $self->pidl("return py_$e->{NAME};"); 202 $self->deindent; 203 $self->pidl("}"); 204 $self->pidl(""); 205 206 $self->pidl("static int py_$name\_set_$e->{NAME}(PyObject *py_obj, PyObject *value, void *closure)"); 207 $self->pidl("{"); 208 $self->indent; 209 $self->pidl("$cname *object = ($cname *)py_talloc_get_ptr(py_obj);"); 210 my $mem_ctx = "py_talloc_get_mem_ctx(py_obj)"; 211 my $l = $e->{LEVELS}[0]; 212 my $nl = GetNextLevel($e, $l); 213 if ($l->{TYPE} eq "POINTER" and 214 not ($nl->{TYPE} eq "ARRAY" and ($nl->{IS_FIXED} or is_charset_array($e, $nl))) and 215 not ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE}))) { 216 $self->pidl("talloc_free($varname);"); 217 } 218 $self->ConvertObjectFromPython($env, $mem_ctx, $e, "value", $varname, "return -1;"); 219 $self->pidl("return 0;"); 220 $self->deindent; 221 $self->pidl("}"); 222 $self->pidl(""); 223 } 224 225 $getsetters = "py_$name\_getsetters"; 226 $self->pidl("static PyGetSetDef ".$getsetters."[] = {"); 227 $self->indent; 228 foreach my $e (@{$d->{ELEMENTS}}) { 229 $self->pidl("{ discard_const_p(char, \"$e->{NAME}\"), py_$name\_get_$e->{NAME}, py_$name\_set_$e->{NAME} },"); 230 } 231 $self->pidl("{ NULL }"); 232 $self->deindent; 233 $self->pidl("};"); 234 $self->pidl(""); 235 } 236 237 $self->pidl("static PyObject *py_$name\_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)"); 238 $self->pidl("{"); 239 $self->indent; 240 $self->pidl("return py_talloc_new($cname, type);"); 241 $self->deindent; 242 $self->pidl("}"); 243 $self->pidl(""); 244 245 my $py_methods = "NULL"; 246 247 # If the struct is not public there ndr_pull/ndr_push functions will 248 # be static so not callable from here 249 if (has_property($d, "public")) { 250 $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj)"); 251 $self->pidl("{"); 252 $self->indent; 253 $self->pidl("$cname *object = ($cname *)py_talloc_get_ptr(py_obj);"); 254 $self->pidl("DATA_BLOB blob;"); 255 $self->pidl("enum ndr_err_code err;"); 256 $self->pidl("err = ndr_push_struct_blob(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_push_flags_fn_t)ndr_push_$name);"); 257 $self->pidl("if (err != NDR_ERR_SUCCESS) {"); 258 $self->indent; 259 $self->pidl("PyErr_SetNdrError(err);"); 260 $self->pidl("return NULL;"); 261 $self->deindent; 262 $self->pidl("}"); 263 $self->pidl(""); 264 $self->pidl("return PyString_FromStringAndSize((char *)blob.data, blob.length);"); 265 $self->deindent; 266 $self->pidl("}"); 267 $self->pidl(""); 268 269 $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, PyObject *args)"); 270 $self->pidl("{"); 271 $self->indent; 272 $self->pidl("$cname *object = ($cname *)py_talloc_get_ptr(py_obj);"); 273 $self->pidl("DATA_BLOB blob;"); 274 $self->pidl("enum ndr_err_code err;"); 275 $self->pidl("if (!PyArg_ParseTuple(args, \"s#:__ndr_unpack__\", &blob.data, &blob.length))"); 276 $self->pidl("\treturn NULL;"); 277 $self->pidl(""); 278 279 # This disgusting hack works around the fact that ndr_pull_struct_blob_all will always fail on structures with relative pointers. 280 # So, map ndr_unpack to ndr_pull_struct_blob_all only if we don't have any relative pointers in this 281 my $got_relative = 0; 282 if ($#{$d->{ELEMENTS}} > -1) { 283 foreach my $e (@{$d->{ELEMENTS}}) { 284 my $l = $e->{LEVELS}[0]; 285 if ($l->{TYPE} eq "POINTER" and ($l->{POINTER_TYPE} eq "relative")) { 286 $got_relative = 1; 287 last; 288 } 289 } 290 } 291 if ($got_relative == 0) { 292 $self->pidl("err = ndr_pull_struct_blob_all(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_pull_flags_fn_t)ndr_pull_$name);"); 293 } else { 294 $self->pidl("err = ndr_pull_struct_blob(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_pull_flags_fn_t)ndr_pull_$name);"); 295 } 296 $self->pidl("if (err != NDR_ERR_SUCCESS) {"); 297 $self->indent; 298 $self->pidl("PyErr_SetNdrError(err);"); 299 $self->pidl("return NULL;"); 300 $self->deindent; 301 $self->pidl("}"); 302 $self->pidl(""); 303 $self->pidl("Py_RETURN_NONE;"); 304 $self->deindent; 305 $self->pidl("}"); 306 $self->pidl(""); 307 $py_methods = "py_$name\_methods"; 308 $self->pidl("static PyMethodDef $py_methods\[] = {"); 309 $self->indent; 310 $self->pidl("{ \"__ndr_pack__\", (PyCFunction)py_$name\_ndr_pack, METH_NOARGS, \"S.pack() -> blob\\nNDR pack\" },"); 311 $self->pidl("{ \"__ndr_unpack__\", (PyCFunction)py_$name\_ndr_unpack, METH_VARARGS, \"S.unpack(blob) -> None\\nNDR unpack\" },"); 312 $self->pidl("{ NULL, NULL, 0, NULL }"); 313 $self->deindent; 314 $self->pidl("};"); 315 $self->pidl(""); 316 } 317 318 $self->pidl_hdr("staticforward PyTypeObject $name\_Type;\n"); 319 $self->pidl(""); 320 my $docstring = $self->DocString($d, $name); 321 my $typeobject = "$name\_Type"; 322 $self->pidl("static PyTypeObject $typeobject = {"); 323 $self->indent; 324 $self->pidl("PyObject_HEAD_INIT(NULL) 0,"); 325 $self->pidl(".tp_name = \"$modulename.$prettyname\","); 326 $self->pidl(".tp_basicsize = sizeof(py_talloc_Object),"); 327 $self->pidl(".tp_dealloc = py_talloc_dealloc,"); 328 $self->pidl(".tp_getset = $getsetters,"); 329 $self->pidl(".tp_repr = py_talloc_default_repr,"); 330 if ($docstring) { 331 $self->pidl(".tp_doc = $docstring,"); 332 } 333 $self->pidl(".tp_methods = $py_methods,"); 334 $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,"); 335 $self->pidl(".tp_new = py_$name\_new,"); 336 $self->deindent; 337 $self->pidl("};"); 338 339 $self->pidl(""); 340 341 return "&$typeobject"; 342} 343 344sub get_metadata_var($) 345{ 346 my ($e) = @_; 347 sub get_var($) { my $x = shift; $x =~ s/\*//g; return $x; } 348 349 if (has_property($e, "length_is")) { 350 return get_var($e->{PROPERTIES}->{length_is}); 351 } elsif (has_property($e, "size_is")) { 352 return get_var($e->{PROPERTIES}->{size_is}); 353 } 354 355 return undef; 356} 357 358sub find_metadata_args($) 359{ 360 my ($fn) = @_; 361 my $metadata_args = { in => {}, out => {} }; 362 363 # Determine arguments that are metadata for other arguments (size_is/length_is) 364 foreach my $e (@{$fn->{ELEMENTS}}) { 365 foreach my $dir (@{$e->{DIRECTION}}) { 366 my $main = get_metadata_var($e); 367 if ($main) { 368 $metadata_args->{$dir}->{$main} = $e->{NAME}; 369 } 370 } 371 } 372 373 return $metadata_args; 374} 375 376sub PythonFunctionUnpackOut($$$) 377{ 378 my ($self, $fn, $fnname) = @_; 379 380 my $outfnname = "unpack_$fnname\_args_out"; 381 my $signature = ""; 382 383 my $metadata_args = find_metadata_args($fn); 384 385 my $env = GenerateFunctionOutEnv($fn, "r->"); 386 my $result_size = 0; 387 388 $self->pidl("static PyObject *$outfnname(struct $fn->{NAME} *r)"); 389 $self->pidl("{"); 390 $self->indent; 391 $self->pidl("PyObject *result = Py_None;"); 392 foreach my $e (@{$fn->{ELEMENTS}}) { 393 next unless (grep(/out/,@{$e->{DIRECTION}})); 394 next if (($metadata_args->{in}->{$e->{NAME}} and grep(/in/, @{$e->{DIRECTION}})) or 395 ($metadata_args->{out}->{$e->{NAME}}) and grep(/out/, @{$e->{DIRECTION}})); 396 $self->pidl("PyObject *py_$e->{NAME};"); 397 $result_size++; 398 } 399 400 if ($fn->{RETURN_TYPE}) { 401 $result_size++ unless ($fn->{RETURN_TYPE} eq "WERROR" or $fn->{RETURN_TYPE} eq "NTSTATUS"); 402 } 403 404 my $i = 0; 405 406 if ($result_size > 1) { 407 $self->pidl("result = PyTuple_New($result_size);"); 408 $signature .= "("; 409 } elsif ($result_size == 0) { 410 $signature .= "None"; 411 } 412 413 foreach my $e (@{$fn->{ELEMENTS}}) { 414 next if ($metadata_args->{out}->{$e->{NAME}}); 415 my $py_name = "py_$e->{NAME}"; 416 if (grep(/out/,@{$e->{DIRECTION}})) { 417 $self->ConvertObjectToPython("r", $env, $e, "r->out.$e->{NAME}", $py_name, "return NULL;"); 418 if ($result_size > 1) { 419 $self->pidl("PyTuple_SetItem(result, $i, $py_name);"); 420 $i++; 421 $signature .= "$e->{NAME}, "; 422 } else { 423 $self->pidl("result = $py_name;"); 424 $signature .= $e->{NAME}; 425 } 426 } 427 } 428 429 if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") { 430 $self->handle_ntstatus("r->out.result", "NULL", undef); 431 } elsif (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "WERROR") { 432 $self->handle_werror("r->out.result", "NULL", undef); 433 } elsif (defined($fn->{RETURN_TYPE})) { 434 my $conv = $self->ConvertObjectToPythonData("r", $fn->{RETURN_TYPE}, "r->out.result", $fn); 435 if ($result_size > 1) { 436 $self->pidl("PyTuple_SetItem(result, $i, $conv);"); 437 } else { 438 $self->pidl("result = $conv;"); 439 } 440 $signature .= "result"; 441 } 442 443 if (substr($signature, -2) eq ", ") { 444 $signature = substr($signature, 0, -2); 445 } 446 if ($result_size > 1) { 447 $signature .= ")"; 448 } 449 450 $self->pidl("return result;"); 451 $self->deindent; 452 $self->pidl("}"); 453 $self->pidl(""); 454 455 return ($outfnname, $signature); 456} 457 458sub PythonFunctionPackIn($$$) 459{ 460 my ($self, $fn, $fnname) = @_; 461 my $metadata_args = find_metadata_args($fn); 462 463 my $infnname = "pack_$fnname\_args_in"; 464 465 $self->pidl("static bool $infnname(PyObject *args, PyObject *kwargs, struct $fn->{NAME} *r)"); 466 $self->pidl("{"); 467 $self->indent; 468 my $args_format = ""; 469 my $args_string = ""; 470 my $args_names = ""; 471 my $signature = ""; 472 473 foreach my $e (@{$fn->{ELEMENTS}}) { 474 next unless (grep(/in/,@{$e->{DIRECTION}})); 475 next if (($metadata_args->{in}->{$e->{NAME}} and grep(/in/, @{$e->{DIRECTION}})) or 476 ($metadata_args->{out}->{$e->{NAME}}) and grep(/out/, @{$e->{DIRECTION}})); 477 $self->pidl("PyObject *py_$e->{NAME};"); 478 $args_format .= "O"; 479 $args_string .= ", &py_$e->{NAME}"; 480 $args_names .= "\"$e->{NAME}\", "; 481 $signature .= "$e->{NAME}, "; 482 } 483 if (substr($signature, -2) eq ", ") { 484 $signature = substr($signature, 0, -2); 485 } 486 $self->pidl("const char *kwnames[] = {"); 487 $self->indent; 488 $self->pidl($args_names . "NULL"); 489 $self->deindent; 490 $self->pidl("};"); 491 492 $self->pidl(""); 493 $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"$args_format:$fn->{NAME}\", discard_const_p(char *, kwnames)$args_string)) {"); 494 $self->indent; 495 $self->pidl("return false;"); 496 $self->deindent; 497 $self->pidl("}"); 498 $self->pidl(""); 499 500 my $env = GenerateFunctionInEnv($fn, "r->"); 501 502 my $fail = "return false;"; 503 foreach my $e (@{$fn->{ELEMENTS}}) { 504 next unless (grep(/in/,@{$e->{DIRECTION}})); 505 if ($metadata_args->{in}->{$e->{NAME}}) { 506 my $py_var = "py_".$metadata_args->{in}->{$e->{NAME}}; 507 $self->pidl("PY_CHECK_TYPE(&PyList_Type, $py_var, $fail);"); 508 my $val = "PyList_Size($py_var)"; 509 if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") { 510 $self->pidl("r->in.$e->{NAME} = talloc_ptrtype(r, r->in.$e->{NAME});"); 511 $self->pidl("*r->in.$e->{NAME} = $val;"); 512 } else { 513 $self->pidl("r->in.$e->{NAME} = $val;"); 514 } 515 } else { 516 $self->ConvertObjectFromPython($env, "r", $e, "py_$e->{NAME}", "r->in.$e->{NAME}", $fail); 517 } 518 } 519 $self->pidl("return true;"); 520 $self->deindent; 521 $self->pidl("}"); 522 $self->pidl(""); 523 return ($infnname, $signature); 524} 525 526sub PythonFunction($$$) 527{ 528 my ($self, $fn, $iface, $prettyname) = @_; 529 530 my $fnname = "py_$fn->{NAME}"; 531 my $docstring = $self->DocString($fn, $fn->{NAME}); 532 533 my ($insignature, $outsignature); 534 my ($infn, $outfn); 535 536 if (has_property($fn, "todo")) { 537 unless ($docstring) { $docstring = "NULL"; } 538 $infn = "NULL"; 539 $outfn = "NULL"; 540 } else { 541 ($infn, $insignature) = $self->PythonFunctionPackIn($fn, $fnname); 542 ($outfn, $outsignature) = $self->PythonFunctionUnpackOut($fn, $fnname); 543 my $signature = "S.$prettyname($insignature) -> $outsignature"; 544 if ($docstring) { 545 $docstring = "\"$signature\\n\\n\"$docstring"; 546 } else { 547 $docstring = "\"$signature\""; 548 } 549 } 550 551 return ($infn, $outfn, $docstring); 552} 553 554sub handle_werror($$$$) 555{ 556 my ($self, $var, $retval, $mem_ctx) = @_; 557 558 $self->pidl("if (!W_ERROR_IS_OK($var)) {"); 559 $self->indent; 560 $self->pidl("PyErr_SetWERROR($var);"); 561 $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx); 562 $self->pidl("return $retval;"); 563 $self->deindent; 564 $self->pidl("}"); 565 $self->pidl(""); 566} 567 568sub handle_ntstatus($$$$) 569{ 570 my ($self, $var, $retval, $mem_ctx) = @_; 571 572 $self->pidl("if (NT_STATUS_IS_ERR($var)) {"); 573 $self->indent; 574 $self->pidl("PyErr_SetNTSTATUS($var);"); 575 $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx); 576 $self->pidl("return $retval;"); 577 $self->deindent; 578 $self->pidl("}"); 579 $self->pidl(""); 580} 581 582sub PythonType($$$$) 583{ 584 my ($self, $modulename, $d, $interface, $basename) = @_; 585 586 my $actual_ctype = $d; 587 if ($actual_ctype->{TYPE} eq "TYPEDEF") { 588 $actual_ctype = $actual_ctype->{DATA}; 589 } 590 591 if ($actual_ctype->{TYPE} eq "STRUCT") { 592 my $typeobject; 593 my $fn_name = PrettifyTypeName($d->{NAME}, $basename); 594 595 if ($d->{TYPE} eq "STRUCT") { 596 $typeobject = $self->PythonStruct($modulename, $fn_name, $d->{NAME}, mapTypeName($d), $d); 597 } else { 598 $typeobject = $self->PythonStruct($modulename, $fn_name, $d->{NAME}, mapTypeName($d), $d->{DATA}); 599 } 600 601 $self->register_module_typeobject($fn_name, $typeobject); 602 } 603 604 if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP") { 605 $self->EnumAndBitmapConsts($d->{NAME}, $d); 606 } 607 608 if ($d->{TYPE} eq "TYPEDEF" and ($d->{DATA}->{TYPE} eq "ENUM" or $d->{DATA}->{TYPE} eq "BITMAP")) { 609 $self->EnumAndBitmapConsts($d->{NAME}, $d->{DATA}); 610 } 611 612 if ($actual_ctype->{TYPE} eq "UNION" and defined($actual_ctype->{ELEMENTS})) { 613 $self->pidl("PyObject *py_import_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, " .mapTypeName($d) . " *in)"); 614 $self->pidl("{"); 615 $self->indent; 616 $self->FromUnionToPythonFunction("mem_ctx", $actual_ctype, "level", "in") if ($actual_ctype->{TYPE} eq "UNION"); 617 $self->deindent; 618 $self->pidl("}"); 619 $self->pidl(""); 620 621 $self->pidl(mapTypeName($d) . " *py_export_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, PyObject *in)"); 622 $self->pidl("{"); 623 $self->indent; 624 $self->FromPythonToUnionFunction($actual_ctype, mapTypeName($d), "level", "mem_ctx", "in") if ($actual_ctype->{TYPE} eq "UNION"); 625 $self->deindent; 626 $self->pidl("}"); 627 $self->pidl(""); 628 } 629} 630 631sub DocString($$$) 632{ 633 my ($self, $d, $name) = @_; 634 if (has_property($d, "helpstring")) { 635 my $docstring = uc("py_doc_$name"); 636 $self->pidl("#define $docstring ".has_property($d, "helpstring")); 637 return $docstring; 638 } 639 640 return undef; 641} 642 643sub Interface($$$) 644{ 645 my($self,$interface,$basename) = @_; 646 647 if (has_property($interface, "pyhelper")) { 648 $self->pidl("#include \"".unmake_str($interface->{PROPERTIES}->{pyhelper})."\"\n"); 649 } 650 651 $self->Const($_) foreach (@{$interface->{CONSTS}}); 652 653 foreach my $d (@{$interface->{TYPES}}) { 654 next if has_property($d, "nopython"); 655 656 $self->PythonType($basename, $d, $interface, $basename); 657 } 658 659 if (defined $interface->{PROPERTIES}->{uuid}) { 660 $self->pidl_hdr("staticforward PyTypeObject $interface->{NAME}_InterfaceType;\n"); 661 $self->pidl(""); 662 663 my @fns = (); 664 665 foreach my $d (@{$interface->{FUNCTIONS}}) { 666 next if not defined($d->{OPNUM}); 667 next if has_property($d, "nopython"); 668 669 my $prettyname = $d->{NAME}; 670 671 $prettyname =~ s/^$interface->{NAME}_//; 672 $prettyname =~ s/^$basename\_//; 673 674 my ($infn, $outfn, $fndocstring) = $self->PythonFunction($d, $interface->{NAME}, $prettyname); 675 676 push (@fns, [$infn, $outfn, "dcerpc_$d->{NAME}", $prettyname, $fndocstring, $d->{OPNUM}]); 677 } 678 679 $self->pidl("const struct PyNdrRpcMethodDef py_ndr_$interface->{NAME}\_methods[] = {"); 680 $self->indent; 681 foreach my $d (@fns) { 682 my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d; 683 $self->pidl("{ \"$prettyname\", $docstring, (dcerpc_call_fn)$callfn, (py_data_pack_fn)$infn, (py_data_unpack_fn)$outfn, $opnum, &ndr_table_$interface->{NAME} },"); 684 } 685 $self->pidl("{ NULL }"); 686 $self->deindent; 687 $self->pidl("};"); 688 $self->pidl(""); 689 690 $self->pidl("static PyObject *interface_$interface->{NAME}_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)"); 691 $self->pidl("{"); 692 $self->indent; 693 $self->pidl("return py_dcerpc_interface_init_helper(type, args, kwargs, &ndr_table_$interface->{NAME});"); 694 $self->deindent; 695 $self->pidl("}"); 696 697 $self->pidl(""); 698 699 my $signature = 700"\"$interface->{NAME}(binding, lp_ctx=None, credentials=None) -> connection\\n\" 701\"\\n\" 702\"binding should be a DCE/RPC binding string (for example: ncacn_ip_tcp:127.0.0.1)\\n\" 703\"lp_ctx should be a path to a smb.conf file or a param.LoadParm object\\n\" 704\"credentials should be a credentials.Credentials object.\\n\\n\""; 705 706 my $docstring = $self->DocString($interface, $interface->{NAME}); 707 708 if ($docstring) { 709 $docstring = "$signature$docstring"; 710 } else { 711 $docstring = $signature; 712 } 713 714 $self->pidl("static PyTypeObject $interface->{NAME}_InterfaceType = {"); 715 $self->indent; 716 $self->pidl("PyObject_HEAD_INIT(NULL) 0,"); 717 $self->pidl(".tp_name = \"$basename.$interface->{NAME}\","); 718 $self->pidl(".tp_basicsize = sizeof(dcerpc_InterfaceObject),"); 719 $self->pidl(".tp_base = &dcerpc_InterfaceType,"); 720 $self->pidl(".tp_doc = $docstring,"); 721 $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,"); 722 $self->pidl(".tp_new = interface_$interface->{NAME}_new,"); 723 $self->deindent; 724 $self->pidl("};"); 725 726 $self->pidl(""); 727 728 $self->register_module_typeobject($interface->{NAME}, "&$interface->{NAME}_InterfaceType"); 729 $self->register_module_readycode(["if (!PyInterface_AddNdrRpcMethods(&$interface->{NAME}_InterfaceType, py_ndr_$interface->{NAME}\_methods))", "\treturn;", ""]); 730 } 731 732 $self->pidl_hdr("\n"); 733} 734 735sub register_module_method($$$$$) 736{ 737 my ($self, $fn_name, $pyfn_name, $flags, $doc) = @_; 738 739 push (@{$self->{module_methods}}, [$fn_name, $pyfn_name, $flags, $doc]) 740} 741 742sub register_module_typeobject($$$) 743{ 744 my ($self, $name, $py_name) = @_; 745 746 $self->register_module_object($name, "(PyObject *)$py_name"); 747 748 $self->check_ready_type($py_name); 749 750 $self->register_patch_type_call($name, $py_name); 751} 752 753sub check_ready_type($$) 754{ 755 my ($self, $py_name) = @_; 756 push (@{$self->{ready_types}}, $py_name) unless (grep(/^$py_name$/,@{$self->{ready_types}})); 757} 758 759sub register_module_import($$) 760{ 761 my ($self, $basename) = @_; 762 763 push (@{$self->{module_imports}}, $basename) unless (grep(/^$basename$/,@{$self->{module_imports}})); 764} 765 766sub use_type_variable($$) 767{ 768 my ($self, $orig_ctype) = @_; 769 # FIXME: Have a global lookup table for types that look different on the 770 # wire than they are named in C? 771 if ($orig_ctype->{NAME} eq "dom_sid2") { 772 $orig_ctype->{NAME} = "dom_sid"; 773 } 774 my $ctype = resolveType($orig_ctype); 775 unless (defined($ctype->{BASEFILE})) { 776 return undef; 777 } 778 # If this is an external type, make sure we do the right imports. 779 if (($ctype->{BASEFILE} ne $self->{BASENAME})) { 780 $self->register_module_import($ctype->{BASEFILE}); 781 unless (defined($self->{type_imports}->{$ctype->{NAME}})) { 782 $self->{type_imports}->{$ctype->{NAME}} = $ctype->{BASEFILE}; 783 } 784 return "$ctype->{NAME}_Type"; 785 } 786 return "&$ctype->{NAME}_Type"; 787} 788 789sub register_patch_type_call($$$) 790{ 791 my ($self, $typename, $cvar) = @_; 792 793 push(@{$self->{patch_type_calls}}, [$typename, $cvar]); 794 795} 796 797sub register_module_readycode($$) 798{ 799 my ($self, $code) = @_; 800 801 push (@{$self->{readycode}}, @$code); 802} 803 804sub register_module_object($$$) 805{ 806 my ($self, $name, $py_name) = @_; 807 808 push (@{$self->{module_objects}}, [$name, $py_name]) 809} 810 811sub assign($$$) 812{ 813 my ($self, $dest, $src) = @_; 814 if ($dest =~ /^\&/ and $src eq "NULL") { 815 $self->pidl("memset($dest, 0, sizeof(" . get_value_of($dest) . "));"); 816 } elsif ($dest =~ /^\&/) { 817 $self->pidl("memcpy($dest, $src, sizeof(" . get_value_of($dest) . "));"); 818 } else { 819 $self->pidl("$dest = $src;"); 820 } 821} 822 823sub ConvertObjectFromPythonData($$$$$$;$) 824{ 825 my ($self, $mem_ctx, $cvar, $ctype, $target, $fail, $location) = @_; 826 827 fatal($location, "undef type for $cvar") unless(defined($ctype)); 828 829 $ctype = resolveType($ctype); 830 831 my $actual_ctype = $ctype; 832 if ($actual_ctype->{TYPE} eq "TYPEDEF") { 833 $actual_ctype = $actual_ctype->{DATA}; 834 } 835 836 if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or 837 $actual_ctype->{TYPE} eq "SCALAR" and ( 838 expandAlias($actual_ctype->{NAME}) =~ /^(u?int[0-9]*|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong|udlongr)$/)) { 839 $self->pidl("PY_CHECK_TYPE(&PyInt_Type, $cvar, $fail);"); 840 $self->pidl("$target = PyInt_AsLong($cvar);"); 841 return; 842 } 843 844 if ($actual_ctype->{TYPE} eq "STRUCT" or $actual_ctype->{TYPE} eq "INTERFACE") { 845 my $ctype_name = $self->use_type_variable($ctype); 846 unless (defined ($ctype_name)) { 847 error($location, "Unable to determine origin of type `" . mapTypeName($ctype) . "'"); 848 $self->pidl("PyErr_SetString(PyExc_TypeError, \"Can not convert C Type " . mapTypeName($ctype) . " to Python\");"); 849 return; 850 } 851 $self->pidl("PY_CHECK_TYPE($ctype_name, $cvar, $fail);"); 852 $self->assign($target, "py_talloc_get_ptr($cvar)"); 853 return; 854 } 855 856 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "DATA_BLOB") { 857 $self->pidl("$target = data_blob_talloc($mem_ctx, PyString_AsString($cvar), PyString_Size($cvar));"); 858 return; 859 } 860 861 if ($actual_ctype->{TYPE} eq "SCALAR" and 862 ($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")) { 863 $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AsString($cvar));"); 864 return; 865 } 866 867 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") { 868 $self->pidl("$target = PyString_AsString($cvar);"); 869 return; 870 } 871 872 873 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") { 874 $self->pidl("$target = NT_STATUS(PyInt_AsLong($cvar));"); 875 return; 876 } 877 878 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") { 879 $self->pidl("$target = W_ERROR(PyInt_AsLong($cvar));"); 880 return; 881 } 882 883 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "string_array") { 884 $self->pidl("$target = PyCObject_AsVoidPtr($cvar);"); 885 return; 886 } 887 888 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "pointer") { 889 $self->assign($target, "PyCObject_AsVoidPtr($cvar)"); 890 return; 891 } 892 893 fatal($location, "unknown type `$actual_ctype->{TYPE}' for ".mapTypeName($ctype) . ": $cvar"); 894 895} 896 897sub ConvertObjectFromPythonLevel($$$$$$$$) 898{ 899 my ($self, $env, $mem_ctx, $py_var, $e, $l, $var_name, $fail) = @_; 900 my $nl = GetNextLevel($e, $l); 901 902 if ($l->{TYPE} eq "POINTER") { 903 if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { 904 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail); 905 return; 906 } 907 if ($l->{POINTER_TYPE} ne "ref") { 908 $self->pidl("if ($py_var == Py_None) {"); 909 $self->indent; 910 $self->pidl("$var_name = NULL;"); 911 $self->deindent; 912 $self->pidl("} else {"); 913 $self->indent; 914 } 915 $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);"); 916 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, get_value_of($var_name), $fail); 917 if ($l->{POINTER_TYPE} ne "ref") { 918 $self->deindent; 919 $self->pidl("}"); 920 } 921 } elsif ($l->{TYPE} eq "ARRAY") { 922 my $pl = GetPrevLevel($e, $l); 923 if ($pl && $pl->{TYPE} eq "POINTER") { 924 $var_name = get_pointer_to($var_name); 925 } 926 927 if (is_charset_array($e, $l)) { 928 $self->pidl("PY_CHECK_TYPE(&PyUnicode_Type, $py_var, $fail);"); 929 # FIXME: Use Unix charset setting rather than utf-8 930 $self->pidl($var_name . " = PyString_AsString(PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\"));"); 931 } else { 932 my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}"; 933 $self->pidl("PY_CHECK_TYPE(&PyList_Type, $py_var, $fail);"); 934 $self->pidl("{"); 935 $self->indent; 936 $self->pidl("int $counter;"); 937 if (ArrayDynamicallyAllocated($e, $l)) { 938 $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_Size($py_var));"); 939 } 940 $self->pidl("for ($counter = 0; $counter < PyList_Size($py_var); $counter++) {"); 941 $self->indent; 942 $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GetItem($py_var, $counter)", $e, GetNextLevel($e, $l), $var_name."[$counter]", $fail); 943 $self->deindent; 944 $self->pidl("}"); 945 $self->deindent; 946 $self->pidl("}"); 947 } 948 } elsif ($l->{TYPE} eq "DATA") { 949 950 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE})) { 951 $var_name = get_pointer_to($var_name); 952 } 953 $self->ConvertObjectFromPythonData($mem_ctx, $py_var, $l->{DATA_TYPE}, $var_name, $fail, $e->{ORIGINAL}); 954 } elsif ($l->{TYPE} eq "SWITCH") { 955 $var_name = get_pointer_to($var_name); 956 my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e); 957 $self->assign($var_name, "py_export_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $py_var)"); 958 } elsif ($l->{TYPE} eq "SUBCONTEXT") { 959 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, GetNextLevel($e, $l), $var_name, $fail); 960 } else { 961 fatal($e->{ORIGINAL}, "unknown level type $l->{TYPE}"); 962 } 963} 964 965sub ConvertObjectFromPython($$$$$$$) 966{ 967 my ($self, $env, $mem_ctx, $ctype, $cvar, $target, $fail) = @_; 968 969 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $cvar, $ctype, $ctype->{LEVELS}[0], $target, $fail); 970} 971 972sub ConvertScalarToPython($$$) 973{ 974 my ($self, $ctypename, $cvar) = @_; 975 976 die("expected string for $cvar, not $ctypename") if (ref($ctypename) eq "HASH"); 977 978 $ctypename = expandAlias($ctypename); 979 980 if ($ctypename =~ /^(char|u?int[0-9]*|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) { 981 return "PyInt_FromLong($cvar)"; 982 } 983 984 if ($ctypename eq "DATA_BLOB") { 985 return "PyString_FromStringAndSize((char *)($cvar).data, ($cvar).length)"; 986 } 987 988 if ($ctypename eq "NTSTATUS") { 989 return "PyErr_FromNTSTATUS($cvar)"; 990 } 991 992 if ($ctypename eq "WERROR") { 993 return "PyErr_FromWERROR($cvar)"; 994 } 995 996 if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) { 997 return "PyString_FromString($cvar)"; 998 } 999 1000 # Not yet supported 1001 if ($ctypename eq "string_array") { return "PyCObject_FromTallocPtr($cvar)"; } 1002 if ($ctypename eq "ipv4address") { return "PyString_FromString($cvar)"; } 1003 if ($ctypename eq "pointer") { 1004 return "PyCObject_FromTallocPtr($cvar)"; 1005 } 1006 1007 die("Unknown scalar type $ctypename"); 1008} 1009 1010sub ConvertObjectToPythonData($$$$$;$) 1011{ 1012 my ($self, $mem_ctx, $ctype, $cvar, $location) = @_; 1013 1014 die("undef type for $cvar") unless(defined($ctype)); 1015 1016 $ctype = resolveType($ctype); 1017 1018 my $actual_ctype = $ctype; 1019 if ($actual_ctype->{TYPE} eq "TYPEDEF") { 1020 $actual_ctype = $actual_ctype->{DATA}; 1021 } 1022 1023 if ($actual_ctype->{TYPE} eq "ENUM") { 1024 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::enum_type_fn($actual_ctype), $cvar); 1025 } elsif ($actual_ctype->{TYPE} eq "BITMAP") { 1026 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::bitmap_type_fn($actual_ctype), $cvar); 1027 } elsif ($actual_ctype->{TYPE} eq "SCALAR") { 1028 return $self->ConvertScalarToPython($actual_ctype->{NAME}, $cvar); 1029 } elsif ($actual_ctype->{TYPE} eq "UNION") { 1030 fatal($ctype, "union without discriminant: " . mapTypeName($ctype) . ": $cvar"); 1031 } elsif ($actual_ctype->{TYPE} eq "STRUCT" or $actual_ctype->{TYPE} eq "INTERFACE") { 1032 my $ctype_name = $self->use_type_variable($ctype); 1033 unless (defined($ctype_name)) { 1034 error($location, "Unable to determine origin of type `" . mapTypeName($ctype) . "'"); 1035 return "NULL"; # FIXME! 1036 } 1037 return "py_talloc_reference_ex($ctype_name, $mem_ctx, $cvar)"; 1038 } 1039 1040 fatal($location, "unknown type $actual_ctype->{TYPE} for ".mapTypeName($ctype) . ": $cvar"); 1041} 1042 1043sub fail_on_null($$$) 1044{ 1045 my ($self, $var, $fail) = @_; 1046 $self->pidl("if ($var == NULL) {"); 1047 $self->indent; 1048 $self->pidl($fail); 1049 $self->deindent; 1050 $self->pidl("}"); 1051} 1052 1053sub ConvertObjectToPythonLevel($$$$$$) 1054{ 1055 my ($self, $mem_ctx, $env, $e, $l, $var_name, $py_var, $fail) = @_; 1056 my $nl = GetNextLevel($e, $l); 1057 1058 if ($l->{TYPE} eq "POINTER") { 1059 if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { 1060 $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name, $py_var, $fail); 1061 return; 1062 } 1063 if ($l->{POINTER_TYPE} ne "ref") { 1064 $self->pidl("if ($var_name == NULL) {"); 1065 $self->indent; 1066 $self->pidl("$py_var = Py_None;"); 1067 $self->deindent; 1068 $self->pidl("} else {"); 1069 $self->indent; 1070 } 1071 $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, get_value_of($var_name), $py_var, $fail); 1072 if ($l->{POINTER_TYPE} ne "ref") { 1073 $self->deindent; 1074 $self->pidl("}"); 1075 } 1076 } elsif ($l->{TYPE} eq "ARRAY") { 1077 my $pl = GetPrevLevel($e, $l); 1078 if ($pl && $pl->{TYPE} eq "POINTER") { 1079 $var_name = get_pointer_to($var_name); 1080 } 1081 1082 if (is_charset_array($e, $l)) { 1083 # FIXME: Use Unix charset setting rather than utf-8 1084 $self->pidl("$py_var = PyUnicode_Decode($var_name, strlen($var_name), \"utf-8\", \"ignore\");"); 1085 } else { 1086 die("No SIZE_IS for array $var_name") unless (defined($l->{SIZE_IS})); 1087 my $length = $l->{SIZE_IS}; 1088 if (defined($l->{LENGTH_IS})) { 1089 $length = $l->{LENGTH_IS}; 1090 } 1091 1092 $length = ParseExpr($length, $env, $e); 1093 $self->pidl("$py_var = PyList_New($length);"); 1094 $self->fail_on_null($py_var, $fail); 1095 $self->pidl("{"); 1096 $self->indent; 1097 my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}"; 1098 $self->pidl("int $counter;"); 1099 $self->pidl("for ($counter = 0; $counter < $length; $counter++) {"); 1100 $self->indent; 1101 my $member_var = "py_$e->{NAME}_$l->{LEVEL_INDEX}"; 1102 $self->pidl("PyObject *$member_var;"); 1103 $self->ConvertObjectToPythonLevel($var_name, $env, $e, GetNextLevel($e, $l), $var_name."[$counter]", $member_var, $fail); 1104 $self->pidl("PyList_SetItem($py_var, $counter, $member_var);"); 1105 $self->deindent; 1106 $self->pidl("}"); 1107 $self->deindent; 1108 $self->pidl("}"); 1109 } 1110 } elsif ($l->{TYPE} eq "SWITCH") { 1111 $var_name = get_pointer_to($var_name); 1112 my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e); 1113 $self->pidl("$py_var = py_import_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $var_name);"); 1114 $self->fail_on_null($py_var, $fail); 1115 1116 } elsif ($l->{TYPE} eq "DATA") { 1117 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE})) { 1118 $var_name = get_pointer_to($var_name); 1119 } 1120 my $conv = $self->ConvertObjectToPythonData($mem_ctx, $l->{DATA_TYPE}, $var_name, $e->{ORIGINAL}); 1121 $self->pidl("$py_var = $conv;"); 1122 } elsif ($l->{TYPE} eq "SUBCONTEXT") { 1123 $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, GetNextLevel($e, $l), $var_name, $py_var, $fail); 1124 } else { 1125 fatal($e->{ORIGINAL}, "Unknown level type $l->{TYPE} $var_name"); 1126 } 1127} 1128 1129sub ConvertObjectToPython($$$$$$) 1130{ 1131 my ($self, $mem_ctx, $env, $ctype, $cvar, $py_var, $fail) = @_; 1132 1133 $self->ConvertObjectToPythonLevel($mem_ctx, $env, $ctype, $ctype->{LEVELS}[0], $cvar, $py_var, $fail); 1134} 1135 1136sub Parse($$$$$) 1137{ 1138 my($self,$basename,$ndr,$ndr_hdr,$hdr) = @_; 1139 1140 $self->{BASENAME} = $basename; 1141 1142 $self->pidl_hdr(" 1143/* Python wrapper functions auto-generated by pidl */ 1144#include \"includes.h\" 1145#include <Python.h> 1146#include \"librpc/rpc/dcerpc.h\" 1147#include \"lib/talloc/pytalloc.h\" 1148#include \"librpc/rpc/pyrpc.h\" 1149#include \"$hdr\" 1150#include \"$ndr_hdr\" 1151 1152#ifndef Py_RETURN_NONE 1153#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None 1154#endif 1155 1156"); 1157 1158 foreach my $x (@$ndr) { 1159 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}}); 1160 ($x->{TYPE} eq "INTERFACE") && $self->Interface($x, $basename); 1161 } 1162 1163 $self->pidl("static PyMethodDef $basename\_methods[] = {"); 1164 $self->indent; 1165 foreach (@{$self->{module_methods}}) { 1166 my ($fn_name, $pyfn_name, $flags, $doc) = @$_; 1167 $self->pidl("{ \"$fn_name\", (PyCFunction)$pyfn_name, $flags, $doc },"); 1168 } 1169 1170 $self->pidl("{ NULL, NULL, 0, NULL }"); 1171 $self->deindent; 1172 $self->pidl("};"); 1173 1174 $self->pidl(""); 1175 1176 $self->pidl("void init$basename(void)"); 1177 $self->pidl("{"); 1178 $self->indent; 1179 $self->pidl("PyObject *m;"); 1180 foreach (@{$self->{module_imports}}) { 1181 $self->pidl("PyObject *dep_$_;"); 1182 } 1183 $self->pidl(""); 1184 1185 foreach (@{$self->{module_imports}}) { 1186 $self->pidl("dep_$_ = PyImport_ImportModule(\"samba.dcerpc.$_\");"); 1187 $self->pidl("if (dep_$_ == NULL)"); 1188 $self->pidl("\treturn;"); 1189 $self->pidl(""); 1190 } 1191 1192 foreach (keys %{$self->{type_imports}}) { 1193 my $basefile = $self->{type_imports}->{$_}; 1194 $self->pidl_hdr("static PyTypeObject *$_\_Type;\n"); 1195 my $pretty_name = PrettifyTypeName($_, $basefile); 1196 $self->pidl("$_\_Type = (PyTypeObject *)PyObject_GetAttrString(dep_$basefile, \"$pretty_name\");"); 1197 $self->pidl("if ($_\_Type == NULL)"); 1198 $self->pidl("\treturn;"); 1199 $self->pidl(""); 1200 } 1201 1202 foreach (@{$self->{ready_types}}) { 1203 $self->pidl("if (PyType_Ready($_) < 0)"); 1204 $self->pidl("\treturn;"); 1205 } 1206 1207 $self->pidl($_) foreach (@{$self->{readycode}}); 1208 1209 foreach (@{$self->{patch_type_calls}}) { 1210 my ($typename, $cvar) = @$_; 1211 $self->pidl("#ifdef PY_".uc($typename)."_PATCH"); 1212 $self->pidl("PY_".uc($typename)."_PATCH($cvar);"); 1213 $self->pidl("#endif"); 1214 } 1215 1216 $self->pidl(""); 1217 1218 $self->pidl("m = Py_InitModule3(\"$basename\", $basename\_methods, \"$basename DCE/RPC\");"); 1219 $self->pidl("if (m == NULL)"); 1220 $self->pidl("\treturn;"); 1221 $self->pidl(""); 1222 foreach my $name (keys %{$self->{constants}}) { 1223 my $py_obj; 1224 my ($ctype, $cvar) = @{$self->{constants}->{$name}}; 1225 if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) { 1226 $py_obj = "PyInt_FromLong($cvar)"; 1227 } elsif ($cvar =~ /^".*"$/) { 1228 $py_obj = "PyString_FromString($cvar)"; 1229 } else { 1230 $py_obj = $self->ConvertObjectToPythonData("NULL", expandAlias($ctype), $cvar, undef); 1231 } 1232 1233 $self->pidl("PyModule_AddObject(m, \"$name\", $py_obj);"); 1234 } 1235 1236 foreach (@{$self->{module_objects}}) { 1237 my ($object_name, $c_name) = @$_; 1238 $self->pidl("Py_INCREF($c_name);"); 1239 $self->pidl("PyModule_AddObject(m, \"$object_name\", $c_name);"); 1240 } 1241 1242 $self->pidl("#ifdef PY_MOD_".uc($basename)."_PATCH"); 1243 $self->pidl("PY_MOD_".uc($basename)."_PATCH(m);"); 1244 $self->pidl("#endif"); 1245 1246 $self->pidl(""); 1247 $self->deindent; 1248 $self->pidl("}"); 1249 return ($self->{res_hdr} . $self->{res}); 1250} 1251 12521; 1253