From 76feebbbfad30a449a182367a9aa2d732c6cd587 Mon Sep 17 00:00:00 2001 From: h_vogt Date: Thu, 25 Feb 2010 21:43:03 +0000 Subject: [PATCH] various bug fixes --- ChangeLog | 10 + src/frontend/inp.c | 1 + src/frontend/inpcom.c | 14 +- src/frontend/numparam/general.h | 104 ++- src/frontend/numparam/mystring.c | 1031 ++++++++++++++++++------------ src/frontend/numparam/numparam.h | 25 +- src/frontend/numparam/spicenum.c | 503 ++++++++------- src/frontend/numparam/xpressn.c | 800 +++++++++++++---------- src/frontend/subckt.c | 11 +- src/include/Makefile.am | 1 + src/include/inpptree.h | 1 + src/misc/Makefile.am | 1 + src/spicelib/parser/ifeval.c | 19 + src/spicelib/parser/inpptree.c | 93 ++- visualc/vngspice.sln | 8 +- visualc/vngspice.vcproj | 688 ++++++++++---------- 16 files changed, 1921 insertions(+), 1389 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd790446c..6ad758dd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-02-25 Holger Vogt + * inpcom.c, general.h, mystring.c, numparam.h, spicenum.c, xpressn.c, + include/makefile.am, misc/makefile.am, hash.c, hash.h: + major bug-fix on numparam by Bill Swartz + * subckt.c: bugfix on bxx_printf() + * inp.c memory leak, line 707 wl_free(wl); added + * ifeval.c, inpptree.c, inpptree.h: first try of ternary fcn in B source + by Robert Larice + * vngspice.sln, vngspice.vcproj: new files hash.c, .h added to project + 2010-02-22 Dietmar Warning * xpressn.c, spicenum.c: more characters for real number insertion (up to 15) by introducing a long long placeholder diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 673c29002..64f972b0a 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -704,6 +704,7 @@ inp_dodeck( eev->va_next = cp_setparse(wl); else ct->ci_vars = eev = cp_setparse(wl); + wl_free(wl); while (eev->va_next) eev = eev->va_next; } diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 7daaa4049..76bf2e66b 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -1786,7 +1786,7 @@ inp_fix_subckt( char *s ) head = alloc(struct line); /* create list of parameters that need to get sorted */ - while ( ( ptr1 = strstr( beg, "=" ) ) ) { + while ( *beg && (ptr1 = strstr( beg, "=" ) ) ) { ptr2 = ptr1+1; ptr1--; while ( isspace(*ptr1) ) ptr1--; @@ -1797,8 +1797,16 @@ inp_fix_subckt( char *s ) while ( *ptr2 && !isspace(*ptr2) ) ptr2++; /* ptr2 points to end of parameter */ keep = *ptr2; - *ptr2 = '\0'; - beg = ptr2+1; + if( keep == '\0' ){ + /* End of string - don't go over end. This needed to change because + * strings don't store line size here anymore since we use dynamic + * strings. Previously, we could step on string size which was stored + * at string[length+2] and string[length+2] */ + beg = ptr2 ; + } else { + *ptr2 = '\0' ; + beg = ptr2+1 ; + } newcard = alloc(struct line); str = strdup(ptr1); diff --git a/src/frontend/numparam/general.h b/src/frontend/numparam/general.h index dc5d312a1..7819cb957 100644 --- a/src/frontend/numparam/general.h +++ b/src/frontend/numparam/general.h @@ -9,40 +9,39 @@ #define Use(x) x=0;x=x #define Uses(s) s=s #define Usep(x) x=x -#define Hi(x) (((x) >> 8) & 0xff) -#define Lo(x) ((x) & 0xff) -//#define Strbig(n,a) char a[n+4]={0, (char)Hi(n), (char)Lo(n)} -#define Strbig(n,a) char*(a)=(char*)tmalloc((n+4)*sizeof(char)); \ - (a)[0]=0; (a)[1]=(char)Hi(n); (a)[2]=(char)Lo(n) -#define Strdbig(n,a,b) char*(a); char*(b); \ - (a)=(char*)tmalloc((n+4)*sizeof(char)); \ - (a)[0]=0; (a)[1]=(char)Hi(n); (a)[2]=(char)Lo(n);\ - (b)=(char*)tmalloc((n+4)*sizeof(char)); \ - (b)[0]=0; (b)[1]=(char)Hi(n); (b)[2]=(char)Lo(n) +/* ----------------------------------------------------------------- + * This structure is modified from Tcl. We do this to avoid a + * conflict and later add a conditional compile to just use the Tcl + * code if desired. +----------------------------------------------------------------- */ +#define SPICE_DSTRING_STATIC_SIZE 200 +typedef struct spice_dstring { + char *string ; /* Points to beginning of string: either + * staticSpace below or a malloced array. */ + int length ; /* Number of non-NULL characters in the + * string. */ + int spaceAvl ; /* Total number of bytes available for the + * string and its terminating NULL char. */ + char staticSpace[SPICE_DSTRING_STATIC_SIZE] ; + /* Space to use in common case where string + * is small. */ +} SPICE_DSTRING, *SPICE_DSTRINGPTR ; -#define Strfbig(n,a,b,c,d) char*(a); char*(b); char*(c); char*(d);\ - (a)=(char*)tmalloc((n+4)*sizeof(char)); \ - (a)[0]=0; (a)[1]=(char)Hi(n); (a)[2]=(char)Lo(n);\ - (b)=(char*)tmalloc((n+4)*sizeof(char)); \ - (b)[0]=0; (b)[1]=(char)Hi(n); (b)[2]=(char)Lo(n);\ - (c)=(char*)tmalloc((n+4)*sizeof(char)); \ - (c)[0]=0; (c)[1]=(char)Hi(n); (c)[2]=(char)Lo(n);\ - (d)=(char*)tmalloc((n+4)*sizeof(char)); \ - (d)[0]=0; (d)[1]=(char)Hi(n); (d)[2]=(char)Lo(n) +/* ----------------------------------------------------------------- + * spice_dstring_xxxx routines. Used to manipulate dynamic strings. +----------------------------------------------------------------- */ +extern void spice_dstring_init(SPICE_DSTRINGPTR dsPtr) ; +extern char *spice_dstring_append(SPICE_DSTRINGPTR dsPtr,char *string,int length) ; +extern char *spice_dstring_print(SPICE_DSTRINGPTR dsPtr,char *format, ... ) ; +extern char *spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) ; +extern char *_spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) ; +extern void spice_dstring_free(SPICE_DSTRINGPTR dsPtr) ; +#define spice_dstring_reinit(x_xz) spice_dstring_setlength(x_xz,0) ; +#define spice_dstring_value(x_xz) ((x_xz)->string) +#define spice_dstring_space(x_xz) ((x_xz)->spaceAvl) +#define spice_dstring_length(x_xz) ((x_xz)->length) -#define Strrem(a) tfree(a) -#define Strdrem(a,b) tfree(a); tfree(b) -#define Strfrem(a,b,c,d) tfree(a); tfree(b); tfree(c); tfree(d) - -#define Str(n,a) char a[n+3]={0,0,(char)n} /* n<255 ! */ -#define Sini(s) sini(s,sizeof(s)-4) - - -/* was 255, then 15000, string maxlen, 40000 to catch really big - macros in .model lines, now just a big number, a line length - which never should be exceeded, may be removed later*/ -typedef enum {Maxstr=4000000} _nMaxstr; typedef enum {Esc=27} _nEsc; typedef enum {Tab=9} _nTab; typedef enum {Bs=8} _nBs; @@ -52,22 +51,22 @@ typedef enum {Cr=13} _nCr; typedef char string[258]; -void sini( char * s, int i); -void sfix(char * s, int i, int max); -int maxlen(char * s); -char * pscopy( char * s, char * a, int i,int j); -char * pscopy_up( char * s, char * a, int i,int j); -unsigned char scopy( char * a, char * b); -unsigned char scopy_up( char * a, char * b); -unsigned char ccopy( char * a, char c); -unsigned char sadd( char * s, char * t); -unsigned char nadd( char * s, long n); -unsigned char naddll( char * s, long long n); -unsigned char cadd( char * s, char c); -unsigned char sins( char * s, char * t); -unsigned char cins( char * s, char c); -int cpos( char c, char * s); -int spos( char * sub, char * s); +void sfix( SPICE_DSTRINGPTR dstr_p, int len) ; +char * pscopy( SPICE_DSTRINGPTR s, char * a, int i,int j); +char * pscopy_up( SPICE_DSTRINGPTR s, char * a, int i,int j); +unsigned char scopyd( SPICE_DSTRINGPTR a, SPICE_DSTRINGPTR b); +unsigned char scopys( SPICE_DSTRINGPTR a, char *b); +unsigned char scopy_up( SPICE_DSTRINGPTR a, char *str) ; +unsigned char scopy_lower( SPICE_DSTRINGPTR a, char *str) ; +unsigned char ccopy( SPICE_DSTRINGPTR a, char c); +unsigned char sadd( SPICE_DSTRINGPTR s, char * t); +unsigned char nadd( SPICE_DSTRINGPTR s, long n); +unsigned char cadd( SPICE_DSTRINGPTR s, char c); +unsigned char naddll( SPICE_DSTRINGPTR s, long long n); +unsigned char cins( SPICE_DSTRINGPTR s, char c); +unsigned char sins( SPICE_DSTRINGPTR s, char * t); +int cpos( char c, char *s); +int spos_( char * sub, char * s); int ci_prefix( register char *p, register char *s ); int length(char * s); unsigned char steq(char * s, char * t); @@ -76,9 +75,9 @@ int scompare(char * a, char * b); int ord(char c); int pred(int i); int succ(int i); -void stri(long n, char * s); -void strif(long n, int f, char * s); -void strf(double x, int a, int b, char * s); /* float -> string */ +void stri(long n, SPICE_DSTRINGPTR s); +void strif(long n, int f, SPICE_DSTRINGPTR dstr_p); +void strf(double x, int a, int b, SPICE_DSTRINGPTR dstr_p); /* float -> string */ long ival(char * s, int *err); double rval(char * s, int *err); @@ -97,10 +96,10 @@ void wc(char c); void wln(void); void ws( char * s); void wi(long i); -void rs( char * s); +void rs( SPICE_DSTRINGPTR s); char rc(void); -int freadstr(FILE * f, char * s, int max); +int freadstr(FILE * f, SPICE_DSTRINGPTR dstr_p); char freadc(FILE * f); long freadi(FILE * f); @@ -116,4 +115,3 @@ unsigned char rewrite(FILE * f); void rawcopy(void * a, void * b, int la, int lb); void * new(long sz); void dispose(void * p); -char * newstring(int n); diff --git a/src/frontend/numparam/mystring.c b/src/frontend/numparam/mystring.c index 0e217fc06..9cd3d13bc 100644 --- a/src/frontend/numparam/mystring.c +++ b/src/frontend/numparam/mystring.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "config.h" #ifdef HAS_WINDOWS @@ -21,7 +22,7 @@ #include "../error.h" /* controlled_exit() */ -#define Getmax(s,ls) (((unsigned char)(s[ls+1])) << 8) + (unsigned char)(s[ls+2]) +#define EOS '\0' /***** primitive input-output ***/ @@ -66,31 +67,24 @@ ws (char *s) void wi (long i) { - Str (16, s); - nadd (s, i); - ws (s); + SPICE_DSTRING s ; + spice_dstring_init(&s) ; + nadd (&s, i); + ws ( spice_dstring_value(&s)) ; + spice_dstring_free(&s) ; } void -rs (char *s) +rs ( SPICE_DSTRINGPTR dstr_p) { /* basic line input, limit= 80 chars */ - int max, i; char c; - max = maxlen (s); - i = 0; - sini (s, max); - if (max > 80) - max = 80; + spice_dstring_reinit(dstr_p) ; do { c = fgetc (stdin); - if ((i < max) && (c >= ' ')) - { - cadd (s, c); - i++; - } + cadd (dstr_p, c); } while (!((c == Cr) || (c == '\n'))); /* return i */ ; @@ -100,13 +94,21 @@ char rc (void) { int ls; - Str (80, s); - rs (s); - ls = length (s); - if (ls > 0) - return s[ls - 1]; - else - return 0; + char val ; + char *s_p ; + SPICE_DSTRING dstr ; + + spice_dstring_init(&dstr) ; + rs (&dstr); + ls = spice_dstring_length (&dstr); + if (ls > 0){ + s_p = spice_dstring_value(&dstr) ; + val = s_p[ls - 1] ; + } else { + val = 0 ; + } + spice_dstring_free(&dstr) ; + return val ; } @@ -123,93 +125,30 @@ rc (void) * * the 'killer idea' is the following: * on string overflow and/or on heap allocation failure, a program - * MUST die. + * MUST die. Now we only die on a heap failure as with dynamic + * string we cannot have a string overflow. */ -static void -stringbug (char *op, char *s, char *t, char c) -/* we brutally stop the program on string overflow */ -{ - char rep = ' '; - fprintf (stderr, " STRING overflow %s\n", op); - fprintf (stderr, " Operand1: %s\n", s); - if (t != NULL) - fprintf (stderr, " Operand2: %s\n", t); - - if (c != 0) - fprintf (stderr, "{%c}\n", c); - - fprintf (stderr, "Aborting...\n"); - controlled_exit(EXIT_FAILURE); - -/* The code below cannot be reached */ -/* Remnants of old interface ?*/ - - ws (" [A]bort [I]gnore ? "); - rep = rc (); - if (upcase (rep) == 'A') - controlled_exit(EXIT_FAILURE); -} - void -sini (char *s, int max) /* suppose s is allocated */ -{ - if (max < 1) - max = 1; - else if (max > Maxstr) - max = Maxstr; - - s[0] = 0; - s[1] = Hi (max); - s[2] = Lo (max); -} - -void -sfix (char *s, int i, int max) +sfix ( SPICE_DSTRINGPTR dstr_p, int len) /* suppose s is allocated and filled with non-zero stuff */ { + /* This function will now eliminate the max field. The length of + * the string is going to be i-1 and a null is going to be added + * at the ith position to be compatible with old codel. Also no + * null characters will be present in the string leading up to the + * NULL so this will make it a valid string. */ int j; - if (max < 1) - max = 1; - else if (max > Maxstr) - max = Maxstr; + char *s ; - if (i > max) - i = max; - else if (i < 0) - i = 0; - - s[i] = 0; - s[i + 1] = Hi (max); - s[i + 2] = Lo (max); - - for (j = 0; j < i; j++) /* eliminate null characters ! */ + spice_dstring_setlength( dstr_p, len ) ; + s = spice_dstring_value( dstr_p ) ; + for (j = 0; j < len; j++) /* eliminate null characters ! */ if (s[j] == 0) s[j] = 1; } -static void -inistring (char *s, char c, int max) -/* suppose s is allocated. empty it if c is zero ! */ -{ - int i = 0; - s[i] = c; - if (c != 0) - { - i++; - s[i] = 0; - } - - if (max < 1) - max = 1; - else if (max > Maxstr) - max = Maxstr; - - s[i + 1] = Hi (max); - s[i + 2] = Lo (max); -} - int length (char *s) { @@ -221,107 +160,77 @@ length (char *s) return lg; } -int -maxlen (char *s) +/* ----------------------------------------------------------------- + * Function: add string t to dynamic string dstr_p. + * ----------------------------------------------------------------- */ +unsigned char +sadd ( SPICE_DSTRINGPTR dstr_p, char *t) { - int ls = length (s); - - return Getmax (s, ls); + spice_dstring_append( dstr_p, t, -1 ) ; + return 1 ; } +/* ----------------------------------------------------------------- + * Function: add character c to dynamic string dstr_p. + * ----------------------------------------------------------------- */ unsigned char -sadd (char *s, char *t) +cadd ( SPICE_DSTRINGPTR dstr_p, char c) { - unsigned char ok; - int i = 0, max, ls = length (s); - max = Getmax (s, ls); - - while ((t[i] != 0) && (ls < max)) - { - s[ls] = t[i]; - i++; - ls++; - } - - s[ls] = 0; - s[ls + 1] = Hi (max); - s[ls + 2] = Lo (max); - ok = (t[i] == 0); /* end of t is reached */ - - if (!ok) - stringbug ("sadd", s, t, 0); - - return ok; + char tmp_str[2] ; + tmp_str[0] = c ; + tmp_str[1] = 0 ; + spice_dstring_append( dstr_p, tmp_str, -1 ) ; + return 1 ; } +/* ----------------------------------------------------------------- + * Function: insert character c at front of dynamic string dstr_p + * ----------------------------------------------------------------- */ unsigned char -cadd (char *s, char c) +cins ( SPICE_DSTRINGPTR dstr_p, char c) { - int max, ls = length (s); - unsigned char ok; - max = Getmax (s, ls); - ok = (ls < max); - if (ok) - { - s[ls + 3] = s[ls + 2]; - s[ls + 2] = s[ls + 1]; - s[ls + 1] = 0; - s[ls] = c; - } - if (!ok) - stringbug ("cadd", s, NULL, c); - - return ok; + int i ; + int ls ; + char *s_p ; + + ls = spice_dstring_length(dstr_p) ; + spice_dstring_setlength(dstr_p,ls+2) ; /* make sure we have space for char + EOS */ + s_p = spice_dstring_value(dstr_p) ; + for (i = ls + 1; i >= 0; i--) + s_p[i + 1] = s_p[i]; + s_p[0] = c; + return 1 ; } +/* ----------------------------------------------------------------- + * Function: insert string t at front of dynamic string dstr_p + * ----------------------------------------------------------------- */ unsigned char -cins (char *s, char c) +sins ( SPICE_DSTRINGPTR dstr_p, char *t) { - int i, max, ls = length (s); - unsigned char ok; - max = Getmax (s, ls); - ok = (ls < max); + int i ; + int ls ; + int lt ; + char *s_p ; + + ls = spice_dstring_length(dstr_p) ; + lt = length (t) ; + spice_dstring_setlength(dstr_p,ls+lt+1) ; /* make sure we have space for string + EOS */ + s_p = spice_dstring_value(dstr_p) ; + for (i = ls + 1; i >= 0; i--) + s_p[i + lt] = s_p[i]; - if (ok) - { - for (i = ls + 2; i >= 0; i--) - s[i + 1] = s[i]; - s[0] = c; - } + for (i = 0; i < lt; i++) + s_p[i] = t[i]; + return 1 ; - if (!ok) - stringbug ("cins", s, NULL, c); - - return ok; -} - -unsigned char -sins (char *s, char *t) -{ - int i, max, ls = length (s), lt = length (t); - unsigned char ok; - max = Getmax (s, ls); - ok = ((ls + lt) < max); - - if (ok) - { - for (i = ls + 2; i >= 0; i--) - s[i + lt] = s[i]; - - for (i = 0; i < lt; i++) - s[i] = t[i]; - } - - if (!ok) - stringbug ("sins", s, t, 0); - - return ok; } int cpos (char c, char *s) /* return position of c in s, or 0 if not found. * BUG, Pascal inherited: first char is at 1, not 0 ! + * No longer! Now position is C-based to make life easier. */ { int i = 0; @@ -329,9 +238,9 @@ cpos (char c, char *s) i++; if (s[i] == c) - return (i + 1); + return i ; else - return 0; + return -1 ; } char @@ -343,163 +252,132 @@ upcase (char c) return c; } +/* ----------------------------------------------------------------- + * Create copy of the dynamic string. Dynamic strings are always NULL + * terminated. + * ----------------------------------------------------------------- */ unsigned char -scopy (char *s, char *t) /* returns success flag */ +scopyd(SPICE_DSTRINGPTR s, SPICE_DSTRINGPTR t) /* returns success flag */ { - unsigned char ok; - int i, max, ls = length (s); - max = Getmax (s, ls); - i = 0; + spice_dstring_reinit( s ) ; + spice_dstring_append( s, spice_dstring_value(t), -1 ) ; + return 1 ; /* Dstrings expand to any length */ +} - while ((t[i] != 0) && (i < max)) - { - s[i] = t[i]; - i++; - } +/* ----------------------------------------------------------------- + * Create copy of the string in the dynamic string. Dynamic strings + * are always NULLterminated. + * ----------------------------------------------------------------- */ +unsigned char +scopys(SPICE_DSTRINGPTR s, char *t) /* returns success flag */ +{ + spice_dstring_reinit( s ) ; + spice_dstring_append( s, t, -1 ) ; + return 1 ; /* Dstrings expand to any length */ +} - s[i] = 0; - s[i + 1] = Hi (max); - s[i + 2] = Lo (max); - ok = (t[i] == 0); /* end of t is reached */ +/* ----------------------------------------------------------------- + * Create an upper case copy of a string and store it in a dynamic string. + * Dynamic strings are always NULL * terminated. + * ----------------------------------------------------------------- */ +unsigned char +scopy_up (SPICE_DSTRINGPTR dstr_p, char *str) /* returns success flag */ +{ + char up[2] ; /* short string */ + char *ptr ; /* position in string */ - if (!ok) - stringbug ("scopy", s, t, 0); + spice_dstring_reinit( dstr_p ) ; + up[1] = 0 ; + for( ptr = str ; ptr && *ptr ; ptr++ ){ + up[0] = upcase ( *ptr ); + spice_dstring_append( dstr_p, up, 1 ) ; + } + return 1 ; /* Dstrings expand to any length */ +} - return ok; +/* ----------------------------------------------------------------- + * Create a lower case copy of a string and store it in a dynamic string. + * Dynamic strings are always NULL * terminated. + * ----------------------------------------------------------------- */ +unsigned char +scopy_lower (SPICE_DSTRINGPTR dstr_p, char *str) /* returns success flag */ +{ + char low[2] ; /* short string */ + char *ptr ; /* position in string */ + + spice_dstring_reinit( dstr_p ) ; + low[1] = 0 ; + for( ptr = str ; ptr && *ptr ; ptr++ ){ + low[0] = lowcase ( *ptr ); + spice_dstring_append( dstr_p, low, 1 ) ; + } + return 1 ; /* Dstrings expand to any length */ } unsigned char -scopy_up (char *s, char *t) /* returns success flag */ +ccopy ( SPICE_DSTRINGPTR dstr_p, char c) /* returns success flag */ { - unsigned char ok; - int i, max, ls = length (s); - max = Getmax (s, ls); - i = 0; - while ((t[i] != 0) && (i < max)) - { - s[i] = upcase (t[i]); - i++; - } + char *s_p ; /* current string */ - s[i] = 0; - s[i + 1] = Hi (max); - s[i + 2] = Lo (max); - ok = (t[i] == 0); /* end of t is reached */ - - if (!ok) - stringbug ("scopy_up", s, t, 0); - - return ok; -} - -unsigned char -ccopy (char *s, char c) /* returns success flag */ -{ - int max, ls = length (s); - unsigned char ok = 0; - max = Getmax (s, ls); - - if (max > 0) - { - s[0] = c; - sfix (s, 1, max); - ok = 1; - } - - if (!ok) - stringbug ("ccopy", s, NULL, c); - - return ok; + sfix ( dstr_p, 1); + s_p = spice_dstring_value(dstr_p) ; + s_p[0] = c ; + return 1 ; } char * -pscopy (char *s, char *t, int start, int leng) -/* partial string copy, with Turbo Pascal convention for "start" */ -/* BUG: position count starts at 1, not 0 ! */ +pscopy (SPICE_DSTRINGPTR dstr_p, char *t, int start, int leng) +/* partial string copy, with C-based start - Because we now have a 0 based + * start and string may copy outselves, we may need to restore the first + * character of the original dstring because resetting string will wipe + * out first character. */ { - int max = maxlen (s); /* keep it for later */ - int stop = length (t); - int i; - unsigned char ok = (max >= 0) && (max <= Maxstr); + int i; /* counter */ + int stop ; /* stop value */ + char *s_p ; /* value of dynamic string */ - if (!ok) - stringbug ("copy target non-init", s, t, 0); + stop = length(t) ; - if (leng > max) - { - leng = max; - ok = 0; + if (start < stop) { /* nothing! */ + if ((start + leng - 1) > stop) { +// leng = stop - start + 1; + leng = stop - start ; } - - if (start > stop) - { /* nothing! */ - ok = 0; - inistring (s, 0, max); - } - else - { - if ((start + leng - 1) > stop) - { - leng = stop - start + 1; - ok = 0; - } - for (i = 0; i < leng; i++) - s[i] = t[start + i - 1]; - - i = leng; - s[i] = 0; - s[i + 1] = Hi (max); - s[i + 2] = Lo (max); - } - /* if ( ! ok ) { stringbug("copy",s, t, 0) ;} */ - /* if ( ok ) { return s ;} else { return NULL ;} */ - ok = ok; - return s; + _spice_dstring_setlength(dstr_p,leng) ; + s_p = spice_dstring_value(dstr_p) ; + for (i = 0; i < leng; i++) + s_p[i] = t[start + i]; + s_p[leng] = EOS ; + } else { + s_p = spice_dstring_reinit(dstr_p) ; + } + return s_p ; } char * -pscopy_up (char *s, char *t, int start, int leng) -/* partial string copy, with Turbo Pascal convention for "start" */ -/* BUG: position count starts at 1, not 0 ! */ +pscopy_up (SPICE_DSTRINGPTR dstr_p, char *t, int start, int leng) +/* partial string copy to upper case, with C convention for start. */ { - int max = maxlen (s); /* keep it for later */ - int stop = length (t); - int i; - unsigned char ok = (max >= 0) && (max <= Maxstr); + int i; /* counter */ + int stop ; /* stop value */ + char *s_p ; /* value of dynamic string */ - if (!ok) - stringbug ("copy target non-init", s, t, 0); + stop = length(t) ; - if (leng > max) - { - leng = max; - ok = 0; + if (start < stop) { /* nothing! */ + if ((start + leng - 1) > stop) { +// leng = stop - start + 1; + leng = stop - start ; } - - if (start > stop) - { /* nothing! */ - ok = 0; - inistring (s, 0, max); - } - else - { - if ((start + leng - 1) > stop) - { - leng = stop - start + 1; - ok = 0; - } - for (i = 0; i < leng; i++) - s[i] = upcase (t[start + i - 1]); - - i = leng; - s[i] = 0; - s[i + 1] = Hi (max); - s[i + 2] = Lo (max); - } - /* if ( ! ok ) { stringbug("copy",s, t, 0) ;} */ - /* if ( ok ) { return s ;} else { return NULL ;} */ - ok = ok; - return s; + _spice_dstring_setlength(dstr_p,leng) ; + s_p = spice_dstring_value(dstr_p) ; + for (i = 0; i < leng; i++) + s_p[i] = upcase ( t[start + i] ) ; + s_p[leng] = EOS ; + } else { + s_p = spice_dstring_reinit(dstr_p) ; + } + return s_p ; } int @@ -521,15 +399,14 @@ succ (int i) } unsigned char -nadd (char *s, long n) +nadd ( SPICE_DSTRINGPTR dstr_p, long n) /* append a decimal integer to a string */ { int d[25]; - int j, k, ls, len; + int j, k ; char sg; /* the sign */ - unsigned char ok; + char load_str[2] ; /* used to load dstring */ k = 0; - len = maxlen (s); if (n < 0) { @@ -547,43 +424,32 @@ nadd (char *s, long n) } if (k == 0) - ok = cadd (s, '0'); - else - { - ls = length (s); - ok = (len - ls) > k; - if (ok) + cadd (dstr_p, '0'); + else { + load_str[1] = 0 ; + if (sg == '-') { - if (sg == '-') - { - s[ls] = sg; - ls++; - } - for (j = k - 1; j >= 0; j--) - { - s[ls] = d[j] + '0'; - ls++; - } - sfix (s, ls, len); + load_str[0] = sg ; + spice_dstring_append( dstr_p, load_str, 1 ) ; } + for (j = k - 1; j >= 0; j--) { + load_str[0] = d[j] + '0'; + spice_dstring_append( dstr_p, load_str, 1 ) ; + } } - if (!ok) - stringbug ("nadd", s, NULL, sg); - - return ok; + return 1 ; } unsigned char -naddll (char *s, long long n) -/* append a decimal integer to a string */ +naddll (SPICE_DSTRINGPTR dstr_p, long long n) +/* append a decimal integer (but a long long) to a string */ { int d[25]; - int j, k, ls, len; + int j, k ; char sg; /* the sign */ - unsigned char ok; + char load_str[2] ; /* used to load dstring */ k = 0; - len = maxlen (s); if (n < 0) { @@ -601,39 +467,29 @@ naddll (char *s, long long n) } if (k == 0) - ok = cadd (s, '0'); - else - { - ls = length (s); - ok = (len - ls) > k; - if (ok) + cadd (dstr_p, '0'); + else { + load_str[1] = 0 ; + if (sg == '-') { - if (sg == '-') - { - s[ls] = sg; - ls++; - } - for (j = k - 1; j >= 0; j--) - { - s[ls] = d[j] + '0'; - ls++; - } - sfix (s, ls, len); + load_str[0] = sg ; + spice_dstring_append( dstr_p, load_str, 1 ) ; } + for (j = k - 1; j >= 0; j--) { + load_str[0] = d[j] + '0'; + spice_dstring_append( dstr_p, load_str, 1 ) ; + } } - if (!ok) - stringbug ("naddll", s, NULL, sg); - - return ok; + return 1 ; } void -stri (long n, char *s) +stri (long n, SPICE_DSTRINGPTR dstr_p) /* convert integer to string */ { - sini (s, maxlen (s)); - nadd (s, n); + spice_dstring_reinit( dstr_p ) ; + nadd (dstr_p, n) ; } void @@ -723,33 +579,32 @@ alfanum (char c) } int -freadstr (FILE * f, char *s, int max) +freadstr (FILE * f, SPICE_DSTRINGPTR dstr_p) /* read a line from a file. - BUG: long lines truncated without warning, ctrl chars are dumped. + was BUG: long lines truncated without warning, ctrl chars are dumped. + Bug no more as we can only run out of memory. Removed max argument. */ { char c; - int i = 0, mxlen = maxlen (s); - - if (mxlen < max) - max = mxlen; + char str_load[2] ; + int len = 0 ; + str_load[0] = 0 ; + str_load[1] = 0 ; + spice_dstring_reinit(dstr_p) ; do { c = fgetc (f); /* tab is the only control char accepted */ - if (((c >= ' ') || (c < 0) || (c == Tab)) && (i < max)) + if (((c >= ' ') || (c < 0) || (c == Tab))) { - s[i] = c; - i++; + str_load[0] = c; + spice_dstring_append( dstr_p, str_load, 1 ) ; } } while (!(feof (f) || (c == '\n'))); - s[i] = 0; - s[i + 1] = Hi (mxlen); - s[i + 2] = Lo (mxlen); - return i; + return len ; } char @@ -833,15 +688,6 @@ new (long sz) } } -char * -newstring (int n) -{ - char *s = (char *) new (n + 4); - - sini (s, n); - return s; -} - /***** elementary math *******/ double @@ -869,14 +715,14 @@ absi (long i) } void -strif (long i, int f, char *s) +strif (long i, int f, SPICE_DSTRINGPTR dstr_p) /* formatting like str(i:f,s) in Turbo Pascal */ { - int j, k, n, max; + int j, k ; char cs; char t[32]; + char load_str[2] ; /* load dstring */ k = 0; - max = maxlen (s); if (i < 0) { @@ -912,22 +758,22 @@ strif (long i, int f, char *s) t[k + j] = t[k - j]; /* mirror image */ t[2 * k + 1] = 0; /* null termination */ - n = 0; + load_str[1] = 0 ; /* not really needed */ + spice_dstring_reinit(dstr_p) ; if ((f > k) && (f < 40)) { /* reasonable format */ for (j = k + 2; j <= f; j++) { - s[n] = ' '; - n++; + load_str[0] = ' '; + spice_dstring_append( dstr_p, load_str, 1 ) ; } } - for (j = 0; j <= k + 1; j++) - s[n + j] = t[k + j]; /* shift t down */ - - k = length (s); - sfix (s, k, max); + for (j = 0; j <= k + 1; j++){ + load_str[0] = t[k + j]; /* shift t down */ + spice_dstring_append( dstr_p, load_str, 1 ) ; + } } unsigned char @@ -1019,20 +865,22 @@ posi (char *sub, char *s, int opt) /* opt=2: position in space separated wordlist for scanners */ int a, b, k, j; unsigned char ok, tstcase; - Str (250, t); + SPICE_DSTRING tstr ; + ok = 0; + spice_dstring_init(&tstr) ; tstcase = (opt == 0); if (opt <= 1) - scopy (t, sub); + scopys (&tstr, sub); else { - cadd (t, ' '); - sadd (t, sub); - cadd (t, ' '); + cadd (&tstr, ' '); + sadd (&tstr, sub); + cadd (&tstr, ' '); } - a = length (t); + a = spice_dstring_length(&tstr) ; b = (int) (length (s) - a); k = 0; j = 1; @@ -1040,7 +888,7 @@ posi (char *sub, char *s, int opt) if (a > 0) /* ;} else { return 0 */ while ((k <= b) && (!ok)) { - ok = match (t, s, a, k, tstcase); /* we must start at k=0 ! */ + ok = match ( spice_dstring_value(&tstr), s, a, k, tstcase); /* we must start at k=0 ! */ k++; if (s[k] == ' ') j++; /* word counter */ ; @@ -1057,7 +905,7 @@ posi (char *sub, char *s, int opt) } int -spos (char *sub, char *s) +spos_(char *sub, char *s) /* equivalent to Turbo Pascal pos(). BUG: counts 1 ... length(s), not from 0 like C */ @@ -1065,9 +913,9 @@ spos (char *sub, char *s) char *ptr; if ((ptr = strstr (s, sub))) - return strlen (s) - strlen (ptr) + 1; + return strlen (s) - strlen (ptr) ; else - return 0; + return -1 ; } @@ -1085,34 +933,44 @@ valr (char *s, double *r) } void -strf (double x, int f1, int f2, char *t) +strf (double x, int f1, int f2, SPICE_DSTRINGPTR dstr_p) /* e-format if f2<0, else f2 digits after the point, total width=f1 */ /* if f1=0, also e-format with f2 digits */ { /* default f1=17, f2=-1 */ - Str (30, fmt); - int n, mlt; - mlt = maxlen (t); - cadd (fmt, '%'); + int dlen ; /* length of digits */ + char *dbuf_p ; /* beginning of sprintf buffer */ + SPICE_DSTRING fmt ; /* format string */ + SPICE_DSTRING dformat ; /* format float */ + + spice_dstring_init(&fmt) ; + spice_dstring_init(&dformat) ; + cadd (&fmt, '%'); if (f1 > 0) { - nadd (fmt, f1); /* f1 is the total width */ + nadd (&fmt, f1); /* f1 is the total width */ if (f2 < 0) - sadd (fmt, "lE"); /* exponent format */ + sadd (&fmt, "lE"); /* exponent format */ else { - cadd (fmt, '.'); - nadd (fmt, f2); - sadd (fmt, "lg"); + cadd (&fmt, '.'); + nadd (&fmt, f2); + sadd (&fmt, "lg"); } } else { - cadd (fmt, '.'); - nadd (fmt, absi (f2 - 6)); /* note the 6 surplus positions */ - cadd (fmt, 'e'); + cadd (&fmt, '.'); + nadd (&fmt, absi (f2 - 6)); /* note the 6 surplus positions */ + cadd (&fmt, 'e'); } - n = sprintf (t, fmt, x); - sfix (t, n, mlt); + + dlen = 2 * (f1 + f2) + 1 ; /* be conservative */ + dbuf_p = spice_dstring_setlength(&dformat, dlen) ; + sprintf (dbuf_p, spice_dstring_value(&fmt), x); + scopys( dstr_p, dbuf_p ) ; + + spice_dstring_free(&fmt) ; + spice_dstring_free(&dformat) ; } double @@ -1261,3 +1119,328 @@ intp (double x) /* integral part */ } #endif + +/* ----------------------------------------------------------------- + * Dynamic string utilities. + * ----------------------------------------------------------------- */ + +/* + *---------------------------------------------------------------------- + * + * spice_dstring_init -- + * + * Initializes a dynamic string, discarding any previous contents + * of the string (spice_dstring_free should have been called already + * if the dynamic string was previously in use). + * + * Results: + * None. + * + * Side effects: + * The dynamic string is initialized to be empty. + * + *---------------------------------------------------------------------- + */ + +void spice_dstring_init(SPICE_DSTRINGPTR dsPtr) +{ + dsPtr->string = dsPtr->staticSpace ; + dsPtr->length = 0 ; + dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE ; + dsPtr->staticSpace[0] = EOS; +} /* end spice_dstring_init() */ + +/* + *---------------------------------------------------------------------- + * + * spice_dstring_append -- + * + * Append more characters to the current value of a dynamic string. + * + * Results: + * The return value is a pointer to the dynamic string's new value. + * + * Side effects: + * Length bytes from string (or all of string if length is less + * than zero) are added to the current value of the string. Memory + * gets reallocated if needed to accomodate the string's new size. + * + * Notes: char *string; String to append. If length is -1 then + * this must be null-terminated. + * INT length; Number of characters from string to append. + * If < 0, then append all of string, up to null at end. + * + *---------------------------------------------------------------------- + */ +char *spice_dstring_append(SPICE_DSTRINGPTR dsPtr,char *string,int length) +{ + int newSize ; /* needed size */ + char *newString ; /* newly allocated string buffer */ + char *dst ; /* destination */ + char *end ; /* end of string */ + + if( length < 0){ + length = strlen(string) ; + } + newSize = length + dsPtr->length ; + + /* ----------------------------------------------------------------- + * Allocate a larger buffer for the string if the current one isn't + * large enough. Allocate extra space in the new buffer so that there + * will be room to grow before we have to allocate again. + ----------------------------------------------------------------- */ + if (newSize >= dsPtr->spaceAvl) { + dsPtr->spaceAvl = 2 * newSize ; + newString = new( dsPtr->spaceAvl * sizeof(char) ) ; + memcpy((void *) newString, (void *) dsPtr->string, (size_t) dsPtr->length) ; + if (dsPtr->string != dsPtr->staticSpace) { + dispose(dsPtr->string) ; + } + dsPtr->string = newString; + } + + /* ----------------------------------------------------------------- + * Copy the new string into the buffer at the end of the old + * one. + ----------------------------------------------------------------- */ + for( dst = dsPtr->string + dsPtr->length, end = string+length; + string < end; string++, dst++) { + *dst = *string ; + } + *dst = EOS ; + dsPtr->length += length ; + + return(dsPtr->string) ; + +} /* end spice_dstring_append() */ + + +static int spice_format_length( va_list args, char *fmt ) +{ + int i ; /* integer */ + int len ; /* length of format */ + int size_format ; /* width of field */ + int found_special ; /* look for special characters */ + char *s ; /* string */ + char c ; /* character */ + + /* ----------------------------------------------------------------- + * First find length of buffer. + ----------------------------------------------------------------- */ + len = 0 ; + while(fmt && *fmt){ + if( *fmt == '%' ){ + fmt++ ; + if( *fmt == '%' ){ + len++ ; + } else { + /* ----------------------------------------------------------------- + * We have a real formatting character, loop until we get a special + * character. + ----------------------------------------------------------------- */ + if( *fmt == '.' || *fmt == '-' ){ + fmt++ ; /* skip over these characters */ + } + size_format = atoi(fmt) ; + if( size_format > 0 ){ + len += size_format ; + } + found_special = FALSE ; + for( ; fmt && *fmt ; fmt++ ){ + switch( *fmt ){ + case 's': + s = va_arg(args, char *) ; + if( s ){ + len += strlen(s) ; + } + found_special = TRUE ; + break ; + case 'i': + case 'd': + case 'o': + case 'x': + case 'X': + case 'u': + i = va_arg(args, int) ; + len += 10 ; + found_special = TRUE ; + break ; + case 'c': + c = va_arg(args, int) ; + len++ ; + found_special = TRUE ; + break ; + case 'f': + case 'e': + case 'F': + case 'g': + case 'G': + c = va_arg(args, double) ; + len += 35 ; + found_special = TRUE ; + break ; + default: + ; + } /* end switch() */ + + if( found_special ){ + break ; + } + } + } + } else { + len++ ; + } + fmt++ ; + } /* end while() */ + va_end(args) ; + + return(len) ; + +} /* end Ymessage_format_length() */ + + +char *spice_dstring_print( SPICE_DSTRINGPTR dsPtr,char *format, ... ) +{ + va_list args ; + int format_len ; /* length of format */ + int length ; /* new length */ + int orig_length ; /* original length of buffer */ + char *buffer ; /* proper length of buffer */ + + /* ----------------------------------------------------------------- + * First get the length of the buffer needed. + ----------------------------------------------------------------- */ + va_start( args, format ) ; + format_len = spice_format_length(args,format) ; + + /* ----------------------------------------------------------------- + * Next allocate the proper buffer size. + ----------------------------------------------------------------- */ + orig_length = dsPtr->length ; + length = orig_length + format_len + 1 ; + buffer = spice_dstring_setlength( dsPtr, length) ; + + /* ----------------------------------------------------------------- + * Convert the format. + ----------------------------------------------------------------- */ + va_start( args, format ) ; + if( format ){ + vsprintf( buffer + orig_length, format, args ) ; + dsPtr->length = strlen( buffer ) ; + } else { + buffer = NULL ; + } + va_end(args) ; + return( buffer ) ; + +} /* end spice_dstring_print() */ + +/* + *---------------------------------------------------------------------- + * + * _spice_dstring_setlength -- + * + * Change the length of a dynamic string. This can cause the + * string to either grow or shrink, depending on the value of + * length. + * + * Results: + * Returns the current string buffer. + * + * Side effects: + * The length of dsPtr is changed to length but a null byte is not + * stored at that position in the string. Use spice_dstring_setlength + * for that function. If length is larger + * than the space allocated for dsPtr, then a panic occurs. + * + *---------------------------------------------------------------------- + */ + +char *_spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) +{ + char *newString ; + + if (length < 0) { + length = 0 ; + } + if (length >= dsPtr->spaceAvl) { + + dsPtr->spaceAvl = length+1; + newString = new( dsPtr->spaceAvl * sizeof(char) ) ; + /* ----------------------------------------------------------------- + * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string + * to a larger buffer, since there may be embedded NULLs in the + * string in some cases. + ----------------------------------------------------------------- */ + memcpy((void *) newString, (void *) dsPtr->string, (size_t) dsPtr->length) ; + if( dsPtr->string != dsPtr->staticSpace ) { + dispose(dsPtr->string) ; + } + dsPtr->string = newString ; + } + dsPtr->length = length ; + return(dsPtr->string) ; + +} /* end _spice_dstring_setlength() */ + + +/* + *---------------------------------------------------------------------- + * + * spice_dstring_setlength -- + * + * Change the length of a dynamic string. This can cause the + * string to either grow or shrink, depending on the value of + * length. + * + * Results: + * Returns the current string buffer. + * + * Side effects: + * The length of dsPtr is changed to length and a null byte is + * stored at that position in the string. If length is larger + * than the space allocated for dsPtr, then a panic occurs. + * + *---------------------------------------------------------------------- + */ + +char *spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) +{ + char *str_p ; /* newly create string */ + + str_p = _spice_dstring_setlength( dsPtr,length) ; + str_p[length] = EOS ; + return( str_p ) ; + +} /* end spice_dstring_setlength() */ + +/* + *---------------------------------------------------------------------- + * + * spice_dstring_free -- + * + * Frees up any memory allocated for the dynamic string and + * reinitializes the string to an empty state. + * + * Results: + * None. + * + * Side effects: + * The previous contents of the dynamic string are lost, and + * the new value is an empty string. + * + *---------------------------------------------------------------------- + */ + +void spice_dstring_free(SPICE_DSTRINGPTR dsPtr) +{ + if (dsPtr->string != dsPtr->staticSpace) { + dispose(dsPtr->string) ; + } + dsPtr->string = dsPtr->staticSpace ; + dsPtr->length = 0 ; + dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE; + dsPtr->staticSpace[0] = EOS ; + +} /* end spice_dstring_free() */ diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h index 38fb7851e..e5480662f 100644 --- a/src/frontend/numparam/numparam.h +++ b/src/frontend/numparam/numparam.h @@ -6,6 +6,7 @@ /*** interface to spice frontend subckt.c ***/ #include "numpaif.h" +#include "hash.h" /***** numparam internals ********/ @@ -27,8 +28,6 @@ typedef enum {Defd=15} _nDefd; /* serial numb. of 'defined' keyword. The others macros in .model lines. Will add 100k of memory compared to previous 25004*/ //typedef enum {Llen=40000} _nLlen; -typedef char str50 [54]; -typedef char str80 [84]; //typedef enum {Maxline=70000} _nMaxline; /* Size of initial unexpanded circuit code */ //typedef enum {Maxckt=40000} _nMaxckt; /* Size of expanded circuit code */ @@ -36,13 +35,17 @@ typedef char str80 [84]; typedef char * auxtable; /* dummy */ +/* ----------------------------------------------------------------- + * I believe the entry should be a union of type but I need more info. + * ----------------------------------------------------------------- */ typedef struct _tentry { char tp; /* type: I)nt R)eal S)tring F)unction M)acro P)ointer */ - char nom[100]; + char *symbol ; int level; /* subckt nesting level */ double vl; /* float value if defined */ unsigned short ivl; /*int value or string buffer index*/ char * sbbase; /* string buffer base address if any */ + struct _tentry *pointer ; /* pointer chain */ } entry; typedef struct _tfumas { /*function,macro,string*/ @@ -51,19 +54,21 @@ typedef struct _tfumas { /*function,macro,string*/ typedef struct _ttdico { /* the input scanner data structure */ - str80 srcfile; /* last piece of source file name */ + SPICE_DSTRING srcfile; /* last piece of source file name */ + SPICE_DSTRING option; /* one-character translator options */ + SPICE_DSTRING lookup_buf ; /* useful temp buffer for quick symbol lookup */ int srcline; int oldline; int errcount; -// entry dat[Maxdico+1]; - entry* dyndat; - int nbd; /* number of data entries */ + int num_symbols ; /* number of symbols in entry array */ + entry **symbol_array ; /* symbol entries in array format for stack ops */ + NGHASHPTR symbol_table ; /* hash table of symbols for quick lookup */ + int nbd; /* number of data entries */ fumas fms[101]; int nfms; /* number of functions & macros */ int stack[20]; char *inst_name[20]; int tos; /* top of stack index for symbol mark/release mechanics */ - str80 option; /* one-character translator options */ auxtable nodetab; // char * refptr[Maxline]; /* pointers to source code lines */ char **dynrefptr; @@ -75,11 +80,11 @@ typedef struct _ttdico { void initdico(tdico * dico); int donedico(tdico * dico); unsigned char defsubckt( tdico *dico, char * s, int w, char categ); -int findsubckt( tdico *dico, char * s, char * subname); +int findsubckt( tdico *dico, char * s, SPICE_DSTRINGPTR subname); unsigned char nupa_substitute( tdico *dico, char * s, char * r, unsigned char err); unsigned char nupa_assignment( tdico *dico, char * s, char mode); unsigned char nupa_subcktcall( tdico *dico, char * s, char * x, unsigned char err); void nupa_subcktexit( tdico *dico); tdico * nupa_fetchinstance(void); char getidtype( tdico *d, char * s); -int attrib( tdico *dico, char * t, char op ); +entry *attrib( tdico *dico, char * t, char op ); diff --git a/src/frontend/numparam/spicenum.c b/src/frontend/numparam/spicenum.c index c2789e837..e3b30646d 100644 --- a/src/frontend/numparam/spicenum.c +++ b/src/frontend/numparam/spicenum.c @@ -32,7 +32,7 @@ Todo: extern void txfree (void *ptr); char *nupa_inst_name; -static tdico *inst_dico; +static tdico *inst_dicoS ; /* number of parameter substitutions, available only after the substitution */ extern long dynsubst; /* spicenum.c:144 */ @@ -41,7 +41,7 @@ extern long dynsubst; /* spicenum.c:144 */ extern int dynmaxline; /* inpcom.c:1529 */ /* max. line length in input deck */ -unsigned int dynLlen; /* inpcom.c:1531 */ +/* unsigned int dynLlen; No longer needed with d strings */ /* inpcom.c:1531 */ /* Uncomment this line to allow debug tracing */ /* #define TRACE_NUMPARAMS */ @@ -71,34 +71,43 @@ static long placeholder = 0; static void -stripsomespace (char *s, unsigned char incontrol) +stripsomespace (SPICE_DSTRINGPTR dstr_p, unsigned char incontrol) { /* if s starts with one of some markers, strip leading space */ - Str (12, markers); int i, ls; - scopy (markers, "*.&+#$"); + char *sstr ; /* string contained in s */ + SPICE_DSTRING markers ; + + spice_dstring_init( &markers ) ; + scopys( &markers, "*.&+#$") ; if (!incontrol) - sadd (markers, "xX"); + sadd ( &markers, "xX"); - ls = length (s); + sstr = spice_dstring_value(dstr_p) ; + ls = spice_dstring_length (dstr_p); i = 0; - while ((i < ls) && (s[i] <= ' ')) + while ((i < ls) && (sstr[i] <= ' ')) i++; - if ((i > 0) && (i < ls) && (cpos (s[i], markers) > 0)) - pscopy (s, s, i + 1, ls); + if ((i > 0) && (i < ls) && (cpos (sstr[i], spice_dstring_value(&markers)) >= 0)) + pscopy (dstr_p, sstr, i, ls); } static int -stripbraces (char *s) +stripbraces (SPICE_DSTRINGPTR dstr_p) /* puts the funny placeholders. returns the number of {...} substitutions */ { int n, i, nest, ls, j; - Strbig (dynLlen, t); + char *s ; /* value of dynamic string */ + char *t_p ; /* value of t dynamic string */ + SPICE_DSTRING tstr ; /* temporary dynamic string */ + n = 0; - ls = length (s); + spice_dstring_init( &tstr ) ; + s = spice_dstring_value( dstr_p ) ; + ls = spice_dstring_length (dstr_p); i = 0; while (i < ls) @@ -117,47 +126,54 @@ stripbraces (char *s) nest--; j++; } - pscopy (t, s, 1, i); + pscopy (&tstr, s, 0, i); placeholder++; - if (t[i - 1] > ' ') - cadd (t, ' '); + t_p = spice_dstring_value(&tstr) ; - cadd (t, ' '); - naddll (t, PlaceHold + placeholder); /* placeholder has 15 digits */ - cadd (t, ' '); + if (t_p[i - 1] > ' ') + cadd (&tstr, ' '); + + cadd ( &tstr, ' '); + naddll( &tstr, PlaceHold + placeholder); /* placeholder has 15 digits */ + cadd ( &tstr, ' '); if (s[j] >= ' ') - cadd (t, ' '); + cadd ( &tstr, ' '); - i = length (t); - pscopy (s, s, j + 1, ls); - sadd (t, s); - scopy (s, t); + i = spice_dstring_length (&tstr); + pscopy (dstr_p, s, j, ls); + sadd ( &tstr, s); + scopyd ( dstr_p, &tstr); + s = spice_dstring_value( dstr_p ) ; + ls = spice_dstring_length( dstr_p ) ; } else i++; - ls = length (s); } dynsubst = placeholder; - Strrem(t); + spice_dstring_free(&tstr); return n; } static int -findsubname (tdico * dico, char *s) +findsubname (tdico * dico, SPICE_DSTRINGPTR dstr_p) /* truncate the parameterized subckt call to regular old Spice */ /* scan a string from the end, skipping non-idents and {expressions} */ /* then truncate s after the last subckt(?) identifier */ { - Str (80, name); + SPICE_DSTRING name ; /* extract a name */ + char *s ; /* current dstring */ int h, j, k, nest, ls; unsigned char found; h = 0; - ls = length (s); - k = ls; + + ls = spice_dstring_length (dstr_p) ; + s = spice_dstring_value (dstr_p) ; + k = ls - 1 ; /* now a C - string */ found = 0; + spice_dstring_init( &name ) ; while ((k >= 0) && (!found)) { /* skip space, then non-space */ @@ -191,32 +207,37 @@ findsubname (tdico * dico, char *s) found = (k >= 0) && alfanum (s[k + 1]); /* suppose an identifier */ if (found) { /* check for known subckt name */ - scopy (name, ""); + spice_dstring_reinit( &name ) ; j = k + 1; while (alfanum (s[j])) { - cadd (name, upcase (s[j])); + cadd ( &name, upcase (s[j])); j++; } - found = (getidtype (dico, name) == 'U'); + found = (getidtype (dico, spice_dstring_value(&name) ) == 'U'); } } if (found && (h < ls)) - pscopy (s, s, 1, h); + pscopy (dstr_p, s, 0, h); return h; } static void -modernizeex (char *s) +modernizeex (SPICE_DSTRINGPTR dstr_p) /* old style expressions &(..) and &id --> new style with braces. */ { int i, state, ls; char c, d; - Strbig (dynLlen, t); + char *s ; /* current string */ + SPICE_DSTRING t ; /* temporary dyna string */ + i = 0; state = 0; - ls = length (s); + ls = spice_dstring_length (dstr_p); + s = spice_dstring_value( dstr_p ) ; + spice_dstring_init( &t ) ; + while (i < ls) { @@ -232,11 +253,11 @@ modernizeex (char *s) } else if (alfa (d)) { - cadd (t, '{'); + cadd (&t, '{'); i++; while (alfanum (s[i])) { - cadd (t, s[i]); + cadd (&t, s[i]); i++; } c = '}'; @@ -255,15 +276,16 @@ modernizeex (char *s) } - cadd (t, c); + cadd (&t, c); i++; } - scopy (s, t); - Strrem(t); + scopyd (dstr_p, &t); + spice_dstring_free(&t) ; } static char -transform (tdico * dico, char *s, unsigned char nostripping, char *u) +transform (tdico * dico, SPICE_DSTRINGPTR dstr_p, unsigned char nostripping, + SPICE_DSTRINGPTR u_p) /* line s is categorized and crippled down to basic Spice * returns in u control word following dot, if any * @@ -288,21 +310,27 @@ transform (tdico * dico, char *s, unsigned char nostripping, char *u) * 'B' netlist (or .model ?) line that had Braces killed */ { - char category; int i, k, a, n; - Strbig (dynLlen, t); - stripsomespace (s, nostripping); - modernizeex (s); /* required for stripbraces count */ - scopy (u, ""); + char *s ; /* dstring value of dstr_p */ + char *t ; /* dstring value of tstr */ + char category; + SPICE_DSTRING tstr ; /* temporary string */ + spice_dstring_init(&tstr) ; + spice_dstring_reinit(u_p) ; + stripsomespace (dstr_p, nostripping); + modernizeex (dstr_p); /* required for stripbraces count */ + + s = spice_dstring_value(dstr_p) ; if (s[0] == '.') { /* check Pspice parameter format */ - scopy_up (t, s); + scopy_up (&tstr, spice_dstring_value(dstr_p) ) ; k = 1; + t = spice_dstring_value(&tstr) ; while (t[k] > ' ') { - cadd (u, t[k]); + cadd (u_p, t[k]); k++; } @@ -313,9 +341,9 @@ transform (tdico * dico, char *s, unsigned char nostripping, char *u) } else if (ci_prefix (".SUBCKT", t) == 1) { /* split off any "params" tail */ - a = spos ("PARAMS:", t); - if (a > 0) - pscopy (s, s, 1, a - 1); + a = spos_ ("PARAMS:", t); + if (a >= 0) + pscopy (dstr_p, s, 0, a ); category = 'S'; } else if (ci_prefix (".CONTROL", t) == 1) @@ -327,7 +355,7 @@ transform (tdico * dico, char *s, unsigned char nostripping, char *u) else { category = '.'; - n = stripbraces (s); + n = stripbraces (dstr_p); if (n > 0) category = 'B'; /* priority category ! */ } @@ -339,14 +367,14 @@ transform (tdico * dico, char *s, unsigned char nostripping, char *u) } else if (upcase (s[0]) == 'X') { /* strip actual parameters */ - i = findsubname (dico, s); /* i= index following last identifier in s */ + i = findsubname (dico, dstr_p) ; /* i= index following last identifier in s */ category = 'X'; } else if (s[0] == '+') /* continuation line */ category = '+'; - else if (cpos (s[0], "*$#") <= 0) + else if (cpos (s[0], "*$#") < 0) { /* not a comment line! */ - n = stripbraces (s); + n = stripbraces (dstr_p); if (n > 0) category = 'B'; /* line that uses braces */ else @@ -355,7 +383,7 @@ transform (tdico * dico, char *s, unsigned char nostripping, char *u) else category = '*'; - Strrem(t); + spice_dstring_free(&tstr) ; return category; } @@ -363,21 +391,21 @@ transform (tdico * dico, char *s, unsigned char nostripping, char *u) /* some day, all these nasty globals will go into the tdico structure and everything will get hidden behind some "handle" ... + For the time being we will rename this variable to end in S so we know + they are statics within this file for easier reading of the code. */ -static int linecount = 0; /* global: number of lines received via nupa_copy */ -static int evalcount = 0; /* number of lines through nupa_eval() */ -static int nblog = 0; /* serial number of (debug) logfile */ -static unsigned char inexpansion = 0; /* flag subckt expansion phase */ -static unsigned char incontrol = 0; /* flag control code sections */ -static unsigned char dologfile = 0; /* for debugging */ -static unsigned char firstsignal = 1; -static FILE *logfile = NULL; -static tdico *dico = NULL; +static int linecountS = 0; /* global: number of lines received via nupa_copy */ +static int evalcountS = 0; /* number of lines through nupa_eval() */ +static int nblogS = 0; /* serial number of (debug) logfile */ +static unsigned char inexpansionS = 0; /* flag subckt expansion phase */ +static unsigned char incontrolS = 0; /* flag control code sections */ +static unsigned char dologfileS = 0; /* for debugging */ +static unsigned char firstsignalS = 1; +static FILE *logfileS = NULL; +static tdico *dicoS = NULL; /* already part of dico : */ -/* Str(80, srcfile); source file */ - /* Open ouput to a log file. takes no action if logging is disabled. @@ -386,30 +414,34 @@ static tdico *dico = NULL; static void putlogfile (char c, int num, char *t) { - Str (20, fname); - Strbig (dynLlen, u); - if (dologfile) + SPICE_DSTRING fname ; /* file name */ + SPICE_DSTRING u ; /* temp dynamic variable */ + + spice_dstring_init( &fname ) ; + spice_dstring_init( &u ) ; + if (dologfileS) { - if ((logfile == NULL)) + if ((logfileS == NULL)) { - scopy (fname, "logfile."); - nblog++; - nadd (fname, nblog); - logfile = fopen (fname, "w"); + scopys(&fname, "logfile.") ; + nblogS++; + nadd (&fname, nblogS) ; + logfileS = fopen ( spice_dstring_value(&fname), "w"); } - if ((logfile != NULL)) + if ((logfileS != NULL)) { - cadd (u, c); - nadd (u, num); - cadd (u, ':'); - cadd (u, ' '); - sadd (u, t); - cadd (u, '\n'); - fputs (u, logfile); + cadd (&u, c); + nadd (&u, num); + cadd (&u, ':'); + cadd (&u, ' '); + sadd (&u, t); + cadd (&u, '\n'); + fputs ( spice_dstring_value(&u), logfileS); } } - Strrem(u); + spice_dstring_free(&u) ; + spice_dstring_free(&fname) ; } static void @@ -417,42 +449,44 @@ nupa_init (char *srcfile) { int i; /* init the symbol table and so on, before the first nupa_copy. */ - evalcount = 0; - linecount = 0; - incontrol = 0; + evalcountS = 0; + linecountS = 0; + incontrolS = 0; placeholder = 0; - dico = (tdico *)new(sizeof(tdico)); - inst_dico = (tdico *)new(sizeof(tdico)); - initdico (dico); - initdico (inst_dico); + dicoS = (tdico *)new(sizeof(tdico)); + inst_dicoS = (tdico *)new(sizeof(tdico)); + initdico (dicoS); + initdico (inst_dicoS); - dico->dynrefptr = (char**)tmalloc((dynmaxline + 1)*sizeof(char*)); - dico->dyncategory = (char*)tmalloc((dynmaxline + 1)*sizeof(char)); + dicoS->dynrefptr = (char**)tmalloc((dynmaxline + 1)*sizeof(char*)); + dicoS->dyncategory = (char*)tmalloc((dynmaxline + 1)*sizeof(char)); for (i = 0; i <= dynmaxline; i++) { - dico->dynrefptr[i] = NULL; - dico->dyncategory[i] = '?'; + dicoS->dynrefptr[i] = NULL; + dicoS->dyncategory[i] = '?'; } if (srcfile != NULL) - scopy (dico->srcfile, srcfile); + scopys(&dicoS->srcfile, srcfile ) ; } static void nupa_done (void) { /* int i; not needed so far, see below */ - Str (80, rep); + char *reply ; /* user reply */ + SPICE_DSTRING rep ; /* dynamic report */ int dictsize, nerrors; - if (logfile != NULL) + spice_dstring_init(&rep) ; + if (logfileS != NULL) { - fclose (logfile); - logfile = NULL; + fclose (logfileS); + logfileS = NULL; } - nerrors = dico->errcount; - dictsize = donedico (dico); + nerrors = dicoS->errcount; + dictsize = donedico (dicoS); /* We cannot remove dico here because numparam is usedby the .measure statement, which is invoked only after the simulation has finished */ @@ -472,26 +506,28 @@ nupa_done (void) if (nerrors) { /* debug: ask if spice run really wanted */ - scopy (rep, " Copies="); - nadd (rep, linecount); - sadd (rep, " Evals="); - nadd (rep, evalcount); - sadd (rep, " Placeholders="); - nadd (rep, placeholder); - sadd (rep, " Symbols="); - nadd (rep, dictsize); - sadd (rep, " Errors="); - nadd (rep, nerrors); - cadd (rep, '\n'); - ws (rep); + sadd (&rep, " Copies="); + nadd (&rep, linecountS); + sadd (&rep, " Evals="); + nadd (&rep, evalcountS); + sadd (&rep, " Placeholders="); + nadd (&rep, placeholder); + sadd (&rep, " Symbols="); + nadd (&rep, dictsize); + sadd (&rep, " Errors="); + nadd (&rep, nerrors); + cadd (&rep, '\n'); + ws ( spice_dstring_value(&rep) ) ; ws ("Numparam expansion errors: Run Spice anyway? y/n ? \n"); - rs (rep); - if (upcase (rep[0]) != 'Y') + spice_dstring_reinit(&rep) ; + rs (&rep); + reply = spice_dstring_value(&rep) ; + if (upcase (reply[0]) != 'Y') controlled_exit(EXIT_FAILURE); } - linecount = 0; - evalcount = 0; + linecountS = 0; + evalcountS = 0; placeholder = 0; /* release symbol table data */ ; } @@ -502,110 +538,126 @@ nupa_scan (char *s, int linenum, int is_subckt) { if (is_subckt) - defsubckt (dico, s, linenum, 'U'); + defsubckt (dicoS, s, linenum, 'U'); else - defsubckt (dico, s, linenum, 'O'); + defsubckt (dicoS, s, linenum, 'O'); } -static char * -lower_str (char *str) -{ - char *s; - - for (s = str; *s; s++) - *s = tolower (*s); - - return str; -} - -static char * -upper_str (char *str) -{ - char *s; - - for (s = str; *s; s++) - *s = toupper (*s); - - return str; -} - +/* ----------------------------------------------------------------- + * Dump the contents of the symbol table. + * ----------------------------------------------------------------- */ void nupa_list_params (FILE * cp_out) { - char *name; - int i; + char *name; /* current symbol */ + entry *entry_p ; /* current entry */ + tdico *dico_p ; /* local copy for speed */ + NGHASHITER iter ; /* hash iterator - thread safe */ + dico_p = dicoS ; fprintf (cp_out, "\n\n"); - for (i = 1; i <= dico->nbd; i++) + for (entry_p = nghash_enumerateRE(dico_p->symbol_table,NGHASH_FIRST(&iter)) ; + entry_p ; + entry_p = nghash_enumerateRE(dico_p->symbol_table,&iter)) { - if (dico->dyndat[i].tp == 'R') + if (entry_p->tp == 'R') { - name = lower_str (strdup (dico->dyndat[i].nom)); - fprintf (cp_out, " ---> %s = %g\n", name, dico->dyndat[i].vl); - txfree (name); + spice_dstring_reinit( & dico_p->lookup_buf ) ; + scopy_lower( & dico_p->lookup_buf, entry_p->symbol ) ; + name = spice_dstring_value( & dico_p->lookup_buf ) ; + fprintf (cp_out, " ---> %s = %g\n", name, entry_p->vl) ; + spice_dstring_free( & dico_p->lookup_buf ) ; } } } +/* ----------------------------------------------------------------- + * Lookup a parameter value in the symbol table. + * ----------------------------------------------------------------- */ double nupa_get_param (char *param_name, int *found) { - char *name = upper_str (strdup (param_name)); - double result = 0; - int i; + char *up_name; /* current parameter upper case */ + entry *entry_p ; /* current entry */ + tdico *dico_p ; /* local copy for speed */ + double result = 0; /* parameter value */ + + dico_p = dicoS ; + spice_dstring_reinit( & dico_p->lookup_buf ) ; + scopy_up( & dico_p->lookup_buf, param_name ) ; + up_name = spice_dstring_value( & dico_p->lookup_buf ) ; *found = 0; - - for (i = 1; i <= dico->nbd + 1; i++) - { - if (strcmp (dico->dyndat[i].nom, name) == 0) - { - result = dico->dyndat[i].vl; - *found = 1; - break; - } + entry_p = nghash_find( dico_p->symbol_table, up_name ) ; + if( entry_p ){ + result = entry_p->vl ; + *found = 1; } - - txfree (name); + spice_dstring_free( & dico_p->lookup_buf ) ; return result; } void nupa_add_param (char *param_name, double value) { - char *up_name = upper_str (strdup (param_name)); - int i = attrib (dico, up_name, 'N'); + char *up_name; /* current parameter upper case */ + entry *entry_p ; /* current entry */ + tdico *dico_p ; /* local copy for speed */ - dico->dyndat[i].vl = value; - dico->dyndat[i].tp = 'R'; - dico->dyndat[i].ivl = 0; - dico->dyndat[i].sbbase = NULL; - txfree (up_name); + dico_p = dicoS ; + /* ----------------------------------------------------------------- + * We use a dynamic string here because most of the time we will + * be using short names and no memory allocation will occur. + * ----------------------------------------------------------------- */ + spice_dstring_reinit( & dico_p->lookup_buf ) ; + scopy_up( & dico_p->lookup_buf, param_name ) ; + up_name = spice_dstring_value( & dico_p->lookup_buf ) ; + + entry_p = attrib (dicoS, up_name, 'N'); + if( entry_p ){ + entry_p->vl = value; + entry_p->tp = 'R'; + entry_p->ivl = 0; + entry_p->sbbase = NULL; + } + spice_dstring_free( & dico_p->lookup_buf ) ; } void nupa_add_inst_param (char *param_name, double value) { - char *up_name = upper_str (strdup (param_name)); - int i = attrib (inst_dico, up_name, 'N'); + char *up_name; /* current parameter upper case */ + entry *entry_p ; /* current entry */ + tdico *dico_p ; /* local copy for speed */ - inst_dico->dyndat[i].vl = value; - inst_dico->dyndat[i].tp = 'R'; - inst_dico->dyndat[i].ivl = 0; - inst_dico->dyndat[i].sbbase = NULL; + dico_p = inst_dicoS ; + spice_dstring_reinit( & dico_p->lookup_buf ) ; + scopy_up( & dico_p->lookup_buf, param_name ) ; + up_name = spice_dstring_value( & dico_p->lookup_buf ) ; - - txfree (up_name); + entry_p = attrib (dicoS, up_name, 'N'); + if( entry_p ){ + entry_p->vl = value; + entry_p->tp = 'R'; + entry_p->ivl = 0; + entry_p->sbbase = NULL; + } + spice_dstring_free( & dico_p->lookup_buf ) ; } void nupa_copy_inst_dico () { - int i; + tdico *idico_p ; /* local copy for speed */ + entry *entry_p ; /* current entry */ + NGHASHITER iter ; /* hash iterator - thread safe */ - for (i = 1; i <= inst_dico->nbd; i++) - nupa_add_param (inst_dico->dyndat[i].nom, inst_dico->dyndat[i].vl); + idico_p = inst_dicoS ; + for (entry_p = nghash_enumerateRE(idico_p->symbol_table,NGHASH_FIRST(&iter)) ; + entry_p ; + entry_p = nghash_enumerateRE(idico_p->symbol_table,&iter)) + nupa_add_param ( entry_p->symbol, entry_p->vl) ; } char * @@ -626,39 +678,43 @@ nupa_copy (char *s, int linenum) char *t; int ls; char c, d; - Strdbig (dynLlen, u, keywd); + SPICE_DSTRING u ; + SPICE_DSTRING keywd ; + + spice_dstring_init(&u) ; + spice_dstring_init(&keywd) ; ls = length (s); while ((ls > 0) && (s[ls - 1] <= ' ')) ls--; - pscopy (u, s, 1, ls); /* strip trailing space, CrLf and so on */ - dico->srcline = linenum; + pscopy (&u, s, 0, ls); /* strip trailing space, CrLf and so on */ + dicoS->srcline = linenum; - if ((!inexpansion) && (linenum >= 0) && (linenum <= dynmaxline)) + if ((!inexpansionS) && (linenum >= 0) && (linenum <= dynmaxline)) { - linecount++; - dico->dynrefptr[linenum] = s; - c = transform (dico, u, incontrol, keywd); + linecountS++; + dicoS->dynrefptr[linenum] = s; + c = transform (dicoS, &u, incontrolS, &keywd); if (c == 'C') - incontrol = 1; + incontrolS = 1; else if (c == 'E') - incontrol = 0; + incontrolS = 0; - if (incontrol) + if (incontrolS) c = 'C'; /* force it */ - d = dico->dyncategory[linenum]; /* warning if already some strategic line! */ + d = dicoS->dyncategory[linenum]; /* warning if already some strategic line! */ if ((d == 'P') || (d == 'S') || (d == 'X')) fprintf (stderr, " Numparam warning: overwriting P,S or X line (linenum == %d).\n", linenum); - dico->dyncategory[linenum] = c; + dicoS->dyncategory[linenum] = c; } /* keep a local copy and mangle the string */ - ls = length (u); - t = strdup (u); + ls = spice_dstring_length (&u); + t = strdup ( spice_dstring_value(&u) ); if (t == NULL) { @@ -667,12 +723,12 @@ nupa_copy (char *s, int linenum) } else { - if (!inexpansion) + if (!inexpansionS) { - putlogfile (dico->dyncategory[linenum], linenum, t); + putlogfile (dicoS->dyncategory[linenum], linenum, t); }; } - Strdrem(u, keywd); + spice_dstring_free(&u) ; return t; } @@ -688,12 +744,13 @@ nupa_eval (char *s, int linenum, int orig_linenum) int idef; /* subckt definition line */ char c, keep, *ptr; unsigned int i; - Str (80, subname); + SPICE_DSTRING subname ; /* dynamic string for subcircuit name */ unsigned char err = 1; - dico->srcline = linenum; - dico->oldline = orig_linenum; - c = dico->dyncategory[linenum]; + spice_dstring_init(&subname) ; + dicoS->srcline = linenum; + dicoS->oldline = orig_linenum; + c = dicoS->dyncategory[linenum]; #ifdef TRACE_NUMPARAMS fprintf (stderr, "** SJB - in nupa_eval()\n"); fprintf (stderr, "** SJB - processing line %3d: %s\n", linenum, s); @@ -701,10 +758,10 @@ nupa_eval (char *s, int linenum, int orig_linenum) #endif /* TRACE_NUMPARAMS */ if (c == 'P') { /* evaluate parameters */ // err = nupa_substitute (dico, dico->dynrefptr[linenum], s, 0); - nupa_assignment (dico, dico->dynrefptr[linenum], 'N'); + nupa_assignment (dicoS, dicoS->dynrefptr[linenum], 'N'); } else if (c == 'B') /* substitute braces line */ - err = nupa_substitute (dico, dico->dynrefptr[linenum], s, 0); + err = nupa_substitute (dicoS, dicoS->dynrefptr[linenum], s, 0); else if (c == 'X') { /* compute args of subcircuit, if required */ ptr = s; @@ -719,17 +776,17 @@ nupa_eval (char *s, int linenum, int orig_linenum) for (i = 0; i < strlen (nupa_inst_name); i++) nupa_inst_name[i] = toupper (nupa_inst_name[i]); - idef = findsubckt (dico, s, subname); + idef = findsubckt (dicoS, s, &subname); if (idef > 0) - nupa_subcktcall (dico, dico->dynrefptr[idef], dico->dynrefptr[linenum], 0); + nupa_subcktcall (dicoS, dicoS->dynrefptr[idef], dicoS->dynrefptr[linenum], 0); else putlogfile ('?', linenum, " illegal subckt call."); } else if (c == 'U') /* release local symbols = parameters */ - nupa_subcktexit (dico); + nupa_subcktexit (dicoS); putlogfile ('e', linenum, s); - evalcount++; + evalcountS++; #ifdef TRACE_NUMPARAMS fprintf (stderr, "** SJB - leaving nupa_eval(): %s %d\n", s, err); ws ("** SJB - --> "); @@ -753,23 +810,23 @@ nupa_signal (int sig, char *info) putlogfile ('!', sig, " Nupa Signal"); if (sig == NUPADECKCOPY) { - if (firstsignal) + if (firstsignalS) { nupa_init (info); - firstsignal = 0; + firstsignalS = 0; } } else if (sig == NUPASUBSTART) - inexpansion = 1; + inexpansionS = 1; else if (sig == NUPASUBDONE) { - inexpansion = 0; + inexpansionS = 0; nupa_inst_name = NULL; } else if (sig == NUPAEVALDONE) { nupa_done (); - firstsignal = 1; + firstsignalS = 1; } return 1; } @@ -782,3 +839,19 @@ nupa_fetchinstance (void) return dico; } #endif /* USING_NUPATEST */ + +static void dump_symbols( tdico *dico_p ) +{ + char *name_p ; /* current symbol */ + entry *entry_p ; /* current entry */ + void *key ; /* return key */ + NGHASHITER iter ; /* hash iterator - thread safe */ + + fprintf (stderr, "Symbol table\n"); + for (entry_p = nghash_enumeratekRE(dico_p->symbol_table,&key,NGHASH_FIRST(&iter)) ; + entry_p ; + entry_p = nghash_enumeratekRE(dico_p->symbol_table,&key,&iter)) { + name_p = (char *) key ; + fprintf (stderr, " ---> %s = %g\n", name_p, entry_p->vl) ; + } +} diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 346ad16ac..63e566167 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -23,8 +23,8 @@ extern COMPATMODE_T ngspice_compat_mode(void) ; /************ keywords ************/ /* SJB - 150 chars is ample for this - see initkeys() */ -static Str (150, keys); /* all my keywords */ -static Str (150, fmath); /* all math functions */ +static SPICE_DSTRING keyS ; /* all my keywords */ +static SPICE_DSTRING fmathS ; /* all math functions */ extern char *nupa_inst_name; /* see spicenum.c */ extern long dynsubst; /* see inpcom.c */ @@ -56,10 +56,11 @@ static void initkeys (void) /* the list of reserved words */ { - scopy_up (keys, + spice_dstring_init(&keyS) ; + scopy_up (&keyS, "and or not div mod if else end while macro funct defined" " include for to downto is var"); - scopy_up (fmath, + scopy_up (&fmathS, "sqr sqrt sin cos exp ln arctan abs pow pwr max min int log sinh cosh tanh ternary_fcn v agauss"); } @@ -131,25 +132,29 @@ static unsigned char message (tdico * dic, char *s) /* record 'dic' should know about source file and line */ { - Strbig (dynLlen, t); + char *srcfile ; /* src file name */ + SPICE_DSTRING t ; /* temp dstring */ + + spice_dstring_init(&t) ; dic->errcount++; - if ((dic->srcfile != NULL) && dic->srcfile[0]) + srcfile = spice_dstring_value( &(dic->srcfile) ) ; + if ((srcfile != NULL) && srcfile[0]) { - scopy (t, dic->srcfile); - cadd (t, ':'); + scopyd(&t, &(dic->srcfile)) ; + cadd (&t, ':'); } if (dic->srcline >= 0) { - sadd (t, "Original line no.: "); - nadd (t, dic->oldline); - sadd (t, ", new internal line no.: "); - nadd (t, dic->srcline); - sadd (t, ":\n"); + sadd (&t, "Original line no.: "); + nadd (&t, dic->oldline); + sadd (&t, ", new internal line no.: "); + nadd (&t, dic->srcline); + sadd (&t, ":\n"); } - sadd (t, s); - cadd (t, '\n'); - fputs (t, stderr); - Strrem(t); + sadd (&t, s); + cadd (&t, '\n'); + fputs ( spice_dstring_value(&t), stderr); + spice_dstring_free(&t) ; return 1 /* error! */ ; } @@ -167,20 +172,19 @@ debugwarn (tdico * d, char *s) void initdico (tdico * dico) { - int i; COMPATMODE_T compat_mode; dico->nbd = 0; - sini(dico->option,sizeof(dico->option)-4); - sini(dico->srcfile,sizeof(dico->srcfile)-4); + spice_dstring_init( &(dico->option) ) ; + spice_dstring_init( &(dico->srcfile) ) ; + dico->srcline = -1; dico->errcount = 0; - dico->dyndat = (entry*)tmalloc(3 * sizeof(entry)); + dico->symbol_table = nghash_init( NGHASH_MIN_SIZE ) ; + nghash_unique( dico->symbol_table, FALSE ) ; + spice_dstring_init( &(dico->lookup_buf) ) ; - for (i = 0; i < 3; i++) - sini (dico->dyndat[i].nom, 100); - dico->tos = 0; dico->stack[dico->tos] = 0; /* global data beneath */ initkeys (); @@ -193,6 +197,41 @@ initdico (tdico * dico) dico->hspice_compatibility = 0 ; } +static void dico_free_entry( entry *entry_p ) +{ + if( entry_p->symbol ){ + txfree(entry_p->symbol ) ; + } + txfree(entry_p) ; +} /* end dico_free_entry() */ + +static +entry **dico_rebuild_symbol_array( tdico * dico, int *num_entries_ret ) +{ + int i ; /* counter */ + int size ; /* number of entries in symbol table */ + entry *entry_p ; /* current entry */ + NGHASHITER iter ; /* hash iterator - thread safe */ + + size = *num_entries_ret = nghash_get_size( dico->symbol_table ) ; + if( dico->num_symbols == size ){ + /* no work to do up to date */ + return( dico->symbol_array ) ; + } + if( size <= 0 ){ + size = 1 ; + } + dico->symbol_array = trealloc( dico->symbol_array, (size+1) * sizeof(entry *) ) ; + i = 0 ; + for (entry_p = nghash_enumerateRE(dico->symbol_table,NGHASH_FIRST(&iter)) ; + entry_p ; + entry_p = nghash_enumerateRE(dico->symbol_table,&iter)){ + dico->symbol_array[i++] = entry_p ; + } + dico->num_symbols = *num_entries_ret ; + return dico->symbol_array ; +} + /* local semantics for parameters inside a subckt */ /* arguments as wll as .param expressions */ /* to do: scope semantics ? @@ -207,8 +246,12 @@ static void dicostack (tdico * dico, char op) /* push or pop operation for nested subcircuit locals */ { - char *param_name, *inst_name; + char *param_p, *inst_name; int i, current_stack_size, old_stack_size; + int num_entries ; /* number of entries */ + entry **entry_array ; /* entry array */ + entry *entry_p ; /* current entry */ + SPICE_DSTRING param_name ; if (op == Push) { @@ -228,16 +271,24 @@ dicostack (tdico * dico, char op) current_stack_size = dico->nbd; old_stack_size = dico->stack[dico->tos]; inst_name = dico->inst_name[dico->tos]; + spice_dstring_init(¶m_name) ; + entry_array = dico_rebuild_symbol_array( dico, &num_entries ) ; for (i = old_stack_size + 1; i <= current_stack_size; i++) { - param_name = - tmalloc (strlen (inst_name) + strlen (dico->dyndat[i].nom) + 2); - sprintf (param_name, "%s.%s", inst_name, dico->dyndat[i].nom); - nupa_add_inst_param (param_name, dico->dyndat[i].vl); - tfree (param_name); + spice_dstring_reinit(¶m_name) ; + if( i < num_entries ){ + entry_p = entry_array[i] ; + param_p = spice_dstring_print( ¶m_name, "%s.%s", + inst_name, + entry_p->symbol ) ; + nupa_add_inst_param (param_p, entry_p->vl); + nghash_deleteItem( dico->symbol_table, entry_p->symbol, entry_p ) ; + dico_free_entry( entry_p ) ; + } } tfree (inst_name); + spice_dstring_free(¶m_name) ; dico->nbd = dico->stack[dico->tos]; /* simply kill all local items */ dico->tos--; @@ -256,109 +307,99 @@ donedico (tdico * dico) return sze; } -static int +/* FIXME : WPS this should be a hash table */ +static entry * entrynb (tdico * d, char *s) /* symbol lookup from end to start, for stacked local symbols .*/ /* bug: sometimes we need access to same-name symbol, at lower level? */ { - int i; - unsigned char ok; - ok = 0; - i = d->nbd + 1; + entry *entry_p ; /* search hash table */ - while ((!ok) && (i > 1)) - { - i--; - ok = steq (d->dyndat[i].nom, s); - } - if (!ok) - return 0; - else - return i; + entry_p = nghash_find( d->symbol_table, s ) ; + return( entry_p ) ; } char getidtype (tdico * d, char *s) -/* test if identifier s is known. Answer its type, or '?' if not in list */ +/* test if identifier s is known. Answer its type, or '?' if not in table */ { + entry *entry_p ; /* hash table entry */ char itp = '?'; /* assume unknown */ - int i = entrynb (d, s); - if (i > 0) - itp = d->dyndat[i].tp; - return itp; + entry_p = entrynb (d, s) ; + if( entry_p ){ + itp = entry_p->tp ; + } + return (itp) ; } static double fetchnumentry (tdico * dico, char *t, unsigned char *perr) { unsigned char err = *perr; - unsigned short k; double u; - Strbig (dynLlen, s); - k = entrynb (dico, t); /* no keyword */ + entry *entry_p ; /* hash table entry */ + SPICE_DSTRING s ; /* dynamic string */ + + spice_dstring_init(&s) ; + entry_p = entrynb (dico, t); /* no keyword */ /*dbg -- if ( k<=0 ) { ws("Dico num lookup fails. ") ;} */ - while ((k > 0) && (dico->dyndat[k].tp == 'P')) - k = dico->dyndat[k].ivl; /* pointer chain */ + while ( entry_p && (entry_p->tp == 'P') ){ + entry_p = entry_p->pointer ; + } - if (k > 0) - if (dico->dyndat[k].tp != 'R') - k = 0; + if ( entry_p ) + if (entry_p->tp != 'R') + entry_p = NULL ; - if (k > 0) - u = dico->dyndat[k].vl; + if ( entry_p ) + u = entry_p->vl ; else { u = 0.0; - scopy (s, "Undefined number ["); - sadd (s, t); - cadd (s, ']'); - err = message (dico, s); + scopys(&s, "Undefined number [") ; + sadd (&s, t); + cadd (&s, ']'); + err = message (dico, spice_dstring_value(&s) ) ; } *perr = err; - Strrem(s); + spice_dstring_free(&s) ; return u; } /******* writing dictionary entries *********/ -int +entry * attrib (tdico * dico, char *t, char op) { /* seek or attribute dico entry number for string t. Option op='N' : force a new entry, if tos>level and old is valid. */ int i; - unsigned char ok; - i = dico->nbd + 1; - ok = 0; - while ((!ok) && (i > 1)) - { /* search old */ - i--; - ok = steq (dico->dyndat[i].nom, t); - } + entry *entry_p ; /* symbol table entry */ - if (ok && (op == 'N') - && (dico->dyndat[i].level < dico->tos) && (dico->dyndat[i].tp != '?')) + entry_p = nghash_find( dico->symbol_table, t ) ; + if ( entry_p && (op == 'N') + && ( entry_p->level < dico->tos) && ( entry_p->tp != '?')) { - ok = 0; + entry_p = NULL ; } - if (!ok) + if (!(entry_p)) { dico->nbd++; i = dico->nbd; - dico->dyndat = trealloc(dico->dyndat, (i+1) * sizeof(entry)); - sini (dico->dyndat[i].nom, 100); - scopy (dico->dyndat[i].nom, t); - dico->dyndat[i].tp = '?'; /* signal Unknown */ - dico->dyndat[i].level = dico->tos; + entry_p = tmalloc( sizeof(entry) ) ; + entry_p->symbol = strdup( t ) ; + entry_p->tp = '?'; /* signal Unknown */ + entry_p->level = dico->tos ; + nghash_insert( dico->symbol_table, t, entry_p ) ; } - return i; + return entry_p ; } static unsigned char @@ -368,6 +409,7 @@ define (tdico * dico, char tpe, /* type marker */ double z, /* float value if any */ int w, /* integer value if any */ + entry *pval, /* pointer value if any */ char *base) /* string pointer if any */ { /*define t as real or integer, @@ -378,48 +420,50 @@ define (tdico * dico, we already make symbol entries which are dummy globals ! we mark each id with its subckt level, and warn if write at higher one. */ - int i; char c; unsigned char err, warn; - Strbig (dynLlen, v); - i = attrib (dico, t, op); + entry *entry_p ; /* spice table entry */ + SPICE_DSTRING vartemp ; /* vairable temp */ + + spice_dstring_init(&vartemp) ; + entry_p = attrib (dico, t, op); err = 0; - if (i <= 0) + if (!(entry_p)) err = message (dico, " Symbol table overflow"); else { - if (dico->dyndat[i].tp == 'P') - i = dico->dyndat[i].ivl; /* pointer indirection */ + if ( entry_p->tp == 'P') + entry_p = entry_p->pointer ; /* pointer indirection */ - if (i > 0) - c = dico->dyndat[i].tp; + if (entry_p) + c = entry_p->tp ; else c = ' '; if ((c == 'R') || (c == 'S') || (c == '?')) { - dico->dyndat[i].vl = z; - dico->dyndat[i].tp = tpe; - dico->dyndat[i].ivl = w; - dico->dyndat[i].sbbase = base; + entry_p->vl = z; + entry_p->tp = tpe; + entry_p->ivl = w ; + entry_p->sbbase = base ; /* if ( (c !='?') && (i<= dico->stack[dico->tos]) ) { */ if (c == '?') - dico->dyndat[i].level = dico->tos; /* promote! */ + entry_p->level = dico->tos; /* promote! */ - if (dico->dyndat[i].level < dico->tos) + if ( entry_p->level < dico->tos) { /* warn about re-write to a global scope! */ - scopy (v, t); - cadd (v, ':'); - nadd (v, dico->dyndat[i].level); - sadd (v, " overwritten."); - warn = message (dico, v); + scopys(&vartemp, t) ; + cadd (&vartemp, ':'); + nadd (&vartemp, entry_p->level); + sadd (&vartemp, " overwritten."); + warn = message (dico, spice_dstring_value(&vartemp)); } } else { - scopy (v, t); - sadd (v, ": cannot redefine"); + scopys( &vartemp, t) ; + sadd ( &vartemp, ": cannot redefine"); /* suppress error message, resulting from multiple definition of symbols (devices) in .model lines with same name, but in different subcircuits. Subcircuit expansion is o.k., we have to deal with this numparam @@ -428,7 +472,7 @@ define (tdico * dico, /*err = message (dico, v);*/ } } - Strrem(v); + spice_dstring_free(&vartemp) ; return err; } @@ -438,7 +482,7 @@ defsubckt (tdico * dico, char *s, int w, char categ) to enter subcircuit (categ=U) and model (categ=O) names */ { - Str (80, u); + SPICE_DSTRING ustr ; /* temp user string */ unsigned char err; int i, j, ls; ls = length (s); @@ -460,8 +504,10 @@ defsubckt (tdico * dico, char *s, int w, char categ) if ((j > i)) { - pscopy_up (u, s, i + 1, j - i); - err = define (dico, u, ' ', categ, 0.0, w, NULL); + spice_dstring_init(&ustr) ; + pscopy_up ( &ustr, s, i, j - i) ; + err = define (dico, spice_dstring_value(&ustr), ' ', categ, 0.0, w, NULL, NULL); + spice_dstring_free(&ustr) ; } else err = message (dico, "Subcircuit or Model without name."); @@ -470,13 +516,16 @@ defsubckt (tdico * dico, char *s, int w, char categ) } int -findsubckt (tdico * dico, char *s, char *subname) +findsubckt (tdico * dico, char *s, SPICE_DSTRINGPTR subname) /* input: s is a subcircuit invocation line. returns 0 if not found, else the stored definition line number value and the name in string subname */ { - Str (80, u); /* u= subckt name is last token in string s */ - int i, j, k; + entry *entry_p ; /* symbol table entry */ + SPICE_DSTRING ustr ; /* u= subckt name is last token in string s */ + int j, k; + int line ; /* stored line number */ + spice_dstring_init(&ustr) ; k = length (s); while ((k >= 0) && (s[k] <= ' ')) @@ -487,22 +536,22 @@ findsubckt (tdico * dico, char *s, char *subname) while ((k >= 0) && (s[k] > ' ')) k--; - pscopy_up (u, s, k + 2, j - k); - i = entrynb (dico, u); + pscopy_up ( &ustr, s, k + 1, j - k) ; + entry_p = entrynb (dico, spice_dstring_value(&ustr) ) ; - if ((i > 0) && (dico->dyndat[i].tp == 'U')) + if ((entry_p) && ( entry_p->tp == 'U')) { - i = dico->dyndat[i].ivl; - scopy (subname, u); + line = entry_p->ivl; + scopyd ( subname, &ustr ) ; } else { - i = 0; - scopy (subname, ""); + line = 0; + spice_dstring_reinit(subname); message (dico, "Cannot find subcircuit."); } - return i; + return line ; } #if 0 /* unused, from the full macro language... */ @@ -558,14 +607,18 @@ deffuma ( /* define function or macro entry. */ /************ input scanner stuff **************/ static unsigned char -keyword (char *keys, char *t) +keyword ( SPICE_DSTRINGPTR keys_p, SPICE_DSTRINGPTR tstr_p) { /* return 0 if t not found in list keys, else the ordinal number */ unsigned char i, j, k; int lt, lk; unsigned char ok; - lt = length (t); - lk = length (keys); + char *t ; + char *keys ; + lt = spice_dstring_length(tstr_p) ; + t = spice_dstring_value(tstr_p) ; + lk = spice_dstring_length (keys_p); + keys = spice_dstring_value(keys_p); k = 0; j = 0; @@ -599,12 +652,14 @@ parseunit (double x, char *s) /* the Spice suffixes */ { double u = 0; - Str (20, t); + SPICE_DSTRING t ; unsigned char isunit; isunit = 1; - pscopy (t, s, 1, 3); + spice_dstring_init(&t) ; - if (steq (t, "MEG")) + pscopy (&t, s, 0, 3); + + if (steq ( spice_dstring_value(&t), "MEG")) u = 1e6; else if (s[0] == 'G') u = 1e9; @@ -626,11 +681,13 @@ parseunit (double x, char *s) if (isunit) x = x * u; + spice_dstring_free(&t) ; + return x; } static int -fetchid (char *s, char *t, int ls, int i) +fetchid (char *s, SPICE_DSTRINGPTR t, int ls, int i) /* copy next identifier from s into t, advance and return scan index i */ { char c; @@ -643,7 +700,7 @@ fetchid (char *s, char *t, int ls, int i) c = s[i - 1]; } - scopy (t, ""); + spice_dstring_reinit(t) ; cadd (t, upcase (c)); do { @@ -673,8 +730,10 @@ exists (tdico * d, char *s, int *pi, unsigned char *perror) int ls; char c; unsigned char ok; - Strbig (dynLlen, t); + SPICE_DSTRING t ; + ls = length (s); + spice_dstring_init(&t) ; x = 0.0; do { @@ -689,9 +748,9 @@ exists (tdico * d, char *s, int *pi, unsigned char *perror) if (ok) { - i = fetchid (s, t, ls, i); + i = fetchid (s, &t, ls, i); i--; - if (entrynb (d, t) > 0) + if (entrynb (d, spice_dstring_value(&t)) > 0) x = 1.0; do { @@ -712,7 +771,7 @@ exists (tdico * d, char *s, int *pi, unsigned char *perror) *perror = error; *pi = i; - Strrem(t); + spice_dstring_free(&t) ; return x; } @@ -724,9 +783,12 @@ fetchnumber (tdico * dico, char *s, int ls, int *pi, unsigned char *perror) int i = *pi; int k, err; char d; - Str (20, t); + char *t ; + SPICE_DSTRING tstr ; + SPICE_DSTRING vstr ; double u; - Strbig (dynLlen, v); + spice_dstring_init(&tstr) ; + spice_dstring_init(&vstr) ; k = i; do { @@ -754,27 +816,29 @@ fetchnumber (tdico * dico, char *s, int ls, int *pi, unsigned char *perror) } while (!(!((d >= '0') && (d <= '9')))); } - pscopy (t, s, i, k - i); + pscopy (&tstr, s, i-1, k - i) ; + t = spice_dstring_value(&tstr) ; if (t[0] == '.') - cins (t, '0'); + cins ( &tstr, '0'); else if (t[length (t) - 1] == '.') - cadd (t, '0'); + cadd (&tstr, '0'); - u = rval (t, &err); + t = spice_dstring_value(&tstr) ; + u = rval (t, &err); /* extract real value from string here */ if (err != 0) { - scopy (v, "Number format error: "); - sadd (v, t); - error = message (dico, v); + scopys(&vstr, "Number format error: ") ; + sadd (&vstr, t); + error = message (dico, spice_dstring_value(&vstr)) ; } else { - scopy (t, ""); + spice_dstring_reinit(&tstr); while (alfa (d)) { - cadd (t, upcase (d)); + cadd (&tstr, upcase (d)); k++; if (k > ls) @@ -783,13 +847,15 @@ fetchnumber (tdico * dico, char *s, int ls, int *pi, unsigned char *perror) d = s[k - 1]; } + t = spice_dstring_value(&tstr) ; u = parseunit (u, t); } i = k - 1; *perror = error; *pi = i; - Strrem(v); + spice_dstring_free(&tstr) ; + spice_dstring_free(&vstr) ; return u; } @@ -808,8 +874,9 @@ fetchoperator (tdico * dico, unsigned char level = *plevel; unsigned char error = *perror; char c, d; - Strbig (dynLlen, v); + SPICE_DSTRING vstr ; c = s[i - 1]; + spice_dstring_init(&vstr) ; if (i < ls) d = s[i]; @@ -892,17 +959,17 @@ fetchoperator (tdico * dico, state = 0; if (c > ' ') { - scopy (v, "Syntax error: letter ["); - cadd (v, c); - cadd (v, ']'); - error = message (dico, v); + spice_dstring_append(&vstr, "Syntax error: letter [", -1 ); + cadd (&vstr, c); + cadd (&vstr, ']'); + error = message (dico, spice_dstring_value(&vstr) ); } } *pi = i; *pstate = state; *plevel = level; *perror = error; - Strrem(v); + spice_dstring_free(&vstr) ; return c; } @@ -1079,8 +1146,9 @@ formula (tdico * dico, char *s, unsigned char *perror) int i, k, ls, natom, arg2, arg3; char c, d; unsigned char ok; - Strbig (dynLlen, t); + SPICE_DSTRING tstr ; + spice_dstring_init(&tstr) ; for (i = 0; i <= nprece; i++) { accu[i] = 0.0; @@ -1145,18 +1213,18 @@ formula (tdico * dico, char *s, unsigned char *perror) { if (arg2 > i) { - pscopy (t, s, i + 1, arg2 - i - 1); - v = formula (dico, t, &error); + pscopy (&tstr, s, i, arg2 - i - 1); + v = formula (dico, spice_dstring_value(&tstr), &error); i = arg2; } if (arg3 > i) { - pscopy (t, s, i + 1, arg3 - i - 1); - w = formula (dico, t, &error); + pscopy (&tstr, s, i, arg3 - i - 1); + w = formula (dico, spice_dstring_value(&tstr), &error); i = arg3; } - pscopy (t, s, i + 1, k - i - 1); - u = formula (dico, t, &error); + pscopy (&tstr, s, i, k - i - 1); + u = formula (dico, spice_dstring_value(&tstr), &error); state = 1; /* atom */ if (fu > 0) { @@ -1174,15 +1242,15 @@ formula (tdico * dico, char *s, unsigned char *perror) } else if (alfa (c)) { - i = fetchid (s, t, ls, i); /* user id, but sort out keywords */ + i = fetchid (s, &tstr, ls, i); /* user id, but sort out keywords */ state = 1; i--; - kw = keyword (keys, t); /* debug ws('[',kw,']'); */ + kw = keyword (&keyS, &tstr); /* debug ws('[',kw,']'); */ if (kw == 0) { - fu = keyword (fmath, t); /* numeric function? */ + fu = keyword (&fmathS, &tstr); /* numeric function? */ if (fu == 0) - u = fetchnumentry (dico, t, &error); + u = fetchnumentry (dico, spice_dstring_value(&tstr), &error); else state = 0; /* state==0 means: ignore for the moment */ } @@ -1261,9 +1329,10 @@ formula (tdico * dico, char *s, unsigned char *perror) } /* while */ ; if ((natom == 0) || (oldstate != 4)) { - scopy (t, " Expression err: "); - sadd (t, s); - error = message (dico, t); + spice_dstring_reinit(&tstr) ; + sadd( &tstr, " Expression err: "); + sadd (&tstr, s); + error = message (dico, spice_dstring_value(&tstr)); } if (negate == 1) @@ -1275,7 +1344,7 @@ formula (tdico * dico, char *s, unsigned char *perror) *perror = error; - Strrem(t); + spice_dstring_free(&tstr) ; if (error) return 1.0; @@ -1316,71 +1385,73 @@ fmttype (double x) } static unsigned char -evaluate (tdico * dico, char *q, char *t, unsigned char mode) +evaluate (tdico * dico, SPICE_DSTRINGPTR qstr_p, char *t, unsigned char mode) { /* transform t to result q. mode 0: expression, mode 1: simple variable */ double u = 0.0; - int k, j, lq; + int j, lq; char dt, fmt; + entry *entry_p ; unsigned char numeric, done, nolookup; unsigned char err; - Strbig (dynLlen, v); - scopy (q, ""); + SPICE_DSTRING vstr ; + + spice_dstring_init(&vstr) ; + spice_dstring_reinit(qstr_p) ; numeric = 0; err = 0; if (mode == 1) { /* string? */ stupcase (t); - k = entrynb (dico, t); - nolookup = (k <= 0); - while ((k > 0) && (dico->dyndat[k].tp == 'P')) - k = dico->dyndat[k].ivl; + entry_p = entrynb (dico, t); + nolookup = (!(entry_p)); + while ((entry_p) && (entry_p->tp == 'P')){ + entry_p = entry_p->pointer ; /* follow pointer chain */ + } /* pointer chain */ - if (k > 0) - dt = dico->dyndat[k].tp; + if (entry_p) + dt = entry_p->tp; else dt = ' '; /* data type: Real or String */ if (dt == 'R') { - u = dico->dyndat[k].vl; + u = entry_p->vl; numeric = 1; } else if (dt == 'S') { /* suppose source text "..." at */ - j = dico->dyndat[k].ivl; + j = entry_p->ivl; lq = 0; do { j++; lq++; - dt = /* ibf->bf[j]; */ dico->dyndat[k].sbbase[j]; + dt = /* ibf->bf[j]; */ entry_p->sbbase[j]; - if (cpos ('3', dico->option) <= 0) + if (cpos ('3', spice_dstring_value(&dico->option)) <= 0) dt = upcase (dt); /* spice-2 */ done = (dt == '\"') || (dt < ' ') || (lq > 99); if (!done) - cadd (q, dt); + cadd (qstr_p, dt); } while (!(done)); } - else - k = 0; - if (k <= 0) + if (!(entry_p)) { - scopy (v, ""); - cadd (v, '\"'); - sadd (v, t); - sadd (v, "\" not evaluated. "); + spice_dstring_reinit(&vstr) ; + cadd (&vstr, '\"'); + sadd (&vstr, t); + sadd (&vstr, "\" not evaluated. "); if (nolookup) - sadd (v, "Lookup failure."); + sadd (&vstr, "Lookup failure."); - err = message (dico, v); + err = message (dico, spice_dstring_value(&vstr)); } } else @@ -1392,13 +1463,13 @@ evaluate (tdico * dico, char *q, char *t, unsigned char mode) { fmt = fmttype (u); if (fmt == 'I') - stri (np_round (u), q); + stri (np_round (u), qstr_p); else { - strf (u, 17, 10, q); + strf (u, 17, 10, qstr_p); } } - Strrem(v); + spice_dstring_free(&vstr) ; return err; } @@ -1576,36 +1647,53 @@ scanline (tdico * dico, char *s, char *r, unsigned char err) /********* interface functions for spice3f5 extension ***********/ static void -compactfloatnb (char *v) +compactfloatnb (SPICE_DSTRINGPTR vstr_p) /* try to squeeze a floating pt format to ACT_CHARACTS characters */ /* erase superfluous 000 digit streams before E */ /* bug: truncating, no rounding */ { int n, k, m, lex, lem; - Str (20, expo); - Str (10, expn); - n = cpos ('E', v); /* if too long, try to delete digits */ - if (n==0) n = cpos ('e', v); + char *expov ; + char *expnv ; + char *v_p ; + SPICE_DSTRING expo_str ; + SPICE_DSTRING expn_str ; - if (n > 0) { - pscopy (expo, v, n, length (v)); - lex = length (expo); + spice_dstring_init(&expo_str) ; + spice_dstring_init(&expn_str) ; + n = cpos ('E', spice_dstring_value(vstr_p)) ; /* if too long, try to delete digits */ + if (n<0) n = cpos ('e', spice_dstring_value(vstr_p)); + + if (n >= 0) { + pscopy (&expo_str, spice_dstring_value(vstr_p), n, + spice_dstring_length(vstr_p)); + lex = spice_dstring_length (&expo_str) ; if (lex > 4) { /* exponent only 2 digits */ - pscopy (expn, expo, 2, 4); - if (atoi(expn) < -99) scopy(expo, "e-099"); /* brutal */ - if (atoi(expn) > +99) scopy(expo, "e+099"); - expo[2] = expo[3]; - expo[3] = expo[4]; - expo[4] = '\0'; + pscopy (&expn_str, spice_dstring_value(&expo_str), 1, 4); + expnv = spice_dstring_value(&expn_str) ; + if (atoi(expnv) < -99){ + spice_dstring_reinit(&expo_str) ; + sadd(&expo_str, "e-099"); /* brutal */ + } + if (atoi(expnv) > +99){ + spice_dstring_reinit(&expo_str) ; + sadd(&expo_str, "e+099"); + } + expov = spice_dstring_value(&expo_str) ; + expov[2] = expov[3]; + expov[3] = expov[4]; + expov[4] = '\0'; + spice_dstring_setlength(&expo_str,4) ; lex = 4; } - k = n - 1; /* mantissa is 0...k */ + k = n ; /* mantissa is 0...k */ m = MAX_STRING_INSERT; - while (v[m] != ' ') + v_p = spice_dstring_value(vstr_p) ; + while (v_p[m] != ' ') m--; m++; - while ((v[k] == '0') && (v[k - 1] == '0')) + while ((v_p[k] == '0') && (v_p[k - 1] == '0')) k--; lem = k - m; @@ -1613,54 +1701,58 @@ compactfloatnb (char *v) if ((lem + lex) > ACT_CHARACTS) lem = ACT_CHARACTS - lex; - pscopy (v, v, m+1, lem); - if (cpos('.', v) > 0) { + pscopy (vstr_p, spice_dstring_value(vstr_p), m, lem); + if (cpos('.', spice_dstring_value(vstr_p)) >= 0) { while (lem < ACT_CHARACTS - 4) { - cadd(v, '0'); + cadd(vstr_p, '0'); lem++; } } else { - cadd(v, '.'); + cadd(vstr_p, '.'); lem++; while (lem < ACT_CHARACTS - 4) { - cadd(v, '0'); + cadd(vstr_p, '0'); lem++; } } - sadd (v, expo); + sadd (vstr_p, spice_dstring_value(&expo_str) ); } else { m = 0; - while (v[m] == ' ') + v_p = spice_dstring_value(vstr_p) ; + while (v_p[m] == ' ') m++; - lem = length(v) - m; + lem = spice_dstring_length(vstr_p) - m; if (lem > ACT_CHARACTS) lem = ACT_CHARACTS; - pscopy (v, v, m+1, lem); + pscopy (vstr_p, spice_dstring_value(vstr_p), m, lem); } } static int -insertnumber (tdico * dico, int i, char *s, char *u) +insertnumber (tdico * dico, int i, char *s, SPICE_DSTRINGPTR ustr_p) /* insert u in string s in place of the next placeholder number */ { - Str (40, v); - Str (80, msg); + SPICE_DSTRING vstr ; /* dynamic string */ + SPICE_DSTRING mstr ; /* dynamic string */ + char *v_p ; /* value of vstr dyna string */ unsigned char found; int ls, k; long long accu; ls = length (s); - scopy (v, u); - compactfloatnb (v); + spice_dstring_init(&vstr) ; + spice_dstring_init(&mstr) ; + scopyd (&vstr, ustr_p) ; + compactfloatnb (&vstr) ; - while (length (v) < MAX_STRING_INSERT) - cadd (v, ' '); + while ( spice_dstring_length (&vstr) < MAX_STRING_INSERT) + cadd (&vstr, ' '); - if (length (v) > MAX_STRING_INSERT) + if ( spice_dstring_length (&vstr) > MAX_STRING_INSERT) { - scopy (msg, " insertnumber fails: "); - sadd (msg, u); - message (dico, msg); + spice_dstring_append( &mstr, " insertnumber fails: ", -1); + sadd (&mstr, spice_dstring_value(ustr_p)); + message (dico, spice_dstring_value(&mstr)) ; } found = 0; @@ -1672,7 +1764,7 @@ insertnumber (tdico * dico, int i, char *s, char *u) accu = 0; while (found && (k < 15)) - { /* parse a 15-digit number */ + { /* parse a 15-digit number */ found = num (s[i + k]); if (found) @@ -1683,7 +1775,8 @@ insertnumber (tdico * dico, int i, char *s, char *u) if (found) { - accu = accu - 100000000000000LL; /* plausibility test */ + accu = accu - 100000000000000LL; /* plausibility test */ + found = (accu > 0) && (accu < dynsubst + 1); /* dynsubst numbers have been allocated */ } i++; @@ -1692,8 +1785,9 @@ insertnumber (tdico * dico, int i, char *s, char *u) if (found) { /* substitute at i-1 ongoing */ i--; + v_p = spice_dstring_value(&vstr) ; for (k = 0; k < ACT_CHARACTS; k++) - s[i + k] = v[k]; + s[i + k] = v_p[k]; i = i + MAX_STRING_INSERT; @@ -1702,12 +1796,11 @@ insertnumber (tdico * dico, int i, char *s, char *u) { i = ls; fprintf (stderr, "xpressn.c--insertnumber: i=%d s=%s u=%s\n", i, s, - u); + spice_dstring_value(ustr_p)) ; message (dico, "insertnumber: missing slot "); } return i; } - unsigned char nupa_substitute (tdico * dico, char *s, char *r, unsigned char err) /* s: pointer to original source line. @@ -1718,7 +1811,11 @@ nupa_substitute (tdico * dico, char *s, char *r, unsigned char err) { int i, k, ls, level, nnest, ir; char c, d; - Strdbig (dynLlen, q, t); + SPICE_DSTRING qstr ; /* temp result dynamic string */ + SPICE_DSTRING tstr ; /* temp dynamic string */ + + spice_dstring_init(&qstr) ; + spice_dstring_init(&tstr) ; i = 0; ls = length (s); err = 0; @@ -1745,18 +1842,19 @@ nupa_substitute (tdico * dico, char *s, char *r, unsigned char err) err = message (dico, "Closing \"}\" not found."); else { - pscopy (t, s, i + 1, k - i - 1); + pscopy (&tstr, s, i , k - i - 1); /* exeption made for .meas */ - if( strcasecmp(t,"LAST")==0) { - strcpy(q,"last") ; + if( strcasecmp( spice_dstring_value(&tstr),"LAST")==0) { + spice_dstring_reinit(&qstr) ; + sadd(&qstr,"last") ; err=0; } else - err = evaluate (dico, q, t, 0); + err = evaluate (dico, &qstr, spice_dstring_value(&tstr), 0); } i = k; if (!err) - ir = insertnumber (dico, ir, r, q); + ir = insertnumber (dico, ir, r, &qstr) ; else err = message (dico, "Cannot compute substitute"); } @@ -1788,8 +1886,8 @@ nupa_substitute (tdico * dico, char *s, char *r, unsigned char err) err = message (dico, "Closing \")\" not found."); else { - pscopy (t, s, i + 1, k - i - 1); - err = evaluate (dico, q, t, 0); + pscopy (&tstr, s, i, k - i - 1); + err = evaluate (dico, &qstr, spice_dstring_value(&tstr), 0); } i = k; } @@ -1803,29 +1901,31 @@ nupa_substitute (tdico * dico, char *s, char *r, unsigned char err) d = s[k - 1]; } while (!((k > ls) || (d <= ' '))); - pscopy (t, s, i, k - i); - err = evaluate (dico, q, t, 1); + pscopy (&tstr, s, i-1, k - i); + err = evaluate (dico, &qstr, spice_dstring_value(&tstr), 1); i = k - 1; } if (!err) - ir = insertnumber (dico, ir, r, q); + ir = insertnumber (dico, ir, r, &qstr); else message (dico, "Cannot compute &(expression)"); } } /* while */ - Strdrem(q,t); + spice_dstring_free(&qstr) ; + spice_dstring_free(&tstr) ; return err; } static unsigned char -getword (char *s, char *t, int after, int *pi) +getword (char *s, SPICE_DSTRINGPTR tstr_p, int after, int *pi) /* isolate a word from s after position "after". return i= last read+1 */ { int i = *pi; int ls; unsigned char key; + char *t_p ; i = after; ls = length (s); @@ -1834,16 +1934,17 @@ getword (char *s, char *t, int after, int *pi) i++; } while (!((i >= ls) || alfa (s[i - 1]))); - scopy (t, ""); + spice_dstring_reinit(tstr_p) ; while ((i <= ls) && (alfa (s[i - 1]) || num (s[i - 1]))) { - cadd (t, upcase (s[i - 1])); + cadd (tstr_p, upcase (s[i - 1])); i++; } - if (t[0]) - key = keyword (keys, t); + t_p = spice_dstring_value(tstr_p) ; + if (t_p[0]) + key = keyword (&keyS, tstr_p); else key = 0; @@ -1852,7 +1953,7 @@ getword (char *s, char *t, int after, int *pi) } static char -getexpress (char *s, char *t, int *pi) +getexpress (char *s, SPICE_DSTRINGPTR tstr_p, int *pi) /* returns expression-like string until next separator Input i=position before expr, output i=just after expr, on separator. returns tpe=='R' if ( numeric, 'S' if ( string only @@ -1917,13 +2018,13 @@ getexpress (char *s, char *t, int *pi) } /* buggy? */ if ((c == '/') || (c == '-')) comment = (s[i] == c); - } while (!((cpos (c, ",;)}") > 0) || comment)); /* legal separators */ + } while (!((cpos (c, ",;)}") >= 0) || comment)); /* legal separators */ tpe = 'R'; } - pscopy (t, s, ia, i - ia); + pscopy (tstr_p, s, ia-1, i - ia); if (s[i - 1] == '}') i++; @@ -1950,14 +2051,18 @@ nupa_assignment (tdico * dico, char *s, char mode) char dtype; int wval = 0; double rval = 0.0; - Strdbig (dynLlen, t, u); + char *t_p ; /* dstring contents value */ + SPICE_DSTRING tstr ; /* temporary dstring */ + SPICE_DSTRING ustr ; /* temporary dstring */ + spice_dstring_init(&tstr) ; + spice_dstring_init(&ustr) ; ls = length (s); error = 0; i = 0; - j = spos ("//", s); /* stop before comment if any */ + j = spos_ ("//", s); /* stop before comment if any */ - if (j > 0) - ls = j - 1; + if (j >= 0) + ls = j ; /* bug: doesnt work. need to revise getexpress ... !!! */ i = 0; @@ -1975,8 +2080,9 @@ nupa_assignment (tdico * dico, char *s, char mode) while ((i < ls) && (!error)) { - key = getword (s, t, i, &i); - if ((t[0] == 0) || (key > 0)) + key = getword (s, &tstr, i, &i); + t_p = spice_dstring_value(&tstr) ; + if ((t_p[0] == 0) || (key > 0)) error = message (dico, " Identifier expected"); if (!error) @@ -1987,11 +2093,11 @@ nupa_assignment (tdico * dico, char *s, char mode) if (i > ls) error = message (dico, " = sign expected ."); - dtype = getexpress (s, u, &i); + dtype = getexpress (s, &ustr, &i); if (dtype == 'R') { - rval = formula (dico, u, &error); + rval = formula (dico, spice_dstring_value(&ustr), &error); if (error) { message (dico, " Formula() error."); @@ -2001,7 +2107,8 @@ nupa_assignment (tdico * dico, char *s, char mode) else if (dtype == 'S') wval = i; - err = define (dico, t, mode /* was ' ' */ , dtype, rval, wval, NULL); + err = define (dico, spice_dstring_value(&tstr), mode /* was ' ' */ , + dtype, rval, wval, NULL, NULL); error = error || err; } @@ -2010,7 +2117,8 @@ nupa_assignment (tdico * dico, char *s, char mode) else /* i++ */; } - Strdrem(t,u); + spice_dstring_free(&tstr) ; + spice_dstring_free(&ustr) ; return error; } @@ -2021,10 +2129,21 @@ nupa_subcktcall (tdico * dico, char *s, char *x, unsigned char err) */ { int n, m, i, j, k, g, h, narg = 0, ls, nest; - Str (80, subname); + SPICE_DSTRING subname ; + SPICE_DSTRING tstr ; + SPICE_DSTRING ustr ; + SPICE_DSTRING vstr ; + SPICE_DSTRING idlist ; + SPICE_DSTRING parsebuf ; char *buf, *token; + char *t_p ; + char *u_p ; unsigned char found; - Strfbig (dynLlen, t, u, v, idlist); + spice_dstring_init(&subname) ; + spice_dstring_init(&tstr) ; + spice_dstring_init(&ustr) ; + spice_dstring_init(&vstr) ; + spice_dstring_init(&idlist) ; /* skip over instance name -- fixes bug where instance 'x1' is same name as subckt 'x1' @@ -2035,164 +2154,172 @@ nupa_subcktcall (tdico * dico, char *s, char *x, unsigned char err) /***** first, analyze the subckt definition line */ n = 0; /* number of parameters if any */ ls = length (s); - j = spos ("//", s); + j = spos_ ("//", s); - if (j > 0) - pscopy_up (t, s, 1, j - 1); + if (j >= 0) + pscopy_up (&tstr, s, 0, j ); else - scopy_up (t, s); + scopy_up (&tstr, s); - j = spos ("SUBCKT", t); + j = spos_ ("SUBCKT", spice_dstring_value(&tstr) ) ; - if (j > 0) + if (j >= 0) { - j = j + 6; /* fetch its name */ - while ((j < ls) && (t[j] <= ' ')) + j = j + 6; /* fetch its name - skip subckt */ + t_p = spice_dstring_value(&tstr) ; + while ((j < ls) && (t_p[j] <= ' ')) j++; - while (t[j] != ' ') + while (t_p[j] != ' ') { - cadd (subname, t[j]); + cadd (&subname, t_p[j]); j++; } } else err = message (dico, " ! a subckt line!"); - i = spos ("PARAMS:", t); + i = spos_ ("PARAMS:", spice_dstring_value(&tstr)); - if (i > 0) + if (i >= 0) { - pscopy (t, t, i + 7, length (t)); - while (j = cpos ('=', t), j > 0) + pscopy (&tstr, spice_dstring_value(&tstr), i + 7, spice_dstring_length (&tstr)); + while (j = cpos ('=', spice_dstring_value(&tstr)), j >= 0) { /* isolate idents to the left of =-signs */ - k = j - 2; - while ((k >= 0) && (t[k] <= ' ')) + k = j - 1; + t_p = spice_dstring_value(&tstr) ; + while ((k >= 0) && (t_p[k] <= ' ')) k--; h = k; - while ((h >= 0) && alfanum (t[h])) + while ((h >= 0) && alfanum (t_p[h])) h--; - if (alfa (t[h + 1]) && (k > h)) + if (alfa (t_p[h + 1]) && (k > h)) { /* we have some id */ for (m = (h + 1); m <= k; m++) - cadd (idlist, t[m]); + cadd (&idlist, t_p[m]); - sadd (idlist, "=$;"); + sadd (&idlist, "=$;"); n++; } else message (dico, "identifier expected."); - pscopy (t, t, j + 1, length (t)); + /* It is j+1 to skip over the '=' */ + pscopy (&tstr, spice_dstring_value(&tstr), j+1, spice_dstring_length (&tstr)); } } /***** next, analyze the circuit call line */ if (!err) { narg = 0; - j = spos ("//", x); + j = spos_ ("//", x); - if (j > 0) - pscopy_up (t, x, 1, j - 1); - else - scopy_up (t, x); + if (j >= 0) + pscopy_up ( &tstr, x, 0, j ); + else { + scopy_up (&tstr, x); + j = 0 ; + } - ls = length (t); + ls = spice_dstring_length (&tstr); - buf = (char*) tmalloc(strlen(t) + 1); - strcpy(buf, t); + spice_dstring_init(&parsebuf) ; + scopyd(&parsebuf, &tstr) ; + buf = spice_dstring_value(&parsebuf) ; found = 0; token = strtok(buf, " "); /* a bit more exact - but not sufficient everytime */ j = j + strlen(token) + 1; - if (strcmp(token, subname)) { + if (strcmp(token, spice_dstring_value(&subname))) { while ((token = strtok(NULL, " "))) { - if (!strcmp(token, subname)) { + if (!strcmp(token, spice_dstring_value(&subname))) { found = 1; break; } j = j + strlen(token) + 1; } } - free(buf); + spice_dstring_free(&parsebuf) ; /* make sure that subname followed by space */ if (found) { - j = j + length (subname) + 1; /* 1st position of arglist: j */ + j = j + spice_dstring_length (&subname) + 1; /* 1st position of arglist: j */ - while ((j < ls) && ((t[j] <= ' ') || (t[j] == ','))) + t_p = spice_dstring_value(&tstr) ; + while ((j < ls) && ((t_p[j] <= ' ') || (t_p[j] == ','))) j++; while (j < ls) { /* try to fetch valid arguments */ k = j; - scopy (u, ""); - if ((t[k] == Intro)) + spice_dstring_reinit(&ustr) ; + if ((t_p[k] == Intro)) { /* handle historical syntax... */ - if (alfa (t[k + 1])) + if (alfa (t_p[k + 1])) k++; - else if (t[k + 1] == '(') + else if (t_p[k + 1] == '(') { /* transform to braces... */ k++; - t[k] = '{'; + t_p[k] = '{'; g = k; nest = 1; while ((nest > 0) && (g < ls)) { g++; - if (t[g] == '(') + if (t_p[g] == '(') nest++; - else if (t[g] == ')') + else if (t_p[g] == ')') nest--; } if ((g < ls) && (nest == 0)) - t[g] = '}'; + t_p[g] = '}'; } } - if (alfanum (t[k]) || t[k] == '.') + if (alfanum (t_p[k]) || t_p[k] == '.') { /* number, identifier */ h = k; - while (t[k] > ' ') + while (t_p[k] > ' ') k++; - pscopy (u, t, h + 1, k - h); + pscopy (&ustr, spice_dstring_value(&tstr), h, k - h); j = k; } - else if (t[k] == '{') + else if (t_p[k] == '{') { - getexpress (t, u, &j); + getexpress ( spice_dstring_value(&tstr), &ustr, &j); j--; /* confusion: j was in Turbo Pascal convention */ ; } else { j++; - if (t[k] > ' ') + if (t_p[k] > ' ') { - scopy (v, "Subckt call, symbol "); - cadd (v, t[k]); - sadd (v, " not understood"); - message (dico, v); + spice_dstring_append(&vstr, "Subckt call, symbol ",-1) ; + cadd (&vstr, t_p[k]); + sadd (&vstr, " not understood"); + message (dico, spice_dstring_value(&vstr) ) ; } } - if (u[0]) + u_p = spice_dstring_value(&ustr) ; + if (u_p[0]) { narg++; - k = cpos ('$', idlist); + k = cpos ('$', spice_dstring_value(&idlist)) ; - if (k > 0) + if (k >= 0) { /* replace dollar with expression string u */ - pscopy (v, idlist, 1, k - 1); - sadd (v, u); - pscopy (u, idlist, k + 1, length (idlist)); - scopy (idlist, v); - sadd (idlist, u); + pscopy (&vstr, spice_dstring_value(&idlist), 0, k); + sadd ( &vstr, spice_dstring_value(&ustr)) ; + pscopy (&ustr, spice_dstring_value(&idlist), k+1, spice_dstring_length (&idlist)); + scopyd (&idlist, &vstr); + sadd (&idlist, spice_dstring_value(&ustr)); } } } @@ -2204,17 +2331,22 @@ nupa_subcktcall (tdico * dico, char *s, char *x, unsigned char err) dicostack (dico, Push); /* create local symbol scope */ if (narg != n) { - scopy (t, " Mismatch: "); - nadd (t, n); - sadd (t, " formal but "); - nadd (t, narg); - sadd (t, " actual params."); - err = message (dico, t); - message (dico, idlist); + scopys(&tstr, " Mismatch: "); + nadd (&tstr, n); + sadd (&tstr, " formal but "); + nadd (&tstr, narg); + sadd (&tstr, " actual params."); + err = message (dico, spice_dstring_value(&tstr)); + message (dico, spice_dstring_value(&idlist)); /* ;} else { debugwarn(dico, idlist) */ ; } - err = nupa_assignment (dico, idlist, 'N'); - Strfrem(t,u,v,idlist); + err = nupa_assignment (dico, spice_dstring_value(&idlist), 'N'); + + spice_dstring_free(&subname) ; + spice_dstring_free(&tstr) ; + spice_dstring_free(&ustr) ; + spice_dstring_free(&vstr) ; + spice_dstring_free(&idlist) ; return err; } diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index 3c92beea9..b8ab996fc 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -781,12 +781,13 @@ bxx_printf(struct bxx_buffer *t, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - while(1) { - int size = t->limit - t->buffer; - int ret = vsnprintf(t->dst, size, fmt, ap); - if(ret == -1) { + int ret; + int size = t->limit - t->dst; + va_start(ap, fmt); + ret = vsnprintf(t->dst, size, fmt, ap); + va_end(ap); + if(ret == -1) { bxx_extend(t, bxx_chunksize); } else if(ret >= size) { bxx_extend(t, ret - size + 1); diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 560860e64..c16b8b0f6 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -46,6 +46,7 @@ noinst_HEADERS = \ gendev.h \ graph.h \ grid.h \ + hash.h \ hlpdefs.h \ iferrmsg.h \ ifsim.h \ diff --git a/src/include/inpptree.h b/src/include/inpptree.h index c4b828cd2..4a01f58f6 100644 --- a/src/include/inpptree.h +++ b/src/include/inpptree.h @@ -69,6 +69,7 @@ typedef struct INPparseNode { #define PT_CONSTANT 7 #define PT_VAR 8 #define PT_COMMA 10 +#define PT_TERN 11 /* These are the functions that we support. */ diff --git a/src/misc/Makefile.am b/src/misc/Makefile.am index 068f1f1d2..5f068d7ee 100644 --- a/src/misc/Makefile.am +++ b/src/misc/Makefile.am @@ -11,6 +11,7 @@ libmisc_la_SOURCES = \ alloc.h \ dup2.c \ dup2.h \ + hash.c \ ivars.c \ ivars.h \ mktemp.c \ diff --git a/src/spicelib/parser/ifeval.c b/src/spicelib/parser/ifeval.c index 3ddb002be..21aa35129 100644 --- a/src/spicelib/parser/ifeval.c +++ b/src/spicelib/parser/ifeval.c @@ -85,6 +85,25 @@ PTeval(INPparseNode * tree, double gmin, double *res, double *vals) } break; + case PT_TERN: + { + INPparseNode *arg1 = tree->left; + INPparseNode *arg2 = tree->right->left; + INPparseNode *arg3 = tree->right->right; + + err = PTeval(arg1, gmin, &r1, vals); + if (err != OK) + return (err); + + /*FIXME > 0.0, >= 0.5, != 0.0 or what ? */ + err = PTeval((r1 != 0.0) ? arg2 : arg3, gmin, &r2, vals); + if (err != OK) + return (err); + + *res = r2; + break; + } + case PT_PLUS: case PT_MINUS: case PT_TIMES: diff --git a/src/spicelib/parser/inpptree.c b/src/spicelib/parser/inpptree.c index 3726e5aec..5db3690ec 100644 --- a/src/spicelib/parser/inpptree.c +++ b/src/spicelib/parser/inpptree.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group **********/ +// #define TRACE #include "ngspice.h" #include "ifsim.h" @@ -227,6 +228,31 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum) } break; + + case PT_TERN: /* ternary_fcn(cond,exp1,exp2) */ + // naive: + // d/d ternary_fcn(cond,exp1,exp2) --> ternary_fcn(cond, d/d exp1, d/d exp2) + { + INPparseNode *arg1 = p->left; + INPparseNode *arg2 = p->right->left; + INPparseNode *arg3 = p->right->right; + +// extern void printTree(INPparseNode *); +// +// printf("debug: %s, PT_TERN: ", __func__); +// printTree(p); +// printf("\n"); + + newp = mkb(PT_TERN, arg1, mkb(PT_COMMA, + PTdifferentiate(arg2, varnum), + PTdifferentiate(arg3, varnum))); + +// printf("debug, %s, returns; ", __func__); +// printTree(newp); +// printf("\n"); + + return (newp); + } case PT_FUNCTION: /* Many cases. Set arg1 to the derivative of the function, @@ -491,11 +517,28 @@ static INPparseNode *mkb(int type, INPparseNode * left, return (left); } break; + + case PT_TERN: + if (left->type == PT_CONSTANT) + /*FIXME > 0.0, >= 0.5, != 0.0 or what ? */ + return ((left->constant != 0.0) ? right->left : right->right); + if((right->left->type == PT_CONSTANT) && + (right->right->type == PT_CONSTANT) && + (right->left->constant == right->right->constant)) + return (right->left); + break; + } + + p->type = type; + p->left = left; + p->right = right; + + if(type == PT_TERN) { + p->function = NULL; + p->funcname = NULL; + return (p); } - p->type = type; - p->left = left; - p->right = right; for (i = 0; i < NUM_OPS; i++) if (ops[i].number == type) @@ -563,6 +606,8 @@ static int PTcheck(INPparseNode * p) case PT_POWER: case PT_COMMA: return (PTcheck(p->left) && PTcheck(p->right)); + case PT_TERN: + return (PTcheck(p->left) && PTcheck(p->right->left) && PTcheck(p->right->right)); default: fprintf(stderr, "Internal error: bad node type %d\n", p->type); @@ -925,6 +970,29 @@ static INPparseNode *mkfnode(char *fname, INPparseNode * arg) } p->valueIndex = i; p->type = PT_VAR; + + } else if(!strcmp("ternary_fcn", buf)) { + +// extern void printTree(INPparseNode *); +// +// printf("debug: %s ternary_fcn: ", __func__); +// printTree(arg); +// printf("\n"); + + if(arg->type != PT_COMMA || arg->left->type != PT_COMMA) { + fprintf(stderr, "Error: bogus ternary_fcn form\n"); + return (NULL); + } else { + INPparseNode *arg1 = arg->left->left; + INPparseNode *arg2 = arg->left->right; + INPparseNode *arg3 = arg->right; + + p->type = PT_TERN; + p->left = arg1; + p->right = mkb(PT_COMMA, arg2, arg3); + } + + } else { for (i = 0; i < NUM_FUNCS; i++) if (!strcmp(funcs[i].name, buf)) @@ -1127,7 +1195,7 @@ static PTelement *PTlexer(char **line) #ifdef TRACE printf("PTlexer: token = %d, type = %d, left = '%s'\n", - el.token, el.type, sbuf); */ + el.token, el.type, sbuf); #endif return (&el); } @@ -1204,11 +1272,28 @@ void printTree(INPparseNode * pt) printf(")"); break; + + case PT_COMMA: + printf("("); + printTree(pt->left); + printf(") , ("); + printTree(pt->right); + printf(")"); + break; + case PT_FUNCTION: printf("%s (", pt->funcname); printTree(pt->left); printf(")"); break; + + case PT_TERN: + printf("ternary_fcn ("); + printTree(pt->left); + printf(") , ("); + printTree(pt->right); + printf(")"); + break; default: printf("oops"); diff --git a/visualc/vngspice.sln b/visualc/vngspice.sln index cbe5b5c52..61f6266ed 100644 --- a/visualc/vngspice.sln +++ b/visualc/vngspice.sln @@ -29,12 +29,12 @@ Global {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|Win32.Build.0 = Debug|Win32 {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|x64.ActiveCfg = Debug|x64 {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|x64.Build.0 = Debug|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.ActiveCfg = Debug|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.Build.0 = Debug|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.ActiveCfg = Release|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.Build.0 = Release|Win32 {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|x64.ActiveCfg = Release|x64 {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|x64.Build.0 = Release|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.ActiveCfg = release64|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.Build.0 = release64|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.ActiveCfg = release64|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.Build.0 = release64|x64 {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|x64.ActiveCfg = release64|x64 {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|x64.Build.0 = release64|x64 EndGlobalSection diff --git a/visualc/vngspice.vcproj b/visualc/vngspice.vcproj index 2b86f77c1..e0fd937ff 100644 --- a/visualc/vngspice.vcproj +++ b/visualc/vngspice.vcproj @@ -48,7 +48,7 @@ + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + +