Jspice3
srcparse.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: 1987 Thomas L. Quarles
5  1993 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 #include "spice.h"
9 #include <stdio.h>
10 #include "inpdefs.h"
11 #include "inpmacs.h"
12 #include "iferrmsg.h"
13 
14 #ifdef __STDC__
15 static char *src_parse(char**,GENERIC*,int,GENERIC*,double*,int*,INPtables*);
16 #else
17 static char *src_parse();
18 #endif
19 
20 void
21 SRCparse(type,ckt,tabp,currentp)
22 
23 int type;
24 GENERIC *ckt;
25 GENERIC *tabp;
26 GENERIC *currentp;
27 {
28  /* parser for all voltage/current sources */
29 
30  /*
31  * 'arbitrary' source:
32  * Aname <node> <node> [{"v" | "i"}=<expr>]
33  * [[DC] <val>] [AC [<val> [<val>]]]
34  *
35  * 'independent' voltage source:
36  * Vname <node> <node> [<expr>] [[DC] <val>] [AC [<val> [<val>]]]
37  *
38  * 'independent' current source:
39  * Iname <node> <node> [<expr>] [[DC] <val>] [AC [<val> [<val>]]]
40  *
41  * 'ccvs'
42  * Gname <node> <node> {"function" | <node> <node>} <expr>
43  * [[DC] <val>] [AC [<val> [<val>]]]
44  *
45  * 'vcvs'
46  * Ename <node> <node> {"function" | <node> <node>} <expr>
47  * [[DC] <val>] [AC [<val> [<val>]]]
48  *
49  * 'ccvs'
50  * Fname <node> <node> {"function" | <vname>} <expr>
51  * [[DC] <val>] [AC [<val> [<val>]]]
52  *
53  * 'cccs'
54  * Hname <node> <node> {"function" | <vname>} <expr>
55  * [[DC] <val>] [AC [<val> [<val>]]]
56  *
57  * General rules:
58  * For G,E,F,H the DC/AC values must appear after the expr (which
59  * is a number for linear dependent sources).
60  * Otherwise, the DC/AC specs can appear before or after the expr.
61  * If before, the numerical parameters must be given explicitly
62  * unless the following token prefix is manifestly not a number.
63  * The AC spec must be followed by something that is numerically
64  * not a number (vector parse not smart enough to stop).
65  * The expr must appear immediately after "v", "i", or "function".
66  * If "DC" is omitted, and an expr is given, the dc value must
67  * follow the expr.
68  */
69 
70  INPtables *tab = (INPtables*)tabp;
71  card *current = (card*)currentp;
72 
73  char *line; /* the part of the current line left to parse */
74  char *name; /* the device's name */
75  char *nname1; /* the first node's name */
76  char *nname2; /* the second node's name */
77  char *nname3; /* the third node's name */
78  char *nname4; /* the fourth node's name */
79  GENERIC *node1; /* the first node's node pointer */
80  GENERIC *node2; /* the second node's node pointer */
81  GENERIC *node3; /* the third node's node pointer */
82  GENERIC *node4; /* the fourth node's node pointer */
83  int error; /* error code temporary */
84  GENERIC *fast; /* pointer to the actual instance */
85  IFvalue ptemp; /* a value structure to package resistance into */
86  IFvalue *parm; /* a pointer to value structure to pick things up into */
87  int waslead; /* flag to indicate that unlabeled number was found */
88  double leadval; /* actual value of unlabeled number */
89  IFuid uid; /* uid of default model to be created */
90  char *tl; /* temporary */
91  char *nm;
92  char key;
93  char *leadname = NULL;
94  char *groundname = "0";
95  char buf[128];
96 
97  line = current->line;
98  key = *line;
99  if (islower(key))
100  key = toupper(key);
101  INPgetTok(&line,&name,1);
102  INPinsert(&name,tab);
103 
104  INPgetTok(&line,&nname1,1);
105  INPtermInsert(ckt,&nname1,tab,&node1);
106 
107  INPgetTok(&line,&nname2,1);
108  INPtermInsert(ckt,&nname2,tab,&node2);
109 
110  if (!tab->defAmod) {
111  /* create default source model */
112  IFnewUid(ckt,&uid,(IFuid)NULL,"A",UID_MODEL,(GENERIC**)NULL);
113  IFC(newModel,(ckt,type,&(tab->defAmod),uid))
114  }
115  IFC(newInstance,(ckt,tab->defAmod,&fast,name))
116  IFC(bindNode,(ckt,fast,1,node1))
117  IFC(bindNode,(ckt,fast,2,node2))
118 
120 
121  switch (key) {
122  case 'A':
123  break;
124  case 'I':
125  case 'V':
126  /* set alias for "x" in function */
127  ft_sim->ptXalias = copy("time");
128  leadname = "dc";
129  break;
130  case 'E':
131  case 'G':
132  /* control nodes optional with function */
133  tl = line;
134  INPgetTok(&line,&nname3,1);
135  if (strcmp(nname3,"function")) {
136  INPtermInsert(ckt,&nname3,tab,&node3);
137  INPgetTok(&line,&nname4,1);
138  INPtermInsert(ckt,&nname4,tab,&node4);
139  IFC(bindNode,(ckt,fast,3,node3))
140  IFC(bindNode,(ckt,fast,4,node4))
141 
142  /* set alias for "x" in function */
143  *buf = '\0';
144  if (strcmp(nname3,groundname) && strcmp(nname4,groundname))
145  sprintf(buf,"v(%s,%s)",nname3,nname4);
146  else if (strcmp(nname3,groundname))
147  sprintf(buf,"v(%s)",nname3);
148  else if (strcmp(nname4,groundname))
149  sprintf(buf,"(-v(%s))",nname4);
150 
151  if (strlen(buf)) {
152  ft_sim->ptXalias = copy(buf);
153  }
154  }
155  else {
156  line = tl;
157  txfree(nname3);
158  }
159  leadname = "gain";
160  break;
161  case 'F':
162  case 'H':
163  /* control device is optional with function */
164  tl = line;
165  INPgetTok(&tl,&nm,1);
166  if (strcmp(nm,"function")) {
167  parm = INPgetValue(ckt,&line,IF_INSTANCE,tab);
168  GCA(INPpName,("control",parm,ckt,type,fast))
169 
170  /* set alias for "x" in function */
171  sprintf(buf,"i(%s)",parm->uValue);
172  ft_sim->ptXalias = copy(buf);
173  }
174  txfree(nm);
175  leadname = "gain";
176  break;
177  }
178  ptemp.iValue = key;
179  GCA(INPpName,("type",&ptemp,ckt,type,fast))
180  current->error = INPerrCat(current->error,
181  src_parse(&line,ckt,type,fast,&leadval,&waslead,tab));
182  if (waslead && leadname != NULL) {
183  ptemp.rValue = leadval;
184  GCA(INPpName,(leadname,&ptemp,ckt,type,fast))
185  }
186 }
187 
188 
189 static char *
190 src_parse(line,ckt,dev,fast,leading,waslead,tab)
191 
192 /* A special parser for source specifications. The strategy is to
193  * first extract the recognized keywords and variables from the string,
194  * then examine what is left. If only a number remains, the leadval
195  * is set. Otherwise, if anything remains, a parse tree is built.
196  */
197 
198 char **line; /* the line to parse */
199 GENERIC *ckt; /* the circuit this device is a member of */
200 int dev; /* the device type code to the device being parsed */
201 GENERIC *fast; /* direct pointer to device being parsed */
202 double *leading; /* the optional leading numeric parameter */
203 int *waslead; /* flag - 1 if leading double given, 0 otherwise */
204 INPtables *tab;
205 {
206  int error; /* int to store evaluate error return codes in */
207  char *parm;
208  char *errbuf;
209  char *place;
210  int i;
211  IFvalue *val;
212  IFdevice *device = ft_sim->devices[dev];
213  char *nline, *nend, *start, *end;
214 
215  nline = tmalloc(strlen(*line)+1);
216  nend = nline;
217  start = end = *line;
218  *waslead = 0;
219 
220  while (**line != (char) 0) {
221 
222  /* get token, make sure we move past ')' */
223  start = *line;
224  error = INPgetTok(line,&parm,1);
225  if (error)
226  return (INPerror(error));
227  while (**line == ')')
228  (*line)++;
229  end = *line;
230 
231  if (!isalpha(*parm)) {
232  /* a keyword always starts with letter */
233  txfree(parm);
234  while (start < end)
235  *nend++ = *start++;
236  continue;
237  }
238 
239  /* Have to be careful here. If the token is "v" or "i", it
240  * could be a parameter for asrc, or it could be part of the
241  * function specification.
242  */
243 
244  if ((*parm == 'v' || *parm == 'i') && strlen(parm) == 1) {
245  char *s = start;
246  while (*s != *parm) s++;
247  s++;
248  if (*s == '(' || *s == ')') {
249  /* v(something) or i(something), or i(v) (source named
250  * "v"). Not a parameter.
251  */
252  txfree(parm);
253  while (start < end)
254  *nend++ = *start++;
255  continue;
256  }
257  }
258 
259  for (i = 0; i < *device->numInstanceParms; i++) {
260  if (!strcmp(parm,device->instanceParms[i].keyword)
261  && (device->instanceParms[i].dataType & IF_SET)) {
262 
263  txfree(parm);
264  val = INPgetValue(ckt,line,
265  device->instanceParms[i].dataType,tab);
266  if (!val) {
267  return (INPerror(E_PARMVAL));
268  }
269  error = (*(ft_sim->setInstanceParm))(ckt,fast,
270  device->instanceParms[i].id,
271  val,(IFvalue*)NULL);
272  if (error) {
273  return (INPerror(error));
274  }
275  break;
276  }
277  }
278  if (i == *device->numInstanceParms) {
279  txfree(parm);
280  while (start < end)
281  *nend++ = *start++;
282  }
283  }
284  *nend = '\0';
285 
286  /* nline contains function spec and/or leadval */
287  nend = nline;
288 
289  /* count tokens */
290  i = 0;
291  while (*nend != (char) 0) {
292  error = INPgetTok(&nend,&parm,1);
293  if (error)
294  return (INPerror(error));
295  if (*parm)
296  i++;
297  txfree(parm);
298  }
299  nend = nline;
300 
301  if (i == 0) {
302  /* nothing left */
303  txfree(nline);
304  return ((char *)NULL);
305  }
306 
307  /* check for leading value */
308  *leading = INPevaluate(&nend,&error,0);
309  if (error == 0) {
310  /* found a good leading number */
311  *waslead = 1;
312  if (i == 1) {
313  txfree(nline);
314  return ((char *)NULL);
315  }
316  while (isalpha(*nend))
317  nend++;
318  while (isspace(*nend) || *nend == ',')
319  nend++;
320  }
321  else {
322  *leading = 0.0;
323  nend = nline;
324  }
325 
326  /* something parseable left */
327 
328  for (i = 0; i < *device->numInstanceParms; i++) {
329  if (!strcmp("function",device->instanceParms[i].keyword)) {
330 
331  place = nend;
332  val = INPgetValue(ckt,&nend,
333  device->instanceParms[i].dataType,tab);
334  if (!val) {
335  /* leading value was part of function, perhaps */
336  if (*waslead == 1) {
337  errbuf = errMsg;
338  errMsg = NULL;
339  nend = nline;
340  val = INPgetValue(ckt,&nend,
341  device->instanceParms[i].dataType,tab);
342  if (!val || nend <= place) {
343  /* leadval asumed ok, later tokens bad */
344  if (val) {
345  IFfree(val->tValue);
346  }
347  txfree(errMsg);
348  errMsg = errbuf;
349  return (INPerror(E_SYNTAX));
350  }
351  /* leadval was part of function */
352  *waslead = 0;
353  *leading = 0.0;
354  txfree(errbuf);
355  }
356  else {
357  return (INPerror(E_SYNTAX));
358  }
359  }
360  error = (*(ft_sim->setInstanceParm))(ckt,fast,
361  device->instanceParms[i].id,
362  val,(IFvalue*)NULL);
363  if (error) {
364  return (INPerror(error));
365  }
366  break;
367  }
368  }
369 
370  /* anything still there? */
371  while (*nend) {
372  if (!*waslead) {
373  /* check for leading value after function */
374  *leading = INPevaluate(&nend,&error,1);
375 
376  if (error == 0) {
377  /* found a good leading number */
378  *waslead = 1;
379  continue;
380  }
381  }
382  (void)INPgetTok(&nend,&parm,1);
383  if (*parm) {
384  errbuf = tmalloc(strlen(parm)+25);
385  (void)sprintf(errbuf,"Unknown parameter (%s).",parm);
386  txfree(parm);
387  txfree(nline);
388  return (errbuf);
389  }
390  }
391  txfree(nline);
392  return ((char *)NULL);
393 }
static char * src_parse()
static char buf[MAXPROMPT]
Definition: arg.c:18
DISPDEVICE device[]
Definition: display.c:24
void IFfree()
char * INPerror()
int INPpName()
IFsimulator * ft_sim
Definition: main.c:111
char * ptXalias
Definition: ifsim.h:471
char * line
Definition: inpdefs.h:64
int INPtermInsert()
int * numInstanceParms
Definition: ifsim.h:312
IFvalue * INPgetValue()
Definition: cddefs.h:119
int IFnewUid()
IFparm * instanceParms
Definition: ifsim.h:313
Definition: inpdefs.h:62
#define UID_MODEL
Definition: ifsim.h:83
char * errMsg
Definition: main.c:42
#define E_SYNTAX
Definition: iferrmsg.h:37
void SRCparse(int type, GENERIC *ckt, GENERIC *tabp, GENERIC *currentp)
Definition: srcparse.c:21
double INPevaluate()
Definition: subckt.c:51
#define IF_INSTANCE
Definition: ifsim.h:112
int iValue
Definition: ifsim.h:232
double rValue
Definition: ifsim.h:233
char * copy()
int INPinsert()
char * tmalloc()
Definition: fteinp.h:14
static char start[32]
Definition: subckt.c:76
#define E_PARMVAL
Definition: iferrmsg.h:32
GENERIC * IFuid
Definition: ifsim.h:72
IFdevice ** devices
Definition: ifsim.h:461
int id
Definition: ifsim.h:56
#define IF_SET
Definition: ifsim.h:135
#define tfree(x)
Definition: cdmacs.h:22
void txfree()
#define NULL
Definition: spdefs.h:121
Definition: types.c:18
#define GCA(func, args)
Definition: inpmacs.h:27
#define IFC(func, args)
Definition: inpmacs.h:19
char * error
Definition: inpdefs.h:65
int dataType
Definition: ifsim.h:57
IFparseTree * tValue
Definition: ifsim.h:238
GENERIC * defAmod
Definition: inpdefs.h:35
char * keyword
Definition: ifsim.h:55
char GENERIC
Definition: ifsim.h:27
IFuid uValue
Definition: ifsim.h:236
char * INPerrCat()
int INPgetTok()