diff options
author | andy <andrew.m.goth@gmail.com> | 2016-12-02 21:00:11 (GMT) |
---|---|---|
committer | andy <andrew.m.goth@gmail.com> | 2016-12-02 21:00:11 (GMT) |
commit | 5b0d69d46310f6ce08f6ae7038745b0db0830664 (patch) | |
tree | ae8a6d8a645dca92f73d3795b322dd5bd37d72ff | |
parent | abcff616bd61f0d6174da259be06f1f1b767694d (diff) | |
parent | c9bee15d7360f859a1916da19733e2595caad00b (diff) | |
download | tcl-5b0d69d46310f6ce08f6ae7038745b0db0830664.zip tcl-5b0d69d46310f6ce08f6ae7038745b0db0830664.tar.gz tcl-5b0d69d46310f6ce08f6ae7038745b0db0830664.tar.bz2 |
Merge trunk
-rw-r--r-- | ChangeLog.2000 | 2 | ||||
-rw-r--r-- | ChangeLog.2002 | 6 | ||||
-rw-r--r-- | ChangeLog.2003 | 4 | ||||
-rw-r--r-- | ChangeLog.2004 | 2 | ||||
-rw-r--r-- | generic/tcl.h | 4 | ||||
-rw-r--r-- | generic/tclBasic.c | 22 | ||||
-rw-r--r-- | generic/tclBinary.c | 174 | ||||
-rw-r--r-- | generic/tclCmdMZ.c | 65 | ||||
-rw-r--r-- | generic/tclIO.c | 2 | ||||
-rw-r--r-- | generic/tclInt.h | 5 | ||||
-rw-r--r-- | generic/tclStringObj.c | 158 | ||||
-rw-r--r-- | generic/tclStringRep.h | 10 | ||||
-rw-r--r-- | generic/tclVar.c | 2 | ||||
-rw-r--r-- | library/http/http.tcl | 2 | ||||
-rw-r--r-- | unix/tcl.m4 | 2 | ||||
-rw-r--r-- | win/makefile.vc | 4 |
16 files changed, 324 insertions, 140 deletions
diff --git a/ChangeLog.2000 b/ChangeLog.2000 index 0d20eaf..5b62351 100644 --- a/ChangeLog.2000 +++ b/ChangeLog.2000 @@ -414,7 +414,7 @@ Tcl_IsChannelExisting, and Tcl_ClearChannelHandlers to conform to the new stacked channel implementation. Their stub slots were also moved to give preference to the new 8.3.2 stub functions. This will cause an - incompatability with 8.4a1 only. + incompatibility with 8.4a1 only. (StopCopy): fixed a bug introduced by a partial fix in 8.3.2 that didn't set nonBlocking correctly when resetting the flags for the write side. [Bug: 6261] diff --git a/ChangeLog.2002 b/ChangeLog.2002 index 30b8b17..9931657 100644 --- a/ChangeLog.2002 +++ b/ChangeLog.2002 @@ -847,7 +847,7 @@ exit. * tests/exec.test: marked exec-18.1 unixOnly until the Windows - incompatability (in the test, not the core) can be resolved. + incompatibility (in the test, not the core) can be resolved. * tests/http.test (http-3.11): added close $fp that was causing an error on Windows because the file was not closed before deleting. @@ -3642,7 +3642,7 @@ * compat/strtoll.c (strtoll): * compat/strtoull.c (strtoull): * unix/tclUnixPort.h: - * win/tclWinPort.h: Const-ing 64-bit compatability declarations. Note + * win/tclWinPort.h: Const-ing 64-bit compatibility declarations. Note that the return pointer is non-const because it is entirely legal for the functions to be called from somewhere that owns the string being passed. Fixes problem reported by Larry Virden. @@ -3779,7 +3779,7 @@ There are a lot of changes from this TIP, so please see http://purl.org/tcl/tip/72.html for discussion of - backward-compatability issues, but the main ones modifications are in: + backward-compatibility issues, but the main ones modifications are in: * generic/tcl.h: New types. * generic/tcl.decls: New public functions. diff --git a/ChangeLog.2003 b/ChangeLog.2003 index c586ba9..3c3ee11 100644 --- a/ChangeLog.2003 +++ b/ChangeLog.2003 @@ -947,7 +947,7 @@ declarations match and will end up using the declarations in the public code from now on because of #include ordering. Keeping the old declarations in tclInt.decls; there's no need to gratuitously break - compatability for those extensions which are already clients of the + compatibility for those extensions which are already clients of the namespace code. 2003-08-23 Zoran Vasiljevic <zoran@archiwrae.com> @@ -1278,7 +1278,7 @@ * generic/tclVar.c (Tcl_ArrayObjCmd, TclArraySet): Made [array get] and [array set] work with dictionaries, producing them and consuming - them. Note that for compatability reasons, you will never get a dict + them. Note that for compatibility reasons, you will never get a dict from feeding a string literal to [array set] since that alters the trace behaviour of "multi-key" sets. [Bug 759935] diff --git a/ChangeLog.2004 b/ChangeLog.2004 index 82acd5c..daf124f 100644 --- a/ChangeLog.2004 +++ b/ChangeLog.2004 @@ -1356,7 +1356,7 @@ 2004-10-07 Donal K. Fellows <donal.k.fellows@man.ac.uk> * *.3: Convert CONST to const and VOID to void so we document how - people should actually use the Tcl API and not the compatability hacks + people should actually use the Tcl API and not the compatibility hacks that it has to have. * doc/man.macros, *.3: Update .AS macro so it can know how wide to diff --git a/generic/tcl.h b/generic/tcl.h index 67bf2c4..18033c3 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -1327,9 +1327,9 @@ typedef struct Tcl_HashSearch { * TCL_CUSTOM_PTR_KEYS: The keys are pointers to arbitrary types, the * pointer is stored in the entry. * - * While maintaining binary compatability the above have to be distinct values + * While maintaining binary compatibility the above have to be distinct values * as they are used to differentiate between old versions of the hash table - * which don't have a typePtr and new ones which do. Once binary compatability + * which don't have a typePtr and new ones which do. Once binary compatibility * is discarded in favour of making more wide spread changes TCL_STRING_KEYS * can be the same as TCL_CUSTOM_TYPE_KEYS, and TCL_ONE_WORD_KEYS can be the * same as TCL_CUSTOM_PTR_KEYS because they simply determine how the key is diff --git a/generic/tclBasic.c b/generic/tclBasic.c index c1dd52d..81b3513 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -3024,13 +3024,6 @@ Tcl_DeleteCommandFromToken( Tcl_Command importCmd; /* - * Bump the command epoch counter. This will invalidate all cached - * references that point to this command. - */ - - cmdPtr->cmdEpoch++; - - /* * The code here is tricky. We can't delete the hash table entry before * invoking the deletion callback because there are cases where the * deletion callback needs to invoke the command (e.g. object systems such @@ -3052,6 +3045,14 @@ Tcl_DeleteCommandFromToken( Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = NULL; } + + /* + * Bump the command epoch counter. This will invalidate all cached + * references that point to this command. + */ + + cmdPtr->cmdEpoch++; + return 0; } @@ -3154,6 +3155,13 @@ Tcl_DeleteCommandFromToken( if (cmdPtr->hPtr != NULL) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = NULL; + + /* + * Bump the command epoch counter. This will invalidate all cached + * references that point to this command. + */ + + cmdPtr->cmdEpoch++; } /* diff --git a/generic/tclBinary.c b/generic/tclBinary.c index 9a5771e..4d063b2 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -155,35 +155,108 @@ static const EnsembleImplMap decodeMap[] = { }; /* - * The following object type represents an array of bytes. An array of bytes - * is not equivalent to an internationalized string. Conceptually, a string is - * an array of 16-bit quantities organized as a sequence of properly formed - * UTF-8 characters, while a ByteArray is an array of 8-bit quantities. - * Accessor functions are provided to convert a ByteArray to a String or a - * String to a ByteArray. Two or more consecutive bytes in an array of bytes - * may look like a single UTF-8 character if the array is casually treated as - * a string. But obtaining the String from a ByteArray is guaranteed to - * produced properly formed UTF-8 sequences so that there is a one-to-one map - * between bytes and characters. - * - * Converting a ByteArray to a String proceeds by casting each byte in the - * array to a 16-bit quantity, treating that number as a Unicode character, - * and storing the UTF-8 version of that Unicode character in the String. For - * ByteArrays consisting entirely of values 1..127, the corresponding String - * representation is the same as the ByteArray representation. - * - * Converting a String to a ByteArray proceeds by getting the Unicode - * representation of each character in the String, casting it to a byte by - * truncating the upper 8 bits, and then storing the byte in the ByteArray. - * Converting from ByteArray to String and back to ByteArray is not lossy, but - * converting an arbitrary String to a ByteArray may be. + * The following object types represent an array of bytes. The intent is + * to allow arbitrary binary data to pass through Tcl as a Tcl value + * without loss or damage. Such values are useful for things like + * encoded strings or Tk images to name just two. + * + * It's strange to have two Tcl_ObjTypes in place for this task when + * one would do, so a bit of detail and history how we got to this point + * and where we might go from here. + * + * A bytearray is an ordered sequence of bytes. Each byte is an integer + * value in the range [0-255]. To be a Tcl value type, we need a way to + * encode each value in the value set as a Tcl string. The simplest + * encoding is to represent each byte value as the same codepoint value. + * A bytearray of N bytes is encoded into a Tcl string of N characters + * where the codepoint of each character is the value of corresponding byte. + * This approach creates a one-to-one map between all bytearray values + * and a subset of Tcl string values. + * + * When converting a Tcl string value to the bytearray internal rep, the + * question arises what to do with strings outside that subset? That is, + * those Tcl strings containing at least one codepoint greater than 255? + * The obviously correct answer is to raise an error! That string value + * does not represent any valid bytearray value. Full Stop. The + * setFromAnyProc signature has a completion code return value for just + * this reason, to reject invalid inputs. + * + * Unfortunately this was not the path taken by the authors of the + * original tclByteArrayType. They chose to accept all Tcl string values + * as acceptable string encodings of the bytearray values that result + * from masking away the high bits of any codepoint value at all. This + * meant that every bytearray value had multiple accepted string + * representations. + * + * The implications of this choice are truly ugly. When a Tcl value has + * a string representation, we are required to accept that as the true + * value. Bytearray values that possess a string representation cannot + * be processed as bytearrays because we cannot know which true value + * that bytearray represents. The consequence is that we drag around + * an internal rep that we cannot make any use of. This painful price + * is extracted at any point after a string rep happens to be generated + * for the value. This happens even when the troublesome codepoints + * outside the byte range never show up. This happens rather routinely + * in normal Tcl operations unless we burden the script writer with the + * cognitive burden of avoiding it. The price is also paid by callers + * of the C interface. The routine + * + * unsigned char *Tcl_GetByteArrayFromObj(objPtr, lenPtr) + * + * has a guarantee to always return a non-NULL value, but that value + * points to a byte sequence that cannot be used by the caller to + * process the Tcl value absent some sideband testing that objPtr + * is "pure". Tcl offers no public interface to perform this test, + * so callers either break encapsulation or are unavoidably buggy. Tcl + * has defined a public interface that cannot be used correctly. The + * Tcl source code itself suffers the same problem, and has been buggy, + * but progressively less so as more and more portions of the code have + * been retrofitted with the required "purity testing". The set of values + * able to pass the purity test can be increased via the introduction of + * a "canonical" flag marker, but the only way the broken interface itself + * can be discarded is to start over and define the Tcl_ObjType properly. + * Bytearrays should simply be usable as bytearrays without a kabuki + * dance of testing. + * + * The Tcl_ObjType "properByteArrayType" is (nearly) a correct + * implementation of bytearrays. Any Tcl value with the type + * properByteArrayType can have its bytearray value fetched and + * used with confidence that acting on that value is equivalent to + * acting on the true Tcl string value. This still implies a side + * testing burden -- past mistakes will not let us avoid that + * immediately, but it is at least a conventional test of type, and + * can be implemented entirely by examining the objPtr fields, with + * no need to query the intrep, as a canonical flag would require. + * + * Until Tcl_GetByteArrayFromObj() and Tcl_SetByteArrayLength() can + * be revised to admit the possibility of returning NULL when the true + * value is not a valid bytearray, we need a mechanism to retain + * compatibility with the deployed callers of the broken interface. + * That's what the retained "tclByteArrayType" provides. In those + * unusual circumstances where we convert an invalid bytearray value + * to a bytearray type, it is to this legacy type. Essentially any + * time this legacy type gets used, it's a signal of a bug being ignored. + * A TIP should be drafted to remove this connection to the broken past + * so that Tcl 9 will no longer have any trace of it. Prescribing a + * migration path will be the key element of that work. The internal + * changes now in place are the limit of what can be done short of + * interface repair. They provide a great expansion of the histories + * over which bytearray values can be useful in the meanwhile. */ -const Tcl_ObjType tclByteArrayType = { +static const Tcl_ObjType properByteArrayType = { "bytearray", FreeByteArrayInternalRep, DupByteArrayInternalRep, UpdateStringOfByteArray, + NULL +}; + +const Tcl_ObjType tclByteArrayType = { + "bytearray", + FreeByteArrayInternalRep, + DupByteArrayInternalRep, + NULL, SetByteArrayFromAny }; @@ -211,6 +284,12 @@ typedef struct ByteArray { #define SET_BYTEARRAY(objPtr, baPtr) \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (baPtr) +int +TclIsPureByteArray( + Tcl_Obj * objPtr) +{ + return (objPtr->typePtr == &properByteArrayType); +} /* *---------------------------------------------------------------------- @@ -341,7 +420,7 @@ Tcl_SetByteArrayObj( if ((bytes != NULL) && (length > 0)) { memcpy(byteArrayPtr->bytes, bytes, (size_t) length); } - objPtr->typePtr = &tclByteArrayType; + objPtr->typePtr = &properByteArrayType; SET_BYTEARRAY(objPtr, byteArrayPtr); } @@ -371,7 +450,8 @@ Tcl_GetByteArrayFromObj( { ByteArray *baPtr; - if (objPtr->typePtr != &tclByteArrayType) { + if ((objPtr->typePtr != &properByteArrayType) + && (objPtr->typePtr != &tclByteArrayType)) { SetByteArrayFromAny(NULL, objPtr); } baPtr = GET_BYTEARRAY(objPtr); @@ -414,7 +494,8 @@ Tcl_SetByteArrayLength( if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength"); } - if (objPtr->typePtr != &tclByteArrayType) { + if ((objPtr->typePtr != &properByteArrayType) + && (objPtr->typePtr != &tclByteArrayType)) { SetByteArrayFromAny(NULL, objPtr); } @@ -450,29 +531,35 @@ SetByteArrayFromAny( Tcl_Interp *interp, /* Not used. */ Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */ { - int length; + int length, improper = 0; const char *src, *srcEnd; unsigned char *dst; ByteArray *byteArrayPtr; Tcl_UniChar ch; - if (objPtr->typePtr != &tclByteArrayType) { - src = TclGetStringFromObj(objPtr, &length); - srcEnd = src + length; - - byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); - for (dst = byteArrayPtr->bytes; src < srcEnd; ) { - src += Tcl_UtfToUniChar(src, &ch); - *dst++ = UCHAR(ch); - } + if (objPtr->typePtr == &properByteArrayType) { + return TCL_OK; + } + if (objPtr->typePtr == &tclByteArrayType) { + return TCL_OK; + } - byteArrayPtr->used = dst - byteArrayPtr->bytes; - byteArrayPtr->allocated = length; + src = TclGetStringFromObj(objPtr, &length); + srcEnd = src + length; - TclFreeIntRep(objPtr); - objPtr->typePtr = &tclByteArrayType; - SET_BYTEARRAY(objPtr, byteArrayPtr); + byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); + for (dst = byteArrayPtr->bytes; src < srcEnd; ) { + src += Tcl_UtfToUniChar(src, &ch); + improper = improper || (ch > 255); + *dst++ = UCHAR(ch); } + + byteArrayPtr->used = dst - byteArrayPtr->bytes; + byteArrayPtr->allocated = length; + + TclFreeIntRep(objPtr); + objPtr->typePtr = improper ? &tclByteArrayType : &properByteArrayType; + SET_BYTEARRAY(objPtr, byteArrayPtr); return TCL_OK; } @@ -535,7 +622,7 @@ DupByteArrayInternalRep( memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, (size_t) length); SET_BYTEARRAY(copyPtr, copyArrayPtr); - copyPtr->typePtr = &tclByteArrayType; + copyPtr->typePtr = srcPtr->typePtr; } /* @@ -642,7 +729,8 @@ TclAppendBytesToByteArray( /* Append zero bytes is a no-op. */ return; } - if (objPtr->typePtr != &tclByteArrayType) { + if ((objPtr->typePtr != &properByteArrayType) + && (objPtr->typePtr != &tclByteArrayType)) { SetByteArrayFromAny(NULL, objPtr); } byteArrayPtr = GET_BYTEARRAY(objPtr); diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 023c671..2572b2b 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2118,9 +2118,7 @@ StringReptCmd( 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) { @@ -2138,70 +2136,15 @@ 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 = attemptckalloc((unsigned) 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); + if (TCL_OK != TclStringRepeat(interp, objv[1], count, &resultPtr)) { return TCL_ERROR; } - for (index = 0; index < count; index++) { - memcpy(string2 + (length1 * index), string1, (size_t) length1); - } - 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; } diff --git a/generic/tclIO.c b/generic/tclIO.c index 80f6fa4..ffd2430 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -7129,7 +7129,7 @@ Tcl_Tell( * * Tcl_SeekOld, Tcl_TellOld -- * - * Backward-compatability versions of the seek/tell interface that do not + * Backward-compatibility versions of the seek/tell interface that do not * support 64-bit offsets. This interface is not documented or expected * to be supported indefinitely. * diff --git a/generic/tclInt.h b/generic/tclInt.h index 4257ea1..ca8ad70 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3147,6 +3147,8 @@ MODULE_SCOPE int TclStringMatch(const char *str, int strLen, MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, Tcl_Obj *patternObj, int flags); MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr); +MODULE_SCOPE int TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr, + int count, Tcl_Obj **objPtrPtr); MODULE_SCOPE void TclSubstCompile(Tcl_Interp *interp, const char *bytes, int numBytes, int flags, int line, struct CompileEnv *envPtr); @@ -4425,8 +4427,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, *---------------------------------------------------------------- */ -#define TclIsPureByteArray(objPtr) \ - (((objPtr)->typePtr==&tclByteArrayType) && ((objPtr)->bytes==NULL)) +MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr); /* *---------------------------------------------------------------- diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 34931e0..4b171f3 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2472,6 +2472,10 @@ AppendPrintfToObjVA( Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj( va_arg(argList, long))); break; + case 2: + Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj( + va_arg(argList, Tcl_WideInt))); + break; } break; case 'e': @@ -2500,9 +2504,9 @@ AppendPrintfToObjVA( gotPrecision = 1; p++; break; - /* TODO: support for wide (and bignum?) arguments */ + /* TODO: support for bignum arguments */ case 'l': - size = 1; + ++size; p++; break; case 'h': @@ -2613,6 +2617,146 @@ TclGetStringStorage( /* *--------------------------------------------------------------------------- * + * TclStringRepeat -- + * + * Performs the [string repeat] function. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Writes to *objPtrPtr the address of Tcl_Obj that is concatenation + * of count copies of the value in objPtr. + * + *--------------------------------------------------------------------------- + */ + +int +TclStringRepeat( + Tcl_Interp *interp, + Tcl_Obj *objPtr, + int count, + Tcl_Obj **objPtrPtr) +{ + Tcl_Obj *objResultPtr; + int length = 0, unichar = 0, done = 1; + int binary = TclIsPureByteArray(objPtr); + + /* assert (count >= 2) */ + + /* + * Analyze to determine what representation result should be. + * GOALS: Avoid shimmering & string rep generation. + * Produce pure bytearray when possible. + * Error on overflow. + */ + + if (!binary) { + if (objPtr->typePtr == &tclStringType) { + String *stringPtr = GET_STRING(objPtr); + if (stringPtr->hasUnicode) { + unichar = 1; + } + } + } + + if (binary) { + /* Result will be pure byte array. Pre-size it */ + Tcl_GetByteArrayFromObj(objPtr, &length); + } else if (unichar) { + /* Result will be pure Tcl_UniChar array. Pre-size it. */ + Tcl_GetUnicodeFromObj(objPtr, &length); + } else { + /* Result will be concat of string reps. Pre-size it. */ + Tcl_GetStringFromObj(objPtr, &length); + } + + if (length == 0) { + /* Any repeats of empty is empty. */ + *objPtrPtr = objPtr; + return TCL_OK; + } + + if (count > INT_MAX/length) { + if (interp) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "max size for a Tcl value (%d bytes) exceeded", INT_MAX)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + } + return TCL_ERROR; + } + + if (binary) { + /* Efficiently produce a pure byte array result */ + objResultPtr = Tcl_IsShared(objPtr) ? Tcl_DuplicateObj(objPtr) + : objPtr; + + Tcl_SetByteArrayLength(objResultPtr, count*length); /* PANIC? */ + Tcl_SetByteArrayLength(objResultPtr, length); + while (count - done > done) { + Tcl_AppendObjToObj(objResultPtr, objResultPtr); + done *= 2; + } + TclAppendBytesToByteArray(objResultPtr, + Tcl_GetByteArrayFromObj(objResultPtr, NULL), + (count - done) * length); + } else if (unichar) { + /* Efficiently produce a pure Tcl_UniChar array result */ + if (Tcl_IsShared(objPtr)) { + objResultPtr = Tcl_NewUnicodeObj(Tcl_GetUnicode(objPtr), length); + } else { + TclInvalidateStringRep(objPtr); + objResultPtr = objPtr; + } + + if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) { + if (interp) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "string size overflow: unable to alloc %llu bytes", + (Tcl_WideUInt)STRING_SIZE(count*length))); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + } + return TCL_ERROR; + } + Tcl_SetObjLength(objResultPtr, length); + while (count - done > done) { + Tcl_AppendObjToObj(objResultPtr, objResultPtr); + done *= 2; + } + Tcl_AppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr), + (count - done) * length); + } else { + /* Efficiently concatenate string reps */ + if (Tcl_IsShared(objPtr)) { + objResultPtr = Tcl_NewStringObj(Tcl_GetString(objPtr), length); + } else { + TclFreeIntRep(objPtr); + objResultPtr = objPtr; + } + if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) { + if (interp) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "string size overflow: unable to alloc %u bytes", + count*length)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + } + return TCL_ERROR; + } + Tcl_SetObjLength(objResultPtr, length); + while (count - done > done) { + Tcl_AppendObjToObj(objResultPtr, objResultPtr); + done *= 2; + } + Tcl_AppendToObj(objResultPtr, Tcl_GetString(objResultPtr), + (count - done) * length); + } + *objPtrPtr = objResultPtr; + return TCL_OK; +} + +/* + *--------------------------------------------------------------------------- + * * TclStringCatObjv -- * * Performs the [string cat] function. @@ -2755,7 +2899,7 @@ TclStringCatObjv( * Broken interface! Byte array value routines offer no way * to handle failure to allocate enough space. Following * stanza may panic. - */ + */ if (inPlace && !Tcl_IsShared(*objv)) { int start; @@ -2791,8 +2935,8 @@ TclStringCatObjv( if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "concatenation failed: unable to alloc %lu bytes", - STRING_SIZE(length))); + "concatenation failed: unable to alloc %llu bytes", + (Tcl_WideUInt)STRING_SIZE(length))); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return TCL_ERROR; @@ -2806,8 +2950,8 @@ TclStringCatObjv( if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "concatenation failed: unable to alloc %lu bytes", - STRING_SIZE(length))); + "concatenation failed: unable to alloc %llu bytes", + (Tcl_WideUInt)STRING_SIZE(length))); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return TCL_ERROR; diff --git a/generic/tclStringRep.h b/generic/tclStringRep.h index db6f7e4..1ef1957 100644 --- a/generic/tclStringRep.h +++ b/generic/tclStringRep.h @@ -72,17 +72,17 @@ typedef struct { do { \ if ((numChars) < 0 || (numChars) > STRING_MAXCHARS) { \ Tcl_Panic("max length for a Tcl unicode value (%d chars) exceeded", \ - STRING_MAXCHARS); \ + (int)STRING_MAXCHARS); \ } \ } while (0) #define stringAttemptAlloc(numChars) \ - (String *) attemptckalloc((unsigned) STRING_SIZE(numChars)) + (String *) attemptckalloc(STRING_SIZE(numChars)) #define stringAlloc(numChars) \ - (String *) ckalloc((unsigned) STRING_SIZE(numChars)) + (String *) ckalloc(STRING_SIZE(numChars)) #define stringRealloc(ptr, numChars) \ - (String *) ckrealloc((ptr), (unsigned) STRING_SIZE(numChars)) + (String *) ckrealloc((ptr), STRING_SIZE(numChars)) #define stringAttemptRealloc(ptr, numChars) \ - (String *) attemptckrealloc((ptr), (unsigned) STRING_SIZE(numChars)) + (String *) attemptckrealloc((ptr), STRING_SIZE(numChars)) #define GET_STRING(objPtr) \ ((String *) (objPtr)->internalRep.twoPtrValue.ptr1) #define SET_STRING(objPtr, stringPtr) \ diff --git a/generic/tclVar.c b/generic/tclVar.c index ab47147..4620397 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -1553,7 +1553,7 @@ Tcl_ArraySet( } else { /* * Not a dictionary, so assume (and convert to, for backward- - * -compatability reasons) a list. + * -compatibility reasons) a list. */ int elemLen; diff --git a/library/http/http.tcl b/library/http/http.tcl index d105886..ccd4cd1 100644 --- a/library/http/http.tcl +++ b/library/http/http.tcl @@ -1447,7 +1447,7 @@ proc http::mapReply {string} { set converted [string map $formMap $string] if {[string match "*\[\u0100-\uffff\]*" $converted]} { regexp "\[\u0100-\uffff\]" $converted badChar - # Return this error message for maximum compatability... :^/ + # Return this error message for maximum compatibility... :^/ return -code error \ "can't read \"formMap($badChar)\": no such element in array" } diff --git a/unix/tcl.m4 b/unix/tcl.m4 index f5aa84e..3189960 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -2706,7 +2706,7 @@ AC_DEFUN([SC_TCL_CFG_ENCODING], [ # advancedTest - the advanced test to run if the function is present # # Results: -# Might cause compatability versions of the function to be used. +# Might cause compatibility versions of the function to be used. # Might affect the following vars: # USE_COMPAT (implicit) # diff --git a/win/makefile.vc b/win/makefile.vc index c10b196..d6de5e1 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -113,12 +113,12 @@ the build instructions. # memdbg = Enables the debugging memory allocator.
#
# CHECKS=64bit,fullwarn,nodep,none
-# Sets special macros for checking compatability.
+# Sets special macros for checking compatibility.
#
# 64bit = Enable 64bit portability warnings (if available)
# fullwarn = Builds with full compiler and link warnings enabled.
# Very verbose.
-# nodep = Turns off compatability macros to ensure the core
+# nodep = Turns off compatibility macros to ensure the core
# isn't being built with deprecated functions.
#
# MACHINE=(ALPHA|AMD64|IA64|IX86)
|