diff options
author | mongo <mongo@iomega> | 2016-05-06 14:59:46 -0300 |
---|---|---|
committer | mongo <mongo@iomega> | 2016-05-06 14:59:46 -0300 |
commit | ae2606bfa49ca65a0e5ebe40d025328e56e18ebf (patch) | |
tree | d754d29f81f25fff09f2dc4760f5ff48af11edc1 | |
parent | aac40d577f60c835c97ccf8d240a6d647bd1d78b (diff) |
added dep_graph
-rw-r--r-- | CHANGES | 10 | ||||
-rw-r--r-- | Readme.md | 2 | ||||
-rw-r--r-- | src/cmds.c | 53 | ||||
-rw-r--r-- | src/cmds_normal.c | 38 | ||||
-rwxr-xr-x | src/dep_graph.c | 388 | ||||
-rwxr-xr-x | src/dep_graph.h | 38 | ||||
-rw-r--r-- | src/filter.c | 1 | ||||
-rw-r--r-- | src/interp.c | 704 | ||||
-rw-r--r-- | src/interp.h | 116 | ||||
-rw-r--r-- | src/main.c | 38 | ||||
-rw-r--r-- | src/sc.h | 53 | ||||
-rw-r--r-- | src/screen.c | 4 | ||||
-rw-r--r-- | src/version.h | 2 |
13 files changed, 971 insertions, 476 deletions
@@ -1,3 +1,13 @@ +v0.4.0 +* Fix de memory leak en funciones que usan seval. ej.: dosval docat. esto tambien sucedia en SC! +* Chain cells with equations into a new graph structure. +* Change how cell expressions are evaluated. +* new function to rebuilt graph +* Added free() call in GOTO in gram.y +* Added free() call in SORT in gram.y +* Added rebuild_graph, print_graph, undo and redo to gram.y +* Added function to remove elements in dep_graph. (specific vertex and linked edges) + v0.3.0 * FIX when importing large CSV files * SC-IM now supports wide chars, enabling the use of different alphabets. @@ -31,7 +31,7 @@ SC-IM stands for Spreadsheet Calculator Improvised. :-) * Edit Makefile file according to your system and needs. ``` - vim Makefile + vim /src/Makefile ``` * Only for OSX users do: @@ -15,6 +15,7 @@ #include "vmtbl.h" // for growtbl #include "utils/string.h" // for add_char #include "y.tab.h" // for yyparse +#include "dep_graph.h" #ifdef UNDO #include "undo.h" #endif @@ -24,6 +25,8 @@ extern unsigned int shall_quit; char insert_edit_submode; struct ent * freeents = NULL; // keep deleted ents around before sync_refs wchar_t interp_line[BUFFERSIZE]; +extern graphADT graph; + // mark_ent_as_deleted (free_ents en sc original): // This structure is used to keep ent structs around before they @@ -82,31 +85,31 @@ void sync_refs() { void syncref(register struct enode *e) { if ( e == (struct enode *) 0 ) { //if ( e == NULL || e->op == ERR_ ) { - return; + return; } else if (e->op & REDUCE) { - e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col); - e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col); + e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col); + e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col); } else { - switch (e->op) { + switch (e->op) { case 'v': - //if (e->e.v.vp->flags & iscleared) { - if (e->e.v.vp->flags & is_deleted) { - e->op = ERR_; - //sc_info("%d %d", e->e.v.vp->row, e->e.v.vp->col); - e->e.o.left = NULL; - e->e.o.right = NULL; - } else if (e->e.v.vp->flags & may_sync) - e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col); - break; + //if (e->e.v.vp->flags & iscleared) { + if (e->e.v.vp->flags & is_deleted) { + e->op = ERR_; + //sc_info("%d %d", e->e.v.vp->row, e->e.v.vp->col); + e->e.o.left = NULL; + e->e.o.right = NULL; + } else if (e->e.v.vp->flags & may_sync) + e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col); + break; case 'k': - break; + break; case '$': - break; + break; default: - syncref(e->e.o.right); - syncref(e->e.o.left); + syncref(e->e.o.right); + syncref(e->e.o.left); break; - } + } } return; } @@ -289,18 +292,19 @@ void erase_area(int sr, int sc, int er, int ec, int ignorelock) { sc = 0; checkbounds(&er, &ec); + // mark the ent as delete // Do a lookat() for the upper left and lower right cells of the range // being erased to make sure they are included in the delete buffer so // that pulling cells always works correctly even if the cells at one // or more edges of the range are all empty. - (void) lookat(sr, sc); (void) lookat(er, ec); - for (r = sr; r <= er; r++) { for (c = sc; c <= ec; c++) { pp = ATBL(tbl, r, c); if (*pp && (!((*pp)->flags & is_locked) || ignorelock)) { + /* delete vertex in graph */ + if (getVertex(graph, *pp, 0) != NULL) destroy_vertex(*pp); mark_ent_as_deleted(*pp); *pp = NULL; } @@ -965,7 +969,7 @@ void insert_or_edit_cell() { char * opt = get_conf_value("newline_action"); switch (opt[0]) { case 'j': - currow = forw_row(1)->row; + currow = forw_row(1)->row; break; case 'l': curcol = forw_col(1)->col; @@ -1574,9 +1578,12 @@ int is_single_command (struct block * buf, long timeout) { else if (buf->value == L'>') res = MOVEMENT_CMD; else if (buf->value == L'=') res = MOVEMENT_CMD; else if (buf->value == L'e') res = MOVEMENT_CMD; - else if (buf->value == L'E') res = MOVEMENT_CMD; else if (buf->value == L'v') res = MOVEMENT_CMD; + else if (buf->value == L'Q') res = MOVEMENT_CMD; //TEST + else if (buf->value == L'A') res = MOVEMENT_CMD; //TEST + else if (buf->value == L'W') res = MOVEMENT_CMD; //TEST + // movement commands else if (buf->value == L'j') res = MOVEMENT_CMD; else if (buf->value == L'k') res = MOVEMENT_CMD; @@ -1616,7 +1623,7 @@ int is_single_command (struct block * buf, long timeout) { else if (buf->value == L'x') res = EDITION_CMD; // cuts a cell else if (buf->value == L'u') res = EDITION_CMD; // undo else if (buf->value == ctl('r')) res = EDITION_CMD; // redo - else if (buf->value == L'@') res = EDITION_CMD; // EvallAll + else if (buf->value == L'@') res = EDITION_CMD; // EvalAll else if (buf->value == L'{') res = EDITION_CMD; else if (buf->value == L'}') res = EDITION_CMD; else if (buf->value == L'|') res = EDITION_CMD; diff --git a/src/cmds_normal.c b/src/cmds_normal.c index 60d0683..3c88b43 100644 --- a/src/cmds_normal.c +++ b/src/cmds_normal.c @@ -1,5 +1,5 @@ #include <ctype.h> -#include <stdlib.h> +#include <stdlib.h> #include "yank.h" #include "marks.h" #include "cmds.h" @@ -17,6 +17,12 @@ #include "undo.h" #endif + +#include "dep_graph.h" +extern graphADT graph; +extern char valores; + + extern int cmd_multiplier; extern struct history * commandline_history; extern void start_visualmode(int tlrow, int tlcol, int brrow, int brcol); @@ -27,6 +33,36 @@ void do_normalmode(struct block * buf) { struct ent * e; switch (buf->value) { + // TEST + case L'A': + print_vertexs(graph); + break; + + case L'Q': + //scim_RealEval(); + //destroy_graph(graph); + //graph = NULL; + destroy_vertex(lookat(8, 3)); + break; + + case L'W': + rebuild_graph(); +// GraphAddEdge( getVertex(graph, lookat(0, 0)), getVertex(graph, lookat(0,4)) ) ; +// GraphAddEdge( getVertex(graph, lookat(0, 4)), getVertex(graph, lookat(2,2)) ) ; +// GraphAddEdge( getVertex(graph, lookat(8, 5)), getVertex(graph, lookat(0,0)) ) ; +// GraphAddEdge( getVertex(graph, lookat(2, 2)), getVertex(graph, lookat(2,3)) ) ; +// GraphAddEdge( getVertex(graph, lookat(2, 3)), getVertex(graph, lookat(1,1)) ) ; + +// markAllVerticesNotVisited(graph); +// ents_that_depends_on(graph, lookat(2, 2)); +// show_text(&valores); + break; + + + + + + // MOVEMENT COMMANDS case L'j': diff --git a/src/dep_graph.c b/src/dep_graph.c new file mode 100755 index 0000000..7bfb04d --- /dev/null +++ b/src/dep_graph.c @@ -0,0 +1,388 @@ +#include <stdio.h> +#include <stdlib.h> +#include "dep_graph.h" +#include "interp.h" +#include "screen.h" // for show_text + +/****************************************************************************** + * This file contains all functions used for maintaining a dependence graph + * that keeps track of all the cells that depends on each other. + * this is done in a two way relationship. + * + * A vertex represents an ent and has in "edges", links to other vertex's(ents) which the first vertex depends on. + * + * The other relationship is "back_edges". This is a pointer to other vertex's and + * there you will keep linked all the vertex's that use the first vertex in their formulas. + * In other words, you will keep track of all the vertex's that depends on the first vertex. + *******************************************************************************/ +#define CREATE_NEW(type) (type *) malloc(sizeof(type)) + +#define APPEND_TO_LINKLIST(firstNode, newNode, tempNode) \ + if( firstNode == NULL ) { \ + firstNode = newNode ; \ + } \ + else { \ + tempNode = firstNode; \ + while (tempNode->next != NULL) { \ + tempNode = tempNode->next; \ + } \ + tempNode->next = newNode; \ + } + +/* LINKS: + * https://www.cs.bu.edu/teaching/c/graph/linked/ + * https://github.com/Chetan496/cpp-algortihms/blob/master/graph.c + */ + +graphADT graph; + + +/* Creates an empty graph, with no vertices. Allocate memory from the heap */ +graphADT GraphCreate() { + graphADT emptyGraph = (graphCDT *) malloc(sizeof(graphCDT)); + emptyGraph->vertices = NULL; + return emptyGraph; +} + + +/* this adds the vertex sorted in the list + * and not at the end + * given a row & col to insert as a new vertex, this function will create a new vertex with those values + * and add it order in the list! + * returns a pointer to the new vertex + */ +vertexT * GraphAddVertex(graphADT graph , struct ent * ent) { + vertexT * newVertex = (vertexT *) malloc(sizeof(vertexT)); + newVertex->visited = 0; + newVertex->ent = ent; + newVertex->edges = NULL; + newVertex->back_edges = NULL; + newVertex->next = NULL; + + vertexT * temp_ant = NULL; + vertexT * tempNode = NULL; + + // first element added to the list + if( graph->vertices == NULL) { + graph->vertices = newVertex ; + + // append in first position + } else if (ent->row < graph->vertices->ent->row || (ent->row == graph->vertices->ent->row && ent->col < graph->vertices->ent->col)) { + newVertex->next = graph->vertices; + graph->vertices = newVertex ; + + // append in second position or after that + } else { + tempNode = graph->vertices; + temp_ant = tempNode; + while (tempNode != NULL && (ent->row > tempNode->ent->row || (ent->row == tempNode->ent->row && ent->col > tempNode->ent->col) ) ) { + temp_ant = tempNode; + tempNode = temp_ant->next; + } + temp_ant->next = newVertex; + newVertex->next = tempNode; + } + //scinfo("Added the vertex %d %d in the graph", row, col) ; + return newVertex; +} + + +/* This looks for a vertex representing a specific ent in a sorted list + * we search for a vertex in graph and return it if found. + * if not found and create flag, we add the vertex (malloc it) and return it + * else if not found, it returns NULL + */ +vertexT * getVertex(graphADT graph, struct ent * ent, int create) { + if (graph == NULL) return NULL; + vertexT * temp = graph->vertices; + while (temp != NULL && (temp->ent->row < ent->row || (temp->ent->row == ent->row && temp->ent->col <= ent->col))) { + if (temp->ent->row == ent->row && temp->ent->col == ent->col) return temp; + temp = temp->next; + } + + // if we get to here, there is not vertex representing ent + // we add it if create is set to true! + return create ? GraphAddVertex(graph, ent) : NULL; +} + + +/* This function adds a edge in our graph from the vertex "from" to the vertex "to" */ +// should add edges ordered in list ? +void GraphAddEdge(vertexT * from, vertexT * to) { + if (from == NULL || to == NULL) { + sc_info("Error while adding edge: either of the vertices do not exist") ; + return; + } + // do we have to check this here? or shall we handle it outside from the caller? + markAllVerticesNotVisited(); // needed to check if edge already exists + if (GraphIsReachable(from, to, 0)) { + //sc_info("Error while adding edge: the edge already exists!") ; + return; + } + + edgeT * newEdge = CREATE_NEW(edgeT) ; + newEdge->connectsTo = to; + newEdge->next = NULL; + edgeT * tempEdge = NULL; + APPEND_TO_LINKLIST(from->edges, newEdge, tempEdge); +//sc_info("Added the edge from %d %d to %d %d", from->row, from->col, to->row, to->col) ; + + // BACK APPEND + newEdge = CREATE_NEW(edgeT) ; + newEdge->connectsTo = from; + newEdge->next = NULL; + tempEdge = NULL; + APPEND_TO_LINKLIST(to->back_edges, newEdge, tempEdge); +//sc_info("Added BACK reference from %d %d to %d %d", to->row, to->col, from->row, from->col) ; + return; +} + +void rebuild_graph() { + destroy_graph(graph); + graph = GraphCreate(); + int i, j, chgct = 0; + struct ent * p; + + for (i = 0; i <= maxrow; i++) + for (j = 0; j <= maxcol; j++) + if ((p = *ATBL(tbl, i, j)) && p->expr) + RealEvalOne(p, i, j, &chgct, 1); + return; +} + +// iterate through all the vertices. Set visited = false +void markAllVerticesNotVisited () { + vertexT * temp = graph->vertices; + while (temp != NULL) { + temp->visited = 0; + temp = temp->next; + } + return; +} + +// print vertices +void print_vertexs() { + char det[20000] = ""; // TODO: - improve: malloc, remalloc and free dinamically + if (graph == NULL) { + strcpy(det, "Graph is empty"); + show_text((char *) &det); + return; + } + + vertexT * temp = graph->vertices; + edgeT * etemp; + det[0]='\0'; + while (temp != NULL) { + sprintf(det + strlen(det), "%d %d\n", temp->ent->row, temp->ent->col); + etemp = temp->edges; + while (etemp != NULL) { + sprintf(det + strlen(det), " \\-> depends on the following ents: %d %d\n", etemp->connectsTo->ent->row, etemp->connectsTo->ent->col); + etemp = etemp->next; + } + etemp = temp->back_edges; + while (etemp != NULL) { + sprintf(det + strlen(det), "edges that depend on that ent: \\-> %d %d\n", etemp->connectsTo->ent->row, etemp->connectsTo->ent->col); + etemp = etemp->next; + } + + temp = temp->next; + } + show_text((char *) &det); + return; +} + + + + +/* this function frees the memory of vertex's edges. + * this also frees the vertex itself, but only if it has no back_dependences. + * the only parameter is an ent pointer. + */ +void destroy_vertex(struct ent * ent) { + if (graph == NULL || ent == NULL) return; + + vertexT * v_prev, * v_cur = graph->vertices; + + // if is in the middle of the list + if (v_cur->ent->row != ent->row || v_cur->ent->col != ent->col) { + if (v_cur->ent == NULL) sc_error("ERROR"); + v_prev = v_cur; + v_cur = v_cur->next; + while (v_cur != NULL && (v_cur->ent->row < ent->row || (v_cur->ent->row == ent->row && v_cur->ent->col <= ent->col))) { + if (v_cur->ent->row == ent->row && v_cur->ent->col == ent->col) break; + v_prev = v_cur; + v_cur = v_cur->next; + } + if (v_cur->ent->row != ent->row || v_cur->ent->col != ent->col) { + sc_debug("Error while destroying a vertex. Vertex not found! Please rebuild graph"); + return; + } + v_prev->next = v_cur->next; + } + + // for each edge in back_edges, we look for the reference to the vertex we are deleting, and we erase it! + edgeT * e2 = v_cur->back_edges; + while (e2 != NULL) { + // sc_debug("back_edge: we follow %d %d", e2->connectsTo->ent->row, e2->connectsTo->ent->col); + delete_reference(v_cur, e2->connectsTo, 0); + e2 = e2->next; + } + + // for each edge in edges, we look for the reference to the vertex we are deleting, and we erase it! + edgeT * e = v_cur->edges; + while (e != NULL) { + // sc_debug("edge: we follow %d %d", e->connectsTo->ent->row, e->connectsTo->ent->col); + delete_reference(v_cur, e->connectsTo, 1); + if (e->connectsTo->edges == NULL) destroy_vertex(e->connectsTo->ent); + e = e->next; + } + + destroy_list_edges(v_cur->edges); + v_cur->edges = NULL; + + destroy_list_edges(v_cur->back_edges); + v_cur->back_edges = NULL; + + + // if vertex to free was the first one.. + if (graph->vertices->ent->row == ent->row && graph->vertices->ent->col == ent->col) + graph->vertices = v_cur->next; + + free(v_cur); + return; +} + +// for each edge in edges, we look for the reference to the vertex we are deleting and we erase it! +// v_cur is the reference +// if back_reference is set, the delete is done over the back_edges list +// if not, it is done over edges list. +void delete_reference(vertexT * v_cur, vertexT * vc, int back_reference) { + if (v_cur == NULL || vc == NULL) return; +// sc_debug("we follow %d %d", vc->ent->row, vc->ent->col); + + // If v_cur is in the first position of back_edge list of vc + if (back_reference && vc->back_edges->connectsTo == v_cur) { + edgeT * e_cur = vc->back_edges; + vc->back_edges = e_cur->next; + free(e_cur); + return; + // If v_cur is in the first position of edge list of vc + } else if (! back_reference && vc->edges->connectsTo == v_cur) { + edgeT * e_cur = vc->edges; + vc->edges = e_cur->next; + free(e_cur); + return; + } + + // If v_cur is not in the first position + edgeT * eb = back_reference ? vc->back_edges : vc->edges; + edgeT * e_prev = eb; + edgeT * e_cur = eb->next; + while (e_cur != NULL && e_cur->connectsTo != v_cur) { + e_prev = eb; + e_cur = eb->next; + } + if (e_cur != NULL && e_cur->connectsTo == v_cur) { + e_prev->next = e_cur->next; + free(e_cur); + } + return; +} + +// this free memory of an edge and its linked edges +void destroy_list_edges(edgeT * e) { + if (e == NULL) return; + edgeT * e_next, * e_cur = e; + + while (e_cur != NULL) { + e_next = e_cur->next; + e_cur->connectsTo = NULL; + free(e_cur); + e_cur = e_next; + } + return; +} + +// this free memory of a graph +void destroy_graph(graphADT graph) { + if (graph == NULL) return; + + vertexT * v_next, * v_cur = graph->vertices; + while (v_cur != NULL) { + v_next = v_cur->next; + if (v_cur->edges != NULL) destroy_list_edges(v_cur->edges); + if (v_cur->back_edges != NULL) destroy_list_edges(v_cur->back_edges); + free(v_cur); + v_cur = v_next; + } + free(graph); + return; +} + +// this variable is for debugging ent_that_depends_on function +char valores[2000] = ""; + +void ents_that_depends_on (graphADT graph, struct ent * ent) { + if (graph == NULL) { + return; + } else { + vertexT * v = getVertex(graph, ent, 0); + if (v->visited) return; + + struct edgeTag * edges = v->back_edges; + while (edges != NULL) { + sprintf(valores + strlen(valores), "%d %d\n", edges->connectsTo->ent->row, edges->connectsTo->ent->col); + ents_that_depends_on(graph, edges->connectsTo->ent); + edges->connectsTo->visited = 1; + edges = edges->next; + } + } + return; +} + +int GraphIsReachable(vertexT * src, vertexT * dest, int back_dep) { + // This method returns if a vertex called dest is reachable from the vertex called source + // first set visited = false for all vertices + if (src == dest) { + return 1; + }else if (src->visited) { + return 0; + }else{ + // visit all edges of vertexT * src + src->visited = 1; + + edgeT * tempe; // the first edge outgoing from this vertex + if (! back_dep) + tempe = src->edges; // the first edge outgoing from this vertex + else + tempe = src->back_edges; // the first edge outgoing from this vertex + + while (tempe != NULL) { + if ( ! GraphIsReachable(tempe->connectsTo, dest, back_dep)) { + tempe = tempe->next; + } else{ + return 1; + } + } + } + return 0; +} + +/* +int isDestReachable(graphADT graph, int from_row, int from_col, int to_row, int to_col, int back_dep) { + if(graph == NULL){ + return 0; + }else{ + vertexT * src = getVertex(graph, from_row, from_col); + vertexT * dest = getVertex(graph, to_row, to_col); + if(src == NULL || dest == NULL) { + return 0; + }else{ + // The graph is not null. The vertices do exist in the graph. Get to work! find if dest is rechable from src + // first set visited = false for all vertices + markAllVerticesNotVisited(graph); + return GraphIsReachable(graph, src, dest, back_dep); + } + } +} +*/ diff --git a/src/dep_graph.h b/src/dep_graph.h new file mode 100755 index 0000000..0c54188 --- /dev/null +++ b/src/dep_graph.h @@ -0,0 +1,38 @@ +#include "sc.h" + +// For each vertex, we need to store an element, its visited flag, its list of edges and a link to the next vertex +typedef struct vertexTag { + struct ent * ent; + int visited; + struct edgeTag * edges; + struct edgeTag * back_edges; + struct vertexTag * next; +} vertexT; + +/* For each edge, we need a link to the vertex it connects to and a link to the next edge w.r.t source vertex*/ +typedef struct edgeTag { + vertexT * connectsTo; + struct edgeTag * next; +} edgeT; + +typedef struct graphCDT { + vertexT * vertices; +} graphCDT; + +typedef struct graphCDT * graphADT; + + +graphADT GraphCreate(); +vertexT * GraphAddVertex(graphADT graph , struct ent * ent); +vertexT * getVertex(graphADT graph, struct ent * ent, int create); +void GraphAddEdge(vertexT * from, vertexT * to); +void print_vertexs(); + +void destroy_list_edges(edgeT * e); +void destroy_graph (graphADT graph); +void destroy_vertex(struct ent * ent); +void delete_reference(vertexT * v_cur, vertexT * vc, int back_reference); + +void markAllVerticesNotVisited(); +void ents_that_depends_on (graphADT graph, struct ent * ent); +int GraphIsReachable(vertexT * src, vertexT * dest, int back_dep); diff --git a/src/filter.c b/src/filter.c index fdf43bc..ac3f7b2 100644 --- a/src/filter.c +++ b/src/filter.c @@ -85,6 +85,7 @@ void enable_filters(struct ent * left, struct ent * right) { results[r-minr+2] = 1; // this row does not eval to expression. we hide it. (1 = HIDDEN)! i = howmany; } + if (seval_result != NULL) free(seval_result); } } diff --git a/src/interp.c b/src/interp.c index 2988f2d..a2248e5 100644 --- a/src/interp.c +++ b/src/interp.c @@ -47,8 +47,8 @@ #endif #ifdef RE_COMP -extern char * re_comp(char *s); -extern char * re_exec(char *s); +extern char * re_comp(char * s); +extern char * re_exec(char * s); #endif #ifdef REGCMP @@ -81,29 +81,28 @@ int rowoffset = 0, coloffset = 0; /* row & col offsets for range functions */ extern bool decimal; /* Set if there was a decimal point in the number */ /* a linked list of free [struct enodes]'s, uses .e.o.left as the pointer */ -//struct enode *freeenodes = NULL; - -double dolookup(struct enode * val, int minr, int minc, int maxr, int maxc, int offr, int offc); -double fn1_eval(double (* fn)(), double arg); -double fn2_eval(double (* fn)(), double arg1, double arg2); -int RealEvalAll(); -int constant(register struct enode * e); -void RealEvalOne(register struct ent * p, int i, int j, int * chgct); -void copydbuf(int deltar, int deltac); -void decompile(register struct enode * e, int priority); -void index_arg(char * s, struct enode * e); -void list_arg(char * s, struct enode * e); -void one_arg(char * s, struct enode * e); -void range_arg(char * s, struct enode * e); -void three_arg(char * s, struct enode * e); -void two_arg(char * s, struct enode * e); -void two_arg_index(char * s, struct enode * e); - -double rint(double d); -int cellerror = CELLOK; /* is there an error in this cell */ +//struct enode * freeenodes = NULL; + +double dolookup (struct enode * val, int minr, int minc, int maxr, int maxc, int offr, int offc); +double fn1_eval (double (* fn)(), double arg); +double fn2_eval (double (* fn)(), double arg1, double arg2); +int RealEvalAll (); +int constant (register struct enode * e); +void RealEvalOne (register struct ent * p, int i, int j, int * chgct, int rebuild_graph); +void copydbuf (int deltar, int deltac); +void decompile (register struct enode * e, int priority); +void index_arg (char * s, struct enode * e); +void list_arg (char * s, struct enode * e); +void one_arg (char * s, struct enode * e); +void range_arg (char * s, struct enode * e); +void three_arg (char * s, struct enode * e); +void two_arg (char * s, struct enode * e); +void two_arg_index (char * s, struct enode * e); +double rint (double d); +int cellerror = CELLOK; /* is there an error in this cell */ #ifndef M_PI - #define M_PI (double)3.14159265358979323846 + #define M_PI (double)3.14159265358979323846 #endif #define dtr(x) ((x)*(M_PI/(double)180.0)) @@ -112,6 +111,13 @@ int cellerror = CELLOK; /* is there an error in this cell */ extern int find_range(char * name, int len, struct ent * lmatch, struct ent * rmatch, struct range ** rng); +#include "dep_graph.h" +extern graphADT graph; +extern char valores; + + + + double finfunc(int fun, double v1, double v2, double v3) { double answer,p; @@ -151,58 +157,58 @@ double finfunc(int fun, double v1, double v2, double v3) { return (answer); } -char * dostindex(int minr, int minc, int maxr, int maxc, struct enode *val) { +char * dostindex(int minr, int minc, int maxr, int maxc, struct enode * val) { int r, c; - register struct ent *p; - char *pr; + register struct ent * p; + char * pr; - p = (struct ent *)0; + p = (struct ent *) 0; if (minr == maxr) { /* look along the row */ r = minr; - c = minc + (int) eval(val) - 1; + c = minc + (int) eval(NULL, val) - 1; } else if (minc == maxc) { /* look down the column */ - r = minr + (int) eval(val) - 1; + r = minr + (int) eval(NULL, val) - 1; c = minc; } else { - r = minr + (int) eval(val->e.o.left) - 1; - c = minc + (int) eval(val->e.o.right) - 1; + r = minr + (int) eval(NULL, val->e.o.left) - 1; + c = minc + (int) eval(NULL, val->e.o.right) - 1; } if (c <= maxc && c >=minc && r <= maxr && r >=minr) p = *ATBL(tbl, r, c); if (p && p->label) { - pr = scxmalloc((size_t)(strlen(p->label)+1)); + pr = scxmalloc((size_t) (strlen(p->label) + 1)); (void) strcpy(pr, p->label); if (p->cellerror) cellerror = CELLINVALID; return (pr); } else - return ((char *)0); + return ((char *) 0); } -double doascii(char *s) { - double v=0.; +double doascii(char * s) { + double v = 0.; int i ; - if (!s) - return ((double)0); + if ( !s ) + return ((double) 0); for (i = 0; s[i] != '\0' ; v = v*256 + (unsigned char)(s[i++]) ) ; scxfree(s); return(v); } -double doindex(int minr, int minc, int maxr, int maxc, struct enode *val) { +double doindex(int minr, int minc, int maxr, int maxc, struct enode * val) { int r, c; - register struct ent *p; + register struct ent * p; if (val->op == ',') { /* index by both row and column */ - r = minr + (int) eval(val->e.o.left) - 1; - c = minc + (int) eval(val->e.o.right) - 1; + r = minr + (int) eval(NULL, val->e.o.left) - 1; + c = minc + (int) eval(NULL, val->e.o.right) - 1; } else if (minr == maxr) { /* look along the row */ r = minr; - c = minc + (int) eval(val) - 1; + c = minc + (int) eval(NULL, val) - 1; } else if (minc == maxc) { /* look down the column */ - r = minr + (int) eval(val) - 1; + r = minr + (int) eval(NULL, val) - 1; c = minc; } else { sc_error("Improper indexing operation"); @@ -219,16 +225,16 @@ double doindex(int minr, int minc, int maxr, int maxc, struct enode *val) { } double dolookup(struct enode * val, int minr, int minc, int maxr, int maxc, int offset, int vflag) { - double v, ret = (double)0; + double v, ret = (double) 0; int r, c; - register struct ent *p = (struct ent *)0; + register struct ent * p = (struct ent *) 0; int incr, incc, fndr, fndc; - char *s; + char * s; incr = vflag; incc = 1 - vflag; if (etype(val) == NUM) { cellerror = CELLOK; - v = eval(val); + v = eval(NULL, val); for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) { if ((p = *ATBL(tbl, r, c)) && p->flags & is_valid) { if (p->v <= v) { @@ -253,7 +259,7 @@ double dolookup(struct enode * val, int minr, int minc, int maxr, int maxc, int } } else { cellerror = CELLOK; - s = seval(val); + s = seval(NULL, val); for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) { if ((p = *ATBL(tbl, r, c)) && p->label) { if (strcmp(p->label,s) == 0) { @@ -278,20 +284,20 @@ double dolookup(struct enode * val, int minr, int minc, int maxr, int maxc, int return ret; } -double docount(int minr, int minc, int maxr, int maxc, struct enode *e) { +double docount(int minr, int minc, int maxr, int maxc, struct enode * e) { int v; int r, c; int cellerr = CELLOK; register struct ent *p; v = 0; - for (r = minr; r<=maxr; r++) - for (c = minc; c<=maxc; c++) { + for (r = minr; r <= maxr; r++) + for (c = minc; c <= maxc; c++) { if (e) { rowoffset = r - minr; coloffset = c - minc; } - if (!e || eval(e)) + if (!e || eval(NULL, e)) if ((p = *ATBL(tbl, r, c)) && p->flags & is_valid) { if (p->cellerror) cellerr = CELLINVALID; v++; @@ -302,20 +308,20 @@ double docount(int minr, int minc, int maxr, int maxc, struct enode *e) { return v; } -double dosum(int minr, int minc, int maxr, int maxc, struct enode *e) { +double dosum(int minr, int minc, int maxr, int maxc, struct enode * e) { double v; int r, c; int cellerr = CELLOK; - register struct ent *p; + register struct ent * p; v = (double)0; - for (r = minr; r<=maxr; r++) - for (c = minc; c<=maxc; c++) { + for (r = minr; r <= maxr; r++) + for (c = minc; c <= maxc; c++) { if (e) { rowoffset = r - minr; coloffset = c - minc; } - if (!e || eval(e)) + if ( !e || eval(NULL, e)) if ((p = *ATBL(tbl, r, c)) && p->flags & is_valid) { if (p->cellerror) cellerr = CELLINVALID; @@ -327,20 +333,20 @@ double dosum(int minr, int minc, int maxr, int maxc, struct enode *e) { return v; } -double doprod(int minr, int minc, int maxr, int maxc, struct enode *e) { +double doprod(int minr, int minc, int maxr, int maxc, struct enode * e) { double v; int r, c; int cellerr = CELLOK; - register struct ent *p; + register struct ent * p; v = 1; - for (r = minr; r<=maxr; r++) - for (c = minc; c<=maxc; c++) { + for (r = minr; r <= maxr; r++) + for (c = minc; c <= maxc; c++) { if (e) { rowoffset = r - minr; coloffset = c - minc; } - if (!e || eval(e)) + if ( !e || eval(NULL, e)) if ((p = *ATBL(tbl, r, c)) && p->flags & is_valid) { if (p->cellerror) cellerr = CELLINVALID; v *= p->v; @@ -351,22 +357,22 @@ double doprod(int minr, int minc, int maxr, int maxc, struct enode *e) { return v; } -double doavg(int minr, int minc, int maxr, int maxc, struct enode *e) { +double doavg(int minr, int minc, int maxr, int maxc, struct enode * e) { |