Jspice3
subckt.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: 1985 Wayne A. Christopher, Norbert Jeske
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Expand subcircuits. This is very spice-dependent.
10  */
11 
12 #include "spice.h"
13 #include "ftedefs.h"
14 #include "fteinp.h"
15 #include "kwords.h"
16 #include "spfteext.h"
17 
18 
19 #ifdef __STDC__
20 static struct line *doit(struct line*);
21 static bool translate(struct line*,char*,char*,char*,char*,char*);
22 static void finishLine(char*,char*,char*);
23 static bool settrans(char*,char*,char*,char*);
24 static bool aredups(void);
25 static char *gettrans(char*);
26 static void numrefs(char*,int*,int*);
27 static bool modtranslate(struct line*,char*);
28 static void devmodtranslate(struct line*,char*);
29 static void looksubmod(char**,char*,char*);
30 #else
31 static struct line *doit();
32 static bool translate();
33 static void finishLine();
34 static bool settrans();
35 static bool aredups();
36 static char *gettrans();
37 static void numrefs();
38 static bool modtranslate();
39 static void devmodtranslate();
40 static void looksubmod();
41 #endif
42 
43 struct subs {
44  char *su_name; /* The name. */
45  char *su_args; /* The arguments, space seperated. */
47  struct line *su_def; /* The deck that is to be substituted. */
48  struct subs *su_next;
49 } ;
50 
51 static struct tab {
52  char *t_old;
53  char *t_new;
54 } table[512]; /* That had better be enough. */
55 
56 
57 /* Expand all subcircuits in the deck. This handles imbedded .subckt
58  * definitions. The variables substart, subend, and subinvoke can be used
59  * to redefine the controls used. The syntax is invariant though.
60  * NOTE: the deck must be passed without the title card.
61  * What we do is as follows: first make one pass through the circuit
62  * and collect all of the subcircuits. Then, whenever a card that starts
63  * with 'x' is found, copy the subcircuit associated with that name and
64  * splice it in. A few of the problems: the nodes in the spliced-in
65  * stuff must be unique, so when we copy it, append "subcktname:" to
66  * each node. If we are in a nested subcircuit, use foo:bar:...:node.
67  * Then we have to systematically change all references to the renamed
68  * nodes. On top of that, we have to know how many args BJT's have,
69  * so we have to keep track of model names.
70  */
71 
73 static struct subs *subs;
74 static bool nobjthack = false;
75 
76 static char start[32], sbend[32], invoke[32], model[32];
77 
78 
79 struct line *
81 
82 struct line *deck;
83 {
84  struct line *ll, *c;
85  char *s;
87  extern char *kw_nobjthack;
88 
89  if (!cp_getvar(kw_substart, VT_STRING, start))
90  (void) strcpy(start, ".subckt");
91  if (!cp_getvar(kw_subend, VT_STRING, sbend))
92  (void) strcpy(sbend, ".ends");
93  if (!cp_getvar(kw_subinvoke, VT_STRING, invoke))
94  (void) strcpy(invoke, "X");
95  if (!cp_getvar(kw_modelcard, VT_STRING, model))
96  (void) strcpy(model, ".model");
97  (void) cp_getvar(kw_nobjthack, VT_BOOL, (char *) &nobjthack);
98 
99  /* Let's do a few cleanup things first... Get rid of ( ) around node
100  * lists...
101  */
102  for (c = deck; c; c = c->li_next) {
103  if (prefix(start, c->li_line)) {
104  for (s = c->li_line; *s && (*s != '('); s++)
105  ;
106  if (*s) {
107  while (s[0] && (s[1] != ')')) {
108  s[0] = s[1];
109  s++;
110  }
111  while (s[1]) {
112  s[0] = s[2];
113  s++;
114  }
115  }
116  }
117  else {
118  for (s = c->li_line; *s && !isspace(*s); s++)
119  ;
120  while (isspace(*s))
121  s++;
122  if (*s == '(') {
123  while (s[0] && (s[1] != ')')) {
124  s[0] = s[1];
125  s++;
126  }
127  while (s[1]) {
128  s[0] = s[2];
129  s++;
130  }
131  }
132  }
133  }
134 
135  ll = doit(deck);
136 
137  /* Now check to see if there are still subckt instances undefined... */
138  if (ll) {
139  for (c = ll; c; c = c->li_next)
140  if (ciprefix(invoke, c->li_line)) {
141  fprintf(cp_err, "Error: unknown subckt: %s\n",
142  c->li_line);
143  ll = NULL;
144  }
145  }
146 
147  return (ll);
148 }
149 
150 
151 #define MAXNEST 21
152 
153 static struct line *
154 doit(deck)
155 
156 struct line *deck;
157 {
158  struct line *c, *last, *lc, *lcc;
159  struct subs *sss;
160  char *s, *t, *tt, *scname, *subname;
161  int nest, numpasses = MAXNEST, i;
162  bool gotone;
163  wordlist *wl;
164  wordlist *tmodnames = modnames;
165  wordlist *tsubmod = submod;
166  struct subs *ts = subs;
167 
168  /* Save all the old stuff... */
169  modnames = NULL;
170  subs = NULL;
171  submod = NULL;
172 
173  /* Extract all the .subckts */
174  for (last = deck, lc = NULL; last; ) {
175  if (prefix(sbend, last->li_line)) {
176  fprintf(cp_err, "Error: misplaced %s card: %s\n", sbend,
177  last->li_line);
178  deck = NULL;
179  goto cleanup;
180  }
181  else if (prefix(start, last->li_line)) {
182  if (last->li_next == NULL) {
183  fprintf(cp_err, "Error: no %s card.\n", sbend);
184  deck = NULL;
185  goto cleanup;
186  }
187  gotone = false;
188  lcc = NULL;
189  for (nest = 0, c = last->li_next; c; lcc = c,c = c->li_next) {
190  if (prefix(sbend, c->li_line)) {
191  if (!nest)
192  break;
193  else {
194  nest--;
195  continue;
196  }
197  }
198  else if (prefix(start, c->li_line))
199  nest++;
200  }
201  if (!c) {
202  fprintf(cp_err, "Error: no %s card.\n", sbend);
203  deck = NULL;
204  goto cleanup;
205  }
206  if (lcc)
207  lcc->li_next = NULL;
208  else
209  last->li_next = NULL;
210 
211  sss = alloc(struct subs);
212  if (lc)
213  lc->li_next = c->li_next;
214  else
215  deck = c->li_next;
216 
217  sss->su_def = last->li_next;
218  s = last->li_line;
219  advtok(&s);
220  sss->su_name = gettok(&s);
221  sss->su_args = copy(s);
222  for (sss->su_numargs = 0, i = 0; s[i]; ) {
223  while (isspace(s[i]))
224  i++;
225  if (s[i]) {
226  sss->su_numargs++;
227  while (s[i] && !isspace(s[i]))
228  i++;
229  }
230  }
231  sss->su_next = subs;
232  subs = sss;
233 
234  last->li_next = NULL;
235  inp_deckfree(last);
236 
237  last = c->li_next;
238 
239  c->li_next = NULL;
240  inp_deckfree(c);
241  }
242  else {
243  lc = last;
244  last = last->li_next;
245  }
246  }
247 
248  /* Expand sub-subcircuits. */
249  for (sss = subs; sss; sss = sss->su_next)
250  if (sss->su_def) {
251  if (!(sss->su_def = doit(sss->su_def))) {
252  deck = NULL;
253  goto cleanup;
254  }
255  }
256 
257  /* Get all the model names so we can deal with BJT's. */
258  for (c = deck; c; c = c->li_next)
259  if (prefix(model, c->li_line)) {
260  s = c->li_line;
261  advtok(&s);
262  wl = alloc(struct wordlist);
263  wl->wl_next = modnames;
264  if (modnames)
265  modnames->wl_prev = wl;
266  modnames = wl;
267  wl->wl_word = gettok(&s);
268  }
269 
270  /* Now do the replacements. */
271  do {
272  gotone = false;
273  for (c = deck, lc = NULL; c; ) {
274  if (ciprefix(invoke, c->li_line)) {
275  char *tmpscname;
276  gotone = true;
277  t = s = copy(c->li_line);
278  tmpscname = scname = gettok(&s);
279  scname += strlen(invoke);
280  while ((*scname == ' ') || (*scname == '\t') ||
281  (*scname == ':'))
282  scname++;
283  while(*s)
284  s++;
285  s--;
286  while ((*s == ' ') || (*s == '\t'))
287  *s-- = '\0';
288  while ((*s != ' ') && (*s != '\t'))
289  s--;
290  s++;
291  for (sss = subs; sss; sss = sss->su_next)
292  if (eq(sss->su_name, s))
293  break;
294 
295  /* Don't complain -- this might be an
296  * instance of a subckt that is defined above.
297  */
298  if (!sss) {
299  lc = c;
300  c = c->li_next;
301  txfree(tmpscname);
302  txfree(t);
303  continue;
304  }
305 
306  if (!sss->su_def) {
307  /* null subccircuit, just clip out
308  * invocation and ignore
309  */
310  if (lc)
311  lc->li_next = c->li_next;
312  else
313  deck = c->li_next;
314 
315  c->li_next = NULL;
316  inp_deckfree(c);
317 
318  if (lc)
319  c = lc->li_next;
320  else
321  c = deck;
322 
323  txfree(tmpscname);
324  txfree(t);
325  fprintf(cp_err,
326  "Warning: empty subcircuit %s referenced, ignored\n",
327  sss->su_name);
328  continue;
329  }
330 
331  /* Now we have to replace this card with the
332  * macro definition.
333  */
334  subname = copy(sss->su_name);
335 
336  lcc = inp_deckcopy(sss->su_def);
337 
338  /* Change the names of the models... */
339  if (modtranslate(lcc, scname))
340  devmodtranslate(lcc, scname);
341 
342  s = sss->su_args;
343  tt = t;
344  advtok(&t); /* Throw out the name. */
345 
346  if (translate(lcc, s, t, scname, subname, c->li_line)) {
347  txfree(tmpscname);
348  tfree(subname);
349  txfree(tt);
350  deck = NULL;
351  goto cleanup;
352  }
353 
354  txfree(tmpscname);
355  tfree(subname);
356  txfree(tt);
357 
358  /* Now splice the decks together. */
359  if (lc)
360  lc->li_next = lcc;
361  else
362  deck = lcc;
363  while (lcc->li_next != NULL)
364  lcc = lcc->li_next;
365  lcc->li_next = c->li_next;
366 
367  c->li_next = NULL;
368  inp_deckfree(c);
369  c = lcc->li_next;
370  lc = lcc;
371  }
372  else {
373  lc = c;
374  c = c->li_next;
375  }
376  }
377  } while (numpasses-- && gotone);
378 
379  if (!numpasses) {
380  fprintf(cp_err, "Error: infinite subckt recursion\n");
381  deck = NULL;
382  }
383 
384 cleanup:
385  wl_free(modnames);
386  wl_free(submod);
387  for (sss = subs; sss; sss = subs) {
388  subs = sss->su_next;
389  txfree(sss->su_name);
390  txfree(sss->su_args);
391  inp_deckfree(sss->su_def);
392  txfree((char*)sss);
393  }
394  subs = ts;
395  modnames = tmodnames;
396  submod = tsubmod;
397  return (deck);
398 }
399 
400 
401 static bool
402 translate(deck, formal, actual, scname, subname, instr)
403 
404 /* Translate all of the device names and node names in the deck. They are
405  * pre-pended with subname:, unless they are in the formal list, in which
406  * case they are replaced with the corresponding entry in the actual list.
407  * The one special case is node 0 -- this is always ground and we don't
408  * touch it.
409  */
410 struct line *deck;
411 char *formal, *actual, *scname, *subname, *instr;
412 {
413  struct line *c;
414  char *buffer, *name, *s, *t, ch;
415  int nnodes, ndevs, i;
416  char *tmpname;
417  bool retval = false;
418 
419  if (settrans(formal, actual, subname, instr)) {
420  retval = true;
421  goto cleanup;
422  }
423 
424  for (c = deck; c; c = c->li_next) {
425  /* Rename the device. */
426  ch = *c->li_line;
427  if (ch == '.' || ch == '*' || ch == '\0')
428  /* Nothing any good here. */
429  continue;
430 
431  s = c->li_line;
432  tmpname = name = gettok(&s);
433  if (!name)
434  continue;
435  if (!*name) {
436  txfree(name);
437  continue;
438  }
439  ch = *name;
440  buffer = tmalloc(1000);
441  name++;
442  if (*name == ':')
443  name++;
444  if (*name)
445  (void) sprintf(buffer, "%c:%s:%s ", ch, scname, name);
446  else
447  (void) sprintf(buffer, "%c:%s ", ch, scname);
448  txfree(tmpname);
449 
450  numrefs(c->li_line,&nnodes,&ndevs);
451  while (nnodes-- > 0) {
452  name = gettok(&s);
453  if (name == NULL) {
454  fprintf(cp_err, "Warning: too few nodes: %s\n", c->li_line);
455  retval = true;
456  txfree(name);
457  goto cleanup;
458  }
459  t = gettrans(name);
460  if (t)
461  (void) sprintf(buffer + strlen(buffer), "%s ", t);
462  else
463  (void) sprintf(buffer + strlen(buffer),
464  "%s:%s ", scname, name);
465  txfree(name);
466  }
467  while (ndevs-- > 0) {
468  tmpname = name = gettok(&s);
469  if (name == NULL) {
470  fprintf(cp_err, "Warning: too few devs: %s\n", c->li_line);
471  retval = true;
472  goto cleanup;
473  }
474  ch = *name;
475  name++;
476  if (*name == ':')
477  name++;
478  if (*name)
479  (void) sprintf(buffer + strlen(buffer),
480  "%c:%s:%s ", ch, scname, name);
481  else
482  (void) sprintf(buffer + strlen(buffer),
483  "%c:%s ", ch, scname);
484  txfree(tmpname);
485  }
486  /* Now scan through the line for v(something) and
487  * i(something)...
488  */
489  finishLine(buffer + strlen(buffer), s, scname);
490  txfree(c->li_line);
491  c->li_line = copy(buffer);
492  txfree(buffer);
493  }
494 cleanup:
495  for (i = 0; i < 512; i++) {
496  if (table[i].t_old == NULL) {
497  tfree(table[i].t_new);
498  break;
499  }
500  tfree(table[i].t_old);
501  tfree(table[i].t_new);
502  }
503  return retval;
504 }
505 
506 
507 static void
508 finishLine(dst, src, scname)
509 
510 char *dst;
511 char *src;
512 char *scname;
513 {
514  char buf[4 * BSIZE_SP], which;
515  char *s;
516  int i;
517  int lastwasalpha;
518 
519  lastwasalpha = 0;
520  while (*src) {
521  /* Find the next instance of "<non-alpha>[vi]<opt spaces>(" in
522  * this string.
523  */
524  if (((*src != 'v') && (*src != 'V') &&
525  (*src != 'i') && (*src != 'I')) ||
526  lastwasalpha) {
527  lastwasalpha = isalpha(*src);
528  *dst++ = *src++;
529  continue;
530  }
531  for (s = src + 1; *s && isspace(*s); s++)
532  ;
533  if (!*s || (*s != '(')) {
534  lastwasalpha = isalpha(*src);
535  *dst++ = *src++;
536  continue;
537  }
538  lastwasalpha = 0;
539  which = *dst++ = *src;
540  src = s;
541  *dst++ = *src++;
542  while (isspace(*src))
543  src++;
544  for (i = 0;
545  *src && !isspace(*src) && *src != ',' && (*src != ')'); i++) {
546  buf[i] = *src++;
547  }
548  buf[i] = '\0';
549 
550  if ((which == 'v') || (which == 'V'))
551  s = gettrans(buf);
552  else
553  s = NULL;
554 
555  if (s) {
556  while (*s)
557  *dst++ = *s++;
558  }
559  else {
560  /*
561  * i(vname) -> i(v:subckt:name)
562  * i(v:other:name) -> i(v:subckt:other:name)
563  */
564  if (buf[0] == 'v' || buf[0] == 'V') {
565  *dst++ = buf[0];
566  *dst++ = ':';
567  i = 1;
568  }
569  else {
570  i = 0;
571  }
572  for (s = scname; *s; )
573  *dst++ = *s++;
574  *dst++ = ':';
575  for (s = buf + i; *s; )
576  *dst++ = *s++;
577  }
578 
579  /* translate the reference node, as in the "2" in "v(4,2)" */
580 
581  if ((which == 'v') || (which == 'V')) {
582  while (*src && (isspace(*src) || *src == ',')) {
583  src++;
584  }
585  if (*src && *src != ')') {
586  for (i = 0; *src && !isspace(*src) && (*src != ')'); i++)
587  buf[i] = *src++;
588  buf[i] = '\0';
589  s = gettrans(buf);
590  *dst++ = ',';
591  if (s) {
592  while (*s)
593  *dst++ = *s++;
594  }
595  else {
596  for (s = scname; *s; )
597  *dst++ = *s++;
598  *dst++ = ':';
599  for (s = buf; *s; )
600  *dst++ = *s++;
601  }
602  }
603  }
604  }
605  return;
606 }
607 
608 
609 static bool
610 settrans(formal, actual, subname, instr)
611 
612 char *formal, *actual, *subname, *instr;
613 {
614  int i;
615 
616  for (i = 0; ; i++) {
617  table[i].t_old = gettok(&formal);
618  table[i].t_new = gettok(&actual);
619 
620  if (table[i].t_new == NULL) {
621  fprintf(cp_err, "Error: too many params: %s\n", instr);
622  return (true); /* Too few formal / too many actual */
623  }
624  if (table[i].t_old == NULL) {
625  if (eq(table[i].t_new, subname))
626  break;
627  else {
628  fprintf(cp_err, "Error: too few params: %s\n", instr);
629  return (true); /* Too few actual / too many formal */
630  }
631  }
632  }
633  if (aredups()) {
634  fprintf(cp_err,
635  "Error: duplicate nodes given in subckt %s\n",subname);
636  return (true);
637  }
638  return (false);
639 }
640 
641 
642 static bool
644 
645 {
646  int i, j;
647  char *s;
648 
649  for (i = 0; table[i].t_old; i++) {
650  s = table[i].t_old;
651  for (j = i+1; table[j].t_old; j++) {
652  if (eq(s,table[j].t_old))
653  return (true);
654  }
655  }
656  return (false);
657 }
658 
659 
660 static char *
661 gettrans(name)
662 
663 char *name;
664 {
665  int i;
666 
667  if (eq(name, "0"))
668  return (name);
669  for (i = 0; table[i].t_old; i++)
670  if (eq(table[i].t_old, name))
671  return (table[i].t_new);
672  return (NULL);
673 }
674 
675 
676 static void
677 numrefs(name,terms,devs)
678 
679 char *name;
680 int *terms, *devs;
681 {
682  char c;
683  struct subs *sss;
684  char *s, *t, buf[4 * BSIZE_SP];
685  wordlist *wl;
686  int n, i, soft;
687 
688  while (*name && isspace(*name))
689  name++;
690 
691  c = (isupper(*name) ? tolower(*name) : *name);
692 
693  (void) strncpy(buf, name, sizeof(buf));
694  s = buf;
695  if (c == 'x') { /* Handle this ourselves. */
696  while(*s)
697  s++;
698  s--;
699  while ((*s == ' ') || (*s == '\t'))
700  *s-- = '\0';
701  while ((*s != ' ') && (*s != '\t'))
702  s--;
703  s++;
704  for (sss = subs; sss; sss = sss->su_next)
705  if (eq(sss->su_name, s))
706  break;
707  if (!sss) {
708  *terms = 0;
709  *devs = 0;
710  fprintf(cp_err, "Error: no such subcircuit: %s\n", s);
711  return;
712  }
713  *terms = sss->su_numargs;
714  *devs = 0;
715  return;
716  }
717 
718  (void)INPnumRefs(c,&n,devs,&soft,NULL);
719  if (isalpha(c) && n == 0 && *devs == 0)
720  fprintf(cp_err, "Warning: unknown device key: %c\n", c);
721 
722  if (!soft) {
723  *terms = n;
724  return;
725  }
726  for (s = buf, i = 0; *s && (i < n); i++)
727  advtok(&s);
728  if (i == n-1) {
729  *terms = n-1;
730  return;
731  }
732  else if (i < n) {
733  fprintf(cp_err, "Error: too few nodes for %s\n", name);
734  *terms = 0;
735  return;
736  }
737  /* Now, is this a model? */
738  t = gettok(&s);
739  for (wl = modnames; wl; wl = wl->wl_next) {
740  if (eq(t, wl->wl_word)) {
741  txfree(t);
742  *terms = n-1;
743  return;
744  }
745  }
746  txfree(t);
747  *terms = n;
748  return;
749 }
750 
751 
752 static bool
753 modtranslate(deck, subname)
754 
755 struct line *deck;
756 char *subname;
757 {
758  struct line *c;
759  char *buffer, *name, *t;
760  wordlist *wl, *wlsub;
761  bool gotone;
762 
763  gotone = false;
764  for (c = deck; c; c = c->li_next) {
765  if (prefix(model, c->li_line)) {
766  gotone = true;
767  t = c->li_line;
768  name = gettok(&t);
769  buffer = tmalloc(strlen(name) + strlen(t) +
770  strlen(subname) + 4);
771  (void) sprintf(buffer, "%s ",name);
772  txfree(name);
773  name = gettok(&t);
774  wlsub = alloc(struct wordlist);
775  wlsub->wl_next = submod;
776  if (submod)
777  submod->wl_prev = wlsub;
778  submod = wlsub;
779  wlsub->wl_word = name;
780  (void) sprintf(buffer + strlen(buffer), "%s:%s ",
781  subname, name);
782  (void) strcat(buffer, t);
783  txfree(c->li_line);
784  c->li_line = buffer;
785  t = c->li_line;
786  advtok(&t);
787  wl = alloc(struct wordlist);
788  wl->wl_next = modnames;
789  if (modnames)
790  modnames->wl_prev = wl;
791  modnames = wl;
792  wl->wl_word = gettok(&t);
793  }
794  }
795  return (gotone);
796 }
797 
798 
799 static void
800 devmodtranslate(deck, subname)
801 
802 struct line *deck;
803 char *subname;
804 {
805  struct line *s;
806  char *buffer, *name, *t, c;
807  int terms, devs, soft, hasmod;
808 
809  for (s = deck; s; s = s->li_next) {
810  t = s->li_line;
811  while (*t && isspace(*t))
812  t++;
813  c = isupper(*t) ? tolower(*t) : *t;
814 
815  INPnumRefs(c,&terms,&devs,&soft,&hasmod);
816  if (!hasmod)
817  continue;
818 
819  buffer = tmalloc(strlen(t) + strlen(subname) + 4);
820 
821  terms += devs + 1;
822  if (soft) terms--;
823  *buffer = '\0';
824  while (terms--)
825  copytok1(buffer + strlen(buffer),&t);
826 
827  looksubmod(&t,buffer,subname);
828  if (soft)
829  looksubmod(&t,buffer,subname);
830  (void) strcat(buffer, t);
831  txfree(s->li_line);
832  s->li_line = buffer;
833  }
834 }
835 
836 
837 static void
838 looksubmod(t,buffer,subname)
839 
840 char **t, *buffer, *subname;
841 {
842  wordlist *wlsub;
843  char *name;
844  bool found = false;;
845 
846  if (**t == '\0') return;
847  name = gettok(t);
848  /* Now, is this a subcircuit model? */
849  for (wlsub = submod; wlsub; wlsub = wlsub->wl_next)
850  if (eq(name, wlsub->wl_word)) {
851  (void) sprintf(buffer + strlen(buffer), "%s:%s ", subname, name);
852  found = true;
853  break;
854  }
855  if (!found)
856  (void) sprintf(buffer + strlen(buffer), "%s ", name);
857  txfree(name);
858 }
859 
860 
861 
862 
863 
864 
865 
static struct subs * subs
Definition: subckt.c:73
static char buf[MAXPROMPT]
Definition: arg.c:18
char * gettok()
#define BSIZE_SP
Definition: misc.h:19
#define eq(a, b)
Definition: misc.h:29
int ciprefix()
int copytok1(char *dst, char **s)
Definition: string.c:241
static bool translate()
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
static struct tab table[512]
static char * gettrans()
#define prefix(x, y)
Definition: readhelp.c:39
struct line * inp_subcktexpand(struct line *deck)
Definition: subckt.c:80
char * strcpy()
struct line * inp_deckcopy()
Definition: cddefs.h:119
struct line * su_def
Definition: subckt.c:47
char * kw_nobjthack
Definition: options.c:380
Definition: xforms.c:16
static bool aredups()
Definition: subckt.c:643
static struct line * doit()
static char invoke[32]
Definition: subckt.c:76
static void looksubmod()
Definition: subckt.c:51
Definition: library.c:18
#define alloc(type)
Definition: cdmacs.h:21
char * copy()
#define MAXNEST
Definition: subckt.c:151
void wl_free()
FILE * cp_err
Definition: help.c:101
char * tmalloc()
Definition: fteinp.h:14
static char start[32]
Definition: subckt.c:76
struct wordlist * wl_prev
Definition: cpstd.h:24
#define tfree(x)
Definition: cdmacs.h:22
static bool settrans()
void txfree()
#define NULL
Definition: spdefs.h:121
char * su_name
Definition: subckt.c:44
char * kw_modelcard
Definition: options.c:375
char * li_line
Definition: fteinp.h:16
static wordlist * modnames
Definition: subckt.c:72
static void finishLine()
static void devmodtranslate()
static double c
Definition: vectors.c:16
#define VT_STRING
Definition: cpstd.h:63
struct subs * su_next
Definition: subckt.c:48
void advtok()
struct line * li_next
Definition: fteinp.h:18
static void numrefs()
#define VT_BOOL
Definition: cpstd.h:60
void inp_deckfree()
char * su_args
Definition: subckt.c:45
char * t_old
Definition: subckt.c:52
Definition: cpstd.h:21
static char model[32]
Definition: subckt.c:76
int su_numargs
Definition: subckt.c:46
char * kw_subend
Definition: options.c:420
static bool modtranslate()
static char sbend[32]
Definition: subckt.c:76
struct wordlist * wl_next
Definition: cpstd.h:23
int INPnumRefs()
char * wl_word
Definition: cpstd.h:22
char * t_new
Definition: subckt.c:53
char * kw_substart
Definition: options.c:422
Definition: subckt.c:43
Definition: cddefs.h:192
static bool nobjthack
Definition: subckt.c:74
char * kw_subinvoke
Definition: options.c:421
static wordlist * submod
Definition: subckt.c:72