X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=9e7e51013e3a050f04a8c48c9e28aa1e971be542;hb=a67f1cfd7bb89dfd00cdc099651b81456ca4c327;hp=a1602a0f3b05360e8a34bfb29b7f25f5582e4b86;hpb=9b759869476fd697c534a6c3b126c0ee34a88778;p=calc.git diff --git a/parser.c b/parser.c index a1602a0..9e7e510 100644 --- a/parser.c +++ b/parser.c @@ -21,6 +21,9 @@ double *storage = NULL; char *format = NULL; char *minform = NULL; +workspace_t *programs = NULL; +int nb_programs = 0; + /* compare codes */ int codecmp (char *ref, char *str) @@ -43,21 +46,28 @@ int codecmp (char *ref, char *str) return 0; } -/* allocate new element */ +/* calloc or die function */ -element_t *newelement (func_t function, int nbops, int prio) +void *callocordie (size_t count, size_t size) { - element_t *new = (element_t *) calloc (1, sizeof (element_t)); + 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 **) calloc (nbops, sizeof (element_t *)); - if (new->ops == NULL) { - VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n")); - exit (1); - } + new->ops = (element_t **) callocordie (nbops, sizeof (element_t *)); } new->func = function; new->nbops = nbops; @@ -73,9 +83,7 @@ void delelement (element_t *root) if ((root != NULL) && (root != ERROR_OP)) { int i; for (i = 0; i < root->nbops; i++) { - if ((root->ops[i] != NULL) && (root->ops[i] != ERROR_OP)) { - delelement (root->ops[i]); - } + delelement (root->ops[i]); } if (root->nbops) { free (root->ops); @@ -122,7 +130,7 @@ keyword_t operators[NB_OPERATORS] = { { "|", Or, 2, 1, -2} }; -#define NB_FUNCTIONS 25 +#define NB_FUNCTIONS 31 keyword_t functions[NB_FUNCTIONS] = { { "sqrt", Sqr, 1, 4, 5}, { "pow", Pow, 2, 3, 5}, @@ -143,12 +151,18 @@ keyword_t functions[NB_FUNCTIONS] = { { "dec", Dec, 1, 3, 5}, { "disp", Disp, 0, 4, 9}, { "mem", Mem, 1, 3, 9}, + { "clr", Clear, 0, 3, 9}, { "quit", Quit, 0, 4, 9}, { "help", Help, 0, 4, 9}, { "!", Not, 1, 1, 6}, { "cond", Cond, 3, 4, 5}, { "while", While, 2, 5, 5}, - { "print", Print, 1, 5, 5} + { "print", Print, 1, 5, 5}, + { "prog", Prog, 3, 4, 9}, + { "call", Call, 10, 4, 5}, + { "ls", List, 0, 2, 9}, + { "edit", Edit, 1, 4, 9}, + { "del", Del, 1, 3, 9} }; #define NB_CONSTANTS 3 @@ -190,6 +204,7 @@ element_t *subparser (element_t **proot, char **pstr, func_t func, int nbops, in element_t *parser (char *str, char **next, int prio) { element_t *root = NULL; + char *string = str; int i; VERBOSE (DEBUG, fprintf (stdout, "Starting parsing\n")); @@ -224,10 +239,7 @@ element_t *parser (char *str, char **next, int prio) delelement (root); return ERROR_OP; } - element_t **prog = NULL; - new = newelement (Prog, 0, 5); - root = new; - prog = &root; + root = newelement (Code, 0, 5); do { new = parser (str + 1, &str, 0); @@ -239,14 +251,14 @@ element_t *parser (char *str, char **next, int prio) delelement (root); return ERROR_OP; } - element_t *newprog = newelement (Prog, (*prog)->nbops + 1, 5); - for (i = 0; i < (*prog)->nbops; i++) { - newprog->ops[i] = (*prog)->ops[i]; - (*prog)->ops[i] = NULL; + element_t *newprog = newelement (Code, root->nbops + 1, 5); + for (i = 0; i < root->nbops; i++) { + newprog->ops[i] = root->ops[i]; + root->ops[i] = NULL; } - newprog->ops[(*prog)->nbops] = new; - delelement (*prog); - (*prog) = newprog; + newprog->ops[root->nbops] = new; + delelement (root); + root = newprog; } while (*str == ','); if (*str != '}') { @@ -462,6 +474,11 @@ element_t *parser (char *str, char **next, int prio) *next = str; } + /* save string */ + if (root != NULL) { + root->string = string; + } + return root; } @@ -507,6 +524,7 @@ void print_element (element_t *root, int level) case Dec: func = "Decrease"; break; case Disp: func = "Display"; break; case Mem: func = "Memory"; break; + case Clear: func = "Clear"; break; case Quit: func = "Quit"; break; case Help: func = "Help"; break; case Ans: func = "Ans"; break; @@ -523,8 +541,13 @@ void print_element (element_t *root, int level) case Not: func = "Not"; break; case Cond: func = "Condition"; break; case While: func = "While"; break; - case Prog: func = "Program"; break; + case Code: func = "Code"; break; case Print: func = "Print"; break; + case Prog: func = "Program"; break; + case Call: func = "Call"; break; + case List: func = "List"; break; + case Edit: func = "Edit"; break; + case Del: func = "Del"; break; } fprintf (stdout, "Function: %s\n", func); @@ -549,11 +572,7 @@ void memory (int nb) double *tmp = NULL; if (nb != storage_size) { l = (nb < storage_size) ? nb : storage_size; - tmp = (double *) calloc (nb, sizeof (double)); - if (tmp == NULL) { - VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n")); - exit (1); - } + tmp = (double *) callocordie (nb, sizeof (double)); for (i = 0; i < l; i++) { tmp[i] = storage[i]; } @@ -631,6 +650,14 @@ void display (void) 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) @@ -643,12 +670,15 @@ double while_do (element_t *cond, element_t *action) VERBOSE (DEBUG, fprintf (stdout, "loop...\n")); temp = dupelement (cond); - if (!evaluate_element (temp, 0)) { + double test = evaluate_element (temp, 0); + delelement (temp); + if (!test) { break; } if (action) { temp = dupelement (action); ret = evaluate_element (temp, 0); + delelement (temp); } } @@ -659,13 +689,12 @@ double while_do (element_t *cond, element_t *action) /* program function */ -double program_do (element_t **prog, int nbcalls) +double execute_code (element_t **prog, int nbcalls) { double ret = 0; int i; for (i = 0; i < nbcalls; i++) { ret = evaluate_element (prog[i], 0); - prog[i] = NULL; } return ret; } @@ -709,6 +738,218 @@ void quit (void) exit (0); } +/* program function */ + +void prog (int id, int nbmems, 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)->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 = (double *) callocordie (nbmems, sizeof (double)); + (programs + n)->storage_size = nbmems; + (programs + n)->root = dupelement (root); +} + +double call (int id, int nbops, element_t **ops) +{ + 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; + } + } + } + if (n == -1) { + VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id)); + return 0; + } + + /* store context */ + tmp.answer = answer; + tmp.storage = storage; + tmp.storage_size = storage_size; + + /* change context */ + answer = 0; + storage = (programs + n)->storage; + storage_size = (programs + n)->storage_size; + if (nbops > storage_size) { + double *tmp = (double *) callocordie (nbops, sizeof (double)); + memcpy (tmp, storage, storage_size * sizeof (double)); + free (storage); + (programs + n)->storage = storage = tmp; + (programs + n)->storage_size = storage_size = nbops; + } + for (i = 0; i < nbops; i++) { + double val = evaluate_element (ops[i], 0); + store (i + 1, val); + } + + /* evaluate program */ + element_t *elements = dupelement ((programs + n)->root); + ret = evaluate_element (elements, 0); + delelement (elements); + + /* restore context */ + answer = tmp.answer; + storage = tmp.storage; + storage_size = tmp.storage_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); + //} + + (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)->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--; +} + /* help message */ void help (void) @@ -745,6 +986,7 @@ double evaluate_element (element_t *root, char mask) { double op0 = 0, op1 = 0; char nextmask = mask; + int i, nb; if ((root == NULL) || (root == ERROR_OP)) { VERBOSE (WARNING, fprintf (stdout, "error while evaluating\n")); @@ -791,6 +1033,7 @@ double evaluate_element (element_t *root, char mask) case Lt: case And: case Or: + case Prog: if (root->ops[1]) { op1 = evaluate_element (root->ops[1], nextmask); } else if (root->func != Store) { @@ -816,6 +1059,9 @@ double evaluate_element (element_t *root, char mask) case Not: case Mem: case Cond: + case Call: + case Edit: + case Del: if (root->ops[0]) { op0 = evaluate_element (root->ops[0], 0); } else { @@ -824,12 +1070,14 @@ double evaluate_element (element_t *root, char mask) } break; case Disp: + case Clear: case Quit: case Help: case Ans: case Pi: case E: - case Prog: + case Code: + case List: break; case While: if (root->ops[0] == NULL) { @@ -869,6 +1117,7 @@ double evaluate_element (element_t *root, char mask) case Dec: return decrease ((int)op0); case Disp: display (); break; case Mem: memory ((int)op0); break; + case Clear: clear (); break; case Quit: quit (); break; case Help: help (); break; case Ans: return answer; @@ -892,8 +1141,22 @@ double evaluate_element (element_t *root, char mask) return 0; } case While: return while_do (root->ops[0], root->ops[1]); - case Prog: return program_do (root->ops, root->nbops); + case Code: return execute_code (root->ops, root->nbops); case Print: return print (op0); + case Prog: + prog ((int)op0, (int)op1, root->ops[2]); + savestring ((int)op0, root->string); + break; + case Call: + for (i = 1, nb =0; i < root->nbops; i++) { + if (root->ops[i]) { + nb++; + } + } + return call ((int)op0, nb, root->ops + 1); + case List: list (); break; + case Edit: edit ((int)op0); break; + case Del: del ((int)op0); break; } return 0; @@ -902,11 +1165,7 @@ double evaluate_element (element_t *root, char mask) char **generate_completion_list () { int i, j, l = 0; - char **list = (char **) calloc (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *)); - if (list == NULL) { - VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n")); - exit (1); - } + char **list = (char **) callocordie (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *)); for (i = 0; i < NB_OPERATORS; i++) { list[l] = strdup ((operators + i)->keyword); @@ -949,7 +1208,7 @@ void free_completion_list (char **list) int i; if (list) { - for (i = 0; i < NB_FUNCTIONS + NB_CONSTANTS; i++) { + for (i = 0; i < NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1; i++) { if (list[i] != NULL) { free (list[i]); }