2000-04-27 22:03:57 +02:00
|
|
|
/**********
|
|
|
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
2012-09-20 20:30:53 +02:00
|
|
|
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
2000-04-27 22:03:57 +02:00
|
|
|
**********/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Various post-processor commands having to do with vectors.
|
|
|
|
|
*/
|
|
|
|
|
|
2011-12-11 19:05:00 +01:00
|
|
|
#include "ngspice/ngspice.h"
|
|
|
|
|
#include "ngspice/cpdefs.h"
|
|
|
|
|
#include "ngspice/ftedefs.h"
|
|
|
|
|
#include "ngspice/dvec.h"
|
|
|
|
|
#include "ngspice/sim.h"
|
|
|
|
|
#include "ngspice/plot.h"
|
|
|
|
|
#include "ngspice/graph.h"
|
|
|
|
|
#include "ngspice/ftedbgra.h"
|
2010-10-16 19:09:46 +02:00
|
|
|
#include "com_display.h"
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2000-05-06 16:12:51 +02:00
|
|
|
#include "completion.h"
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
#include "postcoms.h"
|
|
|
|
|
#include "quote.h"
|
2000-06-27 18:09:02 +02:00
|
|
|
#include "variable.h"
|
2003-07-23 21:36:39 +02:00
|
|
|
#include "parser/complete.h" /* va: throwaway */
|
2012-09-21 21:15:41 +02:00
|
|
|
#include "plotting/plotting.h"
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
static void killplot(struct plot *pl);
|
2009-02-10 20:00:24 +01:00
|
|
|
static void DelPlotWindows(struct plot *pl);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
void
|
|
|
|
|
com_unlet(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
while (wl) {
|
|
|
|
|
vec_remove(wl->wl_word);
|
|
|
|
|
wl = wl->wl_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Load in a file. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
com_load(wordlist *wl)
|
|
|
|
|
{
|
2012-09-20 20:30:53 +02:00
|
|
|
char *copypath;
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!wl)
|
|
|
|
|
ft_loadfile(ft_rawfile);
|
|
|
|
|
else
|
|
|
|
|
while (wl) {
|
2000-10-26 19:02:12 +02:00
|
|
|
/*ft_loadfile(cp_unquote(wl->wl_word)); DG: bad memory leak*/
|
2012-09-20 20:30:53 +02:00
|
|
|
copypath = cp_unquote(wl->wl_word);/*DG*/
|
2000-10-26 19:02:12 +02:00
|
|
|
ft_loadfile(copypath);
|
|
|
|
|
tfree(copypath);
|
2000-04-27 22:03:57 +02:00
|
|
|
wl = wl->wl_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* note: default is to display the vectors in the last (current) plot */
|
|
|
|
|
com_display(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Print out the value of an expression. When we are figuring out what to
|
|
|
|
|
* print, link the vectors we want with v_link2... This has to be done
|
|
|
|
|
* because of the way temporary vectors are linked together with permanent
|
|
|
|
|
* ones under the plot.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
com_print(wordlist *wl)
|
|
|
|
|
{
|
2001-04-15 12:11:04 +02:00
|
|
|
struct dvec *v, *lv = NULL, *bv, *nv, *vecs = NULL;
|
2000-04-27 22:03:57 +02:00
|
|
|
int i, j, ll, width = DEF_WIDTH, height = DEF_HEIGHT, npoints, lineno;
|
2012-10-01 17:59:40 +02:00
|
|
|
struct pnode *pn, *names;
|
2000-04-27 22:03:57 +02:00
|
|
|
struct plot *p;
|
|
|
|
|
bool col = TRUE, nobreak = FALSE, noprintscale, plotnames = FALSE;
|
|
|
|
|
bool optgiven = FALSE;
|
2012-09-20 20:30:53 +02:00
|
|
|
char *s, *buf, *buf2; /*, buf[BSIZE_SP], buf2[BSIZE_SP];*/
|
2001-12-02 21:12:56 +01:00
|
|
|
char numbuf[BSIZE_SP], numbuf2[BSIZE_SP]; /* Printnum buffers */
|
2000-04-27 22:03:57 +02:00
|
|
|
int ngood;
|
|
|
|
|
|
|
|
|
|
if (wl == NULL)
|
|
|
|
|
return;
|
2011-01-12 18:49:18 +01:00
|
|
|
|
|
|
|
|
buf = TMALLOC(char, BSIZE_SP);
|
2012-09-20 20:30:53 +02:00
|
|
|
buf2 = TMALLOC(char, BSIZE_SP);
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (eq(wl->wl_word, "col")) {
|
|
|
|
|
col = TRUE;
|
|
|
|
|
optgiven = TRUE;
|
|
|
|
|
wl = wl->wl_next;
|
|
|
|
|
} else if (eq(wl->wl_word, "line")) {
|
|
|
|
|
col = FALSE;
|
|
|
|
|
optgiven = TRUE;
|
|
|
|
|
wl = wl->wl_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngood = 0;
|
2012-10-01 17:53:01 +02:00
|
|
|
names = ft_getpnames(wl, TRUE);
|
2012-10-01 17:59:40 +02:00
|
|
|
for (pn = names; pn; pn = pn->pn_next) {
|
|
|
|
|
if ((v = ft_evaluate(pn)) == NULL)
|
2011-01-12 18:49:18 +01:00
|
|
|
continue;
|
|
|
|
|
if (!vecs)
|
|
|
|
|
vecs = lv = v;
|
|
|
|
|
else
|
|
|
|
|
lv->v_link2 = v;
|
|
|
|
|
for (lv = v; lv->v_link2; lv = lv->v_link2)
|
|
|
|
|
;
|
|
|
|
|
ngood += 1;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ngood)
|
2011-01-12 18:49:18 +01:00
|
|
|
goto done;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* See whether we really have to print plot names. */
|
|
|
|
|
for (v = vecs; v; v = v->v_link2)
|
|
|
|
|
if (vecs->v_plot != v->v_plot) {
|
|
|
|
|
plotnames = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!optgiven) {
|
|
|
|
|
/* Figure out whether col or line should be used... */
|
|
|
|
|
col = FALSE;
|
|
|
|
|
for (v = vecs; v; v = v->v_link2)
|
|
|
|
|
if (v->v_length > 1) {
|
|
|
|
|
col = TRUE;
|
2009-01-15 23:16:32 +01:00
|
|
|
/* Improvement made to print cases @[sin] = (0 12 13 100K) */
|
2012-09-20 20:30:53 +02:00
|
|
|
if ((v->v_plot->pl_scale && v->v_length != v->v_plot->pl_scale->v_length) && (*(v->v_name) == '@'))
|
2009-01-15 23:16:32 +01:00
|
|
|
{
|
2011-01-12 18:49:18 +01:00
|
|
|
col = FALSE;
|
2009-01-15 23:16:32 +01:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
/* With this I have found that the vector has less elements than the SCALE vector
|
|
|
|
|
* in the linked PLOT. But now I must make sure in case of a print @vin[sin] or
|
|
|
|
|
* @vin[pulse]
|
|
|
|
|
* for it appear that the v->v_name begins with '@'
|
|
|
|
|
* And then be in this case.
|
|
|
|
|
*/
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out_init();
|
|
|
|
|
if (!col) {
|
|
|
|
|
for (v = vecs; v; v = v->v_link2) {
|
2012-10-17 19:51:30 +02:00
|
|
|
char *basename = vec_basename(v);
|
2012-09-20 20:30:53 +02:00
|
|
|
if (plotnames)
|
2012-10-17 19:51:30 +02:00
|
|
|
(void) sprintf(buf, "%s.%s", v->v_plot->pl_typename, basename);
|
2012-09-20 20:30:53 +02:00
|
|
|
else
|
2012-10-17 19:51:30 +02:00
|
|
|
(void) strcpy(buf, basename);
|
|
|
|
|
tfree(basename);
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
for (s = buf; *s; s++)
|
|
|
|
|
;
|
|
|
|
|
s--;
|
|
|
|
|
while (isspace(*s)) {
|
|
|
|
|
*s = '\0';
|
|
|
|
|
s--;
|
|
|
|
|
}
|
|
|
|
|
ll = 10;
|
2009-01-15 23:16:32 +01:00
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
/* v->v_rlength = 1 when it comes to make a print @ M1 and does not want to come out on screen
|
|
|
|
|
* Multiplier factor [m]=1
|
|
|
|
|
* @M1 = 0,00e+00
|
|
|
|
|
* In any other case rlength not used for anything and only applies in the copy of the vectors.
|
|
|
|
|
*/
|
|
|
|
|
if (v->v_rlength == 0) {
|
|
|
|
|
if (v->v_length == 1) {
|
|
|
|
|
if (isreal(v)) {
|
2011-01-12 18:49:18 +01:00
|
|
|
printnum(numbuf, *v->v_realdata);
|
|
|
|
|
out_printf("%s = %s\n", buf, numbuf);
|
2000-04-27 22:03:57 +02:00
|
|
|
} else {
|
2012-09-20 20:30:53 +02:00
|
|
|
printnum(numbuf, realpart(v->v_compdata[0]));
|
2012-02-07 20:53:12 +01:00
|
|
|
printnum(numbuf2, imagpart(v->v_compdata[0]));
|
2012-09-20 20:30:53 +02:00
|
|
|
out_printf("%s = %s,%s\n", buf, numbuf, numbuf2);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2011-01-12 18:49:18 +01:00
|
|
|
} else {
|
|
|
|
|
out_printf("%s = ( ", buf);
|
|
|
|
|
for (i = 0; i < v->v_length; i++)
|
|
|
|
|
if (isreal(v)) {
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2011-01-12 18:49:18 +01:00
|
|
|
printnum(numbuf, v->v_realdata[i]);
|
|
|
|
|
(void) strcpy(buf, numbuf);
|
|
|
|
|
out_send(buf);
|
|
|
|
|
ll += (int) strlen(buf);
|
|
|
|
|
ll = (ll + 7) / 8;
|
|
|
|
|
ll = ll * 8 + 1;
|
|
|
|
|
if (ll > 60) {
|
|
|
|
|
out_send("\n\t");
|
|
|
|
|
ll = 9;
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2011-01-12 18:49:18 +01:00
|
|
|
out_send("\t");
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2011-01-12 18:49:18 +01:00
|
|
|
} else {
|
2012-09-20 20:30:53 +02:00
|
|
|
/*DG*/
|
|
|
|
|
printnum(numbuf, realpart(v->v_compdata[i]));
|
2012-02-07 20:53:12 +01:00
|
|
|
printnum(numbuf2, imagpart(v->v_compdata[i]));
|
2012-09-20 20:30:53 +02:00
|
|
|
(void) sprintf(buf, "%s,%s", numbuf, numbuf2);
|
2011-01-12 18:49:18 +01:00
|
|
|
out_send(buf);
|
|
|
|
|
ll += (int) strlen(buf);
|
|
|
|
|
ll = (ll + 7) / 8;
|
|
|
|
|
ll = ll * 8 + 1;
|
|
|
|
|
if (ll > 60) {
|
|
|
|
|
out_send("\n\t");
|
|
|
|
|
ll = 9;
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2011-01-12 18:49:18 +01:00
|
|
|
out_send("\t");
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2011-01-12 18:49:18 +01:00
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
out_send(")\n");
|
2011-01-12 18:49:18 +01:00
|
|
|
} //end if (v->v_length == 1)
|
|
|
|
|
} //end if (v->v_rlength == 1)
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
} else { /* Print in columns. */
|
2011-04-30 14:29:19 +02:00
|
|
|
if (cp_getvar("width", CP_NUM, &i))
|
2000-04-27 22:03:57 +02:00
|
|
|
width = i;
|
|
|
|
|
if (width < 40)
|
|
|
|
|
width = 40;
|
2012-09-20 20:30:53 +02:00
|
|
|
if (width > BSIZE_SP - 2) {
|
2011-01-12 18:49:18 +01:00
|
|
|
buf = TREALLOC(char, buf, width + 1);
|
2012-09-20 20:30:53 +02:00
|
|
|
buf2 = TREALLOC(char, buf2, width + 1);
|
|
|
|
|
}
|
2011-04-30 14:29:19 +02:00
|
|
|
if (cp_getvar("height", CP_NUM, &i))
|
2000-04-27 22:03:57 +02:00
|
|
|
height = i;
|
|
|
|
|
if (height < 20)
|
|
|
|
|
height = 20;
|
2010-07-20 20:52:19 +02:00
|
|
|
nobreak = cp_getvar("nobreak", CP_BOOL, NULL);
|
|
|
|
|
if (!nobreak && !ft_nopage)
|
2000-04-27 22:03:57 +02:00
|
|
|
nobreak = FALSE;
|
2011-01-12 18:49:18 +01:00
|
|
|
else
|
|
|
|
|
nobreak = TRUE;
|
2010-07-20 20:52:19 +02:00
|
|
|
noprintscale = cp_getvar("noprintscale", CP_BOOL, NULL);
|
2000-04-27 22:03:57 +02:00
|
|
|
bv = vecs;
|
2012-09-20 20:30:53 +02:00
|
|
|
nextpage:
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Make the first vector of every page be the scale... */
|
2012-09-20 20:30:53 +02:00
|
|
|
/* XXX But what if there is no scale? e.g. op, pz */
|
|
|
|
|
if (!noprintscale && bv->v_plot->pl_ndims)
|
2000-04-27 22:03:57 +02:00
|
|
|
if (bv->v_plot->pl_scale && !vec_eq(bv, bv->v_plot->pl_scale)) {
|
|
|
|
|
nv = vec_copy(bv->v_plot->pl_scale);
|
|
|
|
|
vec_new(nv);
|
|
|
|
|
nv->v_link2 = bv;
|
|
|
|
|
bv = nv;
|
|
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
ll = 8;
|
|
|
|
|
for (lv = bv; lv; lv = lv->v_link2) {
|
|
|
|
|
if (isreal(lv))
|
|
|
|
|
ll += 16; /* Two tabs for real, */
|
|
|
|
|
else
|
|
|
|
|
ll += 32; /* 4 for complex. */
|
|
|
|
|
/* Make sure we have at least 2 vectors per page... */
|
|
|
|
|
if ((ll > width) && (lv != bv) && (lv != bv->v_link2))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print the header on the first page only. */
|
|
|
|
|
p = bv->v_plot;
|
2012-09-20 20:30:53 +02:00
|
|
|
j = (width - (int) strlen(p->pl_title)) / 2; /* Yes, keep "(int)" */
|
2011-01-12 18:49:18 +01:00
|
|
|
if (j < 0)
|
|
|
|
|
j = 0;
|
2000-04-27 22:03:57 +02:00
|
|
|
for (i = 0; i < j; i++)
|
|
|
|
|
buf2[i] = ' ';
|
|
|
|
|
buf2[j] = '\0';
|
|
|
|
|
out_send(buf2);
|
|
|
|
|
out_send(p->pl_title);
|
|
|
|
|
out_send("\n");
|
|
|
|
|
out_send(buf2);
|
|
|
|
|
(void) sprintf(buf, "%s %s", p->pl_name, p->pl_date);
|
2010-11-06 21:17:19 +01:00
|
|
|
j = (width - (int) strlen(buf)) / 2;
|
2000-04-27 22:03:57 +02:00
|
|
|
out_send(buf);
|
|
|
|
|
out_send("\n");
|
|
|
|
|
for (i = 0; i < width; i++)
|
|
|
|
|
buf2[i] = '-';
|
|
|
|
|
buf2[width] = '\n';
|
|
|
|
|
buf2[width+1] = '\0';
|
|
|
|
|
out_send(buf2);
|
|
|
|
|
(void) sprintf(buf, "Index ");
|
|
|
|
|
for (v = bv; v && (v != lv); v = v->v_link2) {
|
2012-09-20 20:30:53 +02:00
|
|
|
if (isreal(v)) {
|
2000-04-27 22:03:57 +02:00
|
|
|
(void) sprintf(buf2, "%-16.15s", v->v_name);
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
|
|
|
|
/* The frequency vector is complex but often with imaginary part = 0,
|
|
|
|
|
* this prevents to print two columns.
|
|
|
|
|
*/
|
|
|
|
|
if (eq(v->v_name, "frequency")) {
|
|
|
|
|
if (imagpart(v->v_compdata[0]) == 0.0)
|
2011-01-12 18:49:18 +01:00
|
|
|
(void) sprintf(buf2, "%-16.15s", v->v_name);
|
|
|
|
|
else
|
|
|
|
|
(void) sprintf(buf2, "%-32.31s", v->v_name);
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2011-01-12 18:49:18 +01:00
|
|
|
(void) sprintf(buf2, "%-32.31s", v->v_name);
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2011-01-12 18:49:18 +01:00
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
(void) strcat(buf, buf2);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
lineno = 3;
|
|
|
|
|
j = 0;
|
|
|
|
|
npoints = 0;
|
|
|
|
|
for (v = bv; (v && (v != lv)); v = v->v_link2)
|
|
|
|
|
if (v->v_length > npoints)
|
|
|
|
|
npoints = v->v_length;
|
2012-09-20 20:30:53 +02:00
|
|
|
pbreak: /* New page. */
|
2000-04-27 22:03:57 +02:00
|
|
|
out_send(buf);
|
|
|
|
|
out_send("\n");
|
|
|
|
|
for (i = 0; i < width; i++)
|
|
|
|
|
buf2[i] = '-';
|
|
|
|
|
buf2[width] = '\n';
|
|
|
|
|
buf2[width+1] = '\0';
|
|
|
|
|
out_send(buf2);
|
|
|
|
|
lineno += 2;
|
2012-09-20 20:30:53 +02:00
|
|
|
loop:
|
2000-04-27 22:03:57 +02:00
|
|
|
while ((j < npoints) && (lineno < height)) {
|
2012-08-18 18:27:13 +02:00
|
|
|
out_printf("%d\t", j);
|
2000-04-27 22:03:57 +02:00
|
|
|
for (v = bv; (v && (v != lv)); v = v->v_link2) {
|
|
|
|
|
if (v->v_length <= j) {
|
|
|
|
|
if (isreal(v))
|
|
|
|
|
out_send("\t\t");
|
|
|
|
|
else
|
|
|
|
|
out_send("\t\t\t\t");
|
|
|
|
|
} else {
|
2012-09-20 20:30:53 +02:00
|
|
|
if (isreal(v)) {
|
|
|
|
|
printnum(numbuf, v->v_realdata[j]);
|
2012-08-18 18:27:13 +02:00
|
|
|
out_printf("%s\t", numbuf);
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
|
|
|
|
/* In case of a single frequency and have a real part avoids print imaginary part equals 0. */
|
|
|
|
|
if (eq(v->v_name, "frequency") &&
|
|
|
|
|
imagpart(v->v_compdata[j]) == 0.0)
|
2011-01-12 18:49:18 +01:00
|
|
|
{
|
2012-09-20 20:30:53 +02:00
|
|
|
printnum(numbuf, realpart(v->v_compdata[j]));
|
|
|
|
|
out_printf("%s\t", numbuf);
|
|
|
|
|
} else {
|
|
|
|
|
printnum(numbuf, realpart(v->v_compdata[j]));
|
2012-02-07 20:53:12 +01:00
|
|
|
printnum(numbuf2, imagpart(v->v_compdata[j]));
|
2012-08-18 18:27:13 +02:00
|
|
|
out_printf("%s,\t%s\t", numbuf, numbuf2);
|
2011-01-12 18:49:18 +01:00
|
|
|
}
|
2009-01-15 22:08:09 +01:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
out_send("\n");
|
|
|
|
|
j++;
|
|
|
|
|
lineno++;
|
|
|
|
|
}
|
|
|
|
|
if ((j == npoints) && (lv == NULL)) /* No more to print. */
|
|
|
|
|
goto done;
|
|
|
|
|
if (j == npoints) { /* More vectors to print. */
|
|
|
|
|
bv = lv;
|
|
|
|
|
out_send("\f\n"); /* Form feed. */
|
|
|
|
|
goto nextpage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Otherwise go to a new page. */
|
|
|
|
|
lineno = 0;
|
|
|
|
|
if (nobreak)
|
|
|
|
|
goto loop;
|
|
|
|
|
else
|
|
|
|
|
out_send("\f\n"); /* Form feed. */
|
|
|
|
|
goto pbreak;
|
|
|
|
|
}
|
|
|
|
|
done:
|
|
|
|
|
/* Get rid of the vectors. */
|
2012-10-01 19:44:49 +02:00
|
|
|
free_pnode(names);
|
2011-01-12 18:49:18 +01:00
|
|
|
tfree(buf);
|
|
|
|
|
tfree(buf2);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Write out some data. write filename expr ... Some cleverness here is
|
|
|
|
|
* required. If the user mentions a few vectors from various plots,
|
|
|
|
|
* probably he means for them to be written out seperate plots. In any
|
|
|
|
|
* case, we have to be sure to write out the scales for everything we
|
|
|
|
|
* write...
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
com_write(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
char *file, buf[BSIZE_SP];
|
2012-10-01 17:59:40 +02:00
|
|
|
struct pnode *pn;
|
2000-04-27 22:03:57 +02:00
|
|
|
struct dvec *d, *vecs = NULL, *lv = NULL, *end, *vv;
|
2012-09-20 20:30:53 +02:00
|
|
|
static wordlist all = { "all", NULL, NULL };
|
2000-04-27 22:03:57 +02:00
|
|
|
struct pnode *names;
|
|
|
|
|
bool ascii = AsciiRawFile;
|
|
|
|
|
bool scalefound, appendwrite;
|
|
|
|
|
struct plot *tpl, newplot;
|
|
|
|
|
|
|
|
|
|
if (wl) {
|
|
|
|
|
file = wl->wl_word;
|
|
|
|
|
wl = wl->wl_next;
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2000-04-27 22:03:57 +02:00
|
|
|
file = ft_rawfile;
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
|
|
|
|
|
2010-07-17 22:48:20 +02:00
|
|
|
if (cp_getvar("filetype", CP_STRING, buf)) {
|
2000-04-27 22:03:57 +02:00
|
|
|
if (eq(buf, "binary"))
|
|
|
|
|
ascii = FALSE;
|
|
|
|
|
else if (eq(buf, "ascii"))
|
|
|
|
|
ascii = TRUE;
|
2012-09-20 20:30:53 +02:00
|
|
|
else
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_err, "Warning: strange file type %s\n", buf);
|
|
|
|
|
}
|
2010-07-20 20:52:19 +02:00
|
|
|
appendwrite = cp_getvar("appendwrite", CP_BOOL, NULL);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (wl)
|
|
|
|
|
names = ft_getpnames(wl, TRUE);
|
|
|
|
|
else
|
|
|
|
|
names = ft_getpnames(&all, TRUE);
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (names == NULL)
|
|
|
|
|
return;
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2012-10-01 17:59:40 +02:00
|
|
|
for (pn = names; pn; pn = pn->pn_next) {
|
|
|
|
|
d = ft_evaluate(pn);
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!d)
|
2012-10-01 21:03:53 +02:00
|
|
|
goto done;
|
2000-04-27 22:03:57 +02:00
|
|
|
if (vecs)
|
|
|
|
|
lv->v_link2 = d;
|
|
|
|
|
else
|
|
|
|
|
vecs = d;
|
|
|
|
|
for (lv = d; lv->v_link2; lv = lv->v_link2)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now we have to write them out plot by plot. */
|
|
|
|
|
|
|
|
|
|
while (vecs) {
|
|
|
|
|
tpl = vecs->v_plot;
|
|
|
|
|
tpl->pl_written = TRUE;
|
|
|
|
|
end = NULL;
|
2012-09-20 20:30:53 +02:00
|
|
|
bcopy(tpl, &newplot, sizeof(struct plot));
|
2000-04-27 22:03:57 +02:00
|
|
|
scalefound = FALSE;
|
|
|
|
|
|
|
|
|
|
/* Figure out how many vectors are in this plot. Also look
|
|
|
|
|
* for the scale, or a copy of it, which may have a different
|
|
|
|
|
* name.
|
|
|
|
|
*/
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
if (d->v_plot == tpl) {
|
2012-10-15 20:55:55 +02:00
|
|
|
char *basename = vec_basename(d);
|
2000-04-27 22:03:57 +02:00
|
|
|
vv = vec_copy(d);
|
|
|
|
|
/* Note that since we are building a new plot
|
|
|
|
|
* we don't want to vec_new this one...
|
|
|
|
|
*/
|
2012-10-15 20:55:55 +02:00
|
|
|
tfree(vv->v_name);
|
|
|
|
|
vv->v_name = basename;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (end)
|
|
|
|
|
end->v_next = vv;
|
|
|
|
|
else
|
|
|
|
|
end = newplot.pl_dvecs = vv;
|
|
|
|
|
end = vv;
|
|
|
|
|
|
|
|
|
|
if (vec_eq(d, tpl->pl_scale)) {
|
|
|
|
|
newplot.pl_scale = vv;
|
|
|
|
|
scalefound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
end->v_next = NULL;
|
|
|
|
|
|
|
|
|
|
/* Maybe we shouldn't make sure that the default scale is
|
|
|
|
|
* present if nobody uses it.
|
|
|
|
|
*/
|
|
|
|
|
if (!scalefound) {
|
|
|
|
|
newplot.pl_scale = vec_copy(tpl->pl_scale);
|
|
|
|
|
newplot.pl_scale->v_next = newplot.pl_dvecs;
|
|
|
|
|
newplot.pl_dvecs = newplot.pl_scale;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
/* Now let's go through and make sure that everything that
|
2000-04-27 22:03:57 +02:00
|
|
|
* has its own scale has it in the plot.
|
|
|
|
|
*/
|
|
|
|
|
for (;;) {
|
|
|
|
|
scalefound = FALSE;
|
|
|
|
|
for (d = newplot.pl_dvecs; d; d = d->v_next) {
|
|
|
|
|
if (d->v_scale) {
|
2012-09-20 20:30:53 +02:00
|
|
|
for (vv = newplot.pl_dvecs; vv; vv = vv->v_next)
|
2000-04-27 22:03:57 +02:00
|
|
|
if (vec_eq(vv, d->v_scale))
|
|
|
|
|
break;
|
|
|
|
|
/* We have to grab it... */
|
|
|
|
|
vv = vec_copy(d->v_scale);
|
|
|
|
|
vv->v_next = newplot.pl_dvecs;
|
|
|
|
|
newplot.pl_dvecs = vv;
|
|
|
|
|
scalefound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!scalefound)
|
|
|
|
|
break;
|
|
|
|
|
/* Otherwise loop through again... */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ascii)
|
|
|
|
|
raw_write(file, &newplot, appendwrite, FALSE);
|
|
|
|
|
else
|
|
|
|
|
raw_write(file, &newplot, appendwrite, TRUE);
|
|
|
|
|
|
2012-10-15 20:55:55 +02:00
|
|
|
for (vv = newplot.pl_dvecs; vv;) {
|
|
|
|
|
struct dvec *next_vv = vv->v_next;
|
|
|
|
|
vv->v_plot = NULL;
|
|
|
|
|
vec_free(vv);
|
|
|
|
|
vv = next_vv;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Now throw out the vectors we have written already... */
|
|
|
|
|
for (d = vecs, lv = NULL; d; d = d->v_link2)
|
|
|
|
|
if (d->v_plot == tpl) {
|
|
|
|
|
if (lv) {
|
|
|
|
|
lv->v_link2 = d->v_link2;
|
|
|
|
|
d = lv;
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2000-04-27 22:03:57 +02:00
|
|
|
vecs = d->v_link2;
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
2000-04-27 22:03:57 +02:00
|
|
|
lv = d;
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
/* If there are more plots we want them appended... */
|
|
|
|
|
appendwrite = TRUE;
|
|
|
|
|
}
|
2012-10-01 21:03:53 +02:00
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
free_pnode(names);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2010-10-16 14:05:09 +02:00
|
|
|
/* Write scattering parameters into a file with Touchstone File Format Version 1
|
2012-09-20 20:30:53 +02:00
|
|
|
with command wrs2p file .
|
|
|
|
|
Format info from http://www.eda.org/ibis/touchstone_ver2.0/touchstone_ver2_0.pdf
|
|
|
|
|
See example 13 on page 15: Two port, ASCII, real-imaginary
|
|
|
|
|
Check if S11, S21, S12, S22 and frequency vectors are available
|
|
|
|
|
Check if vector Rbase is available
|
|
|
|
|
Call spar_write()
|
|
|
|
|
*/
|
2010-10-16 14:05:09 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
com_write_sparam(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
char *file;
|
2012-09-20 20:30:53 +02:00
|
|
|
char *sbuf[6];
|
2010-10-16 14:05:09 +02:00
|
|
|
wordlist *wl_sparam;
|
2012-10-01 17:59:40 +02:00
|
|
|
struct pnode *pn;
|
2012-09-20 20:30:53 +02:00
|
|
|
struct dvec *d, *vecs = NULL, *lv = NULL, *end, *vv, *Rbasevec = NULL;
|
2010-10-16 14:05:09 +02:00
|
|
|
struct pnode *names;
|
2012-09-20 20:30:53 +02:00
|
|
|
bool scalefound, appendwrite = FALSE;
|
2010-10-16 14:05:09 +02:00
|
|
|
struct plot *tpl, newplot;
|
|
|
|
|
double Rbaseval;
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
if (wl)
|
2010-10-16 14:05:09 +02:00
|
|
|
file = wl->wl_word;
|
2012-09-20 20:30:53 +02:00
|
|
|
else
|
2010-10-16 14:05:09 +02:00
|
|
|
file = "s_param.s2p";
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2010-10-16 14:05:09 +02:00
|
|
|
/* generate wordlist with all vectors required*/
|
|
|
|
|
sbuf[0] = "frequency";
|
|
|
|
|
sbuf[1] = "S11";
|
|
|
|
|
sbuf[2] = "S21";
|
|
|
|
|
sbuf[3] = "S12";
|
|
|
|
|
sbuf[4] = "S22";
|
|
|
|
|
sbuf[5] = NULL;
|
|
|
|
|
wl_sparam = wl_build(sbuf);
|
|
|
|
|
|
|
|
|
|
names = ft_getpnames(wl_sparam, TRUE);
|
|
|
|
|
if (names == NULL)
|
2012-10-01 21:28:48 +02:00
|
|
|
goto done;
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2012-10-01 17:59:40 +02:00
|
|
|
for (pn = names; pn; pn = pn->pn_next) {
|
|
|
|
|
d = ft_evaluate(pn);
|
2010-10-16 14:05:09 +02:00
|
|
|
if (!d)
|
2012-10-01 21:03:53 +02:00
|
|
|
goto done;
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2010-10-16 14:05:09 +02:00
|
|
|
if (vecs)
|
|
|
|
|
lv->v_link2 = d;
|
|
|
|
|
else
|
|
|
|
|
vecs = d;
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2010-10-16 14:05:09 +02:00
|
|
|
for (lv = d; lv->v_link2; lv = lv->v_link2)
|
|
|
|
|
;
|
|
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2010-10-16 14:05:09 +02:00
|
|
|
Rbasevec = vec_get("Rbase");
|
2012-09-20 20:30:53 +02:00
|
|
|
if (Rbasevec) {
|
2010-10-16 14:05:09 +02:00
|
|
|
Rbaseval = Rbasevec->v_realdata[0];
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2010-10-16 14:05:09 +02:00
|
|
|
fprintf(stderr, "Error: No Rbase vector given\n");
|
2012-10-01 21:03:53 +02:00
|
|
|
goto done;
|
2010-10-16 14:05:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now we have to write them out plot by plot. */
|
|
|
|
|
|
|
|
|
|
while (vecs) {
|
|
|
|
|
tpl = vecs->v_plot;
|
|
|
|
|
tpl->pl_written = TRUE;
|
|
|
|
|
end = NULL;
|
2012-09-20 20:30:53 +02:00
|
|
|
bcopy(tpl, &newplot, sizeof(struct plot));
|
2010-10-16 14:05:09 +02:00
|
|
|
scalefound = FALSE;
|
|
|
|
|
|
|
|
|
|
/* Figure out how many vectors are in this plot. Also look
|
|
|
|
|
* for the scale, or a copy of it, which may have a different
|
|
|
|
|
* name.
|
|
|
|
|
*/
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
if (d->v_plot == tpl) {
|
2012-10-15 20:55:55 +02:00
|
|
|
char *basename = vec_basename(d);
|
2010-10-16 14:05:09 +02:00
|
|
|
vv = vec_copy(d);
|
|
|
|
|
/* Note that since we are building a new plot
|
|
|
|
|
* we don't want to vec_new this one...
|
|
|
|
|
*/
|
2012-10-15 20:55:55 +02:00
|
|
|
tfree(vv->v_name);
|
|
|
|
|
vv->v_name = basename;
|
2010-10-16 14:05:09 +02:00
|
|
|
|
|
|
|
|
if (end)
|
|
|
|
|
end->v_next = vv;
|
|
|
|
|
else
|
|
|
|
|
end = newplot.pl_dvecs = vv;
|
|
|
|
|
end = vv;
|
|
|
|
|
|
|
|
|
|
if (vec_eq(d, tpl->pl_scale)) {
|
|
|
|
|
newplot.pl_scale = vv;
|
|
|
|
|
scalefound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
end->v_next = NULL;
|
|
|
|
|
|
|
|
|
|
/* Maybe we shouldn't make sure that the default scale is
|
|
|
|
|
* present if nobody uses it.
|
|
|
|
|
*/
|
|
|
|
|
if (!scalefound) {
|
|
|
|
|
newplot.pl_scale = vec_copy(tpl->pl_scale);
|
|
|
|
|
newplot.pl_scale->v_next = newplot.pl_dvecs;
|
|
|
|
|
newplot.pl_dvecs = newplot.pl_scale;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
/* Now let's go through and make sure that everything that
|
2010-10-16 14:05:09 +02:00
|
|
|
* has its own scale has it in the plot.
|
|
|
|
|
*/
|
|
|
|
|
for (;;) {
|
|
|
|
|
scalefound = FALSE;
|
|
|
|
|
for (d = newplot.pl_dvecs; d; d = d->v_next) {
|
|
|
|
|
if (d->v_scale) {
|
2012-09-20 20:30:53 +02:00
|
|
|
for (vv = newplot.pl_dvecs; vv; vv = vv->v_next)
|
2010-10-16 14:05:09 +02:00
|
|
|
if (vec_eq(vv, d->v_scale))
|
|
|
|
|
break;
|
|
|
|
|
/* We have to grab it... */
|
|
|
|
|
vv = vec_copy(d->v_scale);
|
|
|
|
|
vv->v_next = newplot.pl_dvecs;
|
|
|
|
|
newplot.pl_dvecs = vv;
|
|
|
|
|
scalefound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!scalefound)
|
|
|
|
|
break;
|
|
|
|
|
/* Otherwise loop through again... */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
spar_write(file, &newplot, Rbaseval);
|
|
|
|
|
|
2012-10-15 20:55:55 +02:00
|
|
|
for (vv = newplot.pl_dvecs; vv;) {
|
|
|
|
|
struct dvec *next_vv = vv->v_next;
|
|
|
|
|
vv->v_plot = NULL;
|
|
|
|
|
vec_free(vv);
|
|
|
|
|
vv = next_vv;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 14:05:09 +02:00
|
|
|
/* Now throw out the vectors we have written already... */
|
|
|
|
|
for (d = vecs, lv = NULL; d; d = d->v_link2)
|
|
|
|
|
if (d->v_plot == tpl) {
|
|
|
|
|
if (lv) {
|
|
|
|
|
lv->v_link2 = d->v_link2;
|
|
|
|
|
d = lv;
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2010-10-16 14:05:09 +02:00
|
|
|
vecs = d->v_link2;
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
2010-10-16 14:05:09 +02:00
|
|
|
lv = d;
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2010-10-16 14:05:09 +02:00
|
|
|
/* If there are more plots we want them appended... */
|
|
|
|
|
appendwrite = TRUE;
|
|
|
|
|
}
|
2012-10-01 21:03:53 +02:00
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
free_pnode(names);
|
2012-10-01 21:28:48 +02:00
|
|
|
wl_free(wl_sparam);
|
2010-10-16 14:05:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* If the named vectors have more than 1 dimension, then consider
|
|
|
|
|
* to be a collection of one or more matrices. This command transposes
|
|
|
|
|
* each named matrix.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
com_transpose(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
struct dvec *d;
|
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
|
|
while (wl) {
|
|
|
|
|
s = cp_unquote(wl->wl_word);
|
|
|
|
|
d = vec_get(s);
|
2000-10-26 19:02:12 +02:00
|
|
|
tfree(s); /*DG: Avoid Memory Leak */
|
2000-04-27 22:03:57 +02:00
|
|
|
if (d == NULL)
|
2012-09-20 20:30:53 +02:00
|
|
|
fprintf(cp_err, "Error: no such vector as %s.\n", wl->wl_word);
|
2000-04-27 22:03:57 +02:00
|
|
|
else
|
|
|
|
|
while (d) {
|
|
|
|
|
vec_transpose(d);
|
|
|
|
|
d = d->v_link2;
|
|
|
|
|
}
|
|
|
|
|
if (wl->wl_next == NULL)
|
|
|
|
|
return;
|
|
|
|
|
wl = wl->wl_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Take a set of vectors and form a new vector of the nth elements of each. */
|
|
|
|
|
void
|
|
|
|
|
com_cross(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
char *newvec, *s;
|
|
|
|
|
struct dvec *n, *v, *vecs = NULL, *lv = NULL;
|
2012-10-01 17:53:01 +02:00
|
|
|
struct pnode *pn, *names;
|
2000-04-27 22:03:57 +02:00
|
|
|
int i, ind;
|
|
|
|
|
bool comp = FALSE;
|
|
|
|
|
double *d;
|
|
|
|
|
|
|
|
|
|
newvec = wl->wl_word;
|
|
|
|
|
wl = wl->wl_next;
|
|
|
|
|
s = wl->wl_word;
|
2010-11-19 19:54:40 +01:00
|
|
|
if ((d = ft_numparse(&s, FALSE)) == NULL) {
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_err, "Error: bad number %s\n", wl->wl_word);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2011-01-12 18:49:18 +01:00
|
|
|
if ((ind = (int)*d) < 0) {
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_err, "Error: badstrchr %d\n", ind);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
wl = wl->wl_next;
|
2012-10-01 17:53:01 +02:00
|
|
|
names = ft_getpnames(wl, TRUE);
|
|
|
|
|
for (pn = names; pn; pn = pn->pn_next) {
|
2010-11-19 19:54:40 +01:00
|
|
|
if ((n = ft_evaluate(pn)) == NULL)
|
2012-10-01 21:03:53 +02:00
|
|
|
goto done;
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!vecs)
|
|
|
|
|
vecs = lv = n;
|
|
|
|
|
else
|
|
|
|
|
lv->v_link2 = n;
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
for (lv = n; lv->v_link2; lv = lv->v_link2)
|
|
|
|
|
;
|
|
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
for (n = vecs, i = 0; n; n = n->v_link2) {
|
|
|
|
|
if (iscomplex(n))
|
|
|
|
|
comp = TRUE;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
vec_remove(newvec);
|
|
|
|
|
v = alloc(struct dvec);
|
|
|
|
|
v->v_name = copy(newvec);
|
|
|
|
|
v->v_type = vecs ? vecs->v_type : SV_NOTYPE;
|
|
|
|
|
v->v_length = i;
|
2010-11-04 20:28:00 +01:00
|
|
|
|
|
|
|
|
if (comp) {
|
|
|
|
|
v->v_flags = VF_COMPLEX;
|
2010-10-28 21:32:34 +02:00
|
|
|
v->v_compdata = TMALLOC(ngcomplex_t, i);
|
2010-11-04 20:28:00 +01:00
|
|
|
} else {
|
|
|
|
|
v->v_flags = VF_REAL;
|
2010-10-28 21:32:34 +02:00
|
|
|
v->v_realdata = TMALLOC(double, i);
|
2010-11-04 20:28:00 +01:00
|
|
|
}
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Now copy the ind'ths elements into this one. */
|
|
|
|
|
for (n = vecs, i = 0; n; n = n->v_link2, i++)
|
|
|
|
|
if (n->v_length > ind) {
|
|
|
|
|
if (comp) {
|
2012-09-20 20:30:53 +02:00
|
|
|
realpart(v->v_compdata[i]) = realpart(n->v_compdata[ind]);
|
|
|
|
|
imagpart(v->v_compdata[i]) = imagpart(n->v_compdata[ind]);
|
|
|
|
|
} else {
|
2000-04-27 22:03:57 +02:00
|
|
|
v->v_realdata[i] = n->v_realdata[ind];
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
} else {
|
|
|
|
|
if (comp) {
|
2012-02-07 20:53:12 +01:00
|
|
|
realpart(v->v_compdata[i]) = 0.0;
|
|
|
|
|
imagpart(v->v_compdata[i]) = 0.0;
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2000-04-27 22:03:57 +02:00
|
|
|
v->v_realdata[i] = 0.0;
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
vec_new(v);
|
|
|
|
|
v->v_flags |= VF_PERMANENT;
|
|
|
|
|
cp_addkword(CT_VECTOR, v->v_name);
|
2012-10-01 21:03:53 +02:00
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
free_pnode(names);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
void
|
|
|
|
|
com_destroy(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
struct plot *pl, *npl = NULL;
|
|
|
|
|
|
2009-02-10 20:00:24 +01:00
|
|
|
if (!wl) {
|
2012-09-20 20:30:53 +02:00
|
|
|
DelPlotWindows(plot_cur);
|
|
|
|
|
killplot(plot_cur);
|
|
|
|
|
} else if (eq(wl->wl_word, "all")) {
|
2000-04-27 22:03:57 +02:00
|
|
|
for (pl = plot_list; pl; pl = npl) {
|
|
|
|
|
npl = pl->pl_next;
|
2012-09-20 20:30:53 +02:00
|
|
|
if (!eq(pl->pl_typename, "const")) {
|
|
|
|
|
DelPlotWindows(pl);
|
2009-02-10 20:00:24 +01:00
|
|
|
killplot(pl);
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
|
|
|
|
plot_num = 1;
|
2009-02-10 20:00:24 +01:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
while (wl) {
|
|
|
|
|
for (pl = plot_list; pl; pl = pl->pl_next)
|
|
|
|
|
if (eq(pl->pl_typename, wl->wl_word))
|
|
|
|
|
break;
|
2012-09-20 20:30:53 +02:00
|
|
|
if (pl) {
|
2009-02-10 20:00:24 +01:00
|
|
|
DelPlotWindows(pl);
|
2000-04-27 22:03:57 +02:00
|
|
|
killplot(pl);
|
2012-09-20 20:30:53 +02:00
|
|
|
} else {
|
2009-02-10 20:00:24 +01:00
|
|
|
fprintf(cp_err, "Error: no such plot %s\n", wl->wl_word);
|
2012-09-20 20:30:53 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
wl = wl->wl_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
static void
|
|
|
|
|
killplot(struct plot *pl)
|
|
|
|
|
{
|
|
|
|
|
struct dvec *v, *nv = NULL;
|
|
|
|
|
struct plot *op;
|
|
|
|
|
|
|
|
|
|
if (eq(pl->pl_typename, "const")) {
|
|
|
|
|
fprintf(cp_err, "Error: can't destroy the constant plot\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2003-07-23 21:36:39 +02:00
|
|
|
/* pl_dvecs, pl_scale */
|
2000-04-27 22:03:57 +02:00
|
|
|
for (v = pl->pl_dvecs; v; v = nv) {
|
|
|
|
|
nv = v->v_next;
|
|
|
|
|
vec_free(v);
|
|
|
|
|
}
|
2003-07-23 21:36:39 +02:00
|
|
|
/* unlink from plot_list (linked via pl_next) */
|
2000-04-27 22:03:57 +02:00
|
|
|
if (pl == plot_list) {
|
|
|
|
|
plot_list = pl->pl_next;
|
|
|
|
|
if (pl == plot_cur)
|
|
|
|
|
plot_cur = plot_list;
|
|
|
|
|
} else {
|
|
|
|
|
for (op = plot_list; op; op = op->pl_next)
|
|
|
|
|
if (op->pl_next == pl)
|
|
|
|
|
break;
|
|
|
|
|
if (!op)
|
|
|
|
|
fprintf(cp_err,
|
2012-09-20 20:30:53 +02:00
|
|
|
"Internal Error: kill plot -- not in list\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
op->pl_next = pl->pl_next;
|
|
|
|
|
if (pl == plot_cur)
|
|
|
|
|
plot_cur = op;
|
|
|
|
|
}
|
|
|
|
|
tfree(pl->pl_title);
|
|
|
|
|
tfree(pl->pl_name);
|
|
|
|
|
tfree(pl->pl_typename);
|
|
|
|
|
wl_free(pl->pl_commands);
|
2003-07-23 21:36:39 +02:00
|
|
|
tfree(pl->pl_date); /* va: also tfree (memory leak) */
|
|
|
|
|
if (pl->pl_ccom) /* va: also tfree (memory leak) */
|
2012-09-21 21:14:52 +02:00
|
|
|
throwaway(pl->pl_ccom);
|
2012-09-20 20:30:53 +02:00
|
|
|
|
|
|
|
|
if (pl->pl_env) { /* The 'environment' for this plot. */
|
|
|
|
|
/* va: HOW to do? */
|
|
|
|
|
printf("va: killplot should tfree pl->pl_env=(%p)\n", pl->pl_env);
|
|
|
|
|
fflush(stdout);
|
2003-07-23 21:36:39 +02:00
|
|
|
}
|
|
|
|
|
tfree(pl); /* va: also tfree pl itself (memory leak) */
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2012-09-21 21:15:41 +02:00
|
|
|
void
|
|
|
|
|
destroy_const_plot(void)
|
|
|
|
|
{
|
|
|
|
|
struct dvec *v, *nv = NULL;
|
|
|
|
|
struct plot *pl = &constantplot;
|
|
|
|
|
|
|
|
|
|
/* pl_dvecs, pl_scale */
|
|
|
|
|
for (v = pl->pl_dvecs; v; v = nv) {
|
|
|
|
|
nv = v->v_next;
|
|
|
|
|
vec_free(v);
|
|
|
|
|
}
|
|
|
|
|
wl_free(pl->pl_commands);
|
|
|
|
|
if (pl->pl_ccom) /* va: also tfree (memory leak) */
|
|
|
|
|
throwaway(pl->pl_ccom);
|
|
|
|
|
|
|
|
|
|
if (pl->pl_env) { /* The 'environment' for this plot. */
|
|
|
|
|
/* va: HOW to do? */
|
|
|
|
|
printf("va: killplot should tfree pl->pl_env=(%p)\n", pl->pl_env);
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
/* delete all windows with graphs dedrived from a given plot */
|
2009-02-10 20:00:24 +01:00
|
|
|
static void
|
|
|
|
|
DelPlotWindows(struct plot *pl)
|
|
|
|
|
{
|
2012-09-20 20:30:53 +02:00
|
|
|
/* do this only if windows or X11 is defined */
|
2013-03-23 09:54:44 +01:00
|
|
|
#if defined(HAS_WINGUI) || !defined(X_DISPLAY_MISSING)
|
2012-09-20 20:30:53 +02:00
|
|
|
GRAPH *dgraph;
|
|
|
|
|
int n;
|
|
|
|
|
/* find and remove all graph structures derived from a given plot */
|
|
|
|
|
for (n = 1; n < 100; n++) { /* should be no more than 100 */
|
|
|
|
|
dgraph = FindGraph(n);
|
|
|
|
|
if (dgraph) {
|
|
|
|
|
if (ciprefix(pl->pl_typename, dgraph->plotname))
|
|
|
|
|
RemoveWindow(dgraph);
|
|
|
|
|
}
|
|
|
|
|
/* We have to run through all potential graph ids. If some numbers are
|
|
|
|
|
already missing, 'else break;' might miss the plotwindow to be removed. */
|
|
|
|
|
/* else
|
|
|
|
|
break;
|
|
|
|
|
*/
|
|
|
|
|
}
|
2012-02-10 17:57:21 +01:00
|
|
|
#else
|
|
|
|
|
NG_IGNORE(pl);
|
2009-02-10 20:00:24 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
void
|
|
|
|
|
com_splot(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
struct plot *pl;
|
|
|
|
|
char buf[BSIZE_SP], *s, *t;
|
|
|
|
|
|
|
|
|
|
if (wl) {
|
|
|
|
|
plot_setcur(wl->wl_word);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fprintf(cp_out, "\tType the name of the desired plot:\n\n");
|
|
|
|
|
fprintf(cp_out, "\tnew\tNew plot\n");
|
|
|
|
|
for (pl = plot_list; pl; pl = pl->pl_next)
|
|
|
|
|
fprintf(cp_out, "%s%s\t%s (%s)\n",
|
|
|
|
|
(pl == plot_cur) ? "Current " : "\t",
|
|
|
|
|
pl->pl_typename, pl->pl_title, pl->pl_name);
|
2012-09-20 20:30:53 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_out, "? ");
|
|
|
|
|
if (!fgets(buf, BSIZE_SP, cp_in)) {
|
|
|
|
|
clearerr(cp_in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
t = buf;
|
2010-11-19 19:54:40 +01:00
|
|
|
if ((s = gettok(&t)) == NULL)
|
2000-04-27 22:03:57 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
plot_setcur(s);
|
|
|
|
|
}
|