From 3097c4e04bdcd142a34fee1700bf0ae27138a4e5 Mon Sep 17 00:00:00 2001 From: pnenzi Date: Mon, 8 Oct 2007 14:52:25 +0000 Subject: [PATCH] Improvements in numparam from Phil Barker --- ChangeLog | 10 ++ src/frontend/numparam/general.h | 56 ++++--- src/frontend/numparam/mystring.c | 210 +++++++++++++++-------- src/frontend/numparam/numpaif.h | 7 +- src/frontend/numparam/numparam.h | 36 ++-- src/frontend/numparam/nupatest.c | 58 +++---- src/frontend/numparam/spicenum.c | 207 +++++++++++++++++------ src/frontend/numparam/washprog.c | 130 +++++++-------- src/frontend/numparam/xpressn.c | 276 ++++++++++++++++++++----------- 9 files changed, 631 insertions(+), 359 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7409692d9..bcc58e94b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2207-10-8 Paolo Nenzi + * src/frontend/numparam/{general.h, mystring.c, numpaif.h, numparam.h, + nupatest.c, spicenum.c, washprog.c, xpressn.c}: Applied patch from Phil + Barker that improves the capabilites of numparam library. Now numparam + supports fully parametrized netlists and can handle a larger set of + parameters than the previous implementation. Added 'nupa_add_param' routine + and ability to reevaluate parameter set using 'nupa_eval' by keeping parameter + value set. Added support for 'ternary' operators in parameters as well as 'max' + and 'min'. + 2007-09-17 Paolo Nenzi * src/frontend/com_let.c: Applied patch from Friedrich Schmidt to fix the big in let command that prevented the following command to be diff --git a/src/frontend/numparam/general.h b/src/frontend/numparam/general.h index fcf033dc1..aac98f6cc 100644 --- a/src/frontend/numparam/general.h +++ b/src/frontend/numparam/general.h @@ -9,7 +9,7 @@ #define Proc void #define Begin { #define EndProc ;} - /* Func short ...(...) Begin...EndFunc */ + /* Func int ...(...) Begin...EndFunc */ #define Func #define EndFunc ;} /* If ... Then...ElsIf..Then...Else...EndIf */ @@ -94,7 +94,7 @@ Type(Byte, unsigned char) #ifndef Bool Type(Bool, unsigned char) #endif -Type(Word, unsigned short) +Type(Word, unsigned int) Type(Pchar, char AT) #define Intern static @@ -103,7 +103,7 @@ Type(Pchar, char AT) #define Tarray2(a,d,n,m) typedef d a[n][m]; #define Darray(a,d,n) d a[n]; -#define Const(x,y) const short x=y; +#define Const(x,y) const int x=y; #define Cconst(x,y) typedef enum {x=y} _n ## x; #define Aconst(a,tp,sze) tp a[sze] ={ @@ -136,7 +136,7 @@ Type(Pchar, char AT) #define Str(n,a) char a[n+3]={0,0,(char)n} /* n<255 ! */ #define Sini(s) sini(s,sizeof(s)-4) -Cconst(Maxstr,2004) /* was 255, string maxlen, may be up to 32000 or so */ +Cconst(Maxstr,15000) /* was 255, string maxlen, may be up to 32000 or so */ typedef char string[258]; @@ -146,37 +146,39 @@ Cconst(Bs, 8) Cconst(Lf, 10) Cconst(Cr, 13) -Proc sini( Pchar s, short i); -Proc sfix(Pchar s, short i, short max); -Func short maxlen(Pchar s); -Func Pchar pscopy( Pchar s, Pchar a, short i,short j); +Proc sini( Pchar s, int i); +Proc sfix(Pchar s, int i, int max); +Func int maxlen(Pchar s); +Func Pchar pscopy( Pchar s, Pchar a, int i,int j); +Func Pchar pscopy_up( Pchar s, Pchar a, int i,int j); Func Bool scopy( Pchar a, Pchar b); +Func Bool scopy_up( Pchar a, Pchar b); Func Bool ccopy( Pchar a, char c); Func Bool sadd( Pchar s, Pchar t); Func Bool nadd( Pchar s, long n); Func Bool cadd( Pchar s, char c); Func Bool sins( Pchar s, Pchar t); Func Bool cins( Pchar s, char c); -Func short cpos( char c, Pchar s); -Func short spos( Pchar sub, Pchar s); - -Func short length(Pchar s); +Func int cpos( char c, Pchar s); +Func int spos( Pchar sub, Pchar s); +int ci_prefix( register char *p, register char *s ); +Func int length(Pchar s); Func Bool steq(Pchar s, Pchar t); Func Bool stne(Pchar s, Pchar t); -Func short scompare(Pchar a, Pchar b); -Func short ord(char c); -Func short pred(short i); -Func short succ(short i); +Func int scompare(Pchar a, Pchar b); +Func int ord(char c); +Func int pred(int i); +Func int succ(int i); Proc stri(long n, Pchar s); -Proc strif(long n, short f, Pchar s); -Proc strf(double x, short a, short b, Pchar s); /* float -> string */ -Func long ival(Pchar s, short *err); -Func double rval(Pchar s, short *err); +Proc strif(long n, int f, Pchar s); +Proc strf(double x, int a, int b, Pchar s); /* float -> string */ +Func long ival(Pchar s, int *err); +Func double rval(Pchar s, int *err); Func char upcase(char c); Func char lowcase(char c); -Func short hi(long w); -Func short lo(long w); +Func int hi(long w); +Func int lo(long w); Func Bool odd(long x); Func Bool alfa(char c); Func Bool num(char c); @@ -191,12 +193,12 @@ Proc wi(long i); Proc rs( Pchar s); Func char rc(void); -Func short freadstr(Pfile f, Pchar s, short max); +Func int freadstr(Pfile f, Pchar s, int max); Func char freadc(Pfile f); Func long freadi(Pfile f); -Func long np_round(double d); /* sjb to avoid clash with round() in math.h */ -Func long np_trunc(double x); /* sjb to avoid clash with trunc() in math.h */ +Func long np_round(double d); // sjb to avoid clash with round() in math.h +Func long np_trunc(double x); // sjb to avoid clash with trunc() in math.h Func double sqr(double x); Func double absf(double x); /* abs */ Func long absi( long i); @@ -204,8 +206,8 @@ Func double frac(double x); Func Bool reset(Pfile f); Func Bool rewrite(Pfile f); -Proc rawcopy(Pointer a, Pointer b, short la, short lb); +Proc rawcopy(Pointer a, Pointer b, int la, int lb); Func Pointer new(long sz); Proc dispose(Pointer p); -Func Pchar newstring(short n); +Func Pchar newstring(int n); diff --git a/src/frontend/numparam/mystring.c b/src/frontend/numparam/mystring.c index cde0eaf67..47aa64395 100644 --- a/src/frontend/numparam/mystring.c +++ b/src/frontend/numparam/mystring.c @@ -11,6 +11,8 @@ extern unsigned _stklen= 32000; /* Turbo C default was only 4 K */ #include #include +#include +#include /* #include -- ceil floor */ #include "config.h" #ifdef HAS_WINDOWS @@ -23,6 +25,19 @@ extern unsigned _stklen= 32000; /* Turbo C default was only 4 K */ /***** primitive input-output ***/ +int +ci_prefix(register char *p, register char *s) +{ + while (*p) { + if ((isupper(*p) ? tolower(*p) : *p) != + (isupper(*s) ? tolower(*s) : *s)) + return(0); + p++; + s++; + } + return (1); +} + Proc wc(char c) Begin fputc(c, stdout) @@ -33,7 +48,7 @@ Begin wc('\n') EndProc Proc ws( Pchar s) Begin - short k=0; + int k=0; While s[k] !=0 Do wc(s[k]); Inc(k) Done @@ -48,8 +63,9 @@ EndProc Proc rs( Pchar s) Begin /*basic line input, limit= 80 chars */ - short max,i; + int max,i; char c; + exit(-1); max=maxlen(s); i=0; sini(s,max); If max>80 Then max=80 EndIf @@ -64,7 +80,7 @@ EndFunc Func char rc(void) Begin - short ls; + int ls; Str(80,s); rs(s); ls=length(s); If ls>0 Then @@ -95,23 +111,22 @@ Proc stringbug(Pchar op, Pchar s, Pchar t, char c) /* we brutally stop the program on string overflow */ Begin char rep=' '; - ws(" STRING overflow "); - ws(op); wln(); - ws(" Operand1: "); - ws(s); wln(); + fprintf( stderr, " STRING overflow %s\n", op ); + fprintf( stderr, " Operand1: %s\n", s ); If t != Null Then - ws(" Operand2: "); - ws(t); wln(); + fprintf( stderr, " Operand2: %s\n", t ); EndIf If c != 0 Then - wc('{'); wc(c); wc('}') + fprintf( stderr, "{%c}\n", c ); EndIf + fprintf( stderr, "Aborting...\n" ); + exit(1); ws(" [A]bort [I]gnore ? "); rep=rc(); If upcase(rep)=='A' Then exit(1) EndIf EndProc -Proc sini(Pchar s, short max) /* suppose s is allocated */ +Proc sini(Pchar s, int max) /* suppose s is allocated */ Begin If max<1 Then max=1 @@ -122,10 +137,10 @@ Begin s[1]= Hi(max); s[2]= Lo(max); EndProc -Proc sfix(Pchar s, short i, short max) +Proc sfix(Pchar s, int i, int max) /* suppose s is allocated and filled with non-zero stuff */ Begin - short j; + int j; If max<1 Then max=1 ElsIf max>Maxstr Then @@ -144,10 +159,10 @@ Begin EndProc Intern -Proc inistring(Pchar s, char c, short max) +Proc inistring(Pchar s, char c, int max) /* suppose s is allocated. empty it if c is zero ! */ Begin - short i=0; + int i=0; s[i]=c; If c!=0 Then Inc(i); s[i]=0 @@ -160,23 +175,23 @@ Begin s[i+1]= Hi(max); s[i+2]= Lo(max); EndProc -Func short length(Pchar s) +Func int length(Pchar s) Begin - short lg=0; + int lg=0; While NotZ(s[lg]) Do Inc(lg) Done return lg EndFunc -Func short maxlen(Pchar s) +Func int maxlen(Pchar s) Begin - short ls= length(s); + int ls= length(s); return Getmax(s,ls) EndFunc Func Bool sadd( Pchar s, Pchar t) Begin Bool ok; - short i=0, max, ls= length(s); + int i=0, max, ls= length(s); max= Getmax(s,ls); While (t[i] !=0) And (ls0 Then @@ -295,13 +328,13 @@ Begin return ok EndProc -Func Pchar pscopy(Pchar s, Pchar t, short start, short leng) +Func Pchar pscopy(Pchar s, Pchar t, int start, int leng) /* partial string copy, with Turbo Pascal convention for "start" */ /* BUG: position count starts at 1, not 0 ! */ Begin - short max= maxlen(s); /* keep it for later */ - short stop= length(t); - short i; + int max= maxlen(s); /* keep it for later */ + int stop= length(t); + int i; Bool ok= (max>=0) And (max<=Maxstr); If Not ok Then stringbug("copy target non-init", s, t, 0) @@ -327,17 +360,49 @@ Begin return s EndProc -Func short ord(char c) +Func Pchar pscopy_up(Pchar s, Pchar t, int start, int leng) +/* partial string copy, with Turbo Pascal convention for "start" */ +/* BUG: position count starts at 1, not 0 ! */ +Begin + int max= maxlen(s); /* keep it for later */ + int stop= length(t); + int i; + Bool ok= (max>=0) And (max<=Maxstr); + If Not ok Then + stringbug("copy target non-init", s, t, 0) + EndIf + If leng>max Then + leng=max; ok=False + EndIf + If start>stop Then /* nothing! */ + ok=False; + inistring(s,0,max) + Else + If (start+leng-1)>stop Then + leng = stop-start+1; + ok=False + EndIf + For i=0; i='a') And (c<='z')) Or ((c>='A') And (c<='Z')); + return ((c>='a') And (c<='z')) Or ((c>='A') And (c<='Z')) || c == '_' || c == '[' || c == ']'; EndFunc Func Bool num( char c) @@ -459,18 +524,17 @@ EndFunc Func Bool alfanum(char c) Begin return - ((c>='a') And (c<='z')) Or ((c>='A')And(c<='Z')) + alfa(c) Or ((c>='0')And(c<='9')) - Or (c=='_') EndFunc -Func short freadstr(Pfile f, Pchar s, short max) +Func int freadstr(Pfile f, Pchar s, int max) /* read a line from a file. BUG: long lines truncated without warning, ctrl chars are dumped. */ Begin char c; - short i=0, mxlen=maxlen(s); + int i=0, mxlen=maxlen(s); If mxlen0 Do - j=(short)(i Mod 10); + j=(int)(i Mod 10); i=(long)(i Div 10); t[k]=chr('0'+j); Inc(k) Done @@ -621,11 +685,11 @@ Begin return NotZ(x AND 1) EndFunc -Func short vali(Pchar s, long * i) +Func int vali(Pchar s, long * i) /* convert s to integer i. returns error code 0 if Ok */ /* BUG: almost identical to ival() with arg/return value swapped ... */ Begin - short k=0, digit=0, ls; + int k=0, digit=0, ls; long z=0; Bool minus=False, ok=True; char c; @@ -654,11 +718,11 @@ EndFunc Intern Func Bool match - (Pchar s, Pchar t, short n, short tstart, Bool testcase) + (Pchar s, Pchar t, int n, int tstart, Bool testcase) Begin /* returns 0 If tstart is out of range. But n may be 0 ? */ /* True if s matches t[tstart...tstart+n] */ - short i,j,lt; + int i,j,lt; Bool ok; char a,b; i=0; j=tstart; @@ -676,13 +740,13 @@ Begin EndFunc Intern -Func short posi(Pchar sub, Pchar s, short opt) +Func int posi(Pchar sub, Pchar s, int opt) /* find position of substring in s */ Begin /* opt=0: like Turbo Pascal */ /* opt=1: like Turbo Pascal Pos, but case insensitive */ /* opt=2: position in space separated wordlist for scanners */ - short a,b,k,j; + int a,b,k,j; Bool ok, tstcase; Str(250,t); ok=False; @@ -693,7 +757,7 @@ Begin cadd(t,' '); sadd(t,sub); cadd(t,' '); EndIf a= length(t); - b= (short)(length(s)-a); + b= (int)(length(s)-a); k=0; j=1; If a>0 Then /*Else return 0*/ While (k<=b) And (Not ok) Do @@ -710,20 +774,24 @@ Begin EndIf EndFunc -Func short spos(Pchar sub, Pchar s) +Func int spos(Pchar sub, Pchar s) /* equivalent to Turbo Pascal pos(). BUG: counts 1 ... length(s), not from 0 like C */ Begin - return posi( sub, s, 0) + char *ptr; + + if ( ( ptr = strstr( s, sub ) ) ) return strlen(s) - strlen(ptr) + 1; + else return 0; + EndFunc /**** float formatting with printf/scanf ******/ -Func short valr(Pchar s, double *r) +Func int valr(Pchar s, double *r) /* returns 0 if ok, else length of partial string ? */ Begin - short n=sscanf(s, "%lG", r); + int n=sscanf(s, "%lG", r); If n==1 Then return(0) Else @@ -731,12 +799,12 @@ Begin EndIf EndFunc -Proc strf( double x, short f1, short f2, Pchar t) +Proc strf( double x, int f1, int f2, Pchar t) /* e-format if f2<0, else f2 digits after the point, total width=f1 */ /* if f1=0, also e-format with f2 digits */ Begin /*default f1=17, f2=-1*/ Str(30,fmt); - short n,mlt; + int n,mlt; mlt=maxlen(t); cadd(fmt,'%'); If f1>0 Then @@ -746,7 +814,7 @@ Begin /*default f1=17, f2=-1*/ Else cadd(fmt,'.'); nadd(fmt,f2); - sadd(fmt,"lf") + sadd(fmt,"lg") EndIf Else cadd(fmt,'.'); @@ -757,11 +825,11 @@ Begin /*default f1=17, f2=-1*/ sfix(t,n, mlt); EndProc -Func double rval(Pchar s, short *err) +Func double rval(Pchar s, int *err) /* returns err=0 if ok, else length of partial string ? */ Begin double r= 0.0; - short n=sscanf(s, "%lG", &r); + int n=sscanf(s, "%lG", &r); If n==1 Then (*err)=0 Else @@ -770,10 +838,10 @@ Begin return r; EndFunc -Func long ival(Pchar s, short *err) +Func long ival(Pchar s, int *err) /* value of s as integer string. error code err= 0 if Ok */ Begin - short k=0, digit=0, ls; + int k=0, digit=0, ls; long z=0; Bool minus=False, ok=True; char c; @@ -807,7 +875,7 @@ Func long np_round(double x) Begin double u; long z; - short n; + int n; Str(40,s); u=2e9; If x>u Then diff --git a/src/frontend/numparam/numpaif.h b/src/frontend/numparam/numpaif.h index bb795c65d..31895897d 100644 --- a/src/frontend/numparam/numpaif.h +++ b/src/frontend/numparam/numpaif.h @@ -15,6 +15,11 @@ extern char * nupa_copy(char *s, int linenum); extern int nupa_eval(char *s, int linenum); extern int nupa_signal(int sig, char *info); -extern void nupa_scan(char * s, int linenum); +extern void nupa_scan(char * s, int linenum, int is_subckt); +extern void nupa_list_params(); +extern double nupa_get_param(char *param_name, int *found); +extern void nupa_add_param(char *param_name, double value); +extern void nupa_add_inst_param(char *param_name, double value); +extern void nupa_copy_inst_dico(); #endif /* NUMPAIF_H */ diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h index 04adc3175..786124313 100644 --- a/src/frontend/numparam/numparam.h +++ b/src/frontend/numparam/numparam.h @@ -17,27 +17,27 @@ Cconst(Nodekey,'#') /*introduces node symbol*/ Cconst(Intro ,'&') /*introduces preprocessor tokens*/ Cconst(Comment,'*') /*Spice Comment lines*/ Cconst(Pspice,'{') /*Pspice expression */ -Cconst(Maxdico,200) /*size of symbol table*/ +Cconst(Maxdico,40000) /*size of symbol table*/ /* Composite line length This used to be 250 characters, but this is too easy to exceed with a .model line, especially when spread over several continuation lines with much white space. I hope 1000 will be enough. */ -Cconst(Llen,1000) +Cconst(Llen,15000) -typedef char str20 [24]; +typedef char str50 [54]; typedef char str80 [84]; -Cconst(Maxline, 1000) /* size of initial unexpanded circuit code */ -Cconst(Maxckt, 5000) /* size of expanded circuit code */ +Cconst(Maxline, 40000) /* size of initial unexpanded circuit code */ +Cconst(Maxckt, 40000) /* size of expanded circuit code */ typedef Pchar auxtable; /* dummy */ Record(entry) char tp; /* type: I)nt R)eal S)tring F)unction M)acro P)ointer */ - str20 nom; - short level; /* subckt nesting level */ + char nom[100]; + int level; /* subckt nesting level */ double vl; /* float value if defined */ Word ivl; /*int value or string buffer index*/ Pchar sbbase; /* string buffer base address if any */ @@ -50,28 +50,32 @@ EndRec(fumas) Record(tdico) /* the input scanner data structure */ str80 srcfile; /* last piece of source file name */ - short srcline; - short errcount; + int srcline; + int errcount; entry dat[Maxdico+1]; - short nbd; /* number of data entries */ + int nbd; /* number of data entries */ fumas fms[101]; - short nfms; /* number of functions & macros */ - short stack[20]; - short tos; /* top of stack index for symbol mark/release mechanics */ - str20 option; /* one-character translator options */ + 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; Darray(refptr, Pchar, Maxline) /* pointers to source code lines */ Darray(category, char, Maxline) /* category of each line */ EndRec(tdico) Proc initdico(tdico * dico); -Func short donedico(tdico * dico); +Func int donedico(tdico * dico); Func Bool defsubckt( tdico *dico, Pchar s, Word w, char categ); -Func short findsubckt( tdico *dico, Pchar s, Pchar subname); +Func int findsubckt( tdico *dico, Pchar s, Pchar subname); Func Bool nupa_substitute( tdico *dico, Pchar s, Pchar r, Bool err); Func Bool nupa_assignment( tdico *dico, Pchar s, char mode); Func Bool nupa_subcktcall( tdico *dico, Pchar s, Pchar x, Bool err); Proc nupa_subcktexit( tdico *dico); Func tdico * nupa_fetchinstance(void); Func char getidtype( tdico *d, Pchar s); +Func int attrib( tdico *dico, Pchar t, char op ); +char *nupa_inst_name; +tdico *inst_dico; diff --git a/src/frontend/numparam/nupatest.c b/src/frontend/numparam/nupatest.c index 830a15e0e..858b58aac 100644 --- a/src/frontend/numparam/nupatest.c +++ b/src/frontend/numparam/nupatest.c @@ -18,10 +18,10 @@ Cconst(pfxsep,'_') /* official prefix separator is ':' not '_' ! */ Darray(buff, Pchar, Maxline) /* input lines */ Darray(buf2, Pchar, Maxline) /* stripped lines */ Darray(pxbuf, Pchar, Maxline) /* prefix for subnodes */ -Darray(runbuf, short, Maxckt) /* index list of expanded circuit */ -Darray(pindex, short, Maxckt) /* prefix index list */ -short irunbuf= 0; /* count lines of runbuf */ -short ipx=0; /* count prefixes in pxbuf */ +Darray(runbuf, int, Maxckt) /* index list of expanded circuit */ +Darray(pindex, int, Maxckt) /* prefix index list */ +int irunbuf= 0; /* count lines of runbuf */ +int ipx=0; /* count prefixes in pxbuf */ /* this toy imitates the Spice subcircuit expansion. @@ -49,15 +49,15 @@ and substitute node/device name arguments. */ -Func short runscript( tdico *dico, Pchar prefix, - short istart, short istop, short maxnest) +Func int runscript( tdico *dico, Pchar prefix, + int istart, int istop, int maxnest) /* recursive top-down expansion: circuit --> list of line numbers */ /* keep it simple,stupid compared to Spice's code */ /* prefix: inherited string for node & device prefixing */ /* istart, istop: allowed interval in table buf[], buf2[]. */ /* return value: number of lines included */ Begin - short i,j, idef, nnest, nline, dn, myipx; + int i,j, idef, nnest, nline, dn, myipx; Strbig(Llen, subpfx); /* subckt prefix */ Str(80, subname); char c; @@ -113,10 +113,10 @@ Begin return nline EndProc -Proc gluepluslines( short imax) +Proc gluepluslines( int imax) /* general sweep to eliminate continuation lines */ Begin - short i,j,k, ls, p; + int i,j,k, ls, p; Strbig(Llen,s); i=1; While i<= imax Do @@ -145,10 +145,10 @@ EndProc #if 0 /* sjb - this is in mystring.c */ Proc rs(Pchar s) /* 78 coumn limit */ Begin - short i; + int i; Bool done; char c; - short max=maxlen(s); + int max=maxlen(s); If max>78 Then max=78 EndIf i=0; done=False; scopy(s,""); @@ -173,9 +173,9 @@ Begin EndProc Intern -Proc freadln(Pfile f, Pchar s, short max) +Proc freadln(Pfile f, Pchar s, int max) Begin - short ls; + int ls; freadstr(f,s,max); ls=length(s); If feof(f) And (ls>0) Then @@ -183,21 +183,21 @@ Begin EndIf /* kill EOF character */ EndProc -Proc wordinsert(Pchar s, Pchar w, short i) +Proc wordinsert(Pchar s, Pchar w, int i) /* insert w before s[i] */ Begin Strbig(Llen,t); - short ls=length(s); + int ls=length(s); pscopy(t,s,i+1,ls); pscopy(s,s,1,i); sadd(s,w); sadd(s,t); EndProc -Func short worddelete(Pchar s, short i) +Func int worddelete(Pchar s, int i) /* delete word starting at s[i] */ Begin Strbig(Llen,t); - short ls= length(s); - short j=i; + int ls= length(s); + int j=i; While (j' ') Do Inc(j) Done pscopy(t,s,j+1,ls); pscopy(s,s,1,i); @@ -205,9 +205,9 @@ Begin return j-i /* nb of chars deleted */ EndProc -Func short getnextword(Pchar s, Pchar u, short j) +Func int getnextword(Pchar s, Pchar u, int j) Begin - short ls,k; + int ls,k; ls= length(s); k=j; While (j ' ') Do Inc(j) Done /* skip current word */ @@ -216,10 +216,10 @@ Begin return j EndFunc -Func short inwordlist(Pchar u, Pchar wl) +Func int inwordlist(Pchar u, Pchar wl) /* suppose wl is single-space separated, plus 1 space at start and end. */ Begin - short n,p,k; + int n,p,k; Str(80,t); n=0; ccopy(t,' '); sadd(t,u); cadd(t,' '); @@ -232,9 +232,9 @@ Begin return n EndFunc -Proc takewordlist(Pchar u, short k, Pchar wl) +Proc takewordlist(Pchar u, int k, Pchar wl) Begin - short i,j,lwl; + int i,j,lwl; lwl= length(wl); i=0; j=0; scopy(u,""); @@ -268,8 +268,8 @@ Reminder on Numparam symbols: cannot re-use a model name as a param name elsewhere, for example. */ Begin - short i,j,k,ls, jnext, dsize; - short dtype, nodes, subdv; + int i,j,k,ls, jnext, dsize; + int dtype, nodes, subdv; Bool done; char leadchar; Str(80,u); Str(80,v); Str(80,pfx); @@ -324,10 +324,10 @@ Begin EndIf EndProc -Proc getnodelist(Pchar form, Pchar act, Pchar s, tdico *dic, short k) +Proc getnodelist(Pchar form, Pchar act, Pchar s, tdico *dic, int k) /* the line s contains the actual node parameters, between 1st & last word */ Begin - short j,ls, idef; + int j,ls, idef; Str(80,u); Strbig(Llen,t); ccopy(act,' '); ccopy(form,' '); j=0; ls= length(s); @@ -364,7 +364,7 @@ Begin /* Strbig(Llen, formals); Strbig(Llen,actuals); */ Darray(formals, Pchar, 10) Darray(actuals, Pchar, 10) - short i, j, k, nline, parstack; + int i, j, k, nline, parstack; For i=0; i #include +#include +#include #ifdef __TURBOC__ #include /* exit() */ #endif #include "general.h" #include "numparam.h" +#include "ngspice.h" + +extern void txfree(void *ptr); /* Uncomment this line to allow debug tracing */ -/* #define TRACE_NUMPARAMS */ +/*#define TRACE_NUMPARAMS*/ /* the nupa_signal arguments sent from Spice: @@ -58,10 +63,10 @@ Intern long placeholder= 0; #ifdef NOT_REQUIRED /* SJB - not required as front-end now does stripping */ Intern -Func short stripcomment( Pchar s) +Func int stripcomment( Pchar s) /* allow end-of-line comments in Spice, like C++ */ Begin - short i,ls; + int i,ls; char c,d; Bool stop; ls=length(s); @@ -91,7 +96,7 @@ Proc stripsomespace(Pchar s, Bool incontrol) Begin /* iff s starts with one of some markers, strip leading space */ Str(12,markers); - short i,ls; + int i,ls; scopy(markers,"*.&+#$"); If Not incontrol Then sadd(markers,"xX") @@ -110,7 +115,7 @@ Proc partition(Pchar t) /* bug: strip trailing spaces */ Begin Strbig(Llen,u); - short i,lt,state; + int i,lt,state; char c; cadd(u,Intro); state=0; /* a trivial 3-state machine */ @@ -139,10 +144,10 @@ EndProc #endif Intern -Func short stripbraces( Pchar s) +Func int stripbraces( Pchar s) /* puts the funny placeholders. returns the number of {...} substitutions */ Begin - short n,i,nest,ls,j; + int n,i,nest,ls,j; Strbig(Llen,t); n=0; ls=length(s); i=0; @@ -162,6 +167,13 @@ Begin Inc(placeholder); If t[i-1]>' ' Then cadd(t,' ') EndIf nadd(t, PlaceHold + placeholder); + cadd(t,' '); // add extra character to increase number significant digits for evaluated numbers + cadd(t,' '); + cadd(t,' '); + cadd(t,' '); + cadd(t,' '); + cadd(t,' '); + cadd(t,' '); If s[j]>=' ' Then cadd(t,' ') EndIf i=length(t); pscopy(s,s, j+1, ls); @@ -170,19 +182,19 @@ Begin Else Inc(i) EndIf - ls=length(s) + ls=length(s); Done return n EndFunc Intern -Func short findsubname(tdico * dico, Pchar s) +Func int findsubname(tdico * dico, Pchar s) /* 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 */ Begin Str(80, name); - short h,j,k,nest,ls; + int h,j,k,nest,ls; Bool found; h=0; ls=length(s); @@ -207,7 +219,7 @@ Begin Dec(k) EndIf; Done - found = (k>=0) And alfa(s[k+1]); /* suppose an identifier */ + found = (k>=0) And alfanum(s[k+1]); /* suppose an identifier */ If found Then /* check for known subckt name */ scopy(name,""); j= k+1; While alfanum(s[j]) Do @@ -227,7 +239,7 @@ Proc modernizeex( Pchar s) /* old style expressions &(..) and &id --> new style with braces. */ Begin Strbig(Llen,t); - short i,state, ls; + int i,state, ls; char c,d; i=0; state=0; ls= length(s); @@ -287,32 +299,31 @@ Func char transform(tdico * dico, Pchar s, Bool nostripping, Pchar u) Begin Strbig(Llen,t); char category; - short i,k, a,n; -/* i=stripcomment(s); sjb - not required now that front-end does stripping */ + int i,k, a,n; + stripsomespace(s, nostripping); modernizeex(s); /* required for stripbraces count */ scopy(u,""); If s[0]=='.' Then /* check Pspice parameter format */ - scopy(t,s); - stupcase(t); + scopy_up(t,s); k=1; While t[k]>' ' Do cadd(u, t[k]); Inc(k) Done - If spos(".PARAM",t) ==1 Then /* comment it out */ - s[0]='*'; + If ci_prefix(".PARAM",t) ==1 Then /* comment it out */ + /*s[0]='*';*/ category='P'; - ElsIf spos(".SUBCKT",t) ==1 Then /* split off any "params" tail */ + ElsIf ci_prefix(".SUBCKT",t) ==1 Then /* split off any "params" tail */ a= spos("PARAMS:",t); If a>0 Then pscopy(s,s,1,a-1); EndIf category='S'; - ElsIf spos(".CONTROL",t) ==1 Then + ElsIf ci_prefix(".CONTROL",t) ==1 Then category='C' - ElsIf spos(".ENDC",t) ==1 Then + ElsIf ci_prefix(".ENDC",t) ==1 Then category='E' - ElsIf spos(".ENDS",t) ==1 Then + ElsIf ci_prefix(".ENDS",t) ==1 Then category='U' Else category='.'; @@ -324,8 +335,7 @@ Begin category='P'; ElsIf upcase(s[0])=='X' Then /* strip actual parameters */ i=findsubname(dico, s); /* i= index following last identifier in s */ -/* pscopy(s,s,1,i); sjb - this is already done by findsubname() */ - category='X' + category='X'; ElsIf s[0]=='+' Then /* continuation line */ category='+' ElsIf cpos(s[0],"*$#")<=0 Then /* not a comment line! */ @@ -352,7 +362,7 @@ Intern int evalcount= 0; /* number of lines through nupa_eval() */ Intern int nblog=0; /* serial number of (debug) logfile */ Intern Bool inexpansion= False; /* flag subckt expansion phase */ Intern Bool incontrol= False; /* flag control code sections */ -Intern Bool dologfile= True; /* for debugging */ +Intern Bool dologfile= False; /* for debugging */ Intern Bool firstsignal=True; Intern Pfile logfile= Null; Intern tdico * dico=Null; @@ -390,14 +400,16 @@ EndProc Intern Proc nupa_init( Pchar srcfile) Begin - short i; + int i; /* init the symbol table and so on, before the first nupa_copy. */ evalcount=0; linecount= 0; incontrol=False; placeholder= 0; dico= New(tdico); + inst_dico = New(tdico); initdico(dico); + initdico(inst_dico); For i=0; irefptr[i]= Null; dico->category[i]='?'; @@ -409,9 +421,9 @@ EndProc Intern Proc nupa_done(void) Begin - short i; + int i; Str(80,rep); - short dictsize, nerrors; + int dictsize, nerrors; If logfile != Null Then fclose(logfile); logfile=Null; @@ -442,13 +454,102 @@ Begin EndProc /* SJB - Scan the line for subcircuits */ -Proc nupa_scan(Pchar s, int linenum) +Proc nupa_scan(Pchar s, int linenum, int is_subckt) Begin - If spos(".SUBCKT",s) ==1 Then - defsubckt( dico, s, linenum, 'U' ); - EndIf + + if ( is_subckt ) defsubckt( dico, s, linenum, 'U' ); + else defsubckt( dico, s, linenum, 'O' ); + EndProc +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; +} + +void +nupa_list_params(FILE *cp_out) { + char *name; + int i; + + fprintf( cp_out, "\n\n" ); + for ( i = 1; i <= dico->nbd+1; i++ ) { + if ( dico->dat[i].tp == 'R' ) { + name = lower_str( strdup( dico->dat[i].nom ) ); + fprintf( cp_out, " ---> %s = %g\n", name, dico->dat[i].vl ); + txfree(name); + } + } +} + +double +nupa_get_param( char *param_name, int *found ) { + char *name = upper_str(strdup(param_name)); + double result = 0; + int i; + + *found = 0; + + for ( i = 1; i <= dico->nbd+1; i++ ) { + if ( strcmp( dico->dat[i].nom, name ) == 0 ) { + result = dico->dat[i].vl; + *found = 1; + break; + } + } + + txfree(name); + 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' ); + + dico->dat[i].vl = value; + dico->dat[i].tp = 'R'; + dico->dat[i].ivl = 0; + dico->dat[i].sbbase = NULL; + + txfree(up_name); +} + +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' ); + + inst_dico->dat[i].vl = value; + inst_dico->dat[i].tp = 'R'; + inst_dico->dat[i].ivl = 0; + inst_dico->dat[i].sbbase = NULL; + + txfree( up_name ); +} + +void +nupa_copy_inst_dico() { + int i; + + for ( i = 1; i <= inst_dico->nbd; i++ ) { + nupa_add_param( inst_dico->dat[i].nom, inst_dico->dat[i].vl ); + } +} + Func Pchar nupa_copy(Pchar s, int linenum) /* returns a copy (not quite) of s in freshly allocated memory. linenum, for info only, is the source line number. @@ -466,8 +567,9 @@ Begin Strbig(Llen,u); Strbig(Llen,keywd); Pchar t; - short i,ls; + int ls; char c,d; + ls= length(s); While (ls>0) And (s[ls-1]<=' ') Do Dec(ls) Done pscopy(u,s, 1,ls); /* strip trailing space, CrLf and so on */ @@ -484,24 +586,16 @@ Begin If incontrol Then c='C' EndIf /* force it */ d= dico->category[linenum]; /* warning if already some strategic line! */ If (d=='P') Or (d=='S') Or (d=='X') Then - fputs(" Numparam warning: overwriting P,S or X line.\n",stderr); + fprintf(stderr," Numparam warning: overwriting P,S or X line (linenum == %d).\n", linenum); EndIf - If c=='S' Then - defsubckt( dico, s, linenum, 'U' ) - ElsIf steq(keywd,"MODEL") Then - defsubckt( dico, s, linenum, 'O' ) - EndIf; /* feed symbol table */ dico->category[linenum]= c; EndIf /* keep a local copy and mangle the string */ ls=length(u); - t= NewArr( char, ls+1); /* == (Pchar)malloc(ls+1); */ + t = strdup(u); If t==NULL Then fputs("Fatal: String malloc crash in nupa_copy()\n", stderr); exit(-1) Else - For i=0;i<=ls; Inc(i) Do - t[i]=u[i] - Done If Not inexpansion Then putlogfile(dico->category[linenum],linenum,t) EndIf; @@ -517,21 +611,29 @@ Func int nupa_eval(Pchar s, int linenum) All the X lines are preserved (commented out) in the expanded circuit. */ Begin - short idef; /* subckt definition line */ - char c; + int idef; /* subckt definition line */ + char c, keep, *ptr; + int i; Str(80,subname); + Bool err = True; + dico->srcline= linenum; c= dico->category[linenum]; #ifdef TRACE_NUMPARAMS - printf("** SJB - in nupa_eval()\n"); - printf("** SJB - processing line %3d: %s\n",linenum,s); - printf("** SJB - category '%c'\n",c); + fprintf(stderr,"** SJB - in nupa_eval()\n"); + fprintf(stderr,"** SJB - processing line %3d: %s\n",linenum,s); + fprintf(stderr,"** SJB - category '%c'\n",c); #endif /* TRACE_NUMPARAMS */ If c=='P' Then /* evaluate parameters */ nupa_assignment( dico, dico->refptr[linenum] , 'N'); ElsIf c=='B' Then /* substitute braces line */ - nupa_substitute( dico, dico->refptr[linenum], s, False); + err = nupa_substitute( dico, dico->refptr[linenum], s, False); ElsIf c=='X' Then /* compute args of subcircuit, if required */ + ptr = s; + while ( !isspace(*ptr) ) ptr++; keep = *ptr; *ptr = '\0'; + nupa_inst_name = strdup(s); *nupa_inst_name = 'x'; *ptr = keep; + for ( i = 0; i < strlen(nupa_inst_name); i++ ) nupa_inst_name[i] = toupper(nupa_inst_name[i]); + idef = findsubckt( dico, s, subname); If idef>0 Then nupa_subcktcall( dico, @@ -545,10 +647,12 @@ Begin putlogfile('e',linenum,s); Inc(evalcount); #ifdef TRACE_NUMPARAMS + fprintf(stderr,"** SJB - leaving nupa_eval(): %s %d\n", s, err); ws("** SJB - --> "); ws(s); wln(); ws("** SJB - leaving nupa_eval()"); wln(); wln(); #endif /* TRACE_NUMPARAMS */ - return 1 + if ( err ) return 0; + else return 1; EndFunc Func int nupa_signal(int sig, Pchar info) @@ -564,7 +668,8 @@ Begin ElsIf sig == NUPASUBSTART Then inexpansion=True ElsIf sig == NUPASUBDONE Then - inexpansion=False + inexpansion=False; + nupa_inst_name = NULL; ElsIf sig == NUPAEVALDONE Then nupa_done(); firstsignal=True diff --git a/src/frontend/numparam/washprog.c b/src/frontend/numparam/washprog.c index a53f14d8d..832a9bd0b 100644 --- a/src/frontend/numparam/washprog.c +++ b/src/frontend/numparam/washprog.c @@ -59,9 +59,9 @@ Cconst( Recursion, True) /* 20 % slower, re-substitute inside macro args */ Tarray(macargs, string, nargs) /* 0..9 macro copy args, 10: a wildcard */ /* global vars */ -short isr; /* nb of substitution rules */ +int isr; /* nb of substitution rules */ Bool cMode; /* a scanning options: c language mode */ -short lookmax; /* input lookahead max size */ +int lookmax; /* input lookahead max size */ Pfile fout; /* file filled by: echoOut macroOut translate traduire */ Tarray(str40, char, 44) @@ -73,25 +73,25 @@ Str(nsub, wildcard); /********* trivial io ***/ -Proc wsf( Pchar s, short fmt) +Proc wsf( Pchar s, int fmt) Begin - short k; + int k; For k=1; k<=fmt-length(s); Inc(k) Do wc(' ') Done ws(s) EndProc -Proc wcf(char c, short fmt) +Proc wcf(char c, int fmt) Begin - short k; + int k; For k=1; k<=fmt-1; Inc(k) Do wc(' ') Done wc(c) EndProc -Proc wif(long i, short fmt) +Proc wif(long i, int fmt) Begin /*default fmt=1*/ Str(30, s); nadd(s,i); @@ -100,8 +100,8 @@ EndProc Proc rln(Pchar s) /* 78 column limit */ Begin - short i; Bool done; char c; - short max=maxlen(s); + int i; Bool done; char c; + int max=maxlen(s); If max>78 Then max=78 EndIf i=0; done=False; scopy(s,""); @@ -116,10 +116,10 @@ EndProc /*****************/ -Proc saddn( Pchar s, Pchar t, short n) +Proc saddn( Pchar s, Pchar t, int n) Begin Strbig(Llen,u); - short lt= length(t); + int lt= length(t); If lt<= n Then sadd(s,t) Else @@ -130,7 +130,7 @@ EndProc Proc allocdata(void) Begin /* prevent any string overflow */ - short i; + int i; For i=0; i='0') And (c<='9'); - If num Then z= (short)( 10*z+ c - '0') EndIf + If num Then z= (int)( 10*z+ c - '0') EndIf Until Not num EndRep If (z>lookmax) And (z<255) Then lookmax= z @@ -169,10 +169,10 @@ EndProc /******** matching routines *******/ -Proc copySpace(Pchar s, Pchar t, short a, short b) /* a,b>0 ! Pascal indexing */ +Proc copySpace(Pchar s, Pchar t, int a, int b) /* a,b>0 ! Pascal indexing */ Begin /*echo any "nontrivial" whitespace t-->s */ - short lt,i,k, comment; + int lt,i,k, comment; Bool leader; char c; /*-StartProc-*/ @@ -182,7 +182,7 @@ Begin comment=0; /* for C type whitespaces 1 And 2*/ lt= length(t); If b>lt Then b=lt EndIf - For i=(short)(a-1); i0) And (c<' ') Then leader=True EndIf If cMode And (c=='/') And (t[i+1]=='*') Then comment=1 EndIf @@ -193,12 +193,12 @@ Begin Done EndProc -Func short skipCwhite(Pchar t, short j, short lt) /* assume C indexing */ +Func int skipCwhite(Pchar t, int j, int lt) /* assume C indexing */ Begin /* skip any C And C++ type whitespace in t, from j to lt */ /* returns j-1 If current char is no white at all! */ char c; - short comment; /*types 1 And 2! */ + int comment; /*types 1 And 2! */ /*t[j] may already be '/' ? */ comment=0; c=t[j]; /*If c>' ', we are done! */ If (c>0) And (c<=' ') Then @@ -217,13 +217,13 @@ Begin Inc(j); c=t[j]; Until (j>lt) Or ((comment==0) And (c>' ')) EndRep EndIf - return (short)(j-1); /* return last white-matching char position */ + return (int)(j-1); /* return last white-matching char position */ EndProc Func Bool simple(Pchar s) Begin /* check if no strange punctuations inside s */ char c; - short i,ls; + int i,ls; Bool found; /*-StartProc-*/ ls=length(s); @@ -235,13 +235,13 @@ Begin /* check if no strange punctuations inside s */ return Not found; EndFunc -Func Bool match(Pchar s, Pchar t, short n, short tstart) +Func Bool match(Pchar s, Pchar t, int n, int tstart) Begin /* test if t starts with substring s. returns 0 If tstart is out of range. But n may be 0 ? options: Singlechar wildcards "?" */ - short i,j,lt; + int i,j,lt; Bool ok; /*-StartProc-*/ i=0; j=tstart; @@ -254,14 +254,14 @@ Begin return ok EndFunc -Func short posi(Pchar sub, Pchar s) +Func int posi(Pchar sub, Pchar s) Begin /*re-defines Turbo Pos, result Pascal compatible */ - short a,b,k; + int a,b,k; Bool ok; /*-StartProc-*/ ok=False; a=length(sub); - b=(short)(length(s)-a); + b=(int)(length(s)-a); k=0; If a>0 Then /*Else return 0*/ While (k<=b) And (Not ok) Do @@ -276,10 +276,10 @@ Begin /*re-defines Turbo Pos, result Pascal compatible */ EndIf EndFunc -Func short matchwhite(Pchar s, Pchar t, short n, short tstart) +Func int matchwhite(Pchar s, Pchar t, int n, int tstart) Begin /* like match, but any whitespace in t matches space in s*/ - short i,j,lt; Bool ok; + int i,j,lt; Bool ok; /*-StartProc-*/ i=0; j=tstart; lt= length(t); @@ -302,23 +302,23 @@ Begin Inc(i); Inc(j); Done If ok Then - return (short)(j-tstart) + return (int)(j-tstart) Else - return (short)0 + return (int)0 EndIf EndFunc -Func short posizero(Pchar sub, Pchar s) +Func int posizero(Pchar sub, Pchar s) Begin /*another Pos */ /* substring search. like posi, but reject quotes & bracketed stuff */ - short a,b,k; + int a,b,k; Bool ok; - short blevel; + int blevel; char c; /*-StartProc-*/ ok=False; a=length(sub); - b=(short)(length(s)-a); + b=(int)(length(s)-a); k=0; blevel=0; If a>0 Then /*Else return 0*/ While (k<=b) And (Not ok) Do @@ -353,7 +353,7 @@ Begin /*another Pos */ EndIf EndFunc -Func short isMacro(Pchar s, char option, Pchar t, short tstart, +Func int isMacro(Pchar s, char option, Pchar t, int tstart, string maccopy[] ) /* s= macro template, t=buffer, maccopy = arg Array return value: number of characters matched, @@ -363,7 +363,7 @@ Func short isMacro(Pchar s, char option, Pchar t, short tstart, substitute 1 by maccopy[1] etc */ Begin - Darray(ps, short, nargs+1) + Darray(ps, int, nargs+1) Word j,k,dk,ls, lst, lmt, jmax, pj; Bool ok; char arg; @@ -371,7 +371,7 @@ Begin Str(40,st); /* returns >0 If comparison Ok == length of compared Pchar */ /*-StartProc-*/ k=0; - ok= (s[0]==t[tstart]); /* shortcut: how much does it accelerate ? some % */ + ok= (s[0]==t[tstart]); /* intcut: how much does it accelerate ? some % */ If ok Then ps[0]=0; ps[nargs]=0; /*only 1..9 are valid data, 10 filler templates*/ @@ -381,7 +381,7 @@ Begin ps[j]= cpos(arg,s); Until (j>=nargs) Or (ps[j]==0) EndRep ls= length(s); - ps[j]=(short)(ls+1); /*For last template chunk*/ + ps[j]=(int)(ls+1); /*For last template chunk*/ jmax=j; j=1; k=0; lmt=0; Repeat @@ -403,7 +403,7 @@ Begin Else If option=='u' Then pj= posizero(st,u); - If pj>0 Then lmt= matchwhite(st,u, lst, (short)(pj-1)) EndIf + If pj>0 Then lmt= matchwhite(st,u, lst, (int)(pj-1)) EndIf Else pj= posi(st,u) EndIf /* qs[j]= k+pj; is position in t*/ @@ -432,8 +432,8 @@ Begin return k EndFunc -Func short similar(Pchar s, char wilds, Pchar t, - short tstart, string maccopy[] ) +Func int similar(Pchar s, char wilds, Pchar t, + int tstart, string maccopy[] ) /* try to match s with t, then save the wildcard parts ins maccopy[] */ /* s=template, t=buffer, wilds= number of wildcards, maccopy=substitute */ /* return value: number of characters matched */ @@ -466,7 +466,7 @@ Begin k= (Word)(ps-1); While s[k]==wild Do Inc(k) Done endc=s[k]; /*End char to detect, at length */ - ok= match(s,t, (short)(ps-1), tstart); + ok= match(s,t, (int)(ps-1), tstart); If ok Then pscopy(u,t, (Word)(ps+tstart), (Word)255); j= cpos(endc, u); @@ -481,10 +481,10 @@ Begin return k EndProc -Func short addSubList(Pchar s, short isr) +Func int addSubList(Pchar s, int isr) /* add the rule s to the Rule list at isr */ Begin - short j,ls; + int j,ls; char c,d,endc; Bool start,stop; /*-StartProc-*/ @@ -592,7 +592,7 @@ Begin done= (f == Null); ok= Not done; While Not done Do - fgets(s,(short)80,f); + fgets(s,(int)80,f); isr=addSubList(s,isr); done= feof(f) Done @@ -630,8 +630,8 @@ EndFunc Bool washmore= True; /* flag that activates the postprocessor */ Strbig(Llen,obf); /* output buffer */ -short iobf=0; /* its index */ -short wstate=0; /* output state machine */ +int iobf=0; /* its index */ +int wstate=0; /* output state machine */ Proc washinit(void) Begin @@ -641,7 +641,7 @@ EndProc Proc washchar(char c) Begin /* state machine receives one character */ - short i; + int i; If Not washmore Then /* never leave state 0 */ fputc(c, fout) ElsIf wstate==0 Then /* buffer empty */ @@ -698,7 +698,7 @@ EndProc Proc washflush(void) Begin - short i; + int i; If NotZ(wstate) Then For i=0; i0) And (j0) And (j0; If ok And (srule[i]=='w') Then @@ -860,7 +860,7 @@ Begin Darray( mac, string, nargs) Pfile fin; Bool ok; - short i,sm, exclusion, idot; + int i,sm, exclusion, idot; char c,lastBf1; Word nbrep,nline; /*-StartProc-*/ @@ -906,7 +906,7 @@ Begin sm=0; i=0; If exclusion>0 Then i=exclusion; - sm=similar(replace[i], (char)0, bf, (short)0, mac); + sm=similar(replace[i], (char)0, bf, (int)0, mac); ok= sm>0 EndIf If Zero(exclusion) Then @@ -916,10 +916,10 @@ Begin If alfa(lastBf1) And (alfa(search[i][0])) Then sm=0 /*inside word*/ Else - sm= isMacro(search[i], srule[i], bf, (short)0,mac) + sm= isMacro(search[i], srule[i], bf, (int)0,mac) EndIf Else - sm=similar(search[i],wildcard[i],bf, (short)0, mac) + sm=similar(search[i],wildcard[i],bf, (int)0, mac) EndIf ok=sm>0; If ok And (srule[i]=='w') Then @@ -966,7 +966,7 @@ EndProc Func int main( int argc, Pchar argv[]) Begin Str(80,dico); - short istart= 1; + int istart= 1; Bool ok= True; /*-StartProc-*/ allocdata(); diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 626863ead..39621298c 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -6,30 +6,48 @@ #include /* for function message() only. */ #include +#include #include "general.h" #include "numparam.h" - +#include "ngspice.h" /************ keywords ************/ /* SJB - 150 chars is ample for this - see initkeys() */ Intern Str(150, keys); /*all my keywords*/ Intern Str(150, fmath); /* all math functions */ - + +static double +max( double x, double y ) +{ + return ( x > y ) ? x : y; +} + +static double +min( double x, double y ) +{ + return ( x < y ) ? x : y; +} + +static double +ternary_fcn( int conditional, double if_value, double else_value ) +{ + if ( conditional ) return if_value; + else return else_value; +} + Intern Proc initkeys(void) /* the list of reserved words */ Begin - scopy(keys, + scopy_up(keys, "and or not div mod if else end while macro funct defined" " include for to downto is var"); - stupcase(keys); - scopy(fmath, "sqr sqrt sin cos exp ln arctan abs pwr"); - stupcase(fmath); + scopy_up(fmath, "sqr sqrt sin cos exp ln arctan abs pwr max min int log ternary_fcn"); EndProc Intern -Func double mathfunction(short f, double z, double x) +Func double mathfunction(int f, double z, double x) /* the list of built-in functions. Patch 'fmath' and here to get more ...*/ Begin double y; @@ -42,8 +60,12 @@ Begin Case 6 Is y= ln(x) Case 7 Is y= atan(x) Case 8 Is y= fabs(x) - Case 9 Is y= exp( x* ln(fabs(z))) + Case 9 Is y= exp( x* ln(fabs(z))) /* pwr(,): the only one with 2 args */ + Case 10 Is y= max( x, z ) + Case 11 Is y= min( x, z ) + Case 12 Is y= trunc( x ) + Case 13 Is y= log(x) Default y=x EndSw return y EndFunc @@ -88,7 +110,7 @@ Begin EndProc /* Intern -Func short parsenode(auxtable *n, Pchar s) +Func int parsenode(auxtable *n, Pchar s) Begin return 0 EndFunc @@ -98,14 +120,14 @@ EndFunc Proc initdico(tdico * dico) Begin - short i; + int i; dico->nbd=0; Sini(dico->option); Sini(dico->srcfile); dico->srcline= -1; dico->errcount= 0; For i=0; i<=Maxdico; Inc(i) Do - sini(dico->dat[i].nom,20) + sini(dico->dat[i].nom,100) Done dico->tos= 0; dico->stack[dico->tos]= 0; /* global data beneath */ @@ -127,12 +149,15 @@ Intern Proc dicostack(tdico *dico, char op) /* push or pop operation for nested subcircuit locals */ Begin + char *param_name, *inst_name; + int i, current_stack_size, old_stack_size; If op==Push Then If dico->tos < (20-1) Then Inc(dico->tos) Else message(dico, " Subckt Stack overflow") EndIf dico->stack [dico->tos]= dico->nbd; + dico->inst_name[dico->tos] = nupa_inst_name; ElsIf op==Pop Then /* obsolete: undefine all data items of level dico->tos For i=dico->nbd; i>0; Dec(i) Do @@ -143,29 +168,44 @@ Begin Done */ If dico->tos >0 Then + // keep instance parameters around + current_stack_size = dico->nbd; + old_stack_size = dico->stack[dico->tos]; + inst_name = dico->inst_name[dico->tos]; + + for ( i = old_stack_size+1; i <= current_stack_size; i++ ) { + param_name = tmalloc( strlen(inst_name) + strlen(dico->dat[i].nom) + 2 ); + sprintf( param_name, "%s.%s", inst_name, dico->dat[i].nom ); + nupa_add_inst_param( param_name, dico->dat[i].vl ); + tfree(param_name); + } + tfree(inst_name); + dico->nbd= dico->stack[dico->tos]; /* simply kill all local items */ - Dec(dico->tos) + Dec(dico->tos); + Else message(dico," Subckt Stack underflow.") EndIf EndIf EndProc -Func short donedico(tdico * dico) +Func int donedico(tdico * dico) Begin - short sze= dico->nbd; + int sze= dico->nbd; donesymbols(Addr(dico->nodetab)); return sze; EndProc Intern -Func short entrynb( tdico * d, Pchar s) +Func int entrynb( tdico * d, Pchar s) /* symbol lookup from end to start, for stacked local symbols .*/ /* bug: sometimes we need access to same-name symbol, at lower level? */ Begin - short i; + int i; Bool ok; ok=False; i=d->nbd+1; + While (Not ok) And (i>1) Do Dec(i); ok= steq(d->dat[i].nom, s); @@ -181,7 +221,7 @@ Func char getidtype( tdico *d, Pchar s) /* test if identifier s is known. Answer its type, or '?' if not in list */ Begin char itp='?'; /* assume unknown */ - short i= entrynb(d, s); + int i= entrynb(d, s); If i >0 Then itp= d->dat[i].tp EndIf return itp EndFunc @@ -209,7 +249,8 @@ Begin Else u=0.0; scopy(s,"Undefined number ["); sadd(s,t); cadd(s,']'); - err=message( dico, s) + err=message( dico, s); + EndIf *perr= err; return u @@ -217,13 +258,12 @@ EndFunc /******* writing dictionary entries *********/ -Intern -Func short attrib( tdico * dico, Pchar t, char op) +Func int attrib( tdico * dico, Pchar t, char op) Begin /* seek or attribute dico entry number for string t. Option op='N' : force a new entry, if tos>level and old is valid. */ - short i; + int i; Bool ok; i=dico->nbd+1; ok=False; @@ -267,7 +307,7 @@ Begin we already make symbol entries which are dummy globals ! we mark each id with its subckt level, and warn if write at higher one. */ - short i; + int i; char c; Bool err, warn; Strbig(Llen,v); @@ -275,7 +315,7 @@ Begin err=False; If i<=0 Then err=message( dico," Symbol table overflow") - Else + Else If dico->dat[i].tp=='P' Then i= dico->dat[i].ivl EndIf; /*pointer indirection*/ @@ -284,6 +324,7 @@ Begin Else c=' ' EndIf + If (c=='R') Or (c=='S') Or (c=='?') Then dico->dat[i].vl=z; dico->dat[i].tp=tpe; @@ -316,7 +357,7 @@ Func Bool defsubckt(tdico *dico, Pchar s, Word w, char categ) Begin Str(80,u); Bool err; - short i,j,ls; + int i,j,ls; ls=length(s); i=0; While (i' ') Do Inc(j) Done - If (j>i) And alfa(s[i]) Then - pscopy(u,s, i+1, j-i); - stupcase(u); + If (j>i) Then + pscopy_up(u,s, i+1, j-i); err= define( dico, u, ' ',categ, 0.0, w, Null); Else err= message( dico,"Subcircuit or Model without name."); @@ -334,23 +374,22 @@ Begin return err EndFunc -Func short findsubckt( tdico *dico, Pchar s, Pchar subname) +Func int findsubckt( tdico *dico, Pchar s, Pchar 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 */ Begin Str(80,u); /* u= subckt name is last token in string s */ - short i,j,k; + int i,j,k; k=length(s); While (k>=0) And (s[k]<=' ') Do Dec(k) Done j=k; While (k>=0) And (s[k]>' ') Do Dec(k) Done - pscopy(u,s, k+2, j-k); - stupcase(u); + pscopy_up(u,s, k+2, j-k); i= entrynb(dico,u); If (i>0) And (dico->dat[i].tp == 'U') Then i= dico->dat[i].ivl; - scopy(subname,u) + scopy(subname,u); Else i= 0; scopy(subname,""); @@ -361,7 +400,7 @@ EndFunc #if 0 /* unused, from the full macro language... */ Intern -Func short deffuma( /* define function or macro entry. */ +Func int deffuma( /* define function or macro entry. */ tdico * dico, Pchar t, char tpe, Word bufstart, Bool * pjumped, Bool * perr) Begin @@ -369,7 +408,7 @@ Begin /* if not jumped, define new function or macro, returns index to buffferstart if jumped, return index to existing function */ - short i,j; + int i,j; Strbig(Llen, v); i=attrib(dico,t,' '); j=0; If i<=0 Then @@ -402,7 +441,7 @@ Func Byte keyword( Pchar keys, Pchar t) Begin /* return 0 if t not found in list keys, else the ordinal number */ Byte i,j,k; - short lt,lk; + int lt,lk; Bool ok; lt=length(t); lk=length(keys); @@ -432,7 +471,7 @@ Intern Func double parseunit( double x, Pchar s) /* the Spice suffixes */ Begin - double u; + double u = 0; Str(20, t); Bool isunit; isunit=True; @@ -461,9 +500,9 @@ Begin EndFunc Intern -Func short fetchid( +Func int fetchid( Pchar s, Pchar t, - short ls, short i) + int ls, int i) /* copy next identifier from s into t, advance and return scan index i */ Begin char c; @@ -482,7 +521,7 @@ Begin c=Nul EndIf c= upcase(c); - ok= ((c>='0') And (c<='9')) Or ((c>='A') And (c<='Z')); + ok= alfanum(c) || c == '.'; If ok Then cadd(t,c) EndIf Until Not ok EndRep return i /*return updated i */ @@ -492,14 +531,14 @@ Intern Func double exists( tdico * d, Pchar s, - short * pi, + int * pi, Bool * perror) /* check if s in smboltable 'defined': expect (ident) and return 0 or 1 */ Begin Bool error= *perror; - short i= *pi; + int i= *pi; double x; - short ls; + int ls; char c; Bool ok; Strbig(Llen, t); @@ -537,14 +576,14 @@ EndFunc Intern Func double fetchnumber( tdico *dico, - Pchar s, short ls, - short * pi, + Pchar s, int ls, + int * pi, Bool * perror) /* parse a Spice number in string s */ Begin Bool error= *perror; - short i= *pi; - short k,err; + int i= *pi; + int k,err; char d; Str(20, t); Strbig(Llen, v); @@ -602,15 +641,15 @@ EndFunc Intern Func char fetchoperator( tdico *dico, - Pchar s, short ls, - short * pi, + Pchar s, int ls, + int * pi, Byte * pstate, Byte * plevel, Bool * perror) /* grab an operator from string s and advance scan index pi. each operator has: one-char alias, precedence level, new interpreter state. */ Begin - short i= *pi; + int i= *pi; Byte state= *pstate; Byte level= *plevel; Bool error= *perror; @@ -729,7 +768,7 @@ Begin If tls Then @@ -812,7 +853,10 @@ Begin ElsIf d==')' Then Dec(level) EndIf - If (d==',') And (level==1) Then arg2=k EndIf /* comma list? */ + If (d==',') And (level==1) Then + if ( arg2 == 0 ) { arg2 = k; } + else { arg3 = k; } // kludge for more than 2 args (ternary expression) + EndIf /* comma list? */ Until (k>ls) Or ((d==')') And (level<=0)) EndRep If k>ls Then error=message( dico,"Closing \")\" not found."); @@ -823,11 +867,17 @@ Begin v=formula( dico, t, Addr(error)); i=arg2; EndIf + if ( arg3 > i ) { + pscopy(t,s,i+1, arg3-i-1); + w=formula( dico, t, Addr(error)); + i = arg3; + } pscopy(t,s,i+1, k-i-1); - u=formula( dico, t, Addr(error)); + u=formula( dico, t, Addr(error)); state=1; /*atom*/ If fu>0 Then - u= mathfunction(fu,v,u) + if ( fu == 14 ) u= ternary_fcn(v,w,u); + else u= mathfunction(fu,v,u); EndIf EndIf i=k; fu=0; @@ -839,18 +889,22 @@ Begin If kw==0 Then fu= keyword(fmath,t); /* numeric function? */ If fu==0 Then - u=fetchnumentry( dico, t, Addr(error)) + u=fetchnumentry( dico, t, Addr(error)); Else - state=0 + state=0; EndIf /* state==0 means: ignore for the moment */ Else - c=opfunctkey( dico, kw,c, Addr(state), Addr(level) ,Addr(error)) + c=opfunctkey( dico, kw,c, Addr(state), Addr(level) ,Addr(error)); EndIf If kw==Defd Then - u=exists( dico, s, Addr(i), Addr(error)) + u=exists( dico, s, Addr(i), Addr(error)); EndIf ElsIf ((c=='.') Or ((c>='0') And (c<='9'))) Then u=fetchnumber( dico, s,ls, Addr(i), Addr(error)); + if ( negate ) { + u = -1*u; + negate = False; + } state=1; Else c=fetchoperator(dico, s,ls, @@ -859,6 +913,11 @@ Begin EndIf /* control chars <' ' ignored*/ ok= (oldstate==0) Or (state==0) Or ((oldstate==1) And (state==2)) Or ((oldstate!=1)And(state!=2)); + if ( oldstate == 2 && state == 2 && c == '-' ) { + ok = 1; + negate = True; + continue; + } If Not ok Then error=message( dico," Misplaced operator") EndIf @@ -870,7 +929,7 @@ Begin state=4; level=topop EndIf /*close all ops below*/ For k=ustack; k>=1; Dec(k) Do - u=operate(uop[k],u,u) + u=operate(uop[k],u,u); Done ustack=0; accu[0]=u; /* done: all pending unary operators */ @@ -892,11 +951,16 @@ Begin sadd(t,s); error=message( dico,t) EndIf + + if ( negate == True ) { + error = message( dico, " Problem with formula eval -- wrongly determined negation!" ); + } + *perror= error; If error Then - return 1.0 + return 1.0; Else - return accu[topop] + return accu[topop]; EndIf EndFunc /*formula*/ @@ -906,7 +970,7 @@ Begin /* I=integer, P=fixedpoint F=floatpoint*/ /* find out the "natural" type of format for number x*/ double ax,dx; - short rx; + int rx; Bool isint,astronomic; ax=absf(x); isint=False; @@ -938,7 +1002,7 @@ Func Bool evaluate( Begin /* transform t to result q. mode 0: expression, mode 1: simple variable */ double u=0.0; - short k,j,lq; + int k,j,lq; char dt,fmt; Bool numeric, done, nolookup; Bool err; @@ -990,7 +1054,8 @@ Begin If fmt=='I' Then stri(np_round(u), q) Else - strf(u,6,-1,q) + //strf(u,6,-1,q); + strf(u,17,10,q); EndIf /* strf() arg 2 doesnt work: always >10 significant digits ! */ EndIf return err; @@ -1004,7 +1069,7 @@ Func Bool scanline( Bool err) /* scan host code line s for macro substitution. r=result line */ Begin - short i,k,ls,level,nd, nnest; + int i,k,ls,level,nd, nnest; Bool spice3; char c,d; Strbig(Llen, q); @@ -1120,7 +1185,7 @@ Proc compactfloatnb(Pchar v) /* erase superfluous 000 digit streams before E */ /* bug: truncating, no rounding */ Begin - short n,k, lex; + int n,k, lex; Str(20,expo); n=cpos('E',v); /* if too long, try to delete digits */ If n >3 Then @@ -1128,28 +1193,28 @@ Begin lex= length(expo); k=n-2; /* mantissa is 0...k */ While (v[k]=='0') And (v[k-1]=='0') Do Dec(k) Done - If (k+1+lex) > 10 Then k= 9-lex EndIf + If (k+1+lex) > 17 Then k= 17-lex EndIf pscopy(v,v, 1,k+1); sadd(v,expo); EndIf EndProc Intern -Func short insertnumber(tdico *dico, short i, Pchar s, Pchar u) +Func int insertnumber(tdico *dico, int i, Pchar s, Pchar u) /* insert u in string s in place of the next placeholder number */ Begin Str(40,v); Str(80,msg); Bool found; - short ls, k; + int ls, k; long accu; ls= length(s); scopy(v,u); compactfloatnb(v); - While length(v)<10 Do + While length(v)<17 Do cadd(v,' ') Done - If length(v)>10 Then + If length(v)>17 Then scopy(msg," insertnumber fails: "); sadd(msg,u); message( dico, msg) @@ -1167,16 +1232,17 @@ Begin Done If found Then accu=accu - 1000000000L; /* plausibility test */ - found= (accu>0) And (accu<2000) + found= (accu>0) And (accu<40000) EndIf Inc(i) Done If found Then /* substitute at i-1 */ Dec(i); - For k=0; k<10; Inc(k) Do s[i+k]= v[k] Done - i= i+10; + For k=0; k<17; Inc(k) Do s[i+k]= v[k] Done + i= i+17; Else i= ls; + fprintf(stderr,"xpressn.c--insertnumber: i=%d s=%s u=%s\n",i,s,u); message( dico,"insertnumber: missing slot "); EndIf return i @@ -1189,7 +1255,7 @@ Func Bool nupa_substitute( tdico *dico, Pchar s, Pchar r, Bool err) bug: wont flag overflow! */ Begin - short i,k,ls,level, nnest, ir; + int i,k,ls,level, nnest, ir; char c,d; Strbig(Llen, q); Strbig(Llen, t); @@ -1261,7 +1327,7 @@ Begin i= k-1; EndIf If Not err Then - ir= insertnumber(dico, ir, r,q) + ir= insertnumber(dico, ir, r,q); Else message( dico, "Cannot compute &(expression)") EndIf @@ -1273,12 +1339,12 @@ EndFunc Intern Func Byte getword( Pchar s, Pchar t, - Byte after, - short * pi) + int after, + int * pi) /* isolate a word from s after position "after". return i= last read+1 */ Begin - short i= *pi; - short ls; + int i= *pi; + int ls; Byte key; i=after; ls=length(s); @@ -1300,14 +1366,14 @@ Begin EndFunc Intern -Func char getexpress( Pchar s, Pchar t, short * pi) +Func char getexpress( Pchar s, Pchar t, 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 */ Begin - short i= *pi; - short ia,ls,level; + int i= *pi; + int ia,ls,level; char c,d, tpe; Bool comment= False; ls=length(s); @@ -1315,10 +1381,10 @@ Begin While (ia0 Then pscopy(t,s,1,j-1) Else scopy(t,s) EndIf - stupcase(t); + If j>0 Then pscopy_up(t,s,1,j-1) Else scopy_up(t,s) EndIf j= spos("SUBCKT", t); If j>0 Then j= j +6; /* fetch its name */ While (j0 Then pscopy(t,x,1,j-1) Else scopy(t,x) EndIf - stupcase(t); + If j>0 Then pscopy_up(t,x,1,j-1) Else scopy_up(t,x) EndIf ls=length(t); - j= spos(subname,t); + j= spos(subname,t); + + /* make sure that subname followed by space */ + while ( j > 0 && *(t+j+length(subname)-1) > ' ' ) { + j = j+length(subname)-1 + spos( subname, t+j+length(subname)-1 ); + } + If j>0 Then j=j + length(subname) -1; /* 1st position of arglist: j */ While (j ' ' Do Inc(k) Done pscopy(u,t, h+1, k-h);