tclTest.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:188k
源码类别:

通讯编程

开发平台:

Visual C++

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