From d89d52039f1d662e74cf3f1d68e1d5430c266ccb Mon Sep 17 00:00:00 2001 From: h_vogt Date: Fri, 3 Sep 2010 12:51:42 +0000 Subject: [PATCH] bug in B source parsing removed --- ChangeLog | 4 + src/frontend/inpcom.c | 2 +- src/spicelib/parser/inp.h | 1 + src/spicelib/parser/inpeval.c | 288 +++++++++++++++++----------------- src/spicelib/parser/inpgtok.c | 127 +++++++++++++++ 5 files changed, 279 insertions(+), 143 deletions(-) diff --git a/ChangeLog b/ChangeLog index 167f7e6c7..f91dd598e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 84f9d874c..76b560611 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -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 */ diff --git a/src/spicelib/parser/inp.h b/src/spicelib/parser/inp.h index d86f9ebf8..7c8aa49e3 100644 --- a/src/spicelib/parser/inp.h +++ b/src/spicelib/parser/inp.h @@ -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); diff --git a/src/spicelib/parser/inpeval.c b/src/spicelib/parser/inpeval.c index 029487830..e28c9749d 100644 --- a/src/spicelib/parser/inpeval.c +++ b/src/spicelib/parser/inpeval.c @@ -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))); } diff --git a/src/spicelib/parser/inpgtok.c b/src/spicelib/parser/inpgtok.c index fc5b2e7da..5f6d87031 100644 --- a/src/spicelib/parser/inpgtok.c +++ b/src/spicelib/parser/inpgtok.c @@ -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); +}