Change the code that makes variables from device/model parameters
(spiceif.c) and vectors from variables (vectors.c) so that array and string-valued parameters and the resulting variables are handled correctly. Fix a memory leak in converting array parameters; that requires a change in cplask.c so that CPL devices behave the same way as others. Add a "device" variant of the Compose command so that generated vectors are available in scripts.
This commit is contained in:
parent
02172448e7
commit
cb69d8b96b
|
|
@ -226,6 +226,36 @@ com_compose(wordlist *wl)
|
|||
}
|
||||
|
||||
length *= blocksize;
|
||||
} else if (eq(wl->wl_word, "device") && resname[0] == '@') {
|
||||
/* Make vector(s) from device parameters; also works with models. */
|
||||
|
||||
result = vec_get(resname);
|
||||
|
||||
/* With @dev[all] a chain of vectors is returned. */
|
||||
|
||||
while (result) {
|
||||
char *cp;
|
||||
|
||||
/* Change name so it is not an array reference. */
|
||||
|
||||
for (cp = result->v_name; cp && *cp; ++cp) {
|
||||
if (*cp == '[')
|
||||
*cp = '_';
|
||||
if (*cp == ']') {
|
||||
*cp = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set dimension info */
|
||||
|
||||
result->v_numdims = 1;
|
||||
result->v_dims[0] = length;
|
||||
|
||||
result->v_flags |= VF_PERMANENT;
|
||||
result = result->v_link2;
|
||||
}
|
||||
goto done;
|
||||
#ifdef XSPICE
|
||||
} else if (eq(wl->wl_word, "xspice")) {
|
||||
/* Make vectors from an event node. */
|
||||
|
|
@ -240,7 +270,6 @@ com_compose(wordlist *wl)
|
|||
result->v_scale->v_flags |= VF_PERMANENT;
|
||||
vec_new(result->v_scale);
|
||||
cp_addkword(CT_VECTOR, result->v_scale->v_name);
|
||||
txfree(resname); // It was copied
|
||||
goto finished;
|
||||
#endif
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ extern INPmodel *modtab;
|
|||
extern NGHASHPTR modtabhash;
|
||||
extern bool ft_batchmode;
|
||||
|
||||
static struct variable *parmtovar(IFvalue *pv, IFparm *opt);
|
||||
static struct variable *parmtovar(IFvalue *pv, IFparm *opt,
|
||||
int use_description);
|
||||
static IFparm *parmlookup(IFdevice *dev, GENinstance **inptr, char *param,
|
||||
int do_model, int inout);
|
||||
static IFvalue *doask(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod,
|
||||
|
|
@ -688,17 +689,12 @@ spif_getparam_special(CKTcircuit *ckt, char **name, char *param, int ind, int do
|
|||
continue;
|
||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||
if (pv) {
|
||||
tv = parmtovar(pv, opt);
|
||||
|
||||
/* With the following we pack the name and the acronym of the parameter */
|
||||
{
|
||||
char *x = tv->va_name;
|
||||
tv->va_name = tprintf("%s [%s]", tv->va_name, device->instanceParms[i].keyword);
|
||||
tfree(x);
|
||||
tv = parmtovar(pv, opt, 0);
|
||||
if (tv) {
|
||||
if (vv)
|
||||
tv->va_next = vv;
|
||||
vv = tv;
|
||||
}
|
||||
if (vv)
|
||||
tv->va_next = vv;
|
||||
vv = tv;
|
||||
} else {
|
||||
fprintf(cp_err,
|
||||
"Internal Error: no parameter '%s' on device '%s'\n",
|
||||
|
|
@ -725,26 +721,12 @@ spif_getparam_special(CKTcircuit *ckt, char **name, char *param, int ind, int do
|
|||
continue;
|
||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||
if (pv) {
|
||||
tv = parmtovar(pv, opt);
|
||||
/* Inside parmtovar:
|
||||
* 1. tv->va_name = copy(opt->description);
|
||||
* 2. Copy the type of variable of IFparm into a variable (thus parm-to-var)
|
||||
* vv->va_type = opt->dataType
|
||||
* The long description of the parameter:
|
||||
* IFparm MOS_SGTmPTable[] = { // model parameters //
|
||||
* OP("type", MOS_SGT_MOD_TYPE, IF_STRING, "N-channel or P-channel MOS")
|
||||
* goes into tv->va_name to put braces around the parameter of the model
|
||||
* tv->va_name += device->modelParms[i].keyword;
|
||||
*/
|
||||
{
|
||||
char *x = tv->va_name;
|
||||
tv->va_name = tprintf("%s [%s]", tv->va_name, device->modelParms[i].keyword);
|
||||
tfree(x);
|
||||
tv = parmtovar(pv, opt, 0);
|
||||
if (tv) {
|
||||
if (vv)
|
||||
tv->va_next = vv;
|
||||
vv = tv;
|
||||
}
|
||||
/* tv->va_string = device->modelParms[i].keyword; Put the name of the variable */
|
||||
if (vv)
|
||||
tv->va_next = vv;
|
||||
vv = tv;
|
||||
} else {
|
||||
fprintf(cp_err,
|
||||
"Internal Error: no parameter '%s' on device '%s'\n",
|
||||
|
|
@ -768,7 +750,7 @@ spif_getparam_special(CKTcircuit *ckt, char **name, char *param, int ind, int do
|
|||
}
|
||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||
if (pv)
|
||||
vv = parmtovar(pv, opt);
|
||||
vv = parmtovar(pv, opt, 0);
|
||||
return (vv);
|
||||
} else {
|
||||
return (if_getstat(ckt, *name));
|
||||
|
|
@ -814,10 +796,12 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model)
|
|||
continue;
|
||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||
if (pv) {
|
||||
tv = parmtovar(pv, opt);
|
||||
if (vv)
|
||||
tv->va_next = vv;
|
||||
vv = tv;
|
||||
tv = parmtovar(pv, opt, 0);
|
||||
if (tv) {
|
||||
if (vv)
|
||||
tv->va_next = vv;
|
||||
vv = tv;
|
||||
}
|
||||
} else {
|
||||
fprintf(cp_err,
|
||||
"Internal Error: no parameter '%s' on device '%s'\n",
|
||||
|
|
@ -843,7 +827,7 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model)
|
|||
}
|
||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||
if (pv)
|
||||
vv = parmtovar(pv, opt);
|
||||
vv = parmtovar(pv, opt, 0);
|
||||
return (vv);
|
||||
} else {
|
||||
return (if_getstat(ckt, *name));
|
||||
|
|
@ -991,49 +975,90 @@ if_setparam(CKTcircuit *ckt, char **name, char *param, struct dvec *val, int do_
|
|||
}
|
||||
}
|
||||
|
||||
/* Make a linked list where the first node is a CP_LIST variable
|
||||
* pointing to the different values of the vector variables.
|
||||
*
|
||||
*
|
||||
* In the case of Vin_sin 1 0 sin (0 2 2000)
|
||||
* and of print @vin_sin[sin]
|
||||
*
|
||||
* vv->va_V.vV_list->va_V.vV_real = 2000
|
||||
* vv->va_V.vV_list->va_next->va_V.vV_real = 2
|
||||
* vv->va_V.vV_list->va_next->va_next->va_V.vV_real = 0
|
||||
* So the list is starting from behind, but no problem
|
||||
* This works fine
|
||||
*/
|
||||
|
||||
static struct variable *
|
||||
parmtovar(IFvalue *pv, IFparm *opt)
|
||||
parmtolist(IFvalue *pv, IFparm *opt, char *name)
|
||||
{
|
||||
/* It is not clear whether we want to name the variable
|
||||
* by `keyword' or by `description' */
|
||||
struct variable *list = NULL;
|
||||
int i;
|
||||
|
||||
for (i = pv->v.numValue; --i >= 0;) {
|
||||
switch (opt->dataType & (IF_VARTYPES & ~IF_VECTOR)) {
|
||||
case IF_INTEGER:
|
||||
list = var_alloc_num(NULL, pv->v.vec.iVec[i], list);
|
||||
break;
|
||||
case IF_REAL:
|
||||
case IF_COMPLEX:
|
||||
list = var_alloc_real(NULL, pv->v.vec.rVec[i], list);
|
||||
break;
|
||||
case IF_STRING:
|
||||
list = var_alloc_string(NULL, copy(pv->v.vec.sVec[i]), list);
|
||||
break;
|
||||
case IF_FLAG:
|
||||
list = var_alloc_bool(NULL, pv->v.vec.iVec[i] ? TRUE : FALSE,
|
||||
list);
|
||||
break;
|
||||
default:
|
||||
fprintf(cp_err,
|
||||
"parmtolist: Internal Error: bad PARM type "
|
||||
"%#x for %s (%s).\n",
|
||||
opt->dataType, opt->keyword, opt->description);
|
||||
if (name)
|
||||
free(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i || pv->v.numValue == 0)
|
||||
list = var_alloc_vlist(name, list, NULL);
|
||||
if (pv->v.vec.iVec) { // All the union members are pointers
|
||||
free(pv->v.vec.iVec);
|
||||
pv->v.vec.iVec = NULL;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static struct variable *
|
||||
parmtovar(IFvalue *pv, IFparm *opt, int use_description)
|
||||
{
|
||||
char *name;
|
||||
|
||||
name = use_description ? opt->description : opt->keyword;
|
||||
if (name)
|
||||
name = copy(name);
|
||||
if (opt->dataType & IF_VECTOR)
|
||||
return parmtolist(pv, opt, name);
|
||||
|
||||
switch (opt->dataType & IF_VARTYPES) {
|
||||
case IF_INTEGER:
|
||||
return var_alloc_num(copy(opt->description), pv->iValue, NULL);
|
||||
return var_alloc_num(name, pv->iValue, NULL);
|
||||
case IF_REAL:
|
||||
case IF_COMPLEX:
|
||||
return var_alloc_real(copy(opt->description), pv->rValue, NULL);
|
||||
return var_alloc_real(name, pv->rValue, NULL);
|
||||
case IF_STRING:
|
||||
return var_alloc_string(copy(opt->description), pv->sValue, NULL);
|
||||
return var_alloc_string(name, copy(pv->sValue), NULL);
|
||||
case IF_FLAG:
|
||||
return var_alloc_bool(copy(opt->description), pv->iValue ? TRUE : FALSE, NULL);
|
||||
case IF_REALVEC: {
|
||||
struct variable *list = NULL;
|
||||
int i;
|
||||
for (i = pv->v.numValue; --i >= 0;)
|
||||
list = var_alloc_real(NULL, pv->v.vec.rVec[i], list);
|
||||
return var_alloc_vlist(copy(opt->description), list, NULL);
|
||||
/* It is a linked list where the first node is a variable
|
||||
* pointing to the different values of the variables.
|
||||
*
|
||||
* To access the values of the real variable vector must be
|
||||
* vv->va_V.vV_real = valor node ppal that is of no use.
|
||||
*
|
||||
* In the case of Vin_sin 1 0 sin (0 2 2000)
|
||||
* and of print @vin_sin[sin]
|
||||
*
|
||||
* vv->va_V.vV_list->va_V.vV_real = 2000
|
||||
* vv->va_V.vV_list->va_next->va_V.vV_real = 2
|
||||
* vv->va_V.vV_list->va_next->va_next->va_V.vV_real = 0
|
||||
* So the list is starting from behind, but no problem
|
||||
* This works fine
|
||||
*/
|
||||
}
|
||||
return var_alloc_bool(name, pv->iValue ? TRUE : FALSE,
|
||||
NULL);
|
||||
default:
|
||||
fprintf(cp_err,
|
||||
"parmtovar: Internal Error: bad PARM type %d.\n",
|
||||
opt->dataType);
|
||||
"parmtovar: Internal Error: bad PARM type %#x for %s (%s).\n",
|
||||
opt->dataType, opt->keyword, opt->description);
|
||||
if (name)
|
||||
free(name);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -1317,7 +1342,7 @@ if_getstat(CKTcircuit *ckt, char *name)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
return (parmtovar(&parm, if_parm));
|
||||
return (parmtovar(&parm, if_parm, 1));
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1339,7 +1364,7 @@ if_getstat(CKTcircuit *ckt, char *name)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
*v = parmtovar(&parm, if_parm);
|
||||
*v = parmtovar(&parm, if_parm, 1);
|
||||
v = &((*v)->va_next);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -580,8 +580,8 @@ vec_get(const char *vec_name) {
|
|||
struct dvec *d, *end = NULL, *newv = NULL;
|
||||
struct plot *pl;
|
||||
char buf[BSIZE_SP], *s, *wd, *word, *whole, *name = NULL, *param;
|
||||
int i = 0;
|
||||
struct variable *vv;
|
||||
int i = 0;
|
||||
struct variable *vv, *v;
|
||||
|
||||
wd = word = copy(vec_name); /* Gets mangled below... */
|
||||
|
||||
|
|
@ -638,6 +638,8 @@ vec_get(const char *vec_name) {
|
|||
}
|
||||
|
||||
if (!d && (*word == SPECCHAR)) { /* "@" */
|
||||
int multiple;
|
||||
|
||||
/* This is a special quantity... */
|
||||
if (ft_nutmeg) {
|
||||
fprintf(cp_err,
|
||||
|
|
@ -646,6 +648,12 @@ vec_get(const char *vec_name) {
|
|||
return (NULL); /* va: use NULL */
|
||||
}
|
||||
|
||||
if (!ft_curckt) {
|
||||
fprintf(cp_err, "Error: No circuit loaded.\n");
|
||||
tfree(wd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
whole = copy(word);
|
||||
name = ++word;
|
||||
for (param = name; *param && (*param != '['); param++)
|
||||
|
|
@ -660,157 +668,131 @@ vec_get(const char *vec_name) {
|
|||
param = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is what is done in case of "alter r1 resistance = 1234"
|
||||
* r1 resistance, 0
|
||||
* if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model);
|
||||
*/
|
||||
|
||||
if (ft_curckt) {
|
||||
/*
|
||||
* This is what is done in case of "alter r1 resistance = 1234"
|
||||
* r1 resistance, 0
|
||||
* if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model);
|
||||
*/
|
||||
|
||||
/* vv = if_getparam (ft_curckt->ci_ckt, &name, param, 0, 0); */
|
||||
vv = if_getparam(ft_curckt->ci_ckt, &name, param, 0, 0);
|
||||
if (!vv) {
|
||||
tfree(whole);
|
||||
tfree(wd);
|
||||
return (NULL);
|
||||
}
|
||||
} else {
|
||||
fprintf(cp_err, "Error: No circuit loaded.\n");
|
||||
vv = if_getparam(ft_curckt->ci_ckt, &name, param, 0, 0);
|
||||
if (!vv) {
|
||||
tfree(whole);
|
||||
tfree(wd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
d = dvec_alloc(copy(whole), /* MW. The same as word before */
|
||||
SV_NOTYPE,
|
||||
VF_REAL, /* No complex values yet... */
|
||||
1, NULL);
|
||||
|
||||
/* In case the represented variable is a REAL vector this takes
|
||||
* the actual value of the first element of the linked list which
|
||||
* does not make sense.
|
||||
* This is an error.
|
||||
/* If vec_name was "@dev", "@model", "@dev[all]" or @model[all]",
|
||||
* if_getparam() returns a list.
|
||||
*/
|
||||
|
||||
/* This will copy the contents of the structure vv in another structure
|
||||
* dvec (FTEDATA.H) that do not have INTEGER so that those parameters
|
||||
* defined as IF_INTEGER are not given their value when using
|
||||
* print @pot[pos_node]
|
||||
* To fix this, it is necessary to define:
|
||||
* OPU( "pos_node", POT_QUEST_POS_NODE, IF_REAL,"Positive node of potenciometer"),
|
||||
* int POTnegNode; // number of negative node of potenciometer (Nodo_3)
|
||||
* case POT_QUEST_POS_NODE:
|
||||
* value->rValue = (double)fast->POTposNode;
|
||||
* return (OK);
|
||||
* Works but with the format 1.00000E0
|
||||
*/
|
||||
multiple = (vv->va_next != NULL);
|
||||
if (multiple && param)
|
||||
*--param = '\0';
|
||||
|
||||
/* We must make a change in format between the data that carries a variable to
|
||||
* put in a dvec.
|
||||
*/
|
||||
for (v = vv; v; v = v->va_next) {
|
||||
struct dvec *nd;
|
||||
char *vec_name, new_name[256];
|
||||
|
||||
/*
|
||||
* #define va_bool va_V.vV_bool
|
||||
* #define va_num va_V.vV_num
|
||||
* #define va_real va_V.vV_real
|
||||
* #define va_string va_V.vV_string
|
||||
* #define va_vlist va_V.vV_list
|
||||
* enum cp_types {
|
||||
* CP_BOOL,
|
||||
* CP_NUM,
|
||||
* CP_REAL,
|
||||
* CP_STRING,
|
||||
* CP_LIST
|
||||
° };
|
||||
*/
|
||||
|
||||
/* The variable is a vector */
|
||||
if (vv->va_type == CP_LIST) {
|
||||
/* Compute the length of the vector,
|
||||
* used with the parameters of isrc and vsrc
|
||||
*/
|
||||
struct variable *nv;
|
||||
|
||||
/* Count the number of nodes in the list */
|
||||
i = 0;
|
||||
for (nv = vv->va_vlist; nv; nv = nv->va_next) {
|
||||
i++;
|
||||
if (multiple) {
|
||||
snprintf(new_name, sizeof new_name, "@%s[%s]",
|
||||
name, v->va_name);
|
||||
vec_name = new_name;
|
||||
} else {
|
||||
vec_name = whole;
|
||||
}
|
||||
nd = dvec_alloc(copy(vec_name),
|
||||
SV_NOTYPE,
|
||||
VF_REAL, /* No complex values yet... */
|
||||
1, NULL);
|
||||
|
||||
dvec_realloc(d, i, NULL); /* Resize to # nodes */
|
||||
switch (v->va_type) {
|
||||
case CP_BOOL:
|
||||
*nd->v_realdata = (double)v->va_bool;
|
||||
break;
|
||||
case CP_NUM:
|
||||
*nd->v_realdata = (double)v->va_num;
|
||||
break;
|
||||
case CP_REAL:
|
||||
*nd->v_realdata = v->va_real;
|
||||
break;
|
||||
case CP_STRING:
|
||||
fprintf(stderr,
|
||||
"ERROR: can not handle string value "
|
||||
"of '%s' in vec_get(%s)\nIgnoring...\n",
|
||||
v->va_name, vec_name);
|
||||
dvec_free(nd);
|
||||
continue;
|
||||
break;
|
||||
case CP_LIST:
|
||||
{
|
||||
struct variable *nv;
|
||||
enum cp_types ft;
|
||||
|
||||
/* Step through the list again, setting values this time */
|
||||
i = 0;
|
||||
for (nv = vv->va_vlist; nv; nv = nv->va_next) {
|
||||
d->v_realdata[i++] = nv->va_real;
|
||||
}
|
||||
|
||||
/* To be able to identify the vector to represent
|
||||
* belongs to a special "conunto" and should be printed in a
|
||||
* special way.
|
||||
*/
|
||||
d->v_dims[1] = 1;
|
||||
}
|
||||
else if (vv->va_type == CP_NUM) { /* Variable is an integer */
|
||||
*d->v_realdata = (double) vv->va_num;
|
||||
}
|
||||
else if (vv->va_type == CP_REAL) { /* Variable is a real */
|
||||
if (!(vv->va_next)) {
|
||||
/* Only a real data
|
||||
* usually normal
|
||||
*/
|
||||
*d->v_realdata = vv->va_real;
|
||||
}
|
||||
else {
|
||||
/* Real data set
|
||||
* When you print a model @ [all]
|
||||
* Just print numerical values, not the string
|
||||
*/
|
||||
struct variable *nv;
|
||||
/* We go to print the list of values
|
||||
* nv->va_name = Parameter description
|
||||
* nv->va_string = Parameter
|
||||
* nv->va_real= Value
|
||||
*/
|
||||
nv = vv;
|
||||
for (i = 1; ; i++) {
|
||||
switch (nv->va_type) {
|
||||
case CP_REAL:
|
||||
fprintf(stdout, "%s=%g\n", nv->va_name, nv->va_real);
|
||||
break;
|
||||
case CP_STRING:
|
||||
fprintf(stdout, "%s=%s\n", nv->va_name, nv->va_string);
|
||||
break;
|
||||
case CP_NUM:
|
||||
fprintf(stdout, "%s=%d\n", nv->va_name, nv->va_num);
|
||||
break;
|
||||
case CP_BOOL:
|
||||
fprintf(stdout, "%s=%d\n", nv->va_name, nv->va_bool);
|
||||
break;
|
||||
default: {
|
||||
fprintf(stderr, "ERROR: enumeration value `CP_LIST' not handled in vec_get\nIgnoring...\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
nv = nv->va_next;
|
||||
/* Array values are presented as a list.
|
||||
* Compute the length of the vector, and check that
|
||||
* it is homogenous:
|
||||
* used with the parameters of isrc and vsrc
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
nv = v->va_vlist;
|
||||
if (!nv) {
|
||||
break;
|
||||
dvec_free(nd);
|
||||
continue;
|
||||
}
|
||||
ft = nv->va_type;
|
||||
for (; nv; nv = nv->va_next) {
|
||||
/* Count the number of nodes in the list */
|
||||
|
||||
i++;
|
||||
if (nv->va_type != ft)
|
||||
break;
|
||||
}
|
||||
if (nv || ft == CP_STRING || ft == CP_LIST) {
|
||||
fprintf(stderr,
|
||||
"ERROR: can not handle mixed, string or list "
|
||||
"value of '%s' in vec_get(%s)\nIgnoring...\n",
|
||||
v->va_name, vec_name);
|
||||
dvec_free(nd);
|
||||
continue;
|
||||
}
|
||||
dvec_realloc(nd, i, NULL); /* Resize to # nodes */
|
||||
|
||||
/* Step through the list again, setting values this time */
|
||||
|
||||
i = 0;
|
||||
for (nv = v->va_vlist; nv; nv = nv->va_next) {
|
||||
switch (ft) {
|
||||
case CP_BOOL:
|
||||
nd->v_realdata[i++] = (double)nv->va_bool;
|
||||
break;
|
||||
case CP_NUM:
|
||||
nd->v_realdata[i++] = (double)nv->va_num;
|
||||
break;
|
||||
default:
|
||||
case CP_REAL:
|
||||
nd->v_realdata[i++] = nv->va_real;
|
||||
break;
|
||||
}
|
||||
|
||||
/* To be able to identify the vector to represent
|
||||
* belongs to a special "conunto" and should be printed
|
||||
* in a special way.
|
||||
*/
|
||||
nd->v_dims[1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* To distinguish those does not take anything for print screen to
|
||||
* make a print or M1 @ @ M1 [all] leaving only the correct data
|
||||
* and not the last
|
||||
*/
|
||||
d->v_rlength = 1;
|
||||
break;
|
||||
}
|
||||
/* Chain it on. */
|
||||
|
||||
vec_new(nd);
|
||||
nd->v_link2 = d;
|
||||
d = nd;
|
||||
}
|
||||
|
||||
free_struct_variable(vv);
|
||||
tfree(wd);
|
||||
vec_new(d);
|
||||
tfree(whole);
|
||||
return d;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,18 @@ CPLask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *s
|
|||
NG_IGNORE(select);
|
||||
|
||||
switch(which) {
|
||||
/* String tables are expected to be freed, but not the strings. */
|
||||
|
||||
case CPL_POS_NODE:
|
||||
value->v.vec.sVec = here->in_node_names;
|
||||
value->v.vec.sVec = TMALLOC(char *, here->dimension);
|
||||
memcpy(value->v.vec.sVec, here->in_node_names,
|
||||
here->dimension * sizeof (char *));
|
||||
value->v.numValue = here->dimension;
|
||||
return(OK);
|
||||
case CPL_NEG_NODE:
|
||||
value->v.vec.sVec = here->out_node_names;
|
||||
value->v.vec.sVec = TMALLOC(char *, here->dimension);
|
||||
memcpy(value->v.vec.sVec, here->out_node_names,
|
||||
here->dimension * sizeof (char *));
|
||||
value->v.numValue = here->dimension;
|
||||
return(OK);
|
||||
case CPL_DIM:
|
||||
|
|
|
|||
Loading…
Reference in New Issue