From 2f508696a632044a929deef2cb06ff8ce9ee39db Mon Sep 17 00:00:00 2001 From: rlar Date: Tue, 8 Oct 2013 18:38:43 +0200 Subject: [PATCH] numparm, cleanup rewrite formula() --- src/frontend/numparam/xpressn.c | 173 ++++++++++++++++---------------- 1 file changed, 87 insertions(+), 86 deletions(-) diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index fb2283656..6aed9d4e0 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -765,19 +765,19 @@ parseunit(const char *s) } -static int -fetchid(const char *s, SPICE_DSTRINGPTR t, int ls, int i) +static const char * +fetchid(SPICE_DSTRINGPTR t, const char *s_end, const char *iptr) /* copy next identifier from s into t, advance and return scan index i */ { char c; bool ok; - c = s[i]; - i++; + c = *iptr; + iptr++; - while (!alfa(c) && (i < ls)) { - i++; - c = s[i - 1]; + while (!alfa(c) && (iptr < s_end)) { + iptr++; + c = iptr[-1]; } spice_dstring_reinit(t); @@ -785,9 +785,9 @@ fetchid(const char *s, SPICE_DSTRINGPTR t, int ls, int i) do { - i++; - if (i <= ls) - c = s[i - 1]; + iptr++; + if (iptr <= s_end) + c = iptr[-1]; else c = '\0'; @@ -799,33 +799,31 @@ fetchid(const char *s, SPICE_DSTRINGPTR t, int ls, int i) } while (ok); - return i; /* return updated i */ + return iptr; /* return updated iptr */ } static double -exists(tdico *d, const char *s, int *pi, bool *perror) +exists(tdico *d, const char *s_end, const char **pi, bool *perror) /* check if s in simboltable 'defined': expect (ident) and return 0 or 1 */ { bool error = *perror; - int i = *pi; + const char *iptr = *pi; double x; - int ls; char c; bool ok; SPICE_DSTRING t; - ls = length(s); spice_dstring_init(&t); x = 0.0; do { - i++; - if (i > ls) + iptr++; + if (iptr > s_end) c = '\0'; else - c = s[i - 1]; + c = iptr[-1]; ok = (c == '('); @@ -833,20 +831,20 @@ exists(tdico *d, const char *s, int *pi, bool *perror) if (ok) { - i--; - i = fetchid(s, &t, ls, i); - i--; + iptr--; + iptr = fetchid(&t, s_end, iptr); + iptr--; if (entrynb(d, spice_dstring_value(&t))) x = 1.0; do { - i++; + iptr++; - if (i > ls) + if (iptr > s_end) c = '\0'; else - c = s[i - 1]; + c = iptr[-1]; ok = (c == ')'); @@ -859,7 +857,7 @@ exists(tdico *d, const char *s, int *pi, bool *perror) /* keep pointer on last closing ")" */ *perror = error; - *pi = i; + *pi = iptr; spice_dstring_free(&t); return x; @@ -867,13 +865,13 @@ exists(tdico *d, const char *s, int *pi, bool *perror) static double -fetchnumber(tdico *dico, const char *s, int *pi, bool *perror) +fetchnumber(tdico *dico, const char **pi, bool *perror) /* parse a Spice number in string s */ { double u; int n = 0; - s += *pi; + const char *s = *pi; if (1 != sscanf(s, "%lG%n", &u, &n)) { @@ -901,49 +899,49 @@ fetchnumber(tdico *dico, const char *s, int *pi, bool *perror) static char fetchoperator(tdico *dico, - const char *s, int ls, - int *pi, + const char *s_end, + const char **pi, unsigned char *pstate, unsigned char *plevel, bool *perror) /* grab an operator from string s and advance scan index pi. each operator has: one-char alias, precedence level, new interpreter state. */ { - int i = *pi; + const char *iptr = *pi; unsigned char state = *pstate; unsigned char level = *plevel; bool error = *perror; char c, d; - c = s[i]; - i++; + c = *iptr; + iptr++; - if (i < ls) - d = s[i]; + if (iptr < s_end) + d = iptr[0]; else d = '\0'; if ((c == '!') && (d == '=')) { c = '#'; - i++; + iptr++; } else if ((c == '<') && (d == '>')) { c = '#'; - i++; + iptr++; } else if ((c == '<') && (d == '=')) { c = 'L'; - i++; + iptr++; } else if ((c == '>') && (d == '=')) { c = 'G'; - i++; + iptr++; } else if ((c == '*') && (d == '*')) { c = '^'; - i++; + iptr++; } else if ((c == '=') && (d == '=')) { - i++; + iptr++; } else if ((c == '&') && (d == '&')) { - i++; + iptr++; } else if ((c == '|') && (d == '|')) { - i++; + iptr++; } if ((c == '+') || (c == '-')) { state = S_binop; /* pending operator */ level = 4; @@ -970,7 +968,7 @@ fetchoperator(tdico *dico, error = message(dico, "Syntax error: letter [%c]", c); } - *pi = i; + *pi = iptr; *pstate = state; *plevel = level; *perror = error; @@ -1137,7 +1135,7 @@ operate(char op, double x, double y) static double -formula(tdico *dico, const char *s, bool *perror) +formula(tdico *dico, const char *s, const char *s_end, bool *perror) { /* Expression parser. s is a formula with parentheses and math ops +-* / ... @@ -1156,10 +1154,14 @@ formula(tdico *dico, const char *s, bool *perror) double accu[nprece + 1]; char oper[nprece + 1]; char uop[nprece + 1]; - int i, k, ls, natom, arg2, arg3; + int i, k, natom; char c, d; bool ok; SPICE_DSTRING tstr; + const char *iptr; + const char *kptr; + const char *arg2; + const char *arg3; spice_dstring_init(&tstr); @@ -1168,11 +1170,11 @@ formula(tdico *dico, const char *s, bool *perror) oper[i] = ' '; } - i = 0; - ls = length(s); + iptr = s; - while ((ls > 0) && (s[ls - 1] <= ' ')) - ls--; /* clean s */ + /* trim trailing whitespace */ + while ((s_end > s) && (s_end[-1] <= ' ')) + s_end--; state = S_init; natom = 0; @@ -1183,25 +1185,25 @@ formula(tdico *dico, const char *s, bool *perror) error = 0; level = 0; - while ((i < ls) && !error) { - i++; - c = s[i - 1]; + while ((iptr < s_end) && !error) { + iptr++; + c = iptr[-1]; if (c == '(') { /* sub-formula or math function */ level = 1; /* new: must support multi-arg functions */ - k = i; - arg2 = 0; + kptr = iptr; + arg2 = NULL; v = 1.0; - arg3 = 0; + arg3 = NULL; do { - k++; - if (k > ls) + kptr++; + if (kptr > s_end) d = '\0'; else - d = s[k - 1]; + d = kptr[-1]; if (d == '(') level++; @@ -1209,30 +1211,27 @@ formula(tdico *dico, const char *s, bool *perror) level--; if ((d == ',') && (level == 1)) { - if (arg2 == 0) - arg2 = k; + if (arg2 == NULL) + arg2 = kptr; else - arg3 = k; /* kludge for more than 2 args (ternary expression) */ + arg3 = kptr; /* kludge for more than 2 args (ternary expression) */ } /* comma list? */ - } while ((k <= ls) && !((d == ')') && (level <= 0))); + } while ((kptr <= s_end) && !((d == ')') && (level <= 0))); - if (k > ls) { + if (kptr > s_end) { error = message(dico, "Closing \")\" not found."); natom++; /* shut up other error message */ } else { - if (arg2 > i) { - pscopy(&tstr, s, i, arg2 - i - 1); - v = formula(dico, spice_dstring_value(&tstr), &error); - i = arg2; + if (arg2 > iptr) { + v = formula(dico, iptr, arg2 - 1, &error); + iptr = arg2; } - if (arg3 > i) { - pscopy(&tstr, s, i, arg3 - i - 1); - w = formula(dico, spice_dstring_value(&tstr), &error); - i = arg3; + if (arg3 > iptr) { + w = formula(dico, iptr, arg3 - 1, &error); + iptr = arg3; } - pscopy(&tstr, s, i, k - i - 1); - u = formula(dico, spice_dstring_value(&tstr), &error); + u = formula(dico, iptr, kptr - 1, &error); state = S_atom; if (fu > 0) { if ((fu == 18)) @@ -1251,13 +1250,13 @@ formula(tdico *dico, const char *s, bool *perror) u = mathfunction(fu, v, u); } } - i = k; + iptr = kptr; fu = 0; } else if (alfa(c)) { - i--; - i = fetchid(s, &tstr, ls, i); /* user id, but sort out keywords */ + iptr--; + iptr = fetchid(&tstr, s_end, iptr); /* user id, but sort out keywords */ state = S_atom; - i--; + iptr--; kw = keyword(&keyS, &tstr); /* debug ws('[',kw,']'); */ if (kw == 0) { fu = keyword(&fmathS, &tstr); /* numeric function? */ @@ -1269,19 +1268,20 @@ formula(tdico *dico, const char *s, bool *perror) c = opfunctkey(dico, kw, c, &state, &level, &error); } - if (kw == Defd) - u = exists(dico, s, &i, &error); + if (kw == Defd) { + u = exists(dico, s_end, &iptr, &error); + } } else if (((c == '.') || ((c >= '0') && (c <= '9')))) { - i--; - u = fetchnumber(dico, s, &i, &error); + iptr--; + u = fetchnumber(dico, &iptr, &error); if (negate) { u = -1 * u; negate = 0; } state = S_atom; } else { - i--; - c = fetchoperator(dico, s, ls, &i, &state, &level, &error); + iptr--; + c = fetchoperator(dico, s_end, &iptr, &state, &level, &error); } /* may change c to some other operator char! */ @@ -1307,7 +1307,7 @@ formula(tdico *dico, const char *s, bool *perror) } else if (state == S_atom) { /* atom pending */ natom++; - if (i >= ls) { + if (iptr >= s_end) { state = S_stop; level = topop; } /* close all ops below */ @@ -1416,7 +1416,7 @@ evaluate(tdico *dico, SPICE_DSTRINGPTR qstr_p, char *t, unsigned char mode) "\"%s\" not evaluated.%s", t, nolookup ? " Lookup failure." : ""); } else { - u = formula(dico, t, &err); + u = formula(dico, t, t + strlen(t), &err); numeric = 1; } @@ -1956,7 +1956,8 @@ nupa_assignment(tdico *dico, char *s, char mode) dtype = getexpress(s, &ustr, &i); if (dtype == 'R') { - rval = formula(dico, spice_dstring_value(&ustr), &error); + const char *tmp = spice_dstring_value(&ustr); + rval = formula(dico, tmp, tmp + strlen(tmp), &error); if (error) { message(dico, " Formula() error."); fprintf(stderr, " %s\n", s);