catacomb.c, util.c: Publish negative constants correctly.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 24 Nov 2019 15:11:46 +0000 (15:11 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 27 Nov 2019 15:10:43 +0000 (15:10 +0000)
The various `KERR_...' constants and `PGEN_ABORT' are canonically
negative integers, but weren't published correctly.  Add a flags word to
`struct nameval' to identify constants which should really be signed,
and some fancy footwork to convert unsigned integers back to negative
values without upsetting C.  Adjust the `C' macro to spot negative
constants and mark them specially.

Not all is well.  In particular, the `KEXP_...' constants should /not/
be published as signed values, even if `time_t' is signed on the target
platform, because the Python bindings handle them exclusively as
`unsigned long' values.  To make this work, also introduce `CF' which
allows us to set the flags explicitly, and use it for `KEXP_...'.

catacomb-python.h
catacomb.c
util.c

index c272b53..b1120fa 100644 (file)
@@ -233,7 +233,8 @@ MODULES(DO)
     return (d);                                                                \
   }
 
-struct nameval { const char *name; unsigned long value; };
+struct nameval { const char *name; unsigned f; unsigned long value; };
+#define CF_SIGNED 1u
 extern void setconstants(PyObject *, const struct nameval *);
 
 extern PyObject *mexp_common(PyObject *, PyObject *, size_t,
index d7b3dc7..daa404a 100644 (file)
@@ -31,7 +31,8 @@
 /*----- Main code ---------------------------------------------------------*/
 
 static const struct nameval consts[] = {
-#define C(x) { #x, x }
+#define CF(f, x) { #x, f, x }
+#define C(x) { #x, (x) >= 0 ? 0 : CF_SIGNED, x }
   C(FTY_PRIME), C(FTY_BINARY),
   C(PGEN_PASS), C(PGEN_FAIL), C(PGEN_BEGIN), C(PGEN_TRY), C(PGEN_DONE),
   C(PGEN_ABORT),
@@ -39,7 +40,7 @@ static const struct nameval consts[] = {
   C(RAND_IBITS),
   C(PMODE_READ), C(PMODE_VERIFY),
   C(KOPEN_READ), C(KOPEN_WRITE), C(KOPEN_NOFILE),
-  C(KEXP_FOREVER), C(KEXP_EXPIRE),
+  CF(0, KEXP_FOREVER), CF(0, KEXP_EXPIRE),
   C(KF_ENCMASK), C(KENC_BINARY), C(KENC_MP), C(KENC_STRUCT),
     C(KENC_ENCRYPT), C(KENC_STRING), C(KENC_EC),
   C(KF_CATMASK), C(KCAT_SYMM), C(KCAT_PRIV), C(KCAT_PUB), C(KCAT_SHARE),
@@ -55,6 +56,7 @@ static const struct nameval consts[] = {
   KEY_ERRORS(ENTRY)
 #undef ENTRY
 #undef C
+#undef CF
   { 0 }
 };
 
diff --git a/util.c b/util.c
index d613a7a..9332c8b 100644 (file)
--- a/util.c
+++ b/util.c
@@ -280,14 +280,14 @@ PyTypeObject *inittype(PyTypeObject *tyskel, PyTypeObject *meta)
 void setconstants(PyObject *mod, const struct nameval *c)
 {
   PyObject *x;
+  unsigned long u;
 
   while (c->name) {
-    if (c->value > LONG_MAX)
-      x = PyLong_FromUnsignedLong(c->value);
-    else
-      x = PyInt_FromLong(c->value);
-    PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x);
-    c++;
+    u = c->value;
+    if (u <= LONG_MAX) x = PyInt_FromLong(u);
+    else if (c->f&CF_SIGNED) x = PyInt_FromLong(-1 - (long)(ULONG_MAX - u));
+    else x = PyLong_FromUnsignedLong(u);
+    PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x); c++;
   }
 }