diff options
Diffstat (limited to 'generic/tclCmdMZ.c')
-rw-r--r-- | generic/tclCmdMZ.c | 1472 |
1 files changed, 327 insertions, 1145 deletions
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 841002f..70943e9 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -10,7 +10,7 @@ * 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 (c) 2003 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -18,53 +18,9 @@ #include "tclInt.h" #include "tclRegexp.h" -#include "tclStringTrim.h" - -static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode, - Tcl_Obj *oldOptions, Tcl_Obj *errorInfo); -static int SwitchPostProc(ClientData data[], Tcl_Interp *interp, - int result); -static int TryPostBody(ClientData data[], Tcl_Interp *interp, - int result); -static int TryPostFinal(ClientData data[], Tcl_Interp *interp, - int result); -static int TryPostHandler(ClientData data[], Tcl_Interp *interp, - int result); + static int UniCharIsAscii(int character); static int UniCharIsHexDigit(int character); - -/* - * Default set of characters to trim in [string trim] and friends. This is a - * UTF-8 literal string containing all Unicode space characters [TIP #413] - */ - -const char tclDefaultTrimSet[] = - "\x09\x0a\x0b\x0c\x0d " /* ASCII */ - "\xc0\x80" /* nul (U+0000) */ - "\xc2\x85" /* next line (U+0085) */ - "\xc2\xa0" /* non-breaking space (U+00a0) */ - "\xe1\x9a\x80" /* ogham space mark (U+1680) */ - "\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */ - "\xe2\x80\x80" /* en quad (U+2000) */ - "\xe2\x80\x81" /* em quad (U+2001) */ - "\xe2\x80\x82" /* en space (U+2002) */ - "\xe2\x80\x83" /* em space (U+2003) */ - "\xe2\x80\x84" /* three-per-em space (U+2004) */ - "\xe2\x80\x85" /* four-per-em space (U+2005) */ - "\xe2\x80\x86" /* six-per-em space (U+2006) */ - "\xe2\x80\x87" /* figure space (U+2007) */ - "\xe2\x80\x88" /* punctuation space (U+2008) */ - "\xe2\x80\x89" /* thin space (U+2009) */ - "\xe2\x80\x8a" /* hair space (U+200a) */ - "\xe2\x80\x8b" /* zero width space (U+200b) */ - "\xe2\x80\xa8" /* line separator (U+2028) */ - "\xe2\x80\xa9" /* paragraph separator (U+2029) */ - "\xe2\x80\xaf" /* narrow no-break space (U+202f) */ - "\xe2\x81\x9f" /* medium mathematical space (U+205f) */ - "\xe2\x81\xa0" /* word joiner (U+2060) */ - "\xe3\x80\x80" /* ideographic space (U+3000) */ - "\xef\xbb\xbf" /* zero width no-break space (U+feff) */ -; /* *---------------------------------------------------------------------- @@ -135,7 +91,7 @@ Tcl_RegexpObjCmd( Tcl_RegExp regExpr; Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL; Tcl_RegExpInfo info; - static const char *const options[] = { + static const char *options[] = { "-all", "-about", "-indices", "-inline", "-expanded", "-line", "-linestop", "-lineanchor", "-nocase", "-start", "--", NULL @@ -149,19 +105,20 @@ Tcl_RegexpObjCmd( indices = 0; about = 0; cflags = TCL_REG_ADVANCED; + eflags = 0; offset = 0; all = 0; doinline = 0; for (i = 1; i < objc; i++) { - const char *name; + char *name; int index; name = TclGetString(objv[i]); if (name[0] != '-') { break; } - if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT, + if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT, &index) != TCL_OK) { goto optionError; } @@ -217,7 +174,7 @@ Tcl_RegexpObjCmd( endOfForLoop: if ((objc - i) < (2 - about)) { Tcl_WrongNumArgs(interp, 1, objv, - "?-option ...? exp string ?matchVar? ?subMatchVar ...?"); + "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"); goto optionError; } objc -= i; @@ -229,10 +186,8 @@ Tcl_RegexpObjCmd( */ if (doinline && ((objc - 2) != 0)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "regexp match variables not allowed when using -inline", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGEXP", - "MIX_VAR_INLINE", NULL); + Tcl_AppendResult(interp, "regexp match variables not allowed" + " when using -inline", NULL); goto optionError; } @@ -413,8 +368,11 @@ Tcl_RegexpObjCmd( return TCL_ERROR; } } else { - if (Tcl_ObjSetVar2(interp, objv[i], NULL, newPtr, - TCL_LEAVE_ERR_MSG) == NULL) { + Tcl_Obj *valuePtr; + valuePtr = Tcl_ObjSetVar2(interp, objv[i], NULL, newPtr, 0); + if (valuePtr == NULL) { + Tcl_AppendResult(interp, "couldn't set variable \"", + TclGetString(objv[i]), "\"", NULL); return TCL_ERROR; } } @@ -434,8 +392,7 @@ Tcl_RegexpObjCmd( * offset never changes). */ - matchLength = (info.matches[0].end - info.matches[0].start); - + matchLength = info.matches[0].end - info.matches[0].start; offset += info.matches[0].end; /* @@ -497,7 +454,7 @@ Tcl_RegsubObjCmd( Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL; Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend; - static const char *const options[] = { + static const char *options[] = { "-all", "-nocase", "-expanded", "-line", "-linestop", "-lineanchor", "-start", "--", NULL @@ -514,14 +471,14 @@ Tcl_RegsubObjCmd( resultPtr = NULL; for (idx = 1; idx < objc; idx++) { - const char *name; + char *name; int index; name = TclGetString(objv[idx]); if (name[0] != '-') { break; } - if (Tcl_GetIndexFromObj(interp, objv[idx], options, "option", + if (Tcl_GetIndexFromObj(interp, objv[idx], options, "switch", TCL_EXACT, &index) != TCL_OK) { goto optionError; } @@ -568,7 +525,7 @@ Tcl_RegsubObjCmd( endOfForLoop: if (objc-idx < 3 || objc-idx > 4) { Tcl_WrongNumArgs(interp, 1, objv, - "?-option ...? exp string subSpec ?varName?"); + "?switches? exp string subSpec ?varName?"); optionError: if (startIndex) { Tcl_DecrRefCount(startIndex); @@ -842,8 +799,9 @@ Tcl_RegsubObjCmd( Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset); } if (objc == 4) { - if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, - TCL_LEAVE_ERR_MSG) == NULL) { + if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, 0) == NULL) { + Tcl_AppendResult(interp, "couldn't set variable \"", + TclGetString(objv[3]), "\"", NULL); result = TCL_ERROR; } else { /* @@ -898,7 +856,7 @@ Tcl_RenameObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - const char *oldName, *newName; + char *oldName, *newName; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "oldName newName"); @@ -981,16 +939,6 @@ Tcl_SourceObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRSourceObjCmd, dummy, objc, objv); -} - -int -TclNRSourceObjCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ -{ const char *encodingName = NULL; Tcl_Obj *fileName; @@ -1002,7 +950,7 @@ TclNRSourceObjCmd( fileName = objv[objc-1]; if (objc == 4) { - static const char *const options[] = { + static const char *options[] = { "-encoding", NULL }; int index; @@ -1014,7 +962,7 @@ TclNRSourceObjCmd( encodingName = TclGetString(objv[2]); } - return TclNREvalFile(interp, fileName, encodingName); + return Tcl_FSEvalFileEx(interp, fileName, encodingName); } /* @@ -1043,9 +991,7 @@ Tcl_SplitObjCmd( { Tcl_UniChar ch; int len; - const char *splitChars; - const char *stringPtr; - const char *end; + char *splitChars, *stringPtr, *end; int splitCharLen, stringLen; Tcl_Obj *listPtr, *objPtr; @@ -1090,8 +1036,7 @@ Tcl_SplitObjCmd( * Assume Tcl_UniChar is an integral type... */ - hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR((int) ch), - &isNew); + hPtr = Tcl_CreateHashEntry(&charReuseTable, (char*)0+ch, &isNew); if (isNew) { TclNewStringObj(objPtr, stringPtr, len); @@ -1099,9 +1044,9 @@ Tcl_SplitObjCmd( * Don't need to fiddle with refcount... */ - Tcl_SetHashValue(hPtr, objPtr); + Tcl_SetHashValue(hPtr, (ClientData) objPtr); } else { - objPtr = Tcl_GetHashValue(hPtr); + objPtr = (Tcl_Obj *) Tcl_GetHashValue(hPtr); } Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } @@ -1124,7 +1069,7 @@ Tcl_SplitObjCmd( TclNewStringObj(objPtr, stringPtr, end - stringPtr); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } else { - const char *element, *p, *splitEnd; + char *element, *p, *splitEnd; int splitLen; Tcl_UniChar splitChar; @@ -1161,8 +1106,7 @@ Tcl_SplitObjCmd( * StringFirstCmd -- * * This procedure is invoked to process the "string first" 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. @@ -1180,8 +1124,8 @@ StringFirstCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar *needleStr, *haystackStr; - int match, start, needleLen, haystackLen; + Tcl_UniChar *ustring1, *ustring2; + int match, start, length1, length2; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, @@ -1190,15 +1134,15 @@ StringFirstCmd( } /* - * We are searching haystackStr for the sequence needleStr. + * We are searching string2 for the sequence string1. */ match = -1; start = 0; - haystackLen = -1; + length2 = -1; - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); + ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1); + ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2); if (objc == 4) { /* @@ -1206,8 +1150,7 @@ StringFirstCmd( * point in the string before we think about a match. */ - if (TclGetIntForIndexM(interp, objv[3], haystackLen-1, - &start) != TCL_OK){ + if (TclGetIntForIndexM(interp, objv[3], length2-1, &start) != TCL_OK){ return TCL_ERROR; } @@ -1215,14 +1158,14 @@ StringFirstCmd( * Reread to prevent shimmering problems. */ - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); + ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1); + ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2); - if (start >= haystackLen) { + if (start >= length2) { goto str_first_done; } else if (start > 0) { - haystackStr += start; - haystackLen -= start; + ustring2 += start; + length2 -= start; } else if (start < 0) { /* * Invalid start index mapped to string start; Bug #423581 @@ -1237,18 +1180,18 @@ StringFirstCmd( * cannot be contained in there so we can avoid searching. [Bug 2960021] */ - if (needleLen > 0 && needleLen <= haystackLen) { + if (length1 > 0 && length1 <= length2) { register Tcl_UniChar *p, *end; - end = haystackStr + haystackLen - needleLen + 1; - for (p = haystackStr; p < end; p++) { + end = ustring2 + length2 - length1 + 1; + for (p = ustring2; p < end; p++) { /* * Scan forward to find the first character. */ - if ((*p == *needleStr) && (TclUniCharNcmp(needleStr, p, - (unsigned long) needleLen) == 0)) { - match = p - haystackStr; + if ((*p == *ustring1) && (TclUniCharNcmp(ustring1, p, + (unsigned long) length1) == 0)) { + match = p - ustring2; break; } } @@ -1274,8 +1217,7 @@ StringFirstCmd( * StringLastCmd -- * * This procedure is invoked to process the "string last" 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. @@ -1293,8 +1235,8 @@ StringLastCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar *needleStr, *haystackStr, *p; - int match, start, needleLen, haystackLen; + Tcl_UniChar *ustring1, *ustring2, *p; + int match, start, length1, length2; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, @@ -1303,15 +1245,15 @@ StringLastCmd( } /* - * We are searching haystackString for the sequence needleString. + * We are searching string2 for the sequence string1. */ match = -1; start = 0; - haystackLen = -1; + length2 = -1; - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); + ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1); + ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2); if (objc == 4) { /* @@ -1319,8 +1261,7 @@ StringLastCmd( * range to that char index in the string */ - if (TclGetIntForIndexM(interp, objv[3], haystackLen-1, - &start) != TCL_OK){ + if (TclGetIntForIndexM(interp, objv[3], length2-1, &start) != TCL_OK){ return TCL_ERROR; } @@ -1328,18 +1269,18 @@ StringLastCmd( * Reread to prevent shimmering problems. */ - needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); - haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); + ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1); + ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2); if (start < 0) { goto str_last_done; - } else if (start < haystackLen) { - p = haystackStr + start + 1 - needleLen; + } else if (start < length2) { + p = ustring2 + start + 1 - length1; } else { - p = haystackStr + haystackLen - needleLen; + p = ustring2 + length2 - length1; } } else { - p = haystackStr + haystackLen - needleLen; + p = ustring2 + length2 - length1; } /* @@ -1347,15 +1288,15 @@ StringLastCmd( * cannot be contained in there so we can avoid searching. [Bug 2960021] */ - if (needleLen > 0 && needleLen <= haystackLen) { - for (; p >= haystackStr; p--) { + if (length1 > 0 && length1 <= length2) { + for (; p >= ustring2; p--) { /* * Scan backwards to find the first character. */ - if ((*p == *needleStr) && !memcmp(needleStr, p, - sizeof(Tcl_UniChar) * (size_t)needleLen)) { - match = p - haystackStr; + if ((*p == *ustring1) && !memcmp(ustring1, p, + sizeof(Tcl_UniChar) * (size_t)length1)) { + match = p - ustring2; break; } } @@ -1399,29 +1340,37 @@ StringIndexCmd( } /* - * Get the char length to calulate what 'end' means. + * If we have a ByteArray object, avoid indexing in the Utf string since + * the byte array contains one byte per character. Otherwise, use the + * Unicode string rep to get the index'th char. */ - length = Tcl_GetCharLength(objv[1]); - if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) { - return TCL_ERROR; - } - - if ((index >= 0) && (index < length)) { - Tcl_UniChar ch = Tcl_GetUniChar(objv[1], index); + if (TclIsPureByteArray(objv[1])) { + const unsigned char *string = + Tcl_GetByteArrayFromObj(objv[1], &length); + if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK){ + return TCL_ERROR; + } + string = Tcl_GetByteArrayFromObj(objv[1], &length); + if ((index >= 0) && (index < length)) { + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(string + index, 1)); + } + } else { /* - * If we have a ByteArray object, we're careful to generate a new - * bytearray for a result. + * Get Unicode char length to calulate what 'end' means. */ - if (TclIsPureByteArray(objv[1])) { - unsigned char uch = (unsigned char) ch; + length = Tcl_GetCharLength(objv[1]); - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(&uch, 1)); - } else { + if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK){ + return TCL_ERROR; + } + if ((index >= 0) && (index < length)) { char buf[TCL_UTF_MAX]; + Tcl_UniChar ch; + ch = Tcl_GetUniChar(objv[1], index); length = Tcl_UniCharToUtf(ch, buf); Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, length)); } @@ -1461,23 +1410,22 @@ StringIsCmd( Tcl_Obj *objPtr, *failVarObj = NULL; Tcl_WideInt w; - static const char *const isClasses[] = { + static const char *isClasses[] = { "alnum", "alpha", "ascii", "control", - "boolean", "digit", "double", "entier", - "false", "graph", "integer", "list", - "lower", "print", "punct", "space", - "true", "upper", "wideinteger", "wordchar", - "xdigit", NULL + "boolean", "digit", "double", "false", + "graph", "integer", "list", "lower", + "print", "punct", "space", "true", + "upper", "wideinteger", "wordchar", "xdigit", + NULL }; enum isClasses { - 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_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL, + STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, 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 }; - static const char *const isOptions[] = { + static const char *isOptions[] = { "-strict", "-failindex", NULL }; enum isOptions { @@ -1544,8 +1492,7 @@ StringIsCmd( case STR_IS_BOOL: case STR_IS_TRUE: case STR_IS_FALSE: - if ((objPtr->typePtr != &tclBooleanType) - && (TCL_OK != TclSetBooleanFromAny(NULL, objPtr))) { + if (TCL_OK != Tcl_ConvertToType(NULL, objPtr, &tclBooleanType)) { if (strict) { result = 0; } else { @@ -1569,7 +1516,7 @@ StringIsCmd( /* TODO */ if ((objPtr->typePtr == &tclDoubleType) || (objPtr->typePtr == &tclIntType) || -#ifndef TCL_WIDE_INT_IS_LONG +#ifndef NO_WIDE_TYPE (objPtr->typePtr == &tclWideIntType) || #endif (objPtr->typePtr == &tclBignumType)) { @@ -1592,6 +1539,7 @@ StringIsCmd( if (stop < end) { result = 0; TclFreeIntRep(objPtr); + objPtr->typePtr = NULL; } } break; @@ -1604,51 +1552,6 @@ StringIsCmd( break; } goto failedIntParse; - case STR_IS_ENTIER: - if ((objPtr->typePtr == &tclIntType) || -#ifndef TCL_WIDE_INT_IS_LONG - (objPtr->typePtr == &tclWideIntType) || -#endif - (objPtr->typePtr == &tclBignumType)) { - break; - } - string1 = TclGetStringFromObj(objPtr, &length1); - if (length1 == 0) { - if (strict) { - result = 0; - } - goto str_is_done; - } - end = string1 + length1; - if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, - (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) { - if (stop == end) { - /* - * Entire string parses as an integer. - */ - - break; - } else { - /* - * Some prefix parsed as an integer, but not the whole string, - * so return failure index as the point where parsing stopped. - * Clear out the internal rep, since keeping it would leave - * *objPtr in an inconsistent state. - */ - - result = 0; - failat = stop - string1; - TclFreeIntRep(objPtr); - } - } else { - /* - * No prefix is a valid integer. Fail at beginning. - */ - - result = 0; - failat = 0; - } - break; case STR_IS_WIDE: if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) { break; @@ -1693,6 +1596,7 @@ StringIsCmd( failat = stop - string1; TclFreeIntRep(objPtr); + objPtr->typePtr = NULL; } } else { /* @@ -1867,10 +1771,8 @@ StringMapCmd( strncmp(string, "-nocase", (size_t) length2) == 0) { nocase = 1; } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": must be -nocase", string)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", - string, NULL); + Tcl_AppendResult(interp, "bad option \"", string, + "\": must be -nocase", NULL); return TCL_ERROR; } } @@ -1907,7 +1809,8 @@ StringMapCmd( * adapt this code... */ - mapElemv = TclStackAlloc(interp, sizeof(Tcl_Obj *) * mapElemc); + mapElemv = (Tcl_Obj **) + TclStackAlloc(interp, sizeof(Tcl_Obj *) * mapElemc); Tcl_DictObjFirst(interp, objv[objc-2], &search, mapElemv+0, mapElemv+1, &done); for (i=2 ; i<mapElemc ; i+=2) { @@ -1933,8 +1836,6 @@ StringMapCmd( Tcl_SetObjResult(interp, Tcl_NewStringObj("char map list unbalanced", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "MAP", - "UNBALANCED", NULL); return TCL_ERROR; } } @@ -2018,10 +1919,12 @@ StringMapCmd( * case. */ - mapStrings = TclStackAlloc(interp, mapElemc*2*sizeof(Tcl_UniChar *)); - mapLens = TclStackAlloc(interp, mapElemc * 2 * sizeof(int)); + mapStrings = (Tcl_UniChar **) TclStackAlloc(interp, + mapElemc * 2 * sizeof(Tcl_UniChar *)); + mapLens = (int *) TclStackAlloc(interp, mapElemc * 2 * sizeof(int)); if (nocase) { - u2lc = TclStackAlloc(interp, mapElemc * sizeof(Tcl_UniChar)); + u2lc = (Tcl_UniChar *) TclStackAlloc(interp, + mapElemc * sizeof(Tcl_UniChar)); } for (index = 0; index < mapElemc; index++) { mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index], @@ -2134,10 +2037,8 @@ StringMatchCmd( strncmp(string, "-nocase", (size_t) length) == 0) { nocase = TCL_MATCH_NOCASE; } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": must be -nocase", string)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", - string, NULL); + Tcl_AppendResult(interp, "bad option \"", string, + "\": must be -nocase", NULL); return TCL_ERROR; } } @@ -2171,6 +2072,7 @@ StringRangeCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + const unsigned char *string; int length, first, last; if (objc != 4) { @@ -2179,11 +2081,22 @@ StringRangeCmd( } /* - * Get the length in actual characters; Then reduce it by one because - * 'end' refers to the last character, not one past it. + * If we have a ByteArray object, avoid indexing in the Utf string since + * the byte array contains one byte per character. Otherwise, use the + * Unicode string rep to get the range. */ - length = Tcl_GetCharLength(objv[1]) - 1; + if (TclIsPureByteArray(objv[1])) { + string = Tcl_GetByteArrayFromObj(objv[1], &length); + length--; + } else { + /* + * Get the length in actual characters. + */ + + string = NULL; + length = Tcl_GetCharLength(objv[1]) - 1; + } if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK || TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK) { @@ -2197,7 +2110,17 @@ StringRangeCmd( last = length; } if (last >= first) { - Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last)); + if (string != NULL) { + /* + * Reread the string to prevent shimmering nasties. + */ + + string = Tcl_GetByteArrayFromObj(objv[1], &length); + Tcl_SetObjResult(interp, + Tcl_NewByteArrayObj(string+first, last - first + 1)); + } else { + Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last)); + } } return TCL_OK; } @@ -2266,11 +2189,9 @@ StringReptCmd( * We need to keep 2 <= length2 <= INT_MAX. */ - if (count > INT_MAX/length1) { + 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); + "result exceeds max size for a Tcl value (%d bytes)", INT_MAX)); return TCL_ERROR; } length2 = length1 * count; @@ -2291,7 +2212,6 @@ StringReptCmd( 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++) { @@ -2569,7 +2489,7 @@ StringEqualCmd( * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ - const char *string1, *string2; + char *string1, *string2; int length1, length2, i, match, length, nocase = 0, reqlength = -1; typedef int (*strCmpFn_t)(const char *, const char *, unsigned int); strCmpFn_t strCmpFn; @@ -2590,16 +2510,13 @@ StringEqualCmd( if (i+1 >= objc-2) { goto str_cmp_args; } - i++; + ++i; if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { return TCL_ERROR; } } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": must be -nocase or -length", - string2)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", - string2, NULL); + Tcl_AppendResult(interp, "bad option \"", string2, + "\": must be -nocase or -length", NULL); return TCL_ERROR; } } @@ -2719,7 +2636,7 @@ StringCmpCmd( * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ - const char *string1, *string2; + char *string1, *string2; int length1, length2, i, match, length, nocase = 0, reqlength = -1; typedef int (*strCmpFn_t)(const char *, const char *, unsigned int); strCmpFn_t strCmpFn; @@ -2740,16 +2657,13 @@ StringCmpCmd( if (i+1 >= objc-2) { goto str_cmp_args; } - i++; + ++i; if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { return TCL_ERROR; } } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": must be -nocase or -length", - string2)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", - string2, NULL); + Tcl_AppendResult(interp, "bad option \"", string2, + "\": must be -nocase or -length", NULL); return TCL_ERROR; } } @@ -2838,59 +2752,6 @@ StringCmpCmd( /* *---------------------------------------------------------------------- * - * StringCatCmd -- - * - * This procedure is invoked to process the "string cat" Tcl command. - * See the user documentation for details on what it does. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * See the user documentation. - * - *---------------------------------------------------------------------- - */ - -static int -StringCatCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ -{ - int i; - Tcl_Obj *objResultPtr; - - if (objc < 2) { - /* - * If there are no args, the result is an empty object. - * Just leave the preset empty interp result. - */ - return TCL_OK; - } - if (objc == 2) { - /* - * Other trivial case, single arg, just return it. - */ - Tcl_SetObjResult(interp, objv[1]); - 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; -} - -/* - *---------------------------------------------------------------------- - * * StringBytesCmd -- * * This procedure is invoked to process the "string bytelength" Tcl @@ -2951,12 +2812,25 @@ StringLenCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + int length; + if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_GetCharLength(objv[1]))); + /* + * If we have a ByteArray object, avoid recomputing the string since the + * byte array contains one byte per character. Otherwise, use the Unicode + * string rep to calculate the length. + */ + + if (objv[1]->typePtr == &tclByteArrayType) { + (void) Tcl_GetByteArrayFromObj(objv[1], &length); + } else { + length = Tcl_GetCharLength(objv[1]); + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(length)); return TCL_OK; } @@ -2986,8 +2860,7 @@ StringLowerCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { int length1, length2; - const char *string1; - char *string2; + char *string1, *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); @@ -3071,8 +2944,7 @@ StringUpperCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { int length1, length2; - const char *string1; - char *string2; + char *string1, *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); @@ -3156,8 +3028,7 @@ StringTitleCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { int length1, length2; - const char *string1; - char *string2; + char *string1, *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); @@ -3246,8 +3117,8 @@ StringTrimCmd( if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); } else if (objc == 2) { - string2 = tclDefaultTrimSet; - length2 = strlen(tclDefaultTrimSet); + string2 = " \t\n\r"; + length2 = strlen(string2); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; @@ -3294,8 +3165,8 @@ StringTrimLCmd( if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); } else if (objc == 2) { - string2 = tclDefaultTrimSet; - length2 = strlen(tclDefaultTrimSet); + string2 = " \t\n\r"; + length2 = strlen(string2); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; @@ -3340,8 +3211,8 @@ StringTrimRCmd( if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); } else if (objc == 2) { - string2 = tclDefaultTrimSet; - length2 = strlen(tclDefaultTrimSet); + string2 = " \t\n\r"; + length2 = strlen(string2); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; @@ -3382,30 +3253,29 @@ TclInitStringCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap stringImplMap[] = { - {"bytelength", StringBytesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, - {"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}, - {"is", StringIsCmd, TclCompileStringIsCmd, NULL, NULL, 0}, - {"last", StringLastCmd, TclCompileStringLastCmd, NULL, NULL, 0}, - {"length", StringLenCmd, TclCompileStringLenCmd, NULL, NULL, 0}, - {"map", StringMapCmd, TclCompileStringMapCmd, NULL, NULL, 0}, - {"match", StringMatchCmd, TclCompileStringMatchCmd, NULL, NULL, 0}, - {"range", StringRangeCmd, TclCompileStringRangeCmd, NULL, NULL, 0}, - {"repeat", StringReptCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, - {"replace", StringRplcCmd, TclCompileStringReplaceCmd, NULL, NULL, 0}, - {"reverse", StringRevCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, - {"tolower", StringLowerCmd, TclCompileStringToLowerCmd, NULL, NULL, 0}, - {"toupper", StringUpperCmd, TclCompileStringToUpperCmd, NULL, NULL, 0}, - {"totitle", StringTitleCmd, TclCompileStringToTitleCmd, NULL, NULL, 0}, - {"trim", StringTrimCmd, TclCompileStringTrimCmd, NULL, NULL, 0}, - {"trimleft", StringTrimLCmd, TclCompileStringTrimLCmd, NULL, NULL, 0}, - {"trimright", StringTrimRCmd, TclCompileStringTrimRCmd, NULL, NULL, 0}, - {"wordend", StringEndCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, - {"wordstart", StringStartCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, - {NULL, NULL, NULL, NULL, NULL, 0} + {"bytelength", StringBytesCmd, NULL}, + {"compare", StringCmpCmd, TclCompileStringCmpCmd}, + {"equal", StringEqualCmd, TclCompileStringEqualCmd}, + {"first", StringFirstCmd, NULL}, + {"index", StringIndexCmd, TclCompileStringIndexCmd}, + {"is", StringIsCmd, NULL}, + {"last", StringLastCmd, NULL}, + {"length", StringLenCmd, TclCompileStringLenCmd}, + {"map", StringMapCmd, NULL}, + {"match", StringMatchCmd, TclCompileStringMatchCmd}, + {"range", StringRangeCmd, NULL}, + {"repeat", StringReptCmd, NULL}, + {"replace", StringRplcCmd, NULL}, + {"reverse", StringRevCmd, NULL}, + {"tolower", StringLowerCmd, NULL}, + {"toupper", StringUpperCmd, NULL}, + {"totitle", StringTitleCmd, NULL}, + {"trim", StringTrimCmd, NULL}, + {"trimleft", StringTrimLCmd, NULL}, + {"trimright", StringTrimRCmd, NULL}, + {"wordend", StringEndCmd, NULL}, + {"wordstart", StringStartCmd, NULL}, + {NULL, NULL, NULL} }; return TclMakeEnsemble(interp, "string", stringImplMap); @@ -3430,24 +3300,30 @@ TclInitStringCmd( */ int -TclSubstOptions( - Tcl_Interp *interp, - int numOpts, - Tcl_Obj *const opts[], - int *flagPtr) +Tcl_SubstObjCmd( + ClientData dummy, /* Not used. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - static const char *const substOptions[] = { + static const char *substOptions[] = { "-nobackslashes", "-nocommands", "-novariables", NULL }; - enum { + enum substOptions { SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS }; - int i, flags = TCL_SUBST_ALL; + Tcl_Obj *resultPtr; + int flags, i; + + /* + * Parse command-line options. + */ - for (i = 0; i < numOpts; i++) { + flags = TCL_SUBST_ALL; + for (i = 1; i < (objc-1); i++) { int optionIndex; - if (Tcl_GetIndexFromObj(interp, opts[i], substOptions, "option", 0, + if (Tcl_GetIndexFromObj(interp, objv[i], substOptions, "switch", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } @@ -3465,39 +3341,23 @@ TclSubstOptions( Tcl_Panic("Tcl_SubstObjCmd: bad option index to SubstOptions"); } } - *flagPtr = flags; - return TCL_OK; -} - -int -Tcl_SubstObjCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ -{ - return Tcl_NRCallObjProc(interp, TclNRSubstObjCmd, dummy, objc, objv); -} - -int -TclNRSubstObjCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ -{ - int flags; - - if (objc < 2) { + if (i != objc-1) { Tcl_WrongNumArgs(interp, 1, objv, "?-nobackslashes? ?-nocommands? ?-novariables? string"); return TCL_ERROR; } - if (TclSubstOptions(interp, objc-2, objv+1, &flags) != TCL_OK) { + /* + * Perform the substitution. + */ + + resultPtr = Tcl_SubstObj(interp, objv[i], flags); + + if (resultPtr == NULL) { return TCL_ERROR; } - return Tcl_NRSubstObj(interp, objv[objc-1], flags); + Tcl_SetObjResult(interp, resultPtr); + return TCL_OK; } /* @@ -3524,18 +3384,9 @@ Tcl_SwitchObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRSwitchObjCmd, dummy, objc, objv); -} -int -TclNRSwitchObjCmd( - ClientData dummy, /* Not used. */ - 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 i,j, index, mode, foundmode, result, splitObjs, numMatchesSaved; int noCase, patternLength; - const char *pattern; + char *pattern; Tcl_Obj *stringObj, *indexVarObj, *matchVarObj; Tcl_Obj *const *savedObjv = objv; Tcl_RegExp regExpr = NULL; @@ -3551,7 +3402,7 @@ TclNRSwitchObjCmd( * -glob, you *must* fix TclCompileSwitchCmd's option parser as well. */ - static const char *const options[] = { + static const char *options[] = { "-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp", "--", NULL }; @@ -3599,16 +3450,15 @@ TclNRSwitchObjCmd( * Mode already set via -exact, -glob, or -regexp. */ - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": %s option already found", - TclGetString(objv[i]), options[mode])); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "DOUBLEOPT", NULL); + Tcl_AppendResult(interp, "bad option \"", + TclGetString(objv[i]), "\": ", options[mode], + " option already found", NULL); return TCL_ERROR; + } else { + foundmode = 1; + mode = index; + break; } - foundmode = 1; - mode = index; - break; /* * Check for TIP#75 options specifying the variables to write @@ -3618,11 +3468,8 @@ TclNRSwitchObjCmd( case OPT_INDEXV: i++; if (i >= objc-2) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "missing variable name argument to %s option", - "-indexvar")); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "NOVAR", NULL); + Tcl_AppendResult(interp, "missing variable name argument to ", + "-indexvar", " option", NULL); return TCL_ERROR; } indexVarObj = objv[i]; @@ -3631,11 +3478,8 @@ TclNRSwitchObjCmd( case OPT_MATCHV: i++; if (i >= objc-2) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "missing variable name argument to %s option", - "-matchvar")); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "NOVAR", NULL); + Tcl_AppendResult(interp, "missing variable name argument to ", + "-matchvar", " option", NULL); return TCL_ERROR; } matchVarObj = objv[i]; @@ -3647,21 +3491,17 @@ TclNRSwitchObjCmd( finishedOptions: if (objc - i < 2) { Tcl_WrongNumArgs(interp, 1, objv, - "?-option ...? string ?pattern body ...? ?default body?"); + "?switches? string pattern body ... ?default body?"); return TCL_ERROR; } if (indexVarObj != NULL && mode != OPT_REGEXP) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%s option requires -regexp option", "-indexvar")); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "MODERESTRICTION", NULL); + Tcl_AppendResult(interp, + "-indexvar option requires -regexp option", NULL); return TCL_ERROR; } if (matchVarObj != NULL && mode != OPT_REGEXP) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%s option requires -regexp option", "-matchvar")); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "MODERESTRICTION", NULL); + Tcl_AppendResult(interp, + "-matchvar option requires -regexp option", NULL); return TCL_ERROR; } @@ -3682,8 +3522,8 @@ TclNRSwitchObjCmd( splitObjs = 0; if (objc == 1) { Tcl_Obj **listv; - blist = objv[0]; + if (TclListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK){ return TCL_ERROR; } @@ -3694,7 +3534,7 @@ TclNRSwitchObjCmd( if (objc < 1) { Tcl_WrongNumArgs(interp, 1, savedObjv, - "?-option ...? string {?pattern body ...? ?default body?}"); + "?switches? string {pattern body ... ?default body?}"); return TCL_ERROR; } objv = listv; @@ -3708,10 +3548,7 @@ TclNRSwitchObjCmd( if (objc % 2) { Tcl_ResetResult(interp); - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "extra switch pattern with no body", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "BADARM", - NULL); + Tcl_AppendResult(interp, "extra switch pattern with no body", NULL); /* * Check if this can be due to a badly placed comment in the switch @@ -3724,12 +3561,10 @@ TclNRSwitchObjCmd( if (splitObjs) { for (i=0 ; i<objc ; i+=2) { if (TclGetString(objv[i])[0] == '#') { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - ", this may be due to a comment incorrectly" - " placed outside of a switch body - see the" - " \"switch\" documentation", -1); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "BADARM", "COMMENT?", NULL); + Tcl_AppendResult(interp, ", this may be due to a " + "comment incorrectly placed outside of a " + "switch body - see the \"switch\" " + "documentation", NULL); break; } } @@ -3744,11 +3579,9 @@ TclNRSwitchObjCmd( */ if (strcmp(TclGetString(objv[objc-1]), "-") == 0) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "no body specified for pattern \"%s\"", - TclGetString(objv[objc-2]))); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "BADARM", - "FALLTHROUGH", NULL); + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "no body specified for pattern \"", + TclGetString(objv[objc-2]), "\"", NULL); return TCL_ERROR; } @@ -3787,35 +3620,36 @@ TclNRSwitchObjCmd( } } goto matchFound; - } - - switch (mode) { - case OPT_EXACT: - if (strCmpFn(TclGetString(stringObj), pattern) == 0) { - goto matchFound; - } - break; - case OPT_GLOB: - if (Tcl_StringCaseMatch(TclGetString(stringObj),pattern,noCase)) { - goto matchFound; - } - break; - case OPT_REGEXP: - regExpr = Tcl_GetRegExpFromObj(interp, objv[i], - TCL_REG_ADVANCED | (noCase ? TCL_REG_NOCASE : 0)); - if (regExpr == NULL) { - return TCL_ERROR; - } else { - int matched = Tcl_RegExpExecObj(interp, regExpr, stringObj, 0, - numMatchesSaved, 0); - - if (matched < 0) { + } else { + switch (mode) { + case OPT_EXACT: + if (strCmpFn(TclGetString(stringObj), pattern) == 0) { + goto matchFound; + } + break; + case OPT_GLOB: + if (Tcl_StringCaseMatch(TclGetString(stringObj), pattern, + noCase)) { + goto matchFound; + } + break; + case OPT_REGEXP: + regExpr = Tcl_GetRegExpFromObj(interp, objv[i], + TCL_REG_ADVANCED | (noCase ? TCL_REG_NOCASE : 0)); + if (regExpr == NULL) { return TCL_ERROR; - } else if (matched) { - goto matchFoundRegexp; + } else { + int matched = Tcl_RegExpExecObj(interp, regExpr, + stringObj, 0, numMatchesSaved, 0); + + if (matched < 0) { + return TCL_ERROR; + } else if (matched) { + goto matchFoundRegexp; + } } + break; } - break; } } return TCL_OK; @@ -3911,7 +3745,7 @@ TclNRSwitchObjCmd( */ matchFound: - ctxPtr = TclStackAlloc(interp, sizeof(CmdFrame)); + ctxPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame)); *ctxPtr = *iPtr->cmdFramePtr; if (splitObjs) { @@ -3926,7 +3760,7 @@ TclNRSwitchObjCmd( if (ctxPtr->type == TCL_LOCATION_BC) { /* * Type BC => ctxPtr->data.eval.path is not used. - * ctxPtr->data.tebc.codePtr is used instead. + * ctxPtr->data.tebc.codePtr is used instead. */ TclGetSrcInfoForPc(ctxPtr); @@ -3941,7 +3775,7 @@ TclNRSwitchObjCmd( if (ctxPtr->type == TCL_LOCATION_SOURCE && ctxPtr->line[bidx] >= 0) { int bline = ctxPtr->line[bidx]; - ctxPtr->line = ckalloc(objc * sizeof(int)); + ctxPtr->line = (int *) ckalloc(objc * sizeof(int)); ctxPtr->nline = objc; TclListLines(blist, bline, objc, ctxPtr->line, objv); } else { @@ -3955,7 +3789,7 @@ TclNRSwitchObjCmd( int k; - ctxPtr->line = ckalloc(objc * sizeof(int)); + ctxPtr->line = (int *) ckalloc(objc * sizeof(int)); ctxPtr->nline = objc; for (k=0; k < objc; k++) { ctxPtr->line[k] = -1; @@ -3981,31 +3815,9 @@ TclNRSwitchObjCmd( * TIP #280: Make invoking context available to switch branch. */ - Tcl_NRAddCallback(interp, SwitchPostProc, INT2PTR(splitObjs), ctxPtr, - INT2PTR(pc), (ClientData) pattern); - return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j); -} - -static int -SwitchPostProc( - ClientData data[], /* Data passed from Tcl_NRAddCallback above */ - Tcl_Interp *interp, /* Tcl interpreter */ - int result) /* Result to return*/ -{ - /* Unpack the preserved data */ - - int splitObjs = PTR2INT(data[0]); - CmdFrame *ctxPtr = data[1]; - int pc = PTR2INT(data[2]); - const char *pattern = data[3]; - int patternLength = strlen(pattern); - - /* - * Clean up TIP 280 context information - */ - + result = TclEvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j); if (splitObjs) { - ckfree(ctxPtr->line); + ckfree((char *) ctxPtr->line); if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) { /* * Death of SrcInfo reference. @@ -4026,7 +3838,7 @@ SwitchPostProc( Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s%s\" arm line %d)", (overflow ? limit : patternLength), pattern, - (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); + (overflow ? "..." : ""), interp->errorLine)); } TclStackFree(interp, ctxPtr); return result; @@ -4035,69 +3847,6 @@ SwitchPostProc( /* *---------------------------------------------------------------------- * - * Tcl_ThrowObjCmd -- - * - * This procedure is invoked to process the "throw" Tcl command. See the - * user documentation for details on what it does. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * See the user documentation. - * - *---------------------------------------------------------------------- - */ - - /* ARGSUSED */ -int -Tcl_ThrowObjCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ -{ - Tcl_Obj *options; - int len; - - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "type message"); - return TCL_ERROR; - } - - /* - * The type must be a list of at least length 1. - */ - - if (Tcl_ListObjLength(interp, objv[1], &len) != TCL_OK) { - return TCL_ERROR; - } else if (len < 1) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "type must be non-empty list", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "THROW", "BADEXCEPTION", - NULL); - return TCL_ERROR; - } - - /* - * Now prepare the result options dictionary. We use the list API as it is - * slightly more convenient. - */ - - TclNewLiteralStringObj(options, "-code error -level 0 -errorcode"); - Tcl_ListObjAppendElement(NULL, options, objv[1]); - - /* - * We're ready to go. Fire things into the low-level result machinery. - */ - - Tcl_SetObjResult(interp, objv[2]); - return Tcl_SetReturnOptions(interp, options); -} - -/* - *---------------------------------------------------------------------- - * * Tcl_TimeObjCmd -- * * This object-based procedure is invoked to process the "time" Tcl @@ -4190,578 +3939,6 @@ Tcl_TimeObjCmd( /* *---------------------------------------------------------------------- * - * Tcl_TryObjCmd, TclNRTryObjCmd -- - * - * This procedure is invoked to process the "try" Tcl command. See the - * user documentation (or TIP #329) for details on what it does. - * - * Results: - * A standard Tcl object result. - * - * Side effects: - * See the user documentation. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_TryObjCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ -{ - return Tcl_NRCallObjProc(interp, TclNRTryObjCmd, dummy, objc, objv); -} - -int -TclNRTryObjCmd( - ClientData clientData, /* Not used. */ - 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; - static const char *const handlerNames[] = { - "finally", "on", "trap", NULL - }; - enum Handlers { - TryFinally, TryOn, TryTrap - }; - - /* - * Parse the arguments. The handlers are passed to subsequent callbacks as - * a Tcl_Obj list of the 5-tuples like (type, returnCode, errorCodePrefix, - * bindVariables, script), and the finally script is just passed as it is. - */ - - if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, - "body ?handler ...? ?finally script?"); - return TCL_ERROR; - } - bodyObj = objv[1]; - handlersObj = Tcl_NewObj(); - bodyShared = 0; - haveHandlers = 0; - for (i=2 ; i<objc ; i++) { - int type; - Tcl_Obj *info[5]; - - if (Tcl_GetIndexFromObj(interp, objv[i], handlerNames, "handler type", - 0, &type) != TCL_OK) { - Tcl_DecrRefCount(handlersObj); - return TCL_ERROR; - } - switch ((enum Handlers) type) { - case TryFinally: /* finally script */ - if (i < objc-2) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "finally clause must be last", -1)); - Tcl_DecrRefCount(handlersObj); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "FINALLY", - "NONTERMINAL", NULL); - return TCL_ERROR; - } else if (i == objc-1) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "wrong # args to finally clause: must be" - " \"... finally script\"", -1)); - Tcl_DecrRefCount(handlersObj); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "FINALLY", - "ARGUMENT", NULL); - return TCL_ERROR; - } - finallyObj = objv[++i]; - break; - - case TryOn: /* on code variableList script */ - if (i > objc-4) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "wrong # args to on clause: must be \"... on code" - " variableList script\"", -1)); - Tcl_DecrRefCount(handlersObj); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "ON", - "ARGUMENT", NULL); - return TCL_ERROR; - } - if (TclGetCompletionCodeFromObj(interp, objv[i+1], - &code) != TCL_OK) { - Tcl_DecrRefCount(handlersObj); - return TCL_ERROR; - } - info[2] = NULL; - goto commonHandler; - - case TryTrap: /* trap pattern variableList script */ - if (i > objc-4) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "wrong # args to trap clause: " - "must be \"... trap pattern variableList script\"", - -1)); - Tcl_DecrRefCount(handlersObj); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "TRAP", - "ARGUMENT", NULL); - return TCL_ERROR; - } - code = 1; - if (Tcl_ListObjLength(NULL, objv[i+1], &dummy) != TCL_OK) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad prefix '%s': must be a list", - Tcl_GetString(objv[i+1]))); - Tcl_DecrRefCount(handlersObj); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "TRAP", - "EXNFORMAT", NULL); - return TCL_ERROR; - } - info[2] = objv[i+1]; - - commonHandler: - if (Tcl_ListObjLength(interp, objv[i+2], &dummy) != TCL_OK) { - Tcl_DecrRefCount(handlersObj); - return TCL_ERROR; - } - - info[0] = objv[i]; /* type */ - TclNewIntObj(info[1], code); /* returnCode */ - if (info[2] == NULL) { /* errorCodePrefix */ - TclNewObj(info[2]); - } - info[3] = objv[i+2]; /* bindVariables */ - info[4] = objv[i+3]; /* script */ - - bodyShared = !strcmp(TclGetString(objv[i+3]), "-"); - Tcl_ListObjAppendElement(NULL, handlersObj, - Tcl_NewListObj(5, info)); - haveHandlers = 1; - i += 3; - break; - } - } - if (bodyShared) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "last non-finally clause must not have a body of \"-\"", -1)); - Tcl_DecrRefCount(handlersObj); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "BADFALLTHROUGH", - NULL); - return TCL_ERROR; - } - if (!haveHandlers) { - Tcl_DecrRefCount(handlersObj); - handlersObj = NULL; - } - - /* - * Execute the body. - */ - - Tcl_NRAddCallback(interp, TryPostBody, handlersObj, finallyObj, - (ClientData)objv, INT2PTR(objc)); - return TclNREvalObjEx(interp, bodyObj, 0, - ((Interp *) interp)->cmdFramePtr, 1); -} - -/* - *---------------------------------------------------------------------- - * - * During -- - * - * This helper function patches together the updates to the interpreter's - * return options that are needed when things fail during the processing - * of a handler or finally script for the [try] command. - * - * Returns: - * The new option dictionary. - * - *---------------------------------------------------------------------- - */ - -static inline Tcl_Obj * -During( - Tcl_Interp *interp, - int resultCode, /* The result code from the just-evaluated - * script. */ - Tcl_Obj *oldOptions, /* The old option dictionary. */ - Tcl_Obj *errorInfo) /* An object to append to the errorinfo and - * release, or NULL if nothing is to be added. - * Designed to be used with Tcl_ObjPrintf. */ -{ - Tcl_Obj *during, *options; - - if (errorInfo != NULL) { - Tcl_AppendObjToErrorInfo(interp, errorInfo); - } - options = Tcl_GetReturnOptions(interp, resultCode); - TclNewLiteralStringObj(during, "-during"); - Tcl_IncrRefCount(during); - Tcl_DictObjPut(interp, options, during, oldOptions); - Tcl_DecrRefCount(during); - Tcl_IncrRefCount(options); - Tcl_DecrRefCount(oldOptions); - return options; -} - -/* - *---------------------------------------------------------------------- - * - * TryPostBody -- - * - * Callback to handle the outcome of the execution of the body of a 'try' - * command. - * - *---------------------------------------------------------------------- - */ - -static int -TryPostBody( - ClientData data[], - Tcl_Interp *interp, - int result) -{ - Tcl_Obj *resultObj, *options, *handlersObj, *finallyObj, *cmdObj, **objv; - int i, dummy, code, objc; - int numHandlers = 0; - - handlersObj = data[0]; - finallyObj = data[1]; - objv = data[2]; - objc = PTR2INT(data[3]); - - cmdObj = objv[0]; - - /* - * Check for limits/rewinding, which override normal trapping behaviour. - */ - - if (((Interp*) interp)->execEnvPtr->rewind || Tcl_LimitExceeded(interp)) { - Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( - "\n (\"%s\" body line %d)", TclGetString(cmdObj), - Tcl_GetErrorLine(interp))); - if (handlersObj != NULL) { - Tcl_DecrRefCount(handlersObj); - } - return TCL_ERROR; - } - - /* - * Basic processing of the outcome of the script, including adding of - * errorinfo trace. - */ - - if (result == TCL_ERROR) { - Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( - "\n (\"%s\" body line %d)", TclGetString(cmdObj), - Tcl_GetErrorLine(interp))); - } - resultObj = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(resultObj); - options = Tcl_GetReturnOptions(interp, result); - Tcl_IncrRefCount(options); - Tcl_ResetResult(interp); - - /* - * Handle the results. - */ - - if (handlersObj != NULL) { - int found = 0; - Tcl_Obj **handlers, **info; - - Tcl_ListObjGetElements(NULL, handlersObj, &numHandlers, &handlers); - for (i=0 ; i<numHandlers ; i++) { - Tcl_Obj *handlerBodyObj; - - Tcl_ListObjGetElements(NULL, handlers[i], &dummy, &info); - if (!found) { - Tcl_GetIntFromObj(NULL, info[1], &code); - if (code != result) { - continue; - } - - /* - * When processing an error, we must also perform list-prefix - * matching of the errorcode list. However, if this was an - * 'on' handler, the list that we are matching against will be - * empty. - */ - - if (code == TCL_ERROR) { - Tcl_Obj *errorCodeName, *errcode, **bits1, **bits2; - int len1, len2, j; - - TclNewLiteralStringObj(errorCodeName, "-errorcode"); - Tcl_DictObjGet(NULL, options, errorCodeName, &errcode); - Tcl_DecrRefCount(errorCodeName); - Tcl_ListObjGetElements(NULL, info[2], &len1, &bits1); - if (Tcl_ListObjGetElements(NULL, errcode, &len2, - &bits2) != TCL_OK) { - continue; - } - if (len2 < len1) { - continue; - } - for (j=0 ; j<len1 ; j++) { - if (strcmp(TclGetString(bits1[j]), - TclGetString(bits2[j])) != 0) { - /* - * Really want 'continue outerloop;', but C does - * not give us that. - */ - - goto didNotMatch; - } - } - } - - found = 1; - } - - /* - * Now we need to scan forward over "-" bodies. Note that we've - * already checked that the last body is not a "-", so this search - * will terminate successfully. - */ - - if (!strcmp(TclGetString(info[4]), "-")) { - continue; - } - - /* - * Bind the variables. We already know this is a list of variable - * names, but it might be empty. - */ - - Tcl_ResetResult(interp); - result = TCL_ERROR; - Tcl_ListObjLength(NULL, info[3], &dummy); - if (dummy > 0) { - Tcl_Obj *varName; - - Tcl_ListObjIndex(NULL, info[3], 0, &varName); - if (Tcl_ObjSetVar2(interp, varName, NULL, resultObj, - TCL_LEAVE_ERR_MSG) == NULL) { - Tcl_DecrRefCount(resultObj); - goto handlerFailed; - } - Tcl_DecrRefCount(resultObj); - if (dummy > 1) { - Tcl_ListObjIndex(NULL, info[3], 1, &varName); - if (Tcl_ObjSetVar2(interp, varName, NULL, options, - TCL_LEAVE_ERR_MSG) == NULL) { - goto handlerFailed; - } - } - } else { - /* - * Dispose of the result to prevent a memleak. [Bug 2910044] - */ - - Tcl_DecrRefCount(resultObj); - } - - /* - * Evaluate the handler body and process the outcome. Note that we - * need to keep the kind of handler for debugging purposes, and in - * any case anything we want from info[] must be extracted right - * now because the info[] array is about to become invalid. There - * is very little refcount handling here however, since we know - * that the objects that we still want to refer to now were input - * arguments to [try] and so are still on the Tcl value stack. - */ - - handlerBodyObj = info[4]; - Tcl_NRAddCallback(interp, TryPostHandler, objv, options, info[0], - INT2PTR((finallyObj == NULL) ? 0 : objc - 1)); - Tcl_DecrRefCount(handlersObj); - return TclNREvalObjEx(interp, handlerBodyObj, 0, - ((Interp *) interp)->cmdFramePtr, 4*i + 5); - - handlerFailed: - resultObj = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(resultObj); - options = During(interp, result, options, NULL); - break; - - didNotMatch: - continue; - } - - /* - * No handler matched; get rid of the list of handlers. - */ - - Tcl_DecrRefCount(handlersObj); - } - - /* - * Process the finally clause. - */ - - if (finallyObj != NULL) { - Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj, - NULL); - return TclNREvalObjEx(interp, finallyObj, 0, - ((Interp *) interp)->cmdFramePtr, objc - 1); - } - - /* - * Install the correct result/options into the interpreter and clean up - * any temporary storage. - */ - - result = Tcl_SetReturnOptions(interp, options); - Tcl_DecrRefCount(options); - Tcl_SetObjResult(interp, resultObj); - Tcl_DecrRefCount(resultObj); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TryPostHandler -- - * - * Callback to handle the outcome of the execution of a handler of a - * 'try' command. - * - *---------------------------------------------------------------------- - */ - -static int -TryPostHandler( - ClientData data[], - Tcl_Interp *interp, - int result) -{ - Tcl_Obj *resultObj, *cmdObj, *options, *handlerKindObj, **objv; - Tcl_Obj *finallyObj; - int finally; - - objv = data[0]; - options = data[1]; - handlerKindObj = data[2]; - finally = PTR2INT(data[3]); - - cmdObj = objv[0]; - finallyObj = finally ? objv[finally] : 0; - - /* - * Check for limits/rewinding, which override normal trapping behaviour. - */ - - if (((Interp*) interp)->execEnvPtr->rewind || Tcl_LimitExceeded(interp)) { - options = During(interp, result, options, Tcl_ObjPrintf( - "\n (\"%s ... %s\" handler line %d)", - TclGetString(cmdObj), TclGetString(handlerKindObj), - Tcl_GetErrorLine(interp))); - Tcl_DecrRefCount(options); - return TCL_ERROR; - } - - /* - * The handler result completely substitutes for the result of the body. - */ - - resultObj = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(resultObj); - if (result == TCL_ERROR) { - options = During(interp, result, options, Tcl_ObjPrintf( - "\n (\"%s ... %s\" handler line %d)", - TclGetString(cmdObj), TclGetString(handlerKindObj), - Tcl_GetErrorLine(interp))); - } else { - Tcl_DecrRefCount(options); - options = Tcl_GetReturnOptions(interp, result); - Tcl_IncrRefCount(options); - } - - /* - * Process the finally clause if it is present. - */ - - if (finallyObj != NULL) { - Interp *iPtr = (Interp *) interp; - - Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj, - NULL); - - /* The 'finally' script is always the last argument word. */ - return TclNREvalObjEx(interp, finallyObj, 0, iPtr->cmdFramePtr, - finally); - } - - /* - * Install the correct result/options into the interpreter and clean up - * any temporary storage. - */ - - result = Tcl_SetReturnOptions(interp, options); - Tcl_DecrRefCount(options); - Tcl_SetObjResult(interp, resultObj); - Tcl_DecrRefCount(resultObj); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TryPostFinal -- - * - * Callback to handle the outcome of the execution of the finally script - * of a 'try' command. - * - *---------------------------------------------------------------------- - */ - -static int -TryPostFinal( - ClientData data[], - Tcl_Interp *interp, - int result) -{ - Tcl_Obj *resultObj, *options, *cmdObj; - - resultObj = data[0]; - options = data[1]; - cmdObj = data[2]; - - /* - * If the result wasn't OK, we need to adjust the result options. - */ - - if (result != TCL_OK) { - Tcl_DecrRefCount(resultObj); - resultObj = NULL; - if (result == TCL_ERROR) { - options = During(interp, result, options, Tcl_ObjPrintf( - "\n (\"%s ... finally\" body line %d)", - TclGetString(cmdObj), Tcl_GetErrorLine(interp))); - } else { - Tcl_Obj *origOptions = options; - - options = Tcl_GetReturnOptions(interp, result); - Tcl_IncrRefCount(options); - Tcl_DecrRefCount(origOptions); - } - } - - /* - * Install the correct result/options into the interpreter and clean up - * any temporary storage. - */ - - result = Tcl_SetReturnOptions(interp, options); - Tcl_DecrRefCount(options); - if (resultObj != NULL) { - Tcl_SetObjResult(interp, resultObj); - Tcl_DecrRefCount(resultObj); - } - return result; -} - -/* - *---------------------------------------------------------------------- - * * Tcl_WhileObjCmd -- * * This procedure is invoked to process the "while" Tcl command. See the @@ -4787,37 +3964,40 @@ Tcl_WhileObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - return Tcl_NRCallObjProc(interp, TclNRWhileObjCmd, dummy, objc, objv); -} - -int -TclNRWhileObjCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ -{ - ForIterData *iterPtr; + int result, value; + Interp *iPtr = (Interp *) interp; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "test command"); return TCL_ERROR; } - /* - * We reuse [for]'s callback, passing a NULL for the 'next' script. - */ - - TclSmallAllocEx(interp, sizeof(ForIterData), iterPtr); - iterPtr->cond = objv[1]; - iterPtr->body = objv[2]; - iterPtr->next = NULL; - iterPtr->msg = "\n (\"while\" body line %d)"; - iterPtr->word = 2; + while (1) { + result = Tcl_ExprBooleanObj(interp, objv[1], &value); + if (result != TCL_OK) { + return result; + } + if (!value) { + break; + } - TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, - NULL, NULL); - return TCL_OK; + /* TIP #280. */ + result = TclEvalObjEx(interp, objv[2], 0, iPtr->cmdFramePtr, 2); + if ((result != TCL_OK) && (result != TCL_CONTINUE)) { + if (result == TCL_ERROR) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"while\" body line %d)", interp->errorLine)); + } + break; + } + } + if (result == TCL_BREAK) { + result = TCL_OK; + } + if (result == TCL_OK) { + Tcl_ResetResult(interp); + } + return result; } /* @@ -4838,30 +4018,32 @@ TclNRWhileObjCmd( void TclListLines( - Tcl_Obj *listObj, /* Pointer to obj holding a string with list - * structure. Assumed to be valid. Assumed to - * contain n elements. */ + 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_Obj *const *elems) /* The list elems as Tcl_Obj*, in need of + Tcl_Obj* const* elems) /* The list elems as Tcl_Obj*, in need of * derived continuation data */ { - const char *listStr = Tcl_GetString(listObj); - const char *listHead = listStr; + const char* listStr = Tcl_GetString (listObj); + const char* listHead = listStr; int i, length = strlen(listStr); const char *element = NULL, *next = NULL; - ContLineLoc *clLocPtr = TclContinuationsGet(listObj); - int *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL); + ContLineLoc* clLocPtr = TclContinuationsGet(listObj); + int* clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL); for (i = 0; i < n; i++) { TclFindElement(NULL, listStr, length, &element, &next, NULL, NULL); TclAdvanceLines(&line, listStr, element); /* Leading whitespace */ - TclAdvanceContinuations(&line, &clNext, element - listHead); + TclAdvanceContinuations (&line, &clNext, element - listHead); if (elems && clNext) { - TclContinuationsEnterDerived(elems[i], element-listHead, clNext); + TclContinuationsEnterDerived (elems[i], element - listHead, + clNext); } lines[i] = line; length -= (next - listStr); |