ngspice/src/frontend/dotcards.c

544 lines
14 KiB
C
Raw Normal View History

2000-04-27 22:03:57 +02:00
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
**********/
/*
* Spice-2 compatibility stuff for .plot, .print, .four, and .width.
*/
#include "ngspice.h"
#include "cpdefs.h"
#include "ftedefs.h"
* src/Makefile.am src/main.c src/sconvert.c src/analysis/cktdisto.c src/analysis/cktnoise.c src/analysis/noisean.c: Updates for the new header files. * src/maths/cmaths/cmath1.c src/maths/cmaths/cmath2.c src/maths/cmaths/cmath3.c src/maths/cmaths/cmath4.c: Updates for the new header files. * src/frontend/.cvsignore src/frontend/Makefile.am: Updates for the new files. * src/frontend/agraf.c src/frontend/aspice.c src/frontend/breakp.c src/frontend/breakp2.c src/frontend/circuits.c src/frontend/cpitf.c src/frontend/debugcom.c src/frontend/define.c src/frontend/diff.c src/frontend/dimens.c src/frontend/display.c src/frontend/doplot.c src/frontend/dotcards.c src/frontend/evaluate.c src/frontend/fourier.c src/frontend/graf.c src/frontend/grid.c src/frontend/inp.c src/frontend/inpcom.c src/frontend/interp.c src/frontend/linear.c src/frontend/misccoms.c src/frontend/misccoms.h src/frontend/miscvars.c src/frontend/mw_coms.c src/frontend/newcoms.c src/frontend/nutinp.c src/frontend/options.c src/frontend/outitf.c src/frontend/parse.c src/frontend/plotcurv.c src/frontend/points.c src/frontend/postcoms.c src/frontend/rawfile.c src/frontend/runcoms.c src/frontend/runcoms2.c src/frontend/shyu.c src/frontend/spec.c src/frontend/spiceif.c src/frontend/typesdef.c src/frontend/vectors.c src/frontend/where.c src/frontend/postcoms.c: Updates for the new header files. Some commands have moved into the new files below. * src/frontend/README src/frontend/com_compose.c src/frontend/com_compose.h src/frontend/com_display.c src/frontend/com_display.h src/frontend/com_let.c src/frontend/com_let.h src/frontend/com_setscale.c src/frontend/com_setscale.h src/frontend/commands.c src/frontend/commands.h src/frontend/completion.h src/frontend/streams.h src/frontend/testcommands.c: Separation into different com_* commands. This is a start. The rest of the subdirectory needs doing. * src/include/complex.h src/include/cpdefs.h src/include/cpextern.h src/include/cpstd.h src/include/fteconst.h src/include/ftedata.h src/include/ftedev.h src/include/fteext.h src/include/ftegraph.h src/include/fteparse.h src/include/dvec.h src/include/grid.h src/include/plot.h src/include/pnode.h src/include/sim.h src/include/variable.h src/include/wordlist.h src/include/bool.h: Separation of header files into smaller pieces. This limits recompilation to only the affected source files. The original header files have a warning message embedded to flag obsoleted use. * src/frontend/compose.c src/frontend/compose.h src/frontend/nutctab.c src/frontend/nutctab.h src/frontend/plot5.c src/frontend/plot5.h src/frontend/spcmdtab.c src/frontend/x11.c src/frontend/x11.h src/frontend/xgraph.c src/frontend/xgraph.h: Moved these files into src/frontend/plotting subdirectory. * src/frontend/plotting/.cvsignore src/frontend/plotting/Makefile.am src/frontend/plotting/plot5.c src/frontend/plotting/plot5.h src/frontend/plotting/plotting.c src/frontend/plotting/plotting.h src/frontend/plotting/pvec.c src/frontend/plotting/pvec.h src/frontend/plotting/x11.c src/frontend/plotting/x11.h src/frontend/plotting/xgraph.c src/frontend/plotting/xgraph.h: The new libplotting library with automake and CVS infrastructure.
2000-05-06 16:12:51 +02:00
#include "dvec.h"
2000-04-27 22:03:57 +02:00
#include "fteinp.h"
* src/Makefile.am src/main.c src/sconvert.c src/analysis/cktdisto.c src/analysis/cktnoise.c src/analysis/noisean.c: Updates for the new header files. * src/maths/cmaths/cmath1.c src/maths/cmaths/cmath2.c src/maths/cmaths/cmath3.c src/maths/cmaths/cmath4.c: Updates for the new header files. * src/frontend/.cvsignore src/frontend/Makefile.am: Updates for the new files. * src/frontend/agraf.c src/frontend/aspice.c src/frontend/breakp.c src/frontend/breakp2.c src/frontend/circuits.c src/frontend/cpitf.c src/frontend/debugcom.c src/frontend/define.c src/frontend/diff.c src/frontend/dimens.c src/frontend/display.c src/frontend/doplot.c src/frontend/dotcards.c src/frontend/evaluate.c src/frontend/fourier.c src/frontend/graf.c src/frontend/grid.c src/frontend/inp.c src/frontend/inpcom.c src/frontend/interp.c src/frontend/linear.c src/frontend/misccoms.c src/frontend/misccoms.h src/frontend/miscvars.c src/frontend/mw_coms.c src/frontend/newcoms.c src/frontend/nutinp.c src/frontend/options.c src/frontend/outitf.c src/frontend/parse.c src/frontend/plotcurv.c src/frontend/points.c src/frontend/postcoms.c src/frontend/rawfile.c src/frontend/runcoms.c src/frontend/runcoms2.c src/frontend/shyu.c src/frontend/spec.c src/frontend/spiceif.c src/frontend/typesdef.c src/frontend/vectors.c src/frontend/where.c src/frontend/postcoms.c: Updates for the new header files. Some commands have moved into the new files below. * src/frontend/README src/frontend/com_compose.c src/frontend/com_compose.h src/frontend/com_display.c src/frontend/com_display.h src/frontend/com_let.c src/frontend/com_let.h src/frontend/com_setscale.c src/frontend/com_setscale.h src/frontend/commands.c src/frontend/commands.h src/frontend/completion.h src/frontend/streams.h src/frontend/testcommands.c: Separation into different com_* commands. This is a start. The rest of the subdirectory needs doing. * src/include/complex.h src/include/cpdefs.h src/include/cpextern.h src/include/cpstd.h src/include/fteconst.h src/include/ftedata.h src/include/ftedev.h src/include/fteext.h src/include/ftegraph.h src/include/fteparse.h src/include/dvec.h src/include/grid.h src/include/plot.h src/include/pnode.h src/include/sim.h src/include/variable.h src/include/wordlist.h src/include/bool.h: Separation of header files into smaller pieces. This limits recompilation to only the affected source files. The original header files have a warning message embedded to flag obsoleted use. * src/frontend/compose.c src/frontend/compose.h src/frontend/nutctab.c src/frontend/nutctab.h src/frontend/plot5.c src/frontend/plot5.h src/frontend/spcmdtab.c src/frontend/x11.c src/frontend/x11.h src/frontend/xgraph.c src/frontend/xgraph.h: Moved these files into src/frontend/plotting subdirectory. * src/frontend/plotting/.cvsignore src/frontend/plotting/Makefile.am src/frontend/plotting/plot5.c src/frontend/plotting/plot5.h src/frontend/plotting/plotting.c src/frontend/plotting/plotting.h src/frontend/plotting/pvec.c src/frontend/plotting/pvec.h src/frontend/plotting/x11.c src/frontend/plotting/x11.h src/frontend/plotting/xgraph.c src/frontend/plotting/xgraph.h: The new libplotting library with automake and CVS infrastructure.
2000-05-06 16:12:51 +02:00
#include <sim.h>
2000-04-27 22:03:57 +02:00
* src/Makefile.am src/main.c src/sconvert.c src/analysis/cktdisto.c src/analysis/cktnoise.c src/analysis/noisean.c: Updates for the new header files. * src/maths/cmaths/cmath1.c src/maths/cmaths/cmath2.c src/maths/cmaths/cmath3.c src/maths/cmaths/cmath4.c: Updates for the new header files. * src/frontend/.cvsignore src/frontend/Makefile.am: Updates for the new files. * src/frontend/agraf.c src/frontend/aspice.c src/frontend/breakp.c src/frontend/breakp2.c src/frontend/circuits.c src/frontend/cpitf.c src/frontend/debugcom.c src/frontend/define.c src/frontend/diff.c src/frontend/dimens.c src/frontend/display.c src/frontend/doplot.c src/frontend/dotcards.c src/frontend/evaluate.c src/frontend/fourier.c src/frontend/graf.c src/frontend/grid.c src/frontend/inp.c src/frontend/inpcom.c src/frontend/interp.c src/frontend/linear.c src/frontend/misccoms.c src/frontend/misccoms.h src/frontend/miscvars.c src/frontend/mw_coms.c src/frontend/newcoms.c src/frontend/nutinp.c src/frontend/options.c src/frontend/outitf.c src/frontend/parse.c src/frontend/plotcurv.c src/frontend/points.c src/frontend/postcoms.c src/frontend/rawfile.c src/frontend/runcoms.c src/frontend/runcoms2.c src/frontend/shyu.c src/frontend/spec.c src/frontend/spiceif.c src/frontend/typesdef.c src/frontend/vectors.c src/frontend/where.c src/frontend/postcoms.c: Updates for the new header files. Some commands have moved into the new files below. * src/frontend/README src/frontend/com_compose.c src/frontend/com_compose.h src/frontend/com_display.c src/frontend/com_display.h src/frontend/com_let.c src/frontend/com_let.h src/frontend/com_setscale.c src/frontend/com_setscale.h src/frontend/commands.c src/frontend/commands.h src/frontend/completion.h src/frontend/streams.h src/frontend/testcommands.c: Separation into different com_* commands. This is a start. The rest of the subdirectory needs doing. * src/include/complex.h src/include/cpdefs.h src/include/cpextern.h src/include/cpstd.h src/include/fteconst.h src/include/ftedata.h src/include/ftedev.h src/include/fteext.h src/include/ftegraph.h src/include/fteparse.h src/include/dvec.h src/include/grid.h src/include/plot.h src/include/pnode.h src/include/sim.h src/include/variable.h src/include/wordlist.h src/include/bool.h: Separation of header files into smaller pieces. This limits recompilation to only the affected source files. The original header files have a warning message embedded to flag obsoleted use. * src/frontend/compose.c src/frontend/compose.h src/frontend/nutctab.c src/frontend/nutctab.h src/frontend/plot5.c src/frontend/plot5.h src/frontend/spcmdtab.c src/frontend/x11.c src/frontend/x11.h src/frontend/xgraph.c src/frontend/xgraph.h: Moved these files into src/frontend/plotting subdirectory. * src/frontend/plotting/.cvsignore src/frontend/plotting/Makefile.am src/frontend/plotting/plot5.c src/frontend/plotting/plot5.h src/frontend/plotting/plotting.c src/frontend/plotting/plotting.h src/frontend/plotting/pvec.c src/frontend/plotting/pvec.h src/frontend/plotting/x11.c src/frontend/plotting/x11.h src/frontend/plotting/xgraph.c src/frontend/plotting/xgraph.h: The new libplotting library with automake and CVS infrastructure.
2000-05-06 16:12:51 +02:00
#include "dotcards.h"
2000-04-27 22:03:57 +02:00
/* Extract all the .save lines */
static void fixdotplot(wordlist *wl);
static void fixdotprint(wordlist *wl);
static char * fixem(char *string);
static bool setcplot(char *name);
static wordlist * gettoks(char *s);
extern void com_save2 (wordlist *wl, char *name);
void
ft_dotsaves(void)
{
wordlist *iline, *wl = NULL;
char *s;
if (!ft_curckt) /* Shouldn't happen. */
return;
for (iline = ft_curckt->ci_commands; iline; iline = iline->wl_next) {
if (ciprefix(".save", iline->wl_word)) {
s = iline->wl_word;
(void) gettok(&s);
wl = wl_append(wl, gettoks(s));
}
}
com_save(wl);
return;
}
/* Go through the dot lines given and make up a big "save" command with
* all the node names mentioned. Note that if a node is requested for
* one analysis, it is saved for all of them.
*/
static char *plot_opts[ ] = {
"linear",
"xlog",
"ylog",
"loglog"
};
int
ft_savedotargs(void)
{
wordlist *w, *wl = NULL, *iline, **prev_wl, *w_next;
char *name;
char *s;
int some = 0;
static wordlist all = { "all", NULL };
int isaplot;
int i;
if (!ft_curckt) /* Shouldn't happen. */
return 0;
for (iline = ft_curckt->ci_commands; iline; iline = iline->wl_next) {
s = iline->wl_word;
if (ciprefix(".plot", s))
isaplot = 1;
else
isaplot = 0;
if (isaplot || ciprefix(".print", s)) {
(void) gettok(&s);
name = gettok(&s);
if (!(w = gettoks(s))) {
fprintf(cp_err, "Warning: no nodes given: %s\n",
iline->wl_word);
} else {
if (isaplot) {
prev_wl = &w;
for (wl = w; wl; wl = w_next) {
w_next = wl->wl_next;
for (i = 0; i < NUMELEMS(plot_opts); i++) {
if (!strcmp(wl->wl_word, plot_opts[i])) {
/* skip it */
*prev_wl = w_next;
tfree(wl);
break;
}
}
if (i == NUMELEMS(plot_opts))
prev_wl = &wl->wl_next;
}
}
some = 1;
com_save2(w, name);
}
} else if (ciprefix(".four", s)) {
(void) gettok(&s);
(void) gettok(&s);
if (!(w = gettoks(s)))
fprintf(cp_err, "Warning: no nodes given: %s\n",
iline->wl_word);
else {
some = 1;
com_save2(w, "TRAN"); /* A hack */
}
} else if (ciprefix(".op", s)) {
some = 1;
com_save2(&all, "OP");
} else if (ciprefix(".tf", s)) {
some = 1;
com_save2(&all, "TF");
}
}
return some;
}
/* Execute the .whatever lines found in the deck, after we are done running.
* We'll be cheap and use cp_lexer to get the words... This should make us
* spice-2 compatible. If terse is TRUE then there was a rawfile, so don't
* print lots of junk.
*/
int
ft_cktcoms(bool terse)
{
wordlist *coms, *command, all;
char *plottype, *s;
struct dvec *v;
static wordlist twl = { "col", NULL, NULL } ;
struct plot *pl;
int i, found;
all.wl_next = NULL;
all.wl_word = "all";
if (!ft_curckt)
return 1;
if (!ft_curckt->ci_commands)
goto nocmds;
coms = ft_curckt->ci_commands;
cp_interactive = FALSE;
/* Circuit name */
fprintf(cp_out, "Circuit: %s\nDate: %s\n\n", ft_curckt->ci_name,
datestring());
fprintf(cp_out, "\n");
/* Listing */
if (ft_listprint) {
if (terse)
fprintf(cp_err, ".options: no listing, rawfile was generated.\n");
else
inp_list(cp_out, ft_curckt->ci_deck, ft_curckt->ci_options,
LS_DECK);
}
/* If there was a .op line, then we have to do the .op output. */
if (setcplot("op")) {
if (terse) {
fprintf(cp_out, "OP information in rawfile.\n");
} else {
fprintf(cp_out, "\nOperating point information:\n\n");
fprintf(cp_out, "\tNode\tVoltage\n");
fprintf(cp_out, "\t----\t-------\n");
for (v = plot_cur->pl_dvecs; v; v = v->v_next) {
if (!isreal(v)) {
fprintf(cp_err,
"Internal error: op vector %s not real\n",
v->v_name);
continue;
}
if (v->v_type == SV_VOLTAGE)
fprintf(cp_out, "\t%s\t%s\n", v->v_name,
printnum(v->v_realdata[0]));
}
fprintf(cp_out, "\n\tSource\tCurrent\n");
fprintf(cp_out, "\t------\t-------\n\n");
for (v = plot_cur->pl_dvecs; v; v = v->v_next)
if (v->v_type == SV_CURRENT)
fprintf(cp_out, "\t%s\t%s\n", v->v_name,
printnum(v->v_realdata[0]));
fprintf(cp_out, "\n");
if (!ft_nomod)
com_showmod(&all);
com_show(&all);
}
}
for (pl = plot_list; pl; pl = pl->pl_next) {
if (ciprefix("tf", pl->pl_typename)) {
if (terse) {
fprintf(cp_out, "TF information in rawfile.\n");
break;
}
plot_cur = pl;
fprintf(cp_out, "Transfer function information:\n");
com_print(&all);
fprintf(cp_out, "\n");
}
}
/* Now all the '.' lines */
while (coms) {
command = cp_lexer(coms->wl_word);
if (!command)
goto bad;
if (eq(command->wl_word, ".width")) {
do {
command = command->wl_next;
} while (command && !ciprefix("out", command->wl_word));
if (command) {
s =strchr(command->wl_word, '=');
if (!s || !s[1]) {
fprintf(cp_err, "Error: bad line %s\n", coms->wl_word);
coms = coms->wl_next;
continue;
}
i = atoi(++s);
cp_vset("width", VT_NUM, (char *) &i);
}
} else if (eq(command->wl_word, ".print")) {
if (terse) {
fprintf(cp_out,
".print line ignored since rawfile was produced.\n");
} else {
command = command->wl_next;
if (!command) {
fprintf(cp_err, "Error: bad line %s\n", coms->wl_word);
coms = coms->wl_next;
continue;
}
plottype = command->wl_word;
command = command->wl_next;
fixdotprint(command);
twl.wl_next = command;
found = 0;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (ciprefix(plottype, pl->pl_typename)) {
plot_cur = pl;
com_print(&twl);
fprintf(cp_out, "\n");
found = 1;
}
}
if (!found)
fprintf(cp_err, "Error: .print: no %s analysis found.\n",
plottype);
}
} else if (eq(command->wl_word, ".plot")) {
if (terse) {
fprintf(cp_out,
".plot line ignored since rawfile was produced.\n");
} else {
command = command->wl_next;
if (!command) {
fprintf(cp_err, "Error: bad line %s\n",
coms->wl_word);
coms = coms->wl_next;
continue;
}
plottype = command->wl_word;
command = command->wl_next;
fixdotplot(command);
found = 0;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (ciprefix(plottype, pl->pl_typename)) {
plot_cur = pl;
com_asciiplot(command);
fprintf(cp_out, "\n");
found = 1;
}
}
if (!found)
fprintf(cp_err, "Error: .plot: no %s analysis found.\n",
plottype);
}
} else if (ciprefix(".four", command->wl_word)) {
if (terse) {
fprintf(cp_out,
".fourier line ignored since rawfile was produced.\n");
} else if (setcplot("tran")) {
com_fourier(command->wl_next);
fprintf(cp_out, "\n\n");
} else
fprintf(cp_err,
"No transient data available for fourier analysis");
} else if (!eq(command->wl_word, ".save")
&& !eq(command->wl_word, ".op")
&& !eq(command->wl_word, ".tf"))
{
goto bad;
}
coms = coms->wl_next;
}
nocmds:
/* Now the node table */
if (ft_nodesprint)
;
/* The options */
if (ft_optsprint) {
fprintf(cp_err, "Options:\n\n");
cp_vprint();
(void) putc('\n', cp_out);
}
/* And finally the accounting info. */
if (ft_acctprint) {
static wordlist ww = { "everything", NULL, NULL } ;
com_rusage(&ww);
} else
com_rusage((wordlist *) NULL);
(void) putc('\n', cp_out);
return 0;
bad: fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n");
return 1;
}
/* These routines make sure that the arguments to .plot and .print in
* spice2 decks are acceptable to spice3. The things we look for are:
* trailing (a,b) in .plot -> xlimit a b
* vm(x) -> mag(v(x))
* vp(x) -> ph(v(x))
* v(x,0) -> v(x)
* v(0,x) -> -v(x)
*/
static void
fixdotplot(wordlist *wl)
{
char buf[BSIZE_SP], *s;
double *d, d1, d2;
while (wl) {
wl->wl_word = fixem(wl->wl_word);
/* Is this a trailing (a,b) ? Note that we require it to be
* one word.
*/
if (!wl->wl_next && (*wl->wl_word == '(')) /*)*/ {
s = wl->wl_word + 1;
d = ft_numparse(&s, FALSE);
if (*s != ',') {
fprintf(cp_err, "Error: bad limits \"%s\"\n",
wl->wl_word);
return;
}
d1 = *d;
s++;
d = ft_numparse(&s, FALSE);
if ((*s != /*(*/ ')') || s[1]) {
fprintf(cp_err, "Error: bad limits \"%s\"\n",
wl->wl_word);
return;
}
d2 = *d;
tfree(wl->wl_word);
wl->wl_word = copy("xlimit");
wl->wl_next = alloc(struct wordlist);
wl->wl_next->wl_prev = wl;
wl = wl->wl_next;
(void) strcpy(buf, printnum(d1));
wl->wl_word = copy(buf);
wl->wl_next = alloc(struct wordlist);
wl->wl_next->wl_prev = wl;
wl = wl->wl_next;
(void) strcpy(buf, printnum(d2));
wl->wl_word = copy(buf);
}
wl = wl->wl_next;
}
return;
}
static void
fixdotprint(wordlist *wl)
{
while (wl) {
wl->wl_word = fixem(wl->wl_word);
wl = wl->wl_next;
}
return;
}
static char *
fixem(char *string)
{
char buf[BSIZE_SP], *s, *t, *ss = string;
if (ciprefix("v(", string) &&strchr(string, ',')) {
for (s = string; *s && (*s != ','); s++)
;
*s++ = '\0';
for (t = s; *t && (*t != ')'); t++)
;
*t = '\0';
if (eq(s, "0"))
(void) sprintf(buf, "v(%s)", string + 2);
else if (eq(string + 2, "0"))
(void) sprintf(buf, "-v(%s)", s);
else
(void) sprintf(buf, "v(%s)-v(%s)", string + 2, s);
tfree(ss);
string = copy(buf);
} else if (ciprefix("vm(", string)) {
for (s = string; *s && (*s != ')'); s++)
;
*s = '\0';
(void) sprintf(buf, "mag(v(%s))", string + 3);
tfree(ss);
string = copy(buf);
} else if (ciprefix("vp(", string)) {
for (s = string; *s && (*s != ')'); s++)
;
*s = '\0';
(void) sprintf(buf, "ph(v(%s))", string + 3);
tfree(ss);
string = copy(buf);
} else if (ciprefix("vi(", string)) {
for (s = string; *s && (*s != ')'); s++)
;
*s = '\0';
(void) sprintf(buf, "imag(v(%s))", string + 3);
tfree(ss);
string = copy(buf);
} else if (ciprefix("vr(", string)) {
for (s = string; *s && (*s != ')'); s++)
;
*s = '\0';
(void) sprintf(buf, "real(v(%s))", string + 3);
tfree(ss);
string = copy(buf);
} else if (ciprefix("vdb(", string)) {
for (s = string; *s && (*s != ')'); s++)
;
*s = '\0';
(void) sprintf(buf, "db(v(%s))", string + 4);
tfree(ss);
string = copy(buf);
} else if (ciprefix("i(", string)) {
for (s = string; *s && (*s != ')'); s++)
;
*s = '\0';
string += 2;
(void) sprintf(buf, "%s#branch", string);
tfree(ss);
string = copy(buf);
}
return (string);
}
/* Don't bother with ccom strangeness here. */
static bool
setcplot(char *name)
{
struct plot *pl;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (ciprefix(name, pl->pl_typename)) {
plot_cur = pl;
return (TRUE);
}
}
return (FALSE);
}
static wordlist *
gettoks(char *s)
{
char *t;
char *l, *r, *c; /* left, right, center/comma */
wordlist *wl, *list, **prevp;
list = NULL;
prevp = &list;
while ((t = gettok(&s))) {
if (*t == '(')
continue;
l =strrchr(t, '('/*)*/);
if (!l) {
wl = alloc(struct wordlist);
wl->wl_word = copy(t);
*prevp = wl;
prevp = &wl->wl_next;
continue;
}
r =strchr(t, /*(*/')');
c =strchr(t, ',');
if (!c)
c = r;
if (c)
*c = 0;
wl = alloc(struct wordlist);
if (*(l - 1) == 'i' || *(l - 1) == 'I') {
char buf[513];
sprintf(buf, "%s#branch", l + 1);
wl->wl_word = copy(buf);
c = r = NULL;
} else
wl->wl_word = copy(l + 1);
*prevp = wl;
prevp = &wl->wl_next;
if (c != r) {
*r = 0;
wl = alloc(struct wordlist);
wl->wl_word = copy(c + 1);
*prevp = wl;
prevp = &wl->wl_next;
}
}
return list;
}