5 * (c) 2019 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the Python interface to mLib.
12 * mLib/Python is free software: you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
17 * mLib/Python is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with mLib/Python. If not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 /*----- Header files ------------------------------------------------------*/
30 #include "mLib-python.h"
32 /*----- Program name ------------------------------------------------------*/
34 static int set_program_name(void)
36 PyObject *p = TEXT_FROMSTR(pn__name);
39 if (!home_module) SYSERR("home module not set");
40 if (PyObject_SetAttrString(home_module, "quis", p)) goto end;
41 pn__name = TEXT_PTR(p); p = 0; rc = 0;
47 static PyObject *meth_ego(PyObject *me, PyObject *arg)
52 if (!PyArg_ParseTuple(arg, "s:ego", &p)) goto end;
53 old = pn__name; ego(p);
54 if (set_program_name()) { pn__name = old; goto end; }
60 /*----- Error reporting ---------------------------------------------------*/
62 static PyObject *meth_moan(PyObject *me, PyObject *arg)
66 if (!PyArg_ParseTuple(arg, "s:moan", &p)) goto end;
73 static PyObject *meth_die(PyObject *me, PyObject *arg, PyObject *kw)
75 const char *const kwlist[] = { "msg", "rc", 0 };
80 if (!PyArg_ParseTupleAndKeywords(arg, kw, "s|i:moan", KWLIST, &p, &rc))
82 rcobj = PyInt_FromLong(rc); if (!rcobj) goto end;
84 PyErr_SetObject(PyExc_SystemExit, rcobj);
90 /*----- Option parser -----------------------------------------------------*/
100 char **argv, *stringdata;
102 struct option *longopt;
104 static PyTypeObject *mdwopt_pytype;
105 #define MDWOPT_PYCHECK(o) PyObject_TypeCheck((o), mdwopt_pytype)
106 #define MDWOPT_OPT(o) (&((mdwopt_pyobj *)(o))->opt)
107 #define MDWOPT_ARGV(o) (((mdwopt_pyobj *)(o))->argv)
108 #define MDWOPT_SHORT(o) (((mdwopt_pyobj *)(o))->shortopt)
109 #define MDWOPT_LONG(o) (((mdwopt_pyobj *)(o))->longopt)
111 #define IXTAG(ix) (((ix)&0xff) | (((ix)&~0xff) << 1))
112 #define TAGIX(tag) (((tag)&0xff) | (((tag)&~0x1ff) >> 1))
114 static PyObject *mdwopt_pynew(PyTypeObject *cls, PyObject *arg, PyObject *kw)
116 DA_DECL(obj_v, PyObject *);
117 DA_DECL(opt_v, struct option);
118 DA_DECL(size_v, size_t);
120 PyObject *argvobj = 0, *longoptobj = 0;
121 PyObject *it = 0, *t = 0, *u = 0;
124 mdwopt_pyobj *me = 0;
128 opt_v opts = DA_INIT;
129 obj_v tags = DA_INIT;
130 size_v off = DA_INIT;
131 dstr strbuf = DSTR_INIT;
133 static const char *const kwlist[] =
134 { "argv", "shortopt", "longopt", "flags", 0 };
136 if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OsOO&:new", KWLIST,
143 argvobj = PySys_GetObject("argv");
144 if (!argvobj) SYSERR("sys.argv missing");
147 it = PyObject_GetIter(argvobj); if (!it) goto end;
149 t = PyIter_Next(it); if (!t) break;
150 if (!TEXT_CHECK(t)) TYERR("argv should be a sequence of strings");
151 TEXT_PTRLEN(t, p, sz);
152 DA_PUSH(&off, strbuf.len);
153 DPUTM(&strbuf, p, sz + 1);
156 if (PyErr_Occurred()) goto end;
158 Py_DECREF(it); it = 0;
160 it = PyObject_GetIter(longoptobj); if (!it) goto end;
162 t = PyIter_Next(it); if (!t) break;
163 n = PySequence_Size(t); if (n < 0) goto end;
165 VALERR("long-options entry should be "
166 "(OPT, TAG, [FLAGS = 0, [ATTR = None]])");
168 u = PySequence_GetItem(t, 0); if (!u) goto end;
169 if (!TEXT_CHECK(u)) TYERR("option name should be a string");
170 TEXT_PTRLEN(u, p, sz);
171 DA_PUSH(&off, strbuf.len);
172 DPUTM(&strbuf, p, sz + 1);
175 u = PySequence_GetItem(t, 1); if (!u) goto end;
176 DA_PUSH(&tags, u); u = 0;
181 u = PySequence_GetItem(t, 0); if (!u) goto end;
182 if (getint(u, &f)) goto end;
189 return (PyObject *)me;
192 static void mdwopt_pydealloc(PyObject *me)
194 mdwopt_pyobj *m = (mdwopt_pyobj *)me;
196 xfree(m->stringdata);
201 static const PyMemberDef mdwopt_pymembers[] = {
202 #define MEMBERSTRUCT mdwopt_pyobj
207 static const PyGetSetDef mdwopt_pygetset[] = {
208 #define GETSETNAME(op, name) mo##op##_##name
213 static const PyMethodDef mdwopt_pymethods[] = {
214 #define METHNAME(name) mometh_##name
219 static const PyTypeObject mdwopt_pytype_skel = {
220 PyVarObject_HEAD_INIT(0, 0) /* Header */
221 "MdwOpt", /* @tp_name@ */
222 sizeof(mdwopt_pyobj), /* @tp_basicsize@ */
223 0, /* @tp_itemsize@ */
225 mdwopt_pydealloc, /* @tp_dealloc@ */
227 0, /* @tp_getattr@ */
228 0, /* @tp_setattr@ */
229 0, /* @tp_compare@ */
231 0, /* @tp_as_number@ */
232 0, /* @tp_as_sequence@ */
233 0, /* @tp_as_mapping@ */
237 0, /* @tp_getattro@ */
238 0, /* @tp_setattro@ */
239 0, /* @tp_as_buffer@ */
240 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
244 "MdwOpt([argv = SEQ], [shortopt = STR], [longopt = SEQ], [flags = 0])",
246 0, /* @tp_traverse@ */
248 0, /* @tp_richcompare@ */
249 0, /* @tp_weaklistoffset@ */
251 0, /* @tp_iternext@ */
252 PYMETHODS(mdwopt), /* @tp_methods@ */
253 PYMEMBERS(mdwopt), /* @tp_members@ */
254 PYGETSET(mdwopt), /* @tp_getset@ */
257 0, /* @tp_descr_get@ */
258 0, /* @tp_descr_set@ */
259 0, /* @tp_dictoffset@ */
261 PyType_GenericAlloc, /* @tp_alloc@ */
262 mdwopt_pynew, /* @tp_new@ */
267 /*----- Main code ---------------------------------------------------------*/
269 static const PyMethodDef methods[] = {
270 #define METHNAME(name) meth_##name
271 METH (ego, "ego(PROG): set program name")
272 METH (moan, "moan(MSG): report a warning")
273 KWMETH(die, "die(MSG, [rc = 126]): report a fatal error and exit")
280 INITTYPE(mdwopt, root);
284 void ui_pyinsert(PyObject *mod)
286 INSERT("MdwOpt", mdwopt_pytype);
289 int ui_pyready(void) { return (set_program_name()); }
291 /*----- That's all, folks -------------------------------------------------*/