split code into multiple files
[calc.git] / program.c
diff --git a/program.c b/program.c
new file mode 100644 (file)
index 0000000..3c94986
--- /dev/null
+++ b/program.c
@@ -0,0 +1,271 @@
+#include <malloc.h>
+#include <string.h>
+
+#include "alloc.h"
+#include "debug.h"
+#include "parser.h"
+#include "stack.h"
+#include "storage.h"
+
+#include "program.h"
+
+/* global variables */
+
+int argument_size = 0;
+double *argument = NULL;
+
+workspace_t *programs = NULL;
+int nb_programs = 0;
+
+/* program function */
+
+void prog (int id, element_t *root)
+{
+    int i, n = -1;
+
+    if (programs == NULL) {
+
+        /* initial memory allocation */
+        programs = (workspace_t *) callocordie (1, sizeof (workspace_t));
+        nb_programs = 1;
+        n = 0;
+
+    } else {
+
+        /* look for existing program */
+        for (i = 0; i < nb_programs; i++) {
+            if ((programs + i)->id == id) {
+                n = i;
+                break;
+            }
+        }
+        if (n == -1) {
+
+            /* new program */
+            n = nb_programs++;
+            workspace_t *tmp = (workspace_t *) callocordie (nb_programs, sizeof (workspace_t));
+            memcpy (tmp, programs, (nb_programs - 1) * sizeof (workspace_t));
+            free (programs);
+            programs = tmp;
+        } else {
+
+            /* clean old program */
+            if ((programs + n)->storage) {
+                free ((programs + n)->storage);
+            }
+            if ((programs + n)->stack) {
+                free ((programs + n)->stack);
+            }
+            if ((programs + n)->root) {
+                delelement ((programs + n)->root);
+            }
+            if ((programs + n)->string) {
+                free ((programs + n)->string);
+                (programs + n)->string = NULL;
+            }
+        }
+    }
+
+    /* set program */
+    (programs + n)->id = id;
+    (programs + n)->answer = 0;
+    (programs + n)->storage = NULL;
+    (programs + n)->storage_size = 0;
+    (programs + n)->stack = NULL;
+    (programs + n)->stack_size = 0;
+    (programs + n)->root = dupelement (root);
+}
+
+double arg (int id)
+{
+    double ret = 0;
+    if ((id <= 0) || (id > argument_size)) {
+        VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", id, argument_size));
+    } else {
+        ret = argument[id - 1];
+    }
+    return ret;
+}
+
+double call (int id, int nbargs, element_t **args)
+{
+    workspace_t tmp = {0};
+    int i, l, n = -1;
+    double ret = 0;
+
+    if (programs) {
+
+        /* look for program */
+        for (i = 0; i < nb_programs; i++) {
+            if ((programs + i)->id == id) {
+                n = i;
+                break;
+            }
+        }
+    }
+    if (n == -1) {
+        VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
+        return 0;
+    }
+
+    /* store context */
+    tmp.answer = answer;
+    tmp.argument = argument;
+    tmp.argument_size = argument_size;
+    tmp.storage = storage;
+    tmp.storage_size = storage_size;
+    tmp.stack = stack;
+    tmp.stack_size = stack_size;
+
+    /* change context */
+    answer = 0;
+    storage = (programs + n)->storage;
+    storage_size = (programs + n)->storage_size;
+    argument = NULL;
+    argument_size = 0;
+    stack = (programs + n)->stack;
+    stack_size = (programs + n)->stack_size;
+    if (nbargs > 0) {
+        argument = (double *) callocordie (nbargs, sizeof (double));
+        for (i = 0, l = 0; i < nbargs; l++) {
+            if (args[l]) {
+                argument[i++] = evaluate_element (args[l], 0);
+            }
+        }
+        argument_size = nbargs;
+    }
+
+    /* evaluate program */
+    element_t *elements = dupelement ((programs + n)->root);
+    ret = evaluate_element (elements, 0);
+    delelement (elements);
+    (programs + n)->answer = answer;
+    (programs + n)->storage = storage;
+    (programs + n)->storage_size = storage_size;
+    if (argument) {
+        free (argument);
+    }
+    (programs + n)->stack = stack;
+    (programs + n)->stack_size = stack_size;
+
+    /* restore context */
+    answer = tmp.answer;
+    storage = tmp.storage;
+    storage_size = tmp.storage_size;
+    argument = tmp.argument;
+    argument_size = tmp.argument_size;
+    stack = tmp.stack;
+    stack_size = tmp.stack_size;
+
+    return ret;
+}
+
+void list ()
+{
+    int i;
+    fprintf (stdout, "programs:");
+    for (i = 0; i < nb_programs; i++) {
+        fprintf (stdout, " %d", (programs + i)->id);
+    }
+    fprintf (stdout, "\n");
+}
+
+void edit (int id)
+{
+    int i, n = -1;
+
+    if (programs) {
+
+        /* look for program */
+        for (i = 0; i < nb_programs; i++) {
+            if ((programs + i)->id == id) {
+                n = i;
+                break;
+            }
+        }
+    }
+    if (n == -1) {
+        VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
+        return;
+    }
+
+    /* set string program */
+    fprintf (stdout, "edit: %s\n", (programs + n)->string);
+}
+
+void savestring (int id, char *string)
+{
+    int i, n = -1;
+
+    if (programs) {
+
+        /* look for program */
+        for (i = 0; i < nb_programs; i++) {
+            if ((programs + i)->id == id) {
+                n = i;
+                break;
+            }
+        }
+    }
+
+    /* unnecesary code */
+    //if (n == -1) {
+    //    VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
+    //    return;
+    //}
+    //if ((programs + n)->string) {
+    //    free ((programs + n)->string);
+    //}
+
+    if (string) {
+        (programs + n)->string = strdup (string);
+    }
+}
+
+void del (int id)
+{
+    int i, j, n = -1;
+
+    if (programs) {
+
+        /* look for program */
+        for (i = 0; i < nb_programs; i++) {
+            if ((programs + i)->id == id) {
+                n = i;
+                break;
+            }
+        }
+    }
+    if (n == -1) {
+        VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
+        return;
+    }
+
+    /* clean program */
+    if ((programs + n)->storage) {
+        free ((programs + n)->storage);
+    }
+    if ((programs + n)->stack) {
+        free ((programs + n)->stack);
+    }
+    if ((programs + n)->root) {
+        delelement ((programs + n)->root);
+    }
+    if ((programs + n)->string) {
+        free ((programs + n)->string);
+    }
+
+    /* remove entry */
+    workspace_t *tmp = (workspace_t *) callocordie (nb_programs - 1, sizeof (workspace_t));
+    for (i = 0, j = 0; i < nb_programs; i++) {
+        if (i != n) {
+            memcpy (tmp + j, programs + i, sizeof (workspace_t));
+            j++;
+        }
+    }
+    free (programs);
+    programs = tmp;
+    nb_programs--;
+}
+
+/* vim: set ts=4 sw=4 et: */