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