1 |
johnpye |
575 |
/* ASCEND modelling environment |
2 |
|
|
Copyright 1997, Carnegie Mellon University |
3 |
|
|
Copyright (C) 2006 Carnegie Mellon University |
4 |
johnpye |
571 |
|
5 |
johnpye |
575 |
This program is free software; you can redistribute it and/or modify |
6 |
|
|
it under the terms of the GNU General Public License as published by |
7 |
|
|
the Free Software Foundation; either version 2, or (at your option) |
8 |
|
|
any later version. |
9 |
|
|
|
10 |
|
|
This program is distributed in the hope that it will be useful, |
11 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
|
|
GNU General Public License for more details. |
14 |
|
|
|
15 |
|
|
You should have received a copy of the GNU General Public License |
16 |
|
|
along with this program; if not, write to the Free Software |
17 |
|
|
Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
|
|
Boston, MA 02111-1307, USA. |
19 |
|
|
*//* |
20 |
|
|
by Kirk Abbott and Ben Allan |
21 |
|
|
Created: 1/94 |
22 |
johnpye |
742 |
Last in CVS: $Revision: 1.48 $ $Date: 2003/08/23 18:43:06 $ $Author: ballan $ |
23 |
johnpye |
575 |
*/ |
24 |
|
|
|
25 |
johnpye |
742 |
#define ASC_BUILDING_INTERFACE |
26 |
|
|
|
27 |
johnpye |
571 |
#include <stdarg.h> |
28 |
|
|
#include <ctype.h> |
29 |
|
|
#include <time.h> |
30 |
|
|
#include <tcl.h> |
31 |
|
|
#include <tk.h> |
32 |
johnpye |
1142 |
#include <utilities/config.h> |
33 |
johnpye |
571 |
#include <utilities/ascConfig.h> |
34 |
johnpye |
586 |
#include <general/ospath.h> |
35 |
|
|
#include <utilities/ascPrint.h> |
36 |
johnpye |
588 |
#include <utilities/error.h> |
37 |
johnpye |
1142 |
#ifdef ASC_SIGNAL_TRAPS |
38 |
|
|
# include <utilities/ascSignal.h> |
39 |
|
|
#endif |
40 |
johnpye |
571 |
|
41 |
|
|
#ifndef __WIN32__ |
42 |
|
|
# include <unistd.h> |
43 |
|
|
#else |
44 |
|
|
|
45 |
|
|
/* jds20041229 - windows.h now included in ascConfig.h. */ |
46 |
johnpye |
575 |
/* jp - i took it back out of ascConfig.h - Apr 2005 */ |
47 |
johnpye |
571 |
# define WIN32_LEAN_AND_MEAN |
48 |
|
|
# include <windows.h> |
49 |
|
|
|
50 |
|
|
# include <locale.h> |
51 |
|
|
# include "tkConsole.h" |
52 |
|
|
# undef WIN32_LEAN_AND_MEAN |
53 |
|
|
#endif /* __WIN32__ */ |
54 |
|
|
|
55 |
|
|
#include <utilities/config.h> |
56 |
|
|
#include <utilities/ascMalloc.h> /* for ascshutdown */ |
57 |
|
|
#include <utilities/ascPanic.h> /* for Asc_Panic */ |
58 |
|
|
#include <utilities/ascEnvVar.h> |
59 |
johnpye |
1183 |
#include <utilities/ascPrint.h> |
60 |
|
|
|
61 |
johnpye |
571 |
#include <compiler/ascCompiler.h> |
62 |
|
|
#include <compiler/instance_enum.h> |
63 |
|
|
#include <compiler/units.h> |
64 |
johnpye |
929 |
/* #include <compiler/redirectFile.h> */ /* for Asc_RedirectCompilerDefault() */ |
65 |
johnpye |
742 |
#include <compiler/simlist.h> |
66 |
johnpye |
1183 |
|
67 |
|
|
#include <linear/mtx.h> |
68 |
|
|
|
69 |
johnpye |
1316 |
#include <system/slv_client.h> |
70 |
|
|
#include <system/slv_stdcalls.h> |
71 |
johnpye |
1183 |
|
72 |
johnpye |
571 |
#include "AscBitmaps.h" |
73 |
|
|
#include "AscPrintTcl.h" |
74 |
|
|
#include "HelpProc.h" |
75 |
|
|
#include "Commands.h" |
76 |
|
|
#include "Driver.h" |
77 |
|
|
#include "ScriptProc.h" |
78 |
|
|
#include "SolverProc.h" |
79 |
|
|
#include "UnitsProc.h" |
80 |
|
|
|
81 |
|
|
#ifndef lint |
82 |
|
|
static CONST char DriverID[] = "$Id: Driver.c,v 1.48 2003/08/23 18:43:06 ballan Exp $"; |
83 |
|
|
#endif |
84 |
|
|
|
85 |
|
|
/* |
86 |
|
|
* EXPORTED VARIABLES |
87 |
|
|
*/ |
88 |
|
|
|
89 |
|
|
/** |
90 |
johnpye |
670 |
Interpreter for this application. We need to make it global |
91 |
|
|
so that our signal/floating-porint traps can access it. |
92 |
|
|
*/ |
93 |
johnpye |
571 |
Tcl_Interp *g_interp; |
94 |
|
|
|
95 |
|
|
/* |
96 |
johnpye |
670 |
Comes from the yacc file if yacc was built with debugging information |
97 |
|
|
*/ |
98 |
johnpye |
571 |
#ifdef ZZ_DEBUG |
99 |
|
|
extern int zz_debug; |
100 |
|
|
#endif |
101 |
|
|
|
102 |
|
|
|
103 |
|
|
/* |
104 |
johnpye |
670 |
Declarations for procedures defined outside of this file. |
105 |
johnpye |
571 |
*/ |
106 |
|
|
extern int Tktable_Init(Tcl_Interp*); |
107 |
|
|
|
108 |
johnpye |
1175 |
#ifdef ASC_SIGNAL_TRAPS |
109 |
johnpye |
571 |
static void AscTrap(int); |
110 |
johnpye |
1176 |
#endif |
111 |
johnpye |
1175 |
|
112 |
johnpye |
908 |
static void AscCheckEnvironVars(Tcl_Interp*,const char *progname); |
113 |
johnpye |
571 |
static void AscPrintHelpExit(CONST char *); |
114 |
|
|
static int AscProcessCommandLine(Tcl_Interp*, int, CONST char **); |
115 |
|
|
static void Prompt(Tcl_Interp*, int); |
116 |
|
|
static int AscSetStartupFile(Tcl_Interp*); |
117 |
|
|
static void StdinProc(ClientData, int); |
118 |
|
|
#ifdef DEBUG_MALLOC |
119 |
|
|
static void InitDebugMalloc(void); |
120 |
|
|
#endif /* DEBUG_MALLOC */ |
121 |
|
|
|
122 |
|
|
|
123 |
|
|
/* |
124 |
johnpye |
742 |
LOCALLY GLOBAL VARIABLES |
125 |
johnpye |
670 |
think global, act local :-) |
126 |
|
|
*/ |
127 |
johnpye |
571 |
|
128 |
johnpye |
670 |
/** |
129 |
|
|
TRUE for compiler optimizations default is TRUE, set to FALSE by passing |
130 |
johnpye |
742 |
+s on the command line |
131 |
johnpye |
670 |
*/ |
132 |
johnpye |
571 |
static int g_interface_simplify_relations = TRUE; |
133 |
|
|
|
134 |
johnpye |
670 |
/** TRUE if windows to be built; default is TRUE, false is not supported */ |
135 |
johnpye |
571 |
static int g_interfacever = 1; |
136 |
|
|
|
137 |
johnpye |
670 |
/** Used to assemble lines of terminal input into Tcl commands. */ |
138 |
johnpye |
571 |
static Tcl_DString g_command; |
139 |
|
|
|
140 |
johnpye |
670 |
/** Used to read the next line from the terminal input. */ |
141 |
johnpye |
571 |
static Tcl_DString g_line; |
142 |
|
|
|
143 |
johnpye |
670 |
/** |
144 |
|
|
Non-zero means standard input is a terminal-like device. |
145 |
|
|
Zero means it's a file. |
146 |
|
|
*/ |
147 |
johnpye |
571 |
static int tty; |
148 |
|
|
|
149 |
|
|
/* |
150 |
johnpye |
670 |
initScriptTclAdjust |
151 |
|
|
initScriptTkAdjust |
152 |
johnpye |
742 |
|
153 |
johnpye |
670 |
These two variables hold Tcl scripts that will set the TCL_LIBRARY |
154 |
|
|
and TK_LIBRARY environment variables if they are not already |
155 |
|
|
set in the user's environment. |
156 |
|
|
TCL_LIBRARY is set to: dirnameofexecutable/../../Tcl/lib/tcl8.0 |
157 |
|
|
TK_LIBRARY is set to $tcl_library/../tk8.0 |
158 |
|
|
*/ |
159 |
johnpye |
571 |
static char initScriptTclAdjust[] = |
160 |
|
|
"proc asc_tclInit {} {\n\ |
161 |
|
|
global env\n\ |
162 |
|
|
rename asc_tclInit {}\n\ |
163 |
|
|
set errors {}\n\ |
164 |
|
|
set dirs {}\n\ |
165 |
|
|
if [info exists env(TCL_LIBRARY)] {\n\ |
166 |
|
|
return\n\ |
167 |
|
|
} else {\n\ |
168 |
|
|
set parentDir [file dirname [info nameofexecutable]]\n\ |
169 |
|
|
set env(TCL_LIBRARY) $parentDir/../../Tcl/lib/tcl8.0\n\ |
170 |
|
|
}\n\ |
171 |
|
|
}\n\ |
172 |
|
|
asc_tclInit"; |
173 |
|
|
/* for tcl, FOO/ascend4/bin/ascend4.exe is the executable, then |
174 |
|
|
* /-- up to FOO/ascend4/bin |
175 |
|
|
* set parentDir [file dirname [info nameofexecutable]]\n\ |
176 |
|
|
* Then if Tcl is next to ascend4, ../../Tcl/lib/tcl8.0 should work. |
177 |
|
|
*/ |
178 |
|
|
|
179 |
|
|
static char initScriptTkAdjust[] = |
180 |
|
|
"proc asc_tkInit {} {\n\ |
181 |
|
|
global env\n\ |
182 |
|
|
rename asc_tkInit {}\n\ |
183 |
|
|
set errors {}\n\ |
184 |
|
|
set dirs {}\n\ |
185 |
|
|
if [info exists env(TK_LIBRARY)] {\n\ |
186 |
|
|
return\n\ |
187 |
|
|
} else {\n\ |
188 |
|
|
set parentDir [file dirname [info library]]\n\ |
189 |
|
|
set env(TK_LIBRARY) $parentDir/tk8.0\n\ |
190 |
|
|
}\n\ |
191 |
|
|
}\n\ |
192 |
|
|
asc_tkInit"; |
193 |
johnpye |
670 |
/**< |
194 |
|
|
This assumes tcl_library has been found and that tcl8.0 and tk8.0 |
195 |
|
|
are installed in the same lib directory -- the default tcl/tk install. |
196 |
|
|
*/ |
197 |
johnpye |
571 |
|
198 |
johnpye |
670 |
/** |
199 |
|
|
who built this binary and when |
200 |
johnpye |
571 |
*/ |
201 |
|
|
#ifndef TIMESTAMP |
202 |
|
|
static char build_name[]="by anonymous"; |
203 |
|
|
#else |
204 |
|
|
static char build_name[]=TIMESTAMP; |
205 |
|
|
#endif /* TIMESTAMP */ |
206 |
|
|
|
207 |
johnpye |
670 |
/* |
208 |
|
|
jp: Moved 'main' and 'WinMain' to separate 'main.c' |
209 |
johnpye |
571 |
so that ascend4.exe can be built without linkage to Tcl/Tk |
210 |
|
|
*/ |
211 |
|
|
|
212 |
|
|
|
213 |
johnpye |
670 |
/** |
214 |
|
|
A common entry point for Windows and Unix. The corresponding |
215 |
|
|
WinMain() and main() functions just call this function. |
216 |
johnpye |
742 |
|
217 |
johnpye |
670 |
This function creates a Tcl interpreter, initializes Tcl and Tk, |
218 |
|
|
initializes the Ascend data structures, sets up the user's |
219 |
|
|
environment, sources ASCEND's startup script, and calls Tk_MainLoop |
220 |
|
|
so the user can interact with ASCEND. Cleans up and exits the |
221 |
|
|
program when Tk_MainLoop returns. |
222 |
johnpye |
742 |
|
223 |
johnpye |
670 |
This function is based on the functions Tk_Main and Tcl_AppInit |
224 |
|
|
from the Tk8.0 distribution. See the files tkMain.c and tkAppInit.c |
225 |
|
|
in the Tk sources. |
226 |
|
|
*/ |
227 |
johnpye |
590 |
int AscDriver(int argc, CONST char **argv) |
228 |
johnpye |
571 |
{ |
229 |
|
|
Tcl_Interp *interp; /* local version of global g_interp */ |
230 |
|
|
Tcl_Channel inChannel; |
231 |
|
|
Tcl_Channel outChannel; |
232 |
|
|
|
233 |
johnpye |
929 |
/* Remove the stream redirection stuff for the moment -- JP Nov 2006 */ |
234 |
johnpye |
571 |
/* jds20050119: Initialize ASCERR before any calls to ascPanic(). */ |
235 |
|
|
/* TODO: revisit when interface is decoupled from base - this may change. */ |
236 |
johnpye |
929 |
#ifdef REIMPLEMENT_STREAMS |
237 |
johnpye |
571 |
Asc_RedirectCompilerDefault(); |
238 |
johnpye |
929 |
#endif |
239 |
|
|
|
240 |
johnpye |
571 |
#ifdef USE_ASC_PRINTF |
241 |
|
|
Asc_PrintInit_TclVtable(); |
242 |
|
|
#endif /* USE_ASC_PRINTF */ |
243 |
|
|
/* |
244 |
|
|
* Create the Tk Console |
245 |
|
|
* |
246 |
|
|
* Create the console channels and install them as the standard |
247 |
|
|
* channels. All I/O will be discarded until TkConsoleInit() is |
248 |
|
|
* called to attach the console to a text widget. |
249 |
|
|
*/ |
250 |
|
|
#ifdef ASC_USE_TK_CONSOLE |
251 |
|
|
TkConsoleCreate(); |
252 |
|
|
#endif /* ASC_USE_TK_CONSOLE */ |
253 |
|
|
|
254 |
|
|
/* |
255 |
|
|
* Find the name of the current executable---available in the |
256 |
|
|
* Tcl command `info nameofexecutable' |
257 |
|
|
*/ |
258 |
|
|
Tcl_FindExecutable(argv[0]); |
259 |
|
|
|
260 |
|
|
/* |
261 |
|
|
* Create the interpreter |
262 |
|
|
*/ |
263 |
|
|
g_interp = Tcl_CreateInterp(); |
264 |
|
|
interp = g_interp; |
265 |
|
|
if( interp == NULL ) { |
266 |
|
|
Asc_Panic(2, "Asc_Driver", |
267 |
|
|
"Call to Tcl_CreateInterp returned NULL interpreter"); |
268 |
|
|
} |
269 |
|
|
|
270 |
|
|
/* |
271 |
|
|
* Check the arguments on the command line |
272 |
|
|
*/ |
273 |
|
|
AscProcessCommandLine(interp, argc, argv); |
274 |
|
|
|
275 |
|
|
/* |
276 |
|
|
* Set the "tcl_interactive" variable. |
277 |
|
|
* |
278 |
|
|
* ASCEND sets tty to `1', since we assume ASCEND is always interactive. |
279 |
|
|
*/ |
280 |
|
|
tty = 1; |
281 |
|
|
Tcl_SetVar(interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); |
282 |
|
|
|
283 |
|
|
/* |
284 |
|
|
* Initialize Tcl and Tk |
285 |
|
|
*/ |
286 |
|
|
(void)Tcl_Eval(interp,initScriptTclAdjust); |
287 |
|
|
if (Tcl_Init(interp) == TCL_ERROR) { |
288 |
johnpye |
1064 |
ASC_PANIC("Tcl initialization failed:\n%s", |
289 |
johnpye |
571 |
Tcl_GetStringResult(interp)); |
290 |
|
|
} |
291 |
|
|
(void)Tcl_Eval(interp,initScriptTkAdjust); |
292 |
|
|
if (Tk_Init(interp) == TCL_ERROR) { |
293 |
johnpye |
1064 |
ASC_PANIC("Tk initialization failed:\n%s", |
294 |
johnpye |
571 |
Tcl_GetStringResult(interp)); |
295 |
|
|
} |
296 |
|
|
Tcl_StaticPackage( interp, "Tk", Tk_Init, Tk_SafeInit ); |
297 |
|
|
|
298 |
|
|
/* |
299 |
|
|
* Initialize the console and the ASCEND printf() substitutes. |
300 |
|
|
* All output before this point is lost. |
301 |
|
|
*/ |
302 |
|
|
#ifdef ASC_USE_TK_CONSOLE |
303 |
|
|
if (TkConsoleInit(interp) == TCL_ERROR) { |
304 |
|
|
Asc_Panic(2, "Asc_Driver", |
305 |
|
|
"Call to TkConsoleInit failed:\n%s", |
306 |
|
|
Tcl_GetStringResult(interp)); |
307 |
|
|
} |
308 |
|
|
#endif /* ASC_USE_TK_CONSOLE */ |
309 |
|
|
#ifdef USE_ASC_PRINTF |
310 |
|
|
Asc_PrintInit_Tcl(); |
311 |
|
|
#endif /* USE_ASC_PRINTF */ |
312 |
|
|
|
313 |
|
|
/* |
314 |
|
|
* Now that our console and printing functions are properly |
315 |
|
|
* initialized, print our startup banner. |
316 |
|
|
*/ |
317 |
|
|
|
318 |
johnpye |
586 |
color_on(stderr,"34;1"); |
319 |
|
|
ASC_FPRINTF(stderr,"\nASCEND modelling environment\n"); |
320 |
jpye |
1412 |
ASC_FPRINTF(stderr,"Copyright(C) 1997, 2006-2007 Carnegie Mellon University\n"); |
321 |
johnpye |
586 |
ASC_FPRINTF(stderr,"Copyright(C) 1993-1996 Kirk Andre Abbott, Ben Allan\n"); |
322 |
|
|
ASC_FPRINTF(stderr,"Copyright(C) 1990, 1993, 1994 Thomas Guthrie Epperly\n"); |
323 |
|
|
ASC_FPRINTF(stderr,"Built %s %s %s\n\n",__DATE__,__TIME__,build_name); |
324 |
|
|
ASC_FPRINTF(stderr,"ASCEND comes with ABSOLUTELY NO WARRANTY, and is free software that you may\n"); |
325 |
|
|
ASC_FPRINTF(stderr,"redistribute within the conditions of the GNU General Public License. See the\n"); |
326 |
|
|
ASC_FPRINTF(stderr,"included file 'LICENSE.txt' for full details.\n\n"); |
327 |
|
|
color_off(stderr); |
328 |
|
|
|
329 |
johnpye |
571 |
/* |
330 |
|
|
* Call the init procedures for included packages. |
331 |
|
|
*/ |
332 |
|
|
#ifdef STATIC_TKTABLE |
333 |
|
|
if( Tktable_Init(interp) == TCL_ERROR ) { |
334 |
|
|
Asc_Panic(2, "Asc_Driver", |
335 |
|
|
"Call to Tktable_Init failed:\n%s", |
336 |
|
|
Tcl_GetStringResult(interp)); |
337 |
|
|
} |
338 |
|
|
#endif /* STATIC_TKTABLE */ |
339 |
|
|
|
340 |
|
|
/* |
341 |
|
|
* Initialize ASCEND C Structures |
342 |
|
|
* Create ASCEND Tcl Commands |
343 |
|
|
*/ |
344 |
|
|
clock(); |
345 |
|
|
/* the next line should NOT be Asc_SignalHandlerPush */ |
346 |
johnpye |
1142 |
#ifdef ASC_SIGNAL_TRAPS |
347 |
johnpye |
1002 |
(void)SIGNAL(SIGINT, AscTrap); |
348 |
johnpye |
1142 |
#endif |
349 |
|
|
|
350 |
johnpye |
571 |
#ifdef DEBUG_MALLOC |
351 |
|
|
InitDebugMalloc(); |
352 |
|
|
ascstatus("Memory status after calling InitDebugMalloc()"); |
353 |
|
|
#endif /* DEBUG_MALLOC */ |
354 |
|
|
if ( Asc_CompilerInit(g_interface_simplify_relations) != 0 ) { |
355 |
|
|
Asc_Panic(2, "Asc_CompilerInit", |
356 |
|
|
"Insufficient memory to initialize compiler."); |
357 |
|
|
} |
358 |
|
|
SlvRegisterStandardClients(); |
359 |
|
|
if( Asc_HelpInit() == TCL_ERROR ) { |
360 |
|
|
Asc_Panic(2, "Asc_HelpInit", |
361 |
|
|
"Insufficient memory to initialize help system."); |
362 |
|
|
} |
363 |
|
|
Asc_CreateCommands(interp); |
364 |
|
|
Asc_RegisterBitmaps(interp); |
365 |
|
|
|
366 |
|
|
/* |
367 |
|
|
* Set the environment, and set find the |
368 |
|
|
* location of ASCEND's startup file. |
369 |
|
|
*/ |
370 |
johnpye |
586 |
AscCheckEnvironVars(interp,argv[0]); |
371 |
johnpye |
571 |
if( AscSetStartupFile(interp) != TCL_OK ) { |
372 |
|
|
Asc_Panic(2, "Asc_Driver", |
373 |
|
|
"Cannot find ~/.ascendrc nor the default AscendRC\n%s", |
374 |
|
|
Tcl_GetStringResult(interp)); |
375 |
|
|
} |
376 |
|
|
|
377 |
|
|
/* |
378 |
|
|
* Evaluate the ~/.ascendrc or $ASCENDTK/AscendRC file |
379 |
|
|
*/ |
380 |
|
|
Tcl_SourceRCFile(interp); |
381 |
|
|
|
382 |
|
|
/* |
383 |
|
|
* Establish a channel handlers for stdin and stdout |
384 |
|
|
*/ |
385 |
|
|
inChannel = Tcl_GetStdChannel(TCL_STDIN); |
386 |
|
|
if (inChannel) { |
387 |
|
|
Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc, |
388 |
|
|
(ClientData) inChannel); |
389 |
|
|
} |
390 |
|
|
if (tty) { |
391 |
|
|
Prompt(interp, 0); |
392 |
|
|
} |
393 |
|
|
outChannel = Tcl_GetStdChannel(TCL_STDOUT); |
394 |
|
|
if (outChannel) { |
395 |
|
|
Tcl_Flush(outChannel); |
396 |
|
|
} |
397 |
|
|
|
398 |
|
|
/* |
399 |
|
|
* Initialize the Dynamic Strings used in StdinProc() |
400 |
|
|
*/ |
401 |
|
|
Tcl_DStringInit(&g_command); |
402 |
|
|
Tcl_DStringInit(&g_line); |
403 |
|
|
Tcl_ResetResult(interp); |
404 |
|
|
|
405 |
|
|
/* |
406 |
|
|
* Loop infinitely, waiting for commands to execute. When there |
407 |
|
|
* are no windows left, Tk_MainLoop returns and we exit. |
408 |
|
|
*/ |
409 |
|
|
#ifdef DEBUG_MALLOC |
410 |
|
|
ascstatus("Memory status before calling Tk_MainLoop()"); |
411 |
|
|
#endif /* DEBUG_MALLOC */ |
412 |
|
|
if (Asc_ScriptConfigureInterrupt(1,interp)!=0) { |
413 |
|
|
Asc_Panic(2, "Asc_ScriptConfigureInterrupt", |
414 |
|
|
"Unable to configure script interrupt."); |
415 |
|
|
} |
416 |
|
|
Tk_MainLoop(); |
417 |
|
|
Asc_ScriptConfigureInterrupt(0,interp); |
418 |
|
|
#ifdef USE_ASC_PRINTF |
419 |
|
|
Asc_PrintFinalize_Tcl(); |
420 |
|
|
#endif /* USE_ASC_PRINTF */ |
421 |
|
|
#ifdef DEBUG_MALLOC |
422 |
|
|
ascstatus("Memory status after Tk_MainLoop() exits"); |
423 |
|
|
#endif /* DEBUG_MALLOC */ |
424 |
|
|
|
425 |
|
|
/* |
426 |
|
|
* Do ASCEND Cleanup |
427 |
|
|
*/ |
428 |
|
|
Asc_HelpDestroy(); |
429 |
|
|
Asc_UnitValue(NULL); |
430 |
|
|
Asc_SolvMemoryCleanup(); |
431 |
|
|
Asc_CompilerDestroy(); |
432 |
|
|
Asc_DestroyEnvironment(); |
433 |
|
|
#ifdef DEBUG_MALLOC |
434 |
|
|
ascshutdown("Memory status just before exiting"); |
435 |
|
|
#endif /* DEBUG_MALLOC */ |
436 |
|
|
|
437 |
|
|
/* |
438 |
|
|
* Destroy the interpreter and exit |
439 |
|
|
*/ |
440 |
|
|
Tcl_DeleteInterp(interp); |
441 |
|
|
Tcl_Exit(0); |
442 |
|
|
return 0; |
443 |
|
|
} |
444 |
|
|
|
445 |
johnpye |
586 |
/*------------------------------------------------------- |
446 |
|
|
SETTING UP ENVIRONMENT... |
447 |
|
|
*/ |
448 |
johnpye |
571 |
|
449 |
johnpye |
586 |
#define GETENV Asc_GetEnv |
450 |
|
|
#define PUTENV Asc_PutEnv |
451 |
johnpye |
571 |
|
452 |
johnpye |
586 |
/** |
453 |
|
|
This is a quick macro to output a FilePath to an environment |
454 |
|
|
variable. |
455 |
|
|
*/ |
456 |
|
|
#define OSPATH_PUTENV(VAR,FP) \ |
457 |
johnpye |
588 |
CONSOLE_DEBUG("VAR: %s",VAR); \ |
458 |
|
|
sprintf(envcmd,"%s=",VAR); \ |
459 |
johnpye |
586 |
ospath_strcat(FP,envcmd,MAX_ENV_VAR_LENGTH); \ |
460 |
johnpye |
588 |
CONSOLE_DEBUG("ENVCMD: %s",envcmd); \ |
461 |
johnpye |
586 |
PUTENV(envcmd) |
462 |
johnpye |
571 |
|
463 |
johnpye |
586 |
/** |
464 |
|
|
This is a quick macro to send data to Tcl using Tcl_SetVar. |
465 |
|
|
It uses an intermediate buffer which is assumed to be |
466 |
|
|
empty already. |
467 |
johnpye |
571 |
|
468 |
johnpye |
586 |
usage: ASC_SEND_TO_TCL(tclvarname,"some string value"); |
469 |
|
|
*/ |
470 |
|
|
#define ASC_SEND_TO_TCL(VAR,VAL) \ |
471 |
|
|
Tcl_DStringAppend(&buffer,VAL,-1); \ |
472 |
|
|
Tcl_SetVar(interp,#VAR,Tcl_DStringValue(&buffer),TCL_GLOBAL_ONLY); \ |
473 |
|
|
Tcl_DStringFree(&buffer); |
474 |
johnpye |
575 |
|
475 |
johnpye |
586 |
/** |
476 |
|
|
This is a quick macro to send data to Tcl using Tcl_SetVar2. |
477 |
|
|
It uses an intermediate buffer which is assumed to be |
478 |
|
|
empty already. |
479 |
johnpye |
571 |
|
480 |
johnpye |
586 |
usage: ASC_SEND_TO_TCL2(arrayname,"keyname","some string value"); |
481 |
|
|
*/ |
482 |
|
|
#define ASC_SEND_TO_TCL2(ARR,KEY,VAL) \ |
483 |
|
|
Tcl_DStringAppend(&buffer,VAL,-1); \ |
484 |
|
|
Tcl_SetVar2(interp,#ARR,KEY,Tcl_DStringValue(&buffer),TCL_GLOBAL_ONLY); \ |
485 |
|
|
Tcl_DStringFree(&buffer); |
486 |
johnpye |
571 |
|
487 |
johnpye |
588 |
static void printenv(){ |
488 |
|
|
int n; |
489 |
johnpye |
908 |
const char **l; |
490 |
johnpye |
588 |
l = Asc_EnvNames(&n); |
491 |
|
|
CONSOLE_DEBUG("VARS = %d",n); |
492 |
johnpye |
908 |
ascfree(l); |
493 |
johnpye |
588 |
} |
494 |
|
|
|
495 |
johnpye |
586 |
/** |
496 |
|
|
Ensure that all required environment variables are present |
497 |
|
|
and set values for them if they are not present. The names |
498 |
|
|
for the environment variables are specified in |
499 |
|
|
<utilities/config.h>. The following comments assume that you |
500 |
|
|
use the usual names for each of these: |
501 |
johnpye |
571 |
|
502 |
johnpye |
589 |
ASCENDDIST defaults to $PROGDIR/@ASC_DATADIR_REL_BIN@ (also in config.h) |
503 |
johnpye |
628 |
ASCENDTK defaults to $ASCENDDIST/TK (latter is from config.h) |
504 |
johnpye |
586 |
ASCENDBITMAPS defaults $ASCENDTK/bitmaps |
505 |
|
|
ASCENDLIBRARY defaults to $ASCENDDIST/models |
506 |
johnpye |
571 |
|
507 |
johnpye |
586 |
Also check for the existence of the file AscendRC in $ASCENDTK |
508 |
|
|
and if found, export the location of that file to the Tcl |
509 |
|
|
variable tcl_rcFileName. |
510 |
johnpye |
628 |
|
511 |
|
|
If you set ASC_ABSOLUTE_PATHS then ASCENDDIST defaults to @ASC_DATADIR@ and |
512 |
|
|
the rest follows through as above. |
513 |
johnpye |
586 |
*/ |
514 |
johnpye |
908 |
static void AscCheckEnvironVars(Tcl_Interp *interp,const char *progname){ |
515 |
johnpye |
586 |
char *distdir, *tkdir, *bitmapsdir, *librarydir; |
516 |
|
|
struct FilePath *fp, *fp1, *distfp, *tkfp, *bitmapsfp, *libraryfp; |
517 |
|
|
char envcmd[MAX_ENV_VAR_LENGTH]; |
518 |
|
|
char s1[PATH_MAX]; |
519 |
johnpye |
589 |
int err; |
520 |
johnpye |
742 |
int guessedtk=0; |
521 |
|
|
FILE *f; |
522 |
johnpye |
571 |
|
523 |
johnpye |
586 |
Tcl_DString buffer; |
524 |
johnpye |
571 |
|
525 |
johnpye |
586 |
Tcl_DStringInit(&buffer); |
526 |
johnpye |
571 |
|
527 |
johnpye |
589 |
/* import these into the environment */ |
528 |
|
|
err = env_import(ASC_ENV_DIST,getenv,PUTENV); |
529 |
|
|
if(err)CONSOLE_DEBUG("No %s var imported, error %d",ASC_ENV_DIST,err); |
530 |
|
|
env_import(ASC_ENV_TK,getenv,PUTENV); |
531 |
|
|
env_import(ASC_ENV_BITMAPS,getenv,PUTENV); |
532 |
|
|
env_import(ASC_ENV_LIBRARY,getenv,PUTENV); |
533 |
johnpye |
571 |
|
534 |
johnpye |
670 |
/* used for colour console output */ |
535 |
|
|
env_import("TERM",getenv,PUTENV); |
536 |
johnpye |
571 |
|
537 |
johnpye |
670 |
CONSOLE_DEBUG("IMPORTING VARS"); |
538 |
|
|
|
539 |
johnpye |
588 |
distdir = GETENV(ASC_ENV_DIST); |
540 |
|
|
tkdir = GETENV(ASC_ENV_TK); |
541 |
|
|
bitmapsdir = GETENV(ASC_ENV_BITMAPS); |
542 |
|
|
librarydir = GETENV(ASC_ENV_LIBRARY); |
543 |
johnpye |
586 |
|
544 |
johnpye |
908 |
|
545 |
johnpye |
586 |
/* Create an ASCENDDIST value if it's missing */ |
546 |
|
|
|
547 |
|
|
if(distdir == NULL){ |
548 |
|
|
CONSOLE_DEBUG("NO " ASC_ENV_DIST " VAR DEFINED"); |
549 |
|
|
|
550 |
johnpye |
628 |
# ifndef ASC_ABSOLUTE_PATHS |
551 |
johnpye |
586 |
|
552 |
johnpye |
908 |
/* read the executable's name/relative path.*/ |
553 |
johnpye |
586 |
fp = ospath_new(progname); |
554 |
|
|
|
555 |
johnpye |
742 |
ospath_strncpy(fp,s1,PATH_MAX); |
556 |
johnpye |
586 |
CONSOLE_DEBUG("PROGNAME = %s",s1); |
557 |
|
|
|
558 |
johnpye |
908 |
/* get the directory name from the exe path*/ |
559 |
johnpye |
586 |
fp1 = ospath_getdir(fp); |
560 |
|
|
ospath_free(fp); |
561 |
|
|
|
562 |
johnpye |
742 |
ospath_strncpy(fp1,s1,PATH_MAX); |
563 |
johnpye |
586 |
CONSOLE_DEBUG("DIR = %s",s1); |
564 |
|
|
|
565 |
johnpye |
908 |
/* append the contents of ASC_DISTDIR_REL_BIN to this path*/ |
566 |
johnpye |
589 |
fp = ospath_new_noclean(ASC_DISTDIR_REL_BIN); |
567 |
johnpye |
586 |
distfp = ospath_concat(fp1,fp); |
568 |
|
|
ospath_cleanup(distfp); |
569 |
|
|
|
570 |
johnpye |
742 |
ospath_strncpy(fp1,s1,PATH_MAX); |
571 |
johnpye |
586 |
CONSOLE_DEBUG("DIST = %s",s1); |
572 |
|
|
|
573 |
|
|
# else |
574 |
jpye |
1412 |
CONSOLE_DEBUG("ASC_ABSOLUTE_PATHS=%d",ASC_ABSOLUTE_PATHS); |
575 |
johnpye |
586 |
distfp = ospath_new(ASC_DATADIR); |
576 |
johnpye |
908 |
(void)progname; |
577 |
johnpye |
586 |
# endif |
578 |
|
|
distdir = ospath_str(distfp); |
579 |
johnpye |
588 |
CONSOLE_DEBUG("GUESSING %s = %s",ASC_ENV_DIST,distdir); |
580 |
johnpye |
586 |
OSPATH_PUTENV(ASC_ENV_DIST,distfp); |
581 |
johnpye |
588 |
distdir = GETENV(ASC_ENV_DIST); |
582 |
|
|
CONSOLE_DEBUG("RETRIEVED %s = %s",ASC_ENV_DIST,distdir); |
583 |
|
|
printenv(); |
584 |
johnpye |
586 |
} |
585 |
|
|
|
586 |
|
|
if(tkdir == NULL){ |
587 |
johnpye |
589 |
CONSOLE_DEBUG("USING DEFAULT %s = %s",ASC_ENV_TK,ASC_ENV_TK_DEFAULT); |
588 |
johnpye |
586 |
guessedtk=1; |
589 |
johnpye |
589 |
tkfp = ospath_new_expand_env(ASC_ENV_TK_DEFAULT, &GETENV); |
590 |
johnpye |
586 |
tkdir = ospath_str(tkfp); |
591 |
|
|
|
592 |
johnpye |
742 |
ospath_strncpy(tkfp,envcmd,MAX_ENV_VAR_LENGTH); |
593 |
johnpye |
586 |
CONSOLE_DEBUG("TK = %s",envcmd); |
594 |
|
|
|
595 |
|
|
OSPATH_PUTENV(ASC_ENV_TK,tkfp); |
596 |
johnpye |
589 |
}else{ |
597 |
|
|
tkfp = ospath_new_expand_env(tkdir, &GETENV); |
598 |
|
|
tkdir = ospath_str(tkfp); |
599 |
|
|
OSPATH_PUTENV(ASC_ENV_TK,tkfp); |
600 |
johnpye |
586 |
} |
601 |
|
|
|
602 |
|
|
if(bitmapsdir == NULL){ |
603 |
johnpye |
589 |
CONSOLE_DEBUG("NO " ASC_ENV_BITMAPS " VAR DEFINED"); |
604 |
johnpye |
586 |
/* Create a path $ASCENDTK/bitmaps */ |
605 |
|
|
bitmapsfp = ospath_new_expand_env("$ASCENDTK/bitmaps", &GETENV); |
606 |
|
|
OSPATH_PUTENV(ASC_ENV_BITMAPS,bitmapsfp); |
607 |
johnpye |
588 |
bitmapsdir = ospath_str(bitmapsfp); |
608 |
johnpye |
586 |
} |
609 |
|
|
|
610 |
|
|
/** |
611 |
|
|
@TODO FIXME Note, at present this default library path only caters for a |
612 |
|
|
** SINGLE PATH COMPONENT ** |
613 |
|
|
|
614 |
|
|
@TODO Also, what about ASCEND_DEFAULTLIBRARY ? |
615 |
|
|
*/ |
616 |
|
|
if(librarydir == NULL){ |
617 |
johnpye |
589 |
CONSOLE_DEBUG("NO " ASC_ENV_LIBRARY " VAR DEFINED"); |
618 |
johnpye |
586 |
libraryfp = ospath_new_expand_env("$ASCENDDIST/models", &GETENV); |
619 |
johnpye |
589 |
CONSOLE_DEBUG("CREATED LIBRARY VAL"); |
620 |
johnpye |
586 |
OSPATH_PUTENV(ASC_ENV_LIBRARY,libraryfp); |
621 |
johnpye |
588 |
librarydir = ospath_str(libraryfp); |
622 |
johnpye |
586 |
} |
623 |
|
|
|
624 |
|
|
CONSOLE_DEBUG("CHECKING FOR AscendRC FILE"); |
625 |
|
|
|
626 |
|
|
fp1 = ospath_new("AscendRC"); |
627 |
|
|
fp = ospath_concat(tkfp,fp1); |
628 |
|
|
ospath_free(fp1); |
629 |
johnpye |
742 |
f = ospath_fopen(fp,"r"); |
630 |
johnpye |
586 |
if(f==NULL){ |
631 |
|
|
if(guessedtk){ |
632 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
633 |
|
|
"Cannot located AscendRC file in expected (guessed) location:\n%s\n" |
634 |
|
|
"Please set the %s environment variable to the correct location (typically\n" |
635 |
|
|
"it would be c:\\Program Files\\ASCEND\\TK or /usr/share/ascend/tcltk/TK. You\n" |
636 |
|
|
"should do this, then start ASCEND again." |
637 |
|
|
,tkdir,ASC_ENV_TK |
638 |
|
|
); |
639 |
|
|
}else{ |
640 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
641 |
|
|
"Cannot located AscendRC file in the specified location:\n%s\n" |
642 |
|
|
"Please check your value for the %s environment variable.\n" |
643 |
|
|
,tkdir,ASC_ENV_TK |
644 |
|
|
); |
645 |
|
|
} |
646 |
|
|
/* can't get here, hopefully */ |
647 |
|
|
} |
648 |
|
|
fclose(f); |
649 |
|
|
/* reuse 'envcmd' to get the string file location for AscendRC */ |
650 |
johnpye |
742 |
ospath_strncpy(fp,envcmd,MAX_ENV_VAR_LENGTH); |
651 |
johnpye |
586 |
ospath_free(fp); |
652 |
|
|
|
653 |
|
|
/* export the value to Tcl/Tk */ |
654 |
|
|
ASC_SEND_TO_TCL(tcl_rcFileName, envcmd); |
655 |
|
|
|
656 |
|
|
/* send all the environment variables to Tcl/Tk as well */ |
657 |
|
|
ASC_SEND_TO_TCL2(env,ASC_ENV_DIST,distdir); |
658 |
|
|
ASC_SEND_TO_TCL2(env,ASC_ENV_LIBRARY,librarydir); |
659 |
|
|
ASC_SEND_TO_TCL2(env,ASC_ENV_BITMAPS,bitmapsdir); |
660 |
|
|
ASC_SEND_TO_TCL2(env,ASC_ENV_TK,tkdir); |
661 |
johnpye |
571 |
} |
662 |
|
|
|
663 |
|
|
|
664 |
johnpye |
586 |
|
665 |
johnpye |
670 |
/** |
666 |
|
|
Look for ~/.ascendrc; if found, set the Tcl variable tcl_rcFileName |
667 |
|
|
to this file's location. This overrides the value set in |
668 |
|
|
AscCheckEnvironVars(). |
669 |
|
|
If ~/_ascendrc is available it only gets used if ~/.ascendrc is not. |
670 |
|
|
Returns a standard Tcl return code. |
671 |
|
|
*/ |
672 |
johnpye |
571 |
static int AscSetStartupFile(Tcl_Interp *interp) |
673 |
|
|
{ |
674 |
|
|
char *fullname; /* try to find this if first fails */ |
675 |
|
|
Tcl_DString buffer; |
676 |
|
|
Tcl_Channel c; /* used to check for file existance */ |
677 |
|
|
|
678 |
|
|
Tcl_ResetResult(interp); |
679 |
|
|
|
680 |
|
|
fullname = Tcl_TranslateFileName( interp, "~/.ascendrc", &buffer ); |
681 |
|
|
if( fullname != NULL ) { |
682 |
|
|
/* |
683 |
|
|
* Use the Tcl file channel routines to determine if ~/.ascendrc |
684 |
|
|
* exists. We cannot use access() since Windows doesn't use it. |
685 |
|
|
*/ |
686 |
|
|
c = Tcl_OpenFileChannel( NULL, fullname, "r", 0 ); |
687 |
|
|
if( c != (Tcl_Channel)NULL ) { |
688 |
|
|
/* file exists. close the channel and set tcl_rcFileName. */ |
689 |
|
|
Tcl_Close( NULL, c ); |
690 |
|
|
Tcl_SetVar(interp, "tcl_rcFileName", fullname, TCL_GLOBAL_ONLY); |
691 |
|
|
Tcl_DStringFree(&buffer); |
692 |
|
|
return TCL_OK; |
693 |
|
|
} |
694 |
|
|
Tcl_DStringFree(&buffer); |
695 |
|
|
} |
696 |
|
|
fullname = Tcl_TranslateFileName( interp, "~/_ascendrc", &buffer ); |
697 |
|
|
if( fullname != NULL ) { |
698 |
|
|
/* |
699 |
|
|
* Use the Tcl file channel routines to determine if ~/_ascendrc |
700 |
|
|
* exists. We cannot use access() since Windows doesn't use it. |
701 |
|
|
*/ |
702 |
|
|
c = Tcl_OpenFileChannel( NULL, fullname, "r", 0 ); |
703 |
|
|
if( c != (Tcl_Channel)NULL ) { |
704 |
|
|
/* file exists. close the channel and set tcl_rcFileName */ |
705 |
|
|
Tcl_Close( NULL, c ); |
706 |
|
|
Tcl_SetVar(interp, "tcl_rcFileName", fullname, TCL_GLOBAL_ONLY); |
707 |
|
|
Tcl_DStringFree(&buffer); |
708 |
|
|
return TCL_OK; |
709 |
|
|
} |
710 |
|
|
Tcl_DStringFree(&buffer); |
711 |
|
|
} |
712 |
|
|
return TCL_OK; /* probably should be TCL_ERROR */ |
713 |
|
|
} |
714 |
|
|
|
715 |
|
|
|
716 |
johnpye |
670 |
/** |
717 |
|
|
Process the options given on the command line `argv' where `argc' is |
718 |
|
|
the length of argv. |
719 |
johnpye |
742 |
|
720 |
johnpye |
670 |
Strip out ASCEND specific flags and then pass the rest to Tcl so it |
721 |
|
|
can set what it needs. |
722 |
johnpye |
742 |
|
723 |
johnpye |
670 |
This function may call exit() if the user requests help. |
724 |
johnpye |
571 |
*/ |
725 |
|
|
static int AscProcessCommandLine(Tcl_Interp *interp, int argc, CONST char **argv) |
726 |
|
|
{ |
727 |
|
|
int i; |
728 |
|
|
int flag; /* set to 1 for `+arg', -1 for `-arg' */ |
729 |
|
|
size_t length; /* length of an argv */ |
730 |
|
|
char *args; |
731 |
|
|
char buf[MAXIMUM_NUMERIC_LENGTH]; /* space for integer->string conversion */ |
732 |
|
|
int new_argc = 0; /* the argc we will pass to Tcl */ |
733 |
|
|
#ifdef ZZ_DEBUG |
734 |
|
|
zz_debug = 0; /* nonzero to print parser debugging info*/ |
735 |
|
|
#endif |
736 |
|
|
|
737 |
|
|
for( i = 1; i < argc; i++ ) { |
738 |
|
|
if( (length = strlen(argv[i])) == 0 ) { |
739 |
|
|
/* ignore 0-length arguments */ |
740 |
|
|
continue; |
741 |
|
|
} |
742 |
|
|
|
743 |
|
|
if(( length >= 2 ) && ( strncmp(argv[i],"-h",2) == 0 )) { |
744 |
|
|
AscPrintHelpExit(argv[0]); |
745 |
|
|
} |
746 |
|
|
if(( length >= 2 ) && ( strncmp(argv[i],"-H",2) == 0 )) { |
747 |
|
|
AscPrintHelpExit(argv[0]); |
748 |
|
|
} |
749 |
|
|
if(( length >= 4 ) && ( strncmp(argv[i],"help",4) == 0 )) { |
750 |
|
|
AscPrintHelpExit(argv[0]); |
751 |
|
|
} |
752 |
|
|
|
753 |
|
|
if( argv[i][0] == '-' ) { |
754 |
|
|
flag = -1; |
755 |
|
|
} else if( argv[i][0] == '+' ) { |
756 |
|
|
flag = 1; |
757 |
|
|
} else { |
758 |
|
|
flag = 0; |
759 |
|
|
} |
760 |
|
|
|
761 |
|
|
if(( length == 2 ) && ( flag != 0 )) { |
762 |
|
|
switch( argv[i][1] ) { |
763 |
|
|
case 'd': |
764 |
|
|
/* '-d' turns on scanner debugging (if ascend was built with it) |
765 |
|
|
* '+d' turns off scanner debugging [default] |
766 |
|
|
*/ |
767 |
|
|
if( flag == -1 ) { |
768 |
|
|
#ifdef ZZ_DEBUG |
769 |
|
|
zz_debug = 1; |
770 |
|
|
} else { |
771 |
|
|
zz_debug = 0; |
772 |
|
|
#else |
773 |
|
|
FPRINTF(ASCERR, "Sorry, %s wasn't compiled with %s defined.\n", |
774 |
|
|
argv[0], "ZZ_DEBUG"); |
775 |
|
|
#endif /* ZZ_DEBUG */ |
776 |
|
|
} |
777 |
|
|
break; |
778 |
|
|
case 's': |
779 |
|
|
/* '-s' turns on compiler optimizations [default] |
780 |
|
|
* '+s' turns off compiler optimizations |
781 |
|
|
*/ |
782 |
|
|
if( flag == -1 ) { |
783 |
|
|
g_interface_simplify_relations = 1; |
784 |
|
|
} else { |
785 |
|
|
g_interface_simplify_relations = 0; |
786 |
|
|
} |
787 |
|
|
break; |
788 |
|
|
case 't': |
789 |
|
|
/* '-t' turns on timing of compiler optimizations |
790 |
|
|
* '+t' turns off timing of compiler optimizations [default] |
791 |
|
|
*/ |
792 |
|
|
if( flag == 0 ) { |
793 |
|
|
g_compiler_timing = 1; |
794 |
|
|
} else { |
795 |
|
|
g_compiler_timing = 0; |
796 |
|
|
} |
797 |
|
|
break; |
798 |
|
|
case 'c': |
799 |
|
|
case 'g': |
800 |
|
|
fprintf(ASCERR, "WARNING! Obsolete ASCEND option \"%s\"\n", argv[i]); |
801 |
|
|
break; |
802 |
|
|
default: |
803 |
|
|
/* unknown ASCEND option, pass it on to Tcl |
804 |
|
|
*/ |
805 |
|
|
argv[++new_argc] = argv[i]; |
806 |
|
|
break; |
807 |
|
|
} |
808 |
|
|
} else { |
809 |
|
|
/* unknown ASCEND option, pass it on to Tcl |
810 |
|
|
*/ |
811 |
|
|
argv[++new_argc] = argv[i]; |
812 |
|
|
} |
813 |
|
|
} |
814 |
|
|
|
815 |
|
|
/* |
816 |
|
|
* Make command-line arguments available in the Tcl variables "argc" |
817 |
|
|
* and "argv". |
818 |
|
|
*/ |
819 |
|
|
args = Tcl_Merge(new_argc, (argv+1)); |
820 |
|
|
Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY); |
821 |
|
|
ckfree(args); |
822 |
|
|
sprintf(buf, "%d", new_argc); |
823 |
|
|
Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY); |
824 |
|
|
Tcl_SetVar(interp, "argv0", argv[0], TCL_GLOBAL_ONLY); |
825 |
|
|
|
826 |
|
|
return TCL_OK; |
827 |
|
|
} |
828 |
|
|
|
829 |
|
|
|
830 |
johnpye |
670 |
/** |
831 |
|
|
Print a help message and exit. Use invoke_name as the name of the binary |
832 |
|
|
*/ |
833 |
johnpye |
571 |
static |
834 |
|
|
void AscPrintHelpExit(CONST char *invoke_name) |
835 |
|
|
{ |
836 |
|
|
PRINTF("usage: %s [options]\n" |
837 |
|
|
"\n" |
838 |
|
|
"where options include [default value]:\n" |
839 |
|
|
" -h print this message\n" |
840 |
|
|
" -/+d turn on/off yacc debugging [off]\n" |
841 |
|
|
" -/+s turn on/off compiler optimizations [on]\n" |
842 |
|
|
" -/+t turn on/off timing of compiler operations [off]\n", |
843 |
|
|
invoke_name); |
844 |
|
|
Tcl_Exit(0); /* Show this help message and leave */ |
845 |
|
|
} |
846 |
|
|
|
847 |
|
|
|
848 |
johnpye |
1142 |
#ifdef ASC_SIGNAL_TRAPS |
849 |
johnpye |
670 |
/** |
850 |
|
|
Function to call when we receive an interrupt. |
851 |
johnpye |
571 |
*/ |
852 |
|
|
static |
853 |
|
|
void AscTrap(int sig) |
854 |
|
|
{ |
855 |
|
|
putchar('\n'); |
856 |
|
|
Asc_Panic(sig, "AscTrap", "Caught Signal: %d", sig); |
857 |
|
|
} |
858 |
johnpye |
1142 |
#endif |
859 |
johnpye |
571 |
|
860 |
|
|
int Asc_LoadWin(ClientData cdata, Tcl_Interp *interp, |
861 |
|
|
int argc, CONST84 char *argv[]) |
862 |
|
|
{ |
863 |
johnpye |
670 |
UNUSED_PARAMETER(cdata); |
864 |
johnpye |
571 |
(void)argv; /* stop gcc whine about unused parameter */ |
865 |
|
|
|
866 |
|
|
if ( argc != 1 ) { |
867 |
|
|
FPRINTF(stderr,"call is: ascloadwin <no args> \n"); |
868 |
|
|
return TCL_ERROR; |
869 |
|
|
} |
870 |
|
|
if (g_interfacever) { |
871 |
|
|
Tcl_SetResult(interp, "1", TCL_STATIC); |
872 |
|
|
} else { |
873 |
|
|
Tcl_SetResult(interp, "0", TCL_STATIC); |
874 |
|
|
} |
875 |
|
|
return TCL_OK; |
876 |
|
|
} |
877 |
|
|
|
878 |
johnpye |
670 |
/*--------------------------------------------------------------------- |
879 |
|
|
The following StdinProc() and Prompt() are from tkMain.c in |
880 |
|
|
the Tk4.1 distribution (and did not change in Tk8.0). |
881 |
|
|
----------------------------------------------------------------------*/ |
882 |
johnpye |
571 |
|
883 |
johnpye |
670 |
/** |
884 |
|
|
This procedure is invoked by the event dispatcher whenever |
885 |
|
|
standard input becomes readable. It grabs the next line of |
886 |
|
|
input characters, adds them to a command being assembled, and |
887 |
|
|
executes the command if it's complete. |
888 |
johnpye |
742 |
|
889 |
johnpye |
670 |
Results: |
890 |
|
|
None. |
891 |
johnpye |
742 |
|
892 |
johnpye |
670 |
Side effects: |
893 |
|
|
Could be almost arbitrary, depending on the command that's |
894 |
|
|
typed. |
895 |
|
|
*/ |
896 |
johnpye |
571 |
static void |
897 |
|
|
StdinProc(ClientData clientData, int mask) |
898 |
|
|
{ |
899 |
|
|
static int gotPartial = 0; |
900 |
|
|
char *cmd; |
901 |
|
|
int code, count; |
902 |
|
|
Tcl_Channel chan = (Tcl_Channel) clientData; |
903 |
|
|
|
904 |
|
|
Tcl_Interp *interp = g_interp; /* use a local copy of the |
905 |
|
|
* global tcl interpreter |
906 |
|
|
*/ |
907 |
|
|
|
908 |
|
|
(void)clientData; /* stop gcc whine about unused parameter */ |
909 |
|
|
(void)mask; /* stop gcc whine about unused parameter */ |
910 |
|
|
|
911 |
|
|
count = Tcl_Gets(chan, &g_line); |
912 |
|
|
|
913 |
|
|
if (count < 0) { |
914 |
|
|
if (!gotPartial) { |
915 |
|
|
if (tty) { |
916 |
|
|
return; |
917 |
|
|
} else { |
918 |
|
|
Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan); |
919 |
|
|
} |
920 |
|
|
return; |
921 |
|
|
} else { |
922 |
|
|
count = 0; |
923 |
|
|
} |
924 |
|
|
} |
925 |
|
|
|
926 |
|
|
(void) Tcl_DStringAppend(&g_command, Tcl_DStringValue(&g_line), -1); |
927 |
|
|
cmd = Tcl_DStringAppend(&g_command, "\n", -1); |
928 |
|
|
Tcl_DStringFree(&g_line); |
929 |
|
|
|
930 |
|
|
if (!Tcl_CommandComplete(cmd)) { |
931 |
|
|
gotPartial = 1; |
932 |
|
|
goto prompt; |
933 |
|
|
} |
934 |
|
|
gotPartial = 0; |
935 |
|
|
|
936 |
|
|
/* |
937 |
|
|
* Disable the stdin channel handler while evaluating the command; |
938 |
|
|
* otherwise if the command re-enters the event loop we might |
939 |
|
|
* process commands from stdin before the current command is |
940 |
|
|
* finished. Among other things, this will trash the text of the |
941 |
|
|
* command being evaluated. |
942 |
|
|
*/ |
943 |
|
|
|
944 |
|
|
Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan); |
945 |
|
|
code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL); |
946 |
|
|
Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, |
947 |
|
|
(ClientData) chan); |
948 |
|
|
Tcl_DStringFree(&g_command); |
949 |
|
|
if (*interp->result != 0) { |
950 |
|
|
if ((code != TCL_OK) || (tty)) { |
951 |
|
|
/* |
952 |
|
|
* The statement below used to call "printf", but that resulted |
953 |
|
|
* in core dumps under Solaris 2.3 if the result was very long. |
954 |
|
|
* |
955 |
|
|
* NOTE: This probably will not work under Windows either. |
956 |
|
|
*/ |
957 |
|
|
|
958 |
|
|
puts(interp->result); |
959 |
|
|
} |
960 |
|
|
} |
961 |
|
|
|
962 |
|
|
/* |
963 |
|
|
* Output a prompt. |
964 |
|
|
*/ |
965 |
|
|
|
966 |
|
|
prompt: |
967 |
|
|
if (tty) { |
968 |
|
|
Prompt(interp, gotPartial); |
969 |
|
|
} |
970 |
|
|
Tcl_ResetResult(interp); |
971 |
|
|
} |
972 |
|
|
|
973 |
johnpye |
670 |
/** |
974 |
|
|
Issue a prompt on standard output, or invoke a script |
975 |
|
|
to issue the prompt. |
976 |
johnpye |
742 |
|
977 |
johnpye |
670 |
Results: |
978 |
|
|
None. |
979 |
johnpye |
742 |
|
980 |
johnpye |
670 |
Side effects: |
981 |
|
|
A prompt gets output, and a Tcl script may be evaluated |
982 |
|
|
in interp. |
983 |
johnpye |
742 |
|
984 |
johnpye |
670 |
Parameters: |
985 |
|
|
interp Interpreter to use for prompting. |
986 |
|
|
partial Non-zero means there already exists a partial |
987 |
|
|
command, so use the secondary prompt. |
988 |
|
|
*/ |
989 |
johnpye |
571 |
static void |
990 |
|
|
Prompt(Tcl_Interp *interp, int partial) |
991 |
|
|
{ |
992 |
|
|
CONST84 char *promptCmd; |
993 |
|
|
int code; |
994 |
|
|
Tcl_Channel outChannel, errChannel; |
995 |
|
|
CONST84 char *subPrompt; |
996 |
|
|
|
997 |
|
|
errChannel = Tcl_GetChannel(interp, "stderr", NULL); |
998 |
|
|
|
999 |
|
|
subPrompt = (partial ? "tcl_prompt2" : "tcl_prompt1"); |
1000 |
|
|
promptCmd = Tcl_GetVar(interp, subPrompt, TCL_GLOBAL_ONLY); |
1001 |
|
|
if (promptCmd == NULL) { |
1002 |
|
|
defaultPrompt: |
1003 |
|
|
|
1004 |
|
|
/* |
1005 |
|
|
* We must check that outChannel is a real channel - it |
1006 |
|
|
* is possible that someone has transferred stdout out of |
1007 |
|
|
* this interpreter with "interp transfer". |
1008 |
|
|
*/ |
1009 |
|
|
|
1010 |
|
|
outChannel = Tcl_GetChannel(interp, "stdout", NULL); |
1011 |
|
|
if (outChannel != (Tcl_Channel) NULL) { |
1012 |
|
|
if (!partial) { |
1013 |
|
|
Tcl_Write(outChannel, "AscendIV% ", 10); |
1014 |
|
|
} else { |
1015 |
|
|
Tcl_Write(outChannel, "more? ", 6); |
1016 |
|
|
} |
1017 |
|
|
} |
1018 |
|
|
} else { |
1019 |
|
|
code = Tcl_Eval(interp, promptCmd); |
1020 |
|
|
if (code != TCL_OK) { |
1021 |
|
|
Tcl_AddErrorInfo(interp, |
1022 |
|
|
"\n (script that generates prompt)"); |
1023 |
|
|
/* |
1024 |
|
|
* We must check that errChannel is a real channel - it |
1025 |
|
|
* is possible that someone has transferred stderr out of |
1026 |
|
|
* this interpreter with "interp transfer". |
1027 |
|
|
*/ |
1028 |
|
|
|
1029 |
|
|
errChannel = Tcl_GetChannel(interp, "stderr", NULL); |
1030 |
|
|
if (errChannel != (Tcl_Channel) NULL) { |
1031 |
|
|
Tcl_Write(errChannel, interp->result, -1); |
1032 |
|
|
Tcl_Write(errChannel, "\n", 1); |
1033 |
|
|
} |
1034 |
|
|
goto defaultPrompt; |
1035 |
|
|
} |
1036 |
|
|
} |
1037 |
|
|
outChannel = Tcl_GetChannel(interp, "stdout", NULL); |
1038 |
|
|
if (outChannel != (Tcl_Channel) NULL) { |
1039 |
|
|
Tcl_Flush(outChannel); |
1040 |
|
|
} |
1041 |
|
|
} |
1042 |
johnpye |
670 |
|
1043 |
johnpye |
571 |
#ifdef DEBUG_MALLOC |
1044 |
johnpye |
670 |
/** |
1045 |
|
|
Tom Epperly's Malloc Debugger |
1046 |
|
|
*/ |
1047 |
johnpye |
571 |
static void InitDebugMalloc(void) |
1048 |
|
|
{ |
1049 |
|
|
union dbmalloptarg m; |
1050 |
|
|
m.str = NULL; |
1051 |
|
|
m.i = 0; |
1052 |
|
|
dbmallopt(MALLOC_CKDATA,&m); |
1053 |
|
|
} |
1054 |
|
|
|
1055 |
|
|
int Asc_DebugMallocCmd(ClientData cdata, Tcl_Interp *interp, |
1056 |
|
|
int argc, CONST84 char *argv[]) |
1057 |
|
|
{ |
1058 |
|
|
union dbmalloptarg m; |
1059 |
|
|
|
1060 |
|
|
if ( argc != 2 ) { |
1061 |
|
|
Tcl_SetResult(interp, "wrong # args : Usage __dbmalloc ?on?off?", |
1062 |
|
|
TCL_STATIC); |
1063 |
|
|
return TCL_ERROR; |
1064 |
|
|
} |
1065 |
|
|
m.str = NULL; |
1066 |
|
|
if (strcmp(argv[1],"on")==0) { |
1067 |
|
|
m.i = 1; |
1068 |
|
|
} else if (strcmp(argv[1],"off")==0) { |
1069 |
|
|
m.i = 0; |
1070 |
|
|
} else { |
1071 |
|
|
Tcl_SetResult(interp, "incorrect args : should be \"on\" or \"off\"", |
1072 |
|
|
TCL_STATIC); |
1073 |
|
|
return TCL_ERROR; |
1074 |
|
|
} |
1075 |
|
|
dbmallopt(MALLOC_CKDATA,&m); /* turn on str* mem* and b* checking */ |
1076 |
|
|
return TCL_OK; |
1077 |
|
|
} |
1078 |
|
|
#endif /* DEBUG_MALLOC */ |