]>
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 (interp
, exitCode
)
80 fprintf (stderr
, "Error: %s\n", interp
->result
);
82 errorStack
= Tcl_GetVar (interp
, "errorInfo", 1);
83 if (errorStack
!= NULL
)
84 fprintf (stderr
, "%s\n", errorStack
);
89 *-----------------------------------------------------------------------------
93 * Parse the arguments passed to the Tcl shell
96 * o argc, argv - Arguments passed to main.
97 * o tclParmsPtr - Results of the parsed Tcl shell command line.
98 *-----------------------------------------------------------------------------
101 ParseCmdArgs (argc
, argv
, tclParmsPtr
)
104 tclParms_t
*tclParmsPtr
;
106 char *scanPtr
, *programName
;
110 tclParmsPtr
->execFile
= FALSE
;
111 tclParmsPtr
->execCommand
= FALSE
;
112 tclParmsPtr
->options
= 0;
113 tclParmsPtr
->execStr
= NULL
;
116 * Determine file name (less directories) that the Tcl interpreter is
119 scanPtr
= programName
= argv
[0];
120 while (*scanPtr
!= '\0') {
122 programName
= scanPtr
+ 1;
125 tclParmsPtr
->programName
= programName
;
126 programNameLen
= strlen (programName
);
129 * Scan arguments looking for flags to process here rather than to pass
130 * on to the scripts. The '-c' or '-f' must also be the last option to
131 * allow for script arguments starting with `-'.
133 while ((option
= getopt (argc
, argv
, "qc:f:u")) != -1) {
136 if (tclParmsPtr
->options
& TCLSH_QUICK_STARTUP
)
138 tclParmsPtr
->options
|= TCLSH_QUICK_STARTUP
;
141 tclParmsPtr
->execCommand
= TRUE
;
142 tclParmsPtr
->execStr
= optarg
;
145 tclParmsPtr
->execFile
= TRUE
;
146 tclParmsPtr
->execStr
= optarg
;
156 * If neither `-c' nor `-f' were specified and at least one parameter
157 * is supplied, then if is the file to execute. The rest of the arguments
158 * are passed to the script. Check for '--' as the last option, this also
159 * is a terminator for the file to execute.
161 if ((!tclParmsPtr
->execCommand
) && (!tclParmsPtr
->execFile
) &&
162 (optind
!= argc
) && !STREQU (argv
[optind
-1], "--")) {
163 tclParmsPtr
->execFile
= TRUE
;
164 tclParmsPtr
->execStr
= argv
[optind
];
168 tclParmsPtr
->tclArgv
= &argv
[optind
];
169 tclParmsPtr
->tclArgc
= argc
- optind
;
173 fprintf (stderr
, "usage: %s %s\n", argv
[0],
174 "[-qu] [[-f] script]|[-c command] [args]");
179 *-----------------------------------------------------------------------------
182 * Find the Tcl default file. If is looked for in the following order:
183 * o A environment variable named `TCLDEFAULT'.
184 * o The specified defaultFile (which normally has an version number
186 * A tcl variable `TCLDEFAULT', will contain the path of the default file
187 * to use after this procedure is executed, or a null string if it is not
190 * o interp (I) - A pointer to the interpreter.
191 * o defaultFile (I) - The file name of the default file to use, it
192 * normally contains a version number.
194 * TCL_OK if all is ok, TCL_ERROR if a error occured.
195 *-----------------------------------------------------------------------------
198 FindDefaultFile (interp
, defaultFile
)
202 char *defaultFileToUse
;
205 if ((defaultFileToUse
= getenv ("TCLDEFAULT")) == NULL
)
206 defaultFileToUse
= defaultFile
;
208 if (stat (defaultFileToUse
, &statBuf
) < 0)
209 defaultFileToUse
= "";
210 if (Tcl_SetVar (interp
, "TCLDEFAULT", defaultFileToUse
,
211 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
218 *-----------------------------------------------------------------------------
219 * ProcessDefaultFile --
221 * Process the Tcl default file and TclInit files. The default file
222 * is the only file at a fixed path. It is a script file that usaually
223 * defines a variable "TCLINIT", which has the path of the full
224 * initialization file. The default file can also set things such as path
225 * variables. If the TCLINIT variable is set, that file is then evaluated.
226 * If usually does the full Tcl initialization.
229 * o interp (I) - A pointer to the interpreter.
230 * o defaultFile (I) - The file name of the default file to use, it
231 * normally contains a version number.
233 * TCL_OK if all is ok, TCL_ERROR if an error occured.
234 *-----------------------------------------------------------------------------
237 ProcessDefaultFile (interp
, defaultFile
)
241 char *defaultFileToUse
;
243 defaultFileToUse
= Tcl_GetVar (interp
, "TCLDEFAULT", 1);
244 if (*defaultFileToUse
== '\0') {
245 Tcl_AppendResult (interp
,
246 "Can't access Tcl default file,\n",
247 " Located in one of the following ways:\n",
248 " Environment variable: `TCLDEFAULT' or,\n",
249 " File `", defaultFile
, "'.\n",
253 if (Tcl_EvalFile (interp
, defaultFileToUse
) != TCL_OK
)
255 Tcl_ResetResult (interp
);
261 *-----------------------------------------------------------------------------
264 * Process the Tcl init file, its abolute patch should be contained in
265 * a Tcl variable "TCLINIT". If the variable is not found, the file will
269 * o interp (I) - A pointer to the interpreter.
271 * TCL_OK if all is ok, TCL_ERROR if an error occured.
272 *-----------------------------------------------------------------------------
275 ProcessInitFile (interp
)
280 initFile
= Tcl_GetVar (interp
, "TCLINIT", 1);
281 if (initFile
!= NULL
) {
282 if (Tcl_EvalFile (interp
, initFile
) != TCL_OK
)
285 Tcl_ResetResult (interp
);
290 *-----------------------------------------------------------------------------
292 * Tcl_ShellEnvInit --
294 * Process the Tcl default file. The default file is the only file at a
295 * fixed path. It is a script file that usaually defines a variable "TCLINIT",
296 * which has the path of the full initialization file. The default file can
297 * also set things such as path variables.
300 * o interp - A pointer to the interpreter.
301 * o options - Flags to control the behavior of this routine, the following
302 * option is supported:
303 * o TCLSH_QUICK_STARTUP - Don't source the default file or Tcl init
305 * o TCLSH_ABORT_STARTUP_ERR - If set, abort the process if an error
307 * o TCLSH_NO_INIT_FILE - If set, process the default file, but not the
308 * init file. This can be used to make the default file do all
310 * o programName (I) - The name of the program being executed, usually
311 * taken from the main argv [0]. Used to set the Tcl variable. If NULL
312 * then the variable will not be set.
313 * o argc, argv (I) - Arguments to pass to the program in a Tcl list variable
314 * `argv'. Argv [0] should contain the first argument not the program
315 * name. If argv is NULL, then the variable will not be set.
316 * o interactive (I) - The value to assign to the `interactiveSession' Tcl
317 * variable. TRUE if an interactive Tcl command loop will be entered,
318 * FALSE if a script will be executed . The function does not enter the
319 * command loop, it just sets the variable.
320 * o defaultFile (I) - The file name of the default file to use. If NULL,
321 * then the standard Tcl default file is used, which is formed from a
322 * location specified at compile time and the Extended Tcl version
325 * The variables tclAppName, tclAppLongName, tclAppVersion
326 * must be set before calling thus routine if special values are desired.
329 * TCL_OK if all is ok, TCL_ERROR if an error occured.
330 *-----------------------------------------------------------------------------
333 Tcl_ShellEnvInit (interp
, options
, programName
, argc
, argv
, interactive
,
337 CONST
char *programName
;
341 CONST
char *defaultFile
;
344 char *defaultFilePath
;
347 * Setup patch to default file, if not specified.
349 if (defaultFile
== NULL
) {
350 defaultFilePath
= ckalloc (strlen (TCL_DEFAULT
) +
351 strlen (TCL_VERSION
) +
352 strlen (TCL_EXTD_VERSION_SUFFIX
) + 1);
353 strcpy (defaultFilePath
, TCL_DEFAULT
);
354 strcat (defaultFilePath
, TCL_VERSION
);
355 strcat (defaultFilePath
, TCL_EXTD_VERSION_SUFFIX
);
357 defaultFilePath
= (char *) defaultFile
;
360 if (programName
!= NULL
) {
361 if (Tcl_SetVar (interp
, "programName", (char *) programName
,
362 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
369 args
= Tcl_Merge (argc
, (char **) argv
);
370 if (Tcl_SetVar (interp
, "argv", args
,
371 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
374 if (result
!= TCL_OK
)
377 if (Tcl_SetVar (interp
, "interactiveSession", interactive
? "1" : "0",
378 TCL_GLOBAL_ONLY
| TCL_LEAVE_ERR_MSG
) == NULL
)
381 tclxVersion
= ckalloc (strlen (TCL_VERSION
) +
382 strlen (TCL_EXTD_VERSION_SUFFIX
) + 1);
383 strcpy (tclxVersion
, TCL_VERSION
);
384 strcat (tclxVersion
, TCL_EXTD_VERSION_SUFFIX
);
387 tclxPatchlevel
= PATCHLEVEL
;
393 * Set application specific values to return from the infox if they
396 if (tclAppName
== NULL
)
398 if (tclAppLongname
== NULL
)
399 tclAppLongname
= "Extended Tcl";
400 if (tclAppVersion
== NULL
)
401 tclAppVersion
= tclxVersion
;
404 * Locate the default file and save in Tcl var TCLDEFAULT. If not quick
405 * startup, process the Tcl default file and execute the Tcl
406 * initialization file.
408 if (FindDefaultFile (interp
, (char *) defaultFilePath
) != TCL_OK
)
410 if (!(options
& TCLSH_QUICK_STARTUP
)) {
411 if (ProcessDefaultFile (interp
, defaultFilePath
) != TCL_OK
)
413 if (!(options
& TCLSH_NO_INIT_FILE
)) {
414 if (ProcessInitFile (interp
) != TCL_OK
)
418 if (defaultFilePath
!= defaultFile
)
419 ckfree (defaultFilePath
);
423 if (defaultFilePath
!= defaultFile
)
424 ckfree (defaultFilePath
);
425 if (options
& TCLSH_ABORT_STARTUP_ERR
)
426 Tcl_ErrorAbort (interp
, 255);
431 *-----------------------------------------------------------------------------
435 * Initializes the Tcl extended environment. This function processes the
436 * standard command line arguments and locates the Tcl default file. It then
437 * sources the default file and initialization file pointed to by the default
438 * file. Either an interactive command loop is created or a Tcl script file
439 * is executed depending on the command line. This functions calls
440 * Tcl_ShellEnvInit, so it should not be called separately.
443 * o interp - A pointer to the interpreter.
444 * o argc, argv - Arguments passed to main for the command line.
445 * o defaultFile (I) - The file name of the default file to use. If NULL,
446 * then the standard Tcl default file is used, which is formed from a
447 * location specified at compile time and the Extended Tcl version
449 * o options (I) - Options that control startup behavior. None are
452 * The variables tclAppName, tclAppLongName, tclAppVersion
453 * must be set before calling thus routine if special values are desired.
454 *-----------------------------------------------------------------------------
457 Tcl_Startup (interp
, argc
, argv
, defaultFile
, options
)
461 CONST
char *defaultFile
;
469 * Process the arguments.
471 ParseCmdArgs (argc
, (char **) argv
, &tclParms
);
473 if (Tcl_ShellEnvInit (interp
,
475 (CONST
char *)tclParms
.programName
,
476 tclParms
.tclArgc
, (CONST
char **)tclParms
.tclArgv
,
477 (tclParms
.execStr
== NULL
),
478 (CONST
char *)defaultFile
) != TCL_OK
)
482 * If the invoked tcl interactively, give the user an interactive session,
483 * otherwise, source the command file or execute the specified command.
485 if (tclParms
.execFile
) {
486 result
= Tcl_EvalFile (interp
, tclParms
.execStr
);
487 if (result
!= TCL_OK
)
489 } else if (tclParms
.execCommand
) {
490 result
= Tcl_Eval (interp
, tclParms
.execStr
, 0, NULL
);
491 if (result
!= TCL_OK
)
494 Tcl_CommandLoop (interp
, stdin
, stdout
, tclShellCmdEvalProc
, 0);
496 Tcl_ResetResult (interp
);
500 Tcl_ErrorAbort (interp
, 255);