PageRenderTime 60ms CodeModel.GetById 15ms app.highlight 37ms RepoModel.GetById 0ms app.codeStats 0ms

/bundles/pyml/pyml-current/pyml_stubs.c

http://github.com/coccinelle/coccinelle
C | 1372 lines | 1206 code | 120 blank | 46 comment | 176 complexity | f8b0bcc2179767017ea0d88039fbf649 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-4.0
   1#define _GNU_SOURCE
   2#include <caml/mlvalues.h>
   3#include <caml/memory.h>
   4#include <caml/fail.h>
   5#include <caml/callback.h>
   6#include <caml/custom.h>
   7#include <caml/alloc.h>
   8#include <sys/param.h>
   9#include <string.h>
  10#include <stdbool.h>
  11#include <stdio.h>
  12#include <stdlib.h>
  13#include <unistd.h>
  14#include <errno.h>
  15#include "pyml_stubs.h"
  16
  17static FILE *(*Python__Py_fopen)(const char *pathname, const char *mode);
  18
  19static void *xmalloc(size_t size)
  20{
  21    void *p = malloc(size);
  22    if (!p) {
  23        failwith("Virtual memory exhausted\n");
  24    }
  25    return p;
  26}
  27
  28#ifdef _WIN32
  29#include <windows.h>
  30
  31typedef HINSTANCE library_t;
  32
  33static library_t
  34open_library(const char *filename)
  35{
  36    return LoadLibrary(filename);
  37}
  38
  39void
  40close_library(library_t library)
  41{
  42    if (!FreeLibrary(library)) {
  43        fprintf(stderr, "close_library.\n");
  44        exit(EXIT_FAILURE);
  45    }
  46}
  47
  48static library_t
  49get_default_library(void)
  50{
  51    return GetModuleHandle(0);
  52}
  53
  54static void *
  55find_symbol(library_t library, const char *name)
  56{
  57    return GetProcAddress(library, name);
  58}
  59
  60int
  61unsetenv(const char *name)
  62{
  63    size_t len = strlen(name);
  64    char string[len + 2];
  65    snprintf(string, len + 2, "%s=", name);
  66    return _putenv(string);
  67}
  68
  69extern int win_CRT_fd_of_filedescr(value handle);
  70
  71static FILE *
  72file_of_file_descr(value file_descr, const char *mode)
  73{
  74    CAMLparam1(file_descr);
  75    int fd = win_CRT_fd_of_filedescr(file_descr);
  76    FILE *result = _fdopen(dup(fd), mode);
  77    CAMLreturnT(FILE *, result);
  78}
  79#else
  80#include <dlfcn.h>
  81
  82typedef void *library_t;
  83
  84static library_t
  85open_library(const char *filename)
  86{
  87    return dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
  88}
  89
  90void
  91close_library(library_t filename)
  92{
  93    if (dlclose(filename)) {
  94        fprintf(stderr, "close_library: %s.\n", dlerror());
  95        exit(EXIT_FAILURE);
  96    }
  97}
  98
  99static library_t
 100get_default_library(void)
 101{
 102    return RTLD_DEFAULT;
 103}
 104
 105static void *
 106find_symbol(library_t library, const char *name)
 107{
 108    return dlsym(library, name);
 109}
 110
 111static FILE *
 112file_of_file_descr(value file_descr, const char *mode)
 113{
 114    CAMLparam1(file_descr);
 115    int fd = Int_val(file_descr);
 116    FILE *result = fdopen(dup(fd), mode);
 117    CAMLreturnT(FILE *, result);
 118}
 119#endif
 120
 121/* The following definitions are extracted and simplified from
 122#include <Python.h>
 123*/
 124
 125typedef struct {
 126    int cf_flags;
 127} PyCompilerFlags;
 128
 129#define Py_TPFLAGS_INT_SUBCLASS         (1L<<23)
 130#define Py_TPFLAGS_LONG_SUBCLASS        (1UL << 24)
 131#define Py_TPFLAGS_LIST_SUBCLASS        (1UL << 25)
 132#define Py_TPFLAGS_TUPLE_SUBCLASS       (1UL << 26)
 133#define Py_TPFLAGS_BYTES_SUBCLASS       (1UL << 27)
 134#define Py_TPFLAGS_UNICODE_SUBCLASS     (1UL << 28)
 135#define Py_TPFLAGS_DICT_SUBCLASS        (1UL << 29)
 136#define Py_TPFLAGS_BASE_EXC_SUBCLASS    (1UL << 30)
 137#define Py_TPFLAGS_TYPE_SUBCLASS        (1UL << 31)
 138
 139#define Py_LT 0
 140#define Py_LE 1
 141#define Py_EQ 2
 142#define Py_NE 3
 143#define Py_GT 4
 144#define Py_GE 5
 145
 146typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
 147
 148typedef struct PyMethodDef {
 149    const char *ml_name;
 150    PyCFunction ml_meth;
 151    int ml_flags;
 152    const char	*ml_doc;
 153} PyMethodDef;
 154
 155typedef void (*PyCapsule_Destructor)(PyObject *);
 156
 157static void *Python27__PyObject_NextNotImplemented;
 158
 159/* Global variables for the library */
 160
 161/* version_major != 0 iff the library is initialized */
 162static int version_major;
 163static int version_minor;
 164
 165static library_t library;
 166
 167/* Functions that are special enough to deserved to be wrapped specifically */
 168
 169/* Wrapped by pywrap_closure */
 170static PyObject *(*Python_PyCFunction_NewEx)
 171(PyMethodDef *, PyObject *, PyObject *);
 172
 173/* Wrapped by closure and capsule */
 174static void *(*Python27_PyCapsule_New)
 175    (void *, const char *, PyCapsule_Destructor);
 176static void *(*Python27_PyCapsule_GetPointer)(PyObject *, const char *);
 177static int (*Python27_PyCapsule_IsValid)(PyObject *, char *);
 178static void *(*Python2_PyCObject_FromVoidPtr)(void *, void (*)(void *));
 179static void *(*Python2_PyCObject_AsVoidPtr)(PyObject *);
 180
 181/* Hack for multi-arguments */
 182static PyObject *(*Python_PyObject_CallFunctionObjArgs)(PyObject *, ...);
 183static PyObject *(*Python_PyObject_CallMethodObjArgs)(
 184  PyObject *, PyObject *, ...);
 185
 186/* Wrapped by PyErr_Fetch_wrapper */
 187static void (*Python_PyErr_Fetch)(PyObject **, PyObject **, PyObject **);
 188static void (*Python_PyErr_NormalizeException)
 189(PyObject **, PyObject **, PyObject **);
 190
 191/* Resolved differently between Python 2 and Python 3 */
 192static PyObject *Python__Py_FalseStruct;
 193
 194/* Buffer and size */
 195static int (*Python_PyString_AsStringAndSize)
 196(PyObject *, char **, Py_ssize_t *);
 197static int (*Python_PyObject_AsCharBuffer)
 198(PyObject *, const char **, Py_ssize_t *);
 199static int (*Python_PyObject_AsReadBuffer)
 200(PyObject *, const void **, Py_ssize_t *);
 201static int (*Python_PyObject_AsWriteBuffer)
 202(PyObject *, void **, Py_ssize_t *);
 203
 204/* Length argument */
 205static PyObject *(*Python_PyLong_FromString)(char *, char **, int);
 206
 207/* Internal use only */
 208static void (*Python_PyMem_Free)(void *);
 209
 210static enum UCS { UCS_NONE, UCS2, UCS4 } ucs;
 211
 212/* Single instance of () */
 213static PyObject *tuple_empty;
 214
 215#include "pyml.h"
 216
 217static void *getcustom( value v )
 218{
 219    return *((void **)Data_custom_val(v));
 220}
 221
 222static void pydecref( value v )
 223{
 224    if (getcustom(v)) {
 225        Py_DECREF((PyObject *)getcustom(v));
 226    }
 227}
 228
 229static int
 230rich_compare_bool_nofail
 231(PyObject *o1, PyObject *o2, int opid)
 232{
 233    int result = Python_PyObject_RichCompareBool(o1, o2, opid);
 234    if (result == -1) {
 235        Python_PyErr_Clear();
 236        result = 0;
 237    }
 238    return result;
 239}
 240
 241static int
 242pycompare(value v1, value v2)
 243{
 244    int result;
 245    PyObject *o1 = getcustom(v1);
 246    PyObject *o2 = getcustom(v2);
 247
 248    if (o1 && !o2)
 249        result = -1;
 250    else if (o2 && !o1)
 251        result = 1;
 252    else if (!o1 && !o2)
 253        result = 0;
 254    else if (version_major < 3)
 255        Python2_PyObject_Cmp(o1, o2, &result);
 256    else if (rich_compare_bool_nofail(o1, o2, Py_EQ))
 257        result = 0;
 258    else if (rich_compare_bool_nofail(o1, o2, Py_LT))
 259        result = -1;
 260    else if (rich_compare_bool_nofail(o1, o2, Py_GT))
 261        result = 1;
 262    else
 263        result = -1;
 264
 265    return result;
 266}
 267
 268static intnat
 269pyhash( value v )
 270{
 271    if (getcustom(v)) {
 272        intnat result = Python_PyObject_Hash((PyObject *)getcustom(v));
 273        if (result == -1) {
 274            Python_PyErr_Clear();
 275        }
 276        return result;
 277    }
 278    else {
 279        return 0;
 280    }
 281}
 282
 283static uintnat
 284pydeserialize(void *dst)
 285{
 286    return 0L;
 287}
 288
 289struct custom_operations pyops =
 290{
 291    "PythonObject",
 292    pydecref,
 293    pycompare,
 294    pyhash,
 295    custom_serialize_default,
 296    pydeserialize
 297};
 298
 299enum code {
 300    CODE_NULL,
 301    CODE_NONE,
 302    CODE_TRUE,
 303    CODE_FALSE,
 304    CODE_TUPLE_EMPTY
 305};
 306
 307static void *
 308resolve(const char *symbol)
 309{
 310    void *result = find_symbol(library, symbol);
 311    if (!result) {
 312        char *fmt = "Cannot resolve %s.\n";
 313        ssize_t size = snprintf(NULL, 0, fmt, symbol);
 314        char *msg = xmalloc(size + 1);
 315        snprintf(msg, size + 1, fmt, symbol);
 316        failwith(msg);
 317    }
 318    return result;
 319}
 320
 321static void *
 322resolve_optional(const char *symbol)
 323{
 324    return find_symbol(library, symbol);
 325}
 326
 327value
 328pyml_wrap(PyObject *object, bool steal)
 329{
 330    CAMLparam0();
 331    CAMLlocal1(v);
 332    if (!object) {
 333        CAMLreturn(Val_int(CODE_NULL));
 334    }
 335    if (object == Python__Py_NoneStruct) {
 336        CAMLreturn(Val_int(CODE_NONE));
 337    }
 338    if (object == Python__Py_TrueStruct) {
 339        CAMLreturn(Val_int(CODE_TRUE));
 340    }
 341    if (object == Python__Py_FalseStruct) {
 342        CAMLreturn(Val_int(CODE_FALSE));
 343    }
 344    unsigned long flags =
 345        ((struct _typeobject *) pyobjectdescr(pyobjectdescr(object)->ob_type))
 346        ->tp_flags;
 347    if (flags & Py_TPFLAGS_TUPLE_SUBCLASS
 348        && Python_PySequence_Length(object) == 0) {
 349        CAMLreturn(Val_int(CODE_TUPLE_EMPTY));
 350    }
 351    if (!steal) {
 352        Py_INCREF(object);
 353    }
 354    v = caml_alloc_custom(&pyops, sizeof(PyObject *), 100, 30000000);
 355    *((PyObject **)Data_custom_val(v)) = object;
 356    CAMLreturn(v);
 357}
 358
 359PyObject *
 360pyml_unwrap(value v)
 361{
 362    if (Is_long(v))
 363        switch (Int_val(v)) {
 364        case CODE_NULL:
 365            return NULL;
 366        case CODE_NONE:
 367            return Python__Py_NoneStruct;
 368        case CODE_TRUE:
 369            return Python__Py_TrueStruct;
 370        case CODE_FALSE:
 371            return Python__Py_FalseStruct;
 372        case CODE_TUPLE_EMPTY:
 373            return tuple_empty;
 374        }
 375
 376    return *((PyObject **)Data_custom_val(v));
 377}
 378
 379/*
 380static value
 381pyml_wrap_compilerflags(PyCompilerFlags *flags)
 382{
 383    CAMLparam0();
 384    CAMLlocal2(ref, some);
 385    if (!flags) {
 386        CAMLreturn(Val_int(0));
 387    }
 388    else {
 389        ref = caml_alloc(0, 1);
 390        Store_field(ref, 0, Val_int(flags->cf_flags));
 391        some = caml_alloc(0, 1);
 392        Store_field(some, 0, ref);
 393        CAMLreturn(some);
 394    }
 395}
 396*/
 397
 398static PyCompilerFlags *
 399pyml_unwrap_compilerflags(value v)
 400{
 401    CAMLparam1(v);
 402    if (Is_block(v)) {
 403        PyCompilerFlags *flags = malloc(sizeof(PyCompilerFlags));
 404        flags->cf_flags = Int_val(Field(Field(v, 0), 0));
 405        CAMLreturnT(PyCompilerFlags *, flags);
 406    }
 407    else {
 408        CAMLreturnT(PyCompilerFlags *, NULL);
 409    }
 410}
 411
 412/*
 413static value
 414pyml_wrap_intref(int v)
 415{
 416    CAMLparam0();
 417    CAMLlocal1(ref);
 418    ref = caml_alloc(0, 1);
 419    Store_field(ref, 0, Val_int(v));
 420    CAMLreturn(ref);
 421}
 422*/
 423
 424static int
 425pyml_unwrap_intref(value v)
 426{
 427    CAMLparam1(v);
 428    CAMLreturnT(int, Int_val(Field(v, 0)));
 429}
 430
 431static void *
 432unwrap_capsule(PyObject *obj, const char *type)
 433{
 434    if (Python27_PyCapsule_GetPointer) {
 435        return Python27_PyCapsule_GetPointer(obj, type);
 436    }
 437    else {
 438        return Python2_PyCObject_AsVoidPtr(obj);
 439    }
 440}
 441
 442
 443static PyObject *
 444wrap_capsule(void *ptr, char *type, void (*destr)(PyObject *))
 445{
 446    if (Python27_PyCapsule_New) {
 447        return Python27_PyCapsule_New(ptr, type, destr);
 448    }
 449    else {
 450        return Python2_PyCObject_FromVoidPtr(ptr, (void(*)(void *))destr);
 451    }
 452}
 453
 454static PyObject *
 455pycall_callback(PyObject *obj, PyObject *args)
 456{
 457    CAMLparam0();
 458    CAMLlocal3(ml_out, ml_func, ml_args);
 459    PyObject *out;
 460    void *p = unwrap_capsule(obj, "ocaml-closure");
 461    if (!p) {
 462        Py_INCREF(Python__Py_NoneStruct);
 463        return Python__Py_NoneStruct;
 464    }
 465    ml_func = *(value *) p;
 466    ml_args = pyml_wrap(args, false);
 467    ml_out = caml_callback(ml_func, ml_args);
 468    out = pyml_unwrap(ml_out);
 469    Py_XINCREF(out);
 470    CAMLreturnT(PyObject *, out);
 471}
 472
 473static PyObject *
 474pycall_callback_with_keywords(PyObject *obj, PyObject *args, PyObject *keywords)
 475{
 476    CAMLparam0();
 477    CAMLlocal4(ml_out, ml_func, ml_args, ml_keywords);
 478    PyObject *out;
 479    void *p = unwrap_capsule(obj, "ocaml-closure");
 480    if (!p) {
 481        Py_INCREF(Python__Py_NoneStruct);
 482        return Python__Py_NoneStruct;
 483    }
 484    ml_func = *(value *) p;
 485    ml_args = pyml_wrap(args, false);
 486    ml_keywords = pyml_wrap(keywords, false);
 487    ml_out = caml_callback2(ml_func, ml_args, ml_keywords);
 488    out = pyml_unwrap(ml_out);
 489    Py_XINCREF(out);
 490    CAMLreturnT(PyObject *, out);
 491}
 492
 493static void
 494caml_destructor(PyObject *v, const char *capsule_name)
 495{
 496    value *valptr = (value *) unwrap_capsule(v, capsule_name);
 497    caml_remove_global_root(valptr);
 498    free(valptr);
 499}
 500
 501static void
 502camldestr_closure(PyObject *v)
 503{
 504    caml_destructor(v, "ocaml-closure");
 505}
 506
 507static PyObject *
 508camlwrap_closure(value val, void *aux_str, int size)
 509{
 510    value *v = (value *) malloc(sizeof(value) + size);
 511    *v = val;
 512    memcpy((void *)v + sizeof(value), aux_str, size);
 513    caml_register_global_root(v);
 514    return wrap_capsule(v, "ocaml-closure", camldestr_closure);
 515}
 516
 517static void
 518camldestr_capsule(PyObject *v)
 519{
 520    caml_destructor(v, "ocaml-capsule");
 521}
 522
 523static PyObject *
 524camlwrap_capsule(value val, void *aux_str, int size)
 525{
 526    value *v = (value *) malloc(sizeof(value) + size);
 527    *v = val;
 528    memcpy((void *)v + sizeof(value), aux_str, size);
 529    caml_register_global_root(v);
 530    return wrap_capsule(v, "ocaml-capsule", camldestr_capsule);
 531}
 532
 533static void *
 534caml_aux(PyObject *obj)
 535{
 536    value *v = (value *) unwrap_capsule(obj, "ocaml-closure");
 537    return (void *) v + sizeof(value);
 538}
 539
 540void
 541pyml_assert_initialized()
 542{
 543    if (!version_major) {
 544        failwith("Run 'Py.initialize ()' first");
 545    }
 546}
 547
 548void
 549pyml_assert_python2()
 550{
 551    if (version_major != 2) {
 552        pyml_assert_initialized();
 553        failwith("Python 2 needed");
 554    }
 555}
 556
 557void
 558pyml_assert_ucs2()
 559{
 560    if (ucs != UCS2) {
 561        pyml_assert_initialized();
 562        failwith("Python with UCS2 needed");
 563    }
 564}
 565
 566void
 567pyml_assert_ucs4()
 568{
 569    if (ucs != UCS4) {
 570        pyml_assert_initialized();
 571        failwith("Python with UCS4 needed");
 572    }
 573}
 574
 575void
 576pyml_assert_python3()
 577{
 578    if (version_major != 3) {
 579        pyml_assert_initialized();
 580        failwith("Python 3 needed");
 581    }
 582}
 583
 584void
 585pyml_check_symbol_available(void *symbol, char *symbol_name)
 586{
 587    if (!symbol) {
 588        char *fmt = "Symbol unavailable with this version of Python: %s.\n";
 589        ssize_t size = snprintf(NULL, 0, fmt, symbol_name);
 590        if (size < 0) {
 591          failwith("Symbol unavailable with this version of Python.\n");
 592          return;
 593        }
 594        char *msg = xmalloc(size + 1);
 595        size = snprintf(msg, size + 1, fmt, symbol_name);
 596        if (size < 0) {
 597          failwith("Symbol unavailable with this version of Python.\n");
 598          return;
 599        }
 600        failwith(msg);
 601    }
 602}
 603
 604void *
 605deref_not_null(void *pointer)
 606{
 607    if (pointer) {
 608        return *(void **) pointer;
 609    }
 610    else {
 611        return NULL;
 612    }
 613}
 614
 615CAMLprim value
 616pyml_wrap_closure(value docstring, value closure)
 617{
 618    CAMLparam2(docstring, closure);
 619    pyml_assert_initialized();
 620    PyMethodDef ml;
 621    PyObject *obj;
 622    PyMethodDef *ml_def;
 623    ml.ml_name = "anonymous_closure";
 624    if (Tag_val(closure) == 0) {
 625        ml.ml_flags = 1;
 626        ml.ml_meth = pycall_callback;
 627    }
 628    else {
 629        ml.ml_flags = 3;
 630        ml.ml_meth = (PyCFunction) pycall_callback_with_keywords;
 631    }
 632    ml.ml_doc = String_val(docstring);
 633    obj = camlwrap_closure(Field(closure, 0), &ml, sizeof(ml));
 634    ml_def = (PyMethodDef *) caml_aux(obj);
 635    PyObject *f = Python_PyCFunction_NewEx(ml_def, obj, NULL);
 636    CAMLreturn(pyml_wrap(f, true));
 637}
 638
 639int debug_build;
 640
 641CAMLprim value
 642py_load_library(value filename_ocaml, value debug_build_ocaml)
 643{
 644    CAMLparam2(filename_ocaml, debug_build_ocaml);
 645    if (Is_block(filename_ocaml)) {
 646        char *filename = String_val(Field(filename_ocaml, 0));
 647        library = open_library(filename);
 648        if (!library) {
 649            failwith("Library not found");
 650        }
 651    }
 652    else {
 653        library = get_default_library();
 654    }
 655    Python_Py_GetVersion = find_symbol(library, "Py_GetVersion");
 656    if (!Python_Py_GetVersion) {
 657        failwith("No Python symbol");
 658    }
 659    const char *version = Python_Py_GetVersion();
 660    version_major = version[0] - '0';
 661    version_minor = version[2] - '0';
 662    Python_PyCFunction_NewEx = resolve("PyCFunction_NewEx");
 663    if ((version_major == 2 && version_minor >= 7) || version_major >= 3) {
 664        Python27_PyCapsule_New = resolve("PyCapsule_New");
 665        Python27_PyCapsule_GetPointer = resolve("PyCapsule_GetPointer");
 666        Python27_PyCapsule_IsValid = resolve("PyCapsule_IsValid");
 667        Python27__PyObject_NextNotImplemented =
 668            resolve("_PyObject_NextNotImplemented");
 669    }
 670    Python_PyObject_CallFunctionObjArgs =
 671        resolve("PyObject_CallFunctionObjArgs");
 672    Python_PyObject_CallMethodObjArgs =
 673        resolve("PyObject_CallMethodObjArgs");
 674    Python_PyErr_Fetch = resolve("PyErr_Fetch");
 675    Python_PyErr_NormalizeException = resolve("PyErr_NormalizeException");
 676    Python_PyObject_AsCharBuffer = resolve("PyObject_AsCharBuffer");
 677    Python_PyObject_AsReadBuffer = resolve("PyObject_AsReadBuffer");
 678    Python_PyObject_AsWriteBuffer = resolve("PyObject_AsWriteBuffer");
 679    if (version_major >= 3) {
 680        Python__Py_FalseStruct = resolve("_Py_FalseStruct");
 681        Python_PyString_AsStringAndSize = resolve("PyBytes_AsStringAndSize");
 682    }
 683    else {
 684        Python__Py_FalseStruct = resolve("_Py_ZeroStruct");
 685        Python_PyString_AsStringAndSize = resolve("PyString_AsStringAndSize");
 686    }
 687    Python_PyLong_FromString = resolve("PyLong_FromString");
 688    Python_PyMem_Free = resolve("PyMem_Free");
 689    if (version_major >= 3) {
 690        Python__Py_fopen = resolve("_Py_fopen");
 691    }
 692    else {
 693        Python2_PyCObject_FromVoidPtr = resolve("PyCObject_FromVoidPtr");
 694        Python2_PyCObject_AsVoidPtr = resolve("PyCObject_AsVoidPtr");
 695    }
 696    if (find_symbol(library, "PyUnicodeUCS2_AsEncodedString")) {
 697        ucs = UCS2;
 698    }
 699    else if (find_symbol(library, "PyUnicodeUCS4_AsEncodedString")) {
 700        ucs = UCS4;
 701    }
 702    else {
 703        ucs = UCS_NONE;
 704    }
 705#include "pyml_dlsyms.inc"
 706    Python_Py_Initialize();
 707    if (Is_block(debug_build_ocaml)) {
 708        debug_build = Int_val(Field(debug_build_ocaml, 0));
 709    }
 710    else {
 711        PyObject *sysconfig = Python_PyImport_ImportModule("sysconfig");
 712        PyObject *get_config_var =
 713            Python_PyObject_GetAttrString(sysconfig, "get_config_var");
 714        PyObject *args;
 715        PyObject *py_debug;
 716        PyObject *debug_build_py;
 717        char *py_debug_str = "Py_DEBUG";
 718        if (version_major >= 3) {
 719            py_debug = Python3_PyUnicode_FromStringAndSize(py_debug_str, 8);
 720        }
 721        else {
 722            py_debug = Python2_PyString_FromStringAndSize(py_debug_str, 8);
 723        }
 724        if (!py_debug) {
 725            failwith("py_debug");
 726        }
 727        args = Python_PyTuple_New(1);
 728        if (!args) {
 729            failwith("PyTuple_New");
 730        }
 731        if (Python_PyTuple_SetItem(args, 0, py_debug)) {
 732            failwith("PyTuple_SetItem");
 733        }
 734        debug_build_py =
 735            Python_PyEval_CallObjectWithKeywords(get_config_var, args, NULL);
 736        if (!debug_build_py) {
 737            failwith("PyEval_CallObjectWithKeywords");
 738        }
 739        if (version_major >= 3) {
 740            debug_build = Python_PyLong_AsLong(debug_build_py);
 741        }
 742        else {
 743            debug_build = Python2_PyInt_AsLong(debug_build_py);
 744        }
 745        if (debug_build == -1) {
 746            failwith("AsLong");
 747        }
 748    }
 749    tuple_empty = Python_PyTuple_New(0);
 750    CAMLreturn(Val_unit);
 751}
 752
 753struct PyObjectDebug {
 754    PyObject *_ob_next;           \
 755    PyObject *_ob_prev;
 756    PyObjectDescr descr;
 757};
 758
 759PyObjectDescr *pyobjectdescr(PyObject *obj) {
 760    if (debug_build) {
 761        return &((struct PyObjectDebug *) obj)->descr;
 762    }
 763    else {
 764        return (PyObjectDescr *) obj;
 765    }
 766}
 767
 768CAMLprim value
 769py_is_debug_build()
 770{
 771    CAMLparam0();
 772    CAMLreturn(Val_int(debug_build));
 773}
 774
 775CAMLprim value
 776py_finalize_library(value unit)
 777{
 778    CAMLparam1(unit);
 779    pyml_assert_initialized();
 780    Py_DECREF(tuple_empty);
 781    if (library != get_default_library()) {
 782        close_library(library);
 783    }
 784    version_major = 0;
 785    ucs = UCS_NONE;
 786    CAMLreturn(Val_unit);
 787}
 788
 789CAMLprim value
 790py_unsetenv(value name_ocaml)
 791{
 792    CAMLparam1(name_ocaml);
 793    char *name = String_val(name_ocaml);
 794    if (unsetenv(name) == -1) {
 795        failwith(strerror(errno));
 796    }
 797    CAMLreturn(Val_unit);
 798}
 799
 800CAMLprim value
 801py_get_UCS(value unit)
 802{
 803    CAMLparam1(unit);
 804    pyml_assert_initialized();
 805    CAMLreturn(Val_int(ucs));
 806}
 807
 808CAMLprim value
 809PyNull_wrapper(value unit)
 810{
 811    CAMLparam1(unit);
 812    CAMLreturn(Val_int(CODE_NULL));
 813}
 814
 815CAMLprim value
 816PyNone_wrapper(value unit)
 817{
 818    CAMLparam1(unit);
 819    CAMLreturn(Val_int(CODE_NONE));
 820}
 821
 822CAMLprim value
 823PyTrue_wrapper(value unit)
 824{
 825    CAMLparam1(unit);
 826    CAMLreturn(Val_int(CODE_TRUE));
 827}
 828
 829CAMLprim value
 830PyFalse_wrapper(value unit)
 831{
 832    CAMLparam1(unit);
 833    CAMLreturn(Val_int(CODE_FALSE));
 834}
 835
 836CAMLprim value
 837PyTuple_Empty_wrapper(value unit)
 838{
 839    CAMLparam1(unit);
 840    CAMLreturn(Val_int(CODE_TUPLE_EMPTY));
 841}
 842
 843enum pytype_labels {
 844    PyUnknown,
 845    Bool,
 846    Bytes,
 847    Callable,
 848    Capsule,
 849    Closure,
 850    Dict,
 851    Float,
 852    List,
 853    Int,
 854    Long,
 855    Module,
 856    NoneType,
 857    Null,
 858    Tuple,
 859    Type,
 860    Unicode,
 861    Iter
 862};
 863
 864CAMLprim value
 865pytype(value object_ocaml)
 866{
 867    CAMLparam1(object_ocaml);
 868    pyml_assert_initialized();
 869    PyObject *object = pyml_unwrap(object_ocaml);
 870    if (!object) {
 871        CAMLreturn(Val_int(Null));
 872    }
 873    PyObject *ob_type = pyobjectdescr(object)->ob_type;
 874    struct _typeobject *typeobj = (struct _typeobject *) pyobjectdescr(ob_type);
 875    unsigned long flags = typeobj->tp_flags;
 876    int result;
 877    if (ob_type == Python_PyBool_Type) {
 878        result = Bool;
 879    }
 880    else if (flags & Py_TPFLAGS_BYTES_SUBCLASS) {
 881        result = Bytes;
 882    }
 883    else if (Python_PyCallable_Check(object)) {
 884        result = Callable;
 885    }
 886    else if (Python27_PyCapsule_IsValid
 887        && Python27_PyCapsule_IsValid(object, "ocaml-capsule")) {
 888        result = Capsule;
 889    }
 890    else if (Python27_PyCapsule_IsValid
 891        && Python27_PyCapsule_IsValid(object, "ocaml-closure")) {
 892        result = Closure;
 893    }
 894    else if (flags & Py_TPFLAGS_DICT_SUBCLASS) {
 895        result = Dict;
 896    }
 897    else if (ob_type == Python_PyFloat_Type ||
 898        Python_PyType_IsSubtype(ob_type, Python_PyFloat_Type)) {
 899        result = Float;
 900    }
 901    else if (flags & Py_TPFLAGS_LIST_SUBCLASS) {
 902        result = List;
 903    }
 904    else if (flags & Py_TPFLAGS_INT_SUBCLASS) {
 905        result = Int;
 906    }
 907    else if (flags & Py_TPFLAGS_LONG_SUBCLASS) {
 908        result = Long;
 909    }
 910    else if (ob_type == Python_PyModule_Type ||
 911        Python_PyType_IsSubtype(ob_type, Python_PyModule_Type)) {
 912        result = Module;
 913    }
 914    else if (object == Python__Py_NoneStruct) {
 915        result = NoneType;
 916    }
 917    else if (flags & Py_TPFLAGS_TUPLE_SUBCLASS) {
 918        result = Tuple;
 919    }
 920    else if (flags & Py_TPFLAGS_TYPE_SUBCLASS) {
 921        result = Type;
 922    }
 923    else if (flags & Py_TPFLAGS_UNICODE_SUBCLASS) {
 924        result = Unicode;
 925    }
 926    else if (typeobj->tp_iternext != NULL &&
 927        typeobj->tp_iternext != &Python27__PyObject_NextNotImplemented) {
 928        result = Iter;
 929    }
 930    else {
 931        result = PyUnknown;
 932    }
 933    CAMLreturn(Val_int(result));
 934}
 935
 936CAMLprim value
 937PyObject_CallFunctionObjArgs_wrapper(
 938    value callable_ocaml, value arguments_ocaml)
 939{
 940    CAMLparam2(callable_ocaml, arguments_ocaml);
 941    pyml_assert_initialized();
 942    PyObject *callable = pyml_unwrap(callable_ocaml);
 943    PyObject *result;
 944    mlsize_t argument_count = Wosize_val(arguments_ocaml);
 945    switch (argument_count) {
 946    case 0:
 947        result = Python_PyObject_CallFunctionObjArgs(callable, NULL);
 948        break;
 949    case 1:
 950        result = Python_PyObject_CallFunctionObjArgs
 951            (callable,
 952             pyml_unwrap(Field(arguments_ocaml, 0)),
 953             NULL);
 954        break;
 955    case 2:
 956        result = Python_PyObject_CallFunctionObjArgs
 957            (callable,
 958             pyml_unwrap(Field(arguments_ocaml, 0)),
 959             pyml_unwrap(Field(arguments_ocaml, 1)),
 960             NULL);
 961        break;
 962    case 3:
 963        result = Python_PyObject_CallFunctionObjArgs
 964            (callable,
 965             pyml_unwrap(Field(arguments_ocaml, 0)),
 966             pyml_unwrap(Field(arguments_ocaml, 1)),
 967             pyml_unwrap(Field(arguments_ocaml, 2)),
 968             NULL);
 969        break;
 970    case 4:
 971        result = Python_PyObject_CallFunctionObjArgs
 972            (callable,
 973             pyml_unwrap(Field(arguments_ocaml, 0)),
 974             pyml_unwrap(Field(arguments_ocaml, 1)),
 975             pyml_unwrap(Field(arguments_ocaml, 2)),
 976             pyml_unwrap(Field(arguments_ocaml, 3)),
 977             NULL);
 978        break;
 979    case 5:
 980        result = Python_PyObject_CallFunctionObjArgs
 981            (callable,
 982             pyml_unwrap(Field(arguments_ocaml, 0)),
 983             pyml_unwrap(Field(arguments_ocaml, 1)),
 984             pyml_unwrap(Field(arguments_ocaml, 2)),
 985             pyml_unwrap(Field(arguments_ocaml, 3)),
 986             pyml_unwrap(Field(arguments_ocaml, 4)),
 987             NULL);
 988        break;
 989    default:
 990        fprintf(stderr,
 991                "PyObject_CallFunctionObjArgs_wrapper not implemented for more "
 992                "than 5 arguments\n");
 993        exit(EXIT_FAILURE);
 994    }
 995
 996    CAMLreturn(pyml_wrap(result, true));
 997}
 998
 999CAMLprim value
1000PyObject_CallMethodObjArgs_wrapper(
1001    value object_ocaml, value name_ocaml, value arguments_ocaml)
1002{
1003    CAMLparam3(object_ocaml, name_ocaml, arguments_ocaml);
1004    pyml_assert_initialized();
1005    PyObject *object = pyml_unwrap(object_ocaml);
1006    PyObject *name = pyml_unwrap(name_ocaml);
1007    PyObject *result;
1008    mlsize_t argument_count = Wosize_val(arguments_ocaml);
1009    switch (argument_count) {
1010    case 0:
1011        result = Python_PyObject_CallMethodObjArgs(object, name);
1012        break;
1013    case 1:
1014        result = Python_PyObject_CallMethodObjArgs
1015            (object, name,
1016             pyml_unwrap(Field(arguments_ocaml, 0)),
1017             NULL);
1018        break;
1019    case 2:
1020        result = Python_PyObject_CallMethodObjArgs
1021            (object, name,
1022             pyml_unwrap(Field(arguments_ocaml, 0)),
1023             pyml_unwrap(Field(arguments_ocaml, 1)),
1024             NULL);
1025        break;
1026    case 3:
1027        result = Python_PyObject_CallMethodObjArgs
1028            (object, name,
1029             pyml_unwrap(Field(arguments_ocaml, 0)),
1030             pyml_unwrap(Field(arguments_ocaml, 1)),
1031             pyml_unwrap(Field(arguments_ocaml, 2)),
1032             NULL);
1033        break;
1034    case 4:
1035        result = Python_PyObject_CallMethodObjArgs
1036            (object, name,
1037             pyml_unwrap(Field(arguments_ocaml, 0)),
1038             pyml_unwrap(Field(arguments_ocaml, 1)),
1039             pyml_unwrap(Field(arguments_ocaml, 2)),
1040             pyml_unwrap(Field(arguments_ocaml, 3)),
1041             NULL);
1042        break;
1043    case 5:
1044        result = Python_PyObject_CallMethodObjArgs
1045            (object, name,
1046             pyml_unwrap(Field(arguments_ocaml, 0)),
1047             pyml_unwrap(Field(arguments_ocaml, 1)),
1048             pyml_unwrap(Field(arguments_ocaml, 2)),
1049             pyml_unwrap(Field(arguments_ocaml, 3)),
1050             pyml_unwrap(Field(arguments_ocaml, 4)),
1051             NULL);
1052        break;
1053    default:
1054        fprintf(stderr,
1055                "PyObject_CallMethodObjArgs_wrapper not implemented for more "
1056                "than 5 arguments\n");
1057        exit(EXIT_FAILURE);
1058    }
1059
1060    CAMLreturn(pyml_wrap(result, true));
1061}
1062
1063CAMLprim value
1064pyml_wrap_value(value v)
1065{
1066    CAMLparam1(v);
1067    pyml_assert_initialized();
1068    PyObject *result = camlwrap_capsule(v, NULL, 0);
1069    CAMLreturn(pyml_wrap(result, true));
1070}
1071
1072CAMLprim value
1073pyml_unwrap_value(value x_ocaml)
1074{
1075    CAMLparam1(x_ocaml);
1076    CAMLlocal1(v);
1077    pyml_assert_initialized();
1078    PyObject *x = pyml_unwrap(x_ocaml);
1079    void *p = unwrap_capsule(x, "ocaml-capsule");
1080    if (!p) {
1081        fprintf(stderr, "pyml_unwrap_value: type mismatch");
1082        exit(EXIT_FAILURE);
1083    }
1084    v = *(value *) p;
1085    CAMLreturn(v);
1086}
1087
1088CAMLprim value
1089PyErr_Fetch_wrapper(value unit)
1090{
1091    CAMLparam1(unit);
1092    CAMLlocal1(result);
1093    pyml_assert_initialized();
1094    PyObject *excType, *excValue, *excTraceback;
1095    Python_PyErr_Fetch(&excType, &excValue, &excTraceback);
1096    Python_PyErr_NormalizeException(&excType, &excValue, &excTraceback);
1097    result = caml_alloc_tuple(3);
1098    Store_field(result, 0, pyml_wrap(excType, false));
1099    Store_field(result, 1, pyml_wrap(excValue, false));
1100    Store_field(result, 2, pyml_wrap(excTraceback, false));
1101    CAMLreturn(result);
1102}
1103
1104CAMLprim value
1105pyml_wrap_string_option(char *s)
1106{
1107    CAMLparam0();
1108    CAMLlocal1(result);
1109    if (!s) {
1110        CAMLreturn(Val_int(0));
1111    }
1112    result = caml_alloc_tuple(1);
1113    Store_field(result, 0, caml_copy_string(s));
1114    CAMLreturn(result);
1115}
1116
1117CAMLprim value
1118pyrefcount(value pyobj)
1119{
1120    CAMLparam1(pyobj);
1121    PyObject *obj = pyml_unwrap(pyobj);
1122    CAMLreturn(Val_int(pyobjectdescr(obj)->ob_refcnt));
1123}
1124
1125static value
1126pyml_wrap_wide_string(wchar_t *ws)
1127{
1128    CAMLparam0();
1129    CAMLlocal1(result);
1130    size_t n = wcstombs(NULL, ws, 0);
1131    if (n == (size_t) -1) {
1132        fprintf(stderr, "pyml_wrap_wide_string failure.\n");
1133        exit(EXIT_FAILURE);
1134    }
1135    char *s = xmalloc((n + 1) * sizeof (char));
1136    wcstombs(s, ws, n);
1137    result = caml_copy_string(s);
1138    free(s);
1139    CAMLreturn(result);
1140}
1141
1142static wchar_t *
1143pyml_unwrap_wide_string(value string_ocaml)
1144{
1145    CAMLparam1(string_ocaml);
1146    char *s = String_val(string_ocaml);
1147    size_t n = mbstowcs(NULL, s, 0);
1148    if (n == (size_t) -1) {
1149        fprintf(stderr, "pyml_unwrap_wide_string failure.\n");
1150        exit(EXIT_FAILURE);
1151    }
1152    wchar_t *ws = xmalloc((n + 1) * sizeof (wchar_t));
1153    mbstowcs(ws, s, n);
1154    CAMLreturnT(wchar_t *, ws);
1155}
1156
1157static int16_t *
1158pyml_unwrap_ucs2(value array_ocaml)
1159{
1160    CAMLparam1(array_ocaml);
1161    mlsize_t len = Wosize_val(array_ocaml);
1162    int16_t *result = xmalloc(len * sizeof(int16_t));
1163    size_t i;
1164    for (i = 0; i < len; i++) {
1165        result[i] = Field(array_ocaml, i);
1166    }
1167    CAMLreturnT(int16_t *, result);
1168}
1169
1170static int32_t *
1171pyml_unwrap_ucs4(value array_ocaml)
1172{
1173    CAMLparam1(array_ocaml);
1174    mlsize_t len = Wosize_val(array_ocaml);
1175    int32_t *result = xmalloc(len * sizeof(int32_t));
1176    size_t i;
1177    for (i = 0; i < len; i++) {
1178        result[i] = Field(array_ocaml, i);
1179    }
1180    CAMLreturnT(int32_t *, result);
1181}
1182
1183static value
1184pyml_wrap_ucs2_option(int16_t *buffer)
1185{
1186    CAMLparam0();
1187    CAMLlocal2(result, array);
1188    mlsize_t len;
1189    if (buffer == NULL) {
1190        CAMLreturn(Val_int(0));
1191    }
1192    len = 0;
1193    while (buffer[len]) {
1194        len++;
1195    }
1196    array = caml_alloc_tuple(len);
1197    size_t i;
1198    for (i = 0; i < len; i++) {
1199        Store_field(array, i, buffer[i]);
1200    }
1201    result = caml_alloc_tuple(1);
1202    Store_field(result, 0, array);
1203    CAMLreturn(result);
1204}
1205
1206static value
1207pyml_wrap_ucs4_option_and_free(int32_t *buffer, bool free)
1208{
1209    CAMLparam0();
1210    CAMLlocal2(result, array);
1211    mlsize_t len;
1212    if (buffer == NULL) {
1213        CAMLreturn(Val_int(0));
1214    }
1215    len = 0;
1216    while (buffer[len]) {
1217        len++;
1218    }
1219    array = caml_alloc_tuple(len);
1220    size_t i;
1221    for (i = 0; i < len; i++) {
1222        Store_field(array, i, buffer[i]);
1223    }
1224    result = caml_alloc_tuple(1);
1225    Store_field(result, 0, array);
1226    if (free) {
1227        Python_PyMem_Free(buffer);
1228    }
1229    CAMLreturn(result);
1230}
1231
1232#define StringAndSize_wrapper(func, byte_type)                                 \
1233    CAMLprim value                                                             \
1234    func##_wrapper(value arg_ocaml)                                            \
1235    {                                                                          \
1236        CAMLparam1(arg_ocaml);                                                 \
1237        CAMLlocal2(result, string);                                            \
1238        PyObject *arg = pyml_unwrap(arg_ocaml);                                \
1239        byte_type *buffer;                                                     \
1240        Py_ssize_t length;                                                     \
1241        int return_value;                                                      \
1242        return_value = Python_##func(arg, &buffer, &length);                   \
1243        if (return_value == -1) {                                              \
1244            CAMLreturn(Val_int(0));                                            \
1245        }                                                                      \
1246        string = caml_alloc_string(length);                                    \
1247        memcpy(String_val(string), buffer, length);                            \
1248        result = caml_alloc_tuple(1);                                          \
1249        Store_field(result, 0, string);                                        \
1250        CAMLreturn(result);                                                    \
1251    }
1252
1253StringAndSize_wrapper(PyString_AsStringAndSize, char);
1254StringAndSize_wrapper(PyObject_AsCharBuffer, const char);
1255StringAndSize_wrapper(PyObject_AsReadBuffer, const void);
1256StringAndSize_wrapper(PyObject_AsWriteBuffer, void);
1257
1258static FILE *
1259open_file(value file, const char *mode)
1260{
1261    CAMLparam1(file);
1262    FILE *result;
1263    if (Tag_val(file) == 0) {
1264        char *filename = String_val(Field(file, 0));
1265        if (version_major >= 3) {
1266            result = Python__Py_fopen(filename, mode);
1267        }
1268        else {
1269            result = fopen(filename, mode);
1270        }
1271    }
1272    else {
1273        result = file_of_file_descr(Field(file, 0), mode);
1274    }
1275    CAMLreturnT(FILE *, result);
1276}
1277
1278static void
1279close_file(value file, FILE *file_struct)
1280{
1281    CAMLparam1(file);
1282    if (Tag_val(file) == 0) {
1283        if (version_major >= 3) {
1284            /* No _Py_fclose :( */
1285        }
1286        else {
1287            fclose(file_struct);
1288        }
1289    }
1290    else if (Tag_val(file) == 1) {
1291        fclose(file_struct);
1292    }
1293    CAMLreturn0;
1294}
1295
1296/* Numpy */
1297
1298void **
1299pyml_get_pyarray_api(PyObject *c_api)
1300{
1301    if (version_major >= 3) {
1302        return (void **)Python27_PyCapsule_GetPointer(c_api, NULL);
1303    }
1304    else {
1305        return (void **)Python2_PyCObject_AsVoidPtr(c_api);
1306    }
1307}
1308
1309CAMLprim value
1310get_pyarray_type(value numpy_api_ocaml)
1311{
1312    CAMLparam1(numpy_api_ocaml);
1313    PyObject *c_api = pyml_unwrap(numpy_api_ocaml);
1314    void **PyArray_API = pyml_get_pyarray_api(c_api);
1315    PyObject *result = PyArray_API[2];
1316    CAMLreturn(pyml_wrap(result, true));
1317}
1318
1319CAMLprim value
1320pyarray_of_floatarray_wrapper(
1321    value numpy_api_ocaml, value array_type_ocaml, value array_ocaml)
1322{
1323    CAMLparam3(numpy_api_ocaml, array_type_ocaml, array_ocaml);
1324    pyml_assert_initialized();
1325    PyObject *c_api = pyml_unwrap(numpy_api_ocaml);
1326    void **PyArray_API = pyml_get_pyarray_api(c_api);
1327    PyObject *(*PyArray_New)
1328        (PyTypeObject *, int, npy_intp *, int, npy_intp *, void *, int, int,
1329         PyObject *) = PyArray_API[93];
1330    npy_intp length = Wosize_val(array_ocaml);
1331    void *data = (double *) array_ocaml;
1332    PyTypeObject (*PyArray_SubType) =
1333        (PyTypeObject *) pyml_unwrap(array_type_ocaml);
1334    PyObject *result = PyArray_New(
1335        PyArray_SubType, 1, &length, NPY_DOUBLE, NULL, data, 0,
1336        NPY_ARRAY_CARRAY, NULL);
1337    CAMLreturn(pyml_wrap(result, true));
1338}
1339
1340CAMLprim value
1341PyLong_FromString_wrapper(value str_ocaml, value base_ocaml)
1342{
1343    CAMLparam2(str_ocaml, base_ocaml);
1344    CAMLlocal1(result);
1345    pyml_assert_initialized();
1346    char *str = String_val(str_ocaml);
1347    char *pend;
1348    int base = Int_val(base_ocaml);
1349    PyObject *l = Python_PyLong_FromString(str, &pend, base);
1350    ssize_t len = pend - str;
1351    result = caml_alloc_tuple(2);
1352    Store_field(result, 0, pyml_wrap(l, true));
1353    Store_field(result, 1, Val_int(len));
1354    CAMLreturn(result);
1355}
1356
1357CAMLprim value
1358Python27_PyCapsule_IsValid_wrapper(value arg0_ocaml, value arg1_ocaml)
1359{
1360    CAMLparam2(arg0_ocaml, arg1_ocaml);
1361
1362    pyml_assert_initialized();
1363    if (!Python27_PyCapsule_IsValid) {
1364        failwith("PyCapsule_IsValid is only available in Python >2.7");
1365    }
1366    PyObject *arg0 = pyml_unwrap(arg0_ocaml);
1367    char *arg1 = String_val(arg1_ocaml);
1368    int result = Python27_PyCapsule_IsValid(arg0, arg1);
1369    CAMLreturn(Val_int(result));
1370}
1371
1372#include "pyml_wrappers.inc"