1 /* SC A Spreadsheet Calculator 2 * Expression interpreter and assorted support routines. 3 * 4 * original by James Gosling, September 1982 5 * modified by Mark Weiser and Bruce Israel, 6 * University of Maryland 7 * 8 * More mods Robert Bond, 12/86 9 * More mods by Alan Silverstein, 3-4/88, see list of changes. 10 * $Revision: 6.8 $ 11 */ 12 13 #define DEBUGDTS 1 /* REMOVE ME */ 14 /* #define EXPRTREE /* expr. dependency tree stuff, not ready yet */ 15 16 #ifdef aiws 17 #undef _C_func /* Fixes for undefined symbols on AIX */ 18 #endif 19 20 #ifdef IEEE_MATH 21 #include <ieeefp.h> 22 #endif /* IEEE_MATH */ 23 24 #include <math.h> 25 #include <signal.h> 26 #include <setjmp.h> 27 #include <stdio.h> 28 29 extern int errno; /* set by math functions */ 30 #ifdef BSD42 31 #include <strings.h> 32 #include <sys/time.h> 33 #ifndef strchr 34 #define strchr index 35 #endif 36 #else 37 #include <time.h> 38 #ifndef SYSIII 39 #include <string.h> 40 #endif 41 #endif 42 43 #include <curses.h> 44 #include "sc.h" 45 46 #if defined(BSD42) || defined(BSD43) 47 char *re_comp(); 48 #endif 49 #if defined(SYSV2) || defined(SYSV3) 50 char *regcmp(); 51 char *regex(); 52 #endif 53 54 #ifdef SIGVOID 55 void quit(); 56 #else 57 int quit(); 58 #endif 59 60 /* Use this structure to save the the last 'g' command */ 61 62 struct go_save { 63 int g_type; 64 double g_n; 65 char *g_s; 66 int g_row; 67 int g_col; 68 } gs; 69 70 /* g_type can be: */ 71 72 #define G_NONE 0 /* Starting value - must be 0*/ 73 #define G_NUM 1 74 #define G_STR 2 75 #define G_CELL 3 76 77 #define ISVALID(r,c) ((r)>=0 && (r)<maxrows && (c)>=0 && (c)<maxcols) 78 79 extern FILE *popen(); 80 81 jmp_buf fpe_save; 82 int exprerr; /* Set by eval() and seval() if expression errors */ 83 double prescale = 1.0; /* Prescale for constants in let() */ 84 int extfunc = 0; /* Enable/disable external functions */ 85 int loading = 0; /* Set when readfile() is active */ 86 double fn1_eval(); 87 double fn2_eval(); 88 struct ent *firstev = (struct ent *)0; /* first expr in the eval list */ 89 90 #define PI (double)3.14159265358979323846 91 #define dtr(x) ((x)*(PI/(double)180.0)) 92 #define rtd(x) ((x)*(180.0/(double)PI)) 93 94 double finfunc(fun,v1,v2,v3) 95 int fun; 96 double v1,v2,v3; 97 { 98 double answer,p; 99 100 p = fn2_eval(pow, 1 + v2, v3); 101 102 switch(fun) 103 { 104 case PV: 105 answer = v1 * (1 - 1/p) / v2; 106 break; 107 case FV: 108 answer = v1 * (p - 1) / v2; 109 break; 110 case PMT: 111 answer = v1 * v2 / (1 - 1/p); 112 break; 113 default: 114 error("Unknown function in finfunc"); 115 return((double)0); 116 } 117 return(answer); 118 } 119 120 char * 121 dostindex( val, minr, minc, maxr, maxc) 122 double val; 123 int minr, minc, maxr, maxc; 124 { 125 register r,c; 126 register struct ent *p; 127 char *pr; 128 int x; 129 130 x = (int) val; 131 r = minr; c = minc; 132 p = (struct ent *)0; 133 if ( minr == maxr ) { /* look along the row */ 134 c = minc + x - 1; 135 if (c <= maxc && c >=minc) 136 p = *ATBL(tbl, r, c); 137 } else if ( minc == maxc ) { /* look down the column */ 138 r = minr + x - 1; 139 if (r <= maxr && r >=minr) 140 p = *ATBL(tbl, r, c); 141 } else { 142 error ("range specified to @stindex"); 143 return((char *)0); 144 } 145 146 if (p && p->label) { 147 pr = xmalloc((unsigned)(strlen(p->label)+1)); 148 (void)strcpy(pr, p->label); 149 return (pr); 150 } else 151 return((char *)0); 152 } 153 154 double 155 doindex( val, minr, minc, maxr, maxc) 156 double val; 157 int minr, minc, maxr, maxc; 158 { 159 double v; 160 register r,c; 161 register struct ent *p; 162 int x; 163 164 x = (int) val; 165 v = (double)0; 166 r = minr; c = minc; 167 if ( minr == maxr ) { /* look along the row */ 168 c = minc + x - 1; 169 if (c <= maxc && c >=minc 170 && (p = *ATBL(tbl, r, c)) && p->flags&is_valid ) 171 return p->v; 172 } 173 else if ( minc == maxc ){ /* look down the column */ 174 r = minr + x - 1; 175 if (r <= maxr && r >=minr 176 && (p = *ATBL(tbl, r, c)) && p->flags&is_valid ) 177 return p->v; 178 } 179 else error(" range specified to @index"); 180 return v; 181 } 182 183 double 184 dolookup( val, minr, minc, maxr, maxc, offr, offc) 185 struct enode * val; 186 int minr, minc, maxr, maxc, offr, offc; 187 { 188 double v, ret = (double)0; 189 register r,c; 190 register struct ent *p = (struct ent *)0; 191 int incr,incc,fndr,fndc; 192 char *s; 193 194 incr = (offc != 0); incc = (offr != 0); 195 if (etype(val) == NUM) { 196 v = eval(val); 197 for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) { 198 if ( (p = *ATBL(tbl, r, c)) && p->flags&is_valid ) { 199 if (p->v <= v) { 200 fndr = incc ? (minr + offr) : r; 201 fndc = incr ? (minc + offc) : c; 202 if (ISVALID(fndr,fndc)) 203 p = *ATBL(tbl, fndr, fndc); 204 else error(" range specified to @[hv]lookup"); 205 if ( p && p->flags&is_valid) 206 ret = p->v; 207 } else break; 208 } 209 } 210 } else { 211 s = seval(val); 212 for (r = minr, c = minc; r <= maxr && c <= maxc; r+=incr, c+=incc) { 213 if ( (p = *ATBL(tbl, r, c)) && p->label ) { 214 if (strcmp(p->label,s) == 0) { 215 fndr = incc ? (minr + offr) : r; 216 fndc = incr ? (minc + offc) : c; 217 if (ISVALID(fndr,fndc)) 218 p = *ATBL(tbl, fndr, fndc); 219 else error(" range specified to @[hv]lookup"); 220 break; 221 } 222 } 223 } 224 if ( p && p->flags&is_valid) 225 ret = p->v; 226 xfree(s); 227 } 228 return ret; 229 } 230 231 double 232 docount(minr, minc, maxr, maxc) 233 int minr, minc, maxr, maxc; 234 { 235 int v; 236 register r,c; 237 register struct ent *p; 238 239 v = 0; 240 for (r = minr; r<=maxr; r++) 241 for (c = minc; c<=maxc; c++) 242 if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) 243 v++; 244 return v; 245 } 246 247 double 248 dosum(minr, minc, maxr, maxc) 249 int minr, minc, maxr, maxc; 250 { 251 double v; 252 register r,c; 253 register struct ent *p; 254 255 v = (double)0; 256 for (r = minr; r<=maxr; r++) 257 for (c = minc; c<=maxc; c++) 258 if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) 259 v += p->v; 260 return v; 261 } 262 263 double 264 doprod(minr, minc, maxr, maxc) 265 int minr, minc, maxr, maxc; 266 { 267 double v; 268 register r,c; 269 register struct ent *p; 270 271 v = 1; 272 for (r = minr; r<=maxr; r++) 273 for (c = minc; c<=maxc; c++) 274 if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) 275 v *= p->v; 276 return v; 277 } 278 279 double 280 doavg(minr, minc, maxr, maxc) 281 int minr, minc, maxr, maxc; 282 { 283 double v; 284 register r,c,count; 285 register struct ent *p; 286 287 v = (double)0; 288 count = 0; 289 for (r = minr; r<=maxr; r++) 290 for (c = minc; c<=maxc; c++) 291 if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) { 292 v += p->v; 293 count++; 294 } 295 296 if (count == 0) 297 return ((double) 0); 298 299 return (v / (double)count); 300 } 301 302 double 303 dostddev(minr, minc, maxr, maxc) 304 int minr, minc, maxr, maxc; 305 { 306 double lp, rp, v, nd; 307 register r,c,n; 308 register struct ent *p; 309 310 n = 0; 311 lp = 0; 312 rp = 0; 313 for (r = minr; r<=maxr; r++) 314 for (c = minc; c<=maxc; c++) 315 if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) { 316 v = p->v; 317 lp += v*v; 318 rp += v; 319 n++; 320 } 321 322 if ((n == 0) || (n == 1)) 323 return ((double) 0); 324 nd = (double)n; 325 return (sqrt((nd*lp-rp*rp)/(nd*(nd-1)))); 326 } 327 328 double 329 domax(minr, minc, maxr, maxc) 330 int minr, minc, maxr, maxc; 331 { 332 double v = (double)0; 333 register r,c,count; 334 register struct ent *p; 335 336 count = 0; 337 for (r = minr; r<=maxr; r++) 338 for (c = minc; c<=maxc; c++) 339 if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) { 340 if (!count) { 341 v = p->v; 342 count++; 343 } else if (p->v > v) 344 v = p->v; 345 } 346 347 if (count == 0) 348 return ((double) 0); 349 350 return (v); 351 } 352 353 double 354 domin(minr, minc, maxr, maxc) 355 int minr, minc, maxr, maxc; 356 { 357 double v = (double)0; 358 register r,c,count; 359 register struct ent *p; 360 361 count = 0; 362 for (r = minr; r<=maxr; r++) 363 for (c = minc; c<=maxc; c++) 364 if ((p = *ATBL(tbl, r, c)) && p->flags&is_valid) { 365 if (!count) { 366 v = p->v; 367 count++; 368 } else if (p->v < v) 369 v = p->v; 370 } 371 372 if (count == 0) 373 return ((double) 0); 374 375 return (v); 376 } 377 378 #define sec_min 60 379 #define sec_hr 3600L 380 #define sec_day 86400L 381 #define sec_yr 31471200L /* 364.25 days/yr */ 382 #define sec_mo 2622600L /* sec_yr/12: sort of an average */ 383 int mdays[12]={ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 384 385 double 386 dodts(mo, day, yr) 387 int mo, day, yr; 388 { 389 long trial; 390 register struct tm *tp; 391 register int i; 392 register long jdate; 393 394 mdays[1] = 28 + (yr%4 == 0); 395 396 if (mo < 1 || mo > 12 || day < 1 || day > mdays[--mo] || 397 yr > 1999 || yr < 1970) { 398 error("@dts: invalid argument"); 399 return(0.0); 400 } 401 402 jdate = day-1; 403 for (i=0; i<mo; i++) 404 jdate += mdays[i]; 405 for (i = 1970; i < yr; i++) 406 jdate += 365 + (i%4 == 0); 407 408 trial = jdate * sec_day; 409 410 yr -= 1900; 411 412 tp = localtime(&trial); 413 414 if (tp->tm_year != yr) { 415 /* 416 * We may fail this test once a year because of time zone 417 * and daylight savings time errors. This bounces the 418 * trial time past the boundary. The error introduced is 419 * corrected below. 420 */ 421 trial += sec_day*(yr - tp->tm_year); 422 tp = localtime(&trial); 423 } 424 if (tp->tm_mon != mo) { 425 /* We may fail this test once a month. */ 426 trial += sec_day*(mo - tp->tm_mon); 427 tp = localtime(&trial); 428 } 429 if (tp->tm_mday + tp->tm_hour + tp->tm_min + tp->tm_sec != day) { 430 trial -= (tp->tm_mday - day)*sec_day + tp->tm_hour*sec_hr 431 + tp->tm_min*sec_min + tp->tm_sec; 432 } 433 434 #ifdef DEBUGDTS 435 tp = localtime(&trial); 436 if (tp->tm_mday + tp->tm_hour + tp->tm_min + tp->tm_sec + 437 tp->tm_year + tp->tm_mon != yr+mo+day) 438 error("Dts broke down"); 439 #endif 440 441 return ((double)trial); 442 } 443 444 double 445 dotts(hr, min, sec) 446 int hr, min, sec; 447 { 448 if (hr < 0 || hr > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) { 449 error ("@tts: Invalid argument"); 450 return ((double)0); 451 } 452 return ((double)(sec+min*60+hr*3600)); 453 } 454 455 double 456 dotime(which, when) 457 int which; 458 double when; 459 { 460 long time(); 461 462 static long t_cache; 463 static struct tm tm_cache; 464 struct tm *tp; 465 long tloc; 466 467 if (which == NOW) 468 return (double)time((long *)0); 469 470 tloc = (long)when; 471 472 if (tloc != t_cache) { 473 tp = localtime(&tloc); 474 tm_cache = *tp; 475 tm_cache.tm_mon += 1; 476 tm_cache.tm_year += 1900; 477 t_cache = tloc; 478 } 479 480 switch (which) { 481 case HOUR: return((double)(tm_cache.tm_hour)); 482 case MINUTE: return((double)(tm_cache.tm_min)); 483 case SECOND: return((double)(tm_cache.tm_sec)); 484 case MONTH: return((double)(tm_cache.tm_mon)); 485 case DAY: return((double)(tm_cache.tm_mday)); 486 case YEAR: return((double)(tm_cache.tm_year)); 487 } 488 /* Safety net */ 489 return ((double)0); 490 } 491 492 double 493 doston(s) 494 char *s; 495 { 496 char *strtof(); 497 double v; 498 499 if (!s) 500 return((double)0); 501 502 (void)strtof(s, &v); 503 xfree(s); 504 return(v); 505 } 506 507 double 508 doeqs(s1, s2) 509 char *s1, *s2; 510 { 511 double v; 512 513 if (!s1 && !s2) 514 return((double)1.0); 515 516 if (!s1 || !s2) 517 v = 0.0; 518 else if (strcmp(s1, s2) == 0) 519 v = 1.0; 520 else 521 v = 0.0; 522 523 if (s1) 524 xfree(s1); 525 526 if (s2) 527 xfree(s2); 528 529 return(v); 530 } 531 532 533 /* 534 * Given a string representing a column name and a value which is a column 535 * number, return a pointer to the selected cell's entry, if any, else 0. Use 536 * only the integer part of the column number. Always free the string. 537 */ 538 539 struct ent * 540 getent (colstr, rowdoub) 541 char *colstr; 542 double rowdoub; 543 { 544 int collen; /* length of string */ 545 int row, col; /* integer values */ 546 struct ent *ep = (struct ent *)0; /* selected entry */ 547 548 if (((row = (int) floor (rowdoub)) >= 0) 549 && (row < maxrows) /* in range */ 550 && ((collen = strlen (colstr)) <= 2) /* not too long */ 551 && ((col = atocol (colstr, collen)) >= 0) 552 && (col < maxcols)) /* in range */ 553 { 554 ep = *ATBL(tbl, row, col); 555 } 556 557 xfree (colstr); 558 return (ep); 559 } 560 561 562 /* 563 * Given a string representing a column name and a value which is a column 564 * number, return the selected cell's numeric value, if any. 565 */ 566 567 double 568 donval (colstr, rowdoub) 569 char *colstr; 570 double rowdoub; 571 { 572 struct ent *ep; 573 574 return (((ep = getent (colstr, rowdoub)) && ((ep -> flags) & is_valid)) ? 575 (ep -> v) : (double)0); 576 } 577 578 579 /* 580 * The list routines (e.g. dolmax) are called with an LMAX enode. 581 * The left pointer is a chain of ELIST nodes, the right pointer 582 * is a value. 583 */ 584 double 585 dolmax(ep) 586 struct enode *ep; 587 { 588 register int count = 0; 589 register double maxval = 0; /* Assignment to shut up lint */ 590 register struct enode *p; 591 register double v; 592 593 for (p = ep; p; p = p->e.o.left) { 594 v = eval(p->e.o.right); 595 if (!count || v > maxval) { 596 maxval = v; count++; 597 } 598 } 599 if (count) return maxval; 600 else return (double)0; 601 } 602 603 double 604 dolmin(ep) 605 struct enode *ep; 606 { 607 register int count = 0; 608 register double minval = 0; /* Assignment to shut up lint */ 609 register struct enode *p; 610 register double v; 611 612 for (p = ep; p; p = p->e.o.left) { 613 v = eval(p->e.o.right); 614 if (!count || v < minval) { 615 minval = v; count++; 616 } 617 } 618 if (count) return minval; 619 else return (double)0; 620 } 621 622 double 623 eval(e) 624 register struct enode *e; 625 { 626 if (e == (struct enode *)0) return (double)0; 627 switch (e->op) { 628 case '+': return (eval(e->e.o.left) + eval(e->e.o.right)); 629 case '-': return (eval(e->e.o.left) - eval(e->e.o.right)); 630 case '*': return (eval(e->e.o.left) * eval(e->e.o.right)); 631 case '/': return (eval(e->e.o.left) / eval(e->e.o.right)); 632 case '%': { double num, denom; 633 num = floor(eval(e->e.o.left)); 634 denom = floor(eval (e->e.o.right)); 635 return denom ? num - floor(num/denom)*denom : (double)0; } 636 case '^': return (fn2_eval(pow,eval(e->e.o.left),eval(e->e.o.right))); 637 case '<': return (eval(e->e.o.left) < eval(e->e.o.right)); 638 case '=': return (eval(e->e.o.left) == eval(e->e.o.right)); 639 case '>': return (eval(e->e.o.left) > eval(e->e.o.right)); 640 case '&': return (eval(e->e.o.left) && eval(e->e.o.right)); 641 case '|': return (eval(e->e.o.left) || eval(e->e.o.right)); 642 case IF: 643 case '?': return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left) 644 : eval(e->e.o.right->e.o.right); 645 case 'm': return (-eval(e->e.o.right)); 646 case 'f': return (eval(e->e.o.right)); 647 case '~': return (eval(e->e.o.right) == 0.0); 648 case 'k': return (e->e.k); 649 case 'v': return (e->e.v.vp->v); 650 case INDEX: 651 case LOOKUP: 652 case HLOOKUP: 653 case VLOOKUP: 654 { register r,c; 655 register maxr, maxc; 656 register minr, minc; 657 maxr = e->e.o.right->e.r.right.vp -> row; 658 maxc = e->e.o.right->e.r.right.vp -> col; 659 minr = e->e.o.right->e.r.left.vp -> row; 660 minc = e->e.o.right->e.r.left.vp -> col; 661 if (minr>maxr) r = maxr, maxr = minr, minr = r; 662 if (minc>maxc) c = maxc, maxc = minc, minc = c; 663 switch(e->op){ 664 case LOOKUP: 665 return dolookup(e->e.o.left, minr, minc, maxr, maxc, 666 minr==maxr, minc==maxc); 667 case HLOOKUP: 668 return dolookup(e->e.o.left->e.o.left, minr,minc,maxr,maxc, 669 (int) eval(e->e.o.left->e.o.right), 0); 670 case VLOOKUP: 671 return dolookup(e->e.o.left->e.o.left, minr,minc,maxr,maxc, 672 0, (int) eval(e->e.o.left->e.o.right)); 673 case INDEX: 674 return doindex(eval(e->e.o.left), minr, minc, maxr, maxc); 675 } 676 } 677 case REDUCE | '+': 678 case REDUCE | '*': 679 case REDUCE | 'a': 680 case REDUCE | 'c': 681 case REDUCE | 's': 682 case REDUCE | MAX: 683 case REDUCE | MIN: 684 { register r,c; 685 register maxr, maxc; 686 register minr, minc; 687 maxr = e->e.r.right.vp -> row; 688 maxc = e->e.r.right.vp -> col; 689 minr = e->e.r.left.vp -> row; 690 minc = e->e.r.left.vp -> col; 691 if (minr>maxr) r = maxr, maxr = minr, minr = r; 692 if (minc>maxc) c = maxc, maxc = minc, minc = c; 693 switch (e->op) { 694 case REDUCE | '+': return dosum(minr, minc, maxr, maxc); 695 case REDUCE | '*': return doprod(minr, minc, maxr, maxc); 696 case REDUCE | 'a': return doavg(minr, minc, maxr, maxc); 697 case REDUCE | 'c': return docount(minr, minc, maxr, maxc); 698 case REDUCE | 's': return dostddev(minr, minc, maxr, maxc); 699 case REDUCE | MAX: return domax(minr, minc, maxr, maxc); 700 case REDUCE | MIN: return domin(minr, minc, maxr, maxc); 701 } 702 } 703 case ABS: return (fn1_eval( fabs, eval(e->e.o.right))); 704 case ACOS: return (fn1_eval( acos, eval(e->e.o.right))); 705 case ASIN: return (fn1_eval( asin, eval(e->e.o.right))); 706 case ATAN: return (fn1_eval( atan, eval(e->e.o.right))); 707 case ATAN2: return (fn2_eval( atan2, eval(e->e.o.left), eval(e->e.o.right))); 708 case CEIL: return (fn1_eval( ceil, eval(e->e.o.right))); 709 case COS: return (fn1_eval( cos, eval(e->e.o.right))); 710 case EXP: return (fn1_eval( exp, eval(e->e.o.right))); 711 case FABS: return (fn1_eval( fabs, eval(e->e.o.right))); 712 case FLOOR: return (fn1_eval( floor, eval(e->e.o.right))); 713 case HYPOT: return (fn2_eval( hypot, eval(e->e.o.left), eval(e->e.o.right))); 714 case LOG: return (fn1_eval( log, eval(e->e.o.right))); 715 case LOG10: return (fn1_eval( log10, eval(e->e.o.right))); 716 case POW: return (fn2_eval( pow, eval(e->e.o.left), eval(e->e.o.right))); 717 case SIN: return (fn1_eval( sin, eval(e->e.o.right))); 718 case SQRT: return (fn1_eval( sqrt, eval(e->e.o.right))); 719 case TAN: return (fn1_eval( tan, eval(e->e.o.right))); 720 case DTR: return (dtr(eval(e->e.o.right))); 721 case RTD: return (rtd(eval(e->e.o.right))); 722 case RND: { 723 double temp; 724 temp = eval(e->e.o.right); 725 return(temp-floor(temp) < 0.5 ? 726 floor(temp) : ceil(temp)); 727 } 728 case ROUND: { 729 double temp = eval(e->e.o.left); 730 int prec = (int) eval(e->e.o.right), scal = 1; 731 while (prec-- > 0) scal *= 10; 732 temp *= scal; 733 temp = ((temp-floor(temp)) < 0.5 ? 734 floor(temp) : ceil(temp)); 735 return(temp / scal); 736 } 737 case FV: 738 case PV: 739 case PMT: return(finfunc(e->op,eval(e->e.o.left), 740 eval(e->e.o.right->e.o.left), 741 eval(e->e.o.right->e.o.right))); 742 case HOUR: return (dotime(HOUR, eval(e->e.o.right))); 743 case MINUTE: return (dotime(MINUTE, eval(e->e.o.right))); 744 case SECOND: return (dotime(SECOND, eval(e->e.o.right))); 745 case MONTH: return (dotime(MONTH, eval(e->e.o.right))); 746 case DAY: return (dotime(DAY, eval(e->e.o.right))); 747 case YEAR: return (dotime(YEAR, eval(e->e.o.right))); 748 case NOW: return (dotime(NOW, (double)0.0)); 749 case DTS: return (dodts((int)eval(e->e.o.left), 750 (int)eval(e->e.o.right->e.o.left), 751 (int)eval(e->e.o.right->e.o.right))); 752 case TTS: return (dotts((int)eval(e->e.o.left), 753 (int)eval(e->e.o.right->e.o.left), 754 (int)eval(e->e.o.right->e.o.right))); 755 case STON: return (doston(seval(e->e.o.right))); 756 case EQS: return (doeqs(seval(e->e.o.right),seval(e->e.o.left))); 757 case LMAX: return dolmax(e); 758 case LMIN: return dolmin(e); 759 case NVAL: return (donval(seval(e->e.o.left),eval(e->e.o.right))); 760 default: error ("Illegal numeric expression"); 761 exprerr = 1; 762 } 763 return((double)0.0); 764 } 765 766 #ifdef SIGVOID 767 void 768 #endif 769 eval_fpe(signo) /* Trap for FPE errors in eval */ 770 int signo; 771 { 772 #ifdef IEEE_MATH 773 (void)fpsetsticky((fp_except)0); /* Clear exception */ 774 #endif /* IEEE_MATH */ 775 longjmp(fpe_save, 1); 776 } 777 778 double fn1_eval(fn, arg) 779 double (*fn)(); 780 double arg; 781 { 782 double res; 783 errno = 0; 784 res = (*fn)(arg); 785 if(errno) 786 eval_fpe(0); 787 788 return res; 789 } 790 791 double fn2_eval(fn, arg1, arg2) 792 double (*fn)(); 793 double arg1, arg2; 794 { 795 double res; 796 errno = 0; 797 res = (*fn)(arg1, arg2); 798 if(errno) 799 eval_fpe(0); 800 801 return res; 802 } 803 804 /* 805 * Rules for string functions: 806 * Take string arguments which they xfree. 807 * All returned strings are assumed to be xalloced. 808 */ 809 810 char * 811 docat(s1, s2) 812 register char *s1, *s2; 813 { 814 register char *p; 815 char *arg1, *arg2; 816 817 if (!s1 && !s2) 818 return((char *)0); 819 arg1 = s1 ? s1 : ""; 820 arg2 = s2 ? s2 : ""; 821 p = xmalloc((unsigned)(strlen(arg1)+strlen(arg2)+1)); 822 (void) strcpy(p, arg1); 823 (void) strcat(p, arg2); 824 if (s1) 825 xfree(s1); 826 if (s2) 827 xfree(s2); 828 return(p); 829 } 830 831 char * 832 dodate(tloc) 833 long tloc; 834 { 835 char *tp; 836 char *p; 837 838 tp = ctime(&tloc); 839 tp[24] = '\0'; 840 p = xmalloc((unsigned)25); 841 (void) strcpy(p, tp); 842 return(p); 843 } 844 845 846 char * 847 dofmt(fmtstr, v) 848 char *fmtstr; 849 double v; 850 { 851 char buff[FBUFLEN]; 852 char *p; 853 854 if (!fmtstr) 855 return((char *)0); 856 (void)sprintf(buff, fmtstr, v); 857 p = xmalloc((unsigned)(strlen(buff)+1)); 858 (void) strcpy(p, buff); 859 xfree(fmtstr); 860 return(p); 861 } 862 863 864 /* 865 * Given a command name and a value, run the command with the given value and 866 * read and return its first output line (only) as an allocated string, always 867 * a copy of prevstr, which is set appropriately first unless external 868 * functions are disabled, in which case the previous value is used. The 869 * handling of prevstr and freeing of command is tricky. Returning an 870 * allocated string in all cases, even if null, insures cell expressions are 871 * written to files, etc. 872 */ 873 874 #ifdef VMS 875 char * 876 doext(command, value) 877 char *command; 878 double value; 879 { 880 error("Warning: External functions unavailable on VMS"); 881 if (command) 882 xfree(command); 883 return (strcpy (xmalloc((unsigned) 1), "\0")); 884 } 885 886 #else /* VMS */ 887 888 char * 889 doext (command, value) 890 char *command; 891 double value; 892 { 893 static char *prevstr = (char *)0; /* previous result */ 894 char buff[FBUFLEN]; /* command line/return, not permanently alloc */ 895 896 if (!prevstr) { 897 prevstr = xmalloc((unsigned)1); 898 *prevstr = '\0'; 899 } 900 if (!extfunc) { 901 error ("Warning: external functions disabled; using %s value", 902 prevstr ? "previous" : "null"); 903 904 if (command) xfree (command); 905 } else { 906 if (prevstr) xfree (prevstr); /* no longer needed */ 907 prevstr = '\0'; 908 909 if ((! command) || (! *command)) { 910 error ("Warning: external function given null command name"); 911 if (command) xfree (command); 912 } else { 913 FILE *pp; 914 915 (void) sprintf (buff, "%s %g", command, value); /* build cmd line */ 916 xfree (command); 917 918 error ("Running external function..."); 919 (void) refresh(); 920 921 if ((pp = popen (buff, "r")) == (FILE *) NULL) /* run it */ 922 error ("Warning: running \"%s\" failed", buff); 923 else { 924 if (fgets (buff, sizeof(buff)-1, pp) == NULL) /* one line */ 925 error ("Warning: external function returned nothing"); 926 else { 927 char *cp; 928 929 error (""); /* erase notice */ 930 buff[sizeof(buff)-1] = '\0'; 931 932 if (cp = strchr (buff, '\n')) /* contains newline */ 933 *cp = '\0'; /* end string there */ 934 935 (void) strcpy (prevstr = 936 xmalloc ((unsigned) (strlen (buff) + 1)), buff); 937 /* save alloc'd copy */ 938 } 939 (void) pclose (pp); 940 941 } /* else */ 942 } /* else */ 943 } /* else */ 944 return (strcpy (xmalloc ((unsigned) (strlen (prevstr) + 1)), prevstr)); 945 } 946 947 #endif /* VMS */ 948 949 950 /* 951 * Given a string representing a column name and a value which is a column 952 * number, return the selected cell's string value, if any. Even if none, 953 * still allocate and return a null string so the cell has a label value so 954 * the expression is saved in a file, etc. 955 */ 956 957 char * 958 dosval (colstr, rowdoub) 959 char *colstr; 960 double rowdoub; 961 { 962 struct ent *ep; 963 char *label; 964 965 label = (ep = getent (colstr, rowdoub)) ? (ep -> label) : ""; 966 return (strcpy (xmalloc ((unsigned) (strlen (label) + 1)), label)); 967 } 968 969 970 /* 971 * Substring: Note that v1 and v2 are one-based to users, but zero-based 972 * when calling this routine. 973 */ 974 975 char * 976 dosubstr(s, v1, v2) 977 char *s; 978 register int v1,v2; 979 { 980 register char *s1, *s2; 981 char *p; 982 983 if (!s) 984 return((char *)0); 985 986 if (v2 >= strlen (s)) /* past end */ 987 v2 = strlen (s) - 1; /* to end */ 988 989 if (v1 < 0 || v1 > v2) { /* out of range, return null string */ 990 xfree(s); 991 p = xmalloc((unsigned)1); 992 p[0] = '\0'; 993 return(p); 994 } 995 s2 = p = xmalloc((unsigned)(v2-v1+2)); 996 s1 = &s[v1]; 997 for(; v1 <= v2; s1++, s2++, v1++) 998 *s2 = *s1; 999 *s2 = '\0'; 1000 xfree(s); 1001 return(p); 1002 } 1003 1004 char * 1005 seval(se) 1006 register struct enode *se; 1007 { 1008 register char *p; 1009 1010 if (se == (struct enode *)0) return (char *)0; 1011 switch (se->op) { 1012 case O_SCONST: p = xmalloc((unsigned)(strlen(se->e.s)+1)); 1013 (void) strcpy(p, se->e.s); 1014 return(p); 1015 case O_VAR: { 1016 struct ent *ep; 1017 ep = se->e.v.vp; 1018 1019 if (!ep->label) 1020 return((char *)0); 1021 p = xmalloc((unsigned)(strlen(ep->label)+1)); 1022 (void) strcpy(p, ep->label); 1023 return(p); 1024 } 1025 case '#': return(docat(seval(se->e.o.left), seval(se->e.o.right))); 1026 case 'f': return(seval(se->e.o.right)); 1027 case IF: 1028 case '?': return(eval(se->e.o.left) ? seval(se->e.o.right->e.o.left) 1029 : seval(se->e.o.right->e.o.right)); 1030 case DATE: return(dodate((long)(eval(se->e.o.right)))); 1031 case FMT: return(dofmt(seval(se->e.o.left), eval(se->e.o.right))); 1032 case STINDEX: 1033 { register r,c; 1034 register maxr, maxc; 1035 register minr, minc; 1036 maxr = se->e.o.right->e.r.right.vp -> row; 1037 maxc = se->e.o.right->e.r.right.vp -> col; 1038 minr = se->e.o.right->e.r.left.vp -> row; 1039 minc = se->e.o.right->e.r.left.vp -> col; 1040 if (minr>maxr) r = maxr, maxr = minr, minr = r; 1041 if (minc>maxc) c = maxc, maxc = minc, minc = c; 1042 return dostindex(eval(se->e.o.left), minr, minc, maxr, maxc); 1043 } 1044 case EXT: return(doext(seval(se->e.o.left), eval(se->e.o.right))); 1045 case SVAL: return(dosval(seval(se->e.o.left), eval(se->e.o.right))); 1046 case SUBSTR: return(dosubstr(seval(se->e.o.left), 1047 (int)eval(se->e.o.right->e.o.left) - 1, 1048 (int)eval(se->e.o.right->e.o.right) - 1)); 1049 default: 1050 error ("Illegal string expression"); 1051 exprerr = 1; 1052 return((char *)0); 1053 } 1054 } 1055 1056 /* 1057 * The graph formed by cell expressions which use other cells's values is not 1058 * evaluated "bottom up". The whole table is merely re-evaluated cell by cell, 1059 * top to bottom, left to right, in RealEvalAll(). Each cell's expression uses 1060 * constants in other cells. However, RealEvalAll() notices when a cell gets a 1061 * new numeric or string value, and reports if this happens for any cell. 1062 * EvalAll() repeats calling RealEvalAll() until there are no changes or the 1063 * evaluation count expires. 1064 */ 1065 1066 int propagation = 10; /* max number of times to try calculation */ 1067 1068 void 1069 setiterations(i) 1070 int i; 1071 { 1072 if(i<1) { 1073 error("iteration count must be at least 1"); 1074 propagation = 1; 1075 } 1076 else propagation = i; 1077 } 1078 1079 void 1080 EvalAll () { 1081 int lastcnt, repct = 0; 1082 1083 while ((lastcnt = RealEvalAll()) && (repct++ <= propagation)); 1084 if((propagation>1)&& (lastcnt >0 )) 1085 error("Still changing after %d iterations",propagation-1); 1086 } 1087 1088 /* 1089 * Evaluate all cells which have expressions and alter their numeric or string 1090 * values. Return the number of cells which changed. 1091 */ 1092 1093 int 1094 RealEvalAll () { 1095 register int i,j; 1096 int chgct = 0; 1097 register struct ent *p; 1098 1099 (void) signal(SIGFPE, eval_fpe); 1100 #ifdef EXPRTREE 1101 for (p = firstev; p; p = p->evnext) 1102 RealEvalOne(p, &chgct); 1103 #else 1104 if(calc_order == BYROWS ) { 1105 for (i=0; i<=maxrow; i++) 1106 for (j=0; j<=maxcol; j++) 1107 if ((p=tbl[i][j]) && p->expr) RealEvalOne(p,i,j, &chgct); 1108 } 1109 else if ( calc_order == BYCOLS ) { 1110 for (j=0; j<=maxcol; j++) 1111 { for (i=0; i<=maxrow; i++) 1112 if ((p=tbl[i][j]) && p->expr) RealEvalOne(p,i,j, &chgct); 1113 } 1114 } 1115 else error("Internal error calc_order"); 1116 #endif 1117 1118 (void) signal(SIGFPE, quit); 1119 return(chgct); 1120 } 1121 1122 void 1123 #ifdef EXPRTREE 1124 RealEvalOne(p, chgct) 1125 register struct ent *p; 1126 int *chgct; 1127 #else 1128 RealEvalOne(p, i, j, chgct) 1129 register struct ent *p; 1130 int i, j, *chgct; 1131 #endif 1132 { 1133 if (p->flags & is_strexpr) { 1134 char *v; 1135 if (setjmp(fpe_save)) { 1136 #ifdef EXPRTREE 1137 error("Floating point exception %s", v_name(p->row, p->col)); 1138 #else 1139 error("Floating point exception %s", v_name(i, j)); 1140 #endif 1141 v = ""; 1142 } else { 1143 v = seval(p->expr); 1144 } 1145 if (!v && !p->label) /* Everything's fine */ 1146 return; 1147 if (!p->label || !v || strcmp(v, p->label) != 0) { 1148 (*chgct)++; 1149 p->flags |= is_changed; 1150 changed++; 1151 } 1152 if(p->label) 1153 xfree(p->label); 1154 p->label = v; 1155 } else { 1156 double v; 1157 if (setjmp(fpe_save)) { 1158 #ifdef EXPRTREE 1159 error("Floating point exception %s", v_name(p->row, p->col)); 1160 #else 1161 error("Floating point exception %s", v_name(i, j)); 1162 #endif 1163 v = (double)0.0; 1164 } else { 1165 v = eval (p->expr); 1166 } 1167 if (v != p->v) { 1168 p->v = v; (*chgct)++; 1169 p->flags |= is_changed|is_valid; 1170 changed++; 1171 } 1172 } 1173 } 1174 1175 struct enode * 1176 new(op, a1, a2) 1177 int op; 1178 struct enode *a1, *a2; 1179 { 1180 register struct enode *p; 1181 p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode)); 1182 p->op = op; 1183 p->e.o.left = a1; 1184 p->e.o.right = a2; 1185 return p; 1186 } 1187 1188 struct enode * 1189 new_var(op, a1) 1190 int op; 1191 struct ent_ptr a1; 1192 { 1193 register struct enode *p; 1194 p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode)); 1195 p->op = op; 1196 p->e.v = a1; 1197 return p; 1198 } 1199 1200 struct enode * 1201 new_range(op, a1) 1202 int op; 1203 struct range_s a1; 1204 { 1205 register struct enode *p; 1206 p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode)); 1207 p->op = op; 1208 p->e.r = a1; 1209 return p; 1210 } 1211 1212 struct enode * 1213 new_const(op, a1) 1214 int op; 1215 double a1; 1216 { 1217 register struct enode *p; 1218 p = (struct enode *) xmalloc ((unsigned)sizeof (struct enode)); 1219 p->op = op; 1220 p->e.k = a1; 1221 return p; 1222 } 1223 1224 struct enode * 1225 new_str(s) 1226 char *s; 1227 { 1228 register struct enode *p; 1229 1230 p = (struct enode *) xmalloc ((unsigned)sizeof(struct enode)); 1231 p->op = O_SCONST; 1232 p->e.s = s; 1233 return(p); 1234 } 1235 1236 void 1237 copy(dv1, dv2, v1, v2) 1238 struct ent *dv1, *dv2, *v1, *v2; 1239 { 1240 int minsr, minsc; 1241 int maxsr, maxsc; 1242 int mindr, mindc; 1243 int maxdr, maxdc; 1244 int vr, vc; 1245 int r, c; 1246 1247 mindr = dv1->row; 1248 mindc = dv1->col; 1249 maxdr = dv2->row; 1250 maxdc = dv2->col; 1251 if (mindr>maxdr) r = maxdr, maxdr = mindr, mindr = r; 1252 if (mindc>maxdc) c = maxdc, maxdc = mindc, mindc = c; 1253 maxsr = v2->row; 1254 maxsc = v2->col; 1255 minsr = v1->row; 1256 minsc = v1->col; 1257 if (minsr>maxsr) r = maxsr, maxsr = minsr, minsr = r; 1258 if (minsc>maxsc) c = maxsc, maxsc = minsc, minsc = c; 1259 checkbounds(&maxdr, &maxdc); 1260 1261 erase_area(mindr, mindc, maxdr, maxdc); 1262 if (minsr == maxsr && minsc == maxsc) { 1263 /* Source is a single cell */ 1264 for(vr = mindr; vr <= maxdr; vr++) 1265 for (vc = mindc; vc <= maxdc; vc++) 1266 copyrtv(vr, vc, minsr, minsc, maxsr, maxsc); 1267 } else if (minsr == maxsr) { 1268 /* Source is a single row */ 1269 for (vr = mindr; vr <= maxdr; vr++) 1270 copyrtv(vr, mindc, minsr, minsc, maxsr, maxsc); 1271 } else if (minsc == maxsc) { 1272 /* Source is a single column */ 1273 for (vc = mindc; vc <= maxdc; vc++) 1274 copyrtv(mindr, vc, minsr, minsc, maxsr, maxsc); 1275 } else { 1276 /* Everything else */ 1277 copyrtv(mindr, mindc, minsr, minsc, maxsr, maxsc); 1278 } 1279 sync_refs(); 1280 } 1281 1282 void 1283 copyrtv(vr, vc, minsr, minsc, maxsr, maxsc) 1284 int vr, vc, minsr, minsc, maxsr, maxsc; 1285 { 1286 register struct ent *p; 1287 register struct ent *n; 1288 register int sr, sc; 1289 register int dr, dc; 1290 1291 for (dr=vr, sr=minsr; sr<=maxsr; sr++, dr++) 1292 for (dc=vc, sc=minsc; sc<=maxsc; sc++, dc++) { 1293 if (p = *ATBL(tbl, sr, sc)) 1294 { n = lookat (dr, dc); 1295 (void) clearent(n); 1296 copyent( n, p, dr - sr, dc - sc); 1297 } 1298 else 1299 if (n = *ATBL(tbl, dr, dc)) 1300 (void) clearent(n); 1301 } 1302 } 1303 1304 void 1305 eraser(v1, v2) 1306 struct ent *v1, *v2; 1307 { 1308 FullUpdate++; 1309 flush_saved(); 1310 erase_area(v1->row, v1->col, v2->row, v2->col); 1311 sync_refs(); 1312 } 1313 1314 /* Goto subroutines */ 1315 1316 void 1317 g_free() 1318 { 1319 switch (gs.g_type) { 1320 case G_STR: xfree(gs.g_s); break; 1321 default: break; 1322 } 1323 gs.g_type = G_NONE; 1324 } 1325 1326 void 1327 go_last() 1328 { 1329 switch (gs.g_type) { 1330 case G_NONE: 1331 error("Nothing to repeat"); break; 1332 case G_NUM: 1333 num_search(gs.g_n); 1334 break; 1335 case G_CELL: 1336 moveto(gs.g_row, gs.g_col); 1337 break; 1338 case G_STR: 1339 gs.g_type = G_NONE; /* Don't free the string */ 1340 str_search(gs.g_s); 1341 break; 1342 1343 default: error("go_last: internal error"); 1344 } 1345 } 1346 1347 void 1348 moveto(row, col) 1349 int row, col; 1350 { 1351 currow = row; 1352 curcol = col; 1353 g_free(); 1354 gs.g_type = G_CELL; 1355 gs.g_row = currow; 1356 gs.g_col = curcol; 1357 } 1358 1359 void 1360 num_search(n) 1361 double n; 1362 { 1363 register struct ent *p; 1364 register int r,c; 1365 int endr, endc; 1366 1367 g_free(); 1368 gs.g_type = G_NUM; 1369 gs.g_n = n; 1370 1371 if (currow > maxrow) 1372 endr = maxrow ? maxrow-1 : 0; 1373 else 1374 endr = currow; 1375 if (curcol > maxcol) 1376 endc = maxcol ? maxcol-1 : 0; 1377 else 1378 endc = curcol; 1379 r = endr; 1380 c = endc; 1381 do { 1382 if (c < maxcol) 1383 c++; 1384 else { 1385 if (r < maxrow) { 1386 while(++r < maxrow && row_hidden[r]) /* */; 1387 c = 0; 1388 } else { 1389 r = 0; 1390 c = 0; 1391 } 1392 } 1393 if (r == endr && c == endc) { 1394 error("Number not found"); 1395 return; 1396 } 1397 p = *ATBL(tbl, r, c); 1398 } while(col_hidden[c] || !p || p && (!(p->flags & is_valid) 1399 || (p->flags&is_valid) && p->v != n)); 1400 currow = r; 1401 curcol = c; 1402 } 1403 1404 void 1405 str_search(s) 1406 char *s; 1407 { 1408 register struct ent *p; 1409 register int r,c; 1410 int endr, endc; 1411 char *tmp; 1412 1413 #if defined(BSD42) || defined(BSD43) 1414 if ((tmp = re_comp(s)) != (char *)0) { 1415 xfree(s); 1416 error(tmp); 1417 return; 1418 } 1419 #endif 1420 #if defined(SYSV2) || defined(SYSV3) 1421 if ((tmp = regcmp(s, (char *)0)) == (char *)0) { 1422 xfree(s); 1423 error("Invalid search string"); 1424 return; 1425 } 1426 #endif 1427 g_free(); 1428 gs.g_type = G_STR; 1429 gs.g_s = s; 1430 if (currow > maxrow) 1431 endr = maxrow ? maxrow-1 : 0; 1432 else 1433 endr = currow; 1434 if (curcol > maxcol) 1435 endc = maxcol ? maxcol-1 : 0; 1436 else 1437 endc = curcol; 1438 r = endr; 1439 c = endc; 1440 do { 1441 if (c < maxcol) 1442 c++; 1443 else { 1444 if (r < maxrow) { 1445 while(++r < maxrow && row_hidden[r]) /* */; 1446 c = 0; 1447 } else { 1448 r = 0; 1449 c = 0; 1450 } 1451 } 1452 if (r == endr && c == endc) { 1453 error("String not found"); 1454 #if defined(SYSV2) || defined(SYSV3) 1455 free(tmp); 1456 #endif 1457 return; 1458 } 1459 p = *ATBL(tbl, r, c); 1460 } while(col_hidden[c] || !p || p && (!(p->label) 1461 #if defined(BSD42) || defined(BSD43) 1462 || (re_exec(p->label) == 0))); 1463 #else 1464 #if defined(SYSV2) || defined(SYSV3) 1465 || (regex(tmp, p->label) == (char *)0))); 1466 #else 1467 || (strcmp(s, p->label) != 0))); 1468 #endif 1469 #endif 1470 currow = r; 1471 curcol = c; 1472 #if defined(SYSV2) || defined(SYSV3) 1473 free(tmp); 1474 #endif 1475 } 1476 1477 void 1478 fill (v1, v2, start, inc) 1479 struct ent *v1, *v2; 1480 double start, inc; 1481 { 1482 register r,c; 1483 register struct ent *n; 1484 int maxr, maxc; 1485 int minr, minc; 1486 1487 maxr = v2->row; 1488 maxc = v2->col; 1489 minr = v1->row; 1490 minc = v1->col; 1491 if (minr>maxr) r = maxr, maxr = minr, minr = r; 1492 if (minc>maxc) c = maxc, maxc = minc, minc = c; 1493 checkbounds(&maxr, &maxc); 1494 if (minr < 0) minr = 0; 1495 if (minr < 0) minr = 0; 1496 1497 FullUpdate++; 1498 if( calc_order == BYROWS ) { 1499 for (r = minr; r<=maxr; r++) 1500 for (c = minc; c<=maxc; c++) { 1501 n = lookat (r, c); 1502 (void) clearent(n); 1503 n->v = start; 1504 start += inc; 1505 n->flags |= (is_changed|is_valid); 1506 } 1507 } 1508 else if ( calc_order == BYCOLS ) { 1509 for (c = minc; c<=maxc; c++) 1510 for (r = minr; r<=maxr; r++) { 1511 n = lookat (r, c); 1512 (void) clearent(n); 1513 n->v = start; 1514 start += inc; 1515 n->flags |= (is_changed|is_valid); 1516 } 1517 } 1518 else error(" Internal error calc_order"); 1519 changed++; 1520 } 1521 1522 void 1523 let (v, e) 1524 struct ent *v; 1525 struct enode *e; 1526 { 1527 double val; 1528 1529 exprerr = 0; 1530 (void) signal(SIGFPE, eval_fpe); 1531 if (setjmp(fpe_save)) { 1532 error ("Floating point exception in cell %s", v_name(v->row, v->col)); 1533 val = (double)0.0; 1534 } else { 1535 val = eval(e); 1536 } 1537 (void) signal(SIGFPE, quit); 1538 if (exprerr) { 1539 efree((struct ent *)0, e); 1540 return; 1541 } 1542 if (constant(e)) { 1543 if (!loading) 1544 v->v = val * prescale; 1545 else 1546 v->v = val; 1547 if (!(v->flags & is_strexpr)) { 1548 efree(v, v->expr); 1549 v->expr = (struct enode *)0; 1550 } 1551 efree((struct ent *)0, e); 1552 v->flags |= (is_changed|is_valid); 1553 changed++; 1554 modflg++; 1555 return; 1556 } 1557 efree (v, v->expr); 1558 v->expr = e; 1559 v->flags |= (is_changed|is_valid); 1560 v->flags &= ~is_strexpr; 1561 1562 #ifdef EXPRTREE 1563 totoptree(v); 1564 #endif 1565 changed++; 1566 modflg++; 1567 } 1568 1569 void 1570 slet (v, se, flushdir) 1571 struct ent *v; 1572 struct enode *se; 1573 int flushdir; 1574 { 1575 char *p; 1576 1577 exprerr = 0; 1578 (void) signal(SIGFPE, eval_fpe); 1579 if (setjmp(fpe_save)) { 1580 error ("Floating point exception in cell %s", v_name(v->row, v->col)); 1581 p = ""; 1582 } else { 1583 p = seval(se); 1584 } 1585 (void) signal(SIGFPE, quit); 1586 if (exprerr) { 1587 efree((struct ent *)0, se); 1588 return; 1589 } 1590 if (constant(se)) { 1591 label(v, p, flushdir); 1592 if (p) 1593 xfree(p); 1594 efree((struct ent *)0, se); 1595 if (v->flags & is_strexpr) { 1596 efree (v, v->expr); 1597 v->expr = (struct enode *)0; 1598 v->flags &= ~is_strexpr; 1599 } 1600 return; 1601 } 1602 efree (v, v->expr); 1603 v->expr = se; 1604 v->flags |= (is_changed|is_strexpr); 1605 if (flushdir<0) v->flags |= is_leftflush; 1606 else v->flags &= ~is_leftflush; 1607 1608 #ifdef EXPRTREE 1609 totoptree(); 1610 #endif 1611 FullUpdate++; 1612 changed++; 1613 modflg++; 1614 } 1615 1616 #ifdef EXPRTREE 1617 /* 1618 * put an expression in the expression tree, only the top of each branch is 1619 * in the firstev list 1620 */ 1621 totoptree(v) 1622 struct ent *v; 1623 { 1624 int right; 1625 int left; 1626 if (!v->expr) 1627 return; 1628 1629 #ifdef notdef 1630 right = FALSE; 1631 left = FALSE; 1632 switch(v->expr->op) 1633 { 1634 /* no real expression */ 1635 case 'v': 1636 if (v->expr->o.v->evnext) 1637 evdel(v->expr->o.v); 1638 case 'k': 1639 case LMAX: 1640 case LMIN: 1641 case NOW: 1642 case O_SCONST: 1643 case O_VAR: 1644 default: 1645 return; 1646 1647 /* left && right */ 1648 case '#': 1649 case '%': 1650 case '&': 1651 case '*': 1652 case '+': 1653 case '-': 1654 case '/': 1655 case '<': 1656 case '=': 1657 case '>': 1658 case '?': 1659 case '^': 1660 case '|': 1661 case ATAN2: 1662 case DTS: 1663 case EQS: 1664 case EXT: 1665 case FMT: 1666 case FV: 1667 case HYPOT: 1668 case IF: 1669 case NVAL: 1670 case PMT: 1671 case POW: 1672 case PV: 1673 case REDUCE | '*': 1674 case REDUCE | '+': 1675 case REDUCE | 'a': 1676 case REDUCE | 'c': 1677 case REDUCE | 's': 1678 case REDUCE | MAX: 1679 case REDUCE | MIN: 1680 case ROUND: 1681 case STINDEX: 1682 case SUBSTR: 1683 case SVAL: 1684 case TTS: 1685 left = right = TRUE; 1686 break; 1687 /* right only */ 1688 case 'f': 1689 case 'm': 1690 case '~': 1691 case ABS: 1692 case ACOS: 1693 case ASIN: 1694 case ATAN: 1695 case CEIL: 1696 case COS: 1697 case DATE: 1698 case DAY: 1699 case DTR: 1700 case EXP: 1701 case FABS: 1702 case FLOOR: 1703 case HLOOKUP: 1704 case HOUR: 1705 case IF: 1706 case INDEX: 1707 case LOG10: 1708 case LOG: 1709 case LOOKUP: 1710 case MINUTE: 1711 case MONTH: 1712 case RND: 1713 case RTD: 1714 case SECOND: 1715 case SIN: 1716 case SQRT: 1717 case STON: 1718 case TAN: 1719 case VLOOKUP: 1720 case YEAR: 1721 right = TRUE; 1722 break; 1723 } 1724 /* for now insert at the beginning of the list */ 1725 v->evnext = firstev; 1726 v->evprev = (struct ent *)0; 1727 if (firstev) 1728 firstev->evprev = v; 1729 firstev = v; 1730 #endif 1731 firstev = v; 1732 } 1733 #endif /* EXPRTREE*/ 1734 1735 void 1736 hide_row(arg) 1737 int arg; 1738 { 1739 if (arg < 0) { 1740 error("Invalid Range"); 1741 return; 1742 } 1743 if (arg >= maxrows-1) 1744 { 1745 if (!growtbl(GROWROW, arg+1, 0)) 1746 { error("You can't hide the last row"); 1747 return; 1748 } 1749 } 1750 FullUpdate++; 1751 row_hidden[arg] = 1; 1752 } 1753 1754 void 1755 hide_col(arg) 1756 int arg; 1757 { 1758 if (arg < 0) { 1759 error("Invalid Range"); 1760 return; 1761 } 1762 if (arg >= maxcols-1) 1763 { if ((arg >= ABSMAXCOLS-1) || !growtbl(GROWCOL, 0, arg+1)) 1764 { error("You can't hide the last col"); 1765 return; 1766 } 1767 } 1768 FullUpdate++; 1769 col_hidden[arg] = 1; 1770 } 1771 1772 void 1773 clearent (v) 1774 struct ent *v; 1775 { 1776 if (!v) 1777 return; 1778 label(v,"",-1); 1779 v->v = (double)0; 1780 if (v->expr) 1781 efree(v, v->expr); 1782 v->expr = (struct enode *)0; 1783 v->flags |= (is_changed); 1784 v->flags &= ~(is_valid); 1785 changed++; 1786 modflg++; 1787 } 1788 1789 /* 1790 * Say if an expression is a constant (return 1) or not. 1791 */ 1792 int 1793 constant (e) 1794 register struct enode *e; 1795 { 1796 return ((e == (struct enode *)0) 1797 || ((e -> op) == O_CONST) 1798 || ((e -> op) == O_SCONST) 1799 || (((e -> op) != O_VAR) 1800 && (((e -> op) & REDUCE) != REDUCE) 1801 && constant (e -> e.o.left) 1802 && constant (e -> e.o.right) 1803 && (e -> op != EXT) /* functions look like constants but aren't */ 1804 && (e -> op != NVAL) 1805 && (e -> op != SVAL) 1806 && (e -> op != NOW))); 1807 } 1808 1809 void 1810 efree (v, e) 1811 struct ent *v; 1812 struct enode *e; 1813 { 1814 if (e) { 1815 if (e->op != O_VAR && e->op !=O_CONST && e->op != O_SCONST 1816 && (e->op & REDUCE) != REDUCE) { 1817 efree(v, e->e.o.left); 1818 efree(v, e->e.o.right); 1819 } 1820 if (e->op == O_SCONST && e->e.s) 1821 xfree(e->e.s); 1822 xfree ((char *)e); 1823 1824 #ifdef EXPRTREE 1825 /* delete this cell from the eval list */ 1826 if (v) 1827 { if (v->evprev) 1828 v->evprev->evnext = v->evnext; 1829 if (v->evnext) 1830 v->evnext->evprev = v->evprev; 1831 } 1832 #endif /* EXPRTREE */ 1833 } 1834 } 1835 1836 void 1837 label (v, s, flushdir) 1838 register struct ent *v; 1839 register char *s; 1840 int flushdir; 1841 { 1842 if (v) { 1843 if (flushdir==0 && v->flags&is_valid) { 1844 register struct ent *tv; 1845 if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0) 1846 v = tv, flushdir = 1; 1847 else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0) 1848 v = tv, flushdir = -1; 1849 else flushdir = -1; 1850 } 1851 if (v->label) xfree((char *)(v->label)); 1852 if (s && s[0]) { 1853 v->label = xmalloc ((unsigned)(strlen(s)+1)); 1854 (void) strcpy (v->label, s); 1855 } else 1856 v->label = (char *)0; 1857 if (flushdir<0) v->flags |= is_leftflush; 1858 else v->flags &= ~is_leftflush; 1859 FullUpdate++; 1860 modflg++; 1861 } 1862 } 1863 1864 void 1865 decodev (v) 1866 struct ent_ptr v; 1867 { 1868 register struct range *r; 1869 1870 if (!v.vp) (void)sprintf (line+linelim,"VAR?"); 1871 else if ((r = find_range((char *)0, 0, v.vp, v.vp)) && !r->r_is_range) 1872 (void)sprintf(line+linelim, "%s", r->r_name); 1873 else 1874 (void)sprintf (line+linelim, "%s%s%s%d", 1875 v.vf & FIX_COL ? "$" : "", 1876 coltoa(v.vp->col), 1877 v.vf & FIX_ROW ? "$" : "", 1878 v.vp->row); 1879 linelim += strlen (line+linelim); 1880 } 1881 1882 char * 1883 coltoa(col) 1884 int col; 1885 { 1886 static char rname[3]; 1887 register char *p = rname; 1888 1889 if (col > 25) { 1890 *p++ = col/26 + 'A' - 1; 1891 col %= 26; 1892 } 1893 *p++ = col+'A'; 1894 *p = '\0'; 1895 return(rname); 1896 } 1897 1898 /* 1899 * To make list elements come out in the same order 1900 * they were entered, we must do a depth-first eval 1901 * of the ELIST tree 1902 */ 1903 static void 1904 decompile_list(p) 1905 struct enode *p; 1906 { 1907 if (!p) return; 1908 decompile_list(p->e.o.left); /* depth first */ 1909 decompile(p->e.o.right, 0); 1910 line[linelim++] = ','; 1911 } 1912 1913 void 1914 decompile(e, priority) 1915 register struct enode *e; 1916 int priority; 1917 { 1918 register char *s; 1919 if (e) { 1920 int mypriority; 1921 switch (e->op) { 1922 default: mypriority = 99; break; 1923 case '?': mypriority = 1; break; 1924 case ':': mypriority = 2; break; 1925 case '|': mypriority = 3; break; 1926 case '&': mypriority = 4; break; 1927 case '<': case '=': case '>': mypriority = 6; break; 1928 case '+': case '-': case '#': mypriority = 8; break; 1929 case '*': case '/': case '%': mypriority = 10; break; 1930 case '^': mypriority = 12; break; 1931 } 1932 if (mypriority<priority) line[linelim++] = '('; 1933 switch (e->op) { 1934 case 'f': for (s="fixed "; line[linelim++] = *s++;); 1935 linelim--; 1936 decompile (e->e.o.right, 30); 1937 break; 1938 case 'm': line[linelim++] = '-'; 1939 decompile (e->e.o.right, 30); 1940 break; 1941 case '~': line[linelim++] = '~'; 1942 decompile (e->e.o.right, 30); 1943 break; 1944 case 'v': decodev (e->e.v); 1945 break; 1946 case 'k': (void)sprintf (line+linelim,"%.15g",e->e.k); 1947 linelim += strlen (line+linelim); 1948 break; 1949 case '$': (void)sprintf (line+linelim, "\"%s\"", e->e.s); 1950 linelim += strlen(line+linelim); 1951 break; 1952 1953 case REDUCE | '+': range_arg( "@sum(", e); break; 1954 case REDUCE | '*': range_arg( "@prod(", e); break; 1955 case REDUCE | 'a': range_arg( "@avg(", e); break; 1956 case REDUCE | 'c': range_arg( "@count(", e); break; 1957 case REDUCE | 's': range_arg( "@stddev(", e); break; 1958 case REDUCE | MAX: range_arg( "@max(", e); break; 1959 case REDUCE | MIN: range_arg( "@min(", e); break; 1960 1961 case ABS: one_arg( "@abs(", e); break; 1962 case ACOS: one_arg( "@acos(", e); break; 1963 case ASIN: one_arg( "@asin(", e); break; 1964 case ATAN: one_arg( "@atan(", e); break; 1965 case ATAN2: two_arg( "@atan2(", e); break; 1966 case CEIL: one_arg( "@ceil(", e); break; 1967 case COS: one_arg( "@cos(", e); break; 1968 case EXP: one_arg( "@exp(", e); break; 1969 case FABS: one_arg( "@fabs(", e); break; 1970 case FLOOR: one_arg( "@floor(", e); break; 1971 case HYPOT: two_arg( "@hypot(", e); break; 1972 case LOG: one_arg( "@ln(", e); break; 1973 case LOG10: one_arg( "@log(", e); break; 1974 case POW: two_arg( "@pow(", e); break; 1975 case SIN: one_arg( "@sin(", e); break; 1976 case SQRT: one_arg( "@sqrt(", e); break; 1977 case TAN: one_arg( "@tan(", e); break; 1978 case DTR: one_arg( "@dtr(", e); break; 1979 case RTD: one_arg( "@rtd(", e); break; 1980 case RND: one_arg( "@rnd(", e); break; 1981 case ROUND: two_arg( "@round(", e); break; 1982 case HOUR: one_arg( "@hour(", e); break; 1983 case MINUTE: one_arg( "@minute(", e); break; 1984 case SECOND: one_arg( "@second(", e); break; 1985 case MONTH: one_arg( "@month(", e); break; 1986 case DAY: one_arg( "@day(", e); break; 1987 case YEAR: one_arg( "@year(", e); break; 1988 case DATE: one_arg( "@date(", e); break; 1989 case DTS: three_arg( "@dts(", e); break; 1990 case TTS: three_arg( "@tts(", e); break; 1991 case STON: one_arg( "@ston(", e); break; 1992 case FMT: two_arg( "@fmt(", e); break; 1993 case EQS: two_arg( "@eqs(", e); break; 1994 case NOW: for ( s = "@now"; line[linelim++] = *s++;); 1995 linelim--; 1996 break; 1997 case LMAX: list_arg("@max(", e); break; 1998 case LMIN: list_arg("@min(", e); break; 1999 case FV: three_arg("@fv(", e); break; 2000 case PV: three_arg("@pv(", e); break; 2001 case PMT: three_arg("@pmt(", e); break; 2002 case NVAL: two_arg("@nval(", e); break; 2003 case SVAL: two_arg("@sval(", e); break; 2004 case EXT: two_arg("@ext(", e); break; 2005 case SUBSTR: three_arg("@substr(", e); break; 2006 case STINDEX: index_arg("@stindex(", e); break; 2007 case INDEX: index_arg("@index(", e); break; 2008 case LOOKUP: index_arg("@lookup(", e); break; 2009 case HLOOKUP: two_arg_index("@hlookup(", e); break; 2010 case VLOOKUP: two_arg_index("@vlookup(", e); break; 2011 case IF: three_arg("@if(", e); break; 2012 default: decompile (e->e.o.left, mypriority); 2013 line[linelim++] = e->op; 2014 decompile (e->e.o.right, mypriority+1); 2015 break; 2016 } 2017 if (mypriority<priority) line[linelim++] = ')'; 2018 } else line[linelim++] = '?'; 2019 } 2020 2021 void 2022 index_arg(s, e) 2023 char *s; 2024 struct enode *e; 2025 { 2026 for (; line[linelim++] = *s++;); 2027 linelim--; 2028 decompile( e-> e.o.left, 0 ); 2029 range_arg(", ", e->e.o.right); 2030 } 2031 2032 void 2033 two_arg_index(s, e) 2034 char *s; 2035 struct enode *e; 2036 { 2037 for (; line[linelim++] = *s++;); 2038 linelim--; 2039 decompile( e->e.o.left->e.o.left, 0 ); 2040 range_arg(",", e->e.o.right); 2041 linelim--; 2042 line[linelim++] = ','; 2043 decompile( e->e.o.left->e.o.right, 0 ); 2044 line[linelim++] = ')'; 2045 } 2046 2047 void 2048 list_arg(s, e) 2049 char *s; 2050 struct enode *e; 2051 { 2052 for (; line[linelim++] = *s++;); 2053 linelim--; 2054 2055 decompile (e->e.o.right, 0); 2056 line[linelim++] = ','; 2057 decompile_list(e->e.o.left); 2058 line[linelim - 1] = ')'; 2059 } 2060 2061 void 2062 one_arg(s, e) 2063 char *s; 2064 struct enode *e; 2065 { 2066 for (; line[linelim++] = *s++;); 2067 linelim--; 2068 decompile (e->e.o.right, 0); 2069 line[linelim++] = ')'; 2070 } 2071 2072 void 2073 two_arg(s,e) 2074 char *s; 2075 struct enode *e; 2076 { 2077 for (; line[linelim++] = *s++;); 2078 linelim--; 2079 decompile (e->e.o.left, 0); 2080 line[linelim++] = ','; 2081 decompile (e->e.o.right, 0); 2082 line[linelim++] = ')'; 2083 } 2084 2085 void 2086 three_arg(s,e) 2087 char *s; 2088 struct enode *e; 2089 { 2090 for (; line[linelim++] = *s++;); 2091 linelim--; 2092 decompile (e->e.o.left, 0); 2093 line[linelim++] = ','; 2094 decompile (e->e.o.right->e.o.left, 0); 2095 line[linelim++] = ','; 2096 decompile (e->e.o.right->e.o.right, 0); 2097 line[linelim++] = ')'; 2098 } 2099 2100 void 2101 range_arg(s,e) 2102 char *s; 2103 struct enode *e; 2104 { 2105 struct range *r; 2106 2107 for (; line[linelim++] = *s++;); 2108 linelim--; 2109 if ((r = find_range((char *)0, 0, e->e.r.left.vp, 2110 e->e.r.right.vp)) && r->r_is_range) { 2111 (void)sprintf(line+linelim, "%s", r->r_name); 2112 linelim += strlen(line+linelim); 2113 } else { 2114 decodev (e->e.r.left); 2115 line[linelim++] = ':'; 2116 decodev (e->e.r.right); 2117 } 2118 line[linelim++] = ')'; 2119 } 2120 2121 void 2122 editv (row, col) 2123 int row, col; 2124 { 2125 register struct ent *p; 2126 2127 p = lookat (row, col); 2128 (void)sprintf (line, "let %s = ", v_name(row, col)); 2129 linelim = strlen(line); 2130 if (p->flags & is_strexpr || p->expr == 0) { 2131 (void)sprintf (line+linelim, "%.15g", p->v); 2132 linelim += strlen (line+linelim); 2133 } else { 2134 editexp(row,col); 2135 } 2136 } 2137 2138 void 2139 editexp(row,col) 2140 int row, col; 2141 { 2142 register struct ent *p; 2143 2144 p = lookat (row, col); 2145 decompile (p->expr, 0); 2146 line[linelim] = '\0'; 2147 } 2148 2149 void 2150 edits (row, col) 2151 int row, col; 2152 { 2153 register struct ent *p; 2154 2155 p = lookat (row, col); 2156 (void)sprintf (line, "%sstring %s = ", 2157 ((p->flags&is_leftflush) ? "left" : "right"), 2158 v_name(row, col)); 2159 linelim = strlen(line); 2160 if (p->flags & is_strexpr && p->expr) { 2161 editexp(row, col); 2162 } else if (p->label) { 2163 (void)sprintf (line+linelim, "\"%s\"", p->label); 2164 linelim += strlen (line+linelim); 2165 } else { 2166 (void)sprintf (line+linelim, "\""); 2167 linelim += 1; 2168 } 2169 } 2170