]>
git.zerfleddert.de Git - micropolis/blob - src/tclx/src/tclxstup.c
4 * Startup code for the Tcl shell and other interactive applications. Also
5 * create special commands used just by Tcl shell features.
6 *-----------------------------------------------------------------------------
7 * Copyright 1992 Karl Lehenbauer and Mark Diekhans.
9 * Permission to use, copy, modify, and distribute this software and its
10 * documentation for any purpose and without fee is hereby granted, provided
11 * that the above copyright notice appear in all copies. Karl Lehenbauer and
12 * Mark Diekhans make no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without express or
15 *-----------------------------------------------------------------------------
16 * $Id: tclXstartup.c,v 2.1 1992/11/10 04:02:06 markd Exp $
17 *-----------------------------------------------------------------------------
23 extern char * etenv ();
26 extern int optind
, opterr
;
28 typedef struct tclParms_t
{
29 int execFile
; /* Run the specified file. (no searching) */
30 int execCommand
; /* Execute the specified command. */
31 unsigned options
; /* Quick startup option. */
32 char *execStr
; /* Command file or command to execute. */
33 char **tclArgv
; /* Arguments to pass to tcl script. */
34 int tclArgc
; /* Count of arguments to pass to tcl script. */
35 char *programName
; /* Name of program (less path). */
39 * Prototypes of internal functions.
42 ParseCmdArgs
_ANSI_ARGS_((int argc
,
44 tclParms_t
*tclParmsPtr
));
47 FindDefaultFile
_ANSI_ARGS_((Tcl_Interp
*interp
,
51 ProcessDefaultFile
_ANSI_ARGS_((Tcl_Interp
*interp
,
55 ProcessInitFile
_ANSI_ARGS_((Tcl_Interp
*interp
));
59 *-----------------------------------------------------------------------------
63 * Display error information and abort when an error is returned in the
67 * o interp - A pointer to the interpreter, should contain the
68 * error message in `result'.
69 * o exitCode - The code to pass to exit.
70 *-----------------------------------------------------------------------------
73 Tcl_ErrorAbort (Tcl_Interp
*interp
, int exitCode
)
78 fprintf (stderr
, "Error: %s\n", interp
->result
);
80 errorStack
= Tcl_GetVar (interp
, "errorInfo", 1);
81 if (errorStack
!= NULL
)
82 fprintf (stderr
, "%s\n", errorStack
);
87 *-----------------------------------------------------------------------------
91 * Parse the arguments passed to the Tcl shell
94 * o argc, argv - Arguments passed to main.
95 * o tclParmsPtr - Results of the parsed Tcl shell command line.
96 *-----------------------------------------------------------------------------
99 ParseCmdArgs (int argc
, char **argv
, tclParms_t
*tclParmsPtr
)
101 char *scanPtr
, *programName
;
105 tclParmsPtr
->execFile
= FALSE
;
106 tclParmsPtr
->execCommand
= FALSE
;
107 tclParmsPtr
->options
= 0;
108 tclParmsPtr
->execStr
= NULL
;
111 * Determine file name (less directories) that the Tcl interpreter is
114 scanPtr
= programName
= argv
[0];
115 while (*scanPtr
!= '\0') {
117 programName
= scanPtr
+ 1;
120 tclParmsPtr
->programName
= programName
;
121 programNameLen
= strlen (programName
);
124 * Scan arguments looking for flags to process here rather than to pass
125 * on to the scripts. The '-c' or '-f' must also be the last option to
126 * allow for script arguments starting with `-'.
128 while ((option
= getopt (argc
, argv
, "qc:f:u")) != -1) {
131 if (tclParmsPtr
->options
& TCLSH_QUICK_STARTUP
)
133 tclParmsPtr
->options
|= TCLSH_QUICK_STARTUP
;
136 tclParmsPtr
->execCommand
= TRUE
;
137 tclParmsPtr
->execStr
= optarg
;
140 tclParmsPtr
->execFile
= TRUE
;
141 tclParmsPtr
->execStr
= optarg
;
151 * If neither `-c' nor `-f' were specified and at least one parameter
152 * is supplied, then if is the file to execute. The rest of the arguments
153 * are passed to the script. Check for '--' as the last option, this also
154 * is a terminator for the file to execute.
156 if ((!tclParmsPtr
->execCommand
) && (!tclParmsPtr
->execFile
) &&
157 (optind
!= argc
) && !STREQU (argv
[optind
-1], "--")) {
158 tclParmsPtr
->execFile
= TRUE
;
159 tclParmsPtr
->execStr
= argv
[optind
];
163 tclParmsPtr
->tclArgv
= &argv
[optind
];
164 tclParmsPtr
->tclArgc
= argc
- optind
;
168 fprintf (stderr
, "usage: %s %s\n", argv
[0],
169 "[-qu] [[-f] script]|[-c command] [args]");
174 *-----------------------------------------------------------------------------
177 * Find the Tcl default file. If is looked for in the following order:
178 * o A environment variable named `TCLDEFAULT'.
179 * o The specified defaultFile (which normally has an version number
181 * A tcl variable `TCLDEFAULT', will contain the path of the default file
182 * to use after this procedure is executed, or a null string if it is not
185 * o interp (I) - A pointer to the interpreter.
186 * o defaultFile (I) - The file name of the default file to use, it
187 * normally contains a version number.
189 * TCL_OK if all is ok, TCL_ERROR if a error occured.
190 *-----------------------------------------------------------------------------
193 FindDefaultFile (Tcl_Interp
*interp
, char *defaultFile
)
195 char *defaultFileToUse
;
198 if ((defaultFileToUse
= getenv ("TCLDEFAULT")) == NULL
)
199 defaultFileToUse
= defaultFile
;
201 if (stat (defaultFileToUse
, &statBuf
) < 0)
202 defaultFileToUse
= "";
203 if (Tcl_SetVar (interp
, "TCLDEFAULT", defaultFileToUse
,
204 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
211 *-----------------------------------------------------------------------------
212 * ProcessDefaultFile --
214 * Process the Tcl default file and TclInit files. The default file
215 * is the only file at a fixed path. It is a script file that usaually
216 * defines a variable "TCLINIT", which has the path of the full
217 * initialization file. The default file can also set things such as path
218 * variables. If the TCLINIT variable is set, that file is then evaluated.
219 * If usually does the full Tcl initialization.
222 * o interp (I) - A pointer to the interpreter.
223 * o defaultFile (I) - The file name of the default file to use, it
224 * normally contains a version number.
226 * TCL_OK if all is ok, TCL_ERROR if an error occured.
227 *-----------------------------------------------------------------------------
230 ProcessDefaultFile (Tcl_Interp
*interp
, char *defaultFile
)
232 char *defaultFileToUse
;
234 defaultFileToUse
= Tcl_GetVar (interp
, "TCLDEFAULT", 1);
235 if (*defaultFileToUse
== '\0') {
236 Tcl_AppendResult (interp
,
237 "Can't access Tcl default file,\n",
238 " Located in one of the following ways:\n",
239 " Environment variable: `TCLDEFAULT' or,\n",
240 " File `", defaultFile
, "'.\n",
244 if (Tcl_EvalFile (interp
, defaultFileToUse
) != TCL_OK
)
246 Tcl_ResetResult (interp
);
252 *-----------------------------------------------------------------------------
255 * Process the Tcl init file, its abolute patch should be contained in
256 * a Tcl variable "TCLINIT". If the variable is not found, the file will
260 * o interp (I) - A pointer to the interpreter.
262 * TCL_OK if all is ok, TCL_ERROR if an error occured.
263 *-----------------------------------------------------------------------------
266 ProcessInitFile (Tcl_Interp
*interp
)
270 initFile
= Tcl_GetVar (interp
, "TCLINIT", 1);
271 if (initFile
!= NULL
) {
272 if (Tcl_EvalFile (interp
, initFile
) != TCL_OK
)
275 Tcl_ResetResult (interp
);
280 *-----------------------------------------------------------------------------
282 * Tcl_ShellEnvInit --
284 * Process the Tcl default file. The default file is the only file at a
285 * fixed path. It is a script file that usaually defines a variable "TCLINIT",
286 * which has the path of the full initialization file. The default file can
287 * also set things such as path variables.
290 * o interp - A pointer to the interpreter.
291 * o options - Flags to control the behavior of this routine, the following
292 * option is supported:
293 * o TCLSH_QUICK_STARTUP - Don't source the default file or Tcl init
295 * o TCLSH_ABORT_STARTUP_ERR - If set, abort the process if an error
297 * o TCLSH_NO_INIT_FILE - If set, process the default file, but not the
298 * init file. This can be used to make the default file do all
300 * o programName (I) - The name of the program being executed, usually
301 * taken from the main argv [0]. Used to set the Tcl variable. If NULL
302 * then the variable will not be set.
303 * o argc, argv (I) - Arguments to pass to the program in a Tcl list variable
304 * `argv'. Argv [0] should contain the first argument not the program
305 * name. If argv is NULL, then the variable will not be set.
306 * o interactive (I) - The value to assign to the `interactiveSession' Tcl
307 * variable. TRUE if an interactive Tcl command loop will be entered,
308 * FALSE if a script will be executed . The function does not enter the
309 * command loop, it just sets the variable.
310 * o defaultFile (I) - The file name of the default file to use. If NULL,
311 * then the standard Tcl default file is used, which is formed from a
312 * location specified at compile time and the Extended Tcl version
315 * The variables tclAppName, tclAppLongName, tclAppVersion
316 * must be set before calling thus routine if special values are desired.
319 * TCL_OK if all is ok, TCL_ERROR if an error occured.
320 *-----------------------------------------------------------------------------
323 Tcl_ShellEnvInit (Tcl_Interp
*interp
, unsigned options
, CONST
char *programName
, int argc
, CONST
char **argv
, int interactive
, CONST
char *defaultFile
)
326 char *defaultFilePath
;
329 * Setup patch to default file, if not specified.
331 if (defaultFile
== NULL
) {
332 defaultFilePath
= ckalloc (strlen (TCL_DEFAULT
) +
333 strlen (TCL_VERSION
) +
334 strlen (TCL_EXTD_VERSION_SUFFIX
) + 1);
335 strcpy (defaultFilePath
, TCL_DEFAULT
);
336 strcat (defaultFilePath
, TCL_VERSION
);
337 strcat (defaultFilePath
, TCL_EXTD_VERSION_SUFFIX
);
339 defaultFilePath
= (char *) defaultFile
;
342 if (programName
!= NULL
) {
343 if (Tcl_SetVar (interp
, "programName", (char *) programName
,
344 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
351 args
= Tcl_Merge (argc
, (char **) argv
);
352 if (Tcl_SetVar (interp
, "argv", args
,
353 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
356 if (result
!= TCL_OK
)
359 if (Tcl_SetVar (interp
, "interactiveSession", interactive
? "1" : "0",
360 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
363 tclxVersion
= ckalloc (strlen (TCL_VERSION
) +
364 strlen (TCL_EXTD_VERSION_SUFFIX
) + 1);
365 strcpy (tclxVersion
, TCL_VERSION
);
366 strcat (tclxVersion
, TCL_EXTD_VERSION_SUFFIX
);
369 tclxPatchlevel
= PATCHLEVEL
;
375 * Set application specific values to return from the infox if they
378 if (tclAppName
== NULL
)
380 if (tclAppLongname
== NULL
)
381 tclAppLongname
= "Extended Tcl";
382 if (tclAppVersion
== NULL
)
383 tclAppVersion
= tclxVersion
;
386 * Locate the default file and save in Tcl var TCLDEFAULT. If not quick
387 * startup, process the Tcl default file and execute the Tcl
388 * initialization file.
390 if (FindDefaultFile (interp
, (char *) defaultFilePath
) != TCL_OK
)
392 if (!(options
& TCLSH_QUICK_STARTUP
)) {
393 if (ProcessDefaultFile (interp
, defaultFilePath
) != TCL_OK
)
395 if (!(options
& TCLSH_NO_INIT_FILE
)) {
396 if (ProcessInitFile (interp
) != TCL_OK
)
400 if (defaultFilePath
!= defaultFile
)
401 ckfree (defaultFilePath
);
405 if (defaultFilePath
!= defaultFile
)
406 ckfree (defaultFilePath
);
407 if (options
& TCLSH_ABORT_STARTUP_ERR
)
408 Tcl_ErrorAbort (interp
, 255);
413 *-----------------------------------------------------------------------------
417 * Initializes the Tcl extended environment. This function processes the
418 * standard command line arguments and locates the Tcl default file. It then
419 * sources the default file and initialization file pointed to by the default
420 * file. Either an interactive command loop is created or a Tcl script file
421 * is executed depending on the command line. This functions calls
422 * Tcl_ShellEnvInit, so it should not be called separately.
425 * o interp - A pointer to the interpreter.
426 * o argc, argv - Arguments passed to main for the command line.
427 * o defaultFile (I) - The file name of the default file to use. If NULL,
428 * then the standard Tcl default file is used, which is formed from a
429 * location specified at compile time and the Extended Tcl version
431 * o options (I) - Options that control startup behavior. None are
434 * The variables tclAppName, tclAppLongName, tclAppVersion
435 * must be set before calling thus routine if special values are desired.
436 *-----------------------------------------------------------------------------
439 Tcl_Startup (Tcl_Interp
*interp
, int argc
, CONST
char **argv
, CONST
char *defaultFile
, unsigned options
)
446 * Process the arguments.
448 ParseCmdArgs (argc
, (char **) argv
, &tclParms
);
450 if (Tcl_ShellEnvInit (interp
,
452 (CONST
char *)tclParms
.programName
,
453 tclParms
.tclArgc
, (CONST
char **)tclParms
.tclArgv
,
454 (tclParms
.execStr
== NULL
),
455 (CONST
char *)defaultFile
) != TCL_OK
)
459 * If the invoked tcl interactively, give the user an interactive session,
460 * otherwise, source the command file or execute the specified command.
462 if (tclParms
.execFile
) {
463 result
= Tcl_EvalFile (interp
, tclParms
.execStr
);
464 if (result
!= TCL_OK
)
466 } else if (tclParms
.execCommand
) {
467 result
= Tcl_Eval (interp
, tclParms
.execStr
, 0, NULL
);
468 if (result
!= TCL_OK
)
471 Tcl_CommandLoop (interp
, stdin
, stdout
, tclShellCmdEvalProc
, 0);
473 Tcl_ResetResult (interp
);
477 Tcl_ErrorAbort (interp
, 255);