/[ascend]/trunk/tcltk/generic/interface/Driver.c
ViewVC logotype

Annotation of /trunk/tcltk/generic/interface/Driver.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1412 - (hide annotations) (download) (as text)
Mon Apr 23 13:55:28 2007 UTC (17 years, 7 months ago) by jpye
File MIME type: text/x-csrc
File size: 30440 byte(s)
Fixed problem with Driver.c in ABSOLUTE_PATHS case.
Updated changelog and spec file for new 0.9.5.108 release.
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 */

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22