@@@ mdwopt broken wip
authorMark Wooding <mdw@distorted.org.uk>
Sat, 28 Mar 2020 10:37:20 +0000 (10:37 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 11 Apr 2020 14:23:48 +0000 (15:23 +0100)
mLib-python.h
ui.c

index cd05d8d..33000d4 100644 (file)
@@ -44,6 +44,7 @@ PUBLIC_SYMBOLS;
 #include <mLib/fdflags.h>
 #include <mLib/fdpass.h>
 #include <mLib/mdup.h>
+#include <mLib/mdwopt.h>
 #include <mLib/quis.h>
 #include <mLib/report.h>
 PRIVATE_SYMBOLS;
diff --git a/ui.c b/ui.c
index 82a1769..4316d93 100644 (file)
--- 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()); }