mirror of
https://github.com/tcltk/tcl.git
synced 2026-05-29 00:27:49 +08:00
Merge "revert-dup-pure" branch: get rid of TclDuplicatePureObj()
This commit is contained in:
@@ -812,6 +812,7 @@ Tcl_CreateInterp(void)
|
||||
#endif
|
||||
iPtr->freeProc = NULL;
|
||||
iPtr->errorLine = 0;
|
||||
iPtr->stubTable = &tclStubs;
|
||||
TclNewObj(iPtr->objResultPtr);
|
||||
Tcl_IncrRefCount(iPtr->objResultPtr);
|
||||
iPtr->handle = TclHandleCreate(iPtr);
|
||||
@@ -904,7 +905,8 @@ Tcl_CreateInterp(void)
|
||||
iPtr->activeInterpTracePtr = NULL;
|
||||
iPtr->assocData = NULL;
|
||||
iPtr->execEnvPtr = NULL; /* Set after namespaces initialized. */
|
||||
TclNewObj(iPtr->emptyObjPtr); /* Another empty object. */
|
||||
TclNewObj(iPtr->emptyObjPtr);
|
||||
/* Another empty object. */
|
||||
Tcl_IncrRefCount(iPtr->emptyObjPtr);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
iPtr->resultSpace[0] = 0;
|
||||
@@ -1018,12 +1020,6 @@ Tcl_CreateInterp(void)
|
||||
memset(statsPtr->literalCount, 0, sizeof(statsPtr->literalCount));
|
||||
#endif /* TCL_COMPILE_STATS */
|
||||
|
||||
/*
|
||||
* Initialise the stub table pointer.
|
||||
*/
|
||||
|
||||
iPtr->stubTable = &tclStubs;
|
||||
|
||||
/*
|
||||
* Initialize the ensemble error message rewriting support.
|
||||
*/
|
||||
@@ -5588,7 +5584,7 @@ TclEvalEx(
|
||||
* evaluation of the script. Only
|
||||
* TCL_EVAL_GLOBAL is currently supported. */
|
||||
Tcl_Size line, /* The line the script starts on. */
|
||||
int *clNextOuter, /* Information about an outer context for */
|
||||
Tcl_Size *clNextOuter, /* Information about an outer context for */
|
||||
const char *outerScript) /* continuation line data. This is set only in
|
||||
* TclSubstTokens(), to properly handle
|
||||
* [...]-nested commands. The 'outerScript'
|
||||
@@ -5610,7 +5606,8 @@ TclEvalEx(
|
||||
const char *p, *next;
|
||||
const unsigned int minObjs = 20;
|
||||
Tcl_Obj **objv, **objvSpace;
|
||||
int *expand, *lines, *lineSpace;
|
||||
int *expand;
|
||||
Tcl_Size *lines, *lineSpace;
|
||||
Tcl_Token *tokenPtr;
|
||||
int expandRequested, code = TCL_OK;
|
||||
Tcl_Size bytesLeft, commandLength;
|
||||
@@ -5628,10 +5625,10 @@ TclEvalEx(
|
||||
Tcl_Obj **stackObjArray = (Tcl_Obj **)
|
||||
TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
|
||||
int *expandStack = (int *)TclStackAlloc(interp, minObjs * sizeof(int));
|
||||
int *linesStack = (int *)TclStackAlloc(interp, minObjs * sizeof(int));
|
||||
Tcl_Size *linesStack = (Tcl_Size *)TclStackAlloc(interp, minObjs * sizeof(Tcl_Size));
|
||||
/* TIP #280 Structures for tracking of command
|
||||
* locations. */
|
||||
int *clNext = NULL; /* Pointer for the tracking of invisible
|
||||
Tcl_Size *clNext = NULL; /* Pointer for the tracking of invisible
|
||||
* continuation lines. Initialized only if the
|
||||
* caller gave us a table of locations to
|
||||
* track, via scriptCLLocPtr. It always refers
|
||||
@@ -5755,7 +5752,7 @@ TclEvalEx(
|
||||
|
||||
Tcl_Size wordLine = line;
|
||||
const char *wordStart = parsePtr->commandStart;
|
||||
int *wordCLNext = clNext;
|
||||
Tcl_Size *wordCLNext = clNext;
|
||||
unsigned int objectsNeeded = 0;
|
||||
unsigned int numWords = parsePtr->numWords;
|
||||
|
||||
@@ -5766,7 +5763,7 @@ TclEvalEx(
|
||||
if (numWords > minObjs) {
|
||||
expand = (int *)ckalloc(numWords * sizeof(int));
|
||||
objvSpace = (Tcl_Obj **)ckalloc(numWords * sizeof(Tcl_Obj *));
|
||||
lineSpace = (int *)ckalloc(numWords * sizeof(int));
|
||||
lineSpace = (Tcl_Size *)ckalloc(numWords * sizeof(Tcl_Size));
|
||||
}
|
||||
expandRequested = 0;
|
||||
objv = objvSpace;
|
||||
@@ -5846,14 +5843,14 @@ TclEvalEx(
|
||||
*/
|
||||
|
||||
Tcl_Obj **copy = objvSpace;
|
||||
int *lcopy = lineSpace;
|
||||
int wordIdx = numWords;
|
||||
int objIdx = objectsNeeded - 1;
|
||||
Tcl_Size *lcopy = lineSpace;
|
||||
Tcl_Size wordIdx = numWords;
|
||||
Tcl_Size objIdx = objectsNeeded - 1;
|
||||
|
||||
if ((numWords > minObjs) || (objectsNeeded > minObjs)) {
|
||||
objv = objvSpace =
|
||||
(Tcl_Obj **)ckalloc(objectsNeeded * sizeof(Tcl_Obj *));
|
||||
lines = lineSpace = (int *)ckalloc(objectsNeeded * sizeof(int));
|
||||
lines = lineSpace = (Tcl_Size *)ckalloc(objectsNeeded * sizeof(Tcl_Size));
|
||||
}
|
||||
|
||||
objectsUsed = 0;
|
||||
@@ -6088,7 +6085,7 @@ TclAdvanceLines(
|
||||
void
|
||||
TclAdvanceContinuations(
|
||||
Tcl_Size *line,
|
||||
int **clNextPtrPtr,
|
||||
Tcl_Size **clNextPtrPtr,
|
||||
int loc)
|
||||
{
|
||||
/*
|
||||
@@ -6266,7 +6263,7 @@ TclArgumentBCEnter(
|
||||
int objc,
|
||||
void *codePtr,
|
||||
CmdFrame *cfPtr,
|
||||
int cmd,
|
||||
Tcl_Size cmd,
|
||||
Tcl_Size pc)
|
||||
{
|
||||
ExtCmdLoc *eclPtr;
|
||||
@@ -6658,11 +6655,7 @@ TclNREvalObjEx(
|
||||
*/
|
||||
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
listPtr = TclDuplicatePureObj(interp, objPtr, &tclListType);
|
||||
if (!listPtr) {
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
listPtr = TclListObjCopy(interp, objPtr);
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
|
||||
if (word != INT_MIN) {
|
||||
|
||||
@@ -689,11 +689,11 @@ EncodingConvertfromObjCmd(
|
||||
/* NOTE: ds must be freed beyond this point even on error */
|
||||
switch (result) {
|
||||
case TCL_OK:
|
||||
errorLocation = TCL_INDEX_NONE;
|
||||
break;
|
||||
errorLocation = TCL_INDEX_NONE;
|
||||
break;
|
||||
case TCL_ERROR:
|
||||
/* Error in parameters. Should not happen. interp will have error */
|
||||
Tcl_DStringFree(&ds);
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
default:
|
||||
/*
|
||||
@@ -703,10 +703,10 @@ EncodingConvertfromObjCmd(
|
||||
* what could be decoded and the returned error location.
|
||||
*/
|
||||
if (failVarObj == NULL) {
|
||||
Tcl_DStringFree(&ds);
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -791,7 +791,7 @@ EncodingConverttoObjCmd(
|
||||
break;
|
||||
case TCL_ERROR:
|
||||
/* Error in parameters. Should not happen. interp will have error */
|
||||
Tcl_DStringFree(&ds);
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
default:
|
||||
/*
|
||||
@@ -801,10 +801,10 @@ EncodingConverttoObjCmd(
|
||||
* what could be decoded and the returned error location.
|
||||
*/
|
||||
if (failVarObj == NULL) {
|
||||
Tcl_DStringFree(&ds);
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* TCL_OK or a TCL_CONVERT_* error where the caller wants back as much
|
||||
@@ -1337,10 +1337,10 @@ FileAttrAccessTimeCmd(
|
||||
#if defined(_WIN32)
|
||||
/* We use a value of 0 to indicate the access time not available */
|
||||
if (Tcl_GetAccessTimeFromStat(&buf) == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"could not get access time for file \"%s\"",
|
||||
TclGetString(objv[1])));
|
||||
return TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"could not get access time for file \"%s\"",
|
||||
TclGetString(objv[1])));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1419,10 +1419,10 @@ FileAttrModifyTimeCmd(
|
||||
#if defined(_WIN32)
|
||||
/* We use a value of 0 to indicate the modification time not available */
|
||||
if (Tcl_GetModificationTimeFromStat(&buf) == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"could not get modification time for file \"%s\"",
|
||||
TclGetString(objv[1])));
|
||||
return TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"could not get modification time for file \"%s\"",
|
||||
TclGetString(objv[1])));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#endif
|
||||
if (objc == 3) {
|
||||
@@ -2462,34 +2462,34 @@ StoreStatData(
|
||||
unsigned short mode;
|
||||
|
||||
if (varName == NULL) {
|
||||
TclNewObj(result);
|
||||
Tcl_IncrRefCount(result);
|
||||
TclNewObj(result);
|
||||
Tcl_IncrRefCount(result);
|
||||
#define DOBJPUT(key, objValue) \
|
||||
Tcl_DictObjPut(NULL, result, \
|
||||
Tcl_NewStringObj((key), -1), \
|
||||
(objValue));
|
||||
DOBJPUT("dev", Tcl_NewWideIntObj((long)statPtr->st_dev));
|
||||
DOBJPUT("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
|
||||
DOBJPUT("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink));
|
||||
DOBJPUT("uid", Tcl_NewWideIntObj((long)statPtr->st_uid));
|
||||
DOBJPUT("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
|
||||
DOBJPUT("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
|
||||
DOBJPUT("dev", Tcl_NewWideIntObj((long)statPtr->st_dev));
|
||||
DOBJPUT("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
|
||||
DOBJPUT("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink));
|
||||
DOBJPUT("uid", Tcl_NewWideIntObj((long)statPtr->st_uid));
|
||||
DOBJPUT("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
|
||||
DOBJPUT("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
DOBJPUT("blocks", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
|
||||
DOBJPUT("blocks", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
DOBJPUT("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
|
||||
DOBJPUT("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
|
||||
#endif
|
||||
DOBJPUT("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
|
||||
DOBJPUT("mtime", Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
DOBJPUT("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
|
||||
mode = (unsigned short) statPtr->st_mode;
|
||||
DOBJPUT("mode", Tcl_NewWideIntObj(mode));
|
||||
DOBJPUT("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
|
||||
DOBJPUT("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
|
||||
DOBJPUT("mtime", Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
DOBJPUT("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
|
||||
mode = (unsigned short) statPtr->st_mode;
|
||||
DOBJPUT("mode", Tcl_NewWideIntObj(mode));
|
||||
DOBJPUT("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
|
||||
#undef DOBJPUT
|
||||
Tcl_SetObjResult(interp, result);
|
||||
Tcl_DecrRefCount(result);
|
||||
return TCL_OK;
|
||||
Tcl_SetObjResult(interp, result);
|
||||
Tcl_DecrRefCount(result);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2927,9 +2927,10 @@ EachloopCmd(
|
||||
for (i=0 ; i<numLists ; i++) {
|
||||
/* List */
|
||||
/* Variables */
|
||||
statePtr->vCopyList[i] = TclDuplicatePureObj(
|
||||
interp, objv[1+i*2], &tclListType);
|
||||
if (!statePtr->vCopyList[i]) {
|
||||
|
||||
/* Do not use TclListObjCopy here - shimmers arithseries to list */
|
||||
statePtr->vCopyList[i] = Tcl_DuplicateObj(objv[1+i*2]);
|
||||
if (statePtr->vCopyList[i] == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
@@ -2964,9 +2965,8 @@ EachloopCmd(
|
||||
statePtr->argcList[i] = TclArithSeriesObjLength(statePtr->aCopyList[i]);
|
||||
} else {
|
||||
/* List values */
|
||||
statePtr->aCopyList[i] = TclDuplicatePureObj(
|
||||
interp, objv[2+i*2], &tclListType);
|
||||
if (!statePtr->aCopyList[i]) {
|
||||
statePtr->aCopyList[i] = TclListObjCopy(interp, objv[2+i*2]);
|
||||
if (statePtr->aCopyList[i] == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
@@ -3106,9 +3106,9 @@ ForeachAssignments(
|
||||
valuePtr = TclArithSeriesObjIndex(interp, statePtr->aCopyList[i], k);
|
||||
if (valuePtr == NULL) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (setting %s loop variable \"%s\")",
|
||||
(statePtr->resultList != NULL ? "lmap" : "foreach"),
|
||||
TclGetString(statePtr->varvList[i][v])));
|
||||
"\n (setting %s loop variable \"%s\")",
|
||||
(statePtr->resultList != NULL ? "lmap" : "foreach"),
|
||||
TclGetString(statePtr->varvList[i][v])));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -2333,7 +2333,7 @@ Tcl_LassignObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
listCopyPtr = TclDuplicatePureObj(interp, objv[1], &tclListType);
|
||||
listCopyPtr = TclListObjCopy(interp, objv[1]);
|
||||
if (listCopyPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2498,10 +2498,7 @@ Tcl_LinsertObjCmd(
|
||||
|
||||
listPtr = objv[1];
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
}
|
||||
|
||||
if ((objc == 4) && (index == len)) {
|
||||
@@ -2688,10 +2685,7 @@ Tcl_LpopObjCmd(
|
||||
|
||||
if (objc == 2) {
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
}
|
||||
result = Tcl_ListObjReplace(interp, listPtr, listLen - 1, 1, 0, NULL);
|
||||
if (result != TCL_OK) {
|
||||
@@ -2868,11 +2862,7 @@ Tcl_LremoveObjCmd(
|
||||
*/
|
||||
|
||||
if (Tcl_IsShared(listObj)) {
|
||||
listObj = TclDuplicatePureObj(interp, listObj, &tclListType);
|
||||
if (!listObj) {
|
||||
status = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
listObj = TclListObjCopy(NULL, listObj);
|
||||
copied = 1;
|
||||
}
|
||||
num = 0;
|
||||
@@ -3124,10 +3114,7 @@ Tcl_LreplaceObjCmd(
|
||||
|
||||
listPtr = objv[1];
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4015,91 +4002,6 @@ Tcl_LsearchObjCmd(
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_LsetObjCmd --
|
||||
*
|
||||
* This procedure is invoked to process the "lset" Tcl command. See the
|
||||
* user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
Tcl_LsetObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument values. */
|
||||
{
|
||||
Tcl_Obj *listPtr; /* Pointer to the list being altered. */
|
||||
Tcl_Obj *finalValuePtr; /* Value finally assigned to the variable. */
|
||||
|
||||
/*
|
||||
* Check parameter count.
|
||||
*/
|
||||
|
||||
if (objc < 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"listVar ?index? ?index ...? value");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the list variable's value.
|
||||
*/
|
||||
|
||||
listPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
|
||||
if (listPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Substitute the value in the value. Return either the value or else an
|
||||
* unshared copy of it.
|
||||
*/
|
||||
|
||||
if (objc == 4) {
|
||||
finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
|
||||
} else {
|
||||
finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
|
||||
objv[objc-1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If substitution has failed, bail out.
|
||||
*/
|
||||
|
||||
if (finalValuePtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, update the variable so that traces fire.
|
||||
*/
|
||||
|
||||
listPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, finalValuePtr,
|
||||
TCL_LEAVE_ERR_MSG);
|
||||
Tcl_DecrRefCount(finalValuePtr);
|
||||
if (listPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the new value of the variable as the interpreter result.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, listPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -4314,7 +4216,7 @@ Tcl_LseqObjCmd(
|
||||
goto done;
|
||||
break;
|
||||
|
||||
/* range n */
|
||||
/* lseq n */
|
||||
case 1:
|
||||
start = zero;
|
||||
elementCount = numValues[0];
|
||||
@@ -4322,22 +4224,22 @@ Tcl_LseqObjCmd(
|
||||
step = one;
|
||||
break;
|
||||
|
||||
/* range n n */
|
||||
/* lseq n n */
|
||||
case 11:
|
||||
start = numValues[0];
|
||||
end = numValues[1];
|
||||
break;
|
||||
|
||||
/* range n n n */
|
||||
/* lseq n n n */
|
||||
case 111:
|
||||
start = numValues[0];
|
||||
end = numValues[1];
|
||||
step = numValues[2];
|
||||
break;
|
||||
|
||||
/* range n 'to' n */
|
||||
/* range n 'count' n */
|
||||
/* range n 'by' n */
|
||||
/* lseq n 'to' n */
|
||||
/* lseq n 'count' n */
|
||||
/* lseq n 'by' n */
|
||||
case 121:
|
||||
opmode = (SequenceOperators)values[1];
|
||||
switch (opmode) {
|
||||
@@ -4362,8 +4264,8 @@ Tcl_LseqObjCmd(
|
||||
}
|
||||
break;
|
||||
|
||||
/* range n 'to' n n */
|
||||
/* range n 'count' n n */
|
||||
/* lseq n 'to' n n */
|
||||
/* lseq n 'count' n n */
|
||||
case 1211:
|
||||
opmode = (SequenceOperators)values[1];
|
||||
switch (opmode) {
|
||||
@@ -4390,7 +4292,7 @@ Tcl_LseqObjCmd(
|
||||
}
|
||||
break;
|
||||
|
||||
/* range n n 'by' n */
|
||||
/* lseq n n 'by' n */
|
||||
case 1121:
|
||||
start = numValues[0];
|
||||
end = numValues[1];
|
||||
@@ -4409,8 +4311,8 @@ Tcl_LseqObjCmd(
|
||||
}
|
||||
break;
|
||||
|
||||
/* range n 'to' n 'by' n */
|
||||
/* range n 'count' n 'by' n */
|
||||
/* lseq n 'to' n 'by' n */
|
||||
/* lseq n 'count' n 'by' n */
|
||||
case 12121:
|
||||
start = numValues[0];
|
||||
opmode = (SequenceOperators)values[3];
|
||||
@@ -4500,6 +4402,91 @@ Tcl_LseqObjCmd(
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_LsetObjCmd --
|
||||
*
|
||||
* This procedure is invoked to process the "lset" Tcl command. See the
|
||||
* user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
Tcl_LsetObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument values. */
|
||||
{
|
||||
Tcl_Obj *listPtr; /* Pointer to the list being altered. */
|
||||
Tcl_Obj *finalValuePtr; /* Value finally assigned to the variable. */
|
||||
|
||||
/*
|
||||
* Check parameter count.
|
||||
*/
|
||||
|
||||
if (objc < 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"listVar ?index? ?index ...? value");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the list variable's value.
|
||||
*/
|
||||
|
||||
listPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
|
||||
if (listPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Substitute the value in the value. Return either the value or else an
|
||||
* unshared copy of it.
|
||||
*/
|
||||
|
||||
if (objc == 4) {
|
||||
finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
|
||||
} else {
|
||||
finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
|
||||
objv[objc-1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If substitution has failed, bail out.
|
||||
*/
|
||||
|
||||
if (finalValuePtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, update the variable so that traces fire.
|
||||
*/
|
||||
|
||||
listPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, finalValuePtr,
|
||||
TCL_LEAVE_ERR_MSG);
|
||||
Tcl_DecrRefCount(finalValuePtr);
|
||||
if (listPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the new value of the variable as the interpreter result.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, listPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -4743,7 +4730,7 @@ Tcl_LsortObjCmd(
|
||||
* 1675116]
|
||||
*/
|
||||
|
||||
listObj = TclDuplicatePureObj(interp ,listObj, &tclListType);
|
||||
listObj = TclListObjCopy(interp, listObj);
|
||||
if (listObj == NULL) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done;
|
||||
@@ -5101,10 +5088,7 @@ Tcl_LeditObjCmd(
|
||||
}
|
||||
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
createdNewObj = 1;
|
||||
} else {
|
||||
createdNewObj = 0;
|
||||
|
||||
@@ -1900,11 +1900,7 @@ NsEnsembleImplementationCmdNR(
|
||||
TclListObjLengthM(NULL, prefixObj, &prefixObjc);
|
||||
|
||||
if (objc == 2) {
|
||||
copyPtr = TclDuplicatePureObj(
|
||||
interp, prefixObj, &tclListType);
|
||||
if (!copyPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
copyPtr = TclListObjCopy(NULL, prefixObj);
|
||||
} else {
|
||||
copyPtr = Tcl_NewListObj(objc - 2 + prefixObjc, NULL);
|
||||
Tcl_ListObjAppendList(NULL, copyPtr, prefixObj);
|
||||
@@ -3055,7 +3051,7 @@ TclCompileEnsemble(
|
||||
* No map, so check the dictionary directly.
|
||||
*/
|
||||
|
||||
TclNewStringObj(subcmdObj, word, (int) numBytes);
|
||||
TclNewStringObj(subcmdObj, word, numBytes);
|
||||
result = Tcl_DictObjGet(NULL, mapObj, subcmdObj, &targetCmdObj);
|
||||
if (result == TCL_OK && targetCmdObj != NULL) {
|
||||
/*
|
||||
|
||||
@@ -243,11 +243,7 @@ HandleBgErrors(
|
||||
* support one handler setting another handler.
|
||||
*/
|
||||
|
||||
Tcl_Obj *copyObj = TclDuplicatePureObj(
|
||||
interp, assocPtr->cmdPrefix, &tclListType);
|
||||
if (!copyObj) {
|
||||
return;
|
||||
}
|
||||
Tcl_Obj *copyObj = TclListObjCopy(NULL, assocPtr->cmdPrefix);
|
||||
|
||||
errPtr = assocPtr->firstBgPtr;
|
||||
|
||||
|
||||
@@ -6692,7 +6692,8 @@ TEBCresume(
|
||||
numVars = varListPtr->numVars;
|
||||
|
||||
listVarPtr = LOCAL(listTmpIndex);
|
||||
listPtr = TclDuplicatePureObj(NULL, listVarPtr->value.objPtr, &tclListType);
|
||||
/* Do not use TclListObjCopy here - shimmers arithseries to list */
|
||||
listPtr = Tcl_DuplicateObj(listVarPtr->value.objPtr);
|
||||
TclListObjGetElementsM(interp, listPtr, &listLen, &elements);
|
||||
|
||||
valIndex = (iterNum * numVars);
|
||||
@@ -6789,7 +6790,7 @@ TEBCresume(
|
||||
goto gotError;
|
||||
}
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
/* Do NOT use TclDuplicatePureObj here - shimmers abstract list to list */
|
||||
/* Do not use TclListObjCopy here - shimmers arithseries to list */
|
||||
objPtr = Tcl_DuplicateObj(listPtr);
|
||||
if (!objPtr) {
|
||||
goto gotError;
|
||||
|
||||
@@ -387,11 +387,7 @@ ExecuteCallback(
|
||||
unsigned char *resBuf;
|
||||
Tcl_InterpState state = NULL;
|
||||
int res = TCL_OK;
|
||||
Tcl_Obj *command = TclDuplicatePureObj(
|
||||
interp, dataPtr->command, &tclListType);
|
||||
if (!command) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Obj *command = TclListObjCopy(NULL, dataPtr->command);
|
||||
Tcl_Interp *eval = dataPtr->interp;
|
||||
|
||||
Tcl_Preserve(eval);
|
||||
|
||||
@@ -2285,10 +2285,7 @@ NewReflectedChannel(
|
||||
rcPtr->mode = mode;
|
||||
rcPtr->interest = 0; /* Initially no interest registered */
|
||||
|
||||
rcPtr->cmd = TclDuplicatePureObj(interp, cmdpfxObj, &tclListType);
|
||||
if (!rcPtr->cmd) {
|
||||
return NULL;
|
||||
}
|
||||
rcPtr->cmd = TclListObjCopy(NULL, cmdpfxObj);
|
||||
Tcl_IncrRefCount(rcPtr->cmd);
|
||||
rcPtr->methods = Tcl_NewListObj(METH_WRITE + 1, NULL);
|
||||
while (mn <= (int)METH_WRITE) {
|
||||
@@ -2425,10 +2422,7 @@ InvokeTclMethod(
|
||||
* before the channel id.
|
||||
*/
|
||||
|
||||
cmd = TclDuplicatePureObj(NULL, rcPtr->cmd, &tclListType);
|
||||
if (!cmd) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
cmd = TclListObjCopy(NULL, rcPtr->cmd);
|
||||
Tcl_ListObjIndex(NULL, rcPtr->methods, method, &methObj);
|
||||
Tcl_ListObjAppendElement(NULL, cmd, methObj);
|
||||
Tcl_ListObjAppendElement(NULL, cmd, rcPtr->name);
|
||||
|
||||
@@ -3142,8 +3142,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_Obj *TclDuplicatePureObj(Tcl_Interp *interp,
|
||||
Tcl_Obj * objPtr, const Tcl_ObjType *typPtr);
|
||||
MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp,
|
||||
const char *dict, Tcl_Size dictLength,
|
||||
const char **elementPtr, const char **nextPtr,
|
||||
@@ -3273,6 +3271,7 @@ MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
/* TIP #280 */
|
||||
MODULE_SCOPE void TclListLines(Tcl_Obj *listObj, Tcl_Size line, Tcl_Size n,
|
||||
Tcl_Size *lines, Tcl_Obj *const *elems);
|
||||
MODULE_SCOPE Tcl_Obj * TclListObjCopy(Tcl_Interp *interp, Tcl_Obj *listPtr);
|
||||
MODULE_SCOPE int TclListObjAppendElements(Tcl_Interp *interp,
|
||||
Tcl_Obj *toObj, Tcl_Size elemCount,
|
||||
Tcl_Obj *const elemObjv[]);
|
||||
|
||||
@@ -1341,6 +1341,47 @@ Tcl_SetListObj(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclListObjCopy --
|
||||
*
|
||||
* Makes a "pure list" copy of a list value. This provides for the C
|
||||
* level a counterpart of the [lrange $list 0 end] command, while using
|
||||
* internals details to be as efficient as possible.
|
||||
*
|
||||
* Results:
|
||||
* Normally returns a pointer to a new Tcl_Obj, that contains the same
|
||||
* list value as *listPtr does. The returned Tcl_Obj has a refCount of
|
||||
* zero. If *listPtr does not hold a list, NULL is returned, and if
|
||||
* interp is non-NULL, an error message is recorded there.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclListObjCopy(
|
||||
Tcl_Interp *interp, /* Used to report errors if not NULL. */
|
||||
Tcl_Obj *listObj) /* List object for which an element array is
|
||||
* to be returned. */
|
||||
{
|
||||
Tcl_Obj *copyObj;
|
||||
|
||||
if (!TclHasInternalRep(listObj, &tclListType)) {
|
||||
if (SetListFromAny(interp, listObj) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TclNewObj(copyObj);
|
||||
TclInvalidateStringRep(copyObj);
|
||||
DupListInternalRep(listObj, copyObj);
|
||||
return copyObj;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
@@ -2513,7 +2554,6 @@ TclLindexList(
|
||||
Tcl_Obj *indexListCopy;
|
||||
Tcl_Obj **indexObjs;
|
||||
Tcl_Size numIndexObjs;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Determine whether argPtr designates a list or a single index. We have
|
||||
@@ -2531,30 +2571,19 @@ TclLindexList(
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a private copy of the index list argument to keep the internal
|
||||
* representation of the indices array unchanged while it is in use. This
|
||||
* is probably unnecessary. It does not appear that any damaging change to
|
||||
* the internal representation is possible, and no test has been devised to
|
||||
* show any error when this private copy is not made, But it's cheap, and
|
||||
* it offers some future-proofing insurance in case the TclLindexFlat
|
||||
* implementation changes in some unexpected way, or some new form of trace
|
||||
* or callback permits things to happen that the current implementation
|
||||
* does not.
|
||||
* Here we make a private copy of the index list argument to avoid any
|
||||
* shimmering issues that might invalidate the indices array below while
|
||||
* we are still using it. This is probably unnecessary. It does not appear
|
||||
* that any damaging shimmering is possible, and no test has been devised
|
||||
* to show any error when this private copy is not made. But it's cheap,
|
||||
* and it offers some future-proofing insurance in case the TclLindexFlat
|
||||
* implementation changes in some unexpected way, or some new form of
|
||||
* trace or callback permits things to happen that the current
|
||||
* implementation does not.
|
||||
*/
|
||||
|
||||
indexListCopy = TclDuplicatePureObj(interp, argObj, &tclListType);
|
||||
if (!indexListCopy) {
|
||||
/*
|
||||
* The argument is neither an index nor a well-formed list.
|
||||
* Report the error via TclLindexFlat.
|
||||
* TODO - This is as original code. why not directly return an error?
|
||||
*/
|
||||
return TclLindexFlat(interp, listObj, 1, &argObj);
|
||||
}
|
||||
status = TclListObjGetElementsM(
|
||||
interp, indexListCopy, &numIndexObjs, &indexObjs);
|
||||
if (status != TCL_OK) {
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
indexListCopy = TclListObjCopy(NULL, argObj);
|
||||
if (indexListCopy == NULL) {
|
||||
/*
|
||||
* The argument is neither an index nor a well-formed list.
|
||||
* Report the error via TclLindexFlat.
|
||||
@@ -2562,6 +2591,7 @@ TclLindexList(
|
||||
*/
|
||||
return TclLindexFlat(interp, listObj, 1, &argObj);
|
||||
}
|
||||
TclListObjGetElementsM(interp, indexListCopy, &numIndexObjs, &indexObjs);
|
||||
listObj = TclLindexFlat(interp, listObj, numIndexObjs, indexObjs);
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
return listObj;
|
||||
@@ -2744,8 +2774,7 @@ TclLsetList(
|
||||
|
||||
} else {
|
||||
|
||||
indexListCopy = TclDuplicatePureObj(
|
||||
interp, indexArgObj, &tclListType);
|
||||
indexListCopy = TclListObjCopy(NULL,indexArgObj);
|
||||
if (!indexListCopy) {
|
||||
/*
|
||||
* indexArgPtr designates something that is neither an index nor a
|
||||
@@ -2823,7 +2852,7 @@ TclLsetFlat(
|
||||
Tcl_Obj *valueObj) /* Value arg to 'lset' or NULL to 'lpop'. */
|
||||
{
|
||||
Tcl_Size index, len;
|
||||
int copied = 0, result;
|
||||
int result;
|
||||
Tcl_Obj *subListObj, *retValueObj;
|
||||
Tcl_Obj *pendingInvalidates[10];
|
||||
Tcl_Obj **pendingInvalidatesPtr = pendingInvalidates;
|
||||
@@ -2843,15 +2872,17 @@ TclLsetFlat(
|
||||
}
|
||||
|
||||
/*
|
||||
* If the list is shared, make a copy to modify (copy-on-write). The string
|
||||
* representation and internal representation of listObj remains unchanged.
|
||||
* If the list is shared, make a copy we can modify (copy-on-write). We
|
||||
* use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons:
|
||||
* 1) we have not yet confirmed listObj is actually a list; 2) We make a
|
||||
* verbatim copy of any existing string rep, and when we combine that with
|
||||
* the delayed invalidation of string reps of modified Tcl_Obj's
|
||||
* implemented below, the outcome is that any error condition that causes
|
||||
* this routine to return NULL, will leave the string rep of listObj and
|
||||
* all elements to be unchanged.
|
||||
*/
|
||||
|
||||
subListObj = Tcl_IsShared(listObj)
|
||||
? TclDuplicatePureObj(interp, listObj, &tclListType) : listObj;
|
||||
if (!subListObj) {
|
||||
return NULL;
|
||||
}
|
||||
subListObj = Tcl_IsShared(listObj) ? Tcl_DuplicateObj(listObj) : listObj;
|
||||
|
||||
/*
|
||||
* Anchor the linked list of Tcl_Obj's whose string reps must be
|
||||
@@ -2924,9 +2955,10 @@ TclLsetFlat(
|
||||
}
|
||||
|
||||
/*
|
||||
* No error conditions. If this is not the last index, determine the
|
||||
* next sublist for the next pass through the loop, and take steps to
|
||||
* make sure it is unshared in order to modify it.
|
||||
* No error conditions. As long as we're not yet on the last index,
|
||||
* determine the next sublist for the next pass through the loop,
|
||||
* and take steps to make sure it is an unshared copy, as we intend
|
||||
* to modify it.
|
||||
*/
|
||||
|
||||
if (--indexCount) {
|
||||
@@ -2937,12 +2969,7 @@ TclLsetFlat(
|
||||
subListObj = elemPtrs[index];
|
||||
}
|
||||
if (Tcl_IsShared(subListObj)) {
|
||||
subListObj = TclDuplicatePureObj(
|
||||
interp, subListObj, &tclListType);
|
||||
if (!subListObj) {
|
||||
return NULL;
|
||||
}
|
||||
copied = 1;
|
||||
subListObj = Tcl_DuplicateObj(subListObj);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2960,17 +2987,7 @@ TclLsetFlat(
|
||||
TclListObjSetElement(NULL, parentList, index, subListObj);
|
||||
}
|
||||
if (Tcl_IsShared(subListObj)) {
|
||||
Tcl_Obj * newSubListObj;
|
||||
newSubListObj = TclDuplicatePureObj(
|
||||
interp, subListObj, &tclListType);
|
||||
if (copied) {
|
||||
Tcl_DecrRefCount(subListObj);
|
||||
}
|
||||
if (newSubListObj) {
|
||||
subListObj = newSubListObj;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
subListObj = Tcl_DuplicateObj(subListObj);
|
||||
TclListObjSetElement(NULL, parentList, index, subListObj);
|
||||
}
|
||||
|
||||
|
||||
119
generic/tclObj.c
119
generic/tclObj.c
@@ -205,9 +205,6 @@ static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
|
||||
static void UpdateStringOfBignum(Tcl_Obj *objPtr);
|
||||
static int GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int copy, mp_int *bignumValue);
|
||||
static int SetDuplicatePureObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *dupPtr, Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr);
|
||||
|
||||
/*
|
||||
* Prototypes for the array hash key methods.
|
||||
@@ -1545,14 +1542,6 @@ TclObjBeingDeleted(
|
||||
* Create and return a new object that is a duplicate of the argument
|
||||
* object.
|
||||
*
|
||||
* TclDuplicatePureObj --
|
||||
* Like Tcl_DuplicateObj, except that it converts the duplicate to the
|
||||
* specifid typ, does not duplicate the 'bytes'
|
||||
* field unless it is necessary, i.e. the duplicated Tcl_Obj provides no
|
||||
* updateStringProc. This can avoid an expensive memory allocation since
|
||||
* the data in the 'bytes' field of each Tcl_Obj must reside in allocated
|
||||
* memory.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to a newly created Tcl_Obj. This object
|
||||
* has reference count 0 and the same type, if any, as the source object
|
||||
@@ -1604,114 +1593,6 @@ Tcl_DuplicateObj(
|
||||
return dupPtr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclDuplicatePureObj --
|
||||
*
|
||||
* Duplicates a Tcl_Obj and converts the internal representation of the
|
||||
* duplicate to the given type, changing neither the 'bytes' field
|
||||
* nor the internal representation of the original object, and without
|
||||
* duplicating the bytes field unless necessary, i.e. unless the
|
||||
* duplicate provides no updateStringProc after conversion. This can
|
||||
* avoid an expensive memory allocation since the data in the 'bytes'
|
||||
* field of each Tcl_Obj must reside in allocated memory.
|
||||
*
|
||||
* Results:
|
||||
* A pointer to a newly-created Tcl_Obj or NULL if there was an error.
|
||||
* This object has reference count 0. Also:
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
int SetDuplicatePureObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *dupPtr,
|
||||
Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr)
|
||||
{
|
||||
char *bytes = objPtr->bytes;
|
||||
int status = TCL_OK;
|
||||
|
||||
TclInvalidateStringRep(dupPtr);
|
||||
assert(dupPtr->typePtr == NULL);
|
||||
|
||||
if (objPtr->typePtr && objPtr->typePtr->dupIntRepProc) {
|
||||
objPtr->typePtr->dupIntRepProc(objPtr, dupPtr);
|
||||
} else {
|
||||
dupPtr->internalRep = objPtr->internalRep;
|
||||
dupPtr->typePtr = objPtr->typePtr;
|
||||
}
|
||||
|
||||
if (typePtr != NULL && dupPtr->typePtr != typePtr) {
|
||||
if (bytes) {
|
||||
dupPtr->bytes = bytes;
|
||||
dupPtr->length = objPtr->length;
|
||||
}
|
||||
/* borrow bytes from original object */
|
||||
status = Tcl_ConvertToType(interp, dupPtr, typePtr);
|
||||
if (bytes) {
|
||||
dupPtr->bytes = NULL;
|
||||
dupPtr->length = 0;
|
||||
}
|
||||
if (status != TCL_OK) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* tclUniCharStringType is treated as a special case because a Tcl_Obj having this
|
||||
* type can not always update the string representation. This happens, for
|
||||
* example, when Tcl_GetCharLength() converts the internal representation
|
||||
* to tclUniCharStringType in order to store the number of characters, but does
|
||||
* not store enough information to generate the string representation.
|
||||
*
|
||||
* Perhaps in the future this can be remedied and this special treatment
|
||||
* removed.
|
||||
*
|
||||
* Similar problem with the integer (0x0A vs 10), double (1e-1 vs 0.1) and
|
||||
* index types ("coord" vs "coords", see bug [a34733451b])
|
||||
*/
|
||||
|
||||
|
||||
if (bytes && (dupPtr->typePtr == NULL
|
||||
|| dupPtr->typePtr->updateStringProc == NULL
|
||||
|| objPtr->typePtr == &tclUniCharStringType
|
||||
)
|
||||
) {
|
||||
if (!TclAttemptInitStringRep(dupPtr, bytes, objPtr->length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"insufficient memory to initialize string", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
status = TCL_ERROR;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Tcl_Obj *
|
||||
TclDuplicatePureObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr
|
||||
) /* The object to duplicate. */
|
||||
{
|
||||
int status;
|
||||
Tcl_Obj *dupPtr;
|
||||
|
||||
TclNewObj(dupPtr);
|
||||
status = SetDuplicatePureObj(interp, dupPtr, objPtr, typePtr);
|
||||
if (status == TCL_OK) {
|
||||
return dupPtr;
|
||||
} else {
|
||||
Tcl_DecrRefCount(dupPtr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
TclSetDuplicateObj(
|
||||
Tcl_Obj *dupPtr,
|
||||
|
||||
@@ -2051,11 +2051,7 @@ Tcl_ConcatObj(
|
||||
goto slow;
|
||||
}
|
||||
} else {
|
||||
resPtr = TclDuplicatePureObj(
|
||||
NULL, objPtr, &tclListType);
|
||||
if (!resPtr) {
|
||||
return NULL;
|
||||
}
|
||||
resPtr = TclListObjCopy(NULL, objPtr);
|
||||
}
|
||||
}
|
||||
if (!resPtr) {
|
||||
|
||||
@@ -3221,7 +3221,8 @@ ArrayForNRCmd(
|
||||
* loop) don't vanish.
|
||||
*/
|
||||
|
||||
varListObj = TclDuplicatePureObj(interp, objv[1], &tclListType);
|
||||
/* Do not use TclListObjCopy here - shimmers arithseries to list */
|
||||
varListObj = Tcl_DuplicateObj(objv[1]);
|
||||
if (!varListObj) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -4196,8 +4197,7 @@ ArraySetCmd(
|
||||
* the loop and return an error.
|
||||
*/
|
||||
|
||||
copyListObj =
|
||||
TclDuplicatePureObj(interp, arrayElemObj, &tclListType);
|
||||
copyListObj = TclListObjCopy(NULL, arrayElemObj);
|
||||
if (!copyListObj) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1075,7 +1075,7 @@ test encoding-bug-183a1adcc0-4 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExtern
|
||||
} -result [list 0 [list nospace {} \x00\x00\xFF]]
|
||||
|
||||
test encoding-bug-183a1adcc0-5 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
|
||||
testencoding
|
||||
testencoding
|
||||
} -body {
|
||||
list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 4} result] $result
|
||||
} -result [list 0 [list ok {} [expr {$::tcl_platform(byteOrder) eq "littleEndian" ? "\x41\x00" : "\x00\x41"}]\x00\x00]]
|
||||
|
||||
Reference in New Issue
Block a user