From: Laurent Mazet Date: Wed, 8 Feb 2023 23:02:46 +0000 (+0100) Subject: split code into multiple files X-Git-Tag: v1.1~3^2~15 X-Git-Url: https://secure.softndesign.org/git/?a=commitdiff_plain;h=a24bd5195f9990159a974c98751f1473f29b9fa4;p=calc.git split code into multiple files --- 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: */