add worspace type
authorLaurent Mazet <mazet@softndesign.org>
Mon, 13 Feb 2023 23:05:41 +0000 (00:05 +0100)
committerLaurent Mazet <mazet@softndesign.org>
Mon, 13 Feb 2023 23:05:41 +0000 (00:05 +0100)
calc.c
program.c
program.h
tabular.c
workspace.c [new file with mode: 0644]
workspace.h [new file with mode: 0644]

diff --git a/calc.c b/calc.c
index 920099b46a504c1fc88cd6d3ce733705ebd67584..d444ab109da5220baa4202fd8de061a3074d57d1 100644 (file)
--- a/calc.c
+++ b/calc.c
@@ -1,6 +1,6 @@
 /* depend: */
 /* cflags: */
-/* linker: alloc.o argument.o debug.o element.o format.o parser.o program.o stack.o storage.o tabular.o -lm -lreadline */
+/* linker: alloc.o argument.o debug.o element.o format.o parser.o program.o stack.o storage.o tabular.o workspace.o -lm -lreadline */
 
 #include <malloc.h>
 #include <stddef.h>
index 18a9719d3a318be6819dd5483f5f4a5a92e4cd30..e8cd2d1301379c1f6efffebafaa7985b258f67bf 100644 (file)
--- a/program.c
+++ b/program.c
 #include "stack.h"
 #include "storage.h"
 #include "tabular.h"
+#include "workspace.h"
 
 #include "program.h"
 
 /* global variables */
 
-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_tab ((programs + n)->storage);
-            }
-            if ((programs + n)->stack) {
-                free_tab ((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)->stack = NULL;
-    (programs + n)->root = dupelement (root);
+    programs[n]->id = id;
+    programs[n]->root = dupelement (root);
 }
 
 double call (int id, int nbargs, element_t **args)
 {
-    workspace_t tmp = {0};
-    int i, 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;
-            }
-        }
-    }
+    /* 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.stack = stack;
-    tmp.storage = storage;
-
-    /* change context */
-    answer = 0;
+    /* backup context */
+    workspace_t *tmp = backup_ws (alloc_ws ());
+    restore_ws (programs[n]);
+    
+    /* set arguments */
+    free_tab (argument);
     argument = NULL;
     if (nbargs > 0) {
         def (nbargs, args);
     }
-    stack = (programs + n)->stack;
-    storage = (programs + n)->storage;
 
     /* evaluate program */
-    element_t *elements = dupelement ((programs + n)->root);
+    answer = 0;
+    element_t *elements = dupelement (programs[n]->root);
     ret = evaluate_element (elements, 0);
     delelement (elements);
 
-    /* cleaning context */
-    (programs + n)->answer = answer;
+    /* clean arguments */
     if (argument) {
         free_tab (argument);
     }
-    (programs + n)->stack = stack;
-    (programs + n)->storage = storage;
+    argument = NULL;
+    if (nbargs > 0) {
+        def (nbargs, args);
+    }
 
     /* restore context */
-    answer = tmp.answer;
-    argument = tmp.argument;
-    storage = tmp.storage;
-    stack = tmp.stack;
+    backup_ws (programs[n]);
+    restore_ws (tmp);
 
     return ret;
 }
@@ -137,107 +120,62 @@ void list ()
     int i;
     fprintf (stdout, "programs:");
     for (i = 0; i < nb_programs; i++) {
-        fprintf (stdout, " %d", (programs + i)->id);
+        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;
-            }
-        }
-    }
+    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);
+    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;
-            }
-        }
-    }
+    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_tab ((programs + n)->storage);
-    }
-    if ((programs + n)->stack) {
-        free_tab ((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, sizeof (workspace_t *));
+    if (n != 0) {
+        memcpy (tmp, programs, (n - 1) * sizeof (workspace_t));
+    }
+    if (n != nb_programs) {
+        memcpy (tmp + n - 1, programs + n, (nb_programs - n) * sizeof (workspace_t));
     }
     free (programs);
     programs = tmp;
-    nb_programs--;
 }
 
 /* vim: set ts=4 sw=4 et: */
index d830b7f1f57ce46d0b8e8e18d4ec3d74f5cbe13f..f3f5369981795ba5e49c87e607c960c92d2a44d8 100644 (file)
--- a/program.h
+++ b/program.h
@@ -3,22 +3,11 @@
 
 #include "element.h"
 #include "tabular.h"
+#include "workspace.h"
 
 /* global variables */
 
-/* workspace type */
-
-typedef struct _workspace_t {
-    double answer;
-    tab_t *argument;
-    int id;
-    element_t *root;
-    tab_t *stack;
-    tab_t *storage;
-    char *string;
-} workspace_t;
-
-extern workspace_t *programs;
+extern workspace_t **programs;
 extern int nb_programs;
 
 /* program function */
index 0252a8e8ec1bf82aad5e3f6a723db40644fe35de..60709aa9dd5d8409c8b0b41776f212f1a76a72c4 100644 (file)
--- a/tabular.c
+++ b/tabular.c
@@ -43,6 +43,9 @@ tab_t *resize_tab (tab_t *tab, int nb)
 
 tab_t *copy_tab (tab_t *tab)
 {
+    if (tab == NULL) {
+        return NULL;
+    }
     tab_t *new = alloc_tab (tab->size);
     memcpy (new->data, tab->data, tab->size * sizeof (double));
     return new;
diff --git a/workspace.c b/workspace.c
new file mode 100644 (file)
index 0000000..26bbe8a
--- /dev/null
@@ -0,0 +1,100 @@
+#include <malloc.h>
+#include <stdio.h>
+
+#include "argument.h"
+#include "debug.h"
+#include "element.h"
+#include "parser.h"
+#include "stack.h"
+#include "storage.h"
+#include "tabular.h"
+
+#include "workspace.h"
+
+/* allocate workspace*/
+
+workspace_t *alloc_ws ()
+{
+    return (workspace_t *) callocordie (1, sizeof (workspace_t));
+}
+
+/* backup workspace*/
+
+workspace_t *backup_ws (workspace_t *ws)
+{
+    ws->answer = answer;
+    ws->argument = copy_tab (argument);
+    ws->stack = copy_tab (stack);
+    ws->storage = copy_tab (storage);
+    return ws;
+}
+
+/* clean workspace */
+
+workspace_t *clean_ws (workspace_t *ws)
+{
+    ws->answer = 0;
+
+    if (ws->argument) {
+        free_tab (ws->argument);
+        ws->argument = NULL;
+    }
+
+    ws->id = 0;
+
+    if (ws->root) {
+        delelement (ws->root);
+        ws->root = NULL;
+    }
+
+    if (ws->stack) {
+        free_tab (ws->stack);
+        ws->stack = NULL;
+    }
+
+    if (ws->string) {
+        free (ws->string);
+        ws->string = NULL;
+    }
+
+    if (ws->storage) {
+        free_tab (ws->storage);
+        ws->storage = NULL;
+    }
+
+    return ws;
+}
+
+/* free workspace */
+
+void free_ws (workspace_t *ws)
+{
+    if (ws) {
+        clean_ws (ws);
+        free (ws);
+    }
+}
+
+/* restore workspace*/
+
+void restore_ws (workspace_t *ws)
+{
+    answer = ws->answer;
+
+    if (argument) {
+        free_tab (argument);
+    }
+    argument = copy_tab (ws->argument);
+
+    if (stack) {
+        free_tab (stack);
+    }
+    stack = copy_tab (ws->stack);
+
+    if (storage) {
+        free_tab (storage);
+    }
+    storage = copy_tab (ws->storage);
+}
+
+/* vim: set ts=4 sw=4 et: */
diff --git a/workspace.h b/workspace.h
new file mode 100644 (file)
index 0000000..7bca4e0
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __WORKSPACE_H__
+#define __WORKSPACE_H__
+
+#include "element.h"
+#include "tabular.h"
+
+/* global variables */
+
+/* workspace type */
+
+typedef struct _workspace_t {
+    double answer;
+    tab_t *argument;
+    int id;
+    element_t *root;
+    tab_t *stack;
+    tab_t *storage;
+    char *string;
+} workspace_t;
+
+/* workspace functions */
+
+workspace_t *alloc_ws ();
+workspace_t *backup_ws (workspace_t *ws);
+workspace_t *clean_ws (workspace_t *ws);
+void free_ws (workspace_t *ws);
+void restore_ws (workspace_t *ws);
+
+#endif /*  __WORKSPACE_H__ */
+
+/* vim: set ts=4 sw=4 et: */