📄 interp.c
字号:
right = FALSE; left = FALSE; switch(v->expr->op) { /* no real expression */ case 'v': if (v->expr->o.v->evnext) evdel(v->expr->o.v); case 'k': case LMAX: case LMIN: case NOW: case O_SCONST: case O_VAR: default: return; /* left && right */ case '#': case '%': case '&': case '*': case '+': case '-': case '/': case '<': case '=': case '>': case '?': case '^': case '|': case ATAN2: case DTS: case EQS: case EXT: case FMT: case FV: case HYPOT: case IF: case NVAL: case PMT: case POW: case PV: case REDUCE | '*': case REDUCE | '+': case REDUCE | 'a': case REDUCE | 'c': case REDUCE | 's': case REDUCE | MAX: case REDUCE | MIN: case ROUND: case STINDEX: case SUBSTR: case SVAL: case TTS: left = right = TRUE; break; /* right only */ case 'f': case 'm': case '~': case ABS: case ACOS: case ASIN: case ATAN: case CEIL: case COS: case DATE: case DAY: case DTR: case EXP: case FABS: case FLOOR: case HLOOKUP: case HOUR: case IF: case INDEX: case LOG10: case LOG: case LOOKUP: case MINUTE: case MONTH: case RND: case RTD: case SECOND: case SIN: case SQRT: case STON: case TAN: case VLOOKUP: case YEAR: right = TRUE; break; } /* for now insert at the beginning of the list */ v->evnext = firstev; v->evprev = (struct ent *)0; if (firstev) firstev->evprev = v; firstev = v;#endif firstev = v;}#endif /* EXPRTREE*/voidhide_row(arg)int arg;{ if (arg < 0) { error("Invalid Range"); return; } if (arg >= maxrows-1) { if (!growtbl(GROWROW, arg+1, 0)) { error("You can't hide the last row"); return; } } FullUpdate++; row_hidden[arg] = 1;}voidhide_col(arg)int arg;{ if (arg < 0) { error("Invalid Range"); return; } if (arg >= maxcols-1) { if ((arg >= ABSMAXCOLS-1) || !growtbl(GROWCOL, 0, arg+1)) { error("You can't hide the last col"); return; } } FullUpdate++; col_hidden[arg] = 1;}voidclearent (v)struct ent *v;{ if (!v) return; label(v,"",-1); v->v = (double)0; if (v->expr) efree(v, v->expr); v->expr = (struct enode *)0; v->flags |= (is_changed); v->flags &= ~(is_valid); changed++; modflg++;}/* * Say if an expression is a constant (return 1) or not. */intconstant (e) register struct enode *e;{ return ((e == (struct enode *)0) || ((e -> op) == O_CONST) || ((e -> op) == O_SCONST) || (((e -> op) != O_VAR) && (((e -> op) & REDUCE) != REDUCE) && constant (e -> e.o.left) && constant (e -> e.o.right) && (e -> op != EXT) /* functions look like constants but aren't */ && (e -> op != NVAL) && (e -> op != SVAL) && (e -> op != NOW)));}voidefree (v, e)struct ent *v;struct enode *e;{ if (e) { if (e->op != O_VAR && e->op !=O_CONST && e->op != O_SCONST && (e->op & REDUCE) != REDUCE) { efree(v, e->e.o.left); efree(v, e->e.o.right); } if (e->op == O_SCONST && e->e.s) xfree(e->e.s); xfree ((char *)e);#ifdef EXPRTREE /* delete this cell from the eval list */ if (v) { if (v->evprev) v->evprev->evnext = v->evnext; if (v->evnext) v->evnext->evprev = v->evprev; }#endif /* EXPRTREE */ }}voidlabel (v, s, flushdir)register struct ent *v;register char *s;int flushdir;{ if (v) { if (flushdir==0 && v->flags&is_valid) { register struct ent *tv; if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0) v = tv, flushdir = 1; else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0) v = tv, flushdir = -1; else flushdir = -1; } if (v->label) xfree((char *)(v->label)); if (s && s[0]) { v->label = xmalloc ((unsigned)(strlen(s)+1)); (void) strcpy (v->label, s); } else v->label = (char *)0; if (flushdir<0) v->flags |= is_leftflush; else v->flags &= ~is_leftflush; FullUpdate++; modflg++; }}voiddecodev (v)struct ent_ptr v; { register struct range *r; if (!v.vp) (void)sprintf (line+linelim,"VAR?"); else if ((r = find_range((char *)0, 0, v.vp, v.vp)) && !r->r_is_range) (void)sprintf(line+linelim, "%s", r->r_name); else (void)sprintf (line+linelim, "%s%s%s%d", v.vf & FIX_COL ? "$" : "", coltoa(v.vp->col), v.vf & FIX_ROW ? "$" : "", v.vp->row); linelim += strlen (line+linelim);}char *coltoa(col)int col;{ static char rname[3]; register char *p = rname; if (col > 25) { *p++ = col/26 + 'A' - 1; col %= 26; } *p++ = col+'A'; *p = '\0'; return(rname);}/* * To make list elements come out in the same order * they were entered, we must do a depth-first eval * of the ELIST tree */static voiddecompile_list(p)struct enode *p;{ if (!p) return; decompile_list(p->e.o.left); /* depth first */ decompile(p->e.o.right, 0); line[linelim++] = ',';}voiddecompile(e, priority)register struct enode *e;int priority;{ register char *s; if (e) { int mypriority; switch (e->op) { default: mypriority = 99; break; case '?': mypriority = 1; break; case ':': mypriority = 2; break; case '|': mypriority = 3; break; case '&': mypriority = 4; break; case '<': case '=': case '>': mypriority = 6; break; case '+': case '-': case '#': mypriority = 8; break; case '*': case '/': case '%': mypriority = 10; break; case '^': mypriority = 12; break; } if (mypriority<priority) line[linelim++] = '('; switch (e->op) { case 'f': for (s="fixed "; line[linelim++] = *s++;); linelim--; decompile (e->e.o.right, 30); break; case 'm': line[linelim++] = '-'; decompile (e->e.o.right, 30); break; case '~': line[linelim++] = '~'; decompile (e->e.o.right, 30); break; case 'v': decodev (e->e.v); break; case 'k': (void)sprintf (line+linelim,"%.15g",e->e.k); linelim += strlen (line+linelim); break; case '$': (void)sprintf (line+linelim, "\"%s\"", e->e.s); linelim += strlen(line+linelim); break; case REDUCE | '+': range_arg( "@sum(", e); break; case REDUCE | '*': range_arg( "@prod(", e); break; case REDUCE | 'a': range_arg( "@avg(", e); break; case REDUCE | 'c': range_arg( "@count(", e); break; case REDUCE | 's': range_arg( "@stddev(", e); break; case REDUCE | MAX: range_arg( "@max(", e); break; case REDUCE | MIN: range_arg( "@min(", e); break; case ABS: one_arg( "@abs(", e); break; case ACOS: one_arg( "@acos(", e); break; case ASIN: one_arg( "@asin(", e); break; case ATAN: one_arg( "@atan(", e); break; case ATAN2: two_arg( "@atan2(", e); break; case CEIL: one_arg( "@ceil(", e); break; case COS: one_arg( "@cos(", e); break; case EXP: one_arg( "@exp(", e); break; case FABS: one_arg( "@fabs(", e); break; case FLOOR: one_arg( "@floor(", e); break; case HYPOT: two_arg( "@hypot(", e); break; case LOG: one_arg( "@ln(", e); break; case LOG10: one_arg( "@log(", e); break; case POW: two_arg( "@pow(", e); break; case SIN: one_arg( "@sin(", e); break; case SQRT: one_arg( "@sqrt(", e); break; case TAN: one_arg( "@tan(", e); break; case DTR: one_arg( "@dtr(", e); break; case RTD: one_arg( "@rtd(", e); break; case RND: one_arg( "@rnd(", e); break; case ROUND: two_arg( "@round(", e); break; case HOUR: one_arg( "@hour(", e); break; case MINUTE: one_arg( "@minute(", e); break; case SECOND: one_arg( "@second(", e); break; case MONTH: one_arg( "@month(", e); break; case DAY: one_arg( "@day(", e); break; case YEAR: one_arg( "@year(", e); break; case DATE: one_arg( "@date(", e); break; case DTS: three_arg( "@dts(", e); break; case TTS: three_arg( "@tts(", e); break; case STON: one_arg( "@ston(", e); break; case FMT: two_arg( "@fmt(", e); break; case EQS: two_arg( "@eqs(", e); break; case NOW: for ( s = "@now"; line[linelim++] = *s++;); linelim--; break; case LMAX: list_arg("@max(", e); break; case LMIN: list_arg("@min(", e); break; case FV: three_arg("@fv(", e); break; case PV: three_arg("@pv(", e); break; case PMT: three_arg("@pmt(", e); break; case NVAL: two_arg("@nval(", e); break; case SVAL: two_arg("@sval(", e); break; case EXT: two_arg("@ext(", e); break; case SUBSTR: three_arg("@substr(", e); break; case STINDEX: index_arg("@stindex(", e); break; case INDEX: index_arg("@index(", e); break; case LOOKUP: index_arg("@lookup(", e); break; case HLOOKUP: two_arg_index("@hlookup(", e); break; case VLOOKUP: two_arg_index("@vlookup(", e); break; case IF: three_arg("@if(", e); break; default: decompile (e->e.o.left, mypriority); line[linelim++] = e->op; decompile (e->e.o.right, mypriority+1); break; } if (mypriority<priority) line[linelim++] = ')'; } else line[linelim++] = '?';}voidindex_arg(s, e)char *s;struct enode *e;{ for (; line[linelim++] = *s++;); linelim--; decompile( e-> e.o.left, 0 ); range_arg(", ", e->e.o.right);}voidtwo_arg_index(s, e)char *s;struct enode *e;{ for (; line[linelim++] = *s++;); linelim--; decompile( e->e.o.left->e.o.left, 0 ); range_arg(",", e->e.o.right); linelim--; line[linelim++] = ','; decompile( e->e.o.left->e.o.right, 0 ); line[linelim++] = ')';}voidlist_arg(s, e)char *s;struct enode *e;{ for (; line[linelim++] = *s++;); linelim--; decompile (e->e.o.right, 0); line[linelim++] = ','; decompile_list(e->e.o.left); line[linelim - 1] = ')';}voidone_arg(s, e)char *s;struct enode *e;{ for (; line[linelim++] = *s++;); linelim--; decompile (e->e.o.right, 0); line[linelim++] = ')';}voidtwo_arg(s,e)char *s;struct enode *e;{ for (; line[linelim++] = *s++;); linelim--; decompile (e->e.o.left, 0); line[linelim++] = ','; decompile (e->e.o.right, 0); line[linelim++] = ')';}voidthree_arg(s,e)char *s;struct enode *e;{ for (; line[linelim++] = *s++;); linelim--; decompile (e->e.o.left, 0); line[linelim++] = ','; decompile (e->e.o.right->e.o.left, 0); line[linelim++] = ','; decompile (e->e.o.right->e.o.right, 0); line[linelim++] = ')';}voidrange_arg(s,e)char *s;struct enode *e;{ struct range *r; for (; line[linelim++] = *s++;); linelim--; if ((r = find_range((char *)0, 0, e->e.r.left.vp, e->e.r.right.vp)) && r->r_is_range) { (void)sprintf(line+linelim, "%s", r->r_name); linelim += strlen(line+linelim); } else { decodev (e->e.r.left); line[linelim++] = ':'; decodev (e->e.r.right); } line[linelim++] = ')';}voideditv (row, col)int row, col;{ register struct ent *p; p = lookat (row, col); (void)sprintf (line, "let %s = ", v_name(row, col)); linelim = strlen(line); if (p->flags & is_strexpr || p->expr == 0) { (void)sprintf (line+linelim, "%.15g", p->v); linelim += strlen (line+linelim); } else { editexp(row,col); }}voideditexp(row,col)int row, col;{ register struct ent *p; p = lookat (row, col); decompile (p->expr, 0); line[linelim] = '\0';}voidedits (row, col)int row, col;{ register struct ent *p; p = lookat (row, col); (void)sprintf (line, "%sstring %s = ", ((p->flags&is_leftflush) ? "left" : "right"), v_name(row, col)); linelim = strlen(line); if (p->flags & is_strexpr && p->expr) { editexp(row, col); } else if (p->label) { (void)sprintf (line+linelim, "\"%s\"", p->label); linelim += strlen (line+linelim); } else { (void)sprintf (line+linelim, "\""); linelim += 1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -