diff options
Diffstat (limited to 'generic/tclCmdMZ.c')
-rw-r--r-- | generic/tclCmdMZ.c | 1422 |
1 files changed, 652 insertions, 770 deletions
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index d769da8..32ed560 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -6,11 +6,11 @@ * 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. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Scriptics Corporation. - * Copyright (c) 2002 ActiveState Corporation. - * Copyright (c) 2003-2009 Donal K. Fellows. + * Copyright © 1987-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Scriptics Corporation. + * Copyright © 2002 ActiveState Corporation. + * Copyright © 2003-2009 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -29,6 +29,9 @@ static Tcl_NRPostProc TryPostFinal; static Tcl_NRPostProc TryPostHandler; static int UniCharIsAscii(int character); static int UniCharIsHexDigit(int character); +static int StringCmpOpts(Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[], int *nocase, + Tcl_Size *reqlength); /* * Default set of characters to trim in [string trim] and friends. This is a @@ -82,7 +85,7 @@ const char tclDefaultTrimSet[] = int Tcl_PwdObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -122,13 +125,13 @@ Tcl_PwdObjCmd( int Tcl_RegexpObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int i, indices, match, about, offset, all, doinline, numMatchesSaved; - int cflags, eflags, stringLength, matchLength; + Tcl_Size offset, stringLength, matchLength, cflags, eflags; + int i, indices, match, about, all, doinline, numMatchesSaved; Tcl_RegExp regExpr; Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL; Tcl_RegExpInfo info; @@ -191,11 +194,11 @@ Tcl_RegexpObjCmd( cflags |= TCL_REG_NLANCH; break; case REGEXP_START: { - int temp; + Tcl_Size temp; if (++i >= objc) { goto endOfForLoop; } - if (TclGetIntForIndexM(interp, objv[i], 0, &temp) != TCL_OK) { + if (TclGetIntForIndexM(interp, objv[i], TCL_SIZE_MAX - 1, &temp) != TCL_OK) { goto optionError; } if (startIndex) { @@ -256,10 +259,10 @@ Tcl_RegexpObjCmd( */ objPtr = objv[1]; - stringLength = Tcl_GetCharLength(objPtr); + stringLength = TclGetCharLength(objPtr); if (startIndex) { - TclGetIntForIndexM(NULL, startIndex, stringLength, &offset); + TclGetIntForIndexM(interp, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); if (offset < 0) { offset = 0; @@ -310,7 +313,7 @@ Tcl_RegexpObjCmd( eflags = 0; } else if (offset > stringLength) { eflags = TCL_REG_NOTBOL; - } else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') { + } else if (TclGetUniChar(objPtr, offset-1) == '\n') { eflags = 0; } else { eflags = TCL_REG_NOTBOL; @@ -336,7 +339,7 @@ Tcl_RegexpObjCmd( */ if (!doinline) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); } return TCL_OK; } @@ -364,7 +367,7 @@ Tcl_RegexpObjCmd( Tcl_Obj *newPtr; if (indices) { - int start, end; + Tcl_Size start, end; Tcl_Obj *objs[2]; /* @@ -385,17 +388,17 @@ Tcl_RegexpObjCmd( end--; } } else { - start = -1; - end = -1; + start = TCL_INDEX_NONE; + end = TCL_INDEX_NONE; } - objs[0] = Tcl_NewLongObj(start); - objs[1] = Tcl_NewLongObj(end); + TclNewIndexObj(objs[0], start); + TclNewIndexObj(objs[1], end); newPtr = Tcl_NewListObj(2, objs); } else { if ((i <= info.nsubs) && (info.matches[i].end > 0)) { - newPtr = Tcl_GetRange(objPtr, + newPtr = TclGetRange(objPtr, offset + info.matches[i].start, offset + info.matches[i].end - 1); } else { @@ -458,7 +461,7 @@ Tcl_RegexpObjCmd( if (doinline) { Tcl_SetObjResult(interp, resultPtr); } else { - Tcl_SetObjResult(interp, Tcl_NewIntObj(all ? all-1 : 1)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(all ? all-1 : 1)); } return TCL_OK; } @@ -482,32 +485,34 @@ Tcl_RegexpObjCmd( int Tcl_RegsubObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int idx, result, cflags, all, wlen, wsublen, numMatches, offset; - int start, end, subStart, subEnd, match; + int result, cflags, all, match, command; + Tcl_Size idx, wlen, wsublen, offset, numMatches, numParts; + Tcl_Size start, end, subStart, subEnd; Tcl_RegExp regExpr; Tcl_RegExpInfo info; Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL; - Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend; + Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec = 0, *wend; static const char *const options[] = { - "-all", "-nocase", "-expanded", - "-line", "-linestop", "-lineanchor", "-start", + "-all", "-command", "-expanded", "-line", + "-linestop", "-lineanchor", "-nocase", "-start", "--", NULL }; - enum options { - REGSUB_ALL, REGSUB_NOCASE, REGSUB_EXPANDED, - REGSUB_LINE, REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_START, + enum regsubobjoptions { + REGSUB_ALL, REGSUB_COMMAND, REGSUB_EXPANDED, REGSUB_LINE, + REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_NOCASE, REGSUB_START, REGSUB_LAST }; cflags = TCL_REG_ADVANCED; all = 0; offset = 0; + command = 0; resultPtr = NULL; for (idx = 1; idx < objc; idx++) { @@ -522,13 +527,16 @@ Tcl_RegsubObjCmd( TCL_EXACT, &index) != TCL_OK) { goto optionError; } - switch ((enum options) index) { + switch ((enum regsubobjoptions) index) { case REGSUB_ALL: all = 1; break; case REGSUB_NOCASE: cflags |= TCL_REG_NOCASE; break; + case REGSUB_COMMAND: + command = 1; + break; case REGSUB_EXPANDED: cflags |= TCL_REG_EXPANDED; break; @@ -542,11 +550,11 @@ Tcl_RegsubObjCmd( cflags |= TCL_REG_NLANCH; break; case REGSUB_START: { - int temp; + Tcl_Size temp; if (++idx >= objc) { goto endOfForLoop; } - if (TclGetIntForIndexM(interp, objv[idx], 0, &temp) != TCL_OK) { + if (TclGetIntForIndexM(interp, objv[idx], TCL_SIZE_MAX - 1, &temp) != TCL_OK) { goto optionError; } if (startIndex) { @@ -563,7 +571,7 @@ Tcl_RegsubObjCmd( } endOfForLoop: - if (objc-idx < 3 || objc-idx > 4) { + if (objc < idx + 3 || objc > idx + 4) { Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? exp string subSpec ?varName?"); optionError: @@ -577,16 +585,16 @@ Tcl_RegsubObjCmd( objv += idx; if (startIndex) { - int stringLength = Tcl_GetCharLength(objv[1]); + Tcl_Size stringLength = TclGetCharLength(objv[1]); - TclGetIntForIndexM(NULL, startIndex, stringLength, &offset); + TclGetIntForIndexM(interp, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); if (offset < 0) { offset = 0; } } - if (all && (offset == 0) + if (all && (offset == 0) && (command == 0) && (strpbrk(TclGetString(objv[2]), "&\\") == NULL) && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) { /* @@ -594,17 +602,18 @@ Tcl_RegsubObjCmd( * slightly modified version of the one pair STR_MAP code. */ - int slen, nocase; + Tcl_Size slen; + int nocase, wsrclc; int (*strCmpFn)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned long); - Tcl_UniChar *p, wsrclc; + Tcl_UniChar *p; numMatches = 0; nocase = (cflags & TCL_REG_NOCASE); - strCmpFn = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp; + strCmpFn = nocase ? TclUniCharNcasecmp : TclUniCharNcmp; - wsrc = Tcl_GetUnicodeFromObj(objv[0], &slen); - wstring = Tcl_GetUnicodeFromObj(objv[1], &wlen); - wsubspec = Tcl_GetUnicodeFromObj(objv[2], &wsublen); + wsrc = TclGetUnicodeFromObj(objv[0], &slen); + wstring = TclGetUnicodeFromObj(objv[1], &wlen); + wsubspec = TclGetUnicodeFromObj(objv[2], &wsublen); wend = wstring + wlen - (slen ? slen - 1 : 0); result = TCL_OK; @@ -615,11 +624,11 @@ Tcl_RegsubObjCmd( */ if (wstring < wend) { - resultPtr = Tcl_NewUnicodeObj(wstring, 0); + resultPtr = TclNewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); for (; wstring < wend; wstring++) { - Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen); - Tcl_AppendUnicodeToObj(resultPtr, wstring, 1); + TclAppendUnicodeToObj(resultPtr, wsubspec, wsublen); + TclAppendUnicodeToObj(resultPtr, wstring, 1); numMatches++; } wlen = 0; @@ -632,18 +641,18 @@ Tcl_RegsubObjCmd( (slen==1 || (strCmpFn(wstring, wsrc, (unsigned long) slen) == 0))) { if (numMatches == 0) { - resultPtr = Tcl_NewUnicodeObj(wstring, 0); + resultPtr = TclNewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); } if (p != wstring) { - Tcl_AppendUnicodeToObj(resultPtr, p, wstring - p); + TclAppendUnicodeToObj(resultPtr, p, wstring - p); p = wstring + slen; } else { p += slen; } wstring = p - 1; - Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen); + TclAppendUnicodeToObj(resultPtr, wsubspec, wsublen); numMatches++; } } @@ -662,6 +671,28 @@ Tcl_RegsubObjCmd( return TCL_ERROR; } + if (command) { + /* + * In command-prefix mode, we require that the third non-option + * argument be a list, so we enforce that here. Afterwards, we fetch + * the RE compilation again in case objv[0] and objv[2] are the same + * object. (If they aren't, that's cheap to do.) + */ + + if (TclListObjLengthM(interp, objv[2], &numParts) != TCL_OK) { + return TCL_ERROR; + } + if (numParts < 1) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "command prefix must be a list of at least one element", + -1)); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGSUB", + "CMDEMPTY", NULL); + return TCL_ERROR; + } + regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); + } + /* * Make sure to avoid problems where the objects are shared. This can * cause RegExpObj <> UnicodeObj shimmering that causes data corruption. @@ -673,13 +704,15 @@ Tcl_RegsubObjCmd( } else { objPtr = objv[1]; } - wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen); + wstring = TclGetUnicodeFromObj(objPtr, &wlen); if (objv[2] == objv[0]) { subPtr = Tcl_DuplicateObj(objv[2]); } else { subPtr = objv[2]; } - wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen); + if (!command) { + wsubspec = TclGetUnicodeFromObj(subPtr, &wsublen); + } result = TCL_OK; @@ -714,7 +747,7 @@ Tcl_RegsubObjCmd( break; } if (numMatches == 0) { - resultPtr = Tcl_NewUnicodeObj(wstring, 0); + resultPtr = TclNewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); if (offset > 0) { /* @@ -722,7 +755,7 @@ Tcl_RegsubObjCmd( * specified. */ - Tcl_AppendUnicodeToObj(resultPtr, wstring, offset); + TclAppendUnicodeToObj(resultPtr, wstring, offset); } } numMatches++; @@ -735,7 +768,91 @@ Tcl_RegsubObjCmd( Tcl_RegExpGetInfo(regExpr, &info); start = info.matches[0].start; end = info.matches[0].end; - Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start); + TclAppendUnicodeToObj(resultPtr, wstring + offset, start); + + /* + * In command-prefix mode, the substitutions are added as quoted + * arguments to the subSpec to form a command, that is then executed + * and the result used as the string to substitute in. Actually, + * everything is passed through Tcl_EvalObjv, as that's much faster. + */ + + if (command) { + Tcl_Obj **args = NULL, **parts; + Tcl_Size numArgs; + + TclListObjGetElementsM(interp, subPtr, &numParts, &parts); + numArgs = numParts + info.nsubs + 1; + args = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*) * numArgs); + memcpy(args, parts, sizeof(Tcl_Obj*) * numParts); + + for (idx = 0 ; idx <= info.nsubs ; idx++) { + subStart = info.matches[idx].start; + subEnd = info.matches[idx].end; + if ((subStart >= 0) && (subEnd >= 0)) { + args[idx + numParts] = TclNewUnicodeObj( + wstring + offset + subStart, subEnd - subStart); + } else { + TclNewObj(args[idx + numParts]); + } + Tcl_IncrRefCount(args[idx + numParts]); + } + + /* + * At this point, we're locally holding the references to the + * argument words we added for this time round the loop, and the + * subPtr is holding the references to the words that the user + * supplied directly. None are zero-refcount, which is important + * because Tcl_EvalObjv is "hairy monster" in terms of refcount + * handling, being able to optionally add references to any of its + * argument words. We'll drop the local refs immediately + * afterwards; subPtr is handled in the main exit stanza. + */ + + result = Tcl_EvalObjv(interp, numArgs, args, 0); + for (idx = 0 ; idx <= info.nsubs ; idx++) { + TclDecrRefCount(args[idx + numParts]); + } + ckfree(args); + if (result != TCL_OK) { + if (result == TCL_ERROR) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (%s substitution computation script)", + options[REGSUB_COMMAND])); + } + goto done; + } + + Tcl_AppendObjToObj(resultPtr, Tcl_GetObjResult(interp)); + Tcl_ResetResult(interp); + + /* + * Refetch the unicode, in case the representation was smashed by + * the user code. + */ + + wstring = TclGetUnicodeFromObj(objPtr, &wlen); + + offset += end; + if (end == 0 || start == end) { + /* + * Always consume at least one character of the input string + * in order to prevent infinite loops, even when we + * technically matched the empty string; we must not match + * again at the same spot. + */ + + if (offset < wlen) { + TclAppendUnicodeToObj(resultPtr, wstring + offset, 1); + } + offset++; + } + if (all) { + continue; + } else { + break; + } + } /* * Append the subSpec argument to the variable, making appropriate @@ -755,7 +872,7 @@ Tcl_RegsubObjCmd( idx = ch - '0'; } else if ((ch == '\\') || (ch == '&')) { *wsrc = ch; - Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, + TclAppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar + 1); *wsrc = '\\'; wfirstChar = wsrc + 2; @@ -769,7 +886,7 @@ Tcl_RegsubObjCmd( } if (wfirstChar != wsrc) { - Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, + TclAppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); } @@ -777,7 +894,7 @@ Tcl_RegsubObjCmd( subStart = info.matches[idx].start; subEnd = info.matches[idx].end; if ((subStart >= 0) && (subEnd >= 0)) { - Tcl_AppendUnicodeToObj(resultPtr, + TclAppendUnicodeToObj(resultPtr, wstring + offset + subStart, subEnd - subStart); } } @@ -789,7 +906,7 @@ Tcl_RegsubObjCmd( } if (wfirstChar != wsrc) { - Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); + TclAppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); } if (end == 0) { @@ -799,7 +916,7 @@ Tcl_RegsubObjCmd( */ if (offset < wlen) { - Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1); + TclAppendUnicodeToObj(resultPtr, wstring + offset, 1); } offset++; } else { @@ -811,7 +928,7 @@ Tcl_RegsubObjCmd( */ if (offset < wlen) { - Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1); + TclAppendUnicodeToObj(resultPtr, wstring + offset, 1); } offset++; } @@ -836,7 +953,7 @@ Tcl_RegsubObjCmd( resultPtr = objv[1]; Tcl_IncrRefCount(resultPtr); } else if (offset < wlen) { - Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset); + TclAppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset); } if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, @@ -848,7 +965,7 @@ Tcl_RegsubObjCmd( * holding the number of matches. */ - Tcl_SetObjResult(interp, Tcl_NewIntObj(numMatches)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(numMatches)); } } else { /* @@ -890,7 +1007,7 @@ Tcl_RegsubObjCmd( int Tcl_RenameObjCmd( - ClientData dummy, /* Arbitrary value passed to the command. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -926,7 +1043,7 @@ Tcl_RenameObjCmd( int Tcl_ReturnObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -940,7 +1057,7 @@ Tcl_ReturnObjCmd( */ int explicitResult = (0 == (objc % 2)); - int numOptionWords = objc - 1 - explicitResult; + Tcl_Size numOptionWords = objc - 1 - explicitResult; if (TCL_ERROR == TclMergeReturnOptions(interp, numOptionWords, objv+1, &returnOpts, &code, &level)) { @@ -973,25 +1090,28 @@ Tcl_ReturnObjCmd( int Tcl_SourceObjCmd( - ClientData dummy, /* Not used. */ + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRSourceObjCmd, dummy, objc, objv); + return Tcl_NRCallObjProc(interp, TclNRSourceObjCmd, clientData, objc, objv); } int TclNRSourceObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *encodingName = NULL; Tcl_Obj *fileName; + int result; + void **pkgFiles = NULL; + void *names = NULL; - if (objc != 2 && objc !=4) { + if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "?-encoding name? fileName"); return TCL_ERROR; } @@ -1009,9 +1129,30 @@ TclNRSourceObjCmd( return TCL_ERROR; } encodingName = TclGetString(objv[2]); - } + } else if (objc == 3) { + /* Handle undocumented -nopkg option. This should only be + * used by the internal ::tcl::Pkg::source utility function. */ + static const char *const nopkgoptions[] = { + "-nopkg", NULL + }; + int index; - return TclNREvalFile(interp, fileName, encodingName); + if (TCL_ERROR == Tcl_GetIndexFromObj(interp, objv[1], nopkgoptions, + "option", TCL_EXACT, &index)) { + return TCL_ERROR; + } + pkgFiles = (void **)Tcl_GetAssocData(interp, "tclPkgFiles", NULL); + /* Make sure that during the following TclNREvalFile no filenames + * are recorded for inclusion in the "package files" command */ + names = *pkgFiles; + *pkgFiles = NULL; + } + result = TclNREvalFile(interp, fileName, encodingName); + if (pkgFiles) { + /* restore "tclPkgFiles" assocdata to how it was. */ + *pkgFiles = names; + } + return result; } /* @@ -1033,17 +1174,17 @@ TclNRSourceObjCmd( int Tcl_SplitObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar ch = 0; + int ch = 0; int len; const char *splitChars; const char *stringPtr; const char *end; - int splitCharLen, stringLen; + Tcl_Size splitCharLen, stringLen; Tcl_Obj *listPtr, *objPtr; if (objc == 2) { @@ -1081,10 +1222,8 @@ Tcl_SplitObjCmd( Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS); for ( ; stringPtr < end; stringPtr += len) { - int ucs4; - - len = TclUtfToUCS4(stringPtr, &ucs4); - hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(ucs4), &isNew); + len = Tcl_UtfToUniChar(stringPtr, &ch); + hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(ch), &isNew); if (isNew) { TclNewStringObj(objPtr, stringPtr, len); @@ -1109,7 +1248,7 @@ Tcl_SplitObjCmd( * byte in length. */ - while (*stringPtr && (p=strchr(stringPtr,(int)*splitChars)) != NULL) { + while (*stringPtr && (p=strchr(stringPtr,*splitChars)) != NULL) { objPtr = Tcl_NewStringObj(stringPtr, p - stringPtr); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); stringPtr = p + 1; @@ -1118,8 +1257,8 @@ Tcl_SplitObjCmd( Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } else { const char *element, *p, *splitEnd; - int splitLen; - Tcl_UniChar splitChar = 0; + Tcl_Size splitLen; + int splitChar; /* * Normal case: split on any of a given set of characters. Discard @@ -1129,9 +1268,9 @@ Tcl_SplitObjCmd( splitEnd = splitChars + splitCharLen; for (element = stringPtr; stringPtr < end; stringPtr += len) { - len = TclUtfToUniChar(stringPtr, &ch); + len = Tcl_UtfToUniChar(stringPtr, &ch); for (p = splitChars; p < splitEnd; p += splitLen) { - splitLen = TclUtfToUniChar(p, &splitChar); + splitLen = Tcl_UtfToUniChar(p, &splitChar); if (ch == splitChar) { TclNewStringObj(objPtr, element, stringPtr - element); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); @@ -1168,13 +1307,12 @@ Tcl_SplitObjCmd( static int StringFirstCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar *needleStr, *haystackStr; - int match, start, needleLen, haystackLen; + Tcl_Size start = 0; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, @@ -1182,82 +1320,14 @@ StringFirstCmd( return TCL_ERROR; } - /* - * We are searching haystackStr for the sequence needleStr. - */ - - match = -1; - start = 0; - haystackLen = -1; - - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); - if (objc == 4) { - /* - * If a startIndex is specified, we will need to fast forward to that - * point in the string before we think about a match. - */ + Tcl_Size end = TclGetCharLength(objv[2]) - 1; - if (TclGetIntForIndexM(interp, objv[3], haystackLen-1, - &start) != TCL_OK){ + if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &start)) { return TCL_ERROR; } - - /* - * Reread to prevent shimmering problems. - */ - - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); - - if (start >= haystackLen) { - goto str_first_done; - } else if (start > 0) { - haystackStr += start; - haystackLen -= start; - } else if (start < 0) { - /* - * Invalid start index mapped to string start; Bug #423581 - */ - - start = 0; - } - } - - /* - * If the length of the needle is more than the length of the haystack, it - * cannot be contained in there so we can avoid searching. [Bug 2960021] - */ - - if (needleLen > 0 && needleLen <= haystackLen) { - Tcl_UniChar *p, *end; - - end = haystackStr + haystackLen - needleLen + 1; - for (p = haystackStr; p < end; p++) { - /* - * Scan forward to find the first character. - */ - - if ((*p == *needleStr) && (TclUniCharNcmp(needleStr, p, - (unsigned long) needleLen) == 0)) { - match = p - haystackStr; - break; - } - } } - - /* - * Compute the character index of the matching string by counting the - * number of characters before the match. - */ - - if ((match != -1) && (objc == 4)) { - match += start; - } - - str_first_done: - Tcl_SetObjResult(interp, Tcl_NewIntObj(match)); + Tcl_SetObjResult(interp, TclStringFirst(objv[1], objv[2], start)); return TCL_OK; } @@ -1281,81 +1351,27 @@ StringFirstCmd( static int StringLastCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar *needleStr, *haystackStr, *p; - int match, start, needleLen, haystackLen; + Tcl_Size last = TCL_SIZE_MAX; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, - "needleString haystackString ?startIndex?"); + "needleString haystackString ?lastIndex?"); return TCL_ERROR; } - /* - * We are searching haystackString for the sequence needleString. - */ - - match = -1; - start = 0; - haystackLen = -1; - - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); - if (objc == 4) { - /* - * If a startIndex is specified, we will need to restrict the string - * range to that char index in the string - */ + Tcl_Size end = TclGetCharLength(objv[2]) - 1; - if (TclGetIntForIndexM(interp, objv[3], haystackLen-1, - &start) != TCL_OK){ + if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &last)) { return TCL_ERROR; } - - /* - * Reread to prevent shimmering problems. - */ - - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); - - if (start < 0) { - goto str_last_done; - } else if (start < haystackLen) { - p = haystackStr + start + 1 - needleLen; - } else { - p = haystackStr + haystackLen - needleLen; - } - } else { - p = haystackStr + haystackLen - needleLen; } - - /* - * If the length of the needle is more than the length of the haystack, it - * cannot be contained in there so we can avoid searching. [Bug 2960021] - */ - - if (needleLen > 0 && needleLen <= haystackLen) { - for (; p >= haystackStr; p--) { - /* - * Scan backwards to find the first character. - */ - - if ((*p == *needleStr) && !memcmp(needleStr, p, - sizeof(Tcl_UniChar) * (size_t)needleLen)) { - match = p - haystackStr; - break; - } - } - } - - str_last_done: - Tcl_SetObjResult(interp, Tcl_NewIntObj(match)); + Tcl_SetObjResult(interp, TclStringLast(objv[1], objv[2], last)); return TCL_OK; } @@ -1379,12 +1395,12 @@ StringLastCmd( static int StringIndexCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int length, index; + Tcl_Size index, end; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string charIndex"); @@ -1395,13 +1411,17 @@ StringIndexCmd( * Get the char length to calculate what 'end' means. */ - length = Tcl_GetCharLength(objv[1]); - if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) { + end = TclGetCharLength(objv[1]) - 1; + if (TclGetIntForIndexM(interp, objv[2], end, &index) != TCL_OK) { return TCL_ERROR; } - if ((index >= 0) && (index < length)) { - int ch = TclGetUCS4(objv[1], index); + if ((index >= 0) && (index <= end)) { + int ch = TclGetUniChar(objv[1], index); + + if (ch == -1) { + return TCL_OK; + } /* * If we have a ByteArray object, we're careful to generate a new @@ -1413,10 +1433,13 @@ StringIndexCmd( Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(&uch, 1)); } else { - char buf[8] = ""; + char buf[4] = ""; - length = TclUCS4ToUtf(ch, buf); - Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, length)); + end = Tcl_UniCharToUtf(ch, buf); + if ((ch >= 0xD800) && (end < 3)) { + end += Tcl_UniCharToUtf(-1, buf + end); + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, end)); } } return TCL_OK; @@ -1425,6 +1448,63 @@ StringIndexCmd( /* *---------------------------------------------------------------------- * + * StringInsertCmd -- + * + * This procedure is invoked to process the "string insert" Tcl command. + * See the user documentation for details on what it does. Note that this + * command only functions correctly on properly formed Tcl UTF strings. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +StringInsertCmd( + TCL_UNUSED(void *), + Tcl_Interp *interp, /* Current interpreter */ + int objc, /* Number of arguments */ + Tcl_Obj *const objv[]) /* Argument objects */ +{ + Tcl_Size length; /* String length */ + Tcl_Size index; /* Insert index */ + Tcl_Obj *outObj; /* Output object */ + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "string index insertString"); + return TCL_ERROR; + } + + length = TclGetCharLength(objv[1]); + if (TclGetIntForIndexM(interp, objv[2], length, &index) != TCL_OK) { + return TCL_ERROR; + } + + if (index < 0) { + index = 0; + } + if (index > length) { + index = length; + } + + outObj = TclStringReplace(interp, objv[1], index, 0, objv[3], + TCL_STRING_IN_PLACE); + + if (outObj != NULL) { + Tcl_SetObjResult(interp, outObj); + return TCL_OK; + } + + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * * StringIsCmd -- * * This procedure is invoked to process the "string is" Tcl command. See @@ -1442,7 +1522,7 @@ StringIndexCmd( static int StringIsCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -1455,24 +1535,24 @@ StringIsCmd( static const char *const isClasses[] = { "alnum", "alpha", "ascii", "control", - "boolean", "digit", "double", "entier", - "false", "graph", "integer", "list", - "lower", "print", "punct", "space", - "true", "upper", "wideinteger", "wordchar", - "xdigit", NULL + "boolean", "dict", "digit", "double", + "entier", "false", "graph", "integer", + "list", "lower", "print", "punct", + "space", "true", "upper", "unicode", + "wideinteger", "wordchar", "xdigit", NULL }; - enum isClasses { + enum isClassesEnum { STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL, - STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER, - STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST, - STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE, - STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD, - STR_IS_XDIGIT + STR_IS_BOOL, STR_IS_DICT, STR_IS_DIGIT, STR_IS_DOUBLE, + STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, + STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, + STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_UNICODE, + STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT }; static const char *const isOptions[] = { "-strict", "-failindex", NULL }; - enum isOptions { + enum isOptionsEnum { OPT_STRICT, OPT_FAILIDX }; @@ -1494,7 +1574,7 @@ StringIsCmd( &idx2) != TCL_OK) { return TCL_ERROR; } - switch ((enum isOptions) idx2) { + switch ((enum isOptionsEnum) idx2) { case OPT_STRICT: strict = 1; break; @@ -1523,7 +1603,7 @@ StringIsCmd( * When entering here, result == 1 and failat == 0. */ - switch ((enum isClasses) index) { + switch ((enum isClassesEnum) index) { case STR_IS_ALNUM: chcomp = Tcl_UniCharIsAlnum; break; @@ -1536,7 +1616,7 @@ StringIsCmd( case STR_IS_BOOL: case STR_IS_TRUE: case STR_IS_FALSE: - if ((objPtr->typePtr != &tclBooleanType) + if (!TclHasInternalRep(objPtr, &tclBooleanType) && (TCL_OK != TclSetBooleanFromAny(NULL, objPtr))) { if (strict) { result = 0; @@ -1544,26 +1624,72 @@ StringIsCmd( string1 = TclGetStringFromObj(objPtr, &length1); result = length1 == 0; } - } else if (((index == STR_IS_TRUE) && - objPtr->internalRep.longValue == 0) - || ((index == STR_IS_FALSE) && - objPtr->internalRep.longValue != 0)) { - result = 0; + } else if (index != STR_IS_BOOL) { + TclGetBooleanFromObj(NULL, objPtr, &i); + if ((index == STR_IS_TRUE) ^ i) { + result = 0; + } } break; case STR_IS_CONTROL: chcomp = Tcl_UniCharIsControl; break; + case STR_IS_DICT: { + int dresult; + Tcl_Size dsize; + + dresult = Tcl_DictObjSize(interp, objPtr, &dsize); + Tcl_ResetResult(interp); + result = (dresult == TCL_OK) ? 1 : 0; + if (dresult != TCL_OK && failVarObj != NULL) { + /* + * Need to figure out where the list parsing failed, which is + * fairly expensive. This is adapted from the core of + * SetDictFromAny(). + */ + + const char *elemStart, *nextElem; + Tcl_Size lenRemain, elemSize; + const char *p; + + string1 = TclGetStringFromObj(objPtr, &length1); + end = string1 + length1; + failat = -1; + for (p=string1, lenRemain=length1; lenRemain > 0; + p=nextElem, lenRemain=end-nextElem) { + if (TCL_ERROR == TclFindElement(NULL, p, lenRemain, + &elemStart, &nextElem, &elemSize, NULL)) { + Tcl_Obj *tmpStr; + + /* + * This is the simplest way of getting the number of + * characters parsed. Note that this is not the same as + * the number of bytes when parsing strings with non-ASCII + * characters in them. + * + * Skip leading spaces first. This is only really an issue + * if it is the first "element" that has the failure. + */ + + while (TclIsSpaceProc(*p)) { + p++; + } + TclNewStringObj(tmpStr, string1, p-string1); + failat = TclGetCharLength(tmpStr); + TclDecrRefCount(tmpStr); + break; + } + } + } + break; + } case STR_IS_DIGIT: chcomp = Tcl_UniCharIsDigit; break; case STR_IS_DOUBLE: { - if ((objPtr->typePtr == &tclDoubleType) || - (objPtr->typePtr == &tclIntType) || -#ifndef TCL_WIDE_INT_IS_LONG - (objPtr->typePtr == &tclWideIntType) || -#endif - (objPtr->typePtr == &tclBignumType)) { + if (TclHasInternalRep(objPtr, &tclDoubleType) || + TclHasInternalRep(objPtr, &tclIntType) || + TclHasInternalRep(objPtr, &tclBignumType)) { break; } string1 = TclGetStringFromObj(objPtr, &length1); @@ -1574,7 +1700,7 @@ StringIsCmd( goto str_is_done; } end = string1 + length1; - if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, + if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, (const char **) &stop, 0) != TCL_OK) { result = 0; failat = 0; @@ -1582,7 +1708,7 @@ StringIsCmd( failat = stop - string1; if (stop < end) { result = 0; - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); } } break; @@ -1591,16 +1717,9 @@ StringIsCmd( chcomp = Tcl_UniCharIsGraph; break; case STR_IS_INT: - if (TCL_OK == TclGetIntFromObj(NULL, objPtr, &i)) { - break; - } - goto failedIntParse; case STR_IS_ENTIER: - if ((objPtr->typePtr == &tclIntType) || -#ifndef TCL_WIDE_INT_IS_LONG - (objPtr->typePtr == &tclWideIntType) || -#endif - (objPtr->typePtr == &tclBignumType)) { + if (TclHasInternalRep(objPtr, &tclIntType) || + TclHasInternalRep(objPtr, &tclBignumType)) { break; } string1 = TclGetStringFromObj(objPtr, &length1); @@ -1611,7 +1730,7 @@ StringIsCmd( goto str_is_done; } end = string1 + length1; - if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, + if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) { if (stop == end) { /* @@ -1629,7 +1748,7 @@ StringIsCmd( result = 0; failat = stop - string1; - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); } } else { /* @@ -1645,7 +1764,6 @@ StringIsCmd( break; } - failedIntParse: string1 = TclGetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { @@ -1663,7 +1781,7 @@ StringIsCmd( break; } end = string1 + length1; - if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, + if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) { if (stop == end) { /* @@ -1683,7 +1801,7 @@ StringIsCmd( */ failat = stop - string1; - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); } } else { /* @@ -1699,7 +1817,7 @@ StringIsCmd( * well-formed lists. */ - if (TCL_OK == TclListObjLength(NULL, objPtr, &length2)) { + if (TCL_OK == TclListObjLengthM(NULL, objPtr, &length2)) { break; } @@ -1711,7 +1829,7 @@ StringIsCmd( */ const char *elemStart, *nextElem; - int lenRemain, elemSize; + Tcl_Size lenRemain, elemSize; const char *p; string1 = TclGetStringFromObj(objPtr, &length1); @@ -1737,7 +1855,7 @@ StringIsCmd( p++; } TclNewStringObj(tmpStr, string1, p-string1); - failat = Tcl_GetCharLength(tmpStr); + failat = TclGetCharLength(tmpStr); TclDecrRefCount(tmpStr); break; } @@ -1760,6 +1878,9 @@ StringIsCmd( case STR_IS_UPPER: chcomp = Tcl_UniCharIsUpper; break; + case STR_IS_UNICODE: + chcomp = Tcl_UniCharIsUnicode; + break; case STR_IS_WORD: chcomp = Tcl_UniCharIsWordChar; break; @@ -1780,7 +1901,7 @@ StringIsCmd( for (; string1 < end; string1 += length2, failat++) { int ucs4; - length2 = TclUtfToUCS4(string1, &ucs4); + length2 = Tcl_UtfToUniChar(string1, &ucs4); if (!chcomp(ucs4)) { result = 0; break; @@ -1794,10 +1915,11 @@ StringIsCmd( */ str_is_done: - if ((result == 0) && (failVarObj != NULL) && - Tcl_ObjSetVar2(interp, failVarObj, NULL, Tcl_NewIntObj(failat), - TCL_LEAVE_ERR_MSG) == NULL) { - return TCL_ERROR; + if ((result == 0) && (failVarObj != NULL)) { + TclNewIndexObj(objPtr, failat); + if (Tcl_ObjSetVar2(interp, failVarObj, NULL, objPtr, TCL_LEAVE_ERR_MSG) == NULL) { + return TCL_ERROR; + } } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; @@ -1814,7 +1936,7 @@ static int UniCharIsHexDigit( int character) { - return (character >= 0) && (character < 0x80) && isxdigit(character); + return (character >= 0) && (character < 0x80) && isxdigit(UCHAR(character)); } /* @@ -1837,12 +1959,12 @@ UniCharIsHexDigit( static int StringMapCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int length1, length2, mapElemc, index; + Tcl_Size length1, length2, mapElemc, index; int nocase = 0, mapWithDict = 0, copySource = 0; Tcl_Obj **mapElemv, *sourceObj, *resultPtr; Tcl_UniChar *ustring1, *ustring2, *p, *end; @@ -1870,10 +1992,11 @@ StringMapCmd( /* * This test is tricky, but has to be that way or you get other strange - * inconsistencies (see test string-10.20 for illustration why!) + * inconsistencies (see test string-10.20.1 for illustration why!) */ - if (objv[objc-2]->typePtr == &tclDictType && objv[objc-2]->bytes == NULL){ + if (!TclHasStringRep(objv[objc-2]) + && TclHasInternalRep(objv[objc-2], &tclDictType)) { int i, done; Tcl_DictSearch search; @@ -1908,7 +2031,7 @@ StringMapCmd( } Tcl_DictObjDone(&search); } else { - if (TclListObjGetElements(interp, objv[objc-2], &mapElemc, + if (TclListObjGetElementsM(interp, objv[objc-2], &mapElemc, &mapElemv) != TCL_OK) { return TCL_ERROR; } @@ -1943,7 +2066,7 @@ StringMapCmd( } else { sourceObj = objv[objc-1]; } - ustring1 = Tcl_GetUnicodeFromObj(sourceObj, &length1); + ustring1 = TclGetUnicodeFromObj(sourceObj, &length1); if (length1 == 0) { /* * Empty input string, just stop now. @@ -1953,13 +2076,13 @@ StringMapCmd( } end = ustring1 + length1; - strCmpFn = (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp); + strCmpFn = (nocase ? TclUniCharNcasecmp : TclUniCharNcmp); /* * Force result to be Unicode */ - resultPtr = Tcl_NewUnicodeObj(ustring1, 0); + resultPtr = TclNewUnicodeObj(ustring1, 0); if (mapElemc == 2) { /* @@ -1969,10 +2092,11 @@ StringMapCmd( * larger strings. */ - int mapLen; - Tcl_UniChar *mapString, u2lc; + Tcl_Size mapLen; + int u2lc; + Tcl_UniChar *mapString; - ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2); + ustring2 = TclGetUnicodeFromObj(mapElemv[0], &length2); p = ustring1; if ((length2 > length1) || (length2 == 0)) { /* @@ -1981,7 +2105,7 @@ StringMapCmd( ustring1 = end; } else { - mapString = Tcl_GetUnicodeFromObj(mapElemv[1], &mapLen); + mapString = TclGetUnicodeFromObj(mapElemv[1], &mapLen); u2lc = (nocase ? Tcl_UniCharToLower(*ustring2) : 0); for (; ustring1 < end; ustring1++) { if (((*ustring1 == *ustring2) || @@ -1989,20 +2113,21 @@ StringMapCmd( (length2==1 || strCmpFn(ustring1, ustring2, (unsigned long) length2) == 0)) { if (p != ustring1) { - Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p); + TclAppendUnicodeToObj(resultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } ustring1 = p - 1; - Tcl_AppendUnicodeToObj(resultPtr, mapString, mapLen); + TclAppendUnicodeToObj(resultPtr, mapString, mapLen); } } } } else { - Tcl_UniChar **mapStrings, *u2lc = NULL; - int *mapLens; + Tcl_UniChar **mapStrings; + Tcl_Size *mapLens; + int *u2lc = NULL; /* * Precompute pointers to the Unicode string and length. This saves us @@ -2011,13 +2136,13 @@ StringMapCmd( * case. */ - mapStrings = (Tcl_UniChar **)TclStackAlloc(interp, mapElemc*2*sizeof(Tcl_UniChar *)); - mapLens = (int *)TclStackAlloc(interp, mapElemc * 2 * sizeof(int)); + mapStrings = (Tcl_UniChar **)TclStackAlloc(interp, mapElemc*sizeof(Tcl_UniChar *)*2); + mapLens = (Tcl_Size *)TclStackAlloc(interp, mapElemc * sizeof(Tcl_Size) * 2); if (nocase) { - u2lc = (Tcl_UniChar *)TclStackAlloc(interp, mapElemc * sizeof(Tcl_UniChar)); + u2lc = (int *)TclStackAlloc(interp, mapElemc * sizeof(int)); } for (index = 0; index < mapElemc; index++) { - mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index], + mapStrings[index] = TclGetUnicodeFromObj(mapElemv[index], mapLens+index); if (nocase && ((index % 2) == 0)) { u2lc[index/2] = Tcl_UniCharToLower(*mapStrings[index]); @@ -2041,7 +2166,7 @@ StringMapCmd( * Put the skipped chars onto the result first. */ - Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p); + TclAppendUnicodeToObj(resultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; @@ -2057,7 +2182,7 @@ StringMapCmd( * Append the map value to the Unicode string. */ - Tcl_AppendUnicodeToObj(resultPtr, + TclAppendUnicodeToObj(resultPtr, mapStrings[index+1], mapLens[index+1]); break; } @@ -2074,7 +2199,7 @@ StringMapCmd( * Put the rest of the unmapped chars onto result. */ - Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p); + TclAppendUnicodeToObj(resultPtr, p, ustring1 - p); } Tcl_SetObjResult(interp, resultPtr); done: @@ -2107,7 +2232,7 @@ StringMapCmd( static int StringMatchCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2120,7 +2245,7 @@ StringMatchCmd( } if (objc == 4) { - int length; + Tcl_Size length; const char *string = TclGetStringFromObj(objv[1], &length); if ((length > 1) && @@ -2159,12 +2284,12 @@ StringMatchCmd( static int StringRangeCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int length, first, last; + Tcl_Size first, last, end; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "string first last"); @@ -2176,21 +2301,15 @@ StringRangeCmd( * 'end' refers to the last character, not one past it. */ - length = Tcl_GetCharLength(objv[1]) - 1; + end = TclGetCharLength(objv[1]) - 1; - if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK || - TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK) { + if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK || + TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK) { return TCL_ERROR; } - if (first < 0) { - first = 0; - } - if (last >= length) { - last = length; - } - if (last >= first) { - Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last)); + if (last >= 0) { + Tcl_SetObjResult(interp, TclGetRange(objv[1], first, last)); } return TCL_OK; } @@ -2215,14 +2334,12 @@ StringRangeCmd( static int StringReptCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - const char *string1; - char *string2; - int count, index, length1, length2; + int count; Tcl_Obj *resultPtr; if (objc != 3) { @@ -2240,71 +2357,17 @@ StringReptCmd( if (count == 1) { Tcl_SetObjResult(interp, objv[1]); - goto done; + return TCL_OK; } else if (count < 1) { - goto done; - } - string1 = TclGetStringFromObj(objv[1], &length1); - if (length1 <= 0) { - goto done; - } - - /* - * Only build up a string that has data. Instead of building it up with - * repeated appends, we just allocate the necessary space once and copy - * the string value in. - * - * We have to worry about overflow [Bugs 714106, 2561746]. - * At this point we know 1 <= length1 <= INT_MAX and 2 <= count <= INT_MAX. - * We need to keep 2 <= length2 <= INT_MAX. - */ - - if (count > INT_MAX/length1) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "result exceeds max size for a Tcl value (%d bytes)", - INT_MAX)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); - return TCL_ERROR; + return TCL_OK; } - length2 = length1 * count; - - /* - * Include space for the NUL. - */ - string2 = (char *)attemptckalloc(length2 + 1); - if (string2 == NULL) { - /* - * Alloc failed. Note that in this case we try to do an error message - * since this is a case that's most likely when the alloc is large and - * that's easy to do with this API. Note that if we fail allocating a - * short string, this will likely keel over too (and fatally). - */ - - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "string size overflow, out of memory allocating %u bytes", - length2 + 1)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); - return TCL_ERROR; - } - for (index = 0; index < count; index++) { - memcpy(string2 + (length1 * index), string1, length1); + resultPtr = TclStringRepeat(interp, objv[1], count, TCL_STRING_IN_PLACE); + if (resultPtr) { + Tcl_SetObjResult(interp, resultPtr); + return TCL_OK; } - string2[length2] = '\0'; - - /* - * We have to directly assign this instead of using Tcl_SetStringObj (and - * indirectly TclInitStringRep) because that makes another copy of the - * data. - */ - - TclNewObj(resultPtr); - resultPtr->bytes = string2; - resultPtr->length = length2; - Tcl_SetObjResult(interp, resultPtr); - - done: - return TCL_OK; + return TCL_ERROR; } /* @@ -2327,64 +2390,57 @@ StringReptCmd( static int StringRplcCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar *ustring; - int first, last, length, end; + Tcl_Size first, last, end; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?"); return TCL_ERROR; } - ustring = Tcl_GetUnicodeFromObj(objv[1], &length); - end = length - 1; + end = TclGetCharLength(objv[1]) - 1; if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK || - TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK){ + TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK) { return TCL_ERROR; } /* - * The following test screens out most empty substrings as - * candidates for replacement. When they are detected, no - * replacement is done, and the result is the original string, + * The following test screens out most empty substrings as candidates for + * replacement. When they are detected, no replacement is done, and the + * result is the original string. */ + if ((last < 0) || /* Range ends before start of string */ (first > end) || /* Range begins after end of string */ (last < first)) { /* Range begins after it starts */ - /* * BUT!!! when (end < 0) -- an empty original string -- we can * have (first <= end < 0 <= last) and an empty string is permitted * to be replaced. */ + Tcl_SetObjResult(interp, objv[1]); } else { Tcl_Obj *resultPtr; - /* - * We are re-fetching in case the string argument is same value as - * an index argument, and shimmering cost us our ustring. - */ - - ustring = Tcl_GetUnicodeFromObj(objv[1], &length); - end = length-1; - if (first < 0) { first = 0; } - - resultPtr = Tcl_NewUnicodeObj(ustring, first); - if (objc == 5) { - Tcl_AppendObjToObj(resultPtr, objv[4]); + if (last > end) { + last = end; } - if (last < end) { - Tcl_AppendUnicodeToObj(resultPtr, ustring + last + 1, - end - last); + + resultPtr = TclStringReplace(interp, objv[1], first, + last + 1 - first, (objc == 5) ? objv[4] : NULL, + TCL_STRING_IN_PLACE); + + if (resultPtr == NULL) { + return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); } @@ -2411,7 +2467,7 @@ StringRplcCmd( static int StringRevCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2421,7 +2477,7 @@ StringRevCmd( return TCL_ERROR; } - Tcl_SetObjResult(interp, TclStringReverse(objv[1])); + Tcl_SetObjResult(interp, TclStringReverse(objv[1], TCL_STRING_IN_PLACE)); return TCL_OK; } @@ -2431,9 +2487,7 @@ StringRevCmd( * StringStartCmd -- * * This procedure is invoked to process the "string wordstart" Tcl - * command. See the user documentation for details on what it does. Note - * that this command only functions correctly on properly formed Tcl UTF - * strings. + * command. See the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -2446,46 +2500,46 @@ StringRevCmd( static int StringStartCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar ch = 0; - const char *p, *string; - int cur, index, length, numChars; + int ch; + const Tcl_UniChar *p, *string; + Tcl_Size cur, index, length; + Tcl_Obj *obj; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string index"); return TCL_ERROR; } - string = TclGetStringFromObj(objv[1], &length); - numChars = Tcl_NumUtfChars(string, length); - if (TclGetIntForIndexM(interp, objv[2], numChars-1, &index) != TCL_OK) { + string = TclGetUnicodeFromObj(objv[1], &length); + if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) { return TCL_ERROR; } - string = TclGetStringFromObj(objv[1], &length); - if (index >= numChars) { - index = numChars - 1; + if (index >= length) { + index = length - 1; } cur = 0; if (index > 0) { - p = Tcl_UtfAtIndex(string, index); + p = &string[index]; - TclUtfToUniChar(p, &ch); - for (cur = index; cur >= 0; cur--) { + ch = *p; + for (cur = index; cur != TCL_INDEX_NONE; cur--) { int delta = 0; - const char *next; + const Tcl_UniChar *next; if (!Tcl_UniCharIsWordChar(ch)) { break; } - next = TclUtfPrev(p, string); + next = (p > string) ? p - 1 : p; do { next += delta; - delta = TclUtfToUniChar(next, &ch); + ch = *next; + delta = 1; } while (next + delta < p); p = next; } @@ -2493,7 +2547,8 @@ StringStartCmd( cur += 1; } } - Tcl_SetObjResult(interp, Tcl_NewIntObj(cur)); + TclNewIndexObj(obj, cur); + Tcl_SetObjResult(interp, obj); return TCL_OK; } @@ -2503,8 +2558,7 @@ StringStartCmd( * StringEndCmd -- * * This procedure is invoked to process the "string wordend" Tcl command. - * See the user documentation for details on what it does. Note that this - * command only functions correctly on properly formed Tcl UTF strings. + * See the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -2517,34 +2571,33 @@ StringStartCmd( static int StringEndCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar ch = 0; - const char *p, *end, *string; - int cur, index, length, numChars; + int ch; + const Tcl_UniChar *p, *end, *string; + Tcl_Size cur, index, length; + Tcl_Obj *obj; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string index"); return TCL_ERROR; } - string = TclGetStringFromObj(objv[1], &length); - numChars = Tcl_NumUtfChars(string, length); - if (TclGetIntForIndexM(interp, objv[2], numChars-1, &index) != TCL_OK) { + string = TclGetUnicodeFromObj(objv[1], &length); + if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) { return TCL_ERROR; } - string = TclGetStringFromObj(objv[1], &length); if (index < 0) { index = 0; } - if (index < numChars) { - p = Tcl_UtfAtIndex(string, index); + if (index < length) { + p = &string[index]; end = string+length; for (cur = index; p < end; cur++) { - p += TclUtfToUniChar(p, &ch); + ch = *p++; if (!Tcl_UniCharIsWordChar(ch)) { break; } @@ -2553,9 +2606,10 @@ StringEndCmd( cur++; } } else { - cur = numChars; + cur = length; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(cur)); + TclNewIndexObj(obj, cur); + Tcl_SetObjResult(interp, obj); return TCL_OK; } @@ -2579,7 +2633,7 @@ StringEndCmd( static int StringEqualCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2591,7 +2645,9 @@ StringEqualCmd( */ const char *string2; - int length2, i, match, nocase = 0, reqlength = -1; + int i, match, nocase = 0; + Tcl_Size length; + Tcl_WideInt reqlength = -1; if (objc < 3 || objc > 6) { str_cmp_args: @@ -2601,18 +2657,21 @@ StringEqualCmd( } for (i = 1; i < objc-2; i++) { - string2 = TclGetStringFromObj(objv[i], &length2); - if ((length2 > 1) && !strncmp(string2, "-nocase", length2)) { + string2 = TclGetStringFromObj(objv[i], &length); + if ((length > 1) && !strncmp(string2, "-nocase", length)) { nocase = 1; - } else if ((length2 > 1) - && !strncmp(string2, "-length", length2)) { + } else if ((length > 1) + && !strncmp(string2, "-length", length)) { if (i+1 >= objc-2) { goto str_cmp_args; } i++; - if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { return TCL_ERROR; } + if ((Tcl_WideUInt)reqlength > TCL_SIZE_MAX) { + reqlength = -1; + } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": must be -nocase or -length", @@ -2654,7 +2713,7 @@ StringEqualCmd( static int StringCmpCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2665,220 +2724,33 @@ StringCmpCmd( * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ - int match, nocase, reqlength, status; + int match, nocase, status; + Tcl_Size reqlength = -1; - status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength); + status = StringCmpOpts(interp, objc, objv, &nocase, &reqlength); if (status != TCL_OK) { return status; } objv += objc-2; match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength); - Tcl_SetObjResult(interp, Tcl_NewIntObj(match)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(match)); return TCL_OK; } -/* - *---------------------------------------------------------------------- - * - * TclStringCmp -- - * - * This is the core of Tcl's string comparison. It only handles byte - * arrays, UNICODE strings and UTF-8 strings correctly. - * - * Results: - * -1 if value1Ptr is less than value2Ptr, 0 if they are equal, or 1 if - * value1Ptr is greater. - * - * Side effects: - * May cause string representations of objects to be allocated. - * - *---------------------------------------------------------------------- - */ - int -TclStringCmp( - Tcl_Obj *value1Ptr, - Tcl_Obj *value2Ptr, - int checkEq, /* comparison is only for equality */ - int nocase, /* comparison is not case sensitive */ - int reqlength) /* requested length in characters; -1 to - * compare whole strings */ -{ - const char *s1, *s2; - int empty, length, match, s1len, s2len; - memCmpFn_t memCmpFn; - - if ((reqlength == 0) || (value1Ptr == value2Ptr)) { - /* - * Always match at 0 chars or if it is the same obj. - */ - return 0; - } - - if (!nocase && TclIsPureByteArray(value1Ptr) - && TclIsPureByteArray(value2Ptr)) { - /* - * Use binary versions of comparisons since that won't cause undue - * type conversions and it is much faster. Only do this if we're - * case-sensitive (which is all that really makes sense with byte - * arrays anyway, and we have no memcasecmp() for some reason... :^) - */ - - s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len); - s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); - memCmpFn = memcmp; - } else if ((value1Ptr->typePtr == &tclStringType) - && (value2Ptr->typePtr == &tclStringType)) { - /* - * Do a Unicode-specific comparison if both of the args are of String - * type. If the char length == byte length, we can do a memcmp. In - * benchmark testing this proved the most efficient check between the - * Unicode and string comparison operations. - */ - - if (nocase) { - s1 = (char *) Tcl_GetUnicodeFromObj(value1Ptr, &s1len); - s2 = (char *) Tcl_GetUnicodeFromObj(value2Ptr, &s2len); - memCmpFn = (memCmpFn_t)Tcl_UniCharNcasecmp; - } else { - s1len = Tcl_GetCharLength(value1Ptr); - s2len = Tcl_GetCharLength(value2Ptr); - if ((s1len == value1Ptr->length) - && (value1Ptr->bytes != NULL) - && (s2len == value2Ptr->length) - && (value2Ptr->bytes != NULL)) { - /* each byte represents one character so s1l3n, s2l3n, and - * reqlength are in both bytes and characters - */ - s1 = value1Ptr->bytes; - s2 = value2Ptr->bytes; - memCmpFn = memcmp; - } else { - s1 = (char *) Tcl_GetUnicode(value1Ptr); - s2 = (char *) Tcl_GetUnicode(value2Ptr); - if ( -#if defined(WORDS_BIGENDIAN) && (TCL_UTF_MAX != 4) - 1 -#else - checkEq -#endif /* WORDS_BIGENDIAN */ - ) { - memCmpFn = memcmp; - s1len *= sizeof(Tcl_UniChar); - s2len *= sizeof(Tcl_UniChar); - if (reqlength > 0) { - reqlength *= sizeof(Tcl_UniChar); - } - } else { - memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp; - } - } - } - } else { - /* - * Get the string representations, being careful in case we have - * special empty string objects about. - */ - - empty = TclCheckEmptyString(value1Ptr); - if (empty > 0) { - switch (TclCheckEmptyString(value2Ptr)) { - case -1: - s1 = ""; - s1len = 0; - s2 = TclGetStringFromObj(value2Ptr, &s2len); - break; - case 0: - return -1; - default: /* avoid warn: `s2` may be used uninitialized */ - return 0; - } - } else if (TclCheckEmptyString(value2Ptr) > 0) { - switch (empty) { - case -1: - s2 = ""; - s2len = 0; - s1 = TclGetStringFromObj(value1Ptr, &s1len); - break; - case 0: - return 1; - default: /* avoid warn: `s1` may be used uninitialized */ - return 0; - } - } else { - s1 = TclGetStringFromObj(value1Ptr, &s1len); - s2 = TclGetStringFromObj(value2Ptr, &s2len); - } - - if (!nocase && checkEq && reqlength < 0) { - /* - * When we have equal-length we can check only for (in)equality. - * We can use memcmp() in all (n)eq cases because we don't need to - * worry about lexical LE/BE variance. - */ - memCmpFn = memcmp; - } else { - /* - * As a catch-all we will work with UTF-8. We cannot use memcmp() - * as that is unsafe with any string containing NUL (\xC0\x80 in - * Tcl's utf rep). We can use the more efficient TclpUtfNcmp2 if - * we are case-sensitive and no specific length was requested. - */ - - if ((reqlength < 0) && !nocase) { - memCmpFn = (memCmpFn_t) TclpUtfNcmp2; - } else { - s1len = Tcl_NumUtfChars(s1, s1len); - s2len = Tcl_NumUtfChars(s2, s2len); - memCmpFn = (memCmpFn_t) - (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); - } - } - } - - /* At this point s1len, s2len, and reqlength should by now have been - * adjusted so that they are all in the units expected by the selected - * comparison function. - */ - - length = (s1len < s2len) ? s1len : s2len; - if (reqlength > 0 && reqlength < length) { - length = reqlength; - } else if (reqlength < 0) { - /* - * The requested length is negative, so ignore it by setting it to - * length + 1 to correct the match var. - */ - reqlength = length + 1; - } - - if (checkEq && reqlength < 0 && (s1len != s2len)) { - match = 1; /* This will be reversed below. */ - } else { - /* - * The comparison function should compare up to the minimum byte - * length only. - */ - match = memCmpFn(s1, s2, length); - } - if ((match == 0) && (reqlength > length)) { - match = s1len - s2len; - } - return (match > 0) ? 1 : (match < 0) ? -1 : 0; -} - -int TclStringCmpOpts( +StringCmpOpts( Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[], /* Argument objects. */ int *nocase, - int *reqlength) + Tcl_Size *reqlength) { - int i, length; + int i; + Tcl_Size length; const char *string; + Tcl_WideInt wreqlength = -1; - *reqlength = -1; *nocase = 0; if (objc < 3 || objc > 6) { str_cmp_args: @@ -2897,9 +2769,14 @@ int TclStringCmpOpts( goto str_cmp_args; } i++; - if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[i], &wreqlength) != TCL_OK) { return TCL_ERROR; } + if ((Tcl_WideUInt)wreqlength > TCL_SIZE_MAX) { + *reqlength = -1; + } else { + *reqlength = wreqlength; + } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": must be -nocase or -length", @@ -2931,12 +2808,11 @@ int TclStringCmpOpts( static int StringCatCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int i; Tcl_Obj *objResultPtr; if (objc < 2) { @@ -2946,23 +2822,15 @@ StringCatCmd( */ return TCL_OK; } - if (objc == 2) { - /* - * Other trivial case, single arg, just return it. - */ - Tcl_SetObjResult(interp, objv[1]); + + objResultPtr = TclStringCat(interp, objc-1, objv+1, TCL_STRING_IN_PLACE); + + if (objResultPtr) { + Tcl_SetObjResult(interp, objResultPtr); return TCL_OK; } - objResultPtr = objv[1]; - if (Tcl_IsShared(objResultPtr)) { - objResultPtr = Tcl_DuplicateObj(objResultPtr); - } - for(i = 2;i < objc;i++) { - Tcl_AppendObjToObj(objResultPtr, objv[i]); - } - Tcl_SetObjResult(interp, objResultPtr); - return TCL_OK; + return TCL_ERROR; } /* @@ -2983,10 +2851,10 @@ StringCatCmd( * *---------------------------------------------------------------------- */ - +#if TCL_MAJOR_VERSION < 9 && !defined(TCL_NO_DEPRECATED) static int StringBytesCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(ClientData), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2999,9 +2867,10 @@ StringBytesCmd( } (void) TclGetStringFromObj(objv[1], &length); - Tcl_SetObjResult(interp, Tcl_NewIntObj(length)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(length)); return TCL_OK; } +#endif /* *---------------------------------------------------------------------- @@ -3023,7 +2892,7 @@ StringBytesCmd( static int StringLenCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -3033,7 +2902,7 @@ StringLenCmd( return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_GetCharLength(objv[1]))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(TclGetCharLength(objv[1]))); return TCL_OK; } @@ -3057,12 +2926,12 @@ StringLenCmd( static int StringLowerCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int length1, length2; + Tcl_Size length1, length2; const char *string1; char *string2; @@ -3080,11 +2949,11 @@ StringLowerCmd( Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { - int first, last; + Tcl_Size first, last; const char *start, *end; Tcl_Obj *resultPtr; - length1 = Tcl_NumUtfChars(string1, length1) - 1; + length1 = TclNumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } @@ -3107,8 +2976,8 @@ StringLowerCmd( } string1 = TclGetStringFromObj(objv[1], &length1); - start = Tcl_UtfAtIndex(string1, first); - end = Tcl_UtfAtIndex(start, last - first + 1); + start = TclUtfAtIndex(string1, first); + end = TclUtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); @@ -3142,12 +3011,12 @@ StringLowerCmd( static int StringUpperCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int length1, length2; + Tcl_Size length1, length2; const char *string1; char *string2; @@ -3165,11 +3034,11 @@ StringUpperCmd( Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { - int first, last; + Tcl_Size first, last; const char *start, *end; Tcl_Obj *resultPtr; - length1 = Tcl_NumUtfChars(string1, length1) - 1; + length1 = TclNumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } @@ -3192,8 +3061,8 @@ StringUpperCmd( } string1 = TclGetStringFromObj(objv[1], &length1); - start = Tcl_UtfAtIndex(string1, first); - end = Tcl_UtfAtIndex(start, last - first + 1); + start = TclUtfAtIndex(string1, first); + end = TclUtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); @@ -3227,12 +3096,12 @@ StringUpperCmd( static int StringTitleCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int length1, length2; + Tcl_Size length1, length2; const char *string1; char *string2; @@ -3250,11 +3119,11 @@ StringTitleCmd( Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { - int first, last; + Tcl_Size first, last; const char *start, *end; Tcl_Obj *resultPtr; - length1 = Tcl_NumUtfChars(string1, length1) - 1; + length1 = TclNumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } @@ -3277,8 +3146,8 @@ StringTitleCmd( } string1 = TclGetStringFromObj(objv[1], &length1); - start = Tcl_UtfAtIndex(string1, first); - end = Tcl_UtfAtIndex(start, last - first + 1); + start = TclUtfAtIndex(string1, first); + end = TclUtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); @@ -3312,7 +3181,7 @@ StringTitleCmd( static int StringTrimCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -3359,13 +3228,14 @@ StringTrimCmd( static int StringTrimLCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; - int trim, length1, length2; + int trim; + Tcl_Size length1, length2; if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); @@ -3405,13 +3275,14 @@ StringTrimLCmd( static int StringTrimRCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; - int trim, length1, length2; + int trim; + Tcl_Size length1, length2; if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); @@ -3458,12 +3329,15 @@ TclInitStringCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap stringImplMap[] = { +#if TCL_MAJOR_VERSION < 9 && !defined(TCL_NO_DEPRECATED) {"bytelength", StringBytesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, +#endif {"cat", StringCatCmd, TclCompileStringCatCmd, NULL, NULL, 0}, {"compare", StringCmpCmd, TclCompileStringCmpCmd, NULL, NULL, 0}, {"equal", StringEqualCmd, TclCompileStringEqualCmd, NULL, NULL, 0}, {"first", StringFirstCmd, TclCompileStringFirstCmd, NULL, NULL, 0}, {"index", StringIndexCmd, TclCompileStringIndexCmd, NULL, NULL, 0}, + {"insert", StringInsertCmd, TclCompileStringInsertCmd, NULL, NULL, 0}, {"is", StringIsCmd, TclCompileStringIsCmd, NULL, NULL, 0}, {"last", StringLastCmd, TclCompileStringLastCmd, NULL, NULL, 0}, {"length", StringLenCmd, TclCompileStringLenCmd, NULL, NULL, 0}, @@ -3508,7 +3382,7 @@ TclInitStringCmd( int TclSubstOptions( Tcl_Interp *interp, - int numOpts, + Tcl_Size numOpts, Tcl_Obj *const opts[], int *flagPtr) { @@ -3547,17 +3421,17 @@ TclSubstOptions( int Tcl_SubstObjCmd( - ClientData dummy, /* Not used. */ + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRSubstObjCmd, dummy, objc, objv); + return Tcl_NRCallObjProc(interp, TclNRSubstObjCmd, clientData, objc, objv); } int TclNRSubstObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -3595,22 +3469,23 @@ TclNRSubstObjCmd( int Tcl_SwitchObjCmd( - ClientData dummy, /* Not used. */ + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRSwitchObjCmd, dummy, objc, objv); + return Tcl_NRCallObjProc(interp, TclNRSwitchObjCmd, clientData, objc, objv); } int TclNRSwitchObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int i,j, index, mode, foundmode, splitObjs, numMatchesSaved; - int noCase, patternLength; + int i, index, mode, foundmode, splitObjs, numMatchesSaved; + int noCase; + Tcl_Size patternLength, j; const char *pattern; Tcl_Obj *stringObj, *indexVarObj, *matchVarObj; Tcl_Obj *const *savedObjv = objv; @@ -3631,12 +3506,12 @@ TclNRSwitchObjCmd( "-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp", "--", NULL }; - enum options { + enum switchOptionsEnum { OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_NOCASE, OPT_REGEXP, OPT_LAST }; typedef int (*strCmpFn_t)(const char *, const char *); - strCmpFn_t strCmpFn = strcmp; + strCmpFn_t strCmpFn = TclUtfCmp; mode = OPT_EXACT; foundmode = 0; @@ -3652,7 +3527,7 @@ TclNRSwitchObjCmd( &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum options) index) { + switch ((enum switchOptionsEnum) index) { /* * General options. */ @@ -3760,7 +3635,7 @@ TclNRSwitchObjCmd( Tcl_Obj **listv; blist = objv[0]; - if (TclListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK){ + if (TclListObjLengthM(interp, objv[0], &objc) != TCL_OK) { return TCL_ERROR; } @@ -3773,6 +3648,9 @@ TclNRSwitchObjCmd( "?-option ...? string {?pattern body ...? ?default body?}"); return TCL_ERROR; } + if (TclListObjGetElementsM(interp, objv[0], &objc, &listv) != TCL_OK) { + return TCL_ERROR; + } objv = listv; splitObjs = 1; } @@ -3922,8 +3800,8 @@ TclNRSwitchObjCmd( Tcl_Obj *rangeObjAry[2]; if (info.matches[j].end > 0) { - rangeObjAry[0] = Tcl_NewLongObj(info.matches[j].start); - rangeObjAry[1] = Tcl_NewLongObj(info.matches[j].end-1); + TclNewIndexObj(rangeObjAry[0], info.matches[j].start); + TclNewIndexObj(rangeObjAry[1], info.matches[j].end-1); } else { TclNewIntObj(rangeObjAry[1], -1); rangeObjAry[0] = rangeObjAry[1]; @@ -3941,7 +3819,7 @@ TclNRSwitchObjCmd( Tcl_Obj *substringObj; if (info.matches[j].end > 0) { - substringObj = Tcl_GetRange(stringObj, + substringObj = TclGetRange(stringObj, info.matches[j].start, info.matches[j].end-1); } else { TclNewObj(substringObj); @@ -4022,7 +3900,7 @@ TclNRSwitchObjCmd( if (ctxPtr->type == TCL_LOCATION_SOURCE && ctxPtr->line[bidx] >= 0) { int bline = ctxPtr->line[bidx]; - ctxPtr->line = (int *)ckalloc(objc * sizeof(int)); + ctxPtr->line = (Tcl_Size *)ckalloc(objc * sizeof(Tcl_Size)); ctxPtr->nline = objc; TclListLines(blist, bline, objc, ctxPtr->line, objv); } else { @@ -4036,7 +3914,7 @@ TclNRSwitchObjCmd( int k; - ctxPtr->line = (int *)ckalloc(objc * sizeof(int)); + ctxPtr->line = (Tcl_Size *)ckalloc(objc * sizeof(Tcl_Size)); ctxPtr->nline = objc; for (k=0; k < objc; k++) { ctxPtr->line[k] = -1; @@ -4063,13 +3941,13 @@ TclNRSwitchObjCmd( */ Tcl_NRAddCallback(interp, SwitchPostProc, INT2PTR(splitObjs), ctxPtr, - INT2PTR(pc), (ClientData) pattern); + INT2PTR(pc), (void *)pattern); return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j); } static int SwitchPostProc( - ClientData data[], /* Data passed from Tcl_NRAddCallback above */ + void *data[], /* Data passed from Tcl_NRAddCallback above */ Tcl_Interp *interp, /* Tcl interpreter */ int result) /* Result to return*/ { @@ -4079,7 +3957,7 @@ SwitchPostProc( CmdFrame *ctxPtr = (CmdFrame *)data[1]; int pc = PTR2INT(data[2]); const char *pattern = (const char *)data[3]; - int patternLength = strlen(pattern); + Tcl_Size patternLength = strlen(pattern); /* * Clean up TIP 280 context information @@ -4130,16 +4008,15 @@ SwitchPostProc( *---------------------------------------------------------------------- */ - /* ARGSUSED */ int Tcl_ThrowObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *options; - int len; + Tcl_Size len; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "type message"); @@ -4150,7 +4027,7 @@ Tcl_ThrowObjCmd( * The type must be a list of at least length 1. */ - if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &len) != TCL_OK) { return TCL_ERROR; } else if (len < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( @@ -4195,7 +4072,7 @@ Tcl_ThrowObjCmd( int Tcl_TimeObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -4250,9 +4127,9 @@ Tcl_TimeObjCmd( * Use int obj since we know time is not fractional. [Bug 1202178] */ - objs[0] = Tcl_NewWideIntObj((count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec); + TclNewIntObj(objs[0], (count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec); } else { - objs[0] = Tcl_NewDoubleObj(totalMicroSec/count); + TclNewDoubleObj(objs[0], totalMicroSec/count); } /* @@ -4293,7 +4170,7 @@ Tcl_TimeObjCmd( int Tcl_TimeRateObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -4304,14 +4181,14 @@ Tcl_TimeRateObjCmd( Tcl_Obj *objPtr; int result, i; Tcl_Obj *calibrate = NULL, *direct = NULL; - TclWideMUInt count = 0; /* Holds repetition count */ + Tcl_WideUInt count = 0; /* Holds repetition count */ Tcl_WideInt maxms = WIDE_MIN; /* Maximal running time (in milliseconds) */ - TclWideMUInt maxcnt = WIDE_MAX; + Tcl_WideUInt maxcnt = WIDE_MAX; /* Maximal count of iterations. */ - TclWideMUInt threshold = 1; /* Current threshold for check time (faster + Tcl_WideUInt threshold = 1; /* Current threshold for check time (faster * repeat count without time check) */ - TclWideMUInt maxIterTm = 1; /* Max time of some iteration as max + Tcl_WideUInt maxIterTm = 1; /* Max time of some iteration as max * threshold, additionally avoiding divide to * zero (i.e., never < 1) */ unsigned short factor = 50; /* Factor (4..50) limiting threshold to avoid @@ -4323,7 +4200,7 @@ Tcl_TimeRateObjCmd( static const char *const options[] = { "-direct", "-overhead", "-calibrate", "--", NULL }; - enum options { + enum timeRateOptionsEnum { TMRT_EV_DIRECT, TMRT_OVERHEAD, TMRT_CALIBRATE, TMRT_LAST }; NRE_callback *rootPtr; @@ -4340,7 +4217,7 @@ Tcl_TimeRateObjCmd( i++; break; } - switch (index) { + switch ((enum timeRateOptionsEnum)index) { case TMRT_EV_DIRECT: direct = objv[i]; break; @@ -4355,6 +4232,8 @@ Tcl_TimeRateObjCmd( case TMRT_CALIBRATE: calibrate = objv[i]; break; + case TMRT_LAST: + break; } } @@ -4414,7 +4293,7 @@ Tcl_TimeRateObjCmd( * calibration cycle. */ - TclNewLongObj(clobjv[i], 100); + TclNewIntObj(clobjv[i], 100); Tcl_IncrRefCount(clobjv[i]); result = Tcl_TimeRateObjCmd(NULL, interp, i + 1, clobjv); Tcl_DecrRefCount(clobjv[i]); @@ -4439,7 +4318,7 @@ Tcl_TimeRateObjCmd( maxms = -1000; do { lastMeasureOverhead = measureOverhead; - TclNewLongObj(clobjv[i], (int) maxms); + TclNewIntObj(clobjv[i], (int) maxms); Tcl_IncrRefCount(clobjv[i]); result = Tcl_TimeRateObjCmd(NULL, interp, i + 1, clobjv); Tcl_DecrRefCount(clobjv[i]); @@ -4469,7 +4348,7 @@ Tcl_TimeRateObjCmd( */ measureOverhead = 0; - Tcl_SetObjResult(interp, Tcl_NewLongObj(0)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); return TCL_OK; } @@ -4683,13 +4562,13 @@ Tcl_TimeRateObjCmd( { Tcl_Obj *objarr[8], **objs = objarr; - TclWideMUInt usec, val; + Tcl_WideUInt usec, val; int digits; /* * Absolute execution time in microseconds or in wide clicks. */ - usec = (TclWideMUInt)(middle - start); + usec = (Tcl_WideUInt)(middle - start); #ifdef TCL_WIDE_CLICKS /* @@ -4700,7 +4579,8 @@ Tcl_TimeRateObjCmd( #endif /* TCL_WIDE_CLICKS */ if (!count) { /* no iterations - avoid divide by zero */ - objs[0] = objs[2] = objs[4] = Tcl_NewWideIntObj(0); + TclNewIntObj(objs[4], 0); + objs[0] = objs[2] = objs[4]; goto retRes; } @@ -4718,7 +4598,7 @@ Tcl_TimeRateObjCmd( * Estimate the time of overhead (microsecs). */ - TclWideMUInt curOverhead = overhead * count; + Tcl_WideUInt curOverhead = overhead * count; if (usec > curOverhead) { usec -= curOverhead; @@ -4734,14 +4614,14 @@ Tcl_TimeRateObjCmd( if (measureOverhead > ((double) usec) / count) { measureOverhead = ((double) usec) / count; } - objs[0] = Tcl_NewDoubleObj(measureOverhead); + TclNewDoubleObj(objs[0], measureOverhead); TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#-overhead"); /* mics */ objs += 2; } val = usec / count; /* microsecs per iteration */ if (val >= 1000000) { - objs[0] = Tcl_NewWideIntObj(val); + TclNewIntObj(objs[0], val); } else { if (val < 10) { digits = 6; @@ -4757,7 +4637,7 @@ Tcl_TimeRateObjCmd( objs[0] = Tcl_ObjPrintf("%.*f", digits, ((double) usec)/count); } - objs[2] = Tcl_NewWideIntObj(count); /* iterations */ + TclNewIntObj(objs[2], count); /* iterations */ /* * Calculate speed as rate (count) per sec @@ -4779,7 +4659,7 @@ Tcl_TimeRateObjCmd( objs[4] = Tcl_ObjPrintf("%.*f", digits, ((double) (count * 1000000)) / usec); } else { - objs[4] = Tcl_NewWideIntObj(val); + TclNewIntObj(objs[4], val); } } else { objs[4] = Tcl_NewWideIntObj((count / usec) * 1000000); @@ -4794,7 +4674,7 @@ Tcl_TimeRateObjCmd( if (usec >= 1) { objs[6] = Tcl_ObjPrintf("%.3f", (double)usec / 1000); } else { - objs[6] = Tcl_NewWideIntObj(0); + TclNewIntObj(objs[6], 0); } TclNewLiteralStringObj(objs[7], "net-ms"); } @@ -4836,23 +4716,24 @@ Tcl_TimeRateObjCmd( int Tcl_TryObjCmd( - ClientData dummy, /* Not used. */ + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRTryObjCmd, dummy, objc, objv); + return Tcl_NRCallObjProc(interp, TclNRTryObjCmd, clientData, objc, objv); } int TclNRTryObjCmd( - ClientData clientData, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *bodyObj, *handlersObj, *finallyObj = NULL; - int i, bodyShared, haveHandlers, dummy, code; + int i, bodyShared, haveHandlers, code; + Tcl_Size dummy; static const char *const handlerNames[] = { "finally", "on", "trap", NULL }; @@ -4935,10 +4816,10 @@ TclNRTryObjCmd( return TCL_ERROR; } code = 1; - if (TclListObjLength(NULL, objv[i+1], &dummy) != TCL_OK) { + if (TclListObjLengthM(NULL, objv[i+1], &dummy) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad prefix '%s': must be a list", - Tcl_GetString(objv[i+1]))); + TclGetString(objv[i+1]))); Tcl_DecrRefCount(handlersObj); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "TRAP", "EXNFORMAT", NULL); @@ -4947,7 +4828,7 @@ TclNRTryObjCmd( info[2] = objv[i+1]; commonHandler: - if (TclListObjLength(interp, objv[i+2], &dummy) != TCL_OK) { + if (TclListObjLengthM(interp, objv[i+2], &dummy) != TCL_OK) { Tcl_DecrRefCount(handlersObj); return TCL_ERROR; } @@ -4986,7 +4867,7 @@ TclNRTryObjCmd( */ Tcl_NRAddCallback(interp, TryPostBody, handlersObj, finallyObj, - (ClientData)objv, INT2PTR(objc)); + (void *)objv, INT2PTR(objc)); return TclNREvalObjEx(interp, bodyObj, 0, ((Interp *) interp)->cmdFramePtr, 1); } @@ -5044,13 +4925,13 @@ During( static int TryPostBody( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultObj, *options, *handlersObj, *finallyObj, *cmdObj, **objv; - int i, dummy, code, objc; - int numHandlers = 0; + int code, objc; + Tcl_Size i, numHandlers = 0; handlersObj = (Tcl_Obj *)data[0]; finallyObj = (Tcl_Obj *)data[1]; @@ -5097,11 +4978,12 @@ TryPostBody( int found = 0; Tcl_Obj **handlers, **info; - TclListObjGetElements(NULL, handlersObj, &numHandlers, &handlers); + TclListObjGetElementsM(NULL, handlersObj, &numHandlers, &handlers); for (i=0 ; i<numHandlers ; i++) { Tcl_Obj *handlerBodyObj; + Tcl_Size numElems = 0; - TclListObjGetElements(NULL, handlers[i], &dummy, &info); + TclListObjGetElementsM(NULL, handlers[i], &numElems, &info); if (!found) { Tcl_GetIntFromObj(NULL, info[1], &code); if (code != result) { @@ -5117,13 +4999,13 @@ TryPostBody( if (code == TCL_ERROR) { Tcl_Obj *errorCodeName, *errcode, **bits1, **bits2; - int len1, len2, j; + Tcl_Size len1, len2, j; TclNewLiteralStringObj(errorCodeName, "-errorcode"); Tcl_DictObjGet(NULL, options, errorCodeName, &errcode); Tcl_DecrRefCount(errorCodeName); - TclListObjGetElements(NULL, info[2], &len1, &bits1); - if (TclListObjGetElements(NULL, errcode, &len2, + TclListObjGetElementsM(NULL, info[2], &len1, &bits1); + if (TclListObjGetElementsM(NULL, errcode, &len2, &bits2) != TCL_OK) { continue; } @@ -5163,8 +5045,8 @@ TryPostBody( Tcl_ResetResult(interp); result = TCL_ERROR; - TclListObjLength(NULL, info[3], &dummy); - if (dummy > 0) { + TclListObjLengthM(NULL, info[3], &numElems); + if (numElems> 0) { Tcl_Obj *varName; Tcl_ListObjIndex(NULL, info[3], 0, &varName); @@ -5174,7 +5056,7 @@ TryPostBody( goto handlerFailed; } Tcl_DecrRefCount(resultObj); - if (dummy > 1) { + if (numElems> 1) { Tcl_ListObjIndex(NULL, info[3], 1, &varName); if (Tcl_ObjSetVar2(interp, varName, NULL, options, TCL_LEAVE_ERR_MSG) == NULL) { @@ -5259,7 +5141,7 @@ TryPostBody( static int TryPostHandler( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { @@ -5345,7 +5227,7 @@ TryPostHandler( static int TryPostFinal( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { @@ -5412,17 +5294,17 @@ TryPostFinal( int Tcl_WhileObjCmd( - ClientData dummy, /* Not used. */ + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRWhileObjCmd, dummy, objc, objv); + return Tcl_NRCallObjProc(interp, TclNRWhileObjCmd, clientData, objc, objv); } int TclNRWhileObjCmd( - ClientData dummy, /* Not used. */ + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -5471,18 +5353,18 @@ TclListLines( Tcl_Obj *listObj, /* Pointer to obj holding a string with list * structure. Assumed to be valid. Assumed to * contain n elements. */ - int line, /* Line the list as a whole starts on. */ - int n, /* #elements in lines */ - int *lines, /* Array of line numbers, to fill. */ + Tcl_Size line, /* Line the list as a whole starts on. */ + Tcl_Size n, /* #elements in lines */ + Tcl_Size *lines, /* Array of line numbers, to fill. */ Tcl_Obj *const *elems) /* The list elems as Tcl_Obj*, in need of * derived continuation data */ { - const char *listStr = Tcl_GetString(listObj); + const char *listStr = TclGetString(listObj); const char *listHead = listStr; - int i, length = strlen(listStr); + Tcl_Size i, length = strlen(listStr); const char *element = NULL, *next = NULL; ContLineLoc *clLocPtr = TclContinuationsGet(listObj); - int *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL); + Tcl_Size *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL); for (i = 0; i < n; i++) { TclFindElement(NULL, listStr, length, &element, &next, NULL, NULL); |