Fix variables so that they behave as described (or intended) in the ngspice-26plus manual.
This commit is contained in:
parent
9d32a0a5a9
commit
ee2eb66c45
|
|
@ -33,23 +33,26 @@ wordlist *
|
|||
cp_varwl(struct variable *var)
|
||||
{
|
||||
wordlist *wl = NULL, *w, *wx = NULL;
|
||||
char *buf;
|
||||
char buf[BSIZE_SP], *copystring;
|
||||
struct variable *vt;
|
||||
|
||||
switch (var->va_type) {
|
||||
case CP_BOOL:
|
||||
/* Can't ever be FALSE. */
|
||||
buf = copy(var->va_bool ? "TRUE" : "FALSE");
|
||||
sprintf(buf, "%s", var->va_bool ? "TRUE" : "FALSE");
|
||||
break;
|
||||
case CP_NUM:
|
||||
buf = tprintf("%d", var->va_num);
|
||||
sprintf(buf, "%d", var->va_num);
|
||||
break;
|
||||
case CP_REAL:
|
||||
/* This is a case where printnum isn't too good... */
|
||||
buf = tprintf("%G", var->va_real);
|
||||
sprintf(buf, "%G", var->va_real);
|
||||
break;
|
||||
case CP_STRING:
|
||||
buf = cp_unquote(var->va_string);
|
||||
/*strcpy(buf, cp_unquote(var->va_string)); DG: memory leak here*/
|
||||
copystring = cp_unquote(var->va_string); /*DG*/
|
||||
strcpy(buf, copystring);
|
||||
tfree(copystring);
|
||||
break;
|
||||
case CP_LIST: /* The tricky case. */
|
||||
for (vt = var->va_vlist; vt; vt = vt->va_next) {
|
||||
|
|
@ -65,12 +68,13 @@ cp_varwl(struct variable *var)
|
|||
return (wl);
|
||||
default:
|
||||
fprintf(cp_err,
|
||||
"cp_varwl: Internal Error: bad variable type %d\n",
|
||||
"cp_varwl: INTERNAL ERROR: bad variable type %d\n",
|
||||
var->va_type);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return wl_cons(buf, NULL);
|
||||
wl = wl_cons(copy(buf), NULL);
|
||||
return wl;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -143,7 +147,7 @@ cp_vset(char *varname, enum cp_types type, void *value)
|
|||
|
||||
default:
|
||||
fprintf(cp_err,
|
||||
"cp_vset: Internal Error: bad variable type %d.\n",
|
||||
"cp_vset: INTERNAL ERROR: bad variable type %d.\n",
|
||||
type);
|
||||
tfree(copyvarname);
|
||||
return;
|
||||
|
|
@ -152,7 +156,7 @@ cp_vset(char *varname, enum cp_types type, void *value)
|
|||
v->va_type = type;
|
||||
|
||||
/* Now, see if there is anything interesting going on. We
|
||||
* recognise these special variables: noglob, nonomatch, history,
|
||||
* recognize these special variables: noglob, nonomatch, history,
|
||||
* echo, noclobber, prompt, and verbose. cp_remvar looks for these
|
||||
* variables too. The host program will get any others. */
|
||||
if (eq(copyvarname, "noglob"))
|
||||
|
|
@ -165,18 +169,14 @@ cp_vset(char *varname, enum cp_types type, void *value)
|
|||
cp_maxhistlength = (int)floor(v->va_real + 0.5);
|
||||
else if (eq(copyvarname, "noclobber"))
|
||||
cp_noclobber = TRUE;
|
||||
else if (eq(varname, "echo")) /*CDHW*/
|
||||
cp_echo = TRUE; /*CDHW*/
|
||||
else if (eq(varname, "echo"))
|
||||
cp_echo = TRUE;
|
||||
else if (eq(copyvarname, "prompt") && (type == CP_STRING))
|
||||
cp_promptstring = v->va_string;
|
||||
else if (eq(copyvarname, "ignoreeof"))
|
||||
cp_ignoreeof = TRUE;
|
||||
else if (eq(copyvarname, "cpdebug")) {
|
||||
cp_debug = TRUE;
|
||||
#ifndef CPDEBUG
|
||||
fprintf(cp_err,
|
||||
"Warning: program not compiled with cshpar debug messages\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (i = cp_usrset(v, TRUE)) {
|
||||
|
|
@ -192,15 +192,15 @@ cp_vset(char *varname, enum cp_types type, void *value)
|
|||
case US_DONTRECORD:
|
||||
/* Do nothing... */
|
||||
if (alreadythere) {
|
||||
fprintf(cp_err, "cp_vset: Internal Error: "
|
||||
"%s already there, but 'dont record'\n", v->va_name);
|
||||
fprintf(cp_err, "cp_vset: INTERNAL ERROR: "
|
||||
"%s already there, but `don't record'\n", v->va_name);
|
||||
}
|
||||
break;
|
||||
|
||||
case US_READONLY:
|
||||
fprintf(cp_err, "Error: %s is a read-only variable.\n", v->va_name);
|
||||
fprintf(cp_err, "ERROR: %s is a read-only variable.\n", v->va_name);
|
||||
if (alreadythere)
|
||||
fprintf(cp_err, "cp_vset: Internal Error: "
|
||||
fprintf(cp_err, "cp_vset: INTERNAL ERROR: "
|
||||
"it was already there too!!\n");
|
||||
break;
|
||||
|
||||
|
|
@ -230,16 +230,8 @@ cp_vset(char *varname, enum cp_types type, void *value)
|
|||
else if (u->va_type == CP_LIST)
|
||||
tfree(u->va_vlist);
|
||||
u->va_V = v->va_V;
|
||||
/* va_name is the same string */
|
||||
u->va_type = v->va_type;
|
||||
/* va_next left unchanged */
|
||||
// tfree(v->va_name);
|
||||
tfree(v);
|
||||
/* va: old version with memory leaks
|
||||
w = u->va_next;
|
||||
bcopy(v, u, sizeof(*u));
|
||||
u->va_next = w;
|
||||
*/
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -251,24 +243,28 @@ cp_vset(char *varname, enum cp_types type, void *value)
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(cp_err, "cp_vset: Internal Error: bad US val %d\n", i);
|
||||
fprintf(cp_err, "cp_vset: INTERNAL ERROR: bad US val %d\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
/* if (v_free) {
|
||||
tfree(v->va_name);
|
||||
tfree(v);
|
||||
} */
|
||||
tfree(copyvarname);
|
||||
}
|
||||
|
||||
|
||||
/*CDHW This needs leak checking carefully CDHW*/
|
||||
/* CDHW This needs leak checking carefully CDHW */
|
||||
/* mhx: Uses ft_numparse, which interprets SPICE numbers. Therefore it worked incorrectly
|
||||
for com_set: it prevented e.g. set ape="1MEG" (ape became CP_NUM 1e6 instead of CP_STRING '1meg').
|
||||
Therefore I changed the function to FIRST check if the rhs is a string (look for quotes), and only
|
||||
if it is not, continue with ft_numparse.
|
||||
Note: cp_setparse is used by com_set and com_option, where this new behavior should be ok.
|
||||
cp_setparse is used in inp.c (4) for .option scale=xxx. Assumed new behavior will be ok.
|
||||
cp_setparse is used in rawfile.c (2) to parse "option: xxx". Assumed new behavior will be ok.
|
||||
*/
|
||||
struct variable *
|
||||
cp_setparse(wordlist *wl)
|
||||
{
|
||||
char *name = NULL, *val, *copyval, *s, *ss;
|
||||
double *td;
|
||||
bool isstring;
|
||||
struct variable *listv = NULL, *vv, *lv = NULL;
|
||||
struct variable *vars = NULL;
|
||||
int balance;
|
||||
|
|
@ -281,7 +277,7 @@ cp_setparse(wordlist *wl)
|
|||
name = cp_unquote(wl->wl_word);
|
||||
|
||||
wl = wl->wl_next;
|
||||
if ((!wl || (*wl->wl_word != '=')) && !strchr(name, '=')) {
|
||||
if ((!wl || (*wl->wl_word != '=')) && !strchr(name, '=')) { /* 'name ccccc' */
|
||||
vv = alloc(struct variable);
|
||||
vv->va_name = copy(name);
|
||||
vv->va_type = CP_BOOL;
|
||||
|
|
@ -292,10 +288,10 @@ cp_setparse(wordlist *wl)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (wl && eq(wl->wl_word, "=")) {
|
||||
if (wl && eq(wl->wl_word, "=")) { /* 'name =' */
|
||||
wl = wl->wl_next;
|
||||
if (wl == NULL) {
|
||||
fprintf(cp_err, "Error: bad set form.\n");
|
||||
fprintf(cp_err, "ERROR: bad set form.\n");
|
||||
tfree(name); /*DG: cp_unquote Memory leak*/
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
|
|
@ -303,7 +299,7 @@ cp_setparse(wordlist *wl)
|
|||
}
|
||||
val = wl->wl_word;
|
||||
wl = wl->wl_next;
|
||||
} else if (wl && (*wl->wl_word == '=')) {
|
||||
} else if (wl && (*wl->wl_word == '=')) { /* name =' */
|
||||
val = wl->wl_word + 1;
|
||||
wl = wl->wl_next;
|
||||
} else if ((s = strchr(name, '=')) != NULL) {
|
||||
|
|
@ -311,7 +307,7 @@ cp_setparse(wordlist *wl)
|
|||
*s = '\0';
|
||||
if (*val == '\0') {
|
||||
if (!wl) {
|
||||
fprintf(cp_err, "Error: %s equals what?.\n", name);
|
||||
fprintf(cp_err, "ERROR: %s equals what?\n", name);
|
||||
tfree(name); /*DG: cp_unquote Memory leak: free name before exiting*/
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
|
|
@ -322,7 +318,7 @@ cp_setparse(wordlist *wl)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(cp_err, "Error: bad set form.\n");
|
||||
fprintf(cp_err, "ERROR: bad set form\n");
|
||||
tfree(name); /*DG: cp_unquote Memory leak: free name befor exiting */
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
|
|
@ -330,6 +326,7 @@ cp_setparse(wordlist *wl)
|
|||
}
|
||||
|
||||
/* val = cp_unquote(val); DG: bad old val is lost*/
|
||||
isstring = (*val == '"'); /* mhx: is this sufficient? */
|
||||
copyval = cp_unquote(val); /*DG*/
|
||||
strcpy(val, copyval);
|
||||
tfree(copyval);
|
||||
|
|
@ -340,6 +337,7 @@ cp_setparse(wordlist *wl)
|
|||
* ()'s, treat them as tokens... */
|
||||
balance = 1;
|
||||
while (wl && wl->wl_word) {
|
||||
bool isstringc;
|
||||
if (eq(wl->wl_word, "(")) {
|
||||
balance++;
|
||||
} else if (eq(wl->wl_word, ")")) {
|
||||
|
|
@ -348,7 +346,12 @@ cp_setparse(wordlist *wl)
|
|||
}
|
||||
vv = alloc(struct variable);
|
||||
vv->va_next = NULL;
|
||||
isstringc = (*wl->wl_word == '"'); /* mhx: is this sufficient? */
|
||||
copyval = ss = cp_unquote(wl->wl_word);
|
||||
if (isstringc) {
|
||||
vv->va_type = CP_STRING;
|
||||
vv->va_string = copy(ss);
|
||||
} else {
|
||||
td = ft_numparse(&ss, FALSE);
|
||||
if (td) {
|
||||
vv->va_type = CP_REAL;
|
||||
|
|
@ -356,6 +359,8 @@ cp_setparse(wordlist *wl)
|
|||
} else {
|
||||
vv->va_type = CP_STRING;
|
||||
vv->va_string = copy(ss);
|
||||
fprintf(cp_err, "cp_setparse() :: ft_numparse() didn't recognize `%s' for assignment to `%s' as CP_REAL, using CP_STRING.\n", ss, name);
|
||||
}
|
||||
}
|
||||
tfree(copyval); /*DG: must free ss any way to avoid cp_unquote memory leak*/
|
||||
if (listv) {
|
||||
|
|
@ -367,7 +372,7 @@ cp_setparse(wordlist *wl)
|
|||
wl = wl->wl_next;
|
||||
}
|
||||
if (balance && !wl) {
|
||||
fprintf(cp_err, "Error: bad set form.\n");
|
||||
fprintf(cp_err, "ERROR: bad set form\n");
|
||||
tfree(name); /* va: cp_unquote memory leak: free name before exiting */
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
|
|
@ -385,19 +390,26 @@ cp_setparse(wordlist *wl)
|
|||
continue;
|
||||
}
|
||||
|
||||
copyval = ss = cp_unquote(val);
|
||||
td = ft_numparse(&ss, FALSE);
|
||||
/* there shouldn't be quotes around val at this point? */
|
||||
if (*val == '"')
|
||||
isstring |= TRUE; /* mhx: is this sufficient? */
|
||||
copyval = ss = cp_unquote(val); /* 'name = ccccc' */
|
||||
vv = alloc(struct variable);
|
||||
vv->va_name = copy(name);
|
||||
vv->va_next = vars;
|
||||
vars = vv;
|
||||
if (td) {
|
||||
/*** We should try to get CP_NUM's... */
|
||||
vv->va_type = CP_REAL;
|
||||
vv->va_real = *td;
|
||||
} else {
|
||||
if (isstring) {
|
||||
vv->va_type = CP_STRING;
|
||||
vv->va_string = copy(val);
|
||||
} else {
|
||||
td = ft_numparse(&ss, FALSE); /* FALSE: because set x=1umeter should work and 'meter' ignored */
|
||||
if (td) {
|
||||
vv->va_type = CP_REAL;
|
||||
vv->va_real = *td;
|
||||
} else {
|
||||
vv->va_type = CP_STRING;
|
||||
vv->va_string = copy(val);
|
||||
}
|
||||
}
|
||||
tfree(copyval); /*DG: must free ss any way to avoid cp_unquote memory leak */
|
||||
tfree(name); /* va: cp_unquote memory leak: free name for every loop */
|
||||
|
|
@ -477,8 +489,8 @@ cp_remvar(char *varname)
|
|||
cp_nonomatch = FALSE;
|
||||
else if (eq(varname, "noclobber"))
|
||||
cp_noclobber = FALSE;
|
||||
else if (eq(varname, "echo")) /*CDHW*/
|
||||
cp_echo = FALSE; /*CDHW*/
|
||||
else if (eq(varname, "echo"))
|
||||
cp_echo = FALSE;
|
||||
else if (eq(varname, "prompt"))
|
||||
cp_promptstring = NULL;
|
||||
else if (eq(varname, "cpdebug"))
|
||||
|
|
@ -510,14 +522,14 @@ cp_remvar(char *varname)
|
|||
case US_DONTRECORD:
|
||||
/* Do nothing... */
|
||||
if (found)
|
||||
fprintf(cp_err, "cp_remvar: Internal Error: var %d\n", *varname);
|
||||
fprintf(cp_err, "cp_remvar: INTERNAL ERROR: var %d\n", *varname);
|
||||
break;
|
||||
|
||||
case US_READONLY:
|
||||
/* Badness... */
|
||||
fprintf(cp_err, "Error: %s is read-only.\n", v->va_name);
|
||||
fprintf(cp_err, "ERROR: %s is read-only.\n", v->va_name);
|
||||
if (found)
|
||||
fprintf(cp_err, "cp_remvar: Internal Error: var %d\n", *varname);
|
||||
fprintf(cp_err, "cp_remvar: INTERNAL ERROR: var %d\n", *varname);
|
||||
break;
|
||||
|
||||
case US_SIMVAR:
|
||||
|
|
@ -540,7 +552,7 @@ cp_remvar(char *varname)
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(cp_err, "cp_remvar: Internal Error: US val %d\n", i);
|
||||
fprintf(cp_err, "cp_remvar: INTERNAL ERROR: US val %d\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -551,8 +563,10 @@ cp_remvar(char *varname)
|
|||
}
|
||||
|
||||
|
||||
/* Determine the value of a variable. Fail if the variable is unset,
|
||||
* and if the type doesn't match, try and make it work... */
|
||||
/*
|
||||
* Determine the value of a variable. Fail if the variable is unset,
|
||||
* and if the type doesn't match, try and make it work...
|
||||
*/
|
||||
bool
|
||||
cp_getvar(char *name, enum cp_types type, void *retval)
|
||||
{
|
||||
|
|
@ -561,11 +575,6 @@ cp_getvar(char *name, enum cp_types type, void *retval)
|
|||
|
||||
cp_usrvars(&uv1, &uv2);
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
fprintf(stderr, "in cp_getvar, trying to get value of variable %s.\n", name);
|
||||
#endif
|
||||
|
||||
for (v = variables; v && !eq(name, v->va_name); v = v->va_next)
|
||||
;
|
||||
if (v == NULL)
|
||||
|
|
@ -616,11 +625,10 @@ cp_getvar(char *name, enum cp_types type, void *retval)
|
|||
}
|
||||
default:
|
||||
fprintf(cp_err,
|
||||
"cp_getvar: Internal Error: bad var type %d.\n", type);
|
||||
"cp_getvar: INTERNAL ERROR: bad var type %d.\n", type);
|
||||
break;
|
||||
}
|
||||
free_struct_variable(uv1);
|
||||
// tfree(uv2);
|
||||
return (TRUE);
|
||||
|
||||
} else {
|
||||
|
|
@ -678,7 +686,7 @@ span_var_expr(char *t)
|
|||
int parenthesis = 0;
|
||||
int brackets = 0;
|
||||
|
||||
while (*t && (isalphanum(*t) || strchr(VALIDCHARS, *t)))
|
||||
while (*t && (isalphanum((int)*t) || strchr(VALIDCHARS, *t)))
|
||||
switch (*t++)
|
||||
{
|
||||
case '[':
|
||||
|
|
@ -707,55 +715,59 @@ span_var_expr(char *t)
|
|||
}
|
||||
|
||||
|
||||
/* Substitute variable name by its value and restore to wordlist */
|
||||
wordlist *
|
||||
cp_variablesubst(wordlist *wlist)
|
||||
{
|
||||
wordlist *wl;
|
||||
wordlist *wl, *nwl;
|
||||
char *s, *t, buf[BSIZE_SP], wbuf[BSIZE_SP], tbuf[BSIZE_SP];
|
||||
/* MW. tbuf holds current word after wl_splice() calls free() on it */
|
||||
int i;
|
||||
|
||||
for (wl = wlist; wl; wl = wl->wl_next) {
|
||||
|
||||
char *s_dollar;
|
||||
int i = 0;
|
||||
|
||||
while ((s_dollar = strchr(wl->wl_word + i, cp_dol)) != NULL) {
|
||||
|
||||
int prefix_len = (int) (s_dollar - wl->wl_word);
|
||||
|
||||
char *tail = span_var_expr(s_dollar + 1);
|
||||
char *var = copy_substring(s_dollar + 1, tail);
|
||||
|
||||
wordlist *nwl = vareval(var);
|
||||
tfree(var);
|
||||
|
||||
if (nwl) {
|
||||
char *x = nwl->wl_word;
|
||||
char *tail_ = copy(tail);
|
||||
nwl->wl_word = tprintf("%.*s%s", prefix_len, wl->wl_word, nwl->wl_word);
|
||||
free(x);
|
||||
if (wlist == wl)
|
||||
wlist = nwl;
|
||||
wl = wl_splice(wl, nwl);
|
||||
i = (int) strlen(wl->wl_word);
|
||||
x = wl->wl_word;
|
||||
wl->wl_word = tprintf("%s%s", wl->wl_word, tail_);
|
||||
free(x);
|
||||
free(tail_);
|
||||
} else if (prefix_len || *tail) {
|
||||
char *x = wl->wl_word;
|
||||
wl->wl_word = tprintf("%.*s%s", prefix_len, wl->wl_word, tail);
|
||||
i = prefix_len;
|
||||
free(x);
|
||||
} else {
|
||||
wordlist *next = wl->wl_next;
|
||||
if (wlist == wl)
|
||||
wlist = next;
|
||||
wl_delete_slice(wl, next);
|
||||
if (!next)
|
||||
return wlist;
|
||||
wl = next;
|
||||
i = 0;
|
||||
t = wl->wl_word;
|
||||
i = 0;
|
||||
while ((s = strchr(t, cp_dol)) != NULL) {
|
||||
while (t < s)
|
||||
wbuf[i++] = *t++;
|
||||
wbuf[i] = '\0';
|
||||
t++;
|
||||
s = buf;
|
||||
/* Get s and t past the end of the var name. */
|
||||
{
|
||||
char *end = span_var_expr(t);
|
||||
while (t < end)
|
||||
*s++ = *t++;
|
||||
}
|
||||
*s = '\0';
|
||||
nwl = vareval(buf);
|
||||
if (i) {
|
||||
(void) strcpy(buf, wbuf);
|
||||
if (nwl) {
|
||||
(void) strcat(buf, nwl->wl_word);
|
||||
tfree(nwl->wl_word);
|
||||
nwl->wl_word = copy(buf);
|
||||
} else {
|
||||
nwl = wl_cons(copy(buf), NULL);
|
||||
}
|
||||
}
|
||||
(void) strcpy(tbuf, t); /* MW. Save t*/
|
||||
if ((wl = wl_splice(wl, nwl)) == NULL) {/*CDHW this frees wl CDHW*/
|
||||
wl_free(nwl);
|
||||
return NULL;
|
||||
}
|
||||
/* This is bad... */
|
||||
for (wlist = wl; wlist->wl_prev; wlist = wlist->wl_prev)
|
||||
;
|
||||
(void) strcpy(buf, wl->wl_word);
|
||||
i = (int) strlen(buf);
|
||||
(void) strcat(buf, tbuf); /* MW. tbuf is used here only */
|
||||
tfree(wl->wl_word);
|
||||
wl->wl_word = copy(buf);
|
||||
t = &wl->wl_word[i];
|
||||
s = wl->wl_word;
|
||||
for (i = 0; s < t; s++)
|
||||
wbuf[i++] = *s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -783,7 +795,8 @@ vareval(char *string)
|
|||
switch (*string) {
|
||||
|
||||
case '$':
|
||||
wl = wl_cons(tprintf("%d", getpid()), NULL);
|
||||
(void) sprintf(buf, "%d", getpid());
|
||||
wl = wl_cons(copy(buf), NULL);
|
||||
tfree(oldstring);
|
||||
return (wl);
|
||||
|
||||
|
|
@ -822,7 +835,7 @@ vareval(char *string)
|
|||
if (!v)
|
||||
v = cp_enqvar(string);
|
||||
if (!v) {
|
||||
fprintf(cp_err, "Error: %s: no such variable.\n", string);
|
||||
fprintf(cp_err, "ERROR: %s: no such variable.\n", string);
|
||||
tfree(oldstring);
|
||||
return (NULL);
|
||||
}
|
||||
|
|
@ -831,7 +844,8 @@ vareval(char *string)
|
|||
i++;
|
||||
else
|
||||
i = (v->va_type != CP_BOOL);
|
||||
wl = wl_cons(tprintf("%d", i), NULL);
|
||||
(void) sprintf(buf, "%d", i);
|
||||
wl = wl_cons(copy(buf), NULL);
|
||||
tfree(oldstring);
|
||||
return (wl);
|
||||
|
||||
|
|
@ -848,14 +862,14 @@ vareval(char *string)
|
|||
for (v = variables; v; v = v->va_next)
|
||||
if (eq(v->va_name, string))
|
||||
break;
|
||||
if (!v && isdigit(*string)) {
|
||||
if (!v && isdigit((int)*string)) {
|
||||
for (v = variables; v; v = v->va_next)
|
||||
if (eq(v->va_name, "argv"))
|
||||
break;
|
||||
range = string;
|
||||
}
|
||||
if (!v) {
|
||||
range = NULL;
|
||||
// ? range = NULL;
|
||||
string = oldstring;
|
||||
v = cp_enqvar(string);
|
||||
}
|
||||
|
|
@ -865,7 +879,7 @@ vareval(char *string)
|
|||
return (wl);
|
||||
}
|
||||
if (!v) {
|
||||
fprintf(cp_err, "Error: %s: no such variable.\n", string);
|
||||
fprintf(cp_err, "ERROR: %s: no such variable.\n", string);
|
||||
tfree(oldstring);
|
||||
return (NULL);
|
||||
}
|
||||
|
|
@ -879,22 +893,22 @@ vareval(char *string)
|
|||
char *t = ++range;
|
||||
if (*t == '&')
|
||||
t++;
|
||||
while (isalphanum(*t))
|
||||
while (isalphanum((int)*t))
|
||||
t++;
|
||||
*t = '\0';
|
||||
r = vareval(range);
|
||||
if (!r || r->wl_next) {
|
||||
fprintf(cp_err, "Error: %s: illegal index.\n", string);
|
||||
fprintf(cp_err, "ERROR: %s: illegal index.\n", string);
|
||||
tfree(oldstring);
|
||||
wl_free(r);
|
||||
return NULL;
|
||||
}
|
||||
range = r->wl_word;
|
||||
}
|
||||
for (low = 0; isdigit(*range); range++)
|
||||
for (low = 0; isdigit((int)*range); range++)
|
||||
low = low * 10 + *range - '0';
|
||||
if ((*range == '-') && isdigit(range[1]))
|
||||
for (up = 0, range++; isdigit(*range); range++)
|
||||
if ((*range == '-') && isdigit((int)range[1]))
|
||||
for (up = 0, range++; isdigit((int)*range); range++)
|
||||
up = up * 10 + *range - '0';
|
||||
else if (*range == '-')
|
||||
up = wl_length(wl);
|
||||
|
|
|
|||
|
|
@ -22,11 +22,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|||
#include "ngspice/dstring.h"
|
||||
#include "plotting/plotting.h"
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - begin - add function prototype for EVTfindvec */
|
||||
struct dvec *EVTfindvec(char *node);
|
||||
/* gtri - end - add function prototype for EVTfindvec */
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
|
|
@ -180,14 +176,9 @@ findvec(char *word, struct plot *pl)
|
|||
|
||||
spice_dstring_free(&dbuf);
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - begin - Add processing for getting event-driven vector */
|
||||
|
||||
if (!d)
|
||||
d = EVTfindvec(word);
|
||||
|
||||
/* gtri - end - Add processing for getting event-driven vector */
|
||||
#endif
|
||||
if (d && d->v_link2) {
|
||||
d = vec_copy(d);
|
||||
vec_new(d);
|
||||
|
|
@ -209,18 +200,18 @@ namecmp(const void *a, const void *b)
|
|||
const char *t = (const char *) b;
|
||||
|
||||
for (;;) {
|
||||
while ((*s == *t) && !isdigit(*s) && *s)
|
||||
while ((*s == *t) && !isdigit((int)*s) && *s)
|
||||
s++, t++;
|
||||
if (!*s)
|
||||
return (0);
|
||||
if ((*s != *t) && (!isdigit(*s) || !isdigit(*t)))
|
||||
if ((*s != *t) && (!isdigit((int)*s) || !isdigit((int)*t)))
|
||||
return (*s - *t);
|
||||
|
||||
/* The beginning of a number... Grab the two numbers and then
|
||||
* compare them... */
|
||||
for (i = 0; isdigit(*s); s++)
|
||||
for (i = 0; isdigit((int)*s); s++)
|
||||
i = i * 10 + *s - '0';
|
||||
for (j = 0; isdigit(*t); t++)
|
||||
for (j = 0; isdigit((int)*t); t++)
|
||||
j = j * 10 + *t - '0';
|
||||
|
||||
if (i != j)
|
||||
|
|
@ -383,11 +374,11 @@ vec_fromplot(char *word, struct plot *plot)
|
|||
}
|
||||
|
||||
/* scanf("%c(%s)" doesn't do what it should do. ) */
|
||||
if (!d && (sscanf(word, "%c(%s", &cc, buf) == 2) &&
|
||||
((s = strrchr(buf, ')')) != NULL) &&
|
||||
if (!d && (sscanf(word, "%c(%s", /* ) */ &cc, buf) == 2) &&
|
||||
/* ( */ ((s = strrchr(buf, ')')) != NULL) &&
|
||||
(s[1] == '\0')) {
|
||||
*s = '\0';
|
||||
if (prefix("i(", word) || prefix("I(", word)) {
|
||||
if (prefix("i(", /* ) */ word) || prefix("I(", /* ) */ word)) {
|
||||
/* Spice dependency... */
|
||||
(void) sprintf(buf2, "%s#branch", buf);
|
||||
(void) strcpy(buf, buf2);
|
||||
|
|
@ -422,9 +413,23 @@ vec_get(const char *vec_name)
|
|||
char buf[BSIZE_SP], *s, *wd, *word, *whole, *name = NULL, *param;
|
||||
int i = 0;
|
||||
struct variable *vv;
|
||||
int indexvar; /* mhx */
|
||||
|
||||
wd = word = copy(vec_name); /* Gets mangled below... */
|
||||
|
||||
if (*word != SPECCHAR) { /* mhx: eventually replace atoi() by full evaluate */
|
||||
char *ps = strchr(wd, '['), *pe = strchr(wd, ']');
|
||||
if (ps && pe && pe > ps) {
|
||||
whole = copy(word);
|
||||
*ps = '\0';
|
||||
*pe = '\0';
|
||||
indexvar = atoi(++ps);
|
||||
} else {
|
||||
whole = NULL;
|
||||
indexvar = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (strchr(word, '.')) {
|
||||
/* Snag the plot... */
|
||||
for (i = 0, s = word; *s != '.'; i++, s++)
|
||||
|
|
@ -470,18 +475,34 @@ vec_get(const char *vec_name)
|
|||
d = newv;
|
||||
if (!d) {
|
||||
fprintf(cp_err,
|
||||
"Error: plot wildcard (name %s) matches nothing\n",
|
||||
"ERROR: plot wildcard (name %s) matches nothing\n",
|
||||
word);
|
||||
tfree(wd); /* MW. I don't want core leaks here */
|
||||
tfree(wd);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* In case of data[ix] we must return a SINGLE value
|
||||
(vector of length 1) instead of the vector.
|
||||
Duplicates a lot of code that still follows :-( */
|
||||
if (d && indexvar != -1) {
|
||||
struct dvec *ad;
|
||||
ad = alloc(struct dvec);
|
||||
ZERO(ad, struct dvec);
|
||||
ad->v_name = copy(whole); /* so the name could be data[2] or data[expression] :-) */
|
||||
ad->v_type = d->v_type;
|
||||
ad->v_flags = d->v_flags; /* VF_REAL; or complex? */
|
||||
ad->v_length = 1;
|
||||
ad->v_realdata = TMALLOC(double, 1);
|
||||
*ad->v_realdata = *d->v_realdata;
|
||||
tfree(whole);
|
||||
}
|
||||
|
||||
if (!d && (*word == SPECCHAR)) {
|
||||
/* This is a special quantity... */
|
||||
if (ft_nutmeg) {
|
||||
fprintf(cp_err,
|
||||
"Error: circuit parameters only available with spice\n");
|
||||
"ERROR: circuit parameters only available with spice\n");
|
||||
tfree(wd); /* MW. Memory leak fixed again */
|
||||
return (NULL); /* va: use NULL */
|
||||
}
|
||||
|
|
@ -516,16 +537,19 @@ vec_get(const char *vec_name)
|
|||
return (NULL);
|
||||
}
|
||||
} else {
|
||||
fprintf(cp_err, "Error: No circuit loaded.\n");
|
||||
fprintf(cp_err, "ERROR: No circuit loaded.\n");
|
||||
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);
|
||||
d = alloc(struct dvec);
|
||||
ZERO(d, struct dvec);
|
||||
d->v_name = copy(whole); /* MW. The same as word before */
|
||||
d->v_type = SV_NOTYPE;
|
||||
d->v_flags |= VF_REAL; /* No complex values yet... */
|
||||
d->v_realdata = TMALLOC(double, 1);
|
||||
d->v_length = 1;
|
||||
|
||||
/* In case the represented variable is a REAL vector this takes
|
||||
* the actual value of the first element of the linked list which
|
||||
|
|
@ -538,8 +562,8 @@ vec_get(const char *vec_name)
|
|||
* 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)
|
||||
* OPU( "pos_node", POT_QUEST_POS_NODE, IF_REAL,"Positive node of potentiometer"),
|
||||
* int POTnegNode; // number of negative node of potentiometer (Node_3)
|
||||
* case POT_QUEST_POS_NODE:
|
||||
* value->rValue = (double)fast->POTposNode;
|
||||
* return (OK);
|
||||
|
|
@ -562,7 +586,7 @@ vec_get(const char *vec_name)
|
|||
* CP_REAL,
|
||||
* CP_STRING,
|
||||
* CP_LIST
|
||||
° };
|
||||
* };
|
||||
*/
|
||||
|
||||
/* The variable is a vector */
|
||||
|
|
@ -572,16 +596,20 @@ vec_get(const char *vec_name)
|
|||
*/
|
||||
struct variable *nv;
|
||||
|
||||
i = 0;
|
||||
for (nv = vv->va_vlist; nv; nv = nv->va_next)
|
||||
i++;
|
||||
|
||||
dvec_realloc(d, i, NULL);
|
||||
|
||||
i = 0;
|
||||
for (nv = vv->va_vlist; nv; nv = nv->va_next)
|
||||
d->v_realdata[i++] = nv->va_real;
|
||||
double *list;
|
||||
list = TMALLOC(double, 1);
|
||||
nv = alloc(struct variable);
|
||||
|
||||
nv = vv->va_vlist;
|
||||
for (i = 1; ; i++) {
|
||||
list = TREALLOC(double, list, i);
|
||||
list[i-1] = nv->va_real;
|
||||
nv = nv->va_next;
|
||||
if (!nv)
|
||||
break;
|
||||
}
|
||||
d->v_realdata = list;
|
||||
d->v_length = i;
|
||||
/* To be able to identify the vector to represent
|
||||
* belongs to a special "conunto" and should be printed in a
|
||||
* special way.
|
||||
|
|
@ -681,22 +709,28 @@ vec_copy(struct dvec *v)
|
|||
if (!v)
|
||||
return (NULL);
|
||||
|
||||
nv = dvec_alloc(copy(v->v_name),
|
||||
v->v_type,
|
||||
v->v_flags & ~VF_PERMANENT,
|
||||
v->v_length, NULL);
|
||||
nv = alloc(struct dvec);
|
||||
nv->v_name = copy(v->v_name);
|
||||
nv->v_type = v->v_type;
|
||||
nv->v_flags = v->v_flags & ~VF_PERMANENT;
|
||||
|
||||
if (isreal(v))
|
||||
if (isreal(v)) {
|
||||
nv->v_realdata = TMALLOC(double, v->v_length);
|
||||
bcopy(v->v_realdata, nv->v_realdata,
|
||||
sizeof(double) * (size_t) v->v_length);
|
||||
else
|
||||
nv->v_compdata = NULL;
|
||||
} else {
|
||||
nv->v_realdata = NULL;
|
||||
nv->v_compdata = TMALLOC(ngcomplex_t, v->v_length);
|
||||
bcopy(v->v_compdata, nv->v_compdata,
|
||||
sizeof(ngcomplex_t) * (size_t) v->v_length);
|
||||
}
|
||||
|
||||
nv->v_minsignal = v->v_minsignal;
|
||||
nv->v_maxsignal = v->v_maxsignal;
|
||||
nv->v_gridtype = v->v_gridtype;
|
||||
nv->v_plottype = v->v_plottype;
|
||||
nv->v_length = v->v_length;
|
||||
|
||||
/* Modified to copy the rlength of origin to destination vecor
|
||||
* instead of always putting it to 0.
|
||||
|
|
@ -764,13 +798,10 @@ plot_alloc(char *name)
|
|||
void
|
||||
vec_new(struct dvec *d)
|
||||
{
|
||||
#ifdef FTEDEBUG
|
||||
if (ft_vecdb)
|
||||
fprintf(cp_err, "new vector %s\n", d->v_name);
|
||||
#endif
|
||||
/* Note that this can't happen. */
|
||||
if (plot_cur == NULL) {
|
||||
fprintf(cp_err, "vec_new: Internal Error: no cur plot\n");
|
||||
fprintf(cp_err, "vec_new: INTERNAL ERROR: no cur plot\n");
|
||||
controlled_exit(1);
|
||||
}
|
||||
plot_cur->pl_lookup_valid = FALSE;
|
||||
if ((d->v_flags & VF_PERMANENT) && (plot_cur->pl_scale == NULL))
|
||||
|
|
@ -849,7 +880,7 @@ vec_free_x(struct dvec *v)
|
|||
lv->v_next = v->v_next;
|
||||
else
|
||||
fprintf(cp_err,
|
||||
"vec_free: Internal Error: %s not in plot\n",
|
||||
"vec_free: INTERNAL ERROR: %s not in plot\n",
|
||||
v->v_name);
|
||||
}
|
||||
if (pl->pl_scale == v) {
|
||||
|
|
@ -860,7 +891,13 @@ vec_free_x(struct dvec *v)
|
|||
}
|
||||
}
|
||||
|
||||
dvec_free(v);
|
||||
if (v->v_name)
|
||||
tfree(v->v_name);
|
||||
if (v->v_realdata)
|
||||
tfree(v->v_realdata);
|
||||
if (v->v_compdata)
|
||||
tfree(v->v_compdata);
|
||||
tfree(v);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -868,7 +905,7 @@ vec_free_x(struct dvec *v)
|
|||
* return TRUE if every vector element is zero
|
||||
*/
|
||||
|
||||
bool
|
||||
BOOL
|
||||
vec_iszero(struct dvec *v)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -937,12 +974,12 @@ vec_basename(struct dvec *v)
|
|||
}
|
||||
|
||||
strtolower(buf);
|
||||
for (t = buf; isspace(*t); t++)
|
||||
for (t = buf; isspace((int)*t); t++)
|
||||
;
|
||||
s = t;
|
||||
for (t = s; *t; t++)
|
||||
;
|
||||
while ((t > s) && isspace(t[-1]))
|
||||
while ((t > s) && isspace((int)t[-1]))
|
||||
*--t = '\0';
|
||||
return (copy(s));
|
||||
}
|
||||
|
|
@ -972,7 +1009,7 @@ plot_setcur(char *name)
|
|||
if (plot_prefix(name, pl->pl_typename))
|
||||
break;
|
||||
if (!pl) {
|
||||
fprintf(cp_err, "Error: no such plot named %s\n", name);
|
||||
fprintf(cp_err, "ERROR: no such plot named %s\n", name);
|
||||
return;
|
||||
}
|
||||
/* va: we skip cp_kwswitch, because it confuses the keyword-tree management for
|
||||
|
|
@ -1053,7 +1090,8 @@ vec_transpose(struct dvec *v)
|
|||
}
|
||||
koffset += blocksize; /* koffset = k*blocksize = k*dim0*dim1 */
|
||||
}
|
||||
dvec_realloc(v, v->v_length, newreal);
|
||||
tfree(oldreal);
|
||||
v->v_realdata = newreal;
|
||||
} else {
|
||||
newcomp = TMALLOC(ngcomplex_t, v->v_length);
|
||||
oldcomp = v->v_compdata;
|
||||
|
|
@ -1062,14 +1100,17 @@ vec_transpose(struct dvec *v)
|
|||
joffset = 0;
|
||||
for (j = 0; j < dim0; j++) {
|
||||
for (i = 0; i < dim1; i++) {
|
||||
newcomp[ koffset + joffset + i ] =
|
||||
oldcomp[ koffset + i*dim0 + j ];
|
||||
realpart(newcomp[ koffset + joffset + i ]) =
|
||||
realpart(oldcomp[ koffset + i*dim0 + j ]);
|
||||
imagpart(newcomp[ koffset + joffset + i ]) =
|
||||
imagpart(oldcomp[ koffset + i*dim0 + j ]);
|
||||
}
|
||||
joffset += dim1; /* joffset = j*dim0 */
|
||||
}
|
||||
koffset += blocksize; /* koffset = k*blocksize = k*dim0*dim1 */
|
||||
}
|
||||
dvec_realloc(v, v->v_length, newcomp);
|
||||
tfree(oldcomp);
|
||||
v->v_compdata = newcomp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1082,9 +1123,9 @@ vec_transpose(struct dvec *v)
|
|||
struct dvec *
|
||||
vec_mkfamily(struct dvec *v)
|
||||
{
|
||||
int size, numvecs, i, count[MAXDIMS];
|
||||
struct dvec *vecs, *d, **t;
|
||||
char buf2[BSIZE_SP];
|
||||
int size, numvecs, i, j, count[MAXDIMS];
|
||||
struct dvec *vecs, *d;
|
||||
char buf[BSIZE_SP], buf2[BSIZE_SP];
|
||||
|
||||
if (v->v_numdims < 2)
|
||||
return (v);
|
||||
|
|
@ -1092,16 +1133,25 @@ vec_mkfamily(struct dvec *v)
|
|||
size = v->v_dims[v->v_numdims - 1];
|
||||
for (i = 0, numvecs = 1; i < v->v_numdims - 1; i++)
|
||||
numvecs *= v->v_dims[i];
|
||||
for (i = 0, vecs = d = NULL; i < numvecs; i++) {
|
||||
if (vecs) {
|
||||
d = d->v_link2 = alloc(struct dvec);
|
||||
ZERO(d, struct dvec);
|
||||
} else {
|
||||
d = vecs = alloc(struct dvec);
|
||||
ZERO(d, struct dvec);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAXDIMS; i++)
|
||||
count[i] = 0;
|
||||
for (t = &vecs, i = 0; i < numvecs; i++) {
|
||||
for (d = vecs, j = 0; d; j++, d = d->v_link2) {
|
||||
|
||||
indexstring(count, v->v_numdims - 1, buf2);
|
||||
|
||||
d = dvec_alloc(tprintf("%s%s", v->v_name, buf2),
|
||||
v->v_type,
|
||||
v->v_flags,
|
||||
size, NULL);
|
||||
(void) sprintf(buf, "%s%s", v->v_name, buf2);
|
||||
d->v_name = copy(buf);
|
||||
d->v_type = v->v_type;
|
||||
d->v_flags = v->v_flags;
|
||||
|
||||
d->v_minsignal = v->v_minsignal;
|
||||
d->v_maxsignal = v->v_maxsignal;
|
||||
|
|
@ -1112,18 +1162,17 @@ vec_mkfamily(struct dvec *v)
|
|||
* of these things...
|
||||
*/
|
||||
d->v_numdims = 1;
|
||||
d->v_dims[0] = size;
|
||||
d->v_length = size;
|
||||
|
||||
if (isreal(v)) {
|
||||
bcopy(v->v_realdata + size*i, d->v_realdata, (size_t) size * sizeof(double));
|
||||
d->v_realdata = TMALLOC(double, size);
|
||||
bcopy(v->v_realdata + size*j, d->v_realdata, (size_t) size * sizeof(double));
|
||||
} else {
|
||||
bcopy(v->v_compdata + size*i, d->v_compdata, (size_t) size * sizeof(ngcomplex_t));
|
||||
d->v_compdata = TMALLOC(ngcomplex_t, size);
|
||||
bcopy(v->v_compdata + size*j, d->v_compdata, (size_t) size * sizeof(ngcomplex_t));
|
||||
}
|
||||
/* Add one to the counter. */
|
||||
(void) incindex(count, v->v_numdims - 1, v->v_dims, v->v_numdims);
|
||||
|
||||
*t = d;
|
||||
t = &(d->v_link2);
|
||||
}
|
||||
|
||||
for (d = vecs; d; d = d->v_link2)
|
||||
|
|
@ -1148,7 +1197,7 @@ plot_prefix(char *pre, char *str)
|
|||
str++;
|
||||
}
|
||||
|
||||
if (*pre || (*str && isdigit(pre[-1])))
|
||||
if (*pre || (*str && isdigit((int)pre[-1])))
|
||||
return (FALSE);
|
||||
else
|
||||
return (TRUE);
|
||||
|
|
|
|||
Loading…
Reference in New Issue