1 /***************************************************************************
2 SCED - Schematic Capture Editor
3 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
4 Copyright 1990 Regents of the University of California. All rights reserved.
5 Authors: 1981 Giles C. Billingsley (parts of KIC layout editor)
6 1992 Stephen R. Whiteley
7 ****************************************************************************/
8
9 /*
10 * JSPICE3 interface to SCED.
11 */
12
13 #include "spice.h"
14 #include "sced.h"
15 #include "scedmacs.h"
16 #include "scedio.h"
17 #include <setjmp.h>
18 #include <signal.h>
19
20
21 /* imports from spice */
22 extern int ft_nutmeg;
23 extern int ft_intrpt;
24 #ifdef __STDC__
25 extern int cp_getvar(char*,int,char*);
26 extern wordlist *cp_lexer(char*);
27 extern void wl_free(wordlist*);
28 extern int cp_evloop(char*);
29 extern void cp_pushcontrol(void);
30 extern void cp_popcontrol(void);
31 extern wordlist *GetAnalysisFromDeck(void);
32 #else
33 extern int cp_getvar();
34 extern wordlist *cp_lexer();
35 extern void wl_free();
36 extern int cp_evloop();
37 extern void cp_pushcontrol();
38 extern void cp_popcontrol();
39 extern wordlist *GetAnalysisFromDeck();
40 #endif
41
42
43 /***********************************************************************
44 *
45 * Menu definition package.
46 *
47 ***********************************************************************/
48
49 MENU *BasicMenu;
50 MENU *DeviceMenu;
51 MENU AmbiguityMenu[DefMenuSize];
52
53 char *Menu0;
54 char *Menu90;
55 char *Menu180;
56 char *Menu270;
57 char *MenuMINSB;
58 char *MenuMINSG;
59 char *MenuMINSR;
60 char *MenuPLUSB;
61 char *MenuPLUSG;
62 char *MenuPLUSR;
63 char *MenuABORT;
64 char *MenuAREA;
65 char *MenuARRAY;
66 char *MenuBGRND;
67 char *MenuBREAK;
68 char *MenuCOLOR;
69 char *MenuCOPY;
70 char *MenuCRSYM;
71 char *MenuDELET;
72 char *MenuDESEL;
73 char *MenuDIR;
74 char *MenuDOTS;
75 char *MenuEDIT;
76 char *MenuEXPND;
77 char *MenuFLATN;
78 char *MenuGRAF;
79 char *MenuGRID;
80 char *MenuHCOPY;
81 char *MenuHELP;
82 char *MenuHLITE;
83 char *MenuIPLOT;
84 char *MenuLABEL;
85 char *MenuLAST;
86 char *MenuMENU;
87 char *MenuMORE;
88 char *MenuMOVE;
89 char *MenuMUTUL;
90 char *MenuMX;
91 char *MenuMY;
92 char *MenuNEWSC;
93 char *MenuPAN;
94 char *MenuPLACE;
95 char *MenuPOP;
96 char *MenuPRMPT;
97 char *MenuPRPTY;
98 char *MenuPUSH;
99 char *MenuRDRAW;
100 char *MenuRGB;
101 char *MenuRUN;
102 char *MenuSAVE;
103 char *MenuSELEC;
104 char *MenuSHOW;
105 char *MenuSTRCH;
106 char *MenuSUBCT;
107 char *MenuTERMS;
108 char *MenuUNDO;
109 char *MenuUPDAT;
110 char *MenuVIEW;
111 char *MenuWINDO;
112 char *MenuWIRES;
113 char *MenuZOOM;
114 static char *MenuSpace;
115
116
117 void
InitMenus()118 InitMenus()
119
120 {
121
122 Menu0 = "0 ";
123 Menu90 = "90 ";
124 Menu180 = "180 ";
125 Menu270 = "270 ";
126 MenuMINSB = "-b ";
127 MenuMINSG = "-g ";
128 MenuMINSR = "-r ";
129 MenuPLUSB = "+b ";
130 MenuPLUSG = "+g ";
131 MenuPLUSR = "+r ";
132 MenuABORT = "quit ";
133 MenuAREA = "area ";
134 MenuARRAY = "array";
135 MenuBGRND = "bgrnd";
136 MenuBREAK = "break";
137 MenuCOLOR = "color";
138 MenuCOPY = "copy ";
139 MenuCRSYM = "crsym";
140 MenuDELET = "delet";
141 MenuDESEL = "desel";
142 MenuDIR = "dir ";
143 MenuDOTS = "dots ";
144 MenuEDIT = "edit ";
145 MenuEXPND = "expnd";
146 MenuFLATN = "flatn";
147 MenuGRAF = "graf ";
148 MenuGRID = "grid ";
149 MenuHCOPY = "hcopy";
150 MenuHELP = "help";
151 MenuHLITE = "hlite";
152 MenuIPLOT = "iplot";
153 MenuLABEL = "label";
154 MenuLAST = "last ";
155 MenuMENU = "menu ";
156 MenuMORE = "more ";
157 MenuMOVE = "move ";
158 MenuMUTUL = "mutul";
159 MenuMX = "mx ";
160 MenuMY = "my ";
161 MenuNEWSC = "newsc";
162 MenuPAN = "pan ";
163 MenuPLACE = "place";
164 MenuPOP = "pop ";
165 MenuPRMPT = "prmpt";
166 MenuPRPTY = "prpty";
167 MenuPUSH = "push ";
168 MenuRDRAW = "rdraw";
169 MenuRGB = "rgb ";
170 MenuRUN = "run ";
171 MenuSAVE = "save ";
172 MenuSELEC = "selec";
173 MenuSTRCH = "strch";
174 MenuSUBCT = "subct";
175 MenuTERMS = "terms";
176 MenuUNDO = "undo ";
177 MenuUPDAT = "updat";
178 MenuVIEW = "view ";
179 MenuWINDO = "windo";
180 MenuWIRES = "wires";
181 MenuZOOM = "zoom ";
182 MenuSpace = " ";
183
184 InitBasicMenu();
185 InitDeviceMenu();
186 }
187
188
189 void
InitBasicMenu()190 InitBasicMenu()
191
192 {
193 int i = 0, NumBasicMenu = 53;
194 int nrows = MenuViewport.kaY;
195
196 if (BasicMenu == NULL)
197 BasicMenu = (MENU *) malloc(NumBasicMenu*sizeof(MENU));
198 if (BasicMenu == NULL) MallocFailed();
199 memset(BasicMenu,0,NumBasicMenu*sizeof(MENU));
200
201 BasicMenu[i++].mEntry = MenuHELP;
202 BasicMenu[i++].mEntry = MenuCOLOR;
203 BasicMenu[i++].mEntry = MenuEDIT;
204 BasicMenu[i++].mEntry = MenuDIR;
205 BasicMenu[i++].mEntry = MenuSAVE;
206
207 BasicMenu[i++].mEntry = MenuABORT;
208 BasicMenu[i++].mEntry = MenuSpace;
209 BasicMenu[i++].mEntry = MenuPAN;
210 BasicMenu[i++].mEntry = MenuZOOM;
211 BasicMenu[i++].mEntry = MenuWINDO;
212
213 BasicMenu[i++].mEntry = MenuVIEW;
214 BasicMenu[i++].mEntry = MenuLAST;
215 BasicMenu[i++].mEntry = MenuEXPND;
216 BasicMenu[i++].mEntry = MenuGRID;
217 BasicMenu[i++].mEntry = MenuSpace;
218
219 BasicMenu[i++].mEntry = MenuAREA;
220 BasicMenu[i++].mEntry = MenuSELEC;
221 BasicMenu[i++].mEntry = MenuDESEL;
222 BasicMenu[i++].mEntry = MenuMOVE;
223 BasicMenu[i++].mEntry = MenuCOPY;
224
225 BasicMenu[i++].mEntry = MenuPUSH;
226 BasicMenu[i++].mEntry = MenuPOP;
227 if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
228 BasicMenu[i++].mEntry = MenuSTRCH;
229 BasicMenu[i++].mEntry = MenuBREAK;
230
231 BasicMenu[i++].mEntry = MenuCRSYM;
232 BasicMenu[i++].mEntry = MenuFLATN;
233 BasicMenu[i++].mEntry = MenuDELET;
234 if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
235 BasicMenu[i++].mEntry = MenuUNDO;
236
237 BasicMenu[i++].mEntry = MenuMX;
238 BasicMenu[i++].mEntry = MenuMY;
239 BasicMenu[i++].mEntry = Menu0;
240 if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
241 BasicMenu[i++].mEntry = MenuWIRES;
242
243 BasicMenu[i++].mEntry = MenuLABEL;
244 BasicMenu[i++].mEntry = MenuDOTS;
245 if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
246 BasicMenu[i++].mEntry = MenuTERMS;
247 BasicMenu[i++].mEntry = MenuSUBCT;
248
249 BasicMenu[i++].mEntry = MenuMUTUL;
250 BasicMenu[i++].mEntry = MenuPRPTY;
251 if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
252 BasicMenu[i++].mEntry = MenuRUN;
253 if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
254
255 BasicMenu[i++].mEntry = MenuGRAF;
256 BasicMenu[i++].mEntry = MenuIPLOT;
257 BasicMenu[i++].mEntry = MenuHCOPY;
258 if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
259 BasicMenu[i++].mEntry = MenuNEWSC;
260
261 BasicMenu[i++].mEntry = MenuSpace;
262 BasicMenu[i++].mEntry = NULL;
263 }
264
265
266
267 /***********************************************************************
268 *
269 * Top level entry point and dispatch code.
270 *
271 ***********************************************************************/
272
273 /* set if circuit sourced, so we don't do it again in spice */
274 static int SourceDone;
275 static enum Active SCEDisActive;
276
277 static jmp_buf errjbuf;
278
279 /* from spice */
280 extern FILE *cp_err;
281
282 #ifdef __STDC__
283 static int sced_main(void);
284 static void do_update(void);
285 static RETSIGTYPE sced_interrupt();
286 static void fix_spice_deck(struct line*);
287 #else
288 static int sced_main();
289 static void do_update();
290 static RETSIGTYPE sced_interrupt();
291 static void fix_spice_deck();
292 #endif
293
294
295 int
sced(nameptr)296 sced(nameptr)
297
298 /* main routine, called from com_sced in input.c
299 * return values:
300 * -1 "fatal" error, such as malloc failure
301 * 0 ok, circuit sourced
302 * 1 ok, circuit not sourced
303 * 2 user quit without saving file
304 * 3 bad file or file name
305 */
306 char **nameptr;
307 {
308 FILE *fp;
309 char *c, *name;
310 int i;
311 GRAPH *graph;
312 RETSIGTYPE (*sc_intr)();
313 RETSIGTYPE (*sc_float)();
314
315 if (SCEDisActive) {
316 ShowPromptAndWait("SCED is already running!");
317 return (-1);
318 }
319 name = *nameptr;
320 SourceDone = False;
321 SetPathFromSpice();
322 if (name && *name) {
323
324 fp = POpen(name,"r",(char **)NULL);
325 if (fp) {
326 if (!IsSymFile(fp)) return (3);
327 fclose(fp);
328 }
329 }
330 else
331 return (3);
332
333 graph = (GRAPH*)Init(); /* push graph context on success */
334 if (graph == NULL)
335 return (-1);
336
337 sc_intr = signal(SIGINT,SIG_IGN);
338 sc_float = signal(SIGFPE,SIG_IGN);
339
340 /* clear out iplots */
341 {wordlist wl; wl.wl_next = NULL; wl.wl_word = "iplot";
342 (*ft_sced->sc_clriplot)(&wl);}
343
344 if (!strcmp(Parameters.kpCellName,name) && Parameters.kpCellDesc) {
345 if (Not CDClose(Parameters.kpCellDesc)) MallocFailed();
346 Parameters.kpCellDesc = NULL;
347 }
348 else
349 strcpy(Parameters.kpCellName,name);
350 LibraryOpen(DeviceLibrary);
351 ModelLibraryOpen(ModelLibrary);
352 if (BasicMenu == NULL)
353 InitMenus();
354 if (setjmp(errjbuf) != 1) {
355 SCEDisActive = SCED_active;
356 i = sced_main();
357 DevHalt();
358 PopGraphContext();
359 DestroyGraph(graph->graphid);
360 signal(SIGINT,sc_intr);
361 signal(SIGFPE,sc_float);
362 *nameptr = Parameters.kpCellName;
363 SCEDisActive = SCED_inactive;
364 return (i);
365 }
366 else {
367 ClearContext();
368 PopGraphContext();
369 DestroyGraph(graph->graphid);
370 signal(SIGINT,sc_intr);
371 signal(SIGFPE,sc_float);
372 SCEDisActive = SCED_inactive;
373 return (-1); /* malloc failed */
374 }
375 }
376
377
378 static int
sced_main()379 sced_main()
380
381 {
382 int i, LookedAhead = False;
383 char *TypeIn;
384
385 InitVLT();
386 Basic(&LookedAhead);
387 Edit(True,True,False);
388 loop {
389 InitSignals();
390 if (Not LookedAhead)
391 Point();
392 else
393 LookedAhead = False;
394 if (Parameters.kpCellName[0] == EOS) {
395 /*
396 * The CD package doesn't check the integrity of symbol
397 * descriptors and now Parameters.kpCellDesc == NULL.
398 * Except for a few commands, each command invokes the
399 * CD package. If such a command is invoked now, the
400 * CD package will crash and thus SCED will. So, force user
401 * to select a cell to edit before invoking any such command.
402 */
403 if (Not (Matching(MenuEDIT) Or
404 Matching(MenuDIR) Or Matching(MenuABORT))) {
405 ShowPrompt("You haven't selected a cell to edit.");
406 continue;
407 }
408 }
409 if (SafeCmds(&LookedAhead)) continue;
410
411 if (Matching(MenuABORT)) {
412 i = CheckSaved();
413 if (i == -1) continue;
414 ClearContext();
415 if (i == 0) {
416 if (SourceDone) return (0);
417 return (1);
418 }
419 return (2);
420 }
421
422 if (Matching(MenuAREA)) { Area(&LookedAhead); continue; }
423 if (Matching(MenuBREAK)) { Break(&LookedAhead); continue; }
424 if (Matching(MenuCOPY)) { Copy(&LookedAhead); continue; }
425 if (Matching(MenuCRSYM)) { NewSymbol(); continue; }
426 if (Matching(MenuDELET)) { Del(&LookedAhead); continue; }
427 if (Matching(MenuDESEL)) { Desel(); continue; }
428 if (Matching(MenuDOTS)) { Dots(&LookedAhead); continue; }
429 if (Matching(MenuEDIT)) { SourceDone = False;
430 Edit(False,True,False); continue; }
431 if (Matching(MenuFLATN)) { Flatten(&LookedAhead); continue; }
432 if (Matching(MenuGRAF)) { ShowOutput(&LookedAhead); continue; }
433 if (Matching(MenuHELP)) { SCEDhelp(); continue; }
434 if (Matching(MenuLABEL)) { Label(&LookedAhead); continue; }
435 if (Matching(MenuMOVE)) { Move(&LookedAhead); continue; }
436 if (Matching(MenuMUTUL)) { ShowMutual(&LookedAhead); continue; }
437 if (Matching(MenuNEWSC)) { NewSubckt(); continue; }
438 if (Matching(MenuPLACE)) { Place(&LookedAhead); continue; }
439 if (Matching(MenuPOP)) { Pop(); continue; }
440 if (Matching(MenuPRPTY)) { ShowProperties(&LookedAhead); continue; }
441 if (Matching(MenuPUSH)) { Push(&LookedAhead); continue; }
442 if (Matching(MenuRUN)) { RunSpice(); continue; }
443 if (Matching(MenuSAVE)) { SourceDone = False;
444 WriteCell(); continue; }
445 if (Matching(MenuSELEC)) { Sel(&LookedAhead); continue; }
446 if (Matching(MenuSTRCH)) { StretchPath(&LookedAhead); continue; }
447 if (Matching(MenuSUBCT)) { Subcircuit(&LookedAhead); continue; }
448 if (Matching(MenuUNDO)) { Undo(); continue; }
449 if (Matching(MenuWIRES)) { Wires(&LookedAhead); continue; }
450 }
451 }
452
453
454 int
SafeCmds(LookedAhead)455 SafeCmds(LookedAhead)
456
457 int *LookedAhead;
458 {
459
460 if (Matching(Menu0)) { Rotat0(); return (True); }
461 if (Matching(Menu90)) { Rotat90(); return (True); }
462 if (Matching(Menu180)) { Rotat180(); return (True); }
463 if (Matching(Menu270)) { Rotat270(); return (True); }
464 if (Matching(MenuBGRND)) { Bgrnd(LookedAhead); return (True); }
465 if (Matching(MenuCOLOR)) { Color(LookedAhead); return (True); }
466 if (Matching(MenuDIR)) { Dir(); return (True); }
467 if (Matching(MenuEXPND)) { Expand(); return (True); }
468 if (Matching(MenuGRID)) { SetGrid(LookedAhead); return (True); }
469 if (Matching(MenuHCOPY)) { Hcopy(); return (True); }
470 if (Matching(MenuHLITE)) { Hlite(LookedAhead); return (True); }
471 if (Matching(MenuIPLOT)) { DoIplot(); return (True); }
472 if (Matching(MenuLAST)) { LastView(); return (True); }
473 if (Matching(MenuMENU)) { MenuParams(LookedAhead); return (True); }
474 if (Matching(MenuMINSB)) { AlterColor('b','-'); return (True); }
475 if (Matching(MenuMINSG)) { AlterColor('g','-'); return (True); }
476 if (Matching(MenuMINSR)) { AlterColor('r','-'); return (True); }
477 if (Matching(MenuMORE)) { MenuMore(LookedAhead); return (True); }
478 if (Matching(MenuMX)) { MX(); return (True); }
479 if (Matching(MenuMY)) { MY(); return (True); }
480 if (Matching(MenuPAN)) { Pan(LookedAhead); return (True); }
481 if (Matching(MenuPLUSB)) { AlterColor('b','+'); return (True); }
482 if (Matching(MenuPLUSG)) { AlterColor('g','+'); return (True); }
483 if (Matching(MenuPLUSR)) { AlterColor('r','+'); return (True); }
484 if (Matching(MenuPRMPT)) { MenuPrompt(LookedAhead); return (True); }
485 if (Matching(MenuRDRAW)) { Rdraw(); return (True); }
486 if (Matching(MenuRGB)) { RGB(); return (True); }
487 if (Matching(MenuTERMS)) { ShowTerminals(); return (True); }
488 if (Matching(MenuUPDAT)) { do_update(); return (True); }
489 if (Matching(MenuVIEW)) { ShowFull(); return (True); }
490 if (Matching(MenuWINDO)) { Windo(LookedAhead); return (True); }
491 if (Matching(MenuZOOM)) { Zoom(LookedAhead); return (True); }
492
493 return (False);
494 }
495
496 static char *PathFromFile;
497
498 static void
do_update()499 do_update()
500
501 /* update the init file */
502 {
503 /* set path to what was in file for stand-alone sced */
504 PSetPath(PathFromFile);
505 UpdateSCED();
506 SetPathFromSpice();
507 }
508
509
510
511 /***********************************************************************
512 *
513 * Routines for running spice analysis.
514 *
515 ***********************************************************************/
516
517
518 void
RunSpice()519 RunSpice()
520
521 {
522 char *TypeIn;
523 wordlist *wl;
524 struct line *deck;
525 static char Rcmd[64];
526 RETSIGTYPE (*intrpt)();
527
528 if (Parameters.kpCellDesc != Parameters.kpTopDesc) {
529 ShowPrompt("Pop to top level first.");
530 return;
531 }
532 MenuSelect(MenuRUN);
533
534
535 if ((*ft_sced->sc_inprogress)()) {
536 ShowPrompt("Resume run in progress? [y] ");
537 if ((TypeIn = FBEdit(NULL)) == NULL) {
538 MenuDeselect(MenuRUN);
539 ErasePrompt();
540 return;
541 }
542 if (*TypeIn != 'n' && *TypeIn != 'N') {
543 if (IplotStatusChanged) {
544 ClearIplot();
545 SetIplot();
546 }
547 intrpt = signal(SIGINT,sced_interrupt);
548 (*ft_sced->sc_resume)(NULL);
549 (void)signal(SIGINT,intrpt);
550 if (!dispdev->windows && !dispdev->hardcopy)
551 if ((*ft_sced->sc_isiplot)())
552 RedisplaySCED(currentgraph);
553 (void)CheckError();
554 if (!(*ft_sced->sc_inprogress)()) {
555 ShowPrompt("Analysis complete.");
556 ClearIplot();
557 }
558 MenuDeselect(MenuRUN);
559 return;
560 }
561
562 }
563
564 ClearIplot();
565 deck = MakeSpiceDeck();
566 fix_spice_deck(deck);
567 if (SourceDone)
568 (*ft_sced->sc_cktclear)();
569 (*ft_sced->sc_source)(deck,False,Parameters.kpCellName);
570 (void)CheckError();
571 SourceDone = True;
572
573 wl = GetAnalysisFromDeck();
574 if (wl == NULL) {
575 ShowPrompt("Enter analysis command : ");
576 if ((TypeIn = FBEdit(Rcmd)) != NULL) {
577 wl = cp_lexer(TypeIn);
578 strncpy(Rcmd,TypeIn,64);
579 Rcmd[63] = '\0';
580 }
581 else
582 ErasePrompt();
583 }
584 if (wl) {
585 if (wl->wl_word && *wl->wl_word) {
586 ShowPrompt("Performing analysis, please wait.");
587 SetIplot();
588 intrpt = signal(SIGINT,sced_interrupt);
589 (*ft_sced->sc_dosim)(wl->wl_word,wl->wl_next);
590 (void)signal(SIGINT,intrpt);
591 if (!dispdev->windows && !dispdev->hardcopy)
592 if ((*ft_sced->sc_isiplot)())
593 RedisplaySCED(currentgraph);
594 (void)CheckError();
595 if (!(*ft_sced->sc_inprogress)()) {
596 ShowPrompt("Analysis complete.");
597 ClearIplot();
598 }
599 }
600 wl_free(wl);
601 }
602 MenuDeselect(MenuRUN);
603 }
604
605
606 static RETSIGTYPE
sced_interrupt()607 sced_interrupt()
608
609 {
610 (void)signal(SIGINT,sced_interrupt);
611 ft_intrpt = True;
612 }
613
614
615 static void
fix_spice_deck(deck)616 fix_spice_deck(deck)
617
618 /* Concatenate continuation lines for spice. */
619 struct line *deck;
620 {
621 struct line *d,*d0,*d1,*dn;
622 char *s;
623
624 for (d = deck; d; d = dn) {
625 dn = d->li_next;
626 if (*d->li_line == '+') {
627 /* continuation line */
628 d->li_next = NULL;
629 s = d0->li_line;
630 d0->li_line = AllocateNewString(s,d->li_line+1);
631 d0->li_next = dn;
632 if (d0->li_actual == NULL) {
633 d0->li_actual = AllocateLine(s);
634 d0->li_actual->li_linenum = d0->li_linenum;
635 d0->li_actual->li_next = d;
636 }
637 else {
638 for (d1 = d0->li_actual; d1->li_next; d1 = d1->li_next) ;
639 d1->li_next = d;
640 }
641 continue;
642 }
643 d0 = d;
644 }
645 }
646
647
648
649 /***********************************************************************
650 *
651 * Routines to check for error conditions.
652 *
653 ***********************************************************************/
654
655 int
CheckSaved()656 CheckSaved()
657
658 /* Determine if the circuit, and parent (if any) have been saved,
659 * and query user on intentions.
660 * return values:
661 * 0 saved, quit
662 * 1 not saved, quit anyway
663 * -1 not saved, don't quit
664 */
665 {
666 int i,j;
667 char *TypeIn;
668
669 MenuSelect(MenuABORT);
670 i = CheckModified();
671 j = (Parameters.kpModified And Parameters.kpCellName[0]);
672 if (i And j)
673 TypeIn =
674 "Both parent and current circuit have changed. Quit anyway? (n): ";
675 elif (i And Not j)
676 TypeIn = "Parent circuit has been modified. Quit anyway? (n): ";
677 elif (Not i And j)
678 TypeIn = "Current circuit has been modified. Quit anyway? (n): ";
679 else {
680 MenuDeselect(MenuABORT);
681 return (0);
682 }
683 ShowPrompt(TypeIn);
684 TypeIn = FBEdit(NULL);
685 if (TypeIn != NULL And (TypeIn[0] == 'Y' Or TypeIn[0] == 'y')){
686 MenuDeselect(MenuABORT);
687 return (1);
688 }
689 ErasePrompt();
690 MenuDeselect(MenuABORT);
691 return (-1);
692 }
693
694
695 int
CheckError()696 CheckError()
697
698 /* find out if spice has put anything in the error output file. If
699 * so, display it and return True.
700 */
701 {
702 int c;
703 struct ka *AOI,BB;
704
705 rewind(cp_err);
706 if ((c = getc(cp_err)) == EOF) return (False);
707 ungetc(c,cp_err);
708 if (!PopUpErrMessage(cp_err)) {
709 AOI = View->kvLargeCoarseViewport;
710 FBEraseBox(AOI->kaLeft,AOI->kaBottom,
711 AOI->kaRight,AOI->kaTop);
712 MoreText((int)AOI->kaLeft-1,(int)AOI->kaBottom-1,
713 (int)AOI->kaRight-1,(int)AOI->kaTop-1,cp_err,MoreTextColor);
714 RedisplaySCED(currentgraph);
715 }
716 rewind(cp_err);
717 #ifdef HAVE_NO_FTRUNCATE
718 /* have to add something here */
719 #else
720 ftruncate(fileno(cp_err),0);
721 #endif
722 return (True);
723 }
724
725
726 int
IsSymFile(fp)727 IsSymFile(fp)
728
729 /* Check if the file just opened is a symbol file. */
730 FILE *fp;
731 {
732 char buf[12];
733
734 (void)fgets(buf,8,fp);
735
736 if (buf[0] != '(') return (False);
737 if (buf[1] != 'S') return (False);
738 if (buf[2] != 'y') return (False);
739 if (buf[3] != 'm') return (False);
740 if (buf[4] != 'b') return (False);
741 if (buf[5] != 'o') return (False);
742 if (buf[6] != 'l') return (False);
743 return (True);
744 }
745
746
747
748 /***********************************************************************
749 *
750 * Routines to set the search path as obtained from spice, and get
751 * device name for haedcopy.
752 *
753 ***********************************************************************/
754
755
756 void
SetPathFromSpice()757 SetPathFromSpice()
758
759 /* Set the CD path to the spice search path. */
760 {
761 char buf[80], *t;
762 struct variable *v;
763 extern char *kw_sourcepath;
764 int len;
765
766 TypeOut[0] = '\0';
767
768 if (!cp_getvar(kw_sourcepath,VT_LIST,(char *)&v)) {
769 CDPath(".");
770 return;
771 }
772 len = 256;
773 t = tmalloc(len);
774 switch (v->va_type) {
775 case VT_STRING:
776 sprintf(t,"%s",v->va_string);
777 break;
778 case VT_NUM:
779 sprintf(t,"%d",v->va_num);
780 break;
781 case VT_REAL:
782 sprintf(t,"%lg",v->va_real);
783 break;
784 }
785 for (v = v->va_next; v; v = v->va_next) {
786 switch (v->va_type) {
787 case VT_STRING:
788 sprintf(buf," %s",v->va_string);
789 break;
790 case VT_NUM:
791 sprintf(buf," %d",v->va_num);
792 break;
793 case VT_REAL:
794 sprintf(buf," %lg",v->va_real);
795 break;
796 }
797 if (strlen(t) + strlen(buf) >= len)
798 t = trealloc(t, len += 256);
799 strcat(t,buf);
800 }
801 /* append the path to the sced system files */
802 if (strlen(t) + strlen(Sced_Path) > len)
803 t = trealloc(t, len += 256);
804 strcat(t," ");
805 strcat(t,Sced_Path);
806 CDPath(t);
807 txfree(t);
808 }
809
810
811 void
SetCDPath(Path)812 SetCDPath(Path)
813
814 char *Path;
815 {
816 if (PathFromFile != NULL)
817 free(PathFromFile);
818 PathFromFile = CopyString(Path);
819 }
820
821
822 char *
GetHardCopyDevice()823 GetHardCopyDevice()
824
825 /* Return the name of the device used for output as set in spice. */
826 {
827 struct variable *v;
828 extern char *kw_hcopydev;
829
830 if (!cp_getvar(kw_hcopydev, VT_STRING, (char *)&v))
831 return ("prn");
832 return (v->va_string);
833 }
834
835
836
837 /***********************************************************************
838 *
839 * Routines needed to satisfy references in SCED library, for error and
840 * signal handling.
841 *
842 ***********************************************************************/
843
844 void
InitSignals()845 InitSignals()
846 {
847 ft_intrpt = false;
848 vec_gc();
849 }
850
851 char *
NextCellName()852 NextCellName()
853 {return (NULL);}
854
855
856 void
MallocFailed()857 MallocFailed()
858
859 {
860 char *cp;
861 char *mktemp();
862 cp = mktemp("scXXXXXX");
863 DevHalt();
864 fprintf(stderr,"OUT OF MEMORY. SCED is DEAD!\n");
865
866 if (Parameters.kpCellName[0] != EOS) {
867 if (Not CDUpdate(Parameters.kpCellDesc,cp))
868 fprintf(stderr,"\007Sorry. Couldn't save current circuit.\n");
869 else
870 fprintf(stderr,"\007Current circuit saved in %s.\n",cp);
871 }
872 longjmp(errjbuf,1);
873 }
874
875
876
877 /***********************************************************************
878 *
879 * Routines which allocate memory from spice, etc.
880 *
881 ***********************************************************************/
882
883 extern char *copy();
884
885
886 struct line *
AllocateLine(string)887 AllocateLine(string)
888
889 /* create and initialize a line structure */
890 char *string;
891 {
892 struct line *l;
893
894 /* allocate memory in spice */
895
896 l = alloc(line);
897 l->li_line = copy(string);
898 return (l);
899 }
900
901
902 char *
AllocateNewString(string,buf)903 AllocateNewString(string,buf)
904
905 /* Create a new concatenated string from a previous string and buffer.
906 */
907 char *string;
908 char *buf;
909 {
910 char *c;
911
912 c = tmalloc(strlen(string) + strlen(buf) + 2);
913 sprintf(c,"%s %s",string,buf);
914 return (c);
915 }
916
917
918
919 /***********************************************************************
920 *
921 * Routines to execute spice commands, or enter a shell;
922 *
923 *
924 ***********************************************************************/
925
926 #ifdef __STDC__
927 static int do_spice_cmd(char*);
928 #else
929 static int do_spice_cmd();
930 #endif
931
932 /* imports from spice */
933 extern int cp_evloop();
934 extern void cp_pushcontrol();
935 extern void cp_popcontrol();
936 extern FILE *cp_out;
937 extern FILE *cp_in;
938
939
940 void
ShowProcess(cp)941 ShowProcess(cp)
942
943 char *cp;
944 {
945 char buffer[80];
946 int i, gicalls;
947
948 if (!cp || !strlen(cp)) {
949 if (!dispdev->windows) {
950 #ifdef MSDOS
951 cp = "command";
952 #else
953 cp = "csh";
954 #endif
955 DevHalt();
956 system(cp);
957 DevNewViewport(currentgraph);
958 RedisplaySCED(currentgraph);
959 }
960 else
961 system("xterm &");
962 return;
963 }
964 gicalls = numgraphcxsw;
965 i = do_spice_cmd(cp);
966
967 if (!CheckError()) {
968 if (!dispdev->windows) {
969 /* CheckError() redraws screen if error */
970 if (i) {
971 /* Cmd showed some text */
972 ShowPrompt("Hit any key to continue.");
973 (void)FBGetchar(ERASE);
974 ErasePrompt();
975 }
976 if (gicalls != numgraphcxsw)
977 InitVLT();
978 if (i || gicalls != numgraphcxsw)
979 RedisplaySCED(currentgraph);
980 }
981 }
982 }
983
984
985 static int
do_spice_cmd(Cmd)986 do_spice_cmd(Cmd)
987
988 char *Cmd;
989 {
990 *TypeOut = '\0';
991 (void)EnableMore(True);
992 cp_pushcontrol();
993 cp_evloop(Cmd);
994 cp_popcontrol();
995 return (EnableMore(False));
996 }
997
998
999 int
SCEDline(string)1000 SCEDline(string)
1001
1002 /* Called from output.c in spice, redirects output to
1003 * graphics window.
1004 */
1005 char *string;
1006 {
1007 if (SCEDisActive) {
1008 if (strlen(TypeOut) + strlen(string) < 200)
1009 strcat(TypeOut,string);
1010 else
1011 strcat(TypeOut,"\n");
1012 if (strchr(TypeOut,'\n') == NULL) return (False);
1013 if (MoreLine(TypeOut))
1014 EnableMore(False);
1015 *TypeOut = '\0';
1016 return (True);
1017 }
1018 return (False);
1019 }
1020
1021
1022 void
SCEDfflush()1023 SCEDfflush()
1024
1025 {
1026 if (!SCEDisActive) {
1027 fflush(cp_out);
1028 return;
1029 }
1030 strcat(TypeOut,"\n");
1031 if (MoreLine(TypeOut))
1032 EnableMore(False);
1033 *TypeOut = '\0';
1034 }
1035
1036
1037 char *
SCEDfgets(s,n,fp,prompt)1038 SCEDfgets(s,n,fp,prompt)
1039
1040 /* replacement for fgets() for use in spice */
1041 char *s;
1042 int n;
1043 FILE *fp;
1044 char *prompt;
1045 {
1046 char *c;
1047
1048 if (!SCEDisActive) {
1049 if (prompt != NULL) {
1050 (void)fprintf(cp_out,prompt);
1051 (void)fflush(cp_out);
1052 }
1053 c = fgets(s,n,fp);
1054 if (c == NULL) {
1055 clearerr(fp);
1056 }
1057 return (c);
1058 }
1059 if (!prompt) {
1060 ErasePrompt();
1061 return (NULL);
1062 }
1063 ShowPrompt(prompt);
1064 MorePageDisplay();
1065 c = FBEdit(NULL);
1066 ErasePrompt();
1067 if (c == NULL || *c == '\0' || *c == '\n') return (NULL);
1068 strncpy(s,c,n);
1069 return (s);
1070 }
1071
1072
1073 enum Active
SCEDactive()1074 SCEDactive()
1075
1076 {
1077 return (SCEDisActive);
1078 }
1079
1080
1081
1082 /***********************************************************************
1083 *
1084 * Help interface.
1085 *
1086 *
1087 ***********************************************************************/
1088
1089 void
SCEDhelp()1090 SCEDhelp()
1091
1092 {
1093 int dummy;
1094 char cmd[32];
1095
1096 MenuSelect(MenuHELP);
1097 ShowPrompt("Point to menu item for help (ESC to exit help).");
1098 SCEDisActive = SCED_inhelp;
1099 loop {
1100 switch (PointLoopSafe(&dummy)) {
1101 case PL_ESC:
1102 MenuDeselect(MenuHELP);
1103 if (!dispdev->windows)
1104 RedisplaySCED(currentgraph);
1105 else
1106 ErasePrompt();
1107 SCEDisActive = SCED_active;
1108 return;
1109 case PL_PCW:
1110 continue;
1111 case PL_CMD:
1112 if (Matching(MenuMINSR) ||
1113 Matching(MenuPLUSR) ||
1114 Matching(MenuMINSG) ||
1115 Matching(MenuPLUSG) ||
1116 Matching(MenuMINSB) ||
1117 Matching(MenuPLUSB))
1118 strcpy(Parameters.kpCommand,"chgcolor");
1119
1120 else
1121
1122 if (Matching(Menu0) ||
1123 Matching(Menu90) ||
1124 Matching(Menu180) ||
1125 Matching(Menu270))
1126 strcpy(Parameters.kpCommand,"rotate");
1127
1128 else
1129
1130 if (Matching(MenuMX) ||
1131 Matching(MenuMY))
1132 strcpy(Parameters.kpCommand,"mirror");
1133
1134 else
1135
1136 if (Matching(MenuSpace))
1137 continue;
1138
1139 sprintf(cmd,"help sced:%s",Parameters.kpCommand);
1140 (void)do_spice_cmd(cmd);
1141 }
1142 }
1143 }
1144