new option: base
authorLaurent Mazet <mazet@softndesign.org>
Mon, 27 Feb 2023 14:09:41 +0000 (15:09 +0100)
committerLaurent Mazet <mazet@softndesign.org>
Mon, 27 Feb 2023 14:09:41 +0000 (15:09 +0100)
calc.c
format.c
format.h
parser.c

diff --git a/calc.c b/calc.c
index 2c5ae637657748720df42a0199044593004a9fb5..6043346c3d97ac7c97ae18505b592a58d94343f3 100644 (file)
--- a/calc.c
+++ b/calc.c
@@ -43,7 +43,8 @@ int usage (int ret)
     FILE *fid = ret ? stderr : stdout;
     fprintf (fid, "usage: %s\n", progname);
     fprintf (fid, " -h : help message\n");
-    fprintf (fid, " -i : input prompt (%s)\n", iprompt);
+    fprintf (fid, " -b : in/out-put base (%d-%d)\n", ibase, obase);
+    fprintf (fid, " -n : no readline mode (%s)\n", mode ? "yes" : "no");
     fprintf (fid, " -n : no readline mode (%s)\n", mode ? "yes" : "no");
     fprintf (fid, " -o : output prompt (%s)\n", oprompt);
     fprintf (fid, " -p : precision (%d)\n", precision);
@@ -129,9 +130,13 @@ int main (int argc, char *argv[])
         }
         char c = arg[1];
         switch (c) {
-        case 'n':
-            mode = 0;
-            buffer = buffer_static;
+        case 'b':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ERROR, fprintf (stderr, "%s: missing base definition\n", progname); usage (1));
+                return 1;
+            }
+            ibase = obase = atoi (arg);
             break;
         case 'i':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
@@ -141,6 +146,10 @@ int main (int argc, char *argv[])
             }
             iprompt = arg;
             break;
+        case 'n':
+            mode = 0;
+            buffer = buffer_static;
+            break;
         case 'o':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
             if (arg == NULL) {
@@ -429,6 +438,9 @@ int main (int argc, char *argv[])
 // test: echo -e 'format (12)\n.12345678901' | calc.exe | grep -n '=> 0.12345678901'
 // test: echo -e 'format (4)\n.12345678901\format' | calc.exe | grep -n '=> 4'
 // test: echo -e 'format (0)' | calc.exe | grep -n 'error'
+// test: echo -e 'ff + ff' | calc.exe -b 16 | grep -q '=> 1fe'
+// test: echo -e '60 / 4' | calc.exe -b 8 | grep -q '=> 14'
+// test: echo -e 'z00-z0+1-2*z+20x' | calc.exe -b 36 | grep -q '=> 1000'
 
 // Gauss sequence
 // test: echo -e '{sto (1, 0), sto (10, 0), while (inc (10) <= 100, {sto (1, rcl (1) + rcl (10)), print (rcl (1))})};' | calc.exe | grep -q '=> 5050'
index 152875022ad8a10f826378c7d611a5abd5d6edd4..4b9e6cf5ebeefce69d9b085a3118cf7676579da0 100644 (file)
--- a/format.c
+++ b/format.c
@@ -6,6 +6,9 @@
 
 /* global variables */
 
+int ibase = 10;
+int obase = 10;
+
 #define DEFAULT_FORMAT "=> %.6g\n"
 char *_format = NULL;
 #define DEFAULT_MINFORM "%.6g"
@@ -67,16 +70,53 @@ void free_format ()
     }
 }
 
+
+char *itoa (unsigned long value)
+{
+    static char str[8 * sizeof (long) + 1];
+
+    /* decompose */
+    char buffer[8 * sizeof (long) + 1] = {0};
+    int size = 0;
+    do {
+        char x = value % obase;
+        buffer[size++] = (x > 9) ? 'a' + x - 10 : '0' + x;
+        value /= obase;
+    } while (value != 0);
+
+    /* revert */
+    int i;
+    for (i = 0; i < size; i++) {
+        str[i] = buffer [size - i - 1];
+    }
+    str[size] = '\0';
+
+    return str;
+}
+
+/* vim: set ts=4 sw=4 et: */
+
+
+
+
 double print (double value)
 {
-    fprintf (stdout, _format ? _format : DEFAULT_FORMAT, value);
+    if (obase == 10) {
+        fprintf (stdout, _format ? _format : DEFAULT_FORMAT, value);
+    } else {
+        fprintf (stdout, "%s%s\n", (_prompt) ? _prompt : DEFAULT_PROMPT, itoa ((unsigned int)value));
+    }
     fflush (stdout);
     return value;
 }
 
 double printl (double value)
 {
-    fprintf (stdout, _minform ? _minform : DEFAULT_MINFORM, value);
+    if (obase == 10) {
+        fprintf (stdout, _minform ? _minform : DEFAULT_MINFORM, value);
+    } else {
+        fprintf (stdout, "%s%s", (_prompt) ? _prompt : DEFAULT_PROMPT, itoa ((unsigned int)value));
+    }
     fflush (stdout);
     return value;
 }
index dbbaec1ff3b54585311ced76fb96572063c713b9..d2f8f4ff0fc69fd655a41b125df4d1e30bbcf22b 100644 (file)
--- a/format.h
+++ b/format.h
@@ -3,6 +3,9 @@
 
 /* global variables */
 
+extern int ibase;
+extern int obase;
+
 /* print function */
 
 void set_precision (int precision);
index b9823abaa25f10acd08cc4f40e2667a2e94ea902..94f4c73fd0d752910b28d70ca02261c81446ea65 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -371,51 +371,48 @@ element_t *parser (char *str, char **next, int prio)
 
         /* look for number */
 
-        if (((*str >= '0') && (*str <= '9')) ||
-            (*str == '.') || (*str == '+') || (*str == '-')) {
-            VERBOSE (DEBUG, fprintf (stdout, "start processing value\n"));
-            char *pt;
-            double value = strtod (str, &pt);
-            VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value));
-            if (str != pt) {
-                if ((root == NULL) || (root->prio == 6)) {
-                    new = newelement (Val, 1, 5);
-                    new->value = value;
-                    if (root == NULL) {
-                        root = new;
-                    } else {
-                        for (i = 0; i < root->nbops; i++) {
-                            if (root->ops[i] == NULL) {
-                                root->ops[i] = new;
-                                found = 1;
-                                break;
-                            }
-                        }
-                        if (!found) {
-                            delelement (new);
-                            delelement (root);
-                            return ERROR_OP;
+        VERBOSE (DEBUG, fprintf (stdout, "start processing value\n"));
+        char *pt;
+        double value = (ibase == 10) ? strtod (str, &pt) : strtoul (str, &pt, ibase);
+        VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value));
+        if (str != pt) {
+            if ((root == NULL) || (root->prio == 6)) {
+                new = newelement (Val, 1, 5);
+                new->value = value;
+                if (root == NULL) {
+                    root = new;
+                } else {
+                    for (i = 0; i < root->nbops; i++) {
+                        if (root->ops[i] == NULL) {
+                            root->ops[i] = new;
+                            found = 1;
+                            break;
                         }
                     }
-                    str = pt;
-                } else if ((*str == '+') || (*str == '-')) {
-                    if ((prio) && (prio > 1)) {
-                        VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
-                        *next = str;
-                        return root;
-                    }
-                    if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) {
+                    if (!found) {
+                        delelement (new);
                         delelement (root);
                         return ERROR_OP;
                     }
-                } else {
+                }
+                str = pt;
+            } else if ((*str == '+') || (*str == '-')) {
+                if ((prio) && (prio > 1)) {
+                    VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
+                    *next = str;
+                    return root;
+                }
+                if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) {
                     delelement (root);
                     return ERROR_OP;
                 }
-                found = 1;
+            } else {
+                delelement (root);
+                return ERROR_OP;
             }
-            VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n"));
+            found = 1;
         }
+        VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n"));
 
         /* error */