ngspice/src/frontend/device.c

1509 lines
46 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: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
Modified: 2000 AlansFixes
2000-04-27 22:03:57 +02:00
**********/
/*
* Routines to query and alter devices.
*/
#include <ngspice/ngspice.h>
#include <ngspice/gendefs.h>
#include <ngspice/cktdefs.h>
#include <ngspice/cpdefs.h>
#include <ngspice/ftedefs.h>
#include <ngspice/dgen.h>
2000-04-27 22:03:57 +02:00
src/Makefile.am src/help.c src/main.c src/circuit/Makefile.am src/circuit/ifnewuid.c src/frontend/Makefile.am src/frontend/aspice.c src/frontend/circuits.h src/frontend/com_display.c src/frontend/com_hardcopy.c src/frontend/commands.c src/frontend/commands.h src/frontend/cpitf.c src/frontend/debugcom.c src/frontend/device.c src/frontend/diff.c src/frontend/display.c src/frontend/dotcards.c src/frontend/fourier.c src/frontend/inp.c src/frontend/inpcom.c src/frontend/linear.c src/frontend/misccoms.c src/frontend/mw_coms.c src/frontend/nutinp.c src/frontend/options.c src/frontend/outitf.c src/frontend/parse.c src/frontend/postcoms.c src/frontend/postsc.c src/frontend/rawfile.c src/frontend/resource.c src/frontend/runcoms.c src/frontend/runcoms2.c src/frontend/shyu.c src/frontend/spec.c src/frontend/spiceif.c src/frontend/subckt.c src/frontend/vectors.c src/frontend/where.c src/frontend/plotting/Makefile.am src/frontend/plotting/agraf.c src/frontend/plotting/graf.c src/frontend/plotting/plotcurv.c src/frontend/plotting/plotit.c src/frontend/plotting/x11.c src/frontend/plotting/xgraph.c src/include/Makefile.am src/maths/cmaths/cmath4.c src/misc/terminal.c src/misc/terminal.h src/parser/cshpar.c src/parser/front.c src/parser/front.h src/parser/history.c src/parser/history.h src/parser/modify.c src/parser/var2.c src/parser/var2.h src/parser/variable.c: Refactoring of frontend code. * src/include/ftehelp.h src/include/variable.h: Moved into frontend directory. * src/include/cpdefs.h src/include/cpextern.h src/include/ftedefs.h src/include/plot.h: Updates.
2000-06-27 18:09:02 +02:00
#include "circuits.h"
#include "device.h"
#include "variable.h"
2010-10-16 19:09:46 +02:00
#include "com_commands.h"
2011-09-18 11:03:55 +02:00
#include "../misc/util.h" /* ngdirname() */
2011-10-02 10:29:03 +02:00
#include "error.h" /* controlled_ext() */
2000-04-27 22:03:57 +02:00
2004-08-16 11:10:40 +02:00
#include "gens.h" /* wl_forall */
2000-04-27 22:03:57 +02:00
static wordlist *devexpand(char *name);
static void all_show(wordlist *wl, int mode);
static void all_show_old(wordlist *wl, int mode);
2011-09-18 11:03:55 +02:00
static void com_alter_mod(wordlist *wl);
2000-04-27 22:03:57 +02:00
/*
* devhelp: lists available devices and information on parameters
* devhelp : shows all available devices
* devhelp devname : shows all parameters of that model/instance
* devhelp devname parname : shows parameter meaning
* Options: -csv (comma separated value for generating docs)
*
*/
void com_devhelp(wordlist *wl)
{
/* Just a simple driver now */
devhelp(wl);
}
void devhelp(wordlist *wl)
{
int i, k = 0;
int devindex = -1, devInstParNo = 0 , devModParNo = 0;
bool found = FALSE;
bool csv = FALSE;
wordlist *wlist;
IFparm *plist;
/*First copy the base pointer */
wlist = wl;
/* If there are no arguments output the list of available devices */
if (!wlist) {
out_init();
out_printf("\nDevices available in the simulator\n\n");
for (k = 0; k < ft_sim->numDevices; k++) {
if (ft_sim->devices[k])
out_printf("%-*s:\t%s\n",
DEV_WIDTH, ft_sim->devices[k]->name,
ft_sim->devices[k]->description);
}
out_send("\n");
return;
}
/* The first argument must be the csv option or a device name */
if (wlist && wlist->wl_word && eq(wlist->wl_word, "-csv")) {
csv = TRUE;
if (wlist->wl_next)
wlist = wlist->wl_next;
else
return;
}
/* This argument, if exists, must be the device name */
if (wlist && wlist->wl_word) {
while (k < ft_sim->numDevices && !found) {
if (ft_sim->devices[k])
if (strcasecmp(ft_sim->devices[k]->name, wlist->wl_word) == 0) {
devindex = k;
if (ft_sim->devices[devindex]->numInstanceParms)
devInstParNo = *(ft_sim->devices[devindex]->numInstanceParms);
else
devInstParNo = 0;
if (ft_sim->devices[devindex]->numModelParms)
devModParNo = *(ft_sim->devices[devindex]->numModelParms);
else
devModParNo = 0;
wlist = wlist->wl_next;
found = TRUE;
}
k++;
}
if (!found) {
fprintf(cp_out, "Error: Device %s not found\n", wlist->wl_word);
return;
}
}
/* At this point, found is TRUE and we have found the device.
* Now we have to scan the model and instance parameters to print
* the string
*/
found = FALSE;
if (wlist && wlist->wl_word) {
plist = ft_sim->devices[devindex]->modelParms;
for (i = 0; i < devModParNo; i++) { /* Scan model parameters first */
if (strcasecmp(plist[i].keyword, wlist->wl_word) == 0) {
found = TRUE;
out_init();
out_printf("Model Parameters\n");
if (csv)
out_printf("id#, Name, Dir, Description\n");
else
out_printf("%5s\t %-10s\t Dir\t Description\n", "id#", "Name");
printdesc(plist[i], csv);
out_send("\n");
}
}
if (!found) {
plist = ft_sim->devices[devindex]->instanceParms;
for (i = 0; i < devInstParNo; i++) { /* Scan instance parameters then */
if (strcasecmp(plist[i].keyword, wlist->wl_word) == 0) {
found = TRUE;
out_init();
out_printf("Instance Parameters\n");
if (csv)
out_printf("id#, Name, Dir, Description\n");
else
out_printf("%5s\t %-10s\t Dir\t Description\n", "id#", "Name");
printdesc(plist[i], csv);
out_send("\n");
}
}
}
if (!found)
fprintf(cp_out, "Error: Parameter %s not found\n", wlist->wl_word);
return;
}
/* No arguments - we want all the parameters*/
out_init();
out_printf("%s - %s\n\n", ft_sim->devices[devindex]->name, ft_sim->devices[devindex]->description);
out_printf("Model Parameters\n");
if (csv)
out_printf("id#, Name, Dir, Description\n");
else
out_printf("%5s\t %-10s\t Dir\t Description\n", "id#", "Name");
plist = ft_sim->devices[devindex]->modelParms;
for (i = 0; i < devModParNo; i++)
printdesc(plist[i], csv);
out_printf("\n");
out_printf("Instance Parameters\n");
if (csv)
out_printf("id#, Name, Dir, Description\n");
else
out_printf("%5s\t %-10s\t Dir\t Description\n", "id#", "Name");
plist = ft_sim->devices[devindex]->instanceParms;
for (i = 0; i < devInstParNo; i++)
printdesc(plist[i], csv);
out_send("\n");
}
/*
* Pretty print parameter descriptions
* This function prints description of device parameters
*/
void printdesc(IFparm p, bool csv)
{
char sep;
int spacer1, spacer2;
/* First we indentify the separator */
if (csv) {
sep = ',';
spacer1 = 0;
spacer2 = 0;
} else {
sep = '\t';
spacer1 = 5;
spacer2 = 10;
}
out_printf("%*d%c %-*s%c ", spacer1, p.id, sep, spacer2, p.keyword, sep);
if (p.dataType & IF_SET)
if (p.dataType & IF_ASK)
out_printf("inout%c ", sep);
else
out_printf("in%c ", sep);
else
out_printf("out%c ", sep);
if (p.description)
out_printf("%s\n", p.description);
else
out_printf("n.a.\n");
}
2000-04-27 22:03:57 +02:00
/*
2009-02-08 15:52:16 +01:00
* show: list device operating point info
* show
* show devs : params
* show devs : params ; devs : params
* show dev dev dev : param param param , dev dev : param param
* show t : param param param, t : param param
2000-04-27 22:03:57 +02:00
*
*/
2009-02-08 15:52:16 +01:00
static int count;
2000-04-27 22:03:57 +02:00
void
com_showmod(wordlist *wl)
{
if (cp_getvar("altshow", CP_BOOL, NULL))
all_show(wl, 1);
else
all_show_old(wl, 1);
2000-04-27 22:03:57 +02:00
}
void
com_show(wordlist *wl)
{
if (cp_getvar("altshow", CP_BOOL, NULL))
all_show(wl, 0);
else
all_show_old(wl, 0);
2000-04-27 22:03:57 +02:00
}
static void
all_show(wordlist *wl, int mode)
{
2009-02-08 15:52:16 +01:00
wordlist *params, *nextgroup, *thisgroup;
wordlist *prev, *next, *w;
int screen_width;
dgen *dg, *listdg;
int instances;
int i, j, n;
int param_flag, dev_flag;
2000-04-27 22:03:57 +02:00
if (!ft_curckt) {
fprintf(cp_err, "Error: no circuit loaded\n");
return;
}
if (wl && wl->wl_word && eq(wl->wl_word, "-v")) {
2009-02-08 15:52:16 +01:00
old_show(wl->wl_next);
return;
2000-04-27 22:03:57 +02:00
}
2011-04-30 14:29:19 +02:00
if (!cp_getvar("width", CP_NUM, &screen_width))
2009-02-08 15:52:16 +01:00
screen_width = DEF_WIDTH;
count = (screen_width - LEFT_WIDTH) / (DEV_WIDTH + 1);
2007-10-08 17:55:34 +02:00
count = 1;
2000-04-27 22:03:57 +02:00
n = 0;
do {
2009-02-08 15:52:16 +01:00
prev = NULL;
params = NULL;
nextgroup = NULL;
thisgroup = wl;
param_flag = 0;
dev_flag = 0;
/* find the parameter list and the nextgroup */
for (w = wl; w && !nextgroup; w = next) {
next = w->wl_next;
if ( eq(w->wl_word, "*") ) {
tfree(w->wl_word);
w->wl_word = strdup("all");
}
2007-10-08 17:55:34 +02:00
2009-02-08 15:52:16 +01:00
if (eq(w->wl_word, "++") || eq(w->wl_word, "all")) {
if (params) {
param_flag = DGEN_ALLPARAMS;
if (prev)
prev->wl_next = w->wl_next;
else
params = next;
} else {
dev_flag = DGEN_ALLDEVS;
if (prev)
prev->wl_next = w->wl_next;
else
thisgroup = next;
}
/* w must not be freed here */
w = NULL;
} else if (eq(w->wl_word, "+")) {
if (params) {
param_flag = DGEN_DEFPARAMS;
if (prev)
prev->wl_next = w->wl_next;
else
params = next;
} else {
dev_flag = DGEN_DEFDEVS;
if (prev)
prev->wl_next = w->wl_next;
else
thisgroup = next;
}
/* w must not be freed here */
w = NULL;
} else if (eq(w->wl_word, ":")) {
/* w must not be freed here */
w = NULL;
if (!params) {
params = next;
if (prev)
prev->wl_next = NULL;
else
thisgroup = NULL;
} else {
if (prev)
prev->wl_next = next;
else
params = next;
}
} else if (eq(w->wl_word, ";") || eq(w->wl_word, ",")) {
nextgroup = next;
/* w must not be freed here */
w = NULL;
if (prev)
prev->wl_next = NULL;
break;
}
prev = w;
}
instances = 0;
for (dg = dgen_init(ft_curckt->ci_ckt, thisgroup, 1, dev_flag, mode);
dg; dgen_nth_next(&dg, count))
{
instances = 1;
if (dg->flags & DGEN_INSTANCE) {
instances = 2;
n += 1;
fprintf(cp_out,"%s:\n", dg->instance->GENname);
fprintf(cp_out," %-19s= %s\n", "model", dg->model->GENmodName);
listdg = dg;
if (param_flag) {
param_forall(dg, param_flag);
}
else if (!params) {
param_forall(dg, DGEN_DEFPARAMS);
}
if (params) {
wl_forall(params, listparam, dg);
}
} else if (ft_sim->devices[dg->dev_type_no]->numModelParms) {
fprintf(cp_out," %s models (%s)\n",
ft_sim->devices[dg->dev_type_no]->name,
ft_sim->devices[dg->dev_type_no]->description);
n += 1;
i = 0;
do {
fprintf(cp_out,"%*s", LEFT_WIDTH, "model");
j = dgen_for_n(dg, count, printstr_m, NULL, i);
2009-02-08 15:52:16 +01:00
i += 1;
fprintf(cp_out,"\n");
} while (j);
fprintf(cp_out,"\n");
if (param_flag)
param_forall(dg, param_flag);
else if (!params)
param_forall(dg, DGEN_DEFPARAMS);
if (params)
wl_forall(params, listparam, dg);
fprintf(cp_out,"\n");
}
}
wl = nextgroup;
2007-10-08 17:55:34 +02:00
} while (wl);
if (!n) {
2009-02-08 15:52:16 +01:00
if (instances == 0)
printf("No matching instances or models\n");
else if (instances == 1)
printf("No matching models\n");
else
printf("No matching elements\n");
2007-10-08 17:55:34 +02:00
}
}
static void
all_show_old(wordlist *wl, int mode)
{
2009-02-08 15:52:16 +01:00
wordlist *params, *nextgroup, *thisgroup;
wordlist *prev, *next, *w;
int screen_width;
dgen *dg, *listdg;
int instances;
int i, j, n;
int param_flag, dev_flag;
2007-10-08 17:55:34 +02:00
if (!ft_curckt) {
fprintf(cp_err, "Error: no circuit loaded\n");
return;
}
if (wl && wl->wl_word && eq(wl->wl_word, "-v")) {
2009-02-08 15:52:16 +01:00
old_show(wl->wl_next);
return;
2007-10-08 17:55:34 +02:00
}
2011-04-30 14:29:19 +02:00
if (!cp_getvar("width", CP_NUM, &screen_width))
2009-02-08 15:52:16 +01:00
screen_width = DEF_WIDTH;
2007-10-08 17:55:34 +02:00
count = (screen_width - LEFT_WIDTH) / (DEV_WIDTH + 1);
n = 0;
do {
2009-02-08 15:52:16 +01:00
prev = NULL;
params = NULL;
nextgroup = NULL;
thisgroup = wl;
param_flag = 0;
dev_flag = 0;
/* find the parameter list and the nextgroup */
for (w = wl; w && !nextgroup; w = next) {
next = w->wl_next;
if ( eq(w->wl_word, "*") ) {
tfree(w->wl_word);
w->wl_word = strdup("all");
}
2007-10-08 17:55:34 +02:00
2009-02-08 15:52:16 +01:00
if (eq(w->wl_word, "++") || eq(w->wl_word, "all")) {
if (params) {
param_flag = DGEN_ALLPARAMS;
if (prev)
prev->wl_next = w->wl_next;
else
params = next;
} else {
dev_flag = DGEN_ALLDEVS;
if (prev)
prev->wl_next = w->wl_next;
else
thisgroup = next;
}
/* w must not be freed here */
w = NULL;
} else if (eq(w->wl_word, "+")) {
if (params) {
param_flag = DGEN_DEFPARAMS;
if (prev)
prev->wl_next = w->wl_next;
else
params = next;
} else {
dev_flag = DGEN_DEFDEVS;
if (prev)
prev->wl_next = w->wl_next;
else
thisgroup = next;
}
/* w must not be freed here */
w = NULL;
} else if (eq(w->wl_word, ":")) {
/* w must not be freed here */
w = NULL;
if (!params) {
params = next;
if (prev)
prev->wl_next = NULL;
else
thisgroup = NULL;
} else {
if (prev)
prev->wl_next = next;
else
params = next;
}
} else if (eq(w->wl_word, ";") || eq(w->wl_word, ",")) {
nextgroup = next;
/* w must not be freed here */
w = NULL;
if (prev)
prev->wl_next = NULL;
break;
}
prev = w;
}
instances = 0;
for (dg = dgen_init(ft_curckt->ci_ckt, thisgroup, 1, dev_flag, mode);
dg; dgen_nth_next(&dg, count))
{
instances = 1;
if (dg->flags & DGEN_INSTANCE) {
instances = 2;
fprintf(cp_out," %s: %s\n",
ft_sim->devices[dg->dev_type_no]->name,
ft_sim->devices[dg->dev_type_no]->description);
n += 1;
i = 0;
do {
fprintf(cp_out,"%*s", LEFT_WIDTH, "device");
j = dgen_for_n(dg, count, printstr_n, NULL, i);
2009-02-08 15:52:16 +01:00
i += 1;
fprintf(cp_out,"\n");
} while (j);
if (ft_sim->devices[dg->dev_type_no]->numModelParms) {
i = 0;
do {
fprintf(cp_out,"%*s", LEFT_WIDTH, "model");
j = dgen_for_n(dg, count, printstr_m, NULL, i);
2009-02-08 15:52:16 +01:00
i += 1;
fprintf(cp_out,"\n");
} while (j);
}
listdg = dg;
if (param_flag)
param_forall_old(dg, param_flag);
else if (!params)
param_forall_old(dg, DGEN_DEFPARAMS);
if (params)
wl_forall(params, listparam, dg);
fprintf(cp_out,"\n");
} else if (ft_sim->devices[dg->dev_type_no]->numModelParms) {
fprintf(cp_out," %s models (%s)\n",
ft_sim->devices[dg->dev_type_no]->name,
ft_sim->devices[dg->dev_type_no]->description);
n += 1;
i = 0;
do {
fprintf(cp_out,"%*s", LEFT_WIDTH, "model");
j = dgen_for_n(dg, count, printstr_m, NULL, i);
2009-02-08 15:52:16 +01:00
i += 1;
fprintf(cp_out,"\n");
} while (j);
fprintf(cp_out,"\n");
if (param_flag)
param_forall_old(dg, param_flag);
else if (!params)
param_forall_old(dg, DGEN_DEFPARAMS);
if (params)
wl_forall(params, listparam, dg);
fprintf(cp_out,"\n");
}
}
wl = nextgroup;
2000-04-27 22:03:57 +02:00
} while (wl);
if (!n) {
2009-02-08 15:52:16 +01:00
if (instances == 0)
printf("No matching instances or models\n");
else if (instances == 1)
printf("No matching models\n");
else
printf("No matching elements\n");
2000-04-27 22:03:57 +02:00
}
}
int
printstr_n(dgen *dg, IFparm *p, int i)
2000-04-27 22:03:57 +02:00
{
2010-11-16 21:38:24 +01:00
NG_IGNORE(p);
NG_IGNORE(i);
2010-11-16 20:11:32 +01:00
if (dg->instance)
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, dg->instance->GENname);
else
fprintf(cp_out," %*s", DEV_WIDTH, "<\?\?\?\?\?\?\?>");
return 0;
}
2000-04-27 22:03:57 +02:00
int
printstr_m(dgen *dg, IFparm *p, int i)
{
2010-11-16 21:38:24 +01:00
NG_IGNORE(p);
NG_IGNORE(i);
2010-11-16 20:11:32 +01:00
if (dg->model)
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, dg->model->GENmodName);
else
fprintf(cp_out," %*s", DEV_WIDTH, "<\?\?\?\?\?\?\?>");
2000-04-27 22:03:57 +02:00
return 0;
}
void
2000-04-27 22:03:57 +02:00
param_forall(dgen *dg, int flags)
{
2009-02-08 15:52:16 +01:00
int i, j, k, found;
2000-04-27 22:03:57 +02:00
int xcount;
IFparm *plist;
found = 0;
if (dg->flags & DGEN_INSTANCE) {
2009-02-08 15:52:16 +01:00
xcount = *ft_sim->devices[dg->dev_type_no]->numInstanceParms;
plist = ft_sim->devices[dg->dev_type_no]->instanceParms;
2000-04-27 22:03:57 +02:00
} else {
2009-02-08 15:52:16 +01:00
xcount = *ft_sim->devices[dg->dev_type_no]->numModelParms;
plist = ft_sim->devices[dg->dev_type_no]->modelParms;
2000-04-27 22:03:57 +02:00
}
2007-10-08 17:55:34 +02:00
for (i = 0; i < xcount; i++) {
2009-02-08 15:52:16 +01:00
if (plist[i].dataType & IF_ASK) {
if ((((CKTcircuit *) (dg->ckt))->CKTrhsOld
|| (plist[i].dataType & IF_SET))
&& (!(plist[i].dataType & (IF_REDUNDANT | IF_UNINTERESTING))
|| (flags == DGEN_ALLPARAMS
&& !(plist[i].dataType & IF_REDUNDANT))))
{
j = 0;
do {
fprintf(cp_out," %-19s=", plist[i].keyword);
k = dgen_for_n(dg, count, printvals, (plist + i), j);
fprintf(cp_out,"\n");
j += 1;
} while (k);
}
}
2007-10-08 17:55:34 +02:00
}
}
void
param_forall_old(dgen *dg, int flags)
{
2009-02-08 15:52:16 +01:00
int i, j, k, found;
2007-10-08 17:55:34 +02:00
int xcount;
IFparm *plist;
found = 0;
if (dg->flags & DGEN_INSTANCE) {
2009-02-08 15:52:16 +01:00
xcount = *ft_sim->devices[dg->dev_type_no]->numInstanceParms;
plist = ft_sim->devices[dg->dev_type_no]->instanceParms;
2007-10-08 17:55:34 +02:00
} else {
2009-02-08 15:52:16 +01:00
xcount = *ft_sim->devices[dg->dev_type_no]->numModelParms;
plist = ft_sim->devices[dg->dev_type_no]->modelParms;
2007-10-08 17:55:34 +02:00
}
2000-04-27 22:03:57 +02:00
for (i = 0; i < xcount; i++) {
2009-02-08 15:52:16 +01:00
if (plist[i].dataType & IF_ASK) {
if ((((CKTcircuit *) (dg->ckt))->CKTrhsOld
|| (plist[i].dataType & IF_SET))
&& (!(plist[i].dataType & (IF_REDUNDANT | IF_UNINTERESTING))
|| (flags == DGEN_ALLPARAMS
&& !(plist[i].dataType & IF_REDUNDANT))))
{
j = 0;
do {
if (!j)
fprintf(cp_out,"%*.*s", LEFT_WIDTH, LEFT_WIDTH,
plist[i].keyword);
else
fprintf(cp_out,"%*.*s", LEFT_WIDTH, LEFT_WIDTH, " ");
k = dgen_for_n(dg, count, printvals_old, (plist + i), j);
fprintf(cp_out,"\n");
j += 1;
} while (k);
}
}
2000-04-27 22:03:57 +02:00
}
}
void
2000-04-27 22:03:57 +02:00
listparam(wordlist *p, dgen *dg)
{
2009-02-08 15:52:16 +01:00
int i, j, k, found;
int xcount;
2000-04-27 22:03:57 +02:00
IFparm *plist;
found = 0;
if (dg->flags & DGEN_INSTANCE) {
2009-02-08 15:52:16 +01:00
xcount = *ft_sim->devices[dg->dev_type_no]->numInstanceParms;
plist = ft_sim->devices[dg->dev_type_no]->instanceParms;
2000-04-27 22:03:57 +02:00
} else {
2009-02-08 15:52:16 +01:00
xcount = *ft_sim->devices[dg->dev_type_no]->numModelParms;
plist = ft_sim->devices[dg->dev_type_no]->modelParms;
2000-04-27 22:03:57 +02:00
}
for (i = 0; i < xcount; i++) {
2009-02-08 15:52:16 +01:00
if (eqc(p->wl_word, plist[i].keyword) && (plist[i].dataType & IF_ASK))
{
found = 1;
break;
}
2000-04-27 22:03:57 +02:00
}
if (found) {
2009-02-08 15:52:16 +01:00
if ((((CKTcircuit *) (dg->ckt))->CKTrhsOld
|| (plist[i].dataType & IF_SET)))
{
j = 0;
do {
if (!j)
fprintf(cp_out,"%*.*s", LEFT_WIDTH, LEFT_WIDTH, p->wl_word);
else
fprintf(cp_out,"%*.*s", LEFT_WIDTH, LEFT_WIDTH, " ");
k = dgen_for_n(dg, count, printvals_old, (plist + i), j);
printf("\n");
j += 1;
} while (k > 0);
} else {
j = 0;
do {
if (!j)
fprintf(cp_out,"%*.*s", LEFT_WIDTH, LEFT_WIDTH, p->wl_word);
else
fprintf(cp_out,"%*s", LEFT_WIDTH, " ");
k = dgen_for_n(dg, count, bogus1, 0, j);
fprintf(cp_out,"\n");
j += 1;
} while (k > 0);
}
2000-04-27 22:03:57 +02:00
} else {
2009-02-08 15:52:16 +01:00
j = 0;
do {
if (!j)
fprintf(cp_out,"%*.*s", LEFT_WIDTH, LEFT_WIDTH, p->wl_word);
else
fprintf(cp_out,"%*s", LEFT_WIDTH, " ");
k = dgen_for_n(dg, count, bogus2, 0, j);
fprintf(cp_out,"\n");
j += 1;
} while (k > 0);
2000-04-27 22:03:57 +02:00
}
}
int bogus1(dgen *dg, IFparm *p, int i)
2000-04-27 22:03:57 +02:00
{
2010-11-16 21:38:24 +01:00
NG_IGNORE(dg);
NG_IGNORE(p);
NG_IGNORE(i);
2010-11-16 20:11:32 +01:00
2007-10-08 17:55:34 +02:00
fprintf(cp_out," %*s", DEV_WIDTH, "---------");
2000-04-27 22:03:57 +02:00
return 0;
}
int bogus2(dgen *dg, IFparm *p, int i)
2000-04-27 22:03:57 +02:00
{
2010-11-16 21:38:24 +01:00
NG_IGNORE(dg);
NG_IGNORE(p);
NG_IGNORE(i);
2010-11-16 20:11:32 +01:00
2007-10-08 17:55:34 +02:00
fprintf(cp_out," %*s", DEV_WIDTH, "?????????");
2000-04-27 22:03:57 +02:00
return 0;
}
int
printvals(dgen *dg, IFparm *p, int i)
{
2009-02-08 15:52:16 +01:00
IFvalue val;
int n;
2000-04-27 22:03:57 +02:00
if (dg->flags & DGEN_INSTANCE)
2011-04-27 20:30:15 +02:00
ft_sim->askInstanceQuest (ft_curckt->ci_ckt, dg->instance,
2009-02-08 15:52:16 +01:00
p->id, &val, &val);
2000-04-27 22:03:57 +02:00
else
2011-04-27 20:30:15 +02:00
ft_sim->askModelQuest (ft_curckt->ci_ckt, dg->model,
2009-02-08 15:52:16 +01:00
p->id, &val, &val);
2000-04-27 22:03:57 +02:00
if (p->dataType & IF_VECTOR)
2009-02-08 15:52:16 +01:00
n = val.v.numValue;
2000-04-27 22:03:57 +02:00
else
2009-02-08 15:52:16 +01:00
n = 1;
2000-04-27 22:03:57 +02:00
if (((p->dataType & IF_VARTYPES) & ~IF_VECTOR) == IF_COMPLEX)
2009-02-08 15:52:16 +01:00
n *= 2;
2000-04-27 22:03:57 +02:00
if (i >= n) {
2009-02-08 15:52:16 +01:00
if (i == 0)
fprintf(cp_out," -");
else
fprintf(cp_out," ");
return 0;
2007-10-08 17:55:34 +02:00
}
if (p->dataType & IF_VECTOR) {
/* va: ' ' is no flag for %s */
2009-02-08 15:52:16 +01:00
switch ((p->dataType & IF_VARTYPES) & ~IF_VECTOR) {
case IF_FLAG:
fprintf(cp_out," %d", val.v.vec.iVec[i]);
break;
case IF_INTEGER:
fprintf(cp_out," %d", val.v.vec.iVec[i]);
break;
case IF_REAL:
fprintf(cp_out," %.6g", val.v.vec.rVec[i]);
break;
case IF_COMPLEX:
if (!(i % 2))
fprintf(cp_out," %.6g", val.v.vec.cVec[i / 2].real);
else
fprintf(cp_out," %.6g", val.v.vec.cVec[i / 2].imag);
break;
case IF_STRING:
fprintf(cp_out," %s", val.v.vec.sVec[i]);
break;
case IF_INSTANCE:
fprintf(cp_out," %s", val.v.vec.uVec[i]);
break;
default:
fprintf(cp_out," %s", " ******** ");
}
2007-10-08 17:55:34 +02:00
} else {
2009-02-08 15:52:16 +01:00
switch ((p->dataType & IF_VARTYPES) & ~IF_VECTOR) {
case IF_FLAG:
fprintf(cp_out," %d", val.iValue);
break;
case IF_INTEGER:
fprintf(cp_out," %d", val.iValue);
break;
case IF_REAL:
fprintf(cp_out," %.6g", val.rValue);
break;
case IF_COMPLEX:
if (i % 2)
fprintf(cp_out," %.6g", val.cValue.real);
else
fprintf(cp_out," %.6g", val.cValue.imag);
break;
case IF_STRING:
fprintf(cp_out," %s", val.sValue);
break;
case IF_INSTANCE:
fprintf(cp_out," %s", val.uValue);
break;
default:
fprintf(cp_out," %s", " ******** ");
}
2007-10-08 17:55:34 +02:00
}
return n - 1;
}
int
printvals_old(dgen *dg, IFparm *p, int i)
{
2009-02-08 15:52:16 +01:00
IFvalue val;
2010-05-30 19:17:50 +02:00
int n, error;
2007-10-08 17:55:34 +02:00
if (dg->flags & DGEN_INSTANCE)
2011-04-27 20:30:15 +02:00
error = ft_sim->askInstanceQuest (ft_curckt->ci_ckt, dg->instance,
2009-02-08 15:52:16 +01:00
p->id, &val, &val);
2007-10-08 17:55:34 +02:00
else
2011-04-27 20:30:15 +02:00
error = ft_sim->askModelQuest (ft_curckt->ci_ckt, dg->model,
2009-02-08 15:52:16 +01:00
p->id, &val, &val);
2007-10-08 17:55:34 +02:00
if (p->dataType & IF_VECTOR)
2009-02-08 15:52:16 +01:00
n = val.v.numValue;
2007-10-08 17:55:34 +02:00
else
2009-02-08 15:52:16 +01:00
n = 1;
2007-10-08 17:55:34 +02:00
if (((p->dataType & IF_VARTYPES) & ~IF_VECTOR) == IF_COMPLEX)
2009-02-08 15:52:16 +01:00
n *= 2;
2007-10-08 17:55:34 +02:00
if (i >= n) {
2009-02-08 15:52:16 +01:00
if (i == 0)
fprintf(cp_out," -");
else
fprintf(cp_out," ");
return 0;
2000-04-27 22:03:57 +02:00
}
2010-05-30 19:17:50 +02:00
if(error) {
fprintf(cp_out," <<NAN, error = %d>>", error);
} else
2000-04-27 22:03:57 +02:00
if (p->dataType & IF_VECTOR) {
/* va: ' ' is no flag for %s */
2009-02-08 15:52:16 +01:00
switch ((p->dataType & IF_VARTYPES) & ~IF_VECTOR) {
case IF_FLAG:
fprintf(cp_out," % *d", DEV_WIDTH, val.v.vec.iVec[i]);
break;
case IF_INTEGER:
fprintf(cp_out," % *d", DEV_WIDTH, val.v.vec.iVec[i]);
break;
case IF_REAL:
fprintf(cp_out," % *.6g", DEV_WIDTH, val.v.vec.rVec[i]);
break;
case IF_COMPLEX:
if (!(i % 2))
fprintf(cp_out," % *.6g", DEV_WIDTH, val.v.vec.cVec[i / 2].real);
else
fprintf(cp_out," % *.6g", DEV_WIDTH, val.v.vec.cVec[i / 2].imag);
break;
case IF_STRING:
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, val.v.vec.sVec[i]);
break;
case IF_INSTANCE:
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, val.v.vec.uVec[i]);
break;
default:
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, " ******** ");
}
2000-04-27 22:03:57 +02:00
} else {
2009-02-08 15:52:16 +01:00
switch ((p->dataType & IF_VARTYPES) & ~IF_VECTOR) {
case IF_FLAG:
fprintf(cp_out," % *d", DEV_WIDTH, val.iValue);
break;
case IF_INTEGER:
fprintf(cp_out," % *d", DEV_WIDTH, val.iValue);
break;
case IF_REAL:
fprintf(cp_out," % *.6g", DEV_WIDTH, val.rValue);
break;
case IF_COMPLEX:
if (i % 2)
fprintf(cp_out," % *.6g", DEV_WIDTH, val.cValue.real);
else
fprintf(cp_out," % *.6g", DEV_WIDTH, val.cValue.imag);
break;
case IF_STRING:
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, val.sValue);
break;
case IF_INSTANCE:
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, val.uValue);
break;
default:
fprintf(cp_out," %*.*s", DEV_WIDTH, DEV_WIDTH, " ******** ");
}
2000-04-27 22:03:57 +02:00
}
return n - 1;
}
/* (old "show" command)
* Display various device parameters. The syntax of this command is
2000-04-27 22:03:57 +02:00
* show devicelist : parmlist
* where devicelist can be "all", the name of a device, a string like r*,
* which means all devices with names that begin with 'r', repeated one
* or more times. The parms are names of parameters that are (hopefully)
* valid for all the named devices, or "all".
*/
void
old_show(wordlist *wl)
{
wordlist *devs, *parms, *tw, *ww;
struct variable *v;
char *nn;
devs = wl;
while (wl && !eq(wl->wl_word, ":"))
wl = wl->wl_next;
if (!wl)
parms = NULL;
else {
if (wl->wl_prev)
wl->wl_prev->wl_next = NULL;
parms = wl->wl_next;
if (parms)
parms->wl_prev = NULL;
}
/* Now expand the devicelist... */
for (tw = NULL; devs; devs = devs->wl_next) {
inp_casefix(devs->wl_word);
tw = wl_append(tw, devexpand(devs->wl_word));
}
2000-04-27 22:03:57 +02:00
devs = tw;
for (tw = parms; tw; tw = tw->wl_next)
if (eq(tw->wl_word, "all"))
break;
if (tw)
parms = NULL;
/* This is a crock... */
if (!devs)
devs = cp_cctowl(ft_curckt->ci_devices);
out_init();
while (devs) {
out_printf("%s:\n", devs->wl_word);
if (parms) {
for (tw = parms; tw; tw = tw->wl_next) {
nn = copy(devs->wl_word);
2011-04-27 20:30:15 +02:00
v = if_getparam (ft_curckt->ci_ckt,
2009-02-08 15:52:16 +01:00
&nn, tw->wl_word, 0, 0);
if (!v)
2011-04-27 20:30:15 +02:00
v = if_getparam (ft_curckt->ci_ckt,
2009-02-08 15:52:16 +01:00
&nn, tw->wl_word, 0, 1);
2000-04-27 22:03:57 +02:00
if (v) {
out_printf("\t%s =", tw->wl_word);
for (ww = cp_varwl(v); ww; ww =
ww->wl_next)
out_printf(" %s", ww->wl_word);
out_send("\n");
}
}
} else {
nn = copy(devs->wl_word);
2011-04-27 20:30:15 +02:00
v = if_getparam (ft_curckt->ci_ckt, &nn, "all", 0, 0);
2009-02-08 15:52:16 +01:00
if (!v)
2011-04-27 20:30:15 +02:00
v = if_getparam (ft_curckt->ci_ckt, &nn, "all", 0, 1);
2000-04-27 22:03:57 +02:00
while (v) {
out_printf("\t%s =", v->va_name);
for (ww = cp_varwl(v); ww; ww = ww->wl_next)
out_printf(" %s", ww->wl_word);
out_send("\n");
v = v->va_next;
}
}
devs = devs->wl_next;
}
return;
}
/* Alter a device parameter. The new syntax here is
2009-02-08 15:52:16 +01:00
* alter @device[parameter] = expr
* alter device = expr
* alter device parameter = expr
2000-04-27 22:03:57 +02:00
* expr must be real (complex isn't handled right now, integer is fine though,
* but no strings ... for booleans, use 0/1).
*/
2010-10-16 19:09:46 +02:00
static void com_alter_common(wordlist *wl, int do_model);
2000-04-27 22:03:57 +02:00
void
com_alter(wordlist *wl)
{
if (!wl) {
2009-02-08 15:52:16 +01:00
fprintf(cp_err, "usage: alter dev param = expression\n");
fprintf(cp_err, " or alter @dev[param] = expression\n");
fprintf(cp_err, " or alter dev = expression\n");
return;
2000-04-27 22:03:57 +02:00
}
com_alter_common(wl, 0);
}
void
com_altermod(wordlist *wl)
{
2011-09-18 11:03:55 +02:00
wordlist *fileword;
bool newfile = FALSE;
fileword = wl;
while (fileword){
if (ciprefix("file",fileword->wl_word)) {
newfile = TRUE;
}
fileword = fileword->wl_next;
}
if (newfile)
com_alter_mod(wl);
else
com_alter_common(wl, 1);
2000-04-27 22:03:57 +02:00
}
2010-10-16 19:09:46 +02:00
static void
2000-04-27 22:03:57 +02:00
com_alter_common(wordlist *wl, int do_model)
{
2009-10-04 13:48:37 +02:00
wordlist *eqword = NULL, *words;
2000-04-27 22:03:57 +02:00
char *dev, *p;
char *param;
struct dvec *dv;
struct pnode *names;
2009-02-08 15:52:16 +01:00
/* DIE 2009_02_06 */
char *argument;
char **arglist;
int i=0, step=0, n, wlen, maxelem=3;
2009-10-04 13:48:37 +02:00
wordlist *wl2 = NULL, *wlin, *wleq;
2009-02-08 15:52:16 +01:00
bool eqfound = FALSE, vecfound = FALSE;
2000-04-27 22:03:57 +02:00
if (!ft_curckt) {
fprintf(cp_err, "Error: no circuit loaded\n");
return;
}
2009-02-08 15:52:16 +01:00
/*
wordlist 'wl' will be splitted into a wordlist wl2 with three elements,
containing
1) '@dev[param]' string (i.e.: the substring before '=' char);
2) '=' string;
3) 'expression' string.
Spaces around the '=' sign have to be removed. This is provided
2011-09-18 11:03:55 +02:00
by inp_remove_excess_ws(). But take care if command is entered manually!
2009-02-08 15:52:16 +01:00
If the 'altermod' argument is 'altermod m1 vth0=0.7', 'm1' has to be kept as the
element in wl2 before splitting inserts the three new elements.
If 'expression' is a vector (e.g. [ 1.0 1.2 1.4 ] ), its elements
in wl2 have to follow the splitting. wl_splice() will take care of this.
*/
wlin = wl;
while(wl){
argument = wl->wl_word;
/* searching for '=' ... */
2009-02-12 20:05:43 +01:00
i = 0;
2009-02-08 15:52:16 +01:00
while(argument[i]!='=' && argument[i]!='\0'){
i++;
}
2011-09-18 11:03:55 +02:00
/* argument may be '=', then do nothing
or =token
or token=
or token1=token2
...and if found split argument into three chars and make a new wordlist */
2009-02-08 15:52:16 +01:00
if(argument[i]!='\0'){
2011-09-18 11:03:55 +02:00
/* We found '=' */
eqfound = TRUE;
if (strlen(argument) == 1) {
wl = wl->wl_next;
step = -1;
wl2 = wlin;
}
else if (strlen(argument) > 1) {
arglist = TMALLOC(char*, 4);
2009-02-08 15:52:16 +01:00
arglist[3] = NULL;
arglist[0] = TMALLOC(char, i + 1);
arglist[2] = TMALLOC(char, strlen(&argument[i + 1]) + 1);
2009-02-08 15:52:16 +01:00
/* copy argument */
strncpy(arglist[0], argument, (size_t) i);
2009-02-08 15:52:16 +01:00
arglist[0][i] = '\0';
/* copy equal sign */
arglist[1] = copy("=");
/* copy expression */
strncpy(arglist[2],&argument[i+1],strlen(&argument[i+1])+1);
/* create a new wordlist from array arglist */
wl2 = wl_build(arglist);
/* combine wordlists into wl2, free wl */
wl_splice(wl, wl2);
wl = NULL;
/* free arglist */
for (n=0; n < 3; n++) tfree(arglist[n]);
tfree(arglist);
2011-09-18 11:03:55 +02:00
}
2009-02-08 15:52:16 +01:00
} else {
/* deal with 'altermod m1 vth0=0.7' by moving
forward beyond 'm1' */
wl = wl->wl_next;
step++;
}
}
if(eqfound) {
/* step back in the wordlist, if we have moved forward, to catch 'm1' */
2011-09-18 11:03:55 +02:00
for(n=step;n>0;n--)
wl2 = wl2->wl_prev;
2009-02-08 15:52:16 +01:00
} else {
/* no equal sign found, probably a pre3f4 input format
'alter device value'
'alter device parameter value'
are supported,
'alter device parameter value parameter value [ parameter value ]'
multiple param value pairs are not supported!
*/
wl2 = wlin;
wlen = wl_length(wlin);
/* Return the last element of wlin */
wlin = wl_nthelem(100, wlin); /* no more than 100 vector elements */
if (eq(wlin->wl_word, "]"))/* we have a vector */ {
for (n=0;n<100;n++) {/* no more than 100 vector elements */
wlin=wlin->wl_prev;
maxelem++;
if (eq(wlin->wl_word, "[")) {
vecfound = TRUE;
break;
}
if(wlin->wl_prev==NULL) {
fprintf(cp_err, "Error: '[' is missing.\n");
fprintf(cp_err, "Cannot alter parameters.\n");
return;
}
}
}
if(wlen > maxelem) {
fprintf(cp_err, "Error: Only a single param - value pair supported.\n");
fprintf(cp_err, "Cannot alter parameters.\n");
return;
}
/* add the '=' */
/* create wordlist with '=' */
wleq = TMALLOC(wordlist, 1);
2009-02-08 15:52:16 +01:00
wleq->wl_word = copy("=");
/* add the last element (the value of the param - value pair) */
wleq->wl_next = wlin;
/* move back one element to place equal sign */
wlin = wlin->wl_prev;
/* add ' = value' */
wlin->wl_next = wleq;
/* step back until 'alter' or 'altermod' is found,
then move one step forward */
2011-09-18 11:03:55 +02:00
while (!ciprefix("alter",wlin->wl_word)) //while (!ciprefix(wlin->wl_word,"alter"))
2009-02-08 15:52:16 +01:00
wlin = wlin->wl_prev;
wlin = wlin->wl_next;
wl2 = wlin;
}
/* Everything is ready, parsing of the wordlist starts here. */
words = wl2;
2000-04-27 22:03:57 +02:00
while (words) {
2009-02-08 15:52:16 +01:00
p = words->wl_word;
eqword = words;
words = words->wl_next;
if (eq(p, "=")) {
break;
}
2000-04-27 22:03:57 +02:00
}
if (!words) {
2009-02-08 15:52:16 +01:00
fprintf(cp_err, "Error: no assignment found.\n");
fprintf(cp_err, "Cannot alter parameters.\n");
return;
2000-04-27 22:03:57 +02:00
}
/* device parameter = expr
device = expr
@dev[param] = expr
*/
dev = NULL;
param = NULL;
2009-02-08 15:52:16 +01:00
words = wl2;
2000-04-27 22:03:57 +02:00
while (words != eqword) {
2009-02-08 15:52:16 +01:00
p = words->wl_word;
if (param) {
2011-09-18 11:03:55 +02:00
fprintf(cp_err, "Warning: excess parameter name \"%s\" ignored.\n",
2009-02-08 15:52:16 +01:00
p);
} else if (dev) {
param = words->wl_word;
} else if (*p == '@' || *p == '#') {
dev = p + 1;
p =strchr(p, '[');
if (p) {
*p++ = 0;
param = p;
p =strchr(p, ']');
if (p)
*p = 0;
}
} else {
dev = p;
}
words = words->wl_next;
2000-04-27 22:03:57 +02:00
}
if (!dev) {
2009-02-08 15:52:16 +01:00
fprintf(cp_err, "Error: no model or device name provided.\n" );
fprintf(cp_err, "Cannot alter parameters.\n");
return;
2000-04-27 22:03:57 +02:00
}
words = eqword->wl_next;
2009-02-08 15:52:16 +01:00
/* skip next line if words is a vector */
2011-09-18 11:03:55 +02:00
if(!eq(words->wl_word, "[")) {
2009-02-08 15:52:16 +01:00
names = ft_getpnames(words, FALSE);
2011-09-18 11:03:55 +02:00
}
2009-02-08 15:52:16 +01:00
else names = NULL;
2000-04-27 22:03:57 +02:00
if (!names) {
2009-02-08 15:52:16 +01:00
/* Put this to try to resolve the case of
alter @vin[pulse] = [ 0 5 10n 10n 10n 50n 100n ]
*/
char *xsbuf;
int type = IF_REALVEC,i=0;
double *list;
double tmp;
int error;
/* move beyond '[' to allow INPevaluate() */
if(eq(words->wl_word, "[")) words = words->wl_next;
xsbuf = wl_flatten(words);
/* fprintf(cp_err, "Chain converted %s \n",xsbuf); */
dv = TMALLOC(struct dvec, 1);
dv->v_name = copy("real vector");
type &= IF_VARTYPES;
2009-02-08 15:52:16 +01:00
if (type == IF_REALVEC) {
list = TMALLOC(double, 1);
2009-02-08 15:52:16 +01:00
tmp = INPevaluate(&xsbuf,&error,1);
while (error == 0)
{
/*printf(" returning vector value %g\n",tmp); */
i++;
list=TREALLOC(double, list, i);
2009-02-08 15:52:16 +01:00
*(list+i-1) = tmp;
tmp = INPevaluate(&xsbuf,&error,1);
}
dv->v_realdata=list;
}
dv->v_length=i;
if (!dv)
2009-02-08 15:52:16 +01:00
return;
if (dv->v_length < 1)
{
2009-02-08 15:52:16 +01:00
fprintf(cp_err, "Error: cannot evaluate new parameter value.\n");
return;
}
2009-02-08 15:52:16 +01:00
/* Here I was, to change the inclusion in the circuit.
* will have to revise that dv is right for its insertion.
*/
if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model);
2009-02-08 15:52:16 +01:00
return;
2000-04-27 22:03:57 +02:00
}
dv = ft_evaluate(names);
if (!dv)
2009-02-08 15:52:16 +01:00
return;
2000-04-27 22:03:57 +02:00
if (dv->v_length < 1) {
2009-02-08 15:52:16 +01:00
fprintf(cp_err, "Error: cannot evaluate new parameter value.\n");
return;
2000-04-27 22:03:57 +02:00
}
if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model);
/* va: garbage collection for dv, if pnode names is no simple value */
if (names->pn_value==NULL && dv!=NULL) vec_free(dv);
2004-08-16 11:10:40 +02:00
free_pnode(names); /* free also dv, if pnode names is simple value */
2000-04-27 22:03:57 +02:00
return;
}
/* Given a device name, possibly with wildcards, return the matches. */
static wordlist *
devexpand(char *name)
{
wordlist *wl, *devices, *tw;
if (index(name, '*') ||strchr(name, '[') ||strchr(name, '?')) {
devices = cp_cctowl(ft_curckt->ci_devices);
for (wl = NULL; devices; devices = devices->wl_next)
if (cp_globmatch(name, devices->wl_word)) {
tw = alloc(struct wordlist);
if (wl) {
wl->wl_prev = tw;
tw->wl_next = wl;
wl = tw;
} else
wl = tw;
wl->wl_word = devices->wl_word;
}
} else if (cieq(name, "all")) {
2000-04-27 22:03:57 +02:00
wl = cp_cctowl(ft_curckt->ci_devices);
} else {
wl = alloc(struct wordlist);
wl->wl_word = name;
}
wl_sort(wl);
return (wl);
}
2011-09-18 11:03:55 +02:00
2011-10-02 10:29:03 +02:00
/* altermod mod_1 [mod_nn] file=modelparam.mod
load model file and overwrite models mod_1 till mod_nn with
all new parameters (limited to 16 models) */
2011-09-18 11:03:55 +02:00
static void com_alter_mod(wordlist *wl)
{
2011-10-02 10:29:03 +02:00
#define MODLIM 16 /* max number of models */
2011-09-18 11:03:55 +02:00
FILE *modfile;
2011-10-02 10:29:03 +02:00
char *modellist[MODLIM]={NULL}, *modellines[MODLIM]={NULL}, *newmodelname, *newmodelline;
char *filename=NULL, *eqword, *input, *modelline=NULL, *inptoken;
int modno = 0, molineno = 0, i, j;
wordlist *newcommand;
2011-09-18 11:03:55 +02:00
struct line *modeldeck, *tmpdeck;
char *readmode = "r";
2011-10-02 10:29:03 +02:00
char **arglist;
bool modelfound = FALSE;
int ij[MODLIM];
/* initialize */
for (i = 0; i < MODLIM; i++)
ij[i] = -1;
/* read all model names */
while (!ciprefix("file", wl->wl_word)) {
if (modno == MODLIM) {
fprintf(cp_err, "Error: too many model names in altermod command\n");
controlled_exit(1);
}
modellist[modno] = copy(wl->wl_word);
modno++;
wl = wl->wl_next;
}
input = wl_flatten(wl);
/* get the file name */
2011-09-18 11:03:55 +02:00
eqword = strstr(input, "=");
if (eqword) {
eqword++;
while(*eqword == ' ')
eqword++;
2011-10-02 10:29:03 +02:00
if(eqword=='\0') {
2011-09-18 11:03:55 +02:00
fprintf(cp_err, "Error: no filename given\n");
2011-10-02 10:29:03 +02:00
controlled_exit(1);
}
2011-09-18 11:03:55 +02:00
filename = copy(eqword);
}
else {
eqword = strstr(input, "file");
eqword += 4;
while(*eqword == ' ')
eqword++;
2011-10-02 10:29:03 +02:00
if(eqword=='\0') {
2011-09-18 11:03:55 +02:00
fprintf(cp_err, "Error: no filename given\n");
2011-10-02 10:29:03 +02:00
controlled_exit(1);
}
2011-09-18 11:03:55 +02:00
filename = copy(eqword);
}
modfile = inp_pathopen(filename, readmode);
inp_readall(modfile, &modeldeck, 0, ngdirname(filename), 0);
tfree(input);
tfree(filename);
2011-10-02 10:29:03 +02:00
/* get all lines starting with *model */
2011-09-18 11:03:55 +02:00
for (tmpdeck = modeldeck; tmpdeck; tmpdeck = tmpdeck->li_next)
if (ciprefix("*model", tmpdeck->li_line)) {
2011-10-02 10:29:03 +02:00
if (molineno == MODLIM){
fprintf(cp_err, "Error: more than %d models in deck, rest ignored\n", molineno);
break;
}
modellines[molineno] = tmpdeck->li_line;
molineno++;
}
/* Check if all models named in altermod command are to be found in input deck.
Exit if not successfull */
for (i = 0; i < modno; i++) {
for (j=0; j < molineno; j++) {
newmodelline = modellines[j];
/* get model name from model line */
inptoken = gettok(&newmodelline); /* *model */
tfree(inptoken);
newmodelname = gettok(&newmodelline); /* modelname */
if (cieq(newmodelname,modellist[i])) {
modelfound = TRUE;
tfree(newmodelname);
break;
}
tfree(newmodelname);
}
if (modelfound) {
modelfound = FALSE;
ij[i] = j; /* model in altermod, found in model line */
continue;
2011-09-18 11:03:55 +02:00
}
2011-10-02 10:29:03 +02:00
else {
fprintf(cp_err, "Error: could not find model %s in input deck\n", modellist[i]);
controlled_exit(1);
}
}
/* read the model line, generate the altermod commands as a wordlist,
and call com_alter_common() */
arglist = TMALLOC(char*, 4);
arglist[0] = copy("altermod");
arglist[3] = NULL;
/* for each model name of altermod command */
for (i = 0; i < modno; i++) {
/* model name */
arglist[1] = copy(modellist[i]);
/* parse model line from deck */
modelline = modellines[ij[i]];
inptoken = gettok(&modelline); /* skip *model */
tfree(inptoken);
inptoken = gettok(&modelline); /* skip modelname */
tfree(inptoken);
inptoken = gettok(&modelline); /* skip model type */
2011-09-18 11:03:55 +02:00
tfree(inptoken);
while ((inptoken = gettok(&modelline)) != NULL) {
/* exclude level and version */
if (ciprefix("version", inptoken) || ciprefix("level", inptoken)) {
tfree(inptoken);
continue;
}
arglist[2] = inptoken;
/* create a new wordlist from array arglist */
newcommand = wl_build(arglist);
com_alter_common(newcommand->wl_next, 1);
wl_free(newcommand);
tfree(inptoken);
}
2011-10-02 10:29:03 +02:00
tfree(arglist[1]);
2011-09-18 11:03:55 +02:00
}
2011-10-02 10:29:03 +02:00
tfree(arglist[0]);
tfree(arglist[3]);
2011-09-18 11:03:55 +02:00
}