X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=9e7e51013e3a050f04a8c48c9e28aa1e971be542;hb=a67f1cfd7bb89dfd00cdc099651b81456ca4c327;hp=395e2aea1e90642757ab4cf6fb2d891058d479a1;hpb=c7cbb833c65805634f6e9832b49e4a4680a4a4a6;p=calc.git diff --git a/parser.c b/parser.c index 395e2ae..9e7e510 100644 --- a/parser.c +++ b/parser.c @@ -22,6 +22,7 @@ char *format = NULL; char *minform = NULL; workspace_t *programs = NULL; +int nb_programs = 0; /* compare codes */ @@ -45,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; @@ -75,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); @@ -198,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")); @@ -232,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); @@ -247,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 != '}') { @@ -470,6 +474,11 @@ element_t *parser (char *str, char **next, int prio) *next = str; } + /* save string */ + if (root != NULL) { + root->string = string; + } + return root; } @@ -532,7 +541,7 @@ 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; @@ -563,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]; } @@ -665,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); } } @@ -681,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; } @@ -734,21 +741,214 @@ void quit (void) /* 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 { -double call (int id, int nbobs, element_t **ops) + /* 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) { - return 0; + 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 */ @@ -786,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")); @@ -859,7 +1060,6 @@ double evaluate_element (element_t *root, char mask) case Mem: case Cond: case Call: - case List: case Edit: case Del: if (root->ops[0]) { @@ -876,7 +1076,8 @@ double evaluate_element (element_t *root, char mask) case Ans: case Pi: case E: - case Prog: + case Code: + case List: break; case While: if (root->ops[0] == NULL) { @@ -940,13 +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]); break; - case Call: return call ((int)op0, root->nbops + 1, root->ops + 1); + 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; + case Del: del ((int)op0); break; } return 0; @@ -955,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); @@ -1002,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]); }