Compare commits

...
Author SHA1 Message Date
pooryorick 5e7e1715af Merge unchained branch [22400aa71b] and resolve conflicts. 2023-06-26 07:24:26 +00:00
pooryorick 51f0bfd5ae Merge "unchained branch [a03cbbdf63] and resolve conflicts. 2023-05-20 20:11:18 +00:00
pooryorick 41da2b1489 Merge "unchained" branch [6b0efb4663] and resolve conflicts. 2023-05-20 14:10:31 +00:00
pooryorick 68328fdcd5 Merge "unchained" branch commit [05b72c0b3f] and resolve conflicts. 2023-05-19 11:26:08 +00:00
pooryorick f79b9fa715 Add Tcl_ObjTypeVersion(), fix memory errors in integer list functions, adjust
lset.test so that objInterface.test can use its tests.  All linsert.test and
lset.test tests pass for the integer list.
2021-11-13 09:09:00 +00:00
pooryorick 50baebbe77 Adjust [linsert] tests to check both compiled and uncompiled paths, and run
them for the integer list type as well.  All tests pass.
2021-11-03 14:34:17 +00:00
pooryorick 749fefd640 Fix memory errors in the "list replace" proc for the integer list type,
reorganize code, route "linsert" through the type interface, disable
compilation of linsert pending further developmnt,  and add more tests.
2021-11-03 00:34:21 +00:00
pooryorick 2e12764223 To test object type interfaces, add the beginnings of a list implementation
that stores items as an array of integers and the first few tests.  All tests
pass, and Valgrind reports that no memory leaks are possible.
2021-10-30 19:28:15 +00:00
pooryorick fc2acd077c Add the macro TCL_LENGTH_NONE. 2021-10-26 13:28:11 +00:00
jan.nijtmans e6c0a3dcfb Merge 9.0 2021-10-26 08:54:12 +00:00
jan.nijtmans 962a5361ab typo 2021-10-26 08:42:48 +00:00
pooryorick a15ae048d3 Fix memory errors in lsearch, add the first few string routines to Tcl_ObjType,
modify StringIndexCmd to use to use the Tcl_ObjType interface.  Valgrind
reports no memory errors.
2021-10-24 15:55:24 +00:00
pooryorick f91edb6f99 Add the first few string functions to the Tcl_ObjType interface, move function
declarations out of tclInt.h.
2021-10-18 15:02:39 +00:00
jan.nijtmans 3763c10f23 Adapt Makefile.in and makefile.vc (for Windows) too 2021-10-18 07:43:20 +00:00
jan.nijtmans 84f1110b9d More compiler warnings 2021-10-17 20:55:15 +00:00
jan.nijtmans 6bb895f4c6 Compiler warnings/errors 2021-10-17 15:05:47 +00:00
pooryorick c4329d52b1 Adapt Tcl_LsearchObjCmd to perform efficient binary search on non-finite
Tcl_ObjType list implementations.
2021-10-16 22:04:03 +00:00
jan.nijtmans 86ec6ab749 Make it compile on MacOS too 2021-10-16 11:39:37 +00:00
jan.nijtmans 07235a8a6f at least - make it compile/run on UNIX 2021-10-16 09:45:38 +00:00
pooryorick e36e170f46 Modify Tcl_LsearchObjCmd() to not use TclListObjGetElements. 2021-10-15 19:21:39 +00:00
pooryorick 5f1e5885b7 Add tests for Tcl_ObjType "lrange" interface. 2021-10-14 20:43:04 +00:00
pooryorick f04818aaa8 Modify Tcl_LrangeObjCmd() to handle lists having indeterminate end. Fix typo
in INST_LIST_RANGE_IMM.
2021-10-14 20:08:41 +00:00
pooryorick 2e1f7ff673 Fix TclObjectDispatchNoDefault macro, add a rangeEnd function to the list
interface, improve handling of indeterminate in  
INST_LIST_INDEX_IMM and add similar handling to  INST_LIST_RANGE_IMM,
2021-10-14 14:52:05 +00:00
pooryorick 6d704ccf07 Add "indexEnd" function to Tcl_Obj list interface
table, ditch idea of using ssize_t, add TclObjectDispatchNoDefault for
interface fucntions that have no existing Tcl implemntation, rework
TclLindexFlat to route "end" indices to the indexEnd interface if there is one.
2021-10-13 11:27:45 +00:00
pooryorick fef646d799 Use TCL_INDEX_NONE as the indicator of an invalid index, modify TclLindexFlat
to produce an error when "end" is used as an index of a list having
indeterminate size, and add tests for [lindex] "end" in this case.
2021-10-10 13:00:25 +00:00
pooryorick 2f0b5c46a2 For testing, Add testIndexHexType, a Tcl_ObjType that implements its own list
interface.
2021-10-09 16:46:42 +00:00
pooryorick 03a672aeea Add "interp" argument to TclListRange, add new C procedures "TclLengthIsFinite"
and "TclLindexLast", start using a length of -1 to indicate that a list is
unbounded, and modify TclListObjRange() to be more amenable to unbounded lists,
and modify INST_LIST_RANGE_IMM bytecode routine for the same reason.
2021-10-09 16:39:49 +00:00
pooryorick 3294957eb6 Add length to TclListObjRange since callers alread have it and it makes working
with a Tcl_ObjType interface easier.  Fix tclListType in tclStrToD.c Adapt
INST_LIST_INDEX_IMM in tclExecute.c to work with Tcl_ObjType interfaces.
2021-10-07 21:09:07 +00:00
pooryorick 4789965abd Rework TclLindexFlat to function with Tcl_ObjType interfaces. 2021-10-07 19:36:19 +00:00
pooryorick 9735f7b1a9 For backwards-compatibility, shoehorn Tcl_ObjType interface structure into
existing public interface.
2021-10-05 06:07:38 +00:00
pooryorick 0779620efd Rename the Tcl_ObjType interface.list.append to interface.list.appendlist, use
interface.list.append, and add Tcl_ListObjAppendElement to tclListtype.
2021-09-28 19:26:19 +00:00
pooryorick 69675d1a04 Add remaining list routines to the Tcl_ObjType interface. 2021-09-28 00:12:36 +00:00
pooryorick 57ed822ecb Add an "interface" member to Tcl_ObjType, and plug lindex
and lrange into the interface.
2021-09-27 16:07:11 +00:00
pooryorick 314feacb7c Create new branch named "pyk-objinterface" 2021-09-23 12:56:14 +00:00
41 changed files with 3963 additions and 2227 deletions
View File
+11 -2
View File
@@ -9,6 +9,7 @@
* Copyright (c) 1994-1998 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 by Scriptics Corporation.
* Copyright (c) 2002 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2021 by Nathan Coulter. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -105,6 +106,9 @@ extern "C" {
#include <stdio.h>
#include <stddef.h>
#define TCL_COMMENT(x)
#if defined(__GNUC__) && (__GNUC__ > 2)
# if defined(_WIN32) && defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO
# define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__MINGW_PRINTF_FORMAT, a, b)))
@@ -590,6 +594,10 @@ typedef void (Tcl_MainLoopProc) (void);
* standard operations on objects of that type.
*/
/* forward declaration */
typedef struct Tcl_Obj Tcl_Obj;
typedef struct Tcl_ObjInterface Tcl_ObjInterface;
typedef struct Tcl_ObjType {
const char *name; /* Name of the type, e.g. "int". */
Tcl_FreeInternalRepProc *freeIntRepProc;
@@ -642,7 +650,7 @@ typedef union Tcl_ObjInternalRep { /* The internal representation: */
* or both.
*/
typedef struct Tcl_Obj {
struct Tcl_Obj {
Tcl_Size refCount; /* When 0 the object will be freed. */
char *bytes; /* This points to the first byte of the
* object's string representation. The array
@@ -662,7 +670,7 @@ typedef struct Tcl_Obj {
* internal rep. NULL indicates the object has
* no internal rep (has no type). */
Tcl_ObjInternalRep internalRep; /* The internal representation: */
} Tcl_Obj;
};
/*
@@ -2146,6 +2154,7 @@ typedef int (Tcl_ArgvGenFuncProc)(void *clientData, Tcl_Interp *interp,
#define TCL_IO_FAILURE ((Tcl_Size)-1)
#define TCL_AUTO_LENGTH ((Tcl_Size)-1)
#define TCL_INDEX_NONE ((Tcl_Size)-1)
#define TCL_LENGTH_NONE ((Tcl_Size)-1)
/*
*----------------------------------------------------------------------------
+73 -43
View File
@@ -15,6 +15,7 @@
#include <assert.h>
#include <math.h>
/* -------------------------- ArithSeries object ---------------------------- */
/*
@@ -68,7 +69,7 @@ static inline ArithSeries*
ArithSeriesGetInternalRep(Tcl_Obj *objPtr)
{
const Tcl_ObjInternalRep *irPtr;
irPtr = TclFetchInternalRep((objPtr), &tclArithSeriesType.objType);
irPtr = TclFetchInternalRep((objPtr), tclArithSeriesType);
return irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL;
}
@@ -102,7 +103,12 @@ static void FreeArithSeriesInternalRep (Tcl_Obj *listPtr);
static int SetArithSeriesFromAny (Tcl_Interp *interp, Tcl_Obj *objPtr);
static void UpdateStringOfArithSeries (Tcl_Obj *arithSeriesObj);
static Tcl_Obj* ArithSeriesObjStep(Tcl_Obj *arithSeriesPtr);
static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesPtr);
static int ArithSeriesObjIndex(Tcl_Interp *, Tcl_Obj *,
Tcl_Size index, Tcl_Obj **resultPtr);
static int ArithSeriesObjLength(tclObjTypeInterfaceArgsListLength);
static Tcl_Obj* ArithSeriesObjRange(tclObjTypeInterfaceArgsListRange);
static Tcl_Obj* ArithSeriesObjReverse(tclObjTypeInterfaceArgsListReverse);
static int ArithSeriesGetElements(tclObjTypeInterfaceArgsListAll);
/*
* The structure below defines the arithmetic series Tcl object type by
@@ -131,17 +137,39 @@ static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesPtr);
* are valid and will be equivalent to the empty list.
*/
const TclObjTypeWithAbstractList tclArithSeriesType = {
{"arithseries", /* name */
ObjInterface tclArithSeriesInterface = {
1,
{},
{
ArithSeriesGetElements,
NULL,
NULL,
ArithSeriesObjIndex,
NULL,
NULL,
ArithSeriesObjLength,
ArithSeriesObjRange,
NULL,
NULL,
NULL,
ArithSeriesObjReverse,
NULL,
NULL,
},
};
const ObjectType tclArithSeriesObjType = {
"arithseries",
FreeArithSeriesInternalRep, /* freeIntRepProc */
DupArithSeriesInternalRep, /* dupIntRepProc */
UpdateStringOfArithSeries, /* updateStringProc */
SetArithSeriesFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0_1(
ArithSeriesObjLength
)}
2,
(Tcl_ObjInterface *)&tclArithSeriesInterface
};
MODULE_SCOPE const Tcl_ObjType *tclArithSeriesType
= (Tcl_ObjType *)&tclArithSeriesObjType;
/*
*----------------------------------------------------------------------
*
@@ -233,7 +261,7 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide
arithSeriesRepPtr->elements = NULL;
arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
arithSeriesObj->typePtr = &tclArithSeriesType.objType;
arithSeriesObj->typePtr = tclArithSeriesType;
if (length > 0)
Tcl_InvalidateStringRep(arithSeriesObj);
@@ -288,7 +316,7 @@ NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len)
arithSeriesRepPtr->precision = maxPrecision(start,end,step);
arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
arithSeriesObj->typePtr = &tclArithSeriesType.objType;
arithSeriesObj->typePtr = tclArithSeriesType;
if (length > 0) {
Tcl_InvalidateStringRep(arithSeriesObj);
@@ -478,7 +506,7 @@ ArithSeriesObjStep(
ArithSeries *arithSeriesRepPtr;
Tcl_Obj *stepObj;
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
if (arithSeriesObj->typePtr != tclArithSeriesType) {
Tcl_Panic("ArithSeriesObjStep called with a not ArithSeries Obj.");
}
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
@@ -494,43 +522,43 @@ ArithSeriesObjStep(
/*
*----------------------------------------------------------------------
*
* TclArithSeriesObjIndex --
* ArithSeriesObjIndex --
*
* Returns the element with the specified index in the list
* represented by the specified Arithmetic Sequence object.
* If the index is out of range, NULL is returned.
* Stores in **resultPtr the element with the specified index in the list
* represented by the specified Arithmetic Sequence object. If the index
* is out of range.
*
* Results:
*
* The element on success, NULL on index out of range.
*
* Side Effects:
*
* On success, the integer pointed by *element is modified.
* TCL_OK on success, and TCL_ERROR if the index is out of range.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclArithSeriesObjIndex(
int
ArithSeriesObjIndex(
TCL_UNUSED(Tcl_Interp *),
Tcl_Obj *arithSeriesObj,
Tcl_WideInt index)
Tcl_Size index,
Tcl_Obj **resultPtr)
{
ArithSeries *arithSeriesRepPtr;
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
Tcl_Panic("TclArithSeriesObjIndex called with a not ArithSeries Obj.");
if (arithSeriesObj->typePtr != tclArithSeriesType) {
Tcl_Panic("ArithSeriesObjIndex called with a not ArithSeries Obj.");
}
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (index < 0 || (Tcl_Size)index >= arithSeriesRepPtr->len) {
return Tcl_NewObj();
if (index < 0 || index >= arithSeriesRepPtr->len) {
*resultPtr = Tcl_NewObj();
return TCL_OK;
}
/* List[i] = Start + (Step * index) */
if (arithSeriesRepPtr->isDouble) {
return Tcl_NewDoubleObj(ArithSeriesIndexDbl(arithSeriesRepPtr, index));
*resultPtr = Tcl_NewDoubleObj(ArithSeriesIndexDbl(arithSeriesRepPtr, index));
return TCL_OK;
} else {
return Tcl_NewWideIntObj(ArithSeriesIndexInt(arithSeriesRepPtr, index));
*resultPtr = Tcl_NewWideIntObj(ArithSeriesIndexInt(arithSeriesRepPtr, index));
return TCL_OK;
}
}
@@ -551,11 +579,13 @@ TclArithSeriesObjIndex(
*
*----------------------------------------------------------------------
*/
Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesObj)
int ArithSeriesObjLength(TCL_UNUSED(Tcl_Interp *),
Tcl_Obj *arithSeriesObj, Tcl_Size *result)
{
ArithSeries *arithSeriesRepPtr = (ArithSeries*)
arithSeriesObj->internalRep.twoPtrValue.ptr1;
return arithSeriesRepPtr->len;
*result = arithSeriesRepPtr->len;
return TCL_OK;
}
/*
@@ -638,7 +668,7 @@ DupArithSeriesInternalRep(
copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr;
}
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
copyPtr->typePtr = &tclArithSeriesType.objType;
copyPtr->typePtr = tclArithSeriesType;
}
/*
@@ -712,7 +742,7 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObj)
Tcl_Panic("Unable to allocate string size %" TCL_Z_MODIFIER "u", length);
}
for (i = 0; i < arithSeriesRepPtr->len; i++) {
elemObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, i);
ArithSeriesObjIndex(NULL, arithSeriesObj, i, &elemObj);
elem = Tcl_GetStringFromObj(elemObj, &slen);
if (((p - arithSeriesObj->bytes)+slen) > length) {
break;
@@ -777,7 +807,7 @@ SetArithSeriesFromAny(
*/
Tcl_Obj *
TclArithSeriesObjRange(
ArithSeriesObjRange(
Tcl_Interp *interp, /* For error message(s) */
Tcl_Obj *arithSeriesObj, /* List object to take a range from. */
Tcl_Size fromIdx, /* Index of first element to include. */
@@ -810,12 +840,12 @@ TclArithSeriesObjRange(
toIdx = arithSeriesRepPtr->len-1;
}
startObj = TclArithSeriesObjIndex(interp, arithSeriesObj, fromIdx);
ArithSeriesObjIndex(interp, arithSeriesObj, fromIdx, &startObj);
if (startObj == NULL) {
return NULL;
}
Tcl_IncrRefCount(startObj);
endObj = TclArithSeriesObjIndex(interp, arithSeriesObj, toIdx);
ArithSeriesObjIndex(interp, arithSeriesObj, toIdx, &endObj);
if (endObj == NULL) {
return NULL;
}
@@ -884,7 +914,7 @@ TclArithSeriesObjRange(
/*
*----------------------------------------------------------------------
*
* TclArithSeriesGetElements --
* ArithSeriesGetElements --
*
* This function returns an (objc,objv) array of the elements in a list
* object.
@@ -911,7 +941,7 @@ TclArithSeriesObjRange(
*/
int
TclArithSeriesGetElements(
ArithSeriesGetElements(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
Tcl_Obj *objPtr, /* ArithSeries object for which an element
* array is to be returned. */
@@ -920,7 +950,7 @@ TclArithSeriesGetElements(
Tcl_Obj ***objvPtr) /* Where to store the pointer to an array of
* pointers to the list's objects. */
{
if (TclHasInternalRep(objPtr,&tclArithSeriesType.objType)) {
if (TclHasInternalRep(objPtr,tclArithSeriesType)) {
ArithSeries *arithSeriesRepPtr;
Tcl_Obj **objv;
int i, objc;
@@ -945,7 +975,7 @@ TclArithSeriesGetElements(
}
arithSeriesRepPtr->elements = objv;
for (i = 0; i < objc; i++) {
objv[i] = TclArithSeriesObjIndex(interp, objPtr, i);
ArithSeriesObjIndex(interp, objPtr, i, &objv[i]);
if (objv[i] == NULL) {
return TCL_ERROR;
}
@@ -972,7 +1002,7 @@ TclArithSeriesGetElements(
/*
*----------------------------------------------------------------------
*
* TclArithSeriesObjReverse --
* ArithSeriesObjReverse --
*
* Reverse the order of the ArithSeries value.
* *arithSeriesObj must be known to be a valid list.
@@ -989,7 +1019,7 @@ TclArithSeriesGetElements(
*/
Tcl_Obj *
TclArithSeriesObjReverse(
ArithSeriesObjReverse(
Tcl_Interp *interp, /* For error message(s) */
Tcl_Obj *arithSeriesObj) /* List object to reverse. */
{
@@ -1005,9 +1035,9 @@ TclArithSeriesObjReverse(
isDouble = arithSeriesRepPtr->isDouble;
len = arithSeriesRepPtr->len;
startObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, (len-1));
ArithSeriesObjIndex(NULL, arithSeriesObj, (len-1), &startObj);
Tcl_IncrRefCount(startObj);
endObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, 0);
ArithSeriesObjIndex(NULL, arithSeriesObj, 0, &endObj);
Tcl_IncrRefCount(endObj);
stepObj = ArithSeriesObjStep(arithSeriesObj);
Tcl_IncrRefCount(stepObj);
-8
View File
@@ -34,14 +34,6 @@ typedef struct {
} ArithSeriesDbl;
MODULE_SCOPE Tcl_Obj *TclArithSeriesObjIndex(Tcl_Interp *, Tcl_Obj *,
Tcl_WideInt index);
MODULE_SCOPE Tcl_Obj * TclArithSeriesObjRange(Tcl_Interp *interp,
Tcl_Obj *arithSeriesPtr, Tcl_Size fromIdx, Tcl_Size toIdx);
MODULE_SCOPE Tcl_Obj * TclArithSeriesObjReverse(Tcl_Interp *interp,
Tcl_Obj *arithSeriesPtr);
MODULE_SCOPE int TclArithSeriesGetElements(Tcl_Interp *interp,
Tcl_Obj *objPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr);
MODULE_SCOPE int TclNewArithSeriesObj(Tcl_Interp *interp,
Tcl_Obj **arithSeriesObj, int useDoubles,
Tcl_Obj *startObj, Tcl_Obj *endObj,
+8 -8
View File
@@ -6152,7 +6152,7 @@ TclNREvalObjEx(
*/
Tcl_IncrRefCount(objPtr);
listPtr = TclDuplicatePureObj(interp, objPtr, &tclListType.objType);
listPtr = TclDuplicatePureObj(interp, objPtr, tclListType);
if (!listPtr) {
Tcl_DecrRefCount(objPtr);
return TCL_ERROR;
@@ -7050,7 +7050,7 @@ ExprCeilFunc(
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
if (code != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], tclDoubleType);
if (irPtr) {
Tcl_SetObjResult(interp, objv[1]);
@@ -7090,7 +7090,7 @@ ExprFloorFunc(
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
if (code != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], tclDoubleType);
if (irPtr) {
Tcl_SetObjResult(interp, objv[1]);
@@ -7236,7 +7236,7 @@ ExprSqrtFunc(
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
if (code != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], tclDoubleType);
if (irPtr) {
Tcl_SetObjResult(interp, objv[1]);
@@ -7290,7 +7290,7 @@ ExprUnaryFunc(
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
if (code != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], tclDoubleType);
if (irPtr) {
d = irPtr->doubleValue;
@@ -7354,7 +7354,7 @@ ExprBinaryFunc(
code = Tcl_GetDoubleFromObj(interp, objv[1], &d1);
#ifdef ACCEPT_NAN
if (code != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], tclDoubleType);
if (irPtr) {
d1 = irPtr->doubleValue;
@@ -7369,7 +7369,7 @@ ExprBinaryFunc(
code = Tcl_GetDoubleFromObj(interp, objv[2], &d2);
#ifdef ACCEPT_NAN
if (code != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], tclDoubleType);
if (irPtr) {
d2 = irPtr->doubleValue;
@@ -7530,7 +7530,7 @@ ExprDoubleFunc(
}
if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) {
#ifdef ACCEPT_NAN
if (TclHasInternalRep(objv[1], &tclDoubleType.objType)) {
if (TclHasInternalRep(objv[1], tclDoubleType)) {
Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
}
+2 -2
View File
@@ -1972,7 +1972,7 @@ FormatNumber(
*/
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, tclDoubleType);
if (irPtr == NULL) {
return TCL_ERROR;
}
@@ -1992,7 +1992,7 @@ FormatNumber(
*/
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, &tclDoubleType.objType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, tclDoubleType);
if (irPtr == NULL) {
return TCL_ERROR;
+1 -1
View File
@@ -433,7 +433,7 @@ ClockGetdatefieldsObjCmd(
* that it isn't.
*/
if (TclHasInternalRep(objv[1], &tclBignumType.objType)) {
if (TclHasInternalRep(objv[1], tclBignumType)) {
Tcl_SetObjResult(interp, lit[LIT_INTEGER_VALUE_TOO_LARGE]);
return TCL_ERROR;
}
+17 -9
View File
@@ -17,7 +17,6 @@
#ifdef _WIN32
# include "tclWinInt.h"
#endif
#include "tclArithSeries.h"
/*
* The state structure used by [foreach]. Note that the actual structure has
@@ -2789,7 +2788,7 @@ EachloopCmd(
/* List */
/* Variables */
statePtr->vCopyList[i] = TclDuplicatePureObj(
interp, objv[1+i*2], &tclListType.objType);
interp, objv[1+i*2], tclListType);
if (!statePtr->vCopyList[i]) {
result = TCL_ERROR;
goto done;
@@ -2814,19 +2813,25 @@ EachloopCmd(
&statePtr->varcList[i], &statePtr->varvList[i]);
/* Values */
if (TclHasInternalRep(objv[2+i*2],&tclArithSeriesType.objType)) {
/* Special case for Arith Series */
if (TclObjectHasInterface(objv[2+i*2], list, length)) {
int status;
statePtr->aCopyList[i] = Tcl_DuplicateObj(objv[2+i*2]);
Tcl_IncrRefCount(statePtr->aCopyList[i]);
if (statePtr->aCopyList[i] == NULL) {
result = TCL_ERROR;
goto done;
}
/* Don't compute values here, wait until the last moment */
statePtr->argcList[i] = ABSTRACTLIST_PROC(statePtr->aCopyList[i], lengthProc)(statePtr->aCopyList[i]);
TclObjectDispatchNoDefault(interp, status, statePtr->aCopyList[i], list,
length, interp, statePtr->aCopyList[i], &statePtr->argcList[i]);
if (status != TCL_OK) {
result = TCL_ERROR;
goto done;
}
} else {
/* List values */
statePtr->aCopyList[i] = TclDuplicatePureObj(
interp, objv[2+i*2], &tclListType.objType);
interp, objv[2+i*2], tclListType);
if (!statePtr->aCopyList[i]) {
result = TCL_ERROR;
goto done;
@@ -2964,12 +2969,15 @@ ForeachAssignments(
Tcl_Obj *valuePtr, *varValuePtr;
for (i=0 ; i<statePtr->numLists ; i++) {
int isarithseries = TclHasInternalRep(statePtr->aCopyList[i],&tclArithSeriesType.objType);
TCL_UNUSEDVAR(int status);
int hasindexinterface = TclObjectHasInterface(
statePtr->aCopyList[i], list, index);
for (v=0 ; v<statePtr->varcList[i] ; v++) {
k = statePtr->index[i]++;
if (k < statePtr->argcList[i]) {
if (isarithseries) {
valuePtr = TclArithSeriesObjIndex(interp, statePtr->aCopyList[i], k);
if (hasindexinterface) {
TclObjectDispatchNoDefault(interp, status, statePtr->aCopyList[i], list,
index, interp, statePtr->aCopyList[i], k, &valuePtr);
if (valuePtr == NULL) {
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (setting %s loop variable \"%s\")",
+229 -79
View File
@@ -2203,8 +2203,8 @@ Tcl_JoinObjCmd(
Tcl_Obj *const objv[]) /* The argument objects. */
{
Tcl_Size length, listLen;
int isArithSeries = 0;
Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs;
int status;
Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs = NULL;
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
@@ -2216,9 +2216,12 @@ Tcl_JoinObjCmd(
* pointer to its array of element pointers.
*/
if (TclHasInternalRep(objv[1],&tclArithSeriesType.objType)) {
isArithSeries = 1;
listLen = ABSTRACTLIST_PROC(objv[1], lengthProc)(objv[1]);
if (TclObjectHasInterface(objv[1], list, length)) {
status = TclObjectDispatchNoDefault(interp, status, objv[1], list,
length, interp, objv[1], &listLen);
if (status != TCL_OK ) {
return TCL_ERROR;
}
} else {
if (TclListObjGetElementsM(interp, objv[1], &listLen,
&elemPtrs) != TCL_OK) {
@@ -2231,14 +2234,22 @@ Tcl_JoinObjCmd(
return TCL_OK;
}
if (listLen == 1) {
Tcl_Obj *valueObj;
/* One element; return it */
if (isArithSeries) {
Tcl_Obj *valueObj = TclArithSeriesObjIndex(interp, objv[1], 0);
if (valueObj == NULL) {
if (TclObjectHasInterface(objv[1], list, index)) {
TclObjectDispatchNoDefault(interp, status, objv[1], list,
index, interp, objv[1], 0, &valueObj);
if (status != TCL_OK) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, valueObj);
} else {
if (elemPtrs == NULL) {
if (TclListObjGetElementsM(interp, objv[1], &listLen,
&elemPtrs) != TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, elemPtrs[0]);
}
return TCL_OK;
@@ -2249,12 +2260,16 @@ Tcl_JoinObjCmd(
(void) Tcl_GetStringFromObj(joinObjPtr, &length);
if (length == 0) {
if (TclListObjGetElementsM(interp, objv[1], &listLen,
&elemPtrs) != TCL_OK) {
return TCL_ERROR;
}
resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
} else {
Tcl_Size i;
TclNewObj(resObjPtr);
if (isArithSeries) {
if (TclObjectHasInterface(objv[1], list, index)) {
Tcl_Obj *valueObj;
for (i = 0; i < listLen; i++) {
if (i > 0) {
@@ -2268,14 +2283,21 @@ Tcl_JoinObjCmd(
Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
}
valueObj = TclArithSeriesObjIndex(interp, objv[1], i);
if (valueObj == NULL) {
TclObjectDispatchNoDefault(interp, status, objv[1], list,
index, interp, objv[1], i, &valueObj);
if (status != TCL_OK) {
return TCL_ERROR;
}
Tcl_AppendObjToObj(resObjPtr, valueObj);
Tcl_DecrRefCount(valueObj);
TclBounceRefCount(valueObj);
}
} else {
if (elemPtrs == NULL) {
if (TclListObjGetElementsM(interp, objv[1], &listLen,
&elemPtrs) != TCL_OK) {
return TCL_ERROR;
}
}
for (i = 0; i < listLen; i++) {
if (i > 0) {
@@ -2335,7 +2357,7 @@ Tcl_LassignObjCmd(
return TCL_ERROR;
}
listCopyPtr = TclDuplicatePureObj(interp, objv[1], &tclListType.objType);
listCopyPtr = TclDuplicatePureObj(interp, objv[1], tclListType);
if (!listCopyPtr) {
return TCL_ERROR;
}
@@ -2505,7 +2527,7 @@ Tcl_LinsertObjCmd(
listPtr = objv[1];
if (Tcl_IsShared(listPtr)) {
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
listPtr = TclDuplicatePureObj(interp, listPtr, tclListType);
if (!listPtr) {
return TCL_ERROR;
}
@@ -2705,7 +2727,7 @@ Tcl_LpopObjCmd(
if (objc == 2) {
if (Tcl_IsShared(listPtr)) {
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
listPtr = TclDuplicatePureObj(interp, listPtr, tclListType);
if (!listPtr) {
return TCL_ERROR;
}
@@ -2764,8 +2786,8 @@ Tcl_LrangeObjCmd(
Tcl_Obj *const objv[])
/* Argument objects. */
{
int result;
Tcl_Size listLen, first, last;
int result, status;
Tcl_Size fromAnchor, first, fromIdx, last, listLen, toAnchor, toIdx;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "list first last");
return TCL_ERROR;
@@ -2776,27 +2798,48 @@ Tcl_LrangeObjCmd(
return result;
}
result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ listLen - 1,
&first);
result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ TCL_SIZE_MAX - 1,
&toIdx);
if (result != TCL_OK) {
return result;
}
result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
&last);
result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ TCL_SIZE_MAX - 1,
&fromIdx);
if (result != TCL_OK) {
return result;
}
if (TclHasInternalRep(objv[1],&tclArithSeriesType.objType)) {
Tcl_Obj *rangeObj;
rangeObj = TclArithSeriesObjRange(interp, objv[1], first, last);
if (rangeObj) {
Tcl_SetObjResult(interp, rangeObj);
} else {
toAnchor = TclIndexIsFromEnd(toIdx);
fromAnchor = TclIndexIsFromEnd(fromIdx);
if (!Tcl_LengthIsFinite(listLen)
&& (toAnchor == 1 || fromAnchor == 1)
&& TclObjectHasInterface(objv[1], list, rangeEnd)
) {
Tcl_Obj *objResultPtr;
status = TclObjectDispatchNoDefault(interp, objResultPtr,
objv[1], list, rangeEnd, interp, objv[1], toAnchor,
toIdx, fromAnchor, fromIdx);
if (status != TCL_OK || objResultPtr == NULL) {
return TCL_ERROR;
} else {
Tcl_SetObjResult(interp, objResultPtr);
}
} else {
result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ listLen - 1,
&first);
if (result != TCL_OK) {
return result;
}
result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
&last);
if (result != TCL_OK) {
return result;
}
Tcl_Obj *resultObj = TclListObjRange(interp, objv[1], first, last);
if (resultObj == NULL) {
return TCL_ERROR;
@@ -2892,7 +2935,7 @@ Tcl_LremoveObjCmd(
*/
if (Tcl_IsShared(listObj)) {
listObj = TclDuplicatePureObj(interp, listObj, &tclListType.objType);
listObj = TclDuplicatePureObj(interp, listObj, tclListType);
if (!listObj) {
status = TCL_ERROR;
goto done;
@@ -3147,7 +3190,7 @@ Tcl_LreplaceObjCmd(
listPtr = objv[1];
if (Tcl_IsShared(listPtr)) {
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
listPtr = TclDuplicatePureObj(interp, listPtr, tclListType);
if (!listPtr) {
return TCL_ERROR;
}
@@ -3207,19 +3250,18 @@ Tcl_LreverseObjCmd(
return TCL_ERROR;
}
/*
* Handle ArithSeries special case - don't shimmer a series into a list
* just to reverse it.
*/
if (TclHasInternalRep(objv[1],&tclArithSeriesType.objType)) {
Tcl_Obj *resObj = TclArithSeriesObjReverse(interp, objv[1]);
if (TclObjectHasInterface(objv[1], list, reverse)) {
TCL_UNUSEDVAR(int status);
Tcl_Obj *resObj;
TclObjectDispatchNoDefault(interp, resObj, objv[1], list,
reverse, interp, objv[1]);
if (resObj) {
Tcl_SetObjResult(interp, resObj);
return TCL_OK;
} else {
return TCL_ERROR;
}
} /* end ArithSeries */
}
/* True List */
if (TclListObjLengthM(interp, objv[1], &elemc) != TCL_OK) {
@@ -3314,7 +3356,7 @@ Tcl_LsearchObjCmd(
int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
double patDouble, objDouble;
SortInfo sortInfo;
Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr;
Tcl_Obj *patObj, *itemPtr, *item2Ptr, *listPtr, *subjectPtr, *startPtr;
SortStrCmpFn_t strCmpFn = TclUtfCmp;
Tcl_RegExp regexp = NULL;
static const char *const options[] = {
@@ -3344,6 +3386,7 @@ Tcl_LsearchObjCmd(
isIncreasing = 1;
allMatches = 0;
inlineReturn = 0;
itemPtr = NULL;
returnSubindices = 0;
negatedMatch = 0;
bisect = 0;
@@ -3612,7 +3655,8 @@ Tcl_LsearchObjCmd(
* pointer to its array of element pointers.
*/
result = TclListObjGetElementsM(interp, objv[objc - 2], &listc, &listv);
subjectPtr = objv[objc-2];
result = Tcl_ListObjLength(interp, subjectPtr, &listc);
if (result != TCL_OK) {
goto done;
}
@@ -3666,7 +3710,8 @@ Tcl_LsearchObjCmd(
*/
if (startPtr) {
result = TclGetIntForIndexM(interp, startPtr, listc-1, &start);
result = TclGetIntForIndexM(interp, startPtr,
(Tcl_LengthIsFinite(listc) ? listc - 1 : TCL_SIZE_MAX), &start);
if (result != TCL_OK) {
goto done;
}
@@ -3675,16 +3720,17 @@ Tcl_LsearchObjCmd(
}
/*
* If the search started past the end of the list, we just return a
* If the search started past the end of the list, just return a
* "did not match anything at all" result straight away. [Bug 1374778]
*/
if (start >= listc) {
if (Tcl_LengthIsFinite(listc) && start >= listc) {
if (allMatches || inlineReturn) {
Tcl_ResetResult(interp);
} else {
TclNewIntObj(itemPtr, -1);
Tcl_SetObjResult(interp, itemPtr);
itemPtr = NULL;
}
goto done;
}
@@ -3713,11 +3759,9 @@ Tcl_LsearchObjCmd(
}
/*
* List representation might have been shimmered; restore it. [Bug
* 1844789]
* [Bug 1844789], "lsearch -exact -integer ..." crashes, was
* previously fixed at this point.
*/
TclListObjGetElementsM(NULL, objv[objc - 2], &listc, &listv);
break;
case REAL:
result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble);
@@ -3726,11 +3770,9 @@ Tcl_LsearchObjCmd(
}
/*
* List representation might have been shimmered; restore it. [Bug
* 1844789]
* [Bug 1844789], "lsearch -exact -integer ..." crashes, was
* previously fixed at this point.
*/
TclListObjGetElementsM(NULL, objv[objc - 2], &listc, &listv);
break;
}
} else {
@@ -3746,6 +3788,7 @@ Tcl_LsearchObjCmd(
match = 0;
if (mode == SORTED && !allMatches && !negatedMatch) {
int isfinite;
/*
* If the data is sorted, we can do a more intelligent search. Note
* that there is no point in being smart when -all was specified; in
@@ -3758,18 +3801,57 @@ Tcl_LsearchObjCmd(
*/
lower = start - groupSize;
upper = listc;
while (lower + groupSize != upper && sortInfo.resultCode == TCL_OK) {
i = (lower + upper)/2;
isfinite = Tcl_LengthIsFinite(listc);
if (isfinite) {
upper = listc;
} else {
upper = 1;
}
while (
(lower + groupSize < upper && sortInfo.resultCode == TCL_OK)
|| !isfinite
) {
i = (lower + upper) / 2;
if (i < 0) {
result = TCL_ERROR;
Tcl_SetObjResult(interp, Tcl_NewStringObj("sorted list is incoherent", -1));
goto done;
}
i -= i % groupSize;
result = Tcl_ListObjIndex(interp, subjectPtr, i+groupOffset, &itemPtr);
if (result != TCL_OK) {
if (isfinite) {
goto done;
} else {
if (Tcl_ListObjLength(interp, subjectPtr, &listc) == TCL_OK) {
isfinite = Tcl_LengthIsFinite(listc);
if (isfinite) {
if (listc - 1 > i) {
upper = listc = 1;
break;
} else {
goto done;
}
} else {
goto done;
}
} else {
goto done;
}
}
}
Tcl_IncrRefCount(itemPtr);
if (sortInfo.indexc != 0) {
itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
item2Ptr = SelectObjFromSublist(itemPtr, &sortInfo);
if (sortInfo.resultCode != TCL_OK) {
result = sortInfo.resultCode;
goto done;
}
} else {
itemPtr = listv[i+groupOffset];
/* Increment item2Ptr refcount first in case it's the same
* object as itemPtr. */
Tcl_IncrRefCount(item2Ptr);
Tcl_DecrRefCount(itemPtr);
itemPtr = item2Ptr;
}
switch (dataType) {
case ASCII:
@@ -3807,6 +3889,8 @@ Tcl_LsearchObjCmd(
}
break;
}
Tcl_DecrRefCount(itemPtr);
itemPtr = NULL;
if (match == 0) {
/*
* Normally, binary search is written to stop when it finds a
@@ -3833,14 +3917,22 @@ Tcl_LsearchObjCmd(
} else if (match > 0) {
if (isIncreasing) {
lower = i;
if (!isfinite) {
upper *= 2;
}
} else {
upper = i;
isfinite = 1;
}
} else {
if (isIncreasing) {
upper = i;
isfinite = 1;
} else {
lower = i;
if (!isfinite) {
upper *= 2;
}
}
}
}
@@ -3858,10 +3950,15 @@ Tcl_LsearchObjCmd(
if (allMatches) {
listPtr = Tcl_NewListObj(0, NULL);
}
for (i = start; i < listc; i += groupSize) {
for (i = start; listc < 0 || i < listc; i += groupSize) {
match = 0;
result = Tcl_ListObjIndex(interp, subjectPtr, i+groupOffset, &itemPtr);
if (result != TCL_OK) {
goto done;
}
Tcl_IncrRefCount(itemPtr);
if (sortInfo.indexc != 0) {
itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
item2Ptr = SelectObjFromSublist(itemPtr, &sortInfo);
if (sortInfo.resultCode != TCL_OK) {
if (listPtr != NULL) {
Tcl_DecrRefCount(listPtr);
@@ -3869,8 +3966,11 @@ Tcl_LsearchObjCmd(
result = sortInfo.resultCode;
goto done;
}
} else {
itemPtr = listv[i+groupOffset];
/* Increment item2Ptr refcount first in case it's the same
* object as itemPtr. */
Tcl_IncrRefCount(item2Ptr);
Tcl_DecrRefCount(itemPtr);
itemPtr = item2Ptr;
}
switch (mode) {
@@ -3948,41 +4048,66 @@ Tcl_LsearchObjCmd(
match = !match;
}
if (!match) {
Tcl_DecrRefCount(itemPtr);
itemPtr = NULL;
continue;
}
if (!allMatches) {
index = i;
Tcl_DecrRefCount(itemPtr);
itemPtr = NULL;
break;
} else if (inlineReturn) {
/*
* Note that these appends are not expected to fail.
* These append operations are expected to not fail.
*/
Tcl_DecrRefCount(itemPtr);
itemPtr = NULL;
if (returnSubindices && (sortInfo.indexc != 0)) {
itemPtr = SelectObjFromSublist(listv[i+groupOffset],
&sortInfo);
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
result = Tcl_ListObjIndex(interp, subjectPtr, i+groupOffset, &itemPtr);
if (result != TCL_OK) {
goto done;
}
Tcl_IncrRefCount(itemPtr);
item2Ptr = SelectObjFromSublist(itemPtr, &sortInfo);
Tcl_ListObjAppendElement(interp, listPtr, item2Ptr);
Tcl_DecrRefCount(itemPtr);
} else if (groupSize > 1) {
Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0,
groupSize, &listv[i]);
Tcl_Size j;
for (j = 0; j < groupSize; j++) {
result = Tcl_ListObjIndex(interp, subjectPtr,
i+j, &itemPtr);
if (result != TCL_OK) {
goto done;
}
Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0,
1, &itemPtr);
}
} else {
itemPtr = listv[i];
result = Tcl_ListObjIndex(interp, subjectPtr, i, &itemPtr);
if (result != TCL_OK) {
goto done;
}
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
}
} else if (returnSubindices) {
Tcl_Size j;
Tcl_DecrRefCount(itemPtr);
TclNewIndexObj(itemPtr, i+groupOffset);
for (j=0 ; j<sortInfo.indexc ; j++) {
Tcl_Obj *elObj;
size_t elValue = TclIndexDecode(sortInfo.indexv[j], listc);
Tcl_Size elValue = TclIndexDecode(sortInfo.indexv[j], listc);
TclNewIndexObj(elObj, elValue);
Tcl_ListObjAppendElement(interp, itemPtr, elObj);
}
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
} else {
Tcl_DecrRefCount(itemPtr);
Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewWideIntObj(i));
}
itemPtr = NULL;
}
}
@@ -4004,9 +4129,10 @@ Tcl_LsearchObjCmd(
Tcl_ListObjAppendElement(interp, itemPtr, elObj);
}
Tcl_SetObjResult(interp, itemPtr);
itemPtr = NULL;
} else {
Tcl_Obj *elObj;
TclNewIndexObj(elObj, index);
Tcl_Obj *elObj;
TclNewIndexObj(elObj, index);
Tcl_SetObjResult(interp, elObj);
}
} else if (index < 0) {
@@ -4018,13 +4144,32 @@ Tcl_LsearchObjCmd(
Tcl_SetObjResult(interp, Tcl_NewObj());
} else {
if (returnSubindices) {
Tcl_SetObjResult(interp, SelectObjFromSublist(listv[i+groupOffset],
&sortInfo));
result = Tcl_ListObjIndex(interp, subjectPtr, i+groupOffset, &itemPtr);
if (result != TCL_OK) {
goto done;
}
item2Ptr = SelectObjFromSublist(itemPtr, &sortInfo);
Tcl_SetObjResult(interp, item2Ptr);
} else if (groupSize > 1) {
Tcl_SetObjResult(interp, Tcl_NewListObj(groupSize, &listv[index]));
Tcl_Size j;
listPtr = Tcl_NewListObj(0, NULL);
for (j = 0; j < groupSize; j++) {
result = Tcl_ListObjIndex(interp, subjectPtr, index + j, &itemPtr);
if (result != TCL_OK) {
Tcl_DecrRefCount(listPtr);
goto done;
}
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
}
Tcl_SetObjResult(interp, listPtr);
} else {
Tcl_SetObjResult(interp, listv[index]);
result = Tcl_ListObjIndex(interp, subjectPtr, index, &itemPtr);
if (result != TCL_OK) {
goto done;
}
Tcl_SetObjResult(interp, itemPtr);
}
itemPtr = NULL;
}
result = TCL_OK;
@@ -4033,6 +4178,9 @@ Tcl_LsearchObjCmd(
*/
done:
if (itemPtr != NULL) {
Tcl_DecrRefCount(itemPtr);
}
if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
@@ -4041,6 +4189,7 @@ Tcl_LsearchObjCmd(
}
return result;
}
/*
*----------------------------------------------------------------------
@@ -4771,7 +4920,7 @@ Tcl_LsortObjCmd(
* 1675116]
*/
listObj = TclDuplicatePureObj(interp ,listObj, &tclListType.objType);
listObj = TclDuplicatePureObj(interp ,listObj, tclListType);
if (listObj == NULL) {
sortInfo.resultCode = TCL_ERROR;
goto done;
@@ -4796,9 +4945,10 @@ Tcl_LsortObjCmd(
sortInfo.compareCmdPtr = newCommandPtr;
}
if (TclHasInternalRep(listObj,&tclArithSeriesType.objType)) {
sortInfo.resultCode = TclArithSeriesGetElements(interp,
listObj, &length, &listObjPtrs);
if (TclObjectHasInterface(listObj, list, all)) {
TCL_UNUSEDVAR(int status);
sortInfo.resultCode = TclObjectDispatchNoDefault(interp, status,
listObj, list, all, interp, listObj, &length, &listObjPtrs);
} else {
sortInfo.resultCode = TclListObjGetElementsM(interp, listObj,
&length, &listObjPtrs);
@@ -4992,7 +5142,7 @@ Tcl_LsortObjCmd(
ListObjGetRep(resultPtr, &listRep);
newArray = ListRepElementsBase(&listRep);
if (group) {
for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) {
for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
idx = elementPtr->payload.index;
for (j = 0; j < groupSize; j++) {
if (indices) {
@@ -5127,7 +5277,7 @@ Tcl_LeditObjCmd(
}
if (Tcl_IsShared(listPtr)) {
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
listPtr = TclDuplicatePureObj(interp, listPtr, tclListType);
if (!listPtr) {
return TCL_ERROR;
}
+46 -33
View File
@@ -24,6 +24,7 @@
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
static Tcl_NRPostProc SwitchPostProc;
static Tcl_NRPostProc TryPostBody;
static Tcl_NRPostProc TryPostFinal;
@@ -1311,7 +1312,7 @@ StringFirstCmd(
if (objc < 3 || objc > 4) {
Tcl_WrongNumArgs(interp, 1, objv,
"needleString haystackString ?startIndex?");
"needleString haystackString ?startIndex?");
return TCL_ERROR;
}
@@ -1402,39 +1403,51 @@ StringIndexCmd(
return TCL_ERROR;
}
/*
* Get the char length to calculate what 'end' means.
*/
end = Tcl_GetCharLength(objv[1]) - 1;
if (TclGetIntForIndexM(interp, objv[2], end, &index) != TCL_OK) {
return TCL_ERROR;
}
if ((index >= 0) && (index <= end)) {
int ch = Tcl_GetUniChar(objv[1], index);
if (ch == -1) {
if (TclObjectHasInterface(objv[1], string, index)) {
int status;
Tcl_Obj *charPtr;
status = TclStringIndexInterface(interp, objv[1], objv[2], &charPtr) ;
if (status != TCL_OK) {
return status;
} else {
Tcl_SetObjResult(interp, charPtr);
return TCL_OK;
}
} else {
/*
* If we have a ByteArray object, we're careful to generate a new
* bytearray for a result.
* Get the char length to calculate what 'end' means.
*/
if (TclIsPureByteArray(objv[1])) {
unsigned char uch = UCHAR(ch);
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(&uch, 1));
} else {
char buf[4] = "";
end = Tcl_UniCharToUtf(ch, buf);
Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, end));
end = Tcl_GetCharLength(objv[1]) - 1;
if (TclGetIntForIndexM(interp, objv[2], end, &index) != TCL_OK) {
return TCL_ERROR;
}
if ((index >= 0) && (index <= end)) {
int ch = Tcl_GetUniChar(objv[1], index);
if (ch == -1) {
return TCL_OK;
}
/*
* If we have a ByteArray object, we're careful to generate a new
* bytearray for a result.
*/
if (TclIsPureByteArray(objv[1])) {
unsigned char uch = UCHAR(ch);
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(&uch, 1));
} else {
char buf[4] = "";
end = Tcl_UniCharToUtf(ch, buf);
Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, end));
}
}
return TCL_OK;
}
return TCL_OK;
}
/*
@@ -1607,7 +1620,7 @@ StringIsCmd(
case STR_IS_BOOL:
case STR_IS_TRUE:
case STR_IS_FALSE:
if (!TclHasInternalRep(objPtr, &tclBooleanType.objType)
if (!TclHasInternalRep(objPtr, tclBooleanType)
&& (TCL_OK != TclSetBooleanFromAny(NULL, objPtr))) {
if (strict) {
result = 0;
@@ -1676,9 +1689,9 @@ StringIsCmd(
chcomp = Tcl_UniCharIsDigit;
break;
case STR_IS_DOUBLE: {
if (TclHasInternalRep(objPtr, &tclDoubleType.objType) ||
TclHasInternalRep(objPtr, &tclIntType.objType) ||
TclHasInternalRep(objPtr, &tclBignumType.objType)) {
if (TclHasInternalRep(objPtr, tclDoubleType) ||
TclHasInternalRep(objPtr, tclIntType) ||
TclHasInternalRep(objPtr, tclBignumType)) {
break;
}
string1 = Tcl_GetStringFromObj(objPtr, &length1);
@@ -1707,8 +1720,8 @@ StringIsCmd(
break;
case STR_IS_INT:
case STR_IS_ENTIER:
if (TclHasInternalRep(objPtr, &tclIntType.objType) ||
TclHasInternalRep(objPtr, &tclBignumType.objType)) {
if (TclHasInternalRep(objPtr, tclIntType) ||
TclHasInternalRep(objPtr, tclBignumType)) {
break;
}
string1 = Tcl_GetStringFromObj(objPtr, &length1);
+8 -1
View File
@@ -41,7 +41,7 @@ static int IndexTailVarIfKnown(Tcl_Interp *interp,
*
* Side effects:
* When TCL_OK is returned, the encoded index value is written
* to *index.
* to *indexPtr.
*
*----------------------------------------------------------------------
*/
@@ -1411,6 +1411,13 @@ TclCompileLreplaceCmd(
Tcl_Token *tokenPtr;
int i;
/*
* For now, disable compilation of lreplace. Figure out later if any
* compilation can be done given that any Tcl_ObjType may implement
* lreplace, and should return an object of the same type.
*/
return TCL_ERROR;
if (parsePtr->numWords < 4) {
return TCL_ERROR;
}
+1 -1
View File
@@ -2111,7 +2111,7 @@ ParseLexeme(
* Example: Inf + luence + () becomes a valid function call.
* [Bug 3401704]
*/
if (TclHasInternalRep(literal, &tclDoubleType.objType)) {
if (TclHasInternalRep(literal, tclDoubleType)) {
const char *p = start;
while (p < end) {
+29 -29
View File
@@ -150,7 +150,7 @@ const Tcl_ObjType tclDictType = {
TCL_OBJTYPE_V0
};
#define DictSetInternalRep(objPtr, dictRepPtr) \
#define DictSetIntRep(objPtr, dictRepPtr) \
do { \
Tcl_ObjInternalRep ir; \
ir.twoPtrValue.ptr1 = (dictRepPtr); \
@@ -396,7 +396,7 @@ DupDictInternalRep(
* Store in the object.
*/
DictSetInternalRep(copyPtr, newDict);
DictSetIntRep(copyPtr, newDict);
}
/*
@@ -603,7 +603,7 @@ SetDictFromAny(
* the conversion from lists to dictionaries.
*/
if (TclHasInternalRep(objPtr, &tclListType.objType)) {
if (TclHasInternalRep(objPtr, tclListType)) {
Tcl_Size objc, i;
Tcl_Obj **objv;
@@ -711,7 +711,7 @@ SetDictFromAny(
dict->epoch = 1;
dict->chain = NULL;
dict->refCount = 1;
DictSetInternalRep(objPtr, dict);
DictSetIntRep(objPtr, dict);
return TCL_OK;
missingValue:
@@ -890,7 +890,7 @@ InvalidateDictChain(
dict->refCount++;
TclInvalidateStringRep(dictObj);
TclFreeInternalRep(dictObj);
DictSetInternalRep(dictObj, dict);
DictSetIntRep(dictObj, dict);
dict->epoch++;
dictObj = dict->chain;
@@ -945,7 +945,7 @@ Tcl_DictObjPut(
hPtr = CreateChainEntry(dict, keyPtr, &isNew);
dict->refCount++;
TclFreeInternalRep(dictPtr)
DictSetInternalRep(dictPtr, dict);
DictSetIntRep(dictPtr, dict);
Tcl_IncrRefCount(valuePtr);
if (!isNew) {
Tcl_Obj *oldValuePtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
@@ -1426,7 +1426,7 @@ Tcl_NewDictObj(void)
dict->epoch = 1;
dict->chain = NULL;
dict->refCount = 1;
DictSetInternalRep(dictPtr, dict);
DictSetIntRep(dictPtr, dict);
return dictPtr;
#endif
}
@@ -1474,7 +1474,7 @@ Tcl_DbNewDictObj(
dict->epoch = 1;
dict->chain = NULL;
dict->refCount = 1;
DictSetInternalRep(dictPtr, dict);
DictSetIntRep(dictPtr, dict);
return dictPtr;
}
#else /* !TCL_MEM_DEBUG */
@@ -1509,7 +1509,7 @@ Tcl_DbNewDictObj(
static int
DictCreateCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -1559,7 +1559,7 @@ DictCreateCmd(
static int
DictGetCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -1652,7 +1652,7 @@ DictGetCmd(
static int
DictGetDefCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -1717,7 +1717,7 @@ DictGetDefCmd(
static int
DictReplaceCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -1765,7 +1765,7 @@ DictReplaceCmd(
static int
DictRemoveCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -1813,7 +1813,7 @@ DictRemoveCmd(
static int
DictMergeCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -1900,7 +1900,7 @@ DictMergeCmd(
static int
DictKeysCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -1979,7 +1979,7 @@ DictKeysCmd(
static int
DictValuesCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2039,7 +2039,7 @@ DictValuesCmd(
static int
DictSizeCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2078,7 +2078,7 @@ DictSizeCmd(
static int
DictExistsCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2120,7 +2120,7 @@ DictExistsCmd(
static int
DictInfoCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2164,7 +2164,7 @@ DictInfoCmd(
static int
DictIncrCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2285,7 +2285,7 @@ DictIncrCmd(
static int
DictLappendCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2372,7 +2372,7 @@ DictLappendCmd(
static int
DictAppendCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2474,7 +2474,7 @@ DictAppendCmd(
static int
DictForNRCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2670,7 +2670,7 @@ DictForLoopCallback(
static int
DictMapNRCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2883,7 +2883,7 @@ DictMapLoopCallback(
static int
DictSetCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -2943,7 +2943,7 @@ DictSetCmd(
static int
DictUnsetCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -3002,7 +3002,7 @@ DictUnsetCmd(
static int
DictFilterCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -3288,7 +3288,7 @@ DictFilterCmd(
static int
DictUpdateCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
@@ -3447,7 +3447,7 @@ FinalizeDictUpdate(
static int
DictWithCmd(
TCL_UNUSED(void *),
TCL_UNUSED(ClientData),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
+4 -4
View File
@@ -607,7 +607,7 @@ TclNamespaceEnsembleCmd(
cmd = TclGetString(listv[0]);
if (!(cmd[0] == ':' && cmd[1] == ':')) {
Tcl_Obj *newList = TclDuplicatePureObj(
interp, listObj, &tclListType.objType);
interp, listObj, tclListType);
if (!newList) {
if (patchedDict) {
Tcl_DecrRefCount(patchedDict);
@@ -624,7 +624,7 @@ TclNamespaceEnsembleCmd(
&newCmd);
if (patchedDict == NULL) {
patchedDict = TclDuplicatePureObj(
interp, objv[1], &tclListType.objType);
interp, objv[1], tclListType);
if (!patchedDict) {
goto freeMapAndError;
}
@@ -1926,7 +1926,7 @@ NsEnsembleImplementationCmdNR(
if (objc == 2) {
copyPtr = TclDuplicatePureObj(
interp, prefixObj, &tclListType.objType);
interp, prefixObj, tclListType);
if (!copyPtr) {
return TCL_ERROR;
}
@@ -2330,7 +2330,7 @@ EnsembleUnknownCallback(
*/
unknownCmd = TclDuplicatePureObj(
interp, ensemblePtr->unknownHandler, &tclListType.objType);
interp, ensemblePtr->unknownHandler, tclListType);
if (!unknownCmd) {
return TCL_ERROR;
}
+1 -1
View File
@@ -233,7 +233,7 @@ HandleBgErrors(
*/
Tcl_Obj *copyObj = TclDuplicatePureObj(
interp, assocPtr->cmdPrefix, &tclListType.objType);
interp, assocPtr->cmdPrefix, tclListType);
if (!copyObj) {
return;
}
+263 -132
View File
@@ -10,6 +10,7 @@
* Copyright © 2005-2007 Donal K. Fellows.
* Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright © 2006-2008 Joe Mistachkin. All rights reserved.
* Copyright © 2021 Nathan Coulter. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -19,7 +20,6 @@
#include "tclCompile.h"
#include "tclOOInt.h"
#include "tclTomMath.h"
#include "tclArithSeries.h"
#include <math.h>
#include <assert.h>
@@ -451,11 +451,11 @@ VarHashCreateVar(
*/
#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \
((TclHasInternalRep((objPtr), &tclIntType.objType)) \
((TclHasInternalRep((objPtr), tclIntType)) \
? (*(tPtr) = TCL_NUMBER_INT, \
*(ptrPtr) = (void *) \
(&((objPtr)->internalRep.wideValue)), TCL_OK) : \
TclHasInternalRep((objPtr), &tclDoubleType.objType) \
TclHasInternalRep((objPtr), tclDoubleType) \
? (((isnan((objPtr)->internalRep.doubleValue)) \
? (*(tPtr) = TCL_NUMBER_NAN) \
: (*(tPtr) = TCL_NUMBER_DOUBLE)), \
@@ -1481,7 +1481,7 @@ CompileExprObj(
* DupExprCodeInternalRep --
*
* Part of the Tcl object type implementation for Tcl expression
* bytecode. We do not copy the bytecode internalrep. Instead, we return
* bytecode. We do not copy the bytecode intrep. Instead, we return
* without setting copyPtr->typePtr, so the copy is a plain string copy
* of the expression value, and if it is to be used as a compiled
* expression, it will just need a recompile.
@@ -1490,7 +1490,7 @@ CompileExprObj(
* usual (only?) time Tcl_DuplicateObj() will be called is when the copy
* is about to be modified, which would invalidate any copied bytecode
* anyway. The only reason it might make sense to copy the bytecode is if
* we had some modifying routines that operated directly on the internalrep,
* we had some modifying routines that operated directly on the intrep,
* like we do for lists and dicts.
*
* Results:
@@ -3375,7 +3375,7 @@ TEBCresume(
}
if (Tcl_IsShared(objResultPtr)) {
Tcl_Obj *newValue = TclDuplicatePureObj(
interp, objResultPtr, &tclListType.objType);
interp, objResultPtr, tclListType);
if (!newValue) {
TRACE_ERROR(interp);
goto gotError;
@@ -3439,7 +3439,7 @@ TEBCresume(
} else {
if (Tcl_IsShared(objResultPtr)) {
valueToAssign = TclDuplicatePureObj(
interp, objResultPtr, &tclListType.objType);
interp, objResultPtr, tclListType);
if (!valueToAssign) {
goto errorInLappendListPtr;
}
@@ -4638,7 +4638,8 @@ TEBCresume(
*/
{
int numIndices, nocase, match, cflags;
int dstatus, numIndices, nocase, match, cflags,
toIdxAnchor, fromIdxAnchor;
Tcl_Size slength, length2, fromIdx, toIdx, index, s1len, s2len;
const char *s1, *s2;
@@ -4667,65 +4668,79 @@ TEBCresume(
value2Ptr = OBJ_AT_TOS;
valuePtr = OBJ_UNDER_TOS;
TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr)));
if (
TclHasInternalRep(value2Ptr, tclListType)
||
TclObjectHasInterface(value2Ptr, list, length)
) {
Tcl_Size value2Length;
if (Tcl_ListObjLength(interp,value2Ptr,&value2Length),
value2Length == 1) {
if (TclHasInternalRep(value2Ptr, tclListType)) {
value2Ptr = TclListObjGetElement(value2Ptr, 0);
} else {
Tcl_ListObjIndex(interp, value2Ptr, 0, &value2Ptr);
}
} else {
goto TclLindexList;
}
}
if (TclObjectHasInterface(valuePtr, list, length)
|| TclHasInternalRep(valuePtr, tclListType)) {
int code, haveElements = 0, status;
/* special case for ArithSeries */
if (TclHasInternalRep(valuePtr,&tclArithSeriesType.objType)) {
length = ABSTRACTLIST_PROC(valuePtr, lengthProc)(valuePtr);
if (TclGetIntForIndexM(interp, value2Ptr, length-1, &index)!=TCL_OK) {
CACHE_STACK_INFO();
if (TclHasInternalRep(valuePtr, tclListType)) {
/* since the type is tclListtype, this can't fail */
TclListObjGetElementsM(interp, valuePtr, &objc, &objv);
haveElements = 1;
} else {
TclObjectDispatchNoDefault(interp, status, valuePtr, list,
length, interp, valuePtr, &objc);
if (status != TCL_OK) {
CACHE_STACK_INFO();
TRACE_ERROR(interp);
goto gotError;
}
if (objc < 0) {
objc = TCL_SIZE_MAX;
}
}
Tcl_IncrRefCount(value2Ptr);
DECACHE_STACK_INFO();
code = TclGetIntForIndexM(interp, value2Ptr, objc-1, &index);
CACHE_STACK_INFO();
if (code != TCL_OK) {
goto TclLindexList;
}
Tcl_DecrRefCount(value2Ptr);
if (haveElements && code == TCL_OK) {
tosPtr--;
pcAdjustment = 1;
goto lindexFastPath;
}
Tcl_ResetResult(interp);
TclObjectDispatchNoDefault(interp, status, valuePtr, list,
index, interp, valuePtr, index, &objResultPtr);
if (status != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
}
objResultPtr = TclArithSeriesObjIndex(interp, valuePtr, index);
if (objResultPtr == NULL) {
CACHE_STACK_INFO();
TRACE_ERROR(interp);
goto gotError;
TclNewObj(objResultPtr);
}
Tcl_IncrRefCount(objResultPtr); // reference held here
goto lindexDone;
}
}
TclLindexList:
/*
* Extract the desired list element.
*/
{
Tcl_Size value2Length;
Tcl_Obj *indexListPtr = value2Ptr;
if ((TclListObjGetElementsM(interp, valuePtr, &objc, &objv) == TCL_OK)
&& (
!TclHasInternalRep(value2Ptr, &tclListType.objType)
||
((Tcl_ListObjLength(interp,value2Ptr,&value2Length),
value2Length == 1
? (indexListPtr = TclListObjGetElement(value2Ptr, 0), 1)
: 0
))
)
) {
int code;
/* increment the refCount of value2Ptr because TclListObjGetElement may
* have just extracted it from a list in the condition for this block.
*/
Tcl_IncrRefCount(indexListPtr);
DECACHE_STACK_INFO();
code = TclGetIntForIndexM(interp, indexListPtr, objc-1, &index);
TclDecrRefCount(indexListPtr);
CACHE_STACK_INFO();
if (code == TCL_OK) {
Tcl_DecrRefCount(value2Ptr);
tosPtr--;
pcAdjustment = 1;
goto lindexFastPath;
}
Tcl_ResetResult(interp);
}
}
DECACHE_STACK_INFO();
objResultPtr = TclLindexList(interp, valuePtr, value2Ptr);
CACHE_STACK_INFO();
@@ -4753,9 +4768,10 @@ TEBCresume(
opnd = TclGetInt4AtPtr(pc+1);
TRACE(("\"%.30s\" %d => ", O2S(valuePtr), opnd));
/* special case for ArithSeries */
if (TclHasInternalRep(valuePtr,&tclArithSeriesType.objType)) {
length = ABSTRACTLIST_PROC(valuePtr, lengthProc)(valuePtr);
if (TclObjectHasInterface(valuePtr, list, length)) {
TCL_UNUSEDVAR(int status);
TclObjectDispatchNoDefault(interp, status, valuePtr, list,
length, interp, valuePtr, &length);
/* Decode end-offset index values. */
@@ -4763,7 +4779,8 @@ TEBCresume(
/* Compute value @ index */
if (index >= 0 && index < length) {
objResultPtr = TclArithSeriesObjIndex(interp, valuePtr, index);
TclObjectDispatchNoDefault(interp, status, valuePtr, list,
index, interp, valuePtr, index, &objResultPtr);
if (objResultPtr == NULL) {
CACHE_STACK_INFO();
TRACE_ERROR(interp);
@@ -4781,15 +4798,52 @@ TEBCresume(
* in the process.
*/
if (TclListObjGetElementsM(interp, valuePtr, &objc, &objv) != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
if (!TclHasInternalRep(valuePtr, tclListType)
&& TclObjectHasInterface(valuePtr, list, index)) {
if (Tcl_ListObjLength(interp, valuePtr, &objc) != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
}
if (TclIndexIsFromEnd(opnd) && !Tcl_LengthIsFinite(objc)) {
/* end-relative index, and list end is indeterminate */
if (TclObjectDispatchNoDefault(interp, dstatus, valuePtr, list, indexEnd,
interp, valuePtr, index, &objResultPtr) != TCL_OK
|| dstatus != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
}
} else {
index = TclIndexDecode(opnd, TclIndexLast(objc));
if (Tcl_ListObjIndex(interp, valuePtr, index, &objResultPtr)
!= TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
}
}
if (objResultPtr == NULL) {
TclNewObj(objResultPtr);
}
Tcl_IncrRefCount(objResultPtr);
/*
* Stash the list element on the stack.
*/
TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
/* Already has the correct refCount */
NEXT_INST_F(5, 1, -1);
} else {
if (TclListObjGetElementsM(interp, valuePtr, &objc, &objv) != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
}
/* Decode end-offset index values. */
index = TclIndexDecode(opnd, TclIndexLast(objc));
pcAdjustment = 5;
}
/* Decode end-offset index values. */
index = TclIndexDecode(opnd, objc - 1);
pcAdjustment = 5;
lindexFastPath:
if (index >= 0 && index < objc) {
@@ -4956,34 +5010,43 @@ TEBCresume(
TRACE_APPEND(("\"%.30s\"", O2S(objResultPtr)));
NEXT_INST_F(9, 1, 1);
}
toIdx = TclIndexDecode(toIdx, objc - 1);
if (toIdx == TCL_INDEX_NONE) {
goto emptyList;
} else if (toIdx >= objc) {
toIdx = objc - 1;
}
assert (toIdx >= 0 && toIdx < objc);
/*
assert ( fromIdx != TCL_INDEX_NONE );
*
* Extra safety for legacy bytecodes:
*/
if (fromIdx == TCL_INDEX_NONE) {
fromIdx = TCL_INDEX_START;
}
toIdxAnchor = TclIndexIsFromEnd(toIdx);
fromIdxAnchor = TclIndexIsFromEnd(fromIdx);
fromIdx = TclIndexDecode(fromIdx, objc - 1);
if (!Tcl_LengthIsFinite(objc)
&& (toIdxAnchor == 1 || fromIdxAnchor == 1)) {
if (TclHasInternalRep(valuePtr,&tclArithSeriesType.objType)) {
objResultPtr = TclArithSeriesObjRange(interp, valuePtr, fromIdx, toIdx);
toIdx = TclIndexDecode(toIdx, SIZE_MAX);
fromIdx = TclIndexDecode(fromIdx, SIZE_MAX);
dstatus = TclObjectDispatchNoDefault(interp, objResultPtr,
valuePtr, list, rangeEnd, interp, valuePtr, toIdxAnchor,
toIdx, fromIdxAnchor, fromIdx);
if (dstatus != TCL_OK || objResultPtr == NULL) {
goto gotError;
}
} else {
toIdx = TclIndexDecode(toIdx, TclIndexLast(objc));
if (toIdx == TCL_INDEX_NONE) {
goto emptyList;
} else if (Tcl_LengthIsFinite(objc) && toIdx + 1 >= objc + 1) {
toIdx = TclIndexLast(objc);
}
assert (toIdx < objc);
/*
assert ( fromIdx != TCL_INDEX_NONE );
*
* Extra safety for legacy bytecodes:
*/
if (fromIdx == TCL_INDEX_NONE) {
fromIdx = TCL_INDEX_START;
}
fromIdx = TclIndexDecode(fromIdx, objc - 1);
objResultPtr = TclListObjRange(interp, valuePtr, fromIdx, toIdx);
}
if (objResultPtr == NULL) {
TRACE_ERROR(interp);
goto gotError;
}
TRACE_APPEND(("\"%.30s\"", O2S(objResultPtr)));
NEXT_INST_F(9, 1, 1);
@@ -5003,14 +5066,19 @@ TEBCresume(
if (length > 0) {
Tcl_Size i = 0;
Tcl_Obj *o;
int isArithSeries = TclHasInternalRep(value2Ptr,&tclArithSeriesType.objType);
/*
* An empty list doesn't match anything.
*/
do {
if (isArithSeries) {
o = TclArithSeriesObjIndex(NULL, value2Ptr, i);
if (TclObjectHasInterface(valuePtr, list, index)) {
TCL_UNUSEDVAR(int status);
TclObjectDispatchNoDefault(interp, status, value2Ptr, list,
index, interp, value2Ptr, i, &o);
if (!o) {
TRACE_ERROR(interp);
goto gotError;
}
} else {
Tcl_ListObjIndex(NULL, value2Ptr, i, &o);
}
@@ -5023,9 +5091,7 @@ TEBCresume(
if (s1len == s2len) {
match = (memcmp(s1, s2, s1len) == 0);
}
if (isArithSeries) {
TclDecrRefCount(o);
}
TclBounceRefCount(o);
i++;
} while (i < length && match == 0);
}
@@ -5292,39 +5358,46 @@ TEBCresume(
*/
slength = Tcl_GetCharLength(valuePtr);
DECACHE_STACK_INFO();
if (TclGetIntForIndexM(interp, value2Ptr, slength-1, &index)!=TCL_OK) {
CACHE_STACK_INFO();
TRACE_ERROR(interp);
goto gotError;
}
CACHE_STACK_INFO();
if (index < 0 || index >= slength) {
TclNewObj(objResultPtr);
} else if (TclIsPureByteArray(valuePtr)) {
objResultPtr = Tcl_NewByteArrayObj(
Tcl_GetByteArrayFromObj(valuePtr, (Tcl_Size *)NULL)+index, 1);
} else if (valuePtr->bytes && slength == valuePtr->length) {
objResultPtr = Tcl_NewStringObj((const char *)
valuePtr->bytes+index, 1);
if (TclObjectHasInterface(valuePtr, string, index)) {
int status;
status = TclStringIndexInterface(interp, valuePtr, value2Ptr, &objResultPtr);
if (status != TCL_OK) {
goto gotError;
}
} else {
char buf[4] = "";
int ch = Tcl_GetUniChar(valuePtr, index);
DECACHE_STACK_INFO();
if (TclGetIntForIndexM(interp, value2Ptr, slength-1, &index)!=TCL_OK) {
CACHE_STACK_INFO();
TRACE_ERROR(interp);
goto gotError;
}
CACHE_STACK_INFO();
/*
* This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch, 1)
* but creating the object as a string seems to be faster in
* practical use.
*/
if (ch == -1) {
if (index < 0 || index >= slength) {
TclNewObj(objResultPtr);
} else if (TclIsPureByteArray(valuePtr)) {
objResultPtr = Tcl_NewByteArrayObj(
Tcl_GetByteArrayFromObj(valuePtr, NULL)+index, 1);
} else if (valuePtr->bytes && slength == valuePtr->length) {
objResultPtr = Tcl_NewStringObj((const char *)
valuePtr->bytes+index, 1);
} else {
slength = Tcl_UniCharToUtf(ch, buf);
objResultPtr = Tcl_NewStringObj(buf, slength);
char buf[4] = "";
int ch = Tcl_GetUniChar(valuePtr, index);
/*
* This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch, 1)
* but creating the object as a string seems to be faster in
* practical use.
*/
if (ch == -1) {
TclNewObj(objResultPtr);
} else {
slength = Tcl_UniCharToUtf(ch, buf);
objResultPtr = Tcl_NewStringObj(buf, slength);
}
}
}
TRACE_APPEND(("\"%s\"\n", O2S(objResultPtr)));
NEXT_INST_F(1, 2, 1);
@@ -5369,14 +5442,73 @@ TEBCresume(
NEXT_INST_F(9, 0, 0);
}
/* Decode index operands. */
if (TclObjectHasInterface(valuePtr, list, index)) {
if ((TclIndexIsFromEnd(toIdx) || TclIndexIsFromEnd(fromIdx))
&& !Tcl_LengthIsFinite(slength)) {
toIdx = TclIndexDecode(toIdx, slength - 1);
fromIdx = TclIndexDecode(fromIdx, slength - 1);
if (toIdx == TCL_INDEX_NONE) {
TclNewObj(objResultPtr);
fromIdx = TclIndexDecode(fromIdx, TclIndexLast(slength));
toIdx = TclIndexDecode(toIdx, TclIndexLast(slength));
if (TclObjectDispatchNoDefault(interp, objResultPtr, valuePtr,
string, rangeEnd, valuePtr, fromIdx, toIdx) != TCL_OK
|| objResultPtr == NULL) {
TRACE_ERROR(interp);
goto gotError;
}
} else {
fromIdx = TclIndexDecode(fromIdx, TclIndexLast(slength));
toIdx = TclIndexDecode(toIdx, TclIndexLast(slength));
if (TclObjectDispatchNoDefault(interp, objResultPtr, valuePtr,
string, range, valuePtr, fromIdx, toIdx) != TCL_OK
|| objResultPtr == NULL) {
TRACE_ERROR(interp);
goto gotError;
}
}
} else {
objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
/* Decode index operands. */
/*
assert ( toIdx != TCL_INDEX_NONE );
*
* Extra safety for legacy bytecodes:
*/
if (toIdx == TCL_INDEX_NONE) {
goto emptyRange;
}
toIdx = TclIndexDecode(toIdx, slength - 1);
if (toIdx == TCL_INDEX_NONE) {
goto emptyRange;
} else if (toIdx >= slength) {
toIdx = slength - 1;
}
assert ( toIdx != TCL_INDEX_NONE && toIdx < slength );
/*
assert ( fromIdx != TCL_INDEX_NONE );
*
* Extra safety for legacy bytecodes:
*/
if (fromIdx == TCL_INDEX_NONE) {
fromIdx = TCL_INDEX_START;
}
fromIdx = TclIndexDecode(fromIdx, slength - 1);
if (fromIdx == TCL_INDEX_NONE) {
fromIdx = TCL_INDEX_START;
}
if (fromIdx + 1 <= toIdx + 1) {
objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
if (objResultPtr == NULL) {
goto gotError;
}
} else {
emptyRange:
TclNewObj(objResultPtr);
}
}
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
NEXT_INST_F(9, 1, 1);
@@ -6337,7 +6469,7 @@ TEBCresume(
if (Tcl_IsShared(valuePtr)) {
/*
* Here we do some surgery within the Tcl_Obj internals. We want
* to copy the internalrep, but not the string, so we temporarily hide
* to copy the intrep, but not the string, so we temporarily hide
* the string so we do not copy it.
*/
@@ -6362,7 +6494,7 @@ TEBCresume(
case INST_TRY_CVT_TO_BOOLEAN:
valuePtr = OBJ_AT_TOS;
if (TclHasInternalRep(valuePtr, &tclBooleanType.objType)) {
if (TclHasInternalRep(valuePtr, tclBooleanType)) {
objResultPtr = TCONST(1);
} else {
int res = (TclSetBooleanFromAny(NULL, valuePtr) == TCL_OK);
@@ -6430,7 +6562,7 @@ TEBCresume(
}
if (Tcl_IsShared(listPtr)) {
objPtr = TclDuplicatePureObj(
interp, listPtr, &tclListType.objType);
interp, listPtr, tclListType);
if (!objPtr) {
goto gotError;
}
@@ -6515,7 +6647,6 @@ TEBCresume(
goto gotError;
}
valIndex = (iterNum * numVars);
for (j = 0; j < numVars; j++) {
if (valIndex >= listLen) {
@@ -7044,7 +7175,7 @@ TEBCresume(
/*
* dictPtr is no longer on the stack, and we're not
* moving it into the internalrep of an iterator. We need
* moving it into the intrep of an iterator. We need
* to drop the refcount [Tcl Bug 9b352768e6].
*/
@@ -8392,7 +8523,7 @@ ExecuteExtendedBinaryMathOp(
overflowExpon:
if ((TclGetWideIntFromObj(NULL, value2Ptr, &w2) != TCL_OK)
|| (value2Ptr->typePtr != &tclIntType.objType)
|| (value2Ptr->typePtr != tclIntType)
|| (Tcl_WideUInt)w2 >= (1<<28)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"exponent too large", -1));
+1 -1
View File
@@ -380,7 +380,7 @@ ExecuteCallback(
Tcl_InterpState state = NULL;
int res = TCL_OK;
Tcl_Obj *command = TclDuplicatePureObj(
interp, dataPtr->command, &tclListType.objType);
interp, dataPtr->command, tclListType);
if (!command) {
return TCL_ERROR;
}
+2 -2
View File
@@ -2261,7 +2261,7 @@ NewReflectedChannel(
rcPtr->mode = mode;
rcPtr->interest = 0; /* Initially no interest registered */
rcPtr->cmd = TclDuplicatePureObj(interp, cmdpfxObj, &tclListType.objType);
rcPtr->cmd = TclDuplicatePureObj(interp, cmdpfxObj, tclListType);
if (!rcPtr->cmd) {
return NULL;
}
@@ -2401,7 +2401,7 @@ InvokeTclMethod(
* before the channel id.
*/
cmd = TclDuplicatePureObj(NULL, rcPtr->cmd, &tclListType.objType);
cmd = TclDuplicatePureObj(NULL, rcPtr->cmd, tclListType);
if (!cmd) {
return TCL_ERROR;
}
+267 -47
View File
@@ -11,6 +11,7 @@
* Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved.
* Copyright (c) 2008 by Miguel Sofer. All rights reserved.
* Copyright (c) 2021 by Nathan Coulter. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -46,10 +47,13 @@
#if defined(__cplusplus)
# define TCL_UNUSED(T) T
# define TCL_UNUSEDVAR(T) T
#elif defined(__GNUC__) && (__GNUC__ > 2)
# define TCL_UNUSED(T) T JOIN(dummy, __LINE__) __attribute__((unused))
# define TCL_UNUSEDVAR(T) T __attribute__((unused))
#else
# define TCL_UNUSED(T) T JOIN(dummy, __LINE__)
# define TCL_UNUSEDVAR(T) T
#endif
/*
@@ -206,6 +210,223 @@ typedef struct Tcl_ResolverInfo {
#define TCL_AVOID_RESOLVERS 0x40000
/*
*----------------------------------------------------------------
* Object type
*----------------------------------------------------------------
*/
/* version is a pointer so that it can be overridden if ever needed */
typedef struct TclObjectTypeType {
int *version;
} TclObjectTypeType;
/* keep this structure in sync with Tcl_ObjType */
typedef struct ObjectType {
const char *name; /* Name of the type, e.g. "int". */
Tcl_FreeInternalRepProc *freeIntRepProc;
/* Called to free any storage for the type's
* internal rep. NULL if the internal rep does
* not need freeing. */
Tcl_DupInternalRepProc *dupIntRepProc;
/* Called to create a new object as a copy of
* an existing object. */
Tcl_UpdateStringProc *updateStringProc;
/* Called to update the string rep from the
* type's internal representation. */
Tcl_SetFromAnyProc *setFromAnyProc;
/* Called to convert the object's internal rep
* to this type. Frees the internal rep of the
* old type. Returns TCL_ERROR on failure. */
int version;
Tcl_ObjInterface *interface;
} ObjectType;
#define TclObjectInterfaceCall(objPtr, iface, proc, ...) \
((ObjInterface *)((ObjectType *)(objPtr)->typePtr)->interface) \
->iface.proc(__VA_ARGS__)
#define TclObjectDispatch(objPtr, default, iface, proc, ...) \
TclObjectHasInterface((objPtr), iface, proc) \
? TclObjectInterfaceCall(objPtr, iface, proc, __VA_ARGS__) \
: default(__VA_ARGS__)
#define TclObjectDispatchNoDefault(interp, res, objPtr, iface, proc, ...) \
(TclObjectHasInterface((objPtr), iface, proc) \
? (res = TclObjectInterfaceCall((objPtr), iface, proc, __VA_ARGS__), \
TCL_OK) \
: (Tcl_SetObjResult((interp), \
Tcl_ObjPrintf("interface not provided interface %s proc %s" \
, #iface, #proc )), TCL_ERROR))
#define TclObjectHasInterface(objPtr, iface, proc) \
((objPtr)->typePtr != NULL \
&& (objPtr)->typePtr->version == 2 \
&& ((ObjInterface *)((ObjectType *)(objPtr)->typePtr)->interface) \
->iface.proc != NULL)
/*
*----------------------------------------------------------------
* Object interface data structures and macros
*----------------------------------------------------------------
*/
#define tclObjTypeInterfaceArgsListAll \
Tcl_Interp *interp, /* Used to report errors if not NULL. */ \
Tcl_Obj *listPtr, /* List object for which an element array \
* is to be returned. */ \
Tcl_Size *objcPtr, /* Where to store the count of objects \
* referenced by objv. */ \
Tcl_Obj ***objvPtr /* Where to store the pointer to an \
* array of */
#define tclObjTypeInterfaceArgsListAppend \
Tcl_Interp *interp, /* Used to report errors if not NULL. */ \
Tcl_Obj *listPtr, /* List object to append objPtr to. */ \
Tcl_Obj *objPtr /* Object to append to listPtr's list. */
#define tclObjTypeInterfaceArgsListAppendList \
Tcl_Interp *interp, /* Used to report errors if not NULL. */ \
Tcl_Obj *listPtr, /* List object to append elements to. */ \
Tcl_Obj *elemListPtr /* List obj with elements to append. */
#define tclObjTypeInterfaceArgsListIndex \
Tcl_Interp *interp, /* Used to report errors if not NULL. */ \
Tcl_Obj *listPtr, /* List object to index into. */ \
Tcl_Size index, /* Index of element to return. */ \
Tcl_Obj **objPtrPtr /* The resulting Tcl_Obj* is stored here. */
#define tclObjTypeInterfaceArgsListIndexEnd \
Tcl_Interp *interp, /* Used to report errors if not NULL. */ \
Tcl_Obj *listPtr, /* List object to index into. */ \
Tcl_Size index, /* Index of element to return. */ \
Tcl_Obj **objPtrPtr /* The resulting Tcl_Obj* is stored here. */
#define tclObjTypeInterfaceArgsListIsSorted \
Tcl_Interp * interp, /* Used to report errors */ \
Tcl_Obj *listPtr, /* The list in question */ \
size_t flags /* flags */
#define tclObjTypeInterfaceArgsListLength \
Tcl_Interp *interp, /* Used to report errors if not NULL. */ \
Tcl_Obj *listPtr, /* List object whose #elements to return. */ \
Tcl_Size *lenPtr /* The resulting length is stored here. */
#define tclObjTypeInterfaceArgsListRange \
Tcl_Interp * interp, /* Used to report errors */ \
Tcl_Obj *listObj, /* List object to take a range from. */ \
Tcl_Size rangeStart, /* Index of first element to */ \
/* include. */ \
Tcl_Size rangeEnd /* Index of last element to include. */
#define tclObjTypeInterfaceArgsListRangeEnd \
Tcl_Interp * interp, /* Used to report errors */ \
Tcl_Obj *listPtr, /* List object to take a range from. */ \
Tcl_Size fromAnchor,/* 0 for start and 1 for end */ \
Tcl_Size fromIdx, /* Index of first element to include. */ \
Tcl_Size toAnchor, /* 0 for start and 1 for end */ \
Tcl_Size toIdx /* Index of last element to include. */
#define tclObjTypeInterfaceArgsListReplace \
Tcl_Interp *interp, /* Used for error reporting if not NULL. */ \
Tcl_Obj *listObj, /* List object whose elements to replace. */ \
Tcl_Size first, /* Index of first element to replace. */ \
Tcl_Size numToDelete, /* Number of elements to replace. */ \
Tcl_Size numToInsert, /* Number of objects to insert. */ \
/* An array of objc pointers to Tcl \
* objects to insert. */ \
Tcl_Obj *const insertObjs[]
#define tclObjTypeInterfaceArgsListReplaceList \
Tcl_Interp *interp, /* Used for error reporting if not NULL. */ \
Tcl_Obj *listPtr, /* List object whose elements to replace. */ \
Tcl_Size first, /* Index of first element to replace. */ \
Tcl_Size count, /* Number of elements to replace. */ \
Tcl_Obj *newItemsPtr /* a list of new items to insert */
#define tclObjTypeInterfaceArgsListReverse \
Tcl_Interp *interp, /* Used for error reporting if not NULL. */ \
Tcl_Obj *listPtr /* List object whose elements to replace. */ \
#define tclObjTypeInterfaceArgsListSet \
Tcl_Interp *interp, /* Tcl interpreter; used for error reporting \
* if not NULL. */ \
Tcl_Obj *listObj, /* List object in which element should be \
* stored. */ \
Tcl_Size index, /* Index of element to store. */ \
Tcl_Obj *valueObj /* Tcl object to store in the designated list \
* element. */
#define tclObjTypeInterfaceArgsListSetList \
Tcl_Interp *interp, /* Tcl interpreter. */ \
Tcl_Obj *listObj, /* Pointer to the list being modified. */ \
Tcl_Size indexCount, /* Number of index args. */ \
Tcl_Obj *const indexArray[], /* Index args. */ \
Tcl_Obj *valueObj /* Value arg to 'lset' or NULL to 'lpop'. */
#define tclObjTypeInterfaceArgsStringIndex \
Tcl_Interp *interp, \
Tcl_Obj *objPtr, \
Tcl_Size index, \
Tcl_Obj **objPtrPtr /* The resulting Tcl_Obj* is stored here. */
#define tclObjTypeInterfaceArgsStringIndexEnd \
Tcl_Interp *interp, \
Tcl_Obj *objPtr, \
Tcl_Size index, \
Tcl_Obj **objPtrPtr /* The resulting Tcl_Obj* is stored here. */
#define tclObjTypeInterfaceArgsStringLength \
Tcl_Obj *objPtr
#define tclObjTypeInterfaceArgsStringRange \
Tcl_Obj *objPtr, /* The Tcl object to find the range of. */ \
Tcl_Size first, /* First index of the range. */ \
Tcl_Size last /* Last index of the range. */
#define tclObjTypeInterfaceArgsStringRangeEnd \
Tcl_Obj *objPtr, /* The Tcl object to find the range of. */ \
Tcl_Size first, /* First index of the range. */ \
Tcl_Size last /* Last index of the range. */
typedef struct ObjInterface {
int version;
struct string {
int (*index)(tclObjTypeInterfaceArgsStringIndex);
int (*indexEnd)(tclObjTypeInterfaceArgsStringIndexEnd);
Tcl_Size (*length)(tclObjTypeInterfaceArgsStringLength);
Tcl_Obj* (*range)(tclObjTypeInterfaceArgsStringRange);
Tcl_Obj* (*rangeEnd)(tclObjTypeInterfaceArgsStringRangeEnd);
} string;
struct list {
int (*all)(tclObjTypeInterfaceArgsListAll);
int (*append)(tclObjTypeInterfaceArgsListAppend);
int (*appendlist)(tclObjTypeInterfaceArgsListAppendList);
int (*index)(tclObjTypeInterfaceArgsListIndex);
int (*indexEnd)(tclObjTypeInterfaceArgsListIndexEnd);
int (*isSorted)(tclObjTypeInterfaceArgsListIsSorted);
int (*length)(tclObjTypeInterfaceArgsListLength);
Tcl_Obj* (*range)(tclObjTypeInterfaceArgsListRange);
Tcl_Obj* (*rangeEnd)(tclObjTypeInterfaceArgsListRangeEnd);
int (*replace)(tclObjTypeInterfaceArgsListReplace);
int (*replaceList)(tclObjTypeInterfaceArgsListReplaceList);
Tcl_Obj* (*reverse)(tclObjTypeInterfaceArgsListReverse);
int (*set)(tclObjTypeInterfaceArgsListSet);
Tcl_Obj * (*setlist)(tclObjTypeInterfaceArgsListSetList);
} list;
} ObjInterface;
/*
*----------------------------------------------------------------
* Data structures related to namespaces.
@@ -1071,20 +1292,6 @@ typedef struct ActiveInterpTrace {
#define TCL_TRACE_ENTER_EXEC 1
#define TCL_TRACE_LEAVE_EXEC 2
typedef struct { /* For internal core use only */
Tcl_ObjType objType;
struct {
Tcl_Size (*lengthProc)(Tcl_Obj *obj);
} abstractList;
} TclObjTypeWithAbstractList;
#define TCL_OBJTYPE_V0_1(lengthProc) (sizeof(TclObjTypeWithAbstractList)) \
}, {lengthProc /* For internal core use only */
#define ABSTRACTLIST_PROC(objPtr, proc) (((objPtr)->typePtr \
&& ((objPtr)->typePtr->version > offsetof(TclObjTypeWithAbstractList, abstractList.proc))) ? \
((const TclObjTypeWithAbstractList *)(objPtr)->typePtr)->abstractList.proc : NULL)
MODULE_SCOPE Tcl_Size TclLengthOne(Tcl_Obj *);
/*
* The structure below defines an entry in the assocData hash table which is
* associated with an interpreter. The entry contains a pointer to a function
@@ -2407,6 +2614,7 @@ typedef enum TclEolTranslation {
#define TCL_INVOKE_NO_UNKNOWN (1<<1)
#define TCL_INVOKE_NO_TRACEBACK (1<<2)
/*
* ListStore --
*
@@ -2575,10 +2783,10 @@ typedef struct ListRep {
* converted to a list.
*/
#define TclListObjGetElementsM(interp_, listObj_, objcPtr_, objvPtr_) \
(((listObj_)->typePtr == &tclListType.objType) \
? ((ListObjGetElements((listObj_), *(objcPtr_), *(objvPtr_))), \
TCL_OK) \
: Tcl_ListObjGetElements( \
(((listObj_)->typePtr == tclListType) \
? ((ListObjGetElements((listObj_), *(objcPtr_), *(objvPtr_))), \
TCL_OK) \
: Tcl_ListObjGetElements( \
(interp_), (listObj_), (objcPtr_), (objvPtr_)))
/*
@@ -2586,13 +2794,14 @@ typedef struct ListRep {
* count in lenPtr_. Returns TCL_OK on success or TCL_ERROR if the
* Tcl_Obj cannot be converted to a list.
*/
#define TclListObjLengthM(interp_, listObj_, lenPtr_) \
(((listObj_)->typePtr == &tclListType.objType) \
? ((ListObjLength((listObj_), *(lenPtr_))), TCL_OK) \
#define TclListObjLengthM(interp_, listObj_, lenPtr_) \
(((listObj_)->typePtr == tclListType) \
? ((ListObjLength((listObj_), *(lenPtr_))), TCL_OK) \
: Tcl_ListObjLength((interp_), (listObj_), (lenPtr_)))
#define TclListObjIsCanonical(listObj_) \
(((listObj_)->typePtr == &tclListType.objType) ? ListObjIsCanonical((listObj_)) : 0)
#define TclListObjIsCanonical(listObj_) \
(((listObj_)->typePtr == tclListType) \
? ListObjIsCanonical((listObj_)) : 0)
/*
* Modes for collecting (or not) in the implementations of TclNRForeachCmd,
@@ -2611,19 +2820,19 @@ typedef struct ListRep {
*/
#define TclGetBooleanFromObj(interp, objPtr, intPtr) \
(((objPtr)->typePtr == &tclIntType.objType \
|| (objPtr)->typePtr == &tclBooleanType.objType) \
(((objPtr)->typePtr == tclIntType \
|| (objPtr)->typePtr == tclBooleanType) \
? (*(intPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK) \
: Tcl_GetBooleanFromObj((interp), (objPtr), (intPtr)))
#ifdef TCL_WIDE_INT_IS_LONG
#define TclGetLongFromObj(interp, objPtr, longPtr) \
(((objPtr)->typePtr == &tclIntType.objType) \
(((objPtr)->typePtr == tclIntType) \
? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \
: Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
#else
#define TclGetLongFromObj(interp, objPtr, longPtr) \
(((objPtr)->typePtr == &tclIntType.objType \
(((objPtr)->typePtr == tclIntType \
&& (objPtr)->internalRep.wideValue >= (Tcl_WideInt)(LONG_MIN) \
&& (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(LONG_MAX)) \
? ((*(longPtr) = (long)(objPtr)->internalRep.wideValue), TCL_OK) \
@@ -2631,13 +2840,13 @@ typedef struct ListRep {
#endif
#define TclGetIntFromObj(interp, objPtr, intPtr) \
(((objPtr)->typePtr == &tclIntType.objType \
(((objPtr)->typePtr == tclIntType \
&& (objPtr)->internalRep.wideValue >= (Tcl_WideInt)(INT_MIN) \
&& (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(INT_MAX)) \
? ((*(intPtr) = (int)(objPtr)->internalRep.wideValue), TCL_OK) \
: Tcl_GetIntFromObj((interp), (objPtr), (intPtr)))
#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
((((objPtr)->typePtr == &tclIntType.objType) && ((objPtr)->internalRep.wideValue >= 0) \
((((objPtr)->typePtr == tclIntType) && ((objPtr)->internalRep.wideValue >= 0) \
&& ((objPtr)->internalRep.wideValue <= endValue)) \
? ((*(idxPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \
: Tcl_GetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))
@@ -2651,7 +2860,7 @@ typedef struct ListRep {
*/
#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
(((objPtr)->typePtr == &tclIntType.objType) \
(((objPtr)->typePtr == tclIntType) \
? (*(wideIntPtr) = \
((objPtr)->internalRep.wideValue), TCL_OK) : \
Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
@@ -2926,13 +3135,13 @@ MODULE_SCOPE void *tclTimeClientData;
* Variables denoting the Tcl object types defined in the core.
*/
MODULE_SCOPE const TclObjTypeWithAbstractList tclBignumType;
MODULE_SCOPE const TclObjTypeWithAbstractList tclBooleanType;
MODULE_SCOPE const Tcl_ObjType *tclBignumType;
MODULE_SCOPE const Tcl_ObjType *tclBooleanType;
MODULE_SCOPE const Tcl_ObjType tclByteCodeType;
MODULE_SCOPE const TclObjTypeWithAbstractList tclDoubleType;
MODULE_SCOPE const TclObjTypeWithAbstractList tclIntType;
MODULE_SCOPE const TclObjTypeWithAbstractList tclListType;
MODULE_SCOPE const TclObjTypeWithAbstractList tclArithSeriesType;
MODULE_SCOPE const Tcl_ObjType *tclDoubleType;
MODULE_SCOPE const Tcl_ObjType *tclIntType;
MODULE_SCOPE const Tcl_ObjType *tclListType;
MODULE_SCOPE const Tcl_ObjType *tclArithSeriesType;
MODULE_SCOPE const Tcl_ObjType tclDictType;
MODULE_SCOPE const Tcl_ObjType tclProcBodyType;
MODULE_SCOPE const Tcl_ObjType tclStringType;
@@ -3098,6 +3307,7 @@ MODULE_SCOPE int TclAsyncNotifier(int sigNumber, Tcl_ThreadId threadId,
void *clientData, int *flagPtr, int value);
MODULE_SCOPE void TclAsyncMarkFromNotifier(void);
MODULE_SCOPE double TclBignumToDouble(const void *bignum);
MODULE_SCOPE void TclBounceRefCount(Tcl_Obj *objPtr);
MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string,
Tcl_Size strLen, const unsigned char *pattern,
Tcl_Size ptnLen, int flags);
@@ -3131,7 +3341,6 @@ MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp,
Tcl_Namespace *ensembleNamespacePtr, int flags);
MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr);
MODULE_SCOPE void TclDeleteNamespaceChildren(Namespace *nsPtr);
MODULE_SCOPE Tcl_Size TclDictGetSize(Tcl_Obj *dictPtr);
MODULE_SCOPE Tcl_Obj* TclDuplicatePureObj(Tcl_Interp *interp,
Tcl_Obj * objPtr, const Tcl_ObjType *typPtr);
MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp,
@@ -3222,6 +3431,8 @@ MODULE_SCOPE int TclGetLoadedLibraries(Tcl_Interp *interp,
const char *packageName);
MODULE_SCOPE int TclGetWideBitsFromObj(Tcl_Interp *, Tcl_Obj *,
Tcl_WideInt *);
MODULE_SCOPE int TclIndexIsFromEnd(Tcl_Size encoded);
MODULE_SCOPE Tcl_Size TclIndexLast (Tcl_Size N);
MODULE_SCOPE int TclIncrObj(Tcl_Interp *interp, Tcl_Obj *valuePtr,
Tcl_Obj *incrPtr);
MODULE_SCOPE Tcl_Obj * TclIncrObjVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
@@ -3261,9 +3472,12 @@ MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp,
MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
Tcl_Size indexCount, Tcl_Obj *const indexArray[]);
MODULE_SCOPE Tcl_Obj * TclListObjGetElement(Tcl_Obj *listObj, Tcl_Size index);
MODULE_SCOPE int Tcl_LengthIsFinite(Tcl_Size length);
/* TIP #280 */
MODULE_SCOPE void TclListLines(Tcl_Obj *listObj, Tcl_Size line, int n,
int *lines, Tcl_Obj *const *elems);
MODULE_SCOPE int (*TclObjInterfaceGetListIndex (Tcl_Obj *objPtr))
(tclObjTypeInterfaceArgsListIndex);
MODULE_SCOPE int TclListObjAppendElements(Tcl_Interp *interp,
Tcl_Obj *toObj, Tcl_Size elemCount,
Tcl_Obj *const elemObjv[]);
@@ -3271,9 +3485,9 @@ MODULE_SCOPE Tcl_Obj * TclListObjRange(Tcl_Interp *interp, Tcl_Obj *listPtr,
Tcl_Size fromIdx, Tcl_Size toIdx);
MODULE_SCOPE Tcl_Obj * TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr,
Tcl_Obj *indexPtr, Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Obj * TclLsetFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
Tcl_Size indexCount, Tcl_Obj *const indexArray[],
Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Obj * TclLsetFlat(tclObjTypeInterfaceArgsListSetList);
MODULE_SCOPE Tcl_Obj * TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr,
Tcl_Obj *indexPtr, Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name,
const EnsembleImplMap map[]);
MODULE_SCOPE int TclMakeSafe(Tcl_Interp *interp);
@@ -3287,6 +3501,8 @@ MODULE_SCOPE int TclNokia770Doubles(void);
MODULE_SCOPE void TclNsDecrRefCount(Namespace *nsPtr);
MODULE_SCOPE int TclNamespaceDeleted(Namespace *nsPtr);
MODULE_SCOPE Tcl_Obj * TclObjGetScalar(Tcl_Obj *objPtr);
MODULE_SCOPE const char * TclObjTypeName(const Tcl_ObjType *typePtr);
MODULE_SCOPE int TclObjTypeVersion (const Tcl_ObjType *typePtr);
MODULE_SCOPE void TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, const char *operation,
const char *reason, int index);
@@ -3368,6 +3584,7 @@ MODULE_SCOPE Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
MODULE_SCOPE Tcl_Obj * TclpObjLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr,
int linkType);
MODULE_SCOPE int TclpObjChdir(Tcl_Obj *pathPtr);
MODULE_SCOPE void Tcl_ObjTypeVersion(Tcl_Obj *objPtr, int *version);
MODULE_SCOPE Tcl_Channel TclpOpenTemporaryFile(Tcl_Obj *dirObj,
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
Tcl_Obj *resultingNameObj);
@@ -3415,6 +3632,8 @@ MODULE_SCOPE int TclStringCmp(Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr,
MODULE_SCOPE int TclStringCmpOpts(Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[], int *nocase,
Tcl_Size *reqlength);
MODULE_SCOPE int TclStringIndexInterface(Tcl_Interp *interp, Tcl_Obj *objPtr,
Tcl_Obj *indexPtr, Tcl_Obj **charPtr);
MODULE_SCOPE int TclStringMatch(const char *str, Tcl_Size strLen,
const char *pattern, int ptnLen, int flags);
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
@@ -3440,6 +3659,7 @@ MODULE_SCOPE const char*TclGetCommandTypeName(Tcl_Command command);
MODULE_SCOPE void TclRegisterCommandTypeName(
Tcl_ObjCmdProc *implementationProc,
const char *nameStr);
MODULE_SCOPE void TclUndoRefCount(Tcl_Obj *objPtr);
MODULE_SCOPE int TclUtfCmp(const char *cs, const char *ct);
MODULE_SCOPE int TclUtfCasecmp(const char *cs, const char *ct);
MODULE_SCOPE int TclUtfCount(int ch);
@@ -4822,8 +5042,8 @@ MODULE_SCOPE Tcl_LibraryInitProc TclObjTest_Init;
MODULE_SCOPE Tcl_LibraryInitProc TclThread_Init;
MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_Init;
MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit;
MODULE_SCOPE Tcl_LibraryInitProc TcltestObjectInterfaceInit;
MODULE_SCOPE Tcl_LibraryInitProc TcltestObjectInterfaceListIntegerInit;
/*
*----------------------------------------------------------------
@@ -4854,7 +5074,7 @@ MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit;
Tcl_ObjInternalRep ir; \
ir.wideValue = (Tcl_WideInt) i; \
TclInvalidateStringRep(objPtr); \
Tcl_StoreInternalRep(objPtr, &tclIntType.objType, &ir); \
Tcl_StoreInternalRep(objPtr, tclIntType, &ir); \
} while (0)
#define TclSetDoubleObj(objPtr, d) \
@@ -4862,7 +5082,7 @@ MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit;
Tcl_ObjInternalRep ir; \
ir.doubleValue = (double) d; \
TclInvalidateStringRep(objPtr); \
Tcl_StoreInternalRep(objPtr, &tclDoubleType.objType, &ir); \
Tcl_StoreInternalRep(objPtr, tclDoubleType, &ir); \
} while (0)
/*
@@ -4887,7 +5107,7 @@ MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit;
(objPtr)->refCount = 0; \
(objPtr)->bytes = NULL; \
(objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \
(objPtr)->typePtr = &tclIntType.objType; \
(objPtr)->typePtr = tclIntType; \
TCL_DTRACE_OBJ_CREATE(objPtr); \
} while (0)
@@ -4906,7 +5126,7 @@ MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit;
TclSetBignumInternalRep((objPtr), &bignumValue_); \
} else { \
(objPtr)->internalRep.wideValue = (Tcl_WideInt)(uw_); \
(objPtr)->typePtr = &tclIntType.objType; \
(objPtr)->typePtr = tclIntType; \
} \
TCL_DTRACE_OBJ_CREATE(objPtr); \
} while (0)
@@ -4921,7 +5141,7 @@ MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit;
(objPtr)->refCount = 0; \
(objPtr)->bytes = NULL; \
(objPtr)->internalRep.doubleValue = (double)(d); \
(objPtr)->typePtr = &tclDoubleType.objType; \
(objPtr)->typePtr = tclDoubleType; \
TCL_DTRACE_OBJ_CREATE(objPtr); \
} while (0)
+1 -1
View File
@@ -531,7 +531,7 @@ GetDouble(
return 0;
} else {
#ifdef ACCEPT_NAN
Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &tclDoubleType.objType);
Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, tclDoubleType);
if (irPtr != NULL) {
*dblPtr = irPtr->doubleValue;
+382 -182
View File
@@ -4,6 +4,7 @@
* This file contains functions that implement the Tcl list object type.
*
* Copyright © 2022 Ashok P. Nadkarni. All rights reserved.
* Copyright © 2021 Nathan Coulter. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -12,7 +13,6 @@
#include <assert.h>
#include "tclInt.h"
#include "tclTomMath.h"
#include "tclArithSeries.h"
/*
* TODO - memmove is fast. Measure at what size we should prefer memmove
@@ -69,7 +69,7 @@
/* Checks for when caller should have already converted to internal list type */
#define LIST_ASSERT_TYPE(listObj_) \
LIST_ASSERT(TclHasInternalRep((listObj_), &tclListType.objType))
LIST_ASSERT(TclHasInternalRep((listObj_), tclListType))
/*
* If ENABLE_LIST_INVARIANTS is enabled (-DENABLE_LIST_INVARIANTS from the
@@ -142,7 +142,17 @@ static void DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void FreeListInternalRep(Tcl_Obj *listPtr);
static int SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void UpdateStringOfList(Tcl_Obj *listPtr);
static Tcl_Size ListLength(Tcl_Obj *listPtr);
static int ListObjAppendElement(Tcl_Interp *interp,
Tcl_Obj *listPtr, Tcl_Obj *objPtr);
static int ListObjAppendList(Tcl_Interp *interp,
Tcl_Obj *listPtr, Tcl_Obj *elemListPtr);
static int ListObjIndex(tclObjTypeInterfaceArgsListIndex);
static int ListObjInterfaceGetElements(tclObjTypeInterfaceArgsListAll);
static int ListObjInterfaceLength(tclObjTypeInterfaceArgsListLength);
static int ListObjSetElement(tclObjTypeInterfaceArgsListSet);
static Tcl_Obj * LsetFlat(tclObjTypeInterfaceArgsListSetList);
static Tcl_Obj * ListObjRange(tclObjTypeInterfaceArgsListRange);
static int ListObjReplace(tclObjTypeInterfaceArgsListReplace);
/*
* The structure below defines the list Tcl object type by means of functions
@@ -151,18 +161,65 @@ static Tcl_Size ListLength(Tcl_Obj *listPtr);
* The internal representation of a list object is ListRep defined in tcl.h.
*/
const TclObjTypeWithAbstractList tclListType = {
{"list", /* name */
ObjInterface tclListInterface = {
1,
{},
{
&ListObjInterfaceGetElements,
&ListObjAppendElement,
&ListObjAppendList,
&ListObjIndex,
NULL,
NULL,
&ListObjInterfaceLength,
&ListObjRange,
NULL,
&ListObjReplace,
NULL, /* replaceList */
NULL, /* reverse */
&ListObjSetElement,
&LsetFlat
},
};
const ObjectType tclListObjType = {
"list",
FreeListInternalRep, /* freeIntRepProc */
DupListInternalRep, /* dupIntRepProc */
UpdateStringOfList, /* updateStringProc */
SetListFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0_1(
ListLength
)}
SetListFromAny, /* setFromAnyProc */
2,
(Tcl_ObjInterface *)&tclListInterface
};
MODULE_SCOPE const Tcl_ObjType *tclListType = (Tcl_ObjType *)&tclListObjType;
/* Macros to manipulate the List internal rep */
#define ListSetIntRep(objPtr, listRepPtr) \
do { \
Tcl_ObjInternalRep ir; \
ir.twoPtrValue.ptr1 = (listRepPtr); \
ir.twoPtrValue.ptr2 = NULL; \
(listRepPtr)->refCount++; \
Tcl_StoreInternalRep((objPtr), tclListType, &ir); \
} while (0)
#define ListGetIntRep(objPtr, listRepPtr) \
do { \
const Tcl_ObjInternalRep *irPtr; \
irPtr = TclFetchInternalRep((objPtr), tclListType); \
(listRepPtr) = irPtr ? (List *)irPtr->twoPtrValue.ptr1 : NULL; \
} while (0)
#define ListResetIntRep(objPtr, listRepPtr) \
TclFetchInternalRep((objPtr), tclListType)->twoPtrValue.ptr1 = (listRepPtr)
#ifndef TCL_MIN_ELEMENT_GROWTH
#define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *)
#endif
#define ListRepIncrRefs(repPtr_) \
do { \
(repPtr_)->storePtr->refCount++; \
@@ -205,7 +262,7 @@ const TclObjTypeWithAbstractList tclListType = {
do { \
(objPtr_)->internalRep.twoPtrValue.ptr1 = (repPtr_)->storePtr; \
(objPtr_)->internalRep.twoPtrValue.ptr2 = (repPtr_)->spanPtr; \
(objPtr_)->typePtr = &tclListType.objType; \
(objPtr_)->typePtr = tclListType; \
} while (0)
#define ListObjOverwriteRep(objPtr_, repPtr_) \
@@ -1251,7 +1308,7 @@ TclListObjGetRep(
* to be returned. */
ListRep *repPtr) /* Location to store descriptor */
{
if (!TclHasInternalRep(listObj, &tclListType.objType)) {
if (!TclHasInternalRep(listObj, tclListType)) {
int result;
result = SetListFromAny(interp, listObj);
if (result != TCL_OK) {
@@ -1529,13 +1586,39 @@ ListRepRange(
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclListObjRange(
Tcl_Interp *interp, /* May be NULL. Used for error messages */
Tcl_Obj *listObj, /* List object to take a range from. */
Tcl_Size rangeStart, /* Index of first element to include. */
Tcl_Size rangeEnd) /* Index of last element to include. */
Tcl_Interp *interp,
Tcl_Obj *listPtr, /* List object to take a range from. */
Tcl_Size fromIdx, /* Index of first element to include. */
Tcl_Size toIdx) /* Index of last element to include. */
{
int status;
Tcl_Size length;
status = TclListObjLengthM(interp, listPtr, &length);
if (status != TCL_OK) {
return NULL;
}
if (fromIdx == TCL_INDEX_NONE) {
fromIdx = 0;
}
if (Tcl_LengthIsFinite(length) && toIdx + 1 >= length + 1) {
toIdx = length-1;
}
if (fromIdx + 1 > toIdx + 1) {
Tcl_Obj *obj;
TclNewObj(obj);
return obj;
}
return TclObjectDispatch(listPtr, ListObjRange, list
, range, interp, listPtr, fromIdx, toIdx);
}
Tcl_Obj *
ListObjRange(
tclObjTypeInterfaceArgsListRange)
{
ListRep listRep;
ListRep resultRep;
@@ -1608,25 +1691,49 @@ TclListObjGetElement(
*
*----------------------------------------------------------------------
*/
/*
*----------------------------------------------------------------------
*
* Tcl_ListObjGetElements --
*
* Returns an (objc,objv) array of the elements in a list
* object.
*
* Results:
* The return value is normally TCL_OK; in this case *objcPtr is set to
* the count of list elements and *objvPtr is set to a pointer to an
* array of (*objcPtr) pointers to each list element. If listPtr does not
* refer to a list object and the object can not be converted to one,
* TCL_ERROR is returned and an error message will be left in the
* interpreter's result if interp is not NULL.
*
* The objects referenced by the returned array should be treated as
* readonly and their ref counts are _not_ incremented; the caller must
* do that if it holds on to a reference. Furthermore, the pointer and
* length returned by this function may change as soon as any function is
* called on the list object; be careful about retaining the pointer in a
* local data structure.
*
* Side effects:
* The possible conversion of the object referenced by listPtr
* to a list object.
*
*----------------------------------------------------------------------
*/
#undef Tcl_ListObjGetElements
int
Tcl_ListObjGetElements(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
Tcl_Obj *objPtr, /* List object for which an element array is
* to be returned. */
Tcl_Size *objcPtr, /* Where to store the count of objects
* referenced by objv. */
Tcl_Obj ***objvPtr) /* Where to store the pointer to an array of
* pointers to the list's objects. */
Tcl_ListObjGetElements(tclObjTypeInterfaceArgsListAll)
{
return TclObjectDispatch(listPtr, ListObjInterfaceGetElements,
list, all, interp, listPtr, objcPtr, objvPtr);
}
int
ListObjInterfaceGetElements(tclObjTypeInterfaceArgsListAll)
{
ListRep listRep;
if (TclHasInternalRep(objPtr,&tclArithSeriesType.objType)) {
return TclArithSeriesGetElements(interp, objPtr, objcPtr, objvPtr);
}
if (TclListObjGetRep(interp, objPtr, &listRep) != TCL_OK)
if (TclListObjGetRep(interp, listPtr, &listRep) != TCL_OK)
return TCL_ERROR;
ListRepElements(&listRep, *objcPtr, *objvPtr);
return TCL_OK;
@@ -1655,28 +1762,47 @@ Tcl_ListObjGetElements(
*----------------------------------------------------------------------
*/
int
Tcl_ListObjAppendList(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
Tcl_Obj *toObj, /* List object to append elements to. */
Tcl_Obj *fromObj) /* List obj with elements to append. */
Tcl_ListObjAppendList(tclObjTypeInterfaceArgsListAppendList)
{
Tcl_Size objc;
Tcl_Obj **objv;
return TclObjectDispatch(listPtr, ListObjAppendList,
list, appendlist, interp, listPtr, elemListPtr);
}
if (Tcl_IsShared(toObj)) {
int
ListObjAppendList(tclObjTypeInterfaceArgsListAppendList)
{
int status;
if (Tcl_IsShared(listPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList");
}
if (TclListObjGetElementsM(interp, fromObj, &objc, &objv) != TCL_OK) {
return TCL_ERROR;
if (TclObjectHasInterface(listPtr, list, replaceList)) {
TclObjectDispatchNoDefault(interp, status, listPtr, list,
replaceList, interp, listPtr, LIST_MAX, 0, elemListPtr);
return status;
} else {
Tcl_Size objc;
Tcl_ListObjLength(interp, elemListPtr, &objc);
if (objc == 1) {
Tcl_Obj *itemObj;
status = Tcl_ListObjIndex(interp, elemListPtr, 0, &itemObj);
if (status != TCL_OK) {
return TCL_ERROR;
}
status = Tcl_ListObjAppendElement(interp, listPtr, itemObj);
return status;
} else {
Tcl_Obj **objv;
/*
* Pull the elements to append from elemListPtr.
*/
if (TCL_OK != TclListObjGetElementsM(interp, elemListPtr, &objc, &objv)) {
return TCL_ERROR;
}
return TclListObjAppendElements(interp, listPtr, objc, objv);
}
}
/*
* Insert the new elements starting after the lists's last element.
* Delete zero existing elements.
*/
return TclListObjAppendElements(interp, toObj, objc, objv);
}
/*
@@ -1858,6 +1984,20 @@ Tcl_ListObjAppendList(
*/
int
Tcl_ListObjAppendElement(
Tcl_Interp *interp,
Tcl_Obj *listPtr,
Tcl_Obj *objPtr)
{
if (Tcl_IsShared(listPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement");
}
return TclObjectDispatch(listPtr, ListObjAppendElement,
list, append, interp, listPtr, objPtr);
}
int
ListObjAppendElement(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
Tcl_Obj *toObj, /* List object to append elemObj to. */
Tcl_Obj *elemObj) /* Object to append to toObj's list. */
@@ -1900,21 +2040,25 @@ Tcl_ListObjAppendElement(
*/
int
Tcl_ListObjIndex(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
Tcl_Obj *listObj, /* List object to index into. */
Tcl_Size index, /* Index of element to return. */
Tcl_Obj **objPtrPtr) /* The resulting Tcl_Obj* is stored here. */
tclObjTypeInterfaceArgsListIndex
)
{
return TclObjectDispatch(listPtr, ListObjIndex,
list, index, interp, listPtr, index, objPtrPtr);
}
int
ListObjIndex(tclObjTypeInterfaceArgsListIndex) {
Tcl_Obj **elemObjs;
Tcl_Size numElems;
/* Empty string => empty list. Avoid unnecessary shimmering */
if (listObj->bytes == &tclEmptyString) {
if (listPtr->bytes == &tclEmptyString) {
*objPtrPtr = NULL;
return TCL_OK;
}
if (TclListObjGetElementsM(interp, listObj, &numElems, &elemObjs)
if (TclListObjGetElementsM(interp, listPtr, &numElems, &elemObjs)
!= TCL_OK) {
return TCL_ERROR;
}
@@ -1948,44 +2092,24 @@ Tcl_ListObjIndex(
*
*----------------------------------------------------------------------
*/
#undef Tcl_ListObjLength
int
Tcl_ListObjLength(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
Tcl_Obj *listObj, /* List object whose #elements to return. */
Tcl_Size *lenPtr) /* The resulting length is stored here. */
Tcl_ListObjLength(tclObjTypeInterfaceArgsListLength)
{
return TclObjectDispatch(listPtr, ListObjInterfaceLength,
list, length, interp, listPtr, lenPtr);
}
int
ListObjInterfaceLength(tclObjTypeInterfaceArgsListLength) {
ListRep listRep;
/* Empty string => empty list. Avoid unnecessary shimmering */
if (listObj->bytes == &tclEmptyString) {
*lenPtr = 0;
return TCL_OK;
}
Tcl_Size (*lengthProc)(Tcl_Obj *obj) = ABSTRACTLIST_PROC(listObj, lengthProc);
if (lengthProc) {
*lenPtr = lengthProc(listObj);
return TCL_OK;
}
if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
if (TclListObjGetRep(interp, listPtr, &listRep) != TCL_OK) {
return TCL_ERROR;
}
*lenPtr = ListRepLength(&listRep);
return TCL_OK;
}
Tcl_Size
ListLength(Tcl_Obj *listPtr)
{
ListRep listRep;
ListObjGetRep(listPtr, &listRep);
return ListRepLength(&listRep);
}
/*
*----------------------------------------------------------------------
@@ -2025,13 +2149,57 @@ ListLength(Tcl_Obj *listPtr)
*----------------------------------------------------------------------
*/
int
Tcl_ListObjReplace(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
Tcl_Obj *listObj, /* List object whose elements to replace. */
Tcl_Size first, /* Index of first element to replace. */
Tcl_Size numToDelete, /* Number of elements to replace. */
Tcl_Size numToInsert, /* Number of objects to insert. */
Tcl_Obj *const insertObjs[])/* Tcl objects to insert */
Tcl_ListObjReplace(tclObjTypeInterfaceArgsListReplace)
{
Tcl_Size length, status;
if (Tcl_IsShared(listObj)) {
Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
}
if (first < 0) {
first = 0;
}
status = Tcl_ListObjLength(interp, listObj, &length);
if (status != TCL_OK) {
return status;
}
/* go through the process even in this case to ensure that the result is a
* cononical list
*if (length == 0 && numToInsert == 0) {
* return TCL_OK;
*}
*/
if (first >= length) {
first = length; /* So we'll insert after last element. */
}
if (numToDelete < 0) {
numToDelete = 0;
} else if (first > INT_MAX - numToDelete /* Handle integer overflow */
|| length < first+numToDelete) {
numToDelete = length - first;
}
if (numToDelete > LIST_MAX - (length - numToDelete)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"max length of a Tcl list (%" TCL_Z_MODIFIER
"u elements) exceeded", LIST_MAX));
}
return TCL_ERROR;
}
return TclObjectDispatch(listObj, ListObjReplace,
list, replace, interp, listObj, first, numToDelete, numToInsert, insertObjs);
}
int
ListObjReplace(tclObjTypeInterfaceArgsListReplace)
{
ListRep listRep;
Tcl_Size origListLen;
@@ -2490,7 +2658,7 @@ Tcl_ListObjReplace(
*
* TclLindexList --
*
* This procedure handles the 'lindex' command when objc==3.
* Handles the 'lindex' command when objc==3.
*
* Results:
* Returns a pointer to the object extracted, or NULL if an error
@@ -2527,7 +2695,7 @@ TclLindexList(
* shimmering; if internal rep is already a list do not shimmer it.
* see TIP#22 and TIP#33 for the details.
*/
if (!TclHasInternalRep(argObj, &tclListType.objType)
if (!TclHasInternalRep(argObj, tclListType)
&& TclGetIntForIndexM(NULL, argObj, TCL_SIZE_MAX - 1, &index)
== TCL_OK) {
/*
@@ -2548,7 +2716,7 @@ TclLindexList(
* does not.
*/
indexListCopy = TclDuplicatePureObj(interp, argObj, &tclListType.objType);
indexListCopy = TclDuplicatePureObj(interp, argObj, tclListType);
if (!indexListCopy) {
/*
* The argument is neither an index nor a well-formed list.
@@ -2609,28 +2777,6 @@ TclLindexFlat(
int status;
Tcl_Size i;
/* Handle ArithSeries as special case */
if (TclHasInternalRep(listObj,&tclArithSeriesType.objType)) {
Tcl_Size listLen = ABSTRACTLIST_PROC(listObj, lengthProc)(listObj);
Tcl_Size index;
Tcl_Obj *elemObj = NULL;
for (i=0 ; i<indexCount && listObj ; i++) {
if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
&index) == TCL_OK) {
}
if (i==0) {
elemObj = TclArithSeriesObjIndex(NULL, listObj, index);
} else if (index > 0) {
/* ArithSeries cannot be a list of lists */
Tcl_DecrRefCount(elemObj);
TclNewObj(elemObj);
break;
}
}
Tcl_IncrRefCount(elemObj);
return elemObj;
}
Tcl_IncrRefCount(listObj);
for (i=0 ; i<indexCount && listObj ; i++) {
@@ -2663,29 +2809,56 @@ TclLindexFlat(
TclNewObj(listObj);
Tcl_IncrRefCount(listObj);
} else {
Tcl_Obj *itemObj;
/*
* Must set the internal rep again because it may have been
* changed by TclGetIntForIndexM. See test lindex-8.4.
*/
if (!TclHasInternalRep(listObj, &tclListType.objType)) {
status = SetListFromAny(interp, listObj);
if (status != TCL_OK) {
/* The list is not a list at all => error. */
Tcl_Obj* listItem;
if (TclIndexIsFromEnd(index)
&& TclObjectHasInterface(listObj, list, indexEnd)
&& Tcl_LengthIsFinite(listLen)
) {
TclObjectDispatchNoDefault(interp, status, listObj,
list, indexEnd, interp, listObj, index, &listItem);
if (status == TCL_OK) {
Tcl_IncrRefCount(listItem);
Tcl_DecrRefCount(listObj);
listObj = listItem;
} else {
Tcl_DecrRefCount(listObj);
return NULL;
}
}
} else if (TclObjectHasInterface(listObj, list, index)) {
TclObjectDispatchNoDefault(interp, status, listObj,
list, index, interp, listObj, index, &listItem);
if (status == TCL_OK) {
Tcl_IncrRefCount(listItem);
Tcl_DecrRefCount(listObj);
listObj = listItem;
} else {
Tcl_DecrRefCount(listObj);
return NULL;
}
} else {
/*
* Must set the internal rep again because it may have been
* changed by TclGetIntForIndexM. See test lindex-8.4.
*/
if (!TclHasInternalRep(listObj, tclListType)) {
status = SetListFromAny(interp, listObj);
if (status != TCL_OK) {
/* The list is not a list at all => error. */
Tcl_DecrRefCount(listObj);
return NULL;
}
}
ListObjGetElements(listObj, listLen, elemPtrs);
/* increment this reference count first before decrementing
* just in case they are the same Tcl_Obj
*/
itemObj = elemPtrs[index];
Tcl_IncrRefCount(itemObj);
Tcl_DecrRefCount(listObj);
/* Extract the pointer to the appropriate element. */
listObj = itemObj;
ListObjGetElements(listObj, listLen, elemPtrs);
/* increment this reference count first before decrementing
* just in case they are the same Tcl_Obj
*/
Tcl_IncrRefCount(elemPtrs[index]);
Tcl_DecrRefCount(listObj);
/* Extract the pointer to the appropriate element. */
listObj = elemPtrs[index];
}
}
} else {
Tcl_DecrRefCount(listObj);
@@ -2740,7 +2913,7 @@ TclLsetList(
* shimmering; see TIP #22 and #23 for details.
*/
if (!TclHasInternalRep(indexArgObj, &tclListType.objType)
if (!TclHasInternalRep(indexArgObj, tclListType)
&& TclGetIntForIndexM(NULL, indexArgObj, TCL_SIZE_MAX - 1, &index)
== TCL_OK) {
/* indexArgPtr designates a single index. */
@@ -2749,7 +2922,7 @@ TclLsetList(
}
indexListCopy = TclDuplicatePureObj(
interp, indexArgObj, &tclListType.objType);
interp, indexArgObj, tclListType);
if (!indexListCopy) {
/*
* indexArgPtr designates something that is neither an index nor a
@@ -2813,13 +2986,15 @@ TclLsetList(
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclLsetFlat(
Tcl_Interp *interp, /* Tcl interpreter. */
Tcl_Obj *listObj, /* Pointer to the list being modified. */
Tcl_Size indexCount, /* Number of index args. */
Tcl_Obj *const indexArray[],
/* Index args. */
Tcl_Obj *valueObj) /* Value arg to 'lset' or NULL to 'lpop'. */
TclLsetFlat(tclObjTypeInterfaceArgsListSetList)
{
return TclObjectDispatch(listObj, LsetFlat,
list, setlist, interp, listObj, indexCount, indexArray, valueObj);
}
Tcl_Obj *
LsetFlat(tclObjTypeInterfaceArgsListSetList)
{
Tcl_Size index, len;
int copied = 0, result;
@@ -2847,7 +3022,7 @@ TclLsetFlat(
*/
subListObj = Tcl_IsShared(listObj)
? TclDuplicatePureObj(interp, listObj, &tclListType.objType) : listObj;
? TclDuplicatePureObj(interp, listObj, tclListType) : listObj;
if (!subListObj) {
return NULL;
}
@@ -2934,7 +3109,7 @@ TclLsetFlat(
}
if (Tcl_IsShared(subListObj)) {
subListObj = TclDuplicatePureObj(
interp, subListObj, &tclListType.objType);
interp, subListObj, tclListType);
if (!subListObj) {
return NULL;
}
@@ -2958,7 +3133,7 @@ TclLsetFlat(
if (Tcl_IsShared(subListObj)) {
Tcl_Obj * newSubListObj;
newSubListObj = TclDuplicatePureObj(
interp, subListObj, &tclListType.objType);
interp, subListObj, tclListType);
if (copied) {
Tcl_DecrRefCount(subListObj);
}
@@ -3086,14 +3261,14 @@ TclLsetFlat(
*----------------------------------------------------------------------
*/
int
TclListObjSetElement(
Tcl_Interp *interp, /* Tcl interpreter; used for error reporting
* if not NULL. */
Tcl_Obj *listObj, /* List object in which element should be
* stored. */
Tcl_Size index, /* Index of element to store. */
Tcl_Obj *valueObj) /* Tcl object to store in the designated list
* element. */
TclListObjSetElement(tclObjTypeInterfaceArgsListSet)
{
return TclObjectDispatch(listObj, ListObjSetElement,
list, set, interp, listObj, index, valueObj);
}
int
ListObjSetElement(tclObjTypeInterfaceArgsListSet)
{
ListRep listRep;
Tcl_Obj **elemPtrs; /* Pointers to elements of the list. */
@@ -3249,7 +3424,61 @@ SetListFromAny(
* describe duplicate keys).
*/
if (!TclHasStringRep(objPtr) && TclHasInternalRep(objPtr, &tclDictType)) {
if (TclObjectHasInterface(objPtr, list, index)) {
int status;
Tcl_Size index, length, storeSize, offset;
Tcl_Obj *itemPtr, **lastElemPtr;
status = Tcl_ListObjLength(interp, objPtr, &length);
if (status != TCL_OK) {
return status;
}
storeSize = length;
if (ListRepInitAttempt(
interp, length > 8 ? storeSize : 8, NULL, &listRep)
!= TCL_OK) {
return TCL_ERROR;
}
elemPtrs = listRep.storePtr->slots;
lastElemPtr = elemPtrs + listRep.storePtr->numAllocated - 1;
index = 0;
Tcl_IncrRefCount(objPtr);
while (index < length || length < 0) {
TclObjectDispatchNoDefault(interp, status, objPtr, list,
index, interp, objPtr, index, &itemPtr);
if (status != TCL_OK) {
status = Tcl_ListObjLength(interp, objPtr, &length);
if (status != TCL_OK) {
TclUndoRefCount(objPtr);
return status;
}
continue;
}
if (elemPtrs == lastElemPtr) {
ListStore *newStorePtr;
storeSize += storeSize / 2;
offset = elemPtrs - listRep.storePtr->slots;
newStorePtr = ListStoreReallocate(listRep.storePtr, storeSize);
if (newStorePtr == NULL) {
TclUndoRefCount(objPtr);
return MemoryAllocationError(interp, LIST_SIZE(storeSize));
}
elemPtrs = newStorePtr->slots + offset;
listRep.storePtr = newStorePtr;
lastElemPtr = elemPtrs + listRep.storePtr->numAllocated - 1;
}
listRep.storePtr->numUsed++;
if (itemPtr == objPtr) {
*elemPtrs = Tcl_DuplicateObj(itemPtr);
TclBounceRefCount(itemPtr);
} else {
*elemPtrs = itemPtr;
}
Tcl_IncrRefCount(*elemPtrs);
elemPtrs++;
index++;
}
TclUndoRefCount(objPtr);
} else if (!TclHasStringRep(objPtr) && TclHasInternalRep(objPtr, &tclDictType)) {
Tcl_Obj *keyPtr, *valuePtr;
Tcl_DictSearch search;
int done;
@@ -3289,35 +3518,6 @@ SetListFromAny(
Tcl_IncrRefCount(valuePtr);
Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
}
} else if (TclHasInternalRep(objPtr,&tclArithSeriesType.objType)) {
/*
* Convertion from Arithmetic Series is a special case
* because it can be done an order of magnitude faster
* and may occur frequently.
*/
Tcl_Size j, size = ABSTRACTLIST_PROC(objPtr, lengthProc)(objPtr);
/* TODO - leave space in front and/or back? */
if (ListRepInitAttempt(
interp, size > 0 ? size : 1, NULL, &listRep)
!= TCL_OK) {
return TCL_ERROR;
}
LIST_ASSERT(listRep.spanPtr == NULL); /* Guard against future changes */
LIST_ASSERT(listRep.storePtr->firstUsed == 0);
LIST_ASSERT((listRep.storePtr->flags & LISTSTORE_CANONICAL) == 0);
listRep.storePtr->numUsed = size;
elemPtrs = listRep.storePtr->slots;
for (j = 0; j < size; j++) {
elemPtrs[j] = TclArithSeriesObjIndex(interp, objPtr, j);
if (elemPtrs[j] == NULL) {
return TCL_ERROR;
}
Tcl_IncrRefCount(elemPtrs[j]);
}
} else {
Tcl_Size estCount, length;
const char *limit, *nextElem = Tcl_GetStringFromObj(objPtr, &length);
@@ -3399,7 +3599,7 @@ fail:
TclFreeInternalRep(objPtr);
objPtr->internalRep.twoPtrValue.ptr1 = listRep.storePtr;
objPtr->internalRep.twoPtrValue.ptr2 = listRep.spanPtr;
objPtr->typePtr = &tclListType.objType;
objPtr->typePtr = tclListType;
return TCL_OK;
}
+220 -140
View File
@@ -9,6 +9,7 @@
* Copyright © 2001 ActiveState Corporation.
* Copyright © 2005 Kevin B. Kenny. All rights reserved.
* Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright © 2021 Nathan Coulter. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -19,6 +20,7 @@
#include <math.h>
#include <assert.h>
/*
* Table of all object types.
*/
@@ -27,6 +29,10 @@ static Tcl_HashTable typeTable;
static int typeTableInitialized = 0; /* 0 means not yet initialized. */
TCL_DECLARE_MUTEX(tableMutex)
TclObjectTypeType TclObjectTypeType0 = {
(int *)1
};
/*
* Head of the list of free Tcl_Obj structs we maintain.
*/
@@ -221,6 +227,32 @@ static void DupCmdNameInternalRep(Tcl_Obj *objPtr,
static void FreeCmdNameInternalRep(Tcl_Obj *objPtr);
static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static int ScalarObjIndex(tclObjTypeInterfaceArgsListIndex);
static int ScalarObjInterfaceListLength(tclObjTypeInterfaceArgsListLength);
static Tcl_Obj* ScalarObjRange(tclObjTypeInterfaceArgsListRange);
ObjInterface tclScalarInterface = {
1,
{},
{
NULL,
NULL, /* append */
NULL, /* appendList */
&ScalarObjIndex, /* index */
NULL, /* indexEnd */
NULL, /* isSorted */
&ScalarObjInterfaceListLength, /* length */
&ScalarObjRange, /* range */
NULL, /* rangeEnd */
NULL, /* replace */
NULL, /* replaceList */
NULL, /* reverse */
NULL, /* set */
NULL, /* setList */
},
};
/*
* The structures below defines the Tcl object types defined in this file by
* means of functions that can be invoked by generic object code. See also
@@ -228,47 +260,55 @@ static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
* implementations.
*/
const TclObjTypeWithAbstractList tclBooleanType= {
{"boolean", /* name */
const ObjectType tclBooleanObjType= {
"boolean", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
NULL, /* updateStringProc */
TclSetBooleanFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0_1(
TclLengthOne
)}
2,
(Tcl_ObjInterface *)&tclScalarInterface
};
const TclObjTypeWithAbstractList tclDoubleType= {
{"double", /* name */
MODULE_SCOPE const Tcl_ObjType *tclBooleanType = (Tcl_ObjType *)&tclBooleanObjType;
const ObjectType tclDoubleObjType= {
"double", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
UpdateStringOfDouble, /* updateStringProc */
SetDoubleFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0_1(
TclLengthOne
)}
2,
(Tcl_ObjInterface *)&tclScalarInterface
};
const TclObjTypeWithAbstractList tclIntType = {
{"int", /* name */
MODULE_SCOPE const Tcl_ObjType *tclDoubleType = (Tcl_ObjType *)&tclDoubleObjType;
const ObjectType tclIntObjType = {
"int", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
UpdateStringOfInt, /* updateStringProc */
SetIntFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0_1(
TclLengthOne
)}
2,
(Tcl_ObjInterface *)&tclScalarInterface
};
const TclObjTypeWithAbstractList tclBignumType = {
{"bignum", /* name */
MODULE_SCOPE const Tcl_ObjType *tclIntType = (Tcl_ObjType *)&tclIntObjType;
const ObjectType tclBignumObjType = {
"bignum", /* name */
FreeBignum, /* freeIntRepProc */
DupBignum, /* dupIntRepProc */
UpdateStringOfBignum, /* updateStringProc */
NULL, /* setFromAnyProc */
TCL_OBJTYPE_V0_1(
TclLengthOne
)}
2,
(Tcl_ObjInterface *)&tclScalarInterface
};
MODULE_SCOPE const Tcl_ObjType *tclBignumType = (Tcl_ObjType *)&tclBignumObjType;
/*
* The structure below defines the Tcl obj hash key type.
*/
@@ -311,7 +351,7 @@ Tcl_ObjType tclCmdNameType = {
DupCmdNameInternalRep, /* dupIntRepProc */
NULL, /* updateStringProc */
SetCmdNameFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0
0
};
/*
@@ -388,9 +428,9 @@ TclInitObjSubsystem(void)
Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
Tcl_MutexUnlock(&tableMutex);
Tcl_RegisterObjType(&tclDoubleType.objType);
Tcl_RegisterObjType(tclDoubleType);
Tcl_RegisterObjType(&tclStringType);
Tcl_RegisterObjType(&tclListType.objType);
Tcl_RegisterObjType(tclListType);
Tcl_RegisterObjType(&tclDictType);
Tcl_RegisterObjType(&tclByteCodeType);
Tcl_RegisterObjType(&tclCmdNameType);
@@ -816,6 +856,25 @@ TclThreadFinalizeContLines(
*--------------------------------------------------------------
*/
int TclObjTypeVersion (
const Tcl_ObjType *typePtr)
{
ObjectType *otPtr = (ObjectType *)typePtr;
if ((void *)otPtr->name == (void *)&TclObjectTypeType0) {
return otPtr->version;
}
return 1;
}
const char *TclObjTypeName(
const Tcl_ObjType *typePtr)
{
ObjectType *otPtr = (ObjectType *)typePtr;
return otPtr->name;
}
void
Tcl_RegisterObjType(
const Tcl_ObjType *typePtr) /* Information about object type; storage must
@@ -825,8 +884,9 @@ Tcl_RegisterObjType(
int isNew;
Tcl_MutexLock(&tableMutex);
const char *name = TclObjTypeName(typePtr);
Tcl_SetHashValue(
Tcl_CreateHashEntry(&typeTable, typePtr->name, &isNew), typePtr);
Tcl_CreateHashEntry(&typeTable, name, &isNew), typePtr);
Tcl_MutexUnlock(&tableMutex);
}
@@ -952,7 +1012,7 @@ Tcl_ConvertToType(
}
/*
* Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal form
* Use the target type's setFromAnyProc to set "objPtr"s internal form
* as appropriate for the target type. This frees the old internal
* representation.
*/
@@ -1704,80 +1764,6 @@ TclSetDuplicateObj(
TclFreeInternalRep(dupPtr);
SetDuplicateObj(dupPtr, objPtr);
}
/*
*----------------------------------------------------------------------
*
* TclObjGetScaler --
*
* Without perturbing any existing internal represenation, returns objPtr
* itself if it has an internal scalar type, is the empty list, or if the
* Tcl_Obj is list a containing only one scalar element, tries to returns
* scalar Tcl_Obj from that one item.
*
* Returns NULL if the Tcl_Obj is not scalar.
*
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclObjGetScalar(Tcl_Obj *objPtr)
{
Tcl_ObjType const *typePtr = objPtr->typePtr;
if (typePtr == &tclDictType) {
if (TclDictGetSize(objPtr) == 0) {
return objPtr;
} else {
return NULL;
}
}
if (TclHasInternalRep(objPtr, NULL) && objPtr->bytes != &tclEmptyString) {
void *ClientDataPtr;
int numTypePtr;
if (Tcl_GetNumberFromObj(NULL, objPtr, &ClientDataPtr, &numTypePtr) != TCL_OK) {
Tcl_Size length;
/* convert to list */
Tcl_ListObjLength(NULL, objPtr, &length);
}
}
if (typePtr == &tclIntType.objType
|| typePtr == &tclDoubleType.objType
|| typePtr == &tclBignumType.objType
) {
return objPtr;
}
if (typePtr == &tclListType.objType) {
if (TclListObjIsCanonical(objPtr)) {
Tcl_Size objc;
TclListObjLengthM(NULL, objPtr, &objc);
if (objc == 1) {
Tcl_Obj *elem, *elem2;
Tcl_IncrRefCount(objPtr);
elem = TclListObjGetElement(objPtr, 0);
Tcl_IncrRefCount(elem);
Tcl_DecrRefCount(objPtr);
elem2 = TclObjGetScalar(elem);
if (elem2) {
Tcl_IncrRefCount(elem2);
Tcl_DecrRefCount(elem);
TclUndoRefCount(elem2);
} else {
Tcl_DecrRefCount(elem);
}
return elem2;
} else if (objc == 0) {
return objPtr;
}
} else {
return NULL;
}
}
if (TclCheckEmptyString(objPtr)) {
return objPtr;
}
return NULL;
}
/*
*----------------------------------------------------------------------
@@ -2173,11 +2159,11 @@ Tcl_GetBoolFromObj(
return TCL_ERROR;
}
do {
if (objPtr->typePtr == &tclIntType.objType || objPtr->typePtr == &tclBooleanType.objType) {
if (objPtr->typePtr == tclIntType || objPtr->typePtr == tclBooleanType) {
result = (objPtr->internalRep.wideValue != 0);
goto boolEnd;
}
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
/*
* Caution: Don't be tempted to check directly for the "double"
* Tcl_ObjType and then compare the internalrep to 0.0. This isn't
@@ -2194,7 +2180,7 @@ Tcl_GetBoolFromObj(
result = (d != 0.0);
goto boolEnd;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
result = 1;
boolEnd:
if (charPtr != NULL) {
@@ -2261,18 +2247,18 @@ TclSetBooleanFromAny(
*/
if (objPtr->bytes == NULL) {
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
if ((Tcl_WideUInt)objPtr->internalRep.wideValue < 2) {
return TCL_OK;
}
goto badBoolean;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
goto badBoolean;
}
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
goto badBoolean;
}
}
@@ -2403,13 +2389,13 @@ ParseBoolean(
goodBoolean:
TclFreeInternalRep(objPtr);
objPtr->internalRep.wideValue = newBool;
objPtr->typePtr = &tclBooleanType.objType;
objPtr->typePtr = tclBooleanType;
return TCL_OK;
numericBoolean:
TclFreeInternalRep(objPtr);
objPtr->internalRep.wideValue = newBool;
objPtr->typePtr = &tclIntType.objType;
objPtr->typePtr = tclIntType;
return TCL_OK;
}
@@ -2436,6 +2422,7 @@ ParseBoolean(
*/
#ifdef TCL_MEM_DEBUG
#undef Tcl_NewDoubleObj
Tcl_Obj *
Tcl_NewDoubleObj(
@@ -2500,7 +2487,7 @@ Tcl_DbNewDoubleObj(
objPtr->bytes = NULL;
objPtr->internalRep.doubleValue = dblValue;
objPtr->typePtr = &tclDoubleType.objType;
objPtr->typePtr = tclDoubleType;
return objPtr;
}
@@ -2573,7 +2560,7 @@ Tcl_GetDoubleFromObj(
double *dblPtr) /* Place to store resulting double. */
{
do {
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
if (isnan(objPtr->internalRep.doubleValue)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
@@ -2586,11 +2573,11 @@ Tcl_GetDoubleFromObj(
*dblPtr = (double) objPtr->internalRep.doubleValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
*dblPtr = (double) objPtr->internalRep.wideValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
mp_int big;
TclUnpackBignum(objPtr, big);
@@ -2718,6 +2705,17 @@ Tcl_GetIntFromObj(
return TCL_OK;
#endif
}
int
ScalarObjInterfaceListLength(
TCL_UNUSED(Tcl_Interp *), /* Used to report errors if not NULL. */ \
TCL_UNUSED(Tcl_Obj *), /* List object whose #elements to return. */ \
Tcl_Size *lenPtr /* The resulting length is stored here. */
)
{
*lenPtr = 1;
return TCL_OK;
}
/*
@@ -2804,12 +2802,12 @@ Tcl_GetLongFromObj(
{
do {
#ifdef TCL_WIDE_INT_IS_LONG
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
*longPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
#else
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
/*
* We return any integer in the range LONG_MIN to ULONG_MAX
* converted to a long, ignoring overflow. The rule preserves
@@ -2828,7 +2826,7 @@ Tcl_GetLongFromObj(
goto tooLarge;
}
#endif
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
@@ -2837,7 +2835,7 @@ Tcl_GetLongFromObj(
}
return TCL_ERROR;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
/*
* Must check for those bignum values that can fit in a long, even
* when auto-narrowing is enabled. Only those values in the signed
@@ -2912,6 +2910,7 @@ Tcl_GetLongFromObj(
*/
#ifdef TCL_MEM_DEBUG
#undef Tcl_NewWideIntObj
Tcl_Obj *
Tcl_NewWideIntObj(
@@ -3064,11 +3063,11 @@ Tcl_GetWideIntFromObj(
/* Place to store resulting long. */
{
do {
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
@@ -3077,7 +3076,7 @@ Tcl_GetWideIntFromObj(
}
return TCL_ERROR;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
/*
* Must check for those bignum values that can fit in a
* Tcl_WideInt, even when auto-narrowing is enabled.
@@ -3149,7 +3148,7 @@ Tcl_GetWideUIntFromObj(
/* Place to store resulting long. */
{
do {
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
if (objPtr->internalRep.wideValue < 0) {
wideUIntOutOfRange:
if (interp != NULL) {
@@ -3163,10 +3162,10 @@ Tcl_GetWideUIntFromObj(
*wideUIntPtr = (Tcl_WideUInt)objPtr->internalRep.wideValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
goto wideUIntOutOfRange;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
/*
* Must check for those bignum values that can fit in a
* Tcl_WideUInt, even when auto-narrowing is enabled.
@@ -3233,11 +3232,11 @@ TclGetWideBitsFromObj(
Tcl_WideInt *wideIntPtr) /* Place to store resulting wide integer. */
{
do {
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
@@ -3246,7 +3245,7 @@ TclGetWideBitsFromObj(
}
return TCL_ERROR;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
mp_int big;
mp_err err;
@@ -3350,7 +3349,7 @@ DupBignum(
mp_int bignumVal;
mp_int bignumCopy;
copyPtr->typePtr = &tclBignumType.objType;
copyPtr->typePtr = tclBignumType;
TclUnpackBignum(srcPtr, bignumVal);
if (mp_init_copy(&bignumCopy, &bignumVal) != MP_OKAY) {
Tcl_Panic("initialization failure in DupBignum");
@@ -3428,6 +3427,7 @@ UpdateStringOfBignum(
*/
#ifdef TCL_MEM_DEBUG
#undef Tcl_NewBignumObj
Tcl_Obj *
Tcl_NewBignumObj(
@@ -3519,7 +3519,7 @@ GetBignumFromObj(
mp_int *bignumValue) /* Returned bignum value. */
{
do {
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
if (copy || Tcl_IsShared(objPtr)) {
mp_int temp;
@@ -3544,14 +3544,14 @@ GetBignumFromObj(
}
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
if (mp_init_i64(bignumValue,
objPtr->internalRep.wideValue) != MP_OKAY) {
return TCL_ERROR;
}
return TCL_OK;
}
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
@@ -3711,7 +3711,7 @@ TclSetBignumInternalRep(
void *big)
{
mp_int *bignumValue = (mp_int *)big;
objPtr->typePtr = &tclBignumType.objType;
objPtr->typePtr = tclBignumType;
PACK_BIGNUM(*bignumValue, objPtr);
/*
@@ -3734,14 +3734,13 @@ TclSetBignumInternalRep(
* Extracts a number (of any possible numeric type) from an object.
*
* Results:
* Whether the extraction worked. The type is stored in the variable
* referred to by the typePtr argument, and a pointer to the
* representation is stored in the variable referred to by the
* clientDataPtr.
* A standard Tcl completion code. On success, the type is stored at the
* address given by typePtr, and a pointer to the representation is stored
* at the address given by clientDataPtr.
*
* Side effects:
* Can allocate thread-specific data for handling the copy-out space for
* bignums; this space is shared within a thread.
* May allocate thread-specific data shared within a thread for handling
* the copy-out space for bignums.
*
*----------------------------------------------------------------------
*/
@@ -3754,7 +3753,7 @@ Tcl_GetNumberFromObj(
int *typePtr)
{
do {
if (objPtr->typePtr == &tclDoubleType.objType) {
if (objPtr->typePtr == tclDoubleType) {
if (isnan(objPtr->internalRep.doubleValue)) {
*typePtr = TCL_NUMBER_NAN;
} else {
@@ -3763,12 +3762,12 @@ Tcl_GetNumberFromObj(
*clientDataPtr = &objPtr->internalRep.doubleValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType.objType) {
if (objPtr->typePtr == tclIntType) {
*typePtr = TCL_NUMBER_INT;
*clientDataPtr = &objPtr->internalRep.wideValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclBignumType.objType) {
if (objPtr->typePtr == tclBignumType) {
static Tcl_ThreadDataKey bignumKey;
mp_int *bigPtr = (mp_int *)Tcl_GetThreadData(&bignumKey,
sizeof(mp_int));
@@ -3819,6 +3818,29 @@ Tcl_GetNumber(
return Tcl_GetNumberFromObj(interp, objPtr, clientDataPtr, typePtr);
}
/*
*----------------------------------------------------------------------
*
* TclBounceRefCount --
*
* Performs the equivante of incrementing and then decrementing the
* reference count.
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
void
TclBounceRefCount(
Tcl_Obj *objPtr) /* The object we are registering a reference to. */
{
if (objPtr->refCount < 1) {
TclFreeObj(objPtr);
}
}
/*
*----------------------------------------------------------------------
*
@@ -4611,6 +4633,37 @@ DupCmdNameInternalRep(
resPtr->refCount++;
copyPtr->typePtr = &tclCmdNameType;
}
static int
ScalarObjIndex(
TCL_UNUSED(Tcl_Interp *),/* Used to report errors if not NULL. */ \
Tcl_Obj *listPtr, /* List object to index into. */ \
Tcl_Size index, /* Index of element to return. */ \
Tcl_Obj **objPtrPtr /* The resulting Tcl_Obj* is stored here. */
) {
if (index == 0) {
*objPtrPtr = listPtr;
} else {
*objPtrPtr = NULL;
}
return TCL_OK;
}
static Tcl_Obj* ScalarObjRange(
TCL_UNUSED(Tcl_Interp *),/* Used to report errors */ \
Tcl_Obj *listObj, /* List object to take a range from. */ \
Tcl_Size rangeStart, /* Index of first element to */ \
/* include. */ \
Tcl_Size rangeEnd /* Index of last element to include. */
)
{
if (rangeEnd >= 0 && rangeEnd >= rangeStart) {
return listObj;
} else {
return NULL;
}
}
/*
*----------------------------------------------------------------------
@@ -4723,13 +4776,14 @@ Tcl_RepresentationCmd(
* "1872361827361287"
*/
const char *name = objv[1]->typePtr ? TclObjTypeName(objv[1]->typePtr) : "pure string";
descObj = Tcl_ObjPrintf("value is a %s with a refcount of %" TCL_Z_MODIFIER "u,"
" object pointer at %p",
objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
name,
objv[1]->refCount, objv[1]);
if (objv[1]->typePtr) {
if (objv[1]->typePtr == &tclDoubleType.objType) {
if (objv[1]->typePtr == tclDoubleType) {
Tcl_AppendPrintfToObj(descObj, ", internal representation %g",
objv[1]->internalRep.doubleValue);
} else {
@@ -4751,6 +4805,32 @@ Tcl_RepresentationCmd(
Tcl_SetObjResult(interp, descObj);
return TCL_OK;
}
void Tcl_ObjTypeVersion(Tcl_Obj *objPtr, int *version) {
if ((void *)objPtr->typePtr->name == (void *)&TclObjectTypeType0) {
*version = ((ObjectType *)objPtr->typePtr)->version;
} else {
*version = 1;
}
return;
}
TclObjectTypeType * TclGetObjectTypeType () {
return &TclObjectTypeType0;
}
int (*TclObjInterfaceGetListIndex (Tcl_Obj *objPtr))
(tclObjTypeInterfaceArgsListIndex)
{
ObjInterface *interface = (ObjInterface *)((ObjectType *)objPtr->typePtr)->interface;
if (interface->version >= 1) {
return interface->list.index;
}
return NULL;
}
/*
* Local Variables:
+1 -1
View File
@@ -1046,7 +1046,7 @@ Tcl_ScanObjCmd(
if (Tcl_GetDoubleFromObj(NULL, objPtr, &dvalue) != TCL_OK) {
#ifdef ACCEPT_NAN
const Tcl_ObjInternalRep *irPtr
= TclFetchInternalRep(objPtr, &tclDoubleType.objType);
= TclFetchInternalRep(objPtr, tclDoubleType);
if (irPtr) {
dvalue = irPtr->doubleValue;
} else
+6 -6
View File
@@ -555,7 +555,7 @@ TclParseNumber(
/* A dict can never be a (single) number */
return TCL_ERROR;
}
if (TclHasInternalRep(objPtr, &tclListType.objType)) {
if (TclHasInternalRep(objPtr, tclListType)) {
Tcl_Size length;
/* A list can only be a (single) number if its length == 1 */
TclListObjLengthM(NULL, objPtr, &length);
@@ -1378,7 +1378,7 @@ TclParseNumber(
octalSignificandWide);
octalSignificandOverflow = 1;
} else {
objPtr->typePtr = &tclIntType.objType;
objPtr->typePtr = tclIntType;
if (signum) {
objPtr->internalRep.wideValue =
(Tcl_WideInt)(-octalSignificandWide);
@@ -1414,7 +1414,7 @@ TclParseNumber(
significandWide);
significandOverflow = 1;
} else {
objPtr->typePtr = &tclIntType.objType;
objPtr->typePtr = tclIntType;
if (signum) {
objPtr->internalRep.wideValue =
(Tcl_WideInt)(-significandWide);
@@ -1446,7 +1446,7 @@ TclParseNumber(
* k = numTrailZeros+exponent-numDigitsAfterDp.
*/
objPtr->typePtr = &tclDoubleType.objType;
objPtr->typePtr = tclDoubleType;
if (exponentSignum) {
/*
* At this point exponent>=0, so the following calculation
@@ -1497,14 +1497,14 @@ TclParseNumber(
} else {
objPtr->internalRep.doubleValue = HUGE_VAL;
}
objPtr->typePtr = &tclDoubleType.objType;
objPtr->typePtr = tclDoubleType;
break;
#ifdef IEEE_FLOATING_POINT
case sNAN:
case sNANFINISH:
objPtr->internalRep.doubleValue = MakeNaN(signum, significandWide);
objPtr->typePtr = &tclDoubleType.objType;
objPtr->typePtr = tclDoubleType;
break;
#endif
case INITIAL:
+44 -5
View File
@@ -59,6 +59,8 @@ static void ExtendUnicodeRepWithString(Tcl_Obj *objPtr,
Tcl_Size numAppendChars);
static void FillUnicodeRep(Tcl_Obj *objPtr);
static void FreeStringInternalRep(Tcl_Obj *objPtr);
static Tcl_Size GetCharLength(Tcl_Obj *objPtr);
static Tcl_Obj* GetRange(tclObjTypeInterfaceArgsStringRange);
static void GrowStringBuffer(Tcl_Obj *objPtr, Tcl_Size needed, int flag);
static void GrowUnicodeBuffer(Tcl_Obj *objPtr, Tcl_Size needed);
static int SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
@@ -369,11 +371,18 @@ Tcl_NewUnicodeObj(
*
*----------------------------------------------------------------------
*/
Tcl_Size
Tcl_GetCharLength(
Tcl_Obj *objPtr) /* The String object to get the num chars
* of. */
{
return TclObjectDispatch(objPtr, GetCharLength,
string, length, objPtr);
}
Tcl_Size
GetCharLength(
Tcl_Obj *objPtr)
{
String *stringPtr;
Tcl_Size numChars = 0;
@@ -685,11 +694,15 @@ Tcl_GetUnicodeFromObj(
*/
Tcl_Obj *
Tcl_GetRange(
Tcl_Obj *objPtr, /* The Tcl object to find the range of. */
Tcl_Size first, /* First index of the range. */
Tcl_Size last) /* Last index of the range. */
Tcl_GetRange(tclObjTypeInterfaceArgsStringRange)
{
return TclObjectDispatch(objPtr, GetRange,
string, range, objPtr, first, last);
}
Tcl_Obj *
GetRange(tclObjTypeInterfaceArgsStringRange) {
Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */
String *stringPtr;
Tcl_Size length = 0;
@@ -3701,6 +3714,32 @@ TclStringFirst(
return obj;
}
int
TclStringIndexInterface(
Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *indexPtr, Tcl_Obj **charPtrPtr)
{
Tcl_Size index, status;
status = TclGetIntForIndexM(interp, indexPtr, /*endValue*/ TCL_SIZE_MAX - 1,
&index);
if (status != TCL_OK) {
return status;
}
if (TclIndexIsFromEnd(index)) {
if (TclObjectInterfaceCall(objPtr, string, indexEnd,
interp, objPtr, index, charPtrPtr) != TCL_OK) {
return TCL_ERROR;
}
} else {
if (TclObjectInterfaceCall(objPtr, string, index, interp, objPtr,
index, charPtrPtr) != TCL_OK) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
*---------------------------------------------------------------------------
*
+6
View File
@@ -727,6 +727,12 @@ Tcltest_Init(
if (TclObjTest_Init(interp) != TCL_OK) {
return TCL_ERROR;
}
if (TcltestObjectInterfaceInit(interp) != TCL_OK) {
return TCL_ERROR;
}
if (TcltestObjectInterfaceListIntegerInit(interp) != TCL_OK) {
return TCL_ERROR;
}
if (Procbodytest_Init(interp) != TCL_OK) {
return TCL_ERROR;
}
+10 -6
View File
@@ -974,12 +974,16 @@ TestlistobjCmd(
!= 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 */
}
Tcl_IncrRefCount(objP);
Tcl_DecrRefCount(objP);
TCL_COMMENT(
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;
+530
View File
@@ -0,0 +1,530 @@
/*
* tclTestObjInterface.c --
*
* This file contains C command functions for the additional Tcl commands
* that are used for testing implementations of the Tcl object types.
* These commands are not normally included in Tcl applications; they're
* only used for testing.
*
* Copyright © 2021 Nathan Coulter
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tcl.h"
#include "tclInt.h"
/*
* Prototypes for functions defined later in this file:
*/
typedef struct indexHex {
int refCount;
Tcl_Size offset;
} indexHex;
int TcltestObjectInterfaceInit(Tcl_Interp *interp);
int NewTestIndexHex (
ClientData, Tcl_Interp *interp, Tcl_Size argc, Tcl_Obj *const objv[]);
static void DupTestIndexHexInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void FreeTestIndexHexInternalRep(Tcl_Obj *objPtr);
static int SetTestIndexHexFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void UpdateStringOfTestIndexHex(Tcl_Obj *listPtr);
static int indexHexListStringIndex (tclObjTypeInterfaceArgsStringIndex);
static int indexHexListStringIndexEnd(tclObjTypeInterfaceArgsStringIndexEnd);
static Tcl_Size indexHexListStringLength(tclObjTypeInterfaceArgsStringLength);
static int indexHexStringListIndexFromStringIndex(
Tcl_Size *index, Tcl_Size *itemchars, Tcl_Size *totalitems);
static Tcl_Obj* indexHexListStringRange(tclObjTypeInterfaceArgsStringRange);
static Tcl_Obj* indexHexListStringRangeEnd(tclObjTypeInterfaceArgsStringRangeEnd);
static int indexHexListObjGetElements (tclObjTypeInterfaceArgsListAll);
static int indexHexListObjAppendElement (tclObjTypeInterfaceArgsListAppend);
static int indexHexListObjAppendList (tclObjTypeInterfaceArgsListAppendList);
static int indexHexListObjIndex (tclObjTypeInterfaceArgsListIndex);
static int indexHexListObjIndexEnd (tclObjTypeInterfaceArgsListIndexEnd);
static int indexHexListObjIsSorted(tclObjTypeInterfaceArgsListIsSorted);
static int indexHexListObjLength (tclObjTypeInterfaceArgsListLength);
static Tcl_Obj* indexHexListObjRange (tclObjTypeInterfaceArgsListRange);
static Tcl_Obj* indexHexListObjRangeEnd (tclObjTypeInterfaceArgsListRangeEnd);
static int indexHexListObjReplace (tclObjTypeInterfaceArgsListReplace);
static int indexHexListObjSetElement (tclObjTypeInterfaceArgsListSet);
static Tcl_Obj * indexHexLsetFlat (tclObjTypeInterfaceArgsListSetList);
static int indexHexListErrorIndeterminate (Tcl_Interp *interp);
static int indexHexListErrorReadOnly (Tcl_Interp *interp);
ObjInterface IndexHexInterface = {
1,
{
&indexHexListStringIndex,
&indexHexListStringIndexEnd,
&indexHexListStringLength,
&indexHexListStringRange,
&indexHexListStringRangeEnd
},
{
&indexHexListObjGetElements,
&indexHexListObjAppendElement,
&indexHexListObjAppendList,
&indexHexListObjIndex,
&indexHexListObjIndexEnd,
&indexHexListObjIsSorted,
&indexHexListObjLength,
&indexHexListObjRange,
&indexHexListObjRangeEnd,
&indexHexListObjReplace,
NULL,
NULL,
&indexHexListObjSetElement,
&indexHexLsetFlat
}
};
const ObjectType testIndexHexType = {
"testindexHex",
FreeTestIndexHexInternalRep, /* freeIntRepProc */
DupTestIndexHexInternalRep, /* dupIntRepProc */
UpdateStringOfTestIndexHex, /* updateStringProc */
SetTestIndexHexFromAny, /* setFromAnyProc */
2,
(Tcl_ObjInterface *)&IndexHexInterface
};
const Tcl_ObjType *testIndexHexTypePtr = (Tcl_ObjType *)&testIndexHexType;
int TcltestObjectInterfaceInit(Tcl_Interp *interp) {
Tcl_CreateObjCommand2(interp, "testindexhex", NewTestIndexHex, NULL, NULL);
return TCL_OK;
}
int NewTestIndexHex (
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_Size argc,
Tcl_Obj *const objv[])
{
Tcl_WideInt offset;
Tcl_ObjInternalRep intrep;
if (argc > 2) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("too many arguments", -1));
return TCL_ERROR;
}
}
if (argc == 2) {
if (Tcl_GetWideIntFromObj(interp, objv[1], &offset) != TCL_OK) {
return TCL_ERROR;
}
if (offset < 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("bad offset", -1));
return TCL_ERROR;
}
} else {
offset = 0;
}
Tcl_Obj *objPtr = Tcl_NewObj();
Tcl_InvalidateStringRep(objPtr);
indexHex *indexHexPtr = (indexHex *)Tcl_Alloc(sizeof(indexHex));
indexHexPtr->refCount = 1;
indexHexPtr->offset = offset;
intrep.twoPtrValue.ptr1 = indexHexPtr;
Tcl_StoreInternalRep(objPtr, testIndexHexTypePtr, &intrep);
Tcl_SetObjResult(interp, objPtr);
return TCL_OK;
}
static void
DupTestIndexHexInternalRep(
TCL_UNUSED(Tcl_Obj *),
TCL_UNUSED(Tcl_Obj *))
{
return;
}
static void
FreeTestIndexHexInternalRep(Tcl_Obj *objPtr)
{
indexHex *indexHexPtr = (indexHex *)objPtr->internalRep.twoPtrValue.ptr1;
if (--indexHexPtr->refCount == 0) {
Tcl_Free(indexHexPtr);
}
return;
}
static int
SetTestIndexHexFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr)
{
if (TclHasInternalRep(objPtr, testIndexHexTypePtr)) {
return TCL_OK;
} else {
if (interp != NULL) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("can not set an existing value to this type", -1));
}
return TCL_ERROR;
}
}
static void
UpdateStringOfTestIndexHex(
TCL_UNUSED(Tcl_Obj *))
{
return;
}
static int indexHexListStringIndex(tclObjTypeInterfaceArgsStringIndex) {
Tcl_Obj *hexPtr;
int status;
Tcl_Size itemchars, totalitems;
status = indexHexStringListIndexFromStringIndex(
&index, &itemchars, &totalitems);
if (status != TCL_OK) {
return TCL_ERROR;
}
status = indexHexListObjIndex(interp, objPtr, totalitems, &hexPtr);
if (status != TCL_OK) {
return TCL_ERROR;
}
if (index == itemchars - 1) {
/* index refers to the space delimiter after the item. */
*objPtrPtr = Tcl_NewStringObj(" ", -1);
} else {
*objPtrPtr = Tcl_GetRange(hexPtr, index, index);
}
Tcl_DecrRefCount(hexPtr);
return status;
}
static int indexHexListErrorIndeterminate (Tcl_Interp *interp) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("list length indeterminate", -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "INDETERMINATE", NULL);
return TCL_ERROR;
}
static int indexHexListErrorReadOnly (Tcl_Interp *interp) {
if (interp != NULL) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("list length indeterminate", -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "INTERFACE",
"READONLY", NULL);
}
return TCL_ERROR;
}
static int indexHexStringListIndexFromStringIndex(
Tcl_Size *indexPtr, Tcl_Size *itemcharsPtr, Tcl_Size *totalitemsPtr)
{
Tcl_Size itemoffset, last = 0, power = 1, lasttotalchars = 0, newitems,
top, totalchars = 0;
/* add 1 for the space after the item */
*itemcharsPtr = power + 1;
*totalitemsPtr = 0;
/* Count the number of characters in the items that contain fewer
* characters than the item containing the requested index. */
while (1) {
top = 1u << (4 * power);
if (top < 1u << (4 * (power - 1))) {
/* operation wrapped around */
power -= 1;
break;
}
newitems = top - last;
lasttotalchars = totalchars;
totalchars += newitems * *itemcharsPtr;
last = top;
if (*indexPtr < totalchars) {
break;
}
power += 1;
*itemcharsPtr += 1;
*totalitemsPtr += newitems;
}
*indexPtr -= lasttotalchars;
/* Determine how many items containing the same number of characters
* precede the requested item. */
itemoffset = *indexPtr / *itemcharsPtr ;
*indexPtr = *indexPtr % *itemcharsPtr;
/* Add the number of new characters. */
*totalitemsPtr += itemoffset;
return TCL_OK;
}
static int indexHexListStringIndexEnd(
Tcl_Interp *interp,
TCL_UNUSED(Tcl_Obj *),
TCL_UNUSED(Tcl_Size),
TCL_UNUSED(Tcl_Obj **)
) {
return indexHexListErrorIndeterminate(interp);
}
static Tcl_Size indexHexListStringLength(
TCL_UNUSED(Tcl_Obj *);
) {
return TCL_INDEX_NONE;
}
static Tcl_Obj* indexHexListStringRange(tclObjTypeInterfaceArgsStringRange) {
Tcl_Obj *itemPtr, *item2Ptr, *resPtr;
Tcl_Size index = first, status;
Tcl_Size itemchars, needed, rangeLength, newStringLength,
stringLength, totalitems;
if (last < first) {
return Tcl_NewStringObj("", -1);
}
status = indexHexStringListIndexFromStringIndex(
&index, &itemchars, &totalitems);
if (status != TCL_OK) {
return NULL;
}
status = indexHexListObjIndex(NULL, objPtr, totalitems, &itemPtr);
if (status != TCL_OK) {
return NULL;
}
rangeLength = last - first + 1;
resPtr = Tcl_GetRange(itemPtr, index, index + rangeLength - 1);
Tcl_DecrRefCount(itemPtr);
stringLength = Tcl_GetCharLength(resPtr);
if (stringLength < rangeLength) {
needed = rangeLength - stringLength;
while (needed > 0) {
totalitems++;
status = indexHexListObjIndex(NULL, objPtr, totalitems, &itemPtr);
if (status != TCL_OK) {
return NULL;
}
Tcl_AppendToObj(resPtr, " ", 1);
stringLength += newStringLength;
needed -= 1;
if (needed > 0) {
newStringLength = Tcl_GetCharLength(itemPtr);
if (newStringLength >= needed) {
item2Ptr = Tcl_GetRange(itemPtr, 0, needed-1);
newStringLength = Tcl_GetCharLength(item2Ptr);
Tcl_AppendObjToObj(resPtr, item2Ptr);
Tcl_DecrRefCount(item2Ptr);
} else {
Tcl_AppendObjToObj(resPtr, itemPtr);
}
stringLength += newStringLength;
needed -= newStringLength;
}
Tcl_DecrRefCount(itemPtr);
}
}
return resPtr;
}
static Tcl_Obj* indexHexListStringRangeEnd(
TCL_UNUSED(Tcl_Obj *),/* The Tcl object to find the range of. */
TCL_UNUSED(Tcl_Size),/* First index of the range. */
TCL_UNUSED(Tcl_Size) /* Last index of the range. */
) {
return NULL;
}
static int
indexHexListObjGetElements(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
TCL_UNUSED(Tcl_Obj *),/* List object for which an element array
* is to be returned. */
TCL_UNUSED(Tcl_Size *),/* Where to store the count of objects
* referenced by objv. */
TCL_UNUSED(Tcl_Obj ***)/* Where to store the pointer to an
* array of */
)
{
if (interp != NULL) {
Tcl_SetObjResult(interp,Tcl_NewStringObj("infinite list", -1));
}
return TCL_ERROR;
}
static int
indexHexListObjAppendElement(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
TCL_UNUSED(Tcl_Obj *),/* List object to append objPtr to. */
TCL_UNUSED(Tcl_Obj *)/* Object to append to listPtr's list. */
)
{
indexHexListErrorReadOnly(interp);
return TCL_ERROR;
}
static int
indexHexListObjAppendList(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
TCL_UNUSED(Tcl_Obj *), /* List object to append elements to. */
TCL_UNUSED(Tcl_Obj *) /* List obj with elements to append. */
)
{
indexHexListErrorReadOnly(interp);
return TCL_ERROR;
}
static int
indexHexListObjIndex(
TCL_UNUSED(Tcl_Interp *),/* Used to report errors if not NULL. */ \
TCL_UNUSED(Tcl_Obj *), /* List object to index into. */ \
Tcl_Size index, /* Index of element to return. */ \
Tcl_Obj **objPtrPtr /* The resulting Tcl_Obj* is stored here. */
)
{
Tcl_Obj *resPtr;
resPtr = Tcl_ObjPrintf("%" TCL_T_MODIFIER "x", index);
*objPtrPtr = resPtr;
return TCL_OK;
}
static int
indexHexListObjIndexEnd(
Tcl_Interp * interp,/* Used to report errors if not NULL. */ \
TCL_UNUSED(Tcl_Obj *),/* List object to index into. */ \
TCL_UNUSED(Tcl_Size),/* Index of element to return. */ \
TCL_UNUSED(Tcl_Obj **)/* The resulting Tcl_Obj* is stored here. */
)
{
return indexHexListErrorIndeterminate(interp);
}
static int indexHexListObjIsSorted(
TCL_UNUSED(Tcl_Interp *), /* Used to report errors */
TCL_UNUSED(Tcl_Obj *), /* The list in question */
TCL_UNUSED(size_t) /* flags */
)
{
return 1;
}
static int
indexHexListObjLength(
TCL_UNUSED(Tcl_Interp *), /* Used to report errors if not NULL. */
TCL_UNUSED(Tcl_Obj *), /* List object whose #elements to return. */
Tcl_Size *lenPtr /* The resulting length is stored here. */
)
{
*lenPtr = -1;
return TCL_OK;
}
static Tcl_Obj*
indexHexListObjRange(tclObjTypeInterfaceArgsListRange)
{
Tcl_Obj *itemPtr, *resPtr;
Tcl_Size length;
int status;
resPtr = Tcl_NewListObj(0, NULL);
status = Tcl_ListObjLength(interp, listObj, &length);
if (!status) {
return NULL;
}
while (rangeStart <= length && rangeStart <= rangeEnd) {
indexHexListObjIndex(interp, listObj, rangeStart, &itemPtr);
if (
Tcl_ListObjAppendElement(interp, resPtr, itemPtr) != TCL_OK
) {
Tcl_DecrRefCount(resPtr);
return NULL;
}
rangeStart++;
}
return resPtr;
}
static Tcl_Obj*
indexHexListObjRangeEnd(tclObjTypeInterfaceArgsListRangeEnd) {
if (fromAnchor == 1 || toAnchor == 1) {
indexHexListErrorIndeterminate(interp);
return NULL;
}
return indexHexListObjRange(interp, listPtr, fromIdx, toIdx);
}
static int
indexHexListObjReplace(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */ \
TCL_UNUSED(Tcl_Obj *), /* List object whose elements to replace. */ \
TCL_UNUSED(Tcl_Size), /* Index of first element to replace. */ \
TCL_UNUSED(Tcl_Size), /* Number of elements to replace. */ \
TCL_UNUSED(Tcl_Size), /* Number of objects to insert. */ \
/* An array of objc pointers to Tcl \
* objects to insert. */ \
TCL_UNUSEDVAR(Tcl_Obj *const insertObjs[])
)
{
indexHexListErrorReadOnly(interp);
return TCL_ERROR;
}
static int
indexHexListObjSetElement(
Tcl_Interp *interp, /* Tcl interpreter; used for error reporting
* if not NULL. */
TCL_UNUSED(Tcl_Obj *), /* List object in which element should be
* stored. */
TCL_UNUSED(Tcl_Size), /* Index of element to store. */
TCL_UNUSED(Tcl_Obj *)/* Tcl object to store in the designated list
* element. */
)
{
indexHexListErrorReadOnly(interp);
return TCL_ERROR;
}
static Tcl_Obj * indexHexLsetFlat (
Tcl_Interp *interp, /* Tcl interpreter. */ \
TCL_UNUSED(Tcl_Obj *), /* Pointer to the list being modified. */ \
TCL_UNUSED(Tcl_Size), /* Number of index args. */ \
TCL_UNUSEDVAR(Tcl_Obj *const indexArray[]), /* Index args. */ \
TCL_UNUSED(Tcl_Obj *) /* Value arg to 'lset' or NULL to 'lpop'. */
)
{
indexHexListErrorReadOnly(interp);
return NULL;
}
+683
View File
@@ -0,0 +1,683 @@
/*
* tclTestObjInterfce.c --
*
* This file contains C command functions for the additional Tcl commands
* that are used for testing implementations of the Tcl object types.
* These commands are not normally included in Tcl applications; they're
* only used for testing.
*
* Copyright © 2021 Nathan Coulter
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tcl.h"
#include "tclInt.h"
/*
* Prototypes for functions defined later in this file:
*/
int TestListInteger (
ClientData, Tcl_Interp *interp, Tcl_Size argc, Tcl_Obj *const objv[]);
static Tcl_Obj* NewTestListInteger();
static void DupTestListIntegerInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void FreeTestListIntegerInternalRep(Tcl_Obj *objPtr);
static int SetTestListIntegerFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void UpdateStringOfTestListInteger(Tcl_Obj *listPtr);
static int ListIntegerListStringIndex (tclObjTypeInterfaceArgsStringIndex);
static int ListIntegerListStringIndexEnd(tclObjTypeInterfaceArgsStringIndexEnd);
static Tcl_Size ListIntegerListStringLength(tclObjTypeInterfaceArgsStringLength);
/*
static int ListIntegerStringListIndexFromStringIndex(
Tcl_Size *index, Tcl_Size *itemchars, Tcl_Size *totalitems);
*/
static Tcl_Obj* ListIntegerListStringRange(tclObjTypeInterfaceArgsStringRange);
static Tcl_Obj* ListIntegerListStringRangeEnd(tclObjTypeInterfaceArgsStringRangeEnd);
static int ListIntegerListObjGetElements(tclObjTypeInterfaceArgsListAll);
static int ListIntegerListObjAppendElement(tclObjTypeInterfaceArgsListAppend);
static int ListIntegerListObjAppendList(tclObjTypeInterfaceArgsListAppendList);
static int ListIntegerListObjIndex(tclObjTypeInterfaceArgsListIndex);
static int ListIntegerListObjIndexEnd (tclObjTypeInterfaceArgsListIndexEnd);
static int ListIntegerListObjIsSorted(tclObjTypeInterfaceArgsListIsSorted);
static int ListIntegerListObjLength(tclObjTypeInterfaceArgsListLength);
static Tcl_Obj* ListIntegerListObjRange(tclObjTypeInterfaceArgsListRange);
static Tcl_Obj* ListIntegerListObjRangeEnd(tclObjTypeInterfaceArgsListRangeEnd);
static int ListIntegerListObjReplace(tclObjTypeInterfaceArgsListReplace);
static int ListIntegerListObjReplaceList(tclObjTypeInterfaceArgsListReplaceList);
static int ListIntegerListObjSetElement(tclObjTypeInterfaceArgsListSet);
static Tcl_Obj * ListIntegerLsetFlat(tclObjTypeInterfaceArgsListSetList);
static int ErrorMaxElementsExceeded(Tcl_Interp *interp);
ObjInterface ListIntegerInterface = {
1,
{
&ListIntegerListStringIndex,
&ListIntegerListStringIndexEnd,
&ListIntegerListStringLength,
&ListIntegerListStringRange,
&ListIntegerListStringRangeEnd
},
{
&ListIntegerListObjGetElements,
&ListIntegerListObjAppendElement,
&ListIntegerListObjAppendList,
&ListIntegerListObjIndex,
&ListIntegerListObjIndexEnd,
&ListIntegerListObjIsSorted,
&ListIntegerListObjLength,
&ListIntegerListObjRange,
&ListIntegerListObjRangeEnd,
&ListIntegerListObjReplace,
&ListIntegerListObjReplaceList,
NULL,
&ListIntegerListObjSetElement,
&ListIntegerLsetFlat
}
};
typedef struct ListInteger {
int refCount;
int ownstring;
int size;
int used;
int values[1];
} ListInteger;
static ListInteger* NewTestListIntegerIntrep();
static ListInteger* ListGetInternalRep(Tcl_Obj *listPtr);
static void ListIntegerDecrRefCount(ListInteger *listIntegerPtr);
const ObjectType testListIntegerType = {
"testListInteger",
FreeTestListIntegerInternalRep, /* freeIntRepProc */
DupTestListIntegerInternalRep, /* dupIntRepProc */
UpdateStringOfTestListInteger, /* updateStringProc */
SetTestListIntegerFromAny, /* setFromAnyProc */
2,
(Tcl_ObjInterface *)&ListIntegerInterface
};
const Tcl_ObjType *testListIntegerTypePtr = (Tcl_ObjType *)&testListIntegerType;
int TcltestObjectInterfaceListIntegerInit(Tcl_Interp *interp) {
Tcl_CreateObjCommand2(interp, "testlistinteger", TestListInteger, NULL, NULL);
return TCL_OK;
}
int TestListInteger(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_Size argc,
Tcl_Obj *const objv[])
{
int status;
if (argc != 2) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # arguments", -1));
}
return TCL_ERROR;
}
status = Tcl_ConvertToType(interp, objv[1], testListIntegerTypePtr);
Tcl_SetObjResult(interp, objv[1]);
return status;
}
Tcl_Obj*
NewTestListInteger() {
Tcl_ObjInternalRep intrep;
Tcl_Obj *listPtr = Tcl_NewObj();
Tcl_InvalidateStringRep(listPtr);
ListInteger *listIntegerPtr = NewTestListIntegerIntrep();
intrep.twoPtrValue.ptr1 = listIntegerPtr;
Tcl_StoreInternalRep(listPtr, testListIntegerTypePtr, &intrep);
return listPtr;
}
ListInteger*
NewTestListIntegerIntrep() {
ListInteger *listIntegerPtr = (ListInteger *)Tcl_Alloc(sizeof(ListInteger));
listIntegerPtr->refCount = 1;
listIntegerPtr->ownstring = 0;
listIntegerPtr->size = 1;
listIntegerPtr->used = 0;
return listIntegerPtr;
}
static ListInteger* ListGetInternalRep(Tcl_Obj *listPtr) {
return (ListInteger *)listPtr->internalRep.twoPtrValue.ptr1;
}
static void DupTestListIntegerInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) {
Tcl_ObjInternalRep intrep;
ListInteger *listRepPtr = ListGetInternalRep(srcPtr);
listRepPtr->refCount++;
intrep.twoPtrValue.ptr1 = listRepPtr;
Tcl_StoreInternalRep(copyPtr, testListIntegerTypePtr, &intrep);
return;
}
static void FreeTestListIntegerInternalRep(Tcl_Obj *listPtr) {
ListInteger *listRepPtr = ListGetInternalRep(listPtr);
ListIntegerDecrRefCount(listRepPtr);
return;
}
static int SetTestListIntegerFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) {
int status;
Tcl_Size i, length;
Tcl_Obj *itemPtr, *listPtr;
Tcl_ObjInternalRep intrep;
ListInteger *listRepPtr;
if (TclHasInternalRep(objPtr, testListIntegerTypePtr)) {
return TCL_OK;
} else {
status = Tcl_ListObjLength(interp, objPtr, &length);
if (status != TCL_OK) {
return TCL_ERROR;
}
listPtr = NewTestListInteger();
for (i = 0; i < length; i++) {
status = Tcl_ListObjIndex(interp, objPtr, i, &itemPtr);
if (status != TCL_OK) {
Tcl_DecrRefCount(listPtr);
return status;
}
status = ListIntegerListObjReplace(interp, listPtr, i, 0, 1, &itemPtr);
if (status != TCL_OK) {
Tcl_DecrRefCount(listPtr);
return status;
}
}
listRepPtr = ListGetInternalRep(listPtr);
intrep.twoPtrValue.ptr1 = listRepPtr;
listRepPtr->refCount++;
Tcl_StoreInternalRep(objPtr, testListIntegerTypePtr, &intrep);
Tcl_DecrRefCount(listPtr);
return TCL_OK;
}
}
static void UpdateStringOfTestListInteger(Tcl_Obj *listPtr) {
ListInteger *listRepPtr = ListGetInternalRep(listPtr);
int i, num, used = listRepPtr->used;
Tcl_Obj *strPtr, *numObjPtr;
if (used > 0) {
strPtr = Tcl_NewObj();
Tcl_IncrRefCount(strPtr);
num = listRepPtr->values[0];
numObjPtr = Tcl_NewIntObj(num);
Tcl_IncrRefCount(numObjPtr);
Tcl_AppendFormatToObj(NULL, strPtr, "%d", 1, &numObjPtr);
Tcl_DecrRefCount(numObjPtr);
for (i = 1; i < used; i++) {
num = listRepPtr->values[i];
numObjPtr = Tcl_NewIntObj(num);
Tcl_IncrRefCount(numObjPtr);
Tcl_AppendFormatToObj(NULL, strPtr, " %d", 1, &numObjPtr);
Tcl_DecrRefCount(numObjPtr);
}
listPtr->bytes = strPtr->bytes;
listPtr->length = strPtr->length;
strPtr->bytes = 0;
strPtr->length = 0;
Tcl_DecrRefCount(strPtr);
} else {
Tcl_InitStringRep(listPtr, NULL, 0);
}
listRepPtr->ownstring = 1;
return;
}
static void ListIntegerDecrRefCount(ListInteger *listIntegerPtr) {
if (--listIntegerPtr->refCount <= 0) {
Tcl_Free(listIntegerPtr);
}
return;
}
static int ListIntegerListStringIndex (
TCL_UNUSED(Tcl_Interp *),/* Used to report errors if not NULL. */ \
TCL_UNUSED(Tcl_Obj *), /* List object to index into. */ \
TCL_UNUSED(Tcl_Size), /* Index of element to return. */ \
TCL_UNUSED(Tcl_Obj **)/* The resulting Tcl_Obj* is stored here. */
)
{
return TCL_ERROR;
}
static int ListIntegerListStringIndexEnd(
TCL_UNUSED(Tcl_Interp *),/* Used to report errors if not NULL. */ \
TCL_UNUSED(Tcl_Obj *),/* List object to index into. */ \
TCL_UNUSED(Tcl_Size),/* Index of element to return. */ \
TCL_UNUSED(Tcl_Obj **)/* The resulting Tcl_Obj* is stored here. */
) {
return TCL_ERROR;
}
static Tcl_Size ListIntegerListStringLength(
TCL_UNUSED(Tcl_Obj *);
) {
return TCL_ERROR;
}
/*
static int ListIntegerStringListIndexFromStringIndex(
TCL_UNUSEDVAR(Tcl_Size *index),
TCL_UNUSEDVAR(Tcl_Size *itemchars),
TCL_UNUSEDVAR(Tcl_Size *totalitems)
) {
return TCL_ERROR;
}
*/
static Tcl_Obj* ListIntegerListStringRange(
TCL_UNUSEDVAR(Tcl_Obj *objPtr), /* The Tcl object to find the range of. */
TCL_UNUSEDVAR(Tcl_Size first), /* First index of the range. */
TCL_UNUSEDVAR(Tcl_Size last) /* Last index of the range. */
) {
return NULL;
}
static Tcl_Obj* ListIntegerListStringRangeEnd(
TCL_UNUSED(Tcl_Obj *),/* The Tcl object to find the range of. */
TCL_UNUSED(Tcl_Size),/* First index of the range. */
TCL_UNUSED(Tcl_Size) /* Last index of the range. */
) {
return NULL;
}
static int ListIntegerListObjGetElements(
TCL_UNUSEDVAR(Tcl_Interp *interp), /* Used to report errors if not NULL. */
TCL_UNUSEDVAR(Tcl_Obj *listPtr), /* List object for which an element array
* is to be returned. */
TCL_UNUSEDVAR(Tcl_Size *objcPtr), /* Where to store the count of objects
* referenced by objv. */
TCL_UNUSEDVAR(Tcl_Obj ***objvPtr) /* Where to store the pointer to an
* array of */
) {
ListInteger *listRepPtr;
listRepPtr = ListGetInternalRep(listPtr);
*objcPtr = listRepPtr->used;
*objvPtr = listRepPtr->values;
return TCL_OK;
}
static int ListIntegerListObjAppendElement(tclObjTypeInterfaceArgsListAppend) {
int status;
Tcl_Size length;
status = Tcl_ListObjLength(interp, listPtr, &length);
if (status != TCL_OK) {
return TCL_ERROR;
}
return ListIntegerListObjReplace(interp, listPtr, length, 0, 1, &objPtr);
}
static int ListIntegerListObjAppendList(
TCL_UNUSEDVAR(Tcl_Interp *interp), /* Used to report errors if not NULL. */ \
TCL_UNUSEDVAR(Tcl_Obj *listPtr), /* List object to append elements to. */ \
TCL_UNUSEDVAR(Tcl_Obj *elemListPtr) /* List obj with elements to append. */
) {
return TCL_ERROR;
}
static int ListIntegerListObjIndex(
TCL_UNUSED(Tcl_Interp *),/* Used to report errors if not NULL. */ \
Tcl_Obj * listObj,/* List object to index into. */ \
Tcl_Size index, /* Index of element to return. */ \
Tcl_Obj **objPtrPtr /* The resulting Tcl_Obj* is stored here. */
) {
ListInteger *listRepPtr = ListGetInternalRep(listObj);
Tcl_Size num;
if (index >= 0 && index < listRepPtr->used) {
num = listRepPtr->values[index];
*objPtrPtr = Tcl_NewLongObj(num);
} else {
*objPtrPtr = NULL;
}
return TCL_OK;
}
static int ListIntegerListObjIndexEnd(
TCL_UNUSED(Tcl_Interp *),/* Used to report errors if not NULL. */ \
TCL_UNUSED(Tcl_Obj *),/* List object to index into. */ \
TCL_UNUSED(Tcl_Size),/* Index of element to return. */ \
TCL_UNUSED(Tcl_Obj **)/* The resulting Tcl_Obj* is stored here. */
) {
return TCL_ERROR;
}
static int ListIntegerListObjIsSorted(
TCL_UNUSED(Tcl_Interp *), /* Used to report errors */
TCL_UNUSED(Tcl_Obj *), /* The list in question */
TCL_UNUSED(size_t) /* flags */
) {
return TCL_ERROR;
}
static int ListIntegerListObjLength(
TCL_UNUSED(Tcl_Interp *), /* Used to report errors if not NULL. */
Tcl_Obj * listObj, /* List object whose #elements to return. */
Tcl_Size *lenPtr /* The resulting length is stored here. */
) {
ListInteger *listRepPtr = ListGetInternalRep(listObj);
*lenPtr = listRepPtr->used;
return TCL_OK;
}
static Tcl_Obj* ListIntegerListObjRange(tclObjTypeInterfaceArgsListRange) {
ListInteger *listRepPtr = ListGetInternalRep(listObj);
Tcl_Size i, j, num, used = listRepPtr->used;
Tcl_Obj *numObjPtr, *resPtr;
if ((rangeStart == 0 && rangeEnd >= used - 1) || used == 0) {
return listObj;
}
if (Tcl_IsShared(listObj) ||
((listRepPtr->refCount > 1))) {
if (rangeStart >= used || rangeEnd < rangeStart) {
return Tcl_NewObj();
} else {
resPtr = NewTestListInteger();
for (i = rangeStart, j = 0; i <= rangeEnd; i++, j++) {
num = listRepPtr->values[i];
numObjPtr = Tcl_NewIntObj(num);
Tcl_IncrRefCount(numObjPtr);
if (ListIntegerListObjReplace(
interp, resPtr, j , 0 , 1 ,&numObjPtr) != TCL_OK) {
Tcl_DecrRefCount(resPtr);
Tcl_DecrRefCount(numObjPtr);
return NULL;
}
Tcl_DecrRefCount(numObjPtr);
}
return resPtr;
}
}
return NULL;
}
static Tcl_Obj* ListIntegerListObjRangeEnd(
TCL_UNUSEDVAR(Tcl_Interp * interp), /* Used to report errors */ \
TCL_UNUSEDVAR(Tcl_Obj *listPtr), /* List object to take a range from. */ \
TCL_UNUSEDVAR(Tcl_Size fromAnchor),/* 0 for start and 1 for end */ \
TCL_UNUSEDVAR(Tcl_Size fromIdx), /* Index of first element to include. */ \
TCL_UNUSEDVAR(Tcl_Size toAnchor), /* 0 for start and 1 for end */ \
TCL_UNUSEDVAR(Tcl_Size toIdx) /* Index of last element to include. */
) {
return NULL;
}
static int ListIntegerListObjReplace(tclObjTypeInterfaceArgsListReplace) {
int i, status;
Tcl_Obj *tmpListPtr = Tcl_NewObj();
Tcl_IncrRefCount(tmpListPtr);
for (i = 0; i < numToInsert; i++) {
status = Tcl_ListObjAppendElement(interp, tmpListPtr, insertObjs[i]);
if (status != TCL_OK) {
Tcl_DecrRefCount(tmpListPtr);
return status;
}
}
status = ListIntegerListObjReplaceList(
interp, listObj, first, numToDelete, tmpListPtr);
Tcl_DecrRefCount(tmpListPtr);
return status;
}
static int ListIntegerListObjReplaceList(tclObjTypeInterfaceArgsListReplaceList) {
ListInteger *listRepPtr = ListGetInternalRep(listPtr);
ListInteger *newListRepPtr;
int changed = 0, itemInt, status;
Tcl_Size i, index, newmemsize, itemsLength, j, newsize,
newtailindex, newused, size, newtailend, tailindex, tailsize,
used;
Tcl_Obj *itemPtr;
size = listRepPtr->size;
used = listRepPtr->used;
if (first < used) {
tailsize = used - first;
} else {
tailsize = 0;
}
status = Tcl_ListObjLength(interp, newItemsPtr, &itemsLength);
if (status != TCL_OK) {
return TCL_ERROR;
}
/* Currently this duplicates checks found in of Tcl_ListObjReplace, but
* maybe in the future Tcl remove those checks
*/
if (first >= used) {
first = used;
} else if (first < 0) {
first = 0;
}
if (count > tailsize) {
count = tailsize;
}
/* If count == 0 and itemsLength == 0 this routine is logically a no-op,
* but any non-canonical string representation must still be invalidated.
*/
/* to do:
* Recode this routine to work with incoming of unbounded length
*/
if (used > 0) {
tailindex = first + count;
newtailindex = first + itemsLength;
if (INT_MAX - tailsize - 1 < newtailindex) {
return ErrorMaxElementsExceeded(interp);
}
newused = newtailindex + tailsize;
if (itemsLength > 0 && INT_MAX - itemsLength < newused) {
return ErrorMaxElementsExceeded(interp);
}
} else {
tailindex = 0;
newtailindex = 0;
newused = itemsLength;
}
if (newused > size && newused > 1) {
newsize = (newused + newused / 5 + 1);
if (newsize < size) {
return ErrorMaxElementsExceeded(interp);
}
} else {
newsize = size;
}
if (!listRepPtr->ownstring) {
/* schedule canonicalization of the string rep */
Tcl_InvalidateStringRep(listPtr);
listRepPtr->ownstring = 1;
}
if (newused < used) {
Tcl_InvalidateStringRep(listPtr);
}
newmemsize = sizeof(ListInteger) + newsize * sizeof(int) - sizeof(int);
if (listRepPtr->refCount > 1) {
Tcl_ObjInternalRep intrep;
/* copy only the structure and the head of the old array */
int movsize = sizeof(ListInteger)
+ ((first + 1) * sizeof(int) - sizeof(int));
newListRepPtr = (ListInteger *)Tcl_Alloc(newmemsize);
memmove(newListRepPtr, listRepPtr, movsize);
newListRepPtr->size = newsize;
newListRepPtr->refCount = 1;
/* move the tail to its new location to make room for the new additions
*/
memmove(newListRepPtr->values + newtailindex,
listRepPtr->values + tailindex, tailsize * sizeof(int));
intrep.twoPtrValue.ptr1 = newListRepPtr;
Tcl_StoreInternalRep(listPtr, testListIntegerTypePtr, &intrep);
} else {
if (newsize > size && newused > 1) {
newListRepPtr = (ListInteger *)Tcl_Realloc(listRepPtr, newmemsize);
} else {
newListRepPtr = listRepPtr;
}
newListRepPtr->size = newsize;
if (tailsize > 0 && tailindex != newtailindex) {
/* move the tail to its new location to make room for the new
* additions */
memmove(newListRepPtr->values + newtailindex,
newListRepPtr->values + tailindex, tailsize);
}
listPtr->internalRep.twoPtrValue.ptr1 = newListRepPtr;
}
i = -1;
while (1) {
i++;
index = first + i;
status = Tcl_ListObjIndex(interp, newItemsPtr, i, &itemPtr);
if (status != TCL_OK) {
return status;
}
if (itemPtr == NULL) {
break;
}
if (Tcl_GetIntFromObj(interp, itemPtr, &itemInt)
== TCL_OK) {
if (newListRepPtr->values[index] != itemInt) {
changed = 1;
newListRepPtr->values[index] = itemInt;
}
newListRepPtr->values[index] = itemInt;
} else {
Tcl_Obj *realListPtr;
/* Fall back to normal list */
realListPtr = Tcl_NewListObj(newsize, NULL);
Tcl_IncrRefCount(realListPtr);
for (j = 0; j < index; j++) {
itemPtr = Tcl_NewIntObj(newListRepPtr->values[j]);
status = Tcl_ListObjAppendElement(
interp, realListPtr, itemPtr);
if (status != TCL_OK) {
Tcl_DecrRefCount(realListPtr);
return status;
}
}
while (1) {
if (itemsLength == TCL_LENGTH_NONE) {
status = Tcl_ListObjLength(interp, newItemsPtr, &itemsLength);
if (status != TCL_OK) {
Tcl_DecrRefCount(realListPtr);
return status;
}
}
if (itemsLength != TCL_LENGTH_NONE && i >= itemsLength) {
break;
}
status = Tcl_ListObjIndex(interp, newItemsPtr, i, &itemPtr);
if (status != TCL_OK) {
Tcl_DecrRefCount(realListPtr);
return status;
}
if (itemPtr == NULL) {
break;
}
status = Tcl_ListObjAppendElement(
interp, realListPtr, itemPtr);
if (status != TCL_OK) {
Tcl_DecrRefCount(realListPtr);
return status;
}
i++;
}
newtailend = newtailindex + tailsize;
for (i = newtailindex; i < newtailend; i++) {
itemPtr = Tcl_NewIntObj(newListRepPtr->values[i]);
Tcl_ListObjAppendElement(interp, realListPtr, itemPtr);
if (status != TCL_OK) {
Tcl_DecrRefCount(realListPtr);
return status;
}
}
ListIntegerDecrRefCount(newListRepPtr);
listPtr->internalRep = realListPtr->internalRep;
listPtr->typePtr = realListPtr->typePtr;
realListPtr->typePtr = NULL;
Tcl_DecrRefCount(realListPtr);
/* this might not always be necessary, but probably the best that
* can be done in this case */
Tcl_InvalidateStringRep(listPtr);
return TCL_OK;
}
}
if (changed) {
Tcl_InvalidateStringRep(listPtr);
}
/* To make the operation transactional, update "used" only after all
* elemnts have been succesfully added.
*/
newListRepPtr->used = newused;
return TCL_OK;
}
static int ListIntegerListObjSetElement(
TCL_UNUSED(Tcl_Interp *), /* Tcl interpreter; used for error reporting
* if not NULL. */
TCL_UNUSED(Tcl_Obj *), /* List object in which element should be
* stored. */
TCL_UNUSED(Tcl_Size), /* Index of element to store. */
TCL_UNUSED(Tcl_Obj *) /* Tcl object to store in the designated list
* element. */
) {
return TCL_ERROR;
}
static Tcl_Obj * ListIntegerLsetFlat(
TCL_UNUSED(Tcl_Interp *), /* Tcl interpreter. */ \
TCL_UNUSED(Tcl_Obj *), /* Pointer to the list being modified. */ \
TCL_UNUSED(Tcl_Size), /* Number of index args. */ \
TCL_UNUSEDVAR(Tcl_Obj *const indexArray[]), /* Index args. */ \
TCL_UNUSED(Tcl_Obj *)/* Value arg to 'lset' or NULL to 'lpop'. */
) {
return NULL;
}
static int ErrorMaxElementsExceeded(Tcl_Interp *interp) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"max length of a Tcl list (%" TCL_T_MODIFIER "d elements) exceeded",
LIST_MAX));
}
return TCL_ERROR;
}
+46 -23
View File
@@ -123,24 +123,16 @@ static int FindElement(Tcl_Interp *interp, const char *string,
* is unregistered, so has no need of a setFromAnyProc either.
*/
static const TclObjTypeWithAbstractList endOffsetType = {
{"end-offset", /* name */
static const Tcl_ObjType endOffsetType = {
"end-offset", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
NULL, /* updateStringProc */
NULL, /* setFromAnyProc */
TCL_OBJTYPE_V0_1(
TclLengthOne
)}
0
};
Tcl_Size
TclLengthOne(
TCL_UNUSED(Tcl_Obj *))
{
return 1;
}
/*
* * STRING REPRESENTATION OF LISTS * * *
*
@@ -2005,7 +1997,7 @@ Tcl_ConcatObj(
}
} else {
resPtr = TclDuplicatePureObj(
NULL, objPtr, &tclListType.objType);
NULL, objPtr, tclListType);
if (!resPtr) {
return NULL;
}
@@ -3497,7 +3489,7 @@ GetEndOffsetFromObj(
Tcl_WideInt offset = -1; /* Offset in the "end-offset" expression - 1 */
void *cd;
while ((irPtr = TclFetchInternalRep(objPtr, &endOffsetType.objType)) == NULL) {
while ((irPtr = TclFetchInternalRep(objPtr, &endOffsetType)) == NULL) {
Tcl_ObjInternalRep ir;
Tcl_Size length;
const char *bytes = Tcl_GetStringFromObj(objPtr, &length);
@@ -3509,13 +3501,10 @@ GetEndOffsetFromObj(
/* Value doesn't start with "e" */
/* If we reach here, the string rep of objPtr exists. */
/*
* The valid index syntax does not include any value that is
* a list of more than one element. This is necessary so that
* lists of index values can be reliably distinguished from any
* single index value.
* So that lists of index values can be reliably distinguished from
* any single index value, the valid index syntax does not include
* any value that is a list of more than one element.
*/
/*
@@ -3633,6 +3622,7 @@ GetEndOffsetFromObj(
/* Doesn't start with "end" */
goto parseError;
}
if (length > 4) {
int t;
@@ -3683,7 +3673,7 @@ GetEndOffsetFromObj(
parseOK:
/* Success. Store the new internal rep. */
ir.wideValue = offset;
Tcl_StoreInternalRep(objPtr, &endOffsetType.objType, &ir);
Tcl_StoreInternalRep(objPtr, &endOffsetType, &ir);
}
offset = irPtr->wideValue;
@@ -3740,7 +3730,7 @@ GetEndOffsetFromObj(
*
* Parse objPtr to determine if it is an index value. Two cases
* are possible. The value objPtr might be parsed as an absolute
* index value in the Tcl_Size range. Note that this includes
* index value in the Tcl_Size range. This includes
* index values that are integers as presented and it includes index
* arithmetic expressions.
*
@@ -3835,7 +3825,7 @@ TclIndexEncode(
*/
const Tcl_ObjInternalRep *irPtr =
TclFetchInternalRep(objPtr, &endOffsetType.objType);
TclFetchInternalRep(objPtr, &endOffsetType);
if (irPtr && irPtr->wideValue >= 0) {
/*
@@ -3956,6 +3946,39 @@ TclIndexDecode(
return TCL_INDEX_NONE;
}
int TclIndexIsFromEnd(Tcl_Size index) {
return index <= 0;
}
/*
*----------------------------------------------------------------------
*
* TclIndexLast --
*
* Determine the last index for an array of length "length", where -1 means N is
* not bounded.
*
*----------------------------------------------------------------------
*/
Tcl_Size
TclIndexLast (Tcl_Size length) {
return Tcl_LengthIsFinite(length) ? length - 1 : TCL_INDEX_NONE;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LengthIsFinite --
*
* True if length is Finite.
*
*----------------------------------------------------------------------
*/
int
Tcl_LengthIsFinite(Tcl_Size length) {
return length != TCL_LENGTH_NONE;
}
/*
*------------------------------------------------------------------------
*
+2 -2
View File
@@ -3097,7 +3097,7 @@ ArrayForNRCmd(
* loop) don't vanish.
*/
varListObj = TclDuplicatePureObj(interp, objv[1], &tclListType.objType);
varListObj = TclDuplicatePureObj(interp, objv[1], tclListType);
if (!varListObj) {
return TCL_ERROR;
}
@@ -4074,7 +4074,7 @@ ArraySetCmd(
*/
copyListObj =
TclDuplicatePureObj(interp, arrayElemObj, &tclListType.objType);
TclDuplicatePureObj(interp, arrayElemObj, tclListType);
if (!copyListObj) {
return TCL_ERROR;
}
Regular → Executable
View File
+125 -96
View File
@@ -16,104 +16,133 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
catch {unset lis}
catch {rename p ""}
proc newlist list {
return $list
}
test linsert-1.1 {linsert command} {
linsert {1 2 3 4 5} 0 a
} {a 1 2 3 4 5}
test linsert-1.2 {linsert command} {
linsert {1 2 3 4 5} 1 a
} {1 a 2 3 4 5}
test linsert-1.3 {linsert command} {
linsert {1 2 3 4 5} 2 a
} {1 2 a 3 4 5}
test linsert-1.4 {linsert command} {
linsert {1 2 3 4 5} 3 a
} {1 2 3 a 4 5}
test linsert-1.5 {linsert command} {
linsert {1 2 3 4 5} 4 a
} {1 2 3 4 a 5}
test linsert-1.6 {linsert command} {
linsert {1 2 3 4 5} 5 a
} {1 2 3 4 5 a}
test linsert-1.7 {linsert command} {
linsert {1 2 3 4 5} 2 one two \{three \$four
} {1 2 one two \{three {$four} 3 4 5}
test linsert-1.8 {linsert command} {
linsert {\{one \$two \{three \ four \ five} 2 a b c
} {\{one {$two} a b c \{three { four} { five}}
test linsert-1.9 {linsert command} {
linsert {{1 2} {3 4} {5 6} {7 8}} 2 {x y} {a b}
} {{1 2} {3 4} {x y} {a b} {5 6} {7 8}}
test linsert-1.10 {linsert command} {
linsert {} 2 a b c
} {a b c}
test linsert-1.11 {linsert command} {
linsert {} 2 {}
} {{}}
test linsert-1.12 {linsert command} {
linsert {a b "c c" d e} 3 1
} {a b {c c} 1 d e}
test linsert-1.13 {linsert command} {
linsert { a b c d} 0 1 2
} {1 2 a b c d}
test linsert-1.14 {linsert command} {
linsert {a b c {d e f}} 4 1 2
} {a b c {d e f} 1 2}
test linsert-1.15 {linsert command} {
linsert {a b c \{\ abc} 4 q r
} {a b c \{\ q r abc}
test linsert-1.16 {linsert command} {
linsert {a b c \{ abc} 4 q r
} {a b c \{ q r abc}
test linsert-1.17 {linsert command} {
linsert {a b c} end q r
} {a b c q r}
test linsert-1.18 {linsert command} {
linsert {a} end q r
} {a q r}
test linsert-1.19 {linsert command} {
linsert {} end q r
} {q r}
test linsert-1.20 {linsert command, use of end-int index} {
linsert {a b c d} end-2 e f
} {a b e f c d}
variable tests {
test linsert-2.1 {linsert errors} {
list [catch linsert msg] $msg
} {1 {wrong # args: should be "linsert list index ?element ...?"}}
test linsert-2.2 {linsert errors} {
list [catch {linsert a b} msg] $msg
} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test linsert-2.3 {linsert errors} {
list [catch {linsert a 12x 2} msg] $msg
} {1 {bad index "12x": must be integer?[+-]integer? or end?[+-]integer?}}
test linsert-2.4 {linsert errors} {
list [catch {linsert \{ 12 2} msg] $msg
} {1 {unmatched open brace in list}}
test linsert-2.5 {syntax (TIP 323)} {
linsert {a b c} 0
} [list a b c]
test linsert-2.6 {syntax (TIP 323)} {
linsert "a\nb\nc" 0
} [list a b c]
foreach map {
{
@mode@ compiled
@linsert@ linsert
}
{
@mode@ uncompiled
@linsert@ {[lindex linsert]}
}
} {
set script [string map $map {
catch {unset lis}
catch {rename p ""}
test linsert-3.1 {linsert won't modify shared argument objects} {
proc p {} {
linsert "a b c" 1 "x y"
return "a b c"
test linsert-1.1-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 0 a
} {a 1 2 3 4 5}
test linsert-1.2-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 1 a
} {1 a 2 3 4 5}
test linsert-1.3-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 2 a
} {1 2 a 3 4 5}
test linsert-1.4-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 3 a
} {1 2 3 a 4 5}
test linsert-1.5-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 4 a
} {1 2 3 4 a 5}
test linsert-1.6-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 5 a
} {1 2 3 4 5 a}
test linsert-1.7-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 2 one two \{three \$four
} {1 2 one two \{three {$four} 3 4 5}
test linsert-1.8-@mode@ {linsert command} {
@linsert@ [newlist {\{one \$two \{three \ four \ five}] 2 a b c
} {\{one {$two} a b c \{three { four} { five}}
test linsert-1.9-@mode@ {linsert command} {
@linsert@ [newlist {{1 2} {3 4} {5 6} {7 8}}] 2 {x y} {a b}
} {{1 2} {3 4} {x y} {a b} {5 6} {7 8}}
test linsert-1.10-@mode@ {linsert command} {
@linsert@ [newlist {}] 2 a b c
} {a b c}
test linsert-1.11-@mode@ {linsert command} {
@linsert@ [newlist {}] 2 {}
} {{}}
test linsert-1.12-@mode@ {linsert command} {
@linsert@ [newlist {a b "c c" d e}] 3 1
} {a b {c c} 1 d e}
test linsert-1.13-@mode@ {linsert command} {
@linsert@ [newlist { a b c d}] 0 1 2
} {1 2 a b c d}
test linsert-1.14-@mode@ {linsert command} {
@linsert@ [newlist {a b c {d e f}}] 4 1 2
} {a b c {d e f} 1 2}
test linsert-1.15-@mode@ {linsert command} {
@linsert@ [newlist {a b c \{\ abc}] 4 q r
} {a b c \{\ q r abc}
test linsert-1.16-@mode@ {linsert command} {
@linsert@ [newlist {a b c \{ abc}] 4 q r
} {a b c \{ q r abc}
test linsert-1.17-@mode@ {linsert command} {
@linsert@ [newlist {a b c}] end q r
} {a b c q r}
test linsert-1.18-@mode@ {linsert command} {
@linsert@ [newlist {a}] end q r
} {a q r}
test linsert-1.19-@mode@ {linsert command} {
@linsert@ [newlist {}] end q r
} {q r}
test linsert-1.20-@mode@ {linsert command, use of end-int index} {
@linsert@ [newlist {a b c d}] end-2 e f
} {a b e f c d}
test linsert-2.1-@mode@ {linsert errors} {
list [catch @linsert@ [newlist msg]] $msg
} {1 {wrong # args: should be "linsert list index ?element ...?"}}
test linsert-2.2-@mode@ {linsert errors} {
list [catch {@linsert@ [newlist a] b} msg] $msg
} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test linsert-2.3-@mode@ {linsert errors} {
list [catch {@linsert@ [newlist a] 12x 2} msg] $msg
} {1 {bad index "12x": must be integer?[+-]integer? or end?[+-]integer?}}
test linsert-2.4-@mode@ {linsert errors} {
list [catch {@linsert@ [newlist \{] 12 2} msg] $msg
} {1 {unmatched open brace in list}}
test linsert-2.5-@mode@ {syntax (TIP 323)} {
@linsert@ [newlist {a b c}] 0
} [list a b c]
test linsert-2.6-@mode@ {syntax (TIP 323)} {
@linsert@ [newlist "a\nb\nc"] 0
} [list a b c]
test linsert-3.1-@mode@ {linsert won't modify shared argument objects} {
proc p {} {
set list "a b c"
@linsert@ [newlist $list] 1 "x y"
return "a b c"
}
p
} "a b c"
test linsert-3.2-@mode@ {linsert won't modify shared argument objects} {
catch {unset lis}
puts boom
set lis [format "a \"%s\" c" "b"]
@linsert@ [newlist $lis] 0 [string length $lis]
} "7 a b c"
# cleanup
catch {unset lis}
catch {rename p ""}
}]
try $script
}
p
} "a b c"
test linsert-3.2 {linsert won't modify shared argument objects} {
catch {unset lis}
set lis [format "a \"%s\" c" "b"]
linsert $lis 0 [string length $lis]
} "7 a b c"
}
# cleanup
catch {unset lis}
catch {rename p ""}
::tcltest::cleanupTests
return
if {[info exists ::argv0] && [info script] eq $::argv0} {
try $tests
::tcltest::cleanupTests
return
}
+1
View File
@@ -318,6 +318,7 @@ test lseq-3.14 {array for shimmer} -constraints arithSeriesShimmerOk -body {
array set testarray {a Test for This great Function}
set vars [lseq 2]
set vars-rep [lindex [tcl::unsupported::representation $vars] 3]
after 1
array for $vars testarray {
lappend keys $0
lappend vals $1
+469 -438
View File
@@ -19,462 +19,493 @@ if {"::tcltest" ni [namespace children]} {
::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]
proc failTrace {name1 name2 op} {
error "trace failed"
}
testConstraint testevalex [llength [info commands testevalex]]
set noRead {}
trace add variable noRead read failTrace
set noWrite {a b c}
trace add variable noWrite write failTrace
proc newlist list {
return $list
}
test lset-1.1 {lset, not compiled, arg count} testevalex {
list [catch {testevalex lset} msg] $msg
} "1 {wrong \# args: should be \"lset listVar ?index? ?index ...? value\"}"
test lset-1.2 {lset, not compiled, no such var} testevalex {
list [catch {testevalex {lset noSuchVar 0 {}}} msg] $msg
} "1 {can't read \"noSuchVar\": no such variable}"
test lset-1.3 {lset, not compiled, var not readable} testevalex {
list [catch {testevalex {lset noRead 0 {}}} msg] $msg
} "1 {can't read \"noRead\": trace failed}"
test lset-2.1 {lset, not compiled, 3 args, second arg a plain index} testevalex {
set x {0 1 2}
list [testevalex {lset x 0 3}] $x
} {{3 1 2} {3 1 2}}
test lset-2.2 {lset, not compiled, 3 args, second arg neither index nor list} testevalex {
set x {0 1 2}
list [catch {
testevalex {lset x {{bad}1} 3}
} msg] $msg
} {1 {bad index "{bad}1": must be integer?[+-]integer? or end?[+-]integer?}}
variable tests {
foreach map {
{
@mode@ compiled
@lset@ lset
}
{
@mode@ uncompiled
@lset@ {[lindex lset]}
}
} {
set script [string map $map {
test lset-3.1 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1 2}
list [testevalex {lset x 0 $x}] $x
} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
test lset-3.2 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {lset x 0 2}] $x $y
} {{2 1} {2 1} {0 1}}
test lset-3.3 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {lset x 0 $x}] $x $y
} {{{0 1} 1} {{0 1} 1} {0 1}}
test lset-3.4 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1 2}
list [testevalex {lset x [list 0] $x}] $x
} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
test lset-3.5 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {lset x [list 0] 2}] $x $y
} {{2 1} {2 1} {0 1}}
test lset-3.6 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {lset x [list 0] $x}] $x $y
} {{{0 1} 1} {{0 1} 1} {0 1}}
proc failTrace {name1 name2 op} {
error "trace failed"
}
test lset-4.1 {lset, not compiled, 3 args, not a list} testevalex {
set a "x \{"
list [catch {
testevalex {lset a [list 0] y}
} msg] $msg
} {1 {unmatched open brace in list}}
test lset-4.2 {lset, not compiled, 3 args, bad index} testevalex {
set a {x y z}
list [catch {
testevalex {lset a [list 2a2] w}
} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-4.3 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a [list -1] w}
} msg] $msg
} {1 {index "-1" out of range}}
test lset-4.4 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a [list 4] w}
} msg] $msg
} {1 {index "4" out of range}}
test lset-4.5a {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a [list end--2] w}
} msg] $msg
} {1 {index "end--2" out of range}}
test lset-4.5b {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a [list end+2] w}
} msg] $msg
} {1 {index "end+2" out of range}}
test lset-4.6 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a [list end-3] w}
} msg] $msg
} {1 {index "end-3" out of range}}
test lset-4.7 {lset, not compiled, 3 args, not a list} testevalex {
set a "x \{"
list [catch {
testevalex {lset a 0 y}
} msg] $msg
} {1 {unmatched open brace in list}}
test lset-4.8 {lset, not compiled, 3 args, bad index} testevalex {
set a {x y z}
list [catch {
testevalex {lset a 2a2 w}
} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-4.9 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a -1 w}
} msg] $msg
} {1 {index "-1" out of range}}
test lset-4.10 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a 4 w}
} msg] $msg
} {1 {index "4" out of range}}
test lset-4.11a {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a end--2 w}
} msg] $msg
} {1 {index "end--2" out of range}}
test lset-4.11 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a end+2 w}
} msg] $msg
} {1 {index "end+2" out of range}}
test lset-4.12 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {lset a end-3 w}
} msg] $msg
} {1 {index "end-3" out of range}}
set noRead {}
trace add variable noRead read failTrace
set noWrite {a b c}
trace add variable noWrite write failTrace
test lset-5.1 {lset, not compiled, 3 args, can't set variable} testevalex {
list [catch {
testevalex {lset noWrite 0 d}
} msg] $msg $noWrite
} {1 {can't set "noWrite": trace failed} {d b c}}
test lset-5.2 {lset, not compiled, 3 args, can't set variable} testevalex {
list [catch {
testevalex {lset noWrite [list 0] d}
} msg] $msg $noWrite
} {1 {can't set "noWrite": trace failed} {d b c}}
test lset-1.1-@mode@ {lset, not compiled, arg count} testevalex {
list [catch {testevalex @lset@} msg] $msg
} "1 {wrong \# args: should be \"lset listVar ?index? ?index ...? value\"}"
test lset-1.2-@mode@ {lset, not compiled, no such var} testevalex {
list [catch {testevalex {@lset@ noSuchVar 0 {}}} msg] $msg
} "1 {can't read \"noSuchVar\": no such variable}"
test lset-1.3-@mode@ {lset, not compiled, var not readable} testevalex {
list [catch {testevalex {@lset@ noRead 0 {}}} msg] $msg
} "1 {can't read \"noRead\": trace failed}"
test lset-6.1 {lset, not compiled, 3 args, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a 0 a}] $a
} {{a y z} {a y z}}
test lset-6.2 {lset, not compiled, 3 args, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a [list 0] a}] $a
} {{a y z} {a y z}}
test lset-6.3 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a 2 a}] $a
} {{x y a} {x y a}}
test lset-6.4 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a [list 2] a}] $a
} {{x y a} {x y a}}
test lset-6.5 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a end a}] $a
} {{x y a} {x y a}}
test lset-6.6 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a [list end] a}] $a
} {{x y a} {x y a}}
test lset-6.7 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a end-0 a}] $a
} {{x y a} {x y a}}
test lset-6.8 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a [list end-0] a}] $a
} {{x y a} {x y a}}
test lset-6.9 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a end-2 a}] $a
} {{a y z} {a y z}}
test lset-6.10 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {lset a [list end-2] a}] $a
} {{a y z} {a y z}}
test lset-2.1-@mode@ {lset, not compiled, 3 args, second arg a plain index} testevalex {
set x {0 1 2}
list [testevalex {@lset@ x 0 3}] $x
} {{3 1 2} {3 1 2}}
test lset-2.2-@mode@ {lset, not compiled, 3 args, second arg neither index nor list} testevalex {
set x {0 1 2}
list [catch {
testevalex {@lset@ x {{bad}1} 3}
} msg] $msg
} {1 {bad index "{bad}1": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-7.1 {lset, not compiled, data sharing} testevalex {
set a 0
list [testevalex {lset a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
test lset-7.2 {lset, not compiled, data sharing} testevalex {
set a [list 0]
list [testevalex {lset a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
test lset-7.3 {lset, not compiled, data sharing} testevalex {
set a {x y}
list [testevalex {lset a 0 $a}] $a
} {{{x y} y} {{x y} y}}
test lset-7.4 {lset, not compiled, data sharing} testevalex {
set a {x y}
list [testevalex {lset a [list 0] $a}] $a
} {{{x y} y} {{x y} y}}
test lset-7.5 {lset, not compiled, data sharing} testevalex {
set n 0
set a {x y}
list [testevalex {lset a $n $n}] $a $n
} {{0 y} {0 y} 0}
test lset-7.6 {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a {x y}
list [testevalex {lset a $n $n}] $a $n
} {{0 y} {0 y} 0}
test lset-7.7 {lset, not compiled, data sharing} testevalex {
set n 0
set a [list $n $n]
list [testevalex {lset a $n 1}] $a $n
} {{1 0} {1 0} 0}
test lset-7.8 {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a [list $n $n]
list [testevalex {lset a $n 1}] $a $n
} {{1 0} {1 0} 0}
test lset-7.9 {lset, not compiled, data sharing} testevalex {
set a 0
list [testevalex {lset a $a $a}] $a
} {0 0}
test lset-7.10 {lset, not compiled, data sharing} testevalex {
set a [list 0]
list [testevalex {lset a $a $a}] $a
} {0 0}
test lset-3.1-@mode@ {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1 2}
list [testevalex {@lset@ x 0 $x}] $x
} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
test lset-3.2-@mode@ {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {@lset@ x 0 2}] $x $y
} {{2 1} {2 1} {0 1}}
test lset-3.3-@mode@ {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {@lset@ x 0 $x}] $x $y
} {{{0 1} 1} {{0 1} 1} {0 1}}
test lset-3.4-@mode@ {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1 2}
list [testevalex {@lset@ x [list 0] $x}] $x
} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
test lset-3.5-@mode@ {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {@lset@ x [list 0] 2}] $x $y
} {{2 1} {2 1} {0 1}}
test lset-3.6-@mode@ {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
list [testevalex {@lset@ x [list 0] $x}] $x $y
} {{{0 1} 1} {{0 1} 1} {0 1}}
test lset-8.1 {lset, not compiled, malformed sublist} testevalex {
set a [list "a \{" b]
list [catch {testevalex {lset a 0 1 c}} msg] $msg
} {1 {unmatched open brace in list}}
test lset-8.2 {lset, not compiled, malformed sublist} testevalex {
set a [list "a \{" b]
list [catch {testevalex {lset a {0 1} c}} msg] $msg
} {1 {unmatched open brace in list}}
test lset-8.3 {lset, not compiled, bad second index} testevalex {
set a {{b c} {d e}}
list [catch {testevalex {lset a 0 2a2 f}} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-8.4 {lset, not compiled, bad second index} testevalex {
set a {{b c} {d e}}
list [catch {testevalex {lset a {0 2a2} f}} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-8.5 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a 2 -1 h}} msg] $msg
} {1 {index "-1" out of range}}
test lset-8.6 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a {2 -1} h}} msg] $msg
} {1 {index "-1" out of range}}
test lset-8.7 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a 2 3 h}} msg] $msg
} {1 {index "3" out of range}}
test lset-8.8 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a {2 3} h}} msg] $msg
} {1 {index "3" out of range}}
test lset-8.9a {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a 2 end--2 h}} msg] $msg
} {1 {index "end--2" out of range}}
test lset-8.9b {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a 2 end+2 h}} msg] $msg
} {1 {index "end+2" out of range}}
test lset-8.10a {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a {2 end--2} h}} msg] $msg
} {1 {index "end--2" out of range}}
test lset-8.10b {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a {2 end+2} h}} msg] $msg
} {1 {index "end+2" out of range}}
test lset-8.11 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a 2 end-2 h}} msg] $msg
} {1 {index "end-2" out of range}}
test lset-8.12 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {lset a {2 end-2} h}} msg] $msg
} {1 {index "end-2" out of range}}
test lset-4.1-@mode@ {lset, not compiled, 3 args, not a list} testevalex {
set a "x \{"
list [catch {
testevalex {@lset@ a [list 0] y}
} msg] $msg
} {1 {unmatched open brace in list}}
test lset-4.2-@mode@ {lset, not compiled, 3 args, bad index} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a [list 2a2] w}
} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-4.3-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a [list -1] w}
} msg] $msg
} {1 {index "-1" out of range}}
test lset-4.4-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a [list 4] w}
} msg] $msg
} {1 {index "4" out of range}}
test lset-4.5a-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a [list end--2] w}
} msg] $msg
} {1 {index "end--2" out of range}}
test lset-4.5b-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a [list end+2] w}
} msg] $msg
} {1 {index "end+2" out of range}}
test lset-4.6-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a [list end-3] w}
} msg] $msg
} {1 {index "end-3" out of range}}
test lset-4.7-@mode@ {lset, not compiled, 3 args, not a list} testevalex {
set a "x \{"
list [catch {
testevalex {@lset@ a 0 y}
} msg] $msg
} {1 {unmatched open brace in list}}
test lset-4.8-@mode@ {lset, not compiled, 3 args, bad index} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a 2a2 w}
} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-4.9-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a -1 w}
} msg] $msg
} {1 {index "-1" out of range}}
test lset-4.10-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a 4 w}
} msg] $msg
} {1 {index "4" out of range}}
test lset-4.11a-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a end--2 w}
} msg] $msg
} {1 {index "end--2" out of range}}
test lset-4.11-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a end+2 w}
} msg] $msg
} {1 {index "end+2" out of range}}
test lset-4.12-@mode@ {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
testevalex {@lset@ a end-3 w}
} msg] $msg
} {1 {index "end-3" out of range}}
test lset-9.1 {lset, not compiled, entire variable} testevalex {
set a x
list [testevalex {lset a y}] $a
} {y y}
test lset-9.2 {lset, not compiled, entire variable} testevalex {
set a x
list [testevalex {lset a {} y}] $a
} {y y}
test lset-5.1-@mode@ {lset, not compiled, 3 args, can't set variable} testevalex {
list [catch {
testevalex {@lset@ noWrite 0 d}
} msg] $msg $noWrite
} {1 {can't set "noWrite": trace failed} {d b c}}
test lset-5.2-@mode@ {lset, not compiled, 3 args, can't set variable} testevalex {
list [catch {
testevalex {@lset@ noWrite [list 0] d}
} msg] $msg $noWrite
} {1 {can't set "noWrite": trace failed} {d b c}}
test lset-10.1 {lset, not compiled, shared data} testevalex {
set row {p q}
set a [list $row $row]
list [testevalex {lset a 0 0 x}] $a
} {{{x q} {p q}} {{x q} {p q}}}
test lset-10.2 {lset, not compiled, shared data} testevalex {
set row {p q}
set a [list $row $row]
list [testevalex {lset a {0 0} x}] $a
} {{{x q} {p q}} {{x q} {p q}}}
test lset-10.3 {lset, not compiled, shared data, [Bug 1333036]} testevalex {
set a [list [list p q] [list r s]]
set b $a
list [testevalex {lset b {0 0} x}] $a
} {{{x q} {r s}} {{p q} {r s}}}
test lset-6.1-@mode@ {lset, not compiled, 3 args, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a 0 a}] $a
} {{a y z} {a y z}}
test lset-6.2-@mode@ {lset, not compiled, 3 args, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a [list 0] a}] $a
} {{a y z} {a y z}}
test lset-6.3-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a 2 a}] $a
} {{x y a} {x y a}}
test lset-6.4-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a [list 2] a}] $a
} {{x y a} {x y a}}
test lset-6.5-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a end a}] $a
} {{x y a} {x y a}}
test lset-6.6-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a [list end] a}] $a
} {{x y a} {x y a}}
test lset-6.7-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a end-0 a}] $a
} {{x y a} {x y a}}
test lset-6.8-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a [list end-0] a}] $a
} {{x y a} {x y a}}
test lset-6.9-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a end-2 a}] $a
} {{a y z} {a y z}}
test lset-6.10-@mode@ {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
list [testevalex {@lset@ a [list end-2] a}] $a
} {{a y z} {a y z}}
test lset-11.1 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a 0 0 f}] $a
} {{{f c} {d e}} {{f c} {d e}}}
test lset-11.2 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a {0 0} f}] $a
} {{{f c} {d e}} {{f c} {d e}}}
test lset-11.3 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a 0 1 f}] $a
} {{{b f} {d e}} {{b f} {d e}}}
test lset-11.4 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a {0 1} f}] $a
} {{{b f} {d e}} {{b f} {d e}}}
test lset-11.5 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a 1 0 f}] $a
} {{{b c} {f e}} {{b c} {f e}}}
test lset-11.6 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a {1 0} f}] $a
} {{{b c} {f e}} {{b c} {f e}}}
test lset-11.7 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a 1 1 f}] $a
} {{{b c} {d f}} {{b c} {d f}}}
test lset-11.8 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {lset a {1 1} f}] $a
} {{{b c} {d f}} {{b c} {d f}}}
test lset-7.1-@mode@ {lset, not compiled, data sharing} testevalex {
set a 0
list [testevalex {@lset@ a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
test lset-7.2-@mode@ {lset, not compiled, data sharing} testevalex {
set a [list 0]
list [testevalex {@lset@ a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
test lset-7.3-@mode@ {lset, not compiled, data sharing} testevalex {
set a {x y}
list [testevalex {@lset@ a 0 $a}] $a
} {{{x y} y} {{x y} y}}
test lset-7.4-@mode@ {lset, not compiled, data sharing} testevalex {
set a {x y}
list [testevalex {@lset@ a [list 0] $a}] $a
} {{{x y} y} {{x y} y}}
test lset-7.5-@mode@ {lset, not compiled, data sharing} testevalex {
set n 0
set a {x y}
list [testevalex {@lset@ a $n $n}] $a $n
} {{0 y} {0 y} 0}
test lset-7.6-@mode@ {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a {x y}
list [testevalex {@lset@ a $n $n}] $a $n
} {{0 y} {0 y} 0}
test lset-7.7-@mode@ {lset, not compiled, data sharing} testevalex {
set n 0
set a [list $n $n]
list [testevalex {@lset@ a $n 1}] $a $n
} {{1 0} {1 0} 0}
test lset-7.8-@mode@ {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a [list $n $n]
list [testevalex {@lset@ a $n 1}] $a $n
} {{1 0} {1 0} 0}
test lset-7.9-@mode@ {lset, not compiled, data sharing} testevalex {
set a 0
list [testevalex {@lset@ a $a $a}] $a
} {0 0}
test lset-7.10-@mode@ {lset, not compiled, data sharing} testevalex {
set a [list 0]
list [testevalex {@lset@ a $a $a}] $a
} {0 0}
test lset-12.0 {lset, not compiled, typical sharing pattern} testevalex {
set zero 0
set row [list $zero $zero $zero $zero]
set ident [list $row $row $row $row]
for { set i 0 } { $i < 4 } { incr i } {
testevalex {lset ident $i $i 1}
test lset-8.1-@mode@ {lset, not compiled, malformed sublist} testevalex {
set a [list "a \{" b]
list [catch {testevalex {@lset@ a 0 1 c}} msg] $msg
} {1 {unmatched open brace in list}}
test lset-8.2-@mode@ {lset, not compiled, malformed sublist} testevalex {
set a [list "a \{" b]
list [catch {testevalex {@lset@ a {0 1} c}} msg] $msg
} {1 {unmatched open brace in list}}
test lset-8.3-@mode@ {lset, not compiled, bad second index} testevalex {
set a {{b c} {d e}}
list [catch {testevalex {@lset@ a 0 2a2 f}} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-8.4-@mode@ {lset, not compiled, bad second index} testevalex {
set a {{b c} {d e}}
list [catch {testevalex {@lset@ a {0 2a2} f}} msg] $msg
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lset-8.5-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a 2 -1 h}} msg] $msg
} {1 {index "-1" out of range}}
test lset-8.6-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a {2 -1} h}} msg] $msg
} {1 {index "-1" out of range}}
test lset-8.7-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a 2 3 h}} msg] $msg
} {1 {index "3" out of range}}
test lset-8.8-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a {2 3} h}} msg] $msg
} {1 {index "3" out of range}}
test lset-8.9a-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a 2 end--2 h}} msg] $msg
} {1 {index "end--2" out of range}}
test lset-8.9b-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a 2 end+2 h}} msg] $msg
} {1 {index "end+2" out of range}}
test lset-8.10a-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a {2 end--2} h}} msg] $msg
} {1 {index "end--2" out of range}}
test lset-8.10b-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a {2 end+2} h}} msg] $msg
} {1 {index "end+2" out of range}}
test lset-8.11-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a 2 end-2 h}} msg] $msg
} {1 {index "end-2" out of range}}
test lset-8.12-@mode@ {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
list [catch {testevalex {@lset@ a {2 end-2} h}} msg] $msg
} {1 {index "end-2" out of range}}
test lset-9.1-@mode@ {lset, not compiled, entire variable} testevalex {
set a x
list [testevalex {@lset@ a y}] $a
} {y y}
test lset-9.2-@mode@ {lset, not compiled, entire variable} testevalex {
set a x
list [testevalex {@lset@ a {} y}] $a
} {y y}
test lset-10.1-@mode@ {lset, not compiled, shared data} testevalex {
set row {p q}
set a [list $row $row]
list [testevalex {@lset@ a 0 0 x}] $a
} {{{x q} {p q}} {{x q} {p q}}}
test lset-10.2-@mode@ {lset, not compiled, shared data} testevalex {
set row {p q}
set a [list $row $row]
list [testevalex {@lset@ a {0 0} x}] $a
} {{{x q} {p q}} {{x q} {p q}}}
test lset-10.3-@mode@ {lset, not compiled, shared data, [Bug 1333036]} testevalex {
set a [list [list p q] [list r s]]
set b $a
list [testevalex {@lset@ b {0 0} x}] $a
} {{{x q} {r s}} {{p q} {r s}}}
test lset-11.1-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a 0 0 f}] $a
} {{{f c} {d e}} {{f c} {d e}}}
test lset-11.2-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a {0 0} f}] $a
} {{{f c} {d e}} {{f c} {d e}}}
test lset-11.3-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a 0 1 f}] $a
} {{{b f} {d e}} {{b f} {d e}}}
test lset-11.4-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a {0 1} f}] $a
} {{{b f} {d e}} {{b f} {d e}}}
test lset-11.5-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a 1 0 f}] $a
} {{{b c} {f e}} {{b c} {f e}}}
test lset-11.6-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a {1 0} f}] $a
} {{{b c} {f e}} {{b c} {f e}}}
test lset-11.7-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a 1 1 f}] $a
} {{{b c} {d f}} {{b c} {d f}}}
test lset-11.8-@mode@ {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
list [testevalex {@lset@ a {1 1} f}] $a
} {{{b c} {d f}} {{b c} {d f}}}
test lset-12.0-@mode@ {lset, not compiled, typical sharing pattern} testevalex {
set zero 0
set row [list $zero $zero $zero $zero]
set ident [list $row $row $row $row]
for { set i 0 } { $i < 4 } { incr i } {
testevalex {@lset@ ident $i $i 1}
}
set ident
} {{1 0 0 0} {0 1 0 0} {0 0 1 0} {0 0 0 1}}
test lset-13.0-@mode@ {lset, not compiled, shimmering hell} testevalex {
set a 0
list [testevalex {@lset@ a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
test lset-13.1-@mode@ {lset, not compiled, shimmering hell} testevalex {
set a [list 0]
list [testevalex {@lset@ a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
test lset-13.2-@mode@ {lset, not compiled, shimmering hell} testevalex {
set a [list 0 0 0 0]
list [testevalex {@lset@ a $a {gag me}}] $a
} {{{{{{gag me}}}} 0 0 0} {{{{{gag me}}}} 0 0 0}}
test lset-14.1-@mode@ {lset, not compiled, list args, is string rep preserved?} testevalex {
set a { { 1 2 } { 3 4 } }
catch { testevalex {@lset@ a {1 5} 5} }
list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"
test lset-14.2-@mode@ {lset, not compiled, flat args, is string rep preserved?} testevalex {
set a { { 1 2 } { 3 4 } }
catch { testevalex {@lset@ a 1 5 5} }
list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"
testConstraint testobj [llength [info commands testobj]]
test lset-15.1-@mode@ {lset: shared internalrep [Bug 1677512]} -setup {
teststringobj set 1 {{1 2} 3}
testobj convert 1 list
testobj duplicate 1 2
variable x [teststringobj get 1]
variable y [teststringobj get 2]
testobj freeallvars
set l [list $y z]
unset y
} -constraints testobj -body {
@lset@ l 0 0 0 5
lindex $x 0 0
} -cleanup {
unset -nocomplain x l
} -result 1
test lset-16.1-@mode@ {lset - grow a variable} testevalex {
set x {}
testevalex {@lset@ x 0 {test 1}}
testevalex {lset x 1 {test 2}}
set x
} {{test 1} {test 2}}
test lset-16.2-@mode@ {@lset@ - multiple created sublists} testevalex {
set x {}
testevalex {lset x 0 0 {test 1}}
} {{{test 1}}}
test lset-16.3-@mode@ {@lset@ - sublists 3 deep} testevalex {
set x {}
testevalex {lset x 0 0 0 {test 1}}
} {{{{test 1}}}}
test lset-16.4-@mode@ {@lset@ - append to inner list} testevalex {
set x {test 1}
testevalex {@lset@ x 1 1 2}
testevalex {@lset@ x 1 2 3}
testevalex {@lset@ x 1 2 1 4}
} {test {1 2 {3 4}}}
test lset-16.5-@mode@ {lset - grow a variable} testevalex {
set x {}
testevalex {@lset@ x end+1 {test 1}}
testevalex {@lset@ x end+1 {test 2}}
set x
} {{test 1} {test 2}}
test lset-16.6-@mode@ {lset - multiple created sublists} testevalex {
set x {}
testevalex {@lset@ x end+1 end+1 {test 1}}
} {{{test 1}}}
test lset-16.7-@mode@ {lset - sublists 3 deep} testevalex {
set x {}
testevalex {@lset@ x end+1 end+1 end+1 {test 1}}
} {{{{test 1}}}}
test lset-16.8-@mode@ {lset - append to inner list} testevalex {
set x {test 1}
testevalex {@lset@ x end end+1 2}
testevalex {@lset@ x end end+1 3}
testevalex {@lset@ x end end end+1 4}
} {test {1 2 {3 4}}}
catch {unset noRead}
catch {unset noWrite}
catch {rename failTrace {}}
catch {unset ::x}
catch {unset ::y}
}]
try $script
}
set ident
} {{1 0 0 0} {0 1 0 0} {0 0 1 0} {0 0 0 1}}
}
test lset-13.0 {lset, not compiled, shimmering hell} testevalex {
set a 0
list [testevalex {lset a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
test lset-13.1 {lset, not compiled, shimmering hell} testevalex {
set a [list 0]
list [testevalex {lset a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
test lset-13.2 {lset, not compiled, shimmering hell} testevalex {
set a [list 0 0 0 0]
list [testevalex {lset a $a {gag me}}] $a
} {{{{{{gag me}}}} 0 0 0} {{{{{gag me}}}} 0 0 0}}
try $tests
if {[info exists ::argv0] && [info script] eq $::argv0} {
try $tests
test lset-14.1 {lset, not compiled, list args, is string rep preserved?} testevalex {
set a { { 1 2 } { 3 4 } }
catch { testevalex {lset a {1 5} 5} }
list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"
test lset-14.2 {lset, not compiled, flat args, is string rep preserved?} testevalex {
set a { { 1 2 } { 3 4 } }
catch { testevalex {lset a 1 5 5} }
list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"
::tcltest::cleanupTests
return
}
testConstraint testobj [llength [info commands testobj]]
test lset-15.1 {lset: shared internalrep [Bug 1677512]} -setup {
teststringobj set 1 {{1 2} 3}
testobj convert 1 list
testobj duplicate 1 2
variable x [teststringobj get 1]
variable y [teststringobj get 2]
testobj freeallvars
set l [list $y z]
unset y
} -constraints testobj -body {
lset l 0 0 0 5
lindex $x 0 0
} -cleanup {
unset -nocomplain x l
} -result 1
test lset-16.1 {lset - grow a variable} testevalex {
set x {}
testevalex {lset x 0 {test 1}}
testevalex {lset x 1 {test 2}}
set x
} {{test 1} {test 2}}
test lset-16.2 {lset - multiple created sublists} testevalex {
set x {}
testevalex {lset x 0 0 {test 1}}
} {{{test 1}}}
test lset-16.3 {lset - sublists 3 deep} testevalex {
set x {}
testevalex {lset x 0 0 0 {test 1}}
} {{{{test 1}}}}
test lset-16.4 {lset - append to inner list} testevalex {
set x {test 1}
testevalex {lset x 1 1 2}
testevalex {lset x 1 2 3}
testevalex {lset x 1 2 1 4}
} {test {1 2 {3 4}}}
test lset-16.5 {lset - grow a variable} testevalex {
set x {}
testevalex {lset x end+1 {test 1}}
testevalex {lset x end+1 {test 2}}
set x
} {{test 1} {test 2}}
test lset-16.6 {lset - multiple created sublists} testevalex {
set x {}
testevalex {lset x end+1 end+1 {test 1}}
} {{{test 1}}}
test lset-16.7 {lset - sublists 3 deep} testevalex {
set x {}
testevalex {lset x end+1 end+1 end+1 {test 1}}
} {{{{test 1}}}}
test lset-16.8 {lset - append to inner list} testevalex {
set x {test 1}
testevalex {lset x end end+1 2}
testevalex {lset x end end+1 3}
testevalex {lset x end end end+1 4}
} {test {1 2 {3 4}}}
catch {unset noRead}
catch {unset noWrite}
catch {rename failTrace {}}
catch {unset ::x}
catch {unset ::y}
# cleanup
::tcltest::cleanupTests
+456
View File
@@ -0,0 +1,456 @@
# Copyright © 2021 Nathan Coulter
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
::tcltest::loadTestedCommands
testConstraint testindexhex [expr {[namespace which testindexhex] ne {}}]
testConstraint testlistinteger [expr {[namespace which testlistinteger] ne {}}]
apply [list {} {
variable list
variable res
foreach map {
{
@mode@ compiled
@lappend@ lappend
@lindex@ lindex
@linsert@ linsert
@llength@ length
@lrange@ lrange
@lreplace@ lreplace
}
{
@mode@ uncompiled
@lappend@ {[lindex lappend]}
@lindex@ {[lindex lindex]}
@linsert@ {[lindex linsert]}
@llength@ {[lindex llength]}
@lrange@ {[lindex lrange]}
@lreplace@ {[lindex lreplace]}
}
} {
set script [string map $map {
proc data1 iterations {
for {set i 0} {$i < $iterations} {incr i} {
@lappend@ expected [format %x $i]
}
return $expected
}
test {indexhex llength @mode@} {INST_LIST_INDEX_IMM} \
-constraints testindexhex \
-body {
set list [testindexhex]
llength $list
} -cleanup {
catch {unset list}
} -result -1
test {indexhex lindex constant @mode@} {INST_LIST_INDEX_IMM} \
-constraints testindexhex \
-body {
set list [testindexhex]
@lindex@ $list 731
} -cleanup {
catch {unset list}
} -result 2db
test {indexhex lindex constant end @mode@} {INST_LIST_INDEX_IMM} \
-constraints testindexhex \
-body {
set list [testindexhex]
@lindex@ $list end
} -cleanup {
catch {unset list}
catch {unset res}
} -returnCodes 1 -result {list length indeterminate}
test {indexhex lindex dynamic @mode@} {INST_LIST_INDEX} \
-constraints testindexhex \
-body {
set list [testindexhex]
set val [expr {731 + 0}]
@lindex@ $list $val
} -cleanup {
catch {unset list}
} -result 2db
test {indexhex lindex dynamic end @mode@} {INST_LIST_INDEX} \
-constraints testindexhex \
-body {
set index {}
set list [testindexhex]
append index e n d
@lindex@ $list $index
} -cleanup {
catch {unset index}
catch {unset list}
catch {unset res}
} -returnCodes 1 -result {list length indeterminate}
test {indexhex lindex drill @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
@lindex@ $list 731 0 0 0
} -cleanup {
catch {unset list}
} -result 2db
test {indexhex lrange constant @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
@lrange@ $list 10 15
} -cleanup {
catch {unset list}
} -result {a b c d e f}
test {indexhex lrange dynamic @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
set first [expr {10 + 0}]
set last [expr {15 + 0}]
@lrange@ $list $first $last
} -cleanup {
catch {unset list}
} -result {a b c d e f}
test {indexhex lrange end constant @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
@lrange@ $list 10 end
} -cleanup {
catch {unset list}
} -returnCodes 1 -result {list length indeterminate}
test {indexhex lrange end dynamic @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
set back [expr {-5 + 0}]
@lrange@ $list 10 end-$back
} -cleanup {
catch {unset list}
} -returnCodes 1 -result {list length indeterminate}
test {indexhex lrange end minus constant @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
@lrange@ $list 10 end-1
} -cleanup {
catch {unset list}
} -returnCodes 1 -result {list length indeterminate}
test {indexhex lsearch @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
lsearch $list ff
} -cleanup {
catch {unset list}
} -result 255
test {indexhex lsearch sorted @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
lsearch -sorted $list ff
} -cleanup {
catch {unset list}
} -returnCodes 1 -result {sorted list is incoherent}
test {indexhex lsearch start @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
lsearch -start 5171 -glob $list a*
} -cleanup {
catch {unset list}
} -result 40960
test {indexhex string index @mode@} {} \
-constraints testindexhex \
-body {
set iterations 4097
set expected [data1 $iterations]
set list [testindexhex]
set progres {}
set iterations [string length $expected]
for {set i 0} {$i < $iterations} {incr i} {
set eitem [string index $expected $i]
set item [string index $list $i]
if {$item ne $eitem} {
error [list {failed at index} $i [
format %x $i] expected $eitem got $item]
}
@lappend@ progress $item
}
return success
} -cleanup {
catch {unset i}
catch {unset list}
} -result success
test {indexhex string index end @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
string index $list end
return success
} -cleanup {
catch {unset list}
} -returnCodes 1 -result {list length indeterminate}
test {indexhex string length @mode@} {} \
-constraints testindexhex \
-body {
set list [testindexhex]
string length $list
} -cleanup {
catch {unset list}
} -result -1
test {indexhex string range @mode@} {} \
-constraints testindexhex \
-body {
set res {}
set iterations 4097
set data1 [data1 $iterations]
set data1Length [string length $data1]
set list [testindexhex]
for {set first 0} {$first < $data1Length } {
set first [expr {($first + 1) * 2}]} {
for {set last $first} {$last < $data1Length} {
set last [expr {($last + 1) * 3}]} {
set expected [string range $data1 $first $last]
set range [string range $list $first $last]
if {$range ne $expected} {
set length [expr {
max([string length $expected], [string length $range])
}]
for {set i 0} {$i < $length} {incr i} {
set item1 [string index $range $i]
set item2 [string index $expected $i]
if {$item1 ne $item2} {
error [list {failed at} $first $last $i \
expected $item2 got $item1]
}
}
}
}
}
@lappend@ res success
# The largest string index currently allowed.
@lappend@ res [string range $list 2147483640 2147483647]
# This produces an error until index ranges are expanded in some later
# version of Tcl.
set status [catch {string range $list 2147483640 2147483648} cres copts]
@lappend@ res $status $cres
return $res
} -cleanup {
catch {unset list}
} -result {success {d73ac8f } 1 {}}
test {integer lappend @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list 8 9 10
@lappend@ list 11 12 13
} -cleanup {
catch {unset list}
} -result {8 9 10 11 12 13}
test {integer lappend empty @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list 8 9 10
} -cleanup {
catch {unset list}
} -result {8 9 10}
test {integer lappend noninteger @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list {8 9 10 11 12 13}
} -cleanup {
catch {unset list}
} -result {{8 9 10 11 12 13}}
test {integer lindex before before after @mode@} {
This test just tries to trigger a segmentation fault
} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list 8 9 10 11 12 13
@lindex@ $list -1 -1 7
} -cleanup {
catch {unset list}
} -result {}
test {integer lindex middle @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list 8 9 10 11 12 13
@lindex@ $list 3
} -cleanup {
catch {unset list}
} -result 11
test {integer lindex end @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list 8 9 10 11 12 13
@lindex@ $list end
} -cleanup {
catch {unset list}
} -result 13
apply [list {} {
for {set i 0} {$i < 7} {incr i} {
set items {8 9 10 11 12 13}
set results {13 12 11 10 9 8}
set comment [list integer lindex end-$i @mode@]
set body [string map {@i@ $i @items@ $items} {
set list [testlistinteger {}]
@lappend@ list {*}$items
@lindex@ $list end-$i
}]
set result [lindex $results $i]
test $comment {} \
-constraints testlistinteger \
-body $body -cleanup {
catch {unset list}
} -result $result
}
unset i
} [namespace current]]
test {integer linsert middle one @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
set res {}
@lappend@ list 8 9 10 12 13
after 100
lappend res [@linsert@ $list 3 11]
set representation [::tcl::unsupported::representation $list]
regsub {(value is a testListInteger).*} $representation {\1} representation
lappend res $representation
return $res
} -cleanup {
catch {unset list}
catch {unset res}
catch {unset representation}
} -result {{8 9 10 11 12 13} {value is a testListInteger}}
test {integer lrange middle @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list 8 9 10 11 12 13
@lrange@ $list 3 4
} -cleanup {
catch {unset list}
} -result {11 12}
test {integer lreplace prepend @mode@} {} \
-constraints testlistinteger \
-body {
set list [testlistinteger {}]
@lappend@ list 8 9 10 11 12 13
after 100
@lreplace@ $list -1 -1 7
} -cleanup {
catch {unset list}
} -result {7 8 9 10 11 12 13}
}]
#try $script
}
set suites {linsert lset}
foreach suite {linsert lset} {
set namespace [list $suite tests]
namespace eval $namespace [list source [
file join [file dirname [file dirname [
file normalize [file join [info script] ...]]]] $suite.test]]
namespace eval $namespace {
proc newlist list {
if {[string is list $list]} {
set integer 1
foreach item $list {
if {![string is integer $item]} {
set integer 0
break
}
}
if {$integer} {
testlistinteger $list
}
}
return $list
}
try $tests
}
namespace delete $namespace
}
# cleanup
::tcltest::cleanupTests
} [namespace current]]
return
View File
+16 -4
View File
@@ -287,11 +287,14 @@ DEPEND_SWITCHES = ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} \
TCLSH_OBJS = tclAppInit.o
TCLTEST_OBJS = tclTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
tclThreadTest.o tclUnixTest.o
TCLTEST_OBJS = tclTestInit.o tclTest.o tclTestObj.o tclTestObjInterface.o \
tclTestObjInterfaceInteger.o \
tclTestProcBodyObj.o tclThreadTest.o tclUnixTest.o
XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o
XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestObjInterface.o \
tclTestObjInterfaceInteger.o \
tclTestProcBodyObj.o tclThreadTest.o tclUnixTest.o tclXtNotify.o \
tclXtTest.o
GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
tclArithSeries.o tclAssembly.o tclAsync.o tclBasic.o tclBinary.o \
@@ -464,6 +467,8 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclStrToD.c \
$(GENERIC_DIR)/tclTest.c \
$(GENERIC_DIR)/tclTestObj.c \
$(GENERIC_DIR)/tclTestObjInterface.c \
$(GENERIC_DIR)/tclTestObjInterfaceInteger \
$(GENERIC_DIR)/tclTestProcBodyObj.c \
$(GENERIC_DIR)/tclThread.c \
$(GENERIC_DIR)/tclThreadAlloc.c \
@@ -1557,6 +1562,13 @@ tclTest.o: $(GENERIC_DIR)/tclTest.c $(IOHDR) $(TCLREHDRS) tclUuid.h
tclTestObj.o: $(GENERIC_DIR)/tclTestObj.c $(MATHHDRS)
$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestObj.c
tclTestObjInterface.o: $(GENERIC_DIR)/tclTestObjInterface.c $(MATHHDRS)
$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestObjInterface.c
tclTestObjInterfaceInteger.o: $(GENERIC_DIR)/tclTestObjInterfaceInteger.c \
$(MATHHDRS)
$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestObjInterfaceInteger.c
tclTestProcBodyObj.o: $(GENERIC_DIR)/tclTestProcBodyObj.c
$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestProcBodyObj.c
-920
View File
@@ -1,920 +0,0 @@
#! /bin/bash
# Generated by configure.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
debug=false
ac_cs_recheck=false
ac_cs_silent=false
SHELL=${CONFIG_SHELL-/bin/bash}
## --------------------- ##
## M4sh Initialization. ##
## --------------------- ##
# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
set -o posix
fi
DUALCASE=1; export DUALCASE # for MKS sh
# Support unset when possible.
if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
as_unset=unset
else
as_unset=false
fi
# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH
PS1='$ '
PS2='> '
PS4='+ '
# NLS nuisances.
for as_var in \
LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
LC_TELEPHONE LC_TIME
do
if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
eval $as_var=C; export $as_var
else
$as_unset $as_var
fi
done
# Required to use basename.
if expr a : '\(a\)' >/dev/null 2>&1; then
as_expr=expr
else
as_expr=false
fi
if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
# Name of the executable.
as_me=`$as_basename "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)$' \| \
. : '\(.\)' 2>/dev/null ||
echo X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
/^X\/\(\/\/\)$/{ s//\1/; q; }
/^X\/\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
echo "#! /bin/sh" >conf$$.sh
echo "exit 0" >>conf$$.sh
chmod +x conf$$.sh
if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
PATH_SEPARATOR=';'
else
PATH_SEPARATOR=:
fi
rm -f conf$$.sh
fi
as_lineno_1=103
as_lineno_2=104
as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
test "x$as_lineno_1" != "x$as_lineno_2" &&
test "x$as_lineno_3" = "x$as_lineno_2" || {
# Find who we are. Look in the path if we contain no path at all
# relative or not.
case $0 in
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
done
;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
{ { echo "$as_me:128: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
case $CONFIG_SHELL in
'')
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for as_base in sh bash ksh sh5; do
case $as_dir in
/*)
if ("$as_dir/$as_base" -c '
as_lineno_1=143
as_lineno_2=144
as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
test "x$as_lineno_1" != "x$as_lineno_2" &&
test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
$as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
$as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
CONFIG_SHELL=$as_dir/$as_base
export CONFIG_SHELL
exec "$CONFIG_SHELL" "$0" ${1+"$@"}
fi;;
esac
done
done
;;
esac
# Create $as_me.lineno as a copy of $as_myself, but with 160
# uniformly replaced by the line number. The first 'sed' inserts a
# line-number line before each line; the second 'sed' does the real
# work. The second script uses 'N' to pair each line-number line
# with the numbered line, and appends trailing '-' during
# substitution so that 165 is not a special case at line end.
# (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
# second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
sed '=' <$as_myself |
sed '
N
s,$,-,
: loop
s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
t loop
s,-$,,
s,^['$as_cr_digits']*\n,,
' >$as_me.lineno &&
chmod +x $as_me.lineno ||
{ { echo "$as_me:179: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
{ (exit 1); exit 1; }; }
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensible to this).
. ./$as_me.lineno
# Exit status is that of the last command.
exit
}
case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
*c*,-n*) ECHO_N= ECHO_C='
' ECHO_T=' ' ;;
*c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
*) ECHO_N= ECHO_C='\c' ECHO_T= ;;
esac
if expr a : '\(a\)' >/dev/null 2>&1; then
as_expr=expr
else
as_expr=false
fi
rm -f conf$$ conf$$.exe conf$$.file
echo >conf$$.file
if ln -s conf$$.file conf$$ 2>/dev/null; then
# We could just check for DJGPP; but this test a) works b) is more generic
# and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
if test -f conf$$.exe; then
# Don't use ln at all; we don't have any links
as_ln_s='cp -p'
else
as_ln_s='ln -s'
fi
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.file
if mkdir -p . 2>/dev/null; then
as_mkdir_p=:
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
as_executable_p="test -f"
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
# IFS
# We need space, tab and new line, in precisely that order.
as_nl='
'
IFS=" $as_nl"
# CDPATH.
$as_unset CDPATH
exec 6>&1
# Open the log real soon, to keep \$[0] and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. Logging --version etc. is OK.
exec 5>>config.log
{
echo
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
} >&5
cat >&5 <<_CSEOF
This file was extended by tcl $as_me 8.6, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
CONFIG_LINKS = $CONFIG_LINKS
CONFIG_COMMANDS = $CONFIG_COMMANDS
$ $0 $@
_CSEOF
echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
echo >&5
config_files=" Makefile:../unix/Makefile.in dltest/Makefile:../unix/dltest/Makefile.in tclConfig.sh:../unix/tclConfig.sh.in tcl.pc:../unix/tcl.pc.in"
ac_cs_usage="\
\`$as_me' instantiates files from templates according to the
current configuration.
Usage: $0 [OPTIONS] [FILE]...
-h, --help print this help, then exit
-V, --version print version number, then exit
-q, --quiet do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
--file=FILE[:TEMPLATE]
instantiate the configuration file FILE
Configuration files:
$config_files
Configuration commands:
$config_commands
Report bugs to <bug-autoconf@gnu.org>."
ac_cs_version="\
tcl config.status 8.6
configured by ./configure, generated by GNU Autoconf 2.59,
with options \"'--prefix=/home/jima/space/ins/lin64/dynamic/main'\"
Copyright (C) 2003 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
srcdir=/home/jima/space/bui/lin64/dynamic/main/tcl/unix
# If no file are specified by the user, then we need to provide default
# value. By we need to know if files were specified by the user.
ac_need_defaults=:
while test $# != 0
do
case $1 in
--*=*)
ac_option=`expr "x$1" : 'x\([^=]*\)='`
ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
ac_shift=:
;;
-*)
ac_option=$1
ac_optarg=$2
ac_shift=shift
;;
*) # This is not an option, so the user has probably given explicit
# arguments.
ac_option=$1
ac_need_defaults=false;;
esac
case $ac_option in
# Handling of the options.
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --vers* | -V )
echo "$ac_cs_version"; exit 0 ;;
--he | --h)
# Conflict between --help and --header
{ { echo "$as_me:336: error: ambiguous option: $1
Try \`$0 --help' for more information." >&5
echo "$as_me: error: ambiguous option: $1
Try \`$0 --help' for more information." >&2;}
{ (exit 1); exit 1; }; };;
--help | --hel | -h )
echo "$ac_cs_usage"; exit 0 ;;
--debug | --d* | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
CONFIG_FILES="$CONFIG_FILES $ac_optarg"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
ac_need_defaults=false;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
# This is an error.
-*) { { echo "$as_me:358: error: unrecognized option: $1
Try \`$0 --help' for more information." >&5
echo "$as_me: error: unrecognized option: $1
Try \`$0 --help' for more information." >&2;}
{ (exit 1); exit 1; }; } ;;
*) ac_config_targets="$ac_config_targets $1" ;;
esac
shift
done
ac_configure_extra_args=
if $ac_cs_silent; then
exec 6>/dev/null
ac_configure_extra_args="$ac_configure_extra_args --silent"
fi
if $ac_cs_recheck; then
echo "running /bin/bash ./configure " '--prefix=/home/jima/space/ins/lin64/dynamic/main' $ac_configure_extra_args " --no-create --no-recursion" >&6
exec /bin/bash ./configure '--prefix=/home/jima/space/ins/lin64/dynamic/main' $ac_configure_extra_args --no-create --no-recursion
fi
#
# INIT-COMMANDS section.
#
VERSION=8.6
for ac_config_target in $ac_config_targets
do
case "$ac_config_target" in
# Handling of arguments.
"Tcl-Info.plist" ) CONFIG_FILES="$CONFIG_FILES Tcl-Info.plist:../macosx/Tcl-Info.plist.in" ;;
"Tclsh-Info.plist" ) CONFIG_FILES="$CONFIG_FILES Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in" ;;
"Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile:../unix/Makefile.in" ;;
"dltest/Makefile" ) CONFIG_FILES="$CONFIG_FILES dltest/Makefile:../unix/dltest/Makefile.in" ;;
"tclConfig.sh" ) CONFIG_FILES="$CONFIG_FILES tclConfig.sh:../unix/tclConfig.sh.in" ;;
"tcl.pc" ) CONFIG_FILES="$CONFIG_FILES tcl.pc:../unix/tcl.pc.in" ;;
"Tcl.framework" ) CONFIG_COMMANDS="$CONFIG_COMMANDS Tcl.framework" ;;
*) { { echo "$as_me:399: error: invalid argument: $ac_config_target" >&5
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
{ (exit 1); exit 1; }; };;
esac
done
# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used. Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
fi
# Have a temporary directory for convenience. Make it in the build tree
# simply because there is no reason to put it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Create a temporary directory, and hook for its removal unless debugging.
$debug ||
{
trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
trap '{ (exit 1); exit 1; }' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.
{
tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
test -n "$tmp" && test -d "$tmp"
} ||
{
tmp=./confstat$$-$RANDOM
(umask 077 && mkdir $tmp)
} ||
{
echo "$me: cannot create a temporary directory in ." >&2
{ (exit 1); exit 1; }
}
#
# CONFIG_FILES section.
#
# No need to generate the scripts if there are no CONFIG_FILES.
# This happens for instance when ./config.status config.h
if test -n "$CONFIG_FILES"; then
# Protect against being on the right side of a sed subst in config.status.
sed 's/,@/@@/; s/@,/@@/; s/,;t t$/@;t t/; /@;t t$/s/[\\&,]/\\&/g;
s/@@/,@/; s/@@/@,/; s/@;t t$/,;t t/' >$tmp/subs.sed <<\CEOF
s,@SHELL@,/bin/bash,;t t
s,@PATH_SEPARATOR@,:,;t t
s,@PACKAGE_NAME@,tcl,;t t
s,@PACKAGE_TARNAME@,tcl,;t t
s,@PACKAGE_VERSION@,8.6,;t t
s,@PACKAGE_STRING@,tcl 8.6,;t t
s,@PACKAGE_BUGREPORT@,,;t t
s,@exec_prefix@,/home/jima/space/ins/lin64/dynamic/main,;t t
s,@prefix@,/home/jima/space/ins/lin64/dynamic/main,;t t
s,@program_transform_name@,s,x,x,,;t t
s,@bindir@,${exec_prefix}/bin,;t t
s,@sbindir@,${exec_prefix}/sbin,;t t
s,@libexecdir@,${exec_prefix}/libexec,;t t
s,@datadir@,${prefix}/share,;t t
s,@sysconfdir@,${prefix}/etc,;t t
s,@sharedstatedir@,${prefix}/com,;t t
s,@localstatedir@,${prefix}/var,;t t
s,@libdir@,/home/jima/space/ins/lin64/dynamic/main/lib,;t t
s,@includedir@,${prefix}/include,;t t
s,@oldincludedir@,/usr/include,;t t
s,@infodir@,${prefix}/info,;t t
s,@mandir@,${prefix}/man,;t t
s,@build_alias@,,;t t
s,@host_alias@,,;t t
s,@target_alias@,,;t t
s,@DEFS@,-DPACKAGE_NAME=\"tcl\" -DPACKAGE_TARNAME=\"tcl\" -DPACKAGE_VERSION=\"8.6\" -DPACKAGE_STRING=\"tcl\ 8.6\" -DPACKAGE_BUGREPORT=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_PARAM_H=1 -DUSE_THREAD_ALLOC=1 -D_REENTRANT=1 -D_THREAD_SAFE=1 -DHAVE_PTHREAD_ATTR_SETSTACKSIZE=1 -DHAVE_PTHREAD_ATFORK=1 -DTCL_THREADS=1 -DTCL_CFGVAL_ENCODING=\"iso8859-1\" -DHAVE_ZLIB=1 -DMODULE_SCOPE=extern\ __attribute__\(\(__visibility__\(\"hidden\"\)\)\) -DHAVE_HIDDEN=1 -DHAVE_CAST_TO_UNION=1 -DTCL_SHLIB_EXT=\".so\" -DNDEBUG=1 -DTCL_CFG_OPTIMIZED=1 -DTCL_TOMMATH=1 -DMP_PREC=4 -D_LARGEFILE64_SOURCE=1 -DTCL_WIDE_INT_IS_LONG=1 -DHAVE_GETCWD=1 -DHAVE_MKSTEMP=1 -DHAVE_OPENDIR=1 -DHAVE_STRTOL=1 -DHAVE_WAITPID=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GETADDRINFO=1 -DHAVE_FREEADDRINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_STRUCT_ADDRINFO=1 -DHAVE_STRUCT_IN6_ADDR=1 -DHAVE_STRUCT_SOCKADDR_IN6=1 -DHAVE_STRUCT_SOCKADDR_STORAGE=1 -DHAVE_GETPWUID_R_5=1 -DHAVE_GETPWUID_R=1 -DHAVE_GETPWNAM_R_5=1 -DHAVE_GETPWNAM_R=1 -DHAVE_GETGRGID_R_5=1 -DHAVE_GETGRGID_R=1 -DHAVE_GETGRNAM_R_5=1 -DHAVE_GETGRNAM_R=1 -DHAVE_DECL_GETHOSTBYNAME_R=1 -DHAVE_GETHOSTBYNAME_R_6=1 -DHAVE_GETHOSTBYNAME_R=1 -DHAVE_DECL_GETHOSTBYADDR_R=1 -DHAVE_GETHOSTBYADDR_R_8=1 -DHAVE_GETHOSTBYADDR_R=1 -DHAVE_TERMIOS_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_TIME_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_GMTIME_R=1 -DHAVE_LOCALTIME_R=1 -DHAVE_MKTIME=1 -DHAVE_TM_GMTOFF=1 -DHAVE_TIMEZONE_VAR=1 -DHAVE_STRUCT_STAT_ST_BLOCKS=1 -DHAVE_STRUCT_STAT_ST_BLKSIZE=1 -DHAVE_BLKCNT_T=1 -DHAVE_INTPTR_T=1 -DHAVE_UINTPTR_T=1 -DNO_UNION_WAIT=1 -DHAVE_SIGNED_CHAR=1 -DHAVE_LANGINFO=1 -DHAVE_MKSTEMPS=1 -DHAVE_FTS=1 -DHAVE_SYS_IOCTL_H=1 -DTCL_UNLOAD_DLLS=1 -DHAVE_CPUID=1 ,;t t
s,@ECHO_C@,,;t t
s,@ECHO_N@,-n,;t t
s,@ECHO_T@,,;t t
s,@LIBS@,-lz -lpthread,;t t
s,@MAN_FLAGS@,,;t t
s,@CC@,gcc,;t t
s,@CFLAGS@, -pipe ,;t t
s,@LDFLAGS@, -Wl,--export-dynamic ,;t t
s,@CPPFLAGS@,,;t t
s,@ac_ct_CC@,gcc,;t t
s,@EXEEXT@,,;t t
s,@OBJEXT@,o,;t t
s,@CPP@,gcc -E,;t t
s,@EGREP@,grep -E,;t t
s,@TCL_THREADS@,1,;t t
s,@TCLSH_PROG@,/usr/bin/tclsh8.6,;t t
s,@ZLIB_OBJS@,,;t t
s,@ZLIB_SRCS@,,;t t
s,@ZLIB_INCLUDE@,,;t t
s,@RANLIB@,ranlib,;t t
s,@ac_ct_RANLIB@,ranlib,;t t
s,@AR@,ar,;t t
s,@ac_ct_AR@,ar,;t t
s,@LIBOBJS@,,;t t
s,@TCL_LIBS@,-ldl -lz -lpthread -lm,;t t
s,@DL_LIBS@,-ldl,;t t
s,@DL_OBJS@,tclLoadDl.o,;t t
s,@PLAT_OBJS@,,;t t
s,@PLAT_SRCS@,,;t t
s,@LDAIX_SRC@,,;t t
s,@CFLAGS_DEBUG@,-g,;t t
s,@CFLAGS_OPTIMIZE@,-O2,;t t
s,@CFLAGS_WARNING@,-Wall,;t t
s,@LDFLAGS_DEBUG@,,;t t
s,@LDFLAGS_OPTIMIZE@,,;t t
s,@CC_SEARCH_FLAGS@,-Wl,-rpath,${LIB_RUNTIME_DIR},;t t
s,@LD_SEARCH_FLAGS@,-Wl,-rpath,${LIB_RUNTIME_DIR},;t t
s,@STLIB_LD@,${AR} cr,;t t
s,@SHLIB_LD@,${CC} ${CFLAGS} ${LDFLAGS} -shared,;t t
s,@TCL_SHLIB_LD_EXTRAS@,,;t t
s,@TK_SHLIB_LD_EXTRAS@,,;t t
s,@SHLIB_LD_LIBS@,${LIBS},;t t
s,@SHLIB_CFLAGS@,-fPIC,;t t
s,@SHLIB_SUFFIX@,.so,;t t
s,@MAKE_LIB@,${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS},;t t
s,@MAKE_STUB_LIB@,${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@,;t t
s,@INSTALL_LIB@,$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)",;t t
s,@DLL_INSTALL_DIR@,$(LIB_INSTALL_DIR),;t t
s,@INSTALL_STUB_LIB@,$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)",;t t
s,@CFLAGS_DEFAULT@,$(CFLAGS_OPTIMIZE),;t t
s,@LDFLAGS_DEFAULT@,$(LDFLAGS_OPTIMIZE),;t t
s,@DTRACE@,,;t t
s,@TCL_VERSION@,8.6,;t t
s,@TCL_MAJOR_VERSION@,8,;t t
s,@TCL_MINOR_VERSION@,6,;t t
s,@TCL_PATCH_LEVEL@,.10,;t t
s,@TCL_YEAR@,,;t t
s,@PKG_CFG_ARGS@,'--prefix=/home/jima/space/ins/lin64/dynamic/main' ,;t t
s,@TCL_LIB_FILE@,libtcl8.6.so,;t t
s,@TCL_LIB_FLAG@,-ltcl8.6,;t t
s,@TCL_LIB_SPEC@,-L/home/jima/space/ins/lin64/dynamic/main/lib -ltcl8.6,;t t
s,@TCL_STUB_LIB_FILE@,libtclstub8.6.a,;t t
s,@TCL_STUB_LIB_FLAG@,-ltclstub8.6,;t t
s,@TCL_STUB_LIB_SPEC@,-L/home/jima/space/ins/lin64/dynamic/main/lib -ltclstub8.6,;t t
s,@TCL_STUB_LIB_PATH@,/home/jima/space/ins/lin64/dynamic/main/lib/libtclstub8.6.a,;t t
s,@TCL_INCLUDE_SPEC@,-I/home/jima/space/ins/lin64/dynamic/main/include,;t t
s,@TCL_BUILD_STUB_LIB_SPEC@,-L/home/jima/space/bui/lin64/dynamic/main/tcl/unix -ltclstub8.6,;t t
s,@TCL_BUILD_STUB_LIB_PATH@,/home/jima/space/bui/lin64/dynamic/main/tcl/unix/libtclstub8.6.a,;t t
s,@TCL_SRC_DIR@,/home/jima/space/bui/lin64/dynamic/main/tcl,;t t
s,@CFG_TCL_SHARED_LIB_SUFFIX@,${VERSION}.so,;t t
s,@CFG_TCL_UNSHARED_LIB_SUFFIX@,${VERSION}.a,;t t
s,@TCL_SHARED_BUILD@,1,;t t
s,@LD_LIBRARY_PATH_VAR@,LD_LIBRARY_PATH,;t t
s,@TCL_BUILD_LIB_SPEC@,-L/home/jima/space/bui/lin64/dynamic/main/tcl/unix -ltcl8.6,;t t
s,@TCL_LIB_VERSIONS_OK@,ok,;t t
s,@TCL_SHARED_LIB_SUFFIX@,${VERSION}${SHLIB_SUFFIX},;t t
s,@TCL_UNSHARED_LIB_SUFFIX@,${VERSION}.a,;t t
s,@TCL_HAS_LONGLONG@,,;t t
s,@INSTALL_TZDATA@,,;t t
s,@DTRACE_SRC@,,;t t
s,@DTRACE_HDR@,,;t t
s,@DTRACE_OBJ@,,;t t
s,@MAKEFILE_SHELL@,/bin/sh,;t t
s,@BUILD_DLTEST@,$(DLTEST_TARGETS),;t t
s,@TCL_PACKAGE_PATH@,/home/jima/space/ins/lin64/dynamic/main/lib ,;t t
s,@TCL_MODULE_PATH@,,;t t
s,@TCL_LIBRARY@,$(prefix)/lib/tcl$(VERSION),;t t
s,@PRIVATE_INCLUDE_DIR@,$(includedir),;t t
s,@HTML_DIR@,$(DISTDIR)/html,;t t
s,@PACKAGE_DIR@,/home/jima/space/ins/lin64/dynamic/main/lib,;t t
s,@EXTRA_CC_SWITCHES@,,;t t
s,@EXTRA_APP_CC_SWITCHES@,,;t t
s,@EXTRA_INSTALL@,,;t t
s,@EXTRA_INSTALL_BINARIES@,@:,;t t
s,@EXTRA_BUILD_HTML@,@:,;t t
s,@EXTRA_TCLSH_LIBS@,,;t t
s,@DLTEST_LD@,${SHLIB_LD},;t t
s,@DLTEST_SUFFIX@,,;t t
CEOF
# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
ac_max_sed_lines=48
ac_sed_frag=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_lines # Line after last line for current file.
ac_more_lines=:
ac_sed_cmds=
while $ac_more_lines; do
if test $ac_beg -gt 1; then
sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
else
sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
fi
if test ! -s $tmp/subs.frag; then
ac_more_lines=false
else
# The purpose of the label and of the branching condition is to
# speed up the sed processing (if there are no `@' at all, there
# is no need to browse any of the substitutions).
# These are the two extra sed commands mentioned above.
(echo ':t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
if test -z "$ac_sed_cmds"; then
ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
else
ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
fi
ac_sed_frag=`expr $ac_sed_frag + 1`
ac_beg=$ac_end
ac_end=`expr $ac_end + $ac_max_sed_lines`
fi
done
if test -z "$ac_sed_cmds"; then
ac_sed_cmds=cat
fi
fi # test -n "$CONFIG_FILES"
for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
# Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
case $ac_file in
- | *:- | *:-:* ) # input from stdin
cat >$tmp/stdin
ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
*:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
* ) ac_file_in=$ac_file.in ;;
esac
# Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
ac_dir=`(dirname "$ac_file") 2>/dev/null ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| \
. : '\(.\)' 2>/dev/null ||
echo X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
/^X\(\/\/\)[^/].*/{ s//\1/; q; }
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
{ if $as_mkdir_p; then
mkdir -p "$ac_dir"
else
as_dir="$ac_dir"
as_dirs=
while test ! -d "$as_dir"; do
as_dirs="$as_dir $as_dirs"
as_dir=`(dirname "$as_dir") 2>/dev/null ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| \
. : '\(.\)' 2>/dev/null ||
echo X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
/^X\(\/\/\)[^/].*/{ s//\1/; q; }
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
done
test ! -n "$as_dirs" || mkdir $as_dirs
fi || { { echo "$as_me:660: error: cannot create directory \"$ac_dir\"" >&5
echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
{ (exit 1); exit 1; }; }; }
ac_builddir=.
if test "$ac_dir" != .; then
ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
# A "../" for each directory in $ac_dir_suffix.
ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
else
ac_dir_suffix= ac_top_builddir=
fi
case $srcdir in
.) # No --srcdir option. We are building in place.
ac_srcdir=.
if test -z "$ac_top_builddir"; then
ac_top_srcdir=.
else
ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
fi ;;
[\\/]* | ?:[\\/]* ) # Absolute path.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir ;;
*) # Relative path.
ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_builddir$srcdir ;;
esac
# Do not use `cd foo && pwd` to compute absolute paths, because
# the directories may not exist.
case `pwd` in
.) ac_abs_builddir="$ac_dir";;
*)
case "$ac_dir" in
.) ac_abs_builddir=`pwd`;;
[\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
*) ac_abs_builddir=`pwd`/"$ac_dir";;
esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_builddir=${ac_top_builddir}.;;
*)
case ${ac_top_builddir}. in
.) ac_abs_top_builddir=$ac_abs_builddir;;
[\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
*) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
esac;;
esac
case $ac_abs_builddir in
.) ac_abs_srcdir=$ac_srcdir;;
*)
case $ac_srcdir in
.) ac_abs_srcdir=$ac_abs_builddir;;
[\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
*) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_srcdir=$ac_top_srcdir;;
*)
case $ac_top_srcdir in
.) ac_abs_top_srcdir=$ac_abs_builddir;;
[\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
*) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
esac;;
esac
if test x"$ac_file" != x-; then
{ echo "$as_me:732: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
rm -f "$ac_file"
fi
# Let's still pretend it is `configure' which instantiates (i.e., don't
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
if test x"$ac_file" = x-; then
configure_input=
else
configure_input="$ac_file. "
fi
configure_input=$configure_input"Generated from `echo $ac_file_in |
sed 's,.*/,,'` by configure."
# First look for the input files in the build tree, otherwise in the
# src tree.
ac_file_inputs=`IFS=:
for f in $ac_file_in; do
case $f in
-) echo $tmp/stdin ;;
[\\/$]*)
# Absolute (can't be DOS-style, as IFS=:)
test -f "$f" || { { echo "$as_me:755: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
echo "$f";;
*) # Relative
if test -f "$f"; then
# Build tree
echo "$f"
elif test -f "$srcdir/$f"; then
# Source tree
echo "$srcdir/$f"
else
# /dev/null tree
{ { echo "$as_me:768: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
fi;;
esac
done` || { (exit 1); exit 1; }
sed "
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s,@configure_input@,$configure_input,;t t
s,@srcdir@,$ac_srcdir,;t t
s,@abs_srcdir@,$ac_abs_srcdir,;t t
s,@top_srcdir@,$ac_top_srcdir,;t t
s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
s,@builddir@,$ac_builddir,;t t
s,@abs_builddir@,$ac_abs_builddir,;t t
s,@top_builddir@,$ac_top_builddir,;t t
s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
rm -f $tmp/stdin
if test x"$ac_file" != x-; then
mv $tmp/out $ac_file
else
cat $tmp/out
rm -f $tmp/out
fi
done
#
# CONFIG_COMMANDS section.
#
for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_dest" : 'X\(//\)[^/]' \| \
X"$ac_dest" : 'X\(//\)$' \| \
X"$ac_dest" : 'X\(/\)' \| \
. : '\(.\)' 2>/dev/null ||
echo X"$ac_dest" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
/^X\(\/\/\)[^/].*/{ s//\1/; q; }
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
{ if $as_mkdir_p; then
mkdir -p "$ac_dir"
else
as_dir="$ac_dir"
as_dirs=
while test ! -d "$as_dir"; do
as_dirs="$as_dir $as_dirs"
as_dir=`(dirname "$as_dir") 2>/dev/null ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| \
. : '\(.\)' 2>/dev/null ||
echo X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
/^X\(\/\/\)[^/].*/{ s//\1/; q; }
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
done
test ! -n "$as_dirs" || mkdir $as_dirs
fi || { { echo "$as_me:837: error: cannot create directory \"$ac_dir\"" >&5
echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
{ (exit 1); exit 1; }; }; }
ac_builddir=.
if test "$ac_dir" != .; then
ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
# A "../" for each directory in $ac_dir_suffix.
ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
else
ac_dir_suffix= ac_top_builddir=
fi
case $srcdir in
.) # No --srcdir option. We are building in place.
ac_srcdir=.
if test -z "$ac_top_builddir"; then
ac_top_srcdir=.
else
ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
fi ;;
[\\/]* | ?:[\\/]* ) # Absolute path.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir ;;
*) # Relative path.
ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_builddir$srcdir ;;
esac
# Do not use `cd foo && pwd` to compute absolute paths, because
# the directories may not exist.
case `pwd` in
.) ac_abs_builddir="$ac_dir";;
*)
case "$ac_dir" in
.) ac_abs_builddir=`pwd`;;
[\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
*) ac_abs_builddir=`pwd`/"$ac_dir";;
esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_builddir=${ac_top_builddir}.;;
*)
case ${ac_top_builddir}. in
.) ac_abs_top_builddir=$ac_abs_builddir;;
[\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
*) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
esac;;
esac
case $ac_abs_builddir in
.) ac_abs_srcdir=$ac_srcdir;;
*)
case $ac_srcdir in
.) ac_abs_srcdir=$ac_abs_builddir;;
[\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
*) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_srcdir=$ac_top_srcdir;;
*)
case $ac_top_srcdir in
.) ac_abs_top_srcdir=$ac_abs_builddir;;
[\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
*) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
esac;;
esac
{ echo "$as_me:907: executing $ac_dest commands" >&5
echo "$as_me: executing $ac_dest commands" >&6;}
case $ac_dest in
Tcl.framework ) n=Tcl &&
f=$n.framework && v=Versions/$VERSION &&
rm -rf $f && mkdir -p $f/$v/Resources &&
ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
unset n f v
;;
esac
done
{ (exit 0); exit 0; }
+1
View File
@@ -263,6 +263,7 @@ ${AC_FLAGS} ${COMPILE_DEBUG_FLAGS}
TCLTEST_OBJS = \
tclTest.$(OBJEXT) \
tclTestObj.$(OBJEXT) \
tclTestObjInterface.$(OBJEXT) \
tclTestProcBodyObj.$(OBJEXT) \
tclThreadTest.$(OBJEXT) \
tclWinTest.$(OBJEXT)
+1
View File
@@ -222,6 +222,7 @@ TCLSHOBJS = \
TCLTESTOBJS = \
$(TMP_DIR)\tclTest.obj \
$(TMP_DIR)\tclTestObj.obj \
$(TMP_DIR)\tclTestObjInterface.obj \
$(TMP_DIR)\tclTestProcBodyObj.obj \
$(TMP_DIR)\tclThreadTest.obj \
$(TMP_DIR)\tclWinTest.obj \