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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [generic/] [tclTest.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 578 markom
/*
2
 * tclTest.c --
3
 *
4
 *      This file contains C command procedures for a bunch of additional
5
 *      Tcl commands that are used for testing out Tcl's C interfaces.
6
 *      These commands are not normally included in Tcl applications;
7
 *      they're only used for testing.
8
 *
9
 * Copyright (c) 1993-1994 The Regents of the University of California.
10
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
11
 *
12
 * See the file "license.terms" for information on usage and redistribution
13
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
 *
15
 * RCS: @(#) $Id: tclTest.c,v 1.1.1.1 2002-01-16 10:25:29 markom Exp $
16
 */
17
 
18
#define TCL_TEST
19
 
20
#include "tclInt.h"
21
#include "tclPort.h"
22
 
23
/*
24
 * Declare external functions used in Windows tests.
25
 */
26
 
27
#if defined(__WIN32__)
28
extern TclPlatformType *        TclWinGetPlatform _ANSI_ARGS_((void));
29
#endif
30
 
31
/*
32
 * Dynamic string shared by TestdcallCmd and DelCallbackProc;  used
33
 * to collect the results of the various deletion callbacks.
34
 */
35
 
36
static Tcl_DString delString;
37
static Tcl_Interp *delInterp;
38
 
39
/*
40
 * One of the following structures exists for each asynchronous
41
 * handler created by the "testasync" command".
42
 */
43
 
44
typedef struct TestAsyncHandler {
45
    int id;                             /* Identifier for this handler. */
46
    Tcl_AsyncHandler handler;           /* Tcl's token for the handler. */
47
    char *command;                      /* Command to invoke when the
48
                                         * handler is invoked. */
49
    struct TestAsyncHandler *nextPtr;   /* Next is list of handlers. */
50
} TestAsyncHandler;
51
 
52
static TestAsyncHandler *firstHandler = NULL;
53
 
54
/*
55
 * The dynamic string below is used by the "testdstring" command
56
 * to test the dynamic string facilities.
57
 */
58
 
59
static Tcl_DString dstring;
60
 
61
/*
62
 * The command trace below is used by the "testcmdtraceCmd" command
63
 * to test the command tracing facilities.
64
 */
65
 
66
static Tcl_Trace cmdTrace;
67
 
68
/*
69
 * One of the following structures exists for each command created
70
 * by TestdelCmd:
71
 */
72
 
73
typedef struct DelCmd {
74
    Tcl_Interp *interp;         /* Interpreter in which command exists. */
75
    char *deleteCmd;            /* Script to execute when command is
76
                                 * deleted.  Malloc'ed. */
77
} DelCmd;
78
 
79
/*
80
 * Forward declarations for procedures defined later in this file:
81
 */
82
 
83
int                     Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
84
static int              AsyncHandlerProc _ANSI_ARGS_((ClientData clientData,
85
                            Tcl_Interp *interp, int code));
86
static void             CleanupTestSetassocdataTests _ANSI_ARGS_((
87
                            ClientData clientData, Tcl_Interp *interp));
88
static void             CmdDelProc1 _ANSI_ARGS_((ClientData clientData));
89
static void             CmdDelProc2 _ANSI_ARGS_((ClientData clientData));
90
static int              CmdProc1 _ANSI_ARGS_((ClientData clientData,
91
                            Tcl_Interp *interp, int argc, char **argv));
92
static int              CmdProc2 _ANSI_ARGS_((ClientData clientData,
93
                            Tcl_Interp *interp, int argc, char **argv));
94
static void             CmdTraceDeleteProc _ANSI_ARGS_((
95
                            ClientData clientData, Tcl_Interp *interp,
96
                            int level, char *command, Tcl_CmdProc *cmdProc,
97
                            ClientData cmdClientData, int argc,
98
                            char **argv));
99
static void             CmdTraceProc _ANSI_ARGS_((ClientData clientData,
100
                            Tcl_Interp *interp, int level, char *command,
101
                            Tcl_CmdProc *cmdProc, ClientData cmdClientData,
102
                            int argc, char **argv));
103
static int              CreatedCommandProc _ANSI_ARGS_((
104
                            ClientData clientData, Tcl_Interp *interp,
105
                            int argc, char **argv));
106
static int              CreatedCommandProc2 _ANSI_ARGS_((
107
                            ClientData clientData, Tcl_Interp *interp,
108
                            int argc, char **argv));
109
static void             DelCallbackProc _ANSI_ARGS_((ClientData clientData,
110
                            Tcl_Interp *interp));
111
static int              DelCmdProc _ANSI_ARGS_((ClientData clientData,
112
                            Tcl_Interp *interp, int argc, char **argv));
113
static void             DelDeleteProc _ANSI_ARGS_((ClientData clientData));
114
static void             ExitProcEven _ANSI_ARGS_((ClientData clientData));
115
static void             ExitProcOdd _ANSI_ARGS_((ClientData clientData));
116
static int              GetTimesCmd _ANSI_ARGS_((ClientData clientData,
117
                            Tcl_Interp *interp, int argc, char **argv));
118
static int              NoopCmd _ANSI_ARGS_((ClientData clientData,
119
                            Tcl_Interp *interp, int argc, char **argv));
120
static int              NoopObjCmd _ANSI_ARGS_((ClientData clientData,
121
                            Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
122
static void             SpecialFree _ANSI_ARGS_((char *blockPtr));
123
static int              StaticInitProc _ANSI_ARGS_((Tcl_Interp *interp));
124
static int              TestaccessprocCmd _ANSI_ARGS_((ClientData dummy,
125
                            Tcl_Interp *interp, int argc, char **argv));
126
static int              TestAccessProc1 _ANSI_ARGS_((CONST char *path,
127
                           int mode));
128
static int              TestAccessProc2 _ANSI_ARGS_((CONST char *path,
129
                           int mode));
130
static int              TestAccessProc3 _ANSI_ARGS_((CONST char *path,
131
                           int mode));
132
static int              TestasyncCmd _ANSI_ARGS_((ClientData dummy,
133
                            Tcl_Interp *interp, int argc, char **argv));
134
static int              TestcmdinfoCmd _ANSI_ARGS_((ClientData dummy,
135
                            Tcl_Interp *interp, int argc, char **argv));
136
static int              TestcmdtokenCmd _ANSI_ARGS_((ClientData dummy,
137
                            Tcl_Interp *interp, int argc, char **argv));
138
static int              TestcmdtraceCmd _ANSI_ARGS_((ClientData dummy,
139
                            Tcl_Interp *interp, int argc, char **argv));
140
static int              TestchmodCmd _ANSI_ARGS_((ClientData dummy,
141
                            Tcl_Interp *interp, int argc, char **argv));
142
static int              TestcreatecommandCmd _ANSI_ARGS_((ClientData dummy,
143
                            Tcl_Interp *interp, int argc, char **argv));
144
static int              TestdcallCmd _ANSI_ARGS_((ClientData dummy,
145
                            Tcl_Interp *interp, int argc, char **argv));
146
static int              TestdelCmd _ANSI_ARGS_((ClientData dummy,
147
                            Tcl_Interp *interp, int argc, char **argv));
148
static int              TestdelassocdataCmd _ANSI_ARGS_((ClientData dummy,
149
                            Tcl_Interp *interp, int argc, char **argv));
150
static int              TestdstringCmd _ANSI_ARGS_((ClientData dummy,
151
                            Tcl_Interp *interp, int argc, char **argv));
152
static int              TestexithandlerCmd _ANSI_ARGS_((ClientData dummy,
153
                            Tcl_Interp *interp, int argc, char **argv));
154
static int              TestexprlongCmd _ANSI_ARGS_((ClientData dummy,
155
                            Tcl_Interp *interp, int argc, char **argv));
156
static int              TestexprstringCmd _ANSI_ARGS_((ClientData dummy,
157
                            Tcl_Interp *interp, int argc, char **argv));
158
static int              TestfileCmd _ANSI_ARGS_((ClientData dummy,
159
                            Tcl_Interp *interp, int argc, char **argv));
160
static int              TestfeventCmd _ANSI_ARGS_((ClientData dummy,
161
                            Tcl_Interp *interp, int argc, char **argv));
162
static int              TestgetassocdataCmd _ANSI_ARGS_((ClientData dummy,
163
                            Tcl_Interp *interp, int argc, char **argv));
164
static int              TestgetplatformCmd _ANSI_ARGS_((ClientData dummy,
165
                            Tcl_Interp *interp, int argc, char **argv));
166
static int              TestgetvarfullnameCmd _ANSI_ARGS_((
167
                            ClientData dummy, Tcl_Interp *interp,
168
                            int objc, Tcl_Obj *CONST objv[]));
169
static int              TestinterpdeleteCmd _ANSI_ARGS_((ClientData dummy,
170
                            Tcl_Interp *interp, int argc, char **argv));
171
static int              TestlinkCmd _ANSI_ARGS_((ClientData dummy,
172
                            Tcl_Interp *interp, int argc, char **argv));
173
static int              TestMathFunc _ANSI_ARGS_((ClientData clientData,
174
                            Tcl_Interp *interp, Tcl_Value *args,
175
                            Tcl_Value *resultPtr));
176
static int              TestMathFunc2 _ANSI_ARGS_((ClientData clientData,
177
                            Tcl_Interp *interp, Tcl_Value *args,
178
                            Tcl_Value *resultPtr));
179
static Tcl_Channel      TestOpenFileChannelProc1 _ANSI_ARGS_((Tcl_Interp *interp,
180
                            char *filename, char *modeString, int permissions));
181
static Tcl_Channel      TestOpenFileChannelProc2 _ANSI_ARGS_((Tcl_Interp *interp,
182
                            char *filename, char *modeString, int permissions));
183
static Tcl_Channel      TestOpenFileChannelProc3 _ANSI_ARGS_((Tcl_Interp *interp,
184
                            char *filename, char *modeString, int permissions));
185
static int              TestPanicCmd _ANSI_ARGS_((ClientData dummy,
186
                            Tcl_Interp *interp, int argc, char **argv));
187
static int              TestsetassocdataCmd _ANSI_ARGS_((ClientData dummy,
188
                            Tcl_Interp *interp, int argc, char **argv));
189
static int              TestsetnoerrCmd _ANSI_ARGS_((ClientData dummy,
190
                            Tcl_Interp *interp, int argc, char **argv));
191
static int              TestsetobjerrorcodeCmd _ANSI_ARGS_((
192
                            ClientData dummy, Tcl_Interp *interp,
193
                            int objc, Tcl_Obj *CONST objv[]));
194
static int              TestopenfilechannelprocCmd _ANSI_ARGS_((ClientData dummy,
195
                            Tcl_Interp *interp, int argc, char **argv));
196
static int              TestsetplatformCmd _ANSI_ARGS_((ClientData dummy,
197
                            Tcl_Interp *interp, int argc, char **argv));
198
static int              TestsetrecursionlimitCmd _ANSI_ARGS_((
199
                            ClientData dummy, Tcl_Interp *interp,
200
                            int objc, Tcl_Obj *CONST objv[]));
201
static int              TeststaticpkgCmd _ANSI_ARGS_((ClientData dummy,
202
                            Tcl_Interp *interp, int argc, char **argv));
203
static int              TestStatProc1 _ANSI_ARGS_((CONST char *path,
204
                            TclStat_ *buf));
205
static int              TestStatProc2 _ANSI_ARGS_((CONST char *path,
206
                            TclStat_ *buf));
207
static int              TestStatProc3 _ANSI_ARGS_((CONST char *path,
208
                            TclStat_ *buf));
209
static int              TeststatprocCmd _ANSI_ARGS_((ClientData dummy,
210
                            Tcl_Interp *interp, int argc, char **argv));
211
static int              TesttranslatefilenameCmd _ANSI_ARGS_((ClientData dummy,
212
                            Tcl_Interp *interp, int argc, char **argv));
213
static int              TestupvarCmd _ANSI_ARGS_((ClientData dummy,
214
                            Tcl_Interp *interp, int argc, char **argv));
215
static int              TestwordendObjCmd _ANSI_ARGS_((ClientData dummy,
216
                            Tcl_Interp *interp, int objc,
217
                            Tcl_Obj *CONST objv[]));
218
 
219
/*
220
 * External (platform specific) initialization routine:
221
 */
222
 
223
EXTERN int              TclplatformtestInit _ANSI_ARGS_((
224
                            Tcl_Interp *interp));
225
 
226
/*
227
 *----------------------------------------------------------------------
228
 *
229
 * Tcltest_Init --
230
 *
231
 *      This procedure performs application-specific initialization.
232
 *      Most applications, especially those that incorporate additional
233
 *      packages, will have their own version of this procedure.
234
 *
235
 * Results:
236
 *      Returns a standard Tcl completion code, and leaves an error
237
 *      message in interp->result if an error occurs.
238
 *
239
 * Side effects:
240
 *      Depends on the startup script.
241
 *
242
 *----------------------------------------------------------------------
243
 */
244
 
245
int
246
Tcltest_Init(interp)
247
    Tcl_Interp *interp;         /* Interpreter for application. */
248
{
249
    Tcl_ValueType t3ArgTypes[2];
250
 
251
    if (Tcl_PkgProvide(interp, "Tcltest", TCL_VERSION) == TCL_ERROR) {
252
        return TCL_ERROR;
253
    }
254
 
255
    /*
256
     * Create additional commands and math functions for testing Tcl.
257
     */
258
 
259
    Tcl_CreateCommand(interp, "noop", NoopCmd, (ClientData) 0,
260
            (Tcl_CmdDeleteProc *) NULL);
261
    Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, (ClientData) 0,
262
            (Tcl_CmdDeleteProc *) NULL);
263
    Tcl_CreateCommand(interp, "testaccessproc", TestaccessprocCmd, (ClientData) 0,
264
            (Tcl_CmdDeleteProc *) NULL);
265
    Tcl_CreateCommand(interp, "testasync", TestasyncCmd, (ClientData) 0,
266
            (Tcl_CmdDeleteProc *) NULL);
267
    Tcl_CreateCommand(interp, "testchannel", TclTestChannelCmd,
268
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
269
    Tcl_CreateCommand(interp, "testchannelevent", TclTestChannelEventCmd,
270
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
271
    Tcl_CreateCommand(interp, "testchmod", TestchmodCmd,
272
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
273
    Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, (ClientData) 0,
274
            (Tcl_CmdDeleteProc *) NULL);
275
    Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, (ClientData) 0,
276
            (Tcl_CmdDeleteProc *) NULL);
277
    Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
278
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
279
    Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd,
280
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
281
    Tcl_CreateCommand(interp, "testdcall", TestdcallCmd, (ClientData) 0,
282
            (Tcl_CmdDeleteProc *) NULL);
283
    Tcl_CreateCommand(interp, "testdel", TestdelCmd, (ClientData) 0,
284
            (Tcl_CmdDeleteProc *) NULL);
285
    Tcl_CreateCommand(interp, "testdelassocdata", TestdelassocdataCmd,
286
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
287
    Tcl_DStringInit(&dstring);
288
    Tcl_CreateCommand(interp, "testdstring", TestdstringCmd, (ClientData) 0,
289
            (Tcl_CmdDeleteProc *) NULL);
290
    Tcl_CreateCommand(interp, "testexithandler", TestexithandlerCmd,
291
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
292
    Tcl_CreateCommand(interp, "testexprlong", TestexprlongCmd,
293
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
294
    Tcl_CreateCommand(interp, "testexprstring", TestexprstringCmd,
295
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
296
    Tcl_CreateCommand(interp, "testfile", TestfileCmd,
297
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
298
    Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd,
299
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
300
    Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd,
301
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
302
    Tcl_CreateObjCommand(interp, "testgetvarfullname",
303
            TestgetvarfullnameCmd, (ClientData) 0,
304
            (Tcl_CmdDeleteProc *) NULL);
305
    Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
306
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
307
    Tcl_CreateCommand(interp, "testlink", TestlinkCmd, (ClientData) 0,
308
            (Tcl_CmdDeleteProc *) NULL);
309
    Tcl_CreateCommand(interp, "testopenfilechannelproc",
310
            TestopenfilechannelprocCmd, (ClientData) 0,
311
            (Tcl_CmdDeleteProc *) NULL);
312
    Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
313
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
314
    Tcl_CreateCommand(interp, "testsetnoerr", TestsetnoerrCmd,
315
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
316
    Tcl_CreateObjCommand(interp, "testsetobjerrorcode",
317
            TestsetobjerrorcodeCmd, (ClientData) 0,
318
            (Tcl_CmdDeleteProc *) NULL);
319
    Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
320
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
321
    Tcl_CreateObjCommand(interp, "testsetrecursionlimit",
322
            TestsetrecursionlimitCmd,
323
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
324
    Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
325
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
326
    Tcl_CreateCommand(interp, "testtranslatefilename",
327
            TesttranslatefilenameCmd, (ClientData) 0,
328
            (Tcl_CmdDeleteProc *) NULL);
329
    Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, (ClientData) 0,
330
            (Tcl_CmdDeleteProc *) NULL);
331
    Tcl_CreateObjCommand(interp, "testwordend", TestwordendObjCmd,
332
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
333
    Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, (ClientData) 0,
334
            (Tcl_CmdDeleteProc *) NULL);
335
    Tcl_CreateCommand(interp, "testpanic", TestPanicCmd, (ClientData) 0,
336
            (Tcl_CmdDeleteProc *) NULL);
337
    Tcl_CreateCommand(interp, "gettimes", GetTimesCmd, (ClientData) 0,
338
            (Tcl_CmdDeleteProc *) NULL);
339
    Tcl_CreateMathFunc(interp, "T1", 0, (Tcl_ValueType *) NULL, TestMathFunc,
340
            (ClientData) 123);
341
    Tcl_CreateMathFunc(interp, "T2", 0, (Tcl_ValueType *) NULL, TestMathFunc,
342
            (ClientData) 345);
343
    Tcl_CreateCommand(interp, "teststatproc", TeststatprocCmd, (ClientData) 0,
344
            (Tcl_CmdDeleteProc *) NULL);
345
    t3ArgTypes[0] = TCL_EITHER;
346
    t3ArgTypes[1] = TCL_EITHER;
347
    Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2,
348
            (ClientData) 0);
349
 
350
    /*
351
     * And finally add any platform specific test commands.
352
     */
353
 
354
    return TclplatformtestInit(interp);
355
}
356
 
357
/*
358
 *----------------------------------------------------------------------
359
 *
360
 * TestasyncCmd --
361
 *
362
 *      This procedure implements the "testasync" command.  It is used
363
 *      to test the asynchronous handler facilities of Tcl.
364
 *
365
 * Results:
366
 *      A standard Tcl result.
367
 *
368
 * Side effects:
369
 *      Creates, deletes, and invokes handlers.
370
 *
371
 *----------------------------------------------------------------------
372
 */
373
 
374
        /* ARGSUSED */
375
static int
376
TestasyncCmd(dummy, interp, argc, argv)
377
    ClientData dummy;                   /* Not used. */
378
    Tcl_Interp *interp;                 /* Current interpreter. */
379
    int argc;                           /* Number of arguments. */
380
    char **argv;                        /* Argument strings. */
381
{
382
    TestAsyncHandler *asyncPtr, *prevPtr;
383
    int id, code;
384
    static int nextId = 1;
385
    char buf[30];
386
 
387
    if (argc < 2) {
388
        wrongNumArgs:
389
        Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
390
        return TCL_ERROR;
391
    }
392
    if (strcmp(argv[1], "create") == 0) {
393
        if (argc != 3) {
394
            goto wrongNumArgs;
395
        }
396
        asyncPtr = (TestAsyncHandler *) ckalloc(sizeof(TestAsyncHandler));
397
        asyncPtr->id = nextId;
398
        nextId++;
399
        asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
400
                (ClientData) asyncPtr);
401
        asyncPtr->command = (char *) ckalloc((unsigned) (strlen(argv[2]) + 1));
402
        strcpy(asyncPtr->command, argv[2]);
403
        asyncPtr->nextPtr = firstHandler;
404
        firstHandler = asyncPtr;
405
        sprintf(buf, "%d", asyncPtr->id);
406
        Tcl_SetResult(interp, buf, TCL_VOLATILE);
407
    } else if (strcmp(argv[1], "delete") == 0) {
408
        if (argc == 2) {
409
            while (firstHandler != NULL) {
410
                asyncPtr = firstHandler;
411
                firstHandler = asyncPtr->nextPtr;
412
                Tcl_AsyncDelete(asyncPtr->handler);
413
                ckfree(asyncPtr->command);
414
                ckfree((char *) asyncPtr);
415
            }
416
            return TCL_OK;
417
        }
418
        if (argc != 3) {
419
            goto wrongNumArgs;
420
        }
421
        if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
422
            return TCL_ERROR;
423
        }
424
        for (prevPtr = NULL, asyncPtr = firstHandler; asyncPtr != NULL;
425
                prevPtr = asyncPtr, asyncPtr = asyncPtr->nextPtr) {
426
            if (asyncPtr->id != id) {
427
                continue;
428
            }
429
            if (prevPtr == NULL) {
430
                firstHandler = asyncPtr->nextPtr;
431
            } else {
432
                prevPtr->nextPtr = asyncPtr->nextPtr;
433
            }
434
            Tcl_AsyncDelete(asyncPtr->handler);
435
            ckfree(asyncPtr->command);
436
            ckfree((char *) asyncPtr);
437
            break;
438
        }
439
    } else if (strcmp(argv[1], "mark") == 0) {
440
        if (argc != 5) {
441
            goto wrongNumArgs;
442
        }
443
        if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK)
444
                || (Tcl_GetInt(interp, argv[4], &code) != TCL_OK)) {
445
            return TCL_ERROR;
446
        }
447
        for (asyncPtr = firstHandler; asyncPtr != NULL;
448
                asyncPtr = asyncPtr->nextPtr) {
449
            if (asyncPtr->id == id) {
450
                Tcl_AsyncMark(asyncPtr->handler);
451
                break;
452
            }
453
        }
454
        Tcl_SetResult(interp, argv[3], TCL_VOLATILE);
455
        return code;
456
    } else {
457
        Tcl_AppendResult(interp, "bad option \"", argv[1],
458
                "\": must be create, delete, int, or mark",
459
                (char *) NULL);
460
        return TCL_ERROR;
461
    }
462
    return TCL_OK;
463
}
464
 
465
static int
466
AsyncHandlerProc(clientData, interp, code)
467
    ClientData clientData;      /* Pointer to TestAsyncHandler structure. */
468
    Tcl_Interp *interp;         /* Interpreter in which command was
469
                                 * executed, or NULL. */
470
    int code;                   /* Current return code from command. */
471
{
472
    TestAsyncHandler *asyncPtr = (TestAsyncHandler *) clientData;
473
    char *listArgv[4];
474
    char string[20], *cmd;
475
 
476
    sprintf(string, "%d", code);
477
    listArgv[0] = asyncPtr->command;
478
    listArgv[1] = interp->result;
479
    listArgv[2] = string;
480
    listArgv[3] = NULL;
481
    cmd = Tcl_Merge(3, listArgv);
482
    code = Tcl_Eval(interp, cmd);
483
    ckfree(cmd);
484
    return code;
485
}
486
 
487
/*
488
 *----------------------------------------------------------------------
489
 *
490
 * TestcmdinfoCmd --
491
 *
492
 *      This procedure implements the "testcmdinfo" command.  It is used
493
 *      to test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation
494
 *      and deletion.
495
 *
496
 * Results:
497
 *      A standard Tcl result.
498
 *
499
 * Side effects:
500
 *      Creates and deletes various commands and modifies their data.
501
 *
502
 *----------------------------------------------------------------------
503
 */
504
 
505
        /* ARGSUSED */
506
static int
507
TestcmdinfoCmd(dummy, interp, argc, argv)
508
    ClientData dummy;                   /* Not used. */
509
    Tcl_Interp *interp;                 /* Current interpreter. */
510
    int argc;                           /* Number of arguments. */
511
    char **argv;                        /* Argument strings. */
512
{
513
    Tcl_CmdInfo info;
514
 
515
    if (argc != 3) {
516
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
517
                " option cmdName\"", (char *) NULL);
518
        return TCL_ERROR;
519
    }
520
    if (strcmp(argv[1], "create") == 0) {
521
        Tcl_CreateCommand(interp, argv[2], CmdProc1, (ClientData) "original",
522
                CmdDelProc1);
523
    } else if (strcmp(argv[1], "delete") == 0) {
524
        Tcl_DStringInit(&delString);
525
        Tcl_DeleteCommand(interp, argv[2]);
526
        Tcl_DStringResult(interp, &delString);
527
    } else if (strcmp(argv[1], "get") == 0) {
528
        if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) {
529
            Tcl_SetResult(interp, "??", TCL_STATIC);
530
            return TCL_OK;
531
        }
532
        if (info.proc == CmdProc1) {
533
            Tcl_AppendResult(interp, "CmdProc1", " ",
534
                    (char *) info.clientData, (char *) NULL);
535
        } else if (info.proc == CmdProc2) {
536
            Tcl_AppendResult(interp, "CmdProc2", " ",
537
                    (char *) info.clientData, (char *) NULL);
538
        } else {
539
            Tcl_AppendResult(interp, "unknown", (char *) NULL);
540
        }
541
        if (info.deleteProc == CmdDelProc1) {
542
            Tcl_AppendResult(interp, " CmdDelProc1", " ",
543
                    (char *) info.deleteData, (char *) NULL);
544
        } else if (info.deleteProc == CmdDelProc2) {
545
            Tcl_AppendResult(interp, " CmdDelProc2", " ",
546
                    (char *) info.deleteData, (char *) NULL);
547
        } else {
548
            Tcl_AppendResult(interp, " unknown", (char *) NULL);
549
        }
550
        Tcl_AppendResult(interp, " ", info.namespacePtr->fullName,
551
                (char *) NULL);
552
        if (info.isNativeObjectProc) {
553
            Tcl_AppendResult(interp, " nativeObjectProc", (char *) NULL);
554
        } else {
555
            Tcl_AppendResult(interp, " stringProc", (char *) NULL);
556
        }
557
    } else if (strcmp(argv[1], "modify") == 0) {
558
        info.proc = CmdProc2;
559
        info.clientData = (ClientData) "new_command_data";
560
        info.objProc = NULL;
561
        info.objClientData = (ClientData) NULL;
562
        info.deleteProc = CmdDelProc2;
563
        info.deleteData = (ClientData) "new_delete_data";
564
        if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
565
            Tcl_SetResult(interp, "0", TCL_STATIC);
566
        } else {
567
            Tcl_SetResult(interp, "1", TCL_STATIC);
568
        }
569
    } else {
570
        Tcl_AppendResult(interp, "bad option \"", argv[1],
571
                "\": must be create, delete, get, or modify",
572
                (char *) NULL);
573
        return TCL_ERROR;
574
    }
575
    return TCL_OK;
576
}
577
 
578
        /*ARGSUSED*/
579
static int
580
CmdProc1(clientData, interp, argc, argv)
581
    ClientData clientData;              /* String to return. */
582
    Tcl_Interp *interp;                 /* Current interpreter. */
583
    int argc;                           /* Number of arguments. */
584
    char **argv;                        /* Argument strings. */
585
{
586
    Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData,
587
            (char *) NULL);
588
    return TCL_OK;
589
}
590
 
591
        /*ARGSUSED*/
592
static int
593
CmdProc2(clientData, interp, argc, argv)
594
    ClientData clientData;              /* String to return. */
595
    Tcl_Interp *interp;                 /* Current interpreter. */
596
    int argc;                           /* Number of arguments. */
597
    char **argv;                        /* Argument strings. */
598
{
599
    Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData,
600
            (char *) NULL);
601
    return TCL_OK;
602
}
603
 
604
static void
605
CmdDelProc1(clientData)
606
    ClientData clientData;              /* String to save. */
607
{
608
    Tcl_DStringInit(&delString);
609
    Tcl_DStringAppend(&delString, "CmdDelProc1 ", -1);
610
    Tcl_DStringAppend(&delString, (char *) clientData, -1);
611
}
612
 
613
static void
614
CmdDelProc2(clientData)
615
    ClientData clientData;              /* String to save. */
616
{
617
    Tcl_DStringInit(&delString);
618
    Tcl_DStringAppend(&delString, "CmdDelProc2 ", -1);
619
    Tcl_DStringAppend(&delString, (char *) clientData, -1);
620
}
621
 
622
/*
623
 *----------------------------------------------------------------------
624
 *
625
 * TestcmdtokenCmd --
626
 *
627
 *      This procedure implements the "testcmdtoken" command. It is used
628
 *      to test Tcl_Command tokens and procedures such as
629
 *      Tcl_GetCommandFullName.
630
 *
631
 * Results:
632
 *      A standard Tcl result.
633
 *
634
 * Side effects:
635
 *      Creates and deletes various commands and modifies their data.
636
 *
637
 *----------------------------------------------------------------------
638
 */
639
 
640
        /* ARGSUSED */
641
static int
642
TestcmdtokenCmd(dummy, interp, argc, argv)
643
    ClientData dummy;                   /* Not used. */
644
    Tcl_Interp *interp;                 /* Current interpreter. */
645
    int argc;                           /* Number of arguments. */
646
    char **argv;                        /* Argument strings. */
647
{
648
    Tcl_Command token;
649
    long int l;
650
    char buf[30];
651
 
652
    if (argc != 3) {
653
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
654
                " option arg\"", (char *) NULL);
655
        return TCL_ERROR;
656
    }
657
    if (strcmp(argv[1], "create") == 0) {
658
        token = Tcl_CreateCommand(interp, argv[2], CmdProc1,
659
                (ClientData) "original", (Tcl_CmdDeleteProc *) NULL);
660
        sprintf(buf, "%lx", (long int) token);
661
        Tcl_SetResult(interp, buf, TCL_VOLATILE);
662
    } else if (strcmp(argv[1], "name") == 0) {
663
        Tcl_Obj *objPtr;
664
 
665
        if (sscanf(argv[2], "%lx", &l) != 1) {
666
            Tcl_AppendResult(interp, "bad command token \"", argv[2],
667
                    "\"", (char *) NULL);
668
            return TCL_ERROR;
669
        }
670
 
671
        objPtr = Tcl_NewObj();
672
        Tcl_GetCommandFullName(interp, (Tcl_Command) l, objPtr);
673
 
674
        Tcl_AppendElement(interp,
675
                Tcl_GetCommandName(interp, (Tcl_Command) l));
676
        Tcl_AppendElement(interp,
677
                Tcl_GetStringFromObj(objPtr, (int *) NULL));
678
        Tcl_DecrRefCount(objPtr);
679
    } else {
680
        Tcl_AppendResult(interp, "bad option \"", argv[1],
681
                "\": must be create or name", (char *) NULL);
682
        return TCL_ERROR;
683
    }
684
    return TCL_OK;
685
}
686
 
687
/*
688
 *----------------------------------------------------------------------
689
 *
690
 * TestcmdtraceCmd --
691
 *
692
 *      This procedure implements the "testcmdtrace" command. It is used
693
 *      to test Tcl_CreateTrace and Tcl_DeleteTrace.
694
 *
695
 * Results:
696
 *      A standard Tcl result.
697
 *
698
 * Side effects:
699
 *      Creates and deletes a command trace, and tests the invocation of
700
 *      a procedure by the command trace.
701
 *
702
 *----------------------------------------------------------------------
703
 */
704
 
705
        /* ARGSUSED */
706
static int
707
TestcmdtraceCmd(dummy, interp, argc, argv)
708
    ClientData dummy;                   /* Not used. */
709
    Tcl_Interp *interp;                 /* Current interpreter. */
710
    int argc;                           /* Number of arguments. */
711
    char **argv;                        /* Argument strings. */
712
{
713
    Tcl_DString buffer;
714
    int result;
715
 
716
    if (argc != 3) {
717
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
718
                " option script\"", (char *) NULL);
719
        return TCL_ERROR;
720
    }
721
 
722
    if (strcmp(argv[1], "tracetest") == 0) {
723
        Tcl_DStringInit(&buffer);
724
        cmdTrace = Tcl_CreateTrace(interp, 50000,
725
                (Tcl_CmdTraceProc *) CmdTraceProc, (ClientData) &buffer);
726
        result = Tcl_Eval(interp, argv[2]);
727
        if (result == TCL_OK) {
728
            Tcl_ResetResult(interp);
729
            Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
730
        }
731
        Tcl_DeleteTrace(interp, cmdTrace);
732
        Tcl_DStringFree(&buffer);
733
    } else if (strcmp(argv[1], "deletetest") == 0) {
734
        /*
735
         * Create a command trace then eval a script to check whether it is
736
         * called. Note that this trace procedure removes itself as a
737
         * further check of the robustness of the trace proc calling code in
738
         * TclExecuteByteCode.
739
         */
740
 
741
        cmdTrace = Tcl_CreateTrace(interp, 50000,
742
                (Tcl_CmdTraceProc *) CmdTraceDeleteProc, (ClientData) NULL);
743
        result = Tcl_Eval(interp, argv[2]);
744
    } else {
745
        Tcl_AppendResult(interp, "bad option \"", argv[1],
746
                "\": must be tracetest or deletetest", (char *) NULL);
747
        return TCL_ERROR;
748
    }
749
    return TCL_OK;
750
}
751
 
752
static void
753
CmdTraceProc(clientData, interp, level, command, cmdProc, cmdClientData,
754
        argc, argv)
755
    ClientData clientData;      /* Pointer to buffer in which the
756
                                 * command and arguments are appended.
757
                                 * Accumulates test result. */
758
    Tcl_Interp *interp;         /* Current interpreter. */
759
    int level;                  /* Current trace level. */
760
    char *command;              /* The command being traced (after
761
                                 * substitutions). */
762
    Tcl_CmdProc *cmdProc;       /* Points to command's command procedure. */
763
    ClientData cmdClientData;   /* Client data associated with command
764
                                 * procedure. */
765
    int argc;                   /* Number of arguments. */
766
    char **argv;                /* Argument strings. */
767
{
768
    Tcl_DString *bufPtr = (Tcl_DString *) clientData;
769
    int i;
770
 
771
    Tcl_DStringAppendElement(bufPtr, command);
772
 
773
    Tcl_DStringStartSublist(bufPtr);
774
    for (i = 0;  i < argc;  i++) {
775
        Tcl_DStringAppendElement(bufPtr, argv[i]);
776
    }
777
    Tcl_DStringEndSublist(bufPtr);
778
}
779
 
780
static void
781
CmdTraceDeleteProc(clientData, interp, level, command, cmdProc,
782
        cmdClientData, argc, argv)
783
    ClientData clientData;      /* Unused. */
784
    Tcl_Interp *interp;         /* Current interpreter. */
785
    int level;                  /* Current trace level. */
786
    char *command;              /* The command being traced (after
787
                                 * substitutions). */
788
    Tcl_CmdProc *cmdProc;       /* Points to command's command procedure. */
789
    ClientData cmdClientData;   /* Client data associated with command
790
                                 * procedure. */
791
    int argc;                   /* Number of arguments. */
792
    char **argv;                /* Argument strings. */
793
{
794
    /*
795
     * Remove ourselves to test whether calling Tcl_DeleteTrace within
796
     * a trace callback causes the for loop in TclExecuteByteCode that
797
     * calls traces to reference freed memory.
798
     */
799
 
800
    Tcl_DeleteTrace(interp, cmdTrace);
801
}
802
 
803
/*
804
 *----------------------------------------------------------------------
805
 *
806
 * TestcreatecommandCmd --
807
 *
808
 *      This procedure implements the "testcreatecommand" command. It is
809
 *      used to test that the Tcl_CreateCommand creates a new command in
810
 *      the namespace specified as part of its name, if any. It also
811
 *      checks that the namespace code ignore single ":"s in the middle
812
 *      or end of a command name.
813
 *
814
 * Results:
815
 *      A standard Tcl result.
816
 *
817
 * Side effects:
818
 *      Creates and deletes two commands ("test_ns_basic::createdcommand"
819
 *      and "value:at:").
820
 *
821
 *----------------------------------------------------------------------
822
 */
823
 
824
static int
825
TestcreatecommandCmd(dummy, interp, argc, argv)
826
    ClientData dummy;                   /* Not used. */
827
    Tcl_Interp *interp;                 /* Current interpreter. */
828
    int argc;                           /* Number of arguments. */
829
    char **argv;                        /* Argument strings. */
830
{
831
    if (argc != 2) {
832
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
833
                " option\"", (char *) NULL);
834
        return TCL_ERROR;
835
    }
836
    if (strcmp(argv[1], "create") == 0) {
837
        Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
838
                CreatedCommandProc, (ClientData) NULL,
839
                (Tcl_CmdDeleteProc *) NULL);
840
    } else if (strcmp(argv[1], "delete") == 0) {
841
        Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
842
    } else if (strcmp(argv[1], "create2") == 0) {
843
        Tcl_CreateCommand(interp, "value:at:",
844
                CreatedCommandProc2, (ClientData) NULL,
845
                (Tcl_CmdDeleteProc *) NULL);
846
    } else if (strcmp(argv[1], "delete2") == 0) {
847
        Tcl_DeleteCommand(interp, "value:at:");
848
    } else {
849
        Tcl_AppendResult(interp, "bad option \"", argv[1],
850
                "\": must be create, delete, create2, or delete2",
851
                (char *) NULL);
852
        return TCL_ERROR;
853
    }
854
    return TCL_OK;
855
}
856
 
857
static int
858
CreatedCommandProc(clientData, interp, argc, argv)
859
    ClientData clientData;              /* String to return. */
860
    Tcl_Interp *interp;                 /* Current interpreter. */
861
    int argc;                           /* Number of arguments. */
862
    char **argv;                        /* Argument strings. */
863
{
864
    Tcl_CmdInfo info;
865
    int found;
866
 
867
    found = Tcl_GetCommandInfo(interp, "test_ns_basic::createdcommand",
868
            &info);
869
    if (!found) {
870
        Tcl_AppendResult(interp, "CreatedCommandProc could not get command info for test_ns_basic::createdcommand",
871
                (char *) NULL);
872
        return TCL_ERROR;
873
    }
874
    Tcl_AppendResult(interp, "CreatedCommandProc in ",
875
            info.namespacePtr->fullName, (char *) NULL);
876
    return TCL_OK;
877
}
878
 
879
static int
880
CreatedCommandProc2(clientData, interp, argc, argv)
881
    ClientData clientData;              /* String to return. */
882
    Tcl_Interp *interp;                 /* Current interpreter. */
883
    int argc;                           /* Number of arguments. */
884
    char **argv;                        /* Argument strings. */
885
{
886
    Tcl_CmdInfo info;
887
    int found;
888
 
889
    found = Tcl_GetCommandInfo(interp, "value:at:", &info);
890
    if (!found) {
891
        Tcl_AppendResult(interp, "CreatedCommandProc2 could not get command info for test_ns_basic::createdcommand",
892
                (char *) NULL);
893
        return TCL_ERROR;
894
    }
895
    Tcl_AppendResult(interp, "CreatedCommandProc2 in ",
896
            info.namespacePtr->fullName, (char *) NULL);
897
    return TCL_OK;
898
}
899
 
900
/*
901
 *----------------------------------------------------------------------
902
 *
903
 * TestdcallCmd --
904
 *
905
 *      This procedure implements the "testdcall" command.  It is used
906
 *      to test Tcl_CallWhenDeleted.
907
 *
908
 * Results:
909
 *      A standard Tcl result.
910
 *
911
 * Side effects:
912
 *      Creates and deletes interpreters.
913
 *
914
 *----------------------------------------------------------------------
915
 */
916
 
917
        /* ARGSUSED */
918
static int
919
TestdcallCmd(dummy, interp, argc, argv)
920
    ClientData dummy;                   /* Not used. */
921
    Tcl_Interp *interp;                 /* Current interpreter. */
922
    int argc;                           /* Number of arguments. */
923
    char **argv;                        /* Argument strings. */
924
{
925
    int i, id;
926
 
927
    delInterp = Tcl_CreateInterp();
928
    Tcl_DStringInit(&delString);
929
    for (i = 1; i < argc; i++) {
930
        if (Tcl_GetInt(interp, argv[i], &id) != TCL_OK) {
931
            return TCL_ERROR;
932
        }
933
        if (id < 0) {
934
            Tcl_DontCallWhenDeleted(delInterp, DelCallbackProc,
935
                    (ClientData) (-id));
936
        } else {
937
            Tcl_CallWhenDeleted(delInterp, DelCallbackProc,
938
                    (ClientData) id);
939
        }
940
    }
941
    Tcl_DeleteInterp(delInterp);
942
    Tcl_DStringResult(interp, &delString);
943
    return TCL_OK;
944
}
945
 
946
/*
947
 * The deletion callback used by TestdcallCmd:
948
 */
949
 
950
static void
951
DelCallbackProc(clientData, interp)
952
    ClientData clientData;              /* Numerical value to append to
953
                                         * delString. */
954
    Tcl_Interp *interp;                 /* Interpreter being deleted. */
955
{
956
    int id = (int) clientData;
957
    char buffer[10];
958
 
959
    sprintf(buffer, "%d", id);
960
    Tcl_DStringAppendElement(&delString, buffer);
961
    if (interp != delInterp) {
962
        Tcl_DStringAppendElement(&delString, "bogus interpreter argument!");
963
    }
964
}
965
 
966
/*
967
 *----------------------------------------------------------------------
968
 *
969
 * TestdelCmd --
970
 *
971
 *      This procedure implements the "testdcall" command.  It is used
972
 *      to test Tcl_CallWhenDeleted.
973
 *
974
 * Results:
975
 *      A standard Tcl result.
976
 *
977
 * Side effects:
978
 *      Creates and deletes interpreters.
979
 *
980
 *----------------------------------------------------------------------
981
 */
982
 
983
        /* ARGSUSED */
984
static int
985
TestdelCmd(dummy, interp, argc, argv)
986
    ClientData dummy;                   /* Not used. */
987
    Tcl_Interp *interp;                 /* Current interpreter. */
988
    int argc;                           /* Number of arguments. */
989
    char **argv;                        /* Argument strings. */
990
{
991
    DelCmd *dPtr;
992
    Tcl_Interp *slave;
993
 
994
    if (argc != 4) {
995
        Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
996
        return TCL_ERROR;
997
    }
998
 
999
    slave = Tcl_GetSlave(interp, argv[1]);
1000
    if (slave == NULL) {
1001
        return TCL_ERROR;
1002
    }
1003
 
1004
    dPtr = (DelCmd *) ckalloc(sizeof(DelCmd));
1005
    dPtr->interp = interp;
1006
    dPtr->deleteCmd = (char *) ckalloc((unsigned) (strlen(argv[3]) + 1));
1007
    strcpy(dPtr->deleteCmd, argv[3]);
1008
 
1009
    Tcl_CreateCommand(slave, argv[2], DelCmdProc, (ClientData) dPtr,
1010
            DelDeleteProc);
1011
    return TCL_OK;
1012
}
1013
 
1014
static int
1015
DelCmdProc(clientData, interp, argc, argv)
1016
    ClientData clientData;              /* String result to return. */
1017
    Tcl_Interp *interp;                 /* Current interpreter. */
1018
    int argc;                           /* Number of arguments. */
1019
    char **argv;                        /* Argument strings. */
1020
{
1021
    DelCmd *dPtr = (DelCmd *) clientData;
1022
 
1023
    Tcl_AppendResult(interp, dPtr->deleteCmd, (char *) NULL);
1024
    ckfree(dPtr->deleteCmd);
1025
    ckfree((char *) dPtr);
1026
    return TCL_OK;
1027
}
1028
 
1029
static void
1030
DelDeleteProc(clientData)
1031
    ClientData clientData;              /* String command to evaluate. */
1032
{
1033
    DelCmd *dPtr = (DelCmd *) clientData;
1034
 
1035
    Tcl_Eval(dPtr->interp, dPtr->deleteCmd);
1036
    Tcl_ResetResult(dPtr->interp);
1037
    ckfree(dPtr->deleteCmd);
1038
    ckfree((char *) dPtr);
1039
}
1040
 
1041
/*
1042
 *----------------------------------------------------------------------
1043
 *
1044
 * TestdelassocdataCmd --
1045
 *
1046
 *      This procedure implements the "testdelassocdata" command. It is used
1047
 *      to test Tcl_DeleteAssocData.
1048
 *
1049
 * Results:
1050
 *      A standard Tcl result.
1051
 *
1052
 * Side effects:
1053
 *      Deletes an association between a key and associated data from an
1054
 *      interpreter.
1055
 *
1056
 *----------------------------------------------------------------------
1057
 */
1058
 
1059
static int
1060
TestdelassocdataCmd(clientData, interp, argc, argv)
1061
    ClientData clientData;              /* Not used. */
1062
    Tcl_Interp *interp;                 /* Current interpreter. */
1063
    int argc;                           /* Number of arguments. */
1064
    char **argv;                        /* Argument strings. */
1065
{
1066
    if (argc != 2) {
1067
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
1068
                " data_key\"", (char *) NULL);
1069
        return TCL_ERROR;
1070
    }
1071
    Tcl_DeleteAssocData(interp, argv[1]);
1072
    return TCL_OK;
1073
}
1074
 
1075
/*
1076
 *----------------------------------------------------------------------
1077
 *
1078
 * TestdstringCmd --
1079
 *
1080
 *      This procedure implements the "testdstring" command.  It is used
1081
 *      to test the dynamic string facilities of Tcl.
1082
 *
1083
 * Results:
1084
 *      A standard Tcl result.
1085
 *
1086
 * Side effects:
1087
 *      Creates, deletes, and invokes handlers.
1088
 *
1089
 *----------------------------------------------------------------------
1090
 */
1091
 
1092
        /* ARGSUSED */
1093
static int
1094
TestdstringCmd(dummy, interp, argc, argv)
1095
    ClientData dummy;                   /* Not used. */
1096
    Tcl_Interp *interp;                 /* Current interpreter. */
1097
    int argc;                           /* Number of arguments. */
1098
    char **argv;                        /* Argument strings. */
1099
{
1100
    int count;
1101
 
1102
    if (argc < 2) {
1103
        wrongNumArgs:
1104
        Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
1105
        return TCL_ERROR;
1106
    }
1107
    if (strcmp(argv[1], "append") == 0) {
1108
        if (argc != 4) {
1109
            goto wrongNumArgs;
1110
        }
1111
        if (Tcl_GetInt(interp, argv[3], &count) != TCL_OK) {
1112
            return TCL_ERROR;
1113
        }
1114
        Tcl_DStringAppend(&dstring, argv[2], count);
1115
    } else if (strcmp(argv[1], "element") == 0) {
1116
        if (argc != 3) {
1117
            goto wrongNumArgs;
1118
        }
1119
        Tcl_DStringAppendElement(&dstring, argv[2]);
1120
    } else if (strcmp(argv[1], "end") == 0) {
1121
        if (argc != 2) {
1122
            goto wrongNumArgs;
1123
        }
1124
        Tcl_DStringEndSublist(&dstring);
1125
    } else if (strcmp(argv[1], "free") == 0) {
1126
        if (argc != 2) {
1127
            goto wrongNumArgs;
1128
        }
1129
        Tcl_DStringFree(&dstring);
1130
    } else if (strcmp(argv[1], "get") == 0) {
1131
        if (argc != 2) {
1132
            goto wrongNumArgs;
1133
        }
1134
        Tcl_SetResult(interp, Tcl_DStringValue(&dstring), TCL_VOLATILE);
1135
    } else if (strcmp(argv[1], "gresult") == 0) {
1136
        if (argc != 3) {
1137
            goto wrongNumArgs;
1138
        }
1139
        if (strcmp(argv[2], "staticsmall") == 0) {
1140
            Tcl_SetResult(interp, "short", TCL_STATIC);
1141
        } else if (strcmp(argv[2], "staticlarge") == 0) {
1142
            Tcl_SetResult(interp, "first0 first1 first2 first3 first4 first5 first6 first7 first8 first9\nsecond0 second1 second2 second3 second4 second5 second6 second7 second8 second9\nthird0 third1 third2 third3 third4 third5 third6 third7 third8 third9\nfourth0 fourth1 fourth2 fourth3 fourth4 fourth5 fourth6 fourth7 fourth8 fourth9\nfifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9\nsixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9\nseventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9\n", TCL_STATIC);
1143
        } else if (strcmp(argv[2], "free") == 0) {
1144
            Tcl_SetResult(interp, (char *) ckalloc(100), TCL_DYNAMIC);
1145
            strcpy(interp->result, "This is a malloc-ed string");
1146
        } else if (strcmp(argv[2], "special") == 0) {
1147
            interp->result = (char *) ckalloc(100);
1148
            interp->result += 4;
1149
            interp->freeProc = SpecialFree;
1150
            strcpy(interp->result, "This is a specially-allocated string");
1151
        } else {
1152
            Tcl_AppendResult(interp, "bad gresult option \"", argv[2],
1153
                    "\": must be staticsmall, staticlarge, free, or special",
1154
                    (char *) NULL);
1155
            return TCL_ERROR;
1156
        }
1157
        Tcl_DStringGetResult(interp, &dstring);
1158
    } else if (strcmp(argv[1], "length") == 0) {
1159
        char buf[30];
1160
 
1161
        if (argc != 2) {
1162
            goto wrongNumArgs;
1163
        }
1164
        sprintf(buf, "%d", Tcl_DStringLength(&dstring));
1165
        Tcl_SetResult(interp, buf, TCL_VOLATILE);
1166
    } else if (strcmp(argv[1], "result") == 0) {
1167
        if (argc != 2) {
1168
            goto wrongNumArgs;
1169
        }
1170
        Tcl_DStringResult(interp, &dstring);
1171
    } else if (strcmp(argv[1], "trunc") == 0) {
1172
        if (argc != 3) {
1173
            goto wrongNumArgs;
1174
        }
1175
        if (Tcl_GetInt(interp, argv[2], &count) != TCL_OK) {
1176
            return TCL_ERROR;
1177
        }
1178
        Tcl_DStringTrunc(&dstring, count);
1179
    } else if (strcmp(argv[1], "start") == 0) {
1180
        if (argc != 2) {
1181
            goto wrongNumArgs;
1182
        }
1183
        Tcl_DStringStartSublist(&dstring);
1184
    } else {
1185
        Tcl_AppendResult(interp, "bad option \"", argv[1],
1186
                "\": must be append, element, end, free, get, length, ",
1187
                "result, trunc, or start", (char *) NULL);
1188
        return TCL_ERROR;
1189
    }
1190
    return TCL_OK;
1191
}
1192
 
1193
/*
1194
 * The procedure below is used as a special freeProc to test how well
1195
 * Tcl_DStringGetResult handles freeProc's other than free.
1196
 */
1197
 
1198
static void SpecialFree(blockPtr)
1199
    char *blockPtr;                     /* Block to free. */
1200
{
1201
    ckfree(blockPtr - 4);
1202
}
1203
 
1204
/*
1205
 *----------------------------------------------------------------------
1206
 *
1207
 * TestexithandlerCmd --
1208
 *
1209
 *      This procedure implements the "testexithandler" command. It is
1210
 *      used to test Tcl_CreateExitHandler and Tcl_DeleteExitHandler.
1211
 *
1212
 * Results:
1213
 *      A standard Tcl result.
1214
 *
1215
 * Side effects:
1216
 *      None.
1217
 *
1218
 *----------------------------------------------------------------------
1219
 */
1220
 
1221
static int
1222
TestexithandlerCmd(clientData, interp, argc, argv)
1223
    ClientData clientData;              /* Not used. */
1224
    Tcl_Interp *interp;                 /* Current interpreter. */
1225
    int argc;                           /* Number of arguments. */
1226
    char **argv;                        /* Argument strings. */
1227
{
1228
    int value;
1229
 
1230
    if (argc != 3) {
1231
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
1232
                " create|delete value\"", (char *) NULL);
1233
        return TCL_ERROR;
1234
    }
1235
    if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
1236
        return TCL_ERROR;
1237
    }
1238
    if (strcmp(argv[1], "create") == 0) {
1239
        Tcl_CreateExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
1240
                (ClientData) value);
1241
    } else if (strcmp(argv[1], "delete") == 0) {
1242
        Tcl_DeleteExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
1243
                (ClientData) value);
1244
    } else {
1245
        Tcl_AppendResult(interp, "bad option \"", argv[1],
1246
                "\": must be create or delete", (char *) NULL);
1247
        return TCL_ERROR;
1248
    }
1249
    return TCL_OK;
1250
}
1251
 
1252
static void
1253
ExitProcOdd(clientData)
1254
    ClientData clientData;              /* Integer value to print. */
1255
{
1256
    char buf[100];
1257
 
1258
    sprintf(buf, "odd %d\n", (int) clientData);
1259
    write(1, buf, strlen(buf));
1260
}
1261
 
1262
static void
1263
ExitProcEven(clientData)
1264
    ClientData clientData;              /* Integer value to print. */
1265
{
1266
    char buf[100];
1267
 
1268
    sprintf(buf, "even %d\n", (int) clientData);
1269
    write(1, buf, strlen(buf));
1270
}
1271
 
1272
/*
1273
 *----------------------------------------------------------------------
1274
 *
1275
 * TestexprlongCmd --
1276
 *
1277
 *      This procedure verifies that Tcl_ExprLong does not modify the
1278
 *      interpreter result if there is no error.
1279
 *
1280
 * Results:
1281
 *      A standard Tcl result.
1282
 *
1283
 * Side effects:
1284
 *      None.
1285
 *
1286
 *----------------------------------------------------------------------
1287
 */
1288
 
1289
static int
1290
TestexprlongCmd(clientData, interp, argc, argv)
1291
    ClientData clientData;              /* Not used. */
1292
    Tcl_Interp *interp;                 /* Current interpreter. */
1293
    int argc;                           /* Number of arguments. */
1294
    char **argv;                        /* Argument strings. */
1295
{
1296
    long exprResult;
1297
    char buf[30];
1298
    int result;
1299
 
1300
    Tcl_SetResult(interp, "This is a result", TCL_STATIC);
1301
    result = Tcl_ExprLong(interp, "4+1", &exprResult);
1302
    if (result != TCL_OK) {
1303
        return result;
1304
    }
1305
    sprintf(buf, ": %ld", exprResult);
1306
    Tcl_AppendResult(interp, buf, NULL);
1307
    return TCL_OK;
1308
}
1309
 
1310
/*
1311
 *----------------------------------------------------------------------
1312
 *
1313
 * TestexprstringCmd --
1314
 *
1315
 *      This procedure tests the basic operation of Tcl_ExprString.
1316
 *
1317
 * Results:
1318
 *      A standard Tcl result.
1319
 *
1320
 * Side effects:
1321
 *      None.
1322
 *
1323
 *----------------------------------------------------------------------
1324
 */
1325
 
1326
static int
1327
TestexprstringCmd(clientData, interp, argc, argv)
1328
    ClientData clientData;              /* Not used. */
1329
    Tcl_Interp *interp;                 /* Current interpreter. */
1330
    int argc;                           /* Number of arguments. */
1331
    char **argv;                        /* Argument strings. */
1332
{
1333
    if (argc != 2) {
1334
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
1335
                " expression\"", (char *) NULL);
1336
        return TCL_ERROR;
1337
    }
1338
    return Tcl_ExprString(interp, argv[1]);
1339
}
1340
 
1341
/*
1342
 *----------------------------------------------------------------------
1343
 *
1344
 * TestgetassocdataCmd --
1345
 *
1346
 *      This procedure implements the "testgetassocdata" command. It is
1347
 *      used to test Tcl_GetAssocData.
1348
 *
1349
 * Results:
1350
 *      A standard Tcl result.
1351
 *
1352
 * Side effects:
1353
 *      None.
1354
 *
1355
 *----------------------------------------------------------------------
1356
 */
1357
 
1358
static int
1359
TestgetassocdataCmd(clientData, interp, argc, argv)
1360
    ClientData clientData;              /* Not used. */
1361
    Tcl_Interp *interp;                 /* Current interpreter. */
1362
    int argc;                           /* Number of arguments. */
1363
    char **argv;                        /* Argument strings. */
1364
{
1365
    char *res;
1366
 
1367
    if (argc != 2) {
1368
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
1369
                " data_key\"", (char *) NULL);
1370
        return TCL_ERROR;
1371
    }
1372
    res = (char *) Tcl_GetAssocData(interp, argv[1], NULL);
1373
    if (res != NULL) {
1374
        Tcl_AppendResult(interp, res, NULL);
1375
    }
1376
    return TCL_OK;
1377
}
1378
 
1379
/*
1380
 *----------------------------------------------------------------------
1381
 *
1382
 * TestgetplatformCmd --
1383
 *
1384
 *      This procedure implements the "testgetplatform" command. It is
1385
 *      used to retrievel the value of the tclPlatform global variable.
1386
 *
1387
 * Results:
1388
 *      A standard Tcl result.
1389
 *
1390
 * Side effects:
1391
 *      None.
1392
 *
1393
 *----------------------------------------------------------------------
1394
 */
1395
 
1396
static int
1397
TestgetplatformCmd(clientData, interp, argc, argv)
1398
    ClientData clientData;              /* Not used. */
1399
    Tcl_Interp *interp;                 /* Current interpreter. */
1400
    int argc;                           /* Number of arguments. */
1401
    char **argv;                        /* Argument strings. */
1402
{
1403
    static char *platformStrings[] = { "unix", "mac", "windows" };
1404
    TclPlatformType *platform;
1405
 
1406
#ifdef __WIN32__
1407
    platform = TclWinGetPlatform();
1408
#else
1409
    platform = &tclPlatform;
1410
#endif
1411
 
1412
    if (argc != 1) {
1413
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
1414
                (char *) NULL);
1415
        return TCL_ERROR;
1416
    }
1417
 
1418
    Tcl_AppendResult(interp, platformStrings[*platform], NULL);
1419
    return TCL_OK;
1420
}
1421
 
1422
/*
1423
 *----------------------------------------------------------------------
1424
 *
1425
 * TestinterpdeleteCmd --
1426
 *
1427
 *      This procedure tests the code in tclInterp.c that deals with
1428
 *      interpreter deletion. It deletes a user-specified interpreter
1429
 *      from the hierarchy, and subsequent code checks integrity.
1430
 *
1431
 * Results:
1432
 *      A standard Tcl result.
1433
 *
1434
 * Side effects:
1435
 *      Deletes one or more interpreters.
1436
 *
1437
 *----------------------------------------------------------------------
1438
 */
1439
 
1440
        /* ARGSUSED */
1441
static int
1442
TestinterpdeleteCmd(dummy, interp, argc, argv)
1443
    ClientData dummy;                   /* Not used. */
1444
    Tcl_Interp *interp;                 /* Current interpreter. */
1445
    int argc;                           /* Number of arguments. */
1446
    char **argv;                        /* Argument strings. */
1447
{
1448
    Tcl_Interp *slaveToDelete;
1449
 
1450
    if (argc != 2) {
1451
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1452
                " path\"", (char *) NULL);
1453
        return TCL_ERROR;
1454
    }
1455
    if (argv[1][0] == '\0') {
1456
        Tcl_AppendResult(interp, "cannot delete current interpreter",
1457
                (char *) NULL);
1458
        return TCL_ERROR;
1459
    }
1460
    slaveToDelete = Tcl_GetSlave(interp, argv[1]);
1461
    if (slaveToDelete == (Tcl_Interp *) NULL) {
1462
        Tcl_AppendResult(interp, "could not find interpreter \"",
1463
                argv[1], "\"", (char *) NULL);
1464
        return TCL_ERROR;
1465
    }
1466
    Tcl_DeleteInterp(slaveToDelete);
1467
    return TCL_OK;
1468
}
1469
 
1470
/*
1471
 *----------------------------------------------------------------------
1472
 *
1473
 * TestlinkCmd --
1474
 *
1475
 *      This procedure implements the "testlink" command.  It is used
1476
 *      to test Tcl_LinkVar and related library procedures.
1477
 *
1478
 * Results:
1479
 *      A standard Tcl result.
1480
 *
1481
 * Side effects:
1482
 *      Creates and deletes various variable links, plus returns
1483
 *      values of the linked variables.
1484
 *
1485
 *----------------------------------------------------------------------
1486
 */
1487
 
1488
        /* ARGSUSED */
1489
static int
1490
TestlinkCmd(dummy, interp, argc, argv)
1491
    ClientData dummy;                   /* Not used. */
1492
    Tcl_Interp *interp;                 /* Current interpreter. */
1493
    int argc;                           /* Number of arguments. */
1494
    char **argv;                        /* Argument strings. */
1495
{
1496
    static int intVar = 43;
1497
    static int boolVar = 4;
1498
    static double realVar = 1.23;
1499
    static char *stringVar = NULL;
1500
    static int created = 0;
1501
    char buffer[TCL_DOUBLE_SPACE];
1502
    int writable, flag;
1503
 
1504
    if (argc < 2) {
1505
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1506
                " option ?arg arg arg?\"", (char *) NULL);
1507
        return TCL_ERROR;
1508
    }
1509
    if (strcmp(argv[1], "create") == 0) {
1510
        if (created) {
1511
            Tcl_UnlinkVar(interp, "int");
1512
            Tcl_UnlinkVar(interp, "real");
1513
            Tcl_UnlinkVar(interp, "bool");
1514
            Tcl_UnlinkVar(interp, "string");
1515
        }
1516
        created = 1;
1517
        if (Tcl_GetBoolean(interp, argv[2], &writable) != TCL_OK) {
1518
            return TCL_ERROR;
1519
        }
1520
        flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
1521
        if (Tcl_LinkVar(interp, "int", (char *) &intVar,
1522
                TCL_LINK_INT | flag) != TCL_OK) {
1523
            return TCL_ERROR;
1524
        }
1525
        if (Tcl_GetBoolean(interp, argv[3], &writable) != TCL_OK) {
1526
            return TCL_ERROR;
1527
        }
1528
        flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
1529
        if (Tcl_LinkVar(interp, "real", (char *) &realVar,
1530
                TCL_LINK_DOUBLE | flag) != TCL_OK) {
1531
            return TCL_ERROR;
1532
        }
1533
        if (Tcl_GetBoolean(interp, argv[4], &writable) != TCL_OK) {
1534
            return TCL_ERROR;
1535
        }
1536
        flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
1537
        if (Tcl_LinkVar(interp, "bool", (char *) &boolVar,
1538
                TCL_LINK_BOOLEAN | flag) != TCL_OK) {
1539
            return TCL_ERROR;
1540
        }
1541
        if (Tcl_GetBoolean(interp, argv[5], &writable) != TCL_OK) {
1542
            return TCL_ERROR;
1543
        }
1544
        flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
1545
        if (Tcl_LinkVar(interp, "string", (char *) &stringVar,
1546
                TCL_LINK_STRING | flag) != TCL_OK) {
1547
            return TCL_ERROR;
1548
        }
1549
    } else if (strcmp(argv[1], "delete") == 0) {
1550
        Tcl_UnlinkVar(interp, "int");
1551
        Tcl_UnlinkVar(interp, "real");
1552
        Tcl_UnlinkVar(interp, "bool");
1553
        Tcl_UnlinkVar(interp, "string");
1554
        created = 0;
1555
    } else if (strcmp(argv[1], "get") == 0) {
1556
        sprintf(buffer, "%d", intVar);
1557
        Tcl_AppendElement(interp, buffer);
1558
        Tcl_PrintDouble((Tcl_Interp *) NULL, realVar, buffer);
1559
        Tcl_AppendElement(interp, buffer);
1560
        sprintf(buffer, "%d", boolVar);
1561
        Tcl_AppendElement(interp, buffer);
1562
        Tcl_AppendElement(interp, (stringVar == NULL) ? "-" : stringVar);
1563
    } else if (strcmp(argv[1], "set") == 0) {
1564
        if (argc != 6) {
1565
            Tcl_AppendResult(interp, "wrong # args: should be \"",
1566
                argv[0], " ", argv[1],
1567
                "intValue realValue boolValue stringValue\"", (char *) NULL);
1568
            return TCL_ERROR;
1569
        }
1570
        if (argv[2][0] != 0) {
1571
            if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
1572
                return TCL_ERROR;
1573
            }
1574
        }
1575
        if (argv[3][0] != 0) {
1576
            if (Tcl_GetDouble(interp, argv[3], &realVar) != TCL_OK) {
1577
                return TCL_ERROR;
1578
            }
1579
        }
1580
        if (argv[4][0] != 0) {
1581
            if (Tcl_GetInt(interp, argv[4], &boolVar) != TCL_OK) {
1582
                return TCL_ERROR;
1583
            }
1584
        }
1585
        if (argv[5][0] != 0) {
1586
            if (stringVar != NULL) {
1587
                ckfree(stringVar);
1588
            }
1589
            if (strcmp(argv[5], "-") == 0) {
1590
                stringVar = NULL;
1591
            } else {
1592
                stringVar = (char *) ckalloc((unsigned) (strlen(argv[5]) + 1));
1593
                strcpy(stringVar, argv[5]);
1594
            }
1595
        }
1596
    } else if (strcmp(argv[1], "update") == 0) {
1597
        if (argc != 6) {
1598
            Tcl_AppendResult(interp, "wrong # args: should be \"",
1599
                argv[0], " ", argv[1],
1600
                "intValue realValue boolValue stringValue\"", (char *) NULL);
1601
            return TCL_ERROR;
1602
        }
1603
        if (argv[2][0] != 0) {
1604
            if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
1605
                return TCL_ERROR;
1606
            }
1607
            Tcl_UpdateLinkedVar(interp, "int");
1608
        }
1609
        if (argv[3][0] != 0) {
1610
            if (Tcl_GetDouble(interp, argv[3], &realVar) != TCL_OK) {
1611
                return TCL_ERROR;
1612
            }
1613
            Tcl_UpdateLinkedVar(interp, "real");
1614
        }
1615
        if (argv[4][0] != 0) {
1616
            if (Tcl_GetInt(interp, argv[4], &boolVar) != TCL_OK) {
1617
                return TCL_ERROR;
1618
            }
1619
            Tcl_UpdateLinkedVar(interp, "bool");
1620
        }
1621
        if (argv[5][0] != 0) {
1622
            if (stringVar != NULL) {
1623
                ckfree(stringVar);
1624
            }
1625
            if (strcmp(argv[5], "-") == 0) {
1626
                stringVar = NULL;
1627
            } else {
1628
                stringVar = (char *) ckalloc((unsigned) (strlen(argv[5]) + 1));
1629
                strcpy(stringVar, argv[5]);
1630
            }
1631
            Tcl_UpdateLinkedVar(interp, "string");
1632
        }
1633
    } else {
1634
        Tcl_AppendResult(interp, "bad option \"", argv[1],
1635
                "\": should be create, delete, get, set, or update",
1636
                (char *) NULL);
1637
        return TCL_ERROR;
1638
    }
1639
    return TCL_OK;
1640
}
1641
 
1642
/*
1643
 *----------------------------------------------------------------------
1644
 *
1645
 * TestMathFunc --
1646
 *
1647
 *      This is a user-defined math procedure to test out math procedures
1648
 *      with no arguments.
1649
 *
1650
 * Results:
1651
 *      A normal Tcl completion code.
1652
 *
1653
 * Side effects:
1654
 *      None.
1655
 *
1656
 *----------------------------------------------------------------------
1657
 */
1658
 
1659
        /* ARGSUSED */
1660
static int
1661
TestMathFunc(clientData, interp, args, resultPtr)
1662
    ClientData clientData;              /* Integer value to return. */
1663
    Tcl_Interp *interp;                 /* Not used. */
1664
    Tcl_Value *args;                    /* Not used. */
1665
    Tcl_Value *resultPtr;               /* Where to store result. */
1666
{
1667
    resultPtr->type = TCL_INT;
1668
    resultPtr->intValue = (int) clientData;
1669
    return TCL_OK;
1670
}
1671
 
1672
/*
1673
 *----------------------------------------------------------------------
1674
 *
1675
 * TestMathFunc2 --
1676
 *
1677
 *      This is a user-defined math procedure to test out math procedures
1678
 *      that do have arguments, in this case 2.
1679
 *
1680
 * Results:
1681
 *      A normal Tcl completion code.
1682
 *
1683
 * Side effects:
1684
 *      None.
1685
 *
1686
 *----------------------------------------------------------------------
1687
 */
1688
 
1689
        /* ARGSUSED */
1690
static int
1691
TestMathFunc2(clientData, interp, args, resultPtr)
1692
    ClientData clientData;              /* Integer value to return. */
1693
    Tcl_Interp *interp;                 /* Used to report errors. */
1694
    Tcl_Value *args;                    /* Points to an array of two
1695
                                         * Tcl_Values for the two
1696
                                         * arguments. */
1697
    Tcl_Value *resultPtr;               /* Where to store the result. */
1698
{
1699
    int result = TCL_OK;
1700
 
1701
    /*
1702
     * Return the maximum of the two arguments with the correct type.
1703
     */
1704
 
1705
    if (args[0].type == TCL_INT) {
1706
        int i0 = args[0].intValue;
1707
 
1708
        if (args[1].type == TCL_INT) {
1709
            int i1 = args[1].intValue;
1710
 
1711
            resultPtr->type = TCL_INT;
1712
            resultPtr->intValue = ((i0 > i1)? i0 : i1);
1713
        } else if (args[1].type == TCL_DOUBLE) {
1714
            double d0 = i0;
1715
            double d1 = args[1].doubleValue;
1716
 
1717
            resultPtr->type = TCL_DOUBLE;
1718
            resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
1719
        } else {
1720
            Tcl_SetResult(interp, "T2: wrong type for arg 2", TCL_STATIC);
1721
            result = TCL_ERROR;
1722
        }
1723
    } else if (args[0].type == TCL_DOUBLE) {
1724
        double d0 = args[0].doubleValue;
1725
 
1726
        if (args[1].type == TCL_INT) {
1727
            double d1 = args[1].intValue;
1728
 
1729
            resultPtr->type = TCL_DOUBLE;
1730
            resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
1731
        } else if (args[1].type == TCL_DOUBLE) {
1732
            double d1 = args[1].doubleValue;
1733
 
1734
            resultPtr->type = TCL_DOUBLE;
1735
            resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
1736
        } else {
1737
            Tcl_SetResult(interp, "T2: wrong type for arg 2", TCL_STATIC);
1738
            result = TCL_ERROR;
1739
        }
1740
    } else {
1741
        Tcl_SetResult(interp, "T2: wrong type for arg 1", TCL_STATIC);
1742
        result = TCL_ERROR;
1743
    }
1744
    return result;
1745
}
1746
 
1747
/*
1748
 *----------------------------------------------------------------------
1749
 *
1750
 * CleanupTestSetassocdataTests --
1751
 *
1752
 *      This function is called when an interpreter is deleted to clean
1753
 *      up any data left over from running the testsetassocdata command.
1754
 *
1755
 * Results:
1756
 *      None.
1757
 *
1758
 * Side effects:
1759
 *      Releases storage.
1760
 *
1761
 *----------------------------------------------------------------------
1762
 */
1763
        /* ARGSUSED */
1764
static void
1765
CleanupTestSetassocdataTests(clientData, interp)
1766
    ClientData clientData;              /* Data to be released. */
1767
    Tcl_Interp *interp;                 /* Interpreter being deleted. */
1768
{
1769
    ckfree((char *) clientData);
1770
}
1771
 
1772
/*
1773
 *----------------------------------------------------------------------
1774
 *
1775
 * TestsetassocdataCmd --
1776
 *
1777
 *      This procedure implements the "testsetassocdata" command. It is used
1778
 *      to test Tcl_SetAssocData.
1779
 *
1780
 * Results:
1781
 *      A standard Tcl result.
1782
 *
1783
 * Side effects:
1784
 *      Modifies or creates an association between a key and associated
1785
 *      data for this interpreter.
1786
 *
1787
 *----------------------------------------------------------------------
1788
 */
1789
 
1790
static int
1791
TestsetassocdataCmd(clientData, interp, argc, argv)
1792
    ClientData clientData;              /* Not used. */
1793
    Tcl_Interp *interp;                 /* Current interpreter. */
1794
    int argc;                           /* Number of arguments. */
1795
    char **argv;                        /* Argument strings. */
1796
{
1797
    char *buf;
1798
    char *oldData;
1799
    Tcl_InterpDeleteProc *procPtr;
1800
 
1801
    if (argc != 3) {
1802
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
1803
                " data_key data_item\"", (char *) NULL);
1804
        return TCL_ERROR;
1805
    }
1806
 
1807
    buf = ckalloc((unsigned) strlen(argv[2]) + 1);
1808
    strcpy(buf, argv[2]);
1809
 
1810
    /*
1811
     * If we previously associated a malloced value with the variable,
1812
     * free it before associating a new value.
1813
     */
1814
 
1815
    oldData = (char *) Tcl_GetAssocData(interp, argv[1], &procPtr);
1816
    if ((oldData != NULL) && (procPtr == CleanupTestSetassocdataTests)) {
1817
        ckfree(oldData);
1818
    }
1819
 
1820
    Tcl_SetAssocData(interp, argv[1], CleanupTestSetassocdataTests,
1821
        (ClientData) buf);
1822
    return TCL_OK;
1823
}
1824
 
1825
/*
1826
 *----------------------------------------------------------------------
1827
 *
1828
 * TestsetplatformCmd --
1829
 *
1830
 *      This procedure implements the "testsetplatform" command. It is
1831
 *      used to change the tclPlatform global variable so all file
1832
 *      name conversions can be tested on a single platform.
1833
 *
1834
 * Results:
1835
 *      A standard Tcl result.
1836
 *
1837
 * Side effects:
1838
 *      Sets the tclPlatform global variable.
1839
 *
1840
 *----------------------------------------------------------------------
1841
 */
1842
 
1843
static int
1844
TestsetplatformCmd(clientData, interp, argc, argv)
1845
    ClientData clientData;              /* Not used. */
1846
    Tcl_Interp *interp;                 /* Current interpreter. */
1847
    int argc;                           /* Number of arguments. */
1848
    char **argv;                        /* Argument strings. */
1849
{
1850
    size_t length;
1851
    TclPlatformType *platform;
1852
 
1853
#ifdef __WIN32__
1854
    platform = TclWinGetPlatform();
1855
#else
1856
    platform = &tclPlatform;
1857
#endif
1858
 
1859
    if (argc != 2) {
1860
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
1861
                " platform\"", (char *) NULL);
1862
        return TCL_ERROR;
1863
    }
1864
 
1865
    length = strlen(argv[1]);
1866
    if (strncmp(argv[1], "unix", length) == 0) {
1867
        *platform = TCL_PLATFORM_UNIX;
1868
    } else if (strncmp(argv[1], "mac", length) == 0) {
1869
        *platform = TCL_PLATFORM_MAC;
1870
    } else if (strncmp(argv[1], "windows", length) == 0) {
1871
        *platform = TCL_PLATFORM_WINDOWS;
1872
    } else {
1873
        Tcl_AppendResult(interp, "unsupported platform: should be one of ",
1874
                "unix, mac, or windows", (char *) NULL);
1875
        return TCL_ERROR;
1876
    }
1877
    return TCL_OK;
1878
}
1879
 
1880
/*
1881
 *----------------------------------------------------------------------
1882
 *
1883
 * TestsetrecursionlimitCmd --
1884
 *
1885
 *      This procedure implements the "testsetrecursionlimit" command. It is
1886
 *      used to change the interp recursion limit (to test the effects
1887
 *      of Tcl_SetRecursionLimit).
1888
 *
1889
 * Results:
1890
 *      A standard Tcl result.
1891
 *
1892
 * Side effects:
1893
 *      Sets the interp's recursion limit.
1894
 *
1895
 *----------------------------------------------------------------------
1896
 */
1897
 
1898
static int
1899
TestsetrecursionlimitCmd(dummy, interp, objc, objv)
1900
    ClientData dummy;           /* Not used. */
1901
    Tcl_Interp *interp;         /* Current interpreter. */
1902
    int objc;                   /* Number of arguments. */
1903
    Tcl_Obj *CONST objv[];      /* The argument objects. */
1904
{
1905
    int     value;
1906
 
1907
    if (objc != 2) {
1908
        Tcl_WrongNumArgs(interp, 1, objv, "integer");
1909
        return TCL_ERROR;
1910
    }
1911
    if (Tcl_GetIntFromObj(interp, objv[1], &value) != TCL_OK) {
1912
        return TCL_ERROR;
1913
    }
1914
    value = Tcl_SetRecursionLimit(interp, value);
1915
    Tcl_SetIntObj(Tcl_GetObjResult(interp), value);
1916
    return TCL_OK;
1917
}
1918
 
1919
 
1920
 
1921
/*
1922
 *----------------------------------------------------------------------
1923
 *
1924
 * TeststaticpkgCmd --
1925
 *
1926
 *      This procedure implements the "teststaticpkg" command.
1927
 *      It is used to test the procedure Tcl_StaticPackage.
1928
 *
1929
 * Results:
1930
 *      A standard Tcl result.
1931
 *
1932
 * Side effects:
1933
 *      When the packge given by argv[1] is loaded into an interpeter,
1934
 *      variable "x" in that interpreter is set to "loaded".
1935
 *
1936
 *----------------------------------------------------------------------
1937
 */
1938
 
1939
static int
1940
TeststaticpkgCmd(dummy, interp, argc, argv)
1941
    ClientData dummy;                   /* Not used. */
1942
    Tcl_Interp *interp;                 /* Current interpreter. */
1943
    int argc;                           /* Number of arguments. */
1944
    char **argv;                        /* Argument strings. */
1945
{
1946
    int safe, loaded;
1947
 
1948
    if (argc != 4) {
1949
        Tcl_AppendResult(interp, "wrong # arguments: should be \"",
1950
                argv[0], " pkgName safe loaded\"", (char *) NULL);
1951
        return TCL_ERROR;
1952
    }
1953
    if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) {
1954
        return TCL_ERROR;
1955
    }
1956
    if (Tcl_GetInt(interp, argv[3], &loaded) != TCL_OK) {
1957
        return TCL_ERROR;
1958
    }
1959
    Tcl_StaticPackage((loaded) ? interp : NULL, argv[1], StaticInitProc,
1960
            (safe) ? StaticInitProc : NULL);
1961
    return TCL_OK;
1962
}
1963
 
1964
static int
1965
StaticInitProc(interp)
1966
    Tcl_Interp *interp;                 /* Interpreter in which package
1967
                                         * is supposedly being loaded. */
1968
{
1969
    Tcl_SetVar(interp, "x", "loaded", TCL_GLOBAL_ONLY);
1970
    return TCL_OK;
1971
}
1972
 
1973
/*
1974
 *----------------------------------------------------------------------
1975
 *
1976
 * TesttranslatefilenameCmd --
1977
 *
1978
 *      This procedure implements the "testtranslatefilename" command.
1979
 *      It is used to test the Tcl_TranslateFileName command.
1980
 *
1981
 * Results:
1982
 *      A standard Tcl result.
1983
 *
1984
 * Side effects:
1985
 *      None.
1986
 *
1987
 *----------------------------------------------------------------------
1988
 */
1989
 
1990
static int
1991
TesttranslatefilenameCmd(dummy, interp, argc, argv)
1992
    ClientData dummy;                   /* Not used. */
1993
    Tcl_Interp *interp;                 /* Current interpreter. */
1994
    int argc;                           /* Number of arguments. */
1995
    char **argv;                        /* Argument strings. */
1996
{
1997
    Tcl_DString buffer;
1998
    char *result;
1999
 
2000
    if (argc != 2) {
2001
        Tcl_AppendResult(interp, "wrong # arguments: should be \"",
2002
                argv[0], " path\"", (char *) NULL);
2003
        return TCL_ERROR;
2004
    }
2005
    result = Tcl_TranslateFileName(interp, argv[1], &buffer);
2006
    if (result == NULL) {
2007
        return TCL_ERROR;
2008
    }
2009
    Tcl_AppendResult(interp, result, NULL);
2010
    Tcl_DStringFree(&buffer);
2011
    return TCL_OK;
2012
}
2013
 
2014
/*
2015
 *----------------------------------------------------------------------
2016
 *
2017
 * TestupvarCmd --
2018
 *
2019
 *      This procedure implements the "testupvar2" command.  It is used
2020
 *      to test Tcl_UpVar and Tcl_UpVar2.
2021
 *
2022
 * Results:
2023
 *      A standard Tcl result.
2024
 *
2025
 * Side effects:
2026
 *      Creates or modifies an "upvar" reference.
2027
 *
2028
 *----------------------------------------------------------------------
2029
 */
2030
 
2031
        /* ARGSUSED */
2032
static int
2033
TestupvarCmd(dummy, interp, argc, argv)
2034
    ClientData dummy;                   /* Not used. */
2035
    Tcl_Interp *interp;                 /* Current interpreter. */
2036
    int argc;                           /* Number of arguments. */
2037
    char **argv;                        /* Argument strings. */
2038
{
2039
    int flags = 0;
2040
 
2041
    if ((argc != 5) && (argc != 6)) {
2042
        Tcl_AppendResult(interp, "wrong # arguments: should be \"",
2043
                argv[0], " level name ?name2? dest global\"", (char *) NULL);
2044
        return TCL_ERROR;
2045
    }
2046
 
2047
    if (argc == 5) {
2048
        if (strcmp(argv[4], "global") == 0) {
2049
            flags = TCL_GLOBAL_ONLY;
2050
        } else if (strcmp(argv[4], "namespace") == 0) {
2051
            flags = TCL_NAMESPACE_ONLY;
2052
        }
2053
        return Tcl_UpVar(interp, argv[1], argv[2], argv[3], flags);
2054
    } else {
2055
        if (strcmp(argv[5], "global") == 0) {
2056
            flags = TCL_GLOBAL_ONLY;
2057
        } else if (strcmp(argv[5], "namespace") == 0) {
2058
            flags = TCL_NAMESPACE_ONLY;
2059
        }
2060
        return Tcl_UpVar2(interp, argv[1], argv[2],
2061
                (argv[3][0] == 0) ? (char *) NULL : argv[3], argv[4],
2062
                flags);
2063
    }
2064
}
2065
 
2066
/*
2067
 *----------------------------------------------------------------------
2068
 *
2069
 * TestwordendCmd --
2070
 *
2071
 *      This procedure implements the "testwordend" command.  It is used
2072
 *      to test TclWordEnd.
2073
 *
2074
 * Results:
2075
 *      A standard Tcl result.
2076
 *
2077
 * Side effects:
2078
 *      None.
2079
 *
2080
 *----------------------------------------------------------------------
2081
 */
2082
 
2083
        /* ARGSUSED */
2084
static int
2085
TestwordendObjCmd(dummy, interp, objc, objv)
2086
    ClientData dummy;           /* Not used. */
2087
    Tcl_Interp *interp;         /* Current interpreter. */
2088
    int objc;                   /* Number of arguments. */
2089
    Tcl_Obj *CONST objv[];      /* The argument objects. */
2090
{
2091
    Tcl_Obj *objPtr;
2092
    char *string, *end;
2093
    int length;
2094
 
2095
    if (objc != 2) {
2096
        Tcl_WrongNumArgs(interp, 1, objv, "string");
2097
        return TCL_ERROR;
2098
    }
2099
    objPtr = Tcl_GetObjResult(interp);
2100
    string = Tcl_GetStringFromObj(objv[1], &length);
2101
    end = TclWordEnd(string, string+length, 0, NULL);
2102
    Tcl_AppendToObj(objPtr, end, length - (end - string));
2103
    return TCL_OK;
2104
}
2105
 
2106
/*
2107
 *----------------------------------------------------------------------
2108
 *
2109
 * TestsetobjerrorcodeCmd --
2110
 *
2111
 *      This procedure implements the "testsetobjerrorcodeCmd".
2112
 *      This tests up to five elements passed to the
2113
 *      Tcl_SetObjErrorCode command.
2114
 *
2115
 * Results:
2116
 *      A standard Tcl result. Always returns TCL_ERROR so that
2117
 *      the error code can be tested.
2118
 *
2119
 * Side effects:
2120
 *      None.
2121
 *
2122
 *----------------------------------------------------------------------
2123
 */
2124
 
2125
        /* ARGSUSED */
2126
static int
2127
TestsetobjerrorcodeCmd(dummy, interp, objc, objv)
2128
    ClientData dummy;           /* Not used. */
2129
    Tcl_Interp *interp;         /* Current interpreter. */
2130
    int objc;                   /* Number of arguments. */
2131
    Tcl_Obj *CONST objv[];      /* The argument objects. */
2132
{
2133
    Tcl_Obj *listObjPtr;
2134
 
2135
    if (objc > 1) {
2136
        listObjPtr = Tcl_ConcatObj(objc - 1, objv + 1);
2137
    } else {
2138
        listObjPtr = Tcl_NewObj();
2139
    }
2140
    Tcl_IncrRefCount(listObjPtr);
2141
    Tcl_SetObjErrorCode(interp, listObjPtr);
2142
    Tcl_DecrRefCount(listObjPtr);
2143
    return TCL_ERROR;
2144
}
2145
 
2146
/*
2147
 *----------------------------------------------------------------------
2148
 *
2149
 * TestfeventCmd --
2150
 *
2151
 *      This procedure implements the "testfevent" command.  It is
2152
 *      used for testing the "fileevent" command.
2153
 *
2154
 * Results:
2155
 *      A standard Tcl result.
2156
 *
2157
 * Side effects:
2158
 *      Creates and deletes interpreters.
2159
 *
2160
 *----------------------------------------------------------------------
2161
 */
2162
 
2163
        /* ARGSUSED */
2164
static int
2165
TestfeventCmd(clientData, interp, argc, argv)
2166
    ClientData clientData;              /* Not used. */
2167
    Tcl_Interp *interp;                 /* Current interpreter. */
2168
    int argc;                           /* Number of arguments. */
2169
    char **argv;                        /* Argument strings. */
2170
{
2171
    static Tcl_Interp *interp2 = NULL;
2172
    int code;
2173
    Tcl_Channel chan;
2174
 
2175
    if (argc < 2) {
2176
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2177
                " option ?arg arg ...?", (char *) NULL);
2178
        return TCL_ERROR;
2179
    }
2180
    if (strcmp(argv[1], "cmd") == 0) {
2181
        if (argc != 3) {
2182
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2183
                    " cmd script", (char *) NULL);
2184
            return TCL_ERROR;
2185
        }
2186
        if (interp2 != (Tcl_Interp *) NULL) {
2187
            code = Tcl_GlobalEval(interp2, argv[2]);
2188
            interp->result = interp2->result;
2189
            return code;
2190
        } else {
2191
            Tcl_AppendResult(interp,
2192
                    "called \"testfevent code\" before \"testfevent create\"",
2193
                    (char *) NULL);
2194
            return TCL_ERROR;
2195
        }
2196
    } else if (strcmp(argv[1], "create") == 0) {
2197
        if (interp2 != NULL) {
2198
            Tcl_DeleteInterp(interp2);
2199
        }
2200
        interp2 = Tcl_CreateInterp();
2201
        return TCL_OK;
2202
    } else if (strcmp(argv[1], "delete") == 0) {
2203
        if (interp2 != NULL) {
2204
            Tcl_DeleteInterp(interp2);
2205
        }
2206
        interp2 = NULL;
2207
    } else if (strcmp(argv[1], "share") == 0) {
2208
        if (interp2 != NULL) {
2209
            chan = Tcl_GetChannel(interp, argv[2], NULL);
2210
            if (chan == (Tcl_Channel) NULL) {
2211
                return TCL_ERROR;
2212
            }
2213
            Tcl_RegisterChannel(interp2, chan);
2214
        }
2215
    }
2216
 
2217
    return TCL_OK;
2218
}
2219
 
2220
/*
2221
 *----------------------------------------------------------------------
2222
 *
2223
 * TestPanicCmd --
2224
 *
2225
 *      Calls the panic routine.
2226
 *
2227
 * Results:
2228
 *      Always returns TCL_OK.
2229
 *
2230
 * Side effects:
2231
 *      May exit application.
2232
 *
2233
 *----------------------------------------------------------------------
2234
 */
2235
 
2236
static int
2237
TestPanicCmd(dummy, interp, argc, argv)
2238
    ClientData dummy;                   /* Not used. */
2239
    Tcl_Interp *interp;                 /* Current interpreter. */
2240
    int argc;                           /* Number of arguments. */
2241
    char **argv;                        /* Argument strings. */
2242
{
2243
    char *argString;
2244
 
2245
    /*
2246
     *  Put the arguments into a var args structure
2247
     *  Append all of the arguments together separated by spaces
2248
     */
2249
 
2250
    argString = Tcl_Merge(argc-1, argv+1);
2251
    panic(argString);
2252
    ckfree(argString);
2253
 
2254
    return TCL_OK;
2255
}
2256
 
2257
/*
2258
 *---------------------------------------------------------------------------
2259
 *
2260
 * TestchmodCmd --
2261
 *
2262
 *      Implements the "testchmod" cmd.  Used when testing "file"
2263
 *      command.  The only attribute used by the Mac and Windows platforms
2264
 *      is the user write flag; if this is not set, the file is
2265
 *      made read-only.  Otehrwise, the file is made read-write.
2266
 *
2267
 * Results:
2268
 *      A standard Tcl result.
2269
 *
2270
 * Side effects:
2271
 *      Changes permissions of specified files.
2272
 *
2273
 *---------------------------------------------------------------------------
2274
 */
2275
 
2276
static int
2277
TestchmodCmd(dummy, interp, argc, argv)
2278
    ClientData dummy;                   /* Not used. */
2279
    Tcl_Interp *interp;                 /* Current interpreter. */
2280
    int argc;                           /* Number of arguments. */
2281
    char **argv;                        /* Argument strings. */
2282
{
2283
    int i, mode;
2284
    char *rest;
2285
 
2286
    if (argc < 2) {
2287
        usage:
2288
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2289
                " mode file ?file ...?", (char *) NULL);
2290
        return TCL_ERROR;
2291
    }
2292
 
2293
    mode = (int) strtol(argv[1], &rest, 8);
2294
    if ((rest == argv[1]) || (*rest != '\0')) {
2295
        goto usage;
2296
    }
2297
 
2298
    for (i = 2; i < argc; i++) {
2299
        Tcl_DString buffer;
2300
 
2301
        argv[i] = Tcl_TranslateFileName(interp, argv[i], &buffer);
2302
        if (argv[i] == NULL) {
2303
            return TCL_ERROR;
2304
        }
2305
        if (chmod(argv[i], (unsigned) mode) != 0) {
2306
            Tcl_AppendResult(interp, argv[i], ": ", Tcl_PosixError(interp),
2307
                    (char *) NULL);
2308
            return TCL_ERROR;
2309
        }
2310
        Tcl_DStringFree(&buffer);
2311
    }
2312
    return TCL_OK;
2313
}
2314
 
2315
static int
2316
TestfileCmd(dummy, interp, argc, argv)
2317
    ClientData dummy;                   /* Not used. */
2318
    Tcl_Interp *interp;                 /* Current interpreter. */
2319
    int argc;                           /* Number of arguments. */
2320
    char **argv;                        /* Argument strings. */
2321
{
2322
    int force, i, j, result;
2323
    Tcl_DString error, name[2];
2324
 
2325
    if (argc < 3) {
2326
        return TCL_ERROR;
2327
    }
2328
 
2329
    force = 0;
2330
    i = 2;
2331
    if (strcmp(argv[2], "-force") == 0) {
2332
        force = 1;
2333
        i = 3;
2334
    }
2335
 
2336
    Tcl_DStringInit(&name[0]);
2337
    Tcl_DStringInit(&name[1]);
2338
    Tcl_DStringInit(&error);
2339
 
2340
    if (argc - i > 2) {
2341
        return TCL_ERROR;
2342
    }
2343
 
2344
    for (j = i; j < argc; j++) {
2345
        argv[j] = Tcl_TranslateFileName(interp, argv[j], &name[j - i]);
2346
        if (argv[j] == NULL) {
2347
            return TCL_ERROR;
2348
        }
2349
    }
2350
 
2351
    if (strcmp(argv[1], "mv") == 0) {
2352
        result = TclpRenameFile(argv[i], argv[i + 1]);
2353
    } else if (strcmp(argv[1], "cp") == 0) {
2354
        result = TclpCopyFile(argv[i], argv[i + 1]);
2355
    } else if (strcmp(argv[1], "rm") == 0) {
2356
        result = TclpDeleteFile(argv[i]);
2357
    } else if (strcmp(argv[1], "mkdir") == 0) {
2358
        result = TclpCreateDirectory(argv[i]);
2359
    } else if (strcmp(argv[1], "cpdir") == 0) {
2360
        result = TclpCopyDirectory(argv[i], argv[i + 1], &error);
2361
    } else if (strcmp(argv[1], "rmdir") == 0) {
2362
        result = TclpRemoveDirectory(argv[i], force, &error);
2363
    } else {
2364
        result = TCL_ERROR;
2365
        goto end;
2366
    }
2367
 
2368
    if (result != TCL_OK) {
2369
        if (Tcl_DStringValue(&error)[0] != '\0') {
2370
            Tcl_AppendResult(interp, Tcl_DStringValue(&error), " ", NULL);
2371
        }
2372
        Tcl_AppendResult(interp, Tcl_ErrnoId(), (char *) NULL);
2373
    }
2374
 
2375
    end:
2376
    Tcl_DStringFree(&error);
2377
    Tcl_DStringFree(&name[0]);
2378
    Tcl_DStringFree(&name[1]);
2379
 
2380
    return result;
2381
}
2382
 
2383
/*
2384
 *----------------------------------------------------------------------
2385
 *
2386
 * TestgetvarfullnameCmd --
2387
 *
2388
 *      Implements the "testgetvarfullname" cmd that is used when testing
2389
 *      the Tcl_GetVariableFullName procedure.
2390
 *
2391
 * Results:
2392
 *      A standard Tcl result.
2393
 *
2394
 * Side effects:
2395
 *      None.
2396
 *
2397
 *----------------------------------------------------------------------
2398
 */
2399
 
2400
static int
2401
TestgetvarfullnameCmd(dummy, interp, objc, objv)
2402
    ClientData dummy;           /* Not used. */
2403
    Tcl_Interp *interp;         /* Current interpreter. */
2404
    int objc;                   /* Number of arguments. */
2405
    Tcl_Obj *CONST objv[];      /* The argument objects. */
2406
{
2407
    char *name, *arg;
2408
    int flags = 0;
2409
    Tcl_Namespace *namespacePtr;
2410
    Tcl_CallFrame frame;
2411
    Tcl_Var variable;
2412
    int result;
2413
 
2414
    if (objc != 3) {
2415
        Tcl_WrongNumArgs(interp, 1, objv, "name scope");
2416
        return TCL_ERROR;
2417
    }
2418
 
2419
    name = Tcl_GetStringFromObj(objv[1], (int *) NULL);
2420
 
2421
    arg = Tcl_GetStringFromObj(objv[2], (int *) NULL);
2422
    if (strcmp(arg, "global") == 0) {
2423
        flags = TCL_GLOBAL_ONLY;
2424
    } else if (strcmp(arg, "namespace") == 0) {
2425
        flags = TCL_NAMESPACE_ONLY;
2426
    }
2427
 
2428
    /*
2429
     * This command, like any other created with Tcl_Create[Obj]Command,
2430
     * runs in the global namespace. As a "namespace-aware" command that
2431
     * needs to run in a particular namespace, it must activate that
2432
     * namespace itself.
2433
     */
2434
 
2435
    if (flags == TCL_NAMESPACE_ONLY) {
2436
        namespacePtr = Tcl_FindNamespace(interp, "::test_ns_var",
2437
                (Tcl_Namespace *) NULL, TCL_LEAVE_ERR_MSG);
2438
        if (namespacePtr == NULL) {
2439
            return TCL_ERROR;
2440
        }
2441
        result = Tcl_PushCallFrame(interp, &frame, namespacePtr,
2442
                /*isProcCallFrame*/ 0);
2443
        if (result != TCL_OK) {
2444
            return result;
2445
        }
2446
    }
2447
 
2448
    variable = Tcl_FindNamespaceVar(interp, name, (Tcl_Namespace *) NULL,
2449
            (flags | TCL_LEAVE_ERR_MSG));
2450
 
2451
    if (flags == TCL_NAMESPACE_ONLY) {
2452
        Tcl_PopCallFrame(interp);
2453
    }
2454
    if (variable == (Tcl_Var) NULL) {
2455
        return TCL_ERROR;
2456
    }
2457
    Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp));
2458
    return TCL_OK;
2459
}
2460
 
2461
/*
2462
 *----------------------------------------------------------------------
2463
 *
2464
 * GetTimesCmd --
2465
 *
2466
 *      This procedure implements the "gettimes" command.  It is
2467
 *      used for computing the time needed for various basic operations
2468
 *      such as reading variables, allocating memory, sprintf, converting
2469
 *      variables, etc.
2470
 *
2471
 * Results:
2472
 *      A standard Tcl result.
2473
 *
2474
 * Side effects:
2475
 *      Allocates and frees memory, sets a variable "a" in the interpreter.
2476
 *
2477
 *----------------------------------------------------------------------
2478
 */
2479
 
2480
static int
2481
GetTimesCmd(unused, interp, argc, argv)
2482
    ClientData unused;          /* Unused. */
2483
    Tcl_Interp *interp;         /* The current interpreter. */
2484
    int argc;                   /* The number of arguments. */
2485
    char **argv;                /* The argument strings. */
2486
{
2487
    Interp *iPtr = (Interp *) interp;
2488
    int i, n;
2489
    double timePer;
2490
    Tcl_Time start, stop;
2491
    Tcl_Obj *objPtr;
2492
    Tcl_Obj **objv;
2493
    char *s;
2494
    char newString[30];
2495
 
2496
    /* alloc & free 100000 times */
2497
    fprintf(stderr, "alloc & free 100000 6 word items\n");
2498
    TclpGetTime(&start);
2499
    for (i = 0;  i < 100000;  i++) {
2500
        objPtr = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj));
2501
        ckfree((char *) objPtr);
2502
    }
2503
    TclpGetTime(&stop);
2504
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2505
    fprintf(stderr, "   %.3f usec per alloc+free\n", timePer/100000);
2506
 
2507
    /* alloc 5000 times */
2508
    fprintf(stderr, "alloc 5000 6 word items\n");
2509
    objv = (Tcl_Obj **) ckalloc(5000 * sizeof(Tcl_Obj *));
2510
    TclpGetTime(&start);
2511
    for (i = 0;  i < 5000;  i++) {
2512
        objv[i] = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj));
2513
    }
2514
    TclpGetTime(&stop);
2515
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2516
    fprintf(stderr, "   %.3f usec per alloc\n", timePer/5000);
2517
 
2518
    /* free 5000 times */
2519
    fprintf(stderr, "free 5000 6 word items\n");
2520
    TclpGetTime(&start);
2521
    for (i = 0;  i < 5000;  i++) {
2522
        ckfree((char *) objv[i]);
2523
    }
2524
    TclpGetTime(&stop);
2525
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2526
    fprintf(stderr, "   %.3f usec per free\n", timePer/5000);
2527
 
2528
    /* Tcl_NewObj 5000 times */
2529
    fprintf(stderr, "Tcl_NewObj 5000 times\n");
2530
    TclpGetTime(&start);
2531
    for (i = 0;  i < 5000;  i++) {
2532
        objv[i] = Tcl_NewObj();
2533
    }
2534
    TclpGetTime(&stop);
2535
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2536
    fprintf(stderr, "   %.3f usec per Tcl_NewObj\n", timePer/5000);
2537
 
2538
    /* Tcl_DecrRefCount 5000 times */
2539
    fprintf(stderr, "Tcl_DecrRefCount 5000 times\n");
2540
    TclpGetTime(&start);
2541
    for (i = 0;  i < 5000;  i++) {
2542
        objPtr = objv[i];
2543
        Tcl_DecrRefCount(objPtr);
2544
    }
2545
    TclpGetTime(&stop);
2546
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2547
    fprintf(stderr, "   %.3f usec per Tcl_DecrRefCount\n", timePer/5000);
2548
    ckfree((char *) objv);
2549
 
2550
    /* TclGetStringFromObj 100000 times */
2551
    fprintf(stderr, "TclGetStringFromObj of \"12345\" 100000 times\n");
2552
    objPtr = Tcl_NewStringObj("12345", -1);
2553
    TclpGetTime(&start);
2554
    for (i = 0;  i < 100000;  i++) {
2555
        (void) TclGetStringFromObj(objPtr, &n);
2556
    }
2557
    TclpGetTime(&stop);
2558
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2559
    fprintf(stderr, "   %.3f usec per TclGetStringFromObj of \"12345\"\n",
2560
            timePer/100000);
2561
 
2562
    /* Tcl_GetIntFromObj 100000 times */
2563
    fprintf(stderr, "Tcl_GetIntFromObj of \"12345\" 100000 times\n");
2564
    TclpGetTime(&start);
2565
    for (i = 0;  i < 100000;  i++) {
2566
        if (Tcl_GetIntFromObj(interp, objPtr, &n) != TCL_OK) {
2567
            return TCL_ERROR;
2568
        }
2569
    }
2570
    TclpGetTime(&stop);
2571
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2572
    fprintf(stderr, "   %.3f usec per Tcl_GetIntFromObj of \"12345\"\n",
2573
            timePer/100000);
2574
    Tcl_DecrRefCount(objPtr);
2575
 
2576
    /* Tcl_GetInt 100000 times */
2577
    fprintf(stderr, "Tcl_GetInt of \"12345\" 100000 times\n");
2578
    TclpGetTime(&start);
2579
    for (i = 0;  i < 100000;  i++) {
2580
        if (Tcl_GetInt(interp, "12345", &n) != TCL_OK) {
2581
            return TCL_ERROR;
2582
        }
2583
    }
2584
    TclpGetTime(&stop);
2585
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2586
    fprintf(stderr, "   %.3f usec per Tcl_GetInt of \"12345\"\n",
2587
            timePer/100000);
2588
 
2589
    /* sprintf 100000 times */
2590
    fprintf(stderr, "sprintf of 12345 100000 times\n");
2591
    TclpGetTime(&start);
2592
    for (i = 0;  i < 100000;  i++) {
2593
        sprintf(newString, "%d", 12345);
2594
    }
2595
    TclpGetTime(&stop);
2596
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2597
    fprintf(stderr, "   %.3f usec per sprintf of 12345\n",
2598
            timePer/100000);
2599
 
2600
    /* hashtable lookup 100000 times */
2601
    fprintf(stderr, "hashtable lookup of \"gettimes\" 100000 times\n");
2602
    TclpGetTime(&start);
2603
    for (i = 0;  i < 100000;  i++) {
2604
        (void) Tcl_FindHashEntry(&iPtr->globalNsPtr->cmdTable, "gettimes");
2605
    }
2606
    TclpGetTime(&stop);
2607
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2608
    fprintf(stderr, "   %.3f usec per hashtable lookup of \"gettimes\"\n",
2609
            timePer/100000);
2610
 
2611
    /* Tcl_SetVar 100000 times */
2612
    fprintf(stderr, "Tcl_SetVar of \"12345\" 100000 times\n");
2613
    TclpGetTime(&start);
2614
    for (i = 0;  i < 100000;  i++) {
2615
        s = Tcl_SetVar(interp, "a", "12345", TCL_LEAVE_ERR_MSG);
2616
        if (s == NULL) {
2617
            return TCL_ERROR;
2618
        }
2619
    }
2620
    TclpGetTime(&stop);
2621
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2622
    fprintf(stderr, "   %.3f usec per Tcl_SetVar of a to \"12345\"\n",
2623
            timePer/100000);
2624
 
2625
    /* Tcl_GetVar 100000 times */
2626
    fprintf(stderr, "Tcl_GetVar of a==\"12345\" 100000 times\n");
2627
    TclpGetTime(&start);
2628
    for (i = 0;  i < 100000;  i++) {
2629
        s = Tcl_GetVar(interp, "a", TCL_LEAVE_ERR_MSG);
2630
        if (s == NULL) {
2631
            return TCL_ERROR;
2632
        }
2633
    }
2634
    TclpGetTime(&stop);
2635
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
2636
    fprintf(stderr, "   %.3f usec per Tcl_GetVar of a==\"12345\"\n",
2637
            timePer/100000);
2638
 
2639
    Tcl_ResetResult(interp);
2640
    return TCL_OK;
2641
}
2642
 
2643
/*
2644
 *----------------------------------------------------------------------
2645
 *
2646
 * NoopCmd --
2647
 *
2648
 *      This procedure is just used to time the overhead involved in
2649
 *      parsing and invoking a command.
2650
 *
2651
 * Results:
2652
 *      None.
2653
 *
2654
 * Side effects:
2655
 *      None.
2656
 *
2657
 *----------------------------------------------------------------------
2658
 */
2659
 
2660
static int
2661
NoopCmd(unused, interp, argc, argv)
2662
    ClientData unused;          /* Unused. */
2663
    Tcl_Interp *interp;         /* The current interpreter. */
2664
    int argc;                   /* The number of arguments. */
2665
    char **argv;                /* The argument strings. */
2666
{
2667
    return TCL_OK;
2668
}
2669
 
2670
/*
2671
 *----------------------------------------------------------------------
2672
 *
2673
 * NoopObjCmd --
2674
 *
2675
 *      This object-based procedure is just used to time the overhead
2676
 *      involved in parsing and invoking a command.
2677
 *
2678
 * Results:
2679
 *      Returns the TCL_OK result code.
2680
 *
2681
 * Side effects:
2682
 *      None.
2683
 *
2684
 *----------------------------------------------------------------------
2685
 */
2686
 
2687
static int
2688
NoopObjCmd(unused, interp, objc, objv)
2689
    ClientData unused;          /* Not used. */
2690
    Tcl_Interp *interp;         /* Current interpreter. */
2691
    int objc;                   /* Number of arguments. */
2692
    Tcl_Obj *CONST objv[];      /* The argument objects. */
2693
{
2694
    return TCL_OK;
2695
}
2696
 
2697
/*
2698
 *----------------------------------------------------------------------
2699
 *
2700
 * TestsetnoerrCmd --
2701
 *
2702
 *      Implements the "testsetnoerr" cmd that is used when testing
2703
 *      the Tcl_Set/GetVar C Api without TCL_LEAVE_ERR_MSG flag
2704
 *
2705
 * Results:
2706
 *      A standard Tcl result.
2707
 *
2708
 * Side effects:
2709
 *      None.
2710
 *
2711
 *----------------------------------------------------------------------
2712
 */
2713
 
2714
        /* ARGSUSED */
2715
static int
2716
TestsetnoerrCmd(dummy, interp, argc, argv)
2717
    ClientData dummy;                   /* Not used. */
2718
    register Tcl_Interp *interp;        /* Current interpreter. */
2719
    int argc;                           /* Number of arguments. */
2720
    char **argv;                        /* Argument strings. */
2721
{
2722
    char *value;
2723
    if (argc == 2) {
2724
        Tcl_SetResult(interp, "before get", TCL_STATIC);
2725
        value = Tcl_GetVar2(interp, argv[1], (char *) NULL, TCL_PARSE_PART1);
2726
        if (value == NULL) {
2727
            return TCL_ERROR;
2728
        }
2729
        Tcl_SetResult(interp, value, TCL_VOLATILE);
2730
        return TCL_OK;
2731
    } else if (argc == 3) {
2732
        char *m1 = "before set";
2733
        char *message=Tcl_Alloc(strlen(m1)+1);
2734
 
2735
        strcpy(message,m1);
2736
 
2737
        Tcl_SetResult(interp, message, TCL_DYNAMIC);
2738
 
2739
        value = Tcl_SetVar2(interp, argv[1], (char *) NULL, argv[2],
2740
                            TCL_PARSE_PART1);
2741
        if (value == NULL) {
2742
            return TCL_ERROR;
2743
        }
2744
        Tcl_SetResult(interp, value, TCL_VOLATILE);
2745
        return TCL_OK;
2746
    } else {
2747
        Tcl_AppendResult(interp, "wrong # args: should be \"",
2748
                argv[0], " varName ?newValue?\"", (char *) NULL);
2749
        return TCL_ERROR;
2750
    }
2751
}
2752
 
2753
/*
2754
 *----------------------------------------------------------------------
2755
 *
2756
 * TeststatprocCmd  --
2757
 *
2758
 *      Implements the "testTclStatProc" cmd that is used to test the
2759
 *      'TclStatInsertProc' & 'TclStatDeleteProc' C Apis.
2760
 *
2761
 * Results:
2762
 *      A standard Tcl result.
2763
 *
2764
 * Side effects:
2765
 *      None.
2766
 *
2767
 *----------------------------------------------------------------------
2768
 */
2769
 
2770
static int
2771
TeststatprocCmd (dummy, interp, argc, argv)
2772
    ClientData dummy;                   /* Not used. */
2773
    register Tcl_Interp *interp;        /* Current interpreter. */
2774
    int argc;                           /* Number of arguments. */
2775
    char **argv;                        /* Argument strings. */
2776
{
2777
    TclStatProc_ *proc;
2778
    int retVal;
2779
 
2780
    if (argc != 3) {
2781
        Tcl_AppendResult(interp, "wrong # args: should be \"",
2782
                argv[0], " option arg\"", (char *) NULL);
2783
        return TCL_ERROR;
2784
    }
2785
 
2786
    if (strcmp(argv[2], "TclpStat") == 0) {
2787
        proc = TclpStat;
2788
    } else if (strcmp(argv[2], "TestStatProc1") == 0) {
2789
        proc = TestStatProc1;
2790
    } else if (strcmp(argv[2], "TestStatProc2") == 0) {
2791
        proc = TestStatProc2;
2792
    } else if (strcmp(argv[2], "TestStatProc3") == 0) {
2793
        proc = TestStatProc3;
2794
    } else {
2795
        Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
2796
                "must be TclpStat, ",
2797
                "TestStatProc1, TestStatProc2, or TestStatProc3",
2798
                (char *) NULL);
2799
        return TCL_ERROR;
2800
    }
2801
 
2802
    if (strcmp(argv[1], "insert") == 0) {
2803
        if (proc == TclpStat) {
2804
            Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
2805
                   "must be ",
2806
                   "TestStatProc1, TestStatProc2, or TestStatProc3",
2807
                   (char *) NULL);
2808
            return TCL_ERROR;
2809
        }
2810
        retVal = TclStatInsertProc(proc);
2811
    } else if (strcmp(argv[1], "delete") == 0) {
2812
        retVal = TclStatDeleteProc(proc);
2813
    } else {
2814
        Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ",
2815
                "must be insert or delete", (char *) NULL);
2816
        return TCL_ERROR;
2817
    }
2818
 
2819
    if (retVal == TCL_ERROR) {
2820
        Tcl_AppendResult(interp, "\"", argv[2], "\": ",
2821
                "could not be ", argv[1], "ed", (char *) NULL);
2822
    }
2823
 
2824
    return retVal;
2825
}
2826
 
2827
/* Be careful in the compares in these tests, since the Macintosh puts a
2828
 * leading : in the beginning of non-absolute paths before passing them
2829
 * into the file command procedures.
2830
 */
2831
 
2832
static int
2833
TestStatProc1(path, buf)
2834
    CONST char *path;
2835
    TclStat_ *buf;
2836
{
2837
    buf->st_size = 1234;
2838
    return ((strstr(path, "testStat1%.fil") == NULL) ? -1 : 0);
2839
}
2840
 
2841
 
2842
static int
2843
TestStatProc2(path, buf)
2844
    CONST char *path;
2845
    TclStat_ *buf;
2846
{
2847
    buf->st_size = 2345;
2848
    return ((strstr(path, "testStat2%.fil") == NULL) ? -1 : 0);
2849
}
2850
 
2851
 
2852
static int
2853
TestStatProc3(path, buf)
2854
    CONST char *path;
2855
    TclStat_ *buf;
2856
{
2857
    buf->st_size = 3456;
2858
    return ((strstr(path, "testStat3%.fil") == NULL) ? -1 : 0);
2859
}
2860
 
2861
/*
2862
 *----------------------------------------------------------------------
2863
 *
2864
 * TestaccessprocCmd  --
2865
 *
2866
 *      Implements the "testTclAccessProc" cmd that is used to test the
2867
 *      'TclAccessInsertProc' & 'TclAccessDeleteProc' C Apis.
2868
 *
2869
 * Results:
2870
 *      A standard Tcl result.
2871
 *
2872
 * Side effects:
2873
 *      None.
2874
 *
2875
 *----------------------------------------------------------------------
2876
 */
2877
 
2878
static int
2879
TestaccessprocCmd (dummy, interp, argc, argv)
2880
    ClientData dummy;                   /* Not used. */
2881
    register Tcl_Interp *interp;        /* Current interpreter. */
2882
    int argc;                           /* Number of arguments. */
2883
    char **argv;                        /* Argument strings. */
2884
{
2885
    TclAccessProc_ *proc;
2886
    int retVal;
2887
 
2888
    if (argc != 3) {
2889
        Tcl_AppendResult(interp, "wrong # args: should be \"",
2890
                argv[0], " option arg\"", (char *) NULL);
2891
        return TCL_ERROR;
2892
    }
2893
 
2894
    if (strcmp(argv[2], "TclpAccess") == 0) {
2895
        proc = TclpAccess;
2896
    } else if (strcmp(argv[2], "TestAccessProc1") == 0) {
2897
        proc = TestAccessProc1;
2898
    } else if (strcmp(argv[2], "TestAccessProc2") == 0) {
2899
        proc = TestAccessProc2;
2900
    } else if (strcmp(argv[2], "TestAccessProc3") == 0) {
2901
        proc = TestAccessProc3;
2902
    } else {
2903
        Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
2904
                "must be TclpAccess, ",
2905
                "TestAccessProc1, TestAccessProc2, or TestAccessProc3",
2906
                (char *) NULL);
2907
        return TCL_ERROR;
2908
    }
2909
 
2910
    if (strcmp(argv[1], "insert") == 0) {
2911
        if (proc == TclpAccess) {
2912
            Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
2913
                   "must be ",
2914
                   "TestAccessProc1, TestAccessProc2, or TestAccessProc3",
2915
                   (char *) NULL);
2916
            return TCL_ERROR;
2917
        }
2918
        retVal = TclAccessInsertProc(proc);
2919
    } else if (strcmp(argv[1], "delete") == 0) {
2920
        retVal = TclAccessDeleteProc(proc);
2921
    } else {
2922
        Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ",
2923
                "must be insert or delete", (char *) NULL);
2924
        return TCL_ERROR;
2925
    }
2926
 
2927
    if (retVal == TCL_ERROR) {
2928
        Tcl_AppendResult(interp, "\"", argv[2], "\": ",
2929
                "could not be ", argv[1], "ed", (char *) NULL);
2930
    }
2931
 
2932
    return retVal;
2933
}
2934
 
2935
 
2936
static int
2937
TestAccessProc1(path, mode)
2938
    CONST char *path;
2939
    int mode;
2940
{
2941
    return ((strstr(path, "testAccess1%.fil") == NULL) ? -1 : 0);
2942
}
2943
 
2944
 
2945
static int
2946
TestAccessProc2(path, mode)
2947
    CONST char *path;
2948
    int mode;
2949
{
2950
    return ((strstr(path, "testAccess2%.fil") == NULL) ? -1 : 0);
2951
}
2952
 
2953
 
2954
static int
2955
TestAccessProc3(path, mode)
2956
    CONST char *path;
2957
    int mode;
2958
{
2959
    return ((strstr(path, "testAccess3%.fil") == NULL) ? -1 : 0);
2960
}
2961
 
2962
/*
2963
 *----------------------------------------------------------------------
2964
 *
2965
 * TestopenfilechannelprocCmd  --
2966
 *
2967
 *      Implements the "testTclOpenFileChannelProc" cmd that is used to test the
2968
 *      'TclOpenFileChannelInsertProc' & 'TclOpenFileChannelDeleteProc' C Apis.
2969
 *
2970
 * Results:
2971
 *      A standard Tcl result.
2972
 *
2973
 * Side effects:
2974
 *      None.
2975
 *
2976
 *----------------------------------------------------------------------
2977
 */
2978
 
2979
static int
2980
TestopenfilechannelprocCmd (dummy, interp, argc, argv)
2981
    ClientData dummy;                   /* Not used. */
2982
    register Tcl_Interp *interp;        /* Current interpreter. */
2983
    int argc;                           /* Number of arguments. */
2984
    char **argv;                        /* Argument strings. */
2985
{
2986
    TclOpenFileChannelProc_ *proc;
2987
    int retVal;
2988
 
2989
    if (argc != 3) {
2990
        Tcl_AppendResult(interp, "wrong # args: should be \"",
2991
                argv[0], " option arg\"", (char *) NULL);
2992
        return TCL_ERROR;
2993
    }
2994
 
2995
    if (strcmp(argv[2], "TclpOpenFileChannel") == 0) {
2996
        proc = TclpOpenFileChannel;
2997
    } else if (strcmp(argv[2], "TestOpenFileChannelProc1") == 0) {
2998
        proc = TestOpenFileChannelProc1;
2999
    } else if (strcmp(argv[2], "TestOpenFileChannelProc2") == 0) {
3000
        proc = TestOpenFileChannelProc2;
3001
    } else if (strcmp(argv[2], "TestOpenFileChannelProc3") == 0) {
3002
        proc = TestOpenFileChannelProc3;
3003
    } else {
3004
        Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
3005
                "must be TclpOpenFileChannel, ",
3006
                "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or ",
3007
                "TestOpenFileChannelProc3",
3008
                (char *) NULL);
3009
        return TCL_ERROR;
3010
    }
3011
 
3012
    if (strcmp(argv[1], "insert") == 0) {
3013
        if (proc == TclpOpenFileChannel) {
3014
            Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
3015
                   "must be ",
3016
                   "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or ",
3017
                   "TestOpenFileChannelProc3",
3018
                   (char *) NULL);
3019
            return TCL_ERROR;
3020
        }
3021
        retVal = TclOpenFileChannelInsertProc(proc);
3022
    } else if (strcmp(argv[1], "delete") == 0) {
3023
        retVal = TclOpenFileChannelDeleteProc(proc);
3024
    } else {
3025
        Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ",
3026
                "must be insert or delete", (char *) NULL);
3027
        return TCL_ERROR;
3028
    }
3029
 
3030
    if (retVal == TCL_ERROR) {
3031
        Tcl_AppendResult(interp, "\"", argv[2], "\": ",
3032
                "could not be ", argv[1], "ed", (char *) NULL);
3033
    }
3034
 
3035
    return retVal;
3036
}
3037
 
3038
 
3039
static Tcl_Channel
3040
TestOpenFileChannelProc1(interp, fileName, modeString, permissions)
3041
    Tcl_Interp *interp;                 /* Interpreter for error reporting;
3042
                                         * can be NULL. */
3043
    char *fileName;                     /* Name of file to open. */
3044
    char *modeString;                   /* A list of POSIX open modes or
3045
                                         * a string such as "rw". */
3046
    int permissions;                    /* If the open involves creating a
3047
                                         * file, with what modes to create
3048
                                         * it? */
3049
{
3050
    if (!strcmp("testOpenFileChannel1%.fil", fileName)) {
3051
        return (TclpOpenFileChannel(interp, "__testOpenFileChannel1%__.fil",
3052
                modeString, permissions));
3053
    } else {
3054
        return (NULL);
3055
    }
3056
}
3057
 
3058
 
3059
static Tcl_Channel
3060
TestOpenFileChannelProc2(interp, fileName, modeString, permissions)
3061
    Tcl_Interp *interp;                 /* Interpreter for error reporting;
3062
                                         * can be NULL. */
3063
    char *fileName;                     /* Name of file to open. */
3064
    char *modeString;                   /* A list of POSIX open modes or
3065
                                         * a string such as "rw". */
3066
    int permissions;                    /* If the open involves creating a
3067
                                         * file, with what modes to create
3068
                                         * it? */
3069
{
3070
    if (!strcmp("testOpenFileChannel2%.fil", fileName)) {
3071
        return (TclpOpenFileChannel(interp, "__testOpenFileChannel2%__.fil",
3072
                modeString, permissions));
3073
    } else {
3074
        return (NULL);
3075
    }
3076
}
3077
 
3078
 
3079
static Tcl_Channel
3080
TestOpenFileChannelProc3(interp, fileName, modeString, permissions)
3081
    Tcl_Interp *interp;                 /* Interpreter for error reporting;
3082
                                         * can be NULL. */
3083
    char *fileName;                     /* Name of file to open. */
3084
    char *modeString;                   /* A list of POSIX open modes or
3085
                                         * a string such as "rw". */
3086
    int permissions;                    /* If the open involves creating a
3087
                                         * file, with what modes to create
3088
                                         * it? */
3089
{
3090
    if (!strcmp("testOpenFileChannel3%.fil", fileName)) {
3091
        return (TclpOpenFileChannel(interp, "__testOpenFileChannel3%__.fil",
3092
                modeString, permissions));
3093
    } else {
3094
        return (NULL);
3095
    }
3096
}

powered by: WebSVN 2.1.0

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