123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825 |
- #include "config.h"
- #ifdef HAVE_PYTHON
- # include <Python.h>
- # if PY_MAJOR_VERSION >= 3
- # include <pthread.h>
- # endif /* PY_MAJOR_VERSION >= 3 */
- #endif /* HAVE_PYTHON */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <strings.h>
- #include <alloca.h>
- #include "pci.h"
- #include "debug.h"
- #include "pcilib.h"
- #include "py.h"
- #include "error.h"
- #ifdef HAVE_PYTHON
- # define PCILIB_PYTHON_WRAPPER "pcipywrap"
- typedef struct pcilib_script_s pcilib_script_t;
- struct pcilib_script_s {
- const char *name; /**< Script name */
- PyObject *module; /**< PyModule object, contains script enviroment */
- UT_hash_handle hh; /**< hash */
- };
- struct pcilib_py_s {
- int finalyze; /**< Indicates, that we are initialized from wrapper and should not destroy Python resources in destructor */
- PyObject *main_module; /**< Main interpreter */
- PyObject *pywrap_module; /**< Pcilib python wrapper */
- PyObject *threading_module; /**< Threading module */
- PyObject *global_dict; /**< Dictionary of main interpreter */
- PyObject *pcilib_pywrap; /**< pcilib wrapper context */
- pcilib_script_t *script_hash; /**< Hash with loaded scripts */
-
- # if PY_MAJOR_VERSION >= 3
- int status; /**< Indicates if python was initialized successfuly (0) or error have occured */
- pthread_t pth; /**< Helper thread for Python initialization */
- pthread_cond_t cond; /**< Condition informing about initialization success and request for clean-up */
- pthread_mutex_t lock; /**< Condition lock */
- // PyInterpreterState *istate;
- // PyThreadState *tstate;
- # endif /* PY_MAJOR_VERSION > 3 */
- };
- #endif /* HAVE_PYTHON */
- void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flags, pcilib_log_priority_t prio, const char *msg, ...) {
- va_list va;
- const char *type = NULL;
- const char *val = NULL;
- #ifdef HAVE_PYTHON
- PyGILState_STATE gstate;
- PyObject *pytype = NULL;
- PyObject *pyval = NULL;
- PyObject *pystr = NULL;
- PyObject *pytraceback = NULL;
- gstate = PyGILState_Ensure();
- if (PyErr_Occurred()) {
- PyErr_Fetch(&pytype, &pyval, &pytraceback);
- PyErr_NormalizeException(&pytype, &pyval, &pytraceback);
- if (pyval) pystr = PyObject_Str(pyval);
- # if PY_MAJOR_VERSION >= 3
- if (pytype) {
- if (PyUnicode_Check(pytype))
- type = PyUnicode_AsUTF8(pytype);
- else
- type = PyExceptionClass_Name(pytype);
- }
- if (pystr) {
- val = PyUnicode_AsUTF8(pystr);
- }
- # else /* PY_MAJOR_VERSION >= 3 */
- if (pytype) {
- if (PyString_Check(pytype))
- type = PyString_AsString(pytype);
- else
- type = PyExceptionClass_Name(pytype);
- }
- if (pystr) {
- val = PyString_AsString(pystr);
- }
- # endif /*PY_MAJOR_VERSION >= 3*/
- }
- PyGILState_Release(gstate);
- #endif /* HAVE_PYTHON */
- va_start(va, msg);
- if (type) {
- char *str;
- size_t len = 32;
- if (msg) len += strlen(msg);
- if (type) len += strlen(type);
- if (val) len += strlen(val);
-
- str = alloca(len * sizeof(char));
- if (str) {
- if (msg&&val)
- sprintf(str, "%s <%s: %s>", msg, type, val);
- else if (msg)
- sprintf(str, "%s <%s>", msg, type);
- else if (val)
- sprintf(str, "Python error %s: %s", type, val);
- else
- sprintf(str, "Python error %s", type);
-
- pcilib_log_vmessage(file, line, flags, prio, str, va);
- }
- } else {
- pcilib_log_vmessage(file, line, flags, prio, msg, va);
- }
- va_end(va);
- #ifdef HAVE_PYTHON
- if (pystr) Py_DECREF(pystr);
- if (pytype) Py_DECREF(pytype);
- if (pyval) Py_DECREF(pyval);
- if (pytraceback) Py_DECREF(pytraceback);
- #endif /* HAVE_PYTHON */
- }
- #ifdef HAVE_PYTHON
- static int pcilib_py_load_default_modules(pcilib_t *ctx) {
- PyGILState_STATE gstate = PyGILState_Ensure();
- ctx->py->main_module = PyImport_AddModule("__parser__");
- if (!ctx->py->main_module) {
- PyGILState_Release(gstate);
- pcilib_python_warning("Error importing python parser");
- return PCILIB_ERROR_FAILED;
- }
- ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module);
- if (!ctx->py->global_dict) {
- PyGILState_Release(gstate);
- pcilib_python_warning("Error locating global python dictionary");
- return PCILIB_ERROR_FAILED;
- }
- ctx->py->pywrap_module = PyImport_ImportModule(PCILIB_PYTHON_WRAPPER);
- if (!ctx->py->pywrap_module) {
- PyGILState_Release(gstate);
- pcilib_python_warning("Error importing pcilib python wrapper");
- return PCILIB_ERROR_FAILED;
- }
- /**
- * We need to load threading module here, otherwise if any of the scripts
- * will use threading, on cleanup Python3 will complain:
- * Exception KeyError: KeyError(140702199305984,) in <module 'threading' from '/usr/lib64/python3.3/threading.py'> ignored
- * The idea to load threading module is inspired by
- * http://stackoverflow.com/questions/8774958/keyerror-in-module-threading-after-a-successful-py-test-run
- */
- ctx->py->threading_module = PyImport_ImportModule("threading");
- if (!ctx->py->threading_module) {
- PyGILState_Release(gstate);
- pcilib_python_warning("Error importing threading python module");
- return PCILIB_ERROR_FAILED;
- }
-
- PyObject *mod_name = PyUnicode_FromString(PCILIB_PYTHON_WRAPPER);
- PyObject *pyctx = PyCapsule_New(ctx, "pcilib", NULL);
- ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(ctx->py->pywrap_module, mod_name, pyctx, NULL);
- Py_XDECREF(pyctx);
- Py_XDECREF(mod_name);
-
- if (!ctx->py->pcilib_pywrap) {
- PyGILState_Release(gstate);
- pcilib_python_warning("Error initializing python wrapper");
- return PCILIB_ERROR_FAILED;
- }
- PyGILState_Release(gstate);
- return 0;
- }
- static void pcilib_py_clean_default_modules(pcilib_t *ctx) {
- PyGILState_STATE gstate;
- gstate = PyGILState_Ensure();
- if (ctx->py->pcilib_pywrap) Py_DECREF(ctx->py->pcilib_pywrap);
- if (ctx->py->threading_module) Py_DECREF(ctx->py->threading_module);
- if (ctx->py->pywrap_module) Py_DECREF(ctx->py->pywrap_module);
- // Crashes Python2
- // if (ctx->py->main_module) Py_DECREF(ctx->py->main_module);
- PyGILState_Release(gstate);
- }
- # if PY_MAJOR_VERSION >= 3
- /**
- * Python3 specially treats the main thread intializing Python. It crashes if
- * the Lock is released and any Python code is executed under the GIL compaling
- * that GIL is not locked. Python3 assumes that the main thread most of the time
- * holds the Lock, only shortly giving it away to other threads and re-obtaining
- * it hereafter. This is not possible to do with GILs, but instead (probably)
- * PyEval_{Save,Restore}Thread() should be used. On other hand, the other threads
- * are working fine with GILs. This makes things complicated as we need to know
- * if we are running in main thread or not.
- * To simplify matters, during initalization we start a new thread which will
- * performa actual initialization of Python and, hence, act as main thread.
- * We only intialize here. No python code is executed afterwards. So we don't
- * need to care about special locking mechanisms in main thread. Instead all
- * our user threads can use GILs normally.
- * See more details here:
- * http://stackoverflow.com/questions/24499393/cpython-locking-the-gil-in-the-main-thread
- * http://stackoverflow.com/questions/15470367/pyeval-initthreads-in-python-3-how-when-to-call-it-the-saga-continues-ad-naus
- */
- static void *pcilib_py_run_init_thread(void *arg) {
- PyThreadState *state;
- pcilib_t *ctx = (pcilib_t*)arg;
- pcilib_py_t *py = ctx->py;
- Py_Initialize();
- PyEval_InitThreads();
- // state = PyThreadState_Get();
- // py->istate = state->interp;
- py->status = pcilib_py_load_default_modules(ctx);
- state = PyEval_SaveThread();
- // Ensure that main thread waiting for our signal
- pthread_mutex_lock(&(py->lock));
- // Inform the parent thread that initialization is finished
- pthread_cond_signal(&(py->cond));
- // Wait untill cleanup is requested
- pthread_cond_wait(&(py->cond), &(py->lock));
- pthread_mutex_unlock(&(py->lock));
- PyEval_RestoreThread(state);
- pcilib_py_clean_default_modules(ctx);
- Py_Finalize();
- return NULL;
- }
- # endif /* PY_MAJOR_VERSION < 3 */
- #endif /* HAVE_PYTHON */
- int pcilib_init_py(pcilib_t *ctx) {
- #ifdef HAVE_PYTHON
- int err = 0;
- ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t));
- if (!ctx->py) return PCILIB_ERROR_MEMORY;
- memset(ctx->py, 0, sizeof(pcilib_py_t));
- if (!Py_IsInitialized()) {
- # if PY_MAJOR_VERSION < 3
- Py_Initialize();
- // Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads
- PyEval_InitThreads();
- PyEval_ReleaseLock();
- err = pcilib_py_load_default_modules(ctx);
- # else /* PY_MAJOR_VERSION < 3 */
- int err = pthread_mutex_init(&(ctx->py->lock), NULL);
- if (err) return PCILIB_ERROR_FAILED;
- err = pthread_cond_init(&(ctx->py->cond), NULL);
- if (err) {
- pthread_mutex_destroy(&(ctx->py->lock));
- return PCILIB_ERROR_FAILED;
- }
- err = pthread_mutex_lock(&(ctx->py->lock));
- if (err) {
- pthread_cond_destroy(&(ctx->py->cond));
- pthread_mutex_destroy(&(ctx->py->lock));
- return PCILIB_ERROR_FAILED;
- }
- // Create initalizer thread and wait until it releases the Lock
- err = pthread_create(&(ctx->py->pth), NULL, pcilib_py_run_init_thread, (void*)ctx);
- if (err) {
- pthread_mutex_unlock(&(ctx->py->lock));
- pthread_cond_destroy(&(ctx->py->cond));
- pthread_mutex_destroy(&(ctx->py->lock));
- return PCILIB_ERROR_FAILED;
- }
- // Wait until initialized and keep the lock afterwards until free executed
- pthread_cond_wait(&(ctx->py->cond), &(ctx->py->lock));
- err = ctx->py->status;
- // ctx->py->tstate = PyThreadState_New(ctx->py->istate);
- # endif /* PY_MAJOR_VERSION < 3 */
- ctx->py->finalyze = 1;
- } else {
- err = pcilib_py_load_default_modules(ctx);
- }
- if (err) {
- pcilib_free_py(ctx);
- return err;
- }
- #endif /* HAVE_PYTHON */
- return 0;
- }
- void pcilib_free_py(pcilib_t *ctx) {
- #ifdef HAVE_PYTHON
- if (ctx->py) {
- PyGILState_STATE gstate;
- gstate = PyGILState_Ensure();
- if (ctx->py->script_hash) {
- pcilib_script_t *script, *script_tmp;
- HASH_ITER(hh, ctx->py->script_hash, script, script_tmp) {
- Py_DECREF(script->module);
- HASH_DEL(ctx->py->script_hash, script);
- free(script);
- }
- ctx->py->script_hash = NULL;
- }
- PyGILState_Release(gstate);
- #if PY_MAJOR_VERSION < 3
- pcilib_py_clean_default_modules(ctx);
- #endif /* PY_MAJOR_VERSION < 3 */
- if (ctx->py->finalyze) {
- #if PY_MAJOR_VERSION < 3
- Py_Finalize();
- #else /* PY_MAJOR_VERSION < 3 */
- // PyThreadState_Delete(ctx->py->tstate);
- // singal python init thread to stop and wait it to finish
- pthread_cond_signal(&(ctx->py->cond));
- pthread_mutex_unlock(&(ctx->py->lock));
- pthread_join(ctx->py->pth, NULL);
- // destroy synchronization primitives
- pthread_cond_destroy(&(ctx->py->cond));
- pthread_mutex_destroy(&(ctx->py->lock));
- #endif /* PY_MAJOR_VERSION < 3 */
- }
- free(ctx->py);
- ctx->py = NULL;
- }
- #endif /* HAVE_PYTHON */
- }
- int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) {
- #ifdef HAVE_PYTHON
- int err = 0;
- PyObject *pypath, *pynewdir;
- PyObject *pydict, *pystr, *pyret = NULL;
- char *script_dir;
- if (!ctx->py) return 0;
- const char *model_dir = getenv("PCILIB_MODEL_DIR");
- if (!model_dir) model_dir = PCILIB_MODEL_DIR;
- if (!dir) dir = ctx->model;
- if (*dir == '/') {
- script_dir = (char*)dir;
- } else {
- script_dir = alloca(strlen(model_dir) + strlen(dir) + 2);
- if (!script_dir) return PCILIB_ERROR_MEMORY;
- sprintf(script_dir, "%s/%s", model_dir, dir);
- }
- PyGILState_STATE gstate = PyGILState_Ensure();
- pypath = PySys_GetObject("path");
- if (!pypath) {
- PyGILState_Release(gstate);
- pcilib_python_warning("Can't get python path");
- return PCILIB_ERROR_FAILED;
- }
- pynewdir = PyUnicode_FromString(script_dir);
- if (!pynewdir) {
- PyGILState_Release(gstate);
- pcilib_python_warning("Can't create python string");
- return PCILIB_ERROR_MEMORY;
- }
- // Checking if the directory already in the path?
- pydict = PyDict_New();
- if (pydict) {
- pystr = PyUnicode_FromString("cur");
- if (pystr) {
- PyDict_SetItem(pydict, pystr, pynewdir);
- Py_DECREF(pystr);
- }
- pystr = PyUnicode_FromString("path");
- if (pystr) {
- PyDict_SetItem(pydict, pystr, pypath);
- Py_DECREF(pystr);
- }
- pyret = PyRun_String("cur in path", Py_eval_input, ctx->py->global_dict, pydict);
- Py_DECREF(pydict);
- }
- if ((pyret == Py_False)&&(PyList_Append(pypath, pynewdir) == -1))
- err = PCILIB_ERROR_FAILED;
- if (pyret) Py_DECREF(pyret);
- Py_DECREF(pynewdir);
- PyGILState_Release(gstate);
- if (err) {
- pcilib_python_warning("Can't add directory (%s) to python path", script_dir);
- return err;
- }
- #endif /* HAVE_PYTHON */
- return 0;
- }
- int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) {
- #ifdef HAVE_PYTHON
- PyObject* pymodule;
- pcilib_script_t *module = NULL;
- PyGILState_STATE gstate;
- if (!ctx->py) return 0;
- char *module_name = strdupa(script_name);
- if (!module_name) return PCILIB_ERROR_MEMORY;
- char *py = strrchr(module_name, '.');
- if ((!py)||(strcasecmp(py, ".py"))) {
- pcilib_error("Invalid script name (%s) is specified", script_name);
- return PCILIB_ERROR_INVALID_ARGUMENT;
- }
- *py = 0;
- HASH_FIND_STR(ctx->py->script_hash, script_name, module);
- if (module) return 0;
- gstate = PyGILState_Ensure();
- pymodule = PyImport_ImportModule(module_name);
- if (!pymodule) {
- PyGILState_Release(gstate);
- pcilib_python_error("Error importing script (%s)", script_name);
- return PCILIB_ERROR_FAILED;
- }
- module = (pcilib_script_t*)malloc(sizeof(pcilib_script_t));
- if (!module) {
- Py_DECREF(pymodule);
- PyGILState_Release(gstate);
- return PCILIB_ERROR_MEMORY;
- }
- PyGILState_Release(gstate);
- module->module = pymodule;
- module->name = script_name;
- HASH_ADD_KEYPTR(hh, ctx->py->script_hash, module->name, strlen(module->name), module);
- #endif /* HAVE_PYTHON */
- return 0;
- }
- int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_name, pcilib_access_mode_t *mode_ret) {
- pcilib_access_mode_t mode = 0;
- #ifdef HAVE_PYTHON
- PyObject *dict;
- PyObject *pystr;
- pcilib_script_t *module;
- PyGILState_STATE gstate;
- if (!ctx->py) {
- if (mode_ret) *mode_ret = mode;
- return 0;
- }
- HASH_FIND_STR(ctx->py->script_hash, script_name, module);
- if(!module) {
- pcilib_error("Script (%s) is not loaded yet", script_name);
- return PCILIB_ERROR_NOTFOUND;
- }
-
- gstate = PyGILState_Ensure();
-
- dict = PyModule_GetDict(module->module);
- if (!dict) {
- PyGILState_Release(gstate);
- pcilib_python_error("Error getting dictionary for script (%s)", script_name);
- return PCILIB_ERROR_FAILED;
- }
-
- pystr = PyUnicode_FromString("read_from_register");
- if (pystr) {
- if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_R;
- Py_DECREF(pystr);
- }
- pystr = PyUnicode_FromString("write_to_register");
- if (pystr) {
- if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W;
- Py_DECREF(pystr);
- }
-
- PyGILState_Release(gstate);
- #endif /* HAVE_PYTHON */
- // pcilib_py_load_default_modules(py->ctx);
- if (mode_ret) *mode_ret = mode;
- return 0;
- }
- pcilib_py_object *pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val, int *ret) {
- #ifdef HAVE_PYTHON
- int err = 0;
- PyObject *res = NULL;
- PyGILState_STATE gstate;
- long ival;
- double fval;
- if (!ctx->py) return NULL;
- gstate = PyGILState_Ensure();
- switch(val->type) {
- case PCILIB_TYPE_LONG:
- ival = pcilib_get_value_as_int(ctx, val, &err);
- if (!err) res = (PyObject*)PyLong_FromLong(ival);
- break;
- case PCILIB_TYPE_DOUBLE:
- fval = pcilib_get_value_as_float(ctx, val, &err);
- if (!err) res = (PyObject*)PyFloat_FromDouble(fval);
- break;
- default:
- PyGILState_Release(gstate);
- pcilib_error("Can't convert pcilib value of type (%lu) to PyObject", val->type);
- if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
- return NULL;
- }
- PyGILState_Release(gstate);
- if (err) {
- if (ret) *ret = err;
- return NULL;
- } else if (!res) {
- if (ret) *ret = PCILIB_ERROR_MEMORY;
- return res;
- }
- if (ret) *ret = 0;
- return res;
- #else /* HAVE_PYTHON */
- pcilib_error("Python is not supported");
- return NULL;
- #endif /* HAVE_PYTHON */
- }
- int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py_object *pval) {
- #ifdef HAVE_PYTHON
- int err = 0;
- PyObject *pyval = (PyObject*)pval;
- PyGILState_STATE gstate;
- if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
- gstate = PyGILState_Ensure();
- if (PyLong_Check(pyval)) {
- err = pcilib_set_value_from_int(ctx, val, PyLong_AsLong(pyval));
- } else if (PyFloat_Check(pyval)) {
- err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyval));
- #if PY_MAJOR_VERSION < 3
- } else if (PyInt_Check(pyval)) {
- err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval));
- } else if (PyString_Check(pyval)) {
- err = pcilib_set_value_from_string(ctx, val, PyString_AsString(pyval));
- } else if (PyUnicode_Check(pyval)) {
- PyObject *buf = PyUnicode_AsASCIIString(pyval);
- if (buf) {
- err = pcilib_set_value_from_string(ctx, val, PyString_AsString(buf));
- Py_DecRef(buf);
- } else {
- err = PCILIB_ERROR_FAILED;
- }
- #else /* PY_MAJOR_VERSION < 3 */
- } else if (PyUnicode_Check(pyval)) {
- err = pcilib_set_value_from_string(ctx, val, PyUnicode_AsUTF8(pyval));
- #endif /* PY_MAJOR_VERSION < 3 */
- } else {
- PyGILState_Release(gstate);
- pcilib_error("Can't convert PyObject to polymorphic pcilib value");
- return PCILIB_ERROR_NOTSUPPORTED;
- }
- PyGILState_Release(gstate);
- return err;
- #else /* HAVE_PYTHON */
- pcilib_error("Python is not supported");
- return PCILIB_ERROR_NOTSUPPORTED;
- #endif /* HAVE_PYTHON */
- }
- #ifdef HAVE_PYTHON
- static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
- int i;
- int err = 0;
- pcilib_value_t val = {0};
- pcilib_register_value_t regval;
- char save;
- char *reg, *cur;
- size_t offset = 0;
- size_t size;
- char *src;
- char *dst;
- size_t max_repl = 2 + 2 * sizeof(pcilib_value_t); // the text representation of largest integer
- if (value) {
- err = pcilib_copy_value(ctx, &val, value);
- if (err) return NULL;
- err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
- if (err) return NULL;
- if (strlen(val.sval) > max_repl)
- max_repl = strlen(val.sval);
- }
- size = ((max_repl + 1) / 3 + 1) * strlen(codestr); // minimum register length is 3 symbols ($a + delimiter space), it is replaces with (max_repl+1) symbols
- src = strdup(codestr);
- dst = (char*)malloc(size); // allocating maximum required space
- if ((!src)||(!dst)) {
- if (src) free(src);
- if (dst) free(dst);
- pcilib_error("Failed to allocate memory for string formulas");
- return NULL;
- }
- cur = src;
- reg = strchr(src, '$');
- while (reg) {
- strcpy(dst + offset, cur);
- offset += reg - cur;
- // find the end of the register name
- reg++;
- if (*reg == '{') {
- reg++;
- for (i = 0; (reg[i])&&(reg[i] != '}'); i++);
- if (!reg[i]) {
- pcilib_error("Python formula (%s) contains unterminated variable reference", codestr);
- err = PCILIB_ERROR_INVALID_DATA;
- break;
- }
- } else {
- for (i = 0; isalnum(reg[i])||(reg[i] == '_'); i++);
- }
- save = reg[i];
- reg[i] = 0;
- // determine replacement value
- if (!strcasecmp(reg, "value")) {
- if (!value) {
- pcilib_error("Python formula (%s) relies on the value of register, but it is not provided", codestr);
- err = PCILIB_ERROR_INVALID_REQUEST;
- break;
- }
- strcpy(dst + offset, val.sval);
- } else {
- if (*reg == '/') {
- pcilib_value_t val = {0};
- err = pcilib_get_property(ctx, reg, &val);
- if (err) break;
- err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
- if (err) break;
- sprintf(dst + offset, "%s", val.sval);
- } else {
- err = pcilib_read_register(ctx, NULL, reg, ®val);
- if (err) break;
- sprintf(dst + offset, "0x%lx", regval);
- }
- }
- offset += strlen(dst + offset);
- if (save == '}') i++;
- else reg[i] = save;
- // Advance to the next register if any
- cur = reg + i;
- reg = strchr(cur, '$');
- }
- strcpy(dst + offset, cur);
- free(src);
- if (err) {
- free(dst);
- return NULL;
- }
- return dst;
- }
- #endif /* HAVE_PYTHON */
- int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
- #ifdef HAVE_PYTHON
- int err;
- PyGILState_STATE gstate;
- char *code;
- PyObject* obj;
- if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
- code = pcilib_py_parse_string(ctx, codestr, value);
- if (!code) {
- pcilib_error("Failed to parse registers in the code: %s", codestr);
- return PCILIB_ERROR_FAILED;
- }
- gstate = PyGILState_Ensure();
- obj = PyRun_String(code, Py_eval_input, ctx->py->global_dict, ctx->py->global_dict);
- PyGILState_Release(gstate);
- if (!obj) {
- pcilib_error("Failed to run the Python code: %s", code);
- free(code);
- return PCILIB_ERROR_FAILED;
- }
- pcilib_debug(VIEWS, "Evaluating a Python string \'%s\' to %lf=\'%s\'", codestr, PyFloat_AsDouble(obj), code);
- err = pcilib_set_value_from_float(ctx, value, PyFloat_AsDouble(obj));
- Py_DECREF(obj);
- free(code);
- return err;
- #else /* HAVE_PYTHON */
- pcilib_error("Current build not support python.");
- return PCILIB_ERROR_NOTAVAILABLE;
- #endif /* HAVE_PYTHON */
- }
- int pcilib_py_eval_func(pcilib_t *ctx, const char *script_name, const char *func_name, pcilib_value_t *val) {
- #ifdef HAVE_PYTHON
- int err = 0;
- PyObject *pyfunc;
- PyObject *pyval = NULL, *pyret;
- pcilib_script_t *module = NULL;
- if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
- HASH_FIND_STR(ctx->py->script_hash, script_name, module);
- if (!module) {
- pcilib_error("Script (%s) is not loaded", script_name);
- return PCILIB_ERROR_NOTFOUND;
- }
- if (val) {
- pyval = pcilib_get_value_as_pyobject(ctx, val, &err);
- if (err) return err;
- }
- PyGILState_STATE gstate = PyGILState_Ensure();
- pyfunc = PyUnicode_FromString(func_name);
- if (!pyfunc) {
- if (pyval) Py_DECREF(pyval);
- PyGILState_Release(gstate);
- return PCILIB_ERROR_MEMORY;
- }
- pyret = PyObject_CallMethodObjArgs(module->module, pyfunc, ctx->py->pcilib_pywrap, pyval, NULL);
- Py_DECREF(pyfunc);
- Py_DECREF(pyval);
-
- if (!pyret) {
- PyGILState_Release(gstate);
- pcilib_python_error("Error executing function (%s) of python script (%s)", func_name, script_name);
- return PCILIB_ERROR_FAILED;
- }
- if ((val)&&(pyret != Py_None))
- err = pcilib_set_value_from_pyobject(ctx, val, pyret);
- Py_DECREF(pyret);
- PyGILState_Release(gstate);
- return err;
- #else /* HAVE_PYTHON */
- pcilib_error("Python is not supported");
- return PCILIB_ERROR_NOTSUPPORTED;
- #endif /* HAVE_PYTHON */
- }
|