int handle_vars(struct JsonlangVm *vm, PyObject *map, int code, int tla) { if (map == NULL) return 1; PyObject *key, *val; Py_ssize_t pos = 0; while (PyDict_Next(map, &pos, &key, &val)) { const char *key_ = PyString_AsString(key); if (key_ == NULL) { jsonlang_destroy(vm); return 0; } const char *val_ = PyString_AsString(val); if (val_ == NULL) { jsonlang_destroy(vm); return 0; } if (!tla && !code) { jsonlang_ext_var(vm, key_, val_); } else if (!tla && code) { jsonlang_ext_code(vm, key_, val_); } else if (tla && !code) { jsonlang_tla_var(vm, key_, val_); } else { jsonlang_tla_code(vm, key_, val_); } } return 1; }
static PyObject* evaluate_snippet(PyObject* self, PyObject* args, PyObject *keywds) { const char *filename, *src; char *out; unsigned max_stack = 500, gc_min_objects = 1000, max_trace = 20; double gc_growth_trigger = 2; int debug_ast = 0, error; PyObject *ext_vars = NULL; struct jsonlangVm *vm; static char *kwlist[] = {"filename", "src", "max_stack", "gc_min_objects", "gc_growth_trigger", "ext_vars", "debug_ast", "max_trace", NULL}; (void) self; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|IIdOiI", kwlist, &filename, &src, &max_stack, &gc_min_objects, &gc_growth_trigger, &ext_vars, &debug_ast, &max_trace)) { return NULL; } vm = jsonlang_make(); jsonlang_max_stack(vm, max_stack); jsonlang_gc_min_objects(vm, gc_min_objects); jsonlang_max_trace(vm, max_trace); jsonlang_gc_growth_trigger(vm, gc_growth_trigger); jsonlang_debug_ast(vm, debug_ast); if (ext_vars != NULL) { PyObject *key, *val; Py_ssize_t pos = 0; while (PyDict_Next(ext_vars, &pos, &key, &val)) { const char *key_ = PyString_AsString(key); if (key_ == NULL) { jsonlang_destroy(vm); return NULL; } const char *val_ = PyString_AsString(val); if (val_ == NULL) { jsonlang_destroy(vm); return NULL; } jsonlang_ext_var(vm, key_, val_); } } out = jsonlang_evaluate_snippet(vm, filename, src, &error); if (error) { PyErr_SetString(PyExc_RuntimeError, out); jsonlang_realloc(vm, out, 0); jsonlang_destroy(vm); return NULL; } else { PyObject *ret = PyString_FromString(out); jsonlang_realloc(vm, out, 0); jsonlang_destroy(vm); return ret; } }
static PyObject *handle_result(struct JsonlangVm *vm, char *out, int error) { if (error) { PyErr_SetString(PyExc_RuntimeError, out); jsonlang_realloc(vm, out, 0); jsonlang_destroy(vm); return NULL; } else { PyObject *ret = PyString_FromString(out); jsonlang_realloc(vm, out, 0); jsonlang_destroy(vm); return ret; } }
int handle_import_callback(struct ImportCtx *ctx, PyObject *import_callback) { if (import_callback == NULL) return 1; if (!PyCallable_Check(import_callback)) { jsonlang_destroy(ctx->vm); PyErr_SetString(PyExc_TypeError, "import_callback must be callable"); return 0; } jsonlang_import_callback(ctx->vm, cpython_import_callback, ctx); return 1; }
/** Register native callbacks with Jsonlang VM. * * Example native_callbacks = { 'name': (('p1', 'p2', 'p3'), func) } * * May set *ctxs, in which case it should be free()'d by caller. * * \returns 1 on success, 0 with exception set upon failure. */ static int handle_native_callbacks(struct JsonlangVm *vm, PyObject *native_callbacks, struct NativeCtx **ctxs) { size_t num_natives = 0; PyObject *key, *val; Py_ssize_t pos = 0; if (native_callbacks == NULL) return 1; /* Verify the input before we allocate memory, throw all errors at this point. * Also, count the callbacks to see how much memory we need. */ while (PyDict_Next(native_callbacks, &pos, &key, &val)) { Py_ssize_t i; Py_ssize_t num_params; PyObject *params; const char *key_ = PyString_AsString(key); if (key_ == NULL) { PyErr_SetString(PyExc_TypeError, "native callback dict keys must be string"); goto bad; } if (!PyTuple_Check(val)) { PyErr_SetString(PyExc_TypeError, "native callback dict values must be tuples"); goto bad; } else if (PyTuple_Size(val) != 2) { PyErr_SetString(PyExc_TypeError, "native callback tuples must have size 2"); goto bad; } params = PyTuple_GetItem(val, 0); if (!PyTuple_Check(params)) { PyErr_SetString(PyExc_TypeError, "native callback params must be a tuple"); goto bad; } /* Check the params are all strings */ num_params = PyTuple_Size(params); for (i = 0; i < num_params ; ++i) { PyObject *param = PyTuple_GetItem(params, 0); if (!PyString_Check(param)) { PyErr_SetString(PyExc_TypeError, "native callback param must be string"); goto bad; } } if (!PyCallable_Check(PyTuple_GetItem(val, 1))) { PyErr_SetString(PyExc_TypeError, "native callback must be callable"); goto bad; } num_natives++; continue; bad: jsonlang_destroy(vm); return 0; } if (num_natives == 0) { return 1; } *ctxs = malloc(sizeof(struct NativeCtx) * num_natives); /* Re-use num_natives but just as a counter this time. */ num_natives = 0; pos = 0; while (PyDict_Next(native_callbacks, &pos, &key, &val)) { Py_ssize_t i; Py_ssize_t num_params; PyObject *params; const char *key_ = PyString_AsString(key); params = PyTuple_GetItem(val, 0); num_params = PyTuple_Size(params); /* Include space for terminating NULL. */ const char **params_c = malloc(sizeof(const char*) * (num_params + 1)); for (i = 0; i < num_params ; ++i) { params_c[i] = PyString_AsString(PyTuple_GetItem(params, i)); } params_c[num_params] = NULL; (*ctxs)[num_natives].vm = vm; (*ctxs)[num_natives].callback = PyTuple_GetItem(val, 1); (*ctxs)[num_natives].argc = num_params; jsonlang_native_callback(vm, key_, cpython_native_callback, &(*ctxs)[num_natives], params_c); free(params_c); num_natives++; } return 1; }