summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgzagatti <gzagatti@users.noreply.github.com>2023-05-08 20:06:56 +0800
committergzagatti <gzagatti@users.noreply.github.com>2023-05-08 20:06:56 +0800
commitc310edb5f6c6cd90da0b1fe13e3879dcda632071 (patch)
tree26f1879d0377e190b53eb7f64f77060a4ffe9036
parentde24a4c257fb7fd69bed8d204fe6eef50302ce38 (diff)
fix issue #784, exposes row and column of calling cell in @lua script
-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 0325d6a..7b57a95 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 3d38471..91b93e0 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);
@@ -1511,7 +1511,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, struct sheet * sh, struct ent * v, struct enode
efree(v->expr);
v->expr = se;
- p = seval(sh, v, se); /* ADDED for #652 - here we store the cell dependences in a graph */
+ p = seval(sh, v, se, 1); /* ADDED for #652 - here we store the cell dependences in a graph */
if (p) scxfree(p); /***/
v->flags |= (is_chan