Jspice3
postcoms.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Various post-processor commands having to do with vectors.
10  */
11 
12 #include "spice.h"
13 #include "ftedefs.h"
14 #include "scedio.h"
15 
16 #ifdef __STDC__
17 static struct dvec *copyvec(struct dvec*);
18 static void pvec(struct dvec*);
19 static int dcomp(struct dvec**,struct dvec**);
20 #else
21 static struct dvec *copyvec();
22 static void pvec();
23 static int dcomp();
24 #endif
25 
26 
27 void
29 
30 wordlist *wl;
31 {
32  char *p, *q, *s;
33  int indices[MAXDIMS];
34  int numdims;
35  wordlist word;
36  int need_open, depth;
37  int offset, size, rsize;
38  struct pnode *nn;
39  struct dvec *n, *t;
40  int i, j;
41  int d1, d2;
42  char *rhs;
43 
44  word.wl_next = NULL;
45 
46  if (!wl) {
48  return;
49  }
50 
51  p = wl_flatten(wl);
52 
53  if (rhs = strchr(p, '=')) {
54  *rhs++ = 0;
55  }
56  else {
57  fprintf(cp_err, "Error: bad let syntax\n");
58  goto quit;
59  }
60 
61  /* sanity check */
62  if (eq(p, "all") || strchr(p, '@')) {
63  fprintf(cp_err, "Error: bad variable name %s\n", p);
64  goto quit;
65  }
66 
67  /* extract indices */
68  numdims = 0;
69  if (s = strchr(p, '[')) {
70  need_open = 0;
71  *s++ = 0;
72  while (!need_open || *s == '[') {
73  depth = 0;
74  if (need_open)
75  s++;
76  for (q = s; *q && (*q != ']' && *q != ',' || depth > 0); q++) {
77  switch (*q) {
78  case '[':
79  depth += 1;
80  break;
81  case ']':
82  depth -= 1;
83  break;
84  }
85  }
86 
87  if (depth != 0 || !*q) {
88  printf("Error: bad syntax specifying index\n");
89  goto quit;
90  }
91 
92  if (*q == ']')
93  need_open = 1;
94  else
95  need_open = 0;
96  if (*q)
97  *q++ = 0;
98 
99  /* evaluate expression between s and q */
100  word.wl_word = s;
101  if ((nn = ft_getpnames(&word, true)) == NULL)
102  goto quit;
103  if ((t = ft_evaluate(nn)) == NULL)
104  goto quit;
105  inp_pnfree(nn);
106 
107  if (!isreal(t) || t->v_link2 || t->v_length != 1 ||
108  !t->v_realdata) {
109  fprintf(cp_err, "Error: index is not a scalar.\n");
110  goto quit;
111  }
112  j = t->v_realdata[0]; /* ignore sanity checks for now */
113 
114  if (j < 0) {
115  printf("Error: negative index (%d) is not allowed\n", j);
116  goto quit;
117  }
118 
119  indices[numdims++] = j;
120 
121  for (s = q; *s && isspace(*s); s++)
122  ;
123  }
124  }
125  /* vector name at p */
126 
127  for (q = p + strlen(p) - 1; *q <= ' ' && p <= q; q--)
128  ;
129 
130  *++q = 0;
131 
132  /* evaluate rhs */
133  word.wl_word = rhs;
134  if ((nn = ft_getpnames(&word, true)) == NULL)
135  goto quit;
136  if ((t = ft_evaluate(nn)) == NULL)
137  goto quit;
138  inp_pnfree(nn);
139 
140  if (t->v_link2) {
141  fprintf(cp_err, "Warning: extra wildcard values ignored\n");
142  t = t->v_link2->dl_dvec;
143  }
144 
145  /* make sure dims are ok for unit dimension */
146  if (t->v_numdims <= 1) {
147  t->v_numdims = 1;
148  t->v_dims[0] = t->v_length;
149  }
150  if (numdims + t->v_numdims > MAXDIMS) {
151  fprintf(cp_err,"Error: too many dimensions\n");
152  goto quit;
153  }
154 
155  n = vec_get(p);
156 
157  if (!n) {
158 
159  /* Create and assign a new vector. If a range was specified,
160  * create a vector of the dimensionality and size to contain
161  * the data. The least significant dimension given is added
162  * to the most significant dimension of the vector being assigned.
163  * The entries not explicitly assigned are zero. E.g.,
164  * let a[2] = b. If b is a 1d vector of length n, a will be a
165  * 1d vector of length n+2 with entries (0, 0, b[0], b[1], ...).
166  * If b has dimensions [x][y][z], a will have dimensions
167  * [x+2][y][z]. for let a[2][3] = b, a will have dimensions
168  * [2+1][x+3][y][z], etc.
169  */
170  n = alloc(struct dvec);
171  n->v_name = copy(p);
172  n->v_type = t->v_type;
173  n->v_flags = t->v_flags;
174  n->v_defcolor = t->v_defcolor;
175  n->v_gridtype = t->v_gridtype;
176  n->v_plottype = t->v_plottype;
177 
178  vec_newperm(n);
179 
180  i = 0;
181  if (numdims) {
182  for ( ; i < numdims - 1; i++) {
183  n->v_dims[i] = indices[i] + 1;
184  }
185  n->v_dims[numdims-1] = indices[numdims-1];
186  }
187  if (t->v_numdims <= 1) {
188  n->v_dims[i] += t->v_length;
189  n->v_numdims = numdims ? numdims : 1;
190  }
191  else {
192  n->v_dims[i] += t->v_dims[0];
193  for (i++,j = 1; j < t->v_numdims; i++,j++) {
194  n->v_dims[i] = t->v_dims[j];
195  }
196  n->v_numdims = i;
197  }
198 
199  size = 1;
200  for (i = 0; i < n->v_numdims; i++)
201  size *= n->v_dims[i];
202  rsize = 1;
203  for (i = 0; i < t->v_numdims; i++)
204  rsize *= t->v_dims[i];
205  /* rsize should be t->v_length, but maybe not... */
206  offset = size - rsize;
207 
208  if (offset < 0 || rsize < t->v_length) {
209  fprintf(cp_err, "Error: internal, bad length\n");
210  vec_remove(n->v_name);
211  goto quit;
212  }
213 
214  n->v_length = size;
215  if (isreal(t)) {
216  n->v_realdata = (double *) tmalloc(size * sizeof(double));
217  DCOPY(t->v_realdata,n->v_realdata + offset,t->v_length);
218  }
219  else {
220  n->v_compdata = (complex *) tmalloc(size * sizeof(complex));
221  CCOPY(t->v_compdata,n->v_compdata + offset,t->v_length);
222  }
224  goto quit;
225  }
226 
227  if (numdims == 0) {
228  /* reuse vector n, copy stuff from t */
229 
230  if (isreal(t)) {
231  if (n->v_length != t->v_length || iscomplex(n)) {
232  if (isreal(n))
233  txfree((char*)n->v_realdata);
234  else
235  txfree((char*)n->v_compdata);
236  n->v_realdata = (double *) tmalloc(sizeof (double) *
237  t->v_length);
238  }
239  DCOPY(t->v_realdata, n->v_realdata, t->v_length);
240  }
241  else {
242  if (n->v_length != t->v_length || isreal(n)) {
243  if (isreal(n))
244  txfree((char*)n->v_realdata);
245  else
246  txfree((char*)n->v_compdata);
247  n->v_compdata = (complex *) tmalloc(sizeof (complex) *
248  t->v_length);
249  }
250  CCOPY(t->v_compdata, n->v_compdata, t->v_length);
251  }
252  n->v_type = t->v_type;
253  n->v_flags = t->v_flags;
254  n->v_scale = t->v_scale;
255  n->v_numdims = t->v_numdims;
256  for (i = 0; i < t->v_numdims; i++)
257  n->v_dims[i] = t->v_dims[i];
258  n->v_length = t->v_length;
259  goto quit;
260  }
261 
262  /* make sure dims are ok for unit dimension */
263  if (n->v_numdims <= 1) {
264  n->v_numdims = 1;
265  n->v_dims[0] = n->v_length;
266  }
267 
268  /* Here we copy into an existing vector, expanding the size if
269  * necessary. The given indices except the least significant must
270  * be within the range of n, and "point" to a submatrix with the
271  * same dimensionality as t. However, if t is a 1-d vector,
272  * t is copied into n at the index, if it will fit, but if n is
273  * a 1-d vector n is extended if necessary. Values not explicitly
274  * set remain as they were, and new values created are zero.
275  */
276 
277  if (numdims > n->v_numdims || t->v_numdims > n->v_numdims) {
278  fprintf(cp_err,"Error: can't set %s to higher dimension\n",
279  n->v_name);
280  goto quit;
281  }
282  for (i = 0; i < numdims-1; i++) {
283  if (indices[i] >= n->v_dims[i]) {
284  fprintf(cp_err,"Error: dimension spec. out of range for %s\n",
285  n->v_name);
286  goto quit;
287  }
288  }
289  if (t->v_numdims > 1) {
290  for (i = numdims, j = 1; j < t->v_numdims; i++,j++) {
291  if (i >= n->v_numdims || n->v_dims[i] != t->v_dims[j]) {
292  fprintf(cp_err,
293  "Error: subdimension of %s is incompatible with %s\n",
294  n->v_name,t->v_name);
295  goto quit;
296  }
297  }
298  }
299  else if (n->v_numdims > 1) {
300  if (n->v_numdims - numdims > 1) {
301  fprintf(cp_err,"Error: too few dimensions specified\n");
302  goto quit;
303  }
304 
305  /* will t fit in block? */
306  if (n->v_numdims == numdims)
307  i = indices[numdims-1];
308  else
309  i = 0;
310 
311  if (t->v_dims[0] + i > n->v_dims[n->v_numdims-1]) {
312  fprintf(cp_err,
313  "Error: operation would overflow block in %s\n",
314  n->v_name);
315  goto quit;
316  }
317  }
318 
319  offset = 0;
320  size = 1;
321  for (i = n->v_numdims-1; i >= 0; i--) {
322  if (i < numdims)
323  offset += indices[i]*size;
324  size *= n->v_dims[i];
325  }
326  rsize = 1;
327  for (i = 0; i < t->v_numdims; i++)
328  rsize *= t->v_dims[i];
329  /* rsize should be t->v_length, but maybe not... */
330  if (rsize < t->v_length) {
331  fprintf(cp_err, "Error: internal, bad length\n");
332  goto quit;
333  }
334 
335  /* fix the dimension */
336  j = numdims-1;
337  i = indices[j];
338  if (n->v_numdims > t->v_numdims)
339  i++;
340  else
341  i += t->v_dims[0];
342  if (n->v_dims[j] < i)
343  n->v_dims[j] = i;
344 
345  if (offset + rsize > n->v_length) {
346  /* have to allocate more space */
347  n->v_length = offset + rsize;
348  if (isreal(n))
349  n->v_realdata = (double*)trealloc((char*)n->v_realdata,
350  n->v_length*sizeof(double));
351  else
352  n->v_compdata = (complex*)trealloc((char*)n->v_compdata,
353  n->v_length*sizeof(complex));
354  }
355 
356  if (isreal(n)) {
357  if (isreal(t)) {
358  DCOPY(t->v_realdata,n->v_realdata + offset,t->v_length);
359  }
360  else {
361  for (i = 0,j = offset; i < t->v_length; i++,j++)
362  n->v_realdata[j] = realpart(&t->v_compdata[i]);
363  }
364  }
365  else {
366  if (isreal(t)) {
367  for (i = 0,j = offset; i < t->v_length; i++,j++) {
368  n->v_compdata[j].cx_real = t->v_realdata[i];
369  n->v_compdata[j].cx_imag = 0.0;
370  }
371  }
372  else {
373  CCOPY(t->v_compdata,n->v_compdata + offset,t->v_length);
374  }
375  }
376 
377 quit:
378  txfree(p);
379  return;
380 }
381 
382 
383 /* Undefine vectors. */
384 
385 void
387 
388 wordlist *wl;
389 {
390  while (wl) {
391  vec_remove(wl->wl_word);
392  wl = wl->wl_next;
393  }
394  return;
395 }
396 
397 
398 /* Load in a file. */
399 
400 void
402 
403 wordlist *wl;
404 {
405 
406  if (!wl)
408  else
409  while (wl) {
410  char *s = copy(wl->wl_word);
411  cp_unquote(s);
412  ft_loadfile(s);
413  txfree(s);
414  wl = wl->wl_next;
415  }
416  return;
417 }
418 
419 
420 void
422 
423 /* Print out the value of an expression. */
424 wordlist *wl;
425 {
426  struct dvec *v, *bv;
427  struct dvlist *tl, *bl, *dl, *dl0, xl;
428  int i, j, ll, width = 0, height = 0, npoints, lineno;
429  struct pnode *n0;
430  struct plot *p;
431  bool col = true, nobreak = false, noprintscale, plotnames = false;
432  bool optgiven = false;
433  char *s, buf[BSIZE_SP], buf2[BSIZE_SP];
434  extern char *kw_nobreak, *kw_noprintscale;
435 
436 
437  if (wl == NULL)
438  return;
439  if (eq(wl->wl_word, "col")) {
440  col = true;
441  optgiven = true;
442  wl = wl->wl_next;
443  }
444  else if (eq(wl->wl_word, "line")) {
445  col = false;
446  optgiven = true;
447  wl = wl->wl_next;
448  }
449 
450  n0 = ft_getpnames(wl, true);
451  if (n0 == NULL)
452  return;
453  dl0 = ft_dvlist(n0);
454  if (dl0 == NULL)
455  return;
456 
457  /* See whether we really have to print plot names. */
458  p = dl0->dl_dvec->v_plot;
459  for (dl = dl0->dl_next; dl; dl = dl->dl_next) {
460  if (p != dl->dl_dvec->v_plot) {
461  plotnames = true;
462  break;
463  }
464  }
465 
466  if (!optgiven) {
467  /* Figure out whether col or line should be used... */
468  col = false;
469  for (dl = dl0; dl; dl = dl->dl_next) {
470  if (dl->dl_dvec->v_length > 1) {
471  col = true;
472  break;
473  }
474  }
475  }
476 
477  out_send("\n");
478  if (!col) {
479  for (dl = dl0; dl; dl = dl->dl_next) {
480  v = dl->dl_dvec;
481  s = vec_basename(v);
482  if (plotnames) {
483  (void) sprintf(buf, "%s.%s", v->v_plot->pl_typename,s);
484  }
485  else {
486  (void) strcpy(buf, s);
487  }
488  txfree(s);
489  for (s = buf; *s; s++)
490  ;
491  s--;
492  while (isspace(*s)) {
493  *s = '\0';
494  s--;
495  }
496  ll = 10;
497  if (v->v_length == 1) {
498  if (isreal(v)) {
499  out_printf("%s = %s\n", buf,
500  printnum(*v->v_realdata));
501  }
502  else {
503  out_printf("%s = %s",buf,
505  out_printf(",%s\n",
507  }
508  }
509  else {
510  out_printf("%s = ( ", buf);
511  for (i = 0; i < v->v_length; i++)
512  if (isreal(v)) {
513  (void) strcpy(buf,
514  printnum(v->v_realdata[i]));
515  out_send(buf);
516  ll += strlen(buf);
517  ll = (ll + 7) / 8;
518  ll = ll * 8 + 1;
519  if (ll > 60) {
520  out_send("\n\t");
521  ll = 9;
522  }
523  else
524  out_send("\t");
525  }
526  else {
527  (void) sprintf(buf, "%s",
528  printnum(realpart(&v->v_compdata[i])));
529  (void) sprintf(buf+strlen(buf), ",%s",
530  printnum(imagpart(&v->v_compdata[i])));
531  out_send(buf);
532  ll += strlen(buf);
533  ll = (ll + 7) / 8;
534  ll = ll * 8 + 1;
535  if (ll > 60) {
536  out_send("\n\t");
537  ll = 9;
538  }
539  else
540  out_send("\t");
541  }
542  out_send(")\n");
543  }
544  }
545  }
546  else { /* Print in columns. */
547  if (out_isatty)
548  out_winsize(&width,&height);
549  else {
550  if (out_width > 0)
551  width = out_width;
552  else
553  width = DEF_WIDTH;
554  if (out_height > 0)
555  height = out_height;
556  else
557  height = DEF_HEIGHT;
558  }
559  if (width < 40)
560  width = 40;
561  if (height < 20)
562  height = 20;
563  if (!cp_getvar(kw_nobreak, VT_BOOL, (char *) &nobreak) &&
564  !ft_nopage && !out_isatty)
565  nobreak = false;
566  else
567  nobreak = true;
568  (void) cp_getvar(kw_noprintscale, VT_BOOL, (char *)
569  &noprintscale);
570 
571  bv = dl0->dl_dvec;
572  bl = dl0;
573 nextpage:
574  /* Make the first vector of every page be the scale... */
575 
576  if (!noprintscale && bv->v_plot->pl_ndims) {
577  if (bv->v_plot->pl_scale && !vec_eq(bv, bv->v_plot->pl_scale)) {
578  xl.dl_dvec = bv->v_plot->pl_scale;
579  xl.dl_next = bl;
580  bl = &xl;
581  bv = xl.dl_dvec;
582  }
583  }
584  ll = 8;
585  for (dl = bl; dl; dl = dl->dl_next) {
586  if (isreal(dl->dl_dvec))
587  ll += 16; /* Two tabs for real, */
588  else
589  ll += 32; /* 4 for complex. */
590  /* Make sure we have at least 2 vectors per page... */
591  if ((ll > width) && (dl != bl) && (dl != bl->dl_next))
592  break;
593  }
594 
595  /* Print the header on the first page only. */
596  p = bv->v_plot;
597  j = (width - strlen(p->pl_title)) / 2;
598  for (i = 0; i < j; i++)
599  buf2[i] = ' ';
600  buf2[j] = '\0';
601  out_send(buf2);
602  out_send(p->pl_title);
603  out_send("\n");
604  out_send(buf2);
605  (void) sprintf(buf, "%s %s", p->pl_name, p->pl_date);
606  j = (width - strlen(buf)) / 2;
607  out_send(buf);
608  out_send("\n");
609  for (i = 0; i < width; i++)
610  buf2[i] = '-';
611  buf2[width] = '\n';
612  buf2[width+1] = '\0';
613  out_send(buf2);
614  (void) sprintf(buf, "Index ");
615  for (tl = bl; tl && tl != dl; tl = tl->dl_next) {
616  v = tl->dl_dvec;
617  if (isreal(v))
618  (void) sprintf(buf2, "%-16.15s", v->v_name);
619  else
620  (void) sprintf(buf2, "%-32.31s", v->v_name);
621  (void) strcat(buf, buf2);
622  }
623  lineno = 3;
624  j = 0;
625  npoints = 0;
626  for (tl = bl; tl && tl != dl; tl = tl->dl_next) {
627  v = tl->dl_dvec;
628  if (v->v_length > npoints)
629  npoints = v->v_length;
630  }
631 pbreak:
632  /* New page. */
633  out_send(buf);
634  out_send("\n");
635  for (i = 0; i < width; i++)
636  buf2[i] = '-';
637  buf2[width] = '\n';
638  buf2[width+1] = '\0';
639  out_send(buf2);
640  lineno += 2;
641 loop:
642  while ((j < npoints) && (lineno < height)) {
643  out_printf("%d\t", j);
644  for (tl = bl; tl && tl != dl; tl = tl->dl_next) {
645  v = tl->dl_dvec;
646  if (v->v_length <= j) {
647  if (isreal(v))
648  out_send("\t\t");
649  else
650  out_send("\t\t\t\t");
651  }
652  else {
653  if (isreal(v)) {
654  out_printf("%e\t",v->v_realdata[j]);
655  }
656  else {
657  out_printf("%e,\t%e\t",
658  realpart(&v->v_compdata[j]),
659  imagpart(&v->v_compdata[j]));
660  }
661  }
662  }
663  out_send("\n");
664  j++;
665  lineno++;
666  }
667  if ((j == npoints) && (dl == NULL)) /* No more to print. */
668  goto done;
669  if (j == npoints) { /* More vectors to print. */
670  bl = dl;
671  bv = bl->dl_dvec;
672  out_send("\f\n"); /* Form feed. */
673  goto nextpage;
674  }
675 
676  /* Otherwise go to a new page. */
677  lineno = 0;
678  if (nobreak)
679  goto loop;
680  else
681  out_send("\f\n"); /* Form feed. */
682  goto pbreak;
683  }
684 done:
685  out_send("\n");
686  vec_dlfree(dl0);
687  return;
688 }
689 
690 
691 /* Write out some data. write filename expr ... Some cleverness here is
692  * required. If the user mentions a few vectors from various plots,
693  * probably he means for them to be written out seperate plots. In any
694  * case, we have to be sure to write out the scales for everything we
695  * write...
696  */
697 
698 void
700 
701 wordlist *wl;
702 {
703  char *file, buf[BSIZE_SP];
704  struct dvec *d, *vv;
705  struct dvlist *dl, *dn, *dp, *dl0;
706  struct pnode *names;
707  struct plot *tpl, newplot;
708  wordlist *wl0, *tl, *tll;
709  bool oct = false;
710  bool ascii = AsciiRawFile;
711  bool scalefound, appendwrite;
712  extern char *kw_filetype, *kw_appendwrite;
713 
714  if (wl) {
715  file = wl->wl_word;
716  wl = wl->wl_next;
717  }
718  else
719  file = ft_rawfile;
720  if (cp_getvar(kw_filetype, VT_STRING, buf)) {
721  if (eq(buf, "binary"))
722  ascii = false;
723  else if(eq(buf,"oct"))
724  oct = true;
725  else if (!eq(buf, "ascii"))
726  fprintf(cp_err, "Warning: strange file type %s\n", buf);
727  }
728  (void) cp_getvar(kw_appendwrite, VT_BOOL, (char *) &appendwrite);
729 
730  if (!wl) {
731  /* just dump the current plot */
732  raw_write(file, plot_cur, appendwrite, ascii ? false : true);
733  plot_cur->pl_written = true;
734  return;
735  }
736 
737  if ((names = ft_getpnames(wl, true)) == NULL)
738  return;
739  if ((dl0 = ft_dvlist(names)) == NULL)
740  return;
741 
742  /* Now we have to write them out plot by plot. */
743 
744  while (dl0) {
745 
746  tpl = dl0->dl_dvec->v_plot;
747  tpl->pl_written = true;
748  bcopy((char *) tpl, (char *) &newplot, sizeof (struct plot));
749  newplot.pl_dvecs = NULL;
750  newplot.pl_hashtab = NULL;
751  scalefound = false;
752 
753  /* Figure out how many vectors are in this plot. Also look
754  * for the scale, or a copy of it, which may have a different
755  * name.
756  */
757  for (dl = dl0; dl; dl = dl->dl_next) {
758  d = dl->dl_dvec;
759  if (d->v_plot == tpl) {
760  vv = copyvec(d);
761  txfree(vv->v_name);
762  vv->v_name = vec_basename(d);
763  if (newplot.pl_hashtab == NULL)
764  newplot.pl_hashtab = htab_init();
765  htab_add(vv->v_name,(void*)vv,newplot.pl_hashtab);
766  if (vec_eq(d, tpl->pl_scale)) {
767  newplot.pl_scale = vv;
768  scalefound = true;
769  }
770  }
771  }
772 
773  /* Maybe we shouldn't make sure that the default scale is
774  * present if nobody uses it.
775  */
776  if (!scalefound) {
777  vv = copyvec(tpl->pl_scale);
778  txfree(vv->v_name);
779  vv->v_name = vec_basename(tpl->pl_scale);
780  newplot.pl_scale = vv;
781  htab_add(vv->v_name,(void*)vv,newplot.pl_hashtab);
782  }
783 
784  /* Now let's go through and make sure that everything that
785  * has its own scale has it in the plot.
786  */
787  for (;;) {
788  scalefound = false;
789  wl0 = htab_wl(newplot.pl_hashtab);
790  for (tl = wl0; tl; tl = tl->wl_next) {
791  d = (struct dvec *)htab_get(tl->wl_word,newplot.pl_hashtab);
792  if (d->v_scale) {
793  for (tll = wl0; tll; tll = tll->wl_next) {
794  vv = (struct dvec *)htab_get(tll->wl_word,
795  newplot.pl_hashtab);
796  if (vec_eq(vv, d->v_scale)) {
797  d->v_scale = vv;
798  break;
799  }
800  }
801  if (!tll) {
802  /* We have to grab it... */
803  vv = copyvec(d->v_scale);
804  txfree(vv->v_name);
805  vv->v_name = vec_basename(d->v_scale);
806  htab_add(vv->v_name,(void*)vv,newplot.pl_hashtab);
807  d->v_scale = vv;
808  scalefound = true;
809  }
810  }
811  }
812  wl_free(wl0);
813  if (!scalefound)
814  break;
815  /* Otherwise loop through again... */
816  }
817 
818  raw_write(file, &newplot, appendwrite, ascii ? false : true);
819 
820  /* Now throw out the vectors we have written already... */
821  for (dp = NULL, dl = dl0; dl; dl = dn) {
822  dn = dl->dl_next;
823  if (dl->dl_dvec->v_plot == tpl) {
824  if (dp == NULL)
825  dl0 = dn;
826  else
827  dp->dl_next = dl->dl_next;
828  txfree((char*)dl);
829  }
830  else
831  dp = dl;
832  }
833  wl0 = (wordlist*)htab_list(newplot.pl_hashtab);
834  /* wl_word -> char[2] = (name,*dvec) */
835  for (tl = wl0; tl; tl = tl->wl_next) {
836  vv = (struct dvec *)((char**)tl->wl_word)[1];
837  tfree(vv->v_name);
838  tfree(vv);
839  }
840  wl_free(wl0);
841  htab_free(newplot.pl_hashtab,false);
842  txfree((char*)newplot.pl_hashtab);
843 
844  /* If there are more plots we want them appended... */
845  appendwrite = true;
846  }
847 }
848 
849 /* copy the struct, but not the data (saves time and space) */
850 
851 static struct dvec *
853 struct dvec *d;
854 {
855  int ltmp;
856  struct dvec *v;
857 
858  if (!d)
859  return (struct dvec *) NULL;
860  ltmp = d->v_length;
861  d->v_length = 0;
862  v = vec_copy(d);
863  d->v_length = ltmp;
864  v->v_length = ltmp;
865  if (isreal(v))
866  v->v_realdata = d->v_realdata;
867  else
868  v->v_compdata = d->v_compdata;
869  return (v);
870 }
871 
872 
873 /* Display vector status, etc. Note that this only displays stuff from the
874  * current plot, and you must do a setplot to see the rest of it.
875  */
876 
877 void
879 
880 wordlist *wl;
881 {
882  struct dvec *d;
883  struct dvlist *dl;
884  wordlist *tl, *tl0;
885  int len;
886  bool b;
887  char *s;
888  extern char *kw_nosort;
889 
890  /* Maybe he wants to know about just a few vectors. */
891 
892  while (wl) {
893  s = copy(wl->wl_word);
894  cp_unquote(s);
895  d = vec_get(s);
896  tfree(s);
897  if (d == NULL)
898  fprintf(cp_err, "Error: no such vector as %s.\n",
899  wl->wl_word);
900  else {
901  if (d->v_link2) {
902  for (dl = d->v_link2; dl; dl = dl->dl_next)
903  pvec(dl->dl_dvec);
904  }
905  else
906  pvec(d);
907  }
908  if (wl->wl_next == NULL)
909  return;
910  wl = wl->wl_next;
911  }
912  if (!plot_cur) {
913  fprintf(cp_err,"Error (internal): no current plot\n");
914  return;
915  }
916 
918  if (!tl0) {
919  out_printf("There are no vectors currently active.\n");
920  return;
921  }
922  if (!cp_getvar(kw_nosort, VT_BOOL, (char *) &b))
923  wl_sort(tl0);
924  out_printf("Here are the vectors currently active:\n\n");
925  out_printf("Title: %s\n", plot_cur->pl_title);
926  out_printf("Name: %s (%s)\nDate: %s\n\n",
928  plot_cur->pl_date);
929 
930  /* list scale first */
931  for (tl = tl0; tl; tl = tl->wl_next) {
932  if (eq(tl->wl_word,plot_cur->pl_scale->v_name)) {
933  d = (struct dvec*)htab_get(tl->wl_word,plot_cur->pl_hashtab);
934  pvec(d);
935  break;
936  }
937  }
938  for (tl = tl0; tl; tl = tl->wl_next) {
939  if (!eq(tl->wl_word,plot_cur->pl_scale->v_name)) {
940  d = (struct dvec*)htab_get(tl->wl_word,plot_cur->pl_hashtab);
941  pvec(d);
942  }
943  }
944  wl_free(tl0);
945  return;
946 }
947 
948 
949 static void
951 
952 struct dvec *d;
953 {
954  int i;
955  char buf[BSIZE_SP], buf2[BSIZE_SP];
956 
957  sprintf(buf, " %-20s: %s, %s, %d long", d->v_name,
958  ft_typenames(d->v_type), isreal(d) ? "real" :
959  "complex", d->v_length);
960  if (d->v_flags & VF_MINGIVEN) {
961  sprintf(buf2, ", min = %lg", d->v_minsignal);
962  strcat(buf, buf2);
963  }
964  if (d->v_flags & VF_MAXGIVEN) {
965  sprintf(buf, ", max = %lg", d->v_maxsignal);
966  strcat(buf, buf2);
967  }
968  switch (d->v_gridtype) {
969 
970  case GRID_LOGLOG:
971  strcat(buf, ", grid = loglog");
972  break;
973 
974  case GRID_XLOG:
975  strcat(buf, ", grid = xlog");
976  break;
977 
978  case GRID_YLOG:
979  strcat(buf, ", grid = ylog");
980  break;
981 
982  case GRID_POLAR:
983  strcat(buf, ", grid = polar");
984  break;
985 
986  case GRID_SMITH:
987  strcat(buf, ", grid = smith");
988  break;
989  }
990  switch (d->v_plottype) {
991 
992  case PLOT_COMB:
993  strcat(buf, ", plot = comb");
994  break;
995 
996  case PLOT_POINT:
997  strcat(buf, ", plot = point");
998  break;
999 
1000  }
1001  if (d->v_defcolor) {
1002  sprintf(buf2, ", color = %s", d->v_defcolor);
1003  strcat(buf, buf2);
1004  }
1005  if (d->v_scale) {
1006  sprintf(buf2, ", scale = %s", d->v_scale->v_name);
1007  strcat(buf, buf2);
1008  }
1009  if (d->v_numdims > 1) {
1010  sprintf(buf2, ", dims = [");
1011  strcat(buf, buf2);
1012  for (i = 0; i < d->v_numdims; i++) {
1013  sprintf(buf2, "%d%s", d->v_dims[i],
1014  (i < d->v_numdims - 1) ? ", " : "]");
1015  strcat(buf, buf2);
1016  }
1017  }
1018  if (d->v_plot->pl_scale == d) {
1019  strcat(buf, " [default scale]\n");
1020  }
1021  else {
1022  strcat(buf, "\n");
1023  }
1024  out_send(buf);
1025  return;
1026 }
1027 
1028 
1029 /* Set the current working plot. */
1030 
1031 void
1033 
1034 wordlist *wl;
1035 {
1036  struct plot *p;
1037  char buf[BSIZE_SP], *s;
1038  char *zz = "Type the name of the desired plot: ";
1039 
1040  if (wl == NULL) {
1041  out_printf(" new New plot\n");
1042  for (p = plot_list; p; p = p->pl_next) {
1043  if (plot_cur == p)
1044  out_printf("Current %-11s%-20s (%s)\n",
1045  p->pl_typename, p->pl_title, p->pl_name);
1046  else
1047  out_printf(" %-11s%-20s (%s)\n",
1048  p->pl_typename, p->pl_title, p->pl_name);
1049  }
1050  out_send("\n");
1051  (void) SCEDfgets(buf,BSIZE_SP,cp_in,zz);
1052 
1053  for (s = buf; *s && !isspace(*s); s++)
1054  ;
1055  *s = '\0';
1056  }
1057  else {
1058  (void) strcpy(buf, wl->wl_word);
1059  }
1060  if (prefix("new", buf)) {
1061  p = plot_alloc("unknown");
1062  p->pl_title = copy("Anonymous");
1063  p->pl_name = copy("unknown");
1064  p->pl_next = plot_list;
1065  plot_list = p;
1066  }
1067  else {
1068  for (p = plot_list; p; p = p->pl_next)
1069  if (plot_prefix(buf, p->pl_typename))
1070  break;
1071  if (!p) {
1072  fprintf(cp_err, "Error: no such plot.\n");
1073  return;
1074  }
1075  }
1077  plot_cur = p;
1079  if (wl)
1080  out_printf("%s %s (%s)\n", p->pl_typename, p->pl_title,
1081  p->pl_name);
1082  return;
1083 }
1084 
1085 
1086 /* For the sort in display. */
1087 
1088 static int
1089 dcomp(v1, v2)
1090 
1091 struct dvec **v1, **v2;
1092 {
1093  return (strcmp((*v1)->v_name, (*v2)->v_name));
1094 }
1095 
1096 #ifdef notdef
1097 /* Figure out what the name of this vector should be (if it is a number,
1098  * then make it 'V' or 'I')... Note that the data is static.
1099  */
1100 
1101 static char *
1102 dname(d)
1103 
1104 struct dvec *d;
1105 {
1106  static char buf[128];
1107  char *s;
1108 
1109  for (s = d->v_name; *s; s++)
1110  if (!isdigit(*s))
1111  return (d->v_name);
1112  switch (d->v_type) {
1113  case SV_VOLTAGE:
1114  (void) sprintf(buf, "V(%s)", d->v_name);
1115  return (buf);
1116  case SV_CURRENT:
1117  (void) sprintf(buf, "I(%s)", d->v_name);
1118  return (buf);
1119  }
1120  return (d->v_name);
1121 }
1122 #endif
1123 
1124 /* Take a set of vectors and form a new vector of the nth elements of each. */
1125 
1126 void
1128 
1129 wordlist *wl;
1130 {
1131  char *newvec, *s;
1132  struct dvec *n, *v;
1133  struct pnode *pn, *p0;
1134  struct dvlist *dl, *tl, *dl0;
1135  int i, ind;
1136  bool comp = false;
1137  double *d;
1138 
1139  newvec = wl->wl_word;
1140  wl = wl->wl_next;
1141  s = wl->wl_word;
1142  if (!(d = ft_numparse(&s, false))) {
1143  fprintf(cp_err, "Error: bad number %s\n", wl->wl_word);
1144  return;
1145  }
1146  if ((ind = *d) < 0) {
1147  fprintf(cp_err, "Error: bad index %d\n", ind);
1148  return;
1149  }
1150  wl = wl->wl_next;
1151  p0 = ft_getpnames(wl, true);
1152  if (p0 == NULL)
1153  return;
1154 
1155  dl0 = NULL;
1156  for (pn = p0; pn; pn = pn->pn_next) {
1157  if ((n = ft_evaluate(pn)) == NULL) {
1158  inp_pnfree(p0);
1159  vec_dlfree(dl0);
1160  return;
1161  }
1162  if (!dl0)
1163  dl0 = dl = alloc(struct dvlist);
1164  else {
1165  dl->dl_next = alloc(struct dvlist);
1166  dl = dl->dl_next;
1167  }
1168  if (n->v_link2) {
1169  for (tl = n->v_link2; tl; tl = tl->dl_next) {
1170  dl->dl_dvec = tl->dl_dvec;
1171  if (tl->dl_next) {
1172  dl->dl_next = alloc(struct dvlist);
1173  dl = dl->dl_next;
1174  }
1175  }
1176  }
1177  else
1178  dl->dl_dvec = n;
1179  }
1180  inp_pnfree(p0);
1181 
1182  for (dl = dl0; dl; dl = dl->dl_next) {
1183  if (iscomplex(dl->dl_dvec))
1184  comp = true;
1185  i++;
1186  }
1187 
1188  vec_remove(newvec);
1189  v = alloc(struct dvec);
1190  v->v_name = copy(newvec);
1191  v->v_type = dl0->dl_dvec ? dl0->dl_dvec->v_type : SV_NOTYPE;
1192  v->v_length = i;
1193  v->v_flags = comp ? VF_COMPLEX : VF_REAL;
1194  vec_newperm(v);
1195  if (comp)
1196  v->v_compdata = (complex *) tmalloc(i * sizeof (complex));
1197  else
1198  v->v_realdata = (double *) tmalloc(i * sizeof (double));
1199 
1200  /* Now copy the ind'ths elements into this one. */
1201  for (dl = dl0, i = 0; dl; dl = dl->dl_next, i++) {
1202  n = dl->dl_dvec;
1203  if (n->v_length > ind) {
1204  if (comp) {
1205  realpart(&v->v_compdata[i]) =
1206  realpart(&n->v_compdata[ind]);
1207  imagpart(&v->v_compdata[i]) =
1208  imagpart(&n->v_compdata[ind]);
1209  }
1210  else
1211  v->v_realdata[i] = n->v_realdata[ind];
1212  }
1213  else {
1214  if (comp) {
1215  realpart(&v->v_compdata[i]) = 0.0;
1216  imagpart(&v->v_compdata[i]) = 0.0;
1217  }
1218  else
1219  v->v_realdata[i] = 0.0;
1220  }
1221  }
1223  vec_dlfree(dl0);
1224  return;
1225 }
1226 
1227 
1228 void
1230 
1231 wordlist *wl;
1232 {
1233  struct plot *pl, *npl = NULL;
1234 
1235  if (!wl) {
1236  if (!eq(plot_cur->pl_typename, "constants") && !plot_cur->pl_active)
1238  }
1239  else if (eq(wl->wl_word, "all")) {
1240  for (pl = plot_list; pl; pl = npl) {
1241  npl = pl->pl_next;
1242  if (!eq(pl->pl_typename, "constants") && !pl->pl_active)
1243  plot_delete(pl);
1244  }
1245  }
1246  else {
1247  while (wl) {
1248  for (pl = plot_list; pl; pl = pl->pl_next)
1249  if (eq(pl->pl_typename, wl->wl_word))
1250  break;
1251  if (pl && !pl->pl_active)
1252  plot_delete(pl);
1253  else
1254  fprintf(cp_err, "Error: no such plot %s\n",
1255  wl->wl_word);
1256  wl = wl->wl_next;
1257  }
1258  }
1259  return;
1260 }
1261 
static int dcomp()
struct dvec * ft_evaluate()
static char buf[MAXPROMPT]
Definition: arg.c:18
#define BSIZE_SP
Definition: misc.h:19
#define eq(a, b)
Definition: misc.h:29
#define loop
Definition: cdmacs.h:11
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
struct plot * plot_alloc()
void plot_docoms()
char * pl_typename
Definition: ftedata.h:65
char * pl_date
Definition: ftedata.h:63
void com_destroy(wordlist *wl)
Definition: postcoms.c:1229
#define VF_REAL
Definition: fteconst.h:39
char * kw_appendwrite
Definition: options.c:337
struct dvlist * v_link2
Definition: ftedata.h:44
char * pl_title
Definition: ftedata.h:62
void vec_remove()
#define prefix(x, y)
Definition: readhelp.c:39
char * printnum()
void out_printf()
char * strcpy()
char * pl_name
Definition: ftedata.h:64
Definition: cddefs.h:119
struct plot * plot_cur
Definition: vectors.c:43
struct dvlist * ft_dvlist()
if(TDesc==NULL)
Definition: cd.c:1326
struct dvec * pl_dvecs
Definition: ftedata.h:67
Definition: ftedata.h:49
void com_cross(wordlist *wl)
Definition: postcoms.c:1127
struct pnode * ft_getpnames()
char * vec_basename()
double cx_imag
Definition: cpstd.h:31
void com_splot(wordlist *wl)
Definition: postcoms.c:1032
double * ft_numparse()
Definition: cpstd.h:29
FILE * p
Definition: proc2mod.c:48
#define SV_VOLTAGE
Definition: fteconst.h:14
Definition: ftedata.h:61
int out_width
Definition: output.c:46
Definition: library.c:18
int v_dims[MAXDIMS]
Definition: ftedata.h:41
void com_let(wordlist *wl)
Definition: postcoms.c:28
void * pl_hashtab
Definition: ftedata.h:66
#define alloc(type)
Definition: cdmacs.h:21
complex * v_compdata
Definition: ftedata.h:29
#define DCOPY(s, d, n)
Definition: ftedefs.h:55
#define CCOPY(s, d, n)
Definition: ftedefs.h:59
void cp_unquote()
char * copy()
#define DEF_WIDTH
Definition: ftedefs.h:15
void * htab_wl()
double cx_real
Definition: cpstd.h:30
static struct dvec * copyvec()
char * pl_ccom
Definition: ftedata.h:72
void raw_write()
char * kw_filetype
Definition: options.c:355
struct dvlist * dl_next
Definition: ftedata.h:51
void wl_free()
void inp_pnfree()
void com_print(wordlist *wl)
Definition: postcoms.c:421
char * ft_rawfile
Definition: main.c:39
FILE * cp_err
Definition: help.c:101
void com_display(wordlist *wl)
Definition: postcoms.c:878
char * tmalloc()
void * htab_init()
Definition: hash.c:27
Definition: cddefs.h:237
void htab_free()
#define tfree(x)
Definition: cdmacs.h:22
struct dvec * vec_get()
int AsciiRawFile
#define MAXDIMS
Definition: ftedata.h:22
void txfree()
int pl_active
Definition: ftedata.h:75
struct dvec * pl_scale
Definition: ftedata.h:68
bool vec_eq()
bool plot_prefix()
#define NULL
Definition: spdefs.h:121
void vec_newperm()
#define DEF_HEIGHT
Definition: ftedefs.h:16
bool out_isatty
Definition: output.c:45
GRIDTYPE v_gridtype
Definition: ftedata.h:32
bool pl_written
Definition: ftedata.h:73
struct plot * v_plot
Definition: ftedata.h:42
char * v_defcolor
Definition: ftedata.h:39
struct dvec * v_scale
Definition: ftedata.h:45
void com_write(wordlist *wl)
Definition: postcoms.c:699
struct pnode * pn_next
Definition: fteparse.h:23
char * SCEDfgets(char *s, int n, FILE *fp, char *prompt)
Definition: scedstub.c:41
void com_load(wordlist *wl)
Definition: postcoms.c:401
#define VT_STRING
Definition: cpstd.h:63
#define isreal(v)
Definition: ftedata.h:54
Definition: ftedata.h:24
struct dvec * dl_dvec
Definition: ftedata.h:50
char * v_name
Definition: ftedata.h:25
#define imagpart(cval)
Definition: cpstd.h:36
#define VT_BOOL
Definition: cpstd.h:60
char * ft_typenames()
int pl_ndims
Definition: ftedata.h:74
Definition: cpstd.h:21
#define SV_CURRENT
Definition: fteconst.h:15
void com_unlet(wordlist *wl)
Definition: postcoms.c:386
#define VF_MAXGIVEN
Definition: fteconst.h:45
#define iscomplex(v)
Definition: ftedata.h:55
void vec_dlfree()
struct plot * pl_next
Definition: ftedata.h:69
int out_height
Definition: output.c:47
int v_type
Definition: ftedata.h:26
static void pvec()
struct plot * plot_list
Definition: vectors.c:44
void htab_add()
void * htab_get()
void out_send()
struct wordlist * wl_next
Definition: cpstd.h:23
struct _complex complex
Definition: cpstd.h:33
int v_numdims
Definition: ftedata.h:40
PLOTTYPE v_plottype
Definition: ftedata.h:33
void bcopy(char *from, char *to, int num)
Definition: string.c:339
char * wl_word
Definition: cpstd.h:22
void wl_sort()
void out_winsize()
int v_length
Definition: ftedata.h:34
char * kw_noprintscale
Definition: options.c:393
FILE * cp_in
Definition: help.c:101
short v_flags
Definition: ftedata.h:27
wordlist * pl_commands
Definition: ftedata.h:70
double * v_realdata
Definition: ftedata.h:28
void cp_addkword()
char * wl_flatten()
void ft_loadfile()
Definition: cddefs.h:192
#define VF_COMPLEX
Definition: fteconst.h:40
bool ft_nopage
Definition: options.c:23
char * trealloc()
void * htab_list()
void plot_delete()
char * kw_nobreak
Definition: options.c:381
struct dvec * vec_copy()
char * kw_nosort
Definition: options.c:394
#define VF_MINGIVEN
Definition: fteconst.h:44
#define realpart(cval)
Definition: cpstd.h:35
Definition: fteparse.h:16
#define CT_VECTOR
Definition: fteconst.h:96
char * cp_kwswitch()
#define SV_NOTYPE
Definition: fteconst.h:11