bug in B source parsing removed
This commit is contained in:
parent
d4fc5581d2
commit
d89d52039f
|
|
@ -1,3 +1,7 @@
|
|||
2010-09-03 Holger Vogt
|
||||
* inpcom.c, inp.h, inpeval.c, inpgtok.c:
|
||||
bug removed in B source parsing, as reported by sdaau
|
||||
|
||||
2010-09-02 Holger Vogt
|
||||
* randnumb.c: inproved comments
|
||||
|
||||
|
|
|
|||
|
|
@ -4438,7 +4438,7 @@ static void inp_bsource_compat(struct line *deck)
|
|||
else if (isdigit(actchar))
|
||||
{
|
||||
/* allow 100p, 5MEG etc. */
|
||||
dvalue = INPevaluate(&str_ptr, &error1, 1);
|
||||
dvalue = INPevaluate(&str_ptr, &error1, 2);
|
||||
cvalue = (char*) tmalloc(19);
|
||||
sprintf(cvalue,"%18.10e", dvalue);
|
||||
/* unary -, change sign */
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ int INPgetStr(char **line, char **token, int gobble);
|
|||
int INPgetTitle(CKTcircuit **ckt, card **data);
|
||||
int INPgetTok(char **line, char **token, int gobble);
|
||||
int INPgetUTok(char **line, char **token, int gobble);
|
||||
int INPgetU2Tok(char **line, char **token, int gobble);
|
||||
IFvalue * INPgetValue(CKTcircuit *ckt, char **line, int type, INPtables *tab);
|
||||
void INPkillMods(void);
|
||||
void INPlist(FILE *file, card *deck, int type);
|
||||
|
|
|
|||
|
|
@ -23,15 +23,19 @@ double INPevaluate(char **line, int *error, int gobble)
|
|||
|
||||
/* setup */
|
||||
tmpline = *line;
|
||||
if (gobble) {
|
||||
/* MW. INPgetUTok should be called with gobble=0 or it make
|
||||
* errors in v(1,2) exp */
|
||||
*error = INPgetUTok(line, &token, 0);
|
||||
if (*error)
|
||||
return ((double) 0.0);
|
||||
if (gobble == 1) {
|
||||
/* MW. INPgetUTok should be called with gobble=0 or it make
|
||||
* errors in v(1,2) exp */
|
||||
*error = INPgetUTok(line, &token, 0);
|
||||
if (*error)
|
||||
return ((double) 0.0);
|
||||
} else if (gobble == 2) {
|
||||
*error = INPgetU2Tok(line, &token, 0);
|
||||
if (*error)
|
||||
return ((double) 0.0);
|
||||
} else {
|
||||
token = *line;
|
||||
*error = 0;
|
||||
token = *line;
|
||||
*error = 0;
|
||||
}
|
||||
mantis = 0;
|
||||
expo1 = 0;
|
||||
|
|
@ -41,167 +45,167 @@ double INPevaluate(char **line, int *error, int gobble)
|
|||
/* loop through all of the input token */
|
||||
here = token;
|
||||
if (*here == '+')
|
||||
here++; /* plus, so do nothing except skip it */
|
||||
here++; /* plus, so do nothing except skip it */
|
||||
if (*here == '-') { /* minus, so skip it, and change sign */
|
||||
here++;
|
||||
sign = -1;
|
||||
here++;
|
||||
sign = -1;
|
||||
}
|
||||
if ((*here == 0) || ((!(isdigit(*here))) && (*here != '.'))) {
|
||||
/* number looks like just a sign! */
|
||||
*error = 1;
|
||||
*error = 1;
|
||||
/* back out the 'gettok' operation */
|
||||
*line = tmpline;
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (0);
|
||||
*line = tmpline;
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
while (isdigit(*here)) {
|
||||
/* digit, so accumulate it. */
|
||||
mantis = 10 * mantis + *here - '0';
|
||||
here++;
|
||||
/* digit, so accumulate it. */
|
||||
mantis = 10 * mantis + *here - '0';
|
||||
here++;
|
||||
}
|
||||
if (*here == 0) {
|
||||
/* reached the end of token - done. */
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return ((double) mantis * sign);
|
||||
/* reached the end of token - done. */
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return ((double) mantis * sign);
|
||||
}
|
||||
if (*here == ':') {
|
||||
/* hack for subcircuit node numbering */
|
||||
*error = 1;
|
||||
*line = tmpline;
|
||||
return 0.0;
|
||||
/* hack for subcircuit node numbering */
|
||||
*error = 1;
|
||||
*line = tmpline;
|
||||
return 0.0;
|
||||
}
|
||||
/* after decimal point! */
|
||||
if (*here == '.') {
|
||||
/* found a decimal point! */
|
||||
here++; /* skip to next character */
|
||||
if (*here == 0) {
|
||||
/* number ends in the decimal point */
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return ((double) mantis * sign);
|
||||
}
|
||||
while (isdigit(*here)) {
|
||||
/* digit, so accumulate it. */
|
||||
mantis = 10 * mantis + *here - '0';
|
||||
expo1 = expo1 - 1;
|
||||
if (*here == 0) {
|
||||
/* reached the end of token - done. */
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (mantis * sign * pow(10., (double) expo1));
|
||||
}
|
||||
here++;
|
||||
}
|
||||
/* found a decimal point! */
|
||||
here++; /* skip to next character */
|
||||
if (*here == 0) {
|
||||
/* number ends in the decimal point */
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return ((double) mantis * sign);
|
||||
}
|
||||
while (isdigit(*here)) {
|
||||
/* digit, so accumulate it. */
|
||||
mantis = 10 * mantis + *here - '0';
|
||||
expo1 = expo1 - 1;
|
||||
if (*here == 0) {
|
||||
/* reached the end of token - done. */
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (mantis * sign * pow(10., (double) expo1));
|
||||
}
|
||||
here++;
|
||||
}
|
||||
}
|
||||
/* now look for "E","e",etc to indicate an exponent */
|
||||
if ((*here == 'E') || (*here == 'e') || (*here == 'D')
|
||||
|| (*here == 'd')) {
|
||||
/* have an exponent, so skip the e */
|
||||
here++;
|
||||
/* now look for exponent sign */
|
||||
if (*here == '+')
|
||||
here++; /* just skip + */
|
||||
if (*here == '-') {
|
||||
here++; /* skip over minus sign */
|
||||
expsgn = -1; /* and make a negative exponent */
|
||||
/* now look for the digits of the exponent */
|
||||
}
|
||||
while (isdigit(*here)) {
|
||||
expo2 = 10 * expo2 + *here - '0';
|
||||
here++;
|
||||
}
|
||||
|| (*here == 'd')) {
|
||||
/* have an exponent, so skip the e */
|
||||
here++;
|
||||
/* now look for exponent sign */
|
||||
if (*here == '+')
|
||||
here++; /* just skip + */
|
||||
if (*here == '-') {
|
||||
here++; /* skip over minus sign */
|
||||
expsgn = -1; /* and make a negative exponent */
|
||||
/* now look for the digits of the exponent */
|
||||
}
|
||||
while (isdigit(*here)) {
|
||||
expo2 = 10 * expo2 + *here - '0';
|
||||
here++;
|
||||
}
|
||||
}
|
||||
/* now we have all of the numeric part of the number, time to
|
||||
* look for the scale factor (alphabetic)
|
||||
*/
|
||||
switch (*here) {
|
||||
case 't':
|
||||
case 'T':
|
||||
expo1 = expo1 + 12;
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
expo1 = expo1 + 9;
|
||||
break;
|
||||
case 'k':
|
||||
case 'K':
|
||||
expo1 = expo1 + 3;
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
expo1 = expo1 - 6;
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
expo1 = expo1 - 9;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
expo1 = expo1 - 12;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
expo1 = expo1 - 15;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
{
|
||||
/* special case for m - may be m or mil or meg */
|
||||
if (*(here + 1) != 0 && *(here + 2) != 0) {
|
||||
/* at least 2 characters, so check them. */
|
||||
if ((*(here + 1) == 'E') || (*(here + 1) == 'e')) {
|
||||
if ((*(here + 2) == 'G') || (*(here + 2) == 'g')) {
|
||||
expo1 = expo1 + 6;
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (sign * mantis *
|
||||
pow((double) 10,
|
||||
(double) (expo1 + expsgn * expo2)));
|
||||
}
|
||||
} else if ((*(here + 1) == 'I') || (*(here + 1) == 'i')) {
|
||||
if ((*(here + 2) == 'L') || (*(here + 2) == 'l')) {
|
||||
expo1 = expo1 - 6;
|
||||
mantis = mantis * 25.4;
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (sign * mantis *
|
||||
pow((double) 10,
|
||||
(double) (expo1 + expsgn * expo2)));
|
||||
}
|
||||
}
|
||||
case 't':
|
||||
case 'T':
|
||||
expo1 = expo1 + 12;
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
expo1 = expo1 + 9;
|
||||
break;
|
||||
case 'k':
|
||||
case 'K':
|
||||
expo1 = expo1 + 3;
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
expo1 = expo1 - 6;
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
expo1 = expo1 - 9;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
expo1 = expo1 - 12;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
expo1 = expo1 - 15;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
{
|
||||
/* special case for m - may be m or mil or meg */
|
||||
if (*(here + 1) != 0 && *(here + 2) != 0) {
|
||||
/* at least 2 characters, so check them. */
|
||||
if ((*(here + 1) == 'E') || (*(here + 1) == 'e')) {
|
||||
if ((*(here + 2) == 'G') || (*(here + 2) == 'g')) {
|
||||
expo1 = expo1 + 6;
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (sign * mantis *
|
||||
pow((double) 10,
|
||||
(double) (expo1 + expsgn * expo2)));
|
||||
}
|
||||
} else if ((*(here + 1) == 'I') || (*(here + 1) == 'i')) {
|
||||
if ((*(here + 2) == 'L') || (*(here + 2) == 'l')) {
|
||||
expo1 = expo1 - 6;
|
||||
mantis = mantis * 25.4;
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return (sign * mantis *
|
||||
pow((double) 10,
|
||||
(double) (expo1 + expsgn * expo2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* not either special case, so just m => 1e-3 */
|
||||
expo1 = expo1 - 3;
|
||||
}
|
||||
/* not either special case, so just m => 1e-3 */
|
||||
expo1 = expo1 - 3;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
*line = here;
|
||||
}
|
||||
return (sign * mantis *
|
||||
pow((double) 10, (double) (expo1 + expsgn * expo2)));
|
||||
pow((double) 10, (double) (expo1 + expsgn * expo2)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,3 +356,130 @@ int INPgetUTok(char **line, char **token, int gobble)
|
|||
|
||||
return (OK);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* INPgetUTok plus points < > ? :, called from INPevaluate called
|
||||
* from INPevaluate with gobble == 2
|
||||
* fcn added to avoid unforeseeable side effects during other calls
|
||||
* to INPevaluate.
|
||||
*------------------------------------------------------------------*/
|
||||
int INPgetU2Tok(char **line, char **token, int gobble)
|
||||
/* eat non-whitespace trash AFTER token? */
|
||||
{
|
||||
char *point, separator;
|
||||
int signstate;
|
||||
/* scan along throwing away garbage characters */
|
||||
for (point = *line; *point != '\0'; point++) {
|
||||
if (*point == ' ')
|
||||
continue;
|
||||
if (*point == '\t')
|
||||
continue;
|
||||
if (*point == '=')
|
||||
continue;
|
||||
if (*point == '(')
|
||||
continue;
|
||||
if (*point == ')')
|
||||
continue;
|
||||
if (*point == ',')
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (*point == '"') {
|
||||
separator = '"';
|
||||
point++;
|
||||
} else if (*point == '\'') {
|
||||
separator = '\'';
|
||||
point++;
|
||||
} else
|
||||
separator = 0;
|
||||
|
||||
/* mark beginning of token */
|
||||
*line = point;
|
||||
|
||||
/* now find all good characters */
|
||||
signstate = 0;
|
||||
for (point = *line; *point != '\0'; point++) {
|
||||
if (separator) {
|
||||
if (*point == separator)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (*point == ' ')
|
||||
break;
|
||||
if (*point == '\t')
|
||||
break;
|
||||
if (*point == '=')
|
||||
break;
|
||||
if (*point == '(')
|
||||
break;
|
||||
if (*point == ')')
|
||||
break;
|
||||
if (*point == ',')
|
||||
break;
|
||||
/* This is not complex enough to catch all errors, but it will
|
||||
get the "good" parses */
|
||||
if (*point == '+' && (signstate == 1 || signstate == 3))
|
||||
break;
|
||||
if (*point == '-') {
|
||||
if (signstate == 1 || signstate == 3)
|
||||
break;
|
||||
signstate += 1;
|
||||
continue;
|
||||
}
|
||||
if (*point == '*')
|
||||
break;
|
||||
if (*point == '/')
|
||||
break;
|
||||
if (*point == '^')
|
||||
break;
|
||||
if (*point == '<')
|
||||
break;
|
||||
if (*point == '>')
|
||||
break;
|
||||
if (*point == '?')
|
||||
break;
|
||||
if (*point == ':')
|
||||
break;
|
||||
if (isdigit(*point) || *point == '.') {
|
||||
if (signstate > 1)
|
||||
signstate = 3;
|
||||
else
|
||||
signstate = 1;
|
||||
} else if (tolower(*point) == 'e' && signstate == 1)
|
||||
signstate = 2;
|
||||
else
|
||||
signstate = 3;
|
||||
}
|
||||
if (separator && *point == separator)
|
||||
point--;
|
||||
if (point == *line && *point) /* Weird items, 1 char */
|
||||
point++;
|
||||
*token = (char *) MALLOC(1 + point - *line);
|
||||
if (!*token)
|
||||
return (E_NOMEM);
|
||||
(void) strncpy(*token, *line, point - *line);
|
||||
*(*token + (point - *line)) = '\0';
|
||||
/* gobble garbage to next token */
|
||||
for (; *point != '\0'; point++) {
|
||||
if (*point == separator)
|
||||
continue;
|
||||
if (*point == ' ')
|
||||
continue;
|
||||
if (*point == '\t')
|
||||
continue;
|
||||
if ((*point == '=') && gobble)
|
||||
continue;
|
||||
if ((*point == ',') && gobble)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
*line = point;
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
/* printf("found refdes token (%s) and rest of line (%s)\n",*token,*line); */
|
||||
#endif
|
||||
|
||||
return (OK);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue