Jspice3
inpptree.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 Wayne A. Christopher
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 #include "spice.h"
9 #include "inpdefs.h"
10 #include "iferrmsg.h"
11 #include "misc.h"
12 
13 static IFvalue *values = NULL;
14 static int *types;
15 static int numvalues;
16 static GENERIC *circuit;
17 static INPtables *tables;
18 
19 #ifdef __STDC__
20 static void PTalias(char**);
23 static INPparseNode *mkcon(double);
25 static INPparseNode *mkf(int,INPparseNode*);
26 static int PTcheck(INPparseNode*);
27 static INPparseNode *PTparse(char**);
30 static INPparseNode *mkfnode(char*,INPparseNode*);
31 static INPparseNode *mknnode(double);
32 static INPparseNode *mksnode(char*);
33 static PTelement *PTlexer(char**);
34 static char *get_stringvar(char**,char*);
35 static int tran_hack(char*,char*);
36 static int is_tranfunc(char*,INPparseNode*);
37 static INPparseNode *allocate_pnode(int);
38 static int pt_const(INPparseNode*,double*,double*,double*);
39 static int pt_var(INPparseNode*,double*,double*,double*);
40 static int pt_parm(INPparseNode*,double*,double*,double*);
41 static int pt_fcn(INPparseNode*,double*,double*,double*);
42 static int pt_table(INPparseNode*,double*,double*,double*);
43 static int pt_tran(INPparseNode*,double*,double*,double*);
44 static int pt_op(INPparseNode*,double*,double*,double*);
45 #else
46 static void PTalias();
48 static INPparseNode *copy_node();
49 static INPparseNode *mkcon();
50 static INPparseNode *mkb();
51 static INPparseNode *mkf();
52 static int PTcheck();
53 static INPparseNode *PTparse();
54 static INPparseNode *makepnode();
55 static INPparseNode *mkbnode();
56 static INPparseNode *mkfnode();
57 static INPparseNode *mknnode();
58 static INPparseNode *mksnode();
59 static PTelement *PTlexer();
60 static char *get_stringvar();
61 static int tran_hack();
62 static int is_tranfunc();
64 static int pt_const();
65 static int pt_var();
66 static int pt_parm();
67 static int pt_fcn();
68 static int pt_table();
69 static int pt_tran();
70 static int pt_op();
71 #endif
72 
73 extern IFsimulator *ft_sim; /* XXX */
74 
75 #define P_ALLOC 0
76 #define P_CLEAR 1
77 #define P_RESET 2
78 
79 
80 /* These are all the constants any sane person needs. */
81 
82 static struct constant {
83  char *name;
84  double value;
85 } constants[] = {
86  { "e", M_E },
87  { "pi", M_PI },
88  { NULL, 0 }
89 } ;
90 
91 #define issep(c) ((c)==' '||(c)=='\t'||(c)=='='||(c)=='('||(c)==')'||\
92 (c)==','||(c)=='-'||(c)=='+'||(c)=='*'||(c)=='/'||(c)=='^')
93 
94 
95 void
96 INPgetTree(line, pt, ckt, tab)
97 
98 /* Parse the expression in *line as far as possible, and return the parse
99  * tree obtained. If there is an error, *pt will be set to NULL and an error
100  * message will be printed.
101  */
102 char **line;
103 INPparseTree **pt;
104 GENERIC *ckt;
105 INPtables *tab;
106 {
107  INPparseNode *p;
108  int i;
109  char *tl, *tl0;
110 
111  values = NULL;
112  types = NULL;
113  numvalues = 0;
114 
115  circuit = ckt;
116  tables = tab;
117 
118  tl = *line;
119  PTalias(&tl);
120  tl0 = tl;
121  p = PTparse(&tl);
122  *line += strlen(*line) - strlen(tl);
123  *--tl = '\0';
124 
125  if (!p || !PTcheck(p)) {
126  *pt = NULL;
127  (void)allocate_pnode(P_CLEAR);
128  txfree(tl0);
129  return;
130  }
131 
132  (*pt) = alloc(INPparseTree);
133 
134  (*pt)->p.numVars = numvalues;
135  (*pt)->p.varTypes = types;
136  (*pt)->p.vars = values;
137  (*pt)->p.IFinit = IFinit;
138  (*pt)->p.IFeval = IFeval;
139  (*pt)->p.IFfree = IFfree;
140  (*pt)->p.line = tl0;
141  (*pt)->tree = p;
142 
143  if (numvalues) {
144  (*pt)->derivs = (INPparseNode **)
145  tmalloc(numvalues * sizeof (INPparseNode *));
146 
147  for (i = 0; i < numvalues; i++)
148  (*pt)->derivs[i] = copy_node(PTdifferentiate(p, i));
149  }
150 
151 /*
152 INPptPrint("tree:",*pt);
153 */
154  (void)allocate_pnode(P_RESET);
155  return;
156 }
157 
158 
159 static void
161 
162 /* remove any aliasing in line */
163 char **line;
164 {
165  char *s, *buf, *tok, c, cc;
166  char *newline, *nl, *tl;
167  int len, olen, count = 0;
168  IFvalue *v;
169 
170  tl = *line;
171  newline = copy(tl);
172  nl = newline;
173  len = strlen(newline);
174 
175  while (*tl) {
176 
177  while (*tl && issep(*tl)) {
178  if ((olen = (nl - newline)) >= len) {
179  len += 16;
180  newline = trealloc(newline,len+1);
181  nl = newline + olen;
182  }
183  *nl++ = *tl++;
184  }
185 
186  if (!*tl)
187  break;
188 
189  tok = tl;
190 
191  while (*tl && !issep(*tl))
192  tl++;
193 
194  c = *tl;
195  *tl = '\0';
196 
197  buf = NULL;
198 
199  /* is it a reference to a branch? */
200  if ((s = strchr(tok,'#')) != NULL && !strcmp(s+1,"branch")) {
201  cc = *s;
202  *s = '\0';
203  buf = tmalloc(strlen(tok) + 4);
204  sprintf(buf,"i(%s)",tok);
205  *s = cc;
206  }
207 
208  /* is it 'x' ? */
209  if (*tok == 'x' && !*(tok+1) && ft_sim->ptXalias) {
210  buf = copy(ft_sim->ptXalias);
211  }
212 
213  if (buf)
214  tok = buf;
215 
216  while (*tok) {
217  if ((olen = (nl - newline)) >= len) {
218  len += 16;
219  newline = trealloc(newline,len);
220  nl = newline + olen;
221  }
222  *nl++ = *tok++;
223  }
224 
225  if (buf)
226  txfree(buf);
227 
228  *tl = c;
229  }
230  *nl = '\0';
231  *line = newline;
232 }
233 
234 
235 static INPparseNode *
237 
238 /* This routine takes the partial derivative of the parse tree with respect
239  * to the i'th variable. We try to do optimizations like getting rid of
240  * 0-valued terms.
241  */
242 
243 INPparseNode *p;
244 int varnum;
245 {
246  INPparseNode *arg1, *arg2, *newp;
247 
248 /* printf("differentiating: "); printTree(p); printf(" wrt var %d\n", varnum);*/
249 
250  switch (p->type) {
251 
252  case PT_CONSTANT:
253  case PT_PARAM:
254  case PT_TFUNC:
255  newp = mkcon((double) 0);
256  break;
257 
258  case PT_VAR:
259  /* Is this the variable we're differentiating wrt? */
260  if (p->valueIndex == varnum)
261  newp = mkcon((double) 1);
262  else
263  newp = mkcon((double) 0);
264  break;
265 
266  case PT_PLUS:
267  case PT_MINUS:
268  arg1 = PTdifferentiate(p->left, varnum);
269  arg2 = PTdifferentiate(p->right, varnum);
270  if (arg1->type == PT_CONSTANT && arg1->constant == 0) {
271  txfree((char*)arg1);
272  if (p->type == PT_PLUS)
273  newp = arg2;
274  else
275  newp = mkf(PTF_UMINUS,arg2);
276  }
277  else if (arg2->type == PT_CONSTANT && arg2->constant == 0) {
278  txfree((char*)arg2);
279  newp = arg1;
280  }
281  else
282  newp = mkb(p->type, arg1, arg2);
283  break;
284 
285  case PT_TIMES:
286  /* d(a * b) = d(a) * b + d(b) * a */
287  arg1 = PTdifferentiate(p->left, varnum);
288  arg2 = PTdifferentiate(p->right, varnum);
289  if (arg1->type == PT_CONSTANT && arg1->constant == 0) {
290  txfree((char*)arg1);
291  newp = mkb(PT_TIMES,p->left,arg2);
292  }
293  else if (arg2->type == PT_CONSTANT && arg2->constant == 0) {
294  txfree((char*)arg2);
295  newp = mkb(PT_TIMES,arg1,p->right);
296  }
297  else
298  newp = mkb(PT_PLUS, mkb(PT_TIMES, arg1, p->right),
299  mkb(PT_TIMES, p->left, arg2));
300  break;
301 
302  case PT_DIVIDE:
303  /* d(a / b) = (d(a) * b - d(b) * a) / b^2 */
304  arg1 = PTdifferentiate(p->left, varnum);
305  arg2 = PTdifferentiate(p->right, varnum);
306  if (arg1->type == PT_CONSTANT && arg1->constant == 0) {
307  txfree((char*)arg1);
308  newp = mkb(PT_DIVIDE, mkf(PTF_UMINUS,
309  mkb(PT_TIMES, p->left, arg2)),
310  mkb(PT_POWER, p->right, mkcon((double) 2)));
311  }
312  else if (arg2->type == PT_CONSTANT && arg2->constant == 0) {
313  txfree((char*)arg2);
314  newp = mkb(PT_DIVIDE, arg1, p->right);
315  }
316  else
317  newp = mkb(PT_DIVIDE, mkb(PT_MINUS, mkb(PT_TIMES, arg1,
318  p->right), mkb(PT_TIMES, p->left, arg2)),
319  mkb(PT_POWER, p->right, mkcon((double) 2)));
320  break;
321 
322  case PT_POWER:
323  /* Two cases... If the power is a constant then we're cool.
324  * Otherwise we have to be tricky.
325  */
326 
327  if (p->right->type == PT_CONSTANT) {
328 
329  arg1 = PTdifferentiate(p->left, varnum);
330  newp = mkb(PT_TIMES, mkb(PT_TIMES,
331  mkcon(p->right->constant),
332  mkb(PT_POWER, p->left,
333  mkcon(p->right->constant - 1))),
334  arg1);
335  }
336  else {
337  /* This is complicated. f(x) ^ g(x) ->
338  * exp(y(x) * ln(f(x)) ...
339  */
340  arg1 = PTdifferentiate(p->left, varnum);
341  arg2 = PTdifferentiate(p->right, varnum);
342  newp = mkb(PT_TIMES, mkf(PTF_EXP, mkb(PT_TIMES,
343  p->right, mkf(PTF_LN, p->left))),
344  mkb(PT_PLUS, mkb(PT_TIMES, p->right,
345  mkb(PT_DIVIDE, arg1, p->left)),
346  mkb(PT_TIMES, arg2,
347  mkf(PTF_LN, arg1))));
348 
349  }
350  break;
351 
352  case PT_FUNCTION:
353  /* Many cases. Set arg1 to the derivative of the function,
354  * and arg2 to the derivative of the argument.
355  */
356  arg2 = PTdifferentiate(p->left, varnum);
357  if (arg2->type == PT_CONSTANT && arg2->constant == 0) {
358  newp = arg2;
359  break;
360  }
361 
362  switch (p->funcnum) {
363 
364  case PTF_ABS: /* sgn(u) */
365  arg1 = mkf(PTF_SGN, p->left);
366  break;
367 
368  case PTF_SGN: /* u -> a hack */
369  arg1 = p->left;
370  break;
371 
372  case PTF_ACOS: /* - 1 / sqrt(1 - u^2) */
373  arg1 = mkb(PT_DIVIDE, mkcon((double) -1), mkf(PTF_SQRT,
374  mkb(PT_MINUS, mkcon((double) 1),
375  mkb(PT_POWER, p->left, mkcon((double)
376  2)))));
377  break;
378 
379  case PTF_ACOSH: /* 1 / sqrt(u^2 - 1) */
380  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkf(PTF_SQRT,
381  mkb(PT_MINUS, mkb(PT_POWER, p->left,
382  mkcon((double) 2)),
383  mkcon((double) 1))));
384 
385  break;
386 
387  case PTF_ASIN: /* 1 / sqrt(1 - u^2) */
388  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkf(PTF_SQRT,
389  mkb(PT_MINUS, mkcon((double) 1),
390  mkb(PT_POWER, p->left, mkcon((double)
391  2)))));
392  break;
393 
394  case PTF_ASINH: /* 1 / sqrt(u^2 + 1) */
395  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkf(PTF_SQRT,
396  mkb(PT_PLUS, mkb(PT_POWER, p->left,
397  mkcon((double) 2)),
398  mkcon((double) 1))));
399  break;
400 
401  case PTF_ATAN: /* 1 / (1 + u^2) */
402  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkb(PT_PLUS,
403  mkb(PT_POWER, p->left, mkcon((double)
404  2)), mkcon((double) 1)));
405  break;
406 
407  case PTF_ATANH: /* 1 / (1 - u^2) */
408  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkb(PT_MINUS,
409  mkcon((double) 1), mkb(PT_POWER,
410  p->left, mkcon((double) 2))));
411  break;
412 
413  case PTF_COS: /* - sin(u) */
414  arg1 = mkf(PTF_UMINUS, mkf(PTF_SIN, p->left));
415  break;
416 
417  case PTF_COSH: /* sinh(u) */
418  arg1 = mkf(PTF_SINH, p->left);
419  break;
420 
421  case PTF_EXP: /* exp(u) */
422  arg1 = mkf(PTF_EXP, p->left);
423  break;
424 
425  case PTF_LN: /* 1 / u */
426  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), p->left);
427  break;
428 
429  case PTF_LOG: /* log(e) / u */
430  arg1 = mkb(PT_DIVIDE, mkcon((double) M_LOG10E), p->left);
431  break;
432 
433  case PTF_SIN: /* cos(u) */
434  arg1 = mkf(PTF_COS, p->left);
435  break;
436 
437  case PTF_SINH: /* cosh(u) */
438  arg1 = mkf(PTF_COSH, p->left);
439  break;
440 
441  case PTF_SQRT: /* 1 / (2 * sqrt(u)) */
442  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkb(PT_TIMES,
443  mkcon((double) 2), mkf(PTF_SQRT,
444  p->left)));
445  break;
446 
447  case PTF_TAN: /* 1 / (cos(u) ^ 2) */
448  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkb(PT_POWER,
449  mkf(PTF_COS, p->left), mkcon((double)
450  2)));
451  break;
452 
453  case PTF_TANH: /* 1 / (cosh(u) ^ 2) */
454  arg1 = mkb(PT_DIVIDE, mkcon((double) 1), mkb(PT_POWER,
455  mkf(PTF_COSH, p->left), mkcon((double)
456  2)));
457  break;
458 
459  case PTF_UMINUS: /* - 1 ; like a constant (was 0 !) */
460  arg1 = mkcon((double) - 1.0);
461  break;
462 
463  default:
464  fprintf(stderr, "Internal Error: bad function # %d\n",
465  p->funcnum);
466  newp = NULL;
467  break;
468  }
469  newp = mkb(PT_TIMES, arg1, arg2);
470  break;
471 
472  case PT_TABLE:
473  arg2 = PTdifferentiate(p->left, varnum);
474  if (arg2->type == PT_CONSTANT && arg2->constant == 0) {
475  newp = arg2;
476  break;
477  }
478  arg1 = allocate_pnode(P_ALLOC);
479  arg1->new_deriv = 1;
480  arg1->type = PT_TABLE;
481  arg1->left = p->left;
482  arg1->funcnum = 1; /* return derivative if 1 */
483  arg1->function = p->function;
484  arg1->funcname = p->funcname;
485  arg1->evfunc = pt_table;
486  newp = mkb(PT_TIMES, arg1, arg2);
487  break;
488 
489  default:
490  fprintf(stderr, "Internal error: bad node type %d\n", p->type);
491  newp = NULL;
492  break;
493  }
494 
495 /* printf("result is: "); printTree(newp); printf("\n"); */
496  return (newp);
497 }
498 
499 
500 static INPparseNode *
502 INPparseNode *p;
503 {
504  INPparseNode *new;
505  int num;
506 
507  if (p == NULL)
508  return (NULL);
509 
510  if (p->new_deriv) {
511  p->new_deriv = 0;
512  p->left = copy_node(p->left);
513  p->right = copy_node(p->right);
514  return (p);
515  }
516 
517  new = allocate_pnode(P_ALLOC);
518 
519  *new = *p;
520  if (new->type == PT_TFUNC) {
521  new->trancoeffs =
522  (double*)tmalloc(new->numtrancoeffs*sizeof(double));
523  memcpy(new->trancoeffs,p->trancoeffs,new->numtrancoeffs*sizeof(double));
524  if (new->funcnum == PTF_tPULSE) {
525  new->trancache = (double*)tmalloc(2*sizeof(double));
526  }
527  else if (new->funcnum == PTF_tPWL) {
528  num = new->numtrancoeffs/2 - 1;
529  new->trancache = (double*)tmalloc(num*sizeof(double));
530  memcpy(new->trancache,p->trancache,num*sizeof(double));
531  }
532  }
533  new->left = copy_node(p->left);
534  new->right = copy_node(p->right);
535  return (new);
536 }
537 
538 
539 static INPparseNode *
541 
542 double value;
543 {
545 
546  p->type = PT_CONSTANT;
547  p->constant = value;
548  p->evfunc = pt_const;
549  p->new_deriv = 1;
550 
551  return (p);
552 }
553 
554 
555 static INPparseNode *
556 mkb(type, left, right)
557 
558 int type;
559 INPparseNode *left, *right;
560 {
561  INPparseNode *p;
562  int i;
563 
564  if ((right->type == PT_CONSTANT) && (left->type == PT_CONSTANT)) {
565  switch (type) {
566  case PT_TIMES:
567  return (mkcon(left->constant * right->constant));
568 
569  case PT_DIVIDE:
570  return (mkcon(left->constant / right->constant));
571 
572  case PT_PLUS:
573  return (mkcon(left->constant + right->constant));
574 
575  case PT_MINUS:
576  return (mkcon(left->constant - right->constant));
577 
578  case PT_POWER:
579  return (mkcon(pow(left->constant, right->constant)));
580  }
581  }
582  switch (type) {
583  case PT_TIMES:
584  if ((left->type == PT_CONSTANT) && (left->constant == 0))
585  return (left);
586  else if ((right->type == PT_CONSTANT) && (right->constant == 0))
587  return (right);
588  else if ((left->type == PT_CONSTANT) && (left->constant == 1))
589  return (right);
590  else if ((right->type == PT_CONSTANT) && (right->constant == 1))
591  return (left);
592  break;
593 
594  case PT_DIVIDE:
595  if ((left->type == PT_CONSTANT) && (left->constant == 0))
596  return (left);
597  else if ((right->type == PT_CONSTANT) && (right->constant == 1))
598  return (left);
599  break;
600 
601  case PT_PLUS:
602  if ((left->type == PT_CONSTANT) && (left->constant == 0))
603  return (right);
604  else if ((right->type == PT_CONSTANT) && (right->constant == 0))
605  return (left);
606  break;
607 
608  case PT_MINUS:
609  if ((right->type == PT_CONSTANT) && (right->constant == 0))
610  return (left);
611  else if ((left->type == PT_CONSTANT) && (left->constant == 0))
612  return (mkf(PTF_UMINUS, right));
613  break;
614 
615  case PT_POWER:
616  if (right->type == PT_CONSTANT) {
617  if (right->constant == 0)
618  return (mkcon(1.0));
619  else if (right->constant == 1)
620  return (left);
621  }
622  break;
623  }
624 
625  for (i = 0; PTops[i].number != PT_PLACEHOLDER; i++)
626  if (PTops[i].number == type)
627  break;
628  if (PTops[i].number == PT_PLACEHOLDER) {
629  fprintf(stderr, "Internal Error: bad type %d\n", type);
630  return (NULL);
631  }
632  p = allocate_pnode(P_ALLOC);
633  p->new_deriv = 1;
634  p->type = type;
635  p->left = left;
636  p->right = right;
637  p->function = PTops[i].funcptr;
638  p->funcname = PTops[i].name;
639  p->evfunc = pt_op;
640 
641  return (p);
642 }
643 
644 
645 static INPparseNode *
646 mkf(type, arg)
647 
648 int type;
649 INPparseNode *arg;
650 {
651  INPparseNode *p;
652  int i;
653  double constval;
654 
655  for (i = 0; PTfuncs[i].name; i++)
656  if (PTfuncs[i].number == type)
657  break;
658  if (!PTfuncs[i].name) {
659  fprintf(stderr, "Internal Error: bad type %d\n", type);
660  return (NULL);
661  }
662 
663  if (arg->type == PT_CONSTANT) {
664  constval = ((*PTfuncs[i].funcptr) (arg->constant));
665  return (mkcon(constval));
666  }
667  p = allocate_pnode(P_ALLOC);
668  p->new_deriv = 1;
669  p->type = PT_FUNCTION;
670  p->left = arg;
671  p->funcnum = i;
672  p->function = PTfuncs[i].funcptr;
673  p->funcname = PTfuncs[i].name;
674  p->evfunc = pt_fcn;
675 
676  return (p);
677 }
678 
679 
680 static int
682 
683 /* Check for remaining PT_PLACEHOLDERs in the parse tree.
684  * Returns 1 if ok.
685  */
686 INPparseNode *p;
687 {
688  switch (p->type) {
689  case PT_PLACEHOLDER:
690  return (0);
691 
692  case PT_CONSTANT:
693  case PT_VAR:
694  case PT_PARAM:
695  case PT_TFUNC:
696  return (1);
697 
698  case PT_FUNCTION:
699  return (PTcheck(p->left));
700 
701  case PT_PLUS:
702  case PT_MINUS:
703  case PT_TIMES:
704  case PT_DIVIDE:
705  case PT_POWER:
706  return (PTcheck(p->left) && PTcheck(p->right));
707 
708  default:
709  fprintf(stderr, "Internal error: bad node type %d\n", p->type);
710  return (0);
711  }
712 }
713 
714 
715 /* The operator-precedence table for the parser. */
716 
717 #define G 1 /* Greater than. */
718 #define L 2 /* Less than. */
719 #define E 3 /* Equal. */
720 #define R 4 /* Error. */
721 
722 static char prectable[11][11] = {
723  /* $ + - * / ^ u- ( ) v , */
724 /* $ */ { R, L, L, L, L, L, L, L, R, L, R },
725 /* + */ { G, G, G, L, L, L, L, L, G, L, G },
726 /* - */ { G, G, G, L, L, L, L, L, G, L, G },
727 /* * */ { G, G, G, G, G, L, L, L, G, L, G },
728 /* / */ { G, G, G, G, G, L, L, L, G, L, G },
729 /* ^ */ { G, G, G, G, G, L, L, L, G, L, G },
730 /* u-*/ { G, G, G, G, G, G, G, L, G, L, R },
731 /* ( */ { R, L, L, L, L, L, L, L, E, L, L },
732 /* ) */ { G, G, G, G, G, G, G, R, G, R, G },
733 /* v */ { G, G, G, G, G, G, G, G, G, R, G },
734 /* , */ { G, L, L, L, L, L, L, L, G, L, G }
735 
736 } ;
737 
738 
739 static INPparseNode *
741 
742 /* Return an expr. */
743 char **line;
744 {
745  PTelement stack[PT_STACKSIZE];
746  int sp = 0, st, i;
747  PTelement *top, *next;
748  INPparseNode *pn, *lpn, *rpn;
749 
750  stack[0].token = TOK_END;
751  next = PTlexer(line);
752 
753  while ((sp > 1) || (next->token != TOK_END)) {
754  /* Find the top-most terminal. */
755  i = sp;
756  do {
757  top = &stack[i--];
758  } while (top->token == TOK_VALUE);
759 
760 
761  switch (prectable[top->token][next->token]) {
762  case L:
763  case E:
764  /* Push the token read. */
765  if (sp == (PT_STACKSIZE - 1)) {
766  errMsg = copy("stack overflow");
767  return (NULL);
768  }
769  bcopy((char *) next, (char *) &stack[++sp],
770  sizeof (PTelement));
771  next = PTlexer(line);
772  continue;
773 
774  case R:
775  return (NULL);
776 
777  case G:
778  /* Reduce. Make st and sp point to the elts on the
779  * stack at the end and beginning of the junk to
780  * reduce, then try and do some stuff. When scanning
781  * back for a <, ignore VALUES.
782  */
783  st = sp;
784  if (stack[sp].token == TOK_VALUE)
785  sp--;
786  while (sp > 0) {
787  if (stack[sp - 1].token == TOK_VALUE)
788  i = 2; /* No 2 pnodes together... */
789  else
790  i = 1;
791  if (prectable[stack[sp - i].token]
792  [stack[sp].token] == L)
793  break;
794  else
795  sp = sp - i;
796  }
797  if (stack[sp - 1].token == TOK_VALUE)
798  sp--;
799  /* Now try and see what we can make of this.
800  * The possibilities are: - node
801  * node op node
802  * ( node )
803  * func ( node )
804  * func ( node, node, node, ... ) <- new
805  * node
806  */
807  if (st == sp) {
808  pn = makepnode(&stack[st]);
809  if (pn == NULL)
810  goto err;
811  }
812  else if ((stack[sp].token == TOK_UMINUS) &&
813  (st == sp + 1)) {
814  lpn = makepnode(&stack[st]);
815  if (lpn == NULL)
816  goto err;
817  pn = mkfnode(copy("-"), lpn);
818  }
819  else if ((stack[sp].token == TOK_LPAREN) &&
820  (stack[st].token == TOK_RPAREN)) {
821  pn = makepnode(&stack[sp + 1]);
822  if (pn == NULL)
823  goto err;
824  }
825  else if ((stack[sp + 1].token == TOK_LPAREN) &&
826  (stack[st].token == TOK_RPAREN)) {
827  lpn = makepnode(&stack[sp + 2]);
828  if ((lpn == NULL) || (stack[sp].type != TYP_STRING))
829  goto err;
830  if (!(pn = mkfnode(stack[sp].value.string, lpn)))
831  return (NULL);
832  }
833  else { /* node op node */
834  lpn = makepnode(&stack[sp]);
835  rpn = makepnode(&stack[st]);
836  if ((lpn == NULL) || (rpn == NULL))
837  goto err;
838  pn = mkbnode(stack[sp + 1].token, lpn, rpn);
839  }
840  stack[sp].token = TOK_VALUE;
841  stack[sp].type = TYP_PNODE;
842  stack[sp].value.pnode = pn;
843  continue;
844  }
845  }
846  pn = makepnode(&stack[1]);
847  if (pn)
848  return (pn);
849 err:
850  return (NULL);
851 }
852 
853 
854 static INPparseNode *
856 
857 /* Given a pointer to an element, make a pnode out of it (if it already
858  * is one, return a pointer to it). If it isn't of type VALUE, then return
859  * NULL.
860  */
861 PTelement *elem;
862 {
863  if (elem->token != TOK_VALUE)
864  return (NULL);
865 
866  switch (elem->type) {
867  case TYP_STRING:
868  return (mksnode(elem->value.string));
869 
870  case TYP_NUM:
871  return (mknnode(elem->value.real));
872 
873  case TYP_PNODE:
874  return (elem->value.pnode);
875 
876  default:
877  fprintf(stderr, "Internal Error: bad token type\n");
878  return (NULL);
879  }
880 }
881 
882 
883 static INPparseNode *
884 mkbnode(opnum, arg1, arg2)
885 
886 /* Binop node. */
887 int opnum;
888 INPparseNode *arg1, *arg2;
889 {
890  INPparseNode *p;
891  int i;
892 
893  for (i = 0; PTops[i].name != PT_PLACEHOLDER; i++)
894  if (PTops[i].number == opnum)
895  break;
896 
897  if (PTops[i].number == PT_PLACEHOLDER) {
898  fprintf(stderr, "Internal Error: no such op num %d\n", opnum);
899  return (NULL);
900  }
901  p = allocate_pnode(P_ALLOC);
902 
903  p->type = opnum;
904  p->funcname = PTops[i].name;
905  p->function = PTops[i].funcptr;
906  p->evfunc = pt_op;
907  p->left = arg1;
908  p->right = arg2;
909 
910  return (p);
911 }
912 
913 
914 static INPparseNode *
915 mkfnode(fname, arg)
916 
917 /* fname freed */
918 char *fname;
919 INPparseNode *arg;
920 {
921  int i;
922  INPparseNode *p;
923  char *name, *s;
924  IFvalue temp;
925  GENERIC *table;
926 
927  p = allocate_pnode(P_ALLOC);
928 
929  if (!strcmp(fname, "v")) {
930  name = tmalloc(128);
931  if (arg->type == PT_PLACEHOLDER) {
932  strcpy(name, arg->funcname);
933  txfree(arg->funcname);
934  }
935  else if (arg->type == PT_CONSTANT) {
936  (void) sprintf(name, "%d", (int) arg->constant);
937  }
938  else if (arg->type != PT_COMMA) {
939  errMsg = copy("badly formed node voltage");
940  txfree(fname);
941  return (NULL);
942  }
943 
944  if (arg->type == PT_COMMA) {
945  /* Change v(a,b) into v(a) - v(b) */
946  p = mkb(PT_MINUS, mkfnode(copy(fname), arg->left),
947  mkfnode(copy(fname), arg->right));
948  }
949  else {
950  /* printf("getting a node called '%s'\n", name); */
951  INPtermInsert(circuit, &name, tables, &(temp.nValue));
952  for (i = 0; i < numvalues; i++)
953  if ((types[i] == IF_NODE) && (values[i].nValue ==
954  temp.nValue))
955  break;
956  if (i == numvalues) {
957  if (numvalues) {
958  values = (IFvalue *)
959  trealloc((char *) values,
960  (numvalues + 1) * sizeof (IFvalue));
961  types = (int *)
962  trealloc((char *) types,
963  (numvalues + 1) * sizeof (int));
964  }
965  else {
966  values = alloc(IFvalue);
967  types = (int *) tmalloc(sizeof (int));
968  }
969  values[i] = temp;
970  types[i] = IF_NODE;
971  numvalues++;
972  }
973  p->valueIndex = i;
974  p->type = PT_VAR;
975  p->evfunc = pt_var;
976  }
977  }
978  else if (!strcmp(fname, "i")) {
979  name = tmalloc(128);
980  if (arg->type == PT_PLACEHOLDER) {
981  strcpy(name, arg->funcname);
982  txfree(arg->funcname);
983  }
984  else if (arg->type == PT_CONSTANT) {
985  (void) sprintf(name, "%d", (int) arg->constant);
986  }
987  else {
988  errMsg = copy("badly formed branch current");
989  txfree(fname);
990  return (NULL);
991  }
992 /* printf("getting a device called '%s'\n", name); */
993  INPinsert(&name, tables);
994  for (i = 0; i < numvalues; i++)
995  if ((types[i] == IF_INSTANCE) && (values[i].uValue ==
996  temp.uValue))
997  break;
998  if (i == numvalues) {
999  if (numvalues) {
1000  values = (IFvalue *)
1001  trealloc((char *) values,
1002  (numvalues + 1) * sizeof (IFvalue));
1003  types = (int *)
1004  trealloc((char *) types,
1005  (numvalues + 1) * sizeof (int));
1006  }
1007  else {
1008  values = alloc(IFvalue);
1009  types = (int *) tmalloc(sizeof (int));
1010  }
1011  values[i].uValue = (IFuid) name;
1012  types[i] = IF_INSTANCE;
1013  numvalues++;
1014  }
1015  p->valueIndex = i;
1016  p->type = PT_VAR;
1017  p->evfunc = pt_var;
1018  }
1019  else {
1020  for (i = 0; PTfuncs[i].name; i++)
1021  if (!strcmp(PTfuncs[i].name, fname))
1022  break;
1023 
1024  if (!PTfuncs[i].name) {
1025  if (INPtablFind(fname,circuit,&table)) {
1026  errMsg = tmalloc(strlen(fname) + 100);
1027  sprintf(errMsg,"no such function '%s'",fname);
1028  txfree(fname);
1029  return (NULL);
1030  }
1031  p->type = PT_TABLE;
1032  p->left = arg;
1033  p->funcname = fname;
1034  p->funcnum = 0;
1035  p->function = (double(*)()) table;
1036  p->evfunc = pt_table;
1037  return (p);
1038  }
1039 
1040  p->type = PT_FUNCTION;
1041  p->left = arg;
1042  p->funcname = PTfuncs[i].name;
1043  p->funcnum = PTfuncs[i].number;
1044  p->function = PTfuncs[i].funcptr;
1045  p->evfunc = pt_fcn;
1046  }
1047 
1048  txfree(fname);
1049  return (p);
1050 }
1051 
1052 
1053 static INPparseNode *
1054 mknnode(number)
1055 
1056 /* Number node. */
1057 double number;
1058 {
1059  struct INPparseNode *p;
1060 
1061  p = allocate_pnode(P_ALLOC);
1062 
1063  p->type = PT_CONSTANT;
1064  p->constant = number;
1065  p->evfunc = pt_const;
1066 
1067  return (p);
1068 }
1069 
1070 
1071 static INPparseNode *
1072 mksnode(string)
1073 
1074 /* String node, string is freed */
1075 char *string;
1076 {
1077  int i, j;
1078 
1079  INPparseNode *p;
1080 
1081  p = allocate_pnode(P_ALLOC);
1082 
1083  /* First check it it is really a tran function */
1084  if (is_tranfunc(string,p)) {
1085  txfree(string);
1086  return (p);
1087  }
1088 
1089  /* Next see if it's a special parameter */
1090  for (i = 0; i < ft_sim->numSpecSigs; i++)
1091  if (!strcmp(ft_sim->specSigs[i], string))
1092  break;
1093  if (i < ft_sim->numSpecSigs) {
1094  p->valueIndex = i;
1095  p->type = PT_PARAM;
1096  p->evfunc = pt_parm;
1097  txfree(string);
1098  return (p);
1099  }
1100 
1101  for (i = 0; constants[i].name; i++)
1102  if (!strcmp(constants[i].name, string))
1103  break;
1104 
1105  if (!constants[i].name) {
1106  /* We'd better save this in case it's part of i(something). */
1107  p->type = PT_PLACEHOLDER;
1108  p->funcname = string;
1109  }
1110  else {
1111  p->type = PT_CONSTANT;
1112  p->constant = constants[i].value;
1113  p->evfunc = pt_const;
1114  txfree(string);
1115  }
1116 
1117  return (p);
1118 }
1119 
1120 
1121 
1122 static PTelement *
1124 
1125 /* The lexical analysis routine. */
1126 char **line;
1127 {
1128  double td;
1129  int err;
1130  static PTelement el;
1131  static char *specials = " \t()^+-*/,";
1132  static int lasttoken = TOK_END, lasttype;
1133  char *sbuf, *s;
1134 
1135  sbuf = *line;
1136 /*
1137 printf("entering lexer, sbuf = '%s', lastoken = %d, lasttype = %d\n",
1138 sbuf, lasttoken, lasttype);
1139 */
1140  while ((*sbuf == ' ') || (*sbuf == '\t') || (*sbuf == '='))
1141  sbuf++;
1142 
1143  switch (*sbuf) {
1144  case '\0':
1145  el.token = TOK_END;
1146  break;
1147 
1148  case ',':
1149  el.token = TOK_COMMA;
1150  sbuf++;
1151  break;
1152 
1153  case '-':
1154  if ((lasttoken == TOK_VALUE) || (lasttoken == TOK_RPAREN))
1155  el.token = TOK_MINUS;
1156  else
1157  el.token = TOK_UMINUS;
1158  sbuf++;
1159  break;
1160 
1161  case '+':
1162  el.token = TOK_PLUS;
1163  sbuf++;
1164  break;
1165 
1166  case '*':
1167  el.token = TOK_TIMES;
1168  sbuf++;
1169  break;
1170 
1171  case '/':
1172  el.token = TOK_DIVIDE;
1173  sbuf++;
1174  break;
1175 
1176  case '^':
1177  el.token = TOK_POWER;
1178  sbuf++;
1179  break;
1180 
1181  case '(':
1182  if (((lasttoken == TOK_VALUE) && ((lasttype == TYP_NUM))) ||
1183  (lasttoken == TOK_RPAREN)) {
1184  el.token = TOK_END;
1185  }
1186  else {
1187  el.token = TOK_LPAREN;
1188  sbuf++;
1189  }
1190  break;
1191 
1192  case ')':
1193  el.token = TOK_RPAREN;
1194  sbuf++;
1195  break;
1196 
1197  default:
1198  if ((lasttoken == TOK_VALUE) || (lasttoken == TOK_RPAREN)) {
1199  el.token = TOK_END;
1200  break;
1201  }
1202 
1203  td = INPevaluate(&sbuf, &err, 0);
1204  if (err == OK) {
1205  while (isalpha(*sbuf))
1206  sbuf++;
1207  el.token = TOK_VALUE;
1208  el.type = TYP_NUM;
1209  el.value.real = td;
1210  }
1211  else {
1212  el.token = TOK_VALUE;
1213  el.type = TYP_STRING;
1214  el.value.string = get_stringvar(&sbuf,specials);
1215  }
1216  }
1217 
1218  lasttoken = el.token;
1219  lasttype = el.type;
1220 
1221  *line = sbuf;
1222 
1223 /*
1224 printf("PTlexer: token = %d, type = %d, left = '%s'\n",
1225 el.token, el.type, sbuf);
1226 */
1227 
1228  return (&el);
1229 }
1230 
1231 
1232 static char *
1233 get_stringvar(s,specials)
1234 
1235 char **s, *specials;
1236 {
1237  char *t;
1238  char *buf;
1239  int i, j;
1240 
1241  for (t = *s, i = 0; *t; t++, i++) {
1242  if (strchr(specials,*t))
1243  break;
1244  }
1245  buf = tmalloc(i+1);
1246  memcpy(buf,*s,i);
1247  buf[i] = '\0';
1248 
1249 
1250  for (j = 0; PTtFuncs[j].name; j++)
1251  if (!strcmp(PTtFuncs[j].name, buf))
1252  break;
1253 
1254  if (tran_hack(PTtFuncs[j].name,t)) {
1255  /* found a match, copy parameters and () */
1256  for ( ; *t; t++, i++) {
1257  if (*t == ')') {
1258  t++;
1259  i++;
1260  break;
1261  }
1262  }
1263  txfree(buf);
1264  buf = tmalloc(i+1);
1265  memcpy(buf,*s,i);
1266  buf[i] = '\0';
1267  }
1268  *s = t;
1269 
1270  /* set to lower case */
1271  for (t = buf; *t; t++)
1272  if (isupper(*t)) *t = tolower(*t);
1273 
1274  return (buf);
1275 }
1276 
1277 
1278 static int
1280 
1281 char *name,*str;
1282 /* since tranfuncs sin, exp have the same name as math functions, we
1283  * figure out from the context whether to interpret as a tran func
1284  * or not.
1285  */
1286 {
1287  char *s, *t, *tok;
1288  char *buf;
1289  int n, error;
1290 
1291  if (name == NULL)
1292  return (false);
1293 
1294  if (strcmp(name,"sin") && strcmp(name,"exp"))
1295  return (true);
1296 
1297  for (n = 0, s = str; *s != ')'; n++,s++) ;
1298 
1299  buf = tmalloc(n+1);
1300  memcpy(buf,str,n);
1301  buf[n] = '\0';
1302 
1303  n = 0;
1304  t = buf;
1305  while (*t) {
1306  error = INPgetTok(&t,&tok,1);
1307  if (error) break;
1308  s = tok;
1309  (void)INPevaluate(&tok,&error,1);
1310  if (error) {
1311  txfree(s);
1312  break;
1313  }
1314  txfree(s);
1315  n++;
1316  }
1317  txfree(buf);
1318  if (!error && n >= 2)
1319  return (true);
1320  return (false);
1321 }
1322 
1323 
1324 static int
1326 
1327 char *s;
1328 INPparseNode *p;
1329 {
1330  int i, num, error;
1331  char *t, *tt;
1332  double tmp, *list;
1333 
1334  /* the tran function string includes parameters enclosed in () */
1335  if (!strchr(s,')'))
1336  return (false); /* can't be a tran function */
1337 
1338  t = strchr(s,'(');
1339  if (t == NULL)
1340  return (false); /* syntax error */
1341 
1342  *t = '\0';
1343  t++;
1344 
1345  /* get rid of intermediate space */
1346  tt = s;
1347  while (*tt && !isspace(*tt)) tt++;
1348  *tt = '\0';
1349 
1350  for (i = 0; PTtFuncs[i].name; i++)
1351  if (!strcmp(PTtFuncs[i].name, s))
1352  break;
1353 
1354  if (!PTtFuncs[i].name) {
1355  fprintf(stderr, "Internal Error: no such tran function '%s'", s);
1356  return (false);
1357  }
1358  if (p) {
1359  p->type = PT_TFUNC;
1360 
1361  num = 0;
1362  list = (double *)tmalloc(sizeof(double));
1363  tmp = INPevaluate(&t,&error,1);
1364  while (error == 0) {
1365  num++;
1366  list = (double *)
1367  trealloc((char *)list,num*sizeof(double));
1368  *(list+num-1) = tmp;
1369  tmp = INPevaluate(&t,&error,1);
1370  }
1371  p->trancoeffs = list;
1372  p->numtrancoeffs = num;
1373  p->funcname = PTtFuncs[i].name;
1374  p->funcnum = PTtFuncs[i].number;
1375  p->function = PTtFuncs[i].funcptr;
1376  p->evfunc = pt_tran;
1377  if (p->funcnum != PTF_tPWL)
1378  p->tranparms = (double*)tmalloc(8*sizeof(double));
1379 
1380  if (p->funcnum == PTF_tPULSE)
1381  p->trancache = (double*)tmalloc(2*sizeof(double));
1382  else if (p->funcnum == PTF_tPWL) {
1383  num = p->numtrancoeffs/2 - 1;
1384  if (num) {
1385  p->trancache = (double*)tmalloc(num*sizeof(double));
1386  for (i = 0; i < num; i++) {
1387  p->trancache[i] =
1388  (*(p->trancoeffs+2*i+3) - *(p->trancoeffs+2*i+1))/
1389  (*(p->trancoeffs+2*i+2) - *(p->trancoeffs+2*i));
1390  }
1391  }
1392  else {
1393  p->trancache = (double*)tmalloc(sizeof(double));
1394  p->trancache[0] = 0;
1395  }
1396  }
1397  }
1398  return (true);
1399 }
1400 
1401 
1402 /* memory management */
1403 
1404 static INPparseNode *
1406 
1407 int mode;
1408 {
1409  static nodes, size;
1410  static INPparseNode **pnodes;
1411  int i;
1412 
1413  if (mode == P_ALLOC) {
1414  nodes++;
1415  if (nodes > size) {
1416  size += 10;
1417  if (pnodes)
1418  pnodes = (INPparseNode**)
1419  trealloc((char*)pnodes,size * sizeof(INPparseNode*));
1420  else
1421  pnodes = (INPparseNode**)
1422  tmalloc(size * sizeof(INPparseNode*));
1423  }
1424  pnodes[nodes-1] = alloc(INPparseNode);
1425  return (pnodes[nodes-1]);
1426  }
1427  if (mode == P_CLEAR) {
1428  for (i = 0; i < nodes; i++) {
1429  if (pnodes[i]->type == PT_PLACEHOLDER) continue;
1430  if (pnodes[i]->type == PT_TFUNC) {
1431  if (pnodes[i]->trancoeffs)
1432  txfree((char*)pnodes[i]->trancoeffs);
1433  if (pnodes[i]->tranparms)
1434  txfree((char*)pnodes[i]->tranparms);
1435  if (pnodes[i]->trancache)
1436  txfree((char*)pnodes[i]->trancache);
1437  }
1438  txfree((char*)pnodes[i]);
1439  }
1440  }
1441  for (i = 0; i < nodes; i++) {
1442  if (pnodes[i]->type != PT_PLACEHOLDER) continue;
1443  txfree((char*)pnodes[i]);
1444  }
1445  txfree((char*)pnodes);
1446  pnodes = NULL;
1447  size = 0;
1448  nodes = 0;
1449  return (NULL);
1450 }
1451 
1452 
1453 /* evaluation functions */
1454 
1455 static int
1456 pt_const(tree, res, vals, parms)
1457 
1458 INPparseNode *tree;
1459 double *res;
1460 double *vals;
1461 double *parms;
1462 {
1463  *res = tree->constant;
1464  return (OK);
1465 }
1466 
1467 
1468 static int
1469 pt_var(tree, res, vals, parms)
1470 
1471 INPparseNode *tree;
1472 double *res;
1473 double *vals;
1474 double *parms;
1475 {
1476  *res = vals[tree->valueIndex];
1477  return (OK);
1478 }
1479 
1480 
1481 static int
1482 pt_parm(tree, res, vals, parms)
1483 
1484 INPparseNode *tree;
1485 double *res;
1486 double *vals;
1487 double *parms;
1488 {
1489  *res = parms[tree->valueIndex];
1490  return (OK);
1491 }
1492 
1493 
1494 static int
1495 pt_fcn(tree, res, vals, parms)
1496 
1497 INPparseNode *tree;
1498 double *res;
1499 double *vals;
1500 double *parms;
1501 {
1502  int err;
1503  double r1;
1504 
1505  err = (*tree->left->evfunc)(tree->left, &r1, vals, parms);
1506  if (err != OK)
1507  return (err);
1508  *res = (*tree->function)(r1);
1509  /*
1510  if (*res == HUGE) {
1511  fprintf(stderr, "Error: %lg out of range for %s\n",
1512  r1, tree->funcname);
1513  return (E_PARMVAL);
1514  }
1515  */
1516  return (OK);
1517 }
1518 
1519 
1520 static int
1521 pt_table(tree, res, vals, parms)
1522 
1523 INPparseNode *tree;
1524 double *res;
1525 double *vals;
1526 double *parms;
1527 {
1528  int err;
1529  double r1;
1530 
1531  err = (*tree->left->evfunc)(tree->left, &r1, vals, parms);
1532  if (err != OK)
1533  return (err);
1534 
1535  if (tree->funcnum == 0)
1536  *res = INPtablEval((GENERIC*)tree->function,r1);
1537  else
1538  *res = INPtablEvalDeriv((GENERIC*)tree->function,r1);
1539 
1540  return (OK);
1541 }
1542 
1543 
1544 static int
1545 pt_tran(tree, res, vals, parms)
1546 
1547 INPparseNode *tree;
1548 double *res;
1549 double *vals;
1550 double *parms;
1551 {
1552  *res = (*tree->function)(tree,parms);
1553  return (OK);
1554 }
1555 
1556 
1557 static int
1558 pt_op(tree, res, vals, parms)
1559 
1560 INPparseNode *tree;
1561 double *res;
1562 double *vals;
1563 double *parms;
1564 {
1565  int err;
1566  double r1, r2;
1567 
1568  err = (*tree->left->evfunc)(tree->left, &r1, vals, parms);
1569  if (err != OK)
1570  return (err);
1571  err = (*tree->right->evfunc)(tree->right, &r2, vals, parms);
1572  if (err != OK)
1573  return (err);
1574  *res = (*tree->function)(r1, r2);
1575  /*
1576  if (*res == HUGE) {
1577  fprintf(stderr, "Error: %lg, %lg out of range for %s\n",
1578  r1, r2, tree->funcname);
1579  return (E_PARMVAL);
1580  }
1581  */
1582  return (OK);
1583 }
1584 
1585 
1586 /* Debugging stuff. */
1587 
1588 #ifdef __STDC__
1589 static void printTree(INPparseNode*);
1590 #else /* stdc */
1591 static void printTree();
1592 #endif /* stdc */
1593 
1594 
1595 void
1596 INPptPrint(str, ptree)
1597 
1598 char *str;
1599 IFparseTree *ptree;
1600 {
1601  int i;
1602 
1603  printf("%s\n\t", str);
1604  printTree(((INPparseTree *) ptree)->tree);
1605  printf("\n");
1606  for (i = 0; i < ptree->numVars; i++) {
1607  printf("d / d v%d : ", i);
1608  printTree(((INPparseTree *) ptree)->derivs[i]);
1609  printf("\n");
1610  }
1611  return;
1612 }
1613 
1614 
1615 static void
1617 
1618 INPparseNode *pt;
1619 {
1620  int i;
1621 
1622  switch (pt->type) {
1623  case PT_CONSTANT:
1624  printf("%g", pt->constant);
1625  break;
1626 
1627  case PT_VAR:
1628  printf("v%d", pt->valueIndex);
1629  break;
1630 
1631  case PT_PARAM:
1632  printf("%s", ft_sim->specSigs[pt->valueIndex]);
1633  break;
1634 
1635  case PT_PLUS:
1636  printf("(");
1637  printTree(pt->left);
1638  printf(") + (");
1639  printTree(pt->right);
1640  printf(")");
1641  break;
1642 
1643  case PT_MINUS:
1644  printf("(");
1645  printTree(pt->left);
1646  printf(") - (");
1647  printTree(pt->right);
1648  printf(")");
1649  break;
1650 
1651  case PT_TIMES:
1652  printf("(");
1653  printTree(pt->left);
1654  printf(") * (");
1655  printTree(pt->right);
1656  printf(")");
1657  break;
1658 
1659  case PT_DIVIDE:
1660  printf("(");
1661  printTree(pt->left);
1662  printf(") / (");
1663  printTree(pt->right);
1664  printf(")");
1665  break;
1666 
1667  case PT_POWER:
1668  printf("(");
1669  printTree(pt->left);
1670  printf(") ^ (");
1671  printTree(pt->right);
1672  printf(")");
1673  break;
1674 
1675  case PT_FUNCTION:
1676  printf("%s (", pt->funcname);
1677  printTree(pt->left);
1678  printf(")");
1679  break;
1680 
1681  case PT_TFUNC:
1682  printf("%s (", pt->funcname);
1683  for (i = 0; i < pt->numtrancoeffs; i++)
1684  printf(" %g",pt->trancoeffs[i]);
1685  printf(" )");
1686  break;
1687 
1688  default:
1689  printf("oops");
1690  break;
1691  }
1692  return;
1693 }
1694 
IFsimulator * ft_sim
Definition: main.c:111
static char buf[MAXPROMPT]
Definition: arg.c:18
double(* funcptr)()
Definition: inpptree.h:153
static int pt_fcn()
int IFeval()
#define PTF_SQRT
Definition: inpptree.h:97
#define PTF_tPULSE
Definition: inpptree.h:106
union PTelement::@15 value
Definition: subckt.c:18
char * name
Definition: inpptree.h:151
#define PT_FUNCTION
Definition: inpptree.h:74
#define issep(c)
Definition: inpptree.c:91
void IFfree()
#define PT_TABLE
Definition: inpptree.h:80
#define TOK_VALUE
Definition: inpptree.h:127
char * ptXalias
Definition: ifsim.h:471
#define PT_DIVIDE
Definition: inpptree.h:72
struct sPTfunc PTtFuncs[]
Definition: ptfuncs.c:132
static struct tab table[512]
static INPparseNode * mknnode()
#define TOK_UMINUS
Definition: inpptree.h:124
int INPtermInsert()
#define R
Definition: inpptree.c:720
#define PT_PLACEHOLDER
Definition: inpptree.h:68
#define TOK_MINUS
Definition: inpptree.h:120
#define PTF_ACOS
Definition: inpptree.h:84
static INPparseNode * PTdifferentiate()
char * strcpy()
Definition: cddefs.h:119
#define TOK_TIMES
Definition: inpptree.h:121
int number
Definition: inpptree.h:152
#define P_RESET
Definition: inpptree.c:77
#define PTF_COS
Definition: inpptree.h:90
char * string
Definition: inpptree.h:142
#define P_CLEAR
Definition: inpptree.c:76
Definition: xforms.c:16
double INPtablEvalDeriv(GENERIC *tab, double x)
Definition: inptabpa.c:441
#define PT_CONSTANT
Definition: inpptree.h:75
#define M_PI
Definition: spice.h:132
char * errMsg
Definition: main.c:42
char * name
Definition: inpptree.h:160
static INPparseNode * mkcon()
double INPevaluate()
FILE * p
Definition: proc2mod.c:48
static IFvalue * values
Definition: inpptree.c:13
Definition: subckt.c:51
#define tab(num)
Definition: front.c:1365
static INPparseNode * allocate_pnode()
static INPparseNode * mkbnode()
#define P_ALLOC
Definition: inpptree.c:75
#define PTF_TANH
Definition: inpptree.h:99
static INPparseNode * makepnode()
static char * get_stringvar()
int(* evfunc)()
Definition: inpptree.h:53
static int PTcheck()
#define PTF_COSH
Definition: inpptree.h:91
struct INPparseNode * right
Definition: inpptree.h:48
#define IF_INSTANCE
Definition: ifsim.h:112
Definition: cddefs.h:215
static int tran_hack()
static INPtables * tables
Definition: inpptree.c:17
#define alloc(type)
Definition: cdmacs.h:21
char * copy()
double constant
Definition: inpptree.h:49
#define M_E
Definition: spice.h:136
#define TOK_DIVIDE
Definition: inpptree.h:122
int funcnum
Definition: inpptree.h:52
#define PTF_EXP
Definition: inpptree.h:92
static int pt_tran()
static int lasttype
Definition: parse.c:39
#define PT_STACKSIZE
Definition: inpptree.h:148
int INPinsert()
#define PTF_SIN
Definition: inpptree.h:95
#define OK
Definition: iferrmsg.h:17
char * tmalloc()
double * trancoeffs
Definition: inpptree.h:55
int IFinit()
Definition: fteinp.h:14
#define PT_TFUNC
Definition: inpptree.h:79
#define TYP_PNODE
Definition: inpptree.h:134
static char * sbuf
Definition: parse.c:40
GENERIC * IFuid
Definition: ifsim.h:72
INPparseNode * pnode
Definition: inpptree.h:144
double real
Definition: inpptree.h:143
double(* function)()
Definition: inpptree.h:54
static int pt_const()
int numSpecSigs
Definition: ifsim.h:469
#define PT_VAR
Definition: inpptree.h:76
#define TOK_LPAREN
Definition: inpptree.h:125
double INPtablEval()
struct INPparseNode * left
Definition: inpptree.h:47
void txfree()
#define NULL
Definition: spdefs.h:121
Definition: types.c:18
#define PT_PLUS
Definition: inpptree.h:69
#define PT_MINUS
Definition: inpptree.h:70
#define L
Definition: inpptree.c:718
IFnode nValue
Definition: ifsim.h:237
#define PT_PARAM
Definition: inpptree.h:77
#define PTF_ATANH
Definition: inpptree.h:89
#define TYP_STRING
Definition: inpptree.h:133
static INPparseNode * mkf()
static int lasttoken
Definition: parse.c:39
static int pt_table()
static INPparseNode * mkb()
#define G
Definition: inpptree.c:717
#define PTF_ASINH
Definition: inpptree.h:87
static INPparseNode * mkfnode()
static int numvalues
Definition: inpptree.c:15
static double c
Definition: vectors.c:16
#define PT_COMMA
Definition: inpptree.h:78
#define TOK_RPAREN
Definition: inpptree.h:126
static GENERIC * circuit
Definition: inpptree.c:16
#define PTF_UMINUS
Definition: inpptree.h:100
char ** specSigs
Definition: ifsim.h:470
#define PTF_ASIN
Definition: inpptree.h:86
int INPtablFind()
static INPparseNode * copy_node()
static INPparseNode * mksnode()
#define TOK_END
Definition: inpptree.h:118
char * name
Definition: inpptree.c:83
double value
Definition: inpptree.c:84
double(* funcptr)()
Definition: inpptree.h:161
#define PTF_LN
Definition: inpptree.h:93
struct sPTop PTops[]
Definition: ptfuncs.c:97
#define E
Definition: inpptree.c:719
#define TOK_PLUS
Definition: inpptree.h:119
double * tranparms
Definition: inpptree.h:56
#define TOK_COMMA
Definition: inpptree.h:128
#define PTF_ABS
Definition: inpptree.h:101
void INPptPrint(char *str, IFparseTree *ptree)
Definition: inpptree.c:1596
int numVars
Definition: ifsim.h:159
static char prectable[11][11]
Definition: inpptree.c:722
#define PTF_tPWL
Definition: inpptree.h:107
static int * types
Definition: inpptree.c:14
Definition: dir.c:53
void INPgetTree(char **line, INPparseTree **pt, GENERIC *ckt, INPtables *tab)
Definition: inpptree.c:96
#define PT_POWER
Definition: inpptree.h:73
#define PTF_LOG
Definition: inpptree.h:94
#define TYP_NUM
Definition: inpptree.h:132
static void PTalias()
int type
Definition: inpptree.h:140
static int pt_var()
static INPparseNode * PTparse()
Definition: mfb.h:383
int valueIndex
Definition: inpptree.h:50
int token
Definition: inpptree.h:139
static int pt_parm()
void bcopy(char *from, char *to, int num)
Definition: string.c:339
int count
Definition: output.c:152
static void printTree()
int numtrancoeffs
Definition: inpptree.h:58
#define PTF_SINH
Definition: inpptree.h:96
#define M_LOG10E
Definition: spice.h:140
#define PTF_ACOSH
Definition: inpptree.h:85
#define PTF_ATAN
Definition: inpptree.h:88
#define PTF_SGN
Definition: inpptree.h:102
#define PTF_TAN
Definition: inpptree.h:98
#define TOK_POWER
Definition: inpptree.h:123
double * trancache
Definition: inpptree.h:57
static struct constant constants[]
int new_deriv
Definition: inpptree.h:60
Definition: cddefs.h:192
static int pt_op()
#define IF_NODE
Definition: ifsim.h:110
static int is_tranfunc()
#define PT_TIMES
Definition: inpptree.h:71
int number
Definition: inpptree.h:159
static PTelement * PTlexer()
char * trealloc()
struct sPTfunc PTfuncs[]
Definition: ptfuncs.c:107
char * funcname
Definition: inpptree.h:51
char GENERIC
Definition: ifsim.h:27
IFuid uValue
Definition: ifsim.h:236
int INPgetTok()