numparam dynamic memory allocation, part 1

This commit is contained in:
h_vogt 2009-03-15 15:08:04 +00:00
parent c22fa4be3f
commit 3a319212f3
5 changed files with 414 additions and 512 deletions

View File

@ -1,3 +1,8 @@
2009-03-15 Holger Vogt
* cktfinddev.c: some (optical) cleanup
* numparam.h, xpressn.c, spicenum.c, inpcom.c: dynamic memory
allocation for numparam (the easier part)
2009-03-08 Holger Vogt
* dctran.c no printout of 'Initial transient solution' if
.options noacct is set

View File

@ -92,9 +92,9 @@ static int num_parameters[1000];
/* Collect information for dynamic allocation of numparam arrays */
/* number of lines in input deck */
int dynmaxline; /* inpcom.c 1524 */
int dynmaxline; /* inpcom.c 1529 */
/* max. line length in input deck */
int dynnLen; /* inpcom.c 1526 */
int dynLlen; /* inpcom.c 1526 */
/* number of lines in deck after expansion */
int dynMaxckt = 0; /* subckt.c 307 */
/* number of parameter substitutions */
@ -1524,11 +1524,11 @@ inp_readall(FILE *fp, struct line **data, int call_depth, char *dir_name)
/* get max. line length and number of lines in input deck*/
dynmaxline = 0;
dynnLen = 0;
dynLlen = 0;
for(tmp_ptr1 = cc; tmp_ptr1 != NULL; tmp_ptr1 = tmp_ptr1->li_next) {
dynmaxline++;
if (dynnLen < strlen(tmp_ptr1->li_line))
dynnLen = strlen(tmp_ptr1->li_line);
if (dynLlen < strlen(tmp_ptr1->li_line))
dynLlen = strlen(tmp_ptr1->li_line);
}
#if defined(TRACE) || defined(OUTDECK)
/*debug: print into file*/
@ -1537,7 +1537,7 @@ inp_readall(FILE *fp, struct line **data, int call_depth, char *dir_name)
fprintf(fdo, "%s\n", tmp_ptr1->li_line);
;
(void) fclose(fdo);
fprintf(stdout, "lLen %d, maxline %d\n", dynnLen, dynmaxline);
fprintf(stdout, "lLen %d, maxline %d\n", dynLlen, dynmaxline);
#endif
return;

View File

@ -17,7 +17,8 @@ typedef enum {Nodekey='#'} _nNodekey; /* Introduces node symbol */
typedef enum {Intro='&'} _nIntro; /* Introduces preprocessor tokens */
typedef enum {Comment='*'} _nComment; /* Spice Comment lines*/
typedef enum {Pspice='{'} _nPspice; /* Pspice expression */
typedef enum {Maxdico=40000} _nMaxdico; /* Size of symbol table*/
//typedef enum {Maxdico=40000} _nMaxdico; /* Size of symbol table*/
typedef enum {Defd=15} _nDefd; /* serial numb. of 'defined' keyword. The others are not used (yet) */
/* Composite line length
This used to be 250 characters, but this is too easy to exceed with a
@ -29,8 +30,8 @@ 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 */
//typedef enum {Maxline=70000} _nMaxline; /* Size of initial unexpanded circuit code */
//typedef enum {Maxckt=40000} _nMaxckt; /* Size of expanded circuit code */
typedef char * auxtable; /* dummy */
@ -53,7 +54,8 @@ typedef struct _ttdico {
str80 srcfile; /* last piece of source file name */
int srcline;
int errcount;
entry dat[Maxdico+1];
// entry dat[Maxdico+1];
entry* dyndat;
int nbd; /* number of data entries */
fumas fms[101];
int nfms; /* number of functions & macros */
@ -62,18 +64,20 @@ typedef struct _ttdico {
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 category[Maxline]; /* category of each line */
// char * refptr[Maxline]; /* pointers to source code lines */
char **dynrefptr;
// char category[Maxline]; /* category of each line */
char *dyncategory;
} tdico;
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);
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);
int donedico(tdico * dico);
unsigned char defsubckt( tdico *dico, char * s, int w, char categ);
int findsubckt( tdico *dico, char * s, char * 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 );
tdico * nupa_fetchinstance(void);
char getidtype( tdico *d, char * s);
int attrib( tdico *dico, char * t, char op );

View File

@ -32,7 +32,14 @@ extern void txfree (void *ptr);
char *nupa_inst_name;
static tdico *inst_dico;
extern long dynsubst; /* inpcom.c */
/* number of parameter substitutions, available only after the substitution */
extern long dynsubst; /* spicenum.c:144 */
/* number of lines in input deck */
extern int dynmaxline; /* inpcom.c:1529 */
/* max. line length in input deck */
int dynLlen; /* inpcom.c:1531 */
/* Uncomment this line to allow debug tracing */
/* #define TRACE_NUMPARAMS */
@ -60,49 +67,11 @@ extern long dynsubst; /* inpcom.c */
#define PlaceHold 1000000000L
static long placeholder = 0;
#ifdef NOT_REQUIRED /* SJB - not required as front-end now does stripping */
static int
stripcomment (char *s)
/* allow end-of-line comments in Spice, like C++ */
{
int i, ls;
char c, d;
unsigned char stop;
ls = length (s);
c = ' ';
i = 0;
stop = 0;
while ((i < ls) && !stop)
{
d = c;
i++;
c = s[i - 1];
stop = (c == d) && ((c == '/') || (c == '-'));
/* comments after // or -- */ ;
}
if (stop)
{
i = i - 2; /*last valid character before Comment */
while ((i > 0) && (s[i - 1] <= ' '))
i--; /*strip blank space */
if (i <= 0)
scopy (s, "");
else
pscopy (s, s, 1, i);
}
else
i = -1;
return i /* i>=0 if comment stripped at that position */ ;
}
#endif /* NOT_REQUIRED */
static void
stripsomespace (char *s, unsigned char incontrol)
{
/* iff s starts with one of some markers, strip leading space */
/* if s starts with one of some markers, strip leading space */
Str (12, markers);
int i, ls;
scopy (markers, "*.&+#$");
@ -120,106 +89,60 @@ stripsomespace (char *s, unsigned char incontrol)
}
#if 0 /* unused? */
void
partition (char *t)
/* t is a list val=expr val=expr .... Insert Lf-& before any val= */
/* the Basic preprocessor doesnt understand multiple cmd/line */
/* bug: strip trailing spaces */
{
Strbig (Llen, u);
int i, lt, state;
char c;
cadd (u, Intro);
state = 0; /* a trivial 3-state machine */
lt = length (t);
while (t[lt - 1] <= ' ')
lt--;
for (i = 0; i < lt; i++)
{
c = t[i];
if (c == '=')
{
state = 1;
}
else if ((state == 1) && (c == ' '))
{
state = 2;
}
if (state == 2)
{
cadd (u, Lf);
cadd (u, Intro);
state = 0;
}
cadd (u, c);
}
scopy (t, u);
for (i = 0; i < length (t); i++)
{ /* kill braces inside */
if ((t[i] == '{') || (t[i] == '}'))
{
t[i] = ' ';
}
}
}
#endif
static int
stripbraces (char *s)
/* puts the funny placeholders. returns the number of {...} substitutions */
{
int n, i, nest, ls, j;
Strbig (Llen, t);
n = 0;
ls = length (s);
i = 0;
int n, i, nest, ls, j;
Strbig (Llen, t);
n = 0;
ls = length (s);
i = 0;
while (i < ls)
{
while (i < ls)
{
if (s[i] == '{')
{ /* something to strip */
j = i + 1;
nest = 1;
n++;
{ /* something to strip */
j = i + 1;
nest = 1;
n++;
while ((nest > 0) && (j < ls))
{
if (s[j] == '{')
nest++;
else if (s[j] == '}')
nest--;
j++;
}
pscopy (t, s, 1, i);
placeholder++;
while ((nest > 0) && (j < ls))
{
if (s[j] == '{')
nest++;
else if (s[j] == '}')
nest--;
j++;
}
pscopy (t, s, 1, i);
placeholder++;
if (t[i - 1] > ' ')
cadd (t, ' ');
if (t[i - 1] > ' ')
cadd (t, ' ');
cadd (t, ' '); // add extra character to increase number significant digits for evaluated numbers
cadd (t, ' ');
cadd (t, ' ');
cadd (t, ' ');
nadd (t, PlaceHold + placeholder);
cadd (t, ' ');
cadd (t, ' '); /* add extra character to increase number significant digits for evaluated numbers */
cadd (t, ' ');
cadd (t, ' ');
cadd (t, ' ');
nadd (t, PlaceHold + placeholder);
cadd (t, ' ');
if (s[j] >= ' ')
cadd (t, ' ');
if (s[j] >= ' ')
cadd (t, ' ');
i = length (t);
pscopy (s, s, j + 1, ls);
sadd (t, s);
scopy (s, t);
}
i = length (t);
pscopy (s, s, j + 1, ls);
sadd (t, s);
scopy (s, t);
}
else
i++;
i++;
ls = length (s);
}
dynsubst = placeholder;
return n;
}
dynsubst = placeholder;
return n;
}
static int
@ -364,76 +287,75 @@ transform (tdico * dico, char *s, unsigned char nostripping, char *u)
* 'B' netlist (or .model ?) line that had Braces killed
*/
{
Strbig (Llen, t);
char category;
int i, k, a, n;
Strbig (Llen, t);
char category;
int i, k, a, n;
stripsomespace (s, nostripping);
modernizeex (s); /* required for stripbraces count */
scopy (u, "");
stripsomespace (s, nostripping);
modernizeex (s); /* required for stripbraces count */
scopy (u, "");
if (s[0] == '.')
{ /* check Pspice parameter format */
if (s[0] == '.')
{ /* check Pspice parameter format */
scopy_up (t, s);
k = 1;
while (t[k] > ' ')
{
cadd (u, t[k]);
k++;
}
{
cadd (u, t[k]);
k++;
}
if (ci_prefix (".PARAM", t) == 1)
{ /* comment it out */
/*s[0]='*'; */
category = 'P';
}
{ /* comment it out */
/*s[0]='*'; */
category = 'P';
}
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);
category = 'S';
}
{ /* split off any "params" tail */
a = spos ("PARAMS:", t);
if (a > 0)
pscopy (s, s, 1, a - 1);
category = 'S';
}
else if (ci_prefix (".CONTROL", t) == 1)
category = 'C';
category = 'C';
else if (ci_prefix (".ENDC", t) == 1)
category = 'E';
category = 'E';
else if (ci_prefix (".ENDS", t) == 1)
category = 'U';
category = 'U';
else
{
category = '.';
n = stripbraces (s);
if (n > 0)
category = 'B'; /* priority category ! */
}
}
else if (s[0] == Intro)
{ /* private style preprocessor line */
{
category = '.';
n = stripbraces (s);
if (n > 0)
category = 'B'; /* priority category ! */
}
}
else if (s[0] == Intro)
{ /* private style preprocessor line */
s[0] = '*';
category = 'P';
}
else if (upcase (s[0]) == 'X')
{ /* strip actual parameters */
}
else if (upcase (s[0]) == 'X')
{ /* strip actual parameters */
i = findsubname (dico, s); /* i= index following last identifier in s */
category = 'X';
}
else if (s[0] == '+') /* continuation line */
category = '+';
else if (cpos (s[0], "*$#") <= 0)
{ /* not a comment line! */
}
else if (s[0] == '+') /* continuation line */
category = '+';
else if (cpos (s[0], "*$#") <= 0)
{ /* not a comment line! */
n = stripbraces (s);
if (n > 0)
category = 'B'; /* line that uses braces */
category = 'B'; /* line that uses braces */
else
category = ' '; /* ordinary code line */
}
else
category = '*';
category = ' '; /* ordinary code line */
}
else
category = '*';
return category;
return category;
}
/************ core of numparam **************/
@ -454,8 +376,6 @@ static tdico *dico = NULL;
/* already part of dico : */
/* Str(80, srcfile); source file */
/* Darray(refptr, char *, Maxline) pointers to source code lines */
/* Darray(category, char, Maxline) category of each line */
/*
Open ouput to a log file.
@ -505,12 +425,16 @@ nupa_init (char *srcfile)
initdico (dico);
initdico (inst_dico);
for (i = 0; i < Maxline; i++)
dico->dynrefptr = (char**)tmalloc(dynmaxline*sizeof(char*) + 1);
dico->dyncategory = (char*)tmalloc(dynmaxline*sizeof(char) + 1);
for (i = 0; i <= dynmaxline; i++)
{
dico->refptr[i] = NULL;
dico->category[i] = '?';
dico->dynrefptr[i] = NULL;
dico->dyncategory[i] = '?';
}
sini (dico->srcfile, sizeof (dico->srcfile) - 4);
sini (dico->srcfile, sizeof (dico->srcfile) - 4);
if (srcfile != NULL)
scopy (dico->srcfile, srcfile);
@ -531,11 +455,14 @@ nupa_done (void)
nerrors = dico->errcount;
dictsize = donedico (dico);
for (i = Maxline - 1; i >= 0; i--)
dispose ((void *) dico->refptr[i]);
for (i = dynmaxline ; i >= 0; i--) {
dispose ((void *) dico->dynrefptr[i]);
dispose ((void *) dico->dyncategory[i]);
}
dispose ((void *) dico);
dico = NULL;
dispose ((void *) inst_dico);
inst_dico = NULL;
if (nerrors)
{
/* debug: ask if spice run really wanted */
@ -600,42 +527,42 @@ upper_str (char *str)
void
nupa_list_params (FILE * cp_out)
{
char *name;
int i;
char *name;
int i;
fprintf (cp_out, "\n\n");
for (i = 1; i <= dico->nbd; 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);
}
}
fprintf (cp_out, "\n\n");
for (i = 1; i <= dico->nbd; i++)
{
if (dico->dyndat[i].tp == 'R')
{
name = lower_str (strdup (dico->dyndat[i].nom));
fprintf (cp_out, " ---> %s = %g\n", name, dico->dyndat[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;
char *name = upper_str (strdup (param_name));
double result = 0;
int i;
*found = 0;
*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;
}
}
for (i = 1; i <= dico->nbd + 1; i++)
{
if (strcmp (dico->dyndat[i].nom, name) == 0)
{
result = dico->dyndat[i].vl;
*found = 1;
break;
}
}
txfree (name);
return result;
txfree (name);
return result;
}
void
@ -644,11 +571,10 @@ 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;
dico->dyndat[i].vl = value;
dico->dyndat[i].tp = 'R';
dico->dyndat[i].ivl = 0;
dico->dyndat[i].sbbase = NULL;
txfree (up_name);
}
@ -658,10 +584,11 @@ 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;
inst_dico->dyndat[i].vl = value;
inst_dico->dyndat[i].tp = 'R';
inst_dico->dyndat[i].ivl = 0;
inst_dico->dyndat[i].sbbase = NULL;
txfree (up_name);
}
@ -672,7 +599,7 @@ 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);
nupa_add_param (inst_dico->dyndat[i].nom, inst_dico->dyndat[i].vl);
}
char *
@ -703,10 +630,10 @@ nupa_copy (char *s, int linenum)
pscopy (u, s, 1, ls); /* strip trailing space, CrLf and so on */
dico->srcline = linenum;
if ((!inexpansion) && (linenum >= 0) && (linenum < Maxline))
if ((!inexpansion) && (linenum >= 0) && (linenum < dynmaxline))
{
linecount++;
dico->refptr[linenum] = s;
dico->dynrefptr[linenum] = s;
c = transform (dico, u, incontrol, keywd);
if (c == 'C')
incontrol = 1;
@ -716,14 +643,13 @@ nupa_copy (char *s, int linenum)
if (incontrol)
c = 'C'; /* force it */
d = dico->category[linenum]; /* warning if already some strategic line! */
d = dico->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->category[linenum] = c;
dico->dyncategory[linenum] = c;
} /* keep a local copy and mangle the string */
ls = length (u);
@ -738,7 +664,7 @@ nupa_copy (char *s, int linenum)
{
if (!inexpansion)
{
putlogfile (dico->category[linenum], linenum, t);
putlogfile (dico->dyncategory[linenum], linenum, t);
};
}
return t;
@ -760,16 +686,16 @@ nupa_eval (char *s, int linenum)
unsigned char err = 1;
dico->srcline = linenum;
c = dico->category[linenum];
c = dico->dyncategory[linenum];
#ifdef TRACE_NUMPARAMS
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') /* evaluate parameters */
nupa_assignment (dico, dico->refptr[linenum], 'N');
nupa_assignment (dico, dico->dynrefptr[linenum], 'N');
else if (c == 'B') /* substitute braces line */
err = nupa_substitute (dico, dico->refptr[linenum], s, 0);
err = nupa_substitute (dico, dico->dynrefptr[linenum], s, 0);
else if (c == 'X')
{ /* compute args of subcircuit, if required */
ptr = s;
@ -786,7 +712,7 @@ nupa_eval (char *s, int linenum)
idef = findsubckt (dico, s, subname);
if (idef > 0)
nupa_subcktcall (dico, dico->refptr[idef], dico->refptr[linenum], 0);
nupa_subcktcall (dico, dico->dynrefptr[idef], dico->dynrefptr[linenum], 0);
else
putlogfile ('?', linenum, " illegal subckt call.");
}

View File

@ -16,11 +16,11 @@ extern double gauss();
/************ 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 Str (150, keys); /* all my keywords */
static Str (150, fmath); /* all math functions */
extern char *nupa_inst_name; /* see spicenum.c */
extern long dynsubst; /* see inpcom.c */
extern long dynsubst; /* see inpcom.c */
static double
ternary_fcn (int conditional, double if_value, double else_value)
@ -115,76 +115,57 @@ mathfunction (int f, double z, double x)
return y;
}
typedef enum {Defd=15} _nDefd;
/* serial numb. of 'defined' keyword. The others are not used (yet) */
static unsigned char message (tdico * dic, char *s)
static unsigned char
message (tdico * dic, char *s)
/* record 'dic' should know about source file and line */
{
Strbig (Llen, t);
dic->errcount++;
if ((dic->srcfile != NULL) && dic->srcfile[0])
{
Strbig (Llen, t);
dic->errcount++;
if ((dic->srcfile != NULL) && dic->srcfile[0])
{
scopy (t, dic->srcfile);
cadd (t, ':');
}
if (dic->srcline >= 0)
{
}
if (dic->srcline >= 0)
{
nadd (t, dic->srcline);
sadd (t, ": ");
}
sadd (t, s);
cadd (t, '\n');
fputs (t, stderr);
}
sadd (t, s);
cadd (t, '\n');
fputs (t, stderr);
return 1 /*error! */ ;
return 1 /*error! */ ;
}
void
debugwarn (tdico * d, char *s)
{
message (d, s);
d->errcount--;
message (d, s);
d->errcount--;
}
/************* historical: stubs for nodetable manager ************/
/* in the full preprocessor version there was a node translator for spice2 */
static void
initsymbols (auxtable * n)
{;
}
static void
donesymbols (auxtable * n)
{;
}
/* static
int parsenode(auxtable *n, char * s)
{
return 0;
}
*/
/************ the input text symbol table (dictionary) *************/
void
initdico (tdico * dico)
{
int i;
dico->nbd = 0;
sini(dico->option,sizeof(dico->option)-4);
sini(dico->srcfile,sizeof(dico->srcfile)-4);
dico->srcline = -1;
dico->errcount = 0;
int i;
dico->nbd = 0;
sini(dico->option,sizeof(dico->option)-4);
sini(dico->srcfile,sizeof(dico->srcfile)-4);
dico->srcline = -1;
dico->errcount = 0;
for (i = 0; i <= Maxdico; i++)
sini (dico->dat[i].nom, 100);
dico->dyndat = (entry*)tmalloc(3 * sizeof(entry));
for (i = 0; i < 3; i++)
sini (dico->dyndat[i].nom, 100);
dico->tos = 0;
dico->stack[dico->tos] = 0; /* global data beneath */
initsymbols (&dico->nodetab);
initkeys ();
dico->tos = 0;
dico->stack[dico->tos] = 0; /* global data beneath */
initkeys ();
}
/* local semantics for parameters inside a subckt */
@ -197,67 +178,58 @@ initdico (tdico * dico)
typedef enum {Push='u'} _nPush;
typedef enum {Pop='o'} _nPop;
static void
dicostack (tdico * dico, char op)
static void
dicostack (tdico * dico, char op)
/* push or pop operation for nested subcircuit locals */
{
char *param_name, *inst_name;
int i, current_stack_size, old_stack_size;
char *param_name, *inst_name;
int i, current_stack_size, old_stack_size;
if (op == Push)
{
if (op == Push)
{
if (dico->tos < (20 - 1))
dico->tos++;
dico->tos++;
else
message (dico, " Subckt Stack overflow");
message (dico, " Subckt Stack overflow");
dico->stack[dico->tos] = dico->nbd;
dico->inst_name[dico->tos] = nupa_inst_name;
}
else if (op == Pop)
{
/* obsolete: undefine all data items of level dico->tos
for ( i=dico->nbd; i>0; i--) ) {
c= dico->dat[i].tp;
if ( ((c=='R') || (c=='S')) && (dico->dat[i].level == dico->tos) ) {
dico->dat[i].tp= '?';
}
}
*/
}
else if (op == Pop)
{
if (dico->tos > 0)
{
// keep instance parameters around
current_stack_size = dico->nbd;
old_stack_size = dico->stack[dico->tos];
inst_name = dico->inst_name[dico->tos];
{
/* 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);
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);
}
tfree (inst_name);
dico->nbd = dico->stack[dico->tos]; /* simply kill all local items */
dico->tos--;
}
dico->nbd = dico->stack[dico->tos]; /* simply kill all local items */
dico->tos--;
}
else
{
message (dico, " Subckt Stack underflow.");
}
}
{
message (dico, " Subckt Stack underflow.");
}
}
}
int
donedico (tdico * dico)
{
int sze = dico->nbd;
donesymbols (&dico->nodetab);
return sze;
int sze = dico->nbd;
if (dico->dyndat) tfree(dico->dyndat);
return sze;
}
static int
@ -265,19 +237,19 @@ 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;
int i;
unsigned char ok;
ok = 0;
i = d->nbd + 1;
while ((!ok) && (i > 1))
{
while ((!ok) && (i > 1))
{
i--;
ok = steq (d->dat[i].nom, s);
}
if (!ok)
ok = steq (d->dyndat[i].nom, s);
}
if (!ok)
return 0;
else
else
return i;
}
@ -285,46 +257,45 @@ char
getidtype (tdico * d, char *s)
/* test if identifier s is known. Answer its type, or '?' if not in list */
{
char itp = '?'; /* assume unknown */
int i = entrynb (d, s);
char itp = '?'; /* assume unknown */
int i = entrynb (d, s);
if (i > 0)
itp = d->dat[i].tp;
return itp;
if (i > 0)
itp = d->dyndat[i].tp;
return itp;
}
static double
fetchnumentry (tdico * dico, char *t, unsigned char *perr)
{
unsigned char err = *perr;
unsigned short k;
double u;
Strbig (Llen, s);
k = entrynb (dico, t); /*no keyword */
/*dbg -- if ( k<=0 ) { ws("Dico num lookup fails. ") ;} */
unsigned char err = *perr;
unsigned short k;
double u;
Strbig (Llen, s);
k = entrynb (dico, t); /*no keyword */
/*dbg -- if ( k<=0 ) { ws("Dico num lookup fails. ") ;} */
while ((k > 0) && (dico->dat[k].tp == 'P'))
k = dico->dat[k].ivl; /*pointer chain */
while ((k > 0) && (dico->dyndat[k].tp == 'P'))
k = dico->dyndat[k].ivl; /*pointer chain */
if (k > 0)
if (dico->dat[k].tp != 'R')
k = 0;
if (k > 0)
if (dico->dyndat[k].tp != 'R')
k = 0;
if (k > 0)
u = dico->dat[k].vl;
else
{
if (k > 0)
u = dico->dyndat[k].vl;
else
{
u = 0.0;
scopy (s, "Undefined number [");
sadd (s, t);
cadd (s, ']');
err = message (dico, s);
}
}
*perr = err;
*perr = err;
return u;
return u;
}
/******* writing dictionary entries *********/
@ -335,46 +306,43 @@ 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 */
int i;
unsigned char ok;
i = dico->nbd + 1;
ok = 0;
while ((!ok) && (i > 1))
{ /*search old */
i--;
ok = steq (dico->dat[i].nom, t);
}
ok = steq (dico->dyndat[i].nom, t);
}
if (ok && (op == 'N')
&& (dico->dat[i].level < dico->tos) && (dico->dat[i].tp != '?'))
{
if (ok && (op == 'N')
&& (dico->dyndat[i].level < dico->tos) && (dico->dyndat[i].tp != '?'))
{
ok = 0;
}
}
if (!ok)
{
if (!ok)
{
dico->nbd++;
i = dico->nbd;
if (dico->nbd > Maxdico)
i = 0;
else
{
scopy (dico->dat[i].nom, t);
dico->dat[i].tp = '?'; /*signal Unknown */
dico->dat[i].level = dico->tos;
}
}
return i;
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;
}
return i;
}
static unsigned char
define (tdico * dico, char *t, /* identifier to define */
char op, /* option */
char tpe, /* type marker */
double z, /* float value if any */
int w, /* integer value if any */
char *base) /* string pointer if any */
define (tdico * dico,
char *t, /* identifier to define */
char op, /* option */
char tpe, /* type marker */
double z, /* float value if any */
int w, /* integer value if any */
char *base) /* string pointer if any */
{
/*define t as real or integer,
opcode= 'N' impose a new item under local conditions.
@ -384,53 +352,52 @@ define (tdico * dico, char *t, /* identifier to define */
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 (Llen, v);
i = attrib (dico, t, op);
err = 0;
if (i <= 0)
int i;
char c;
unsigned char err, warn;
Strbig (Llen, v);
i = attrib (dico, t, op);
err = 0;
if (i <= 0)
err = message (dico, " Symbol table overflow");
else
{
if (dico->dat[i].tp == 'P')
i = dico->dat[i].ivl; /*pointer indirection */
else
{
if (dico->dyndat[i].tp == 'P')
i = dico->dyndat[i].ivl; /*pointer indirection */
if (i > 0)
c = dico->dat[i].tp;
c = dico->dyndat[i].tp;
else
c = ' ';
c = ' ';
if ((c == 'R') || (c == 'S') || (c == '?'))
{
dico->dat[i].vl = z;
dico->dat[i].tp = tpe;
dico->dat[i].ivl = w;
dico->dat[i].sbbase = base;
/* if ( (c !='?') && (i<= dico->stack[dico->tos]) ) { */
{
dico->dyndat[i].vl = z;
dico->dyndat[i].tp = tpe;
dico->dyndat[i].ivl = w;
dico->dyndat[i].sbbase = base;
/* if ( (c !='?') && (i<= dico->stack[dico->tos]) ) { */
if (c == '?')
dico->dyndat[i].level = dico->tos; /* promote! */
if (c == '?')
dico->dat[i].level = dico->tos; /* promote! */
if (dico->dat[i].level < dico->tos)
{
/* warn about re-write to a global scope! */
scopy (v, t);
cadd (v, ':');
nadd (v, dico->dat[i].level);
sadd (v, " overwritten.");
warn = message (dico, v);
}
}
if (dico->dyndat[i].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);
}
}
else
{
scopy (v, t);
sadd (v, ": cannot redefine");
err = message (dico, v);
}
}
return err;
{
scopy (v, t);
sadd (v, ": cannot redefine");
err = message (dico, v);
}
}
return err;
}
unsigned char
@ -439,35 +406,35 @@ defsubckt (tdico * dico, char *s, int w, char categ)
to enter subcircuit (categ=U) and model (categ=O) names
*/
{
Str (80, u);
unsigned char err;
int i, j, ls;
ls = length (s);
i = 0;
Str (80, u);
unsigned char err;
int i, j, ls;
ls = length (s);
i = 0;
while ((i < ls) && (s[i] != '.'))
i++; /* skip 1st dotword */
while ((i < ls) && (s[i] != '.'))
i++; /* skip 1st dotword */
while ((i < ls) && (s[i] > ' '))
i++;
while ((i < ls) && (s[i] > ' '))
i++;
while ((i < ls) && (s[i] <= ' '))
i++; /* skip blank */
while ((i < ls) && (s[i] <= ' '))
i++; /* skip blank */
j = i;
j = i;
while ((j < ls) && (s[j] > ' '))
j++;
while ((j < ls) && (s[j] > ' '))
j++;
if ((j > i))
{
if ((j > i))
{
pscopy_up (u, s, i + 1, j - i);
err = define (dico, u, ' ', categ, 0.0, w, NULL);
}
else
}
else
err = message (dico, "Subcircuit or Model without name.");
return err;
return err;
}
int
@ -476,34 +443,34 @@ findsubckt (tdico * dico, char *s, char *subname)
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;
k = length (s);
Str (80, u); /* u= subckt name is last token in string s */
int i, j, k;
k = length (s);
while ((k >= 0) && (s[k] <= ' '))
k--;
while ((k >= 0) && (s[k] <= ' '))
k--;
j = k;
j = k;
while ((k >= 0) && (s[k] > ' '))
k--;
while ((k >= 0) && (s[k] > ' '))
k--;
pscopy_up (u, s, k + 2, j - k);
i = entrynb (dico, u);
pscopy_up (u, s, k + 2, j - k);
i = entrynb (dico, u);
if ((i > 0) && (dico->dat[i].tp == 'U'))
{
i = dico->dat[i].ivl;
if ((i > 0) && (dico->dyndat[i].tp == 'U'))
{
i = dico->dyndat[i].ivl;
scopy (subname, u);
}
else
{
}
else
{
i = 0;
scopy (subname, "");
message (dico, "Cannot find subcircuit.");
}
}
return i;
return i;
}
#if 0 /* unused, from the full macro language... */
@ -562,36 +529,36 @@ static unsigned char
keyword (char *keys, char *t)
{
/* 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);
k = 0;
j = 0;
unsigned char i, j, k;
int lt, lk;
unsigned char ok;
lt = length (t);
lk = length (keys);
k = 0;
j = 0;
do {
do {
j++;
i = 0;
ok = 1;
do{
i++;
k++;
ok = (k <= lk) && (t[i - 1] == keys[k - 1]);
} while (!((!ok) || (i >= lt)));
do {
i++;
k++;
ok = (k <= lk) && (t[i - 1] == keys[k - 1]);
} while (!((!ok) || (i >= lt)));
if (ok)
ok = (k == lk) || (keys[k] <= ' ');
ok = (k == lk) || (keys[k] <= ' ');
if (!ok && (k < lk)) /*skip to next item */
while ((k <= lk) && (keys[k - 1] > ' '))
while ((k <= lk) && (keys[k - 1] > ' '))
k++;
} while (!(ok || (k >= lk)));
} while (!(ok || (k >= lk)));
if (ok)
if (ok)
return j;
else
else
return 0;
}
@ -1331,29 +1298,29 @@ evaluate (tdico * dico, char *q, char *t, unsigned char mode)
stupcase (t);
k = entrynb (dico, t);
nolookup = (k <= 0);
while ((k > 0) && (dico->dat[k].tp == 'P'))
k = dico->dat[k].ivl;
while ((k > 0) && (dico->dyndat[k].tp == 'P'))
k = dico->dyndat[k].ivl;
/*pointer chain */
if (k > 0)
dt = dico->dat[k].tp;
dt = dico->dyndat[k].tp;
else
dt = ' ';
/*data type: Real or String */
if (dt == 'R')
{
u = dico->dat[k].vl;
u = dico->dyndat[k].vl;
numeric = 1;
}
else if (dt == 'S')
{ /*suppose source text "..." at */
j = dico->dat[k].ivl;
j = dico->dyndat[k].ivl;
lq = 0;
do {
j++;
lq++;
dt = /*ibf->bf[j]; */ dico->dat[k].sbbase[j];
dt = /*ibf->bf[j]; */ dico->dyndat[k].sbbase[j];
if (cpos ('3', dico->option) <= 0)
dt = upcase (dt); /* spice-2 */