OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tcl/] [generic/] [tclMain.c] - Blame information for rev 1782

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tclMain.c --
3
 *
4
 *      Main program for Tcl shells and other Tcl-based applications.
5
 *
6
 * Copyright (c) 1988-1994 The Regents of the University of California.
7
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 * RCS: @(#) $Id: tclMain.c,v 1.1.1.1 2002-01-16 10:25:28 markom Exp $
13
 */
14
 
15
#include "tcl.h"
16
#include "tclInt.h"
17
 
18
# undef TCL_STORAGE_CLASS
19
# define TCL_STORAGE_CLASS DLLEXPORT
20
 
21
/*
22
 * The following code ensures that tclLink.c is linked whenever
23
 * Tcl is linked.  Without this code there's no reference to the
24
 * code in that file from anywhere in Tcl, so it may not be
25
 * linked into the application.
26
 */
27
 
28
EXTERN int Tcl_LinkVar();
29
int (*tclDummyLinkVarPtr)() = Tcl_LinkVar;
30
 
31
/*
32
 * Declarations for various library procedures and variables (don't want
33
 * to include tclPort.h here, because people might copy this file out of
34
 * the Tcl source directory to make their own modified versions).
35
 * Note:  "exit" should really be declared here, but there's no way to
36
 * declare it without causing conflicts with other definitions elsewher
37
 * on some systems, so it's better just to leave it out.
38
 */
39
 
40
extern int              isatty _ANSI_ARGS_((int fd));
41
extern char *           strcpy _ANSI_ARGS_((char *dst, CONST char *src));
42
 
43
static Tcl_Interp *interp;      /* Interpreter for application. */
44
 
45
#ifdef TCL_MEM_DEBUG
46
static char dumpFile[100];      /* Records where to dump memory allocation
47
                                 * information. */
48
static int quitFlag = 0; /* 1 means "checkmem" command was called,
49
                                 * so the application should quit and dump
50
                                 * memory allocation information. */
51
#endif
52
 
53
/*
54
 * Forward references for procedures defined later in this file:
55
 */
56
 
57
#ifdef TCL_MEM_DEBUG
58
static int              CheckmemCmd _ANSI_ARGS_((ClientData clientData,
59
                            Tcl_Interp *interp, int argc, char *argv[]));
60
#endif
61
 
62
/*
63
 *----------------------------------------------------------------------
64
 *
65
 * Tcl_Main --
66
 *
67
 *      Main program for tclsh and most other Tcl-based applications.
68
 *
69
 * Results:
70
 *      None. This procedure never returns (it exits the process when
71
 *      it's done.
72
 *
73
 * Side effects:
74
 *      This procedure initializes the Tk world and then starts
75
 *      interpreting commands;  almost anything could happen, depending
76
 *      on the script being interpreted.
77
 *
78
 *----------------------------------------------------------------------
79
 */
80
 
81
void
82
Tcl_Main(argc, argv, appInitProc)
83
    int argc;                   /* Number of arguments. */
84
    char **argv;                /* Array of argument strings. */
85
    Tcl_AppInitProc *appInitProc;
86
                                /* Application-specific initialization
87
                                 * procedure to call after most
88
                                 * initialization but before starting to
89
                                 * execute commands. */
90
{
91
    Tcl_Obj *prompt1NamePtr = NULL;
92
    Tcl_Obj *prompt2NamePtr = NULL;
93
    Tcl_Obj *resultPtr;
94
    Tcl_Obj *commandPtr = NULL;
95
    char buffer[1000], *args, *fileName, *bytes;
96
    int code, gotPartial, tty, length;
97
    int exitCode = 0;
98
    Tcl_Channel inChannel, outChannel, errChannel;
99
 
100
    Tcl_FindExecutable(argv[0]);
101
    interp = Tcl_CreateInterp();
102
#ifdef TCL_MEM_DEBUG
103
    Tcl_InitMemory(interp);
104
    Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0,
105
            (Tcl_CmdDeleteProc *) NULL);
106
#endif
107
 
108
    /*
109
     * Make command-line arguments available in the Tcl variables "argc"
110
     * and "argv".  If the first argument doesn't start with a "-" then
111
     * strip it off and use it as the name of a script file to process.
112
     */
113
 
114
    fileName = NULL;
115
    if ((argc > 1) && (argv[1][0] != '-')) {
116
        fileName = argv[1];
117
        argc--;
118
        argv++;
119
    }
120
    args = Tcl_Merge(argc-1, argv+1);
121
    Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
122
    ckfree(args);
123
    TclFormatInt(buffer, argc-1);
124
    Tcl_SetVar(interp, "argc", buffer, TCL_GLOBAL_ONLY);
125
    Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0],
126
            TCL_GLOBAL_ONLY);
127
 
128
    /*
129
     * Set the "tcl_interactive" variable.
130
     */
131
 
132
    tty = isatty(0);
133
    Tcl_SetVar(interp, "tcl_interactive",
134
            ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY);
135
 
136
    /*
137
     * Invoke application-specific initialization.
138
     */
139
 
140
    if ((*appInitProc)(interp) != TCL_OK) {
141
        errChannel = Tcl_GetStdChannel(TCL_STDERR);
142
        if (errChannel) {
143
            Tcl_Write(errChannel,
144
                    "application-specific initialization failed: ", -1);
145
            Tcl_Write(errChannel, interp->result, -1);
146
            Tcl_Write(errChannel, "\n", 1);
147
        }
148
    }
149
 
150
    /*
151
     * If a script file was specified then just source that file
152
     * and quit.
153
     */
154
 
155
    if (fileName != NULL) {
156
        code = Tcl_EvalFile(interp, fileName);
157
        if (code != TCL_OK) {
158
            errChannel = Tcl_GetStdChannel(TCL_STDERR);
159
            if (errChannel) {
160
                /*
161
                 * The following statement guarantees that the errorInfo
162
                 * variable is set properly.
163
                 */
164
 
165
                Tcl_AddErrorInfo(interp, "");
166
                Tcl_Write(errChannel,
167
                        Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY), -1);
168
                Tcl_Write(errChannel, "\n", 1);
169
            }
170
            exitCode = 1;
171
        }
172
        goto done;
173
    }
174
 
175
    /*
176
     * We're running interactively.  Source a user-specific startup
177
     * file if the application specified one and if the file exists.
178
     */
179
 
180
    Tcl_SourceRCFile(interp);
181
 
182
    /*
183
     * Process commands from stdin until there's an end-of-file.  Note
184
     * that we need to fetch the standard channels again after every
185
     * eval, since they may have been changed.
186
     */
187
 
188
    commandPtr = Tcl_NewObj();
189
    Tcl_IncrRefCount(commandPtr);
190
    prompt1NamePtr = Tcl_NewStringObj("tcl_prompt1", -1);
191
    Tcl_IncrRefCount(prompt1NamePtr);
192
    prompt2NamePtr = Tcl_NewStringObj("tcl_prompt2", -1);
193
    Tcl_IncrRefCount(prompt2NamePtr);
194
 
195
    inChannel = Tcl_GetStdChannel(TCL_STDIN);
196
    outChannel = Tcl_GetStdChannel(TCL_STDOUT);
197
    gotPartial = 0;
198
    while (1) {
199
        if (tty) {
200
            Tcl_Obj *promptCmdPtr;
201
 
202
            promptCmdPtr = Tcl_ObjGetVar2(interp,
203
                    (gotPartial? prompt2NamePtr : prompt1NamePtr),
204
                    (Tcl_Obj *) NULL, TCL_GLOBAL_ONLY);
205
            if (promptCmdPtr == NULL) {
206
                defaultPrompt:
207
                if (!gotPartial && outChannel) {
208
                    Tcl_Write(outChannel, "% ", 2);
209
                }
210
            } else {
211
                code = Tcl_EvalObj(interp, promptCmdPtr);
212
                inChannel = Tcl_GetStdChannel(TCL_STDIN);
213
                outChannel = Tcl_GetStdChannel(TCL_STDOUT);
214
                errChannel = Tcl_GetStdChannel(TCL_STDERR);
215
                if (code != TCL_OK) {
216
                    if (errChannel) {
217
                        resultPtr = Tcl_GetObjResult(interp);
218
                        bytes = Tcl_GetStringFromObj(resultPtr, &length);
219
                        Tcl_Write(errChannel, bytes, length);
220
                        Tcl_Write(errChannel, "\n", 1);
221
                    }
222
                    Tcl_AddErrorInfo(interp,
223
                            "\n    (script that generates prompt)");
224
                    goto defaultPrompt;
225
                }
226
            }
227
            if (outChannel) {
228
                Tcl_Flush(outChannel);
229
            }
230
        }
231
        if (!inChannel) {
232
            goto done;
233
        }
234
        length = Tcl_GetsObj(inChannel, commandPtr);
235
        if (length < 0) {
236
            goto done;
237
        }
238
        if ((length == 0) && Tcl_Eof(inChannel) && (!gotPartial)) {
239
            goto done;
240
        }
241
 
242
        /*
243
         * Add the newline removed by Tcl_GetsObj back to the string.
244
         */
245
 
246
        Tcl_AppendToObj(commandPtr, "\n", 1);
247
        if (!TclObjCommandComplete(commandPtr)) {
248
            gotPartial = 1;
249
            continue;
250
        }
251
 
252
        gotPartial = 0;
253
        code = Tcl_RecordAndEvalObj(interp, commandPtr, 0);
254
        inChannel = Tcl_GetStdChannel(TCL_STDIN);
255
        outChannel = Tcl_GetStdChannel(TCL_STDOUT);
256
        errChannel = Tcl_GetStdChannel(TCL_STDERR);
257
        Tcl_SetObjLength(commandPtr, 0);
258
        if (code != TCL_OK) {
259
            if (errChannel) {
260
                resultPtr = Tcl_GetObjResult(interp);
261
                bytes = Tcl_GetStringFromObj(resultPtr, &length);
262
                Tcl_Write(errChannel, bytes, length);
263
                Tcl_Write(errChannel, "\n", 1);
264
            }
265
        } else if (tty) {
266
            resultPtr = Tcl_GetObjResult(interp);
267
            bytes = Tcl_GetStringFromObj(resultPtr, &length);
268
            if ((length > 0) && outChannel) {
269
                Tcl_Write(outChannel, bytes, length);
270
                Tcl_Write(outChannel, "\n", 1);
271
            }
272
        }
273
#ifdef TCL_MEM_DEBUG
274
        if (quitFlag) {
275
            Tcl_DecrRefCount(commandPtr);
276
            Tcl_DecrRefCount(prompt1NamePtr);
277
            Tcl_DecrRefCount(prompt2NamePtr);
278
            Tcl_DeleteInterp(interp);
279
            Tcl_Exit(0);
280
        }
281
#endif
282
    }
283
 
284
    /*
285
     * Rather than calling exit, invoke the "exit" command so that
286
     * users can replace "exit" with some other command to do additional
287
     * cleanup on exit.  The Tcl_Eval call should never return.
288
     */
289
 
290
    done:
291
    if (commandPtr != NULL) {
292
        Tcl_DecrRefCount(commandPtr);
293
    }
294
    if (prompt1NamePtr != NULL) {
295
        Tcl_DecrRefCount(prompt1NamePtr);
296
    }
297
    if (prompt2NamePtr != NULL) {
298
        Tcl_DecrRefCount(prompt2NamePtr);
299
    }
300
    sprintf(buffer, "exit %d", exitCode);
301
    Tcl_Eval(interp, buffer);
302
}
303
 
304
/*
305
 *----------------------------------------------------------------------
306
 *
307
 * CheckmemCmd --
308
 *
309
 *      This is the command procedure for the "checkmem" command, which
310
 *      causes the application to exit after printing information about
311
 *      memory usage to the file passed to this command as its first
312
 *      argument.
313
 *
314
 * Results:
315
 *      Returns a standard Tcl completion code.
316
 *
317
 * Side effects:
318
 *      None.
319
 *
320
 *----------------------------------------------------------------------
321
 */
322
#ifdef TCL_MEM_DEBUG
323
 
324
        /* ARGSUSED */
325
static int
326
CheckmemCmd(clientData, interp, argc, argv)
327
    ClientData clientData;              /* Not used. */
328
    Tcl_Interp *interp;                 /* Interpreter for evaluation. */
329
    int argc;                           /* Number of arguments. */
330
    char *argv[];                       /* String values of arguments. */
331
{
332
    extern char *tclMemDumpFileName;
333
    if (argc != 2) {
334
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
335
                " fileName\"", (char *) NULL);
336
        return TCL_ERROR;
337
    }
338
    strcpy(dumpFile, argv[1]);
339
    tclMemDumpFileName = dumpFile;
340
    quitFlag = 1;
341
    return TCL_OK;
342
}
343
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.