1 |
aw0a |
1 |
/* |
2 |
|
|
* Driver.c |
3 |
|
|
* by Kirk Abbott and Ben Allan |
4 |
|
|
* Created: 1/94 |
5 |
|
|
* Version: $Revision: 1.48 $ |
6 |
|
|
* Version control file: $RCSfile: Driver.c,v $ |
7 |
|
|
* Date last modified: $Date: 2003/08/23 18:43:06 $ |
8 |
|
|
* Last modified by: $Author: ballan $ |
9 |
|
|
* |
10 |
|
|
* This file is part of the ASCEND Tcl/Tk interface |
11 |
|
|
* |
12 |
|
|
* Copyright 1997, Carnegie Mellon University |
13 |
|
|
* |
14 |
|
|
* The ASCEND Tcl/Tk interface is free software; you can redistribute |
15 |
|
|
* it and/or modify it under the terms of the GNU General Public License as |
16 |
|
|
* published by the Free Software Foundation; either version 2 of the |
17 |
|
|
* License, or (at your option) any later version. |
18 |
|
|
* |
19 |
|
|
* The ASCEND Tcl/Tk interface is distributed in hope that it will be |
20 |
|
|
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
22 |
|
|
* General Public License for more details. |
23 |
|
|
* |
24 |
|
|
* You should have received a copy of the GNU General Public License |
25 |
|
|
* along with the program; if not, write to the Free Software Foundation, |
26 |
|
|
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
27 |
|
|
* COPYING. COPYING is found in ../compiler. |
28 |
|
|
*/ |
29 |
|
|
|
30 |
|
|
#include <stdarg.h> |
31 |
|
|
#include <ctype.h> |
32 |
|
|
#include <signal.h> |
33 |
|
|
#include <time.h> |
34 |
|
|
#include "tcl.h" |
35 |
|
|
#include "tk.h" |
36 |
|
|
#include "utilities/ascConfig.h" |
37 |
|
|
#ifndef __WIN32__ |
38 |
|
|
#include <unistd.h> |
39 |
|
|
#else |
40 |
|
|
#define WIN32_LEAN_AND_MEAN |
41 |
|
|
#include <windows.h> |
42 |
|
|
#include <locale.h> |
43 |
|
|
#undef WIN32_LEAN_AND_MEAN |
44 |
|
|
#endif /* __WIN32__ */ |
45 |
|
|
#include "utilities/ascMalloc.h" /* for ascshutdown */ |
46 |
|
|
#include "utilities/ascPanic.h" /* for Asc_Panic */ |
47 |
|
|
#include "utilities/ascEnvVar.h" |
48 |
|
|
#include "compiler/compiler.h" |
49 |
|
|
#include "compiler/ascCompiler.h" |
50 |
|
|
#include "compiler/instance_enum.h" |
51 |
|
|
#include "compiler/fractions.h" |
52 |
|
|
#include "compiler/dimen.h" |
53 |
|
|
#include "compiler/compiler.h" /* for symchar for units.h */ |
54 |
|
|
#include "compiler/units.h" |
55 |
|
|
#include "solver/slv_types.h" |
56 |
|
|
#include "solver/var.h" |
57 |
|
|
#include "solver/rel.h" |
58 |
|
|
#include "solver/logrel.h" |
59 |
|
|
#include "solver/discrete.h" |
60 |
|
|
#include "solver/mtx.h" |
61 |
|
|
#include "solver/slv_stdcalls.h" |
62 |
|
|
#include "interface/AscBitmaps.h" |
63 |
|
|
#include "interface/HelpProc.h" |
64 |
|
|
#include "interface/Commands.h" |
65 |
|
|
#include "interface/Driver.h" |
66 |
|
|
#include "interface/ScriptProc.h" |
67 |
|
|
#include "interface/SolverProc.h" |
68 |
|
|
#include "interface/UnitsProc.h" |
69 |
|
|
|
70 |
|
|
#ifndef lint |
71 |
|
|
static CONST char DriverID[] = "$Id: Driver.c,v 1.48 2003/08/23 18:43:06 ballan Exp $"; |
72 |
|
|
#endif |
73 |
|
|
|
74 |
|
|
|
75 |
|
|
/* |
76 |
|
|
* The following are the environment variables ASCEND requires. |
77 |
|
|
* If the user does not have the DIST_ENVIRONVAR set in his or her |
78 |
|
|
* environment, a default value is set based on the directory where the |
79 |
|
|
* ascend binary lives. The other enviornment variables will be set |
80 |
|
|
* to default values keyed off of DIST_ENVIRONVAR. See the function |
81 |
|
|
* CheckEnvironmentVars later in this file for the details. |
82 |
|
|
*/ |
83 |
|
|
#define DIST_ENVIRONVAR "ASCENDDIST" |
84 |
|
|
#define ASCTK_ENVIRONVAR "ASCENDTK" |
85 |
|
|
#define BITMAP_ENVIRONVAR "ASCENDBITMAPS" |
86 |
|
|
#define LIBR_ENVIRONVAR "ASCENDLIBRARY" |
87 |
|
|
|
88 |
|
|
/* |
89 |
|
|
* EXPORTED VARIABLES |
90 |
|
|
*/ |
91 |
|
|
|
92 |
|
|
/** |
93 |
|
|
* g_compiler_timing |
94 |
|
|
* |
95 |
|
|
* TRUE if compiler timing is to be printed. |
96 |
|
|
* default is false, set to TRUE by passing -t on the command line |
97 |
|
|
*/ |
98 |
|
|
int g_compiler_timing = 0; |
99 |
|
|
|
100 |
|
|
/** |
101 |
|
|
* g_interp |
102 |
|
|
* |
103 |
|
|
* Interpreter for this application. We need to make it global |
104 |
|
|
* so that our signal/floating-porint traps can access it. |
105 |
|
|
*/ |
106 |
|
|
Tcl_Interp *g_interp; |
107 |
|
|
|
108 |
|
|
/* |
109 |
|
|
* zz_debug |
110 |
|
|
* |
111 |
|
|
* Comes from the yacc file if yacc was built with debugging information |
112 |
|
|
*/ |
113 |
|
|
#ifdef ZZ_DEBUG |
114 |
|
|
extern int zz_debug; |
115 |
|
|
#endif |
116 |
|
|
|
117 |
|
|
|
118 |
|
|
/* |
119 |
|
|
* Declarations for procedures defined outside of this file. |
120 |
|
|
*/ |
121 |
|
|
extern int Tktable_Init(Tcl_Interp*); |
122 |
|
|
|
123 |
|
|
/* |
124 |
|
|
* Forward declarations for procedures defined later in this file. |
125 |
|
|
*/ |
126 |
|
|
static int AscDriver(int, CONST84 char * argv[]); |
127 |
|
|
static void AscTrap(int); |
128 |
|
|
static int AscCheckEnvironVars(Tcl_Interp*); |
129 |
|
|
static void AscPrintHelpExit(CONST char *); |
130 |
|
|
static int AscProcessCommandLine(Tcl_Interp*, int, CONST84 char **); |
131 |
|
|
static void Prompt(Tcl_Interp*, int); |
132 |
|
|
static int AscSetStartupFile(Tcl_Interp*); |
133 |
|
|
static void StdinProc(ClientData, int); |
134 |
|
|
#ifdef DEBUG_MALLOC |
135 |
|
|
static void InitDebugMalloc(void); |
136 |
|
|
#endif /* DEBUG_MALLOC */ |
137 |
|
|
#ifdef __WIN32__ |
138 |
|
|
static void setargv(int*, char ***); |
139 |
|
|
#endif /* __WIN32__ */ |
140 |
|
|
|
141 |
|
|
|
142 |
|
|
/* |
143 |
|
|
* LOCALLY GLOBAL VARIABLES |
144 |
|
|
*/ |
145 |
|
|
|
146 |
|
|
/* |
147 |
|
|
* g_interface_simplify_relations |
148 |
|
|
* |
149 |
|
|
* TRUE for compiler optimizations |
150 |
|
|
* default is TRUE, set to FALSE by passing +s on the command line |
151 |
|
|
*/ |
152 |
|
|
static int g_interface_simplify_relations = TRUE; |
153 |
|
|
|
154 |
|
|
/* |
155 |
|
|
* g_interfacever |
156 |
|
|
* |
157 |
|
|
* TRUE if windows to be built; default is TRUE, false is not supported |
158 |
|
|
*/ |
159 |
|
|
static int g_interfacever = 1; |
160 |
|
|
|
161 |
|
|
/* |
162 |
|
|
* g_command |
163 |
|
|
* |
164 |
|
|
* Used to assemble lines of terminal input into Tcl commands. |
165 |
|
|
*/ |
166 |
|
|
static Tcl_DString g_command; |
167 |
|
|
|
168 |
|
|
/* |
169 |
|
|
* g_line |
170 |
|
|
* |
171 |
|
|
* Used to read the next line from the terminal input. |
172 |
|
|
*/ |
173 |
|
|
static Tcl_DString g_line; |
174 |
|
|
|
175 |
|
|
/* |
176 |
|
|
* tty |
177 |
|
|
* |
178 |
|
|
* Non-zero means standard input is a terminal-like device. |
179 |
|
|
* Zero means it's a file. |
180 |
|
|
*/ |
181 |
|
|
static int tty; |
182 |
|
|
|
183 |
|
|
/* |
184 |
|
|
* initScriptTclAdjust |
185 |
|
|
* initScriptTkAdjust |
186 |
|
|
* |
187 |
|
|
* These two variables hold Tcl scripts that will set the TCL_LIBRARY |
188 |
|
|
* and TK_LIBRARY environment variables if they are not already |
189 |
|
|
* set in the user's environment. |
190 |
|
|
* TCL_LIBRARY is set to: dirnameofexecutable/../../Tcl/lib/tcl8.0 |
191 |
|
|
* TK_LIBRARY is set to $tcl_library/../tk8.0 |
192 |
|
|
*/ |
193 |
|
|
static char initScriptTclAdjust[] = |
194 |
|
|
"proc asc_tclInit {} {\n\ |
195 |
|
|
global env\n\ |
196 |
|
|
rename asc_tclInit {}\n\ |
197 |
|
|
set errors {}\n\ |
198 |
|
|
set dirs {}\n\ |
199 |
|
|
if [info exists env(TCL_LIBRARY)] {\n\ |
200 |
|
|
return\n\ |
201 |
|
|
} else {\n\ |
202 |
|
|
set parentDir [file dirname [info nameofexecutable]]\n\ |
203 |
|
|
set env(TCL_LIBRARY) $parentDir/../../Tcl/lib/tcl8.0\n\ |
204 |
|
|
}\n\ |
205 |
|
|
}\n\ |
206 |
|
|
asc_tclInit"; |
207 |
|
|
/* for tcl, FOO/ascend4/bin/ascend4.exe is the executable, then |
208 |
|
|
* /-- up to FOO/ascend4/bin |
209 |
|
|
* set parentDir [file dirname [info nameofexecutable]]\n\ |
210 |
|
|
* Then if Tcl is next to ascend4, ../../Tcl/lib/tcl8.0 should work. |
211 |
|
|
*/ |
212 |
|
|
|
213 |
|
|
static char initScriptTkAdjust[] = |
214 |
|
|
"proc asc_tkInit {} {\n\ |
215 |
|
|
global env\n\ |
216 |
|
|
rename asc_tkInit {}\n\ |
217 |
|
|
set errors {}\n\ |
218 |
|
|
set dirs {}\n\ |
219 |
|
|
if [info exists env(TK_LIBRARY)] {\n\ |
220 |
|
|
return\n\ |
221 |
|
|
} else {\n\ |
222 |
|
|
set parentDir [file dirname [info library]]\n\ |
223 |
|
|
set env(TK_LIBRARY) $parentDir/tk8.0\n\ |
224 |
|
|
}\n\ |
225 |
|
|
}\n\ |
226 |
|
|
asc_tkInit"; |
227 |
|
|
/* |
228 |
|
|
* This assumes tcl_library has been found and that tcl8.0 and tk8.0 |
229 |
|
|
* are installed in the same lib directory -- the default tcl/tk install. |
230 |
|
|
*/ |
231 |
|
|
|
232 |
|
|
/* |
233 |
|
|
* build_name |
234 |
|
|
* |
235 |
|
|
* who built this binary and when |
236 |
|
|
*/ |
237 |
|
|
#ifndef TIMESTAMP |
238 |
|
|
static char build_name[]="by anonymous"; |
239 |
|
|
#else |
240 |
|
|
static char build_name[]=TIMESTAMP; |
241 |
|
|
#endif /* TIMESTAMP */ |
242 |
|
|
|
243 |
|
|
|
244 |
|
|
|
245 |
|
|
/* |
246 |
|
|
* main or WinMain |
247 |
|
|
* |
248 |
|
|
* The main entry point for a Unix or Windows application. |
249 |
|
|
* |
250 |
|
|
* Each just calls AscDriver(). |
251 |
|
|
* These are based on functions from the Tk 8.0 distribution. |
252 |
|
|
* See unix/tkAppInit.c and win/winMain.c in their sources. |
253 |
|
|
*/ |
254 |
|
|
#ifndef __WIN32__ |
255 |
|
|
|
256 |
|
|
int main(int argc, CONST84 char *argv[]) |
257 |
|
|
{ |
258 |
|
|
AscDriver(argc, argv); |
259 |
|
|
return 0; |
260 |
|
|
} |
261 |
|
|
|
262 |
|
|
#else /* __WIN32__ */ |
263 |
|
|
|
264 |
|
|
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, |
265 |
|
|
LPSTR lpszCmdLine, int nCmdShow) |
266 |
|
|
{ |
267 |
|
|
int argc; |
268 |
|
|
char **argv; |
269 |
|
|
char *p; |
270 |
|
|
char buffer[MAX_PATH]; |
271 |
|
|
|
272 |
|
|
/* |
273 |
|
|
* Set up the default locale to be standard "C" locale so parsing |
274 |
|
|
* is performed correctly. |
275 |
|
|
*/ |
276 |
|
|
setlocale(LC_ALL, "C"); |
277 |
|
|
|
278 |
|
|
/* |
279 |
|
|
* Increase the application queue size from default value of 8. |
280 |
|
|
* At the default value, cross application SendMessage of WM_KILLFOCUS |
281 |
|
|
* will fail because the handler will not be able to do a PostMessage! |
282 |
|
|
* This is only needed for Windows 3.x, since NT dynamically expands |
283 |
|
|
* the queue. |
284 |
|
|
*/ |
285 |
|
|
SetMessageQueue(64); |
286 |
|
|
|
287 |
|
|
/* |
288 |
|
|
* Create the console channels and install them as the standard |
289 |
|
|
* channels. All I/O will be discarded until TkConsoleInit is |
290 |
|
|
* called to attach the console to a text widget. |
291 |
|
|
*/ |
292 |
|
|
|
293 |
|
|
/* |
294 |
|
|
* Windows expects us to parse our arguments ourselves. |
295 |
|
|
*/ |
296 |
|
|
setargv(&argc, &argv); |
297 |
|
|
|
298 |
|
|
/* |
299 |
|
|
* Replace argv[0] with full pathname of executable, and forward |
300 |
|
|
* slashes substituted for backslashes. |
301 |
|
|
*/ |
302 |
|
|
GetModuleFileName(NULL, buffer, sizeof(buffer)); |
303 |
|
|
argv[0] = buffer; |
304 |
|
|
for (p = buffer; *p != '\0'; p++) { |
305 |
|
|
if (*p == '\\') { |
306 |
|
|
*p = '/'; |
307 |
|
|
} |
308 |
|
|
} |
309 |
|
|
|
310 |
|
|
AscDriver(argc, argv); |
311 |
|
|
return 1; |
312 |
|
|
} |
313 |
|
|
#endif /* __WIN32__ */ |
314 |
|
|
|
315 |
|
|
|
316 |
|
|
/* |
317 |
|
|
* int AscDriver( argc, argv ) |
318 |
|
|
* int argc; |
319 |
|
|
* char *argv; |
320 |
|
|
* |
321 |
|
|
* A common entry point for Windows and Unix. The corresponding |
322 |
|
|
* WinMain() and main() functions just call this function. |
323 |
|
|
* |
324 |
|
|
* This function creates a Tcl interpreter, initializes Tcl and Tk, |
325 |
|
|
* initializes the Ascend data structures, sets up the user's |
326 |
|
|
* environment, sources ASCEND's startup script, and calls Tk_MainLoop |
327 |
|
|
* so the user can interact with ASCEND. Cleans up and exits the |
328 |
|
|
* program when Tk_MainLoop returns. |
329 |
|
|
* |
330 |
|
|
* This function is based on the functions Tk_Main and Tcl_AppInit |
331 |
|
|
* from the Tk8.0 distribution. See the files tkMain.c and tkAppInit.c |
332 |
|
|
* in the Tk sources. |
333 |
|
|
* |
334 |
|
|
*/ |
335 |
|
|
static int AscDriver(int argc, CONST84 char *argv[]) |
336 |
|
|
{ |
337 |
|
|
Tcl_Interp *interp; /* local version of global g_interp */ |
338 |
|
|
Tcl_Channel inChannel; |
339 |
|
|
Tcl_Channel outChannel; |
340 |
|
|
|
341 |
|
|
/* |
342 |
|
|
* Create the Tk Console |
343 |
|
|
* |
344 |
|
|
* Create the console channels and install them as the standard |
345 |
|
|
* channels. All I/O will be discarded until TkConsoleInit() is |
346 |
|
|
* called to attach the console to a text widget. |
347 |
|
|
*/ |
348 |
|
|
#ifdef ASC_USE_TK_CONSOLE |
349 |
|
|
TkConsoleCreate(); |
350 |
|
|
#endif /* ASC_USE_TK_CONSOLE */ |
351 |
|
|
|
352 |
|
|
/* |
353 |
|
|
* Find the name of the current executable---available in the |
354 |
|
|
* Tcl command `info nameofexecutable' |
355 |
|
|
*/ |
356 |
|
|
Tcl_FindExecutable(argv[0]); |
357 |
|
|
|
358 |
|
|
/* |
359 |
|
|
* Create the interpreter |
360 |
|
|
*/ |
361 |
|
|
g_interp = Tcl_CreateInterp(); |
362 |
|
|
interp = g_interp; |
363 |
|
|
if( interp == NULL ) { |
364 |
|
|
Asc_Panic(2, "Asc_Driver", |
365 |
|
|
"Call to Tcl_CreateInterp returned NULL interpreter"); |
366 |
|
|
} |
367 |
|
|
|
368 |
|
|
/* |
369 |
|
|
* Check the arguments on the command line |
370 |
|
|
*/ |
371 |
|
|
AscProcessCommandLine(interp, argc, argv); |
372 |
|
|
|
373 |
|
|
/* |
374 |
|
|
* Set the "tcl_interactive" variable. |
375 |
|
|
* |
376 |
|
|
* ASCEND sets tty to `1', since we assume ASCEND is always interactive. |
377 |
|
|
*/ |
378 |
|
|
tty = 1; |
379 |
|
|
Tcl_SetVar(interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); |
380 |
|
|
|
381 |
|
|
/* |
382 |
|
|
* Initialize Tcl and Tk |
383 |
|
|
*/ |
384 |
|
|
(void)Tcl_Eval(interp,initScriptTclAdjust); |
385 |
|
|
if (Tcl_Init(interp) == TCL_ERROR) { |
386 |
|
|
Asc_Panic(2, "Asc_Driver", "Tcl initialization failed:\n%s", |
387 |
|
|
Tcl_GetStringResult(interp)); |
388 |
|
|
} |
389 |
|
|
(void)Tcl_Eval(interp,initScriptTkAdjust); |
390 |
|
|
if (Tk_Init(interp) == TCL_ERROR) { |
391 |
|
|
Asc_Panic(2, "Asc_Driver", "Tk initialization failed:\n%s", |
392 |
|
|
Tcl_GetStringResult(interp)); |
393 |
|
|
} |
394 |
|
|
Tcl_StaticPackage( interp, "Tk", Tk_Init, Tk_SafeInit ); |
395 |
|
|
|
396 |
|
|
/* |
397 |
|
|
* Initialize the console and the ASCEND printf() substitutes. |
398 |
|
|
* All output before this point is lost. |
399 |
|
|
*/ |
400 |
|
|
#ifdef ASC_USE_TK_CONSOLE |
401 |
|
|
if (TkConsoleInit(interp) == TCL_ERROR) { |
402 |
|
|
Asc_Panic(2, "Asc_Driver", |
403 |
|
|
"Call to TkConsoleInit failed:\n%s", |
404 |
|
|
Tcl_GetStringResult(interp)); |
405 |
|
|
} |
406 |
|
|
#endif /* ASC_USE_TK_CONSOLE */ |
407 |
|
|
#ifdef USE_ASC_PRINTF |
408 |
|
|
Asc_PrintInit(); |
409 |
|
|
#endif /* USE_ASC_PRINTF */ |
410 |
|
|
|
411 |
|
|
/* |
412 |
|
|
* Now that our console and printing functions are properly |
413 |
|
|
* initialized, print our startup banner. |
414 |
|
|
*/ |
415 |
|
|
PRINTF("ASCEND VERSION IV\n"); |
416 |
|
|
PRINTF("Compiler Implemention Version: 2.0\n"); |
417 |
|
|
PRINTF("Written by Tom Epperly,Kirk Abbott, and Ben Allan\n"); |
418 |
|
|
PRINTF(" Built: %s %s %s\n",__DATE__,__TIME__,build_name); |
419 |
|
|
PRINTF("Copyright(C) 1990, 1993, 1994 Thomas Guthrie Epperly\n"); |
420 |
|
|
PRINTF("Copyright(C) 1993-1996 Kirk Andre Abbott, Ben Allan\n"); |
421 |
|
|
PRINTF("Copyright(C) 1997 Carnegie Mellon University\n"); |
422 |
|
|
|
423 |
|
|
/* |
424 |
|
|
* Call the init procedures for included packages. |
425 |
|
|
*/ |
426 |
|
|
#ifdef STATIC_TKTABLE |
427 |
|
|
if( Tktable_Init(interp) == TCL_ERROR ) { |
428 |
|
|
Asc_Panic(2, "Asc_Driver", |
429 |
|
|
"Call to Tktable_Init failed:\n%s", |
430 |
|
|
Tcl_GetStringResult(interp)); |
431 |
|
|
} |
432 |
|
|
#endif /* STATIC_TKTABLE */ |
433 |
|
|
|
434 |
|
|
/* |
435 |
|
|
* Initialize ASCEND C Structures |
436 |
|
|
* Create ASCEND Tcl Commands |
437 |
|
|
*/ |
438 |
|
|
clock(); |
439 |
|
|
/* the next line should NOT be Asc_SignalHandlerPush */ |
440 |
|
|
(void)signal(SIGINT, AscTrap); |
441 |
|
|
#ifdef DEBUG_MALLOC |
442 |
|
|
InitDebugMalloc(); |
443 |
|
|
ascstatus("Memory status after calling InitDebugMalloc()"); |
444 |
|
|
#endif /* DEBUG_MALLOC */ |
445 |
|
|
if ( Asc_CompilerInit(g_interface_simplify_relations) != 0 ) { |
446 |
|
|
Asc_Panic(2, "Asc_CompilerInit", |
447 |
|
|
"Insufficient memory to initialize compiler."); |
448 |
|
|
} |
449 |
|
|
SlvRegisterStandardClients(); |
450 |
|
|
if( Asc_HelpInit() == TCL_ERROR ) { |
451 |
|
|
Asc_Panic(2, "Asc_HelpInit", |
452 |
|
|
"Insufficient memory to initialize help system."); |
453 |
|
|
} |
454 |
|
|
Asc_CreateCommands(interp); |
455 |
|
|
Asc_RegisterBitmaps(interp); |
456 |
|
|
|
457 |
|
|
/* |
458 |
|
|
* Set the environment, and set find the |
459 |
|
|
* location of ASCEND's startup file. |
460 |
|
|
*/ |
461 |
|
|
AscCheckEnvironVars(interp); |
462 |
|
|
if( AscSetStartupFile(interp) != TCL_OK ) { |
463 |
|
|
Asc_Panic(2, "Asc_Driver", |
464 |
|
|
"Cannot find ~/.ascendrc nor the default AscendRC\n%s", |
465 |
|
|
Tcl_GetStringResult(interp)); |
466 |
|
|
} |
467 |
|
|
|
468 |
|
|
/* |
469 |
|
|
* Evaluate the ~/.ascendrc or $ASCENDTK/AscendRC file |
470 |
|
|
*/ |
471 |
|
|
Tcl_SourceRCFile(interp); |
472 |
|
|
|
473 |
|
|
/* |
474 |
|
|
* Establish a channel handlers for stdin and stdout |
475 |
|
|
*/ |
476 |
|
|
inChannel = Tcl_GetStdChannel(TCL_STDIN); |
477 |
|
|
if (inChannel) { |
478 |
|
|
Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc, |
479 |
|
|
(ClientData) inChannel); |
480 |
|
|
} |
481 |
|
|
if (tty) { |
482 |
|
|
Prompt(interp, 0); |
483 |
|
|
} |
484 |
|
|
outChannel = Tcl_GetStdChannel(TCL_STDOUT); |
485 |
|
|
if (outChannel) { |
486 |
|
|
Tcl_Flush(outChannel); |
487 |
|
|
} |
488 |
|
|
|
489 |
|
|
/* |
490 |
|
|
* Initialize the Dynamic Strings used in StdinProc() |
491 |
|
|
*/ |
492 |
|
|
Tcl_DStringInit(&g_command); |
493 |
|
|
Tcl_DStringInit(&g_line); |
494 |
|
|
Tcl_ResetResult(interp); |
495 |
|
|
|
496 |
|
|
/* |
497 |
|
|
* Loop infinitely, waiting for commands to execute. When there |
498 |
|
|
* are no windows left, Tk_MainLoop returns and we exit. |
499 |
|
|
*/ |
500 |
|
|
#ifdef DEBUG_MALLOC |
501 |
|
|
ascstatus("Memory status before calling Tk_MainLoop()"); |
502 |
|
|
#endif /* DEBUG_MALLOC */ |
503 |
|
|
if (Asc_ScriptConfigureInterrupt(1,interp)!=0) { |
504 |
|
|
Asc_Panic(2, "Asc_ScriptConfigureInterrupt", |
505 |
|
|
"Unable to configure script interrupt."); |
506 |
|
|
} |
507 |
|
|
Tk_MainLoop(); |
508 |
|
|
Asc_ScriptConfigureInterrupt(0,interp); |
509 |
|
|
#ifdef DEBUG_MALLOC |
510 |
|
|
ascstatus("Memory status after Tk_MainLoop() exits"); |
511 |
|
|
#endif /* DEBUG_MALLOC */ |
512 |
|
|
|
513 |
|
|
/* |
514 |
|
|
* Do ASCEND Cleanup |
515 |
|
|
*/ |
516 |
|
|
Asc_HelpDestroy(); |
517 |
|
|
Asc_UnitValue(NULL); |
518 |
|
|
Asc_SolvMemoryCleanup(); |
519 |
|
|
Asc_CompilerDestroy(); |
520 |
|
|
Asc_DestroyEnvironment(); |
521 |
|
|
#ifdef DEBUG_MALLOC |
522 |
|
|
ascshutdown("Memory status just before exiting"); |
523 |
|
|
#endif /* DEBUG_MALLOC */ |
524 |
|
|
|
525 |
|
|
/* |
526 |
|
|
* Destroy the interpreter and exit |
527 |
|
|
*/ |
528 |
|
|
Tcl_DeleteInterp(interp); |
529 |
|
|
Tcl_Exit(0); |
530 |
|
|
return 0; |
531 |
|
|
} |
532 |
|
|
|
533 |
|
|
|
534 |
|
|
/* |
535 |
|
|
*----------------------------------------------------------------- |
536 |
|
|
* int AscCheckEnvironVars(interp) |
537 |
|
|
* Tcl_Interp *interp; |
538 |
|
|
* |
539 |
|
|
* This function checks the following environment variables and sets them |
540 |
|
|
* to the default value if they are not set. This function will set |
541 |
|
|
* DIST_ENVIRONVAR to the parent of the directory where the ASCEND binary |
542 |
|
|
* lives if it is not set, e.g., if the ascend binary is |
543 |
|
|
* /foo/bar/ascend4 |
544 |
|
|
* DIST_ENVIRONVAR is set to "/foo". |
545 |
|
|
* |
546 |
|
|
* We check to see if ASCTK_ENVIRONVAR points to the proper place by |
547 |
|
|
* looking for the ASCEND startup script "AscendRC". If we find it, set |
548 |
|
|
* the Tcl variable tcl_rcFileName to its location, otherwise, call |
549 |
|
|
* Asc_Panic() to exit. |
550 |
|
|
* |
551 |
|
|
* Returns a standard Tcl return code. |
552 |
|
|
* |
553 |
|
|
* CPP_MACRO ENVIRONMENT VAR DEFAULT VALUE |
554 |
|
|
* ================= =============== ============= |
555 |
|
|
* DIST_ENVIRONVAR ASCENDDIST parent of binary's directory |
556 |
aw0a |
21 |
* AWW20041208: ASCTK_ENVIRONVAR ASCENDTK ASCENDDIST/TK |
557 |
|
|
* ASCTK_ENVIRONVAR ASCENDTK ASCENDDIST/../../tcltk98/TK |
558 |
aw0a |
1 |
* BITMAP_ENVIRONVAR ASCENDBITMAPS ASCENDTK/bitmaps |
559 |
|
|
* LIBR_ENVIRONVAR ASCENDLIBRARY |
560 |
|
|
* .:ASCENDDIST/models/libraries:ASCENDDIST/models/examples |
561 |
|
|
* |
562 |
|
|
*/ |
563 |
|
|
static int AscCheckEnvironVars(Tcl_Interp *interp) |
564 |
|
|
{ |
565 |
|
|
char *tmpenv; /* holds values returned by Asc_GetEnv() */ |
566 |
|
|
Tcl_DString ascenddist; /* holds the value of DIST_ENVIRONVAR */ |
567 |
|
|
Tcl_DString buffer2; /* used to incrementally build environment |
568 |
|
|
* variable values |
569 |
|
|
*/ |
570 |
|
|
Tcl_DString buffer1; /* holds the environment variable value in the |
571 |
|
|
* native format: result of passing buffer2 |
572 |
|
|
* into Tcl_TranslateFileName() |
573 |
|
|
*/ |
574 |
|
|
Tcl_Channel c; /* used to test if file exists */ |
575 |
|
|
|
576 |
|
|
/* initialize */ |
577 |
|
|
Tcl_DStringInit(&ascenddist); |
578 |
|
|
Tcl_DStringInit(&buffer1); |
579 |
|
|
Tcl_DStringInit(&buffer2); |
580 |
|
|
|
581 |
|
|
/* |
582 |
|
|
* Get the value of the ASCENDDIST environment variable; |
583 |
|
|
* if not set, set it to the parent of the directory containing |
584 |
|
|
* the ascend binary. For example, if the ascend binary is |
585 |
|
|
* /foo/bar/bin/ascend4, set ASCENDDIST to /foo/bar |
586 |
|
|
* If Tcl doesn't know where we are---the Tcl command |
587 |
|
|
* `info nameofexecutable' returns ""---then ASCENDDIST is set |
588 |
|
|
* to "." |
589 |
|
|
*/ |
590 |
|
|
if( Asc_ImportPathList(DIST_ENVIRONVAR) == 0 ) { |
591 |
|
|
if( (tmpenv = Asc_GetEnv(DIST_ENVIRONVAR)) == NULL ) { |
592 |
|
|
/* shouldn't be NULL since we just imported it successfully */ |
593 |
|
|
Asc_Panic(2, "CheckEnvironmentVars", |
594 |
|
|
"Asc_GetEnv(%s) returned NULL value.", DIST_ENVIRONVAR); |
595 |
|
|
} |
596 |
|
|
Tcl_DStringAppend(&ascenddist, tmpenv, -1); |
597 |
|
|
ascfree(tmpenv); |
598 |
|
|
} else { |
599 |
|
|
char cmd[] = |
600 |
|
|
"file nativename [file dirname [file dirname [info nameofexecutable]]]"; |
601 |
|
|
if( Tcl_Eval(interp, cmd) == TCL_OK ) { |
602 |
|
|
Tcl_DStringGetResult(interp, &ascenddist); |
603 |
|
|
if(Asc_SetPathList(DIST_ENVIRONVAR,Tcl_DStringValue(&ascenddist)) != 0) { |
604 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
605 |
|
|
"Asc_SetPathList() returned Nonzero: " |
606 |
|
|
"Not enough memory to extend the environment"); |
607 |
|
|
} |
608 |
|
|
} |
609 |
|
|
} |
610 |
|
|
/* Make sure the Tcl side can also see this variable */ |
611 |
|
|
Tcl_SetVar2(interp, "env", DIST_ENVIRONVAR, |
612 |
|
|
Tcl_DStringValue(&ascenddist), TCL_GLOBAL_ONLY); |
613 |
|
|
|
614 |
|
|
/* |
615 |
|
|
* If the user's environment does not have ASCENDLIBRARY set, then set |
616 |
|
|
* it to a reasonable default. |
617 |
|
|
*/ |
618 |
|
|
if( Asc_ImportPathList(LIBR_ENVIRONVAR) == 0 ) { |
619 |
|
|
if( (tmpenv = Asc_GetEnv(LIBR_ENVIRONVAR)) == NULL ) { |
620 |
|
|
/* shouldn't be NULL since we just imported it successfully */ |
621 |
|
|
Asc_Panic(2, "CheckEnvironmentVars", |
622 |
|
|
"Asc_GetEnv(%s) returned NULL value.", LIBR_ENVIRONVAR); |
623 |
|
|
} |
624 |
|
|
/* Make sure the Tcl side can also see this variable */ |
625 |
|
|
Tcl_SetVar2(interp, "env", LIBR_ENVIRONVAR, tmpenv, TCL_GLOBAL_ONLY); |
626 |
|
|
ascfree(tmpenv); |
627 |
|
|
} else { |
628 |
|
|
/* Add ``.'' to the ASCENDLIBRARY envar */ |
629 |
|
|
if( Asc_SetPathList(LIBR_ENVIRONVAR, ".") != 0 ) { |
630 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
631 |
|
|
"Asc_SetPathList() returned Nonzero: " |
632 |
|
|
"Not enough memory to extend the environment"); |
633 |
|
|
} |
634 |
|
|
|
635 |
|
|
/* Add ``$ASCENDDIST/models'' to the ASCENDLIBRARY envar */ |
636 |
|
|
Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&ascenddist), -1); |
637 |
|
|
Tcl_DStringAppend(&buffer2, "/models", -1); |
638 |
|
|
if( NULL != (Tcl_TranslateFileName(interp, Tcl_DStringValue(&buffer2), |
639 |
|
|
&buffer1))) { |
640 |
|
|
if(Asc_AppendPath(LIBR_ENVIRONVAR, Tcl_DStringValue(&buffer1)) != 0) { |
641 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
642 |
|
|
"Asc_AppendPath() returned Nonzero: " |
643 |
|
|
"Not enough memory to extend the environment"); |
644 |
|
|
} |
645 |
|
|
Tcl_DStringFree(&buffer1); |
646 |
|
|
} |
647 |
|
|
Tcl_DStringFree(&buffer2); |
648 |
|
|
|
649 |
|
|
/* Add ``$ASCENDDIST/models/examples'' to the ASCENDLIBRARY envar */ |
650 |
|
|
Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&ascenddist), -1); |
651 |
|
|
Tcl_DStringAppend(&buffer2, "/models/examples", -1); |
652 |
|
|
if( NULL != (Tcl_TranslateFileName(interp, Tcl_DStringValue(&buffer2), |
653 |
|
|
&buffer1))) { |
654 |
|
|
if(Asc_AppendPath(LIBR_ENVIRONVAR, Tcl_DStringValue(&buffer1)) != 0) { |
655 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
656 |
|
|
"Asc_AppendPath() returned Nonzero: " |
657 |
|
|
"Not enough memory to extend the environment"); |
658 |
|
|
} |
659 |
|
|
Tcl_DStringFree(&buffer1); |
660 |
|
|
} |
661 |
|
|
Tcl_DStringFree(&buffer2); |
662 |
|
|
|
663 |
|
|
/* Add ``$ASCENDDIST/models/libraries'' to the ASCENDLIBRARY envar */ |
664 |
|
|
Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&ascenddist), -1); |
665 |
|
|
Tcl_DStringAppend(&buffer2, "/models/libraries", -1); |
666 |
|
|
if( NULL != (Tcl_TranslateFileName(interp, Tcl_DStringValue(&buffer2), |
667 |
|
|
&buffer1))) { |
668 |
|
|
if(Asc_AppendPath(LIBR_ENVIRONVAR, Tcl_DStringValue(&buffer1)) != 0) { |
669 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
670 |
|
|
"Asc_AppendPath() returned Nonzero: " |
671 |
|
|
"Not enough memory to extend the environment"); |
672 |
|
|
} |
673 |
|
|
Tcl_DStringFree(&buffer1); |
674 |
|
|
} |
675 |
|
|
Tcl_DStringFree(&buffer2); |
676 |
|
|
|
677 |
|
|
/* Get the full value of the environment variable and set |
678 |
|
|
* $env(ASCENDLIBRARY) in the Tcl code |
679 |
|
|
*/ |
680 |
|
|
if( (tmpenv = Asc_GetEnv(LIBR_ENVIRONVAR)) == NULL ) { |
681 |
|
|
/* shouldn't be NULL since we just set it. memory error! */ |
682 |
|
|
Asc_Panic(2, "CheckEnvironmentVars", |
683 |
|
|
"Asc_GetEnv(%s) returned NULL value.", LIBR_ENVIRONVAR); |
684 |
|
|
} |
685 |
|
|
/* Make sure the Tcl side can also see this variable */ |
686 |
|
|
Tcl_SetVar2(interp, "env", LIBR_ENVIRONVAR, tmpenv, TCL_GLOBAL_ONLY); |
687 |
|
|
ascfree(tmpenv); |
688 |
|
|
} |
689 |
|
|
|
690 |
|
|
/* |
691 |
|
|
* If the user's environment does not have ASCENDTK set, then set it |
692 |
|
|
* by appending `TK' to ASCENDDIST. Later in this function, we check |
693 |
|
|
* to make sure it is a valid directory by checking for the existence |
694 |
|
|
* of `AscendRC' in that directory. |
695 |
|
|
*/ |
696 |
|
|
if( Asc_ImportPathList(ASCTK_ENVIRONVAR) == 0 ) { |
697 |
|
|
if( (tmpenv = Asc_GetEnv(ASCTK_ENVIRONVAR)) == NULL ) { |
698 |
|
|
/* shouldn't be NULL since we just imported it successfully */ |
699 |
|
|
Asc_Panic(2, "CheckEnvironmentVars", |
700 |
|
|
"Asc_GetEnv(%s) returned NULL value.", ASCTK_ENVIRONVAR); |
701 |
|
|
} |
702 |
|
|
/* store ASCENDTK in ``buffer1'' so we can check for ASCENDTK/AscendRC |
703 |
|
|
* below |
704 |
|
|
*/ |
705 |
|
|
Tcl_DStringAppend(&buffer1, tmpenv, -1); |
706 |
|
|
ascfree(tmpenv); |
707 |
|
|
} else { |
708 |
|
|
Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&ascenddist), -1); |
709 |
aw0a |
21 |
/* AWW20041208: Tcl_DStringAppend(&buffer2, "/TK", -1); |
710 |
|
|
*/ |
711 |
|
|
Tcl_DStringAppend(&buffer2, "/../../tcltk98/TK", -1); |
712 |
aw0a |
1 |
if(NULL != (Tcl_TranslateFileName(interp, Tcl_DStringValue(&buffer2), |
713 |
|
|
&buffer1))) { |
714 |
|
|
if( Asc_SetPathList(ASCTK_ENVIRONVAR, Tcl_DStringValue(&buffer1)) != 0) { |
715 |
|
|
Asc_Panic(2, "Asc_EnvironmentInit", |
716 |
|
|
"Not enough memory to initialize the environment"); |
717 |
|
|
} |
718 |
|
|
} |
719 |
|
|
Tcl_DStringFree(&buffer2); |
720 |
|
|
} |
721 |
|
|
/* Make sure the Tcl side can also see this variable */ |
722 |
|
|
Tcl_SetVar2(interp, "env", ASCTK_ENVIRONVAR, |
723 |
|
|
Tcl_DStringValue(&buffer1), TCL_GLOBAL_ONLY); |
724 |
|
|
|
725 |
|
|
/* |
726 |
|
|
* Check to see if ASCENDTK looks reasonable by checking |
727 |
|
|
* for ASCENDTK/AscendRC We use the Tcl channel |
728 |
|
|
* mechanism to see if file exists. |
729 |
|
|
*/ |
730 |
|
|
Tcl_DStringAppend(&buffer1, "/AscendRC", -1 ); |
731 |
|
|
c = Tcl_OpenFileChannel( NULL, Tcl_DStringValue(&buffer1), "r", 0 ); |
732 |
|
|
if( c != (Tcl_Channel)NULL ) { |
733 |
|
|
/* |
734 |
|
|
* file exists. close the channel and set tcl_rcfilename to |
735 |
|
|
* this location |
736 |
|
|
*/ |
737 |
|
|
Tcl_Close( NULL, c ); |
738 |
|
|
Tcl_SetVar(interp, "tcl_rcFileName", Tcl_DStringValue(&buffer1), |
739 |
|
|
TCL_GLOBAL_ONLY); |
740 |
|
|
} else { |
741 |
|
|
Asc_Panic(2, "AscCheckEnvironVars", |
742 |
aw0a |
21 |
"ERROR: Cannot find the file \"%s\" in the subdirectory \"..\/..\/tcltk98\/TK\"\n" |
743 |
aw0a |
1 |
"under the directory \"%s\"\n" |
744 |
|
|
"Please check the value of the environment variables %s and\n" |
745 |
|
|
"and %s and start ASCEND again.\n", |
746 |
|
|
"AscendRC", Tcl_DStringValue(&ascenddist), DIST_ENVIRONVAR, |
747 |
|
|
ASCTK_ENVIRONVAR); |
748 |
|
|
} |
749 |
|
|
Tcl_DStringFree(&buffer1); |
750 |
|
|
|
751 |
|
|
/* |
752 |
|
|
* If the user's environment does not have ASCENDBITMAPS set, then set |
753 |
|
|
* it by appending `bitmaps' to ASCENDTK. |
754 |
|
|
*/ |
755 |
|
|
if( Asc_ImportPathList(BITMAP_ENVIRONVAR) == 0 ) { |
756 |
|
|
if( (tmpenv = Asc_GetEnv(BITMAP_ENVIRONVAR)) == NULL ) { |
757 |
|
|
/* shouldn't be NULL since we just imported it successfully */ |
758 |
|
|
Asc_Panic(2, "CheckEnvironmentVars", |
759 |
|
|
"Asc_GetEnv(%s) returned NULL value.", BITMAP_ENVIRONVAR); |
760 |
|
|
} |
761 |
|
|
/* Make sure the Tcl side can also see this variable */ |
762 |
|
|
Tcl_SetVar2(interp, "env", BITMAP_ENVIRONVAR, tmpenv, TCL_GLOBAL_ONLY); |
763 |
|
|
ascfree(tmpenv); |
764 |
|
|
} else { |
765 |
|
|
Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&ascenddist), -1); |
766 |
|
|
Tcl_DStringAppend(&buffer2, "/TK/bitmaps", -1); |
767 |
|
|
if(NULL != (Tcl_TranslateFileName(interp, Tcl_DStringValue(&buffer2), |
768 |
|
|
&buffer1))) { |
769 |
|
|
if(Asc_SetPathList(BITMAP_ENVIRONVAR, Tcl_DStringValue(&buffer1)) != 0) { |
770 |
|
|
Asc_Panic(2, "Asc_EnvironmentInit", |
771 |
|
|
"Not enough memory to initialize the environment"); |
772 |
|
|
} |
773 |
|
|
} |
774 |
|
|
Tcl_DStringFree(&buffer2); |
775 |
|
|
/* Make sure the Tcl side can also see this variable */ |
776 |
|
|
Tcl_SetVar2(interp, "env", BITMAP_ENVIRONVAR, |
777 |
|
|
Tcl_DStringValue(&buffer1), TCL_GLOBAL_ONLY); |
778 |
|
|
Tcl_DStringFree(&buffer1); |
779 |
|
|
} |
780 |
|
|
|
781 |
|
|
/* Cleanup */ |
782 |
|
|
Tcl_DStringFree(&ascenddist); |
783 |
|
|
|
784 |
|
|
return TCL_OK; |
785 |
|
|
} |
786 |
|
|
|
787 |
|
|
|
788 |
|
|
/* |
789 |
|
|
* int AscSetStartupFile(interp) |
790 |
|
|
* Tcl_Interp *interp; |
791 |
|
|
* |
792 |
|
|
* Look for ~/.ascendrc; if found, set the Tcl variable tcl_rcFileName |
793 |
|
|
* to this file's location. This overrides the value set in |
794 |
|
|
* AscCheckEnvironVars(). |
795 |
|
|
* If ~/_ascendrc is available it only gets used if ~/.ascendrc is not. |
796 |
|
|
* Returns a standard Tcl return code. |
797 |
|
|
*/ |
798 |
|
|
static int AscSetStartupFile(Tcl_Interp *interp) |
799 |
|
|
{ |
800 |
|
|
char *fullname; /* try to find this if first fails */ |
801 |
|
|
Tcl_DString buffer; |
802 |
|
|
Tcl_Channel c; /* used to check for file existance */ |
803 |
|
|
|
804 |
|
|
Tcl_ResetResult(interp); |
805 |
|
|
|
806 |
|
|
fullname = Tcl_TranslateFileName( interp, "~/.ascendrc", &buffer ); |
807 |
|
|
if( fullname != NULL ) { |
808 |
|
|
/* |
809 |
|
|
* Use the Tcl file channel routines to determine if ~/.ascendrc |
810 |
|
|
* exists. We cannot use access() since Windows doesn't use it. |
811 |
|
|
*/ |
812 |
|
|
c = Tcl_OpenFileChannel( NULL, fullname, "r", 0 ); |
813 |
|
|
if( c != (Tcl_Channel)NULL ) { |
814 |
|
|
/* file exists. close the channel and set tcl_rcFileName. */ |
815 |
|
|
Tcl_Close( NULL, c ); |
816 |
|
|
Tcl_SetVar(interp, "tcl_rcFileName", fullname, TCL_GLOBAL_ONLY); |
817 |
|
|
Tcl_DStringFree(&buffer); |
818 |
|
|
return TCL_OK; |
819 |
|
|
} |
820 |
|
|
Tcl_DStringFree(&buffer); |
821 |
|
|
} |
822 |
|
|
fullname = Tcl_TranslateFileName( interp, "~/_ascendrc", &buffer ); |
823 |
|
|
if( fullname != NULL ) { |
824 |
|
|
/* |
825 |
|
|
* Use the Tcl file channel routines to determine if ~/_ascendrc |
826 |
|
|
* exists. We cannot use access() since Windows doesn't use it. |
827 |
|
|
*/ |
828 |
|
|
c = Tcl_OpenFileChannel( NULL, fullname, "r", 0 ); |
829 |
|
|
if( c != (Tcl_Channel)NULL ) { |
830 |
|
|
/* file exists. close the channel and set tcl_rcFileName */ |
831 |
|
|
Tcl_Close( NULL, c ); |
832 |
|
|
Tcl_SetVar(interp, "tcl_rcFileName", fullname, TCL_GLOBAL_ONLY); |
833 |
|
|
Tcl_DStringFree(&buffer); |
834 |
|
|
return TCL_OK; |
835 |
|
|
} |
836 |
|
|
Tcl_DStringFree(&buffer); |
837 |
|
|
} |
838 |
|
|
return TCL_OK; /* probably should be TCL_ERROR */ |
839 |
|
|
} |
840 |
|
|
|
841 |
|
|
|
842 |
|
|
|
843 |
|
|
/* |
844 |
|
|
* file = AscProcessCommandLine(argc, argv) |
845 |
|
|
* char *file; |
846 |
|
|
* int argc; |
847 |
|
|
* char *argv[]; |
848 |
|
|
* |
849 |
|
|
* Process the options given on the command line `argv' where `argc' is |
850 |
|
|
* the length of argv. |
851 |
|
|
* |
852 |
|
|
* Strip out ASCEND specific flags and then pass the rest to Tcl so it |
853 |
|
|
* can set what it needs. |
854 |
|
|
* |
855 |
|
|
* This function may call exit() if the user requests help. |
856 |
|
|
*/ |
857 |
|
|
static int AscProcessCommandLine(Tcl_Interp *interp, int argc, CONST84 char **argv) |
858 |
|
|
{ |
859 |
|
|
int i; |
860 |
|
|
int flag; /* set to 1 for `+arg', -1 for `-arg' */ |
861 |
|
|
size_t length; /* length of an argv */ |
862 |
|
|
char *args; |
863 |
|
|
char buf[MAXIMUM_NUMERIC_LENGTH]; /* space for integer->string conversion */ |
864 |
|
|
int new_argc = 0; /* the argc we will pass to Tcl */ |
865 |
|
|
#ifdef ZZ_DEBUG |
866 |
|
|
zz_debug = 0; /* nonzero to print parser debugging info*/ |
867 |
|
|
#endif |
868 |
|
|
|
869 |
|
|
for( i = 1; i < argc; i++ ) { |
870 |
|
|
if( (length = strlen(argv[i])) == 0 ) { |
871 |
|
|
/* ignore 0-length arguments */ |
872 |
|
|
continue; |
873 |
|
|
} |
874 |
|
|
|
875 |
|
|
if(( length >= 2 ) && ( strncmp(argv[i],"-h",2) == 0 )) { |
876 |
|
|
AscPrintHelpExit(argv[0]); |
877 |
|
|
} |
878 |
|
|
if(( length >= 2 ) && ( strncmp(argv[i],"-H",2) == 0 )) { |
879 |
|
|
AscPrintHelpExit(argv[0]); |
880 |
|
|
} |
881 |
|
|
if(( length >= 4 ) && ( strncmp(argv[i],"help",4) == 0 )) { |
882 |
|
|
AscPrintHelpExit(argv[0]); |
883 |
|
|
} |
884 |
|
|
|
885 |
|
|
if( argv[i][0] == '-' ) { |
886 |
|
|
flag = -1; |
887 |
|
|
} else if( argv[i][0] == '+' ) { |
888 |
|
|
flag = 1; |
889 |
|
|
} else { |
890 |
|
|
flag = 0; |
891 |
|
|
} |
892 |
|
|
|
893 |
|
|
if(( length == 2 ) && ( flag != 0 )) { |
894 |
|
|
switch( argv[i][1] ) { |
895 |
|
|
case 'd': |
896 |
|
|
/* '-d' turns on scanner debugging (if ascend was built with it) |
897 |
|
|
* '+d' turns off scanner debugging [default] |
898 |
|
|
*/ |
899 |
|
|
if( flag == -1 ) { |
900 |
|
|
#ifdef ZZ_DEBUG |
901 |
|
|
zz_debug = 1; |
902 |
|
|
} else { |
903 |
|
|
zz_debug = 0; |
904 |
|
|
#else |
905 |
|
|
FPRINTF(ASCERR, "Sorry, %s wasn't compiled with %s defined.\n", |
906 |
|
|
argv[0], "ZZ_DEBUG"); |
907 |
|
|
#endif /* ZZ_DEBUG */ |
908 |
|
|
} |
909 |
|
|
break; |
910 |
|
|
case 's': |
911 |
|
|
/* '-s' turns on compiler optimizations [default] |
912 |
|
|
* '+s' turns off compiler optimizations |
913 |
|
|
*/ |
914 |
|
|
if( flag == -1 ) { |
915 |
|
|
g_interface_simplify_relations = 1; |
916 |
|
|
} else { |
917 |
|
|
g_interface_simplify_relations = 0; |
918 |
|
|
} |
919 |
|
|
break; |
920 |
|
|
case 't': |
921 |
|
|
/* '-t' turns on timing of compiler optimizations |
922 |
|
|
* '+t' turns off timing of compiler optimizations [default] |
923 |
|
|
*/ |
924 |
|
|
if( flag == 0 ) { |
925 |
|
|
g_compiler_timing = 1; |
926 |
|
|
} else { |
927 |
|
|
g_compiler_timing = 0; |
928 |
|
|
} |
929 |
|
|
break; |
930 |
|
|
case 'c': |
931 |
|
|
case 'g': |
932 |
|
|
fprintf(ASCERR, "WARNING! Obsolete ASCEND option \"%s\"\n", argv[i]); |
933 |
|
|
break; |
934 |
|
|
default: |
935 |
|
|
/* unknown ASCEND option, pass it on to Tcl |
936 |
|
|
*/ |
937 |
|
|
argv[++new_argc] = argv[i]; |
938 |
|
|
break; |
939 |
|
|
} |
940 |
|
|
} else { |
941 |
|
|
/* unknown ASCEND option, pass it on to Tcl |
942 |
|
|
*/ |
943 |
|
|
argv[++new_argc] = argv[i]; |
944 |
|
|
} |
945 |
|
|
} |
946 |
|
|
|
947 |
|
|
/* |
948 |
|
|
* Make command-line arguments available in the Tcl variables "argc" |
949 |
|
|
* and "argv". |
950 |
|
|
*/ |
951 |
|
|
args = Tcl_Merge(new_argc, (argv+1)); |
952 |
|
|
Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY); |
953 |
|
|
ckfree(args); |
954 |
|
|
sprintf(buf, "%d", new_argc); |
955 |
|
|
Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY); |
956 |
|
|
Tcl_SetVar(interp, "argv0", argv[0], TCL_GLOBAL_ONLY); |
957 |
|
|
|
958 |
|
|
return TCL_OK; |
959 |
|
|
} |
960 |
|
|
|
961 |
|
|
|
962 |
|
|
/* |
963 |
|
|
* AscPrintHelpExit(invoke_name) |
964 |
|
|
* CONST char *invoke_name; |
965 |
|
|
* |
966 |
|
|
* Print a help message and exit. Use invoke_name as the name of |
967 |
|
|
* the binary |
968 |
|
|
*/ |
969 |
|
|
static |
970 |
|
|
void AscPrintHelpExit(CONST char *invoke_name) |
971 |
|
|
{ |
972 |
|
|
PRINTF("usage: %s [options]\n" |
973 |
|
|
"\n" |
974 |
|
|
"where options include [default value]:\n" |
975 |
|
|
" -h print this message\n" |
976 |
|
|
" -/+d turn on/off yacc debugging [off]\n" |
977 |
|
|
" -/+s turn on/off compiler optimizations [on]\n" |
978 |
|
|
" -/+t turn on/off timing of compiler operations [off]\n", |
979 |
|
|
invoke_name); |
980 |
|
|
Tcl_Exit(0); /* Show this help message and leave */ |
981 |
|
|
} |
982 |
|
|
|
983 |
|
|
|
984 |
|
|
/* |
985 |
|
|
* AscTrap(sig) |
986 |
|
|
* int sig; |
987 |
|
|
* |
988 |
|
|
* Function to call when we receive an interrupt. |
989 |
|
|
*/ |
990 |
|
|
static |
991 |
|
|
void AscTrap(int sig) |
992 |
|
|
{ |
993 |
|
|
putchar('\n'); |
994 |
|
|
Asc_Panic(sig, "AscTrap", "Caught Signal: %d", sig); |
995 |
|
|
} |
996 |
|
|
|
997 |
|
|
|
998 |
|
|
/* |
999 |
|
|
* See this file's header for documentation. |
1000 |
|
|
*/ |
1001 |
|
|
int Asc_LoadWin(ClientData cdata, Tcl_Interp *interp, |
1002 |
|
|
int argc, CONST84 char *argv[]) |
1003 |
|
|
{ |
1004 |
|
|
(void)cdata; /* stop gcc whine about unused parameter */ |
1005 |
|
|
(void)argv; /* stop gcc whine about unused parameter */ |
1006 |
|
|
|
1007 |
|
|
if ( argc != 1 ) { |
1008 |
|
|
FPRINTF(stderr,"call is: ascloadwin <no args> \n"); |
1009 |
|
|
return TCL_ERROR; |
1010 |
|
|
} |
1011 |
|
|
if (g_interfacever) { |
1012 |
|
|
Tcl_SetResult(interp, "1", TCL_STATIC); |
1013 |
|
|
} else { |
1014 |
|
|
Tcl_SetResult(interp, "0", TCL_STATIC); |
1015 |
|
|
} |
1016 |
|
|
return TCL_OK; |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
|
1020 |
|
|
/* |
1021 |
|
|
*---------------------------------------------------------------------- |
1022 |
|
|
*---------------------------------------------------------------------- |
1023 |
|
|
* The following StdinProc() and Prompt() are from tkMain.c in |
1024 |
|
|
* the Tk4.1 distribution (and did not change in Tk8.0). |
1025 |
|
|
*---------------------------------------------------------------------- |
1026 |
|
|
*---------------------------------------------------------------------- |
1027 |
|
|
*/ |
1028 |
|
|
/* |
1029 |
|
|
*---------------------------------------------------------------------- |
1030 |
|
|
* |
1031 |
|
|
* StdinProc -- |
1032 |
|
|
* |
1033 |
|
|
* This procedure is invoked by the event dispatcher whenever |
1034 |
|
|
* standard input becomes readable. It grabs the next line of |
1035 |
|
|
* input characters, adds them to a command being assembled, and |
1036 |
|
|
* executes the command if it's complete. |
1037 |
|
|
* |
1038 |
|
|
* Results: |
1039 |
|
|
* None. |
1040 |
|
|
* |
1041 |
|
|
* Side effects: |
1042 |
|
|
* Could be almost arbitrary, depending on the command that's |
1043 |
|
|
* typed. |
1044 |
|
|
* |
1045 |
|
|
*---------------------------------------------------------------------- |
1046 |
|
|
*/ |
1047 |
|
|
|
1048 |
|
|
/* ARGSUSED */ |
1049 |
|
|
static void |
1050 |
|
|
StdinProc(clientData, mask) |
1051 |
|
|
ClientData clientData; /* Not used. */ |
1052 |
|
|
int mask; /* Not used. */ |
1053 |
|
|
{ |
1054 |
|
|
static int gotPartial = 0; |
1055 |
|
|
char *cmd; |
1056 |
|
|
int code, count; |
1057 |
|
|
Tcl_Channel chan = (Tcl_Channel) clientData; |
1058 |
|
|
|
1059 |
|
|
Tcl_Interp *interp = g_interp; /* use a local copy of the |
1060 |
|
|
* global tcl interpreter |
1061 |
|
|
*/ |
1062 |
|
|
|
1063 |
|
|
(void)clientData; /* stop gcc whine about unused parameter */ |
1064 |
|
|
(void)mask; /* stop gcc whine about unused parameter */ |
1065 |
|
|
|
1066 |
|
|
count = Tcl_Gets(chan, &g_line); |
1067 |
|
|
|
1068 |
|
|
if (count < 0) { |
1069 |
|
|
if (!gotPartial) { |
1070 |
|
|
if (tty) { |
1071 |
|
|
return; |
1072 |
|
|
} else { |
1073 |
|
|
Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan); |
1074 |
|
|
} |
1075 |
|
|
return; |
1076 |
|
|
} else { |
1077 |
|
|
count = 0; |
1078 |
|
|
} |
1079 |
|
|
} |
1080 |
|
|
|
1081 |
|
|
(void) Tcl_DStringAppend(&g_command, Tcl_DStringValue(&g_line), -1); |
1082 |
|
|
cmd = Tcl_DStringAppend(&g_command, "\n", -1); |
1083 |
|
|
Tcl_DStringFree(&g_line); |
1084 |
|
|
|
1085 |
|
|
if (!Tcl_CommandComplete(cmd)) { |
1086 |
|
|
gotPartial = 1; |
1087 |
|
|
goto prompt; |
1088 |
|
|
} |
1089 |
|
|
gotPartial = 0; |
1090 |
|
|
|
1091 |
|
|
/* |
1092 |
|
|
* Disable the stdin channel handler while evaluating the command; |
1093 |
|
|
* otherwise if the command re-enters the event loop we might |
1094 |
|
|
* process commands from stdin before the current command is |
1095 |
|
|
* finished. Among other things, this will trash the text of the |
1096 |
|
|
* command being evaluated. |
1097 |
|
|
*/ |
1098 |
|
|
|
1099 |
|
|
Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan); |
1100 |
|
|
code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL); |
1101 |
|
|
Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, |
1102 |
|
|
(ClientData) chan); |
1103 |
|
|
Tcl_DStringFree(&g_command); |
1104 |
|
|
if (*interp->result != 0) { |
1105 |
|
|
if ((code != TCL_OK) || (tty)) { |
1106 |
|
|
/* |
1107 |
|
|
* The statement below used to call "printf", but that resulted |
1108 |
|
|
* in core dumps under Solaris 2.3 if the result was very long. |
1109 |
|
|
* |
1110 |
|
|
* NOTE: This probably will not work under Windows either. |
1111 |
|
|
*/ |
1112 |
|
|
|
1113 |
|
|
puts(interp->result); |
1114 |
|
|
} |
1115 |
|
|
} |
1116 |
|
|
|
1117 |
|
|
/* |
1118 |
|
|
* Output a prompt. |
1119 |
|
|
*/ |
1120 |
|
|
|
1121 |
|
|
prompt: |
1122 |
|
|
if (tty) { |
1123 |
|
|
Prompt(interp, gotPartial); |
1124 |
|
|
} |
1125 |
|
|
Tcl_ResetResult(interp); |
1126 |
|
|
} |
1127 |
|
|
|
1128 |
|
|
/* |
1129 |
|
|
*---------------------------------------------------------------------- |
1130 |
|
|
* |
1131 |
|
|
* Prompt -- |
1132 |
|
|
* |
1133 |
|
|
* Issue a prompt on standard output, or invoke a script |
1134 |
|
|
* to issue the prompt. |
1135 |
|
|
* |
1136 |
|
|
* Results: |
1137 |
|
|
* None. |
1138 |
|
|
* |
1139 |
|
|
* Side effects: |
1140 |
|
|
* A prompt gets output, and a Tcl script may be evaluated |
1141 |
|
|
* in interp. |
1142 |
|
|
* |
1143 |
|
|
*---------------------------------------------------------------------- |
1144 |
|
|
*/ |
1145 |
|
|
|
1146 |
|
|
static void |
1147 |
|
|
Prompt(interp, partial) |
1148 |
|
|
Tcl_Interp *interp; /* Interpreter to use for prompting. */ |
1149 |
|
|
int partial; /* Non-zero means there already |
1150 |
|
|
* exists a partial command, so use |
1151 |
|
|
* the secondary prompt. */ |
1152 |
|
|
{ |
1153 |
|
|
CONST84 char *promptCmd; |
1154 |
|
|
int code; |
1155 |
|
|
Tcl_Channel outChannel, errChannel; |
1156 |
|
|
CONST84 char *subPrompt; |
1157 |
|
|
|
1158 |
|
|
errChannel = Tcl_GetChannel(interp, "stderr", NULL); |
1159 |
|
|
|
1160 |
|
|
subPrompt = (partial ? "tcl_prompt2" : "tcl_prompt1"); |
1161 |
|
|
promptCmd = Tcl_GetVar(interp, subPrompt, TCL_GLOBAL_ONLY); |
1162 |
|
|
if (promptCmd == NULL) { |
1163 |
|
|
defaultPrompt: |
1164 |
|
|
|
1165 |
|
|
/* |
1166 |
|
|
* We must check that outChannel is a real channel - it |
1167 |
|
|
* is possible that someone has transferred stdout out of |
1168 |
|
|
* this interpreter with "interp transfer". |
1169 |
|
|
*/ |
1170 |
|
|
|
1171 |
|
|
outChannel = Tcl_GetChannel(interp, "stdout", NULL); |
1172 |
|
|
if (outChannel != (Tcl_Channel) NULL) { |
1173 |
|
|
if (!partial) { |
1174 |
|
|
Tcl_Write(outChannel, "AscendIV% ", 10); |
1175 |
|
|
} else { |
1176 |
|
|
Tcl_Write(outChannel, "more? ", 6); |
1177 |
|
|
} |
1178 |
|
|
} |
1179 |
|
|
} else { |
1180 |
|
|
code = Tcl_Eval(interp, promptCmd); |
1181 |
|
|
if (code != TCL_OK) { |
1182 |
|
|
Tcl_AddErrorInfo(interp, |
1183 |
|
|
"\n (script that generates prompt)"); |
1184 |
|
|
/* |
1185 |
|
|
* We must check that errChannel is a real channel - it |
1186 |
|
|
* is possible that someone has transferred stderr out of |
1187 |
|
|
* this interpreter with "interp transfer". |
1188 |
|
|
*/ |
1189 |
|
|
|
1190 |
|
|
errChannel = Tcl_GetChannel(interp, "stderr", NULL); |
1191 |
|
|
if (errChannel != (Tcl_Channel) NULL) { |
1192 |
|
|
Tcl_Write(errChannel, interp->result, -1); |
1193 |
|
|
Tcl_Write(errChannel, "\n", 1); |
1194 |
|
|
} |
1195 |
|
|
goto defaultPrompt; |
1196 |
|
|
} |
1197 |
|
|
} |
1198 |
|
|
outChannel = Tcl_GetChannel(interp, "stdout", NULL); |
1199 |
|
|
if (outChannel != (Tcl_Channel) NULL) { |
1200 |
|
|
Tcl_Flush(outChannel); |
1201 |
|
|
} |
1202 |
|
|
} |
1203 |
|
|
|
1204 |
|
|
/* |
1205 |
|
|
*---------------------------------------------------------------------- |
1206 |
|
|
* Tom Epperly's Malloc Debugger |
1207 |
|
|
*---------------------------------------------------------------------- |
1208 |
|
|
*/ |
1209 |
|
|
#ifdef DEBUG_MALLOC |
1210 |
|
|
static void InitDebugMalloc(void) |
1211 |
|
|
{ |
1212 |
|
|
union dbmalloptarg m; |
1213 |
|
|
m.str = NULL; |
1214 |
|
|
m.i = 0; |
1215 |
|
|
dbmallopt(MALLOC_CKDATA,&m); |
1216 |
|
|
} |
1217 |
|
|
|
1218 |
|
|
int Asc_DebugMallocCmd(ClientData cdata, Tcl_Interp *interp, |
1219 |
|
|
int argc, CONST84 char *argv[]) |
1220 |
|
|
{ |
1221 |
|
|
union dbmalloptarg m; |
1222 |
|
|
|
1223 |
|
|
if ( argc != 2 ) { |
1224 |
|
|
Tcl_SetResult(interp, "wrong # args : Usage __dbmalloc ?on?off?", |
1225 |
|
|
TCL_STATIC); |
1226 |
|
|
return TCL_ERROR; |
1227 |
|
|
} |
1228 |
|
|
m.str = NULL; |
1229 |
|
|
if (strcmp(argv[1],"on")==0) { |
1230 |
|
|
m.i = 1; |
1231 |
|
|
} else if (strcmp(argv[1],"off")==0) { |
1232 |
|
|
m.i = 0; |
1233 |
|
|
} else { |
1234 |
|
|
Tcl_SetResult(interp, "incorrect args : should be \"on\" or \"off\"", |
1235 |
|
|
TCL_STATIC); |
1236 |
|
|
return TCL_ERROR; |
1237 |
|
|
} |
1238 |
|
|
dbmallopt(MALLOC_CKDATA,&m); /* turn on str* mem* and b* checking */ |
1239 |
|
|
return TCL_OK; |
1240 |
|
|
} |
1241 |
|
|
#endif /* DEBUG_MALLOC */ |
1242 |
|
|
|
1243 |
|
|
#ifdef __WIN32__ |
1244 |
|
|
/* |
1245 |
|
|
*------------------------------------------------------------------------- |
1246 |
|
|
* |
1247 |
|
|
* setargv -- |
1248 |
|
|
* |
1249 |
|
|
* Parse the Windows command line string into argc/argv. Done here |
1250 |
|
|
* because we don't trust the builtin argument parser in crt0. |
1251 |
|
|
* Windows applications are responsible for breaking their command |
1252 |
|
|
* line into arguments. |
1253 |
|
|
* |
1254 |
|
|
* 2N backslashes + quote -> N backslashes + begin quoted string |
1255 |
|
|
* 2N + 1 backslashes + quote -> literal |
1256 |
|
|
* N backslashes + non-quote -> literal |
1257 |
|
|
* quote + quote in a quoted string -> single quote |
1258 |
|
|
* quote + quote not in quoted string -> empty string |
1259 |
|
|
* quote -> begin quoted string |
1260 |
|
|
* |
1261 |
|
|
* Results: |
1262 |
|
|
* Fills argcPtr with the number of arguments and argvPtr with the |
1263 |
|
|
* array of arguments. |
1264 |
|
|
* |
1265 |
|
|
* Side effects: |
1266 |
|
|
* Memory allocated. |
1267 |
|
|
* |
1268 |
|
|
* This function is from the Tk 8.0 distribution. See win/winMain.c in |
1269 |
|
|
* their sources. |
1270 |
|
|
* |
1271 |
|
|
*-------------------------------------------------------------------------- |
1272 |
|
|
*/ |
1273 |
|
|
static void |
1274 |
|
|
setargv(argcPtr, argvPtr) |
1275 |
|
|
int *argcPtr; /* Filled with number of argument strings. */ |
1276 |
|
|
char ***argvPtr; /* Filled with argument strings (malloc'd). */ |
1277 |
|
|
{ |
1278 |
|
|
char *cmdLine, *p, *arg, *argSpace; |
1279 |
|
|
char **argv; |
1280 |
|
|
int argc, size, inquote, copy, slashes; |
1281 |
|
|
|
1282 |
|
|
cmdLine = GetCommandLine(); |
1283 |
|
|
|
1284 |
|
|
/* |
1285 |
|
|
* Precompute an overly pessimistic guess at the number of arguments |
1286 |
|
|
* in the command line by counting non-space spans. |
1287 |
|
|
*/ |
1288 |
|
|
|
1289 |
|
|
size = 2; |
1290 |
|
|
for (p = cmdLine; *p != '\0'; p++) { |
1291 |
|
|
if (isspace(*p)) { |
1292 |
|
|
size++; |
1293 |
|
|
while (isspace(*p)) { |
1294 |
|
|
p++; |
1295 |
|
|
} |
1296 |
|
|
if (*p == '\0') { |
1297 |
|
|
break; |
1298 |
|
|
} |
1299 |
|
|
} |
1300 |
|
|
} |
1301 |
|
|
argSpace = (char *) ckalloc((unsigned) (size * sizeof(char *) |
1302 |
|
|
+ strlen(cmdLine) + 1)); |
1303 |
|
|
argv = (char **) argSpace; |
1304 |
|
|
argSpace += size * sizeof(char *); |
1305 |
|
|
size--; |
1306 |
|
|
|
1307 |
|
|
p = cmdLine; |
1308 |
|
|
for (argc = 0; argc < size; argc++) { |
1309 |
|
|
argv[argc] = arg = argSpace; |
1310 |
|
|
while (isspace(*p)) { |
1311 |
|
|
p++; |
1312 |
|
|
} |
1313 |
|
|
if (*p == '\0') { |
1314 |
|
|
break; |
1315 |
|
|
} |
1316 |
|
|
|
1317 |
|
|
inquote = 0; |
1318 |
|
|
slashes = 0; |
1319 |
|
|
while (1) { |
1320 |
|
|
copy = 1; |
1321 |
|
|
while (*p == '\\') { |
1322 |
|
|
slashes++; |
1323 |
|
|
p++; |
1324 |
|
|
} |
1325 |
|
|
if (*p == '"') { |
1326 |
|
|
if ((slashes & 1) == 0) { |
1327 |
|
|
copy = 0; |
1328 |
|
|
if ((inquote) && (p[1] == '"')) { |
1329 |
|
|
p++; |
1330 |
|
|
copy = 1; |
1331 |
|
|
} else { |
1332 |
|
|
inquote = !inquote; |
1333 |
|
|
} |
1334 |
|
|
} |
1335 |
|
|
slashes >>= 1; |
1336 |
|
|
} |
1337 |
|
|
|
1338 |
|
|
while (slashes) { |
1339 |
|
|
*arg = '\\'; |
1340 |
|
|
arg++; |
1341 |
|
|
slashes--; |
1342 |
|
|
} |
1343 |
|
|
|
1344 |
|
|
if ((*p == '\0') || (!inquote && isspace(*p))) { |
1345 |
|
|
break; |
1346 |
|
|
} |
1347 |
|
|
if (copy != 0) { |
1348 |
|
|
*arg = *p; |
1349 |
|
|
arg++; |
1350 |
|
|
} |
1351 |
|
|
p++; |
1352 |
|
|
} |
1353 |
|
|
*arg = '\0'; |
1354 |
|
|
argSpace = arg + 1; |
1355 |
|
|
} |
1356 |
|
|
argv[argc] = NULL; |
1357 |
|
|
|
1358 |
|
|
*argcPtr = argc; |
1359 |
|
|
*argvPtr = argv; |
1360 |
|
|
} |
1361 |
|
|
|
1362 |
|
|
#endif /* __WIN32__ */ |