ngspice/src/frontend/newcoms.c

220 lines
5.9 KiB
C

/**********
Copyright 1992 Regents of the University of California. All rights reserved.
**********/
/*
* Some new post-processor commands having to do with vectors.
*/
#include "ngspice/ngspice.h"
#include "ngspice/cpdefs.h"
#include "ngspice/ftedefs.h"
#include "ngspice/fteparse.h"
#include "ngspice/dvec.h"
#include "newcoms.h"
#include "quote.h"
/*
* reshape v(1) vxx#branch [10]
* reshape v(1) vxx#branch [10,4]
* reshape v(1) [,4]
*/
void
com_reshape(wordlist *wl)
{
wordlist *w, *w2, *wlast, *wsave;
char *p;
struct dvec *dv, *d;
int numdims;
int *dims;
int local_dims[MAXDIMS];
int state;
int empty;
int err;
int missing, nprod, prod;
char *vname;
int i;
do {
if (!wl)
return;
/* find the first '[' */
p = NULL;
for (w = wl; w; w = w->wl_next) {
if ((p = strchr(w->wl_word, '[')) != NULL)
break;
}
if (p && *p) {
if (p != w->wl_word)
w = w->wl_next;
wlast = w;
*p++ = 0;
} else {
wlast = NULL;
}
/* get the dimensions */
dims = local_dims;
numdims = 0;
state = 0;
empty = -1;
err = 0;
wsave = NULL;
do {
if (!p || !*p) {
if (!wlast)
break;
p = wlast->wl_word;
if (state == 2)
wsave = wlast;
else
wsave = NULL;
wlast = wlast->wl_next;
}
while (*p && isspace(*p))
p++;
switch (state) {
case 0: /* p just at or before a number */
if (numdims >= MAXDIMS) {
if (numdims == MAXDIMS)
printf("Maximum of %d dimensions possible\n", MAXDIMS);
numdims += 1;
} else if (!isdigit(*p)) {
if (empty > -1) {
printf("dimensions underspecified at dimension %d\n",
numdims++);
err = 1;
} else {
empty = numdims;
dims[numdims++] = 1;
}
} else {
dims[numdims++] = atoi(p);
while (isdigit(*p))
p++;
}
state = 1;
break;
case 1: /* p after a number, looking for ',' or ']' */
if (*p == ']') {
p++;
state = 2;
} else if (*p == ',') {
p++;
state = 0;
} else if (isdigit(*p)) {
state = 0;
break;
} else if (!isspace(*p)) {
/* error */
state = 4;
}
break;
case 2: /* p after a ']', either at the end or looking for '[' */
if (*p == '[') {
p++;
state = 0;
} else {
state = 3;
}
}
while (*p && isspace(*p))
p++;
} while (state < 3);
if (state == 2) {
wlast = wsave;
} else if ((state == 4 || state < 2) && ((state != 0 || p) && *p)) {
printf("syntax error specifying dimensions\n");
return;
}
if (numdims > MAXDIMS)
continue;
if (err)
continue;
/* Copy dimensions from the first item if none are explicitly given */
if (!numdims) {
/* Copy from the first */
vname = cp_unquote(wl->wl_word);
dv = vec_get(vname);
if (!dv) {
printf("'%s' dimensions vector not found\n", vname);
return;
}
numdims = dv->v_numdims;
dims = dv->v_dims;
wl = wl->wl_next;
empty = -1; /* just in case */
}
prod = 1;
for (i = 0; i < numdims; i++)
prod *= dims[i];
/* resize each vector */
for (w2 = wl; w2 && w2 != w; w2 = w2->wl_next) {
vname = cp_unquote(w2->wl_word);
dv = vec_get(vname);
if (!dv) {
printf("'%s' vector not found\n", vname);
continue;
}
/* The name may expand to several vectors */
for (d = dv; d; d = d->v_link2) {
nprod = 1;
for (i = 0; i < d->v_numdims; i++)
nprod *= d->v_dims[i];
if (nprod != d->v_length) {
printf("dimensions of \"%s\" were inconsistent\n",
d->v_name);
nprod = d->v_length;
}
missing = nprod / prod;
if (missing * prod != nprod) {
printf("dimensions don't fit \"%s\" (total size = %d)\n",
d->v_name, nprod);
continue;
}
if (missing > 1 && empty < 0) {
/* last dimension unspecified */
d->v_numdims = numdims + 1;
d->v_dims[numdims] = missing;
} else {
d->v_numdims = numdims;
}
/* fill in dimensions */
for (i = 0; i < numdims; i++) {
if (i == empty)
d->v_dims[i] = missing;
else
d->v_dims[i] = dims[i];
}
}
if (vname)
tfree(vname);
}
} while ((wl = wlast) != NULL);
}