From a24bd5195f9990159a974c98751f1473f29b9fa4 Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Thu, 9 Feb 2023 00:02:46 +0100 Subject: [PATCH] split code into multiple files --- alloc.c | 23 ++ alloc.h | 10 + calc.c | 4 +- element.c | 58 +++++ element.h | 60 +++++ format.c | 42 ++++ format.h | 19 ++ parser.c | 690 +----------------------------------------------------- parser.h | 77 +----- program.c | 271 +++++++++++++++++++++ program.h | 41 ++++ stack.c | 241 +++++++++++++++++++ stack.h | 35 +++ storage.c | 111 +++++++++ storage.h | 22 ++ 15 files changed, 947 insertions(+), 757 deletions(-) create mode 100644 alloc.c create mode 100644 alloc.h create mode 100644 element.c create mode 100644 element.h create mode 100644 format.c create mode 100644 format.h create mode 100644 program.c create mode 100644 program.h create mode 100644 stack.c create mode 100644 stack.h create mode 100644 storage.c create mode 100644 storage.h diff --git a/alloc.c b/alloc.c new file mode 100644 index 0000000..888f23b --- /dev/null +++ b/alloc.c @@ -0,0 +1,23 @@ +#include +#include + +#include "debug.h" + +#include "alloc.h" + +/* calloc or die function */ + +void *callocordie (size_t count, size_t size) +{ + if (count * size == 0) { + return NULL; + } + void *new = calloc (count, size); + if (new == NULL) { + VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n")); + exit (1); + } + return new; +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/alloc.h b/alloc.h new file mode 100644 index 0000000..9f95e69 --- /dev/null +++ b/alloc.h @@ -0,0 +1,10 @@ +#ifndef __ALLOC_H__ +#define __ALLOC_H__ + +#include + +void *callocordie (size_t count, size_t size); + +#endif /* __ALLOC_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/calc.c b/calc.c index 97b2159..4ef05d7 100644 --- a/calc.c +++ b/calc.c @@ -1,6 +1,6 @@ /* depend: */ /* cflags: */ -/* linker: debug.o parser.o -lm -lreadline */ +/* linker: alloc.o debug.o element.o format.o parser.o program.o stack.o storage.o -lm -lreadline */ #include #include @@ -12,6 +12,8 @@ #include #include "debug.h" +#include "element.h" +#include "format.h" #include "parser.h" /* constants */ diff --git a/element.c b/element.c new file mode 100644 index 0000000..19c30df --- /dev/null +++ b/element.c @@ -0,0 +1,58 @@ +#include + +#include "alloc.h" + +#include "element.h" + +/* global variables */ + +/* allocate new element */ + +element_t *newelement (func_t function, int nbops, int prio) +{ + element_t *new = (element_t *) callocordie (1, sizeof (element_t)); + if (nbops) { + new->ops = (element_t **) callocordie (nbops, sizeof (element_t *)); + } + new->func = function; + new->nbops = nbops; + new->prio = prio; + + return new; +} + +/* desallocate element */ + +void delelement (element_t *root) +{ + if ((root != NULL) && (root != ERROR_OP)) { + int i; + for (i = 0; i < root->nbops; i++) { + delelement (root->ops[i]); + } + if (root->nbops) { + free (root->ops); + } + free (root); + } +} + +/* duplicate element */ + +element_t *dupelement (element_t *root) +{ + element_t *tmp = NULL; + int i; + + if ((root == NULL) || (root == ERROR_OP)) { + return root; + } + tmp = newelement (root->func, root->nbops, root->prio); + tmp->value = root->value; + for (i = 0; i < root->nbops; i++) { + tmp->ops[i] = dupelement (root->ops[i]); + } + return tmp; +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/element.h b/element.h new file mode 100644 index 0000000..c36c559 --- /dev/null +++ b/element.h @@ -0,0 +1,60 @@ +#ifndef __ELEMENT_H__ +#define __ELEMENT_H__ + +/* global variables */ + +/* function type */ + +typedef enum { + Val = 0, Sig, + Add, Sub, + Mul, Div, Mod, + Pow, Sqr, + Cos, Sin, Tan, Acos, Asin, Atan, + Ln, Log, Exp, + Erfc, Erf, + Abs, Ceil, Floor, + Store, Recall, Inc, Dec, Disp, Mem, Clear, + Quit, Help, + Ans, E, Pi, + Equal, Diff, Ge, Le, Gt, Lt, + And, Or, Not, + Cond, While, Code, Print, + Prog, Arg, Call, List, Edit, Del, + Get, Length, Pop, Push, Put, Set, Show, + Max, Mean, Median, Min, Order, Prod, Sum, Variance +} func_t; + +/* keyword type */ + +typedef struct _keyword_t { + char *keyword; + func_t func; + int nbops; + int offset; + float prio; +} keyword_t; + +/* calculus element type */ + +typedef struct _element_t { + func_t func; + int nbops; + struct _element_t **ops; + double value; + int prio; + int hidden; + char *string; +} element_t; + +#define ERROR_OP ((element_t *)(-1)) + +/* functions */ + +element_t *newelement (func_t function, int nbops, int prio); +void delelement (element_t *root); +element_t *dupelement (element_t *root); + +#endif /* __ELEMENT_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/format.c b/format.c new file mode 100644 index 0000000..48cc56f --- /dev/null +++ b/format.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "format.h" + +/* global variables */ + +#define DEFAULT_FORMAT "=> %.6g\n" +char *format = NULL; +char *minform = NULL; + +/* print function */ + +void set_format (char *prompt, int precision) +{ + char buffer[128] = {0}; + free_format (); + sprintf (buffer, "%s%%.%dg\n", prompt, precision); + format = strdup (buffer); + sprintf (buffer, "%%.%dg", precision); + minform = strdup (buffer); +} + +void free_format () +{ + if (format) { + free (format); + format = NULL; + } + if (minform) { + free (minform); + minform = NULL; + } +} + +double print (double value) +{ + fprintf (stdout, format ? format : DEFAULT_FORMAT, value); + fflush (stdout); + return value; +} diff --git a/format.h b/format.h new file mode 100644 index 0000000..9849205 --- /dev/null +++ b/format.h @@ -0,0 +1,19 @@ +#ifndef __FORMAT_H__ +#define __FORMAT_H__ + +/* global variables */ + +extern char *format; +extern char *minform; + +/* print function */ + +void set_format (char *prompt, int precision); + +void free_format (); + +double print (double value); + +#endif /* __FORMAT_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/parser.c b/parser.c index 223b173..eba4fb7 100644 --- a/parser.c +++ b/parser.c @@ -1,10 +1,15 @@ -#include #include #include #include #include +#include "alloc.h" #include "debug.h" +#include "element.h" +#include "format.h" +#include "program.h" +#include "stack.h" +#include "storage.h" #include "parser.h" @@ -12,23 +17,6 @@ double answer = 0; -#define DEFAULT_STORAGE_SIZE 10 -int storage_size = -1; -double *storage = NULL; - -int argument_size = 0; -double *argument = NULL; - -int stack_size = 0; -double *stack = NULL; - -#define DEFAULT_FORMAT "=> %.6g\n" -char *format = NULL; -char *minform = NULL; - -workspace_t *programs = NULL; -int nb_programs = 0; - /* compare codes */ int codecmp (char *ref, char *str) @@ -51,70 +39,6 @@ int codecmp (char *ref, char *str) return 0; } -/* calloc or die function */ - -void *callocordie (size_t count, size_t size) -{ - if (count * size == 0) { - return NULL; - } - void *new = calloc (count, size); - if (new == NULL) { - VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n")); - exit (1); - } - return new; -} - -/* allocate new element */ - -element_t *newelement (func_t function, int nbops, int prio) -{ - element_t *new = (element_t *) callocordie (1, sizeof (element_t)); - if (nbops) { - new->ops = (element_t **) callocordie (nbops, sizeof (element_t *)); - } - new->func = function; - new->nbops = nbops; - new->prio = prio; - - return new; -} - -/* desallocate element */ - -void delelement (element_t *root) -{ - if ((root != NULL) && (root != ERROR_OP)) { - int i; - for (i = 0; i < root->nbops; i++) { - delelement (root->ops[i]); - } - if (root->nbops) { - free (root->ops); - } - free (root); - } -} - -/* duplicate element */ - -element_t *dupelement (element_t *root) -{ - element_t *tmp = NULL; - int i; - - if ((root == NULL) || (root == ERROR_OP)) { - return root; - } - tmp = newelement (root->func, root->nbops, root->prio); - tmp->value = root->value; - for (i = 0; i < root->nbops; i++) { - tmp->ops[i] = dupelement (root->ops[i]); - } - return tmp; -} - /* functions */ #define MAX_ARGS 100 @@ -613,100 +537,6 @@ void print_element (element_t *root, int level) } } -/* storage functions */ - -void memory (int nb) -{ - int i, l; - double *tmp = NULL; - if (nb != storage_size) { - l = (nb < storage_size) ? nb : storage_size; - tmp = (double *) callocordie (nb, sizeof (double)); - for (i = 0; i < l; i++) { - tmp[i] = storage[i]; - } - if (storage != NULL) { - free (storage); - } - storage = tmp; - storage_size = nb; - } -} - -double store (int index, double value) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - storage[index - 1] = value; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return value; -} - -double recall (int index) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - return storage[index - 1]; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return 0; -} - -double increase (int index) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - return storage[index - 1]++; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return 0; -} - -double decrease (int index) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - return storage[index - 1]--; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return 0; -} - -void display (void) -{ - int i; - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - fprintf (stdout, "storage:"); - for (i = 0; i < storage_size; i++) { - fprintf (stdout, " "); - fprintf (stdout, minform, storage[i]); - } - fprintf (stdout, "\n"); -} - -void clear () -{ - int i; - for (i = 0; i < storage_size; i++) { - storage[i] = 0; - } -} - /* While do function */ double while_do (element_t *cond, element_t *action) @@ -748,37 +578,6 @@ double execute_code (element_t **prog, int nbcalls) return ret; } -/* print function */ - -void set_format (char *prompt, int precision) -{ - char buffer[128] = {0}; - free_format (); - sprintf (buffer, "%s%%.%dg\n", prompt, precision); - format = strdup (buffer); - sprintf (buffer, "%%.%dg", precision); - minform = strdup (buffer); -} - -void free_format () -{ - if (format) { - free (format); - format = NULL; - } - if (minform) { - free (minform); - minform = NULL; - } -} - -double print (double value) -{ - fprintf (stdout, format ? format : DEFAULT_FORMAT, value); - fflush (stdout); - return value; -} - /* quit function */ void quit (void) @@ -787,482 +586,6 @@ void quit (void) exit (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--; -} - -/* stack management */ - -double get (int n) -{ - double ret = 0; - if ((n <= 0) || (n > stack_size)) { - VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); - } else { - ret = stack[n - 1]; - } - return ret; -} - -double length () -{ - return stack_size; -} - -double pop () -{ - double ret = 0; - if (stack_size > 0) { - ret = stack[--stack_size]; - double *tmp = (double *) callocordie (stack_size, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - free (stack); - stack = tmp; - } else { - VERBOSE (WARNING, fprintf (stdout, "error stack empty\n")); - } - return ret; -} - -double push (double val) -{ - double *tmp = (double *) callocordie (stack_size + 1, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - if (stack) { - free (stack); - } - stack = tmp; - stack[stack_size++] = val; - return val; -} - -double put (int n, double val) -{ - if (n <= 0) { - VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); - return 0; - } - if (n > stack_size) { - double *tmp = (double *) callocordie (n, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - free (stack); - stack = tmp; - stack_size = n; - } - stack[n - 1] = val; - return val; -} - -double set (int nbops, element_t **ops) -{ - int i; - if (stack) { - free (stack); - } - stack = NULL; - stack_size = 0; - if (nbops != 0) { - stack = (double *) callocordie (nbops, sizeof (double)); - for (i = 0; i < nbops; i++) { - stack[i] = evaluate_element (ops[i], 0); - } - stack_size = nbops; - } - return stack_size; -} - -void show (void) -{ - int i; - fprintf (stdout, "stack:"); - for (i = 0; i < stack_size; i++) { - fprintf (stdout, " "); - fprintf (stdout, minform, stack[i]); - } - fprintf (stdout, "\n"); -} - -/* stack functions */ - -double max () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - ret = stack[0]; - for (i = 1; i < stack_size; i++) { - if (stack[i] > ret) { - ret = stack[i]; - } - } - return ret; -} - -double mean () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - for (i = 0; i < stack_size; i++) { - ret += stack[i]; - } - return ret / stack_size; -} - -double min () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - ret = stack[0]; - for (i = 1; i < stack_size; i++) { - if (stack[i] < ret) { - ret = stack[i]; - } - } - return ret; -} - -void order () -{ - int i, j; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return; - } - for (i = 0; i < stack_size - 1; i++) { - int done = 0; - for (j = 0; j < stack_size - 1; j++) { - if (stack[j] > stack[j + 1]) { - double tmp = stack[j]; - stack[j] = stack[j + 1]; - stack[j + 1] = tmp; - done = 1; - } - } - if (done == 0) { - break; - } - } -} - -double median () -{ - double ret = 0; - if (stack_size < 3) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - double *tmp = (double *) callocordie (stack_size, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - order (); - ret = stack[(stack_size - 1)/ 2]; - memcpy (stack, tmp, stack_size * sizeof (double)); - free (tmp); - return ret; -} - -double prod () -{ - double ret = 1; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - for (i = 0; i < stack_size; i++) { - ret *= stack[i]; - } - return ret; -} - -double sum () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - for (i = 0; i < stack_size; i++) { - ret += stack[i]; - } - return ret; -} - -double variance () -{ - double ret = 0; - double m = 0; - int i; - if (stack_size < 2) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - m = mean (); - for (i = 0; i < stack_size; i++) { - ret += (stack[i] - m) * (stack[i] - m); - } - return ret / stack_size; -} - - /* help message */ void help (void) @@ -1613,5 +936,4 @@ void free_completion_list (char **list) } } - /* vim: set ts=4 sw=4 et: */ diff --git a/parser.h b/parser.h index 27bc1e1..9ce4fd0 100644 --- a/parser.h +++ b/parser.h @@ -1,70 +1,17 @@ #ifndef __PARSER_H__ #define __PARSER_H__ +#include "element.h" + /* global variables */ extern double answer; -/* function type */ - -typedef enum { - Val = 0, Sig, - Add, Sub, - Mul, Div, Mod, - Pow, Sqr, - Cos, Sin, Tan, Acos, Asin, Atan, - Ln, Log, Exp, - Erfc, Erf, - Abs, Ceil, Floor, - Store, Recall, Inc, Dec, Disp, Mem, Clear, - Quit, Help, - Ans, E, Pi, - Equal, Diff, Ge, Le, Gt, Lt, - And, Or, Not, - Cond, While, Code, Print, - Prog, Arg, Call, List, Edit, Del, - Get, Length, Pop, Push, Put, Set, Show, - Max, Mean, Median, Min, Order, Prod, Sum, Variance -} func_t; - -/* keyword type */ - -typedef struct _keyword_t { - char *keyword; - func_t func; - int nbops; - int offset; - float prio; -} keyword_t; - -/* calculus element type */ - -typedef struct _element_t { - func_t func; - int nbops; - struct _element_t **ops; - double value; - int prio; - int hidden; - char *string; -} element_t; - -#define ERROR_OP ((element_t *)(-1)) +/* completion functions */ -/* workspace type */ +char **generate_completion_list (); -typedef struct _workspace_t { - int id; - double answer; - double *storage; - int storage_size; - double *argument; - int argument_size; - element_t *root; - double *stack; - int stack_size; - char *string; -} workspace_t; +void free_completion_list (char **list); /* parser function */ @@ -76,20 +23,6 @@ void print_element (element_t *root, int level); double evaluate_element (element_t *root, char mask); -/* completion functions */ - -char **generate_completion_list (); - -void free_completion_list (char **list); - -/* print function */ - -void set_format (char *prompt, int precision); - -void free_format (); - -double print (double value); - #endif /* __PARSER_H__ */ /* vim: set ts=4 sw=4 et: */ diff --git a/program.c b/program.c new file mode 100644 index 0000000..3c94986 --- /dev/null +++ b/program.c @@ -0,0 +1,271 @@ +#include +#include + +#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: */ diff --git a/program.h b/program.h new file mode 100644 index 0000000..8fdca14 --- /dev/null +++ b/program.h @@ -0,0 +1,41 @@ +#ifndef __PROGRAM_H__ +#define __PROGRAM_H__ + +#include "element.h" + +/* global variables */ + +extern int argument_size; +extern double *argument; + +/* workspace type */ + +typedef struct _workspace_t { + int id; + double answer; + double *storage; + int storage_size; + double *argument; + int argument_size; + element_t *root; + double *stack; + int stack_size; + char *string; +} workspace_t; + +extern workspace_t *programs; +extern int nb_programs; + +/* program function */ + +void prog (int id, element_t *root); +double arg (int id); +double call (int id, int nbargs, element_t **args); +void list (); +void edit (int id); +void savestring (int id, char *string); +void del (int id); + +#endif /* __PROGRAM_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/stack.c b/stack.c new file mode 100644 index 0000000..5c203ed --- /dev/null +++ b/stack.c @@ -0,0 +1,241 @@ +#include +#include +#include + +#include "alloc.h" +#include "debug.h" +#include "format.h" +#include "parser.h" + +#include "stack.h" + +/* global variables */ + +int stack_size = 0; +double *stack = NULL; + +/* stack management */ + +double get (int n) +{ + double ret = 0; + if ((n <= 0) || (n > stack_size)) { + VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); + } else { + ret = stack[n - 1]; + } + return ret; +} + +double length () +{ + return stack_size; +} + +double pop () +{ + double ret = 0; + if (stack_size > 0) { + ret = stack[--stack_size]; + double *tmp = (double *) callocordie (stack_size, sizeof (double)); + memcpy (tmp, stack, stack_size * sizeof (double)); + free (stack); + stack = tmp; + } else { + VERBOSE (WARNING, fprintf (stdout, "error stack empty\n")); + } + return ret; +} + +double push (double val) +{ + double *tmp = (double *) callocordie (stack_size + 1, sizeof (double)); + memcpy (tmp, stack, stack_size * sizeof (double)); + if (stack) { + free (stack); + } + stack = tmp; + stack[stack_size++] = val; + return val; +} + +double put (int n, double val) +{ + if (n <= 0) { + VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); + return 0; + } + if (n > stack_size) { + double *tmp = (double *) callocordie (n, sizeof (double)); + memcpy (tmp, stack, stack_size * sizeof (double)); + free (stack); + stack = tmp; + stack_size = n; + } + stack[n - 1] = val; + return val; +} + +double set (int nbops, element_t **ops) +{ + int i; + if (stack) { + free (stack); + } + stack = NULL; + stack_size = 0; + if (nbops != 0) { + stack = (double *) callocordie (nbops, sizeof (double)); + for (i = 0; i < nbops; i++) { + stack[i] = evaluate_element (ops[i], 0); + } + stack_size = nbops; + } + return stack_size; +} + +void show (void) +{ + int i; + fprintf (stdout, "stack:"); + for (i = 0; i < stack_size; i++) { + fprintf (stdout, " "); + fprintf (stdout, minform, stack[i]); + } + fprintf (stdout, "\n"); +} + +/* stack functions */ + +double max () +{ + double ret = 0; + int i; + if (stack_size < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return 0; + } + ret = stack[0]; + for (i = 1; i < stack_size; i++) { + if (stack[i] > ret) { + ret = stack[i]; + } + } + return ret; +} + +double mean () +{ + double ret = 0; + int i; + if (stack_size < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return 0; + } + for (i = 0; i < stack_size; i++) { + ret += stack[i]; + } + return ret / stack_size; +} + +double min () +{ + double ret = 0; + int i; + if (stack_size < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return 0; + } + ret = stack[0]; + for (i = 1; i < stack_size; i++) { + if (stack[i] < ret) { + ret = stack[i]; + } + } + return ret; +} + +void order () +{ + int i, j; + if (stack_size < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return; + } + for (i = 0; i < stack_size - 1; i++) { + int done = 0; + for (j = 0; j < stack_size - 1; j++) { + if (stack[j] > stack[j + 1]) { + double tmp = stack[j]; + stack[j] = stack[j + 1]; + stack[j + 1] = tmp; + done = 1; + } + } + if (done == 0) { + break; + } + } +} + +double median () +{ + double ret = 0; + if (stack_size < 3) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return 0; + } + double *tmp = (double *) callocordie (stack_size, sizeof (double)); + memcpy (tmp, stack, stack_size * sizeof (double)); + order (); + ret = stack[(stack_size - 1)/ 2]; + memcpy (stack, tmp, stack_size * sizeof (double)); + free (tmp); + return ret; +} + +double prod () +{ + double ret = 1; + int i; + if (stack_size < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return 0; + } + for (i = 0; i < stack_size; i++) { + ret *= stack[i]; + } + return ret; +} + +double sum () +{ + double ret = 0; + int i; + if (stack_size < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return 0; + } + for (i = 0; i < stack_size; i++) { + ret += stack[i]; + } + return ret; +} + +double variance () +{ + double ret = 0; + double m = 0; + int i; + if (stack_size < 2) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + return 0; + } + m = mean (); + for (i = 0; i < stack_size; i++) { + ret += (stack[i] - m) * (stack[i] - m); + } + return ret / stack_size; +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/stack.h b/stack.h new file mode 100644 index 0000000..e3f0c44 --- /dev/null +++ b/stack.h @@ -0,0 +1,35 @@ +#ifndef __STACK_H__ +#define __STACK_H__ + +#include "element.h" + +/* global variables */ + +extern int stack_size; + +extern double *stack; + +/* stack management */ + +double get (int n); +double length (); +double pop (); +double push (double val); +double put (int n, double val); +double set (int nbops, element_t **ops); +void show (void); + +/* stack functions */ + +double max (); +double mean (); +double min (); +void order (); +double median (); +double prod (); +double sum (); +double variance (); + +#endif /* __STACK_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/storage.c b/storage.c new file mode 100644 index 0000000..80ebf0a --- /dev/null +++ b/storage.c @@ -0,0 +1,111 @@ +#include +#include + +#include "alloc.h" +#include "debug.h" +#include "format.h" + +#include "storage.h" + +/* global variables */ + +#define DEFAULT_STORAGE_SIZE 10 +double *storage = NULL; + +int storage_size = -1; + +/* storage functions */ + +void memory (int nb) +{ + int i, l; + double *tmp = NULL; + if (nb != storage_size) { + l = (nb < storage_size) ? nb : storage_size; + tmp = (double *) callocordie (nb, sizeof (double)); + for (i = 0; i < l; i++) { + tmp[i] = storage[i]; + } + if (storage != NULL) { + free (storage); + } + storage = tmp; + storage_size = nb; + } +} + +double store (int index, double value) +{ + if (storage_size == -1) { + memory (DEFAULT_STORAGE_SIZE); + } + if ((index > 0) && (index <= storage_size)) { + storage[index - 1] = value; + } else { + VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); + } + return value; +} + +double recall (int index) +{ + if (storage_size == -1) { + memory (DEFAULT_STORAGE_SIZE); + } + if ((index > 0) && (index <= storage_size)) { + return storage[index - 1]; + } else { + VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); + } + return 0; +} + +double increase (int index) +{ + if (storage_size == -1) { + memory (DEFAULT_STORAGE_SIZE); + } + if ((index > 0) && (index <= storage_size)) { + return storage[index - 1]++; + } else { + VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); + } + return 0; +} + +double decrease (int index) +{ + if (storage_size == -1) { + memory (DEFAULT_STORAGE_SIZE); + } + if ((index > 0) && (index <= storage_size)) { + return storage[index - 1]--; + } else { + VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); + } + return 0; +} + +void display (void) +{ + int i; + if (storage_size == -1) { + memory (DEFAULT_STORAGE_SIZE); + } + fprintf (stdout, "storage:"); + for (i = 0; i < storage_size; i++) { + fprintf (stdout, " "); + fprintf (stdout, minform, storage[i]); + } + fprintf (stdout, "\n"); +} + +void clear () +{ + int i; + for (i = 0; i < storage_size; i++) { + storage[i] = 0; + } +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/storage.h b/storage.h new file mode 100644 index 0000000..3a6ef86 --- /dev/null +++ b/storage.h @@ -0,0 +1,22 @@ +#ifndef __STORAGE_H__ +#define __STORAGE_H__ + +/* global variables */ + +extern double *storage; + +extern int storage_size; + +/* storage functions */ + +void memory (int nb); +double store (int index, double value); +double recall (int index); +double increase (int index); +double decrease (int index); +void display (void); +void clear (); + +#endif /* __STORAGE_H__ */ + +/* vim: set ts=4 sw=4 et: */ -- 2.30.2