clean fprintf
[calc.git] / parser.c
index eba4fb7cf62e635927735e9912ad66bb9e734d12..0f4e6418e46593fe9afd14ed4fb4b63a09fe3109 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -4,6 +4,7 @@
 #include <string.h>
 
 #include "alloc.h"
+#include "argument.h"
 #include "debug.h"
 #include "element.h"
 #include "format.h"
@@ -61,7 +62,7 @@ keyword_t operators[NB_OPERATORS] = {
     { "|",   Or, 2, 1, -2}
 };
 
-#define NB_FUNCTIONS 50
+#define NB_FUNCTIONS 52
 keyword_t functions[NB_FUNCTIONS] = {
     { "sqrt", Sqr, 1, 4, 5},
     { "pow",  Pow, 2, 3, 5},
@@ -84,7 +85,7 @@ keyword_t functions[NB_FUNCTIONS] = {
     { "inc",  Inc, 1, 3, 5},
     { "dec",  Dec, 1, 3, 5},
     { "disp", Disp, 0, 4, 9},
-    { "mem",  Mem, 1, 3, 5},
+    { "mem",  Memory, 1, 3, 5},
     { "clr",  Clear, 0, 3, 9},
     { "quit", Quit, 0, 4, 9},
     { "help", Help, 0, 4, 9},
@@ -113,6 +114,8 @@ keyword_t functions[NB_FUNCTIONS] = {
     { "prod", Prod, 0, 4, 5},
     { "sum",  Sum, 0, 3, 5},
     { "var",  Variance, 2, 3, 5},
+    { "format", Precision, 1, 6, 9},
+    { "base", Base, 2, 4, 9}
 };
 
 #define NB_CONSTANTS 3
@@ -369,51 +372,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 = (get_ibase () == 10) ? strtod (str, &pt) : strtoul (str, &pt, get_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 */
 
@@ -448,7 +448,7 @@ void print_element (element_t *root, int level)
     }
 
     for (i = 0; i < level; i++) {
-        fprintf (stdout, " ");
+        printf (" ");
     }
 
     switch (root->func) {
@@ -480,7 +480,7 @@ void print_element (element_t *root, int level)
     case Inc: func = "Increase"; break;
     case Dec: func = "Decrease"; break;
     case Disp: func = "Display"; break;
-    case Mem: func = "Memory"; break;
+    case Memory: func = "Memory"; break;
     case Clear: func = "Clear"; break;
     case Quit: func = "Quit"; break;
     case Help: func = "Help"; break;
@@ -521,15 +521,17 @@ void print_element (element_t *root, int level)
     case Prod: func = "Product"; break;
     case Sum: func = "Sum"; break;
     case Variance: func = "Variance"; break;
+    case Precision: func = "Precision"; break;
+    case Base: func = "Base"; break;
     }
 
-    fprintf (stdout, "Function: %s\n", func);
+    printf ("Function: %s\n", func);
 
     if ((root->func == Val) && (root->ops[0] == NULL)) {
         for (i = 0; i < level; i++) {
-            fprintf (stdout, " ");
+            printf (" ");
         }
-        fprintf (stdout, "value: %f\n", root->value);
+        printf ("value: %f\n", root->value);
     } else {
         for (i = 0; i < root->nbops; i++) {
             print_element (root->ops[i], level + 1);
@@ -582,7 +584,7 @@ double execute_code (element_t **prog, int nbcalls)
 
 void quit (void)
 {
-    fprintf (stdout, "bye\n");
+    printf ("bye\n");
     exit (0);
 }
 
@@ -590,35 +592,67 @@ void quit (void)
 
 void help (void)
 {
-    fprintf (stdout, "calc is a simple calculator\n\n");
-    fprintf (stdout, "arithmetic op.:");
-    fprintf (stdout, " + - * / %% ^\n");
-    fprintf (stdout, "comparison op.:");
-    fprintf (stdout, " == != >= <= > <\n");
-    fprintf (stdout, "logical op.:");
-    fprintf (stdout, " & | !\n");
-    fprintf (stdout, "mathematic func.:");
-    fprintf (stdout, " exp ln log pow sqrt\n");
-    fprintf (stdout, "trigonometric func.:");
-    fprintf (stdout, " acos asin atan cos sin tan\n");
-    fprintf (stdout, "error functions:");
-    fprintf (stdout, " erf erfc\n");
-    fprintf (stdout, "miscellaneous func.:");
-    fprintf (stdout, " abs ceil floor\n");
-    fprintf (stdout, "storage func.:");
-    fprintf (stdout, " clear dec disp inc mem rcl sto\n");
-    fprintf (stdout, "control flow prim.:");
-    fprintf (stdout, " cond print while {} ;\n");
-    fprintf (stdout, "program management:");
-    fprintf (stdout, " arg call del edit ls prog\n");
-    fprintf (stdout, "stack management:");
-    fprintf (stdout, " get len pop push put set show\n");
-    fprintf (stdout, "stack func.:");
-    fprintf (stdout, " max mean med min ord prod sum var\n");
-    fprintf (stdout, "control management:");
-    fprintf (stdout, " help quit\n");
-    fprintf (stdout, "constants:");
-    fprintf (stdout, " ans e pi\n");
+    printf ("calc is a simple calculator\n\n");
+    printf ("arithmetic op.:");
+    printf (" + - * / %% ^\n");
+    printf ("comparison op.:");
+    printf (" == != >= <= > <\n");
+    printf ("logical op.:");
+    printf (" & | !\n");
+    printf ("mathematic func.:");
+    printf (" exp ln log pow sqrt\n");
+    printf ("trigonometric func.:");
+    printf (" acos asin atan cos sin tan\n");
+    printf ("error functions:");
+    printf (" erf erfc\n");
+    printf ("miscellaneous func.:");
+    printf (" abs ceil floor\n");
+    printf ("storage func.:");
+    printf (" clear dec disp inc mem rcl sto\n");
+    printf ("control flow prim.:");
+    printf (" cond print while {} ;\n");
+    printf ("program management:");
+    printf (" arg call del edit ls prog\n");
+    printf ("stack management:");
+    printf (" get len pop push put set show\n");
+    printf ("stack func.:");
+    printf (" max mean med min ord prod sum var\n");
+    printf ("control management:");
+    printf (" base format help quit\n");
+    printf ("constants:");
+    printf (" ans e pi\n");
+}
+
+/* format function */
+
+int format (int precision)
+{
+    if (precision > 0) {
+        set_precision (precision);
+        set_format ();
+    } else if (precision != -1) {
+        VERBOSE (WARNING, fprintf (stdout, "error incorrect precision (%d)\n", precision));
+        return 0;
+    }
+    return get_precision ();
+}
+
+/* base function */
+
+void base (int in, int out)
+{
+    if ((in > 0) && (in < 37)) {
+        set_base (in, in);
+        if ((out > 0) && (out < 37)) {
+            set_base (in, out);
+        } else if (out != - 1) {
+            VERBOSE (WARNING, fprintf (stdout, "error incorrect output base (%d)\n", out));
+        }
+    } else if (in != -1 ) {
+        VERBOSE (WARNING, fprintf (stdout, "error incorrect input base (%d)\n", in));
+    } else {
+        printf ("base (I/O): %s\n", show_base ());
+    }
 }
 
 /* evaluate element tree */
@@ -668,7 +702,6 @@ double evaluate_element (element_t *root, char mask)
     case Div:
     case Mod:
     case Pow:
-    case Store:
     case Equal:
     case Diff:
     case Ge:
@@ -679,7 +712,7 @@ double evaluate_element (element_t *root, char mask)
     case Or:
         if (root->ops[1]) {
             op1 = evaluate_element (root->ops[1], nextmask);
-        } else if (root->func != Store) {
+        } else {
             VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n"));
             return 0;
         }
@@ -703,7 +736,6 @@ double evaluate_element (element_t *root, char mask)
     case Inc:
     case Dec:
     case Not:
-    case Mem:
     case Cond:
     case Prog:
     case Arg:
@@ -742,10 +774,22 @@ double evaluate_element (element_t *root, char mask)
             return 0;
         }
         break;
+    case Memory:
+        if (root->ops[0] == NULL) {
+            op0 = -1;
+        } else {
+            op0 = (int)evaluate_element (root->ops[0], 0);
+            if (op0 < 0) {
+                VERBOSE (WARNING, fprintf (stdout, "error incorrect memory size (%d)\n", (int)op0));
+                return 0;
+            }
+        }
+        break;
     case Push:
     case Print:
         op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer;
         break;
+    case Store:
     case Put:
         if (root->ops[0]) {
             op0 = evaluate_element (root->ops[0], 0);
@@ -763,6 +807,14 @@ double evaluate_element (element_t *root, char mask)
             op0 = evaluate_element (root->ops[0], 0);
             op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
         }
+        break;
+    case Precision:
+        op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : -1;
+        break;
+    case Base:
+        op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : -1;
+        op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : -1;
+        break;
     }
 
     switch (root->func) {
@@ -789,12 +841,12 @@ double evaluate_element (element_t *root, char mask)
     case Abs: return fabs (op0);
     case Ceil: return ceil (op0);
     case Floor: return floor (op0);
-    case Store: return store ((int)op0, (op1) ? op1 : answer);
+    case Store: return store ((int)op0, op1);
     case Recall: return recall ((int)op0);
     case Inc: return increase ((int)op0);
     case Dec: return decrease ((int)op0);
     case Disp: display (); break;
-    case Mem: memory ((int)op0); break;
+    case Memory: return memory ((root->ops[0]) ? (int)op0 : -1);
     case Clear: clear (); break;
     case Quit: quit (); break;
     case Help: help (); break;
@@ -827,7 +879,7 @@ double evaluate_element (element_t *root, char mask)
         break;
     case Arg: return arg ((int)op0);
     case Call:
-        for (i = 1, nb =0; i < root->nbops; i++) {
+        for (i = 1, nb = 0; i < root->nbops; i++) {
             if (root->ops[i]) {
                 nb++;
             }
@@ -876,6 +928,11 @@ double evaluate_element (element_t *root, char mask)
             return op0 * op0 + op1 * op1;
         }
         return variance ();
+    case Precision:
+        return format ((int)op0);
+    case Base:
+        base ((int)op0, (int)op1);
+        break;
     }
 
     return 0;