From: Mark Wooding Date: Sat, 28 Mar 2020 10:37:20 +0000 (+0000) Subject: @@@ mdwopt broken wip X-Git-Url: https://git.distorted.org.uk/~mdw/mLib-python/commitdiff_plain/f18b900ca0aa04648e9bbaa46c57a5007840a4ab?hp=81f68b64afdb80f8ee34e1294ecc5fb452a3e58b @@@ mdwopt broken wip --- diff --git a/mLib-python.h b/mLib-python.h index cd05d8d..33000d4 100644 --- a/mLib-python.h +++ b/mLib-python.h @@ -44,6 +44,7 @@ PUBLIC_SYMBOLS; #include #include #include +#include #include #include PRIVATE_SYMBOLS; diff --git a/ui.c b/ui.c index 82a1769..4316d93 100644 --- a/ui.c +++ b/ui.c @@ -87,6 +87,183 @@ end: return (0); } +/*----- Option parser -----------------------------------------------------*/ + +struct optextra { + PyObject *tag; + PyObject *attr; +}; + +typedef struct { + PyObject_HEAD + mdwopt_data opt; + char **argv, *stringdata; + char *shortopt; + struct option *longopt; +} mdwopt_pyobj; +static PyTypeObject *mdwopt_pytype; +#define MDWOPT_PYCHECK(o) PyObject_TypeCheck((o), mdwopt_pytype) +#define MDWOPT_OPT(o) (&((mdwopt_pyobj *)(o))->opt) +#define MDWOPT_ARGV(o) (((mdwopt_pyobj *)(o))->argv) +#define MDWOPT_SHORT(o) (((mdwopt_pyobj *)(o))->shortopt) +#define MDWOPT_LONG(o) (((mdwopt_pyobj *)(o))->longopt) + +#define IXTAG(ix) (((ix)&0xff) | (((ix)&~0xff) << 1)) +#define TAGIX(tag) (((tag)&0xff) | (((tag)&~0x1ff) >> 1)) + +static PyObject *mdwopt_pynew(PyTypeObject *cls, PyObject *arg, PyObject *kw) +{ + DA_DECL(obj_v, PyObject *); + DA_DECL(opt_v, struct option); + DA_DECL(size_v, size_t); + + PyObject *argvobj = 0, *longoptobj = 0; + PyObject *it = 0, *t = 0, *u = 0; + char *p; size_t sz; + Py_ssize_t n; + mdwopt_pyobj *me = 0; + char *shortopt; + unsigned flags = 0; + int f; + opt_v opts = DA_INIT; + obj_v tags = DA_INIT; + size_v off = DA_INIT; + dstr strbuf = DSTR_INIT; + size_t narg; + static const char *const kwlist[] = + { "argv", "shortopt", "longopt", "flags", 0 }; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OsOO&:new", KWLIST, + &argvobj, + &shortopt, + &longoptobj, + convuint, &flags)) + goto end; + if (!argvobj) { + argvobj = PySys_GetObject("argv"); + if (!argvobj) SYSERR("sys.argv missing"); + } + + it = PyObject_GetIter(argvobj); if (!it) goto end; + for (;;) { + t = PyIter_Next(it); if (!t) break; + if (!TEXT_CHECK(t)) TYERR("argv should be a sequence of strings"); + TEXT_PTRLEN(t, p, sz); + DA_PUSH(&off, strbuf.len); + DPUTM(&strbuf, p, sz + 1); + Py_DECREF(t); t = 0; + } + if (PyErr_Occurred()) goto end; + narg = DA_LEN(&off); + Py_DECREF(it); it = 0; + + it = PyObject_GetIter(longoptobj); if (!it) goto end; + for (;;) { + t = PyIter_Next(it); if (!t) break; + n = PySequence_Size(t); if (n < 0) goto end; + if (n < 2 || n > 4) + VALERR("long-options entry should be " + "(OPT, TAG, [FLAGS = 0, [ATTR = None]])"); + + u = PySequence_GetItem(t, 0); if (!u) goto end; + if (!TEXT_CHECK(u)) TYERR("option name should be a string"); + TEXT_PTRLEN(u, p, sz); + DA_PUSH(&off, strbuf.len); + DPUTM(&strbuf, p, sz + 1); + Py_DECREF(u); u = 0; + + u = PySequence_GetItem(t, 1); if (!u) goto end; + DA_PUSH(&tags, u); u = 0; + + if (n < 3) + f = 0; + else { + u = PySequence_GetItem(t, 0); if (!u) goto end; + if (getint(u, &f)) goto end; + Py_DECREF(u); u = 0; + } + + + +end: + return (PyObject *)me; +} + +static void mdwopt_pydealloc(PyObject *me) +{ + mdwopt_pyobj *m = (mdwopt_pyobj *)me; + + xfree(m->stringdata); + xfree(m->longopt); + FREEOBJ(me); +} + +static const PyMemberDef mdwopt_pymembers[] = { +#define MEMBERSTRUCT mdwopt_pyobj +#undef MEMBERSTRUCT + { 0 } +}; + +static const PyGetSetDef mdwopt_pygetset[] = { +#define GETSETNAME(op, name) mo##op##_##name +#undef GETSETNAME + { 0 } +}; + +static const PyMethodDef mdwopt_pymethods[] = { +#define METHNAME(name) mometh_##name +#undef METHNAME + { 0 } +}; + +static const PyTypeObject mdwopt_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ + "MdwOpt", /* @tp_name@ */ + sizeof(mdwopt_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + mdwopt_pydealloc, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ + "MdwOpt([argv = SEQ], [shortopt = STR], [longopt = SEQ], [flags = 0])", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + PYMETHODS(mdwopt), /* @tp_methods@ */ + PYMEMBERS(mdwopt), /* @tp_members@ */ + PYGETSET(mdwopt), /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + mdwopt_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + /*----- Main code ---------------------------------------------------------*/ static const PyMethodDef methods[] = { @@ -100,11 +277,13 @@ static const PyMethodDef methods[] = { void ui_pyinit(void) { + INITTYPE(mdwopt, root); addmethods(methods); } void ui_pyinsert(PyObject *mod) { + INSERT("MdwOpt", mdwopt_pytype); } int ui_pyready(void) { return (set_program_name()); }