1 /**********
2 Copyright 1990 Regents of the University of California.  All rights reserved.
3 Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
4 **********/
5 
6 #include "../misc/ivars.h"
7 #include "circuits.h"
8 #include "com_alias.h"
9 #include "define.h"
10 #include "display.h"
11 #include "ftehelp.h"
12 #include "misccoms.h"
13 #include "ngspice/ngspice.h"
14 #include "ngspice/cpdefs.h"
15 #include "ngspice/ftedefs.h"
16 #include "ngspice/dvec.h"
17 #include "ngspice/iferrmsg.h"
18 #include "ngspice/hlpdefs.h"
19 #include "plotting/graf.h"
20 #include "plotting/plotit.h"
21 #include "postcoms.h"
22 #include "runcoms2.h"
23 #include "variable.h"
24 #include "com_unset.h"
25 
26 #ifndef SHARED_MODULE
27 #ifdef HAVE_GNUREADLINE
28 #include <readline/readline.h>
29 #include <readline/history.h>
30 extern char history_file[];
31 #endif
32 
33 #ifdef HAVE_BSDEDITLINE
34 #include <editline/readline.h>
35 extern char history_file[];
36 #endif
37 #endif
38 
39 #ifdef SHARED_MODULE
40 extern void rem_controls(void);
41 extern void destroy_wallace(void);
42 extern void sh_delete_myvec(void);
43 #endif
44 
45 extern IFsimulator SIMinfo;
46 extern void spice_destroy_devices(void); /* FIXME need a better place */
47 static void byemesg(void);
48 static int  confirm_quit(void);
49 
50 
51 void
com_quit(wordlist * wl)52 com_quit(wordlist *wl)
53 {
54     int exitcode = EXIT_NORMAL;
55 
56     bool noask =
57         (wl  &&  wl->wl_word  &&  1 == sscanf(wl->wl_word, "%d", &exitcode)) ||
58         (wl  &&  wl->wl_word  &&  cieq(wl->wl_word, "noask"))  ||
59         !cp_getvar("askquit", CP_BOOL, NULL, 0);
60 
61     /* update screen and reset terminal */
62     gr_clean();
63     cp_ccon(FALSE);
64 
65 
66     /* Make sure the guy really wants to quit. */
67     if (!ft_nutmeg)
68         if (!noask && !confirm_quit())
69             return;
70 
71     /* start to clean up the mess */
72 
73 #ifdef SHARED_MODULE
74     {
75         wordlist all = { "all", NULL, NULL };
76         wordlist star = { "*", NULL, NULL };
77 
78         com_destroy(&all);
79         com_unalias(&star);
80         com_undefine(&star);
81 
82         cp_remvar("history");
83         cp_remvar("noglob");
84         cp_remvar("brief");
85         cp_remvar("sourcepath");
86         cp_remvar("program");
87         cp_remvar("prompt");
88 
89         destroy_wallace();
90     }
91 
92     rem_controls();
93 
94     /* Destroy CKT when quit. */
95     if (!ft_nutmeg) {
96         while(ft_curckt)
97             com_remcirc(NULL);
98     }
99     cp_destroy_keywords();
100     destroy_ivars();
101 #else
102     /* remove plotting parameters */
103     pl_rempar();
104 
105     while (ft_curckt)
106         com_remcirc(NULL);
107 #endif
108 
109     tfree(errMsg);
110     byemesg();
111 
112 #ifdef SHARED_MODULE
113     destroy_const_plot();
114     spice_destroy_devices();
115     unset_all();
116     cp_resetcontrol(FALSE);
117     sh_delete_myvec();
118     /* add 1000 to notify that we exit from 'quit' */
119     controlled_exit(1000 + exitcode);
120 #else
121     exit(exitcode);
122 #endif
123 }
124 
125 
126 #ifdef SYSTEM_MAIL
127 
128 void
com_bug(wordlist * wl)129 com_bug(wordlist *wl)
130 {
131     char buf[BSIZE_SP];
132 
133     NG_IGNORE(wl);
134 
135     if (!Bug_Addr || !*Bug_Addr) {
136         fprintf(cp_err, "Error: No address to send bug reports to.\n");
137         return;
138     }
139 
140     fprintf(cp_out,
141             "Calling the mail program . . .(sending to %s)\n\n"
142             "Please include the OS version number and machine architecture.\n"
143             "If the problem is with a specific circuit, please include the\n"
144             "input file.\n",
145             Bug_Addr);
146 
147     (void) sprintf(buf, SYSTEM_MAIL, ft_sim->simulator, ft_sim->version, Bug_Addr);
148     if (system(buf) == -1) {
149         fprintf(cp_err, "Bug report could not be sent: \"%s\" failed.\n",
150                 buf);
151     }
152 
153     fprintf(cp_out, "Bug report sent.  Thank you.\n");
154 }
155 
156 #else
157 
158 void
com_bug(wordlist * wl)159 com_bug(wordlist *wl)
160 {
161     NG_IGNORE(wl);
162 
163     fprintf(cp_out,
164             "Please use the ngspice bug tracker at:\n"
165             "http://sourceforge.net/p/ngspice/bugs/\n");
166 }
167 
168 #endif
169 
170 
171 /* printout upon startup or 'version' command. options to version are -s (short),
172    -f (full), -v (just version), -d (just compile date).
173    'version' with options may also be used in ngspice pipe mode. */
174 void
com_version(wordlist * wl)175 com_version(wordlist *wl)
176 {
177     if (!wl) {
178 
179         /* no printout in pipe mode (-p) */
180         if (ft_pipemode)
181             return;
182 
183         fprintf(cp_out,
184                 "******\n"
185                 "** %s-%s : %s\n"
186                 "** The U. C. Berkeley CAD Group\n"
187                 "** Copyright 1985-1994, Regents of the University of California.\n"
188                 "** Copyright 2001-2020, The ngspice team.\n"
189                 "** %s\n",
190                 ft_sim->simulator, ft_sim->version, ft_sim->description, Spice_Manual);
191         if (*Spice_Notice != '\0')
192             fprintf(cp_out, "** %s\n", Spice_Notice);
193         if (*Spice_Build_Date != '\0')
194             fprintf(cp_out, "** Creation Date: %s\n", Spice_Build_Date);
195         fprintf(cp_out, "******\n");
196 
197     } else {
198 
199         char *s = wl_flatten(wl);
200 
201         if (!strncasecmp(s, "-s", 2)) {
202 
203             fprintf(cp_out,
204                     "******\n"
205                     "** %s-%s\n"
206                     "** %s\n",
207                     ft_sim->simulator, ft_sim->version, Spice_Manual);
208             if (*Spice_Notice != '\0')
209                 fprintf(cp_out, "** %s\n", Spice_Notice);
210             if (*Spice_Build_Date != '\0')
211                 fprintf(cp_out, "** Creation Date: %s\n", Spice_Build_Date);
212             fprintf(cp_out, "******\n");
213 
214         } else if (!strncasecmp(s, "-v", 2)) {
215             fprintf(cp_out, "%s-%s\n",ft_sim->simulator, ft_sim->version);
216         } else if (!strncasecmp(s, "-d", 2) && *Spice_Build_Date != '\0'){
217             fprintf(cp_out, "%s\n", Spice_Build_Date);
218 
219         } else if (!strncasecmp(s, "-f", 2)) {
220             fprintf(cp_out,
221                     "******\n"
222                     "** %s-%s : %s\n"
223                     "** The U. C. Berkeley CAD Group\n"
224                     "** Copyright 1985-1994, Regents of the University of California.\n"
225                     "** Copyright 2001-2020, The ngspice team.\n"
226                     "** %s\n",
227                     ft_sim->simulator, ft_sim->version, ft_sim->description, Spice_Manual);
228             if (*Spice_Notice != '\0')
229                 fprintf(cp_out, "** %s\n", Spice_Notice);
230             if (*Spice_Build_Date != '\0')
231                 fprintf(cp_out, "** Creation Date: %s\n", Spice_Build_Date);
232             fprintf(cp_out, "**\n");
233 #ifdef CIDER
234             fprintf(cp_out, "** CIDER 1.b1 (CODECS simulator) included\n");
235 #endif
236 #ifdef XSPICE
237             fprintf(cp_out, "** XSPICE extensions included\n");
238 #endif
239             fprintf(cp_out, "** Relevant compilation options (refer to user's manual):\n");
240 #ifdef NGDEBUG
241             fprintf(cp_out, "** Debugging option (-g) enabled\n");
242 #endif
243 #ifdef ADMS
244             fprintf(cp_out, "** Adms interface enabled\n");
245 #endif
246 #ifdef USE_OMP
247             fprintf(cp_out, "** OpenMP multithreading for BSIM3, BSIM4 enabled\n");
248 #endif
249 #if defined(X_DISPLAY_MISSING) && !defined(HAS_WINGUI)
250             fprintf(cp_out, "** X11 interface not compiled into ngspice\n");
251 #endif
252 #ifdef NOBYPASS
253             fprintf(cp_out, "** --enable-nobypass\n");
254 #endif
255 #ifdef CAPBYPASS
256             fprintf(cp_out, "** --enable-capbypass\n");
257 #endif
258 #ifdef NODELIMITING
259             fprintf(cp_out, "** --enable-nodelimiting\n");
260 #endif
261 #ifdef PREDICTOR
262             fprintf(cp_out, "** --enable-predictor\n");
263 #endif
264 #ifdef NEWTRUNC
265             fprintf(cp_out, "** --enable-newtrunc\n");
266 #endif
267 #ifdef WANT_SENSE2
268             fprintf(cp_out, "** --enable-sense2\n");
269 #endif
270             fprintf(cp_out, "**\n");
271 #ifdef EXPERIMENTAL_CODE
272             fprintf(cp_out, "** Experimental code enabled.\n");
273 #endif
274 #ifdef EXP_DEV
275             fprintf(cp_out, "** Experimental devices enabled.\n");
276 #endif
277             fprintf(cp_out, "******\n");
278 
279         } else if (!eq(ft_sim->version, s)) {
280 
281             fprintf(stderr,
282                     "Note: rawfile is version %s (current version is %s)\n",
283                     wl->wl_word, ft_sim->version);
284 
285         }
286 
287         tfree(s);
288     }
289 }
290 
291 
292 static void
byemesg(void)293 byemesg(void)
294 {
295 
296 #ifndef SHARED_MODULE
297 #if defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE)
298     /*  write out command history only when saying goodbye.  */
299     if (cp_interactive && (cp_maxhistlength > 0)) {
300         stifle_history(cp_maxhistlength);
301         write_history(history_file);
302     }
303 #endif
304 #endif
305 
306     printf("%s-%s done\n", ft_sim->simulator, ft_sim->version);
307 }
308 
309 
310 static int
confirm_quit(void)311 confirm_quit(void)
312 {
313     struct circ *cc;
314     struct plot *pl;
315     int ncc = 0, npl = 0;
316     char buf[64];
317 
318     for (cc = ft_circuits; cc; cc = cc->ci_next)
319         if (cc->ci_inprogress)
320             ncc++;
321 
322     for (pl = plot_list; pl; pl = pl->pl_next)
323         if (!pl->pl_written && pl->pl_dvecs)
324             npl++;
325 
326     if (!ncc && !npl)
327         return 1;
328 
329     fprintf(cp_out, "Warning: ");
330 
331     if (ncc) {
332         fprintf(cp_out,
333                 "the following simulation%s still in progress:\n",
334                 (ncc > 1) ? "s are" : " is");
335         for (cc = ft_circuits; cc; cc = cc->ci_next)
336             if (cc->ci_inprogress)
337                 fprintf(cp_out, "\t%s\n", cc->ci_name);
338     }
339 
340     if (ncc && npl)
341         fprintf(cp_out, "and ");
342 
343     if (npl) {
344         fprintf(cp_out,
345                 "the following plot%s been saved:\n",
346                 (npl > 1) ? "s haven't" : " hasn't");
347         for (pl = plot_list; pl; pl = pl->pl_next)
348             if (!pl->pl_written && pl->pl_dvecs)
349                 fprintf(cp_out, "%s\t%s, %s\n",
350                         pl->pl_typename, pl->pl_title, pl->pl_name);
351     }
352 
353     fprintf(cp_out, "\nAre you sure you want to quit (yes)? ");
354     (void) fflush(cp_out);
355 
356     if (!fgets(buf, sizeof(buf), stdin)) {
357         clearerr(stdin);
358         *buf = 'y';
359     }
360 
361     return ((*buf == 'y') || (*buf == 'Y') || (*buf == '\n'));
362 }
363