fix an incorrect free
[calc.git] / program.c
index c5b8231929394303669b5cab32b27b3b75830897..b93a90cb299538f1dc0b79b0ae2223baba7c6021 100644 (file)
--- a/program.c
+++ b/program.c
 #include <string.h>
 
 #include "alloc.h"
+#include "argument.h"
 #include "debug.h"
 #include "parser.h"
 #include "stack.h"
 #include "storage.h"
+#include "tabular.h"
+#include "workspace.h"
 
 #include "program.h"
 
 /* global variables */
 
-int argument_size = 0;
-double *argument = NULL;
-
-workspace_t *programs = NULL;
+workspace_t **programs = NULL;
 int nb_programs = 0;
 
+/* lookfor program id */
+
+int lookfor_program (int id)
+{
+    int i;
+    for (i = 0; (programs) && (i < nb_programs); i++) {
+        if (programs[i]->id == id) {
+            return i;
+        }
+    }
+    return -1;
+}
+
 /* program function */
 
 void prog (int id, element_t *root)
 {
-    int i, n = -1;
+    int n = -1;
 
     if (programs == NULL) {
 
         /* initial memory allocation */
-        programs = (workspace_t *) callocordie (1, sizeof (workspace_t));
-        nb_programs = 1;
+        programs = (workspace_t **) callocordie (1, sizeof (workspace_t *));
         n = 0;
+        nb_programs = 1;
+        programs[n] = alloc_ws ();
 
     } else {
 
         /* look for existing program */
-        for (i = 0; i < nb_programs; i++) {
-            if ((programs + i)->id == id) {
-                n = i;
-                break;
-            }
-        }
+        n = lookfor_program (id);
         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));
+            workspace_t **tmp = (workspace_t **) callocordie (nb_programs, sizeof (workspace_t *));
+            memcpy (tmp, programs, (nb_programs - 1) * sizeof (workspace_t *));
             free (programs);
             programs = tmp;
+            programs[n] = alloc_ws ();
+
         } 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;
-            }
+            clean_ws(programs[n]);
         }
     }
 
     /* 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;
+    programs[n]->id = id;
+    programs[n]->root = dupelement (root);
 }
 
 double call (int id, int nbargs, element_t **args)
 {
-    workspace_t tmp = {0};
-    int i, l, n = -1;
+    int i;
     double ret = 0;
 
-    if (programs) {
+    VERBOSE (DEBUG, fprintf (stdout, "new call (%d)\n", id));
 
-        /* look for program */
-        for (i = 0; i < nb_programs; i++) {
-            if ((programs + i)->id == id) {
-                n = i;
-                break;
-            }
-        }
-    }
+    /* look for program */
+    int n = lookfor_program (id);
     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;
+    /* display debug information */
+    VERBOSE (DEBUG, fprintf (stdout, "nbargs: %d\n", nbargs));
+    for (i = 0; i < nbargs; i++) {
+        VERBOSE (DEBUG, fprintf (stdout, "argument %d\n", i + 1); print_element (args[i], 0));
+    }
+    VERBOSE (DEBUG, fprintf (stdout, "program\n"); print_element (programs[n]->root, 0));
+
+    /* backup context */
+    workspace_t *tmp = backup_ws (alloc_ws ());
+    restore_ws (programs[n]);
 
-    /* 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;
+    /* set arguments */
+    VERBOSE (DEBUG, fprintf (stdout, "argument before evaluation (%d)\n", size_tab (argument)));
+    for (i = 0; i < size_tab (argument); i++) {
+        VERBOSE (DEBUG, fprintf (stdout, "arg %d value: %g\n", i + 1, get_tab (argument, i + 1)));
+    }
+    VERBOSE (DEBUG, fprintf (stdout, "evaluate %d args\n", nbargs));
+    tab_t *new_argument = def (nbargs, args);
+    tab_t *old_argument = argument;
+    argument = new_argument;
+    VERBOSE (DEBUG, fprintf (stdout, "argument after evaluation (%d)\n", size_tab (argument)));
+    for (i = 0; i < size_tab (argument); i++) {
+        VERBOSE (DEBUG, fprintf (stdout, "arg %d value: %g\n", i + 1, get_tab (argument, i + 1)));
     }
 
     /* evaluate program */
-    element_t *elements = dupelement ((programs + n)->root);
+    answer = 0;
+    element_t *elements = dupelement (programs[n]->root);
     ret = evaluate_element (elements, 0);
+    VERBOSE (DEBUG, fprintf (stdout, "ret; %g\n", ret));
     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;
+    backup_ws (programs[n]);
+    restore_ws (tmp);
+    free_ws (tmp);
+
+    /* clean arguments */
+    free_tab (argument);
+    argument = old_argument;
 
     return ret;
 }
@@ -164,109 +132,66 @@ double call (int id, int nbargs, element_t **args)
 void list ()
 {
     int i;
-    fprintf (stdout, "programs:");
+    printf ("programs:");
     for (i = 0; i < nb_programs; i++) {
-        fprintf (stdout, " %d", (programs + i)->id);
+        printf (" %d", programs[i]->id);
     }
-    fprintf (stdout, "\n");
+    printf ("\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;
-            }
-        }
-    }
+    extern char *edit_line;
+    int n = lookfor_program (id);
     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);
+    if (edit_line) {
+        free (edit_line);
+    }
+    edit_line = strdup (programs[n]->string);
+    //printf ("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;
-            }
-        }
-    }
+    int n = lookfor_program (id);
 
     /* 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 (programs[n]->string) {
+    //    free (programs[n]->string);
     //}
 
     if (string) {
-        (programs + n)->string = strdup (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;
-            }
-        }
-    }
+    int n = lookfor_program (id);
     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);
-    }
+    free_ws (programs[n]);
 
     /* 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++;
-        }
-    }
+    workspace_t **tmp = (workspace_t **) callocordie (nb_programs - 1, sizeof (workspace_t *));
+    memcpy (tmp, programs, n * sizeof (workspace_t *));
+    memcpy (tmp + n, programs + n + 1, (nb_programs - n - 1) * sizeof (workspace_t *));
+    nb_programs--;
     free (programs);
     programs = tmp;
-    nb_programs--;
 }
 
 /* vim: set ts=4 sw=4 et: */