ASRC, INPgetTree(), fix memory leaks
implement a reference counter `usecnt' for the elements
of the `INPparseTree'
This commit is contained in:
parent
9955379204
commit
bbb1ecc6a8
|
|
@ -104,6 +104,7 @@ char *INPgetModBin(CKTcircuit *, char *, INPmodel **, INPtables *, char *);
|
||||||
int INPgetTok(char **, char **, int);
|
int INPgetTok(char **, char **, int);
|
||||||
int INPgetNetTok(char **, char **, int);
|
int INPgetNetTok(char **, char **, int);
|
||||||
void INPgetTree(char **, INPparseTree **, CKTcircuit *, INPtables *);
|
void INPgetTree(char **, INPparseTree **, CKTcircuit *, INPtables *);
|
||||||
|
void INPfreeTree(IFparseTree *);
|
||||||
IFvalue *INPgetValue(CKTcircuit *, char **, int, INPtables *);
|
IFvalue *INPgetValue(CKTcircuit *, char **, int, INPtables *);
|
||||||
int INPgndInsert(CKTcircuit *, char **, INPtables *, CKTnode **);
|
int INPgndInsert(CKTcircuit *, char **, INPtables *, CKTnode **);
|
||||||
int INPinsertNofree(char **token, INPtables *tab);
|
int INPinsertNofree(char **token, INPtables *tab);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ typedef struct INPparseNode {
|
||||||
int funcnum; /* ... one of PTF_*, */
|
int funcnum; /* ... one of PTF_*, */
|
||||||
void (*function)(void); /* ... and pointer to the function. */
|
void (*function)(void); /* ... and pointer to the function. */
|
||||||
void *data; /* private data for certain functions, currently PTF_PWL */
|
void *data; /* private data for certain functions, currently PTF_PWL */
|
||||||
|
int usecnt;
|
||||||
} INPparseNode;
|
} INPparseNode;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ ASRCdestroy(GENmodel **model)
|
||||||
for(here = mod->ASRCinstances ; here ; here = next) {
|
for(here = mod->ASRCinstances ; here ; here = next) {
|
||||||
next = here->ASRCnextInstance;
|
next = here->ASRCnextInstance;
|
||||||
FREE(here->ASRCacValues);
|
FREE(here->ASRCacValues);
|
||||||
|
INPfreeTree(here->ASRCtree);
|
||||||
|
if(here->ASRCposptr)
|
||||||
|
free(here->ASRCposptr);
|
||||||
FREE(here);
|
FREE(here);
|
||||||
}
|
}
|
||||||
nextmod = mod->ASRCnextModel;
|
nextmod = mod->ASRCnextModel;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,74 @@ static INPparseNode *mknnode(double number);
|
||||||
static INPparseNode *mksnode(const char *string, void *ckt);
|
static INPparseNode *mksnode(const char *string, void *ckt);
|
||||||
static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum);
|
static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum);
|
||||||
|
|
||||||
|
static void free_tree(INPparseNode *);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LAW for INPparseNode* generator and consumer functions:
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
* Newly allocated structs shall be initialized with `usecnt' = 0
|
||||||
|
* When filling INPparseNode * slots of newly initialized structs
|
||||||
|
* their `usecnt' shall be incremented
|
||||||
|
* Generators pass the responsibility `to free' return values
|
||||||
|
* on to their invokers.
|
||||||
|
* Functions generally process args with exactly one of:
|
||||||
|
* - inc_usage(arg) if they insert an argument into a struct
|
||||||
|
* - release_tree(arg) if they don't make any use of it
|
||||||
|
* - pass it on to another function()
|
||||||
|
* Functions use the the result of a function invocations with one of:
|
||||||
|
* - inc_usage(result) if they insert the result into a struct
|
||||||
|
* - release_tree(result) if they don't make any use of it
|
||||||
|
* - pass it on to another function()
|
||||||
|
* - simply return the result
|
||||||
|
*
|
||||||
|
* mkfirst(first, second)
|
||||||
|
* is used to safely release its second argument,
|
||||||
|
* and return its first
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static inline INPparseNode *
|
||||||
|
inc_usage(INPparseNode *p)
|
||||||
|
{
|
||||||
|
if(p)
|
||||||
|
p->usecnt ++;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
dec_usage(INPparseNode *p)
|
||||||
|
{
|
||||||
|
if(p && --p->usecnt <= 0)
|
||||||
|
free_tree(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
release_tree(INPparseNode *p)
|
||||||
|
{
|
||||||
|
if(p && p->usecnt <= 0)
|
||||||
|
free_tree(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static INPparseNode *
|
||||||
|
mkfirst(INPparseNode *fst, INPparseNode *snd)
|
||||||
|
{
|
||||||
|
if(fst) {
|
||||||
|
fst->usecnt ++;
|
||||||
|
release_tree(snd);
|
||||||
|
fst->usecnt --;
|
||||||
|
} else {
|
||||||
|
release_tree(snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "inpptree-parser.c"
|
#include "inpptree-parser.c"
|
||||||
|
|
||||||
static IFvalue *values = NULL;
|
static IFvalue *values = NULL;
|
||||||
|
|
@ -140,9 +208,10 @@ INPgetTree(char **line, INPparseTree ** pt, CKTcircuit *ckt, INPtables * tab)
|
||||||
|
|
||||||
rv = PTparse(line, &p, ckt);
|
rv = PTparse(line, &p, ckt);
|
||||||
|
|
||||||
if (rv || !PTcheck(p)) {
|
if (rv || !p || !PTcheck(p)) {
|
||||||
|
|
||||||
*pt = NULL;
|
*pt = NULL;
|
||||||
|
release_tree(p);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -152,12 +221,12 @@ INPgetTree(char **line, INPparseTree ** pt, CKTcircuit *ckt, INPtables * tab)
|
||||||
(*pt)->p.varTypes = types;
|
(*pt)->p.varTypes = types;
|
||||||
(*pt)->p.vars = values;
|
(*pt)->p.vars = values;
|
||||||
(*pt)->p.IFeval = IFeval;
|
(*pt)->p.IFeval = IFeval;
|
||||||
(*pt)->tree = p;
|
(*pt)->tree = inc_usage(p);
|
||||||
|
|
||||||
(*pt)->derivs = TMALLOC(INPparseNode *, numvalues);
|
(*pt)->derivs = TMALLOC(INPparseNode *, numvalues);
|
||||||
|
|
||||||
for (i = 0; i < numvalues; i++)
|
for (i = 0; i < numvalues; i++)
|
||||||
(*pt)->derivs[i] = PTdifferentiate(p, i);
|
(*pt)->derivs[i] = inc_usage(PTdifferentiate(p, i));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,7 +249,7 @@ INPgetTree(char **line, INPparseTree ** pt, CKTcircuit *ckt, INPtables * tab)
|
||||||
|
|
||||||
static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
{
|
{
|
||||||
INPparseNode *arg1 = NULL, *arg2, *newp;
|
INPparseNode *arg1 = NULL, *arg2 = NULL, *newp = NULL;
|
||||||
|
|
||||||
switch (p->type) {
|
switch (p->type) {
|
||||||
case PT_TIME:
|
case PT_TIME:
|
||||||
|
|
@ -278,7 +347,7 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
// printTree(newp);
|
// printTree(newp);
|
||||||
// printf("\n");
|
// printf("\n");
|
||||||
|
|
||||||
return (newp);
|
return mkfirst(newp, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
case PT_FUNCTION:
|
case PT_FUNCTION:
|
||||||
|
|
@ -474,7 +543,7 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
printTree(newp);
|
printTree(newp);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
return (newp);
|
return mkfirst(newp, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -513,14 +582,13 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
mkb(PT_DIVIDE, arg1, p->left->left)),
|
mkb(PT_DIVIDE, arg1, p->left->left)),
|
||||||
mkb(PT_TIMES, arg2, mkf(PTF_LN, p->left->left))));
|
mkb(PT_TIMES, arg2, mkf(PTF_LN, p->left->left))));
|
||||||
}
|
}
|
||||||
return (newp);
|
return mkfirst(newp, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Internal Error: bad function # %d\n",
|
fprintf(stderr, "Internal Error: bad function # %d\n",
|
||||||
p->funcnum);
|
p->funcnum);
|
||||||
newp = NULL;
|
return mkfirst(NULL, p);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arg2 = PTdifferentiate(p->left, varnum);
|
arg2 = PTdifferentiate(p->left, varnum);
|
||||||
|
|
@ -535,7 +603,7 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (newp);
|
return mkfirst(newp, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static INPparseNode *mkcon(double value)
|
static INPparseNode *mkcon(double value)
|
||||||
|
|
@ -544,6 +612,7 @@ static INPparseNode *mkcon(double value)
|
||||||
|
|
||||||
p->type = PT_CONSTANT;
|
p->type = PT_CONSTANT;
|
||||||
p->constant = value;
|
p->constant = value;
|
||||||
|
p->usecnt = 0;
|
||||||
|
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
@ -555,81 +624,91 @@ static INPparseNode *mkb(int type, INPparseNode * left,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ((right->type == PT_CONSTANT) && (left->type == PT_CONSTANT)) {
|
if ((right->type == PT_CONSTANT) && (left->type == PT_CONSTANT)) {
|
||||||
|
double value;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PT_TIMES:
|
case PT_TIMES:
|
||||||
return (mkcon(left->constant * right->constant));
|
value = left->constant * right->constant;
|
||||||
|
return mkfirst(mkcon(value), mkfirst(left, right));
|
||||||
|
|
||||||
case PT_DIVIDE:
|
case PT_DIVIDE:
|
||||||
return (mkcon(left->constant / right->constant));
|
value = left->constant / right->constant;
|
||||||
|
return mkfirst(mkcon(value), mkfirst(left, right));
|
||||||
|
|
||||||
case PT_PLUS:
|
case PT_PLUS:
|
||||||
return (mkcon(left->constant + right->constant));
|
value = left->constant + right->constant;
|
||||||
|
return mkfirst(mkcon(value), mkfirst(left, right));
|
||||||
|
|
||||||
case PT_MINUS:
|
case PT_MINUS:
|
||||||
return (mkcon(left->constant - right->constant));
|
value = left->constant - right->constant;
|
||||||
|
return mkfirst(mkcon(value), mkfirst(left, right));
|
||||||
|
|
||||||
case PT_POWER:
|
case PT_POWER:
|
||||||
return (mkcon(pow(left->constant, right->constant)));
|
value = pow(left->constant, right->constant);
|
||||||
|
return mkfirst(mkcon(value), mkfirst(left, right));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PT_TIMES:
|
case PT_TIMES:
|
||||||
if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
||||||
return (left);
|
return mkfirst(left, right);
|
||||||
else if ((right->type == PT_CONSTANT) && (right->constant == 0))
|
else if ((right->type == PT_CONSTANT) && (right->constant == 0))
|
||||||
return (right);
|
return mkfirst(right, left);
|
||||||
else if ((left->type == PT_CONSTANT) && (left->constant == 1))
|
else if ((left->type == PT_CONSTANT) && (left->constant == 1))
|
||||||
return (right);
|
return mkfirst(right, left);
|
||||||
else if ((right->type == PT_CONSTANT) && (right->constant == 1))
|
else if ((right->type == PT_CONSTANT) && (right->constant == 1))
|
||||||
return (left);
|
return mkfirst(left, right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_DIVIDE:
|
case PT_DIVIDE:
|
||||||
if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
||||||
return (left);
|
return mkfirst(left, right);
|
||||||
else if ((right->type == PT_CONSTANT) && (right->constant == 1))
|
else if ((right->type == PT_CONSTANT) && (right->constant == 1))
|
||||||
return (left);
|
return mkfirst(left, right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_PLUS:
|
case PT_PLUS:
|
||||||
if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
||||||
return (right);
|
return mkfirst(right, left);
|
||||||
else if ((right->type == PT_CONSTANT) && (right->constant == 0))
|
else if ((right->type == PT_CONSTANT) && (right->constant == 0))
|
||||||
return (left);
|
return mkfirst(left, right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_MINUS:
|
case PT_MINUS:
|
||||||
if ((right->type == PT_CONSTANT) && (right->constant == 0))
|
if ((right->type == PT_CONSTANT) && (right->constant == 0))
|
||||||
return (left);
|
return mkfirst(left, right);
|
||||||
else if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
else if ((left->type == PT_CONSTANT) && (left->constant == 0))
|
||||||
return (mkf(PTF_UMINUS, right));
|
return mkfirst(mkf(PTF_UMINUS, right), left);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_POWER:
|
case PT_POWER:
|
||||||
if (right->type == PT_CONSTANT) {
|
if (right->type == PT_CONSTANT) {
|
||||||
if (right->constant == 0)
|
if (right->constant == 0)
|
||||||
return (mkcon(1.0));
|
return mkfirst(mkcon(1.0), mkfirst(left, right));
|
||||||
else if (right->constant == 1)
|
else if (right->constant == 1)
|
||||||
return (left);
|
return mkfirst(left, right);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_TERN:
|
case PT_TERN:
|
||||||
if (left->type == PT_CONSTANT)
|
if (left->type == PT_CONSTANT) {
|
||||||
/*FIXME > 0.0, >= 0.5, != 0.0 or what ? */
|
/*FIXME > 0.0, >= 0.5, != 0.0 or what ? */
|
||||||
return ((left->constant != 0.0) ? right->left : right->right);
|
p = (left->constant != 0.0) ? right->left : right->right;
|
||||||
|
return mkfirst(p, mkfirst(right, left));
|
||||||
|
}
|
||||||
if((right->left->type == PT_CONSTANT) &&
|
if((right->left->type == PT_CONSTANT) &&
|
||||||
(right->right->type == PT_CONSTANT) &&
|
(right->right->type == PT_CONSTANT) &&
|
||||||
(right->left->constant == right->right->constant))
|
(right->left->constant == right->right->constant))
|
||||||
return (right->left);
|
return mkfirst(right->left, mkfirst(right, left));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
||||||
p->type = type;
|
p->type = type;
|
||||||
p->left = left;
|
p->usecnt = 0;
|
||||||
p->right = right;
|
|
||||||
|
p->left = inc_usage(left);
|
||||||
|
p->right = inc_usage(right);
|
||||||
|
|
||||||
if(type == PT_TERN) {
|
if(type == PT_TERN) {
|
||||||
p->function = NULL;
|
p->function = NULL;
|
||||||
|
|
@ -666,13 +745,15 @@ static INPparseNode *mkf(int type, INPparseNode * arg)
|
||||||
|
|
||||||
if (arg->type == PT_CONSTANT) {
|
if (arg->type == PT_CONSTANT) {
|
||||||
double constval = PTunary(funcs[i].funcptr) (arg->constant);
|
double constval = PTunary(funcs[i].funcptr) (arg->constant);
|
||||||
return (mkcon(constval));
|
return mkfirst(mkcon(constval), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
||||||
p->type = PT_FUNCTION;
|
p->type = PT_FUNCTION;
|
||||||
p->left = arg;
|
p->usecnt = 0;
|
||||||
|
|
||||||
|
p->left = inc_usage(arg);
|
||||||
|
|
||||||
p->funcnum = i;
|
p->funcnum = i;
|
||||||
p->function = funcs[i].funcptr;
|
p->function = funcs[i].funcptr;
|
||||||
|
|
@ -731,16 +812,18 @@ static INPparseNode *mkbnode(const char *opstr, INPparseNode * arg1,
|
||||||
|
|
||||||
if (i == NUM_OPS) {
|
if (i == NUM_OPS) {
|
||||||
fprintf(stderr, "Internal Error: no such op num %s\n", opstr);
|
fprintf(stderr, "Internal Error: no such op num %s\n", opstr);
|
||||||
return (NULL);
|
return mkfirst(NULL, mkfirst(arg1, arg2));
|
||||||
}
|
}
|
||||||
|
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
||||||
p->type = ops[i].number;
|
p->type = ops[i].number;
|
||||||
|
p->usecnt = 0;
|
||||||
|
|
||||||
p->funcname = ops[i].name;
|
p->funcname = ops[i].name;
|
||||||
p->function = ops[i].funcptr;
|
p->function = ops[i].funcptr;
|
||||||
p->left = arg1;
|
p->left = inc_usage(arg1);
|
||||||
p->right = arg2;
|
p->right = inc_usage(arg2);
|
||||||
|
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
@ -786,7 +869,7 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
|
|
||||||
if (i<2 || (i%1)) {
|
if (i<2 || (i%1)) {
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) needs an even and >=2 number of constant args\n");
|
fprintf(stderr, "Error: PWL(expr, points...) needs an even and >=2 number of constant args\n");
|
||||||
return (NULL);
|
return mkfirst(NULL, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
data = TMALLOC(struct pwldata, 1);
|
data = TMALLOC(struct pwldata, 1);
|
||||||
|
|
@ -794,6 +877,8 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
|
|
||||||
data->n = i;
|
data->n = i;
|
||||||
|
|
||||||
|
p->data = (void *) data;
|
||||||
|
|
||||||
for (w = p->left ; --i >= 0 ; w = w->left)
|
for (w = p->left ; --i >= 0 ; w = w->left)
|
||||||
if (w->right->type == PT_CONSTANT) {
|
if (w->right->type == PT_CONSTANT) {
|
||||||
data->vals[i] = w->right->constant;
|
data->vals[i] = w->right->constant;
|
||||||
|
|
@ -806,7 +891,7 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
fprintf(stderr, " type = %d\n", w->right->type);
|
fprintf(stderr, " type = %d\n", w->right->type);
|
||||||
//Breakpoint;
|
//Breakpoint;
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) only *literal* points are supported\n");
|
fprintf(stderr, "Error: PWL(expr, points...) only *literal* points are supported\n");
|
||||||
return (NULL);
|
return mkfirst(NULL, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
|
|
@ -817,15 +902,16 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
for (i = 2 ; i < data->n ; i += 2)
|
for (i = 2 ; i < data->n ; i += 2)
|
||||||
if(data->vals[i-2] >= data->vals[i]) {
|
if(data->vals[i-2] >= data->vals[i]) {
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) the abscissa of points must be ascending\n");
|
fprintf(stderr, "Error: PWL(expr, points...) the abscissa of points must be ascending\n");
|
||||||
return (NULL);
|
return mkfirst(NULL, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* strip all but the first arg,
|
/* strip all but the first arg,
|
||||||
* and attach the rest as opaque data to the INPparseNode
|
* and attach the rest as opaque data to the INPparseNode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
w = inc_usage(w);
|
||||||
|
dec_usage(p->left);
|
||||||
p->left = w;
|
p->left = w;
|
||||||
p->data = (void *) data;
|
|
||||||
|
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
@ -852,14 +938,16 @@ static INPparseNode *mkfnode(const char *fname, INPparseNode * arg)
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
||||||
p->type = PT_TERN;
|
p->type = PT_TERN;
|
||||||
p->left = arg1;
|
p->usecnt = 0;
|
||||||
p->right = mkb(PT_COMMA, arg2, arg3);
|
|
||||||
|
|
||||||
return (p);
|
p->left = inc_usage(arg1);
|
||||||
|
p->right = inc_usage(mkb(PT_COMMA, arg2, arg3));
|
||||||
|
|
||||||
|
return mkfirst(p, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Error: bogus ternary_fcn form\n");
|
fprintf(stderr, "Error: bogus ternary_fcn form\n");
|
||||||
return (NULL);
|
return mkfirst(NULL, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NUM_FUNCS; i++)
|
for (i = 0; i < NUM_FUNCS; i++)
|
||||||
|
|
@ -868,13 +956,15 @@ static INPparseNode *mkfnode(const char *fname, INPparseNode * arg)
|
||||||
|
|
||||||
if (i == NUM_FUNCS) {
|
if (i == NUM_FUNCS) {
|
||||||
fprintf(stderr, "Error: no such function '%s'\n", buf);
|
fprintf(stderr, "Error: no such function '%s'\n", buf);
|
||||||
return (NULL);
|
return mkfirst(NULL, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
||||||
p->type = PT_FUNCTION;
|
p->type = PT_FUNCTION;
|
||||||
p->left = arg;
|
p->usecnt = 0;
|
||||||
|
|
||||||
|
p->left = inc_usage(arg);
|
||||||
p->funcname = funcs[i].name;
|
p->funcname = funcs[i].name;
|
||||||
p->funcnum = funcs[i].number;
|
p->funcnum = funcs[i].number;
|
||||||
p->function = funcs[i].funcptr;
|
p->function = funcs[i].funcptr;
|
||||||
|
|
@ -911,6 +1001,7 @@ static INPparseNode *mkvnode(char *name)
|
||||||
}
|
}
|
||||||
p->valueIndex = i;
|
p->valueIndex = i;
|
||||||
p->type = PT_VAR;
|
p->type = PT_VAR;
|
||||||
|
p->usecnt = 0;
|
||||||
|
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
@ -939,6 +1030,7 @@ static INPparseNode *mkinode(char *name)
|
||||||
}
|
}
|
||||||
p->valueIndex = i;
|
p->valueIndex = i;
|
||||||
p->type = PT_VAR;
|
p->type = PT_VAR;
|
||||||
|
p->usecnt = 0;
|
||||||
|
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
@ -952,6 +1044,8 @@ static INPparseNode *mknnode(double number)
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
||||||
p->type = PT_CONSTANT;
|
p->type = PT_CONSTANT;
|
||||||
|
p->usecnt = 0;
|
||||||
|
|
||||||
p->constant = number;
|
p->constant = number;
|
||||||
|
|
||||||
return (p);
|
return (p);
|
||||||
|
|
@ -971,6 +1065,8 @@ static INPparseNode *mksnode(const char *string, void *ckt)
|
||||||
|
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
||||||
|
p->usecnt = 0;
|
||||||
|
|
||||||
if(!strcmp("time", buf)) {
|
if(!strcmp("time", buf)) {
|
||||||
p->type = PT_TIME;
|
p->type = PT_TIME;
|
||||||
p->data = ckt;
|
p->data = ckt;
|
||||||
|
|
@ -1221,6 +1317,72 @@ int PTlex (YYSTYPE *lvalp, struct PTltype *llocp, char **line)
|
||||||
return (token);
|
return (token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void INPfreeTree(IFparseTree *ptree)
|
||||||
|
{
|
||||||
|
INPparseTree *pt = (INPparseTree *) ptree;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < pt->p.numVars; i++)
|
||||||
|
dec_usage(pt->derivs[i]);
|
||||||
|
|
||||||
|
dec_usage(pt->tree);
|
||||||
|
|
||||||
|
txfree(pt->derivs);
|
||||||
|
txfree(pt->p.varTypes);
|
||||||
|
txfree(pt->p.vars);
|
||||||
|
txfree(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void free_tree(INPparseNode *pt)
|
||||||
|
{
|
||||||
|
if(!pt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pt->usecnt) {
|
||||||
|
fprintf(stderr, "ERROR: fatal internal error, %s\n", __func__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pt->type) {
|
||||||
|
case PT_TIME:
|
||||||
|
case PT_TEMPERATURE:
|
||||||
|
case PT_FREQUENCY:
|
||||||
|
case PT_CONSTANT:
|
||||||
|
case PT_VAR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PT_PLUS:
|
||||||
|
case PT_MINUS:
|
||||||
|
case PT_TIMES:
|
||||||
|
case PT_DIVIDE:
|
||||||
|
case PT_POWER:
|
||||||
|
case PT_COMMA:
|
||||||
|
case PT_TERN:
|
||||||
|
dec_usage(pt->right);
|
||||||
|
case PT_FUNCTION:
|
||||||
|
dec_usage(pt->left);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("oops");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pt->type == PT_FUNCTION && pt->funcnum == PTF_PWL) {
|
||||||
|
struct pwldata { int n; double *vals; } *data = (struct pwldata*)(pt->data);
|
||||||
|
if(data) {
|
||||||
|
txfree(data->vals);
|
||||||
|
txfree(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
txfree(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
|
|
||||||
/* Debugging stuff. */
|
/* Debugging stuff. */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue