Made ft_numparse() thread-safe (no internal static variables) and prepared to support ngspice variable type CP_NUM.
This commit is contained in:
parent
9bbde919e3
commit
b4bbcb1497
|
|
@ -46,7 +46,6 @@ com_stop(wordlist *wl)
|
||||||
struct dbcomm *d = NULL;
|
struct dbcomm *d = NULL;
|
||||||
char *s, buf[64];
|
char *s, buf[64];
|
||||||
int i;
|
int i;
|
||||||
double *val;
|
|
||||||
|
|
||||||
while (wl) {
|
while (wl) {
|
||||||
if (thisone == NULL) {
|
if (thisone == NULL) {
|
||||||
|
|
@ -82,8 +81,7 @@ com_stop(wordlist *wl)
|
||||||
if (strchr(wl->wl_next->wl_word, '=') &&
|
if (strchr(wl->wl_next->wl_word, '=') &&
|
||||||
(!(wl->wl_next->wl_next) ||
|
(!(wl->wl_next->wl_next) ||
|
||||||
strstr(wl->wl_next->wl_next->wl_word, "when") ||
|
strstr(wl->wl_next->wl_next->wl_word, "when") ||
|
||||||
strstr(wl->wl_next->wl_next->wl_word, "after")))
|
strstr(wl->wl_next->wl_next->wl_word, "after"))) {
|
||||||
{
|
|
||||||
/* we have vec=val in a single word */
|
/* we have vec=val in a single word */
|
||||||
wordlist *wln;
|
wordlist *wln;
|
||||||
char **charr = TMALLOC(char*, 4);
|
char **charr = TMALLOC(char*, 4);
|
||||||
|
|
@ -98,17 +96,23 @@ com_stop(wordlist *wl)
|
||||||
wln = wl_build((const char * const *) charr);
|
wln = wl_build((const char * const *) charr);
|
||||||
wl_splice(wl->wl_next, wln);
|
wl_splice(wl->wl_next, wln);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* continue with parsing the enhanced wordlist */
|
/* continue with parsing the enhanced wordlist */
|
||||||
if (wl->wl_next->wl_next && wl->wl_next->wl_next->wl_next) {
|
if (wl->wl_next->wl_next && wl->wl_next->wl_next->wl_next) {
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
d->db_number = debugnumber;
|
d->db_number = debugnumber;
|
||||||
d->db_type = DB_STOPWHEN;
|
d->db_type = DB_STOPWHEN;
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
val = ft_numparse(&s, FALSE);
|
|
||||||
if (val)
|
{
|
||||||
d->db_value1 = *val;
|
double val;
|
||||||
else
|
if (ft_numparse(&s, FALSE, &val) >= 0) {
|
||||||
|
d->db_value1 = val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
d->db_nodename1 = copy(wl->wl_word);
|
d->db_nodename1 = copy(wl->wl_word);
|
||||||
|
}
|
||||||
|
}
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
|
|
||||||
/* Now get the condition */
|
/* Now get the condition */
|
||||||
|
|
@ -130,17 +134,23 @@ com_stop(wordlist *wl)
|
||||||
|
|
||||||
/* Now see about the second one. */
|
/* Now see about the second one. */
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
val = ft_numparse(&s, FALSE);
|
|
||||||
if (val)
|
{
|
||||||
d->db_value2 = *val;
|
double val;
|
||||||
else
|
if (ft_numparse(&s, FALSE, &val) >= 0) {
|
||||||
|
d->db_value2 = val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
d->db_nodename2 = copy(wl->wl_word);
|
d->db_nodename2 = copy(wl->wl_word);
|
||||||
|
}
|
||||||
|
}
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
} /* end of case of word "when" */
|
||||||
}
|
} /* end of loop over wordlist */
|
||||||
|
|
||||||
if (thisone) {
|
if (thisone) {
|
||||||
if (dbs) {
|
if (dbs) {
|
||||||
|
|
@ -159,11 +169,11 @@ com_stop(wordlist *wl)
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
fprintf(cp_err, "Syntax error parsing breakpoint specification.\n");
|
fprintf(cp_err, "Syntax error parsing breakpoint specification.\n");
|
||||||
}
|
} /* end of funtion com_stop */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Trace a node (have wrd_point print it). Usage is "trace node ..."*/
|
/* Trace a node (have wrd_point print it). Usage is "trace node ..."*/
|
||||||
|
|
||||||
void
|
void
|
||||||
com_trce(wordlist *wl)
|
com_trce(wordlist *wl)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
/* The 'compose' command. This is a more powerful and convenient form
|
/* The 'compose' command. This is a more powerful and convenient form
|
||||||
* of the 'let' command. */
|
* of the 'let' command. */
|
||||||
|
#include <math.h> /* log10 */
|
||||||
|
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/complex.h"
|
#include "ngspice/complex.h"
|
||||||
#include "ngspice/dvec.h"
|
#include "ngspice/dvec.h"
|
||||||
|
|
@ -14,7 +16,6 @@
|
||||||
#include "com_compose.h"
|
#include "com_compose.h"
|
||||||
#include "completion.h"
|
#include "completion.h"
|
||||||
|
|
||||||
#include <math.h> /* log10 */
|
|
||||||
|
|
||||||
/* Copy the data from a vector into a buffer with larger dimensions. */
|
/* Copy the data from a vector into a buffer with larger dimensions. */
|
||||||
static void
|
static void
|
||||||
|
|
@ -103,8 +104,7 @@ com_compose(wordlist *wl)
|
||||||
int log = 0, dec = 0, oct = 0, gauss = 0, unif = 0;
|
int log = 0, dec = 0, oct = 0, gauss = 0, unif = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
char *s, *var, *val;
|
double tt;
|
||||||
double *td, tt;
|
|
||||||
double *data = NULL;
|
double *data = NULL;
|
||||||
ngcomplex_t *cdata = NULL;
|
ngcomplex_t *cdata = NULL;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
|
|
@ -227,9 +227,11 @@ com_compose(wordlist *wl)
|
||||||
}
|
}
|
||||||
|
|
||||||
length *= blocksize;
|
length *= blocksize;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
/* Parse the line... */
|
/* Parse the line... */
|
||||||
while (wl) {
|
while (wl) {
|
||||||
|
char *s, *var, *val;
|
||||||
if ((s = strchr(wl->wl_word, '=')) != NULL && s[1]) {
|
if ((s = strchr(wl->wl_word, '=')) != NULL && s[1]) {
|
||||||
/* This is var=val. */
|
/* This is var=val. */
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
|
|
@ -278,109 +280,124 @@ com_compose(wordlist *wl)
|
||||||
}
|
}
|
||||||
if (cieq(var, "start")) {
|
if (cieq(var, "start")) {
|
||||||
startgiven = TRUE;
|
startgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &start) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
start = *td;
|
}
|
||||||
} else if (cieq(var, "stop")) {
|
else if (cieq(var, "stop")) {
|
||||||
stopgiven = TRUE;
|
stopgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &stop) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
stop = *td;
|
}
|
||||||
} else if (cieq(var, "step")) {
|
else if (cieq(var, "step")) {
|
||||||
stepgiven = TRUE;
|
stepgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &step) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
step = *td;
|
}
|
||||||
} else if (cieq(var, "center")) {
|
else if (cieq(var, "center")) {
|
||||||
centergiven = TRUE;
|
centergiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, ¢er) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
center = *td;
|
}
|
||||||
} else if (cieq(var, "span")) {
|
else if (cieq(var, "span")) {
|
||||||
spangiven = TRUE;
|
spangiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &span) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
span = *td;
|
}
|
||||||
} else if (cieq(var, "mean")) {
|
else if (cieq(var, "mean")) {
|
||||||
meangiven = TRUE;
|
meangiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &mean) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
mean = *td;
|
}
|
||||||
} else if (cieq(var, "sd")) {
|
else if (cieq(var, "sd")) {
|
||||||
sdgiven = TRUE;
|
sdgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &sd) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sd = *td;
|
}
|
||||||
} else if (cieq(var, "lin")) {
|
else if (cieq(var, "lin")) {
|
||||||
lingiven = TRUE;
|
lingiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &lin) < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
lin = *td;
|
}
|
||||||
} else if (cieq(var, "log")) {
|
else if (cieq(var, "log")) {
|
||||||
|
double dbl_val;
|
||||||
loggiven = TRUE;
|
loggiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &dbl_val) <= 0) {
|
||||||
|
/* Cannot convert value to int */
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
log = (int)(*td);
|
log = (int) dbl_val;
|
||||||
} else if (cieq(var, "dec")) {
|
}
|
||||||
|
else if (cieq(var, "dec")) {
|
||||||
|
double dbl_val;
|
||||||
decgiven = TRUE;
|
decgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &dbl_val) <= 0) {
|
||||||
|
/* Cannot convert value to int */
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
dec = (int)(*td);
|
dec = (int) dbl_val;
|
||||||
} else if (cieq(var, "oct")) {
|
}
|
||||||
|
else if (cieq(var, "oct")) {
|
||||||
|
double dbl_val;
|
||||||
octgiven = TRUE;
|
octgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &dbl_val) <= 0) {
|
||||||
|
/* Cannot convert value to integer */
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
oct = (int)(*td);
|
oct = (int) dbl_val;
|
||||||
} else if (cieq(var, "gauss")) {
|
}
|
||||||
|
else if (cieq(var, "gauss")) {
|
||||||
|
double dbl_val;
|
||||||
gaussgiven = TRUE;
|
gaussgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &dbl_val) <= 0) {
|
||||||
|
/* Cannot convert value to int */
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
gauss = (int)(*td);
|
gauss = (int) dbl_val;
|
||||||
} else if (cieq(var, "unif")) {
|
}
|
||||||
|
else if (cieq(var, "unif")) {
|
||||||
|
double dbl_val;
|
||||||
unifgiven = TRUE;
|
unifgiven = TRUE;
|
||||||
if ((td = ft_numparse(&val, FALSE)) == NULL) {
|
if (ft_numparse(&val, FALSE, &dbl_val)<= 0) {
|
||||||
|
/* cannot convert to int */
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> bad parm %s = %s\n", var, val);
|
"Error: compose -> bad parm %s = %s\n", var, val);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
unif = (int)(*td);
|
unif = (int) dbl_val;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
fprintf(cp_err, "Error: compose -> bad parm %s\n", var);
|
fprintf(cp_err, "Error: compose -> bad parm %s\n", var);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -405,7 +422,8 @@ com_compose(wordlist *wl)
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> can have at most one of (lin, log, dec, oct, unif, gauss)\n");
|
"Error: compose -> can have at most one of (lin, log, dec, oct, unif, gauss)\n");
|
||||||
goto done;
|
goto done;
|
||||||
} else if (lingiven + loggiven + decgiven + octgiven + unifgiven + gaussgiven == 0) {
|
}
|
||||||
|
else if (lingiven + loggiven + decgiven + octgiven + unifgiven + gaussgiven == 0) {
|
||||||
/* Hmm, if we have a start, stop, and step we're ok. */
|
/* Hmm, if we have a start, stop, and step we're ok. */
|
||||||
if (startgiven && stopgiven && stepgiven) {
|
if (startgiven && stopgiven && stepgiven) {
|
||||||
lingiven = TRUE;
|
lingiven = TRUE;
|
||||||
|
|
@ -415,7 +433,8 @@ com_compose(wordlist *wl)
|
||||||
}
|
}
|
||||||
lin = (stop - start) / step + 1.;
|
lin = (stop - start) / step + 1.;
|
||||||
stepgiven = FALSE; /* Problems below... */
|
stepgiven = FALSE; /* Problems below... */
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: compose -> either one of (lin, log, dec, oct, unif, gauss) must be given, or all\n");
|
"Error: compose -> either one of (lin, log, dec, oct, unif, gauss) must be given, or all\n");
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
|
|
@ -463,10 +482,12 @@ com_compose(wordlist *wl)
|
||||||
step = (stop - start) / (lin - 1.0);
|
step = (stop - start) / (lin - 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, tt = start; i < length; i++, tt += step)
|
for (i = 0, tt = start; i < length; i++, tt += step) {
|
||||||
data[i] = tt;
|
data[i] = tt;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (loggiven || decgiven || octgiven) {
|
}
|
||||||
|
else if (loggiven || decgiven || octgiven) {
|
||||||
/* Create a log sweep... */
|
/* Create a log sweep... */
|
||||||
if (centergiven && spangiven) {
|
if (centergiven && spangiven) {
|
||||||
if (center <= span/2.0) {
|
if (center <= span/2.0) {
|
||||||
|
|
@ -505,7 +526,8 @@ com_compose(wordlist *wl)
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
data[i] = start * pow(stop/start, (double)i/(log-1.0));
|
data[i] = start * pow(stop/start, (double)i/(log-1.0));
|
||||||
|
|
||||||
} else if (unifgiven) {
|
}
|
||||||
|
else if (unifgiven) {
|
||||||
/* Create a set of uniform distributed values... */
|
/* Create a set of uniform distributed values... */
|
||||||
if (startgiven || stopgiven) {
|
if (startgiven || stopgiven) {
|
||||||
if (!startgiven || !stopgiven) {
|
if (!startgiven || !stopgiven) {
|
||||||
|
|
@ -541,7 +563,8 @@ com_compose(wordlist *wl)
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
data[i] = mean + span * 0.5 * drand();
|
data[i] = mean + span * 0.5 * drand();
|
||||||
|
|
||||||
} else if (gaussgiven) {
|
}
|
||||||
|
else if (gaussgiven) {
|
||||||
/* Create a gaussian distribution... */
|
/* Create a gaussian distribution... */
|
||||||
if (gauss <= 0) {
|
if (gauss <= 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
|
|
@ -558,10 +581,11 @@ com_compose(wordlist *wl)
|
||||||
}
|
}
|
||||||
length = gauss;
|
length = gauss;
|
||||||
data = TMALLOC(double, length);
|
data = TMALLOC(double, length);
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++) {
|
||||||
data[i] = mean + sd * gauss1();
|
data[i] = mean + sd * gauss1();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a vector with the data that was processed */
|
/* Create a vector with the data that was processed */
|
||||||
if (realflag) {
|
if (realflag) {
|
||||||
|
|
@ -589,5 +613,5 @@ com_compose(wordlist *wl)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free_pnode(names);
|
free_pnode(names);
|
||||||
tfree(resname);
|
txfree(resname);
|
||||||
}
|
} /* end of function com_compose */
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ com_psd(wordlist *wl)
|
||||||
{
|
{
|
||||||
ngcomplex_t **fdvec = NULL;
|
ngcomplex_t **fdvec = NULL;
|
||||||
double **tdvec = NULL;
|
double **tdvec = NULL;
|
||||||
double *freq, *win = NULL, *time, *ave;
|
double *freq, *win = NULL, *time;
|
||||||
double span, noipower;
|
double span, noipower;
|
||||||
int ngood, fpts, i, j, jj, length, smooth, hsmooth;
|
int ngood, fpts, i, j, jj, length, smooth, hsmooth;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
@ -278,12 +278,15 @@ com_psd(wordlist *wl)
|
||||||
|
|
||||||
// get filter length from parameter input
|
// get filter length from parameter input
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
ave = ft_numparse(&s, FALSE);
|
{
|
||||||
if (!ave || (*ave < 1.0)) {
|
double val;
|
||||||
fprintf(cp_out, "Number of averaged data points: %d\n", 1);
|
if (ft_numparse(&s, FALSE, &val) <= 0 || val < 1.0) {
|
||||||
|
fprintf(cp_out, "Number of averaged data points: 1\n");
|
||||||
smooth = 1;
|
smooth = 1;
|
||||||
} else {
|
}
|
||||||
smooth = (int)(*ave);
|
else {
|
||||||
|
smooth = (int) val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ typedef enum {
|
||||||
MEASUREMENT_FAILURE = 1
|
MEASUREMENT_FAILURE = 1
|
||||||
} MEASURE_VAL_T;
|
} MEASURE_VAL_T;
|
||||||
|
|
||||||
#define MEASURE_DEFAULT -1
|
#define MEASURE_DEFAULT (-1)
|
||||||
#define MEASURE_LAST_TRANSITION -2
|
#define MEASURE_LAST_TRANSITION (-2)
|
||||||
|
|
||||||
typedef struct measure
|
typedef struct measure
|
||||||
{
|
{
|
||||||
|
|
@ -1152,7 +1152,7 @@ measure_parse_stdParams(
|
||||||
{
|
{
|
||||||
int pCnt;
|
int pCnt;
|
||||||
char *p, *pName, *pValue;
|
char *p, *pName, *pValue;
|
||||||
double *engVal, engVal1;
|
double engVal1;
|
||||||
|
|
||||||
pCnt = 0;
|
pCnt = 0;
|
||||||
while (wl != wlBreak) {
|
while (wl != wlBreak) {
|
||||||
|
|
@ -1176,12 +1176,12 @@ measure_parse_stdParams(
|
||||||
|
|
||||||
if (strcasecmp(pValue, "LAST") == 0) {
|
if (strcasecmp(pValue, "LAST") == 0) {
|
||||||
engVal1 = MEASURE_LAST_TRANSITION;
|
engVal1 = MEASURE_LAST_TRANSITION;
|
||||||
} else {
|
}
|
||||||
if ((engVal = ft_numparse(&pValue, FALSE)) == NULL) {
|
else {
|
||||||
|
if (ft_numparse(&pValue, FALSE, &engVal1) < 0) {
|
||||||
sprintf(errbuf, "bad syntax of ??\n");
|
sprintf(errbuf, "bad syntax of ??\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
engVal1 = *engVal; // What is this ??
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(pName, "RISE") == 0) {
|
if (strcasecmp(pName, "RISE") == 0) {
|
||||||
|
|
@ -1257,8 +1257,6 @@ measure_parse_find(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int pCnt;
|
int pCnt;
|
||||||
char *p, *pName, *pVal;
|
|
||||||
double *engVal, engVal1;
|
|
||||||
|
|
||||||
meas->m_vec = NULL;
|
meas->m_vec = NULL;
|
||||||
meas->m_vec2 = NULL;
|
meas->m_vec2 = NULL;
|
||||||
|
|
@ -1280,7 +1278,7 @@ measure_parse_find(
|
||||||
|
|
||||||
pCnt = 0;
|
pCnt = 0;
|
||||||
while (wl != wlBreak) {
|
while (wl != wlBreak) {
|
||||||
p = wl->wl_word;
|
char *p = wl->wl_word;
|
||||||
|
|
||||||
if (pCnt == 0) {
|
if (pCnt == 0) {
|
||||||
meas->m_vec = cp_unquote(wl->wl_word);
|
meas->m_vec = cp_unquote(wl->wl_word);
|
||||||
|
|
@ -1288,8 +1286,8 @@ measure_parse_find(
|
||||||
if (cieq("ac", meas->m_analysis) || cieq("sp", meas->m_analysis))
|
if (cieq("ac", meas->m_analysis) || cieq("sp", meas->m_analysis))
|
||||||
correct_vec(meas);
|
correct_vec(meas);
|
||||||
} else if (pCnt == 1) {
|
} else if (pCnt == 1) {
|
||||||
pName = strtok(p, "=");
|
char * const pName = strtok(p, "=");
|
||||||
pVal = strtok(NULL, "=");
|
char * const pVal = strtok(NULL, "=");
|
||||||
|
|
||||||
if (pVal == NULL) {
|
if (pVal == NULL) {
|
||||||
sprintf(errbuf, "bad syntax of WHEN\n");
|
sprintf(errbuf, "bad syntax of WHEN\n");
|
||||||
|
|
@ -1297,16 +1295,12 @@ measure_parse_find(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(pName, "AT") == 0) {
|
if (strcasecmp(pName, "AT") == 0) {
|
||||||
if ((engVal = ft_numparse(&pVal, FALSE)) == NULL) {
|
if (ft_numparse((char **) &pVal, FALSE, &meas->m_at) < 0) {
|
||||||
sprintf(errbuf, "bad syntax of WHEN\n");
|
sprintf(errbuf, "bad syntax of WHEN\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
engVal1 = *engVal;
|
else {
|
||||||
|
|
||||||
meas->m_at = engVal1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
sprintf(errbuf, "bad syntax of WHEN\n");
|
sprintf(errbuf, "bad syntax of WHEN\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ static void cp_free_control(void); /* needed by resetcontrol */
|
||||||
* more clever. */
|
* more clever. */
|
||||||
|
|
||||||
bool cp_cwait = FALSE;
|
bool cp_cwait = FALSE;
|
||||||
char *cp_csep = ";";
|
char *cp_csep = ";"; /* character that separates commands */
|
||||||
|
|
||||||
bool cp_dounixcom = FALSE;
|
bool cp_dounixcom = FALSE;
|
||||||
|
|
||||||
/* We have to keep the control structures in a stack, so that when we
|
/* We have to keep the control structures in a stack, so that when we
|
||||||
* do a 'source', we can push a fresh set onto the top... Actually
|
* do a 'source', we can push a fresh set onto the top... Actually
|
||||||
* there have to be two stacks -- one for the pointer to the list of
|
* there has to be two stacks -- one for the pointer to the list of
|
||||||
* control structs, and one for the 'current command' pointer... */
|
* control structs, and one for the 'current command' pointer... */
|
||||||
struct control *control[CONTROLSTACKSIZE];
|
struct control *control[CONTROLSTACKSIZE];
|
||||||
struct control *cend[CONTROLSTACKSIZE];
|
struct control *cend[CONTROLSTACKSIZE];
|
||||||
|
|
@ -62,12 +62,13 @@ int stackp = 0;
|
||||||
static char *noredirect[] = { "stop", "define", NULL };
|
static char *noredirect[] = { "stop", "define", NULL };
|
||||||
|
|
||||||
|
|
||||||
static struct control *
|
/* This function returns the (first) structure wit the label s */
|
||||||
findlabel(char *s, struct control *ct)
|
static struct control *findlabel(const char *s, struct control *ct)
|
||||||
{
|
{
|
||||||
while (ct) {
|
while (ct) {
|
||||||
if ((ct->co_type == CO_LABEL) && eq(s, ct->co_text->wl_word))
|
if ((ct->co_type == CO_LABEL) && eq(s, ct->co_text->wl_word)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
ct = ct->co_next;
|
ct = ct->co_next;
|
||||||
}
|
}
|
||||||
return (ct);
|
return (ct);
|
||||||
|
|
@ -116,7 +117,7 @@ ctl_free(struct control *ctrl)
|
||||||
|
|
||||||
wl_free(ctrl->co_cond);
|
wl_free(ctrl->co_cond);
|
||||||
ctrl->co_cond = NULL;
|
ctrl->co_cond = NULL;
|
||||||
tfree(ctrl->co_foreachvar);
|
txfree(ctrl->co_foreachvar);
|
||||||
ctrl->co_foreachvar = NULL;
|
ctrl->co_foreachvar = NULL;
|
||||||
wl_free(ctrl->co_text);
|
wl_free(ctrl->co_text);
|
||||||
ctrl->co_text = NULL;
|
ctrl->co_text = NULL;
|
||||||
|
|
@ -288,8 +289,9 @@ doblock(struct control *bl, int *num)
|
||||||
switch (bl->co_type) {
|
switch (bl->co_type) {
|
||||||
case CO_WHILE:
|
case CO_WHILE:
|
||||||
if (!bl->co_children) {
|
if (!bl->co_children) {
|
||||||
fprintf(cp_err, "Warning: Executing empty 'while' block.\n");
|
fprintf(cp_err, "Warning: Executing empty 'while' block.\n"
|
||||||
fprintf(cp_err, " (Use a label statement as a no-op to suppress this warning.)\n");
|
" (Use a label statement as a no-op "
|
||||||
|
"to suppress this warning.)\n");
|
||||||
}
|
}
|
||||||
while (bl->co_cond && cp_istrue(bl->co_cond)) {
|
while (bl->co_cond && cp_istrue(bl->co_cond)) {
|
||||||
if (!bl->co_children) cp_periodic(); /*CDHW*/
|
if (!bl->co_children) cp_periodic(); /*CDHW*/
|
||||||
|
|
@ -558,11 +560,11 @@ doblock(struct control *bl, int *num)
|
||||||
char *
|
char *
|
||||||
get_alt_prompt(void)
|
get_alt_prompt(void)
|
||||||
{
|
{
|
||||||
int i = 0, j;
|
int i = 0;
|
||||||
static char buf[MAX_CHEVRONS + 2]; /* includes terminating space & null */
|
static char buf[MAX_CHEVRONS + 2]; /* includes terminating space & null */
|
||||||
struct control *c;
|
struct control *c;
|
||||||
|
|
||||||
/* if nothing on the command stack return NULL */
|
/* If nothing on the command stack return NULL */
|
||||||
if (cend[stackp] == NULL)
|
if (cend[stackp] == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
@ -570,8 +572,9 @@ get_alt_prompt(void)
|
||||||
for (c = cend[stackp]->co_parent; c; c = c->co_parent)
|
for (c = cend[stackp]->co_parent; c; c = c->co_parent)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (i <= 0)
|
if (i == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Avoid overflow of buffer and
|
/* Avoid overflow of buffer and
|
||||||
indicate when we've limited the chevrons by starting with a '+' */
|
indicate when we've limited the chevrons by starting with a '+' */
|
||||||
|
|
@ -583,15 +586,19 @@ get_alt_prompt(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return one chevron per command stack depth */
|
/* return one chevron per command stack depth */
|
||||||
|
{
|
||||||
|
int j;
|
||||||
for (j = 1; j < i; j++)
|
for (j = 1; j < i; j++)
|
||||||
buf[j] = '>';
|
buf[j] = '>';
|
||||||
|
|
||||||
/* Add space and terminate */
|
/* Add space and terminate */
|
||||||
buf[j] = ' ';
|
buf[j] = ' ';
|
||||||
buf[j + 1] = '\0';
|
buf[j + 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
} /* end of function get_alt_prompt */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get a command. This does all the bookkeeping things like turning
|
/* Get a command. This does all the bookkeeping things like turning
|
||||||
|
|
@ -601,8 +608,9 @@ getcommand(char *string)
|
||||||
{
|
{
|
||||||
wordlist *wlist;
|
wordlist *wlist;
|
||||||
|
|
||||||
if (cp_debug)
|
if (cp_debug) {
|
||||||
fprintf(cp_err, "calling getcommand %s\n", string ? string : "");
|
fprintf(cp_err, "calling getcommand %s\n", string ? string : "");
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)
|
#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)
|
||||||
/* set cp_altprompt for use by the lexer - see parser/lexical.c */
|
/* set cp_altprompt for use by the lexer - see parser/lexical.c */
|
||||||
|
|
@ -617,7 +625,7 @@ getcommand(char *string)
|
||||||
wl_print(wlist, stdout);
|
wl_print(wlist, stdout);
|
||||||
putc('\n', stdout);
|
putc('\n', stdout);
|
||||||
}
|
}
|
||||||
return (wlist);
|
return wlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -628,7 +636,6 @@ cp_evloop(char *string)
|
||||||
wordlist *wlist, *ww, *freewl;
|
wordlist *wlist, *ww, *freewl;
|
||||||
struct control *x;
|
struct control *x;
|
||||||
char *i;
|
char *i;
|
||||||
int nn;
|
|
||||||
|
|
||||||
#define newblock \
|
#define newblock \
|
||||||
do { \
|
do { \
|
||||||
|
|
@ -653,8 +660,9 @@ cp_evloop(char *string)
|
||||||
/* User just typed return. */
|
/* User just typed return. */
|
||||||
wl_free(wlist); /* va, avoid memory leak */
|
wl_free(wlist); /* va, avoid memory leak */
|
||||||
if (string) {
|
if (string) {
|
||||||
return (1);
|
return 1;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
cp_event--;
|
cp_event--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -708,22 +716,23 @@ cp_evloop(char *string)
|
||||||
cend[stackp]->co_numtimes = -1;
|
cend[stackp]->co_numtimes = -1;
|
||||||
} else {
|
} else {
|
||||||
char *s;
|
char *s;
|
||||||
double *dd;
|
double val;
|
||||||
|
|
||||||
struct wordlist *t; /*CDHW*/
|
struct wordlist *t; /*CDHW*/
|
||||||
/*CDHW wlist = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(wlist)))); Wrong order? Leak? CDHW*/
|
/*CDHW wlist = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(wlist)))); Wrong order? Leak? CDHW*/
|
||||||
t = cp_doglob(cp_bquote(cp_variablesubst(wl_copy(wlist)))); /*CDHW leak from cp_doglob? */
|
t = cp_doglob(cp_bquote(cp_variablesubst(wl_copy(wlist)))); /*CDHW leak from cp_doglob? */
|
||||||
s = t->wl_next->wl_word;
|
s = t->wl_next->wl_word;
|
||||||
|
|
||||||
dd = ft_numparse(&s, FALSE);
|
if (ft_numparse(&s, FALSE, &val) > 0) {
|
||||||
if (dd) {
|
/* Can be converted to int */
|
||||||
if (*dd < 0) {
|
if (val < 0) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: can't repeat a negative number of times\n");
|
"Error: can't repeat a negative number of times\n");
|
||||||
*dd = 0.0;
|
val = 0.0;
|
||||||
}
|
}
|
||||||
cend[stackp]->co_numtimes = (int) *dd;
|
cend[stackp]->co_numtimes = (int) val;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Error: bad repeat argument %s\n",
|
"Error: bad repeat argument %s\n",
|
||||||
t->wl_next->wl_word); /* CDHW */
|
t->wl_next->wl_word); /* CDHW */
|
||||||
|
|
@ -805,7 +814,7 @@ cp_evloop(char *string)
|
||||||
cend[stackp]->co_numtimes = 1;
|
cend[stackp]->co_numtimes = 1;
|
||||||
}
|
}
|
||||||
} else if (eq(wlist->wl_word, "end")) {
|
} else if (eq(wlist->wl_word, "end")) {
|
||||||
/* Throw away this thing. */
|
/* Throw away this thing if not in a block. */
|
||||||
if (!cend[stackp]->co_parent) {
|
if (!cend[stackp]->co_parent) {
|
||||||
fprintf(stderr, "Error: no block to end.\n");
|
fprintf(stderr, "Error: no block to end.\n");
|
||||||
cend[stackp]->co_type = CO_UNFILLED;
|
cend[stackp]->co_type = CO_UNFILLED;
|
||||||
|
|
@ -824,8 +833,7 @@ cp_evloop(char *string)
|
||||||
}
|
}
|
||||||
} else if (eq(wlist->wl_word, "else")) {
|
} else if (eq(wlist->wl_word, "else")) {
|
||||||
if (!cend[stackp]->co_parent ||
|
if (!cend[stackp]->co_parent ||
|
||||||
(cend[stackp]->co_parent->co_type !=
|
(cend[stackp]->co_parent->co_type != CO_IF)) {
|
||||||
CO_IF)) {
|
|
||||||
fprintf(stderr, "Error: misplaced else.\n");
|
fprintf(stderr, "Error: misplaced else.\n");
|
||||||
cend[stackp]->co_type = CO_UNFILLED;
|
cend[stackp]->co_type = CO_UNFILLED;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -847,7 +855,7 @@ cp_evloop(char *string)
|
||||||
* that gotos at the top level will work.
|
* that gotos at the top level will work.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
nn = 0; /* CDHW */
|
int nn = 0; /* CDHW */
|
||||||
i = doblock(x, &nn);
|
i = doblock(x, &nn);
|
||||||
switch (*i) {
|
switch (*i) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
|
|
@ -873,8 +881,8 @@ cp_evloop(char *string)
|
||||||
wl_free(freewl);
|
wl_free(freewl);
|
||||||
if (string)
|
if (string)
|
||||||
return (1); /* The return value is irrelevant. */
|
return (1); /* The return value is irrelevant. */
|
||||||
}
|
} /* end of unconditional loop */
|
||||||
}
|
} /* end of function cp_evloop */
|
||||||
|
|
||||||
|
|
||||||
/* This blows away the control structures... */
|
/* This blows away the control structures... */
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ Modified: 2000 AlansFixes
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "ngspice/cpdefs.h"
|
#include "ngspice/cpdefs.h"
|
||||||
#include "ngspice/ftedefs.h"
|
#include "ngspice/ftedefs.h"
|
||||||
|
#include "ngspice/dstring.h"
|
||||||
#include "ngspice/dvec.h"
|
#include "ngspice/dvec.h"
|
||||||
#include "ngspice/fteinp.h"
|
#include "ngspice/fteinp.h"
|
||||||
#include "ngspice/sim.h"
|
#include "ngspice/sim.h"
|
||||||
|
|
@ -200,8 +201,9 @@ ft_cktcoms(bool terse)
|
||||||
all.wl_next = NULL;
|
all.wl_next = NULL;
|
||||||
all.wl_word = "all";
|
all.wl_word = "all";
|
||||||
|
|
||||||
if (!ft_curckt)
|
if (!ft_curckt) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
plot_cur = setcplot("op");
|
plot_cur = setcplot("op");
|
||||||
if (!ft_curckt->ci_commands && !plot_cur)
|
if (!ft_curckt->ci_commands && !plot_cur)
|
||||||
|
|
@ -249,8 +251,9 @@ ft_cktcoms(bool terse)
|
||||||
}
|
}
|
||||||
fprintf(cp_out, "\n");
|
fprintf(cp_out, "\n");
|
||||||
|
|
||||||
if (!ft_nomod)
|
if (!ft_nomod) {
|
||||||
com_showmod(&all);
|
com_showmod(&all);
|
||||||
|
}
|
||||||
com_show(&all);
|
com_show(&all);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -271,8 +274,10 @@ ft_cktcoms(bool terse)
|
||||||
/* Now all the '.' lines */
|
/* Now all the '.' lines */
|
||||||
while (coms) {
|
while (coms) {
|
||||||
command = cp_lexer(coms->wl_word);
|
command = cp_lexer(coms->wl_word);
|
||||||
if (!command)
|
if (!command || command->wl_word == (char *) NULL) {
|
||||||
|
/* Line not converted to a wordlist */
|
||||||
goto bad;
|
goto bad;
|
||||||
|
}
|
||||||
if (eq(command->wl_word, ".width")) {
|
if (eq(command->wl_word, ".width")) {
|
||||||
do
|
do
|
||||||
command = command->wl_next;
|
command = command->wl_next;
|
||||||
|
|
@ -360,12 +365,11 @@ ft_cktcoms(bool terse)
|
||||||
!eq(command->wl_word, ".op") &&
|
!eq(command->wl_word, ".op") &&
|
||||||
// !eq(command->wl_word, ".measure") &&
|
// !eq(command->wl_word, ".measure") &&
|
||||||
!ciprefix(".meas", command->wl_word) &&
|
!ciprefix(".meas", command->wl_word) &&
|
||||||
!eq(command->wl_word, ".tf"))
|
!eq(command->wl_word, ".tf")) {
|
||||||
{
|
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
coms = coms->wl_next;
|
coms = coms->wl_next; /* go to next line */
|
||||||
}
|
} /* end of loop over '.' lines */
|
||||||
|
|
||||||
nocmds:
|
nocmds:
|
||||||
/* Now the node table
|
/* Now the node table
|
||||||
|
|
@ -399,7 +403,7 @@ bad:
|
||||||
|
|
||||||
|
|
||||||
/* These routines make sure that the arguments to .plot and .print in
|
/* These routines make sure that the arguments to .plot and .print in
|
||||||
* spice2 decks are acceptable to spice3. The things we look for are:
|
* spice2 decks are acceptable to spice3. The things we look for are
|
||||||
* trailing (a,b) in .plot -> xlimit a b
|
* trailing (a,b) in .plot -> xlimit a b
|
||||||
* vm(x) -> mag(v(x))
|
* vm(x) -> mag(v(x))
|
||||||
* vp(x) -> ph(v(x))
|
* vp(x) -> ph(v(x))
|
||||||
|
|
@ -410,60 +414,70 @@ bad:
|
||||||
static void
|
static void
|
||||||
fixdotplot(wordlist *wl)
|
fixdotplot(wordlist *wl)
|
||||||
{
|
{
|
||||||
char *s;
|
/* Create a buffer for printing numbers */
|
||||||
char numbuf[128]; /* Printnum Fix */
|
DS_CREATE(numbuf, 100);
|
||||||
double *d, d1, d2;
|
|
||||||
|
|
||||||
while (wl) {
|
while (wl) {
|
||||||
wl->wl_word = fixem(wl->wl_word);
|
wl->wl_word = fixem(wl->wl_word);
|
||||||
|
|
||||||
/* Is this a trailing (a,b) ? Note that we require it to be
|
/* Is this a trailing "(a,b)"? Note that we require it to be
|
||||||
* one word.
|
* one word. */
|
||||||
*/
|
|
||||||
if (!wl->wl_next && (*wl->wl_word == '(')) {
|
if (!wl->wl_next && (*wl->wl_word == '(')) {
|
||||||
s = wl->wl_word + 1;
|
double d1, d2;
|
||||||
d = ft_numparse(&s, FALSE);
|
char *s = wl->wl_word + 1;
|
||||||
if (*s != ',') {
|
if (ft_numparse(&s, FALSE, &d1) < 0 ||
|
||||||
|
*s != ',') {
|
||||||
fprintf(cp_err, "Error: bad limits \"%s\"\n",
|
fprintf(cp_err, "Error: bad limits \"%s\"\n",
|
||||||
wl->wl_word);
|
wl->wl_word);
|
||||||
return;
|
goto EXITPOINT;
|
||||||
}
|
}
|
||||||
d1 = *d;
|
s++; /* step past comma */
|
||||||
s++;
|
if (ft_numparse(&s, FALSE, &d2) < 0 ||
|
||||||
d = ft_numparse(&s, FALSE);
|
*s != ')' || s[1] != '\0') { /* must end with ")" */
|
||||||
if ((*s != ')') || s[1]) {
|
|
||||||
fprintf(cp_err, "Error: bad limits \"%s\"\n",
|
fprintf(cp_err, "Error: bad limits \"%s\"\n",
|
||||||
wl->wl_word);
|
wl->wl_word);
|
||||||
return;
|
goto EXITPOINT;
|
||||||
}
|
}
|
||||||
d2 = *d;
|
|
||||||
tfree(wl->wl_word);
|
tfree(wl->wl_word);
|
||||||
wl->wl_word = copy("xlimit");
|
wl->wl_word = copy("xlimit");
|
||||||
printnum(numbuf, d1);
|
ds_clear(&numbuf);
|
||||||
wl_append_word(NULL, &wl, copy(numbuf));
|
if (printnum_ds(&numbuf, d1) != 0) {
|
||||||
printnum(numbuf, d2);
|
fprintf(cp_err, "Unable to print limit 1: %g\n", d1);
|
||||||
wl_append_word(NULL, &wl, copy(numbuf));
|
goto EXITPOINT;
|
||||||
}
|
}
|
||||||
|
wl_append_word(NULL, &wl, copy(ds_get_buf(&numbuf)));
|
||||||
|
ds_clear(&numbuf);
|
||||||
|
if (printnum_ds(&numbuf, d2) != 0) {
|
||||||
|
fprintf(cp_err, "Unable to print limit 2: %g\n", d2);
|
||||||
|
goto EXITPOINT;
|
||||||
|
}
|
||||||
|
wl_append_word(NULL, &wl, copy(ds_get_buf(&numbuf)));
|
||||||
|
} /* end of case of start of potential (a,b) */
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
}
|
} /* end of loop over words */
|
||||||
}
|
|
||||||
|
EXITPOINT:
|
||||||
|
ds_free(&numbuf); /* Free DSTRING resources */
|
||||||
|
} /* end of function fixdotplot */
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
fixdotprint(wordlist *wl)
|
static void fixdotprint(wordlist *wl)
|
||||||
{
|
{
|
||||||
|
/* Process each word in the wordlist */
|
||||||
while (wl) {
|
while (wl) {
|
||||||
wl->wl_word = fixem(wl->wl_word);
|
wl->wl_word = fixem(wl->wl_word);
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
}
|
}
|
||||||
}
|
} /* end of function fixdotprint */
|
||||||
|
|
||||||
|
|
||||||
static char *
|
|
||||||
fixem(char *string)
|
static char *fixem(char *string)
|
||||||
{
|
{
|
||||||
char buf[BSIZE_SP], *s, *t;
|
char buf[BSIZE_SP], *s, *t;
|
||||||
char *ss = string; /* Get rid of ss ? */
|
char *ss = string; /* save addr of string in case it is freed */
|
||||||
|
|
||||||
if (ciprefix("v(", string) &&strchr(string, ',')) {
|
if (ciprefix("v(", string) &&strchr(string, ',')) {
|
||||||
for (s = string; *s && (*s != ','); s++)
|
for (s = string; *s && (*s != ','); s++)
|
||||||
|
|
@ -550,14 +564,15 @@ fixem(char *string)
|
||||||
string += 2;
|
string += 2;
|
||||||
(void) sprintf(buf, "%s#branch", string);
|
(void) sprintf(buf, "%s#branch", string);
|
||||||
} else {
|
} else {
|
||||||
return (string);
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
tfree(ss);
|
txfree(ss);
|
||||||
string = copy(buf);
|
string = copy(buf);
|
||||||
|
|
||||||
return (string);
|
return string;
|
||||||
}
|
} /* end of function fixem */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wordlist *
|
wordlist *
|
||||||
|
|
@ -611,7 +626,8 @@ gettoks(char *s)
|
||||||
sprintf(buf, "%s#branch", l + 1);
|
sprintf(buf, "%s#branch", l + 1);
|
||||||
wl->wl_word = copy(buf);
|
wl->wl_word = copy(buf);
|
||||||
c = r = NULL;
|
c = r = NULL;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
wl->wl_word = copy(l + 1);
|
wl->wl_word = copy(l + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -622,7 +638,11 @@ gettoks(char *s)
|
||||||
prevp = &wl->wl_next;
|
prevp = &wl->wl_next;
|
||||||
}
|
}
|
||||||
tfree(t);
|
tfree(t);
|
||||||
}
|
} /* end of loop parsing string */
|
||||||
tfree(s0);
|
|
||||||
|
txfree(s0);
|
||||||
return list;
|
return list;
|
||||||
}
|
} /* end of function gettoks */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ fourier(wordlist *wl, struct plot *current_plot)
|
||||||
{
|
{
|
||||||
struct dvec *time, *vec;
|
struct dvec *time, *vec;
|
||||||
struct pnode *pn, *names;
|
struct pnode *pn, *names;
|
||||||
double *ff, fundfreq, *data = NULL;
|
double fundfreq, *data = NULL;
|
||||||
int nfreqs, fourgridsize, polydegree;
|
int nfreqs, fourgridsize, polydegree;
|
||||||
double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */
|
double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */
|
||||||
double thd, *timescale = NULL;
|
double thd, *timescale = NULL;
|
||||||
|
|
@ -78,11 +78,10 @@ fourier(wordlist *wl, struct plot *current_plot)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
if ((ff = ft_numparse(&s, FALSE)) == NULL || (*ff <= 0.0)) {
|
if (ft_numparse(&s, FALSE, &fundfreq) < 0 || fundfreq <= 0.0) {
|
||||||
fprintf(cp_err, "Error: bad fund freq %s\n", wl->wl_word);
|
fprintf(cp_err, "Error: bad fundamental freq %s\n", wl->wl_word);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fundfreq = *ff;
|
|
||||||
|
|
||||||
freq = TMALLOC(double, nfreqs);
|
freq = TMALLOC(double, nfreqs);
|
||||||
mag = TMALLOC(double, nfreqs);
|
mag = TMALLOC(double, nfreqs);
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,7 @@ extern int PPparse(char **, struct pnode **);
|
||||||
void db_print_pnode_tree(struct pnode *p, char *print);
|
void db_print_pnode_tree(struct pnode *p, char *print);
|
||||||
|
|
||||||
|
|
||||||
struct pnode *
|
struct pnode *ft_getpnames_from_string(const char *sz, bool check)
|
||||||
ft_getpnames_from_string(const char *sz, bool check)
|
|
||||||
{
|
{
|
||||||
struct pnode *pn;
|
struct pnode *pn;
|
||||||
|
|
||||||
|
|
@ -62,7 +61,7 @@ ft_getpnames(const wordlist *wl, bool check)
|
||||||
return (struct pnode *) NULL;
|
return (struct pnode *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the list to a string then parse the string */
|
/* Conver the list to a string then parse the string */
|
||||||
const char * const sz = wl_flatten(wl);
|
const char * const sz = wl_flatten(wl);
|
||||||
struct pnode * const pn = ft_getpnames_from_string(sz, check);
|
struct pnode * const pn = ft_getpnames_from_string(sz, check);
|
||||||
txfree((void *) sz);
|
txfree((void *) sz);
|
||||||
|
|
@ -213,63 +212,70 @@ struct func func_not = { "not", cx_not };
|
||||||
|
|
||||||
|
|
||||||
/* Binary operator node. */
|
/* Binary operator node. */
|
||||||
|
struct pnode *PP_mkbnode(int opnum, struct pnode *arg1, struct pnode *arg2)
|
||||||
struct pnode *
|
|
||||||
PP_mkbnode(int opnum, struct pnode *arg1, struct pnode *arg2)
|
|
||||||
{
|
{
|
||||||
struct op *o;
|
struct op *o;
|
||||||
struct pnode *p;
|
struct pnode *p;
|
||||||
|
|
||||||
for (o = &ops[0]; o->op_name; o++)
|
for (o = &ops[0]; o->op_name; o++) {
|
||||||
if (o->op_num == opnum)
|
if (o->op_num == opnum) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!o->op_name)
|
if (!o->op_name) {
|
||||||
fprintf(cp_err, "PP_mkbnode: Internal Error: no such op num %d\n",
|
fprintf(cp_err, "PP_mkbnode: Internal Error: no such op num %d\n",
|
||||||
opnum);
|
opnum);
|
||||||
|
}
|
||||||
|
|
||||||
p = alloc_pnode();
|
p = alloc_pnode();
|
||||||
|
|
||||||
p->pn_op = o;
|
p->pn_op = o;
|
||||||
|
|
||||||
p->pn_left = arg1;
|
p->pn_left = arg1;
|
||||||
if (p->pn_left)
|
if (p->pn_left) {
|
||||||
p->pn_left->pn_use++;
|
p->pn_left->pn_use++;
|
||||||
|
}
|
||||||
|
|
||||||
p->pn_right = arg2;
|
p->pn_right = arg2;
|
||||||
if (p->pn_right)
|
if (p->pn_right) {
|
||||||
p->pn_right->pn_use++;
|
p->pn_right->pn_use++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
} /* end of function PP_mkbnode */
|
||||||
|
|
||||||
return (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Unary operator node. */
|
/* Unary operator node. */
|
||||||
|
struct pnode *PP_mkunode(int op, struct pnode *arg)
|
||||||
struct pnode *
|
|
||||||
PP_mkunode(int op, struct pnode *arg)
|
|
||||||
{
|
{
|
||||||
struct pnode *p;
|
struct pnode *p;
|
||||||
struct op *o;
|
struct op *o;
|
||||||
|
|
||||||
p = alloc_pnode();
|
p = alloc_pnode();
|
||||||
|
|
||||||
for (o = uops; o->op_name; o++)
|
for (o = uops; o->op_name; o++) {
|
||||||
if (o->op_num == op)
|
if (o->op_num == op) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!o->op_name)
|
if (!o->op_name) {
|
||||||
fprintf(cp_err, "PP_mkunode: Internal Error: no such op num %d\n",
|
fprintf(cp_err, "PP_mkunode: Internal Error: no such op num %d\n",
|
||||||
op);
|
op);
|
||||||
|
}
|
||||||
|
|
||||||
p->pn_op = o;
|
p->pn_op = o;
|
||||||
|
|
||||||
p->pn_left = arg;
|
p->pn_left = arg;
|
||||||
if (p->pn_left)
|
if (p->pn_left) {
|
||||||
p->pn_left->pn_use++;
|
p->pn_left->pn_use++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
} /* end of function PP_mkunode */
|
||||||
|
|
||||||
return (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Function node. We have to worry about a lot of things here. Something
|
/* Function node. We have to worry about a lot of things here. Something
|
||||||
|
|
@ -280,9 +286,7 @@ PP_mkunode(int op, struct pnode *arg)
|
||||||
* the arguments, and then return a copy of the expression that it was
|
* the arguments, and then return a copy of the expression that it was
|
||||||
* defined to be.
|
* defined to be.
|
||||||
*/
|
*/
|
||||||
|
struct pnode *PP_mkfnode(const char *func, struct pnode *arg)
|
||||||
struct pnode *
|
|
||||||
PP_mkfnode(const char *func, struct pnode *arg)
|
|
||||||
{
|
{
|
||||||
struct func *f;
|
struct func *f;
|
||||||
struct pnode *p, *q;
|
struct pnode *p, *q;
|
||||||
|
|
@ -292,15 +296,18 @@ PP_mkfnode(const char *func, struct pnode *arg)
|
||||||
(void) strcpy(buf, func);
|
(void) strcpy(buf, func);
|
||||||
strtolower(buf); /* Make sure the case is ok. */
|
strtolower(buf); /* Make sure the case is ok. */
|
||||||
|
|
||||||
for (f = &ft_funcs[0]; f->fu_name; f++)
|
for (f = &ft_funcs[0]; f->fu_name; f++) {
|
||||||
if (eq(f->fu_name, buf))
|
if (eq(f->fu_name, buf)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (f->fu_name == NULL) {
|
if (f->fu_name == NULL) { /* not found yet */
|
||||||
/* Give the user-defined functions a try. */
|
/* Give the user-defined functions a try. */
|
||||||
q = ft_substdef(func, arg);
|
q = ft_substdef(func, arg);
|
||||||
if (q)
|
if (q) { /* found */
|
||||||
return (q);
|
return q;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((f->fu_name == NULL) && arg->pn_value) {
|
if ((f->fu_name == NULL) && arg->pn_value) {
|
||||||
|
|
@ -312,15 +319,16 @@ PP_mkfnode(const char *func, struct pnode *arg)
|
||||||
/* Well, too bad. */
|
/* Well, too bad. */
|
||||||
fprintf(cp_err, "Error: no such function as %s.\n",
|
fprintf(cp_err, "Error: no such function as %s.\n",
|
||||||
func);
|
func);
|
||||||
return (NULL);
|
return (struct pnode *) NULL;
|
||||||
}
|
}
|
||||||
/* (void) strcpy(buf, d->v_name); XXX */
|
/* (void) strcpy(buf, d->v_name); XXX */
|
||||||
return (PP_mksnode(buf));
|
return PP_mksnode(buf);
|
||||||
} else if (f->fu_name == NULL) {
|
}
|
||||||
|
else if (f->fu_name == NULL) {
|
||||||
fprintf(cp_err, "Error: no function as %s with that arity.\n",
|
fprintf(cp_err, "Error: no function as %s with that arity.\n",
|
||||||
func);
|
func);
|
||||||
free_pnode(arg);
|
free_pnode(arg);
|
||||||
return (NULL);
|
return (struct pnode *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!f->fu_func && arg->pn_op && arg->pn_op->op_num == PT_OP_COMMA) {
|
if (!f->fu_func && arg->pn_op && arg->pn_op->op_num == PT_OP_COMMA) {
|
||||||
|
|
@ -335,17 +343,17 @@ PP_mkfnode(const char *func, struct pnode *arg)
|
||||||
p->pn_func = f;
|
p->pn_func = f;
|
||||||
|
|
||||||
p->pn_left = arg;
|
p->pn_left = arg;
|
||||||
if (p->pn_left)
|
if (p->pn_left) {
|
||||||
p->pn_left->pn_use++;
|
p->pn_left->pn_use++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
} /* end of function PP_mkfnode */
|
||||||
|
|
||||||
return (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Number node. */
|
/* Number node. */
|
||||||
|
struct pnode *PP_mknnode(double number)
|
||||||
struct pnode *
|
|
||||||
PP_mknnode(double number)
|
|
||||||
{
|
{
|
||||||
struct pnode *p;
|
struct pnode *p;
|
||||||
struct dvec *v;
|
struct dvec *v;
|
||||||
|
|
@ -354,7 +362,7 @@ PP_mknnode(double number)
|
||||||
* to be careful to deal properly with node numbers that are quite
|
* to be careful to deal properly with node numbers that are quite
|
||||||
* large...
|
* large...
|
||||||
*/
|
*/
|
||||||
v = dvec_alloc(number < MAXPOSINT
|
v = dvec_alloc(number <= INT_MAX
|
||||||
? tprintf("%d", (int) number)
|
? tprintf("%d", (int) number)
|
||||||
: tprintf("%G", number),
|
: tprintf("%G", number),
|
||||||
SV_NOTYPE,
|
SV_NOTYPE,
|
||||||
|
|
@ -368,13 +376,12 @@ PP_mknnode(double number)
|
||||||
p = alloc_pnode();
|
p = alloc_pnode();
|
||||||
p->pn_value = v;
|
p->pn_value = v;
|
||||||
return (p);
|
return (p);
|
||||||
}
|
} /* end of function PP_mknnode */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* String node. */
|
/* String node. */
|
||||||
|
struct pnode *PP_mksnode(const char *string)
|
||||||
struct pnode *
|
|
||||||
PP_mksnode(const char *string)
|
|
||||||
{
|
{
|
||||||
struct dvec *v, *nv, *vs, *newv = NULL, *end = NULL;
|
struct dvec *v, *nv, *vs, *newv = NULL, *end = NULL;
|
||||||
struct pnode *p;
|
struct pnode *p;
|
||||||
|
|
@ -387,17 +394,19 @@ PP_mksnode(const char *string)
|
||||||
0,
|
0,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
p->pn_value = nv;
|
p->pn_value = nv;
|
||||||
return (p);
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It's not obvious that we should be doing this, but... */
|
/* It's not obvious that we should be doing this, but... */
|
||||||
for (vs = v; vs; vs = vs->v_link2) {
|
for (vs = v; vs; vs = vs->v_link2) {
|
||||||
nv = vec_copy(vs);
|
nv = vec_copy(vs);
|
||||||
vec_new(nv);
|
vec_new(nv);
|
||||||
if (end)
|
if (end) {
|
||||||
end->v_link2 = nv;
|
end->v_link2 = nv;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
newv = end = nv;
|
newv = end = nv;
|
||||||
|
}
|
||||||
end = nv;
|
end = nv;
|
||||||
}
|
}
|
||||||
p->pn_value = newv;
|
p->pn_value = newv;
|
||||||
|
|
@ -410,12 +419,12 @@ PP_mksnode(const char *string)
|
||||||
/* The two lines above have been commented out to prevent deletion of @xxx[par]
|
/* The two lines above have been commented out to prevent deletion of @xxx[par]
|
||||||
after execution of only a single command like plot @xxx[par] or write. We need to
|
after execution of only a single command like plot @xxx[par] or write. We need to
|
||||||
monitor if this will lead to excessive memory usage. h_vogt 090221 */
|
monitor if this will lead to excessive memory usage. h_vogt 090221 */
|
||||||
return (p);
|
return p;
|
||||||
}
|
} /* end of function PP_mksnode */
|
||||||
|
|
||||||
|
|
||||||
struct pnode *
|
|
||||||
alloc_pnode(void)
|
struct pnode *alloc_pnode(void)
|
||||||
{
|
{
|
||||||
struct pnode *pn = TMALLOC(struct pnode, 1);
|
struct pnode *pn = TMALLOC(struct pnode, 1);
|
||||||
|
|
||||||
|
|
@ -432,42 +441,45 @@ alloc_pnode(void)
|
||||||
pn->pn_next = NULL;
|
pn->pn_next = NULL;
|
||||||
|
|
||||||
return pn;
|
return pn;
|
||||||
}
|
} /* end of function alloc_pnode */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Don't call this directly, always use the free_pnode() macro.
|
/* Don't call this directly, always use the free_pnode() macro.
|
||||||
The linked pnodes do not necessarily form a perfect tree as some nodes get
|
The linked pnodes do not necessarily form a perfect tree as some nodes get
|
||||||
reused. Hence, in this recursive walk trough the 'tree' we only free node
|
reused. Hence, in this recursive walk through the 'tree', we only free
|
||||||
that have their pn_use value at zero. Nodes that have pn_use values above
|
nodes that have their pn_use value at zero. Nodes that have pn_use values
|
||||||
zero have the link severed and their pn_use value decremented.
|
above zero have the link severed and their pn_use value decremented.
|
||||||
In addition, we don't walk past nodes with pn_use values avoid zero, just
|
In addition, we don't walk past nodes with pn_use values avoid zero, just
|
||||||
in case we have a circular reference (this probable does not happen in
|
in case we have a circular reference (This probably does not happen in
|
||||||
practice, but it does no harm playing safe) */
|
practice, but it does no harm playing safe.) */
|
||||||
void
|
void free_pnode_x(struct pnode *t)
|
||||||
free_pnode_x(struct pnode *t)
|
|
||||||
{
|
{
|
||||||
if (!t)
|
if (!t) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* don't walk past nodes used elsewhere. We decrement the pn_use value here,
|
/* Don't walk past nodes used elsewhere. We decrement the pn_use value here,
|
||||||
but the link gets severed by the action of the free_pnode() macro */
|
but the link gets severed by the action of the free_pnode() macro */
|
||||||
if (t->pn_use > 1) {
|
if (t->pn_use > 1) {
|
||||||
t->pn_use--;
|
t->pn_use--;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
/* pn_use is now 1, so its safe to free the pnode */
|
/* pn_use is now 1, so its safe to free the pnode */
|
||||||
free_pnode(t->pn_left);
|
free_pnode(t->pn_left);
|
||||||
free_pnode(t->pn_right);
|
free_pnode(t->pn_right);
|
||||||
free_pnode(t->pn_next);
|
free_pnode(t->pn_next);
|
||||||
tfree(t->pn_name); /* va: it is a copy() of original string, can be free'd */
|
tfree(t->pn_name); /* va: it is a copy() of original string, can be free'd */
|
||||||
if (t->pn_value && !(t->pn_value->v_flags & VF_PERMANENT))
|
if (t->pn_value && !(t->pn_value->v_flags & VF_PERMANENT)) {
|
||||||
vec_free(t->pn_value); /* patch by Stefan Jones */
|
vec_free(t->pn_value); /* patch by Stefan Jones */
|
||||||
tfree(t);
|
|
||||||
}
|
}
|
||||||
}
|
txfree(t);
|
||||||
|
}
|
||||||
|
} /* end of function free_pnode_x */
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
db_print_func(FILE *fdst, struct func *f)
|
static void db_print_func(FILE *fdst, struct func *f)
|
||||||
{
|
{
|
||||||
if (!f) {
|
if (!f) {
|
||||||
fprintf(fdst, "nil");
|
fprintf(fdst, "nil");
|
||||||
|
|
@ -475,11 +487,11 @@ db_print_func(FILE *fdst, struct func *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fdst, "(func :fu_name %s :fu_func %p)", f->fu_name, f->fu_func);
|
fprintf(fdst, "(func :fu_name %s :fu_func %p)", f->fu_name, f->fu_func);
|
||||||
}
|
} /* end of function db_print_func */
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
db_print_op(FILE *fdst, struct op *op)
|
static void db_print_op(FILE *fdst, struct op *op)
|
||||||
{
|
{
|
||||||
if (!op) {
|
if (!op) {
|
||||||
fprintf(fdst, "nil");
|
fprintf(fdst, "nil");
|
||||||
|
|
@ -488,11 +500,11 @@ db_print_op(FILE *fdst, struct op *op)
|
||||||
|
|
||||||
fprintf(fdst, "(op :op_num %d :op_name %s :op_arity %d :op_func %p)",
|
fprintf(fdst, "(op :op_num %d :op_name %s :op_arity %d :op_func %p)",
|
||||||
op->op_num, op->op_name, op->op_arity, op->op_func.anonymous);
|
op->op_num, op->op_name, op->op_arity, op->op_func.anonymous);
|
||||||
}
|
} /* end of function db_print_op */
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
db_print_dvec(FILE *fdst, struct dvec *d)
|
static void db_print_dvec(FILE *fdst, struct dvec *d)
|
||||||
{
|
{
|
||||||
if (!d) {
|
if (!d) {
|
||||||
fprintf(fdst, "nil");
|
fprintf(fdst, "nil");
|
||||||
|
|
@ -501,11 +513,11 @@ db_print_dvec(FILE *fdst, struct dvec *d)
|
||||||
|
|
||||||
fprintf(fdst, "(dvec :v_name %s :v_type %d :v_flags %d :v_length %d ...)",
|
fprintf(fdst, "(dvec :v_name %s :v_type %d :v_flags %d :v_length %d ...)",
|
||||||
d->v_name, d->v_type, d->v_flags, d->v_length);
|
d->v_name, d->v_type, d->v_flags, d->v_length);
|
||||||
}
|
} /* end of function db_print_dvec */
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
db_print_pnode(FILE *fdst, struct pnode *p)
|
static void db_print_pnode(FILE *fdst, struct pnode *p)
|
||||||
{
|
{
|
||||||
if (!p) {
|
if (!p) {
|
||||||
fprintf(fdst, "nil\n");
|
fprintf(fdst, "nil\n");
|
||||||
|
|
@ -513,8 +525,7 @@ db_print_pnode(FILE *fdst, struct pnode *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->pn_name && p->pn_value && !p->pn_func && !p->pn_op &&
|
if (!p->pn_name && p->pn_value && !p->pn_func && !p->pn_op &&
|
||||||
!p->pn_left && !p->pn_right && !p->pn_next)
|
!p->pn_left && !p->pn_right && !p->pn_next) {
|
||||||
{
|
|
||||||
fprintf(fdst, "(pnode-value :pn_use %d", p->pn_use);
|
fprintf(fdst, "(pnode-value :pn_use %d", p->pn_use);
|
||||||
fprintf(fdst, " :pn_value "); db_print_dvec(fdst, p->pn_value);
|
fprintf(fdst, " :pn_value "); db_print_dvec(fdst, p->pn_value);
|
||||||
fprintf(fdst, ")\n");
|
fprintf(fdst, ")\n");
|
||||||
|
|
@ -522,8 +533,7 @@ db_print_pnode(FILE *fdst, struct pnode *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->pn_name && !p->pn_value && p->pn_func && !p->pn_op &&
|
if (!p->pn_name && !p->pn_value && p->pn_func && !p->pn_op &&
|
||||||
!p->pn_right && !p->pn_next)
|
!p->pn_right && !p->pn_next) {
|
||||||
{
|
|
||||||
fprintf(fdst, "(pnode-func :pn_use %d", p->pn_use);
|
fprintf(fdst, "(pnode-func :pn_use %d", p->pn_use);
|
||||||
fprintf(fdst, "\n :pn_func "); db_print_func(fdst, p->pn_func);
|
fprintf(fdst, "\n :pn_func "); db_print_func(fdst, p->pn_func);
|
||||||
fprintf(fdst, "\n :pn_left "); db_print_pnode(fdst, p->pn_left);
|
fprintf(fdst, "\n :pn_left "); db_print_pnode(fdst, p->pn_left);
|
||||||
|
|
@ -532,8 +542,7 @@ db_print_pnode(FILE *fdst, struct pnode *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->pn_name && !p->pn_value && !p->pn_func && p->pn_op &&
|
if (!p->pn_name && !p->pn_value && !p->pn_func && p->pn_op &&
|
||||||
!p->pn_next)
|
!p->pn_next) {
|
||||||
{
|
|
||||||
fprintf(fdst, "(pnode-op :pn_use %d", p->pn_use);
|
fprintf(fdst, "(pnode-op :pn_use %d", p->pn_use);
|
||||||
fprintf(fdst, "\n :pn_op "); db_print_op(fdst, p->pn_op);
|
fprintf(fdst, "\n :pn_op "); db_print_op(fdst, p->pn_op);
|
||||||
fprintf(fdst, "\n :pn_left "); db_print_pnode(fdst, p->pn_left);
|
fprintf(fdst, "\n :pn_left "); db_print_pnode(fdst, p->pn_left);
|
||||||
|
|
@ -550,11 +559,11 @@ db_print_pnode(FILE *fdst, struct pnode *p)
|
||||||
fprintf(fdst, "\n :pn_right "); db_print_pnode(fdst, p->pn_right);
|
fprintf(fdst, "\n :pn_right "); db_print_pnode(fdst, p->pn_right);
|
||||||
fprintf(fdst, "\n :pn_next "); db_print_pnode(fdst, p->pn_next);
|
fprintf(fdst, "\n :pn_next "); db_print_pnode(fdst, p->pn_next);
|
||||||
fprintf(fdst, "\n)\n");
|
fprintf(fdst, "\n)\n");
|
||||||
}
|
} /* end of function db_print_pnode */
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
db_print_pnode_tree(struct pnode *p, char *print)
|
void db_print_pnode_tree(struct pnode *p, char *print)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
NG_IGNORE(print);
|
NG_IGNORE(print);
|
||||||
|
|
@ -569,18 +578,19 @@ db_print_pnode_tree(struct pnode *p, char *print)
|
||||||
printf("%s:%d: %s {%s}\n%s\n", __FILE__, __LINE__, __func__, print, buf);
|
printf("%s:%d: %s {%s}\n%s\n", __FILE__, __LINE__, __func__, print, buf);
|
||||||
tfree(buf);
|
tfree(buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
} /* end of function db_print_pnode_tree */
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
|
int PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
|
||||||
{
|
{
|
||||||
static char *specials = " \t%()-^+*,/|&<>~=";
|
static char *specials = " \t%()-^+*,/|&<>~=";
|
||||||
char *sbuf = *line;
|
char *sbuf = *line;
|
||||||
int token;
|
int token;
|
||||||
|
|
||||||
while ((*sbuf == ' ') || (*sbuf == '\t'))
|
while ((*sbuf == ' ') || (*sbuf == '\t')) {
|
||||||
sbuf++;
|
sbuf++;
|
||||||
|
}
|
||||||
|
|
||||||
llocp->start = sbuf;
|
llocp->start = sbuf;
|
||||||
|
|
||||||
|
|
@ -590,28 +600,36 @@ PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
|
||||||
if ((sbuf[0] == 'g') && (sbuf[1] == 't') &&
|
if ((sbuf[0] == 'g') && (sbuf[1] == 't') &&
|
||||||
strchr(specials, sbuf[2])) {
|
strchr(specials, sbuf[2])) {
|
||||||
lexer_return('>', 2);
|
lexer_return('>', 2);
|
||||||
} else if ((sbuf[0] == 'l') && (sbuf[1] == 't') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'l') && (sbuf[1] == 't') &&
|
||||||
strchr(specials, sbuf[2])) {
|
strchr(specials, sbuf[2])) {
|
||||||
lexer_return('<', 2);
|
lexer_return('<', 2);
|
||||||
} else if ((sbuf[0] == 'g') && (sbuf[1] == 'e') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'g') && (sbuf[1] == 'e') &&
|
||||||
strchr(specials, sbuf[2])) {
|
strchr(specials, sbuf[2])) {
|
||||||
lexer_return(TOK_GE, 2);
|
lexer_return(TOK_GE, 2);
|
||||||
} else if ((sbuf[0] == 'l') && (sbuf[1] == 'e') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'l') && (sbuf[1] == 'e') &&
|
||||||
strchr(specials, sbuf[2])) {
|
strchr(specials, sbuf[2])) {
|
||||||
lexer_return(TOK_LE, 2);
|
lexer_return(TOK_LE, 2);
|
||||||
} else if ((sbuf[0] == 'n') && (sbuf[1] == 'e') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'n') && (sbuf[1] == 'e') &&
|
||||||
strchr(specials, sbuf[2])) {
|
strchr(specials, sbuf[2])) {
|
||||||
lexer_return(TOK_NE, 2);
|
lexer_return(TOK_NE, 2);
|
||||||
} else if ((sbuf[0] == 'e') && (sbuf[1] == 'q') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'e') && (sbuf[1] == 'q') &&
|
||||||
strchr(specials, sbuf[2])) {
|
strchr(specials, sbuf[2])) {
|
||||||
lexer_return('=', 2);
|
lexer_return('=', 2);
|
||||||
} else if ((sbuf[0] == 'o') && (sbuf[1] == 'r') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'o') && (sbuf[1] == 'r') &&
|
||||||
strchr(specials, sbuf[2])) {
|
strchr(specials, sbuf[2])) {
|
||||||
lexer_return('|', 2);
|
lexer_return('|', 2);
|
||||||
} else if ((sbuf[0] == 'a') && (sbuf[1] == 'n') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'a') && (sbuf[1] == 'n') &&
|
||||||
(sbuf[2] == 'd') && strchr(specials, sbuf[3])) {
|
(sbuf[2] == 'd') && strchr(specials, sbuf[3])) {
|
||||||
lexer_return('&', 3);
|
lexer_return('&', 3);
|
||||||
} else if ((sbuf[0] == 'n') && (sbuf[1] == 'o') &&
|
}
|
||||||
|
else if ((sbuf[0] == 'n') && (sbuf[1] == 'o') &&
|
||||||
(sbuf[2] == 't') && strchr(specials, sbuf[3])) {
|
(sbuf[2] == 't') && strchr(specials, sbuf[3])) {
|
||||||
lexer_return('~', 3);
|
lexer_return('~', 3);
|
||||||
}
|
}
|
||||||
|
|
@ -623,18 +641,19 @@ PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
|
||||||
lexer_return(*sbuf, 1);
|
lexer_return(*sbuf, 1);
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
case '<':
|
case '<': {
|
||||||
{
|
|
||||||
/* Workaround, The Frontend makes "<>" into "< >" */
|
/* Workaround, The Frontend makes "<>" into "< >" */
|
||||||
int j = 1;
|
size_t j = 1;
|
||||||
while (isspace_c(sbuf[j]))
|
while (isspace_c(sbuf[j]))
|
||||||
j++;
|
j++;
|
||||||
if (((sbuf[j] == '<') || (sbuf[j] == '>')) && (sbuf[0] != sbuf[j])) {
|
if (((sbuf[j] == '<') || (sbuf[j] == '>')) && (sbuf[0] != sbuf[j])) {
|
||||||
/* Allow both <> and >< for NE. */
|
/* Allow both <> and >< for NE. */
|
||||||
lexer_return(TOK_NE, j+1);
|
lexer_return(TOK_NE, j + 1);
|
||||||
} else if (sbuf[1] == '=') {
|
}
|
||||||
|
else if (sbuf[1] == '=') {
|
||||||
lexer_return((sbuf[0] == '>') ? TOK_GE : TOK_LE, 2);
|
lexer_return((sbuf[0] == '>') ? TOK_GE : TOK_LE, 2);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
lexer_return(*sbuf, 1);
|
lexer_return(*sbuf, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -659,26 +678,28 @@ PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
|
||||||
case '\0':
|
case '\0':
|
||||||
lexer_return(*sbuf, 0);
|
lexer_return(*sbuf, 0);
|
||||||
|
|
||||||
case '"':
|
case '"': {
|
||||||
{
|
|
||||||
char *start = ++sbuf;
|
char *start = ++sbuf;
|
||||||
while (*sbuf && (*sbuf != '"'))
|
while (*sbuf && (*sbuf != '"'))
|
||||||
sbuf++;
|
sbuf++;
|
||||||
lvalp->str = copy_substring(start, sbuf);
|
lvalp->str = copy_substring(start, sbuf);
|
||||||
if (*sbuf)
|
if (*sbuf) {
|
||||||
sbuf++;
|
sbuf++;
|
||||||
|
}
|
||||||
lexer_return(TOK_STR, 0);
|
lexer_return(TOK_STR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
char *s = sbuf;
|
char *s = sbuf;
|
||||||
double *td = ft_numparse(&s, FALSE);
|
double val;
|
||||||
if ((!s || *s != ':') && td) {
|
|
||||||
|
if (ft_numparse(&s, FALSE, &val) >= 0 &&
|
||||||
|
(!s || *s != ':')) {
|
||||||
sbuf = s;
|
sbuf = s;
|
||||||
lvalp->num = *td;
|
lvalp->num = val;
|
||||||
lexer_return(TOK_NUM, 0);
|
lexer_return(TOK_NUM, 0);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
int atsign = 0;
|
int atsign = 0;
|
||||||
char *start = sbuf;
|
char *start = sbuf;
|
||||||
/* It is bad how we have to recognise '[' -- sometimes
|
/* It is bad how we have to recognise '[' -- sometimes
|
||||||
|
|
@ -693,13 +714,16 @@ PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
|
||||||
* i(v5) --> v5#branch
|
* i(v5) --> v5#branch
|
||||||
*/
|
*/
|
||||||
for (; *sbuf && !strchr(specials, *sbuf); sbuf++)
|
for (; *sbuf && !strchr(specials, *sbuf); sbuf++)
|
||||||
if (*sbuf == '@')
|
if (*sbuf == '@') {
|
||||||
atsign = 1;
|
atsign = 1;
|
||||||
else if (!atsign && *sbuf == '[')
|
}
|
||||||
|
else if (!atsign && *sbuf == '[') {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
else if (*sbuf == ']') {
|
else if (*sbuf == ']') {
|
||||||
if (atsign)
|
if (atsign) {
|
||||||
sbuf++;
|
sbuf++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -707,19 +731,25 @@ PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
|
||||||
lexer_return(TOK_STR, 0);
|
lexer_return(TOK_STR, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} /* end of switch over characters */
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (ft_parsedb) {
|
if (ft_parsedb) {
|
||||||
if (token == TOK_STR)
|
if (token == TOK_STR) {
|
||||||
fprintf(stderr, "lexer: TOK_STR, \"%s\"\n", lvalp->str);
|
fprintf(stderr, "lexer: TOK_STR, \"%s\"\n", lvalp->str);
|
||||||
else if (token == TOK_NUM)
|
}
|
||||||
|
else if (token == TOK_NUM) {
|
||||||
fprintf(stderr, "lexer: TOK_NUM, %G\n", lvalp->num);
|
fprintf(stderr, "lexer: TOK_NUM, %G\n", lvalp->num);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
fprintf(stderr, "lexer: token %d\n", token);
|
fprintf(stderr, "lexer: token %d\n", token);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*line = sbuf;
|
*line = sbuf;
|
||||||
llocp->stop = sbuf;
|
llocp->stop = sbuf;
|
||||||
return (token);
|
return token;
|
||||||
}
|
} /* end of function PPlex */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||||
**********/
|
**********/
|
||||||
|
|
||||||
/* This routine parses a number. */
|
/* This routine parses a number. */
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/bool.h"
|
#include "ngspice/bool.h"
|
||||||
|
|
@ -11,160 +14,226 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||||
#include "numparse.h"
|
#include "numparse.h"
|
||||||
|
|
||||||
|
|
||||||
static double
|
|
||||||
power10(double num) /* Chris Inbody */
|
|
||||||
{
|
|
||||||
double d = 1.0;
|
|
||||||
|
|
||||||
while (num-- > 0)
|
|
||||||
d *= 10.0;
|
|
||||||
return (d);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ft_strictnumparse = FALSE;
|
bool ft_strictnumparse = FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
static int get_decimal_number(const char **p_str, double *p_val);
|
||||||
|
|
||||||
|
|
||||||
/* Parse a number. This will handle things like 10M, etc... If the number
|
/* Parse a number. This will handle things like 10M, etc... If the number
|
||||||
* must not end before the end of the string, then whole is TRUE.
|
* must not end before the end of the string, then whole is TRUE.
|
||||||
* If whole is FALSE and there is more left to the number, the argument
|
* If whole is FALSE and there is more left to the number, the argument
|
||||||
* is advanced to the end of the word. Returns NULL
|
* is advanced to the end of the word. Returns -1.
|
||||||
* if no number can be found or if there are trailing characters when
|
* if no number can be found or if there are trailing characters when
|
||||||
* whole is TRUE.
|
* whole is TRUE.
|
||||||
*
|
*
|
||||||
* If ft_strictnumparse is TRUE, and whole is FALSE, the first of the
|
* If ft_strictnumparse is TRUE, and whole is FALSE, the first of the
|
||||||
* trailing characters must be a '_'. */
|
* trailing characters must be a '_'.
|
||||||
|
*
|
||||||
double *
|
* Return codes
|
||||||
ft_numparse(char **s, bool whole)
|
* +1: String represented an integer number that was converted to a double
|
||||||
|
* but which can be stored as an int without loss of data
|
||||||
|
* 0: String represented a non-integer number that was converted to a double
|
||||||
|
* that may not be expressed as an integer.
|
||||||
|
* -1: Conversion failure
|
||||||
|
*/
|
||||||
|
int ft_numparse(char **p_str, bool whole, double *p_val)
|
||||||
{
|
{
|
||||||
double mant = 0.0;
|
double mant;
|
||||||
int sign = 1, exsign = 1, p;
|
double expo;
|
||||||
double expo = 0.0;
|
const char *p_cur = *p_str; /* position in string */
|
||||||
static double num;
|
|
||||||
char *string = *s;
|
|
||||||
|
|
||||||
/* See if the number begins with + or -. */
|
/* Parse the mantissa (or decimal number if no exponent) */
|
||||||
if (*string == '+') {
|
if (get_decimal_number(&p_cur, &mant) < 0) {
|
||||||
string++;
|
return -1;
|
||||||
} else if (*string == '-') {
|
|
||||||
string++;
|
|
||||||
sign = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't want to recognise "P" as 0P, or .P as 0.0P... */
|
|
||||||
if ((!isdigit_c(*string) && *string != '.') ||
|
|
||||||
((*string == '.') && !isdigit_c(string[1])))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
/* Now accumulate a number. Note ascii dependencies here... */
|
|
||||||
while (isdigit_c(*string))
|
|
||||||
mant = mant * 10.0 + (*string++ - '0');
|
|
||||||
|
|
||||||
/* Now maybe a decimal point. */
|
|
||||||
if (*string == '.') {
|
|
||||||
string++;
|
|
||||||
p = 1;
|
|
||||||
while (isdigit_c(*string))
|
|
||||||
mant += (*string++ - '0') / power10(p++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now look for the scale factor or the exponent (can't have both). */
|
/* Now look for the scale factor or the exponent (can't have both). */
|
||||||
switch (*string) {
|
switch (*p_cur) {
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
/* Parse another number. */
|
/* Parse another number. Note that a decimal number such as 1.23
|
||||||
string++;
|
* is allowed as the exponent */
|
||||||
if (*string == '+') {
|
++p_cur;
|
||||||
exsign = 1;
|
if (get_decimal_number(&p_cur, &expo) < 0) {
|
||||||
string++;
|
expo = 0.0;
|
||||||
} else if (*string == '-') {
|
--p_cur; /* The "E" was not part of the number */
|
||||||
exsign = -1;
|
|
||||||
string++;
|
|
||||||
}
|
}
|
||||||
while (isdigit_c(*string))
|
|
||||||
expo = expo * 10.0 + (*string++ - '0');
|
|
||||||
if (*string == '.') {
|
|
||||||
string++;
|
|
||||||
p = 1;
|
|
||||||
while (isdigit_c(*string))
|
|
||||||
expo += (*string++ - '0') / power10(p++);
|
|
||||||
}
|
|
||||||
expo *= exsign;
|
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
case 'T':
|
case 'T':
|
||||||
expo = 12.0;
|
expo = 12.0;
|
||||||
string++;
|
++p_cur;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
expo = 9.0;
|
expo = 9.0;
|
||||||
string++;
|
++p_cur;
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
case 'K':
|
case 'K':
|
||||||
expo = 3.0;
|
expo = 3.0;
|
||||||
string++;
|
++p_cur;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'U':
|
case 'U':
|
||||||
expo = -6.0;
|
expo = -6.0;
|
||||||
string++;
|
++p_cur;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
case 'N':
|
case 'N':
|
||||||
expo = -9.0;
|
expo = -9.0;
|
||||||
string++;
|
++p_cur;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'P':
|
case 'P':
|
||||||
expo = -12.0;
|
expo = -12.0;
|
||||||
string++;
|
++p_cur;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
expo = -15.0;
|
expo = -15.0;
|
||||||
string++;
|
++p_cur;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
case 'M':
|
case 'M': {
|
||||||
|
char ch_cur;
|
||||||
|
|
||||||
/* Can be either m, mil, or meg. */
|
/* Can be either m, mil, or meg. */
|
||||||
if (string[1] && string[2] &&
|
if (((ch_cur = p_cur[1]) == 'e' || ch_cur == 'E') &&
|
||||||
((string[1] == 'e') || (string[1] == 'E')) &&
|
(((ch_cur = p_cur[2]) == 'g') || ch_cur == 'G')) {
|
||||||
((string[2] == 'g') || (string[2] == 'G')))
|
|
||||||
{
|
|
||||||
expo = 6.0;
|
expo = 6.0;
|
||||||
string += 3;
|
p_cur += 3;
|
||||||
} else if (string[1] && string[2] &&
|
}
|
||||||
((string[1] == 'i') || (string[1] == 'I')) &&
|
else if (((ch_cur = p_cur[1]) == 'i' || ch_cur == 'I') &&
|
||||||
((string[2] == 'l') || (string[2] == 'L')))
|
(((ch_cur = p_cur[2]) == 'l') || ch_cur == 'L')) {
|
||||||
{
|
|
||||||
expo = -6.0;
|
expo = -6.0;
|
||||||
mant *= 25.4;
|
mant *= 25.4;
|
||||||
string += 3;
|
p_cur += 3;
|
||||||
} else {
|
}
|
||||||
|
else { /* plain m for milli */
|
||||||
expo = -3.0;
|
expo = -3.0;
|
||||||
string++;
|
++p_cur;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
if (whole && *string != '\0') {
|
expo = 0.0;
|
||||||
return (NULL);
|
|
||||||
} else if (ft_strictnumparse && *string && isdigit_c(string[-1])) {
|
|
||||||
if (*string == '_')
|
|
||||||
while (isalpha_c(*string) || (*string == '_'))
|
|
||||||
string++;
|
|
||||||
else
|
|
||||||
return (NULL);
|
|
||||||
} else {
|
|
||||||
while (isalpha_c(*string) || (*string == '_'))
|
|
||||||
string++;
|
|
||||||
}
|
}
|
||||||
*s = string;
|
|
||||||
num = sign * mant * pow(10.0, expo);
|
/* p_cur is now pointing to the fist char after the number */
|
||||||
if (ft_parsedb)
|
{
|
||||||
fprintf(cp_err, "numparse: got %e, left = %s\n", num, *s);
|
/* If whole is true, it must be the end of the string */
|
||||||
return (&num);
|
const char ch_cur = *p_cur;
|
||||||
}
|
if (whole && ch_cur != '\0') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If ft_strictnumparse is true, the first character after the
|
||||||
|
* string representing the number, if any, must be '_' */
|
||||||
|
if (ft_strictnumparse && ch_cur != '\0' && ch_cur != '_') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the alpha and '_' characters after the number */
|
||||||
|
for ( ; ; ++p_cur) {
|
||||||
|
const char ch_cur = *p_cur;
|
||||||
|
if (!isalpha(ch_cur) && ch_cur != '_') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return results */
|
||||||
|
{
|
||||||
|
/* Value of number. Ternary operator used to prevent avoidable
|
||||||
|
* calls to pow(). */
|
||||||
|
const double val = *p_val = mant *
|
||||||
|
(expo == 0.0 ? 1.0 : pow(10.0, expo));
|
||||||
|
*p_str = (char *) p_cur; /* updated location in string */
|
||||||
|
|
||||||
|
if (ft_parsedb) { /* diagnostics for parsing the number */
|
||||||
|
fprintf(cp_err, "numparse: got %e, left = \"%s\"\n",
|
||||||
|
val, p_cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test if the number can be represented as an intger */
|
||||||
|
return (double) (int) val == val;
|
||||||
|
}
|
||||||
|
} /* end of function ft_numparse */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This function converts the string form of a decimal number at *p_str to
|
||||||
|
* its value and returns it in *p_val. The location in *p_str is advanced
|
||||||
|
* to the first character after the number if the conversion is OK and
|
||||||
|
* is unchanged otherwise.
|
||||||
|
*
|
||||||
|
* Return codes
|
||||||
|
* -1: Conversion failure. *p_val is unchanged
|
||||||
|
* 0: Conversion OK. The string was not the representation of an integer
|
||||||
|
* +1: Conversion OK. The string was an integer */
|
||||||
|
static int get_decimal_number(const char **p_str, double *p_val)
|
||||||
|
{
|
||||||
|
double sign = 1.0; /* default sign multiplier if missing is 1.0 */
|
||||||
|
const char *p_cur = *p_str;
|
||||||
|
char ch_cur = *p_cur; /* 1st char */
|
||||||
|
bool f_is_integer = TRUE; /* assume integer */
|
||||||
|
|
||||||
|
/* Test for a sign */
|
||||||
|
if (ch_cur == '+') { /* Advance position in string. Sign unchanged */
|
||||||
|
ch_cur = *++p_cur;
|
||||||
|
}
|
||||||
|
else if (ch_cur == '-') { /* Advance position in string. Sign = -1 */
|
||||||
|
ch_cur = *++p_cur;
|
||||||
|
sign = -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure string either starts with a digit or a decimal point followed
|
||||||
|
* by a digit */
|
||||||
|
if ((!isdigit(ch_cur) && ch_cur != '.') ||
|
||||||
|
((ch_cur == '.') && !isdigit(p_cur[1]))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse and compute the number. Assuming 0-9 digits are contiguous and
|
||||||
|
* increasing in char representation (true for ASCII and EBCDIC) */
|
||||||
|
double val = 0.0;
|
||||||
|
for ( ; ; p_cur++) {
|
||||||
|
const unsigned int digit =
|
||||||
|
(unsigned int) *p_cur - (unsigned int) '0';
|
||||||
|
if (digit > 9) { /* not digit */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
val = val * 10.0 + (double) digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle fraction, if any */
|
||||||
|
if (*p_cur == '.') {
|
||||||
|
const char *p0 = ++p_cur; /* start of fraction */
|
||||||
|
double numerator = 0.0;
|
||||||
|
|
||||||
|
/* Not an integer expression (even if no fraction after the '.') */
|
||||||
|
f_is_integer = FALSE;
|
||||||
|
|
||||||
|
/* Add the fractional part of the number */
|
||||||
|
for ( ; ; p_cur++) {
|
||||||
|
const unsigned int digit =
|
||||||
|
(unsigned int) *p_cur - (unsigned int) '0';
|
||||||
|
if (digit > 9) { /* not digit */
|
||||||
|
/* Add fractional part to intergral part from earlier */
|
||||||
|
val += numerator * pow(10, (double) (p0 - p_cur));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numerator = numerator * 10.0 + (double) digit;
|
||||||
|
}
|
||||||
|
} /* end of case of fraction */
|
||||||
|
|
||||||
|
/* Return the value and update the position in the string */
|
||||||
|
*p_val = sign * val;
|
||||||
|
*p_str = p_cur;
|
||||||
|
return (int) f_is_integer;
|
||||||
|
} /* end of function get_decimal_number */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ static bool sameflag;
|
||||||
static double *
|
static double *
|
||||||
getlims(wordlist *wl, char *name, int number)
|
getlims(wordlist *wl, char *name, int number)
|
||||||
{
|
{
|
||||||
double *d;
|
|
||||||
wordlist *beg, *wk;
|
wordlist *beg, *wk;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
|
@ -43,39 +42,35 @@ getlims(wordlist *wl, char *name, int number)
|
||||||
|
|
||||||
wk = beg->wl_next;
|
wk = beg->wl_next;
|
||||||
|
|
||||||
d = TMALLOC(double, number);
|
double * const d = TMALLOC(double, number); /* alloc for returned vals */
|
||||||
|
|
||||||
for (n = 0; n < number; n++) {
|
for (n = 0; n < number; n++) {
|
||||||
|
|
||||||
char *ss;
|
char *ss;
|
||||||
double *td;
|
|
||||||
|
|
||||||
if (!wk) {
|
if (!wk) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Syntax error: not enough parameters for \"%s\".\n", name);
|
"Syntax error: not enough parameters for \"%s\".\n", name);
|
||||||
txfree(d);
|
txfree(d);
|
||||||
return NULL;
|
return (double *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ss = wk->wl_word;
|
ss = wk->wl_word;
|
||||||
td = ft_numparse(&ss, FALSE);
|
if (ft_numparse(&ss, FALSE, d + n) < 0) { /* put val in d[n] */
|
||||||
|
|
||||||
if (!td) {
|
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Syntax error: bad parameters for \"%s\".\n", name);
|
"Syntax error: bad parameters for \"%s\".\n", name);
|
||||||
txfree(d);
|
txfree(d);
|
||||||
return NULL;
|
return (double *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
d[n] = *td;
|
|
||||||
|
|
||||||
wk = wk->wl_next;
|
wk = wk->wl_next;
|
||||||
}
|
} /* end of loop over numbers */
|
||||||
|
|
||||||
wl_delete_slice(beg, wk);
|
wl_delete_slice(beg, wk); /* remove param name and its value nodes */
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
} /* end of function getlims */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Extend a data vector to length by replicating the last element, or
|
/* Extend a data vector to length by replicating the last element, or
|
||||||
|
|
|
||||||
|
|
@ -444,8 +444,9 @@ com_write(wordlist *wl)
|
||||||
else
|
else
|
||||||
names = ft_getpnames(&all, TRUE);
|
names = ft_getpnames(&all, TRUE);
|
||||||
|
|
||||||
if (names == NULL)
|
if (names == NULL) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (pn = names; pn; pn = pn->pn_next) {
|
for (pn = names; pn; pn = pn->pn_next) {
|
||||||
d = ft_evaluate(pn);
|
d = ft_evaluate(pn);
|
||||||
|
|
@ -731,22 +732,27 @@ com_transpose(wordlist *wl)
|
||||||
struct dvec *d;
|
struct dvec *d;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
while (wl) {
|
/* For each vector named in the wordlist, perform the transform to
|
||||||
|
* it and the vectors associated with it through v_link2 */
|
||||||
|
for ( ; wl != (wordlist *) NULL; wl = wl->wl_next) {
|
||||||
s = cp_unquote(wl->wl_word);
|
s = cp_unquote(wl->wl_word);
|
||||||
d = vec_get(s);
|
d = vec_get(s);
|
||||||
tfree(s); /*DG: Avoid Memory Leak */
|
tfree(s); /*DG: Avoid Memory Leak */
|
||||||
if (d == NULL)
|
if (d == NULL) {
|
||||||
|
/* Print error message, but continue with other vectors */
|
||||||
fprintf(cp_err, "Error: no such vector as %s.\n", wl->wl_word);
|
fprintf(cp_err, "Error: no such vector as %s.\n", wl->wl_word);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
|
/* Transpose the named vector and vectors tied to it
|
||||||
|
* through v_link2 */
|
||||||
while (d) {
|
while (d) {
|
||||||
vec_transpose(d);
|
vec_transpose(d);
|
||||||
d = d->v_link2;
|
d = d->v_link2;
|
||||||
}
|
}
|
||||||
if (wl->wl_next == NULL)
|
|
||||||
return;
|
|
||||||
wl = wl->wl_next;
|
|
||||||
}
|
}
|
||||||
}
|
} /* end of loop over words in wordlist */
|
||||||
|
} /* end of function com_transpose */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Take a set of vectors and form a new vector of the nth elements of each. */
|
/* Take a set of vectors and form a new vector of the nth elements of each. */
|
||||||
|
|
@ -758,19 +764,23 @@ com_cross(wordlist *wl)
|
||||||
struct pnode *pn, *names;
|
struct pnode *pn, *names;
|
||||||
int i, ind;
|
int i, ind;
|
||||||
bool comp = FALSE;
|
bool comp = FALSE;
|
||||||
double *d;
|
|
||||||
|
|
||||||
newvec = wl->wl_word;
|
newvec = wl->wl_word;
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
if ((d = ft_numparse(&s, FALSE)) == NULL) {
|
|
||||||
fprintf(cp_err, "Error: bad number %s\n", wl->wl_word);
|
{
|
||||||
|
double val;
|
||||||
|
if (ft_numparse(&s, FALSE, &val) <= 0) {
|
||||||
|
fprintf(cp_err, "Error: bad index value %s\n", wl->wl_word);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((ind = (int)*d) < 0) {
|
if ((ind = (int) val) < 0) {
|
||||||
fprintf(cp_err, "Error: badstrchr %d\n", ind);
|
fprintf(cp_err, "Error: badstrchr %d\n", ind);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
names = ft_getpnames(wl, TRUE);
|
names = ft_getpnames(wl, TRUE);
|
||||||
for (pn = names; pn; pn = pn->pn_next) {
|
for (pn = names; pn; pn = pn->pn_next) {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ com_spec(wordlist *wl)
|
||||||
{
|
{
|
||||||
ngcomplex_t **fdvec = NULL;
|
ngcomplex_t **fdvec = NULL;
|
||||||
double **tdvec = NULL;
|
double **tdvec = NULL;
|
||||||
double *freq, *win = NULL, *time, *dc = NULL;
|
double *win = NULL, *time, *dc = NULL;
|
||||||
double startf, stopf, stepf, span;
|
double startf, stopf, stepf, span;
|
||||||
int fpts, i, j, k, tlen, ngood;
|
int fpts, i, j, k, tlen, ngood;
|
||||||
bool trace;
|
bool trace;
|
||||||
|
|
@ -45,27 +45,24 @@ com_spec(wordlist *wl)
|
||||||
|
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
tlen = (plot_cur->pl_scale)->v_length;
|
tlen = (plot_cur->pl_scale)->v_length;
|
||||||
if ((freq = ft_numparse(&s, FALSE)) == NULL || (*freq < 0.0)) {
|
if (ft_numparse(&s, FALSE, &startf) < 0 || startf < 0.0) {
|
||||||
fprintf(cp_err, "Error: bad start freq %s\n", wl->wl_word);
|
fprintf(cp_err, "Error: bad start freq %s\n", wl->wl_word);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
startf = *freq;
|
|
||||||
|
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
if ((freq = ft_numparse(&s, FALSE)) == NULL || (*freq <= startf)) {
|
if (ft_numparse(&s, FALSE, &stopf) < 0 || stopf <= startf) {
|
||||||
fprintf(cp_err, "Error: bad stop freq %s\n", wl->wl_word);
|
fprintf(cp_err, "Error: bad stop freq %s\n", wl->wl_word);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
stopf = *freq;
|
|
||||||
|
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
s = wl->wl_word;
|
s = wl->wl_word;
|
||||||
if ((freq = ft_numparse(&s, FALSE)) == NULL || !(*freq <= (stopf-startf))) {
|
if (ft_numparse(&s, FALSE, &stepf) < 0 || stepf > stopf - startf) {
|
||||||
fprintf(cp_err, "Error: bad step freq %s\n", wl->wl_word);
|
fprintf(cp_err, "Error: bad step freq %s\n", wl->wl_word);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
stepf = *freq;
|
|
||||||
|
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
time = (plot_cur->pl_scale)->v_realdata;
|
time = (plot_cur->pl_scale)->v_realdata;
|
||||||
|
|
@ -212,7 +209,6 @@ com_spec(wordlist *wl)
|
||||||
VF_REAL | VF_PERMANENT | VF_PRINT,
|
VF_REAL | VF_PERMANENT | VF_PRINT,
|
||||||
fpts, NULL);
|
fpts, NULL);
|
||||||
vec_new(f);
|
vec_new(f);
|
||||||
freq = f->v_realdata;
|
|
||||||
|
|
||||||
tdvec = TMALLOC(double *, ngood);
|
tdvec = TMALLOC(double *, ngood);
|
||||||
fdvec = TMALLOC(ngcomplex_t *, ngood);
|
fdvec = TMALLOC(ngcomplex_t *, ngood);
|
||||||
|
|
@ -238,10 +234,14 @@ com_spec(wordlist *wl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace = cp_getvar("spectrace", CP_BOOL, NULL, 0);
|
trace = cp_getvar("spectrace", CP_BOOL, NULL, 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
double * const freq = f->v_realdata;
|
||||||
for (j = (startf == 0 ? 1 : 0); j < fpts; j++) {
|
for (j = (startf == 0 ? 1 : 0); j < fpts; j++) {
|
||||||
freq[j] = startf + j*stepf;
|
freq[j] = startf + j*stepf;
|
||||||
if (trace)
|
if (trace) {
|
||||||
fprintf(cp_err, "spec: %e Hz: \r", freq[j]);
|
fprintf(cp_err, "spec: %e Hz: \r", freq[j]);
|
||||||
|
}
|
||||||
for (i = 0; i < ngood; i++) {
|
for (i = 0; i < ngood; i++) {
|
||||||
fdvec[i][j].cx_real = 0;
|
fdvec[i][j].cx_real = 0;
|
||||||
fdvec[i][j].cx_imag = 0;
|
fdvec[i][j].cx_imag = 0;
|
||||||
|
|
@ -270,6 +270,7 @@ com_spec(wordlist *wl)
|
||||||
fdvec[i][0].cx_imag = 0;
|
fdvec[i][0].cx_imag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
fprintf(cp_err, " \r");
|
fprintf(cp_err, " \r");
|
||||||
|
|
|
||||||
|
|
@ -77,11 +77,13 @@ wordlist *cp_varwl(struct variable *var)
|
||||||
}
|
}
|
||||||
|
|
||||||
return wl_cons(buf, NULL);
|
return wl_cons(buf, NULL);
|
||||||
}
|
} /* end of function cp_varwl */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Set a variable. */
|
/* Set a variable. */
|
||||||
void cp_vset(const char *varname, enum cp_types type, const void *value)
|
void cp_vset(const char *varname, enum cp_types type,
|
||||||
|
const void *value)
|
||||||
{
|
{
|
||||||
struct variable *v, *u, *w;
|
struct variable *v, *u, *w;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -387,14 +389,12 @@ static void update_option_variables(const char *sz_var_name,
|
||||||
Generate variables (real, string or list)
|
Generate variables (real, string or list)
|
||||||
Value in double quotes will always become string variable.
|
Value in double quotes will always become string variable.
|
||||||
Without quotes tokens like 2N5401_C will be evaluated as real number 2n, i.e. 2e-9 */
|
Without quotes tokens like 2N5401_C will be evaluated as real number 2n, i.e. 2e-9 */
|
||||||
struct variable *
|
struct variable *cp_setparse(wordlist *wl)
|
||||||
cp_setparse(wordlist *wl)
|
|
||||||
{
|
{
|
||||||
char *name = NULL, *val, *copyval, *s, *ss;
|
char *name = NULL, *val, *copyval, *s, *ss;
|
||||||
double *td;
|
|
||||||
struct variable *listv = NULL, *vv, *lv = NULL;
|
struct variable *listv = NULL, *vv, *lv = NULL;
|
||||||
struct variable *vars = NULL;
|
struct variable *vars = NULL;
|
||||||
int balance;
|
|
||||||
/* Step through the list of words. Words may be various combinations of
|
/* Step through the list of words. Words may be various combinations of
|
||||||
* the information needed to set a variable. For example, to set x to
|
* the information needed to set a variable. For example, to set x to
|
||||||
* the value 3, the data could be supplied as one word x=3, two words
|
* the value 3, the data could be supplied as one word x=3, two words
|
||||||
|
|
@ -415,21 +415,22 @@ cp_setparse(wordlist *wl)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl && eq(wl->wl_word, "=")) {
|
if (wl && eq(wl->wl_word, "=")) { /* name<space>= */
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
if (wl == NULL) {
|
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*/
|
tfree(name); /*DG: cp_unquote Memory leak*/
|
||||||
if (ft_stricterror)
|
if (ft_stricterror)
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
val = wl->wl_word;
|
val = wl->wl_word;
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
} else if (wl && (*wl->wl_word == '=')) {
|
} else if (wl && (*wl->wl_word == '=')) { /* name<space>=val */
|
||||||
val = wl->wl_word + 1;
|
val = wl->wl_word + 1;
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
} else if ((s = strchr(name, '=')) != NULL) {
|
} else if ((s = strchr(name, '=')) != NULL) {
|
||||||
|
/* name=<space>value or name=value */
|
||||||
val = s + 1;
|
val = s + 1;
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
if (*val == '\0') {
|
if (*val == '\0') {
|
||||||
|
|
@ -438,18 +439,19 @@ cp_setparse(wordlist *wl)
|
||||||
tfree(name); /*DG: cp_unquote Memory leak: free name before exiting*/
|
tfree(name); /*DG: cp_unquote Memory leak: free name before exiting*/
|
||||||
if (ft_stricterror)
|
if (ft_stricterror)
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return (NULL);
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
val = wl->wl_word;
|
val = wl->wl_word;
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
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 */
|
tfree(name); /*DG: cp_unquote Memory leak: free name befor exiting */
|
||||||
if (ft_stricterror)
|
if (ft_stricterror)
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if val is in double quotes, treat as string */
|
/* if val is in double quotes, treat as string */
|
||||||
|
|
@ -463,11 +465,12 @@ cp_setparse(wordlist *wl)
|
||||||
strcpy(val, copyval);
|
strcpy(val, copyval);
|
||||||
tfree(copyval);
|
tfree(copyval);
|
||||||
|
|
||||||
|
/* Test for a list variable */
|
||||||
if (eq(val, "(")) {
|
if (eq(val, "(")) {
|
||||||
/* The beginning of a list... We have to walk down the
|
/* The beginning of a list... We have to walk down the
|
||||||
* list until we find a close paren... If there are nested
|
* list until we find a close paren... If there are nested
|
||||||
* ()'s, treat them as tokens... */
|
* ()'s, treat them as tokens... */
|
||||||
balance = 1;
|
int balance = 1;
|
||||||
while (wl && wl->wl_word) {
|
while (wl && wl->wl_word) {
|
||||||
if (eq(wl->wl_word, "(")) {
|
if (eq(wl->wl_word, "(")) {
|
||||||
balance++;
|
balance++;
|
||||||
|
|
@ -481,12 +484,14 @@ cp_setparse(wordlist *wl)
|
||||||
vv = var_alloc_string(NULL, copy(ss), NULL);
|
vv = var_alloc_string(NULL, copy(ss), NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
td = ft_numparse(&ss, FALSE);
|
double dbl_val;
|
||||||
if (td)
|
if (ft_numparse(&ss, FALSE, &dbl_val) >= 0) {
|
||||||
vv = var_alloc_real(NULL, *td, NULL);
|
vv = var_alloc_real(NULL, dbl_val, NULL);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
vv = var_alloc_string(NULL, copy(ss), NULL);
|
vv = var_alloc_string(NULL, copy(ss), NULL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tfree(copyval);
|
tfree(copyval);
|
||||||
if (listv) {
|
if (listv) {
|
||||||
lv->va_next = vv;
|
lv->va_next = vv;
|
||||||
|
|
@ -501,9 +506,10 @@ cp_setparse(wordlist *wl)
|
||||||
tfree(name); /* va: cp_unquote memory leak: free name before exiting */
|
tfree(name); /* va: cp_unquote memory leak: free name before exiting */
|
||||||
if (ft_stricterror)
|
if (ft_stricterror)
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add list variable to linked list of variables. */
|
||||||
vars = var_alloc_vlist(copy(name), listv, vars);
|
vars = var_alloc_vlist(copy(name), listv, vars);
|
||||||
|
|
||||||
wl = wl->wl_next;
|
wl = wl->wl_next;
|
||||||
|
|
@ -516,10 +522,10 @@ cp_setparse(wordlist *wl)
|
||||||
vars = var_alloc_string(copy(name), copy(copyval), vars);
|
vars = var_alloc_string(copy(name), copy(copyval), vars);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
td = ft_numparse(&ss, FALSE);
|
double dbl_val;
|
||||||
if (td) {
|
if (ft_numparse(&ss, FALSE, &dbl_val) >= 0) {
|
||||||
/*** We should try to get CP_NUM's... */
|
/*** We should try to get CP_NUM's... */
|
||||||
vars = var_alloc_real(name, *td, vars);
|
vars = var_alloc_real(name, dbl_val, vars);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vars = var_alloc_string(name, copy(val), vars);
|
vars = var_alloc_string(name, copy(val), vars);
|
||||||
|
|
@ -532,8 +538,9 @@ cp_setparse(wordlist *wl)
|
||||||
if (name) {
|
if (name) {
|
||||||
tfree(name);
|
tfree(name);
|
||||||
}
|
}
|
||||||
return (vars);
|
return vars;
|
||||||
}
|
} /* end of function cp_setparse */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* free the struct variable. The type of the union is given by va_type */
|
/* free the struct variable. The type of the union is given by va_type */
|
||||||
|
|
@ -543,15 +550,15 @@ free_struct_variable(struct variable *v)
|
||||||
while (v) {
|
while (v) {
|
||||||
struct variable *next_v = v->va_next;
|
struct variable *next_v = v->va_next;
|
||||||
if (v->va_name)
|
if (v->va_name)
|
||||||
tfree(v->va_name);
|
txfree(v->va_name);
|
||||||
if (v->va_type == CP_LIST)
|
if (v->va_type == CP_LIST)
|
||||||
free_struct_variable(v->va_vlist);
|
free_struct_variable(v->va_vlist);
|
||||||
if (v->va_type == CP_STRING)
|
if (v->va_type == CP_STRING)
|
||||||
tfree(v->va_string);
|
txfree(v->va_string);
|
||||||
tfree(v);
|
txfree(v);
|
||||||
v = next_v;
|
v = next_v;
|
||||||
}
|
}
|
||||||
}
|
} /* end of function free_struct_variable */
|
||||||
|
|
||||||
|
|
||||||
void cp_remvar(char *varname)
|
void cp_remvar(char *varname)
|
||||||
|
|
@ -770,11 +777,19 @@ char cp_dol = '$';
|
||||||
/* Non-alphanumeric characters that may appear in variable names. < is very
|
/* Non-alphanumeric characters that may appear in variable names. < is very
|
||||||
* special...
|
* special...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VALIDCHARS "$-_<#?@.()[]&"
|
#define VALIDCHARS "$-_<#?@.()[]&"
|
||||||
|
|
||||||
char *
|
/* This function determines the first character after a variable name and
|
||||||
span_var_expr(char *t)
|
* returns its address.
|
||||||
|
*
|
||||||
|
* Parameter
|
||||||
|
* t: Address of the variable name whose end is to be found. This is the
|
||||||
|
* address of the first character following the leading $
|
||||||
|
*
|
||||||
|
* Return value
|
||||||
|
* Address of the first character after the variable name.
|
||||||
|
*/
|
||||||
|
char *span_var_expr(char *t)
|
||||||
{
|
{
|
||||||
int parenthesis = 0;
|
int parenthesis = 0;
|
||||||
int brackets = 0;
|
int brackets = 0;
|
||||||
|
|
@ -805,12 +820,11 @@ span_var_expr(char *t)
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
} /* end of function span_var_expr */
|
||||||
|
|
||||||
|
|
||||||
/* Substitute variable name by its value and restore to wordlist */
|
/* Substitute variable name by its value and restore to wordlist */
|
||||||
wordlist *
|
wordlist *cp_variablesubst(wordlist *wlist)
|
||||||
cp_variablesubst(wordlist *wlist)
|
|
||||||
{
|
{
|
||||||
wordlist *wl;
|
wordlist *wl;
|
||||||
|
|
||||||
|
|
@ -849,24 +863,26 @@ cp_variablesubst(wordlist *wlist)
|
||||||
tfree(x);
|
tfree(x);
|
||||||
} else {
|
} else {
|
||||||
wordlist *next = wl->wl_next;
|
wordlist *next = wl->wl_next;
|
||||||
if (wlist == wl)
|
if (wlist == wl) {
|
||||||
wlist = next;
|
wlist = next;
|
||||||
|
}
|
||||||
wl_delete_slice(wl, next);
|
wl_delete_slice(wl, next);
|
||||||
if (!next)
|
if (!next) { /* wordlist ends after wl */
|
||||||
return wlist;
|
return wlist;
|
||||||
|
}
|
||||||
wl = next;
|
wl = next;
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
} /* end of loop over parts of wordlist node */
|
||||||
}
|
} /* end of loop over words in wordlist */
|
||||||
|
|
||||||
|
return wlist;
|
||||||
|
} /* end of function cp_variablesubst */
|
||||||
|
|
||||||
return (wlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Evaluate a variable. */
|
/* Evaluate a variable. */
|
||||||
wordlist *
|
wordlist *vareval(/* NOT const */ char *string)
|
||||||
vareval(char *string)
|
|
||||||
{
|
{
|
||||||
struct variable *v, *vfree = NULL;
|
struct variable *v, *vfree = NULL;
|
||||||
wordlist *wl;
|
wordlist *wl;
|
||||||
|
|
@ -887,8 +903,8 @@ vareval(char *string)
|
||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
wl = wl_cons(tprintf("%d", getpid()), NULL);
|
wl = wl_cons(tprintf("%d", getpid()), NULL);
|
||||||
tfree(oldstring);
|
txfree(oldstring);
|
||||||
return (wl);
|
return wl;
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
(void) fflush(cp_out);
|
(void) fflush(cp_out);
|
||||||
|
|
@ -903,8 +919,8 @@ vareval(char *string)
|
||||||
/* This is a hack. */
|
/* This is a hack. */
|
||||||
if (!wl->wl_word)
|
if (!wl->wl_word)
|
||||||
wl->wl_word = copy("");
|
wl->wl_word = copy("");
|
||||||
tfree(oldstring);
|
txfree(oldstring);
|
||||||
return (wl);
|
return wl;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
string++;
|
string++;
|
||||||
|
|
@ -918,8 +934,8 @@ vareval(char *string)
|
||||||
}
|
}
|
||||||
wl = wl_cons(copy(v ? "1" : "0"), NULL);
|
wl = wl_cons(copy(v ? "1" : "0"), NULL);
|
||||||
free_struct_variable(vfree);
|
free_struct_variable(vfree);
|
||||||
tfree(oldstring);
|
txfree(oldstring);
|
||||||
return (wl);
|
return wl;
|
||||||
|
|
||||||
case '#':
|
case '#':
|
||||||
string++;
|
string++;
|
||||||
|
|
@ -933,23 +949,26 @@ vareval(char *string)
|
||||||
}
|
}
|
||||||
if (!v) {
|
if (!v) {
|
||||||
fprintf(cp_err, "Error: %s: no such variable.\n", string);
|
fprintf(cp_err, "Error: %s: no such variable.\n", string);
|
||||||
tfree(oldstring);
|
txfree(oldstring);
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
if (v->va_type == CP_LIST)
|
if (v->va_type == CP_LIST) {
|
||||||
for (v = v->va_vlist, i = 0; v; v = v->va_next)
|
for (v = v->va_vlist, i = 0; v; v = v->va_next) {
|
||||||
i++;
|
i++;
|
||||||
else
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
i = (v->va_type != CP_BOOL);
|
i = (v->va_type != CP_BOOL);
|
||||||
|
}
|
||||||
wl = wl_cons(tprintf("%d", i), NULL);
|
wl = wl_cons(tprintf("%d", i), NULL);
|
||||||
tfree(oldstring);
|
txfree(oldstring);
|
||||||
free_struct_variable(vfree);
|
free_struct_variable(vfree);
|
||||||
return (wl);
|
return wl;
|
||||||
|
|
||||||
case '\0':
|
case '\0':
|
||||||
wl = wl_cons(copy("$"), NULL);
|
wl = wl_cons(copy("$"), NULL);
|
||||||
tfree(oldstring);
|
txfree(oldstring);
|
||||||
return (wl);
|
return wl;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfree = NULL; //just in case ...
|
vfree = NULL; //just in case ...
|
||||||
|
|
@ -980,8 +999,8 @@ vareval(char *string)
|
||||||
}
|
}
|
||||||
if (!v) {
|
if (!v) {
|
||||||
fprintf(cp_err, "Error: %s: no such variable.\n", string);
|
fprintf(cp_err, "Error: %s: no such variable.\n", string);
|
||||||
tfree(oldstring);
|
txfree(oldstring);
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
wl = cp_varwl(v);
|
wl = cp_varwl(v);
|
||||||
free_struct_variable(vfree);
|
free_struct_variable(vfree);
|
||||||
|
|
@ -1000,7 +1019,7 @@ vareval(char *string)
|
||||||
r = vareval(range);
|
r = vareval(range);
|
||||||
if (!r || r->wl_next) {
|
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);
|
txfree(oldstring);
|
||||||
wl_free(r);
|
wl_free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1018,8 +1037,9 @@ vareval(char *string)
|
||||||
up--, low--;
|
up--, low--;
|
||||||
wl = wl_range(wl, low, up);
|
wl = wl_range(wl, low, up);
|
||||||
wl_free(r);
|
wl_free(r);
|
||||||
}
|
} /* end of case of range given for variable */
|
||||||
tfree(oldstring);
|
|
||||||
|
txfree(oldstring);
|
||||||
return (wl);
|
return (wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,7 @@ Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||||
#define ngspice_CPSTD_H
|
#define ngspice_CPSTD_H
|
||||||
|
|
||||||
|
|
||||||
#ifndef FILE
|
#include <stdio.h>
|
||||||
/* XXX Bogus */
|
|
||||||
# include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* FIXME: Split this file and adjust all callers to use new header files */
|
/* FIXME: Split this file and adjust all callers to use new header files */
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -23,6 +20,7 @@ Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ngspice/bool.h"
|
#include "ngspice/bool.h"
|
||||||
|
#include "ngspice/dstring.h"
|
||||||
#include "ngspice/wordlist.h"
|
#include "ngspice/wordlist.h"
|
||||||
#include "ngspice/complex.h"
|
#include "ngspice/complex.h"
|
||||||
|
|
||||||
|
|
@ -30,8 +28,12 @@ Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||||
|
|
||||||
extern char *tildexpand(char *string);
|
extern char *tildexpand(char *string);
|
||||||
extern void printnum(char *buf, double num);
|
extern void printnum(char *buf, double num);
|
||||||
|
int printnum_ds(DSTRING *p_ds, double num);
|
||||||
extern int cp_numdgt;
|
extern int cp_numdgt;
|
||||||
|
|
||||||
extern void cp_printword(char *string, FILE *fp);
|
extern void cp_printword(char *string, FILE *fp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ extern void ft_polyderiv(double *coeffs, int degree);
|
||||||
/* numparse.c */
|
/* numparse.c */
|
||||||
|
|
||||||
extern bool ft_strictnumparse;
|
extern bool ft_strictnumparse;
|
||||||
double *ft_numparse(char **s, bool whole);
|
int ft_numparse(char **s, bool whole, double *p_val);
|
||||||
|
|
||||||
/* options.c */
|
/* options.c */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,49 @@ Modified: 2001 Paolo Nenzi
|
||||||
* It is up to the caller to allocate space for strings.
|
* It is up to the caller to allocate space for strings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "printnum.h"
|
#include "printnum.h"
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int cp_numdgt = -1;
|
int cp_numdgt = -1;
|
||||||
|
|
||||||
void printnum(char *buf, double num)
|
|
||||||
|
static inline int get_num_width(double num)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (cp_numdgt > 1)
|
if (cp_numdgt > 1) {
|
||||||
n = cp_numdgt;
|
n = cp_numdgt;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
n = 6;
|
n = 6;
|
||||||
if (num < 0.0)
|
}
|
||||||
|
if (num < 0.0 && n > 1) {
|
||||||
n--;
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
} /* end of function get_num_width */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This funtion writes num to buf. It can cause buffer overruns. The size of
|
||||||
|
* buf is unknown, so cp_numdgt can be large enough to cause sprintf()
|
||||||
|
* to write past the end of the array. */
|
||||||
|
void printnum(char *buf, double num)
|
||||||
|
{
|
||||||
|
int n = get_num_width(num);
|
||||||
(void) sprintf(buf, "%.*e", n, num);
|
(void) sprintf(buf, "%.*e", n, num);
|
||||||
|
} /* end of function printnum */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int printnum_ds(DSTRING *p_ds, double num)
|
||||||
|
{
|
||||||
|
const int n = get_num_width(num);
|
||||||
|
return ds_cat_printf(p_ds, "%.*e", n, num);
|
||||||
|
} /* end of function printnum_ds */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
#ifndef ngspice_PRINTNUM_H
|
#ifndef ngspice_PRINTNUM_H
|
||||||
#define ngspice_PRINTNUM_H
|
#define ngspice_PRINTNUM_H
|
||||||
|
|
||||||
void printnum(char * buf, double num);
|
#include "ngspice/dstring.h"
|
||||||
|
|
||||||
|
void printnum(char *buf, double num);
|
||||||
|
int printnum_ds(DSTRING *p_dstring, double num);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue