From 747ddb1b97d37fd57efae3c99c2bd188a14df308 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 20 Oct 2019 21:18:08 +0100 Subject: [PATCH] pyke/pyke.[ch]: Make type skeleton structures be read-only. We couldn't do this before because `INITTYPE_META' would write the direct superclass to the `tp_base' slot in the skeleton before calling `inittype'. To make this work, then, we adjust `inittype' to take the direct superclass as an extra argument and plug it into the newly created heap-type; and `INITTYPE_META' needs adjusting to pass this argument rather than trying to write to the skeleton directly. Of course, then we need to actually mark the type skeletons as `const'. --- mapping.c | 4 ++-- pyke.c | 5 +++-- pyke.h | 9 ++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mapping.c b/mapping.c index 7080ca5..e97fcb0 100644 --- a/mapping.c +++ b/mapping.c @@ -54,7 +54,7 @@ static PyObject *itemiter_pynext(PyObject *me) return (rc); } -static PyTypeObject itemiter_pytype_skel = { +static const PyTypeObject itemiter_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ "ItemIter", /* @tp_name@ */ sizeof(iter_pyobj), /* @tp_basicsize@ */ @@ -112,7 +112,7 @@ static PyObject *valiter_pynext(PyObject *me) return (rc); } -static PyTypeObject valiter_pytype_skel = { +static const PyTypeObject valiter_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ "ValueIter", /* @tp_name@ */ sizeof(iter_pyobj), /* @tp_basicsize@ */ diff --git a/pyke.c b/pyke.c index b462a1f..f19c9e4 100644 --- a/pyke.c +++ b/pyke.c @@ -218,7 +218,6 @@ void *newtype(PyTypeObject *metaty, (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0)); if (!skel) skel = &emptytype; memcpy(ty, skel, sizeof(*skel)); - if (ty->ht_type.tp_base) Py_INCREF(ty->ht_type.tp_base); #define COPY(blah) do { \ if (ty->ht_type.tp_as_##blah) { \ memcpy(&ty->as_##blah, \ @@ -249,9 +248,11 @@ void typeready(PyTypeObject *ty) PyDict_SetItemString(ty->tp_dict, "__module__", modname); } -PyTypeObject *inittype(PyTypeObject *tyskel, PyTypeObject *meta) +PyTypeObject *inittype(const PyTypeObject *tyskel, + PyTypeObject *base, PyTypeObject *meta) { PyTypeObject *ty = newtype(meta, tyskel, 0); + if (base) { ty->tp_base = base; Py_INCREF(base); } ty->tp_flags |= Py_TPFLAGS_HEAPTYPE; typeready(ty); return (ty); diff --git a/pyke.h b/pyke.h index 3076bb5..138a9fb 100644 --- a/pyke.h +++ b/pyke.h @@ -208,11 +208,11 @@ extern void *newtype(PyTypeObject */*meta*/, extern void typeready(PyTypeObject *); /* The type object is now ready to be used. */ -extern PyTypeObject *inittype(PyTypeObject */*skel*/, +extern PyTypeObject *inittype(const PyTypeObject */*skel*/, + PyTypeObject */*base*/, PyTypeObject */*meta*/); /* All-in-one function to construct a working type from a type skeleton - * SKEL, with metaclass META. The caller is expected to have filled in the - * direct superclass in SKEL->tp_base. + * SKEL, with known base type BASE (null for `object') and metaclass. */ /* Alias for built-in types, to fit in with Pyke naming conventions. */ @@ -220,8 +220,7 @@ extern PyTypeObject *inittype(PyTypeObject */*skel*/, #define type_pytype &PyType_Type #define INITTYPE_META(ty, base, meta) do { \ - ty##_pytype_skel.tp_base = base##_pytype; \ - ty##_pytype = inittype(&ty##_pytype_skel, meta##_pytype); \ + ty##_pytype = inittype(&ty##_pytype_skel, base##_pytype, meta##_pytype); \ } while (0) #define INITTYPE(ty, base) INITTYPE_META(ty, base, type) /* Macros to initialize a type from its skeleton. */ -- 2.11.0