shithub: spread

Download patch

ref: 7e3533cf6041b0c950a0161c11f391617f1aa21d
parent: d0df10c1ad637b550cea8e7dfd538d1f02e9fc0a
author: sirjofri <sirjofri@sirjofri.de>
date: Fri Jul 5 10:06:38 EDT 2024

do some rudimentary cyclic dependency check

--- a/cells.c
+++ b/cells.c
@@ -200,11 +200,23 @@
 	c->num = 0;
 }
 
-void
+int
+findfree(int i)
+{
+	for (; i < block.num; i++) {
+		if (block.cells[i].type == INVALID)
+			return i;
+	}
+	return -1;
+}
+
+int
 sortcells(void)
 {
 	Cell *c;
 	Cellblock b;
+	int nq;
+	P p;
 	
 	// build DAG information
 	funcregexp = regcomp("[A-Z]+[0-9]+[(]+[)]+");
@@ -225,9 +237,62 @@
 		b.num++;
 	}
 	
+	for (int i = 0; i < b.num; i++) {
+		c = &b.cells[i];
+		if (c->points)
+			free(c->points);
+		c->points = nil;
+		c->num = 0;
+		c->size = 0;
+		c->indeg = 0;
+	}
+	
+	for (int i = 0; i < block.num; i++) {
+		c = &block.cells[i];
+		if (c->type == 0)
+			continue;
+		goto Errout;
+	}
+	
 	block.num = b.num;
 	block.cells = b.cells;
 	memset(&b, 0, sizeof(Cellblock));
+	return 1;
+	
+Errout:
+	p = c->p;
+	
+	/* free dependency calculation */
+	for (int i = 0; i < block.num; i++) {
+		c = &block.cells[i];
+		if (c->type == 0)
+			continue;
+		if (c->points)
+			free(c->points);
+		c->points = nil;
+		c->num = 0;
+		c->size = 0;
+		c->indeg = 0;
+	}
+	
+	/* move cells back to original block */
+	nq = 0;
+	for (int i = 0; i < b.num; i++) {
+		c = &b.cells[i];
+		if (c->type == 0)
+			continue;
+		nq = findfree(nq);
+		if (nq < 0)
+			sysfatal("can't happen");
+		memcpy(&block.cells[nq], c, sizeof(Cell));
+		nq++;
+	}
+	
+	free(b.cells);
+	memset(&b, 0, sizeof(Cellblock));
+	
+	werrstr("cyclic dependencies found involving %s", ptoa(p));
+	return 0;
 }
 
 void
--- a/engine.c
+++ b/engine.c
@@ -380,11 +380,13 @@
 	return 1;
 }
 
-void
+int
 updatecells()
 {
-	sortcells();
+	if (!sortcells())
+		return 0;
 	foreachcell(sendctohoc, nil);
+	return 1;
 }
 
 static void
--- a/spread.c
+++ b/spread.c
@@ -84,6 +84,7 @@
 char *file = nil;
 int dirty = 0;
 char *error = nil;
+char errstring[ERRMAX] = "";
 
 void
 drawtopline(void)
@@ -226,7 +227,11 @@
 		return;
 	
 	addcell(p, s, type);
-	updatecells();
+	if (!updatecells()) {
+		rerrstr(errstring, ERRMAX);
+		error = errstring;
+	} else
+		error = nil;
 	dirty = 1;
 	redraw();
 }
--- a/spread.h
+++ b/spread.h
@@ -5,6 +5,7 @@
 typedef struct Cell Cell;
 typedef struct Response Response;
 
+#define INVALID 0
 #define FUNCTION 1
 #define STRING 2
 
@@ -21,8 +22,8 @@
 void gccells(void);
 void dumpcells(void);
 void foreachcell(void (*f)(Cell*,void*), void*);
-void sortcells(void);
-void updatecells(void);
+int sortcells(void);
+int updatecells(void);
 
 void toupperil(char*);
 P atop(char*);