diff --git a/devsupApp/src/Makefile b/devsupApp/src/Makefile index b7993ed..9478944 100644 --- a/devsupApp/src/Makefile +++ b/devsupApp/src/Makefile @@ -24,6 +24,7 @@ setup_CPPFLAGS += -DXEPICS_BASE=\"$(EPICS_BASE)\" setup_CPPFLAGS += -DPYDIR=\"python$(PY_VER)\" pyDevSup$(PY_LD_VER)_SRCS += setup.c +pyDevSup$(PY_LD_VER)_SRCS += dbbase.c pyDevSup$(PY_LD_VER)_SRCS += dbrec.c pyDevSup$(PY_LD_VER)_SRCS += dbfield.c pyDevSup$(PY_LD_VER)_SRCS += dbdset.c diff --git a/devsupApp/src/dbbase.c b/devsupApp/src/dbbase.c new file mode 100644 index 0000000..c129486 --- /dev/null +++ b/devsupApp/src/dbbase.c @@ -0,0 +1,132 @@ + +/* python has its own ideas about which version to support */ +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pydevsup.h" + +static +PyObject *py_iocsh(PyObject *unused, PyObject *args, PyObject *kws) +{ + int ret; + static char* names[] = {"script", "cmd", NULL}; + char *script=NULL, *cmd=NULL; + + if(!PyArg_ParseTupleAndKeywords(args, kws, "|ss", names, &script, &cmd)) + return NULL; + + if(!(!script ^ !cmd)) { + PyErr_SetString(PyExc_ValueError, "iocsh requires a script file name or command string"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS { + if(script) + ret = iocsh(script); + else + ret = iocshCmd(cmd); + } Py_END_ALLOW_THREADS + + return PyInt_FromLong(ret); +} + +static +PyObject *py_dbReadDatabase(PyObject *unused, PyObject *args, PyObject *kws) +{ + long status; + static char* names[] = {"name", "fp", "path", "sub", NULL}; + char *fname=NULL, *path=NULL, *sub=NULL; + int fd=-1; + + if(!PyArg_ParseTupleAndKeywords(args, kws, "|siss", names, &fname, &fd, &path, &sub)) + return NULL; + + if(!((!fname) ^ (fd<0))) { + PyErr_SetString(PyExc_ValueError, "dbReadDatabase requires a file name or descriptor"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS { + if(fname) + status = dbReadDatabase(&pdbbase, fname, path, sub); + else { + FILE *ff = fdopen(fd, "r"); + status = dbReadDatabaseFP(&pdbbase, ff, path, sub); + fclose(ff); + } + } Py_END_ALLOW_THREADS + + if(status) { + char buf[30]; + errSymLookup(status, buf, sizeof(buf)); + PyErr_SetString(PyExc_RuntimeError, buf); + return NULL; + } + Py_RETURN_NONE; +} + +static +PyObject *py_iocInit(PyObject *unused) +{ + Py_BEGIN_ALLOW_THREADS { + iocInit(); + } Py_END_ALLOW_THREADS + + Py_RETURN_NONE; +} + +static struct PyMethodDef dbbasemethods[] = { + {"iocsh", (PyCFunction)py_iocsh, METH_VARARGS|METH_KEYWORDS, + "Execute IOC shell script or command"}, + {"dbReadDatabase", (PyCFunction)py_dbReadDatabase, METH_VARARGS|METH_KEYWORDS, + "Load EPICS database file"}, + {"iocInit", (PyCFunction)py_iocInit, METH_NOARGS, + "Initialize IOC"}, + {NULL} +}; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef dbbasemodule = { + PyModuleDef_HEAD_INIT, + "_dbbase", + NULL, + -1, + &dbbasemethods +}; +#endif + +/* initialize "magic" builtin module */ +PyMODINIT_FUNC init_dbbase(void) +{ + PyObject *mod = NULL, *obj = NULL; + +#if PY_MAJOR_VERSION >= 3 + mod = PyModule_Create(&dbbasemodule); +#else + mod = Py_InitModule("_dbbase", dbbasemethods); +#endif + if(!mod) + goto fail; + + obj = PyCapsule_New(pdbbase, "pdbbase", NULL); + if(!obj) + goto fail; + PyModule_AddObject(mod, "pdbbase", obj); + + MODINIT_RET(mod); +fail: + Py_XDECREF(obj); + Py_XDECREF(mod); + fprintf(stderr, "Failed to initialize builtin _dbbase module!\n"); + MODINIT_RET(NULL); +} diff --git a/devsupApp/src/pydevsup.h b/devsupApp/src/pydevsup.h index e85f6d7..9b7cbf8 100644 --- a/devsupApp/src/pydevsup.h +++ b/devsupApp/src/pydevsup.h @@ -2,6 +2,7 @@ #define PYDEVSUP_H #include +#include #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong @@ -13,6 +14,11 @@ #define MODINIT_RET(VAL) return #endif + +initHookState pyInitLastState; + +PyMODINIT_FUNC init_dbbase(void); + void pyDBD_cleanup(void); int pyField_prepare(PyObject *module); diff --git a/devsupApp/src/setup.c b/devsupApp/src/setup.c index 5b99c1c..34b3734 100644 --- a/devsupApp/src/setup.c +++ b/devsupApp/src/setup.c @@ -102,6 +102,8 @@ void pyfile(const char* file) PyGILState_Release(state); } +initHookState pyInitLastState = (initHookState)-1; + static void pyhook(initHookState state) { static int madenoise = 0; @@ -114,6 +116,8 @@ static void pyhook(initHookState state) gilstate = PyGILState_Ensure(); + pyInitLastState = state; + mod = PyImport_ImportModule("devsup.hooks"); if(!mod) { if(!madenoise) @@ -302,6 +306,7 @@ static void setupPyInit(void) { PyImport_AppendInittab("_dbapi", init_dbapi); PyImport_AppendInittab("_dbconstants", init_dbconstants); + PyImport_AppendInittab("_dbbase", init_dbbase); Py_Initialize(); PyEval_InitThreads();