Fix variables so that they behave as described (or intended) in the ngspice-26plus manual.

This commit is contained in:
mhx 2016-01-01 20:32:22 +01:00 committed by rlar
parent 9d32a0a5a9
commit c4869fccd5
2 changed files with 63 additions and 8 deletions

View File

@ -263,12 +263,21 @@ cp_vset(char *varname, enum cp_types type, void *value)
}
/*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;
@ -330,6 +339,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 +350,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 +359,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 +372,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) {
@ -385,19 +403,26 @@ cp_setparse(wordlist *wl)
continue;
}
/* there shouldn't be quotes around val at this point? */
if (*val == '"')
isstring |= TRUE; /* mhx: is this sufficient? */
copyval = ss = cp_unquote(val);
td = ft_numparse(&ss, FALSE);
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 */
@ -855,7 +880,7 @@ vareval(char *string)
range = string;
}
if (!v) {
range = NULL;
// ? range = NULL;
string = oldstring;
v = cp_enqvar(string);
}

View File

@ -422,9 +422,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++)
@ -477,6 +491,22 @@ vec_get(const char *vec_name)
}
}
/* 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) {