📄 vectors.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group $Id: vectors.c,v 1.8 2005/05/26 19:29:52 sjborley Exp $**********//* * Routines for dealing with the vector database. */#include <ngspice.h>#include <cpdefs.h>#include <ftedefs.h>#include <dvec.h>#include <sim.h>#include "circuits.h"#include "completion.h"#include "variable.h"#include "vectors.h"#include "plotting/plotting.h"#ifdef XSPICE/* gtri - begin - add function prototype for EVTfindvec */struct dvec *EVTfindvec(char *node);/* gtri - end - add function prototype for EVTfindvec */#endif/* Find a named vector in a plot. We are careful to copy the vector if * v_link2 is set, because otherwise we will get screwed up. */static struct dvec *findvec(char *word, struct plot *pl){ struct dvec *d, *newv = NULL, *end = NULL, *v; char buf[BSIZE_SP]; if (pl == NULL) return (NULL); if (cieq(word, "all")) { for (d = pl->pl_dvecs; d; d = d->v_next) { if (d->v_flags & VF_PERMANENT) { if (d->v_link2) { v = vec_copy(d); vec_new(v); } else v = d; if (end) end->v_link2 = v; else newv = v; end = v; } } return (newv); } for (d = pl->pl_dvecs; d; d = d->v_next) if (cieq(word, d->v_name) && (d->v_flags & VF_PERMANENT)) break; if (!d) { (void) sprintf(buf, "v(%s)", word); for (d = pl->pl_dvecs; d; d = d->v_next) if (cieq(buf, d->v_name) && (d->v_flags & VF_PERMANENT)) break; }#ifdef XSPICE/* gtri - begin - Add processing for getting event-driven vector */ if(!d) d = EVTfindvec(word);/* gtri - end - Add processing for getting event-driven vector */#endif if (d && d->v_link2) { d = vec_copy(d); vec_new(d); } return (d);}/* If there are imbedded numeric strings, compare them numerically, not * alphabetically. */static intnamecmp(const void *a, const void *b){ int i, j; char *s = (char *) a; char *t = (char *) b; for (;;) { while ((*s == *t) && !isdigit(*s) && *s) s++, t++; if (!*s) return (0); if ((*s != *t) && (!isdigit(*s) || !isdigit(*t))) return (*s - *t); /* The beginning of a number... Grab the two numbers and then * compare them... */ for (i = 0; isdigit(*s); s++) i = i * 10 + *s - '0'; for (j = 0; isdigit(*t); t++) j = j * 10 + *t - '0'; if (i != j) return (i - j); }}static intveccmp(const void *a, const void *b){ int i; struct dvec **d1 = (struct dvec **) a; struct dvec **d2 = (struct dvec **) b; if ((i = namecmp((*d1)->v_plot->pl_typename, (*d2)->v_plot->pl_typename)) != 0) return (i); return (namecmp((*d1)->v_name, (*d2)->v_name));}/* Sort all the vectors in d, first by plot name and then by vector * name. Do the right thing with numbers. */static struct dvec *sortvecs(struct dvec *d){ struct dvec **array, *t; int i, j; for (t = d, i = 0; t; t = t->v_link2) i++; if (i < 2) return (d); array = (struct dvec **) tmalloc(i * sizeof (struct dvec *)); for (t = d, i = 0; t; t = t->v_link2) array[i++] = t; qsort((char *) array, i, sizeof (struct dvec *), veccmp); /* Now string everything back together... */ for (j = 0; j < i - 1; j++) array[j]->v_link2 = array[j + 1]; array[j]->v_link2 = NULL; d = array[0]; tfree(array); return (d);}/* Load in a rawfile. */voidft_loadfile(char *file){ struct plot *pl, *np, *pp; fprintf(cp_out, "Loading raw data file (\"%s\") . . . ", file); pl = raw_read(file); if (pl) fprintf(cp_out, "done.\n"); else fprintf(cp_out, "no data read.\n"); /* This is a minor annoyance -- we should reverse the plot list so * they get numbered in the correct order. */ for (pp = pl, pl = NULL; pp; pp = np) { np = pp->pl_next; pp->pl_next = pl; pl = pp; } for (; pl; pl = np) { np = pl->pl_next; plot_add(pl); /* Don't want to get too many "plot not written" messages. */ pl->pl_written = TRUE; } plot_num++; plotl_changed = TRUE; return;}voidplot_add(struct plot *pl){ struct dvec *v; struct plot *tp; char *s, buf[BSIZE_SP]; fprintf(cp_out, "Title: %s\nName: %s\nDate: %s\n\n", pl->pl_title, pl->pl_name, pl->pl_date); if (plot_cur) plot_cur->pl_ccom = cp_kwswitch(CT_VECTOR, pl->pl_ccom); for (v = pl->pl_dvecs; v; v = v->v_next) cp_addkword(CT_VECTOR, v->v_name); cp_addkword(CT_VECTOR, "all"); if (!(s = ft_plotabbrev(pl->pl_name))) s = "unknown"; do { (void) sprintf(buf, "%s%d", s, plot_num); for (tp = plot_list; tp; tp = tp->pl_next) if (cieq(tp->pl_typename, buf)) { plot_num++; break; } } while (tp); pl->pl_typename = copy(buf); plot_new(pl); cp_addkword(CT_PLOT, buf); pl->pl_ccom = cp_kwswitch(CT_VECTOR, (char *) NULL); plot_setcur(pl->pl_typename); return;}/* Remove a vector from the database, if it is there. */voidvec_remove(char *name){ struct dvec *ov; for (ov = plot_cur->pl_dvecs; ov; ov = ov->v_next) { if (cieq(name, ov->v_name) && (ov->v_flags & VF_PERMANENT)) break; } if (!ov) return; ov->v_flags &= ~VF_PERMANENT; /* Remove from the keyword list. */ cp_remkword(CT_VECTOR, name); return;}/* Get a vector by name. This deals with v(1), etc. almost properly. Also, * it checks for pre-defined vectors. */struct dvec *vec_fromplot(char *word, struct plot *plot){ struct dvec *d; char buf[BSIZE_SP], buf2[BSIZE_SP], cc, *s; d = findvec(word, plot); if (!d) { (void) strcpy(buf, word); for (s = buf; *s; s++) if (isupper(*s)) *s = tolower(*s); d = findvec(buf, plot); } if (!d) { (void) strcpy(buf, word); for (s = buf; *s; s++) if (islower(*s)) *s = *s - 'a' + 'A'; d = findvec(buf, plot); } /* scanf("%c(%s)" doesn't do what it should do. ) */ if (!d && (sscanf(word, "%c(%s", /* ) */ &cc, buf) == 2) && /* ( */ ((s =strrchr(buf, ')')) != NULL) && (*(s + 1) == '\0')) { *s = '\0'; if (prefix("i(", /* ) */ word)) { /* Spice dependency... */ (void) sprintf(buf2, "%s#branch", buf); (void) strcpy(buf, buf2); } d = findvec(buf, plot); } return (d);}/* This is the main lookup routine for names. The possible types of names are: * name An ordinary vector. * plot.name A vector from a particular plot. * @device[parm] A device parameter. * @model[parm] A model parameter. * @param A circuit parameter. * For the @ cases, we construct a dvec with length 1 to hold the value. * In the other two cases, either the plot or the name can be "all", a * wildcard. * The vector name may have imbedded dots -- if the first component is a plot * name, it is considered the plot, otherwise the current plot is used. */#define SPECCHAR '@'struct dvec *vec_get(char *word){ struct dvec *d, *end = NULL, *newv = NULL; struct plot *pl; char buf[BSIZE_SP], *s, *wd, *whole, *name = NULL, *param; int i = 0; struct variable *vv; wd = word = copy(word); /* Gets mangled below... */ if (index(word, '.')) { /* Snag the plot... */ for (i = 0, s = word; *s != '.'; i++, s++) buf[i] = *s; buf[i] = '\0'; if (cieq(buf, "all")) { word = ++s; pl = NULL; /* NULL pl signifies a wildcard. */ } else { for (pl = plot_list; pl && !plot_prefix(buf, pl->pl_typename); pl = pl->pl_next) ; if (pl) { word = ++s; } else { /* This used to be an error... */ pl = plot_cur; } } } else pl = plot_cur; if (pl) { d = vec_fromplot(word, pl); if (!d) d = vec_fromplot(word, &constantplot); } else { for (pl = plot_list; pl; pl = pl->pl_next) { if (cieq(pl->pl_typename, "const")) continue; d = vec_fromplot(word, pl); if (d) { if (end) end->v_link2 = d; else newv = d; for (end = d; end->v_link2; end = end->v_link2) ; } } d = newv; if (!d) { fprintf(cp_err, "Error: plot wildcard (name %s) matches nothing\n", word); tfree(wd); /* MW. I don't want core leaks here */ return (NULL); } } if (!d && (*word == SPECCHAR)) { /* This is a special quantity... */ if (ft_nutmeg) { fprintf(cp_err, "Error: circuit parameters only available with spice\n"); tfree(wd); /* MW. Memory leak fixed again */ return (NULL); /* va: use NULL */ } whole=copy(word); name = ++word; for (param = name; *param && (*param != '['); param++) ; if (*param) { *param++ = '\0'; for (s = param; *s && *s != ']'; s++) ; *s = '\0'; } else param = NULL; if (ft_curckt) { vv = (*if_getparam)(ft_curckt->ci_ckt, &name, param, 0, 0); if (!vv) { tfree(whole); tfree(wd); return (NULL); } } else { fprintf(cp_err, "Error: No circuit loaded.\n"); tfree(whole); tfree(wd); return (NULL); } d = alloc(struct dvec); ZERO(d, struct dvec); d->v_name = copy(whole); /* MW. The same as word before */ d->v_type = SV_NOTYPE; d->v_flags |= VF_REAL; /* No complex values yet... */ d->v_realdata = (double *) tmalloc(sizeof (double)); d->v_length = 1; *d->v_realdata = vv->va_real; tfree(vv->va_name); tfree(vv); /* va: tfree vv->va_name and vv (avoid memory leakages) */ tfree(wd); vec_new(d); tfree(whole); return (d); } tfree(wd); return (sortvecs(d));}/* Execute the commands for a plot. This is done whenever a plot becomes * the current plot. */voidplot_docoms(wordlist *wl){ bool inter; inter = cp_interactive; cp_interactive = FALSE; while (wl) { (void) cp_evloop(wl->wl_word); wl = wl->wl_next; } cp_resetcontrol(); cp_interactive = inter; return;}/* Create a copy of a vector. */struct dvec *vec_copy(struct dvec *v){ struct dvec *nv; int i; if (!v) return (NULL); nv = alloc(struct dvec);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -