1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Thomas L. Quarles
5 1992 Stephen R. Whiteley
6 ****************************************************************************/
7
8 /*
9 * The main routine for Jspice3 and nutmeg.
10 */
11
12 #include "spice.h"
13 #include "misc.h"
14 #include "ftedefs.h"
15 #include "inpdefs.h"
16 #include "iferrmsg.h"
17 #include "plotdev.h"
18 #include "ftedebug.h"
19 #include "const.h"
20 #include "scedio.h"
21 #include <setjmp.h>
22
23 #ifdef HAVE_GETPWUID
24 #include <pwd.h>
25 #endif
26
27 #ifdef HAVE_SIGNAL
28 #include <sys/types.h>
29 #include <signal.h>
30 #endif
31
32 #ifndef HAVE_GETRUSAGE
33 #ifdef HAVE_FTIME
34 #include <sys/types.h>
35 #include <sys/timeb.h>
36 #endif
37 #endif
38
39 char *ft_rawfile = "rawspice.raw";
40
41 char *errRtn;
42 char *errMsg;
43 char *cp_program;
44 char *cp_display;
45
46 bool ft_servermode = false;
47 bool ft_intrpt = false; /* Set by the signal handlers. */
48 bool ft_setflag = false; /* Don't abort after an interrupt. */
49
50 #ifdef __STDC__
51 struct variable *(*if_getparam)(char*,char**,char*,int,wordlist**);
52 #else
53 struct variable *(*if_getparam)();
54 #endif
55
56 #ifdef BATCH
57
58 DISPDEVICE device[ ] = {
59 {"", 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0,
61 0, 0, 0, 0,
62 0, 0, 0, 0,
63 0, 0, 0, 0 }
64 };
65 DISPDEVICE *dispdev = device;
66 bool ft_nopage = false;
67 bool ft_parsedb = false;
68 bool ft_evdb = false;
69 bool ft_vecdb = false;
70 bool ft_grdb = false;
71 bool ft_gidb = false;
72 bool ft_controldb = false;
73 bool ft_asyncdb = false;
74
75 bool ft_debug = false;
76 bool ft_batchmode = true;
77 bool ft_nospiceadd = true;
78 bool ft_simdb = false;
79 static char *usage = "Usage: %s [ - ] [ -r rawfile ] [ file ... ]\n";
80 FILE *cp_curin = 0;
81 FILE *cp_curout = 0;
82 FILE *cp_curerr = 0;
83 FILE *cp_in = 0;
84 FILE *cp_out = 0;
85 FILE *cp_err = 0;
86 bool gi_endpause = true;
87
88 #ifndef SPICE2
89 bool ft_listprint = true;
90 bool ft_optsprint = false;
91 bool ft_nodesprint = false;
92 bool ft_acctprint = false;
93 struct plot *plot_list = NULL;
94 #endif
95
96 #else
97
98 bool ft_batchmode = false;
99 jmp_buf jbuf;
100 static char *usage =
101 "Usage: %s [-] [-b] [-i] [-s] [-n] [-o outfile] [-r rawfile]\n\
102 \t[-t term] [file ...]\n";
103 struct options *exitoption;
104 struct options *helpoption;
105 extern RETSIGTYPE ft_sigintr(), sigfloat(), sigstop(), sigquit();
106 extern RETSIGTYPE sigill(), sigbus(), sigsegv(), sig_sys();
107
108 #endif
109
110 static started = false;
111 IFsimulator *ft_sim;
112
113 extern IFsimulator SIMinfo;
114
115 /* for HLP */
116 char *hlp_filelist[] = {"spice", "sced", 0 };
117
118 #ifdef SIMULATOR
119
120 bool ft_nutmeg = false;
121
122 #ifndef BATCH
123 extern struct comm spcp_coms[ ];
124 struct comm *cp_coms = spcp_coms;
125 #endif
126 extern int OUTstopnow(), OUTerror();
127 extern int OUTbeginPlot(), OUTdata(), OUTsetDims(), OUTendPlot();
128 extern int OUTendit;
129 static IFfrontEnd nutmeginfo = {
130 IFnewUid,
131 OUTstopnow,
132 seconds,
133 OUTerror,
134 OUTbeginPlot,
135 OUTdata,
136 OUTsetDims,
137 OUTendPlot,
138 &OUTendit
139 };
140
141 static void clear_previous();
142 extern int InProgress(), IsIplot();
143 extern void ft_dosim(), inp_decksource();
144 extern void com_resume(), com_iplot(), com_delete();
145
146 /* for SCED */
147 static struct sSCEDitf sc_itf =
148 {
149 InProgress,
150 ft_dosim,
151 inp_decksource,
152 clear_previous,
153 com_resume,
154 IsIplot,
155 com_iplot,
156 com_delete
157 };
158
159 #else
160
161 bool ft_nutmeg = true;
162 extern struct comm nutcp_coms[ ];
163 struct comm *cp_coms = nutcp_coms;
164 static IFfrontEnd nutmeginfo;
165
166
167 /* for SCED */
168 static struct sSCEDitf sc_itf =
169 {
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL
178 };
179
180 /*
181 * Misc globals we have to fake for nutmeg.
182 */
183
184 struct circ *ft_curckt;
185 struct circ *ft_circuits;
186 struct dbcomm *dbiplot = NULL; /* export for iplot */
187
188 bool ft_listprint;
189 bool ft_optsprint;
190 bool ft_nodesprint;
191 bool ft_acctprint;
192
193 /* ARGSUSED */
194 void
inp_spsource(fp,i,s)195 inp_spsource(fp,i,s) /* main.c */
196 FILE* fp;
197 bool i;
198 char *s;
199 { inp_nutsource(fp,i,s); }
200
201 /* ARGSUSED */
202 void
inp_source(s)203 inp_source(s) /* main.c */
204 char *s;
205 {
206 wordlist *wl;
207
208 wl = cp_lexer(s);
209 nutcom_source(wl);
210 wl_free(wl);
211 }
212
213 /* ARGSUSED */
214 void
ft_dorun(s)215 ft_dorun(s) /* main.c */
216 char *s;
217 { return; }
218
219 /* ARGSUSED */
220 void
ft_dotsaves()221 ft_dotsaves() /* main.c */
222 { return; }
223
224 /* ARGSUSED */
225 void
ft_savedotargs()226 ft_savedotargs() /* main.c */
227 { return; }
228
229 /* ARGSUSED */
230 void
ft_cktcoms(i)231 ft_cktcoms(i) /* main.c */
232 bool i;
233 { return; }
234
235 /* ARGSUSED */
236 char *
if_errstring(code)237 if_errstring(code) /* error.c */
238 { return ("spice error"); }
239
240 /* ARGSUSED */
241 void
if_option(ckt,name,type,value)242 if_option(ckt, name, type, value) /* options.c */
243 char *name, *ckt, *value;
244 int type; { }
245
246 /* ARGSUSED */
247 struct variable *
if_getstat(n,c,w)248 if_getstat(n, c, w) /* resource.c */
249 char *n, *c;
250 wordlist **w;
251 { return (NULL);}
252
253 /* ARGSUSED */
254 wordlist *
GetAnalysisFromDeck()255 GetAnalysisFromDeck() /* scedintr.c */
256 { return (NULL); }
257
258 /* ARGSUSED */
259 void
inp_list(fp,l1,l2,i)260 inp_list(fp,l1,l2,i) /* argaf.c */
261 FILE *fp;
262 struct line *l1, *l2;
263 int i;
264 { return; }
265
266 /* screen line editor for nutmeg, when not using X */
267 /* cursor height - 1 */
268 #define CURHT 0
269 #define FontWidth currentgraph->fontwidth
270
271 static void
textcursor(x,y)272 textcursor(x,y)
273
274 int x,y;
275 {
276 DevBox(x,y-1,x+FontWidth,y+CURHT);
277 }
278
279 char *
KbEdit(s,x,y,bg,fg,cc)280 KbEdit(s,x,y,bg,fg,cc)
281
282 /*
283 * s Initial string to edit.
284 * x,y Lower left coordinates.
285 * bg,fg Background and foreground colors.
286 * cc Background color at cursor location.
287 * Returns edited string (static!).
288 */
289 char *s;
290 int x, y, bg, fg, cc;
291 {
292 char tbuf[128];
293 int i, k;
294 char *end, ctmp[2];
295 int editX, editY, editFg, editCc;
296 char *editC;
297 static char editBuf[128];
298
299 editFg = fg;
300 editCc = cc;
301 editX = x;
302 editY = y;
303
304 DevSetColor(fg);
305 *editBuf = '\0';
306 if (s) {
307 /* s can be NULL */
308 DevText(s, editX, editY);
309 strcpy(editBuf,s);
310 }
311 ctmp[1] = '\0';
312 editC = editBuf;
313 end = strchr(editBuf,'\0');
314 *(end+1) = '\0';
315 ctmp[0] = *editC;
316 DevSetColor(cc);
317 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
318 DevSetColor(fg);
319 DevText(ctmp, editX + (int)(editC-editBuf)*FontWidth, editY);
320 for (;;) {
321 k = DevGetchar(NULL);
322 if ((char) k == '\r') break;
323 switch (k) {
324
325 case 333: /* right arrow */
326 if (editC >= end) continue;
327 ctmp[0] = *editC;
328 DevSetColor(bg);
329 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
330 DevSetColor(fg);
331 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
332 editC++;
333 ctmp[0] = *editC;
334 DevSetColor(cc);
335 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
336 DevSetColor(fg);
337 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
338 continue;
339
340 case 331: /* left arrow */
341 if (editC <= editBuf) continue;
342 ctmp[0] = *editC;
343 DevSetColor(bg);
344 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
345 DevSetColor(fg);
346 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
347 editC--;
348 ctmp[0] = *editC;
349 DevSetColor(cc);
350 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
351 DevSetColor(fg);
352 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
353 continue;
354
355 case '\b':
356 if (editC == editBuf) continue;
357 DevSetColor(bg);
358 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
359 editC--;
360 DevText(editC,editX + (int)(editC-editBuf)*FontWidth,editY);
361 DevSetColor(fg);
362 *editC = '\0';
363 strcat(editBuf,++editC);
364 DevText(editC,editX + (int)(editC-editBuf)*FontWidth,editY);
365 editC--;
366 if (end > editBuf) end--;
367 ctmp[0] = *editC;
368 DevSetColor(cc);
369 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
370 DevSetColor(fg);
371 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
372 continue;
373
374 case 339: /* DEL, in DOS */
375 case 127:
376 if (editC == end) continue;
377 DevSetColor(bg);
378 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
379 DevText(editC,editX + (int)(editC-editBuf)*FontWidth,editY);
380 DevSetColor(fg);
381 *editC = '\0';
382 strcat(editBuf,++editC);
383 DevText(editC,editX + (int)(editC-editBuf)*FontWidth,editY);
384 editC--;
385 if (end > editBuf) end--;
386 ctmp[0] = *editC;
387 DevSetColor(cc);
388 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
389 DevSetColor(fg);
390 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
391 continue;
392
393 case '\025': /* ^U */
394 case '\030': /* ^X */
395 case '\033': /* ESC */
396 DevSetColor(bg);
397 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
398 DevText(editBuf,editX,editY);
399 editC = end = editBuf;
400 *editC = '\0';
401 if ((char) k == '\033') {
402 return (NULL);
403 }
404 DevSetColor(cc);
405 textcursor(editX,editY);
406 DevSetColor(fg);
407 continue;
408 default:
409 if (k > 255) continue;
410 if (((char) k < ' ') || ((char) k > '~')) continue;
411 DevSetColor(bg);
412 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
413 DevText(editC,editX + (int)(editC-editBuf)*FontWidth,editY);
414 strcpy(tbuf,editC);
415 *editC = (char) k;
416 sprintf(++editC,tbuf);
417 ctmp[0] = *editC;
418 DevSetColor(fg);
419 DevText(editC-1,
420 editX+(int)(editC-1-editBuf)*FontWidth,editY);
421 DevSetColor(cc);
422 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
423 DevSetColor(fg);
424 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
425 end++;
426 *(end+1) = '\0';
427
428 }
429 }
430 DevSetColor(bg);
431 textcursor(editX+(int)(editC-editBuf)*FontWidth,editY);
432 DevSetColor(fg);
433 ctmp[0] = *editC;
434 DevText(ctmp,editX + (int)(editC-editBuf)*FontWidth,editY);
435 return (editBuf);
436 }
437 #endif
438
439 typedef RETSIGTYPE (*SigType)();
440
441 struct sSCEDitf *ft_sced = &sc_itf;
442
443 /* at last! */
444 int
main(ac,av)445 main(ac, av)
446
447 int ac;
448 char **av;
449 {
450 char **tv;
451 int tc, i;
452 int err;
453 bool gotone = false;
454 char *p;
455 char *cmd_line_term = 0, term_1stch;
456
457 #ifdef BATCH
458 bool st = false;
459 #else
460
461 #ifdef HAVE_GETPWUID
462 struct passwd *pw;
463 #endif
464 char buf[BSIZE_SP];
465 bool rflag = false, ciprefix();
466 bool istty = true, iflag = false, qflag = false;
467 bool readinit = true;
468 bool gdata = true;
469 bool read_err = false;
470 FILE *fp;
471 extern char *kw_mplot_cur;
472
473 #endif
474
475 /* MFB tends to jump to 0 on errors. This tends to catch it. */
476 if (started) {
477 fprintf(cp_err, "main: Internal Error: jump to zero\n");
478 fatal();
479 }
480 started = true;
481
482 ivars( );
483
484 cp_in = stdin;
485 cp_out = stdout;
486 cp_err = stderr;
487
488 #ifdef BATCH
489
490 cp_curin = stdin;
491 cp_curout = stdout;
492 cp_curerr = stderr;
493
494 #else
495
496 #ifdef MALLOCTRACE
497 mallocTraceInit("malloc.out");
498 #endif
499 #ifdef HAVE_ISATTY
500 istty = (bool) isatty(fileno(stdin));
501 #endif
502
503 rusage_init();
504 #endif
505
506 err = SIMinit(&nutmeginfo,&ft_sim);
507 if(err != OK) {
508 ft_sperror(err,"SIMinit");
509 return (EXIT_BAD);
510 }
511 cp_program = ft_sim->simulator;
512
513 #ifdef HAVE_GETPID
514 srandom(getpid());
515 #else
516 srandom(17);
517 #endif
518
519 tv = av;
520 tc = ac;
521
522 /* Pass 1 -- get options. */
523 while (--tc > 0) {
524 tv++;
525 if (**tv == Spice_OptChar) { /* Option argument. */
526 switch ((*tv)[1]) {
527
528 #ifndef BATCH
529 case '\0': /* No raw file. */
530 gdata = false;
531 break;
532
533 case 'b': /* Batch mode. */
534 case 'B':
535 ft_batchmode = true;
536 break;
537
538 case 's': /* Server mode. */
539 case 'S':
540 ft_servermode = true;
541 break;
542
543 case 'i': /* Interactive mode. */
544 case 'I':
545 iflag = true;
546 break;
547
548 case 'q': /* No command completion. */
549 case 'Q':
550 qflag = true;
551 break;
552
553 case 'n': /* Don't read .spiceinit. */
554 case 'N':
555 readinit = false;
556 break;
557
558 case 't': /* Terminal type. */
559 case 'T':
560 if (tc > 1) {
561 tc--;
562 tv++;
563 cmd_line_term = *tv;
564 term_1stch = **tv;
565 **tv = Spice_OptChar;
566 }
567 else {
568 fprintf(cp_err, usage, cp_program);
569 return (EXIT_BAD);
570 }
571 break;
572 case 'd': /* X display */
573 case 'D':
574 if (tc > 1) {
575 tc--;
576 tv++;
577 cp_display = copy(*tv);
578 **tv = Spice_OptChar;
579 }
580 else {
581 fprintf(cp_err, usage, cp_program);
582 return (EXIT_BAD);
583 }
584 break;
585 case 'r': /* The rawfile. */
586 case 'R':
587 if (tc > 1) {
588 tc--;
589 tv++;
590 ft_rawfile = copy(*tv);
591 cp_vset("rawfile", VT_STRING, *tv);
592 **tv = Spice_OptChar;
593 }
594 rflag = true;
595 break;
596
597 #else /* if BATCH */
598 case 'r': /* The rawfile. */
599 case 'R':
600 if (tc > 1) {
601 tc--;
602 tv++;
603 ft_rawfile = copy(*tv);
604 **tv = Spice_OptChar;
605 }
606 else {
607 fprintf(cp_err, usage, cp_program);
608 return (EXIT_BAD);
609 }
610 #endif
611
612 case 'o': /* Output file. */
613 case 'O':
614 if (tc > 1) {
615 tc--;
616 tv++;
617 if (!(freopen(*tv, "w", stdout))) {
618 perror(*tv);
619 return (EXIT_BAD);
620 }
621 **tv = Spice_OptChar;
622 }
623 else {
624 fprintf(cp_err, usage, av[0]);
625 return (EXIT_BAD);
626 }
627 break;
628
629 default:
630 fprintf(cp_err, "Error: bad option %s\n", *tv);
631 fprintf(cp_err, usage, cp_program);
632 return (EXIT_BAD);
633 }
634 }
635 }
636
637 if (!cp_display) {
638 cp_display = getenv("DISPLAY");
639 if (cp_display)
640 cp_display = copy(cp_display);
641 }
642
643 #ifdef SIMULATOR
644 if_getparam = spif_getparam;
645 #else
646 if_getparam = nutif_getparam;
647 #endif
648
649 #ifndef BATCH
650
651 if ((!iflag && !istty) || ft_servermode)
652 ft_batchmode = true;
653 if ((iflag && !istty) || qflag)
654 cp_nocc = true;
655 if (!istty || ft_batchmode)
656 out_moremode = false;
657 if (ft_servermode)
658 ft_rawfile = "";
659 cp_interactive = false;
660
661 #ifdef HAVE_SIGNAL
662 /* Set up signal handling */
663 if (!ft_batchmode) {
664 (void) signal(SIGINT, (SigType)ft_sigintr);
665 (void) signal(SIGFPE, (SigType)sigfloat);
666 #ifdef SIGTSTP
667 (void) signal(SIGTSTP, (SigType)sigstop);
668 #endif
669 }
670 /* Set up signal handling for fatal errors. */
671 (void) signal(SIGILL, (SigType)sigill);
672
673 #ifdef SIGBUS
674 (void) signal(SIGBUS, (SigType)sigbus);
675 #endif
676 #ifdef SIGSEGV
677 (void) signal(SIGSEGV, (SigType)sigsegv);
678 #endif
679 #ifdef SIGSYS
680 (void) signal(SIGSYS, (SigType)sig_sys);
681 #endif
682 #endif
683
684 /* To catch interrupts during .spiceinit... */
685 if (setjmp(jbuf) == 1) {
686 read_err = true;
687 goto bot;
688 }
689
690 /* init graphics, so we can setrdb in init file */
691 if (!ft_batchmode)
692 DevInit( );
693
694 /* Have to initialize cp now. */
695 ft_cpinit(); /* this sources the spinit file */
696
697 if (!ft_servermode && readinit) {
698 #ifdef HAVE_GETPWUID
699 /* Try to source either .spiceinit or ~/.spiceinit. */
700 if (access(".spiceinit", 0) == 0)
701 inp_source(".spiceinit");
702 else {
703 pw = getpwuid(getuid());
704 (void) strcpy(buf, pw->pw_dir);
705 (void) strcat(buf, "/.spiceinit");
706 if (access(buf, 0) == 0)
707 inp_source(buf);
708 }
709 #else
710 /* Try to source the file "spice.rc" in the current directory. */
711 if ((fp = fopen("spice.rc", "r")) != NULL) {
712 (void) fclose(fp);
713 inp_source("spice.rc");
714 }
715 #endif
716 }
717
718 bot:
719
720 if (cmd_line_term) {
721 *cmd_line_term = term_1stch;
722 /* XXX oh, gross!
723 * First char got squashed scanning the
724 * command line
725 */
726 cp_vset("term", VT_STRING, cmd_line_term);
727 *cmd_line_term = Spice_OptChar;
728 }
729
730 if (!ft_batchmode) {
731 com_version(NULL);
732 if (News_File && *News_File) {
733 fp = fopen(cp_tildexpand(News_File), "r");
734 if (fp) {
735 while (fgets(buf, BSIZE_SP, fp))
736 fputs(buf, stdout);
737 (void) fclose(fp);
738 }
739 }
740 }
741 if (read_err)
742 fprintf(cp_err, "Warning: error executing init file.\n");
743
744 /* Pass 2 -- get the filenames. If we are spice, then this means
745 * build a circuit for this file. If this is in server mode, don't
746 * process any of these args.
747 */
748
749 if (setjmp(jbuf) == 1) {
750 goto evl;
751 }
752
753 #endif /* not BATCH */
754
755 if (!ft_servermode && !ft_nutmeg) {
756 FILE *file = NULL, *tp = NULL;
757 char *tempfile = NULL, buf[BSIZE_SP], *smktemp();
758
759 for (tv = av + 1, i = 0; *tv; tv++)
760 if (**tv != Spice_OptChar)
761 i++;
762 if (i == 1) {
763 for (tv = av + 1, i = 0; *tv; tv++)
764 if (**tv != Spice_OptChar)
765 break;
766 if (!(file = fopen(*tv, "r"))) {
767 perror(*tv);
768 i = 0;
769 }
770 }
771 else if (i) {
772 tempfile = smktemp("sp");
773 if (!(file = fopen(tempfile, "w+"))) {
774 perror(tempfile);
775 return (EXIT_BAD);
776 }
777 for (tv = av + 1, i = 0; *tv; tv++)
778 if (**tv != Spice_OptChar) {
779 if (!(tp = fopen(*tv, "r"))) {
780 perror(*tv);
781 continue;
782 }
783 while ((i = fread(buf, 1, BSIZE_SP, tp)) > 0)
784 (void) fwrite(buf, i, 1, file);
785 (void) fclose(tp);
786 }
787 (void) fseek(file, (long) 0, 0);
788 }
789 if (file) {
790 inp_spsource(file, false, tempfile ? (char *) NULL : *tv);
791 (void) fclose(file);
792 gotone = true;
793 if (tempfile)
794 (void) unlink(tempfile);
795 }
796 }
797
798 if (!gotone && ft_batchmode && !ft_nutmeg)
799 inp_spsource(stdin, false, (char *) NULL);
800
801 #ifndef BATCH
802 if (ft_nutmeg && gdata) {
803 /* Read in the rawfiles */
804 for (av++; *av; av++)
805 if (**av != Spice_OptChar) {
806 ft_loadfile(*av);
807 gotone = true;
808 }
809 if (!gotone)
810 ft_loadfile(ft_rawfile);
811 }
812
813 evl:
814 if (ft_batchmode) {
815 /* If we get back here in batch mode then something is
816 * wrong, so exit.
817 */
818 bool st = false;
819
820 (void) setjmp(jbuf);
821
822 if (st == true)
823 return (EXIT_BAD);
824 st = true;
825
826 if (ft_curckt == NULL) {
827 char p;
828 if (cp_getvar(kw_mplot_cur,VT_STRING,&p))
829 /* margin analysis performed */
830 return (EXIT_NORMAL);
831 fprintf(cp_err, "Error: no circuit loaded!\n");
832 return (EXIT_BAD);
833 }
834 else if (ft_curckt->ci_runonce)
835 /* already did it */
836 return (EXIT_NORMAL);
837
838 if (ft_servermode) {
839 ft_dorun(ft_rawfile);
840 return (EXIT_NORMAL);
841 }
842 /* If -r is specified, then we don't bother with the dot
843 * cards. Otherwise, we use wrd_run, but we are careful
844 * not to save too much.
845 */
846 cp_interactive = false;
847 if (rflag) {
848 ft_dotsaves();
849 ft_dorun(ft_rawfile);
850 ft_cktcoms(true);
851 }
852 else {
853 ft_savedotargs();
854 ft_dorun((char *) NULL);
855 ft_cktcoms(false);
856 }
857 }
858 else {
859 (void) setjmp(jbuf);
860 cp_interactive = true;
861 while (cp_evloop((char *) NULL) == 1) ;
862 }
863
864 #else /* if BATCH */
865
866 if (st == true)
867 return (EXIT_BAD);
868 st = true;
869 if (ft_curckt == NULL) {
870 char p;
871 if (cp_getvar(kw_mplot_cur,VT_STRING,&p))
872 /* margin analysis performed */
873 return (EXIT_NORMAL);
874 fprintf(cp_err, "Error: no circuit loaded!\n");
875 return (EXIT_BAD);
876 }
877 else if (ft_curckt->ci_runonce)
878 /* already did it */
879 return (EXIT_NORMAL);
880 #ifdef SPICE2
881 ft_savedotargs( );
882 ft_dorun(NULL);
883 ft_cktcoms(false);
884 #else
885 ft_dotsaves( );
886 ft_dorun(ft_rawfile);
887 ft_cktcoms(false);
888
889 fprintf(stderr,
890 "Note: \".plot\" or \".print\" lines ignored (rawfile only)\n");
891 #endif
892
893 #endif
894
895 return (EXIT_NORMAL);
896 }
897
898
899 static void
clear_previous()900 clear_previous()
901
902 {
903 /* for SCED, we don't save old circuits or plots */
904 #ifdef SIMULATOR
905 if_cktclear();
906 com_destroy((wordlist *)NULL);
907 #endif
908 }
909
910
911 /* allocate space for global constants in 'CONST.h' */
912
913 double CONSTroot2;
914 double CONSTvt0;
915 double CONSTKoverQ;
916 double CONSTe;
917 IFfrontEnd *SPfrontEnd = NULL;
918
919 int
SPIinit(frtEnd,description)920 SPIinit(frtEnd,description)
921
922 IFfrontEnd *frtEnd;
923 IFsimulator **description;
924 {
925
926 SPfrontEnd = frtEnd;
927 *description = &SIMinfo;
928 CONSTroot2 = sqrt(2.);
929 CONSTvt0 = CONSTboltz * (27 /* deg c */ + CONSTCtoK ) / CHARGE;
930 CONSTKoverQ = CONSTboltz / CHARGE;
931 CONSTe = exp((double)1.0);
932 return (OK);
933 }
934
935 /* XXX SIMinit and SPIinit ?? */
936
937 int
SIMinit(frontEnd,simulator)938 SIMinit(frontEnd,simulator)
939
940 IFfrontEnd *frontEnd;
941 IFsimulator **simulator;
942 {
943 return (SPIinit(frontEnd,simulator));
944 }
945
946 #ifdef BATCH
947 /*
948 * Incredibly Ugly
949 */
950
951 /* Now some misc junk that we need to fake */
952
953 bool cp_nocc = true;
954 bool cp_debug = false;
955 int cp_maxhistlength;
956 char cp_chars[128];
957
MFBHalt()958 MFBHalt( ) { }
959
960 #ifndef SPICE2
cp_tildexpand(s)961 /* ARGSUSED */ char *cp_tildexpand(s) char *s; { return (s); }
vec_fromplot(w,p)962 /* ARGSUSED */ struct dvec *vec_fromplot(w, p) char *w; struct plot *p;
963 { return (NULL); }
vec_new()964 void vec_new() {}
plot_new()965 void plot_new() {}
plot_setcur()966 void plot_setcur() {}
plot_alloc(name)967 /* ARGSUSED */ struct plot *plot_alloc(name) char *name; { return (NULL); }
968 struct plot *plot_cur = NULL;
plot_docoms(wl)969 /* ARGSUSED */ void plot_docoms(wl) wordlist *wl; {}
out_init()970 void out_init() {}
971 /* PC defines out_printf to printf since vsprintf doesn't exist */
out_printf(c)972 /* ARGSUSED */ /* VARARGS1 */ void out_printf(c) char *c; {}
out_send(s)973 /* ARGSUSED */ void out_send(s) char *s; {}
974 char out_pbuf[1];
vec_get(word)975 /* ARGSUSED */ struct dvec *vec_get(word) char *word; { return (NULL); }
976 #endif
977
cp_usrset(v,i)978 /* ARGSUSED */ int cp_usrset(v, i) struct variable *v; bool i; {return(US_OK);}
cp_pushcontrol()979 void cp_pushcontrol() {}
cp_popcontrol()980 void cp_popcontrol() {}
cp_addkword(class,word)981 /* ARGSUSED */ void cp_addkword(class, word) int class; char *word; {}
982 struct circ *ft_circuits = 0, *ft_curckt = 0;
cp_kwswitch(c,t)983 /* ARGSUSED */ char *cp_kwswitch(c, t) int c; char *t; { return (NULL); }
ft_bpcheck(r,i)984 /* ARGSUSED */ bool ft_bpcheck(r, i) struct plot *r; int i; { return (true); }
cp_ccon(b)985 /* ARGSUSED */ void cp_ccon(b) bool b; {}
986
987 int currentgraph = 0;
Input(p,q)988 /* ARGSUSED */ void Input(p, q) char *p, *q; {}
DevSwitch(i)989 /* ARGSUSED */ void DevSwitch(i) int i; {}
CopyGraph(i)990 /* ARGSUSED */ int *CopyGraph(i) int i; {}
DestroyGraph(i)991 /* ARGSUSED */ void DestroyGraph(i) int i; {}
NewViewport(i)992 /* ARGSUSED */ void NewViewport(i) int i; {}
993
cp_remkword()994 /* ARGSUSED */ void cp_remkword() { }
cp_resetcontrol()995 /* ARGSUSED */ void cp_resetcontrol() { }
996
gr_init()997 bool gr_init() {}
gr_redraw()998 void gr_redraw() {}
gr_iplot(pl)999 /* ARGSUSED */ void gr_iplot(pl) struct plot *pl; {}
gr_end_iplot(pl)1000 /* ARGSUSED */ void gr_end_iplot(pl) struct plot *pl; {}
gr_pmsg(text,more)1001 /* ARGSUSED */ void gr_pmsg(text, more) char *text; bool more; {}
gr_clean(intr)1002 /* ARGSUSED */ void gr_clean(intr) bool intr; {}
cp_evloop(string)1003 /* ARGSUSED */ int cp_evloop(string) char *string; { return (0); }
ft_graf()1004 void ft_graf() {}
ft_trquery()1005 void ft_trquery() {}
ft_newcirc(ckt)1006 /* ARGSUSED */ void ft_newcirc(ckt) struct circ *ckt; {}
cp_doquit()1007 void cp_doquit() { exit(0); }
cp_usrvars(v1,v2)1008 /* ARGSUSED */ void cp_usrvars(v1, v2) struct variable **v1, **v2; { return; }
cp_enqvar(word)1009 /* ARGSUSED */ struct variable * cp_enqvar(word) char *word; { return (NULL); }
cp_ccom(w,b,e)1010 /* ARGSUSED */ void cp_ccom(w, b, e) wordlist *w; char *b; bool e; { return; }
1011
1012 void
com_save(wl)1013 com_save(wl)
1014 wordlist *wl;
1015 {
1016 return;
1017 }
1018
1019 int
ft_getSaves(savesp)1020 ft_getSaves(savesp)
1021 char ***savesp;
1022 {
1023 return (0);
1024 }
1025
1026 /* This is from options.c */
1027 /* Extract the .option cards from the deck... */
1028
1029 struct line *
inp_getopts(deck)1030 inp_getopts(deck)
1031
1032 struct line *deck;
1033 {
1034 struct line *last = NULL, *opts = NULL, *dd, *next = NULL;
1035
1036 for (dd = deck->li_next; dd; dd = next) {
1037 next = dd->li_next;
1038 if (ciprefix(".opt", dd->li_line)) {
1039 inp_casefix(dd->li_line);
1040 if (last)
1041 last->li_next = dd->li_next;
1042 else
1043 deck->li_next = dd->li_next;
1044 dd->li_next = opts;
1045 opts = dd;
1046 }
1047 else
1048 last = dd;
1049 }
1050 return (opts);
1051 }
1052
1053 #ifndef SPICE2
1054
1055 static wordlist *gettoks();
1056
1057 /* This is from dotcards.c -- we don't want to include the whole file. */
1058 /* Extract all the .save cards */
1059
1060 void
ft_dotsaves()1061 ft_dotsaves()
1062
1063 {
1064 wordlist *com, *wl = NULL;
1065 char *s;
1066
1067 if (!ft_curckt) /* Shouldn't happen. */
1068 return;
1069
1070 for (com = ft_curckt->ci_commands; com; com = com->wl_next) {
1071 if (ciprefix(".save", com->wl_word)) {
1072 s = com->wl_word;
1073 (void) gettok(&s);
1074 wl = wl_append(wl, gettoks(s));
1075 }
1076 }
1077 /* wrd_saves = wl; */
1078
1079 com_save(wl);
1080 /* fprintf(stderr, "error, .save card code is broken\n"); */
1081 return;
1082 }
1083
1084 /* This is also from dotcards.c. We should probably include the file. */
1085 /* Stripped down version. */
1086
1087 /* Execute the .whatever cards found in the deck, after we are done running.
1088 * We'll be cheap and use cp_lexer to get the words... This should make us
1089 * spice-2 compatible. Is terse is true then there was a rawfile, so don't
1090 * print lots of junk.
1091 */
1092
1093 void
ft_cktcoms(terse)1094 ft_cktcoms(terse)
1095 bool terse;
1096
1097 {
1098 wordlist *coms, *command;
1099 char *plottype, *s;
1100 struct dvec *v;
1101 static wordlist twl = { "col", NULL, NULL } ;
1102 int i;
1103
1104 if (!ft_curckt)
1105 return;
1106 if (!ft_curckt->ci_commands)
1107 goto nocmds;
1108 coms = ft_curckt->ci_commands;
1109 cp_interactive = false;
1110
1111 nocmds:
1112 /* Circuit name */
1113 fprintf(cp_out, "Circuit: %s\nDate: %s\n\n", ft_curckt->ci_name,
1114 datestring());
1115 fprintf(cp_out, "\n");
1116
1117 /* Listing if necessary... */
1118 if (ft_listprint)
1119 inp_list(cp_out, ft_curckt->ci_deck, ft_curckt->ci_options,
1120 LS_DECK);
1121
1122 /* And finally the accounting info. */
1123 if (ft_acctprint) {
1124 static wordlist ww = { "everything", NULL, NULL } ;
1125 com_rusage(&ww);
1126 } else
1127 com_rusage((wordlist *) NULL);
1128
1129 (void) putc('\n', cp_out);
1130 return;
1131
1132 bad: fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n");
1133 return;
1134 }
1135
1136
1137 static wordlist *
gettoks(s)1138 gettoks(s)
1139
1140 char *s;
1141 {
1142 char *t, *r, buf[64];
1143 wordlist *wl = NULL, *end = NULL;
1144 bool iflag;
1145
1146 while (t = gettok(&s)) {
1147 if (*t == '(' /* ) */) {
1148 /* This is a (upper, lower) thing -- ignore. */
1149 continue;
1150 }
1151 else if (!index(t, '(' /*)*/ )) {
1152 if (end) {
1153 end->wl_next = alloc(struct wordlist);
1154 end->wl_next->wl_prev = end;
1155 end = end->wl_next;
1156 }
1157 else
1158 wl = end = alloc(struct wordlist);
1159 end->wl_word = copy(t);
1160 }
1161 else if (!index(t, ',')) {
1162 iflag = ((*t == 'i') || (*t == 'I')) ? true : false;
1163 while (*t != '(' /*)*/)
1164 t++;
1165 t++;
1166 for (r = t; *r && *r != /*(*/ ')'; r++)
1167 ;
1168 *r = '\0';
1169 if (end) {
1170 end->wl_next = alloc(struct wordlist);
1171 end->wl_next->wl_prev = end;
1172 end = end->wl_next;
1173 }
1174 else
1175 wl = end = alloc(struct wordlist);
1176 if (iflag) {
1177 (void) sprintf(buf, "%s#branch", t);
1178 t = buf;
1179 }
1180 end->wl_word = copy(t);
1181 }
1182 else {
1183 /* The painful case... */
1184 while (*t != '(' /*)*/)
1185 t++;
1186 t++;
1187 for (r = t; *r && *r != ','; r++)
1188 ;
1189 *r = '\0';
1190 if (end) {
1191 end->wl_next = alloc(struct wordlist);
1192 end->wl_next->wl_prev = end;
1193 end = end->wl_next;
1194 }
1195 else
1196 wl = end = alloc(struct wordlist);
1197 end->wl_word = copy(t);
1198 t = r + 1;
1199 for (r = t; *r && *r != /*(*/ ')'; r++)
1200 ;
1201 *r = '\0';
1202 if (end) {
1203 end->wl_next = alloc(struct wordlist);
1204 end->wl_next->wl_prev = end;
1205 end = end->wl_next;
1206 }
1207 else
1208 wl = end = alloc(struct wordlist);
1209 end->wl_word = copy(t);
1210 }
1211 }
1212 return (wl);
1213 }
1214
1215 #endif
1216
1217 #endif
1218