diff --git a/src/include/ngspice/inpdefs.h b/src/include/ngspice/inpdefs.h index 49488ea88..661e6a2a3 100644 --- a/src/include/ngspice/inpdefs.h +++ b/src/include/ngspice/inpdefs.h @@ -116,6 +116,7 @@ char *INPerrCat(char *, char *); char *INPstrCat(char *, char, char *); char *INPerror(int); double INPevaluate(char **, int *, int); +double INPevaluate2(char **, int *, int); double INPevaluateRKM_R(char **, int *, int); double INPevaluateRKM_C(char **, int *, int); double INPevaluateRKM_L(char **, int *, int); diff --git a/src/spicelib/parser/inpeval.c b/src/spicelib/parser/inpeval.c index 13dcaa81b..bd17eebbf 100644 --- a/src/spicelib/parser/inpeval.c +++ b/src/spicelib/parser/inpeval.c @@ -686,7 +686,7 @@ INPevaluateRKM_C(char** line, int* error, int gobble) } /* In addition to fcn INPevaluate() above, allow values like 4k7, - similar to the RKM code (used by inp2r) */ + similar to the RKM code (used by inp2l) */ double INPevaluateRKM_L(char** line, int* error, int gobble) /* gobble: non-zero to gobble rest of token, zero to leave it alone */ @@ -923,3 +923,217 @@ INPevaluateRKM_L(char** line, int* error, int gobble) pow(10.0, (double)(expo1 + expsgn * expo2))); } + +/* This version will move past the scale factor for the rest of the token */ +double +INPevaluate2(char** line, int* error, int gobble) +/* gobble: non-zero to gobble rest of token, zero to leave it alone */ +{ + char* token; + char* here; + double mantis; + int expo1; + int expo2; + int sign; + int expsgn; + char* tmpline; + + /* 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 (0.0); + } + else { + token = *line; + *error = 0; + } + + mantis = 0; + expo1 = 0; + expo2 = 0; + sign = 1; + expsgn = 1; + + /* loop through all of the input token */ + here = token; + + if (*here == '+') + here++; /* plus, so do nothing except skip it */ + else if (*here == '-') { /* minus, so skip it, and change sign */ + here++; + sign = -1; + } + + if ((*here == '\0') || ((!(isdigit_c(*here))) && (*here != '.'))) { + /* number looks like just a sign! */ + *error = 1; + if (gobble) { + FREE(token); + /* back out the 'gettok' operation */ + *line = tmpline; + } + return (0); + } + + while (isdigit_c(*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); + } + + if (*here == ':') { + /* ':' is no longer used for subcircuit node numbering + but is part of ternary function a?b:c + FIXME : subcircuit models still use ':' for model numbering + Will this hurt somewhere? */ + if (gobble) { + FREE(token); + } + else { + *line = here; + } + return ((double)mantis * sign); + } + + /* 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_c(*here)) { + /* digit, so accumulate it. */ + mantis = 10 * mantis + *here - '0'; + expo1 = expo1 - 1; + 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 + */ + else if (*here == '-') { + here++; /* skip over minus sign */ + expsgn = -1; /* and make a negative exponent */ + /* now look for the digits of the exponent */ + } + + while (isdigit_c(*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; + here++; + break; + case 'g': + case 'G': + expo1 = expo1 + 9; + here++; + break; + case 'k': + case 'K': + expo1 = expo1 + 3; + here++; + break; + case 'u': + case 'U': + expo1 = expo1 - 6; + here++; + break; + case 'n': + case 'N': + expo1 = expo1 - 9; + here++; + break; + case 'p': + case 'P': + expo1 = expo1 - 12; + here++; + break; + case 'f': + case 'F': + expo1 = expo1 - 15; + here++; + break; + case 'a': + case 'A': + expo1 = expo1 - 18; + here++; + break; + case 'm': + case 'M': + if (((here[1] == 'E') || (here[1] == 'e')) && + ((here[2] == 'G') || (here[2] == 'g'))) + { + expo1 = expo1 + 6; /* Meg */ + here += 3; + } + else if (((here[1] == 'I') || (here[1] == 'i')) && + ((here[2] == 'L') || (here[2] == 'l'))) + { + expo1 = expo1 - 6; + mantis *= 25.4; /* Mil */ + here += 3; + } + else { + expo1 = expo1 - 3; /* m, milli */ + here++; + } + break; + default: + break; + } + + if (gobble) { + FREE(token); + } + else { + *line = here; + } + + return (sign * mantis * + pow(10.0, (double)(expo1 + expsgn * expo2))); +} + + +