summaryrefslogtreecommitdiffstats
path: root/generic/tclCmdIL.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclCmdIL.c')
-rw-r--r--generic/tclCmdIL.c1262
1 files changed, 487 insertions, 775 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index db216e5..ea9c1e4 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -3,7 +3,7 @@
*
* This file contains the top-level command routines for most of the Tcl
* built-in commands whose names begin with the letters I through L. It
- * contains only commands in the generic core (i.e., those that don't
+ * contains only commands in the generic core (i.e. those that don't
* depend much upon UNIX facilities).
*
* Copyright (c) 1987-1993 The Regents of the University of California.
@@ -27,16 +27,13 @@
*/
typedef struct SortElement {
- union { /* The value that we sorting by. */
- const char *strValuePtr;
- Tcl_WideInt wideValue;
+ union {
+ char *strValuePtr;
+ long intValue;
double doubleValue;
Tcl_Obj *objValuePtr;
- } collationKey;
- union { /* Object being sorted, or its index. */
- Tcl_Obj *objPtr;
- int index;
- } payload;
+ } index;
+ Tcl_Obj *objPtr; /* Object being sorted, or its index. */
struct SortElement *nextPtr;/* Next element in the list, or NULL for end
* of list. */
} SortElement;
@@ -104,9 +101,7 @@ typedef struct SortInfo {
* Forward declarations for procedures defined in this file:
*/
-static int DictionaryCompare(const char *left, const char *right);
-static int IfConditionCallback(ClientData data[],
- Tcl_Interp *interp, int result);
+static int DictionaryCompare(char *left, char *right);
static int InfoArgsCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
static int InfoBodyCmd(ClientData dummy, Tcl_Interp *interp,
@@ -119,9 +114,6 @@ static int InfoCompleteCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
static int InfoDefaultCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
-/* TIP #348 - New 'info' subcommand 'errorstack' */
-static int InfoErrorStackCmd(ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *const objv[]);
/* TIP #280 - New 'info' subcommand 'frame' */
static int InfoFrameCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
@@ -148,7 +140,7 @@ static int InfoSharedlibCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
static int InfoTclVersionCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
-static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr,
+static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr,
SortInfo *infoPtr);
static int SortCompare(SortElement *firstPtr, SortElement *second,
SortInfo *infoPtr);
@@ -161,31 +153,29 @@ static Tcl_Obj * SelectObjFromSublist(Tcl_Obj *firstPtr,
*/
static const EnsembleImplMap defaultInfoMap[] = {
- {"args", InfoArgsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
- {"body", InfoBodyCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
- {"cmdcount", InfoCmdCountCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
- {"commands", InfoCommandsCmd, TclCompileInfoCommandsCmd, NULL, NULL, 0},
- {"complete", InfoCompleteCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
- {"coroutine", TclInfoCoroutineCmd, TclCompileInfoCoroutineCmd, NULL, NULL, 0},
- {"default", InfoDefaultCmd, TclCompileBasic3ArgCmd, NULL, NULL, 0},
- {"errorstack", InfoErrorStackCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd, NULL, NULL, 0},
- {"frame", InfoFrameCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"functions", InfoFunctionsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"globals", TclInfoGlobalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"hostname", InfoHostnameCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
- {"level", InfoLevelCmd, TclCompileInfoLevelCmd, NULL, NULL, 0},
- {"library", InfoLibraryCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
- {"loaded", InfoLoadedCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"locals", TclInfoLocalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"nameofexecutable", InfoNameOfExecutableCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
- {"patchlevel", InfoPatchLevelCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
- {"procs", InfoProcsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"script", InfoScriptCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {"sharedlibextension", InfoSharedlibCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
- {"tclversion", InfoTclVersionCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
- {"vars", TclInfoVarsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
- {NULL, NULL, NULL, NULL, NULL, 0}
+ {"args", InfoArgsCmd, NULL},
+ {"body", InfoBodyCmd, NULL},
+ {"cmdcount", InfoCmdCountCmd, NULL},
+ {"commands", InfoCommandsCmd, NULL},
+ {"complete", InfoCompleteCmd, NULL},
+ {"default", InfoDefaultCmd, NULL},
+ {"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd},
+ {"frame", InfoFrameCmd, NULL},
+ {"functions", InfoFunctionsCmd, NULL},
+ {"globals", TclInfoGlobalsCmd, NULL},
+ {"hostname", InfoHostnameCmd, NULL},
+ {"level", InfoLevelCmd, NULL},
+ {"library", InfoLibraryCmd, NULL},
+ {"loaded", InfoLoadedCmd, NULL},
+ {"locals", TclInfoLocalsCmd, NULL},
+ {"nameofexecutable", InfoNameOfExecutableCmd, NULL},
+ {"patchlevel", InfoPatchLevelCmd, NULL},
+ {"procs", InfoProcsCmd, NULL},
+ {"script", InfoScriptCmd, NULL},
+ {"sharedlibextension", InfoSharedlibCmd, NULL},
+ {"tclversion", InfoTclVersionCmd, NULL},
+ {"vars", TclInfoVarsCmd, NULL},
+ {NULL, NULL, NULL}
};
/*
@@ -216,66 +206,40 @@ Tcl_IfObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- return Tcl_NRCallObjProc(interp, TclNRIfObjCmd, dummy, objc, objv);
-}
-
-int
-TclNRIfObjCmd(
- ClientData dummy, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int objc, /* Number of arguments. */
- Tcl_Obj *const objv[]) /* Argument objects. */
-{
- Tcl_Obj *boolObj;
-
- if (objc <= 1) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "wrong # args: no expression after \"%s\" argument",
- TclGetString(objv[0])));
- Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
- return TCL_ERROR;
- }
-
- /*
- * At this point, objv[1] refers to the main expression to test. The
- * arguments after the expression must be "then" (optional) and a script
- * to execute if the expression is true.
- */
-
- TclNewObj(boolObj);
- Tcl_NRAddCallback(interp, IfConditionCallback, INT2PTR(objc),
- (ClientData) objv, INT2PTR(1), boolObj);
- return Tcl_NRExprObj(interp, objv[1], boolObj);
-}
-
-static int
-IfConditionCallback(
- ClientData data[],
- Tcl_Interp *interp,
- int result)
-{
+ int thenScriptIndex = 0; /* "then" script to be evaled after syntax
+ * check. */
Interp *iPtr = (Interp *) interp;
- int objc = PTR2INT(data[0]);
- Tcl_Obj *const *objv = data[1];
- int i = PTR2INT(data[2]);
- Tcl_Obj *boolObj = data[3];
- int value, thenScriptIndex = 0;
- const char *clause;
-
- if (result != TCL_OK) {
- TclDecrRefCount(boolObj);
- return result;
- }
- if (Tcl_GetBooleanFromObj(interp, boolObj, &value) != TCL_OK) {
- TclDecrRefCount(boolObj);
- return TCL_ERROR;
- }
- TclDecrRefCount(boolObj);
+ int i, result, value;
+ char *clause;
+ i = 1;
while (1) {
+ /*
+ * At this point in the loop, objv and objc refer to an expression to
+ * test, either for the main expression or an expression following an
+ * "elseif". The arguments after the expression must be "then"
+ * (optional) and a script to execute if the expression is true.
+ */
+
+ if (i >= objc) {
+ clause = TclGetString(objv[i-1]);
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "no expression after \"", clause, "\" argument", NULL);
+ return TCL_ERROR;
+ }
+ if (!thenScriptIndex) {
+ result = Tcl_ExprBooleanObj(interp, objv[i], &value);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
i++;
if (i >= objc) {
- goto missingScript;
+ missingScript:
+ clause = TclGetString(objv[i-1]);
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "no script following \"", clause, "\" argument", NULL);
+ return TCL_ERROR;
}
clause = TclGetString(objv[i]);
if ((i < objc) && (strcmp(clause, "then") == 0)) {
@@ -301,37 +265,17 @@ IfConditionCallback(
* TIP #280. Make invoking context available to branch.
*/
- return TclNREvalObjEx(interp, objv[thenScriptIndex], 0,
+ return TclEvalObjEx(interp, objv[thenScriptIndex], 0,
iPtr->cmdFramePtr, thenScriptIndex);
}
return TCL_OK;
}
clause = TclGetString(objv[i]);
- if ((clause[0] != 'e') || (strcmp(clause, "elseif") != 0)) {
- break;
- }
- i++;
-
- /*
- * At this point in the loop, objv and objc refer to an expression to
- * test, either for the main expression or an expression following an
- * "elseif". The arguments after the expression must be "then"
- * (optional) and a script to execute if the expression is true.
- */
-
- if (i >= objc) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "wrong # args: no expression after \"%s\" argument",
- clause));
- Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
- return TCL_ERROR;
- }
- if (!thenScriptIndex) {
- TclNewObj(boolObj);
- Tcl_NRAddCallback(interp, IfConditionCallback, data[0], data[1],
- INT2PTR(i), boolObj);
- return Tcl_NRExprObj(interp, objv[i], boolObj);
+ if ((clause[0] == 'e') && (strcmp(clause, "elseif") == 0)) {
+ i++;
+ continue;
}
+ break;
}
/*
@@ -343,14 +287,14 @@ IfConditionCallback(
if (strcmp(clause, "else") == 0) {
i++;
if (i >= objc) {
- goto missingScript;
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "no script following \"else\" argument", NULL);
+ return TCL_ERROR;
}
}
if (i < objc - 1) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "wrong # args: extra words after \"else\" clause in \"if\" command",
- -1));
- Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "extra words after \"else\" clause in \"if\" command", NULL);
return TCL_ERROR;
}
if (thenScriptIndex) {
@@ -358,17 +302,10 @@ IfConditionCallback(
* TIP #280. Make invoking context available to branch/else.
*/
- return TclNREvalObjEx(interp, objv[thenScriptIndex], 0,
+ return TclEvalObjEx(interp, objv[thenScriptIndex], 0,
iPtr->cmdFramePtr, thenScriptIndex);
}
- return TclNREvalObjEx(interp, objv[i], 0, iPtr->cmdFramePtr, i);
-
- missingScript:
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "wrong # args: no script following \"%s\" argument",
- TclGetString(objv[i-1])));
- Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
- return TCL_ERROR;
+ return TclEvalObjEx(interp, objv[i], 0, iPtr->cmdFramePtr, i);
}
/*
@@ -438,7 +375,7 @@ Tcl_IncrObjCmd(
* documentation for details on what it does.
*
* Results:
- * Handle for the info command, or NULL on failure.
+ * FIXME
*
* Side effects:
* none
@@ -481,7 +418,7 @@ InfoArgsCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
- const char *name;
+ char *name;
Proc *procPtr;
CompiledLocal *localPtr;
Tcl_Obj *listObjPtr;
@@ -494,9 +431,7 @@ InfoArgsCmd(
name = TclGetString(objv[1]);
procPtr = TclFindProc(iPtr, name);
if (procPtr == NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "\"%s\" isn't a procedure", name));
- Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL);
+ Tcl_AppendResult(interp, "\"", name, "\" isn't a procedure", NULL);
return TCL_ERROR;
}
@@ -544,7 +479,7 @@ InfoBodyCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
- const char *name;
+ char *name;
Proc *procPtr;
Tcl_Obj *bodyPtr, *resultPtr;
@@ -556,9 +491,7 @@ InfoBodyCmd(
name = TclGetString(objv[1]);
procPtr = TclFindProc(iPtr, name);
if (procPtr == NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "\"%s\" isn't a procedure", name));
- Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL);
+ Tcl_AppendResult(interp, "\"", name, "\" isn't a procedure", NULL);
return TCL_ERROR;
}
@@ -578,7 +511,7 @@ InfoBodyCmd(
* run before. [Bug #545644]
*/
- TclGetString(bodyPtr);
+ (void) TclGetString(bodyPtr);
}
resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length);
@@ -656,7 +589,7 @@ InfoCommandsCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- const char *cmdName, *pattern;
+ char *cmdName, *pattern;
const char *simplePattern;
register Tcl_HashEntry *entryPtr;
Tcl_HashSearch search;
@@ -689,8 +622,8 @@ InfoCommandsCmd(
Namespace *dummy1NsPtr, *dummy2NsPtr;
pattern = TclGetString(objv[1]);
- TclGetNamespaceForQualName(interp, pattern, NULL, 0, &nsPtr,
- &dummy1NsPtr, &dummy2NsPtr, &simplePattern);
+ TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL, 0,
+ &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern);
if (nsPtr != NULL) { /* We successfully found the pattern's ns. */
specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
@@ -726,7 +659,7 @@ InfoCommandsCmd(
entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
if (entryPtr != NULL) {
if (specificNsInPattern) {
- cmd = Tcl_GetHashValue(entryPtr);
+ cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
elemObjPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
} else {
@@ -777,7 +710,7 @@ InfoCommandsCmd(
if ((simplePattern == NULL)
|| Tcl_StringMatch(cmdName, simplePattern)) {
if (specificNsInPattern) {
- cmd = Tcl_GetHashValue(entryPtr);
+ cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
elemObjPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
} else {
@@ -836,7 +769,7 @@ InfoCommandsCmd(
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
(void) Tcl_CreateHashEntry(&addedCommandsTable,
- elemObjPtr, &isNew);
+ (char *)elemObjPtr, &isNew);
}
entryPtr = Tcl_NextHashEntry(&search);
}
@@ -861,7 +794,7 @@ InfoCommandsCmd(
|| Tcl_StringMatch(cmdName, simplePattern)) {
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
(void) Tcl_CreateHashEntry(&addedCommandsTable,
- elemObjPtr, &isNew);
+ (char *) elemObjPtr, &isNew);
if (isNew) {
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
} else {
@@ -971,7 +904,7 @@ InfoDefaultCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
- const char *procName, *argName;
+ char *procName, *argName, *varName;
Proc *procPtr;
CompiledLocal *localPtr;
Tcl_Obj *valueObjPtr;
@@ -986,10 +919,7 @@ InfoDefaultCmd(
procPtr = TclFindProc(iPtr, procName);
if (procPtr == NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "\"%s\" isn't a procedure", procName));
- Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", procName,
- NULL);
+ Tcl_AppendResult(interp, "\"", procName, "\" isn't a procedure",NULL);
return TCL_ERROR;
}
@@ -999,18 +929,17 @@ InfoDefaultCmd(
&& (strcmp(argName, localPtr->name) == 0)) {
if (localPtr->defValuePtr != NULL) {
valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
- localPtr->defValuePtr, TCL_LEAVE_ERR_MSG);
+ localPtr->defValuePtr, 0);
if (valueObjPtr == NULL) {
- return TCL_ERROR;
+ goto defStoreError;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
} else {
Tcl_Obj *nullObjPtr = Tcl_NewObj();
-
valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
- nullObjPtr, TCL_LEAVE_ERR_MSG);
+ nullObjPtr, 0);
if (valueObjPtr == NULL) {
- return TCL_ERROR;
+ goto defStoreError;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
}
@@ -1018,60 +947,15 @@ InfoDefaultCmd(
}
}
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "procedure \"%s\" doesn't have an argument \"%s\"",
- procName, argName));
- Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARGUMENT", argName, NULL);
+ Tcl_AppendResult(interp, "procedure \"", procName,
+ "\" doesn't have an argument \"", argName, "\"", NULL);
return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * InfoErrorStackCmd --
- *
- * Called to implement the "info errorstack" command that returns information
- * about the last error's call stack. Handles the following syntax:
- *
- * info errorstack ?interp?
- *
- * Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
- *
- * Side effects:
- * Returns a result in the interpreter's result object. If there is an
- * error, the result is an error message.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-InfoErrorStackCmd(
- ClientData dummy, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int objc, /* Number of arguments. */
- Tcl_Obj *const objv[]) /* Argument objects. */
-{
- Tcl_Interp *target;
- Interp *iPtr;
- if ((objc != 1) && (objc != 2)) {
- Tcl_WrongNumArgs(interp, 1, objv, "?interp?");
- return TCL_ERROR;
- }
-
- target = interp;
- if (objc == 2) {
- target = Tcl_GetSlave(interp, Tcl_GetString(objv[1]));
- if (target == NULL) {
- return TCL_ERROR;
- }
- }
-
- iPtr = (Interp *) target;
- Tcl_SetObjResult(interp, iPtr->errorStack);
-
- return TCL_OK;
+ defStoreError:
+ varName = TclGetString(objv[3]);
+ Tcl_AppendResult(interp, "couldn't store default value in variable \"",
+ varName, "\"", NULL);
+ return TCL_ERROR;
}
/*
@@ -1101,7 +985,7 @@ TclInfoExistsCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- const char *varName;
+ char *varName;
Var *varPtr;
if (objc != 2) {
@@ -1147,47 +1031,22 @@ InfoFrameCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
- int level, code = TCL_OK;
- CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr;
- CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
- int topLevel = 0;
-
- if (objc > 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "?number?");
- return TCL_ERROR;
- }
-
- while (corPtr) {
- while (*cmdFramePtrPtr) {
- topLevel++;
- cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr);
- }
- if (corPtr->caller.cmdFramePtr) {
- *cmdFramePtrPtr = corPtr->caller.cmdFramePtr;
- }
- corPtr = corPtr->callerEEPtr->corPtr;
- }
- topLevel += (*cmdFramePtrPtr)->level;
-
- if (topLevel != iPtr->cmdFramePtr->level) {
- framePtr = iPtr->cmdFramePtr;
- while (framePtr) {
- framePtr->level = topLevel--;
- framePtr = framePtr->nextPtr;
- }
- if (topLevel) {
- Tcl_Panic("Broken frame level calculation");
- }
- topLevel = iPtr->cmdFramePtr->level;
- }
+ int level;
+ CmdFrame *framePtr;
if (objc == 1) {
/*
* Just "info frame".
*/
- Tcl_SetObjResult(interp, Tcl_NewIntObj(topLevel));
- goto done;
+ int levels =
+ (iPtr->cmdFramePtr == NULL ? 0 : iPtr->cmdFramePtr->level);
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj (levels));
+ return TCL_OK;
+ } else if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?number?");
+ return TCL_ERROR;
}
/*
@@ -1195,62 +1054,40 @@ InfoFrameCmd(
*/
if (TclGetIntFromObj(interp, objv[1], &level) != TCL_OK) {
- code = TCL_ERROR;
- goto done;
+ return TCL_ERROR;
}
+ if (level <= 0) {
+ /*
+ * Negative levels are adressing relative to the current frame's
+ * depth.
+ */
- if ((level > topLevel) || (level <= - topLevel)) {
- levelError:
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "bad level \"%s\"", TclGetString(objv[1])));
- Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_FRAME",
- TclGetString(objv[1]), NULL);
- code = TCL_ERROR;
- goto done;
- }
+ if (iPtr->cmdFramePtr == NULL) {
+ levelError:
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad level \"",
+ TclGetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
- /*
- * Let us convert to relative so that we know how many levels to go back
- */
+ /*
+ * Convert to absolute.
+ */
- if (level > 0) {
- level -= topLevel;
+ level += iPtr->cmdFramePtr->level;
}
- framePtr = iPtr->cmdFramePtr;
- while (++level <= 0) {
- framePtr = framePtr->nextPtr;
- if (!framePtr) {
- goto levelError;
+ for (framePtr = iPtr->cmdFramePtr; framePtr != NULL;
+ framePtr = framePtr->nextPtr) {
+ if (framePtr->level == level) {
+ break;
}
}
+ if (framePtr == NULL) {
+ goto levelError;
+ }
Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr));
-
- done:
- cmdFramePtrPtr = &iPtr->cmdFramePtr;
- corPtr = iPtr->execEnvPtr->corPtr;
- while (corPtr) {
- CmdFrame *endPtr = corPtr->caller.cmdFramePtr;
-
- if (endPtr) {
- if (*cmdFramePtrPtr == endPtr) {
- *cmdFramePtrPtr = NULL;
- } else {
- CmdFrame *runPtr = *cmdFramePtrPtr;
-
- while (runPtr->nextPtr != endPtr) {
- runPtr->level -= endPtr->level;
- runPtr = runPtr->nextPtr;
- }
- runPtr->level = 1;
- runPtr->nextPtr = NULL;
- }
- cmdFramePtrPtr = &corPtr->caller.cmdFramePtr;
- }
- corPtr = corPtr->callerEEPtr->corPtr;
- }
- return code;
+ return TCL_OK;
}
/*
@@ -1275,7 +1112,6 @@ TclInfoFrame(
CmdFrame *framePtr) /* Frame to get info for. */
{
Interp *iPtr = (Interp *) interp;
- Tcl_Obj *tmpObj;
Tcl_Obj *lv[20]; /* Keep uptodate when more keys are added to
* the dict. */
int lc = 0;
@@ -1283,12 +1119,14 @@ TclInfoFrame(
* This array is indexed by the TCL_LOCATION_... values, except
* for _LAST.
*/
- static const char *const typeString[TCL_LOCATION_LAST] = {
+ static const char *typeString[TCL_LOCATION_LAST] = {
"eval", "eval", "eval", "precompiled", "source", "proc"
};
- Proc *procPtr = framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;
+ Tcl_Obj *tmpObj;
+ Proc *procPtr =
+ framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;
- /*
+ /*
* Pull the information and construct the dictionary to return, as list.
* Regarding use of the CmdFrame fields see tclInt.h, and its definition.
*/
@@ -1306,12 +1144,28 @@ TclInfoFrame(
*/
ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1));
- if (framePtr->line) {
- ADD_PAIR("line", Tcl_NewIntObj(framePtr->line[0]));
- } else {
- ADD_PAIR("line", Tcl_NewIntObj(1));
- }
- ADD_PAIR("cmd", TclGetSourceFromFrame(framePtr, 0, NULL));
+ ADD_PAIR("line", Tcl_NewIntObj(framePtr->line[0]));
+ ADD_PAIR("cmd", Tcl_NewStringObj(framePtr->cmd.str.cmd,
+ framePtr->cmd.str.len));
+ break;
+
+ case TCL_LOCATION_EVAL_LIST:
+ /*
+ * List optimized evaluation. Type, line, cmd, the latter through
+ * listPtr, possibly a frame.
+ */
+
+ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1));
+ ADD_PAIR("line", Tcl_NewIntObj(1));
+
+ /*
+ * We put a duplicate of the command list obj into the result to
+ * ensure that the 'pure List'-property of the command itself is not
+ * destroyed. Otherwise the query here would disable the list
+ * optimization path in Tcl_EvalObjEx.
+ */
+
+ ADD_PAIR("cmd", Tcl_DuplicateObj(framePtr->cmd.listPtr));
break;
case TCL_LOCATION_PREBC:
@@ -1327,8 +1181,9 @@ TclInfoFrame(
* Execution of bytecode. Talk to the BC engine to fill out the frame.
*/
- CmdFrame *fPtr = TclStackAlloc(interp, sizeof(CmdFrame));
+ CmdFrame *fPtr;
+ fPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame));
*fPtr = *framePtr;
/*
@@ -1359,7 +1214,8 @@ TclInfoFrame(
Tcl_DecrRefCount(fPtr->data.eval.path);
}
- ADD_PAIR("cmd", TclGetSourceFromFrame(fPtr, 0, NULL));
+ ADD_PAIR("cmd",
+ Tcl_NewStringObj(fPtr->cmd.str.cmd, fPtr->cmd.str.len));
TclStackFree(interp, fPtr);
break;
}
@@ -1378,7 +1234,8 @@ TclInfoFrame(
* the result list object.
*/
- ADD_PAIR("cmd", TclGetSourceFromFrame(framePtr, 0, NULL));
+ ADD_PAIR("cmd", Tcl_NewStringObj(framePtr->cmd.str.cmd,
+ framePtr->cmd.str.len));
break;
case TCL_LOCATION_PROC:
@@ -1395,16 +1252,19 @@ TclInfoFrame(
Tcl_HashEntry *namePtr = procPtr->cmdPtr->hPtr;
if (namePtr) {
- Tcl_Obj *procNameObj;
-
/*
* This is a regular command.
*/
- TclNewObj(procNameObj);
- Tcl_GetCommandFullName(interp, (Tcl_Command) procPtr->cmdPtr,
- procNameObj);
- ADD_PAIR("proc", procNameObj);
+ char *procName = Tcl_GetHashKey(namePtr->tablePtr, namePtr);
+ char *nsName = procPtr->cmdPtr->nsPtr->fullName;
+
+ ADD_PAIR("proc", Tcl_NewStringObj(nsName, -1));
+
+ if (strcmp(nsName, "::") != 0) {
+ Tcl_AppendToObj(lv[lc-1], "::", -1);
+ }
+ Tcl_AppendToObj(lv[lc-1], procName, -1);
} else if (procPtr->cmdPtr->clientData) {
ExtraFrameInfo *efiPtr = procPtr->cmdPtr->clientData;
int i;
@@ -1555,10 +1415,7 @@ InfoHostnameCmd(
Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
return TCL_OK;
}
-
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "unable to determine name of host", -1));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "HOSTNAME", "UNKNOWN", NULL);
+ Tcl_SetResult(interp, "unable to determine name of host", TCL_STATIC);
return TCL_ERROR;
}
@@ -1628,10 +1485,8 @@ InfoLevelCmd(
return TCL_ERROR;
levelError:
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "bad level \"%s\"", TclGetString(objv[1])));
- Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_LEVEL",
- TclGetString(objv[1]), NULL);
+ Tcl_AppendResult(interp, "bad level \"", TclGetString(objv[1]), "\"",
+ NULL);
return TCL_ERROR;
}
@@ -1675,10 +1530,7 @@ InfoLibraryCmd(
Tcl_SetObjResult(interp, Tcl_NewStringObj(libDirName, -1));
return TCL_OK;
}
-
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "no library has been specified for Tcl", -1));
- Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", "tcl_library",NULL);
+ Tcl_SetResult(interp, "no library has been specified for Tcl",TCL_STATIC);
return TCL_ERROR;
}
@@ -1710,7 +1562,7 @@ InfoLoadedCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- const char *interpName;
+ char *interpName;
if ((objc != 1) && (objc != 2)) {
Tcl_WrongNumArgs(interp, 1, objv, "?interp?");
@@ -1836,7 +1688,7 @@ InfoProcsCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- const char *cmdName, *pattern;
+ char *cmdName, *pattern;
const char *simplePattern;
Namespace *nsPtr;
#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
@@ -1870,8 +1722,9 @@ InfoProcsCmd(
Namespace *dummy1NsPtr, *dummy2NsPtr;
pattern = TclGetString(objv[1]);
- TclGetNamespaceForQualName(interp, pattern, NULL, /*flags*/ 0, &nsPtr,
- &dummy1NsPtr, &dummy2NsPtr, &simplePattern);
+ TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
+ /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr,
+ &simplePattern);
if (nsPtr != NULL) { /* We successfully found the pattern's ns. */
specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
@@ -1897,7 +1750,7 @@ InfoProcsCmd(
if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) {
entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
if (entryPtr != NULL) {
- cmdPtr = Tcl_GetHashValue(entryPtr);
+ cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
if (!TclIsProc(cmdPtr)) {
realCmdPtr = (Command *)
@@ -1925,7 +1778,7 @@ InfoProcsCmd(
cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
if ((simplePattern == NULL)
|| Tcl_StringMatch(cmdName, simplePattern)) {
- cmdPtr = Tcl_GetHashValue(entryPtr);
+ cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
if (!TclIsProc(cmdPtr)) {
realCmdPtr = (Command *)
@@ -1972,7 +1825,7 @@ InfoProcsCmd(
if ((simplePattern == NULL)
|| Tcl_StringMatch(cmdName, simplePattern)) {
if (Tcl_FindHashEntry(&nsPtr->cmdTable,cmdName) == NULL) {
- cmdPtr = Tcl_GetHashValue(entryPtr);
+ cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
realCmdPtr = (Command *) TclGetOriginalCommand(
(Tcl_Command) cmdPtr);
@@ -2210,8 +2063,8 @@ Tcl_LassignObjCmd(
int listObjc; /* The length of the list. */
int code = TCL_OK;
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "list ?varName ...?");
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "list varName ?varName ...?");
return TCL_ERROR;
}
@@ -2225,22 +2078,20 @@ Tcl_LassignObjCmd(
objc -= 2;
objv += 2;
while (code == TCL_OK && objc > 0 && listObjc > 0) {
- if (Tcl_ObjSetVar2(interp, *objv++, NULL, *listObjv++,
- TCL_LEAVE_ERR_MSG) == NULL) {
+ if (NULL == Tcl_ObjSetVar2(interp, *objv++, NULL,
+ *listObjv++, TCL_LEAVE_ERR_MSG)) {
code = TCL_ERROR;
}
- objc--;
- listObjc--;
+ objc--; listObjc--;
}
if (code == TCL_OK && objc > 0) {
Tcl_Obj *emptyObj;
-
TclNewObj(emptyObj);
Tcl_IncrRefCount(emptyObj);
while (code == TCL_OK && objc-- > 0) {
- if (Tcl_ObjSetVar2(interp, *objv++, NULL, emptyObj,
- TCL_LEAVE_ERR_MSG) == NULL) {
+ if (NULL == Tcl_ObjSetVar2(interp, *objv++, NULL,
+ emptyObj, TCL_LEAVE_ERR_MSG)) {
code = TCL_ERROR;
}
}
@@ -2283,7 +2134,7 @@ Tcl_LindexObjCmd(
Tcl_Obj *elemPtr; /* Pointer to the element being extracted. */
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "list ?index ...?");
+ Tcl_WrongNumArgs(interp, 1, objv, "list ?index...?");
return TCL_ERROR;
}
@@ -2306,11 +2157,11 @@ Tcl_LindexObjCmd(
if (elemPtr == NULL) {
return TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, elemPtr);
+ Tcl_DecrRefCount(elemPtr);
+ return TCL_OK;
}
-
- Tcl_SetObjResult(interp, elemPtr);
- Tcl_DecrRefCount(elemPtr);
- return TCL_OK;
}
/*
@@ -2341,8 +2192,8 @@ Tcl_LinsertObjCmd(
Tcl_Obj *listPtr;
int index, len, result;
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?");
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "list index element ?element ...?");
return TCL_ERROR;
}
@@ -2424,7 +2275,7 @@ Tcl_ListObjCmd(
*/
if (objc > 1) {
- Tcl_SetObjResult(interp, Tcl_NewListObj(objc-1, &objv[1]));
+ Tcl_SetObjResult(interp, Tcl_NewListObj((objc-1), &(objv[1])));
}
return TCL_OK;
}
@@ -2500,74 +2351,52 @@ Tcl_LrangeObjCmd(
register Tcl_Obj *const objv[])
/* Argument objects. */
{
- Tcl_Obj **elemPtrs;
- int listLen, first, last, result;
+ Tcl_Obj *listPtr, **elemPtrs;
+ int listLen, first, result;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "list first last");
return TCL_ERROR;
}
- result = TclListObjLength(interp, objv[1], &listLen);
- if (result != TCL_OK) {
- return result;
+ /*
+ * Make sure the list argument is a list object and get its length and a
+ * pointer to its array of element pointers.
+ */
+
+ listPtr = TclListObjCopy(interp, objv[1]);
+ if (listPtr == NULL) {
+ return TCL_ERROR;
}
+ TclListObjGetElements(NULL, listPtr, &listLen, &elemPtrs);
result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ listLen - 1,
&first);
- if (result != TCL_OK) {
- return result;
- }
- if (first < 0) {
- first = 0;
- }
+ if (result == TCL_OK) {
+ int last;
- result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
- &last);
- if (result != TCL_OK) {
- return result;
- }
- if (last >= listLen) {
- last = listLen - 1;
- }
-
- if (first > last) {
- /*
- * Returning an empty list is easy.
- */
-
- return TCL_OK;
- }
+ if (first < 0) {
+ first = 0;
+ }
- result = TclListObjGetElements(interp, objv[1], &listLen, &elemPtrs);
- if (result != TCL_OK) {
- return result;
- }
+ result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
+ &last);
+ if (result == TCL_OK) {
+ if (last >= listLen) {
+ last = (listLen - 1);
+ }
- if (Tcl_IsShared(objv[1]) ||
- ((ListRepPtr(objv[1])->refCount > 1))) {
- Tcl_SetObjResult(interp, Tcl_NewListObj(last - first + 1,
- &elemPtrs[first]));
- } else {
- /*
- * In-place is possible.
- */
+ if (first <= last) {
+ int numElems = (last - first + 1);
- if (last < (listLen - 1)) {
- Tcl_ListObjReplace(interp, objv[1], last + 1, listLen - 1 - last,
- 0, NULL);
+ Tcl_SetObjResult(interp,
+ Tcl_NewListObj(numElems, &(elemPtrs[first])));
+ }
}
-
- /*
- * This one is not conditioned on (first > 0) in order to preserve the
- * string-canonizing effect of [lrange 0 end].
- */
-
- Tcl_ListObjReplace(interp, objv[1], 0, first, 0, NULL);
- Tcl_SetObjResult(interp, objv[1]);
}
- return TCL_OK;
+ Tcl_DecrRefCount(listPtr);
+ return result;
}
/*
@@ -2596,25 +2425,23 @@ Tcl_LrepeatObjCmd(
/* The argument objects. */
{
int elementCount, i, totalElems;
- Tcl_Obj *listPtr, **dataArray = NULL;
+ Tcl_Obj *listPtr, **dataArray;
+ List *listRepPtr;
/*
* Check arguments for legality:
- * lrepeat count ?value ...?
+ * lrepeat posInt value ?value ...?
*/
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "count ?value ...?");
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "positiveCount value ?value ...?");
return TCL_ERROR;
}
- if (TCL_OK != TclGetIntFromObj(interp, objv[1], &elementCount)) {
+ if (TCL_ERROR == TclGetIntFromObj(interp, objv[1], &elementCount)) {
return TCL_ERROR;
}
- if (elementCount < 0) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "bad count \"%d\": must be integer >= 0", elementCount));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG",
- NULL);
+ if (elementCount < 1) {
+ Tcl_AppendResult(interp, "must have a count of at least 1", NULL);
return TCL_ERROR;
}
@@ -2627,10 +2454,9 @@ Tcl_LrepeatObjCmd(
/* Final sanity check. Do not exceed limits on max list length. */
- if (elementCount && objc > LIST_MAX/elementCount) {
+ if (objc > LIST_MAX/elementCount) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"max length of a Tcl list (%d elements) exceeded", LIST_MAX));
- Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
return TCL_ERROR;
}
totalElems = objc * elementCount;
@@ -2641,12 +2467,9 @@ Tcl_LrepeatObjCmd(
*/
listPtr = Tcl_NewListObj(totalElems, NULL);
- if (totalElems) {
- List *listRepPtr = ListRepPtr(listPtr);
-
- listRepPtr->elemCount = elementCount*objc;
- dataArray = &listRepPtr->elements;
- }
+ listRepPtr = ListRepPtr(listPtr);
+ listRepPtr->elemCount = elementCount*objc;
+ dataArray = &listRepPtr->elements;
/*
* Set the elements. Note that we handle the common degenerate case of a
@@ -2655,7 +2478,6 @@ Tcl_LrepeatObjCmd(
* number of times.
*/
- CLANG_ASSERT(dataArray);
if (objc == 1) {
register Tcl_Obj *tmpPtr = objv[0];
@@ -2708,7 +2530,7 @@ Tcl_LreplaceObjCmd(
if (objc < 4) {
Tcl_WrongNumArgs(interp, 1, objv,
- "list first last ?element ...?");
+ "list first last ?element element ...?");
return TCL_ERROR;
}
@@ -2734,7 +2556,7 @@ Tcl_LreplaceObjCmd(
}
if (first < 0) {
- first = 0;
+ first = 0;
}
/*
@@ -2745,17 +2567,15 @@ Tcl_LreplaceObjCmd(
*/
if ((first >= listLen) && (listLen > 0)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "list doesn't contain element %s", TclGetString(objv[2])));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPLACE", "BADIDX",
- NULL);
+ Tcl_AppendResult(interp, "list doesn't contain element ",
+ TclGetString(objv[2]), NULL);
return TCL_ERROR;
}
if (last >= listLen) {
- last = listLen - 1;
+ last = (listLen - 1);
}
if (first <= last) {
- numToDelete = last - first + 1;
+ numToDelete = (last - first + 1);
} else {
numToDelete = 0;
}
@@ -2778,7 +2598,7 @@ Tcl_LreplaceObjCmd(
* optimize this case away.
*/
- Tcl_ListObjReplace(NULL, listPtr, first, numToDelete, objc-4, objv+4);
+ Tcl_ListObjReplace(NULL, listPtr, first, numToDelete, objc-4, &(objv[4]));
/*
* Set the interpreter's object result.
@@ -2824,7 +2644,7 @@ Tcl_LreverseObjCmd(
}
/*
- * If the list is empty, just return it. [Bug 1876793]
+ * If the list is empty, just return it [Bug 1876793]
*/
if (!elemc) {
@@ -2891,29 +2711,28 @@ Tcl_LsearchObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument values. */
{
- const char *bytes, *patternBytes;
- int i, match, index, result, listc, length, elemLen, bisect;
- int dataType, isIncreasing, lower, upper, offset;
- Tcl_WideInt patWide, objWide;
+ char *bytes, *patternBytes;
+ int i, match, mode, index, result, listc, length, elemLen;
+ int dataType, isIncreasing, lower, upper, patInt, objInt, offset;
int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
double patDouble, objDouble;
SortInfo sortInfo;
Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr;
SortStrCmpFn_t strCmpFn = strcmp;
Tcl_RegExp regexp = NULL;
- static const char *const options[] = {
- "-all", "-ascii", "-bisect", "-decreasing", "-dictionary",
+ static const char *options[] = {
+ "-all", "-ascii", "-decreasing", "-dictionary",
"-exact", "-glob", "-increasing", "-index",
"-inline", "-integer", "-nocase", "-not",
"-real", "-regexp", "-sorted", "-start",
"-subindices", NULL
};
enum options {
- LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_BISECT, LSEARCH_DECREASING,
- LSEARCH_DICTIONARY, LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING,
- LSEARCH_INDEX, LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOCASE,
- LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED,
- LSEARCH_START, LSEARCH_SUBINDICES
+ LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY,
+ LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING, LSEARCH_INDEX,
+ LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOCASE, LSEARCH_NOT,
+ LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED, LSEARCH_START,
+ LSEARCH_SUBINDICES
};
enum datatypes {
ASCII, DICTIONARY, INTEGER, REAL
@@ -2921,7 +2740,6 @@ Tcl_LsearchObjCmd(
enum modes {
EXACT, GLOB, REGEXP, SORTED
};
- enum modes mode;
mode = GLOB;
dataType = ASCII;
@@ -2930,7 +2748,6 @@ Tcl_LsearchObjCmd(
inlineReturn = 0;
returnSubindices = 0;
negatedMatch = 0;
- bisect = 0;
listPtr = NULL;
startPtr = NULL;
offset = 0;
@@ -2944,7 +2761,7 @@ Tcl_LsearchObjCmd(
sortInfo.indexc = 0;
if (objc < 3) {
- Tcl_WrongNumArgs(interp, 1, objv, "?-option value ...? list pattern");
+ Tcl_WrongNumArgs(interp, 1, objv, "?options? list pattern");
return TCL_ERROR;
}
@@ -2954,8 +2771,10 @@ Tcl_LsearchObjCmd(
if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
- result = TCL_ERROR;
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return TCL_ERROR;
}
switch ((enum options) index) {
case LSEARCH_ALL: /* -all */
@@ -2964,10 +2783,6 @@ Tcl_LsearchObjCmd(
case LSEARCH_ASCII: /* -ascii */
dataType = ASCII;
break;
- case LSEARCH_BISECT: /* -bisect */
- mode = SORTED;
- bisect = 1;
- break;
case LSEARCH_DECREASING: /* -decreasing */
isIncreasing = 0;
sortInfo.isIncreasing = 0;
@@ -3020,11 +2835,11 @@ Tcl_LsearchObjCmd(
Tcl_DecrRefCount(startPtr);
}
if (i > objc-4) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "missing starting index", -1));
- Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
- result = TCL_ERROR;
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ Tcl_AppendResult(interp, "missing starting index", NULL);
+ return TCL_ERROR;
}
i++;
if (objv[i] == objv[objc - 2]) {
@@ -3046,16 +2861,15 @@ Tcl_LsearchObjCmd(
int j;
if (sortInfo.indexc > 1) {
- TclStackFree(interp, sortInfo.indexv);
+ ckfree((char *) sortInfo.indexv);
}
if (i > objc-4) {
if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ Tcl_AppendResult(interp,
"\"-index\" option must be followed by list index",
- -1));
- Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
+ NULL);
return TCL_ERROR;
}
@@ -3081,8 +2895,8 @@ Tcl_LsearchObjCmd(
sortInfo.indexv = &sortInfo.singleIndex;
break;
default:
- sortInfo.indexv =
- TclStackAlloc(interp, sizeof(int) * sortInfo.indexc);
+ sortInfo.indexv = (int *)
+ ckalloc(sizeof(int) * sortInfo.indexc);
}
/*
@@ -3094,10 +2908,12 @@ Tcl_LsearchObjCmd(
for (j=0 ; j<sortInfo.indexc ; j++) {
if (TclGetIntForIndexM(interp, indices[j], SORTIDX_END,
&sortInfo.indexv[j]) != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (-index option item number %d)", j));
- result = TCL_ERROR;
- goto done;
+ return TCL_ERROR;
}
}
break;
@@ -3113,22 +2929,12 @@ Tcl_LsearchObjCmd(
if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "-subindices cannot be used without -index option", -1));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
- "BAD_OPTION_MIX", NULL);
- return TCL_ERROR;
- }
-
- if (bisect && (allMatches || negatedMatch)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "-bisect is not compatible with -all or -not", -1));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
- "BAD_OPTION_MIX", NULL);
+ Tcl_AppendResult(interp,
+ "-subindices cannot be used without -index option", NULL);
return TCL_ERROR;
}
- if (mode == REGEXP) {
+ if ((enum modes) mode == REGEXP) {
/*
* We can shimmer regexp/list if listv[i] == pattern, so get the
* regexp rep before the list rep. First time round, omit the interp
@@ -3154,8 +2960,10 @@ Tcl_LsearchObjCmd(
if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
- result = TCL_ERROR;
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return TCL_ERROR;
}
}
@@ -3169,7 +2977,10 @@ Tcl_LsearchObjCmd(
if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
/*
@@ -3180,7 +2991,10 @@ Tcl_LsearchObjCmd(
result = TclGetIntForIndexM(interp, startPtr, listc-1, &offset);
Tcl_DecrRefCount(startPtr);
if (result != TCL_OK) {
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
if (offset < 0) {
offset = 0;
@@ -3193,7 +3007,7 @@ Tcl_LsearchObjCmd(
if (offset > listc-1) {
if (sortInfo.indexc > 1) {
- TclStackFree(interp, sortInfo.indexv);
+ ckfree((char *) sortInfo.indexv);
}
if (allMatches || inlineReturn) {
Tcl_ResetResult(interp);
@@ -3206,16 +3020,19 @@ Tcl_LsearchObjCmd(
patObj = objv[objc - 1];
patternBytes = NULL;
- if (mode == EXACT || mode == SORTED) {
+ if ((enum modes) mode == EXACT || (enum modes) mode == SORTED) {
switch ((enum datatypes) dataType) {
case ASCII:
case DICTIONARY:
patternBytes = TclGetStringFromObj(patObj, &length);
break;
case INTEGER:
- result = TclGetWideIntFromObj(interp, patObj, &patWide);
+ result = TclGetIntFromObj(interp, patObj, &patInt);
if (result != TCL_OK) {
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
/*
@@ -3228,7 +3045,10 @@ Tcl_LsearchObjCmd(
case REAL:
result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble);
if (result != TCL_OK) {
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
/*
@@ -3251,7 +3071,7 @@ Tcl_LsearchObjCmd(
index = -1;
match = 0;
- if (mode == SORTED && !allMatches && !negatedMatch) {
+ if ((enum modes) mode == SORTED && !allMatches && !negatedMatch) {
/*
* 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
@@ -3266,8 +3086,10 @@ Tcl_LsearchObjCmd(
if (sortInfo.indexc != 0) {
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
if (sortInfo.resultCode != TCL_OK) {
- result = sortInfo.resultCode;
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return sortInfo.resultCode;
}
} else {
itemPtr = listv[i];
@@ -3282,13 +3104,16 @@ Tcl_LsearchObjCmd(
match = DictionaryCompare(patternBytes, bytes);
break;
case INTEGER:
- result = TclGetWideIntFromObj(interp, itemPtr, &objWide);
+ result = TclGetIntFromObj(interp, itemPtr, &objInt);
if (result != TCL_OK) {
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
- if (patWide == objWide) {
+ if (patInt == objInt) {
match = 0;
- } else if (patWide < objWide) {
+ } else if (patInt < objInt) {
match = -1;
} else {
match = 1;
@@ -3297,7 +3122,10 @@ Tcl_LsearchObjCmd(
case REAL:
result = Tcl_GetDoubleFromObj(interp, itemPtr, &objDouble);
if (result != TCL_OK) {
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
if (patDouble == objDouble) {
match = 0;
@@ -3321,16 +3149,10 @@ Tcl_LsearchObjCmd(
* variation means that a search always makes log n
* comparisons (normal binary search might "get lucky" with an
* early comparison).
- *
- * In bisect mode though, we want the last of equals.
*/
index = i;
- if (bisect) {
- lower = i;
- } else {
- upper = i;
- }
+ upper = i;
} else if (match > 0) {
if (isIncreasing) {
lower = i;
@@ -3345,9 +3167,7 @@ Tcl_LsearchObjCmd(
}
}
}
- if (bisect && index < 0) {
- index = lower;
- }
+
} else {
/*
* We need to do a linear search, because (at least one) of:
@@ -3361,20 +3181,22 @@ Tcl_LsearchObjCmd(
}
for (i = offset; i < listc; i++) {
match = 0;
- if (sortInfo.indexc != 0) {
+ if (sortInfo.indexc != 0) {
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
if (sortInfo.resultCode != TCL_OK) {
if (listPtr != NULL) {
Tcl_DecrRefCount(listPtr);
}
- result = sortInfo.resultCode;
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return sortInfo.resultCode;
}
} else {
itemPtr = listv[i];
}
-
- switch (mode) {
+
+ switch ((enum modes) mode) {
case SORTED:
case EXACT:
switch ((enum datatypes) dataType) {
@@ -3401,14 +3223,17 @@ Tcl_LsearchObjCmd(
break;
case INTEGER:
- result = TclGetWideIntFromObj(interp, itemPtr, &objWide);
+ result = TclGetIntFromObj(interp, itemPtr, &objInt);
if (result != TCL_OK) {
if (listPtr != NULL) {
Tcl_DecrRefCount(listPtr);
}
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
- match = (objWide == patWide);
+ match = (objInt == patInt);
break;
case REAL:
@@ -3417,7 +3242,10 @@ Tcl_LsearchObjCmd(
if (listPtr) {
Tcl_DecrRefCount(listPtr);
}
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return result;
}
match = (objDouble == patDouble);
break;
@@ -3436,8 +3264,10 @@ Tcl_LsearchObjCmd(
if (listPtr != NULL) {
Tcl_DecrRefCount(listPtr);
}
- result = TCL_ERROR;
- goto done;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return TCL_ERROR;
}
break;
}
@@ -3510,17 +3340,15 @@ Tcl_LsearchObjCmd(
} else {
Tcl_SetObjResult(interp, listv[index]);
}
- result = TCL_OK;
/*
* Cleanup the index list array.
*/
- done:
if (sortInfo.indexc > 1) {
- TclStackFree(interp, sortInfo.indexv);
+ ckfree((char *) sortInfo.indexv);
}
- return result;
+ return TCL_OK;
}
/*
@@ -3555,8 +3383,7 @@ Tcl_LsetObjCmd(
*/
if (objc < 3) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "listVar ?index? ?index ...? value");
+ Tcl_WrongNumArgs(interp, 1, objv, "listVar ?index? ?index...? value");
return TCL_ERROR;
}
@@ -3564,7 +3391,8 @@ Tcl_LsetObjCmd(
* Look up the list variable's value.
*/
- listPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
+ listPtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
+ TCL_LEAVE_ERR_MSG);
if (listPtr == NULL) {
return TCL_ERROR;
}
@@ -3634,30 +3462,29 @@ Tcl_LsortObjCmd(
{
int i, j, index, indices, length, nocase = 0, indexc;
int sortMode = SORTMODE_ASCII;
- int group, groupSize, groupOffset, idx, allocatedIndexVector = 0;
Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
SortElement *elementArray, *elementPtr;
SortInfo sortInfo; /* Information about this sort that needs to
* be passed to the comparison function. */
-# define NUM_LISTS 30
- SortElement *subList[NUM_LISTS+1];
- /* This array holds pointers to temporary
- * lists built during the merge sort. Element
- * i of the array holds a list of length
- * 2**i. */
- static const char *const switches[] = {
+ static const char *switches[] = {
"-ascii", "-command", "-decreasing", "-dictionary", "-increasing",
- "-index", "-indices", "-integer", "-nocase", "-real", "-stride",
- "-unique", NULL
+ "-index", "-indices", "-integer", "-nocase", "-real", "-unique", NULL
};
enum Lsort_Switches {
LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER,
- LSORT_NOCASE, LSORT_REAL, LSORT_STRIDE, LSORT_UNIQUE
+ LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
};
+ /*
+ * The subList array below holds pointers to temporary lists built during
+ * the merge sort. Element i of the array holds a list of length 2**i.
+ */
+# define NUM_LISTS 30
+ SortElement *subList[NUM_LISTS+1];
+
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "?-option value ...? list");
+ Tcl_WrongNumArgs(interp, 1, objv, "?options? list");
return TCL_ERROR;
}
@@ -3671,31 +3498,30 @@ Tcl_LsortObjCmd(
sortInfo.indexc = 0;
sortInfo.unique = 0;
sortInfo.interp = interp;
- sortInfo.resultCode = TCL_OK;
+ sortInfo.resultCode = TCL_OK;
cmdPtr = NULL;
indices = 0;
- group = 0;
- groupSize = 1;
- groupOffset = 0;
- indexPtr = NULL;
for (i = 1; i < objc-1; i++) {
if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0,
&index) != TCL_OK) {
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return TCL_ERROR;
}
switch ((enum Lsort_Switches) index) {
case LSORT_ASCII:
sortInfo.sortMode = SORTMODE_ASCII;
break;
case LSORT_COMMAND:
- if (i == objc-2) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ if (i == (objc-2)) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ Tcl_AppendResult(interp,
"\"-command\" option must be followed "
- "by comparison command", -1));
- Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
+ "by comparison command", NULL);
+ return TCL_ERROR;
}
sortInfo.sortMode = SORTMODE_COMMAND;
cmdPtr = objv[i+1];
@@ -3711,41 +3537,54 @@ Tcl_LsortObjCmd(
sortInfo.isIncreasing = 1;
break;
case LSORT_INDEX: {
- int indexc, dummy;
- Tcl_Obj **indexv;
+ Tcl_Obj **indices;
- if (i == objc-2) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "\"-index\" option must be followed by list index",
- -1));
- Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
}
- if (TclListObjGetElements(interp, objv[i+1], &indexc,
- &indexv) != TCL_OK) {
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
+ if (i == (objc-2)) {
+ Tcl_AppendResult(interp, "\"-index\" option must be "
+ "followed by list index", NULL);
+ return TCL_ERROR;
}
/*
- * Check each of the indices for syntactic correctness. Note that
- * we do not store the converted values here because we do not
- * know if this is the only -index option yet and so we can't
- * allocate any space; that happens after the scan through all the
- * options is done.
+ * Take copy to prevent shimmering problems.
*/
- for (j=0 ; j<indexc ; j++) {
- if (TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
- &dummy) != TCL_OK) {
+ if (TclListObjGetElements(interp, objv[i+1], &sortInfo.indexc,
+ &indices) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (sortInfo.indexc) {
+ case 0:
+ sortInfo.indexv = NULL;
+ break;
+ case 1:
+ sortInfo.indexv = &sortInfo.singleIndex;
+ break;
+ default:
+ sortInfo.indexv = (int *)
+ ckalloc(sizeof(int) * sortInfo.indexc);
+ }
+
+ /*
+ * Fill the array by parsing each index. We don't know whether
+ * their scale is sensible yet, but we at least perform the
+ * syntactic check here.
+ */
+
+ for (j=0 ; j<sortInfo.indexc ; j++) {
+ if (TclGetIntForIndexM(interp, indices[j], SORTIDX_END,
+ &sortInfo.indexv[j]) != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (-index option item number %d)", j));
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
+ return TCL_ERROR;
}
}
- indexPtr = objv[i+1];
i++;
break;
}
@@ -3764,65 +3603,12 @@ Tcl_LsortObjCmd(
case LSORT_INDICES:
indices = 1;
break;
- case LSORT_STRIDE:
- if (i == objc-2) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "\"-stride\" option must be "
- "followed by stride length", -1));
- Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
- }
- if (Tcl_GetIntFromObj(interp, objv[i+1], &groupSize) != TCL_OK) {
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
- }
- if (groupSize < 2) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "stride length must be at least 2", -1));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT",
- "BADSTRIDE", NULL);
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
- }
- group = 1;
- i++;
- break;
}
}
if (nocase && (sortInfo.sortMode == SORTMODE_ASCII)) {
sortInfo.sortMode = SORTMODE_ASCII_NC;
}
- /*
- * Now extract the -index list for real, if present. No failures are
- * expected here; the values are all of the right type or convertible to
- * it.
- */
-
- if (indexPtr) {
- Tcl_Obj **indexv;
-
- TclListObjGetElements(interp, indexPtr, &sortInfo.indexc, &indexv);
- switch (sortInfo.indexc) {
- case 0:
- sortInfo.indexv = NULL;
- break;
- case 1:
- sortInfo.indexv = &sortInfo.singleIndex;
- break;
- default:
- sortInfo.indexv =
- TclStackAlloc(interp, sizeof(int) * sortInfo.indexc);
- allocatedIndexVector = 1; /* Cannot use indexc field, as it
- * might be decreased by 1 later. */
- }
- for (j=0 ; j<sortInfo.indexc ; j++) {
- TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
- &sortInfo.indexv[j]);
- }
- }
-
listObj = objv[objc-1];
if (sortInfo.sortMode == SORTMODE_COMMAND) {
@@ -3837,8 +3623,10 @@ Tcl_LsortObjCmd(
listObj = TclListObjCopy(interp, listObj);
if (listObj == NULL) {
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return TCL_ERROR;
}
/*
@@ -3855,8 +3643,10 @@ Tcl_LsortObjCmd(
TclDecrRefCount(listObj);
Tcl_IncrRefCount(newObjPtr);
TclDecrRefCount(newObjPtr);
- sortInfo.resultCode = TCL_ERROR;
- goto done2;
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return TCL_ERROR;
}
Tcl_ListObjAppendElement(interp, newCommandPtr, Tcl_NewObj());
sortInfo.compareCmdPtr = newCommandPtr;
@@ -3867,62 +3657,8 @@ Tcl_LsortObjCmd(
if (sortInfo.resultCode != TCL_OK || length <= 0) {
goto done;
}
-
- /*
- * Check for sanity when grouping elements of the overall list together
- * because of the -stride option. [TIP #326]
- */
-
- if (group) {
- if (length % groupSize) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "list size must be a multiple of the stride length",
- -1));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT", "BADSTRIDE",
- NULL);
- sortInfo.resultCode = TCL_ERROR;
- goto done;
- }
- length = length / groupSize;
- if (sortInfo.indexc > 0) {
- /*
- * Use the first value in the list supplied to -index as the
- * offset of the element within each group by which to sort.
- */
-
- groupOffset = sortInfo.indexv[0];
- if (groupOffset <= SORTIDX_END) {
- groupOffset = (groupOffset - SORTIDX_END) + groupSize - 1;
- }
- if (groupOffset < 0 || groupOffset >= groupSize) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "when used with \"-stride\", the leading \"-index\""
- " value must be within the group", -1));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT",
- "BADINDEX", NULL);
- sortInfo.resultCode = TCL_ERROR;
- goto done;
- }
- if (sortInfo.indexc == 1) {
- sortInfo.indexc = 0;
- sortInfo.indexv = NULL;
- } else {
- sortInfo.indexc--;
-
- /*
- * Do not shrink the actual memory block used; that doesn't
- * work with TclStackAlloc-allocated memory. [Bug 2918962]
- */
-
- for (i = 0; i < sortInfo.indexc; i++) {
- sortInfo.indexv[i] = sortInfo.indexv[i+1];
- }
- }
- }
- }
-
sortInfo.numElements = length;
-
+
indexc = sortInfo.indexc;
sortMode = sortInfo.sortMode;
if ((sortMode == SORTMODE_ASCII_NC)
@@ -3930,7 +3666,7 @@ Tcl_LsortObjCmd(
/*
* For this function's purpose all string-based modes are equivalent
*/
-
+
sortMode = SORTMODE_ASCII;
}
@@ -3939,7 +3675,7 @@ Tcl_LsortObjCmd(
* contain a sorted sublist of length 2**i. Use one extra subList at the
* end, always at NULL, to indicate the end of the lists.
*/
-
+
for (j=0 ; j<=NUM_LISTS ; j++) {
subList[j] = NULL;
}
@@ -3949,65 +3685,57 @@ Tcl_LsortObjCmd(
* begins sorting it into the sublists as it appears.
*/
- elementArray = TclStackAlloc(interp, length * sizeof(SortElement));
+ elementArray = (SortElement *) ckalloc( length * sizeof(SortElement));
for (i=0; i < length; i++){
- idx = groupSize * i + groupOffset;
if (indexc) {
/*
* If this is an indexed sort, retrieve the corresponding element
*/
- indexPtr = SelectObjFromSublist(listObjPtrs[idx], &sortInfo);
+ indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
if (sortInfo.resultCode != TCL_OK) {
goto done1;
}
} else {
- indexPtr = listObjPtrs[idx];
+ indexPtr = listObjPtrs[i];
}
/*
* Determine the "value" of this object for sorting purposes
*/
-
+
if (sortMode == SORTMODE_ASCII) {
- elementArray[i].collationKey.strValuePtr = TclGetString(indexPtr);
+ elementArray[i].index.strValuePtr = TclGetString(indexPtr);
} else if (sortMode == SORTMODE_INTEGER) {
- Tcl_WideInt a;
-
- if (TclGetWideIntFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
+ long a;
+ if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
sortInfo.resultCode = TCL_ERROR;
goto done1;
}
- elementArray[i].collationKey.wideValue = a;
+ elementArray[i].index.intValue = a;
} else if (sortMode == SORTMODE_REAL) {
double a;
-
- if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr,
- &a) != TCL_OK) {
+ if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
sortInfo.resultCode = TCL_ERROR;
goto done1;
}
- elementArray[i].collationKey.doubleValue = a;
+ elementArray[i].index.doubleValue = a;
} else {
- elementArray[i].collationKey.objValuePtr = indexPtr;
+ elementArray[i].index.objValuePtr = indexPtr;
}
/*
* Determine the representation of this element in the result: either
* the objPtr itself, or its index in the original list.
*/
-
- if (indices || group) {
- elementArray[i].payload.index = idx;
- } else {
- elementArray[i].payload.objPtr = listObjPtrs[idx];
- }
+
+ elementArray[i].objPtr = (indices ? INT2PTR(i) : listObjPtrs[i]);
/*
* Merge this element in the pre-existing sublists (and merge together
* sublists when we have two of the same size).
*/
-
+
elementArray[i].nextPtr = NULL;
elementPtr = &elementArray[i];
for (j=0 ; subList[j] ; j++) {
@@ -4023,47 +3751,34 @@ Tcl_LsortObjCmd(
/*
* Merge all sublists
*/
-
+
elementPtr = subList[0];
for (j=1 ; j<NUM_LISTS ; j++) {
elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
}
+
/*
* Now store the sorted elements in the result list.
*/
-
+
if (sortInfo.resultCode == TCL_OK) {
List *listRepPtr;
Tcl_Obj **newArray, *objPtr;
-
- resultPtr = Tcl_NewListObj(sortInfo.numElements * groupSize, NULL);
+ int i;
+
+ resultPtr = Tcl_NewListObj(sortInfo.numElements, NULL);
listRepPtr = ListRepPtr(resultPtr);
newArray = &listRepPtr->elements;
- if (group) {
- for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) {
- idx = elementPtr->payload.index;
- for (j = 0; j < groupSize; j++) {
- if (indices) {
- objPtr = Tcl_NewIntObj(idx + j - groupOffset);
- newArray[i++] = objPtr;
- Tcl_IncrRefCount(objPtr);
- } else {
- objPtr = listObjPtrs[idx + j - groupOffset];
- newArray[i++] = objPtr;
- Tcl_IncrRefCount(objPtr);
- }
- }
- }
- } else if (indices) {
- for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
- objPtr = Tcl_NewIntObj(elementPtr->payload.index);
+ if (indices) {
+ for (i = 0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr){
+ objPtr = Tcl_NewIntObj(PTR2INT(elementPtr->objPtr));
newArray[i++] = objPtr;
Tcl_IncrRefCount(objPtr);
}
} else {
- for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
- objPtr = elementPtr->payload.objPtr;
+ for (i = 0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr){
+ objPtr = elementPtr->objPtr;
newArray[i++] = objPtr;
Tcl_IncrRefCount(objPtr);
}
@@ -4073,7 +3788,7 @@ Tcl_LsortObjCmd(
}
done1:
- TclStackFree(interp, elementArray);
+ ckfree((char *)elementArray);
done:
if (sortMode == SORTMODE_COMMAND) {
@@ -4081,9 +3796,8 @@ Tcl_LsortObjCmd(
TclDecrRefCount(listObj);
sortInfo.compareCmdPtr = NULL;
}
- done2:
- if (allocatedIndexVector) {
- TclStackFree(interp, sortInfo.indexv);
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
}
return sortInfo.resultCode;
}
@@ -4100,23 +3814,21 @@ Tcl_LsortObjCmd(
* The unified list of SortElement structures.
*
* Side effects:
- * If infoPtr->unique is set then infoPtr->numElements may be updated.
+ * If infoPtr->unique is set then infoPtr->numElements may be updated.
* Possibly others, if a user-defined comparison command does something
- * weird.
+ * weird.
*
* Note:
- * If infoPtr->unique is set, the merge assumes that there are no
+ * If infoPtr->unique is set, the merge assumes that there are no
* "repeated" elements in each of the left and right lists. In that case,
* if any element of the left list is equivalent to one in the right list
* it is omitted from the merged list.
- *
- * This simplified mechanism works because of the special way our
- * MergeSort creates the sublists to be merged and will fail to eliminate
- * all repeats in the general case where they are already present in
- * either the left or right list. A general code would need to skip
- * adjacent initial repeats in the left and right lists before comparing
- * their initial elements, at each step.
- *
+ * This simplified mechanism works because of the special way
+ * our MergeSort creates the sublists to be merged and will fail to
+ * eliminate all repeats in the general case where they are already
+ * present in either the left or right list. A general code would need to
+ * skip adjacent initial repeats in the left and right lists before
+ * comparing their initial elements, at each step.
*----------------------------------------------------------------------
*/
@@ -4218,25 +3930,25 @@ SortCompare(
int order = 0;
if (infoPtr->sortMode == SORTMODE_ASCII) {
- order = strcmp(elemPtr1->collationKey.strValuePtr,
- elemPtr2->collationKey.strValuePtr);
+ order = strcmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
- order = TclUtfCasecmp(elemPtr1->collationKey.strValuePtr,
- elemPtr2->collationKey.strValuePtr);
+ order = TclUtfCasecmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
- order = DictionaryCompare(elemPtr1->collationKey.strValuePtr,
- elemPtr2->collationKey.strValuePtr);
+ order = DictionaryCompare(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_INTEGER) {
- Tcl_WideInt a, b;
+ long a, b;
- a = elemPtr1->collationKey.wideValue;
- b = elemPtr2->collationKey.wideValue;
+ a = elemPtr1->index.intValue;
+ b = elemPtr2->index.intValue;
order = ((a >= b) - (a <= b));
} else if (infoPtr->sortMode == SORTMODE_REAL) {
double a, b;
- a = elemPtr1->collationKey.doubleValue;
- b = elemPtr2->collationKey.doubleValue;
+ a = elemPtr1->index.doubleValue;
+ b = elemPtr2->index.doubleValue;
order = ((a >= b) - (a <= b));
} else {
Tcl_Obj **objv, *paramObjv[2];
@@ -4248,14 +3960,14 @@ SortCompare(
* Once an error has occurred, skip any future comparisons so as
* to preserve the error message in sortInterp->result.
*/
-
+
return 0;
}
- objPtr1 = elemPtr1->collationKey.objValuePtr;
- objPtr2 = elemPtr2->collationKey.objValuePtr;
-
+ objPtr1 = elemPtr1->index.objValuePtr;
+ objPtr2 = elemPtr2->index.objValuePtr;
+
paramObjv[0] = objPtr1;
paramObjv[1] = objPtr2;
@@ -4273,7 +3985,8 @@ SortCompare(
infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0);
if (infoPtr->resultCode != TCL_OK) {
- Tcl_AddErrorInfo(infoPtr->interp, "\n (-compare command)");
+ Tcl_AddErrorInfo(infoPtr->interp,
+ "\n (-compare command)");
return 0;
}
@@ -4283,10 +3996,9 @@ SortCompare(
if (TclGetIntFromObj(infoPtr->interp,
Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) {
- Tcl_SetObjResult(infoPtr->interp, Tcl_NewStringObj(
- "-compare command returned non-integer result", -1));
- Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT",
- "COMPARISONFAILED", NULL);
+ Tcl_ResetResult(infoPtr->interp);
+ Tcl_AppendResult(infoPtr->interp,
+ "-compare command returned non-integer result", NULL);
infoPtr->resultCode = TCL_ERROR;
return 0;
}
@@ -4323,7 +4035,7 @@ SortCompare(
static int
DictionaryCompare(
- const char *left, const char *right) /* The strings to compare. */
+ char *left, char *right) /* The strings to compare. */
{
Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
int diff, zeros;
@@ -4340,11 +4052,11 @@ DictionaryCompare(
*/
zeros = 0;
- while ((*right == '0') && isdigit(UCHAR(right[1]))) {
+ while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
right++;
zeros--;
}
- while ((*left == '0') && isdigit(UCHAR(left[1]))) {
+ while ((*left == '0') && (isdigit(UCHAR(left[1])))) {
left++;
zeros++;
}
@@ -4497,11 +4209,12 @@ SelectObjFromSublist(
return NULL;
}
if (currentObj == NULL) {
- Tcl_SetObjResult(infoPtr->interp, Tcl_ObjPrintf(
- "element %d missing from sublist \"%s\"",
- index, TclGetString(objPtr)));
- Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT",
- "INDEXFAILED", NULL);
+ char buffer[TCL_INTEGER_SPACE];
+
+ TclFormatInt(buffer, index);
+ Tcl_AppendResult(infoPtr->interp, "element ", buffer,
+ " missing from sublist \"", TclGetString(objPtr), "\"",
+ NULL);
infoPtr->resultCode = TCL_ERROR;
return NULL;
}
@@ -4515,6 +4228,5 @@ SelectObjFromSublist(
* mode: c
* c-basic-offset: 4
* fill-column: 78
- * tab-width: 8
* End:
*/