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
5 1992 Stephen R. Whiteley
6 ****************************************************************************/
7
8 /*
9 * Spice-2 compatibility stuff for .plot, .print, .four, and .width.
10 */
11
12 #include "spice.h"
13 #include "ftedefs.h"
14 #include "fteinp.h"
15 #include "spfteext.h"
16
17 #ifdef __STDC__
18 static void fixdotplot(wordlist*);
19 static void fixdotprint(wordlist*);
20 static char *fixem(char*);
21 static bool setcplot(char*);
22 static wordlist *gettoks(char*);
23 #else
24 static void fixdotplot();
25 static void fixdotprint();
26 static char *fixem();
27 static bool setcplot();
28 static wordlist *gettoks();
29 #endif
30
31 bool ft_acctprint = false;
32 bool ft_listprint = false;
33 bool ft_nodesprint = false;
34 bool ft_optsprint = false;
35
36
37 /* Extract all the .save lines */
38
39 void
ft_dotsaves()40 ft_dotsaves()
41 {
42 wordlist *iline, *wl = NULL;
43 char *s;
44
45 if (!ft_curckt) /* Shouldn't happen. */
46 return;
47
48 for (iline = ft_curckt->ci_commands; iline; iline = iline->wl_next) {
49 if (ciprefix(".save", iline->wl_word)) {
50 s = iline->wl_word;
51 advtok(&s);
52 wl = wl_append(wl, gettoks(s));
53 }
54 }
55 if (wl) {
56 com_save(wl);
57 wl_free(wl);
58 }
59 /* If there aren't any .saves, all vectors will be saved,
60 * which is the default action for rawfiles when com_save()
61 * isn't called.
62 */
63 return;
64 }
65
66
67 /* Go through the dot lines given and make up a big "save" command with
68 * all the node names mentioned. Note that if a node is requested for
69 * one analysis, it is saved for all of them.
70 */
71
72 void
ft_savedotargs()73 ft_savedotargs()
74 {
75 wordlist *w, *wl = NULL, *iline;
76 char *s;
77
78 if (!ft_curckt) /* Shouldn't happen. */
79 return;
80
81 for (iline = ft_curckt->ci_commands; iline; iline = iline->wl_next) {
82 s = iline->wl_word;
83 if (ciprefix(".print", s) || ciprefix(".plot", s) ||
84 ciprefix(".four", s)) {
85 advtok(&s);
86 advtok(&s);
87 if (!(w = gettoks(s)))
88 fprintf(cp_err, "Warning: no nodes given: %s\n",
89 iline->wl_word);
90 wl = wl_append(wl, w);
91 }
92 }
93 if (wl) {
94 com_save(wl);
95 wl_free(wl);
96 }
97 fprintf(cp_err, "Warning: no .print, .plot, or .four lines in input.\n");
98 }
99
100
101 /* Execute the .whatever lines found in the deck, after we are done running.
102 * We'll be cheap and use cp_lexer to get the words. This should make us
103 * spice-2 compatible. If terse is true then there was a rawfile, so don't
104 * print lots of junk.
105 */
106
107 void
ft_cktcoms(terse)108 ft_cktcoms(terse)
109
110 bool terse;
111 {
112 wordlist *coms, *command, *cl;
113 char *plottype, *s;
114 struct dvec *v;
115 struct dvlist *dl0, *dl;
116 static wordlist twl = { "col", NULL, NULL } ;
117 int i;
118
119 if (!ft_curckt)
120 return;
121 if (!ft_curckt->ci_commands)
122 goto nocmds;
123 coms = ft_curckt->ci_commands;
124 cp_interactive = false;
125
126 out_init();
127
128 /* Circuit name */
129 out_printf("Circuit: %s\nDate: %s\n\n", ft_curckt->ci_name,
130 datestring());
131 out_printf("\n");
132
133 /* Listing */
134 if (ft_listprint) {
135 if (terse)
136 out_printf(".options: no listing, rawfile was generated.\n");
137 else
138 inp_list(cp_out, ft_curckt->ci_deck, ft_curckt->ci_options,
139 LS_DECK);
140 }
141
142 /* If there was a .op line, then we have to do the .op output. */
143 if (setcplot("op")) {
144 if (terse) {
145 out_printf("\nOP information in rawfile.\n");
146 }
147 else {
148 out_printf("\nOperating point information:\n\n");
149 out_printf("\tNode\tVoltage\n");
150 out_printf("\t----\t-------\n");
151
152 v = vec_fromplot("all",plot_cur);
153 vec_sort(v);
154 dl0 = v->v_link2;
155
156 for (dl = dl0; dl; dl = dl->dl_next) {
157 v = dl->dl_dvec;
158 if (!isreal(v)) {
159 fprintf(cp_err,
160 "Internal error: op vector %s not real\n", v->v_name);
161 continue;
162 }
163 if (v->v_type == SV_VOLTAGE)
164 out_printf("\t%s\t%s\n", v->v_name,
165 printnum(v->v_realdata[0]));
166 }
167 out_printf("\n\tSource\tCurrent\n");
168 out_printf("\t------\t-------\n\n");
169 for (dl = dl0; dl; dl = dl->dl_next) {
170 v = dl->dl_dvec;
171 if (v->v_type == SV_CURRENT)
172 out_printf("\t%s\t%s\n", v->v_name,
173 printnum(v->v_realdata[0]));
174 }
175 out_printf("\n");
176 }
177 }
178
179 if (setcplot("tf")) {
180 wordlist all;
181
182 if (terse)
183 out_printf("TF information in rawfile.\n");
184 else {
185 out_printf("Transfer function information:\n");
186 all.wl_next = NULL;
187 all.wl_word = "all";
188 com_print(&all);
189 out_printf("\n");
190 }
191 }
192
193 /* Now all the '.' lines */
194 while (coms) {
195 cl = command = cp_lexer(coms->wl_word);
196 if (!command)
197 goto bad;
198 if (eq(command->wl_word, ".width")) {
199 do {
200 command = command->wl_next;
201 } while (command && !ciprefix("out", command->wl_word));
202 if (command) {
203 s = strchr(command->wl_word, '=');
204 if (!s || !s[1]) {
205 fprintf(cp_err,
206 "Error: bad line %s\n", coms->wl_word);
207 coms = coms->wl_next;
208 wl_free(cl);
209 continue;
210 }
211 i = atoi(++s);
212 cp_vset("width", VT_NUM, (char *) &i);
213 }
214 }
215 else if (eq(command->wl_word, ".print")) {
216 if (terse) {
217 out_printf(
218 "\n.print line ignored since rawfile was produced\n");
219 }
220 else {
221 command = command->wl_next;
222 if (!command) {
223 fprintf(cp_err, "Error: bad line %s\n", coms->wl_word);
224 coms = coms->wl_next;
225 wl_free(cl);
226 continue;
227 }
228 plottype = command->wl_word;
229 command = command->wl_next;
230 fixdotprint(command);
231 twl.wl_next = command;
232 if (setcplot(plottype))
233 com_print(&twl);
234 else
235 fprintf(cp_err,
236 "Error: no %s plot found\n", plottype);
237 out_printf("\n\n");
238 }
239 }
240 else if (eq(command->wl_word, ".plot")) {
241 if (terse) {
242 out_printf(
243 "\n.plot line ignored since rawfile was produced\n");
244 }
245 else {
246 command = command->wl_next;
247 if (!command) {
248 fprintf(cp_err, "Error: bad line %s\n", coms->wl_word);
249 coms = coms->wl_next;
250 wl_free(cl);
251 continue;
252 }
253 plottype = command->wl_word;
254 command = command->wl_next;
255 fixdotplot(command);
256 if (setcplot(plottype))
257 com_asciiplot(command);
258 else
259 fprintf(cp_err,
260 "Error: no %s plot found\n", plottype);
261 out_printf("\n\n");
262 }
263 }
264 else if (ciprefix(".four", command->wl_word)) {
265 if (terse)
266 out_printf(
267 ".fourier line ignored since rawfile was produced.\n");
268 else if (setcplot("tran")) {
269 com_fourier(command->wl_next);
270 out_printf("\n\n");
271 }
272 else {
273 out_printf(
274 "No transient data available for fourier analysis");
275 }
276 }
277 else if (!eq(command->wl_word, ".save")
278 && !eq(command->wl_word, ".op")
279 && !eq(command->wl_word, ".tf"))
280 goto bad;
281 wl_free(cl);
282 coms = coms->wl_next;
283 }
284
285 nocmds:
286 /* Now the node table */
287 if (ft_nodesprint)
288 ;
289
290 /* The options */
291 if (ft_optsprint) {
292 fprintf(cp_err, "Options:\n\n");
293 cp_vprint();
294 (void) putc('\n', cp_out);
295 }
296
297 /* And finally the accounting info. */
298 if (ft_acctprint) {
299 static wordlist ww = { "everything", NULL, NULL } ;
300 com_rusage(&ww);
301 }
302 else
303 com_rusage((wordlist *) NULL);
304
305 out_printf("\n");
306 return;
307
308 bad:
309 fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n");
310 return;
311 }
312
313
314 /* These routines make sure that the arguments to .plot and .print in
315 * spice2 decks are acceptable to spice3. The things we look for are:
316 * trailing (a,b) in .plot -> xlimit a b
317 * vm(x) -> mag(v(x))
318 * vp(x) -> ph(v(x))
319 * v(x,0) -> v(x)
320 * v(0,x) -> -v(x)
321 */
322
323 static void
fixdotplot(wl)324 fixdotplot(wl)
325
326 wordlist *wl;
327 {
328 char buf[BSIZE_SP], *s;
329 double *d, d1, d2;
330
331 while (wl) {
332 wl->wl_word = fixem(wl->wl_word);
333
334 /* Is this a trailing (a,b) ? Note that we require it to be
335 * one word.
336 */
337 if (!wl->wl_next && (*wl->wl_word == '(')) {
338 s = wl->wl_word + 1;
339 d = ft_numparse(&s, false);
340 if (*s != ',') {
341 fprintf(cp_err, "Error: bad limits \"%s\"\n",
342 wl->wl_word);
343 return;
344 }
345 d1 = *d;
346 s++;
347 d = ft_numparse(&s, false);
348 if ((*s != ')') || s[1]) {
349 fprintf(cp_err, "Error: bad limits \"%s\"\n",
350 wl->wl_word);
351 return;
352 }
353 d2 = *d;
354 tfree(wl->wl_word);
355 wl->wl_word = copy("xlimit");
356 wl->wl_next = alloc(struct wordlist);
357 wl->wl_next->wl_prev = wl;
358 wl = wl->wl_next;
359 (void) strcpy(buf, printnum(d1));
360 wl->wl_word = copy(buf);
361 wl->wl_next = alloc(struct wordlist);
362 wl->wl_next->wl_prev = wl;
363 wl = wl->wl_next;
364 (void) strcpy(buf, printnum(d2));
365 wl->wl_word = copy(buf);
366 }
367 wl = wl->wl_next;
368 }
369 }
370
371
372 static void
fixdotprint(wl)373 fixdotprint(wl)
374
375 wordlist *wl;
376 {
377 while (wl) {
378 wl->wl_word = fixem(wl->wl_word);
379 wl = wl->wl_next;
380 }
381 }
382
383
384 static char *
fixem(string)385 fixem(string)
386
387 char *string;
388 {
389 char buf[BSIZE_SP], *s, *t, *ss = string;
390
391 if (ciprefix("v(", string) && strchr(string, ',')) {
392 for (s = string; *s && (*s != ','); s++)
393 ;
394 *s++ = '\0';
395 for (t = s; *t && (*t != ')'); t++)
396 ;
397 *t = '\0';
398 if (eq(s, "0"))
399 (void) sprintf(buf, "v(%s)", string + 2);
400 else if (eq(string + 2, "0"))
401 (void) sprintf(buf, "-v(%s)", s);
402 else
403 (void) sprintf(buf, "v(%s)-v(%s)", string + 2, s);
404 tfree(ss);
405 return (copy(buf));
406 }
407 if (ciprefix("vm(", string)) {
408 for (s = string; *s && (*s != ')'); s++)
409 ;
410 *s = '\0';
411 (void) sprintf(buf, "mag(v(%s))", string + 3);
412 tfree(ss);
413 return (copy(buf));
414 }
415 if (ciprefix("vp(", string)) {
416 for (s = string; *s && (*s != ')'); s++)
417 ;
418 *s = '\0';
419 (void) sprintf(buf, "ph(v(%s))", string + 3);
420 tfree(ss);
421 return (copy(buf));
422 }
423 if (ciprefix("vi(", string)) {
424 for (s = string; *s && (*s != ')'); s++)
425 ;
426 *s = '\0';
427 (void) sprintf(buf, "imag(v(%s))", string + 3);
428 tfree(ss);
429 return (copy(buf));
430 }
431 if (ciprefix("vr(", string)) {
432 for (s = string; *s && (*s != ')'); s++)
433 ;
434 *s = '\0';
435 (void) sprintf(buf, "real(v(%s))", string + 3);
436 tfree(ss);
437 return (copy(buf));
438 }
439 if (ciprefix("vdb(", string)) {
440 for (s = string; *s && (*s != ')'); s++)
441 ;
442 *s = '\0';
443 (void) sprintf(buf, "db(v(%s))", string + 4);
444 tfree(ss);
445 return (copy(buf));
446 }
447 if (ciprefix("i(", string)) {
448 for (s = string; *s && (*s != ')'); s++)
449 ;
450 *s = '\0';
451 string += 2;
452 (void) sprintf(buf, "%s#branch", string);
453 tfree(ss);
454 return (copy(buf));
455 }
456 return (string);
457 }
458
459
460 /* Don't bother with ccom strangeness here. */
461
462 static bool
setcplot(name)463 setcplot(name)
464
465 char *name;
466 {
467 struct plot *pl;
468
469 for (pl = plot_list; pl; pl = pl->pl_next) {
470 if (ciprefix(name, pl->pl_typename)) {
471 plot_cur = pl;
472 return (true);
473 }
474 }
475 return (false);
476 }
477
478
479 static wordlist *
gettoks(s)480 gettoks(s)
481
482 char *s;
483 {
484 char *t, *r, buf[64], buf1[BSIZE_SP];
485 wordlist *wl = NULL, *end = NULL;
486 bool iflag;
487
488 while (copytok(buf1,&s)) {
489 t = buf1;
490 if (*t == '(') {
491 /* This is a (upper, lower) thing -- ignore. */
492 continue;
493 }
494 if (!strchr(t, '(')) {
495 ;
496 }
497 else if (!strchr(t, ',')) {
498 iflag = ((*t == 'i') || (*t == 'I')) ? true : false;
499 while (*t != '(')
500 t++;
501 t++;
502 for (r = t; *r && *r != ')'; r++)
503 ;
504 *r = '\0';
505 if (iflag) {
506 (void) sprintf(buf, "%s#branch", t);
507 t = buf;
508 }
509 }
510 else {
511 /* The painful case */
512 while (*t != '(')
513 t++;
514 t++;
515 for (r = t; *r && *r != ','; r++)
516 ;
517 *r = '\0';
518 if (end) {
519 end->wl_next = alloc(struct wordlist);
520 end->wl_next->wl_prev = end;
521 end = end->wl_next;
522 }
523 else
524 wl = end = alloc(struct wordlist);
525 end->wl_word = copy(t);
526 t = r + 1;
527 for (r = t; *r && *r != ')'; r++)
528 ;
529 *r = '\0';
530 }
531 if (end) {
532 end->wl_next = alloc(struct wordlist);
533 end->wl_next->wl_prev = end;
534 end = end->wl_next;
535 }
536 else
537 wl = end = alloc(struct wordlist);
538 end->wl_word = copy(t);
539 }
540 return (wl);
541 }
542
543