numparm, cleanup rewrite formula()

This commit is contained in:
rlar 2013-10-08 18:38:43 +02:00
parent e5e08b6f93
commit 2f508696a6
1 changed files with 87 additions and 86 deletions

View File

@ -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);