summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormongo <andmarti@gmail.com>2023-06-01 10:42:45 -0300
committermongo <andmarti@gmail.com>2023-06-01 10:42:45 -0300
commit95c31eb3d59b589ea9963e9e353547faebc59e72 (patch)
tree694920a0986bc8976b18568b5c2ddc6ed49f03d1
parent0cf3ab008651466d6deec361191d68deb3a22998 (diff)
parentc310edb5f6c6cd90da0b1fe13e3879dcda632071 (diff)
Merge branch 'pr-814' into dev
-rwxr-xr-xsrc/doc12
-rw-r--r--src/function.c42
-rwxr-xr-xsrc/gram.y6
-rw-r--r--src/graph.c4
-rw-r--r--src/interp.c240
-rw-r--r--src/interp.h4
-rw-r--r--src/lua.c39
-rw-r--r--src/lua.h2
-rw-r--r--src/sc.h4
9 files changed, 197 insertions, 156 deletions
diff --git a/src/doc b/src/doc
index 2cb0d36..68e619a 100755
--- a/src/doc
+++ b/src/doc
@@ -1679,14 +1679,20 @@ Commands for handling cell content:
Executes a "luascript". Using Lua script, sc-im can be extend with lot
new functionality, such as complex programming, accessing databases
etc.
+
+ Two global variables {r} and {c} are injected in the "luascript". The
+ variables denote the row and column of the calling cell respectively.
+
The second parameter {i} is 0 or 1 indicating if the reference to this
- cell should be added to the formula evaluation graph.
- Setting it to 0 may be a good idea if you call sc.lquery to often in
- your scripts.
+ cell should be added to the formula evaluation graph. Setting it to 0
+ may be a good idea if you call sc.lquery to often in your scripts.
However, in the cases were its not added to the dependency graph, it
will nevertheless be executed when the cell that calls the script
executions is referenced by another cell.
+ The return of value of the "luascript" is inserted in the calling
+ cell if it is a string.
+
The search patch for LUA scripts files is $PWD/lua/
$HOME/.sc-im/lua/ or /usr/local/share/sc-im/lua (in that order)
diff --git a/src/function.c b/src/function.c
index 1ee6a68..51a2ecb 100644
--- a/src/function.c
+++ b/src/function.c
@@ -132,13 +132,13 @@ char * dostindex(struct sheet * sh, int minr, int minc, int maxr, int maxc, stru
p = (struct ent *) 0;
if (minr == maxr) { /* look along the row */
r = minr;
- c = minc + (int) eval(sh, NULL, val) - 1;
+ c = minc + (int) eval(sh, NULL, val, 0) - 1;
} else if (minc == maxc) { /* look down the column */
- r = minr + (int) eval(sh, NULL, val) - 1;
+ r = minr + (int) eval(sh, NULL, val, 0) - 1;
c = minc;
} else {
- r = minr + (int) eval(sh, NULL, val->e.o.left) - 1;
- c = minc + (int) eval(sh, NULL, val->e.o.right) - 1;
+ r = minr + (int) eval(sh, NULL, val->e.o.left, 0) - 1;
+ c = minc + (int) eval(sh, NULL, val->e.o.right, 0) - 1;
}
if (c <= maxc && c >=minc && r <= maxr && r >=minr)
p = *ATBL(sh, sh->tbl, r, c);
@@ -184,13 +184,13 @@ double doindex(struct sheet * sh, int minr, int minc, int maxr, int maxc, struct
struct ent * p;
if (val->op == ',') { /* index by both row and column */
- r = minr + (int) eval(sh, NULL, val->e.o.left) - 1;
- c = minc + (int) eval(sh, NULL, val->e.o.right) - 1;
+ r = minr + (int) eval(sh, NULL, val->e.o.left, 0) - 1;
+ c = minc + (int) eval(sh, NULL, val->e.o.right, 0) - 1;
} else if (minr == maxr) { /* look along the row */
r = minr;
- c = minc + (int) eval(sh, NULL, val) - 1;
+ c = minc + (int) eval(sh, NULL, val, 0) - 1;
} else if (minc == maxc) { /* look down the column */
- r = minr + (int) eval(sh, NULL, val) - 1;
+ r = minr + (int) eval(sh, NULL, val, 0) - 1;
c = minc;
} else {
sc_error("Improper indexing operation");
@@ -228,7 +228,7 @@ double dolookup(struct sheet * sh, struct enode * val, int minr, int minc, int m
incr = vflag; incc = 1 - vflag;
if (etype(val) == NUM) {
cellerror = CELLOK;
- v = eval(sh, NULL, val);
+ v = eval(sh, NULL, val, 0);
for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) {
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->flags & is_valid) {
if (p->v <= v) {
@@ -253,7 +253,7 @@ double dolookup(struct sheet * sh, struct enode * val, int minr, int minc, int m
}
} else {
cellerror = CELLOK;
- s = seval(sh, NULL, val);
+ s = seval(sh, NULL, val, 0);
for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) {
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->label) {
if (s && strcmp(p->label,s) == 0) {
@@ -303,7 +303,7 @@ double docount(struct sheet * sh, int minr, int minc, int maxr, int maxc, struct
rowoffset = r - minr;
coloffset = c - minc;
}
- if (!e || eval(sh, NULL, e))
+ if (!e || eval(sh, NULL, e, 0))
// the following changed for #430. docount should also count cells with strings. not just numbers
// TODO: create @counta to count both, and leave @count for just numbers
if ((p = *ATBL(sh, sh->tbl, r, c)) && (p->flags & is_valid || p->label) ) {
@@ -339,7 +339,7 @@ double dosum(struct sheet * sh, int minr, int minc, int maxr, int maxc, struct e
rowoffset = r - minr;
coloffset = c - minc;
}
- if ( !e || eval(sh, NULL, e))
+ if ( !e || eval(sh, NULL, e, 0))
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->flags & is_valid) {
if (p->cellerror)
cellerr = CELLINVALID;
@@ -373,7 +373,7 @@ double doprod(struct sheet * sh, int minr, int minc, int maxr, int maxc, struct
rowoffset = r - minr;
coloffset = c - minc;
}
- if ( !e || eval(sh, NULL, e))
+ if ( !e || eval(sh, NULL, e, 0))
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->flags & is_valid) {
if (p->cellerror) cellerr = CELLINVALID;
v *= p->v;
@@ -409,7 +409,7 @@ double doavg(struct sheet * sh, int minr, int minc, int maxr, int maxc, struct e
rowoffset = r - minr;
coloffset = c - minc;
}
- if (!e || eval(sh, NULL, e))
+ if (!e || eval(sh, NULL, e, 0))
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->flags & is_valid) {
if (p->cellerror) cellerr = CELLINVALID;
v += p->v;
@@ -450,7 +450,7 @@ double dostddev(struct sheet * sh, int minr, int minc, int maxr, int maxc, struc
rowoffset = r - minr;
coloffset = c - minc;
}
- if (!e || eval(sh, NULL, e))
+ if (!e || eval(sh, NULL, e, 0))
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->flags & is_valid) {
if (p->cellerror) cellerr = CELLINVALID;
v = p->v;
@@ -491,7 +491,7 @@ double domax(struct sheet * sh, int minr, int minc, int maxr, int maxc, struct e
rowoffset = r - minr;
coloffset = c - minc;
}
- if (!e || eval(sh, NULL, e))
+ if (!e || eval(sh, NULL, e, 0))
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->flags & is_valid) {
if (p->cellerror) cellerr = CELLINVALID;
@@ -534,7 +534,7 @@ double domin(struct sheet * sh, int minr, int minc, int maxr, int maxc, struct e
rowoffset = r - minr;
coloffset = c - minc;
}
- if (!e || eval(sh, NULL, e))
+ if (!e || eval(sh, NULL, e, 0))
if ((p = *ATBL(sh, sh->tbl, r, c)) && p->flags & is_valid) {
if (p->cellerror) cellerr = CELLINVALID;
if (! count) {
@@ -780,7 +780,7 @@ double dolmax(struct sheet * sh, struct ent * e, struct enode * ep) {
cellerror = CELLOK;
for (p = ep; p; p = p->e.o.left) {
- v = eval(sh, e, p->e.o.right);
+ v = eval(sh, e, p->e.o.right, 1);
if ( !count || v > maxval) {
maxval = v;
count++;
@@ -805,7 +805,7 @@ double dolmin(struct sheet * sh, struct ent * e, struct enode * ep) {
cellerror = CELLOK;
for (p = ep; p; p = p->e.o.left) {
- v = eval(sh, e, p->e.o.right);
+ v = eval(sh, e, p->e.o.right, 1);
if ( !count || v < minval) {
minval = v;
count++;
@@ -927,8 +927,8 @@ char * doext(struct sheet * sh, struct enode *se) {
char * command;
double value;
- command = seval(sh, NULL, se->e.o.left);
- value = eval(sh, NULL, se->e.o.right);
+ command = seval(sh, NULL, se->e.o.left, 0);
+ value = eval(sh, NULL, se->e.o.right, 0);
if ( ! get_conf_int("external_functions") ) {
sc_error("Warning: external functions disabled; using %s value",
(se->e.o.s && *se->e.o.s) ? "previous" : "null");
diff --git a/src/gram.y b/src/gram.y
index 11ef14a..fec3876 100755
--- a/src/gram.y
+++ b/src/gram.y
@@ -1118,7 +1118,7 @@ command:
| S_EVAL e {
struct roman * roman = session->cur_doc;
struct sheet * sh = roman->cur_sh;
- eval_result = eval(sh, NULL, $2);
+ eval_result = eval(sh, NULL, $2, 0);
efree($2);
}
| S_EXECUTE STRING {
@@ -1230,7 +1230,7 @@ command:
| S_SEVAL e {
struct roman * roman = session->cur_doc;
struct sheet * sh = roman->cur_sh;
- seval_result = seval(sh, NULL, $2); // always make sure this seval_result is always freed afterwards
+ seval_result = seval(sh, NULL, $2, 0); // always make sure this seval_result is always freed afterwards
efree($2);
}
| S_ERROR STRING { sc_error($2);
@@ -1514,7 +1514,7 @@ var:
| '@' K_GETENT '(' e ',' e ')' {
struct roman * roman = session->cur_doc;
struct sheet * sh = roman->cur_sh;
- $$.vp = lookat(sh, eval(sh, NULL, $4), eval(sh, NULL, $6));
+ $$.vp = lookat(sh, eval(sh, NULL, $4, 0), eval(sh, NULL, $6, 0));
$$.vf = GET_ENT;
if ($$.expr != NULL) efree($$.expr);
$$.expr = new(GETENT, $4, $6);
diff --git a/src/graph.c b/src/graph.c
index 75191fc..ad435f5 100644
--- a/src/graph.c
+++ b/src/graph.c
@@ -825,7 +825,7 @@ void EvalJustOneVertex(struct sheet * sh, struct ent * p, int rebuild_graph) {
v = "";
} else {
cellerror = CELLOK;
- v = rebuild_graph ? seval(sh, p, p->expr) : seval(sh, NULL, p->expr);
+ v = seval(sh, p, p->expr, rebuild_graph);
}
p->cellerror = cellerror;
if ( !v && !p->label) /* Everything's fine */
@@ -844,7 +844,7 @@ void EvalJustOneVertex(struct sheet * sh, struct ent * p, int rebuild_graph) {
v = (double) 0.0;
} else {
cellerror = CELLOK;
- v = rebuild_graph ? eval(sh, p, p->expr) : eval(sh, NULL, p->expr);
+ v = eval(sh, p, p->expr, rebuild_graph);
if (cellerror == CELLOK && ! isfinite(v))
cellerror = CELLERROR;
diff --git a/src/interp.c b/src/interp.c
index 0b5cebf..b67b3fc 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -121,7 +121,10 @@ struct go_save gs = { .g_type = G_NONE }; /* Use this structure to save the last
* \param[in] e
* \return double
*/
-double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
+double eval(struct sheet * sh, struct ent * ent, struct enode * e, int rebuild_graph) {
+ if (rebuild_graph && ent == NULL) {
+ sc_error("Cannot rebuild graph with NULL ent");
+ }
// if (cellerror == CELLERROR || (ent && ent->cellerror == CELLERROR)) {
// if (cellerror == CELLERROR) {
@@ -133,18 +136,18 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
}
switch (e->op) {
- case '+': return (eval(sh, ent, e->e.o.left) + eval(sh, ent, e->e.o.right));
+ case '+': return (eval(sh, ent, e->e.o.left, rebuild_graph) + eval(sh, ent, e->e.o.right, rebuild_graph));
case '-': {
double l, r;
- l = eval(sh, ent, e->e.o.left);
- r = eval(sh, ent, e->e.o.right);
+ l = eval(sh, ent, e->e.o.left, rebuild_graph);
+ r = eval(sh, ent, e->e.o.right, rebuild_graph);
return l - r;
}
- case '*': return (eval(sh, ent, e->e.o.left) * eval(sh, ent, e->e.o.right));
+ case '*': return (eval(sh, ent, e->e.o.left, rebuild_graph) * eval(sh, ent, e->e.o.right, rebuild_graph));
case '/': {
double num, denom;
- num = eval(sh, ent, e->e.o.left);
- denom = eval(sh, ent, e->e.o.right);
+ num = eval(sh, ent, e->e.o.left, rebuild_graph);
+ denom = eval(sh, ent, e->e.o.right, rebuild_graph);
if (cellerror) {
cellerror = CELLINVALID;
return ((double) 0);
@@ -158,8 +161,8 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
}
case '%': {
double num, denom;
- num = floor(eval(sh, ent, e->e.o.left));
- denom = floor(eval(sh, ent, e->e.o.right));
+ num = floor(eval(sh, ent, e->e.o.left, rebuild_graph));
+ denom = floor(eval(sh, ent, e->e.o.right, rebuild_graph));
if (denom)
return (num - floor(num/denom)*denom);
else {
@@ -167,35 +170,35 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
return ((double) 0);
}
}
- case '^': return (fn2_eval(pow,eval(sh, ent, e->e.o.left),eval(sh, ent, e->e.o.right)));
- case '<': return (eval(sh, ent, e->e.o.left) < eval(sh, ent, e->e.o.right));
+ case '^': return (fn2_eval(pow,eval(sh, ent, e->e.o.left, rebuild_graph),eval(sh, ent, e->e.o.right, rebuild_graph)));
+ case '<': return (eval(sh, ent, e->e.o.left, rebuild_graph) < eval(sh, ent, e->e.o.right, rebuild_graph));
case '=': {
double l, r;
- l = eval(sh, ent, e->e.o.left);
- r = eval(sh, ent, e->e.o.right);
+ l = eval(sh, ent, e->e.o.left, rebuild_graph);
+ r = eval(sh, ent, e->e.o.right, rebuild_graph);
return (l == r);
}
- case '>': return (eval(sh, ent, e->e.o.left) > eval(sh, ent, e->e.o.right));
- case '&': return (eval(sh, ent, e->e.o.left) && eval(sh, ent, e->e.o.right));
- case '|': return (eval(sh, ent, e->e.o.left) || eval(sh, ent, e->e.o.right));
+ case '>': return (eval(sh, ent, e->e.o.left, rebuild_graph) > eval(sh, ent, e->e.o.right, rebuild_graph));
+ case '&': return (eval(sh, ent, e->e.o.left, rebuild_graph) && eval(sh, ent, e->e.o.right, rebuild_graph));
+ case '|': return (eval(sh, ent, e->e.o.left, rebuild_graph) || eval(sh, ent, e->e.o.right ,rebuild_graph));
case IF:
- case '?': return eval(sh, ent, e->e.o.left) ? eval(sh, ent, e->e.o.right->e.o.left)
- : eval(sh, ent, e->e.o.right->e.o.right);
- case 'm': return (-eval(sh, ent, e->e.o.left));
+ case '?': return eval(sh, ent, e->e.o.left, rebuild_graph) ? eval(sh, ent, e->e.o.right->e.o.left, rebuild_graph)
+ : eval(sh, ent, e->e.o.right->e.o.right, rebuild_graph);
+ case 'm': return (-eval(sh, ent, e->e.o.left, rebuild_graph));
case 'f': {
int rtmp = rowoffset;
int ctmp = coloffset;
double ret;
rowoffset = coloffset = 0;
- ret = eval(sh, ent, e->e.o.left);
+ ret = eval(sh, ent, e->e.o.left, rebuild_graph);
rowoffset = rtmp;
coloffset = ctmp;
return (ret);
}
- case 'F': return (eval(sh, ent, e->e.o.left));
- case '!': return (eval(sh, ent, e->e.o.left) == 0.0);
- case ';': return (((int) eval(sh, ent, e->e.o.left) & 7) +
- (((int) eval(sh, ent, e->e.o.right) & 7) << 3));
+ case 'F': return (eval(sh, ent, e->e.o.left, rebuild_graph));
+ case '!': return (eval(sh, ent, e->e.o.left, rebuild_graph) == 0.0);
+ case ';': return (((int) eval(sh, ent, e->e.o.left, rebuild_graph) & 7) +
+ (((int) eval(sh, ent, e->e.o.right, rebuild_graph) & 7) << 3));
case O_CONST:
if (! isfinite(e->e.k)) {
@@ -209,8 +212,8 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
case GETENT:
;
- int r = eval(sh, ent, e->e.o.left);
- int c = eval(sh, ent, e->e.o.right);
+ int r = eval(sh, ent, e->e.o.left, rebuild_graph);
+ int c = eval(sh, ent, e->e.o.right, rebuild_graph);
if (r < 0 || c < 0) {
sc_debug("@getent shouldnt be called with negative parameters %d %d", r, c);
return (double) 0;
@@ -344,10 +347,10 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
return dolookup(sh, e->e.o.right, minr, minc, maxr, maxc, 1, minc==maxc);
case HLOOKUP:
return dolookup(sh, e->e.o.right->e.o.left, minr,minc,maxr,maxc,
- (int) eval(sh, ent, e->e.o.right->e.o.right), 0);
+ (int) eval(sh, ent, e->e.o.right->e.o.right, rebuild_graph), 0);
case VLOOKUP:
return dolookup(sh, e->e.o.right->e.o.left, minr,minc,maxr,maxc,
- (int) eval(sh, ent, e->e.o.right->e.o.right), 1);
+ (int) eval(sh, ent, e->e.o.right->e.o.right, rebuild_graph), 1);
case INDEX:
return doindex(sh, minr, minc, maxr, maxc, e->e.o.right);
case SUM:
@@ -382,42 +385,42 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
case REDUCE | 'C': return (maxc - minc + 1);
}
}
- case ABS: return (fn1_eval( fabs, eval(sh, ent, e->e.o.left)));
+ case ABS: return (fn1_eval( fabs, eval(sh, ent, e->e.o.left, rebuild_graph)));
case FROW:
- eval(sh, ent, e->e.o.left);
+ eval(sh, ent, e->e.o.left, rebuild_graph);
return (dorow(e->e.o.left));
case FCOL:
- eval(sh, ent, e->e.o.left);
+ eval(sh, ent, e->e.o.left, rebuild_graph);
return (docol(e->e.o.left));
- case ACOS: return (fn1_eval( acos, eval(sh, ent, e->e.o.left)));
- case ASIN: return (fn1_eval( asin, eval(sh, ent, e->e.o.left)));
- case ATAN: return (fn1_eval( atan, eval(sh, ent, e->e.o.left)));
- case ATAN2: return (fn2_eval( atan2, eval(sh, ent, e->e.o.left), eval(sh, ent, e->e.o.right)));
- case CEIL: return (fn1_eval( ceil, eval(sh, ent, e->e.o.left)));
- case COS: return (fn1_eval( cos, eval(sh, ent, e->e.o.left)));
- case EXP: return (fn1_eval( exp, eval(sh, ent, e->e.o.left)));
- case FABS: return (fn1_eval( fabs, eval(sh, ent, e->e.o.left)));
- case FLOOR: return (fn1_eval( floor, eval(sh, ent, e->e.o.left)));
- case HYPOT: return (fn2_eval( hypot, eval(sh, ent, e->e.o.left), eval(sh, ent, e->e.o.right)));
- case LOG: return (fn1_eval( log, eval(sh, ent, e->e.o.left)));
- case LOG10: return (fn1_eval( log10, eval(sh, ent, e->e.o.left)));
- case POW: return (fn2_eval( pow, eval(sh, ent, e->e.o.left), eval(sh, ent, e->e.o.right)));
- case SIN: return (fn1_eval( sin, eval(sh, ent, e->e.o.left)));
- case SQRT: return (fn1_eval( sqrt, eval(sh, ent, e->e.o.left)));
- case TAN: return (fn1_eval( tan, eval(sh, ent, e->e.o.left)));
- case DTR: return (dtr(eval(sh, ent, e->e.o.left)));
- case RTD: return (rtd(eval(sh, ent, e->e.o.left)));
+ case ACOS: return (fn1_eval( acos, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case ASIN: return (fn1_eval( asin, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case ATAN: return (fn1_eval( atan, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case ATAN2: return (fn2_eval( atan2, eval(sh, ent, e->e.o.left, rebuild_graph), eval(sh, ent, e->e.o.right, rebuild_graph)));
+ case CEIL: return (fn1_eval( ceil, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case COS: return (fn1_eval( cos, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case EXP: return (fn1_eval( exp, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case FABS: return (fn1_eval( fabs, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case FLOOR: return (fn1_eval( floor, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case HYPOT: return (fn2_eval( hypot, eval(sh, ent, e->e.o.left, rebuild_graph), eval(sh, ent, e->e.o.right, rebuild_graph)));
+ case LOG: return (fn1_eval( log, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case LOG10: return (fn1_eval( log10, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case POW: return (fn2_eval( pow, eval(sh, ent, e->e.o.left, rebuild_graph), eval(sh, ent, e->e.o.right, rebuild_graph)));
+ case SIN: return (fn1_eval( sin, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case SQRT: return (fn1_eval( sqrt, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case TAN: return (fn1_eval( tan, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case DTR: return (dtr(eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case RTD: return (rtd(eval(sh, ent, e->e.o.left, rebuild_graph)));
case RND:
if (rndtoeven)
- return rint(eval(sh, ent, e->e.o.left));
+ return rint(eval(sh, ent, e->e.o.left, rebuild_graph));
else {
- double temp = eval(sh, ent, e->e.o.left);
+ double temp = eval(sh, ent, e->e.o.left, rebuild_graph);
return (temp - floor(temp) < 0.5 ? floor(temp) : ceil(temp));
}
case ROUND:
{
- int precision = (int) eval(sh, ent, e->e.o.right);
+ int precision = (int) eval(sh, ent, e->e.o.right, rebuild_graph);
double scale = 1;
if (0 < precision)
do scale *= 10; while (0 < --precision);
@@ -425,9 +428,9 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
do scale /= 10; while (++precision < 0);
if (rndtoeven)
- return (rint(eval(sh, ent, e->e.o.left) * scale) / scale);
+ return (rint(eval(sh, ent, e->e.o.left, rebuild_graph) * scale) / scale);
else {
- double temp = eval(sh, ent, e->e.o.left);
+ double temp = eval(sh, ent, e->e.o.left, rebuild_graph);
temp *= scale;
/* xxx */
/*
@@ -440,38 +443,38 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
}
case FV:
case PV:
- case PMT: return (finfunc(e->op, eval(sh, ent, e->e.o.left), eval(sh, ent, e->e.o.right->e.o.left), eval(sh, ent, e->e.o.right->e.o.right)));
- case HOUR: return (dotime(HOUR, eval(sh, ent, e->e.o.left)));
- case MINUTE: return (dotime(MINUTE, eval(sh, ent, e->e.o.left)));
- case SECOND: return (dotime(SECOND, eval(sh, ent, e->e.o.left)));
- case MONTH: return (dotime(MONTH, eval(sh, ent, e->e.o.left)));
- case DAY: return (dotime(DAY, eval(sh, ent, e->e.o.left)));
- case YEAR: return (dotime(YEAR, eval(sh, ent, e->e.o.left)));
+ case PMT: return (finfunc(e->op, eval(sh, ent, e->e.o.left, rebuild_graph), eval(sh, ent, e->e.o.right->e.o.left, rebuild_graph), eval(sh, ent, e->e.o.right->e.o.right, rebuild_graph)));
+ case HOUR: return (dotime(HOUR, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case MINUTE: return (dotime(MINUTE, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case SECOND: return (dotime(SECOND, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case MONTH: return (dotime(MONTH, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case DAY: return (dotime(DAY, eval(sh, ent, e->e.o.left, rebuild_graph)));
+ case YEAR: return (dotime(YEAR, eval(sh, ent, e->e.o.left, rebuild_graph)));
case NOW:
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
return (dotime(NOW, (double) 0.0));
- case DTS: return (dodts((int) eval(sh, ent, e->e.o.left),
- (int)eval(sh, ent, e->e.o.right->e.o.left),
- (int)eval(sh, ent, e->e.o.right->e.o.right)));
- case TTS: return (dotts((int) eval(sh, ent, e->e.o.left),
- (int)eval(sh, ent, e->e.o.right->e.o.left),
- (int)eval(sh, ent, e->e.o.right->e.o.right)));
+ case DTS: return (dodts((int) eval(sh, ent, e->e.o.left, rebuild_graph),
+ (int)eval(sh, ent, e->e.o.right->e.o.left, rebuild_graph),
+ (int)eval(sh, ent, e->e.o.right->e.o.right, rebuild_graph)));
+ case TTS: return (dotts((int) eval(sh, ent, e->e.o.left, rebuild_graph),
+ (int)eval(sh, ent, e->e.o.right->e.o.left, rebuild_graph),
+ (int)eval(sh, ent, e->e.o.right->e.o.right, rebuild_graph)));
case EVALUATE:
if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- return doevaluate(seval(sh, ent, e->e.o.left));
+ return doevaluate(seval(sh, ent, e->e.o.left, rebuild_graph));
case STON:
if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- return (doston(seval(sh, ent, e->e.o.left)));
+ return (doston(seval(sh, ent, e->e.o.left, rebuild_graph)));
- case ASCII: return (doascii(seval(sh, ent, e->e.o.left)));
+ case ASCII: return (doascii(seval(sh, ent, e->e.o.left, rebuild_graph)));
- case SLEN: return (doslen(seval(sh, ent, e->e.o.left)));
+ case SLEN: return (doslen(seval(sh, ent, e->e.o.left, rebuild_graph)));
- case EQS: return (doeqs(seval(sh, ent, e->e.o.right), seval(sh, ent, e->e.o.left)));
+ case EQS: return (doeqs(seval(sh, ent, e->e.o.right, rebuild_graph), seval(sh, ent, e->e.o.left, rebuild_graph)));
case LMAX: return dolmax(sh, ent, e);
@@ -479,11 +482,11 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
case NVAL:
if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- char * s = seval(sh, ent, e->e.o.left);
+ char * s = seval(sh, ent, e->e.o.left, rebuild_graph);
if (! s) { return (double) (0); }
char * sf = calloc(strlen(s)+1, sizeof(char));
strcpy(sf, s);
- double n = eval(sh, ent, e->e.o.right);
+ double n = eval(sh, ent, e->e.o.right, rebuild_graph);
struct ent * ep = getent(sh, sf, n, 1);
if (! ep) { free(s); return (double) (0); }
if (ent && ep) GraphAddEdge(getVertex(graph, sh, lookat(sh, ent->row, ent->col), 1), getVertex(graph, sh, ep, 1));
@@ -536,9 +539,9 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
case DEFAULT_COLOR: return ((double) DEFAULT_COLOR);
case FACT:
{
- double total = eval(sh, ent, e->e.o.left);
+ double total = eval(sh, ent, e->e.o.left, rebuild_graph);
int i;
- for (i = eval(sh, ent, e->e.o.left) - 1; i > 0; i--) {
+ for (i = eval(sh, ent, e->e.o.left, rebuild_graph) - 1; i > 0; i--) {
total *= i;
}
return total > 0 ? total : 1;
@@ -557,7 +560,10 @@ double eval(struct sheet * sh, struct ent * ent, struct enode * e) {
* \param[in] se
* \return char *
*/
-char * seval(struct sheet * sh, struct ent * ent, struct enode * se) {
+char * seval(struct sheet * sh, struct ent * ent, struct enode * se, int rebuild_graph) {
+ if (rebuild_graph && ent == NULL) {
+ sc_error("Cannot rebuild graph with NULL ent");
+ }
struct sheet * sh_vp = sh;
if (se == (struct enode *) 0) return (char *) 0;
@@ -568,7 +574,7 @@ char * seval(struct sheet * sh, struct ent * ent, struct enode * se) {
p = scxmalloc( (size_t) (strlen(se->e.s) + 1));
(void) strcpy(p, se->e.s);
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
return (p);
case O_VAR:
@@ -577,7 +583,7 @@ char * seval(struct sheet * sh, struct ent * ent, struct enode * se) {
sh_vp = se->e.v.sheet;
if (sh_vp == NULL) sh_vp = sh;
- if (vp && ent && vp->row == ent->row && vp->col == ent->col && sh_vp == sh) {
+ if (rebuild_graph && vp && vp->row == ent->row && vp->col == ent->col && sh_vp == sh) {
sc_error("Circular reference in seval");
se->op = ERR_;
cellerror = CELLERROR;
@@ -597,14 +603,14 @@ char * seval(struct sheet * sh, struct ent * ent, struct enode * se) {
(void) strcpy(p, vp->label);
// here we store the cell dependences in a graph
- if (ent && vp) {
+ if (rebuild_graph && vp) {
GraphAddEdge(getVertex(graph, sh, lookat(sh, ent->row, ent->col), 1), getVertex(graph, sh_vp, lookat(sh_vp, vp->row, vp->col), 1) ) ;
}
return (p);
}
case '#':
- return (docat(seval(sh, ent, se->e.o.left), seval(sh, ent, se->e.o.right)));
+ return (docat(seval(sh, ent, se->e.o.left, rebuild_graph), seval(sh, ent, se->e.o.right, rebuild_graph)));
case 'f':
{
@@ -612,31 +618,31 @@ char * seval(struct sheet * sh, struct ent * ent, struct enode * se) {
int ctmp = coloffset;
char *ret;
rowoffset = coloffset = 0;
- ret = seval(sh, ent, se->e.o.left);
+ ret = seval(sh, ent, se->e.o.left, rebuild_graph);
rowoffset = rtmp;
coloffset = ctmp;
return (ret);
}
- case 'F': return (seval(sh, ent, se->e.o.left));
+ case 'F': return (seval(sh, ent, se->e.o.left, rebuild_graph));
case IF:
- case '?': return (eval(sh, NULL, se->e.o.left) ? seval(sh, ent, se->e.o.right->e.o.left) : seval(sh, ent, se->e.o.right->e.o.right));
+ case '?': return (eval(sh, NULL, se->e.o.left, rebuild_graph) ? seval(sh, ent, se->e.o.right->e.o.left, rebuild_graph) : seval(sh, ent, se->e.o.right->e.o.right, rebuild_graph));
- case DATE: return (dodate( (time_t) (eval(sh, NULL, se->e.o.left)), seval(sh, ent, se->e.o.right)));
+ case DATE: return (dodate( (time_t) (eval(sh, NULL, se->e.o.left, rebuild_graph)), seval(sh, ent, se->e.o.right, rebuild_graph)));
- case FMT: return (dofmt(seval(sh, ent, se->e.o.left), eval(sh, NULL, se->e.o.right)));
+ case FMT: return (dofmt(seval(sh, ent, se->e.o.left, rebuild_graph), eval(sh, NULL, se->e.o.right, 0)));
- case UPPER: return (docase(UPPER, seval(sh, ent, se->e.o.left)));
+ case UPPER: return (docase(UPPER, seval(sh, ent, se->e.o.left, rebuild_graph)));
- case LOWER: return (docase(LOWER, seval(sh, ent, se->e.o.left)));
+ case LOWER: return (docase(LOWER, seval(sh, ent, se->e.o.left, rebuild_graph)));
- case SET8BIT: return (docase(SET8BIT, seval(sh, ent, se->e.o.left)));
+ case SET8BIT: return (docase(SET8BIT, seval(sh, ent, se->e.o.left, rebuild_graph)));
case CAPITAL:
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- return (docapital(seval(sh, ent, se->e.o.left)));
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ return (docapital(seval(sh, ent, se->e.o.left, rebuild_graph)));
case STINDEX: {
int r, c;
@@ -651,17 +657,17 @@ char * seval(struct sheet * sh, struct ent * ent, struct enode * se) {
return dostindex(sh, minr, minc, maxr, maxc, se->e.o.right);
}
case EXT:
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
return (doext(sh, se));
#ifdef XLUA
case LUA:
;
- int dg_store = eval(sh, NULL, se->e.o.right);
// add to depgraph ONLY if second parameter to @lua is 1
- if (dg_store == 1 && ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ int dg_store = eval(sh, ent, se->e.o.right, rebuild_graph);
+ if (rebuild_graph && dg_store && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- if (ent) {
+ if (rebuild_graph) {
ent->label = scxmalloc(sizeof(char)*4);
strcpy(ent->label, "LUA");
}
@@ -669,37 +675,37 @@ char * seval(struct sheet * sh, struct ent * ent, struct enode * se) {
sc_info("Execution of LUA scripts disabled");
return NULL;
}
- return (doLUA(sh, se, dg_store));
+ return (doLUA(sh, ent, se, dg_store));
#endif
- case SVAL: return (dosval(sh, seval(sh, ent, se->e.o.left), eval(sh, NULL, se->e.o.right)));
+ case SVAL: return (dosval(sh, seval(sh, ent, se->e.o.left, rebuild_graph), eval(sh, NULL, se->e.o.right, 0)));
case REPLACE:
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- return (doreplace(seval(sh, ent, se->e.o.left),
- seval(sh, NULL, se->e.o.right->e.o.left),
- seval(sh, NULL, se->e.o.right->e.o.right)));
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ return (doreplace(seval(sh, ent, se->e.o.left, rebuild_graph),
+ seval(sh, NULL, se->e.o.right->e.o.left, 0),
+ seval(sh, NULL, se->e.o.right->e.o.right, 0)));
- case SUBSTR: return (dosubstr(seval(sh, ent, se->e.o.left),
- (int) eval(sh, NULL, se->e.o.right->e.o.left) - 1,
- (int) eval(sh, NULL, se->e.o.right->e.o.right) - 1));
+ case SUBSTR: return (dosubstr(seval(sh, ent, se->e.o.left, rebuild_graph),
+ (int) eval(sh, NULL, se->e.o.right->e.o.left, 0) - 1,
+ (int) eval(sh, NULL, se->e.o.right->e.o.right, 0) - 1));
case COLTOA:
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- return (strcpy(scxmalloc( (size_t) 10), coltoa((int) eval(sh, ent, se->e.o.left))));
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ return (strcpy(scxmalloc( (size_t) 10), coltoa((int) eval(sh, ent, se->e.o.left, rebuild_graph))));
case CHR:
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- return (strcpy(scxmalloc( (size_t) 10), dochr(eval(sh, NULL, se->e.o.left))));
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ return (strcpy(scxmalloc( (size_t) 10), dochr(eval(sh, NULL, se->e.o.left, rebuild_graph))));
case SEVALUATE:
- if (ent && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
- return dosevaluate(seval(sh, ent, se->e.o.left));
+ if (rebuild_graph && getVertex(graph, sh, ent, 0) == NULL) GraphAddVertex(graph, sh, ent);
+ return dosevaluate(seval(sh, ent, se->e.o.left, rebuild_graph));
case FILENAME: {
char * curfile = session->cur_doc->name;
if (curfile == NULL) return curfile;
- int n = eval(sh, NULL, se->e.o.left);
+ int n = eval(sh, NULL, se->e.o.left, 0);
char *s = strrchr(curfile, '/');
if (n || s++ == NULL) s = curfile;
p = scxmalloc( (size_t) (strlen(s) + 1));
@@ -1472,7 +1478,7 @@ void let(struct roman * roman, struct sheet * sh, struct ent * v, struct enode *
cellerror = CELLERROR;
} else {
cellerror = CELLOK;
- val = eval(sh, v, e); // JUST NUMERIC VALUE
+ val = eval(sh, v, e, 1); // JUST NUMERIC VALUE
}
if (v->cellerror != cellerror) {
v->flags |= is_changed;
@@ -1507,7 +1513,7 @@ void let(struct roman * roman, struct sheet * sh, struct ent * v, struct enode *
v->expr = e;
v->flags &= ~is_strexpr;
- eval(sh, v, e); // ADDED - here we store the cell dependences in a graph
+ eval(sh, v, e, 1); // ADDED - here we store the cell dependences in a graph
}
if (v->cellerror == CELLOK) v->flags |= ( is_changed | is_valid );
roman->modflg++;
@@ -1569,10 +1575,10 @@ void slet(struct roman * roman, struct sheet * sh, struct ent * v, struct enode
p = "";
} else if (v->flags & is_strexpr || v->expr) {
cellerror = CELLOK;
- p = seval(sh, v, se);
+ p = seval(sh, v, se, 1);
} else {
cellerror = CELLOK;
- p = seval(sh, NULL, se);
+ p = seval(sh, v, se, 0);
}
if (v->cellerror != cellerror) {
v->flags |= is_changed;
@@ -1610,7 +1616,7 @@ void slet(struct roman * roman, st