/[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 628 - (hide annotations) (download) (as text)
Wed May 24 01:45:02 2006 UTC (18 years, 6 months ago) by johnpye
File MIME type: text/x-csrc
File size: 31937 byte(s)
Fixed up standard paths stuff to use 'INSTALL_ASCDATA' as the place where tcltk/python/models etc
will live. The confusion here came from the fact that I was taking 'INSTALL_SHARE' to be be assumed
to mean 'the location of /usr/share' -- hence the resulting '$INSTALL_SHARE/ascend' that was bothering
Ben. The 'INSTALL_ASCDATA' fixes this, and behaves as he will like, I hope.

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

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