shithub: femtolisp

Download patch

ref: df83e0fd31da4af191a662e4f54df71c905d2f34
parent: b98c14dc639f4da1a80606224ff526731f46905a
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Mar 13 20:08:49 EDT 2023

read: plan9-specific strtoll/strtoull with underflow/overflow control

--- a/read.c
+++ b/read.c
@@ -5,6 +5,56 @@
     TOK_OPENB, TOK_CLOSEB, TOK_SHARPSYM, TOK_GENSYM, TOK_DOUBLEQUOTE
 };
 
+#if defined(__plan9__)
+// FIXME remove all this after adding mp entirely
+#include <mp.h>
+#define ERANGE 34
+#define VLONG_MAX ~(1LL<<63)
+#define VLONG_MIN (1LL<<63)
+#define UVLONG_MAX (1LL<<63)
+static int errno;
+static mpint *mp_vlong_min, *mp_vlong_max, *mp_uvlong_max;
+
+static vlong strtoll_(char *nptr, char **rptr, int base)
+{
+    vlong x;
+    mpint *m, *c;
+
+    x = strtoll(nptr, rptr, base);
+    if((x != VLONG_MAX && x != VLONG_MIN) || *rptr == nptr)
+        return x;
+    m = strtomp(nptr, rptr, base, nil);
+    if(x == VLONG_MAX){
+        if(mp_vlong_max == nil) mp_vlong_max = vtomp(VLONG_MAX, nil);
+        c = mp_vlong_max;
+    }else{
+        if(mp_vlong_min == nil) mp_vlong_min = vtomp(VLONG_MIN, nil);
+        c = mp_vlong_min;
+    }
+    errno = mpcmp(c, m) == 0 ? 0 : ERANGE;
+    mpfree(m);
+    return x;
+}
+
+static uvlong strtoull_(char *nptr, char **rptr, int base)
+{
+    uvlong x;
+    mpint *m;
+
+    x = strtoull(nptr, rptr, base);
+    if(x != UVLONG_MAX || *rptr == nptr)
+        return x;
+    m = strtomp(nptr, rptr, base, nil);
+    if(mp_uvlong_max == nil)
+        mp_uvlong_max = uvtomp(UVLONG_MAX, nil);
+    errno = mpcmp(mp_uvlong_max, m) == 0 ? 0 : ERANGE;
+    mpfree(m);
+    return x;
+}
+#define strtoll strtoll_
+#define strtoull strtoull_
+#endif
+
 #define F value2c(ios_t*,readstate->source)
 
 // defines which characters are ordinary symbol characters.
@@ -60,27 +110,17 @@
             if (pval) *pval = mk_double(D_NINF);
             return 1;
         }
-#if defined(__plan9__)
-        // FIXME use libmp?
-        i64 = strtoll(tok, &end, base);
-#else
         errno = 0;
         i64 = strtoll(tok, &end, base);
         if (errno)
             return 0;
-#endif
         if (pval) *pval = return_from_int64(i64);
         return (*end == '\0');
     }
-#if defined(__plan9__)
-    // FIXME use libmp?
-    ui64 = strtoull(tok, &end, base);
-#else
     errno = 0;
     ui64 = strtoull(tok, &end, base);
     if (errno)
         return 0;
-#endif
     if (pval) *pval = return_from_uint64(ui64);
     return (*end == '\0');
 }
@@ -93,15 +133,10 @@
 static int read_numtok(char *tok, value_t *pval, int base)
 {
     int result;
-#if defined(__plan9__)
-    // FIXME figure out what to do here
-    result = isnumtok_base(tok, pval, base);
-#else
     errno = 0;
     result = isnumtok_base(tok, pval, base);
     if (errno == ERANGE)
         lerrorf(ParseError, "read: overflow in numeric constant %s", tok);
-#endif
     return result;
 }
 
@@ -281,17 +316,10 @@
                 toktype = TOK_LABEL;
             else
                 lerror(ParseError, "read: invalid label");
-#if defined(__plan9__)
-            // FIXME :(
-            x = strtoll(buf, &end, 10);
-            if (*end != '\0')
-                lerror(ParseError, "read: invalid label");
-#else
             errno = 0;
             x = strtoll(buf, &end, 10);
             if (*end != '\0' || errno)
                 lerror(ParseError, "read: invalid label");
-#endif
             tokval = fixnum(x);
         }
         else if (c == '!') {
@@ -342,17 +370,10 @@
             if ((char)ch == 'g')
                 ch = ios_getc(F);
             read_token((char)ch, 0);
-#if defined(__plan9__)
-            // FIXME :(
-            x = strtol(buf, &end, 10);
-            if (*end != '\0' || buf[0] == '\0')
-                lerror(ParseError, "read: invalid gensym label");
-#else
             errno = 0;
             x = strtol(buf, &end, 10);
             if (*end != '\0' || buf[0] == '\0' || errno)
                 lerror(ParseError, "read: invalid gensym label");
-#endif
             toktype = TOK_GENSYM;
             tokval = fixnum(x);
         }