diff options
Diffstat (limited to 'generic/tclTestObj.c')
| -rw-r--r-- | generic/tclTestObj.c | 1030 |
1 files changed, 408 insertions, 622 deletions
diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 9f31cff..f113cfe 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -6,70 +6,59 @@ * These commands are not normally included in Tcl applications; they're * only used for testing. * - * Copyright © 1995-1998 Sun Microsystems, Inc. - * Copyright © 1999 Scriptics Corporation. - * Copyright © 2005 Kevin B. Kenny. All rights reserved. + * Copyright (c) 1995-1998 Sun Microsystems, Inc. + * Copyright (c) 1999 by Scriptics Corporation. + * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#undef BUILD_tcl -#ifndef USE_TCL_STUBS -# define USE_TCL_STUBS -#endif + #include "tclInt.h" -#ifdef TCL_WITH_EXTERNAL_TOMMATH -# include "tommath.h" -#else -# include "tclTomMath.h" -#endif -#include "tclStringRep.h" +#include "tommath.h" -#ifdef __GNUC__ /* - * The rest of this file shouldn't warn about deprecated functions; they're - * there because we intend them to be so and know that this file is OK to - * touch those fields. + * An array of Tcl_Obj pointers used in the commands that operate on or get + * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's + * Tcl_Obj *. */ -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif + +#define NUMBER_OF_OBJECT_VARS 20 +static Tcl_Obj *varPtr[NUMBER_OF_OBJECT_VARS]; /* * Forward declarations for functions defined later in this file: */ -static int CheckIfVarUnset(Tcl_Interp *interp, Tcl_Obj **varPtr, Tcl_Size varIndex); +static int CheckIfVarUnset(Tcl_Interp *interp, int varIndex); static int GetVariableIndex(Tcl_Interp *interp, - Tcl_Obj *obj, Tcl_Size *indexPtr); -static void SetVarToObj(Tcl_Obj **varPtr, Tcl_Size varIndex, Tcl_Obj *objPtr); -static Tcl_ObjCmdProc TestbignumobjCmd; -static Tcl_ObjCmdProc TestbooleanobjCmd; -static Tcl_ObjCmdProc TestdoubleobjCmd; -static Tcl_ObjCmdProc TestindexobjCmd; -static Tcl_ObjCmdProc TestintobjCmd; -static Tcl_ObjCmdProc TestlistobjCmd; -static Tcl_ObjCmdProc TestobjCmd; -static Tcl_ObjCmdProc TeststringobjCmd; - -#define VARPTR_KEY "TCLOBJTEST_VARPTR" -#define NUMBER_OF_OBJECT_VARS 20 - -static void VarPtrDeleteProc(void *clientData, TCL_UNUSED(Tcl_Interp *)) -{ - int i; - Tcl_Obj **varPtr = (Tcl_Obj **) clientData; - for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { - if (varPtr[i]) Tcl_DecrRefCount(varPtr[i]); - } - ckfree(varPtr); -} - -static Tcl_Obj **GetVarPtr(Tcl_Interp *interp) -{ - Tcl_InterpDeleteProc *proc; - - return (Tcl_Obj **) Tcl_GetAssocData(interp, VARPTR_KEY, &proc); -} + const char *string, int *indexPtr); +static void SetVarToObj(int varIndex, Tcl_Obj *objPtr); +int TclObjTest_Init(Tcl_Interp *interp); +static int TestbignumobjCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +static int TestbooleanobjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int TestdoubleobjCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +static int TestindexobjCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +static int TestintobjCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +static int TestlistobjCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +static int TestobjCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +static int TeststringobjCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); + +typedef struct TestString { + int numChars; + size_t allocated; + size_t uallocated; + Tcl_UniChar unicode[2]; +} TestString; /* *---------------------------------------------------------------------- @@ -93,38 +82,27 @@ int TclObjTest_Init( Tcl_Interp *interp) { - int i; - /* - * An array of Tcl_Obj pointers used in the commands that operate on or get - * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's - * Tcl_Obj *. - */ - Tcl_Obj **varPtr; + register int i; - varPtr = (Tcl_Obj **)ckalloc(NUMBER_OF_OBJECT_VARS *sizeof(varPtr[0])); - if (!varPtr) { - return TCL_ERROR; - } - Tcl_SetAssocData(interp, VARPTR_KEY, VarPtrDeleteProc, varPtr); for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { - varPtr[i] = NULL; + varPtr[i] = NULL; } Tcl_CreateObjCommand(interp, "testbignumobj", TestbignumobjCmd, - NULL, NULL); + (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "testbooleanobj", TestbooleanobjCmd, - NULL, NULL); + (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "testdoubleobj", TestdoubleobjCmd, - NULL, NULL); + (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "testintobj", TestintobjCmd, - NULL, NULL); + (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd, - NULL, NULL); + (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "testlistobj", TestlistobjCmd, - NULL, NULL); - Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, NULL, NULL); + (ClientData) 0, NULL); + Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd, - NULL, NULL); + (ClientData) 0, NULL); return TCL_OK; } @@ -133,7 +111,7 @@ TclObjTest_Init( * * TestbignumobjCmd -- * - * This function implements the "testbignumobj" command. It is used + * This function implmenets the "testbignumobj" command. It is used * to exercise the bignum Tcl object type implementation. * * Results: @@ -148,38 +126,36 @@ TclObjTest_Init( static int TestbignumobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Argument count */ Tcl_Obj *const objv[]) /* Argument vector */ { - static const char *const subcmds[] = { - "set", "get", "mult10", "div10", "iseven", "radixsize", NULL + const char * subcmds[] = { + "set", "get", "mult10", "div10", NULL }; enum options { - BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10, BIGNUM_ISEVEN, - BIGNUM_RADIXSIZE + BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10 }; - int index; - Tcl_Size varIndex; - const char *string; - mp_int bignumValue; - Tcl_Obj **varPtr; + + int index, varIndex; + char* string; + mp_int bignumValue, newValue; if (objc < 3) { - Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?..."); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { + string = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) { return TCL_ERROR; } - varPtr = GetVarPtr(interp); - switch ((enum options)index) { + switch (index) { case BIGNUM_SET: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "var value"); @@ -209,7 +185,7 @@ TestbignumobjCmd( if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBignumObj(varPtr[varIndex], &bignumValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&bignumValue)); + SetVarToObj(varIndex, Tcl_NewBignumObj(&bignumValue)); } break; @@ -218,7 +194,7 @@ TestbignumobjCmd( Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } break; @@ -228,23 +204,26 @@ TestbignumobjCmd( Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], &bignumValue) != TCL_OK) { return TCL_ERROR; } - if (mp_mul_d(&bignumValue, 10, &bignumValue) != MP_OKAY) { + if (mp_init(&newValue) != MP_OKAY + || (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) { mp_clear(&bignumValue); + mp_clear(&newValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_mul_d", -1)); return TCL_ERROR; } + mp_clear(&bignumValue); if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetBignumObj(varPtr[varIndex], &bignumValue); + Tcl_SetBignumObj(varPtr[varIndex], &newValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&bignumValue)); + SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue)); } break; @@ -253,74 +232,27 @@ TestbignumobjCmd( Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], &bignumValue) != TCL_OK) { return TCL_ERROR; } - if (mp_div_d(&bignumValue, 10, &bignumValue, NULL) != MP_OKAY) { + if (mp_init(&newValue) != MP_OKAY + || (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) { mp_clear(&bignumValue); + mp_clear(&newValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_div_d", -1)); return TCL_ERROR; } - if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetBignumObj(varPtr[varIndex], &bignumValue); - } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&bignumValue)); - } - break; - - case BIGNUM_ISEVEN: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); - return TCL_ERROR; - } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { - return TCL_ERROR; - } - if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], - &bignumValue) != TCL_OK) { - return TCL_ERROR; - } - if (mp_mod_2d(&bignumValue, 1, &bignumValue) != MP_OKAY) { - mp_clear(&bignumValue); - Tcl_SetObjResult(interp, - Tcl_NewStringObj("error in mp_mod_2d", -1)); - return TCL_ERROR; - } - if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetBooleanObj(varPtr[varIndex], mp_iszero(&bignumValue)); - } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(mp_iszero(&bignumValue))); - } mp_clear(&bignumValue); - break; - - case BIGNUM_RADIXSIZE: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); - return TCL_ERROR; - } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { - return TCL_ERROR; - } - if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], - &bignumValue) != TCL_OK) { - return TCL_ERROR; - } - if (mp_radix_size(&bignumValue, 10, &index) != MP_OKAY) { - return TCL_ERROR; - } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], index); + Tcl_SetBignumObj(varPtr[varIndex], &newValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(index)); + SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue)); } - mp_clear(&bignumValue); - break; } Tcl_SetObjResult(interp, varPtr[varIndex]); @@ -347,15 +279,13 @@ TestbignumobjCmd( static int TestbooleanobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_Size varIndex; - int boolValue; - const char *subCmd; - Tcl_Obj **varPtr; + int varIndex, boolValue; + char *index, *subCmd; if (objc < 3) { wrongNumArgs: @@ -363,12 +293,11 @@ TestbooleanobjCmd( return TCL_ERROR; } - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } - varPtr = GetVarPtr(interp); - subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { @@ -389,14 +318,14 @@ TestbooleanobjCmd( if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBooleanObj(varPtr[varIndex], boolValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(boolValue)); + SetVarToObj(varIndex, Tcl_NewBooleanObj(boolValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); @@ -404,7 +333,7 @@ TestbooleanobjCmd( if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, varPtr[varIndex], @@ -414,13 +343,13 @@ TestbooleanobjCmd( if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBooleanObj(varPtr[varIndex], !boolValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(!boolValue)); + SetVarToObj(varIndex, Tcl_NewBooleanObj(!boolValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), - "\": must be set, get, or not", (void *)NULL); + "\": must be set, get, or not", NULL); return TCL_ERROR; } return TCL_OK; @@ -447,15 +376,14 @@ TestbooleanobjCmd( static int TestdoubleobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_Size varIndex; + int varIndex; double doubleValue; - const char *subCmd; - Tcl_Obj **varPtr; + char *index, *subCmd, *string; if (objc < 3) { wrongNumArgs: @@ -463,9 +391,8 @@ TestdoubleobjCmd( return TCL_ERROR; } - varPtr = GetVarPtr(interp); - - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } @@ -474,7 +401,8 @@ TestdoubleobjCmd( if (objc != 4) { goto wrongNumArgs; } - if (Tcl_GetDouble(interp, Tcl_GetString(objv[3]), &doubleValue) != TCL_OK) { + string = Tcl_GetString(objv[3]); + if (Tcl_GetDouble(interp, string, &doubleValue) != TCL_OK) { return TCL_ERROR; } @@ -489,14 +417,14 @@ TestdoubleobjCmd( if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetDoubleObj(varPtr[varIndex], doubleValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue)); + SetVarToObj(varIndex, Tcl_NewDoubleObj(doubleValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); @@ -504,7 +432,7 @@ TestdoubleobjCmd( if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex], @@ -512,32 +440,32 @@ TestdoubleobjCmd( return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetDoubleObj(varPtr[varIndex], doubleValue * 10.0); + Tcl_SetDoubleObj(varPtr[varIndex], (doubleValue * 10.0)); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue * 10.0)); + SetVarToObj(varIndex, Tcl_NewDoubleObj( (doubleValue * 10.0) )); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "div10") == 0) { if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex], - &doubleValue) != TCL_OK) { + &doubleValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetDoubleObj(varPtr[varIndex], doubleValue / 10.0); + Tcl_SetDoubleObj(varPtr[varIndex], (doubleValue / 10.0)); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue / 10.0)); + SetVarToObj(varIndex, Tcl_NewDoubleObj( (doubleValue / 10.0) )); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), - "\": must be set, get, mult10, or div10", (void *)NULL); + "\": must be set, get, mult10, or div10", NULL); return TCL_ERROR; } return TCL_OK; @@ -563,24 +491,23 @@ TestdoubleobjCmd( static int TestindexobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int allowAbbrev, index, setError, i, result; - Tcl_Size index2; + int allowAbbrev, index, index2, setError, i, result; const char **argv; - static const char *const tablePtr[] = {"a", "b", "check", NULL}; - + static const char *tablePtr[] = {"a", "b", "check", NULL}; /* * Keep this structure declaration in sync with tclIndexObj.c */ struct IndexRep { - void *tablePtr; /* Pointer to the table of strings. */ - Tcl_Size offset; /* Offset between table entries. */ - Tcl_Size index; /* Selected index into table. */ - } *indexRep; + VOID *tablePtr; /* Pointer to the table of strings */ + int offset; /* Offset between table entries */ + int index; /* Selected index into table. */ + }; + struct IndexRep *indexRep; if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), "check") == 0)) { @@ -590,17 +517,17 @@ TestindexobjCmd( * lookups. */ - if (Tcl_GetIntForIndex(interp, objv[2], TCL_INDEX_NONE, &index2) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[2], &index2) != TCL_OK) { return TCL_ERROR; } Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); - indexRep = (struct IndexRep *)objv[1]->internalRep.twoPtrValue.ptr1; + indexRep = (struct IndexRep *) objv[1]->internalRep.twoPtrValue.ptr1; indexRep->index = index2; result = Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); if (result == TCL_OK) { - Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index); + Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } return result; } @@ -617,18 +544,33 @@ TestindexobjCmd( return TCL_ERROR; } - argv = (const char **)ckalloc((objc-3) * sizeof(char *)); + argv = (const char **) ckalloc((unsigned) ((objc-3) * sizeof(char *))); for (i = 4; i < objc; i++) { argv[i-4] = Tcl_GetString(objv[i]); } argv[objc-4] = NULL; + /* + * Tcl_GetIndexFromObj assumes that the table is statically-allocated so + * that its address is different for each index object. If we accidently + * allocate a table at the same address as that cached in the index + * object, clear out the object's cached state. + */ + + if ( objv[3]->typePtr != NULL + && !strcmp( "index", objv[3]->typePtr->name ) ) { + indexRep = (struct IndexRep *) objv[3]->internalRep.twoPtrValue.ptr1; + if (indexRep->tablePtr == (VOID *) argv) { + objv[3]->typePtr->freeIntRepProc(objv[3]); + objv[3]->typePtr = NULL; + } + } + result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3], - argv, "token", TCL_INDEX_TEMP_TABLE|(allowAbbrev? 0 : TCL_EXACT), - &index); - ckfree(argv); + argv, "token", (allowAbbrev? 0 : TCL_EXACT), &index); + ckfree((char *) argv); if (result == TCL_OK) { - Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index); + Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } return result; } @@ -653,18 +595,14 @@ TestindexobjCmd( static int TestintobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_Size varIndex; -#if (INT_MAX != LONG_MAX) /* int is not the same size as long */ - int i; -#endif - Tcl_WideInt wideValue; - const char *subCmd; - Tcl_Obj **varPtr; + int intValue, varIndex, i; + long longValue; + char *index, *subCmd, *string; if (objc < 3) { wrongNumArgs: @@ -672,8 +610,8 @@ TestintobjCmd( return TCL_ERROR; } - varPtr = GetVarPtr(interp); - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } @@ -682,9 +620,11 @@ TestintobjCmd( if (objc != 4) { goto wrongNumArgs; } - if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) { + string = Tcl_GetString(objv[3]); + if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } + intValue = i; /* * If the object currently bound to the variable with index varIndex @@ -695,63 +635,67 @@ TestintobjCmd( */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], wideValue); + Tcl_SetIntObj(varPtr[varIndex], intValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue)); + SetVarToObj(varIndex, Tcl_NewIntObj(intValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "set2") == 0) { /* doesn't set result */ if (objc != 4) { goto wrongNumArgs; } - if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) { + string = Tcl_GetString(objv[3]); + if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } + intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], wideValue); + Tcl_SetIntObj(varPtr[varIndex], intValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue)); + SetVarToObj(varIndex, Tcl_NewIntObj(intValue)); } - } else if (strcmp(subCmd, "setint") == 0) { + } else if (strcmp(subCmd, "setlong") == 0) { if (objc != 4) { goto wrongNumArgs; } - if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) { + string = Tcl_GetString(objv[3]); + if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } + intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], wideValue); + Tcl_SetLongObj(varPtr[varIndex], intValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue)); + SetVarToObj(varIndex, Tcl_NewLongObj(intValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); - } else if (strcmp(subCmd, "setmax") == 0) { - Tcl_WideInt maxWide = WIDE_MAX; + } else if (strcmp(subCmd, "setmaxlong") == 0) { + long maxLong = LONG_MAX; if (objc != 3) { goto wrongNumArgs; } if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], maxWide); + Tcl_SetLongObj(varPtr[varIndex], maxLong); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(maxWide)); + SetVarToObj(varIndex, Tcl_NewLongObj(maxLong)); } - } else if (strcmp(subCmd, "ismax") == 0) { + } else if (strcmp(subCmd, "ismaxlong") == 0) { if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex], &wideValue) != TCL_OK) { + if (Tcl_GetLongFromObj(interp, varPtr[varIndex], &longValue) != TCL_OK) { return TCL_ERROR; } Tcl_AppendToObj(Tcl_GetObjResult(interp), - ((wideValue == WIDE_MAX)? "1" : "0"), -1); + ((longValue == LONG_MAX)? "1" : "0"), -1); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); @@ -759,10 +703,11 @@ TestintobjCmd( if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - Tcl_AppendToObj(Tcl_GetObjResult(interp), Tcl_GetString(varPtr[varIndex]), -1); + string = Tcl_GetString(varPtr[varIndex]); + Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); } else if (strcmp(subCmd, "inttoobigtest") == 0) { /* * If long ints have more bits than ints on this platform, verify that @@ -778,9 +723,9 @@ TestintobjCmd( Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1); #else if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], LONG_MAX); + Tcl_SetLongObj(varPtr[varIndex], LONG_MAX); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(LONG_MAX)); + SetVarToObj(varIndex, Tcl_NewLongObj(LONG_MAX)); } if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &i) != TCL_OK) { Tcl_ResetResult(interp); @@ -793,40 +738,40 @@ TestintobjCmd( if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex], - &wideValue) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, varPtr[varIndex], + &intValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], wideValue * 10); + Tcl_SetIntObj(varPtr[varIndex], (intValue * 10)); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue * 10)); + SetVarToObj(varIndex, Tcl_NewIntObj( (intValue * 10) )); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "div10") == 0) { if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex], - &wideValue) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, varPtr[varIndex], + &intValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], wideValue / 10); + Tcl_SetIntObj(varPtr[varIndex], (intValue / 10)); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue / 10)); + SetVarToObj(varIndex, Tcl_NewIntObj( (intValue / 10) )); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), - "\": must be set, get, get2, mult10, or div10", (void *)NULL); + "\": must be set, get, get2, mult10, or div10", NULL); return TCL_ERROR; } return TCL_OK; @@ -841,35 +786,6 @@ TestintobjCmd( * test a few possible corner cases in list object manipulation from * C code that cannot occur at the Tcl level. * - * Following new commands are added for 8.7 as regression tests for - * memory leaks and use-after-free. Unlike 8.6, 8.7 has multiple internal - * representations for lists. It has to be ensured that corresponding - * implementations obey the invariants of the C list API. The script - * level tests do not suffice as Tcl list commands do not execute - * the same exact code path as the exported C API. - * - * Note these new commands are only useful when Tcl is compiled with - * TCL_MEM_DEBUG defined. - * - * indexmemcheck - loops calling Tcl_ListObjIndex on each element. This - * is to test that abstract lists returning elements do not depend - * on caller to free them. The test case should check allocated counts - * with the following sequence: - * set before <get memory counts> - * testobj set VARINDEX [list a b c] (or lseq etc.) - * testlistobj indexnoop VARINDEX - * testobj unset VARINDEX - * set after <get memory counts> - * after calling this command AND freeing the passed list. The targeted - * bug is if Tcl_LOI returns a ephemeral Tcl_Obj with no other reference - * resulting in a memory leak. Conversely, the command also checks - * that the Tcl_Obj returned by Tcl_LOI does not have a zero reference - * count since it is supposed to have at least one reference held - * by the list implementation. Returns a message in interp otherwise. - * - * getelementsmemcheck - as above but for Tcl_ListObjGetElements - - * * Results: * A standard Tcl object result. * @@ -881,42 +797,35 @@ TestintobjCmd( static int TestlistobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* Not used */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument objects */ { /* Subcommands supported by this command */ - static const char* const subcommands[] = { + const char* subcommands[] = { "set", "get", - "replace", - "indexmemcheck", - "getelementsmemcheck", - "index", - NULL + "replace" }; enum listobjCmdIndex { LISTOBJ_SET, LISTOBJ_GET, - LISTOBJ_REPLACE, - LISTOBJ_INDEXMEMCHECK, - LISTOBJ_GETELEMENTSMEMCHECK, - LISTOBJ_INDEX, - } cmdIndex; - - Tcl_Size varIndex; /* Variable number converted to binary */ - Tcl_Size first; /* First index in the list */ - Tcl_Size count; /* Count of elements in a list */ - Tcl_Obj **varPtr; - Tcl_Size i, len; + LISTOBJ_REPLACE + }; + + const char* index; /* Argument giving the variable number */ + int varIndex; /* Variable number converted to binary */ + int cmdIndex; /* Ordinal number of the subcommand */ + int first; /* First index in the list */ + int count; /* Count of elements in a list */ if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg...?"); return TCL_ERROR; } - varPtr = GetVarPtr(interp); - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "command", @@ -928,7 +837,7 @@ TestlistobjCmd( if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetListObj(varPtr[varIndex], objc-3, objv+3); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewListObj(objc-3, objv+3)); + SetVarToObj(varIndex, Tcl_NewListObj(objc-3, objv+3)); } Tcl_SetObjResult(interp, varPtr[varIndex]); break; @@ -938,7 +847,7 @@ TestlistobjCmd( Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); @@ -950,86 +859,16 @@ TestlistobjCmd( "varIndex start count ?element...?"); return TCL_ERROR; } - if (Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &first) != TCL_OK - || Tcl_GetIntForIndex(interp, objv[4], TCL_INDEX_NONE, &count) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[3], &first) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[4], &count) != TCL_OK) { return TCL_ERROR; } if (Tcl_IsShared(varPtr[varIndex])) { - SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); + SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } Tcl_ResetResult(interp); return Tcl_ListObjReplace(interp, varPtr[varIndex], first, count, objc-5, objv+5); - - case LISTOBJ_INDEXMEMCHECK: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); - return TCL_ERROR; - } - if (CheckIfVarUnset(interp, varPtr, varIndex)) { - return TCL_ERROR; - } - if (Tcl_ListObjLength(interp, varPtr[varIndex], &len) != TCL_OK) { - return TCL_ERROR; - } - for (i = 0; i < len; ++i) { - Tcl_Obj *objP; - if (Tcl_ListObjIndex(interp, varPtr[varIndex], i, &objP) - != TCL_OK) { - return TCL_ERROR; - } - if (objP->refCount <= 0) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Tcl_ListObjIndex returned object with ref count <= 0", - TCL_INDEX_NONE)); - /* Keep looping since we are also looping for leaks */ - } - } - break; - - case LISTOBJ_GETELEMENTSMEMCHECK: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); - return TCL_ERROR; - } - if (CheckIfVarUnset(interp, varPtr, varIndex)) { - return TCL_ERROR; - } else { - Tcl_Obj **elems; - if (Tcl_ListObjGetElements(interp, varPtr[varIndex], &len, &elems) - != TCL_OK) { - return TCL_ERROR; - } - for (i = 0; i < len; ++i) { - if (elems[i]->refCount <= 0) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Tcl_ListObjGetElements element has ref count <= 0", - TCL_INDEX_NONE)); - break; - } - } - } - break; - case LISTOBJ_INDEX: - /* - * Tcl_ListObjIndex semantics differ from lindex for out of bounds. - * Hence this explicit test. - */ - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "varIndex listIndex"); - return TCL_ERROR; - } - if (Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &first) != TCL_OK) { - return TCL_ERROR; - } else { - Tcl_Obj *objP; - if (Tcl_ListObjIndex(interp, varPtr[varIndex], first, &objP) != TCL_OK) { - return TCL_ERROR; - } - Tcl_SetObjResult(interp, objP ? objP : Tcl_NewStringObj("null", -1)); - } - break; } return TCL_OK; } @@ -1053,28 +892,14 @@ TestlistobjCmd( static int TestobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_Size varIndex, destIndex; - int i; - const Tcl_ObjType *targetType; - Tcl_Obj **varPtr; - static const char *const subcommands[] = { - "freeallvars", "bug3598580", - "types", "objtype", "newobj", "set", - "assign", "convert", "duplicate", - "invalidateStringRep", "refcount", "type", - NULL - }; - enum testobjCmdIndex { - TESTOBJ_FREEALLVARS, TESTOBJ_BUG3598580, - TESTOBJ_TYPES, TESTOBJ_OBJTYPE, TESTOBJ_NEWOBJ, TESTOBJ_SET, - TESTOBJ_ASSIGN, TESTOBJ_CONVERT, TESTOBJ_DUPLICATE, - TESTOBJ_INVALIDATESTRINGREP, TESTOBJ_REFCOUNT, TESTOBJ_TYPE, - } cmdIndex; + int varIndex, destIndex, i; + char *index, *subCmd, *string; + Tcl_ObjType *targetType; if (objc < 2) { wrongNumArgs: @@ -1082,175 +907,172 @@ TestobjCmd( return TCL_ERROR; } - varPtr = GetVarPtr(interp); - if (Tcl_GetIndexFromObj( - interp, objv[1], subcommands, "command", 0, &cmdIndex) - != TCL_OK) { - return TCL_ERROR; - } - switch (cmdIndex) { - case TESTOBJ_FREEALLVARS: - if (objc != 2) { - goto wrongNumArgs; - } - for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { - if (varPtr[i] != NULL) { - Tcl_DecrRefCount(varPtr[i]); - varPtr[i] = NULL; - } - } - return TCL_OK; - case TESTOBJ_BUG3598580: - if (objc != 2) { - goto wrongNumArgs; - } else { - Tcl_Obj *listObjPtr, *elemObjPtr; - elemObjPtr = Tcl_NewWideIntObj(123); - listObjPtr = Tcl_NewListObj(1, &elemObjPtr); - /* Replace the single list element through itself, nonsense but - * legal. */ - Tcl_ListObjReplace(interp, listObjPtr, 0, 1, 1, &elemObjPtr); - Tcl_SetObjResult(interp, listObjPtr); + subCmd = Tcl_GetString(objv[1]); + if (strcmp(subCmd, "assign") == 0) { + if (objc != 4) { + goto wrongNumArgs; + } + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + return TCL_ERROR; + } + if (CheckIfVarUnset(interp, varIndex)) { + return TCL_ERROR; } - return TCL_OK; - case TESTOBJ_TYPES: + string = Tcl_GetString(objv[3]); + if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { + return TCL_ERROR; + } + SetVarToObj(destIndex, varPtr[varIndex]); + Tcl_SetObjResult(interp, varPtr[destIndex]); + } else if (strcmp(subCmd, "bug3598580") == 0) { + Tcl_Obj *listObjPtr, *elemObjPtr; if (objc != 2) { goto wrongNumArgs; - } else { - Tcl_Obj *typesObj = Tcl_NewListObj(0, NULL); - Tcl_AppendAllObjTypes(interp, typesObj); - Tcl_SetObjResult(interp, typesObj); - } - return TCL_OK; - case TESTOBJ_OBJTYPE: - /* - * Return an object containing the name of the argument's type of - * internal rep. If none exists, return "none". - */ - - if (objc != 3) { - goto wrongNumArgs; - } else { - const char *typeName; - - if (objv[2]->typePtr == NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1)); - } else { - typeName = objv[2]->typePtr->name; - if (!strcmp(typeName, "utf32string")) - typeName = "string"; -#ifndef TCL_WIDE_INT_IS_LONG - else if (!strcmp(typeName, "wideInt")) typeName = "int"; -#endif - Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1)); - } } + elemObjPtr = Tcl_NewIntObj(123); + listObjPtr = Tcl_NewListObj(1, &elemObjPtr); + /* Replace the single list element through itself, nonsense but legal. */ + Tcl_ListObjReplace(interp, listObjPtr, 0, 1, 1, &elemObjPtr); + Tcl_SetObjResult(interp, listObjPtr); return TCL_OK; - case TESTOBJ_NEWOBJ: - if (objc != 3) { - goto wrongNumArgs; - } - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { + } else if (strcmp(subCmd, "convert") == 0) { + char *typeName; + if (objc != 4) { + goto wrongNumArgs; + } + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + return TCL_ERROR; + } + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - SetVarToObj(varPtr, varIndex, Tcl_NewObj()); + typeName = Tcl_GetString(objv[3]); + if ((targetType = Tcl_GetObjType(typeName)) == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "no type ", typeName, " found", NULL); + return TCL_ERROR; + } + if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType) + != TCL_OK) { + return TCL_ERROR; + } Tcl_SetObjResult(interp, varPtr[varIndex]); - return TCL_OK; - case TESTOBJ_SET: - if (objc != 4) { - goto wrongNumArgs; - } - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { - return TCL_ERROR; - } - SetVarToObj(varPtr, varIndex, objv[3]); - return TCL_OK; - - default: - break; - } - - /* All further commands expect an occupied varindex argument */ - if (objc < 3) { - goto wrongNumArgs; - } - - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { - return TCL_ERROR; - } - if (CheckIfVarUnset(interp, varPtr, varIndex)) { - return TCL_ERROR; - } - - switch (cmdIndex) { - case TESTOBJ_ASSIGN: - if (objc != 4) { - goto wrongNumArgs; - } - if (GetVariableIndex(interp, objv[3], &destIndex) != TCL_OK) { + } else if (strcmp(subCmd, "duplicate") == 0) { + if (objc != 4) { + goto wrongNumArgs; + } + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + return TCL_ERROR; + } + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - SetVarToObj(varPtr, destIndex, varPtr[varIndex]); + string = Tcl_GetString(objv[3]); + if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { + return TCL_ERROR; + } + SetVarToObj(destIndex, Tcl_DuplicateObj(varPtr[varIndex])); Tcl_SetObjResult(interp, varPtr[destIndex]); - break; - case TESTOBJ_CONVERT: - if (objc != 4) { + } else if (strcmp(subCmd, "freeallvars") == 0) { + if (objc != 2) { + goto wrongNumArgs; + } + for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { + if (varPtr[i] != NULL) { + Tcl_DecrRefCount(varPtr[i]); + varPtr[i] = NULL; + } + } + } else if ( strcmp ( subCmd, "invalidateStringRep" ) == 0 ) { + if ( objc != 3 ) { goto wrongNumArgs; } - if ((targetType = Tcl_GetObjType(Tcl_GetString(objv[3]))) == NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "no type ", Tcl_GetString(objv[3]), " found", (void *)NULL); + index = Tcl_GetString( objv[2] ); + if ( GetVariableIndex( interp, index, &varIndex ) != TCL_OK ) { return TCL_ERROR; } - if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType) - != TCL_OK) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } + Tcl_InvalidateStringRep( varPtr[varIndex] ); + Tcl_SetObjResult( interp, varPtr[varIndex] ); + } else if (strcmp(subCmd, "newobj") == 0) { + if (objc != 3) { + goto wrongNumArgs; + } + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + return TCL_ERROR; + } + SetVarToObj(varIndex, Tcl_NewObj()); Tcl_SetObjResult(interp, varPtr[varIndex]); - break; - case TESTOBJ_DUPLICATE: - if (objc != 4) { - goto wrongNumArgs; + } else if (strcmp(subCmd, "objtype") == 0) { + const char *typeName; + + /* + * return an object containing the name of the argument's type + * of internal rep. If none exists, return "none". + */ + + if (objc != 3) { + goto wrongNumArgs; + } + if (objv[2]->typePtr == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1)); + } else { + typeName = objv[2]->typePtr->name; + Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1)); } - if (GetVariableIndex(interp, objv[3], &destIndex) != TCL_OK) { + } else if (strcmp(subCmd, "refcount") == 0) { + char buf[TCL_INTEGER_SPACE]; + + if (objc != 3) { + goto wrongNumArgs; + } + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + return TCL_ERROR; + } + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - SetVarToObj(varPtr, destIndex, Tcl_DuplicateObj(varPtr[varIndex])); - Tcl_SetObjResult(interp, varPtr[destIndex]); - break; - case TESTOBJ_INVALIDATESTRINGREP: - if (objc != 3) { - goto wrongNumArgs; - } - Tcl_InvalidateStringRep(varPtr[varIndex]); - Tcl_SetObjResult(interp, varPtr[varIndex]); - break; - case TESTOBJ_REFCOUNT: - if (objc != 3) { - goto wrongNumArgs; - } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(varPtr[varIndex]->refCount)); - break; - case TESTOBJ_TYPE: - if (objc != 3) { - goto wrongNumArgs; + TclFormatInt(buf, varPtr[varIndex]->refCount); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + } else if (strcmp(subCmd, "type") == 0) { + if (objc != 3) { + goto wrongNumArgs; + } + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + return TCL_ERROR; + } + if (CheckIfVarUnset(interp, varIndex)) { + return TCL_ERROR; } - if (varPtr[varIndex]->typePtr == NULL) { /* a string! */ + if (varPtr[varIndex]->typePtr == NULL) { /* a string! */ Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1); -#ifndef TCL_WIDE_INT_IS_LONG - } else if (!strcmp(varPtr[varIndex]->typePtr->name, "wideInt")) { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "int", -1); -#endif - } else { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - varPtr[varIndex]->typePtr->name, -1); + } else { + Tcl_AppendToObj(Tcl_GetObjResult(interp), + varPtr[varIndex]->typePtr->name, -1); + } + } else if (strcmp(subCmd, "types") == 0) { + if (objc != 2) { + goto wrongNumArgs; + } + if (Tcl_AppendAllObjTypes(interp, + Tcl_GetObjResult(interp)) != TCL_OK) { + return TCL_ERROR; } - break; - default: - break; + } else { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "bad option \"", Tcl_GetString(objv[1]), + "\": must be assign, convert, duplicate, freeallvars, " + "newobj, objcount, objtype, refcount, type, or types", NULL); + return TCL_ERROR; } - return TCL_OK; } @@ -1274,23 +1096,20 @@ TestobjCmd( static int TeststringobjCmd( - TCL_UNUSED(void *), + ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - unsigned short *unicode; - Tcl_Size size, varIndex; - int option, i; - Tcl_Size length; + int varIndex, option, i, length; + Tcl_UniChar *unicode; #define MAX_STRINGS 11 - const char *string, *strings[MAX_STRINGS+1]; - String *strPtr; - Tcl_Obj **varPtr; - static const char *const options[] = { + char *index, *string, *strings[MAX_STRINGS+1]; + TestString *strPtr; + static const char *options[] = { "append", "appendstrings", "get", "get2", "length", "length2", - "set", "set2", "setlength", "maxchars", "range", "appendself", - "appendself2", "newunicode", NULL + "set", "set2", "setlength", "ualloc", "getunicode", + "appendself", "appendself2", NULL }; if (objc < 3) { @@ -1299,8 +1118,8 @@ TeststringobjCmd( return TCL_ERROR; } - varPtr = GetVarPtr(interp); - if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { + index = Tcl_GetString(objv[2]); + if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } @@ -1313,11 +1132,11 @@ TeststringobjCmd( if (objc != 5) { goto wrongNumArgs; } - if (Tcl_GetIntForIndex(interp, objv[4], TCL_INDEX_NONE, &length) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[4], &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] == NULL) { - SetVarToObj(varPtr, varIndex, Tcl_NewObj()); + SetVarToObj(varIndex, Tcl_NewObj()); } /* @@ -1326,9 +1145,10 @@ TeststringobjCmd( */ if (Tcl_IsShared(varPtr[varIndex])) { - SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); + SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } - Tcl_AppendToObj(varPtr[varIndex], Tcl_GetString(objv[3]), length); + string = Tcl_GetString(objv[3]); + Tcl_AppendToObj(varPtr[varIndex], string, length); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 1: /* appendstrings */ @@ -1336,7 +1156,7 @@ TeststringobjCmd( goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { - SetVarToObj(varPtr, varIndex, Tcl_NewObj()); + SetVarToObj(varIndex, Tcl_NewObj()); } /* @@ -1345,7 +1165,7 @@ TeststringobjCmd( */ if (Tcl_IsShared(varPtr[varIndex])) { - SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); + SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } for (i = 3; i < objc; i++) { strings[i-3] = Tcl_GetString(objv[i]); @@ -1356,14 +1176,14 @@ TeststringobjCmd( Tcl_AppendStringsToObj(varPtr[varIndex], strings[0], strings[1], strings[2], strings[3], strings[4], strings[5], strings[6], strings[7], strings[8], strings[9], - strings[10], strings[11], (void *)NULL); + strings[10], strings[11]); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 2: /* get */ if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr,varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); @@ -1372,16 +1192,17 @@ TeststringobjCmd( if (objc != 3) { goto wrongNumArgs; } - if (CheckIfVarUnset(interp, varPtr, varIndex)) { + if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - Tcl_AppendToObj(Tcl_GetObjResult(interp), Tcl_GetString(varPtr[varIndex]), -1); + string = Tcl_GetString(varPtr[varIndex]); + Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); break; case 4: /* length */ if (objc != 3) { goto wrongNumArgs; } - Tcl_SetWideIntObj(Tcl_GetObjResult(interp), (varPtr[varIndex] != NULL) + Tcl_SetIntObj(Tcl_GetObjResult(interp), (varPtr[varIndex] != NULL) ? varPtr[varIndex]->length : -1); break; case 5: /* length2 */ @@ -1389,18 +1210,13 @@ TeststringobjCmd( goto wrongNumArgs; } if (varPtr[varIndex] != NULL) { - const Tcl_ObjType *objType = Tcl_GetObjType("string"); - if (objType != NULL) { - Tcl_ConvertToType(NULL, varPtr[varIndex], objType); - strPtr = (String *)varPtr[varIndex]->internalRep.twoPtrValue.ptr1; - length = (int) strPtr->allocated; - } else { - length = TCL_INDEX_NONE; - } + strPtr = (TestString *) + (varPtr[varIndex])->internalRep.twoPtrValue.ptr1; + length = (int) strPtr->allocated; } else { - length = TCL_INDEX_NONE; + length = -1; } - Tcl_SetWideIntObj(Tcl_GetObjResult(interp), length); + Tcl_SetIntObj(Tcl_GetObjResult(interp), length); break; case 6: /* set */ if (objc != 4) { @@ -1416,12 +1232,12 @@ TeststringobjCmd( * is "copy on write". */ - string = Tcl_GetStringFromObj(objv[3], &size); + string = Tcl_GetStringFromObj(objv[3], &length); if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetStringObj(varPtr[varIndex], string, size); + Tcl_SetStringObj(varPtr[varIndex], string, length); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewStringObj(string, size)); + SetVarToObj(varIndex, Tcl_NewStringObj(string, length)); } Tcl_SetObjResult(interp, varPtr[varIndex]); break; @@ -1429,55 +1245,44 @@ TeststringobjCmd( if (objc != 4) { goto wrongNumArgs; } - SetVarToObj(varPtr, varIndex, objv[3]); + SetVarToObj(varIndex, objv[3]); break; case 8: /* setlength */ if (objc != 4) { goto wrongNumArgs; } - if (Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &length) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[3], &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] != NULL) { Tcl_SetObjLength(varPtr[varIndex], length); } break; - case 9: /* maxchars */ + case 9: /* ualloc */ if (objc != 3) { goto wrongNumArgs; } if (varPtr[varIndex] != NULL) { - const Tcl_ObjType *objType = Tcl_GetObjType("string"); - if (objType != NULL) { - Tcl_ConvertToType(NULL, varPtr[varIndex],objType); - strPtr = (String *)varPtr[varIndex]->internalRep.twoPtrValue.ptr1; - length = strPtr->maxChars; - } else { - length = TCL_INDEX_NONE; - } + strPtr = (TestString *) + (varPtr[varIndex])->internalRep.twoPtrValue.ptr1; + length = (int) strPtr->uallocated; } else { - length = TCL_INDEX_NONE; + length = -1; } - Tcl_SetWideIntObj(Tcl_GetObjResult(interp), length); + Tcl_SetIntObj(Tcl_GetObjResult(interp), length); break; - case 10: { /* range */ - Tcl_Size first, last; - if (objc != 5) { + case 10: /* getunicode */ + if (objc != 3) { goto wrongNumArgs; } - if ((Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &first) != TCL_OK) - || (Tcl_GetIntForIndex(interp, objv[4], TCL_INDEX_NONE, &last) != TCL_OK)) { - return TCL_ERROR; - } - Tcl_SetObjResult(interp, Tcl_GetRange(varPtr[varIndex], first, last)); + Tcl_GetUnicodeFromObj(varPtr[varIndex], NULL); break; - } case 11: /* appendself */ if (objc != 4) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { - SetVarToObj(varPtr, varIndex, Tcl_NewObj()); + SetVarToObj(varIndex, Tcl_NewObj()); } /* @@ -1486,21 +1291,21 @@ TeststringobjCmd( */ if (Tcl_IsShared(varPtr[varIndex])) { - SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); + SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } - string = Tcl_GetStringFromObj(varPtr[varIndex], &size); + string = Tcl_GetStringFromObj(varPtr[varIndex], &length); - if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { return TCL_ERROR; } - if (length == TCL_INDEX_NONE) { + if ((i < 0) || (i > length)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } - Tcl_AppendToObj(varPtr[varIndex], string + length, size - length); + Tcl_AppendToObj(varPtr[varIndex], string + i, length - i); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 12: /* appendself2 */ @@ -1508,7 +1313,7 @@ TeststringobjCmd( goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { - SetVarToObj(varPtr, varIndex, Tcl_NewObj()); + SetVarToObj(varIndex, Tcl_NewObj()); } /* @@ -1517,40 +1322,23 @@ TeststringobjCmd( */ if (Tcl_IsShared(varPtr[varIndex])) { - SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); + SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } - unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &size); + unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &length); - if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { return TCL_ERROR; } - if (length == TCL_INDEX_NONE) { + if ((i < 0) || (i > length)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } - Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + length, size - length); + Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + i, length - i); Tcl_SetObjResult(interp, varPtr[varIndex]); break; - case 13: /* newunicode*/ - unicode = (unsigned short *)ckalloc(((unsigned)objc - 3) * sizeof(unsigned short)); - for (i = 0; i < (objc - 3); ++i) { - int val; - if (Tcl_GetIntFromObj(interp, objv[i + 3], &val) != TCL_OK) { - break; - } - unicode[i] = (unsigned short)val; - } - if (i < (objc-3)) { - ckfree(unicode); - return TCL_ERROR; - } - SetVarToObj(varPtr, varIndex, Tcl_NewUnicodeObj(unicode, objc - 3)); - Tcl_SetObjResult(interp, varPtr[varIndex]); - ckfree(unicode); - break; } return TCL_OK; @@ -1577,8 +1365,7 @@ TeststringobjCmd( static void SetVarToObj( - Tcl_Obj **varPtr, - Tcl_Size varIndex, /* Designates the assignment variable. */ + int varIndex, /* Designates the assignment variable. */ Tcl_Obj *objPtr) /* Points to object to assign to var. */ { if (varPtr[varIndex] != NULL) { @@ -1609,17 +1396,17 @@ SetVarToObj( static int GetVariableIndex( Tcl_Interp *interp, /* Interpreter for error reporting. */ - Tcl_Obj *obj, /* The variable index + const char *string, /* String containing a variable index * specified as a nonnegative number less than * NUMBER_OF_OBJECT_VARS. */ - Tcl_Size *indexPtr) /* Place to store converted result. */ + int *indexPtr) /* Place to store converted result. */ { - Tcl_Size index; + int index; - if (Tcl_GetIntForIndex(interp, obj, NUMBER_OF_OBJECT_VARS - 1, &index) != TCL_OK) { + if (Tcl_GetInt(interp, string, &index) != TCL_OK) { return TCL_ERROR; } - if (index == TCL_INDEX_NONE) { + if (index < 0 || index >= NUMBER_OF_OBJECT_VARS) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "bad variable index", -1); return TCL_ERROR; @@ -1650,13 +1437,12 @@ GetVariableIndex( static int CheckIfVarUnset( Tcl_Interp *interp, /* Interpreter for error reporting. */ - Tcl_Obj ** varPtr, - Tcl_Size varIndex) /* Index of the test variable to check. */ + int varIndex) /* Index of the test variable to check. */ { - if (varIndex < 0 || varPtr[varIndex] == NULL) { + if (varPtr[varIndex] == NULL) { char buf[32 + TCL_INTEGER_SPACE]; - snprintf(buf, sizeof(buf), "variable %" TCL_SIZE_MODIFIER "d is unset (NULL)", varIndex); + sprintf(buf, "variable %d is unset (NULL)", varIndex); Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); return 1; |
