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