summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormongo <mongo@iomega>2016-05-06 14:59:46 -0300
committermongo <mongo@iomega>2016-05-06 14:59:46 -0300
commitae2606bfa49ca65a0e5ebe40d025328e56e18ebf (patch)
treed754d29f81f25fff09f2dc4760f5ff48af11edc1
parentaac40d577f60c835c97ccf8d240a6d647bd1d78b (diff)
added dep_graph
-rw-r--r--CHANGES10
-rw-r--r--Readme.md2
-rw-r--r--src/cmds.c53
-rw-r--r--src/cmds_normal.c38
-rwxr-xr-xsrc/dep_graph.c388
-rwxr-xr-xsrc/dep_graph.h38
-rw-r--r--src/filter.c1
-rw-r--r--src/interp.c704
-rw-r--r--src/interp.h116
-rw-r--r--src/main.c38
-rw-r--r--src/sc.h53
-rw-r--r--src/screen.c4
-rw-r--r--src/version.h2
13 files changed, 971 insertions, 476 deletions
diff --git a/CHANGES b/CHANGES
index f4f0413..5ab9740 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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.
diff --git a/Readme.md b/Readme.md
index 2aec825..e3d5e21 100644
--- a/Readme.md
+++ b/Readme.md
@@ -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:
diff --git a/src/cmds.c b/src/cmds.c
index f061bce..4c239ea 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -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) {