1 /*$Id: main.cc 2016/09/11 al $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
27 #include "u_sim_data.h"
28 #include "e_cardlist.h"
33 #include "declare.h" /* plclose */
36 // #define COMMENT_CHAR "*"
38 /*--------------------------------------------------------------------------*/
40 extern int optind
, opterr
, optopt
;
43 /*--------------------------------------------------------------------------*/
47 /*--------------------------------------------------------------------------*/
48 static void sign_on(void)
50 if (OPT::quiet
) return;
52 "Gnucap : The Gnu Circuit Analysis Package\n"
53 "Never trust any version less than 1.0\n"
54 "Copyright 1982-2015, Albert Davis\n"
55 "Copyright 2009-2015, Felix Salfelder\n"
56 "Gnucap comes with ABSOLUTELY NO WARRANTY\n"
57 "This is free software, and you are welcome\n"
58 "to redistribute it under the terms of \n"
59 "the GNU General Public License, version 3 or later.\n"
60 "See the file \"COPYING\" for details.\n"
62 "main version: " PATCHLEVEL
"\n"
64 "main version: " VERSION
"\n"
66 "core-lib version: " << lib_version() << "\n";
68 /*--------------------------------------------------------------------------*/
69 void read_startup_files(void)
71 trace0("read_startup_files");
72 string name
= findfile(SYSTEMSTARTFILE
, SYSTEMSTARTPATH
, R_OK
);
73 if (name
!= "") {untested();
74 trace1("read_startup_files", name
);
76 CMD::command("get " + name
, &CARD_LIST::card_list
);
78 error(bDANGER
, "%s\n",e
.message().c_str());
81 CMD::command(std::string("load " DEFAULT_PLUGINS
), &CARD_LIST::card_list
);
83 if (!startup_recursive()) {
84 trace1("read_startup_files, no cwd", name
);
85 name
= findfile(USERSTARTFILE
, USERSTARTPATH
, R_OK
);
88 CMD::command("get " + name
, &CARD_LIST::card_list
);
90 error(bDANGER
, "%s\n",e
.message().c_str());
97 CMD::command("clear", &CARD_LIST::card_list
);
99 error(bDANGER
, "%s\n",e
.message().c_str());
101 if (!OPT::language
) {
103 CMD::command(std::string("options lang=") + DEFAULT_LANGUAGE
, &CARD_LIST::card_list
);
104 } catch(Exception e
){
105 error(bDANGER
, "%s\n",e
.message().c_str());
110 /*--------------------------------------------------------------------------*/
111 /* sig_abrt: trap asserts
114 static void sig_abrt(SIGNALARGS
)
116 signal(SIGINT
,sig_abrt
);
117 static int count
= 10;
119 error(bDANGER
, "\n");
125 /*--------------------------------------------------------------------------*/
126 /* sig_int: what to do on receipt of interrupt signal (SIGINT)
127 * cancel batch files, then back to command mode.
128 * (actually, control-c trap)
131 static void sig_int(SIGNALARGS
)
133 signal(SIGINT
,sig_int
);
134 if (ENV::run_mode
== rBATCH
) {
142 /*--------------------------------------------------------------------------*/
144 static void sig_fpe(SIGNALARGS
)
147 signal(SIGFPE
,sig_fpe
);
148 error(bDANGER
, "floating point error\n");
151 /*--------------------------------------------------------------------------*/
152 static void setup_traps(void)
154 signal(SIGFPE
,sig_fpe
);
155 signal(SIGINT
,sig_int
);
156 signal(SIGABRT
,sig_abrt
);
158 /*--------------------------------------------------------------------------*/
159 /* finish: clean up after a command
160 * deallocates space, closes plot windows, resets i/o redirection, etc.
161 * This is done separately for exception handling.
162 * If a command aborts, clean-up is still done, leaving a consistent state.
163 * //BUG// It is a function to call as a remnant of old C code.
164 * Should be in a destructor, so it doesn't need to be explicitly called.
166 static void finish(void)
169 IO::mstdout
.outreset();
171 /*--------------------------------------------------------------------------*/
173 static void do_getopt(int argc
, char * const * argv
)
179 while ((opt
= getopt(argc
, argv
, "a:c:b:i:qt:")) != -1) {
185 nsecs
= atoi(optarg
);
194 fprintf(stderr
, "Usage: %s [-q] name\n", argv
[0]); }
197 // printf("flags=%d; tfnd=%d; optind=%d, argc=%i\n", flags, tfnd, optind, argc);
200 fprintf(stderr
, "Expected argument after options\n");
203 USE(tfnd
); USE(nsecs
);
206 /*--------------------------------------------------------------------------*/
207 static void process_cmd_line(int argc
, char *const *argv
)
209 for (int ii
= 1; ii
< argc
; /*inside*/) {
211 if ( !strcasecmp(argv
[ii
], "-v") ){
212 // FIXME. use git hash for development versions.
213 cout
<< PACKAGE
<< " " << VERSION
<< endl
;
215 } else if ( !strcasecmp(argv
[ii
], "-E")
216 || !strcasecmp(argv
[ii
], "-e") ) {
221 if ( !strcasecmp(argv
[ii
], "-E") )
223 // dashier startet den OPT::language modus
224 CMD::command(string("expect ") + v
+ argv
[ii
++], &CARD_LIST::card_list
);
228 }else if (strcasecmp(argv
[ii
], "-q") == 0) {
230 // doesnt do anything.
231 }else if (strcasecmp(argv
[ii
], "-i") == 0) {
234 CMD::command(std::string("include ") + argv
[ii
++], &CARD_LIST::card_list
);
237 }else if (strcasecmp(argv
[ii
], "-c") == 0) { itested();
239 if (ii
< argc
) { itested();
240 CS
cmd(CS::_STRING
, argv
[ii
++]); // command line
241 CMD::cmdproc(cmd
, &CARD_LIST::card_list
);
244 }else if (strcasecmp(argv
[ii
], "-b") == 0) {
247 // set languacge to spice (since we have defined acs as default.
248 // this is a hack and might be a bug as well.
249 CMD::command("spice", &CARD_LIST::card_list
);
251 // dashier startet den OPT::language modus
252 trace2("-b...", OPT::language
, argv
[ii
]);
253 CMD::command(std::string("< ") + argv
[ii
++], &CARD_LIST::card_list
);
255 CMD::command(std::string("< /dev/stdin"), &CARD_LIST::card_list
);
257 }catch (Exception
& e
) {
258 error(bDANGER
, e
.message() + '\n');
259 throw(Exception("error processing batch file"));
263 CMD::command("end", &CARD_LIST::card_list
);
266 }else if (strcasecmp(argv
[ii
], "-a") == 0) { itested();
268 if (ii
< argc
) { itested();
269 CMD::command(std::string("attach ") + argv
[ii
++], &CARD_LIST::card_list
);
273 CMD::command(std::string("include ") + argv
[ii
++], &CARD_LIST::card_list
);
275 }catch (Exception
& e
) {
281 /*--------------------------------------------------------------------------*/
282 int main(int argc
, char * const * argv
)
284 CKT_BASE::_sim
= new SIM_DATA
;
285 CKT_BASE::_probe_lists
= new PROBE_LISTS
;
288 // parse -v and -q _now_
289 do_getopt(argc
,argv
);
290 // sigsetjmp unneeded here (isnt it?)
294 CMD::command("options lang=acs", &CARD_LIST::card_list
);
295 assert(OPT::language
);
296 read_startup_files();
300 SET_RUN_MODE
xx(rBATCH
);
301 trace0("batch mode");
302 if (!sigsetjmp(env
.p
, true)) {
306 trace0("done traps");
307 process_cmd_line(argc
,argv
);
308 trace0("done cmdline mode");
309 }catch (Exception
& e
) {
311 std::cerr
<< e
.message() << std::endl
;
312 finish(); /* error clean up (from longjmp()) */
313 CMD::command("quit", &CARD_LIST::card_list
);
318 trace0("finish batch");
319 finish(); /* error clean up (from longjmp()) */
320 CMD::command("quit", &CARD_LIST::card_list
);
325 SET_RUN_MODE
xx(rINTERACTIVE
);
326 trace0("interactive mode");
329 if (!sigsetjmp(env
.p
, true)) {
332 OPT::language
->parse_top_item(cmd
, &CARD_LIST::card_list
);
334 CMD::cmdproc(cmd
.get_line(I_PROMPT
), &CARD_LIST::card_list
);
336 }catch (Exception_End_Of_Input
& e
) {
337 error(bDANGER
, e
.message() + '\n');
339 CMD::command("quit", &CARD_LIST::card_list
);
341 }catch (Exception
& e
) {
342 error(bDANGER
, e
.message() + '\n');
347 finish(); /* error clean up (from longjmp()) */
354 /*--------------------------------------------------------------------------*/
355 /*--------------------------------------------------------------------------*/