From 20a645614be5667c1c32169e837b97c067156edb Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Mon, 27 Feb 2023 15:09:41 +0100 Subject: [PATCH] new option: base --- calc.c | 20 +++++++++++++---- format.c | 44 +++++++++++++++++++++++++++++++++++-- format.h | 3 +++ parser.c | 67 +++++++++++++++++++++++++++----------------------------- 4 files changed, 93 insertions(+), 41 deletions(-) diff --git a/calc.c b/calc.c index 2c5ae63..6043346 100644 --- 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' diff --git a/format.c b/format.c index 1528750..4b9e6cf 100644 --- 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; } diff --git a/format.h b/format.h index dbbaec1..d2f8f4f 100644 --- 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); diff --git a/parser.c b/parser.c index b9823ab..94f4c73 100644 --- 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 */ -- 2.30.2