Compare commits

...
Author SHA1 Message Date
jan.nijtmans a13bb5c7e5 Merge 9.0. Further Makefile tweaks 2023-05-03 16:12:46 +00:00
jan.nijtmans 881b147ab5 Merge 8.7 2023-05-03 15:59:09 +00:00
jan.nijtmans b583ea7360 Backport "Comments only. Fix blatantly obsolete ones". And a few more improvements from the same files. 2023-05-03 15:51:10 +00:00
pointsman d40bb9d13a Removed the bug specific test constraint from the tests related to [0306a5563c] because the bug is fixed. 2023-05-03 15:18:17 +00:00
apnadkarni 06cc962945 Comments only. Fix blatantly obsolete ones 2023-05-03 10:01:50 +00:00
pooryorick 88760a8a81 Use Tcl_Size instead of ptrdiff_t in Tcl_ObjCmdProc2(), Tcl_CmdObjTraceProc2, and Tcl_MethodCallProc2(). 2023-05-03 09:31:08 +00:00
apnadkarni aa4247d47b Merge mark 8.7 2023-05-03 04:06:28 +00:00
apnadkarni 81b4fa2fbd Changed CHANNEL_PROFILE_* to ENCODING_PROFILE_* and moved out of tclIO.h. See below.
For whatever reason, these macros were renamed and moved to tclIO.h post-660. This is
inappropriate as those macros deal with *encoding* flags, not *channel* flags and have
relevance outside of I/O making their renaming inappropriate. Further putting them in tclIO.h
forces inclusion of that header in modules that do not otherwise need that header.
2023-05-03 04:03:36 +00:00
apnadkarni 7b688527d7 Changed CHANNEL_PROFILE_* to ENCODING_PROFILE_* and moved out of tclIO.h. See below.
For whatever reason, these macros were renamed and moved to tclIO.h post-660.
This is inappropriate as those macros deal with *encoding* flags, not *channel*
flags and have relevance outside of I/O making their renaming inappropriate. Further
putting them in tclIO.h forces inclusion of that header in modules that do not
otherwise need that header.
2023-05-03 03:31:49 +00:00
pointsman 41aa17e389 Fix for [0306a5563c]. 2023-05-02 22:11:28 +00:00
pointsman 84d939b69a Fix for [0306a5563c]. 2023-05-02 21:50:48 +00:00
apnadkarni 60ba166da0 Merge 8.7 fix [784befb0ba] - tailcall crash 2023-05-02 17:06:38 +00:00
apnadkarni 2dccd2a567 Merge 8.6 - [ab123cfd3d] and [784befb0ba] 2023-05-02 16:48:57 +00:00
apnadkarni df75b91956 Fix [ab123cfd3d] - scan ubsan. Tx chrstphrchvz for patch 2023-05-02 16:33:39 +00:00
apnadkarni 43b5729ddf Fix [784befb0ba] - tailcall crash 2023-05-02 16:08:30 +00:00
apnadkarni 03d0f99e6c Fix [bb69c8d17e] compiled string last 2023-05-02 08:42:21 +00:00
jan.nijtmans 28e5ec7db6 Add missing "deprecated" constraint 2023-05-01 15:50:02 +00:00
apnadkarni b6bc736eee Tests for [dcac54a685] 2023-05-01 12:39:43 +00:00
apnadkarni fe84f70800 Tests for [ad9361fd20] 2023-05-01 12:16:44 +00:00
apnadkarni c77055a803 Fix [d07f42998d] - argument list truncation 2023-05-01 11:41:48 +00:00
apnadkarni 3b426fffa1 Fix [ab123cfd3d] - ubsan warning in ValidateFormat 2023-05-01 10:38:12 +00:00
apnadkarni 782009ca67 Fix [ab123cfd3d] - ubsan scan warning. 2023-05-01 06:51:51 +00:00
apnadkarni e1f2905dbc Added missing bigdata constraint 2023-05-01 06:41:25 +00:00
jan.nijtmans dd6950d635 Merge 8.7 2023-04-30 19:21:50 +00:00
jan.nijtmans c3cb435cf4 Fix OPTS=utf16 build for Tcl 9.0 2023-04-30 19:03:12 +00:00
jan.nijtmans 6c4b78cfa8 Eliminate ListSizeT_MAX, since it's the same as TCL_SIZE_MAX 2023-04-30 17:32:25 +00:00
jan.nijtmans 75eea66ef7 Add testcase for TclGetBytesFromObj() 2023-04-30 12:32:20 +00:00
jan.nijtmans 251211e714 Don't test compatibility macro's when TCL_NO_DEPRECATED is defined: this is expected to fail 2023-04-30 12:02:38 +00:00
apnadkarni e313582726 Fix [27b3ce2997] - check INT_MAX limit on script length 2023-04-30 10:20:19 +00:00
apnadkarni a06189323f Fix one more error message for max arg limit 2023-04-30 09:54:16 +00:00
apnadkarni 93f06f4469 Working on [d07f42998d] 2023-04-30 08:08:24 +00:00
apnadkarni 6c973cf9a2 Add tests. Panic on bytecode length limit 2023-04-29 16:16:58 +00:00
jan.nijtmans e393e2694c Add experimental testcase for TclGetBytesFromObj() 2023-04-29 16:10:56 +00:00
jan.nijtmans 1645895629 Eliminate ListSizeT_MAX, since it's the same as TCL_SIZE_MAX 2023-04-29 15:20:12 +00:00
jan.nijtmans ef51b5aacd Resolve a TODO 2023-04-29 14:56:13 +00:00
jan.nijtmans 905633199c Merge 8.7 2023-04-29 14:50:50 +00:00
pointsman 4d289b8084 Updated from trunk. Simplified bug specific tests. 2023-04-29 14:11:36 +00:00
apnadkarni 85a2a91729 Fix [7cddd2845c] - crash with >= INT_MAX operands 2023-04-29 03:15:11 +00:00
apnadkarni 947e3f8405 Limit scripts to INT_MAX-1 bytes 2023-04-29 02:11:48 +00:00
jan.nijtmans ad7deae634 Remove some (void *) typecasts, which are no longer necessary 2023-04-28 15:02:09 +00:00
pooryorick a6d654980e Limit memset() to "TCL_UTF_MAX=3' builds. 2023-04-28 06:43:49 +00:00
pooryorick 2fae9f1746 Add bytearray checking to TclCheckEmptyString(), and then use
TclCheckEmptyString() in Tcl_AppendObjToObj and TclStringCat() to reduce string
generation.
2023-04-27 20:54:21 +00:00
pooryorick 5eb2064b63 Fix for [f5eadcbf9a6b1b4c], passing pointer to uninitialized memory leads
Tcl_UniCharToUtf() to corrupt data.
2023-04-27 20:42:04 +00:00
pooryorick 7f433932f6 memset(0xff) instead of memset(0) to accomodate tests that fill buffer with
0xff.
2023-04-27 20:34:22 +00:00
jan.nijtmans 2e9301202d More size_t -> Tcl_Size, missed by earlier updates 2023-04-27 14:01:37 +00:00
jan.nijtmans 8bfaaa8337 Simplify Tcl 9 compatibility macro's. No change in functionality. 2023-04-27 13:52:42 +00:00
apnadkarni 175931c905 Merge trunk 2023-04-27 13:34:55 +00:00
apnadkarni 18f61eeeeb More checks for exceeding max words 2023-04-27 12:47:08 +00:00
jan.nijtmans 54b8f46097 RingSizeT -> Tcl_Size 2023-04-26 20:24:01 +00:00
jan.nijtmans 372bf74334 Reduce number of needed type-casts. No change in functionality 2023-04-26 19:29:44 +00:00
griffin f9f1724b36 Fix index descrepencies (bug-fa00fbbbabe).
Fix inconsistent rounding (bug-e5f06285de).
2023-04-26 16:18:04 +00:00
jan.nijtmans cd51753d86 More size_t -> Tcl_Size changes, which were missed before. Also (experimental) make the wrapper macro's produce compiler warnings is Tcl_Size is not used. 2023-04-26 15:53:40 +00:00
apnadkarni f227a5d1ff Test fix for [0f98bce669] 2023-04-26 15:45:12 +00:00
apnadkarni 5ddcd8fea9 Fix for [7cddd2845c] (in progress) 2023-04-26 14:56:21 +00:00
jan.nijtmans fe4e51b427 Merge 8.7 2023-04-26 06:51:52 +00:00
jan.nijtmans bd259695f1 Merge 8.6 2023-04-26 06:49:22 +00:00
jan.nijtmans e5eeaadf3c Don't refer to CVS any more 2023-04-26 06:40:14 +00:00
griffin 3aaf8c0544 merge trunk, address some 32-bit issues. 2023-04-26 03:41:57 +00:00
pooryorick 76130df460 Fix for issue [f5eadcbf9a], passing pointer to uninitialized memory leads
Tcl_UniCharToUtf() to corrupt data.
2023-04-25 20:34:03 +00:00
griffin da6df4adde Add fix inconsistent rounding (bug-e5f06285de).
Compute and use the "precision" for sequences of doubles: determine the number of significant digits in the fractional part of the given arguments, and round the results to that limit.
Fix copy bug in DupArithSeriesInternalRep.
2023-04-25 00:36:30 +00:00
pointsman 1ddccee9d3 Added a test for the initial problem and another for the known remaining problem. 2023-04-24 20:21:42 +00:00
pointsman 48570b93a6 Merge trunk. 2023-04-24 20:09:40 +00:00
apnadkarni 025b74f7c7 Fix [2e3fed53ba] - binary encode uuencode 2023-04-24 17:46:14 +00:00
apnadkarni 51043c29db Fix [c719fa8716] - binary encode base64 assertion failure 2023-04-24 17:16:58 +00:00
apnadkarni 553caf0d2c Fix [9369f83649] - binary format/scan for big data 2023-04-24 16:49:34 +00:00
apnadkarni 87e417c1a1 Fix [a814ee5bbd] - string compare/equal -length for long strings 2023-04-24 16:28:21 +00:00
dgp e95eb57666 Adapt signature of TclCompileScript() to fit better after TIP 660. 2023-04-24 15:51:00 +00:00
apnadkarni 3a9a817f67 Fix [d4ede611a7] - scan bigdata 2023-04-24 14:51:20 +00:00
dgp 277effbc04 TIP 422 eliminated va_list arguments from the API of Tcl 9.
However, some of the documentation lingered on.  No more.
2023-04-24 14:22:07 +00:00
apnadkarni 9f102b5b85 Minor change to length limit checks 2023-04-24 13:54:33 +00:00
apnadkarni 642792b1c2 Fix [a550f9710b] (format bigdata) 2023-04-24 12:55:35 +00:00
apnadkarni ef5af05366 Fix for bug [d4ede611a7] (scan) 2023-04-24 10:02:23 +00:00
pointsman 439a4360b3 Fixes the examples given in [0306a5563c]. Still more to do for a full fix. 2023-04-24 09:41:04 +00:00
pooryorick 321bff2cd5 Add bytearray checking to TclCheckEmptyString(), and then use
TclCheckEmptyString() in Tcl_AppendObjToObj and TclStringCat() to reduce string
generation.
2023-04-23 23:57:17 +00:00
jan.nijtmans d252076f75 Missing !defined(TCL_NO_DEPRECATED) around TIP #616 macro's. Thanks Rolf for noticing! 2023-04-23 21:59:34 +00:00
pooryorick eb3390224b Add bytearray checking to TclCheckEmptyString(), and then use
TclCheckEmptyString() in Tcl_AppendObjToObj and TclStringCat() to reduce string
generation.

jn: See discussion on mailing list "On the changing the sourcing of scripts to using strict profiles by default" for explanation why this commit is wrong, just as [e6fe76ae6b] and [4a7b807856] (which are similar commits, disguised as different ones).
2023-04-23 11:28:19 +00:00
apnadkarni f5125db22b Bug [d4ede611a7] (scan) - in progress 2023-04-23 03:25:33 +00:00
griffin 6ca1315df1 merge trunk 2023-04-21 00:35:20 +00:00
griffin b807564e68 sync with trunk. Fix lseq size bugs. 2023-04-20 18:13:36 +00:00
griffin 2aed8b1bdf Fix bug-fa00fbbbabe - seq / lindex discrepancies
Replace macros with static inline functions.
Limit ArithSeries list size to LIST_MAX. This way, shimmering less likely to fail if it happens.
Speed up UpdateStringOfArithSeries.
Fixed issues around indexing into vary large lseq lists.
2023-04-16 18:36:18 +00:00
mchn1350 77a0b2b716 Windows Threads are joinable 2023-04-03 07:41:10 +00:00
Konrad Schwarz 83d4470ed9 Clarified that it is suboptimal to hold the associated mutex when signaling a condition variable.
If the mutex is held, there is a danger of the signaled, hence newly awakened threads
of immediately blocking again when trying to acquire the mutex.  This is avoided
by signaling after releasing the mutex. Naturally, this somewhat increases the
danger that an unrelated thread will enter the mutex and invalidate the
underlying condition.  However, this case cannot be ruled out even when
the condition variable is signaled while the mutex is being held.
The "spurious wakeup" clause forces applications to re-check the condition
after reacquiring the mutex in any case.
2023-04-02 15:41:39 +00:00
Konrad Schwarz fe5d5b9dec Replaced non-thread-safe re-initialization checks with the Win32 INIT_ONCE one-time initialization API 2023-04-02 08:45:41 +00:00
mchn1350 31855faf56 Use native Win32 ConditionVariables
Replaces the home-grown condition variable implementation
with Win32 ConditionVariables, as introduced in Windows Vista.
2023-04-01 23:01:34 +00:00
Konrad Schwarz 45b907287d added copyright note 2023-03-29 09:02:07 +00:00
mchn1350 71d42c7655 On Windows, join threads using Win32 HANDLEs.
This works by extending the existing WinThread structure
with the thread's HANDLE. The lifetime of the WinThread structure
is until the thread terminates, for non-joinable threads,
or until the thread is joined. For joinable
threadsd, the thread's HANDLE remains open;
Windows signals the HANDLE when the thread terminates.
The thread's return value is transported using
the standard Windows mechanism.

A new thread-specific variable is introduced so a thread can
find its WinThread structure. Initial threads (those
not created via Tcl_CreateThread) receive a
WinThread lazily, when Tcl_GetCurrentThread is called
for the first time.

Instead of using the Windows ThreadId as the Tcl threadId,
the address of the WinThread is used. The least significant
bit of the pointer value is used to distinguish
joinable threads from non-joinable threads.
(For future use or debugging, the Windows ThreadId is stored
in the WinThread structure as well.)

generic/tclThreadJoin.c is made redudant by this patch.
2023-03-28 18:58:30 +00:00
64 changed files with 1405 additions and 1150 deletions
-3
View File
@@ -67,9 +67,6 @@ The \fB\-errorcode\fR return option will be set to this value.
.AP "const char" *element in
String to record as one element of the \fB\-errorcode\fR return option.
Last \fIelement\fR argument must be NULL.
.AP va_list argList in
An argument list which must have been initialized using
\fBva_start\fR, and cleared using \fBva_end\fR.
.AP int lineNum
The line number of a script where an error occurred.
.AP "const char" *script in
+1 -1
View File
@@ -187,7 +187,7 @@ except its \fIproc2\fR argument is of type \fBTcl_ObjCmdProc2\fR.
typedef int \fBTcl_ObjCmdProc2\fR(
void *\fIclientData\fR,
Tcl_Interp *\fIinterp\fR,
ptrdiff_t \fIobjc\fR,
Tcl_Size \fIobjc\fR,
Tcl_Obj *const \fIobjv\fR[]);
.CE
.PP
+2 -2
View File
@@ -88,10 +88,10 @@ typedef int \fBTcl_CmdObjTraceProc\fR(
typedef int \fBTcl_CmdObjTraceProc2\fR(
\fBvoid *\fR \fIclientData\fR,
\fBTcl_Interp\fR* \fIinterp\fR,
ptrdiff_t \fIlevel\fR,
Tcl_Size \fIlevel\fR,
const char *\fIcommand\fR,
\fBTcl_Command\fR \fIcommandToken\fR,
ptrdiff_t \fIobjc\fR,
Tcl_Size \fIobjc\fR,
\fBTcl_Obj\fR *const \fIobjv\fR[]);
.CE
.PP
-4
View File
@@ -27,10 +27,6 @@ void
A printf-style format string.
.AP "" arg in
Arguments matching the format string.
.AP va_list argList in
An argument list of arguments matching the format string.
Must have been initialized using \fBva_start\fR,
and cleared using \fBva_end\fR.
.AP Tcl_PanicProc *panicProc in
Procedure to report fatal error message and abort.
.BE
-3
View File
@@ -45,9 +45,6 @@ to the existing result of \fIinterp\fR.
.AP Tcl_FreeProc *freeProc in
Pointer to a procedure to call to release storage at
\fIresult\fR.
.AP va_list argList in
An argument list which must have been initialized using
\fBva_start\fR, and cleared using \fBva_end\fR.
.AP Tcl_Interp *sourceInterp in
The interpreter to transfer the result and return options from.
.AP Tcl_Interp *targetInterp in
+1 -4
View File
@@ -115,7 +115,7 @@ The index of the last Unicode character in the Unicode range to be
returned as a new value. If negative, take all characters up to
the last one available.
.AP Tcl_Obj *objPtr in/out
Points to a value to manipulate.
A pointer to a value to read, or to an unshared value to modify.
.AP Tcl_Obj *appendObjPtr in
The value to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR.
.AP "Tcl_Size \&| int" *lengthPtr out
@@ -123,9 +123,6 @@ The location where \fBTcl_GetStringFromObj\fR will store the length
of a value's string representation. May be (int *)NULL when not used.
.AP "const char" *string in
Null-terminated string value to append to \fIobjPtr\fR.
.AP va_list argList in
An argument list which must have been initialized using
\fBva_start\fR, and cleared using \fBva_end\fR.
.AP Tcl_Size limit in
Maximum number of bytes to be appended.
.AP "const char" *ellipsis in
+2 -4
View File
@@ -107,8 +107,6 @@ and join it.
Restrictions: On some UNIX systems the pthread-library does not
contain the functionality to specify the stack size of a thread. The
specified value for the stack size is ignored on these systems.
Windows currently does not support joinable threads. This
flag value is therefore ignored on this platform.
.PP
Tcl provides the \fBTcl_ExitThread\fR and \fBTcl_FinalizeThread\fR functions
for terminating threads and invoking optional per-thread exit
@@ -158,9 +156,9 @@ A condition variable is used as a signaling mechanism:
a thread can lock a mutex and then wait on a condition variable
with \fBTcl_ConditionWait\fR. This atomically releases the mutex lock
and blocks the waiting thread until another thread calls
\fBTcl_ConditionNotify\fR. The caller of \fBTcl_ConditionNotify\fR should
\fBTcl_ConditionNotify\fR. The caller of \fBTcl_ConditionNotify\fR may
have the associated mutex held by previously calling \fBTcl_MutexLock\fR,
but this is not enforced. Notifying the
but this tends to produce more thread context switches. Notifying the
condition variable unblocks all threads waiting on the condition variable,
but they do not proceed until the mutex is released with \fBTcl_MutexUnlock\fR.
The implementation of \fBTcl_ConditionWait\fR automatically locks
+1
View File
@@ -1,5 +1,6 @@
'\"
'\" Copyright (c) 1998 Scriptics Corporation.
'\" Copyright (c) 2023 Nathan Coulter
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+11 -11
View File
@@ -146,7 +146,7 @@ declare 32 {
}
# Only available in Tcl 8.x, NULL in Tcl 9.0
declare 33 {
unsigned char *TclGetByteArrayFromObj(Tcl_Obj *objPtr, int *numBytesPtr)
unsigned char *TclGetByteArrayFromObj(Tcl_Obj *objPtr, void *numBytesPtr)
}
declare 34 {
int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr)
@@ -173,7 +173,7 @@ declare 40 {
const Tcl_ObjType *Tcl_GetObjType(const char *typeName)
}
declare 41 {
char *TclGetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr)
char *TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr)
}
declare 42 {
void Tcl_InvalidateStringRep(Tcl_Obj *objPtr)
@@ -188,7 +188,7 @@ declare 44 {
}
declare 45 {
int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
int *objcPtr, Tcl_Obj ***objvPtr)
void *objcPtr, Tcl_Obj ***objvPtr)
}
declare 46 {
int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index,
@@ -196,7 +196,7 @@ declare 46 {
}
declare 47 {
int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
int *lengthPtr)
void *lengthPtr)
}
declare 48 {
int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first,
@@ -881,12 +881,12 @@ declare 241 {
void Tcl_SourceRCFile(Tcl_Interp *interp)
}
declare 242 {
int TclSplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
int TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr,
const char ***argvPtr)
}
# Obsolete, use Tcl_FSSplitPath
declare 243 {
void TclSplitPath(const char *path, int *argcPtr, const char ***argvPtr)
void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr)
}
# Removed in 9.0 (stub entry only)
#declare 244 {
@@ -1601,7 +1601,7 @@ declare 433 {
# introduced in 8.4a3
declare 434 {
Tcl_UniChar *TclGetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr)
Tcl_UniChar *TclGetUnicodeFromObj(Tcl_Obj *objPtr, void *lengthPtr)
}
# TIP#15 (math function introspection) dkf
@@ -1702,7 +1702,7 @@ declare 460 {
Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements)
}
declare 461 {
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr)
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr)
}
declare 462 {
int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr)
@@ -1841,7 +1841,7 @@ declare 496 {
Tcl_Obj *keyPtr)
}
declare 497 {
int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr)
int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr)
}
declare 498 {
int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr,
@@ -2270,7 +2270,7 @@ declare 603 {
# TIP#265 (option parser) dkf for Sam Bromley
declare 604 {
int TclParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable,
int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv)
void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv)
}
# TIP#336 (manipulate the error line) dgp
@@ -2468,7 +2468,7 @@ declare 648 {
# TIP #568
declare 649 {
unsigned char *TclGetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
int *numBytesPtr)
void *numBytesPtr)
}
declare 650 {
unsigned char *Tcl_GetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+8 -5
View File
@@ -561,7 +561,7 @@ typedef int (Tcl_CmdObjTraceProc) (void *clientData, Tcl_Interp *interp,
int level, const char *command, Tcl_Command commandInfo, int objc,
struct Tcl_Obj *const *objv);
typedef int (Tcl_CmdObjTraceProc2) (void *clientData, Tcl_Interp *interp,
ptrdiff_t level, const char *command, Tcl_Command commandInfo, ptrdiff_t objc,
Tcl_Size level, const char *command, Tcl_Command commandInfo, Tcl_Size objc,
struct Tcl_Obj *const *objv);
typedef void (Tcl_CmdObjTraceDeleteProc) (void *clientData);
typedef void (Tcl_DupInternalRepProc) (struct Tcl_Obj *srcPtr,
@@ -586,7 +586,7 @@ typedef void (Tcl_NamespaceDeleteProc) (void *clientData);
typedef int (Tcl_ObjCmdProc) (void *clientData, Tcl_Interp *interp,
int objc, struct Tcl_Obj *const *objv);
typedef int (Tcl_ObjCmdProc2) (void *clientData, Tcl_Interp *interp,
ptrdiff_t objc, struct Tcl_Obj *const *objv);
Tcl_Size objc, struct Tcl_Obj *const *objv);
typedef int (Tcl_LibraryInitProc) (Tcl_Interp *interp);
typedef int (Tcl_LibraryUnloadProc) (Tcl_Interp *interp, int flags);
typedef void (Tcl_PanicProc) (const char *format, ...);
@@ -1969,15 +1969,18 @@ typedef struct Tcl_EncodingType {
#define TCL_ENCODING_CHAR_LIMIT 0x10
/* Internal use bits, do not define bits in this space. See above comment */
#define TCL_ENCODING_INTERNAL_USE_MASK 0xFF00
/* Reserve top byte for profile values (disjoint, not a mask) */
/*
* Reserve top byte for profile values (disjoint, not a mask). In case of
* changes, ensure ENCODING_PROFILE_* macros in tclInt.h are modified if
* necessary.
*/
#define TCL_ENCODING_PROFILE_TCL8 0x01000000
#define TCL_ENCODING_PROFILE_STRICT 0x02000000
#define TCL_ENCODING_PROFILE_REPLACE 0x03000000
/* Still being argued - For Tcl9, is the default strict? TODO */
#if TCL_MAJOR_VERSION < 9
#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8
#else
#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8 /* STRICT? REPLACE? TODO */
#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8
#endif
/*
+180 -61
View File
@@ -13,36 +13,95 @@
#include "tclInt.h"
#include "tclArithSeries.h"
#include <assert.h>
#include <math.h>
/* -------------------------- ArithSeries object ---------------------------- */
/*
* Helper functions
*
* - ArithRound -- Round doubles to the number of significant fractional
* digits
* - ArithSeriesIndexDbl -- base list indexing operation for doubles
* - ArithSeriesIndexInt -- " " " " " integers
* - ArithSeriesGetInternalRep -- Return the internal rep from a Tcl_Obj
* - Precision -- determine the number of factional digits for the given
* double value
* - maxPrecision -- Using the values provide, determine the longest percision
* in the arithSeries
*/
static inline double
ArithRound(double d, unsigned int n) {
double scalefactor = pow(10, n);
return round(d*scalefactor)/scalefactor;
}
#define ArithSeriesRepPtr(arithSeriesObjPtr) \
(ArithSeries *) ((arithSeriesObjPtr)->internalRep.twoPtrValue.ptr1)
static inline double
ArithSeriesIndexDbl(
ArithSeries *arithSeriesRepPtr,
Tcl_WideInt index)
{
ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
if (arithSeriesRepPtr->isDouble) {
double d = dblRepPtr->start + (index * dblRepPtr->step);
unsigned n = (dblRepPtr->precision > 0 ? dblRepPtr->precision : 0);
return ArithRound(d, n);
} else {
return (double)(arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step));
}
}
#define ArithSeriesIndexM(arithSeriesRepPtr, index) \
((arithSeriesRepPtr)->isDouble ? \
(((ArithSeriesDbl*)(arithSeriesRepPtr))->start+((index) * ((ArithSeriesDbl*)(arithSeriesRepPtr))->step)) \
: \
((arithSeriesRepPtr)->start+((index) * arithSeriesRepPtr->step)))
static inline Tcl_WideInt
ArithSeriesIndexInt(
ArithSeries *arithSeriesRepPtr,
Tcl_WideInt index)
{
ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
if (arithSeriesRepPtr->isDouble) {
return (Tcl_WideInt)(dblRepPtr->start + ((index) * dblRepPtr->step));
} else {
return (arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step));
}
}
#define ArithSeriesGetInternalRep(objPtr, arithRepPtr) \
do { \
const Tcl_ObjInternalRep *irPtr; \
irPtr = TclFetchInternalRep((objPtr), &tclArithSeriesType.objType); \
(arithRepPtr) = irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL; \
} while (0)
static inline ArithSeries*
ArithSeriesGetInternalRep(Tcl_Obj *objPtr)
{
const Tcl_ObjInternalRep *irPtr;
irPtr = TclFetchInternalRep((objPtr), &tclArithSeriesType.objType);
return irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL;
}
static inline int
Precision(double d)
{
char tmp[TCL_DOUBLE_SPACE+2], *off;
tmp[0] = 0;
Tcl_PrintDouble(NULL,d,tmp);
off = strchr(tmp, '.');
return (off ? strlen(off+1) : 0);
}
static inline int
maxPrecision(double start, double end, double step)
{
// Find longest number of digits after the decimal point.
int dp = Precision(step);
int i = Precision(start);
dp = i>dp ? i : dp;
i = Precision(end);
dp = i>dp ? i : dp;
return dp;
}
/*
* Prototypes for procedures defined later in this file:
*/
static void DupArithSeriesInternalRep (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void FreeArithSeriesInternalRep (Tcl_Obj *listPtr);
static int SetArithSeriesFromAny (Tcl_Interp *interp, Tcl_Obj *objPtr);
static void UpdateStringOfArithSeries (Tcl_Obj *arithSeriesObj);
static Tcl_Obj *ArithSeriesObjStep(Tcl_Obj *arithSeriesPtr);
static void DupArithSeriesInternalRep (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void FreeArithSeriesInternalRep (Tcl_Obj *listPtr);
static int SetArithSeriesFromAny (Tcl_Interp *interp, Tcl_Obj *objPtr);
static void UpdateStringOfArithSeries (Tcl_Obj *arithSeriesObj);
static Tcl_Obj* ArithSeriesObjStep(Tcl_Obj *arithSeriesPtr);
static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesPtr);
/*
@@ -107,7 +166,7 @@ const TclObjTypeWithAbstractList tclArithSeriesType = {
*----------------------------------------------------------------------
*/
static Tcl_WideInt
ArithSeriesLen(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
ArithSeriesLenInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
{
Tcl_WideInt len;
@@ -118,6 +177,18 @@ ArithSeriesLen(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
return (len < 0) ? -1 : len;
}
static Tcl_WideInt
ArithSeriesLenDbl(double start, double end, double step)
{
Tcl_WideInt len;
if (step == 0) {
return 0;
}
len = ((end-start+step)/step);
return (len < 0) ? -1 : len;
}
/*
*----------------------------------------------------------------------
*
@@ -140,10 +211,13 @@ static
Tcl_Obj *
NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_WideInt len)
{
Tcl_WideInt length = (len>=0 ? len : ArithSeriesLen(start, end, step));
Tcl_WideInt length;
Tcl_Obj *arithSeriesObj;
ArithSeries *arithSeriesRepPtr;
length = len>=0 ? len : -1;
if (length < 0) length = -1;
TclNewObj(arithSeriesObj);
if (length <= 0) {
@@ -184,14 +258,20 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide
* None.
*----------------------------------------------------------------------
*/
static
Tcl_Obj *
NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len)
{
Tcl_WideInt length = (len>=0 ? len : ArithSeriesLen(start, end, step));
Tcl_WideInt length;
Tcl_Obj *arithSeriesObj;
ArithSeriesDbl *arithSeriesRepPtr;
length = len>=0 ? len : -1;
if (length < 0) {
length = -1;
}
TclNewObj(arithSeriesObj);
if (length <= 0) {
@@ -205,11 +285,14 @@ NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len)
arithSeriesRepPtr->step = step;
arithSeriesRepPtr->len = length;
arithSeriesRepPtr->elements = NULL;
arithSeriesRepPtr->precision = maxPrecision(start,end,step);
arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
arithSeriesObj->typePtr = &tclArithSeriesType.objType;
if (length > 0)
if (length > 0) {
Tcl_InvalidateStringRep(arithSeriesObj);
}
return arithSeriesObj;
}
@@ -295,7 +378,7 @@ TclNewArithSeriesObj(
{
double dstart, dend, dstep;
Tcl_WideInt start, end, step;
Tcl_WideInt len;
Tcl_WideInt len = -1;
if (startObj) {
assignNumber(useDoubles, &start, &dstart, startObj);
@@ -337,9 +420,9 @@ TclNewArithSeriesObj(
assert(dstep!=0);
if (!lenObj) {
if (useDoubles) {
len = (dend - dstart + dstep)/dstep;
len = ArithSeriesLenDbl(dstart, dend, dstep);
} else {
len = (end - start + step)/step;
len = ArithSeriesLenInt(start, end, step);
}
}
}
@@ -354,7 +437,7 @@ TclNewArithSeriesObj(
}
}
if (TCL_MAJOR_VERSION < 9 && len > ListSizeT_MAX) {
if (len > TCL_SIZE_MAX) {
Tcl_SetObjResult(
interp,
Tcl_NewStringObj("max length of a Tcl list exceeded", -1));
@@ -398,7 +481,7 @@ ArithSeriesObjStep(
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
Tcl_Panic("ArithSeriesObjStep called with a not ArithSeries Obj.");
}
arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObj);
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (arithSeriesRepPtr->isDouble) {
TclNewDoubleObj(stepObj, ((ArithSeriesDbl*)(arithSeriesRepPtr))->step);
} else {
@@ -430,7 +513,7 @@ ArithSeriesObjStep(
Tcl_Obj *
TclArithSeriesObjIndex(
Tcl_Interp *interp,
TCL_UNUSED(Tcl_Interp *),
Tcl_Obj *arithSeriesObj,
Tcl_WideInt index)
{
@@ -439,21 +522,15 @@ TclArithSeriesObjIndex(
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
Tcl_Panic("TclArithSeriesObjIndex called with a not ArithSeries Obj.");
}
arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObj);
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (index < 0 || (Tcl_Size)index >= arithSeriesRepPtr->len) {
if (interp) {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("index %" TCL_LL_MODIFIER "d is out of bounds 0 to %"
TCL_LL_MODIFIER "d", index, (arithSeriesRepPtr->len-1)));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
}
return NULL;
return Tcl_NewObj();
}
/* List[i] = Start + (Step * index) */
if (arithSeriesRepPtr->isDouble) {
return Tcl_NewDoubleObj(ArithSeriesIndexM(arithSeriesRepPtr, index));
return Tcl_NewDoubleObj(ArithSeriesIndexDbl(arithSeriesRepPtr, index));
} else {
return Tcl_NewWideIntObj(ArithSeriesIndexM(arithSeriesRepPtr, index));
return Tcl_NewWideIntObj(ArithSeriesIndexInt(arithSeriesRepPtr, index));
}
}
@@ -541,16 +618,25 @@ DupArithSeriesInternalRep(
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
ArithSeries *srcArithSeriesRepPtr =
(ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1;
ArithSeries *copyArithSeriesRepPtr;
(ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1;
/*
* Allocate a new ArithSeries structure. */
copyArithSeriesRepPtr = (ArithSeries*) Tcl_Alloc(sizeof(ArithSeries));
*copyArithSeriesRepPtr = *srcArithSeriesRepPtr;
copyArithSeriesRepPtr->elements = NULL;
copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr;
if (srcArithSeriesRepPtr->isDouble) {
ArithSeriesDbl *srcArithSeriesDblRepPtr =
(ArithSeriesDbl *)srcArithSeriesRepPtr;
ArithSeriesDbl *copyArithSeriesDblRepPtr =
(ArithSeriesDbl *) Tcl_Alloc(sizeof(ArithSeriesDbl));
*copyArithSeriesDblRepPtr = *srcArithSeriesDblRepPtr;
copyArithSeriesDblRepPtr->elements = NULL;
copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesDblRepPtr;
} else {
ArithSeries *copyArithSeriesRepPtr =
(ArithSeries *) Tcl_Alloc(sizeof(ArithSeries));
*copyArithSeriesRepPtr = *srcArithSeriesRepPtr;
copyArithSeriesRepPtr->elements = NULL;
copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr;
}
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
copyPtr->typePtr = &tclArithSeriesType.objType;
}
@@ -591,29 +677,47 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObj)
char *elem, *p;
Tcl_Obj *elemObj;
Tcl_Size i;
Tcl_WideInt length = 0;
Tcl_Size length = 0;
Tcl_Size slen;
/*
* Pass 1: estimate space.
*/
for (i = 0; i < arithSeriesRepPtr->len; i++) {
elemObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, i);
elem = Tcl_GetStringFromObj(elemObj, &slen);
Tcl_DecrRefCount(elemObj);
slen += 1; /* + 1 is for the space or the nul-term */
length += slen;
if (!arithSeriesRepPtr->isDouble) {
for (i = 0; i < arithSeriesRepPtr->len; i++) {
double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
slen = d>0 ? log10(d)+1 : d<0 ? log10((0-d))+2 : 1;
length += slen;
}
} else {
for (i = 0; i < arithSeriesRepPtr->len; i++) {
double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
char tmp[TCL_DOUBLE_SPACE+2];
tmp[0] = 0;
Tcl_PrintDouble(NULL,d,tmp);
if ((length + strlen(tmp)) > TCL_SIZE_MAX) {
break; // overflow
}
length += strlen(tmp);
}
}
length += arithSeriesRepPtr->len; // Space for each separator
/*
* Pass 2: generate the string repr.
*/
p = Tcl_InitStringRep(arithSeriesObj, NULL, length);
if (p == NULL) {
Tcl_Panic("Unable to allocate string size %" TCL_Z_MODIFIER "u", length);
}
for (i = 0; i < arithSeriesRepPtr->len; i++) {
elemObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, i);
elem = Tcl_GetStringFromObj(elemObj, &slen);
strcpy(p, elem);
if (((p - arithSeriesObj->bytes)+slen) > length) {
break;
}
strncpy(p, elem, slen);
p[slen] = ' ';
p += slen+1;
Tcl_DecrRefCount(elemObj);
@@ -685,7 +789,7 @@ TclArithSeriesObjCopy(
Tcl_Obj *copyPtr;
ArithSeries *arithSeriesRepPtr;
ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (NULL == arithSeriesRepPtr) {
if (SetArithSeriesFromAny(interp, arithSeriesObj) != TCL_OK) {
/* We know this is going to panic, but it's the message we want */
@@ -728,17 +832,30 @@ TclArithSeriesObjRange(
ArithSeries *arithSeriesRepPtr;
Tcl_Obj *startObj, *endObj, *stepObj;
ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (fromIdx == TCL_INDEX_NONE) {
fromIdx = 0;
}
if (fromIdx > toIdx) {
if (fromIdx > toIdx ||
(toIdx > arithSeriesRepPtr->len-1 &&
fromIdx > arithSeriesRepPtr->len-1)) {
Tcl_Obj *obj;
TclNewObj(obj);
return obj;
}
if (fromIdx < 0) {
fromIdx = 0;
}
if (toIdx < 0) {
toIdx = 0;
}
if (toIdx > arithSeriesRepPtr->len-1) {
toIdx = arithSeriesRepPtr->len-1;
}
startObj = TclArithSeriesObjIndex(interp, arithSeriesObj, fromIdx);
if (startObj == NULL) {
return NULL;
@@ -778,15 +895,17 @@ TclArithSeriesObjRange(
TclInvalidateStringRep(arithSeriesObj);
if (arithSeriesRepPtr->isDouble) {
ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesObj;
ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
double start, end, step;
Tcl_GetDoubleFromObj(NULL, startObj, &start);
Tcl_GetDoubleFromObj(NULL, endObj, &end);
Tcl_GetDoubleFromObj(NULL, stepObj, &step);
arithSeriesDblRepPtr->start = start;
arithSeriesDblRepPtr->end = end;
arithSeriesDblRepPtr->step = step;
arithSeriesDblRepPtr->len = (end-start+step)/step;
arithSeriesDblRepPtr->precision = maxPrecision(start, end, step);
arithSeriesDblRepPtr->len = ArithSeriesLenDbl(start, end, step);
arithSeriesDblRepPtr->elements = NULL;
} else {
@@ -797,7 +916,7 @@ TclArithSeriesObjRange(
arithSeriesRepPtr->start = start;
arithSeriesRepPtr->end = end;
arithSeriesRepPtr->step = step;
arithSeriesRepPtr->len = (end-start+step)/step;
arithSeriesRepPtr->len = ArithSeriesLenInt(start, end, step);
arithSeriesRepPtr->elements = NULL;
}
@@ -852,7 +971,7 @@ TclArithSeriesGetElements(
Tcl_Obj **objv;
int i, objc;
ArithSeriesGetInternalRep(objPtr, arithSeriesRepPtr);
arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr);
objc = arithSeriesRepPtr->len;
if (objc > 0) {
if (arithSeriesRepPtr->elements) {
@@ -927,7 +1046,7 @@ TclArithSeriesObjReverse(
double dstart, dend, dstep;
int isDouble;
ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
isDouble = arithSeriesRepPtr->isDouble;
len = arithSeriesRepPtr->len;
+1
View File
@@ -30,6 +30,7 @@ typedef struct {
double start;
double end;
double step;
int precision;
} ArithSeriesDbl;
+24 -9
View File
@@ -3298,7 +3298,7 @@ invokeObj2Command(
Command *cmdPtr = (Command *) clientData;
if (objc > INT_MAX) {
objc = TCL_INDEX_NONE; /* TODO - why? Should error, not truncate */
return TclCommandWordLimitError(interp, objc);
}
if (cmdPtr->objProc != NULL) {
result = cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
@@ -3315,6 +3315,9 @@ static int cmdWrapper2Proc(void *clientData,
Tcl_Obj *const objv[])
{
Command *cmdPtr = (Command *)clientData;
if (objc > INT_MAX) {
return TclCommandWordLimitError(interp, objc);
}
return cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
}
@@ -5164,17 +5167,17 @@ TclEvalEx(
{
Interp *iPtr = (Interp *) interp;
const char *p, *next;
const unsigned int minObjs = 20;
const int minObjs = 20;
Tcl_Obj **objv, **objvSpace;
int *expand, *lines, *lineSpace;
Tcl_Token *tokenPtr;
int bytesLeft, expandRequested, code = TCL_OK;
Tcl_Size commandLength;
int expandRequested, code = TCL_OK;
Tcl_Size bytesLeft, commandLength;
CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
* TCL_EVAL_GLOBAL was set. */
int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
int gotParse = 0;
TCL_HASH_TYPE i, objectsUsed = 0;
Tcl_Size i, objectsUsed = 0;
/* These variables keep track of how much
* state has been allocated while evaluating
* the script, so that it can be freed
@@ -5312,8 +5315,8 @@ TclEvalEx(
Tcl_Size wordLine = line;
const char *wordStart = parsePtr->commandStart;
int *wordCLNext = clNext;
unsigned int objectsNeeded = 0;
unsigned int numWords = parsePtr->numWords;
Tcl_Size objectsNeeded = 0;
Tcl_Size numWords = parsePtr->numWords;
/*
* Generate an array of objects for the words of the command.
@@ -5332,6 +5335,8 @@ TclEvalEx(
for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr;
objectsUsed < numWords;
objectsUsed++, tokenPtr += tokenPtr->numComponents+1) {
Tcl_Size additionalObjsCount;
/*
* TIP #280. Track lines to current word. Save the information
* on a per-word basis, signaling dynamic words as needed.
@@ -5381,12 +5386,22 @@ TclEvalEx(
expandRequested = 1;
expand[objectsUsed] = 1;
objectsNeeded += (numElements ? numElements : 1);
additionalObjsCount = (numElements ? numElements : 1);
} else {
expand[objectsUsed] = 0;
objectsNeeded++;
additionalObjsCount = 1;
}
/* Currently max command words in INT_MAX */
if (additionalObjsCount > INT_MAX ||
objectsNeeded > (INT_MAX - additionalObjsCount)) {
code = TclCommandWordLimitError(interp, -1);
Tcl_DecrRefCount(objv[objectsUsed]);
break;
}
objectsNeeded += additionalObjsCount;
if (wordCLNext) {
TclContinuationsEnterDerived(objv[objectsUsed],
wordStart - outerScript, wordCLNext);
+17 -17
View File
@@ -386,7 +386,7 @@ unsigned char *
TclGetBytesFromObj(
Tcl_Interp *interp, /* For error reporting */
Tcl_Obj *objPtr, /* Value to extract from */
int *numBytesPtr) /* If non-NULL, write the number of bytes
void *numBytesPtr) /* If non-NULL, write the number of bytes
* in the array here */
{
Tcl_Size numBytes = 0;
@@ -404,7 +404,7 @@ TclGetBytesFromObj(
}
return NULL;
} else {
*numBytesPtr = (int) numBytes;
*(int *)numBytesPtr = (int) numBytes;
}
}
return bytes;
@@ -774,7 +774,7 @@ TclAppendBytesToByteArray(
*/
Tcl_Size attempt;
/* Make sure we do not wrap when doubling */
if (needed <= (BYTEARRAY_MAX_LEN - needed)) {
attempt = 2 * needed;
@@ -870,7 +870,7 @@ BinaryFormatCmd(
int value = 0; /* Current integer value to be packed.
* Initialized to avoid compiler warning. */
char cmd; /* Current format character. */
Tcl_Size count; /* Count associated with current format
Tcl_Size count; /* Count associated with current format
* character. */
int flags; /* Format field flags */
const char *format; /* Pointer to current position in format
@@ -1383,7 +1383,7 @@ BinaryScanCmd(
int value = 0; /* Current integer value to be packed.
* Initialized to avoid compiler warning. */
char cmd; /* Current format character. */
Tcl_Size count; /* Count associated with current format
Tcl_Size count; /* Count associated with current format
* character. */
int flags; /* Format field flags */
const char *format; /* Pointer to current position in format
@@ -1795,14 +1795,14 @@ GetFormatSpec(
(*formatPtr)++;
*countPtr = BINARY_ALL;
} else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
unsigned long count;
unsigned long long count;
errno = 0;
count = strtoul(*formatPtr, (char **) formatPtr, 10);
if (errno || (count > (unsigned long) INT_MAX)) {
*countPtr = INT_MAX;
count = strtoull(*formatPtr, (char **) formatPtr, 10);
if (errno || (count > TCL_SIZE_MAX)) {
*countPtr = TCL_SIZE_MAX;
} else {
*countPtr = (int) count;
*countPtr = count;
}
} else {
*countPtr = BINARY_NOCOUNT;
@@ -2638,11 +2638,11 @@ BinaryEncode64(
{
Tcl_Obj *resultObj;
unsigned char *data, *limit;
int maxlen = 0;
Tcl_Size maxlen = 0;
const char *wrapchar = "\n";
Tcl_Size wrapcharlen = 1;
int i, index, size, outindex = 0, purewrap = 1;
Tcl_Size offset, count = 0;
int index, purewrap = 1;
Tcl_Size i, offset, size, outindex = 0, count = 0;
enum { OPT_MAXLEN, OPT_WRAPCHAR };
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
@@ -2658,7 +2658,7 @@ BinaryEncode64(
}
switch (index) {
case OPT_MAXLEN:
if (Tcl_GetIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
if (Tcl_GetSizeIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
return TCL_ERROR;
}
if (maxlen < 0) {
@@ -2764,12 +2764,12 @@ BinaryEncodeUu(
{
Tcl_Obj *resultObj;
unsigned char *data, *start, *cursor;
int rawLength, i, bits, index;
int i, bits, index;
unsigned int n;
int lineLength = 61;
const unsigned char SingleNewline[] = { UCHAR('\n') };
const unsigned char *wrapchar = SingleNewline;
Tcl_Size j, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
Tcl_Size j, rawLength, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
enum { OPT_MAXLEN, OPT_WRAPCHAR };
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
@@ -2859,7 +2859,7 @@ BinaryEncodeUu(
*/
while (offset < count) {
int lineLen = count - offset;
Tcl_Size lineLen = count - offset;
if (lineLen > rawLength) {
lineLen = rawLength;
+7 -6
View File
@@ -2642,8 +2642,8 @@ StringEqualCmd(
*/
const char *string2;
int i, match, nocase = 0, reqlength = -1;
Tcl_Size length;
int i, match, nocase = 0;
Tcl_Size length, reqlength = -1;
if (objc < 3 || objc > 6) {
str_cmp_args:
@@ -2662,7 +2662,7 @@ StringEqualCmd(
goto str_cmp_args;
}
i++;
if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
if (TclGetSizeIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
return TCL_ERROR;
}
} else {
@@ -2717,7 +2717,8 @@ StringCmpCmd(
* the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
*/
int match, nocase, reqlength, status;
int match, nocase, status;
Tcl_Size reqlength;
status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength);
if (status != TCL_OK) {
@@ -2736,7 +2737,7 @@ TclStringCmpOpts(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[], /* Argument objects. */
int *nocase,
int *reqlength)
Tcl_Size *reqlength)
{
int i;
Tcl_Size length;
@@ -2761,7 +2762,7 @@ TclStringCmpOpts(
goto str_cmp_args;
}
i++;
if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) {
if (TclGetSizeIntFromObj(interp, objv[i], reqlength) != TCL_OK) {
return TCL_ERROR;
}
} else {
+1 -1
View File
@@ -2669,7 +2669,7 @@ TclCompileTailcallCmd(
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
int i;
if (parsePtr->numWords < 2 || parsePtr->numWords > 256
if (parsePtr->numWords < 2 || parsePtr->numWords >= 256
|| envPtr->procPtr == NULL) {
return TCL_ERROR;
}
+31 -2
View File
@@ -869,6 +869,18 @@ TclSetByteCodeFromAny(
result = hookProc(interp, &compEnv, clientData);
}
/*
* After optimization is all done, check that byte code length limits
* are not exceeded. Bug [27b3ce2997].
*/
if ((compEnv.codeNext - compEnv.codeStart) > INT_MAX) {
/*
* Cannot just return TCL_ERROR as callers ignore return value.
* TODO - May be use TclCompileSyntaxError here?
*/
Tcl_Panic("Maximum byte code length %d exceeded.", INT_MAX);
}
/*
* Change the object into a ByteCode object. Ownership of the literal
* objects and aux data items passes to the ByteCode object.
@@ -2136,7 +2148,7 @@ TclCompileScript(
* serves as context for finding and compiling
* commands. May not be NULL. */
const char *script, /* The source script to compile. */
size_t numBytes, /* Number of bytes in script. If -1, the
Tcl_Size numBytes, /* Number of bytes in script. If < 0, the
* script consists of all bytes up to the
* first null character. */
CompileEnv *envPtr) /* Holds resulting instructions. */
@@ -2167,9 +2179,26 @@ TclCompileScript(
return;
}
if (numBytes < 0) {
numBytes = strlen(script);
}
/* Each iteration compiles one command from the script. */
if (numBytes + 1 > 1) {
if (numBytes > 0) {
if (numBytes >= INT_MAX) {
/*
* Note this gets -errorline as 1. Not worth figuring out which line
* crosses the limit to get -errorline for this error case.
*/
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Script length %" TCL_SIZE_MODIFIER
"d exceeds max permitted length %d.",
numBytes, (int)INT_MAX-1));
Tcl_SetErrorCode(interp, "TCL", "LIMIT", "SCRIPTLENGTH", NULL);
TclCompileSyntaxError(interp, envPtr);
return;
}
/*
* Don't use system stack (size of Tcl_Parse is ca. 400 bytes), so
* many nested compilations (body enclosed in body) can cause abnormal
+1 -1
View File
@@ -1100,7 +1100,7 @@ MODULE_SCOPE void TclCompileInvocation(Tcl_Interp *interp,
Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, size_t numWords,
CompileEnv *envPtr);
MODULE_SCOPE void TclCompileScript(Tcl_Interp *interp,
const char *script, size_t numBytes,
const char *script, Tcl_Size numBytes,
CompileEnv *envPtr);
MODULE_SCOPE void TclCompileSyntaxError(Tcl_Interp *interp,
CompileEnv *envPtr);
+48 -45
View File
@@ -136,7 +136,7 @@ EXTERN int Tcl_GetBooleanFromObj(Tcl_Interp *interp,
Tcl_Obj *objPtr, int *intPtr);
/* 33 */
EXTERN unsigned char * TclGetByteArrayFromObj(Tcl_Obj *objPtr,
int *numBytesPtr);
void *numBytesPtr);
/* 34 */
EXTERN int Tcl_GetDouble(Tcl_Interp *interp, const char *src,
double *doublePtr);
@@ -156,7 +156,7 @@ EXTERN int Tcl_GetLongFromObj(Tcl_Interp *interp,
/* 40 */
EXTERN const Tcl_ObjType * Tcl_GetObjType(const char *typeName);
/* 41 */
EXTERN char * TclGetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr);
EXTERN char * TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr);
/* 42 */
EXTERN void Tcl_InvalidateStringRep(Tcl_Obj *objPtr);
/* 43 */
@@ -167,7 +167,7 @@ EXTERN int Tcl_ListObjAppendElement(Tcl_Interp *interp,
Tcl_Obj *listPtr, Tcl_Obj *objPtr);
/* 45 */
EXTERN int TclListObjGetElements(Tcl_Interp *interp,
Tcl_Obj *listPtr, int *objcPtr,
Tcl_Obj *listPtr, void *objcPtr,
Tcl_Obj ***objvPtr);
/* 46 */
EXTERN int Tcl_ListObjIndex(Tcl_Interp *interp,
@@ -175,7 +175,7 @@ EXTERN int Tcl_ListObjIndex(Tcl_Interp *interp,
Tcl_Obj **objPtrPtr);
/* 47 */
EXTERN int TclListObjLength(Tcl_Interp *interp,
Tcl_Obj *listPtr, int *lengthPtr);
Tcl_Obj *listPtr, void *lengthPtr);
/* 48 */
EXTERN int Tcl_ListObjReplace(Tcl_Interp *interp,
Tcl_Obj *listPtr, Tcl_Size first,
@@ -665,9 +665,9 @@ EXTERN const char * Tcl_SignalMsg(int sig);
EXTERN void Tcl_SourceRCFile(Tcl_Interp *interp);
/* 242 */
EXTERN int TclSplitList(Tcl_Interp *interp, const char *listStr,
int *argcPtr, const char ***argvPtr);
void *argcPtr, const char ***argvPtr);
/* 243 */
EXTERN void TclSplitPath(const char *path, int *argcPtr,
EXTERN void TclSplitPath(const char *path, void *argcPtr,
const char ***argvPtr);
/* Slot 244 is reserved */
/* Slot 245 is reserved */
@@ -1137,7 +1137,8 @@ EXTERN int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr,
/* 433 */
EXTERN Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel);
/* 434 */
EXTERN Tcl_UniChar * TclGetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr);
EXTERN Tcl_UniChar * TclGetUnicodeFromObj(Tcl_Obj *objPtr,
void *lengthPtr);
/* Slot 435 is reserved */
/* Slot 436 is reserved */
/* 437 */
@@ -1209,7 +1210,7 @@ EXTERN int Tcl_FSConvertToPathType(Tcl_Interp *interp,
/* 460 */
EXTERN Tcl_Obj * Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements);
/* 461 */
EXTERN Tcl_Obj * TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr);
EXTERN Tcl_Obj * TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr);
/* 462 */
EXTERN int Tcl_FSEqualPaths(Tcl_Obj *firstPtr,
Tcl_Obj *secondPtr);
@@ -1306,7 +1307,7 @@ EXTERN int Tcl_DictObjRemove(Tcl_Interp *interp,
Tcl_Obj *dictPtr, Tcl_Obj *keyPtr);
/* 497 */
EXTERN int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
int *sizePtr);
void *sizePtr);
/* 498 */
EXTERN int Tcl_DictObjFirst(Tcl_Interp *interp,
Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr,
@@ -1612,7 +1613,7 @@ EXTERN int Tcl_GetEnsembleParameterList(Tcl_Interp *interp,
Tcl_Command token, Tcl_Obj **paramListPtr);
/* 604 */
EXTERN int TclParseArgsObjv(Tcl_Interp *interp,
const Tcl_ArgvInfo *argTable, int *objcPtr,
const Tcl_ArgvInfo *argTable, void *objcPtr,
Tcl_Obj *const *objv, Tcl_Obj ***remObjv);
/* 605 */
EXTERN int Tcl_GetErrorLine(Tcl_Interp *interp);
@@ -1744,7 +1745,7 @@ EXTERN int * Tcl_UtfToUniCharDString(const char *src,
Tcl_Size length, Tcl_DString *dsPtr);
/* 649 */
EXTERN unsigned char * TclGetBytesFromObj(Tcl_Interp *interp,
Tcl_Obj *objPtr, int *numBytesPtr);
Tcl_Obj *objPtr, void *numBytesPtr);
/* 650 */
EXTERN unsigned char * Tcl_GetBytesFromObj(Tcl_Interp *interp,
Tcl_Obj *objPtr, Tcl_Size *numBytesPtr);
@@ -1911,7 +1912,7 @@ typedef struct TclStubs {
void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */
int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *intPtr); /* 31 */
int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 32 */
unsigned char * (*tclGetByteArrayFromObj) (Tcl_Obj *objPtr, int *numBytesPtr); /* 33 */
unsigned char * (*tclGetByteArrayFromObj) (Tcl_Obj *objPtr, void *numBytesPtr); /* 33 */
int (*tcl_GetDouble) (Tcl_Interp *interp, const char *src, double *doublePtr); /* 34 */
int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */
void (*reserved36)(void);
@@ -1919,13 +1920,13 @@ typedef struct TclStubs {
int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */
int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */
const Tcl_ObjType * (*tcl_GetObjType) (const char *typeName); /* 40 */
char * (*tclGetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */
char * (*tclGetStringFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 41 */
void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */
int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */
int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */
int (*tclListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
int (*tclListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj **objPtrPtr); /* 46 */
int (*tclListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */
int (*tclListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *lengthPtr); /* 47 */
int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first, Tcl_Size count, Tcl_Size objc, Tcl_Obj *const objv[]); /* 48 */
void (*reserved49)(void);
Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes); /* 50 */
@@ -2120,8 +2121,8 @@ typedef struct TclStubs {
const char * (*tcl_SignalId) (int sig); /* 239 */
const char * (*tcl_SignalMsg) (int sig); /* 240 */
void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */
int (*tclSplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, const char ***argvPtr); /* 242 */
void (*tclSplitPath) (const char *path, int *argcPtr, const char ***argvPtr); /* 243 */
int (*tclSplitList) (Tcl_Interp *interp, const char *listStr, void *argcPtr, const char ***argvPtr); /* 242 */
void (*tclSplitPath) (const char *path, void *argcPtr, const char ***argvPtr); /* 243 */
void (*reserved244)(void);
void (*reserved245)(void);
void (*reserved246)(void);
@@ -2312,7 +2313,7 @@ typedef struct TclStubs {
void * (*tcl_AttemptDbCkrealloc) (void *ptr, TCL_HASH_TYPE size, const char *file, int line); /* 431 */
int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 432 */
Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */
Tcl_UniChar * (*tclGetUnicodeFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 434 */
Tcl_UniChar * (*tclGetUnicodeFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 434 */
void (*reserved435)(void);
void (*reserved436)(void);
Tcl_Obj * (*tcl_SubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 437 */
@@ -2339,7 +2340,7 @@ typedef struct TclStubs {
int (*tcl_FSChdir) (Tcl_Obj *pathPtr); /* 458 */
int (*tcl_FSConvertToPathType) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 459 */
Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, Tcl_Size elements); /* 460 */
Tcl_Obj * (*tclFSSplitPath) (Tcl_Obj *pathPtr, int *lenPtr); /* 461 */
Tcl_Obj * (*tclFSSplitPath) (Tcl_Obj *pathPtr, void *lenPtr); /* 461 */
int (*tcl_FSEqualPaths) (Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 462 */
Tcl_Obj * (*tcl_FSGetNormalizedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 463 */
Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 464 */
@@ -2375,7 +2376,7 @@ typedef struct TclStubs {
int (*tcl_DictObjPut) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr); /* 494 */
int (*tcl_DictObjGet) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 495 */
int (*tcl_DictObjRemove) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 496 */
int (*tclDictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr); /* 497 */
int (*tclDictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr); /* 497 */
int (*tcl_DictObjFirst) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 498 */
void (*tcl_DictObjNext) (Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 499 */
void (*tcl_DictObjDone) (Tcl_DictSearch *searchPtr); /* 500 */
@@ -2482,7 +2483,7 @@ typedef struct TclStubs {
unsigned (*tcl_GetBlockSizeFromStat) (const Tcl_StatBuf *statPtr); /* 601 */
int (*tcl_SetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList); /* 602 */
int (*tcl_GetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr); /* 603 */
int (*tclParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */
int (*tclParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */
int (*tcl_GetErrorLine) (Tcl_Interp *interp); /* 605 */
void (*tcl_SetErrorLine) (Tcl_Interp *interp, int lineNum); /* 606 */
void (*tcl_TransferResult) (Tcl_Interp *sourceInterp, int code, Tcl_Interp *targetInterp); /* 607 */
@@ -2527,7 +2528,7 @@ typedef struct TclStubs {
Tcl_Size (*tcl_UtfToUniChar) (const char *src, int *chPtr); /* 646 */
char * (*tcl_UniCharToUtfDString) (const int *uniStr, Tcl_Size uniLength, Tcl_DString *dsPtr); /* 647 */
int * (*tcl_UtfToUniCharDString) (const char *src, Tcl_Size length, Tcl_DString *dsPtr); /* 648 */
unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *numBytesPtr); /* 649 */
unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, void *numBytesPtr); /* 649 */
unsigned char * (*tcl_GetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size *numBytesPtr); /* 650 */
char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 651 */
Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 652 */
@@ -4040,15 +4041,15 @@ extern const TclStubs *tclStubsPtr;
# if TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED)
# define Tcl_GetBytesFromObj(interp, objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
tclStubsPtr->tclGetBytesFromObj(interp, objPtr, (int *)(void *)(sizePtr)) : \
tclStubsPtr->tclGetBytesFromObj(interp, objPtr, (sizePtr)) : \
tclStubsPtr->tcl_GetBytesFromObj(interp, objPtr, (Tcl_Size *)(void *)(sizePtr)))
# define Tcl_GetStringFromObj(objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
tclStubsPtr->tclGetStringFromObj(objPtr, (int *)(void *)(sizePtr)) : \
tclStubsPtr->tclGetStringFromObj(objPtr, (sizePtr)) : \
tclStubsPtr->tcl_GetStringFromObj(objPtr, (Tcl_Size *)(void *)(sizePtr)))
# define Tcl_GetUnicodeFromObj(objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
tclStubsPtr->tclGetUnicodeFromObj(objPtr, (int *)(void *)(sizePtr)) : \
tclStubsPtr->tclGetUnicodeFromObj(objPtr, (sizePtr)) : \
tclStubsPtr->tcl_GetUnicodeFromObj(objPtr, (Tcl_Size *)(void *)(sizePtr)))
# endif
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
@@ -4063,18 +4064,18 @@ extern const TclStubs *tclStubsPtr;
#if TCL_MAJOR_VERSION > 8
#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
tclStubsPtr->tclGetBytesFromObj(NULL, objPtr, (int *)(void *)(sizePtr)) : \
tclStubsPtr->tclGetBytesFromObj(NULL, objPtr, (sizePtr)) : \
tclStubsPtr->tcl_GetBytesFromObj(NULL, objPtr, (Tcl_Size *)(void *)(sizePtr)))
#else
#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
tclStubsPtr->tclGetByteArrayFromObj(objPtr, (int *)(void *)(sizePtr)) : \
tclStubsPtr->tclGetByteArrayFromObj(objPtr, (sizePtr)) : \
tclStubsPtr->tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)(void *)(sizePtr)))
#endif
#else
#define Tcl_GetBytesFromObj(interp, objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
TclGetBytesFromObj(interp, objPtr, (int *)(void *)(sizePtr)) : \
TclGetBytesFromObj(interp, objPtr, (sizePtr)) : \
(Tcl_GetBytesFromObj)(interp, objPtr, (Tcl_Size *)(void *)(sizePtr)))
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), \
@@ -4087,15 +4088,15 @@ extern const TclStubs *tclStubsPtr;
Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#define Tcl_GetStringFromObj(objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
TclGetStringFromObj(objPtr, (int *)(void *)(sizePtr)) : \
TclGetStringFromObj(objPtr, (sizePtr)) : \
(Tcl_GetStringFromObj)(objPtr, (Tcl_Size *)(void *)(sizePtr)))
#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
TclGetBytesFromObj(NULL, objPtr, (int *)(void *)(sizePtr)) : \
TclGetBytesFromObj(NULL, objPtr, (sizePtr)) : \
(Tcl_GetBytesFromObj)(NULL, objPtr, (Tcl_Size *)(void *)(sizePtr)))
#define Tcl_GetUnicodeFromObj(objPtr, sizePtr) \
(sizeof(*(sizePtr)) <= sizeof(int) ? \
TclGetUnicodeFromObj(objPtr, (int *)(void *)(sizePtr)) : \
TclGetUnicodeFromObj(objPtr, (sizePtr)) : \
(Tcl_GetUnicodeFromObj)(objPtr, (Tcl_Size *)(void *)(sizePtr)))
#endif
@@ -4168,34 +4169,36 @@ extern const TclStubs *tclStubsPtr;
# define Tcl_WCharLen (sizeof(wchar_t) != sizeof(short) \
? (Tcl_Size (*)(wchar_t *))tclStubsPtr->tcl_UniCharLen \
: (Tcl_Size (*)(wchar_t *))Tcl_Char16Len)
#if TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED)
# undef Tcl_ListObjGetElements
# define Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) (sizeof(*(objcPtr)) == sizeof(int) \
? tclStubsPtr->tclListObjGetElements((interp), (listPtr), (int *)(void *)(objcPtr), (objvPtr)) \
? tclStubsPtr->tclListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)) \
: tclStubsPtr->tcl_ListObjGetElements((interp), (listPtr), (Tcl_Size *)(void *)(objcPtr), (objvPtr)))
# undef Tcl_ListObjLength
# define Tcl_ListObjLength(interp, listPtr, lengthPtr) (sizeof(*(lengthPtr)) == sizeof(int) \
? tclStubsPtr->tclListObjLength((interp), (listPtr), (int *)(void *)(lengthPtr)) \
? tclStubsPtr->tclListObjLength((interp), (listPtr), (lengthPtr)) \
: tclStubsPtr->tcl_ListObjLength((interp), (listPtr), (Tcl_Size *)(void *)(lengthPtr)))
# undef Tcl_DictObjSize
# define Tcl_DictObjSize(interp, dictPtr, sizePtr) (sizeof(*(sizePtr)) == sizeof(int) \
? tclStubsPtr->tclDictObjSize((interp), (dictPtr), (int *)(void *)(sizePtr)) \
? tclStubsPtr->tclDictObjSize((interp), (dictPtr), (sizePtr)) \
: tclStubsPtr->tcl_DictObjSize((interp), (dictPtr), (Tcl_Size *)(void *)(sizePtr)))
# undef Tcl_SplitList
# define Tcl_SplitList(interp, listStr, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
? tclStubsPtr->tclSplitList((interp), (listStr), (int *)(void *)(argcPtr), (argvPtr)) \
? tclStubsPtr->tclSplitList((interp), (listStr), (argcPtr), (argvPtr)) \
: tclStubsPtr->tcl_SplitList((interp), (listStr), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
# undef Tcl_SplitPath
# define Tcl_SplitPath(path, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
? tclStubsPtr->tclSplitPath((path), (int *)(void *)(argcPtr), (argvPtr)) \
? tclStubsPtr->tclSplitPath((path), (argcPtr), (argvPtr)) \
: tclStubsPtr->tcl_SplitPath((path), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
# undef Tcl_FSSplitPath
# define Tcl_FSSplitPath(pathPtr, lenPtr) (sizeof(*(lenPtr)) == sizeof(int) \
? tclStubsPtr->tclFSSplitPath((pathPtr), (int *)(void *)(lenPtr)) \
? tclStubsPtr->tclFSSplitPath((pathPtr), (lenPtr)) \
: tclStubsPtr->tcl_FSSplitPath((pathPtr), (Tcl_Size *)(void *)(lenPtr)))
# undef Tcl_ParseArgsObjv
# define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) == sizeof(int) \
? tclStubsPtr->tclParseArgsObjv((interp), (argTable), (int *)(void *)(objcPtr), (objv), (remObjv)) \
? tclStubsPtr->tclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) \
: tclStubsPtr->tcl_ParseArgsObjv((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv)))
#endif /* TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED) */
#else
# define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \
? (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_UniCharToUtfDString \
@@ -4211,25 +4214,25 @@ extern const TclStubs *tclStubsPtr;
: (Tcl_Size (*)(wchar_t *))Tcl_Char16Len)
#if !defined(BUILD_tcl) && !defined(TCL_NO_DEPRECATED)
# define Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) (sizeof(*(objcPtr)) == sizeof(int) \
? TclListObjGetElements((interp), (listPtr), (int *)(void *)(objcPtr), (objvPtr)) \
? TclListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)) \
: (Tcl_ListObjGetElements)((interp), (listPtr), (Tcl_Size *)(void *)(objcPtr), (objvPtr)))
# define Tcl_ListObjLength(interp, listPtr, lengthPtr) (sizeof(*(lengthPtr)) == sizeof(int) \
? TclListObjLength((interp), (listPtr), (int *)(void *)(lengthPtr)) \
? TclListObjLength((interp), (listPtr), (lengthPtr)) \
: (Tcl_ListObjLength)((interp), (listPtr), (Tcl_Size *)(void *)(lengthPtr)))
# define Tcl_DictObjSize(interp, dictPtr, sizePtr) (sizeof(*(sizePtr)) == sizeof(int) \
? TclDictObjSize((interp), (dictPtr), (int *)(void *)(sizePtr)) \
? TclDictObjSize((interp), (dictPtr), (sizePtr)) \
: (Tcl_DictObjSize)((interp), (dictPtr), (Tcl_Size *)(void *)(sizePtr)))
# define Tcl_SplitList(interp, listStr, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
? TclSplitList((interp), (listStr), (int *)(void *)(argcPtr), (argvPtr)) \
? TclSplitList((interp), (listStr), (argcPtr), (argvPtr)) \
: (Tcl_SplitList)((interp), (listStr), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
# define Tcl_SplitPath(path, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
? TclSplitPath((path), (int *)(void *)(argcPtr), (argvPtr)) \
? TclSplitPath((path), (argcPtr), (argvPtr)) \
: (Tcl_SplitPath)((path), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
# define Tcl_FSSplitPath(pathPtr, lenPtr) (sizeof(*(lenPtr)) == sizeof(int) \
? TclFSSplitPath((pathPtr), (int *)(void *)(lenPtr)) \
? TclFSSplitPath((pathPtr), (lenPtr)) \
: (Tcl_FSSplitPath)((pathPtr), (Tcl_Size *)(void *)(lenPtr)))
# define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) == sizeof(int) \
? TclParseArgsObjv((interp), (argTable), (int *)(void *)(objcPtr), (objv), (remObjv)) \
? TclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) \
: (Tcl_ParseArgsObjv)((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv)))
#endif /* !defined(BUILD_tcl) */
#endif
+65 -11
View File
@@ -10,7 +10,6 @@
*/
#include "tclInt.h"
#include "tclIO.h"
typedef size_t (LengthProc)(const char *src);
@@ -200,16 +199,16 @@ static struct TclEncodingProfiles {
{"tcl8", TCL_ENCODING_PROFILE_TCL8},
};
#define PROFILE_TCL8(flags_) \
((CHANNEL_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_TCL8) \
|| (CHANNEL_PROFILE_GET(flags_) == 0 \
((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_TCL8) \
|| (ENCODING_PROFILE_GET(flags_) == 0 \
&& TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_TCL8))
#define PROFILE_STRICT(flags_) \
((CHANNEL_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_STRICT) \
|| (CHANNEL_PROFILE_GET(flags_) == 0 \
((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_STRICT) \
|| (ENCODING_PROFILE_GET(flags_) == 0 \
&& TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_STRICT))
#define PROFILE_REPLACE(flags_) \
((CHANNEL_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE) \
|| (CHANNEL_PROFILE_GET(flags_) == 0 \
((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE) \
|| (ENCODING_PROFILE_GET(flags_) == 0 \
&& TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_REPLACE))
#define UNICODE_REPLACE_CHAR ((Tcl_UniChar)0xFFFD)
@@ -2532,7 +2531,17 @@ UtfToUtfProc(
flags |= PTR2INT(clientData);
dstEnd = dst + dstLen - ((flags & ENCODING_UTF) ? TCL_UTF_MAX : 6);
profile = CHANNEL_PROFILE_GET(flags);
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(dst, 0xff, dstLen);
#endif
profile = ENCODING_PROFILE_GET(flags);
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
@@ -2746,6 +2755,15 @@ Utf32ToUtfProc(
}
result = TCL_OK;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(dst, 0xff, dstLen);
#endif
/*
* Check alignment with utf-32 (4 == sizeof(UTF-32))
*/
@@ -3015,6 +3033,15 @@ Utf16ToUtfProc(
}
result = TCL_OK;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(dst, 0xff, dstLen);
#endif
/*
* Check alignment with utf-16 (2 == sizeof(UTF-16))
*/
@@ -3428,6 +3455,15 @@ TableToUtfProc(
dstStart = dst;
dstEnd = dst + dstLen - TCL_UTF_MAX;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(dst, 0xff, dstLen);
#endif
toUnicode = (const unsigned short *const *) dataPtr->toUnicode;
prefixBytes = dataPtr->prefixBytes;
pageZero = toUnicode[0];
@@ -3669,6 +3705,15 @@ Iso88591ToUtfProc(
dstStart = dst;
dstEnd = dst + dstLen - TCL_UTF_MAX;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(dst, 0xff, dstLen);
#endif
result = TCL_OK;
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
Tcl_UniChar ch = 0;
@@ -3908,6 +3953,15 @@ EscapeToUtfProc(
dstStart = dst;
dstEnd = dst + dstLen - TCL_UTF_MAX;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(dst, 0xff, dstLen);
#endif
state = PTR2INT(*statePtr);
if (flags & TCL_ENCODING_START) {
state = 0;
@@ -4587,9 +4641,9 @@ TclEncodingProfileIdToName(
int TclEncodingSetProfileFlags(int flags)
{
if (flags & TCL_ENCODING_STOPONERROR) {
CHANNEL_PROFILE_SET(flags, TCL_ENCODING_PROFILE_STRICT);
ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_STRICT);
} else {
int profile = CHANNEL_PROFILE_GET(flags);
int profile = ENCODING_PROFILE_GET(flags);
switch (profile) {
case TCL_ENCODING_PROFILE_TCL8:
case TCL_ENCODING_PROFILE_STRICT:
@@ -4597,7 +4651,7 @@ int TclEncodingSetProfileFlags(int flags)
break;
case 0: /* Unspecified by caller */
default:
CHANNEL_PROFILE_SET(flags, TCL_ENCODING_PROFILE_DEFAULT);
ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_DEFAULT);
break;
}
}
+11 -7
View File
@@ -981,10 +981,10 @@ GrowEvaluationStack(
{
ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL;
size_t newBytes;
int growth = growth1;
int newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
Tcl_Size growth = growth1;
Tcl_Size newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart;
int moveWords = 0;
Tcl_Size moveWords = 0;
if (move) {
if (!markerPtr) {
@@ -2825,8 +2825,12 @@ TEBCresume(
pc += pcAdjustment;
TEBC_YIELD();
return TclNREvalObjv(interp, objc, objv,
if (objc > INT_MAX) {
return TclCommandWordLimitError(interp, objc);
} else {
return TclNREvalObjv(interp, objc, objv,
TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME, NULL);
}
case INST_INVOKE_REPLACE:
objc = TclGetUInt4AtPtr(pc+1);
@@ -5272,7 +5276,7 @@ TEBCresume(
TclNewObj(objResultPtr);
} else if (TclIsPureByteArray(valuePtr)) {
objResultPtr = Tcl_NewByteArrayObj(
Tcl_GetByteArrayFromObj(valuePtr, (size_t *)NULL)+index, 1);
Tcl_GetByteArrayFromObj(valuePtr, (Tcl_Size *)NULL)+index, 1);
} else if (valuePtr->bytes && slength == valuePtr->length) {
objResultPtr = Tcl_NewStringObj((const char *)
valuePtr->bytes+index, 1);
@@ -5488,7 +5492,7 @@ TEBCresume(
NEXT_INST_F(1, 2, 1);
case INST_STR_FIND_LAST:
objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, INT_MAX - 1);
objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, TCL_SIZE_MAX - 1);
TRACE(("%.20s %.20s => %s\n",
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(objResultPtr)));
@@ -5536,7 +5540,7 @@ TEBCresume(
nocase);
} else if (TclIsPureByteArray(valuePtr) && TclIsPureByteArray(value2Ptr) && !nocase) {
unsigned char *bytes1, *bytes2;
size_t wlen1 = 0, wlen2 = 0;
Tcl_Size wlen1 = 0, wlen2 = 0;
bytes1 = Tcl_GetByteArrayFromObj(valuePtr, &wlen1);
bytes2 = Tcl_GetByteArrayFromObj(value2Ptr, &wlen2);
+40 -51
View File
@@ -223,8 +223,8 @@ static void StopCopy(CopyState *csPtr);
static void TranslateInputEOL(ChannelState *statePtr, char *dst,
const char *src, int *dstLenPtr, int *srcLenPtr);
static void UpdateInterest(Channel *chanPtr);
static int Write(Channel *chanPtr, const char *src,
int srcLen, Tcl_Encoding encoding);
static Tcl_Size Write(Channel *chanPtr, const char *src,
Tcl_Size srcLen, Tcl_Encoding encoding);
static Tcl_Obj * FixLevelCode(Tcl_Obj *msg);
static void SpliceChannel(Tcl_Channel chan);
static void CutChannel(Tcl_Channel chan);
@@ -1679,11 +1679,11 @@ Tcl_CreateChannel(
statePtr->encoding = Tcl_GetEncoding(NULL, name);
statePtr->inputEncodingState = NULL;
statePtr->inputEncodingFlags = TCL_ENCODING_START;
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags,
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags,
TCL_ENCODING_PROFILE_DEFAULT);
statePtr->outputEncodingState = NULL;
statePtr->outputEncodingFlags = TCL_ENCODING_START;
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags,
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags,
TCL_ENCODING_PROFILE_DEFAULT);
/*
@@ -4240,6 +4240,7 @@ Tcl_WriteObj(
Channel *chanPtr;
ChannelState *statePtr; /* State info for channel */
const char *src;
Tcl_Size srcLen = 0;
statePtr = ((Channel *) chan)->state;
chanPtr = statePtr->topChanPtr;
@@ -4247,34 +4248,21 @@ Tcl_WriteObj(
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
return TCL_INDEX_NONE;
}
Tcl_Size srcLen;
if (statePtr->encoding == NULL) {
Tcl_Size result;
src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen);
if (src == NULL) {
Tcl_SetErrno(EILSEQ);
return TCL_INDEX_NONE;
result = TCL_INDEX_NONE;
} else {
result = WriteBytes(chanPtr, src, srcLen);
}
return result;
} else {
src = Tcl_GetStringFromObj(objPtr, &srcLen);
return WriteChars(chanPtr, src, srcLen);
}
size_t totalWritten = 0;
/*
* Note original code always called WriteChars even if srcLen 0
* so we will too.
*/
do {
int chunkSize = srcLen > INT_MAX ? INT_MAX : srcLen;
int written;
written = WriteChars(chanPtr, src, chunkSize);
if (written < 0) {
return TCL_INDEX_NONE;
}
totalWritten += written;
srcLen -= chunkSize;
} while (srcLen);
return totalWritten;
}
static void
@@ -4345,17 +4333,18 @@ WillRead(
*----------------------------------------------------------------------
*/
static int
static Tcl_Size
Write(
Channel *chanPtr, /* The channel to buffer output for. */
const char *src, /* UTF-8 string to write. */
int srcLen, /* Length of UTF-8 string in bytes. */
Tcl_Size srcLen, /* Length of UTF-8 string in bytes. */
Tcl_Encoding encoding)
{
ChannelState *statePtr = chanPtr->state;
/* State info for channel */
char *nextNewLine = NULL;
int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0;
int endEncoding, needNlFlush = 0;
Tcl_Size saved = 0, total = 0, flushed = 0;
char safe[BUFFER_PADDING];
int encodingError = 0;
@@ -4368,7 +4357,6 @@ Write(
*/
endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);
if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)
|| (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
nextNewLine = (char *)memchr(src, '\n', srcLen);
@@ -4377,7 +4365,8 @@ Write(
while (srcLen + saved + endEncoding > 0 && !encodingError) {
ChannelBuffer *bufPtr;
char *dst;
int result, srcRead, dstLen, dstWrote, srcLimit = srcLen;
int result, srcRead, dstLen, dstWrote;
Tcl_Size srcLimit = srcLen;
if (nextNewLine) {
srcLimit = nextNewLine - src;
@@ -4649,7 +4638,7 @@ Tcl_GetsObj(
if (statePtr->encoding == GetBinaryEncoding()
&& ((statePtr->inputTranslation == TCL_TRANSLATE_LF)
|| (statePtr->inputTranslation == TCL_TRANSLATE_CR))
&& Tcl_GetByteArrayFromObj(objPtr, (size_t *)NULL) != NULL) {
&& Tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)NULL) != NULL) {
return TclGetsObjBinary(chan, objPtr);
}
@@ -5990,7 +5979,7 @@ DoReadChars(
&& (statePtr->inEofChar == '\0');
if (appendFlag) {
if (binaryMode && (NULL == Tcl_GetByteArrayFromObj(objPtr, (size_t *)NULL))) {
if (binaryMode && (NULL == Tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)NULL))) {
binaryMode = 0;
}
} else {
@@ -7985,7 +7974,7 @@ Tcl_GetChannelOption(
Tcl_DStringAppendElement(dsPtr, "-profile");
}
/* Note currently input and output profiles are same */
profile = CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags);
profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags);
profileName = TclEncodingProfileIdToName(interp, profile);
if (profileName == NULL) {
return TCL_ERROR;
@@ -8180,11 +8169,11 @@ Tcl_SetChannelOption(
if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) {
encoding = Tcl_GetEncoding(NULL, "iso8859-1");
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags
,CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags)
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags
,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags)
|TCL_ENCODING_PROFILE_STRICT);
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags
,CHANNEL_PROFILE_GET(statePtr->outputEncodingFlags)
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags
,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags)
|TCL_ENCODING_PROFILE_STRICT);
} else {
encoding = Tcl_GetEncoding(interp, newValue);
@@ -8207,12 +8196,12 @@ Tcl_SetChannelOption(
Tcl_FreeEncoding(statePtr->encoding);
statePtr->encoding = encoding;
statePtr->inputEncodingState = NULL;
profile = CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags);
profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags);
statePtr->inputEncodingFlags = TCL_ENCODING_START;
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags, profile);
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, profile);
statePtr->outputEncodingState = NULL;
statePtr->outputEncodingFlags = TCL_ENCODING_START;
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags, profile); /* Same as input */
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags, profile); /* Same as input */
ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA|CHANNEL_ENCODING_ERROR);
UpdateInterest(chanPtr);
return TCL_OK;
@@ -8255,8 +8244,8 @@ Tcl_SetChannelOption(
if (TclEncodingProfileNameToId(interp, newValue, &profile) != TCL_OK) {
return TCL_ERROR;
}
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags, profile);
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags, profile);
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, profile);
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags, profile);
ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA|CHANNEL_ENCODING_ERROR);
return TCL_OK;
} else if (HaveOpt(1, "-translation")) {
@@ -8294,11 +8283,11 @@ Tcl_SetChannelOption(
statePtr->inEofChar = 0;
Tcl_FreeEncoding(statePtr->encoding);
statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1");
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags
,CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags)
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags
,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags)
|TCL_ENCODING_PROFILE_STRICT);
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags
,CHANNEL_PROFILE_GET(statePtr->outputEncodingFlags)
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags
,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags)
|TCL_ENCODING_PROFILE_STRICT);
} else if (strcmp(readMode, "lf") == 0) {
translation = TCL_TRANSLATE_LF;
@@ -8349,11 +8338,11 @@ Tcl_SetChannelOption(
statePtr->outputTranslation = TCL_TRANSLATE_LF;
Tcl_FreeEncoding(statePtr->encoding);
statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1");
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags
,CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags)
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags
,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags)
|TCL_ENCODING_PROFILE_STRICT);
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags
,CHANNEL_PROFILE_GET(statePtr->outputEncodingFlags)
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags
,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags)
|TCL_ENCODING_PROFILE_STRICT);
} else if (strcmp(writeMode, "lf") == 0) {
statePtr->outputTranslation = TCL_TRANSLATE_LF;
@@ -10280,8 +10269,8 @@ Lossless(
(
toRead == -1
&& inStatePtr->encoding == outStatePtr->encoding
&& CHANNEL_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
&& CHANNEL_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
&& ENCODING_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
&& ENCODING_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
)
);
}
-7
View File
@@ -288,13 +288,6 @@ typedef struct ChannelState {
#define CHANNEL_CLOSEDWRITE (1<<21) /* Channel write side has been closed.
* No further Tcl-level write IO on
* the channel is allowed. */
#define CHANNEL_PROFILE_MASK 0xFF000000
#define CHANNEL_PROFILE_GET(flags_) ((flags_) & CHANNEL_PROFILE_MASK)
#define CHANNEL_PROFILE_SET(flags_, profile_) \
do { \
(flags_) &= ~CHANNEL_PROFILE_MASK; \
(flags_) |= profile_; \
} while (0)
/*
* The length of time to wait between synthetic timer events. Must be zero or
+1 -1
View File
@@ -375,7 +375,7 @@ ExecuteCallback(
* interpreters. */
{
Tcl_Obj *resObj; /* See below, switch (transmit). */
size_t resLen = 0;
Tcl_Size resLen = 0;
unsigned char *resBuf;
Tcl_InterpState state = NULL;
int res = TCL_OK;
+9 -9
View File
@@ -264,7 +264,7 @@ struct ForwardParamTransform {
ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
char *buf; /* I: Bytes to transform,
* O: Bytes in transform result */
size_t size; /* I: #bytes to transform,
Tcl_Size size; /* I: #bytes to transform,
* O: #bytes in the transform result */
};
struct ForwardParamLimit {
@@ -2562,7 +2562,7 @@ ForwardProc(
* Sent it back to the request originator.
*/
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev;
/* Array of returned bytes */
@@ -2596,7 +2596,7 @@ ForwardProc(
* Sent it back to the request originator.
*/
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev;
/* Array of returned bytes */
@@ -2626,7 +2626,7 @@ ForwardProc(
* Sent it back to the request originator.
*/
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev; /* Array of returned bytes */
bytev = Tcl_GetByteArrayFromObj(resObj, &bytec);
@@ -2652,7 +2652,7 @@ ForwardProc(
* Sent it back to the request originator.
*/
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev;
/* Array of returned bytes */
@@ -3045,7 +3045,7 @@ TransformRead(
Tcl_Obj *bufObj)
{
Tcl_Obj *resObj;
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev; /* Array of returned bytes */
/*
@@ -3100,7 +3100,7 @@ TransformWrite(
{
Tcl_Obj *bufObj;
Tcl_Obj *resObj;
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev; /* Array of returned bytes */
int res;
@@ -3167,7 +3167,7 @@ TransformDrain(
int *errorCodePtr)
{
Tcl_Obj *resObj;
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev; /* Array of returned bytes */
/*
@@ -3216,7 +3216,7 @@ TransformFlush(
int op)
{
Tcl_Obj *resObj;
size_t bytec = 0; /* Number of returned bytes */
Tcl_Size bytec = 0; /* Number of returned bytes */
unsigned char *bytev; /* Array of returned bytes */
int res;
+25 -15
View File
@@ -2451,16 +2451,6 @@ typedef enum TclEolTranslation {
#define TCL_INVOKE_NO_UNKNOWN (1<<1)
#define TCL_INVOKE_NO_TRACEBACK (1<<2)
#if TCL_MAJOR_VERSION > 8
/*
* SSIZE_MAX, NOT SIZE_MAX as negative differences need to be expressed
* between values of the Tcl_Size type so limit the range to signed
*/
# define ListSizeT_MAX ((Tcl_Size)PTRDIFF_MAX)
#else
# define ListSizeT_MAX INT_MAX
#endif
/*
* ListStore --
*
@@ -2501,7 +2491,8 @@ typedef struct ListStore {
/* Max number of elements that can be contained in a list */
#define LIST_MAX \
((Tcl_Size)((ListSizeT_MAX - offsetof(ListStore, slots)) / sizeof(Tcl_Obj *)))
((Tcl_Size)(((size_t)TCL_SIZE_MAX - offsetof(ListStore, slots)) \
/ sizeof(Tcl_Obj *)))
/* Memory size needed for a ListStore to hold numSlots_ elements */
#define LIST_SIZE(numSlots_) \
((Tcl_Size)(offsetof(ListStore, slots) + ((numSlots_) * sizeof(Tcl_Obj *))))
@@ -2864,6 +2855,22 @@ typedef struct ProcessGlobalValue {
#define TCL_PARSE_NO_UNDERSCORE 128
/* Reject underscore digit separator */
/*
*----------------------------------------------------------------------
* Internal convenience macros for manipulating encoding flags. See
* TCL_ENCODING_PROFILE_* in tcl.h
*----------------------------------------------------------------------
*/
#define ENCODING_PROFILE_MASK 0xFF000000
#define ENCODING_PROFILE_GET(flags_) ((flags_) & ENCODING_PROFILE_MASK)
#define ENCODING_PROFILE_SET(flags_, profile_) \
do { \
(flags_) &= ~ENCODING_PROFILE_MASK; \
(flags_) |= profile_; \
} while (0)
/*
*----------------------------------------------------------------
* Variables shared among Tcl modules but not used by the outside world.
@@ -3228,7 +3235,6 @@ MODULE_SCOPE Tcl_Obj * TclGetHomeDirObj(Tcl_Interp *interp, const char *user);
MODULE_SCOPE Tcl_Obj * TclResolveTildePath(Tcl_Interp *interp,
Tcl_Obj *pathObj);
MODULE_SCOPE Tcl_Obj * TclResolveTildePathList(Tcl_Obj *pathsObj);
MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result);
MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp,
Tcl_Obj *listPtr, Tcl_Obj *argPtr);
@@ -3356,7 +3362,6 @@ MODULE_SCOPE void TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr,
void *data);
MODULE_SCOPE TCL_NORETURN void TclpThreadExit(int status);
MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex);
MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id);
MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex);
MODULE_SCOPE void TclRemoveScriptLimitCallbacks(Tcl_Interp *interp);
MODULE_SCOPE int TclReToGlob(Tcl_Interp *interp, const char *reStr,
@@ -3375,7 +3380,6 @@ MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr,
Tcl_Obj *newValue, Tcl_Encoding encoding);
MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result);
MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp,
Tcl_Obj *const *objv, Tcl_Size objc, Tcl_Size subIdx,
Tcl_Obj *bad, Tcl_Obj *fix);
@@ -3386,7 +3390,7 @@ MODULE_SCOPE int TclStringCmp(Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr,
int checkEq, int nocase, Tcl_Size reqlength);
MODULE_SCOPE int TclStringCmpOpts(Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[], int *nocase,
int *reqlength);
Tcl_Size *reqlength);
MODULE_SCOPE int TclStringMatch(const char *str, Tcl_Size strLen,
const char *pattern, int ptnLen, int flags);
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
@@ -4173,6 +4177,12 @@ MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr,
MODULE_SCOPE Tcl_Size TclIndexDecode(int encoded, Tcl_Size endValue);
MODULE_SCOPE int TclIndexInvalidError(Tcl_Interp *interp,
const char *idxType, Tcl_Size idx);
/*
* Error message utility functions
*/
MODULE_SCOPE int TclCommandWordLimitError(Tcl_Interp *interp, Tcl_Size count);
#endif /* TCL_MAJOR_VERSION > 8 */
/* Constants used in index value encoding routines. */
+18 -6
View File
@@ -850,7 +850,19 @@ ListStoreReallocate (ListStore *storePtr, Tcl_Size numSlots)
newCapacity = ListStoreUpSize(numSlots);
newStorePtr =
(ListStore *)Tcl_AttemptRealloc(storePtr, LIST_SIZE(newCapacity));
/*
* In case above failed keep looping reducing the requested extra space
* by half every time.
*/
while (newStorePtr == NULL && (newCapacity > (numSlots+1))) {
/* Because of loop condition newCapacity can't overflow */
newCapacity = numSlots + ((newCapacity - numSlots) / 2);
newStorePtr =
(ListStore *)Tcl_AttemptRealloc(storePtr, LIST_SIZE(newCapacity));
}
if (newStorePtr == NULL) {
/* Last resort - allcate what was asked */
newCapacity = numSlots;
newStorePtr = (ListStore *)Tcl_AttemptRealloc(storePtr,
LIST_SIZE(newCapacity));
@@ -2025,7 +2037,7 @@ Tcl_ListObjLength(
return TCL_OK;
}
Tcl_Size
Tcl_Size
ListLength(Tcl_Obj *listPtr)
{
ListRep listRep;
@@ -2110,12 +2122,12 @@ Tcl_ListObjReplace(
}
if (numToDelete < 0) {
numToDelete = 0;
} else if (first > ListSizeT_MAX - numToDelete /* Handle integer overflow */
} else if (first > LIST_MAX - numToDelete /* Handle integer overflow */
|| origListLen < first + numToDelete) {
numToDelete = origListLen - first;
}
if (numToInsert > ListSizeT_MAX - (origListLen - numToDelete)) {
if (numToInsert > LIST_MAX - (origListLen - numToDelete)) {
return ListLimitExceededError(interp);
}
@@ -2576,7 +2588,7 @@ TclLindexList(
* see TIP#22 and TIP#33 for the details.
*/
if (!TclHasInternalRep(argObj, &tclListType.objType)
&& TclGetIntForIndexM(NULL, argObj, ListSizeT_MAX - 1, &index)
&& TclGetIntForIndexM(NULL, argObj, TCL_SIZE_MAX - 1, &index)
== TCL_OK) {
/*
* argPtr designates a single index.
@@ -2702,7 +2714,7 @@ TclLindexFlat(
while (++i < indexCount) {
if (TclGetIntForIndexM(
interp, indexArray[i], ListSizeT_MAX - 1, &index)
interp, indexArray[i], TCL_SIZE_MAX - 1, &index)
!= TCL_OK) {
Tcl_DecrRefCount(sublistCopy);
return NULL;
@@ -2767,7 +2779,7 @@ TclLsetList(
*/
if (!TclHasInternalRep(indexArgObj, &tclListType.objType)
&& TclGetIntForIndexM(NULL, indexArgObj, ListSizeT_MAX - 1, &index)
&& TclGetIntForIndexM(NULL, indexArgObj, TCL_SIZE_MAX - 1, &index)
== TCL_OK) {
/* indexArgPtr designates a single index. */
/* T:listrep-1.{2.1,12.1,15.1,19.1},2.{2.3,9.3,10.1,13.1,16.1}, 3.{4,5,6}.3 */
+1 -1
View File
@@ -646,7 +646,7 @@ TclAddLiteralObj(
if (litPtrPtr) {
*litPtrPtr = lPtr;
}
return objIndex;
}
+1 -1
View File
@@ -63,7 +63,7 @@ typedef struct Tcl_ObjectContext_ *Tcl_ObjectContext;
typedef int (Tcl_MethodCallProc)(void *clientData, Tcl_Interp *interp,
Tcl_ObjectContext objectContext, int objc, Tcl_Obj *const *objv);
typedef int (Tcl_MethodCallProc2)(void *clientData, Tcl_Interp *interp,
Tcl_ObjectContext objectContext, ptrdiff_t objc, Tcl_Obj *const *objv);
Tcl_ObjectContext objectContext, Tcl_Size objc, Tcl_Obj *const *objv);
typedef void (Tcl_MethodDeleteProc)(void *clientData);
typedef int (Tcl_CloneProc)(Tcl_Interp *interp, void *oldClientData,
void **newClientData);
+3 -3
View File
@@ -1670,7 +1670,7 @@ char *
TclGetStringFromObj(
Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
* be returned. */
int *lengthPtr) /* If non-NULL, the location where the string
void *lengthPtr) /* If non-NULL, the location where the string
* rep's byte array length should * be stored.
* If NULL, no length is stored. */
{
@@ -1702,9 +1702,9 @@ TclGetStringFromObj(
if (lengthPtr != NULL) {
if (objPtr->length > INT_MAX) {
Tcl_Panic("Tcl_GetStringFromObj with 'int' lengthPtr"
" cannot handle such long strings. Please use 'size_t'");
" cannot handle such long strings. Please use 'Tcl_Size'");
}
*lengthPtr = (int)objPtr->length;
*(int *)lengthPtr = (int)objPtr->length;
}
return objPtr->bytes;
}
+8 -7
View File
@@ -214,7 +214,7 @@ Tcl_ParseCommand(
* command. */
char type; /* Result returned by CHAR_TYPE(*src). */
Tcl_Token *tokenPtr; /* Pointer to token being filled in. */
int wordIndex; /* Index of word token for current word. */
Tcl_Size wordIndex; /* Index of word token for current word. */
int terminators; /* CHAR_TYPE bits that indicate the end of a
* command. */
const char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to
@@ -327,7 +327,7 @@ Tcl_ParseCommand(
src = termPtr;
numBytes = parsePtr->end - src;
} else if (*src == '{') {
int expIdx = wordIndex + 1;
Tcl_Size expIdx = wordIndex + 1;
Tcl_Token *expPtr;
if (Tcl_ParseBraces(interp, src, numBytes, parsePtr, 1,
@@ -345,7 +345,7 @@ Tcl_ParseCommand(
expPtr = &parsePtr->tokenPtr[expIdx];
if ((0 == expandWord)
/* Haven't seen prefix already */
&& (expIdx + 1 == (int)parsePtr->numTokens)
&& (expIdx + 1 == parsePtr->numTokens)
/* Only one token */
&& (((1 == expPtr->size)
/* Same length as prefix */
@@ -380,7 +380,7 @@ Tcl_ParseCommand(
tokenPtr = &parsePtr->tokenPtr[wordIndex];
tokenPtr->size = src - tokenPtr->start;
tokenPtr->numComponents = (int)parsePtr->numTokens - (wordIndex + 1);
tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
if (expandWord) {
Tcl_Size i;
int isLiteral = 1;
@@ -407,7 +407,8 @@ Tcl_ParseCommand(
}
if (isLiteral) {
int elemCount = 0, code = TCL_OK, literal = 1;
Tcl_Size elemCount = 0;
int code = TCL_OK, literal = 1;
const char *nextElem, *listEnd, *elemStart;
/*
@@ -471,8 +472,8 @@ Tcl_ParseCommand(
*/
const char *listStart;
int growthNeeded = wordIndex + 2*elemCount
- (int)parsePtr->numTokens;
Tcl_Size growthNeeded = wordIndex + 2*elemCount
- parsePtr->numTokens;
parsePtr->numWords += elemCount - 1;
if (growthNeeded > 0) {
+58 -17
View File
@@ -11,6 +11,7 @@
#include "tclInt.h"
#include "tclTomMath.h"
#include <assert.h>
/*
* Flag values used by Tcl_ScanObjCmd.
@@ -258,7 +259,7 @@ ValidateFormat(
int *totalSubs) /* The number of variables that will be
* required. */
{
int gotXpg, gotSequential, value, i, flags;
int gotXpg, gotSequential, i, flags;
char *end;
Tcl_UniChar ch = 0;
int objIndex, xpgSize, nspace = numVars;
@@ -306,7 +307,8 @@ ValidateFormat(
* format string.
*/
value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */
/* assert(value is >= 0) because of the isdigit() check above */
unsigned long long ull = strtoull(format-1, &end, 10); /* INTL: "C" locale. */
if (*end != '$') {
goto notXpg;
}
@@ -316,17 +318,22 @@ ValidateFormat(
if (gotSequential) {
goto mixedXPG;
}
objIndex = value - 1;
if ((objIndex < 0) || (numVars && (objIndex >= numVars))) {
/* >=INT_MAX because 9.0 does not support more than INT_MAX-1 args */
if (ull == 0 || ull >= INT_MAX) {
goto badIndex;
} else if (numVars == 0) {
}
objIndex = (int) ull - 1;
if (numVars && (objIndex >= numVars)) {
goto badIndex;
}
else if (numVars == 0) {
/*
* In the case where no vars are specified, the user can
* specify %9999$ legally, so we have to consider special
* rules for growing the assign array. 'value' is guaranteed
* to be > 0.
* rules for growing the assign array. 'ull' is guaranteed
* to be > 0 and < INT_MAX as per checks above.
*/
xpgSize = (xpgSize > value) ? xpgSize : value;
xpgSize = (xpgSize > (int)ull) ? xpgSize : (int)ull;
}
goto xpgCheckDone;
}
@@ -348,7 +355,22 @@ ValidateFormat(
*/
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
value = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */
/* Note ull >= 0 because of isdigit check above */
unsigned long long ull;
ull = strtoull(
format - 1, (char **)&format, 10); /* INTL: "C" locale. */
/* Note >=, not >, to leave room for a nul */
if (ull >= TCL_SIZE_MAX) {
Tcl_SetObjResult(
interp,
Tcl_ObjPrintf("specified field width %" TCL_LL_MODIFIER
"u exceeds limit %" TCL_SIZE_MODIFIER "d.",
ull,
(Tcl_Size)TCL_SIZE_MAX-1));
Tcl_SetErrorCode(
interp, "TCL", "FORMAT", "WIDTHLIMIT", NULL);
goto error;
}
flags |= SCAN_WIDTH;
format += TclUtfToUniChar(format, &ch);
}
@@ -473,7 +495,7 @@ ValidateFormat(
* guaranteed to be at least one larger than objIndex.
*/
value = nspace;
int nspaceOrig = nspace;
if (xpgSize) {
nspace = xpgSize;
} else {
@@ -481,7 +503,7 @@ ValidateFormat(
}
nassign = (int *)TclStackRealloc(interp, nassign,
nspace * sizeof(int));
for (i = value; i < nspace; i++) {
for (i = nspaceOrig; i < nspace; i++) {
nassign[i] = 0;
}
}
@@ -575,7 +597,8 @@ Tcl_ScanObjCmd(
long value;
const char *string, *end, *baseString;
char op = 0;
int width, underflow = 0;
int underflow = 0;
Tcl_Size width;
Tcl_WideInt wideValue;
Tcl_UniChar ch = 0, sch = 0;
Tcl_Obj **objs = NULL, *objPtr = NULL;
@@ -670,6 +693,7 @@ Tcl_ScanObjCmd(
format += TclUtfToUniChar(format, &ch);
} else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
char *formatEnd;
/* Note currently XPG3 range limited to INT_MAX to match type of objc */
value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */
if (*formatEnd == '$') {
format = formatEnd+1;
@@ -683,7 +707,10 @@ Tcl_ScanObjCmd(
*/
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */
unsigned long long ull;
ull = strtoull(format-1, (char **) &format, 10); /* INTL: "C" locale. */
assert(ull <= TCL_SIZE_MAX); /* Else ValidateFormat should've error'ed */
width = (Tcl_Size)ull;
format += TclUtfToUniChar(format, &ch);
} else {
width = 0;
@@ -1067,12 +1094,15 @@ Tcl_ScanObjCmd(
} else {
/*
* Here no vars were specified, we want a list returned (inline scan)
* We create an empty Tcl_Obj to fill missing values rather than
* allocating a new Tcl_Obj every time. See test scan-bigdata-XX.
*/
Tcl_Obj *emptyObj = Tcl_NewObj();
Tcl_IncrRefCount(emptyObj);
TclNewObj(objPtr);
for (i = 0; i < totalVars; i++) {
for (i = 0; code == TCL_OK && i < totalVars; i++) {
if (objs[i] != NULL) {
Tcl_ListObjAppendElement(NULL, objPtr, objs[i]);
code = Tcl_ListObjAppendElement(interp, objPtr, objs[i]);
Tcl_DecrRefCount(objs[i]);
} else {
/*
@@ -1080,9 +1110,20 @@ Tcl_ScanObjCmd(
* empty strings for these.
*/
Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewObj());
code = Tcl_ListObjAppendElement(interp, objPtr, emptyObj);
}
}
Tcl_DecrRefCount(emptyObj);
if (code != TCL_OK) {
/* If error'ed out, free up remaining. i contains last index freed */
while (++i < totalVars) {
if (objs[i] != NULL) {
Tcl_DecrRefCount(objs[i]);
}
}
Tcl_DecrRefCount(objPtr);
objPtr = NULL;
}
}
if (objs != NULL) {
Tcl_Free(objs);
+75 -48
View File
@@ -1,29 +1,27 @@
/*
* tclStringObj.c --
*
* This file contains functions that implement string operations on Tcl
* objects. Some string operations work with UTF strings and others
* require Unicode format. Functions that require knowledge of the width
* of each character, such as indexing, operate on Unicode data.
* This file contains functions that implement string operations on Tcl
* objects. Some string operations work with UTF-8 encoding forms.
* Functions that require knowledge of the width of each character,
* such as indexing, operate on fixed width encoding forms such as UTF-32.
*
* A Unicode string is an internationalized string. Conceptually, a
* Unicode string is an array of 16-bit quantities organized as a
* sequence of properly formed UTF-8 characters. There is a one-to-one
* map between Unicode and UTF characters. Because Unicode characters
* have a fixed width, operations such as indexing operate on Unicode
* data. The String object is optimized for the case where each UTF char
* Conceptually, a string is a sequence of Unicode code points. Internally
* it may be stored in an encoding form such as a modified version of
* UTF-8 or UTF-16 (when TCL_UTF_MAX=3) or UTF-32.
*
* The String object is optimized for the case where each UTF char
* in a string is only one byte. In this case, we store the value of
* numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
* is explicitly called).
* numChars, but we don't store the fixed form encoding (unless
* Tcl_GetUnicode is explicitly called).
*
* The String object type stores one or both formats. The default
* behavior is to store UTF. Once Unicode is calculated by a function, it
* is stored in the internal rep for future access (without an additional
* O(n) cost).
* The String object type stores one or both formats. The default
* behavior is to store UTF-8. Once UTF-16/UTF32 is calculated, it is
* stored in the internal rep for future access (without an additional
* O(n) cost).
*
* To allow many appends to be done to an object without constantly
* reallocating the space for the string or Unicode representation, we
* allocate double the space for the string or Unicode and use the
* reallocating space, we allocate double the space and use the
* internal representation to keep track of how much space is used vs.
* allocated.
*
@@ -515,6 +513,11 @@ TclCheckEmptyString(
return TCL_EMPTYSTRING_YES;
}
if (TclIsPureByteArray(objPtr)
&& Tcl_GetCharLength(objPtr) == 0) {
return TCL_EMPTYSTRING_YES;
}
if (TclListObjIsCanonical(objPtr)) {
TclListObjLengthM(NULL, objPtr, &length);
return length == 0;
@@ -685,7 +688,7 @@ Tcl_UniChar *
TclGetUnicodeFromObj(
Tcl_Obj *objPtr, /* The object to find the Unicode string
* for. */
int *lengthPtr) /* If non-NULL, the location where the string
void *lengthPtr) /* If non-NULL, the location where the string
* rep's Tcl_UniChar length should be stored. If
* NULL, no length is stored. */
{
@@ -704,7 +707,7 @@ TclGetUnicodeFromObj(
Tcl_Panic("Tcl_GetUnicodeFromObj with 'int' lengthPtr"
" cannot handle such long strings. Please use 'Tcl_Size'");
}
*lengthPtr = (int)stringPtr->numChars;
*(int *)lengthPtr = (int)stringPtr->numChars;
}
return stringPtr->unicode;
}
@@ -1431,26 +1434,26 @@ Tcl_AppendObjToObj(
Tcl_Size appendNumChars = TCL_INDEX_NONE;
const char *bytes;
/*
* Special case: second object is standard-empty is fast case. We know
* that appending nothing to anything leaves that starting anything...
*/
if (appendObjPtr->bytes == &tclEmptyString) {
if (TclCheckEmptyString(appendObjPtr) == TCL_EMPTYSTRING_YES) {
return;
}
/*
* Handle append of one ByteArray object to another as a special case.
* Note that we only do this when the objects are pure so that the
* bytearray faithfully represent the true value; Otherwise appending the
* byte arrays together could lose information;
*/
if (TclCheckEmptyString(objPtr) == TCL_EMPTYSTRING_YES) {
TclSetDuplicateObj(objPtr, appendObjPtr);
return;
}
if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
&& TclIsPureByteArray(appendObjPtr)) {
if (
TclIsPureByteArray(appendObjPtr)
&& (TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
) {
/*
* You might expect the code here to be
* Both bytearray objects are pure, so the second internal bytearray value
* can be appended to the first, with no need to modify the "bytes" field.
*/
/*
* One might expect the code here to be
*
* bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length);
* TclAppendBytesToByteArray(objPtr, bytes, length);
@@ -2006,12 +2009,16 @@ Tcl_AppendFormatToObj(
width = 0;
if (isdigit(UCHAR(ch))) {
width = strtoul(format, &end, 10);
if (width < 0) {
/* Note ull will be >= 0 because of isdigit check above */
unsigned long long ull;
ull = strtoull(format, &end, 10);
/* Comparison is >=, not >, to leave room for nul */
if (ull >= TCL_SIZE_MAX) {
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
width = (Tcl_Size)ull;
format = end;
step = TclUtfToUniChar(format, &ch);
} else if (ch == '*') {
@@ -2048,7 +2055,16 @@ Tcl_AppendFormatToObj(
step = TclUtfToUniChar(format, &ch);
}
if (isdigit(UCHAR(ch))) {
precision = strtoul(format, &end, 10);
/* Note ull will be >= 0 because of isdigit check above */
unsigned long long ull;
ull = strtoull(format, &end, 10);
/* Comparison is >=, not >, to leave room for nul */
if (ull >= TCL_SIZE_MAX) {
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
precision = (Tcl_Size)ull;
format = end;
step = TclUtfToUniChar(format, &ch);
} else if (ch == '*') {
@@ -3126,7 +3142,7 @@ TclStringCat(
int allowUniChar = 1, requestUniChar = 0, forceUniChar = 0;
Tcl_Size first = objc - 1; /* Index of first value possibly not empty */
Tcl_Size last = 0; /* Index of last value possibly not empty */
int inPlace = flags & TCL_STRING_IN_PLACE;
int inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);
/* assert ( objc >= 0 ) */
@@ -3254,7 +3270,8 @@ TclStringCat(
Tcl_Obj *objPtr = *ov++;
if (objPtr->bytes == NULL) {
if (objPtr->bytes == NULL
&& TclCheckEmptyString(objPtr) != TCL_EMPTYSTRING_YES) {
/* No string rep; Take the chance we can avoid making it */
pendingPtr = objPtr;
} else {
@@ -3330,6 +3347,7 @@ TclStringCat(
}
objv += first; objc = (last - first + 1);
inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);
if (binary) {
/* Efficiently produce a pure byte array result */
@@ -3340,7 +3358,7 @@ TclStringCat(
* failure to allocate enough space. Following stanza may panic.
*/
if (inPlace && !Tcl_IsShared(*objv)) {
if (inPlace) {
Tcl_Size start = 0;
objResultPtr = *objv++; objc--;
@@ -3370,7 +3388,7 @@ TclStringCat(
/* Efficiently produce a pure Tcl_UniChar array result */
Tcl_UniChar *dst;
if (inPlace && !Tcl_IsShared(*objv)) {
if (inPlace) {
Tcl_Size start;
objResultPtr = *objv++; objc--;
@@ -3421,7 +3439,7 @@ TclStringCat(
/* Efficiently concatenate string reps */
char *dst;
if (inPlace && !Tcl_IsShared(*objv)) {
if (inPlace) {
Tcl_Size start;
objResultPtr = *objv++; objc--;
@@ -3512,6 +3530,7 @@ TclStringCmp(
if ((reqlength == 0) || (value1Ptr == value2Ptr)) {
/*
* Always match at 0 chars of if it is the same obj.
* Note: as documented reqlength negative means it is ignored
*/
match = 0;
} else {
@@ -3566,7 +3585,7 @@ TclStringCmp(
memCmpFn = memcmp;
s1len *= sizeof(Tcl_UniChar);
s2len *= sizeof(Tcl_UniChar);
if (reqlength != TCL_INDEX_NONE) {
if (reqlength > 0) {
reqlength *= sizeof(Tcl_UniChar);
}
} else {
@@ -3610,7 +3629,7 @@ TclStringCmp(
s1 = Tcl_GetStringFromObj(value1Ptr, &s1len);
s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
}
if (!nocase && checkEq && reqlength == TCL_INDEX_NONE) {
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
@@ -3627,7 +3646,7 @@ TclStringCmp(
* length was requested.
*/
if ((reqlength == TCL_INDEX_NONE) && !nocase) {
if ((reqlength < 0) && !nocase) {
memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
} else {
s1len = Tcl_NumUtfChars(s1, s1len);
@@ -3643,7 +3662,7 @@ TclStringCmp(
* comparison function.
*/
length = (s1len < s2len) ? s1len : s2len;
if (reqlength == TCL_INDEX_NONE) {
if (reqlength < 0) {
/*
* The requested length is negative, so ignore it by setting it
* to length + 1 to correct the match var.
@@ -3654,7 +3673,7 @@ TclStringCmp(
length = reqlength;
}
if (checkEq && reqlength == TCL_INDEX_NONE && (s1len != s2len)) {
if (checkEq && reqlength < 0 && (s1len != s2len)) {
match = 1; /* This will be reversed below. */
} else {
/*
@@ -4483,6 +4502,14 @@ ExtendStringRepWithUnicode(
copyBytes:
dst = objPtr->bytes + origLength;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(dst, 0xff, stringPtr->allocated - origLength);
#endif
for (i = 0; i < numChars; i++) {
dst += Tcl_UniCharToUtf(unicode[i], dst);
}
+13 -35
View File
@@ -1,29 +1,12 @@
/*
* tclStringRep.h --
*
* This file contains the definition of the Unicode string internal
* representation and macros to access it.
* This file contains the definition of internal representations of a string
* and macros to access it.
*
* A Unicode string is an internationalized string. Conceptually, a
* Unicode string is an array of 16-bit quantities organized as a
* sequence of properly formed UTF-8 characters. There is a one-to-one
* map between Unicode and UTF characters. Because Unicode characters
* have a fixed width, operations such as indexing operate on Unicode
* data. The String object is optimized for the case where each UTF char
* in a string is only one byte. In this case, we store the value of
* numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
* is explicitly called).
*
* The String object type stores one or both formats. The default
* behavior is to store UTF. Once Unicode is calculated by a function, it
* is stored in the internal rep for future access (without an additional
* O(n) cost).
*
* To allow many appends to be done to an object without constantly
* reallocating the space for the string or Unicode representation, we
* allocate double the space for the string or Unicode and use the
* internal representation to keep track of how much space is used vs.
* allocated.
* Conceptually, a string is a sequence of Unicode code points. Internally
* it may be stored in an encoding form such as a modified version of UTF-8
* or UTF-16 (when TCL_UTF_MAX=3) or UTF-32.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1999 by Scriptics Corporation.
@@ -39,15 +22,10 @@
/*
* The following structure is the internal rep for a String object. It keeps
* track of how much memory has been used and how much has been allocated for
* the Unicode and UTF string to enable growing and shrinking of the UTF and
* Unicode reps of the String object with fewer mallocs. To optimize string
* the various representations to enable growing and shrinking of
* the String object with fewer mallocs. To optimize string
* length and indexing operations, this structure also stores the number of
* characters (same of UTF and Unicode!) once that value has been computed.
*
* Under normal configurations, what Tcl calls "Unicode" is actually UTF-16
* restricted to the Basic Multilingual Plane (i.e. U+00000 to U+0FFFF). This
* can be officially modified by altering the definition of Tcl_UniChar in
* tcl.h, but do not do that unless you are sure what you're doing!
* code points (independent of encoding form) once that value has been computed.
*/
typedef struct {
@@ -57,15 +35,15 @@ typedef struct {
* Unicode rep, or that the number of UTF bytes ==
* the number of chars. */
Tcl_Size allocated; /* The amount of space actually allocated for
* the UTF string (minus 1 byte for the
* the UTF-8 string (minus 1 byte for the
* termination char). */
Tcl_Size maxChars; /* Max number of chars that can fit in the
* space allocated for the Unicode array. */
int hasUnicode; /* Boolean determining whether the string has
* a Unicode representation. */
Tcl_UniChar unicode[TCLFLEXARRAY]; /* The array of Unicode chars. The actual size
* of this field depends on the 'maxChars'
* field above. */
* a Tcl_UniChar representation. */
Tcl_UniChar unicode[TCLFLEXARRAY]; /* The array of Tcl_UniChar units.
* The actual size of this field depends on
* the maxChars field above. */
} String;
/* Limit on string lengths. The -1 because limit does not include the nul */
+15 -15
View File
@@ -123,7 +123,7 @@ static void uniCodePanic() {
# define TclParseArgsObjv 0
#else /* !defined(TCL_NO_DEPRECATED) */
int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
int *objcPtr, Tcl_Obj ***objvPtr) {
void *objcPtr, Tcl_Obj ***objvPtr) {
Tcl_Size n = TCL_INDEX_NONE;
int result = Tcl_ListObjGetElements(interp, listPtr, &n, objvPtr);
if (objcPtr) {
@@ -133,12 +133,12 @@ int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
}
return TCL_ERROR;
}
*objcPtr = n;
*(int *)objcPtr = (int)n;
}
return result;
}
int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
int *lengthPtr) {
void *lengthPtr) {
Tcl_Size n = TCL_INDEX_NONE;
int result = Tcl_ListObjLength(interp, listPtr, &n);
if (lengthPtr) {
@@ -148,12 +148,12 @@ int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
}
return TCL_ERROR;
}
*lengthPtr = n;
*(int *)lengthPtr = (int)n;
}
return result;
}
int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
int *sizePtr) {
void *sizePtr) {
Tcl_Size n = TCL_INDEX_NONE;
int result = Tcl_DictObjSize(interp, dictPtr, &n);
if (sizePtr) {
@@ -163,11 +163,11 @@ int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
}
return TCL_ERROR;
}
*sizePtr = n;
*(int *)sizePtr = (int)n;
}
return result;
}
int TclSplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
int TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr,
const char ***argvPtr) {
Tcl_Size n = TCL_INDEX_NONE;
int result = Tcl_SplitList(interp, listStr, &n, argvPtr);
@@ -179,11 +179,11 @@ int TclSplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
Tcl_Free((void *)*argvPtr);
return TCL_ERROR;
}
*argcPtr = n;
*(int *)argcPtr = (int)n;
}
return result;
}
void TclSplitPath(const char *path, int *argcPtr, const char ***argvPtr) {
void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr) {
Tcl_Size n = TCL_INDEX_NONE;
Tcl_SplitPath(path, &n, argvPtr);
if (argcPtr) {
@@ -192,10 +192,10 @@ void TclSplitPath(const char *path, int *argcPtr, const char ***argvPtr) {
Tcl_Free((void *)*argvPtr);
*argvPtr = NULL;
}
*argcPtr = n;
*(int *)argcPtr = (int)n;
}
}
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr) {
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr) {
Tcl_Size n = TCL_INDEX_NONE;
Tcl_Obj *result = Tcl_FSSplitPath(pathPtr, &n);
if (lenPtr) {
@@ -203,16 +203,16 @@ Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr) {
Tcl_DecrRefCount(result);
return NULL;
}
*lenPtr = n;
*(int *)lenPtr = (int)n;
}
return result;
}
int TclParseArgsObjv(Tcl_Interp *interp,
const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv,
const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv,
Tcl_Obj ***remObjv) {
Tcl_Size n = (*objcPtr < 0) ? TCL_INDEX_NONE: *objcPtr ;
Tcl_Size n = (*(int *)objcPtr < 0) ? TCL_INDEX_NONE: (Tcl_Size)*(int *)objcPtr ;
int result = Tcl_ParseArgsObjv(interp, argTable, &n, objv, remObjv);
*objcPtr = (int)n;
*(int *)objcPtr = (int)n;
return result;
}
#endif /* !defined(TCL_NO_DEPRECATED) */
+125 -29
View File
@@ -224,7 +224,8 @@ static Tcl_ObjCmdProc TestbytestringObjCmd;
static Tcl_ObjCmdProc TestsetbytearraylengthObjCmd;
static Tcl_ObjCmdProc TestpurebytesobjObjCmd;
static Tcl_ObjCmdProc TeststringbytesObjCmd;
static Tcl_CmdProc TestcmdinfoCmd;
static Tcl_ObjCmdProc2 Testcmdobj2ObjCmd;
static Tcl_ObjCmdProc TestcmdinfoObjCmd;
static Tcl_CmdProc TestcmdtokenCmd;
static Tcl_CmdProc TestcmdtraceCmd;
static Tcl_CmdProc TestconcatobjCmd;
@@ -586,7 +587,9 @@ Tcltest_Init(
NULL, NULL);
Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL,
NULL);
Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, NULL,
Tcl_CreateObjCommand2(interp, "testcmdobj2", Testcmdobj2ObjCmd,
NULL, NULL);
Tcl_CreateObjCommand(interp, "testcmdinfo", TestcmdinfoObjCmd, NULL,
NULL);
Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
NULL, NULL);
@@ -1061,7 +1064,41 @@ TestbumpinterpepochObjCmd(
/*
*----------------------------------------------------------------------
*
* TestcmdinfoCmd --
* Testcmdobj2 --
*
* Mock up to test the Tcl_CreateCommandObj2 functionality
*
* Results:
* Standard Tcl result.
*
* Side effects:
* Sets interpreter result to number of arguments, first arg, last arg.
*
*----------------------------------------------------------------------
*/
static int
Testcmdobj2ObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
Tcl_Size objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Obj *resultObj;
resultObj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewWideIntObj(objc));
if (objc > 1) {
Tcl_ListObjAppendElement(interp, resultObj, objv[1]);
Tcl_ListObjAppendElement(interp, resultObj, objv[objc-1]);
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestcmdinfoObjCmd --
*
* This procedure implements the "testcmdinfo" command. It is used to
* test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation and
@@ -1077,28 +1114,69 @@ TestbumpinterpepochObjCmd(
*/
static int
TestcmdinfoCmd(
TestcmdinfoObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
const char **argv) /* Argument strings. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
static const char *const subcmds[] = {
"call", "call2", "create", "delete", "get", "modify", NULL
};
enum options {
CMDINFO_CALL, CMDINFO_CALL2, CMDINFO_CREATE,
CMDINFO_DELETE, CMDINFO_GET, CMDINFO_MODIFY
} idx;
Tcl_CmdInfo info;
Tcl_Obj **cmdObjv;
Tcl_Size cmdObjc;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option cmdName\"", NULL);
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "command arg");
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
Tcl_CreateCommand(interp, argv[2], CmdProc1, (void *) "original",
CmdDelProc1);
} else if (strcmp(argv[1], "delete") == 0) {
if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
&idx) != TCL_OK) {
return TCL_ERROR;
}
switch (idx) {
case CMDINFO_CALL:
case CMDINFO_CALL2:
if (Tcl_ListObjGetElements(interp, objv[2], &cmdObjc, &cmdObjv) != TCL_OK) {
return TCL_ERROR;
}
if (cmdObjc == 0) {
Tcl_AppendResult(interp, "No command name given", NULL);
return TCL_ERROR;
}
if (Tcl_GetCommandInfo(interp, Tcl_GetString(cmdObjv[0]), &info) == 0) {
return TCL_ERROR;
}
if (idx == CMDINFO_CALL) {
/*
* Note when calling through the old 32-bit API, it is the caller's
* responsibility to check that number of arguments is <= INT_MAX.
* We do not do that here just so we can test what happens if the
* caller mistakenly passes more arguments.
*/
return info.objProc(info.objClientData, interp, cmdObjc, cmdObjv);
} else {
return info.objProc2(info.objClientData2, interp, cmdObjc, cmdObjv);
}
case CMDINFO_CREATE:
Tcl_CreateCommand(interp,
Tcl_GetString(objv[2]),
CmdProc1,
(void *)"original",
CmdDelProc1);
break;
case CMDINFO_DELETE:
Tcl_DStringInit(&delString);
Tcl_DeleteCommand(interp, argv[2]);
Tcl_DeleteCommand(interp, Tcl_GetString(objv[2]));
Tcl_DStringResult(interp, &delString);
} else if (strcmp(argv[1], "get") == 0) {
if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) {
break;
case CMDINFO_GET:
if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ==0) {
Tcl_AppendResult(interp, "??", NULL);
return TCL_OK;
}
@@ -1121,28 +1199,35 @@ TestcmdinfoCmd(
Tcl_AppendResult(interp, " unknown", NULL);
}
Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, NULL);
if (info.isNativeObjectProc) {
Tcl_AppendResult(interp, " nativeObjectProc", NULL);
} else {
if (info.isNativeObjectProc == 0) {
Tcl_AppendResult(interp, " stringProc", NULL);
} else if (info.isNativeObjectProc == 1) {
Tcl_AppendResult(interp, " nativeObjectProc", NULL);
} else if (info.isNativeObjectProc == 2) {
Tcl_AppendResult(interp, " nativeObjectProc2", NULL);
} else {
Tcl_SetObjResult(
interp,
Tcl_ObjPrintf("Invalid isNativeObjectProc value %d",
info.isNativeObjectProc));
return TCL_ERROR;
}
} else if (strcmp(argv[1], "modify") == 0) {
break;
case CMDINFO_MODIFY:
info.proc = CmdProc2;
info.clientData = (void *) "new_command_data";
info.objProc = NULL;
info.objClientData = NULL;
info.deleteProc = CmdDelProc2;
info.deleteData = (void *) "new_delete_data";
if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
if (Tcl_SetCommandInfo(interp, Tcl_GetString(objv[2]), &info) == 0) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
} else {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
}
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, delete, get, or modify", NULL);
return TCL_ERROR;
break;
}
return TCL_OK;
}
@@ -5677,7 +5762,14 @@ TestbytestringObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* The argument objects. */
{
Tcl_Size n = 0;
struct {
#if !defined(TCL_NO_DEPRECATED)
int n; /* On purpose, not Tcl_Size, in order to demonstrate what happens */
#else
Tcl_Size n;
#endif
int m; /* This variable should not be overwritten */
} x = {0, 1};
const char *p;
if (objc != 2) {
@@ -5685,11 +5777,15 @@ TestbytestringObjCmd(
return TCL_ERROR;
}
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &n);
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n);
if (p == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n));
if (x.m != 1) {
Tcl_AppendResult(interp, "Tcl_GetBytesFromObj() overwrites variable", NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, x.n));
return TCL_OK;
}
@@ -6765,7 +6861,7 @@ TestWrongNumArgsObjCmd(
Tcl_Size i, length;
const char *msg;
if (objc + 1 < 4) {
if (objc < 3) {
goto insufArgs;
}
-318
View File
@@ -1,318 +0,0 @@
/*
* tclThreadJoin.c --
*
* This file implements a platform independent emulation layer for the
* handling of joinable threads. The Windows platform uses this code to
* provide the functionality of joining threads. This code is currently
* not necessary on Unix.
*
* Copyright © 2000 Scriptics Corporation
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#ifdef _WIN32
/*
* The information about each joinable thread is remembered in a structure as
* defined below.
*/
typedef struct JoinableThread {
Tcl_ThreadId id; /* The id of the joinable thread. */
int result; /* A place for the result after the demise of
* the thread. */
int done; /* Boolean flag. Initialized to 0 and set to 1
* after the exit of the thread. This allows a
* thread requesting a join to detect when
* waiting is not necessary. */
int waitedUpon; /* Boolean flag. Initialized to 0 and set to 1
* by the thread waiting for this one via
* Tcl_JoinThread. Used to lock any other
* thread trying to wait on this one. */
Tcl_Mutex threadMutex; /* The mutex used to serialize access to this
* structure. */
Tcl_Condition cond; /* This is the condition a thread has to wait
* upon to get notified of the end of the
* described thread. It is signaled indirectly
* by Tcl_ExitThread. */
struct JoinableThread *nextThreadPtr;
/* Reference to the next thread in the list of
* joinable threads. */
} JoinableThread;
/*
* The following variable is used to maintain the global list of all joinable
* threads. Usage by a thread is allowed only if the thread acquired the
* 'joinMutex'.
*/
TCL_DECLARE_MUTEX(joinMutex)
static JoinableThread *firstThreadPtr;
/*
*----------------------------------------------------------------------
*
* TclJoinThread --
*
* This procedure waits for the exit of the thread with the specified id
* and returns its result.
*
* Results:
* A standard tcl result signaling the overall success/failure of the
* operation and an integer result delivered by the thread which was
* waited upon.
*
* Side effects:
* Deallocates the memory allocated by TclRememberJoinableThread.
* Removes the data associated to the thread waited upon from the list of
* joinable threads.
*
*----------------------------------------------------------------------
*/
int
TclJoinThread(
Tcl_ThreadId id, /* The id of the thread to wait upon. */
int *result) /* Reference to a location for the result of
* the thread we are waiting upon. */
{
JoinableThread *threadPtr;
/*
* Steps done here:
* i. Acquire the joinMutex and search for the thread.
* ii. Error out if it could not be found.
* iii. If found, switch from exclusive access to the list to exclusive
* access to the thread structure.
* iv. Error out if some other is already waiting.
* v. Skip the waiting part of the thread is already done.
* vi. Wait for the thread to exit, mark it as waited upon too.
* vii. Get the result form the structure,
* viii. switch to exclusive access of the list,
* ix. remove the structure from the list,
* x. then switch back to exclusive access to the structure
* xi. and delete it.
*/
Tcl_MutexLock(&joinMutex);
threadPtr = firstThreadPtr;
while (threadPtr!=NULL && threadPtr->id!=id) {
threadPtr = threadPtr->nextThreadPtr;
}
if (threadPtr == NULL) {
/*
* Thread not found. Either not joinable, or already waited upon and
* exited. Whatever, an error is in order.
*/
Tcl_MutexUnlock(&joinMutex);
return TCL_ERROR;
}
/*
* [1] If we don't lock the structure before giving up exclusive access to
* the list some other thread just completing its wait on the same thread
* can delete the structure from under us, leaving us with a dangling
* pointer.
*/
Tcl_MutexLock(&threadPtr->threadMutex);
Tcl_MutexUnlock(&joinMutex);
/*
* [2] Now that we have the structure mutex any other thread that just
* tries to delete structure will wait at location [3] until we are done
* with the structure. And in that case we are done with it rather quickly
* as 'waitedUpon' will be set and we will have to error out.
*/
if (threadPtr->waitedUpon) {
Tcl_MutexUnlock(&threadPtr->threadMutex);
return TCL_ERROR;
}
/*
* We are waiting now, let other threads recognize this.
*/
threadPtr->waitedUpon = 1;
while (!threadPtr->done) {
Tcl_ConditionWait(&threadPtr->cond, &threadPtr->threadMutex, NULL);
}
/*
* We have to release the structure before trying to access the list again
* or we can run into deadlock with a thread at [1] (see above) because of
* us holding the structure and the other holding the list. There is no
* problem with dangling pointers here as 'waitedUpon == 1' is still valid
* and any other thread will error out and not come to this place. IOW,
* the fact that we are here also means that no other thread came here
* before us and is able to delete the structure.
*/
Tcl_MutexUnlock(&threadPtr->threadMutex);
Tcl_MutexLock(&joinMutex);
/*
* We have to search the list again as its structure may (may, almost
* certainly) have changed while we were waiting. Especially now is the
* time to compute the predecessor in the list. Any earlier result can be
* dangling by now.
*/
if (firstThreadPtr == threadPtr) {
firstThreadPtr = threadPtr->nextThreadPtr;
} else {
JoinableThread *prevThreadPtr = firstThreadPtr;
while (prevThreadPtr->nextThreadPtr != threadPtr) {
prevThreadPtr = prevThreadPtr->nextThreadPtr;
}
prevThreadPtr->nextThreadPtr = threadPtr->nextThreadPtr;
}
Tcl_MutexUnlock(&joinMutex);
/*
* [3] Now that the structure is not part of the list anymore no other
* thread can acquire its mutex from now on. But it is possible that
* another thread is still holding the mutex though, see location [2]. So
* we have to acquire the mutex one more time to wait for that thread to
* finish. We can (and have to) release the mutex immediately.
*/
Tcl_MutexLock(&threadPtr->threadMutex);
Tcl_MutexUnlock(&threadPtr->threadMutex);
/*
* Copy the result to us, finalize the synchronisation objects, then free
* the structure and return.
*/
*result = threadPtr->result;
Tcl_ConditionFinalize(&threadPtr->cond);
Tcl_MutexFinalize(&threadPtr->threadMutex);
Tcl_Free(threadPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclRememberJoinableThread --
*
* This procedure remembers a thread as joinable. Only a call to
* TclJoinThread will remove the structure created (and initialized) here.
* IOW, not waiting upon a joinable thread will cause memory leaks.
*
* Results:
* None.
*
* Side effects:
* Allocates memory, adds it to the global list of all joinable threads.
*
*----------------------------------------------------------------------
*/
void
TclRememberJoinableThread(
Tcl_ThreadId id) /* The thread to remember as joinable */
{
JoinableThread *threadPtr;
threadPtr = (JoinableThread *)Tcl_Alloc(sizeof(JoinableThread));
threadPtr->id = id;
threadPtr->done = 0;
threadPtr->waitedUpon = 0;
threadPtr->threadMutex = (Tcl_Mutex) NULL;
threadPtr->cond = (Tcl_Condition) NULL;
Tcl_MutexLock(&joinMutex);
threadPtr->nextThreadPtr = firstThreadPtr;
firstThreadPtr = threadPtr;
Tcl_MutexUnlock(&joinMutex);
}
/*
*----------------------------------------------------------------------
*
* TclSignalExitThread --
*
* This procedure signals that the specified thread is done with its
* work. If the thread is joinable this signal is propagated to the
* thread waiting upon it.
*
* Results:
* None.
*
* Side effects:
* Modifies the associated structure to hold the result.
*
*----------------------------------------------------------------------
*/
void
TclSignalExitThread(
Tcl_ThreadId id, /* Id of the thread signaling its exit. */
int result) /* The result from the thread. */
{
JoinableThread *threadPtr;
Tcl_MutexLock(&joinMutex);
threadPtr = firstThreadPtr;
while ((threadPtr != NULL) && (threadPtr->id != id)) {
threadPtr = threadPtr->nextThreadPtr;
}
if (threadPtr == NULL) {
/*
* Thread not found. Not joinable. No problem, nothing to do.
*/
Tcl_MutexUnlock(&joinMutex);
return;
}
/*
* Switch over the exclusive access from the list to the structure, then
* store the result, set the flag and notify the waiting thread, provided
* that it exists. The order of lock/unlock ensures that a thread entering
* 'TclJoinThread' will not interfere with us.
*/
Tcl_MutexLock(&threadPtr->threadMutex);
Tcl_MutexUnlock(&joinMutex);
threadPtr->done = 1;
threadPtr->result = result;
if (threadPtr->waitedUpon) {
Tcl_ConditionNotify(&threadPtr->cond);
}
Tcl_MutexUnlock(&threadPtr->threadMutex);
}
#else
TCL_MAC_EMPTY_FILE(generic_tclThreadJoin_c)
#endif /* _WIN32 */
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
+20
View File
@@ -348,6 +348,16 @@ Tcl_UniCharToUtfDString(
p = string;
wEnd = uniStr + uniLength;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
* prior non-stateful nature, this call to memset can also be removed.
*/
memset(p, 0xff, Tcl_DStringLength(dsPtr) - oldLength);
#endif
for (w = uniStr; w < wEnd; ) {
p += Tcl_UniCharToUtf(*w, p);
w++;
@@ -391,6 +401,16 @@ Tcl_Char16ToUtfDString(
p = string;
wEnd = uniStr + uniLength;
#if TCL_UTF_MAX < 4
/* Initialize the buffer so that some random data doesn't trick
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
* Because TCL_COMBINE is used here, memset() is required even when
* TCL_UTF_MAX == 4.
*/
memset(p, 0xff, Tcl_DStringLength(dsPtr) - oldLength);
#endif
for (w = uniStr; w < wEnd; ) {
if (!len && ((*w & 0xFC00) != 0xDC00)) {
/* Special case for handling high surrogates. */
+42 -2
View File
@@ -3679,8 +3679,8 @@ GetEndOffsetFromObj(
offset = irPtr->wideValue;
if (offset == WIDE_MAX) {
/*
* Encodes end+1. This is distinguished from end+n as noted above
/*
* Encodes end+1. This is distinguished from end+n as noted above
* NOTE: this may wrap around if the caller passes (as lset does)
* listLen-1 as endValue and and listLen is 0. The -1 will be
* interpreted as FF...FF and adding 1 will result in 0 which
@@ -3976,6 +3976,46 @@ TclIndexInvalidError (
return TCL_ERROR; /* Always */
}
/*
*------------------------------------------------------------------------
*
* TclCommandWordLimitErrpr --
*
* Generates an error message limit on number of command words exceeded.
*
* Results:
* Always return TCL_ERROR.
*
* Side effects:
* If interp is not-NULL, an error message is stored in it.
*
*------------------------------------------------------------------------
*/
int
TclCommandWordLimitError (
Tcl_Interp *interp, /* May be NULL */
Tcl_Size count) /* If <= 0, "unknown" */
{
if (interp) {
if (count > 0) {
Tcl_SetObjResult(
interp,
Tcl_ObjPrintf("Number of words (%" TCL_SIZE_MODIFIER
"d) in command exceeds limit %" TCL_SIZE_MODIFIER
"d.",
count,
(Tcl_Size)INT_MAX));
}
else {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Number of words in command exceeds "
"limit %" TCL_SIZE_MODIFIER "d.",
(Tcl_Size)INT_MAX));
}
}
return TCL_ERROR; /* Always */
}
/*
*----------------------------------------------------------------------
*
+1 -1
View File
@@ -5140,7 +5140,7 @@ ZipFSMatchMountPoints(
{
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
size_t l;
size_t l;
Tcl_Size normLength;
const char *path = Tcl_GetStringFromObj(normPathPtr, &normLength);
size_t len = normLength;
+1 -1
View File
@@ -3761,7 +3761,7 @@ ZlibStackChannelTransform(
if (compDictObj != NULL) {
cd->compDictObj = Tcl_DuplicateObj(compDictObj);
Tcl_IncrRefCount(cd->compDictObj);
Tcl_GetByteArrayFromObj(cd->compDictObj, (size_t *)NULL);
Tcl_GetByteArrayFromObj(cd->compDictObj, (Tcl_Size *)NULL);
}
if (format == TCL_ZLIB_FORMAT_RAW) {
-2
View File
@@ -129,8 +129,6 @@ Detailed Instructions for building with macosx/GNUmakefile
(where ${ver} is a shell variable containing the Tcl version number e.g. '9.0').
Setup this shell variable as follows:
ver="9.0"
If you are building from CVS, omit this step (CVS source tree names usually do
not contain a version number).
- Setup environment variables as desired, e.g. for a universal build on 10.5:
CFLAGS="-arch x86_64 -arch arm64 -mmacosx-version-min=10.5"
-4
View File
@@ -86,7 +86,6 @@
F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */; };
F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */; };
F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
@@ -522,7 +521,6 @@
F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = "<group>"; };
F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = "<group>"; };
F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = "<group>"; };
F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = "<group>"; };
F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = "<group>"; };
F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = "<group>"; };
F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = "<group>"; };
@@ -1297,7 +1295,6 @@
F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */,
F96D3F2A08F272A7004A47F5 /* tclThread.c */,
F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */,
F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */,
F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */,
F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */,
F96D3F2F08F272A7004A47F5 /* tclTimer.c */,
@@ -2000,7 +1997,6 @@
F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */,
F96D45C908F272BC004A47F5 /* tclThread.c in Sources */,
F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */,
F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */,
F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */,
F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */,
F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */,
+177 -53
View File
@@ -115,6 +115,30 @@ set ::bigLengths(uintmax) 0xffffffff
set ::bigLengths(patlenmultiple) [bigPatlenMultiple $::bigLengths(intmax)]
set ::bigLengths(upatlenmultiple) [bigPatlenMultiple $::bigLengths(uintmax)]
#
# script limits
bigtestRO script-length-bigdata-1 {Test script length limit} b -body {
try [string cat [string repeat " " 0x7ffffff7] "set a b"]
}
# TODO - different behaviour between compiled and uncompiled
test script-length-bigdata-2.compiled {Test script length limit} -body {
try [string cat [string repeat " " 0x7ffffff8] "set a b"]
} -constraints {
bigdata
} -result {Script length 2147483647 exceeds max permitted length 2147483646.} -returnCodes error
test script-length-bigdata-2.uncompiled {Test script length limit} -body {
testevalex [string cat [string repeat " " 0x7ffffff8] "set a b"]
} -constraints {
bigdata
} -result b
test script-bytecode-length-bigdata-1 {Test bytecode length limit} -body {
# Note we need to exceed bytecode limit without exceeding script char limit
set s [string repeat {{*}$x;} [expr 0x7fffffff/6]]
catch $s r e
} -cleanup {
bigClean
} -constraints panic-in-EnterCmdStartData
#
# string cat
bigtest string-cat-bigdata-1 "string cat large small result > INT_MAX" 1 -body {
@@ -139,9 +163,8 @@ bigtest string-cat-bigdata-3 "string cat result > UINT_MAX" 1 -body {
bigtestRO string-equal/compare-bigdata-1 "string compare/equal equal strings" {0 1} -body {
list [string compare $s1 $s2] [string equal $s1 $s2]
} -setup {
set len [expr {$::bigLengths(intmax)+1}]
set s1 [bigString $len]
set s2 [bigString $len]; # Use separate string to avoid Tcl_Obj * being same
set s1 [bigString 0x100000000]
set s2 [bigString 0x100000000]; # Separate so Tcl_Obj is not the same
} -cleanup {
bigClean
}
@@ -152,15 +175,14 @@ bigtestRO string-equal/compare-bigdata-2 "string compare/equal -length unequal s
lappend result [string equal $s1 $s2]
# Check lengths > UINT_MAX
# Also that lengths do not truncate to sizeof(int)
lappend result [string compare -length $len $s1 $s2]
lappend result [string equal -length $len $s1 $s2]
lappend result [string compare -length 0x100000000 $s1 $s2]
lappend result [string equal -length 0x100000000 $s1 $s2]
} -setup {
set len [expr {$::bigLengths(uintmax)+2}]
set s1 [bigString $len]
set s2 [bigString $len $len]; # Differs in last char
set s1 [bigString 0x100000001]
set s2 [bigString 0x100000001 0x100000000]; # Differs in last char
} -cleanup {
bigClean
} -constraints bug-a814ee5bbd
}
#
# string first
@@ -174,7 +196,7 @@ bigtestRO string-first-bigdata-1 "string first > INT_MAX" {2147483648 -1 2147483
set s [bigString 0x8000000a 0x80000000]
} -cleanup {
bigClean
} -constraints bug-a814ee5bbd
}
bigtestRO string-first-bigdata-2 "string first > UINT_MAX" {4294967296 -1 4294967300 1} -body {
list \
@@ -186,7 +208,7 @@ bigtestRO string-first-bigdata-2 "string first > UINT_MAX" {4294967296 -1 429496
set s [bigString 0x10000000a 0x100000000]
} -cleanup {
bigClean
} -constraints bug-a814ee5bbd
}
bigtestRO string-first-bigdata-3 "string first - long needle" 10 -body {
string first $needle $s
@@ -195,7 +217,7 @@ bigtestRO string-first-bigdata-3 "string first - long needle" 10 -body {
set needle [bigString 0x100000000]
} -cleanup {
bigClean needle
} -constraints bug-a814ee5bbd
}
#
# string index
@@ -252,8 +274,7 @@ bigtestRO string-last-bigdata-1 "string last > INT_MAX" {2 -1 2147483640 11} -bo
set s [bigString 0x80000010 2]
} -cleanup {
bigClean
} -constraints bug-a814ee5bbd
}
bigtestRO string-last-bigdata-2 "string last > UINT_MAX" {4294967300 -1 4294967290 1} -body {
list \
[string last 0 $s] \
@@ -264,8 +285,7 @@ bigtestRO string-last-bigdata-2 "string last > UINT_MAX" {4294967300 -1 42949672
set s [bigString 0x10000000a 2]
} -cleanup {
bigClean
} -constraints bug-a814ee5bbd
}
bigtestRO string-last-bigdata-3 "string last - long needle" 0 -body {
string last $needle $s
} -setup {
@@ -273,7 +293,7 @@ bigtestRO string-last-bigdata-3 "string last - long needle" 0 -body {
set needle [bigString 0x100000000]
} -cleanup {
bigClean needle
} -constraints bug-a814ee5bbd
}
#
# string length
@@ -331,8 +351,18 @@ bigtestRO string-range-bigdata-1 "string range" {6 7 5 {} 5 4 {} 9 {}} -body {
set s [bigString 0x10000000a]
} -cleanup {
bigClean
} -constraints bug-ad9361fd20f0
# TODO - once above bug is fixed, add tests for large result range
}
bigtestRO string-range-bigdata-2 "bug ad9361fd20 case 1" aXaaaa -body {
string range [string insert [string repeat a 0x80000000] end-0x7fffffff X] 0 5
}
bigtestRO string-range-bigdata-3 "bug ad9361fd20 case 2" 2 -body {
string length [string range $s end-0x7fffffff end-0x7ffffffe]
} -setup {
set s [string repeat a 0xffffffff]
} -cleanup {
bigClean
}
# TODO - add tests for large result range
#
# string repeat - use bigtest, not bigtestRO !!
@@ -363,8 +393,8 @@ bigtestRO string-replace-bigdata-1 "string replace" {789012345 012345678 XYZ7890
set s [bigString 0x10000000a]
} -cleanup {
bigClean
} -constraints bug-ad9361fd20f0
# TODO - once above bug is fixed, add tests for large result range:
}
# TODO -
# - replacements string is large
# - replace in the middle - string length grows, shrinks
# - last < first
@@ -550,7 +580,7 @@ bigtestRO format-bigdata-1 "format %s" 1 -body {
set s [bigString 0x100000000]
} -cleanup {
bigClean
} -constraints bug-a550f9710b
}
bigtest format-bigdata-2 "format bigstring%s" 1 -body {
set s [format $s X]
string equal $s [bigString 0x100000001 0x100000000]
@@ -559,24 +589,71 @@ bigtest format-bigdata-2 "format bigstring%s" 1 -body {
append s %s
} -cleanup {
bigClean
} -constraints bug-a550f9710b
# TODO - once above bugs fixed, add tests for width and precision
}
bigtest format-bigdata-3 "format big width" {4294967300 { } { a}} -body {
set s [format %4294967300s a]
list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
bigClean
}
bigtest format-bigdata-4 "format big negative width" {4294967300 {a } { }} -body {
set s [format %-4294967300s a]
list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
bigClean
}
bigtest format-bigdata-5 "format big * width" {4294967300 { } { a}} -body {
set s [format %*s 4294967300 a]
list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
bigClean
}
bigtest format-bigdata-6 "format big negative * width" {4294967300 {a } { }} -body {
set s [format %*s -4294967300 a]
list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
bigClean
}
bigtestRO format-bigdata-7 "format big precision" {4294967300 0123 6789} -body {
# Unset explicitly before setting to save memory as bigtestRO runs the
# script below twice.
unset -nocomplain s2
set s2 [format %.4294967300s $s]
list [string length $s2] [string range $s2 0 3] [string range $s2 end-3 end]
} -setup {
set s [testbigdata string 4294967310]
} -cleanup {
bigClean
}
bigtestRO format-bigdata-8 "format big * precision" {4294967300 0123 6789} -body {
# Unset explicitly before setting to save memory as bigtestRO runs the
# script below twice.
unset -nocomplain s2
set s2 [format %.*s 4294967300 $s]
list [string length $s2] [string range $s2 0 3] [string range $s2 end-3 end]
} -setup {
set s [testbigdata string 4294967310]
} -cleanup {
bigClean
}
#
# scan
bigtestRO scan-bigdata-1 "scan %s" {1 1 2 1} -body {
bigtestRO scan-bigdata-1 "scan %s" {1 1 2 X 1 2 4294967300 01234X} -body {
# Unset explicitly before setting to save memory as bigtestRO runs the
# script below twice.
unset -nocomplain result digits
unset -nocomplain result digits x
lappend result [string equal [scan $s %s] $s]
lappend result [string equal [scan $s {%[0-9X]}] $s]
lappend result [scan $s {%[0-9]%s} digits x] $x
lappend result [string equal $digits [bigString 0x100000008]]
lappend result [string equal $digits [bigString 0x100000009]]
lappend result [scan $s %4294967300s%s x y]
lappend result [string length $x] $y
} -setup {
set s [bigString 0x10000000a 0x100000009]
} -cleanup {
bigClean digits
} -constraints bug-d4ede611a7
}
#
# regexp
@@ -635,16 +712,16 @@ bigtestRO subst-bigdata-1 "subst" {1 1} -body {
#
# binary format
bigtestRO binary-format-bigdata-1 "binary format aN" 4294967296 -body {
bigtestRO binary-format-bigdata-1 "binary format aN" [list 4294967296 X\0\0\0 \0\0\0\0] -body {
# Unset explicitly before setting to save memory as bigtestRO runs the
# script below twice.
unset -nocomplain bin
set bin [binary format a4294967296 X]
string length $bin
list [string length $bin] [string range $bin 0 3] [string range $bin end-3 end]
} -cleanup {
bigClean
} -constraints bug-9369f83649
# TODO - do string compare and add other format specifiers once above bug is fixed
}
# TODO - do string compare and add other format specifiers
bigtestRO binary-format-bigdata-2 "binary format a*" 1 -body {
# Unset explicitly before setting to save memory as bigtestRO runs the
@@ -660,17 +737,17 @@ bigtestRO binary-format-bigdata-2 "binary format a*" 1 -body {
#
# binary scan
bigtestRO binary-scan-bigdata-1 "binary scan aN" 4294967296 -body {
bigtestRO binary-scan-bigdata-1 "binary scan aN" {4294967296 0123 2345} -body {
# Unset explicitly before setting to save memory as bigtestRO runs the
# script below twice.
unset -nocomplain bin2
binary scan $bin a4294967296 bin2
string length $bin2
list [string length $bin2] [string range $bin2 0 3] [string range $bin2 end-3 end]
} -setup {
set bin [bigBinary 4294967296]
} -cleanup {
bigClean
} -constraints bug-9369f83649
}
# TODO - do string compare and add other format specifiers once above bug is fixed
bigtestRO binary-scan-bigdata-2 "binary scan a*" 1 -body {
@@ -696,7 +773,7 @@ bigtestRO binary-encode/decode-base64-bigdata-1 "binary encode/decode base64" 1
set bin [bigBinary 4294967296]
} -cleanup {
bigClean
} -constraints bug-c719fa8716
}
#
# binary encode / decode hex
@@ -718,7 +795,7 @@ bigtestRO binary-encode/decode-uuencode-bigdata-1 "binary encode/decode uuencode
set bin [bigBinary 4294967296]
} -cleanup {
bigClean
} -constraints bug-2e3fed53ba
}
################################################################
# List commands
@@ -782,14 +859,15 @@ bigtest ledit-bigdata-2 "ledit - large result" {4294967304 4294967304 {a b c d e
bigClean
}
bigtest ledit-bigdata-3 "ledit - small -> large result" {2147483651 2147483651} -body {
set l2 {a b c x y z}
list [llength [ledit l2 2 3 {*}$l]] [llength $l2]
bigtest ledit-bigdata-3 "ledit - small -> large result" {2147483650 2147483650 {a b 0 1 2 3 4 5} {0 1 e f g h i j}} -body {
set l2 {a b c d e f g h i j}
list [llength [ledit l2 2 3 {*}$l]] [llength $l2] [lrange $l2 0 7] [lrange $l2 end-7 end]
} -setup {
set l [bigList 2147483647]
# Note total number of arguments has to be less than INT_MAX
set l [bigList 2147483642]
} -cleanup {
bigClean
} -constraints bug-7cddd2845c
} -constraints memory-allocation-panic
#
# lindex
@@ -808,8 +886,8 @@ bigtestRO lindex-bigdata-1 "lindex" {6 7 5 {} 5 4 {} 9 {}} -body {
set l [bigList 0x10000000a]
} -cleanup {
bigClean
} -constraints bug-dcac54a685
# TODO after bug fix - nested index
}
# TODO nested index
#
# linsert
@@ -831,15 +909,25 @@ bigtest linsert-bigdata-1 "linsert" {4294967330 1} -body {
#
# list and {*}
bigtestRO list-bigdata-1 {list {*} } {4294967296 0 4294967295} -body {
unset -nocomplain l2
set l2 [list {*}$l]
list [llength $l2] [lindex $l2 0] [lindex $l2 end]
} -setup {
# TODO - compiled and uncompiled behave differently so tested separately
test list-bigdata-1.compiled {list {*}} -body {
set l [bigList 0x100000000]
set l2 [list {*}$l]
unset l
list [llength $l2] [lindex $l2 0] [lindex $l2 end]
} -cleanup {
bigClean
} -constraints bug-7cddd2845c
} -constraints {
bigdata
} -result {4294967296 0 5}
test list-bigdata-1.uncompiled {list {*}} -body {
set l [bigList 0x7fffffff]
testevalex {set l2 [list {*}$l]}
} -cleanup {
bigClean
} -constraints {
bigdata
} -result {Number of words in command exceeds limit 2147483647.} -returnCodes error
#
# llength
@@ -871,9 +959,10 @@ bigtestRO lmap-bigdata-1 "lmap" 4294967296 -body {
#
# lrange
bigtestRO lrange-bigdata-1 "lrange" {6 7 5 {} 5 4 {} 9 {}} -body {
bigtestRO lrange-bigdata-1 "lrange" {6 {6 7} 7 5 {} 5 4 {} 9 {8 9} {}} -body {
list \
[lrange $l 0x100000000 0x100000000] \
[lrange $l 0x100000000 0x100000001] \
[lrange $l 0x100000000+1 0x100000000+1] \
[lrange $l 0x100000000-1 0x100000000-1] \
[lrange $l 0x10000000a 0x10000000a] \
@@ -881,13 +970,14 @@ bigtestRO lrange-bigdata-1 "lrange" {6 7 5 {} 5 4 {} 9 {}} -body {
[lrange $l end-1 end-1] \
[lrange $l end+1 end+1] \
[lrange $l end-0x100000000 end-0x100000000] \
[lrange $l end-0x100000001 end-0x100000000] \
[lrange $l end-0x10000000a end-0x10000000a]
} -setup {
set l [bigList 0x10000000a]
} -cleanup {
bigClean
} -constraints bug-dcac54a685
# TODO - once above bug is fixed, add tests for large result range
}
# TODO - add tests for large result range
#
# lrepeat - use bigtest, not bigtestRO !!
@@ -1021,6 +1111,40 @@ bigtestRO concat-bigdata-1 "concat" {4294967296 {0 1 2 3 4} {6 7 0 1 2} {3 4 5 6
set l [bigList 0x80000000]
}
test puts-bigdata-1 "puts" -setup {
set fpath [makeFile {} bug-0306a5563.data]
} -constraints {
bigdata
} -body {
set fd [open $fpath w]
puts -nonewline $fd [testbigdata string 0x80000001]
close $fd
set fd [open $fpath]
seek $fd 0x7FFFFFFA
set written [read $fd]
close $fd
set written
} -result {2345678}
test puts-bigdata-2 "puts" -setup {
set fpath [tcltest::makeFile {} bug-0306a5563.data]
} -constraints {
bigdata
} -body {
set fd [open $fpath w]
set s [testbigdata string 0x7FFFFFFE]
# The character to append in the next line is —, EM DASH,
# code point 0x2014 (decimal 8212, UTF-8 #xE2 #x80 #x94)
append s \u2014
puts -nonewline $fd $s
close $fd
set fd [open $fpath]
seek $fd 0x7FFFFFFA
set written [read $fd]
close $fd
set written
} -result {2345—}
#
# TODO
# lremove
+6
View File
@@ -15,11 +15,14 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
::tcltest::loadTestedCommands
source [file join [file dirname [info script]] tcltests.tcl]
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint bigEndian [expr {$tcl_platform(byteOrder) eq "bigEndian"}]
testConstraint littleEndian [expr {$tcl_platform(byteOrder) eq "littleEndian"}]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint pointerIs64bit [expr {$tcl_platform(pointerSize) >= 8}]
# Big test for correct ordering of data in [expr]
proc testIEEE {} {
@@ -3039,6 +3042,9 @@ test binary-80.3 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes
test binary-80.4 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xF0\x9F\x98\x81"]
} -result "expected byte sequence but character 4 was '\U01F601' (U+01F601)"
test binary-80.5 {Tcl_GetBytesFromObj} -constraints testbytestring -constraints {pointerIs64bit deprecated} -body {
testbytestring [string repeat A [expr 2**31]]
} -returnCodes 1 -result "byte sequence length exceeds INT_MAX"
# ----------------------------------------------------------------------
# cleanup
+1 -1
View File
@@ -9512,7 +9512,7 @@ test io-75.14 {
lappend res [gets $chan]
set status [catch {gets $chan} cres copts]
lappend res $status $cres
chan configure $chan -profile tcl8
chan configure $chan -profile tcl8
lappend res [gets $chan]
lappend res [gets $chan]
close $chan
+42 -9
View File
@@ -19,7 +19,7 @@ testConstraint arithSeriesShimmer 1
testConstraint arithSeriesShimmerOk 1
testConstraint has64BitLengths [expr {$tcl_platform(pointerSize) == 8}]
## Arg errors
# Arg errors
test lseq-1.1 {error cases} -body {
lseq
} \
@@ -416,9 +416,9 @@ test lseq-3.30 {lreverse with double values} arithSeriesDouble {
arithseries
18.5 17.0 15.5 14.0 12.5 11.0 9.5 8.0 6.5 5.0 3.5}
test lseq-3.31 {lreverse inplace with doubles} arithSeriesDouble {
test lseq-3.31 {lreverse inplace with doubles} {arithSeriesDouble has64BitLengths} {
lreverse [lseq 1.1 29.9 0.3]
} {29.9 29.599999999999998 29.299999999999997 29.0 28.7 28.4 28.099999999999998 27.799999999999997 27.5 27.2 26.9 26.599999999999998 26.299999999999997 26.0 25.7 25.4 25.099999999999998 24.799999999999997 24.5 24.2 23.9 23.599999999999998 23.299999999999997 23.0 22.7 22.4 22.099999999999998 21.799999999999997 21.5 21.2 20.9 20.6 20.299999999999997 20.0 19.7 19.4 19.1 18.799999999999997 18.5 18.2 17.9 17.6 17.299999999999997 17.0 16.7 16.4 16.1 15.799999999999999 15.5 15.2 14.899999999999999 14.6 14.299999999999999 14.0 13.7 13.399999999999999 13.099999999999998 12.8 12.5 12.2 11.899999999999999 11.599999999999998 11.3 11.0 10.7 10.399999999999999 10.099999999999998 9.8 9.5 9.2 8.899999999999999 8.599999999999998 8.3 8.0 7.699999999999999 7.399999999999999 7.099999999999998 6.800000000000001 6.5 6.199999999999999 5.899999999999999 5.599999999999998 5.300000000000001 5.0 4.699999999999999 4.399999999999999 4.099999999999998 3.8000000000000007 3.5 3.1999999999999993 2.8999999999999986 2.599999999999998 2.3000000000000007 2.0 1.6999999999999993 1.3999999999999986 1.1000000000000014}
} {29.9 29.6 29.3 29.0 28.7 28.4 28.1 27.8 27.5 27.2 26.9 26.6 26.3 26.0 25.7 25.4 25.1 24.8 24.5 24.2 23.9 23.6 23.3 23.0 22.7 22.4 22.1 21.8 21.5 21.2 20.9 20.6 20.3 20.0 19.7 19.4 19.1 18.8 18.5 18.2 17.9 17.6 17.3 17.0 16.7 16.4 16.1 15.8 15.5 15.2 14.9 14.6 14.3 14.0 13.7 13.4 13.1 12.8 12.5 12.2 11.9 11.6 11.3 11.0 10.7 10.4 10.1 9.8 9.5 9.2 8.9 8.6 8.3 8.0 7.7 7.4 7.1 6.8 6.5 6.2 5.9 5.6 5.3 5.0 4.7 4.4 4.1 3.8 3.5 3.2 2.9 2.6 2.3 2.0 1.7 1.4 1.1}
test lseq-4.1 {end expressions} {
set start 7
@@ -538,12 +538,12 @@ test lseq-4.8 {error case lrange} -body {
} -returnCodes 1 \
-result {bad index "fred": must be integer?[+-]integer? or end?[+-]integer?}
test lseq-4.9 {error case lrange} -body {
set fred 7
set ginger 8
lrange [lseq 1 5] $fred $ginger
} -returnCodes 1 \
-result {index 7 is out of bounds 0 to 4}
test lseq-4.9 {lrange empty/partial sets} -body {
foreach {fred ginger} {7 8 4 9 0 15 9 9 4 2} {
lappend res [lrange [lseq 1 5] $fred $ginger]
}
set res
} -result {{} 5 {1 2 3 4 5} {} {}}
# Panic when using variable value?
test lseq-4.10 {panic using variable index} {
@@ -551,6 +551,39 @@ test lseq-4.10 {panic using variable index} {
lindex [lseq 10] $i
} {0}
test lseq-4.11 {bug lseq / lindex discrepancies} -constraints has64BitLengths -body {
lindex [lseq 0x7fffffff] 0x80000000
} -result {}
test lseq-4.12 {bug lseq} -constraints has64BitLengths -body {
llength [lseq 0x100000000]
} -result {4294967296}
test lseq-4.13 {bug lseq} -constraints has64BitLengths -body {
set l [lseq 0x7fffffffffffffff]
list \
[llength $l] \
[lindex $l end] \
[lindex $l 9223372036854775800]
} -result {9223372036854775807 9223372036854775806 9223372036854775800}
test lseq-4.14 {bug lseq - inconsistent rounding} has64BitLengths {
# using a non-integer increment, [lseq] rounding seems to be not consistent:
lseq 4 40 0.1
} {4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}
test lseq-4.15 {bug lseq - inconsistent rounding} has64BitLengths {
# using a non-integer increment, [lseq] rounding seems to be not consistent:
lseq 6 40 0.1
} {6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}
test lseq-4.16 {bug lseq - inconsistent rounding} {
# using a non-integer increment, [lseq] rounding seems to be not consistent:
set res {}
lappend res [lseq 4.07 6 0.1]
lappend res [lseq 4.03 4.208 0.013]
} {{4.07 4.17 4.27 4.37 4.47 4.57 4.67 4.77 4.87 4.97 5.07 5.17 5.27 5.37 5.47 5.57 5.67 5.77 5.87 5.97} {4.03 4.043 4.056 4.069 4.082 4.095 4.108 4.121 4.134 4.147 4.16 4.173 4.186 4.199}}
# cleanup
::tcltest::cleanupTests
+6
View File
@@ -858,6 +858,12 @@ test scan-13.8 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
set msg [scan "10 20 30" {%100$d %5$d %200$d}]
list [llength $msg] [lindex $msg 99] [lindex $msg 4] [lindex $msg 199]
} {200 10 20 30}
test scan-13.9 {Tcl_ScanObjCmd, inline XPG case limit error} -body {
# Note this applies to 64-bit builds as well so long as max number of
# command line arguments allowed for scan command is INT_MAX
scan abc {%2147483648$s}
} -result {"%n$" argument index out of range} -returnCodes error
# scan infinities - not working
+2 -2
View File
@@ -2433,11 +2433,11 @@ test string-29.11.$noComp {string cat, efficiency} -body {
test string-29.12.$noComp {string cat, efficiency} -body {
tcl::unsupported::representation \
[run {string cat [encoding convertto utf-8 {}] [list x]}]
} -match glob -result {*, string representation "x"}
} -match glob -result {*, no string representation}
test string-29.13.$noComp {string cat, efficiency} -body {
tcl::unsupported::representation [run {string cat \
[encoding convertto utf-8 {}] [encoding convertto utf-8 {}] [list x]}]
} -match glob -result {*, string representation "x"}
} -match glob -result {*, no string representation}
test string-29.14.$noComp {string cat, efficiency} -setup {
set e [encoding convertto utf-8 {}]
} -cleanup {
+1 -1
View File
@@ -517,7 +517,7 @@ test stringObj-16.9 {Tcl_GetRange: last = INT_MAX-1} testobj {
} bcde
test stringObj-16.10 {Tcl_GetRange: last = SIZE_MAX-1} testobj {
teststringobj set 1 abcde
teststringobj range 1 1 [expr {$SIZE_MAX - 1}]
teststringobj range 1 1 [expr {$SIZE_MAX - 1}]
} bcde
test stringObj-16.11 {Tcl_GetRange: first = last = INT_MAX-1} testobj {
teststringobj set 1 abcde
+7
View File
@@ -708,6 +708,13 @@ test tailcall-14.1-bc {{in a deleted namespace} {byte compiled}} -body {
}
} -returnCodes 1 -result {namespace "::ns" not found}
test tailcall-bug-784befb0ba {tailcall crash with 254 args} -body {
proc tccrash args {llength $args}
# Must be EXACTLY 254 for crash
proc p {} [list tailcall tccrash {*}[lrepeat 254 x]]
p
} -result 254
# cleanup
::tcltest::cleanupTests
+1 -5
View File
@@ -314,7 +314,7 @@ GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
tclPreserve.o tclProc.o tclProcess.o tclRegexp.o \
tclResolve.o tclResult.o tclScan.o tclStringObj.o \
tclStrToD.o tclThread.o \
tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \
tclThreadAlloc.o tclThreadStorage.o tclStubInit.o \
tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o tclZlib.o \
tclTomMathInterface.o tclZipfs.o
@@ -472,7 +472,6 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclTestProcBodyObj.c \
$(GENERIC_DIR)/tclThread.c \
$(GENERIC_DIR)/tclThreadAlloc.c \
$(GENERIC_DIR)/tclThreadJoin.c \
$(GENERIC_DIR)/tclThreadStorage.c \
$(GENERIC_DIR)/tclTimer.c \
$(GENERIC_DIR)/tclTrace.c \
@@ -1574,9 +1573,6 @@ tclThread.o: $(GENERIC_DIR)/tclThread.c
tclThreadAlloc.o: $(GENERIC_DIR)/tclThreadAlloc.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadAlloc.c
tclThreadJoin.o: $(GENERIC_DIR)/tclThreadJoin.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadJoin.c
tclThreadStorage.o: $(GENERIC_DIR)/tclThreadStorage.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadStorage.c
+4 -4
View File
@@ -16,10 +16,10 @@
static int TraceProc2 (
void *clientData,
Tcl_Interp *interp,
ptrdiff_t level,
Tcl_Size level,
const char *command,
Tcl_Command commandInfo,
ptrdiff_t objc,
Tcl_Size objc,
struct Tcl_Obj *const *objv)
{
(void)clientData;
@@ -55,12 +55,12 @@ static int
Pkgt_EqObjCmd2(
void *dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
ptrdiff_t objc, /* Number of arguments. */
Tcl_Size objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_WideInt result;
const char *str1, *str2;
ptrdiff_t len1, len2;
Tcl_Size len1, len2;
(void)dummy;
if (objc != 3) {
+2 -2
View File
@@ -546,8 +546,8 @@ TclpInitLibraryPath(
*encodingPtr = Tcl_GetEncoding(NULL, NULL);
/*
* Note lengthPtr is (TCL_HASH_TYPE *) which is unsigned so cannot
* pass directly to Tcl_GetStringFromObj.
* Note lengthPtr is (TCL_HASH_TYPE *) which is unsigned so cannot
* pass directly to Tcl_GetStringFromObj.
* TODO - why is the type TCL_HASH_TYPE anyways?
*/
Tcl_Size length;
-1
View File
@@ -354,7 +354,6 @@ GENERIC_OBJS = \
tclStubInit.$(OBJEXT) \
tclThread.$(OBJEXT) \
tclThreadAlloc.$(OBJEXT) \
tclThreadJoin.$(OBJEXT) \
tclThreadStorage.$(OBJEXT) \
tclTimer.$(OBJEXT) \
tclTomMathInterface.$(OBJEXT) \
-1
View File
@@ -310,7 +310,6 @@ COREOBJS = \
$(TMP_DIR)\tclStubInit.obj \
$(TMP_DIR)\tclThread.obj \
$(TMP_DIR)\tclThreadAlloc.obj \
$(TMP_DIR)\tclThreadJoin.obj \
$(TMP_DIR)\tclThreadStorage.obj \
$(TMP_DIR)\tclTimer.obj \
$(TMP_DIR)\tclTomMathInterface.obj \
+1 -1
View File
@@ -887,12 +887,12 @@ TCL_BUILD_FOR = 8
!message *** Force 64-bit time_t
_USE_64BIT_TIME_T = 1
!endif
!endif
!if [nmakehlp -f $(OPTS) "utf16"]
!message *** Force UTF-16 internally
TCL_UTF_MAX = 3
!endif
!endif
# Yes, it's weird that the "symbols" option controls DEBUG and
# the "pdbs" option controls SYMBOLS. That's historical.
-4
View File
@@ -1320,10 +1320,6 @@ SOURCE=..\generic\tclThread.c
# End Source File
# Begin Source File
SOURCE=..\generic\tclThreadJoin.c
# End Source File
# Begin Source File
SOURCE=..\generic\tclThreadTest.c
# End Source File
# Begin Source File
+35 -42
View File
@@ -84,18 +84,11 @@ static int gInitialized = 0;
* Ring buffer for storing data. Actual data is from bufPtr[start]:bufPtr[size-1]
* and bufPtr[0]:bufPtr[length - (size-start)].
*/
#if TCL_MAJOR_VERSION > 8
typedef ptrdiff_t RingSizeT; /* Tcl9 TODO */
#define RingSizeT_MAX PTRDIFF_MAX
#else
typedef int RingSizeT;
#define RingSizeT_MAX INT_MAX
#endif
typedef struct RingBuffer {
char *bufPtr; /* Pointer to buffer storage */
RingSizeT capacity; /* Size of the buffer in RingBufferChar */
RingSizeT start; /* Start of the data within the buffer. */
RingSizeT length; /* Number of RingBufferChar*/
Tcl_Size capacity; /* Size of the buffer in RingBufferChar */
Tcl_Size start; /* Start of the data within the buffer. */
Tcl_Size length; /* Number of RingBufferChar*/
} RingBuffer;
#define RingBufferLength(ringPtr_) ((ringPtr_)->length)
#define RingBufferHasFreeSpace(ringPtr_) ((ringPtr_)->length < (ringPtr_)->capacity)
@@ -234,16 +227,16 @@ static void ConsoleWatchProc(void *instanceData, int mask);
static void ProcExitHandler(void *clientData);
static void ConsoleThreadActionProc(void *instanceData, int action);
static DWORD ReadConsoleChars(HANDLE hConsole, WCHAR *lpBuffer,
RingSizeT nChars, RingSizeT *nCharsReadPtr);
Tcl_Size nChars, Tcl_Size *nCharsReadPtr);
static DWORD WriteConsoleChars(HANDLE hConsole,
const WCHAR *lpBuffer, RingSizeT nChars,
RingSizeT *nCharsWritten);
static void RingBufferInit(RingBuffer *ringPtr, RingSizeT capacity);
const WCHAR *lpBuffer, Tcl_Size nChars,
Tcl_Size *nCharsWritten);
static void RingBufferInit(RingBuffer *ringPtr, Tcl_Size capacity);
static void RingBufferClear(RingBuffer *ringPtr);
static RingSizeT RingBufferIn(RingBuffer *ringPtr, const char *srcPtr,
RingSizeT srcLen, int partialCopyOk);
static RingSizeT RingBufferOut(RingBuffer *ringPtr, char *dstPtr,
RingSizeT dstCapacity, int partialCopyOk);
static Tcl_Size RingBufferIn(RingBuffer *ringPtr, const char *srcPtr,
Tcl_Size srcLen, int partialCopyOk);
static Tcl_Size RingBufferOut(RingBuffer *ringPtr, char *dstPtr,
Tcl_Size dstCapacity, int partialCopyOk);
static ConsoleHandleInfo *AllocateConsoleHandleInfo(HANDLE consoleHandle,
int permissions);
static ConsoleHandleInfo *FindConsoleInfo(const ConsoleChannelInfo *);
@@ -331,9 +324,9 @@ static const Tcl_ChannelType consoleChannelType = {
*------------------------------------------------------------------------
*/
static void
RingBufferInit(RingBuffer *ringPtr, RingSizeT capacity)
RingBufferInit(RingBuffer *ringPtr, Tcl_Size capacity)
{
if (capacity <= 0 || capacity > RingSizeT_MAX) {
if (capacity <= 0 || capacity > TCL_SIZE_MAX) {
Tcl_Panic("Internal error: invalid ring buffer capacity requested.");
}
ringPtr->bufPtr = (char *)Tcl_Alloc(capacity);
@@ -384,15 +377,15 @@ RingBufferClear(RingBuffer *ringPtr)
*
*------------------------------------------------------------------------
*/
static RingSizeT
static Tcl_Size
RingBufferIn(
RingBuffer *ringPtr,
const char *srcPtr, /* Source to be copied */
RingSizeT srcLen, /* Length of source */
Tcl_Size srcLen, /* Length of source */
int partialCopyOk /* If true, partial copy is permitted */
)
{
RingSizeT freeSpace;
Tcl_Size freeSpace;
RINGBUFFER_ASSERT(ringPtr);
@@ -407,8 +400,8 @@ RingBufferIn(
if (ringPtr->capacity - ringPtr->start > ringPtr->length) {
/* There is room at the back */
RingSizeT endSpaceStart = ringPtr->start + ringPtr->length;
RingSizeT endSpace = ringPtr->capacity - endSpaceStart;
Tcl_Size endSpaceStart = ringPtr->start + ringPtr->length;
Tcl_Size endSpace = ringPtr->capacity - endSpaceStart;
if (endSpace >= srcLen) {
/* Everything fits at the back */
memmove(endSpaceStart + ringPtr->bufPtr, srcPtr, srcLen);
@@ -419,7 +412,7 @@ RingBufferIn(
}
} else {
/* No room at the back. Existing data wrap to front. */
RingSizeT wrapLen =
Tcl_Size wrapLen =
ringPtr->start + ringPtr->length - ringPtr->capacity;
memmove(wrapLen + ringPtr->bufPtr, srcPtr, srcLen);
}
@@ -447,13 +440,13 @@ RingBufferIn(
*
*------------------------------------------------------------------------
*/
static RingSizeT
static Tcl_Size
RingBufferOut(RingBuffer *ringPtr,
char *dstPtr, /* Buffer for output data. May be NULL */
RingSizeT dstCapacity, /* Size of buffer */
Tcl_Size dstCapacity, /* Size of buffer */
int partialCopyOk) /* If true, return what's available */
{
RingSizeT leadLen;
Tcl_Size leadLen;
RINGBUFFER_ASSERT(ringPtr);
@@ -477,7 +470,7 @@ RingBufferOut(RingBuffer *ringPtr,
}
ringPtr->start += dstCapacity;
} else {
RingSizeT wrapLen = dstCapacity - leadLen;
Tcl_Size wrapLen = dstCapacity - leadLen;
if (dstPtr) {
memmove(dstPtr,
ringPtr->start + ringPtr->bufPtr,
@@ -529,8 +522,8 @@ static DWORD
ReadConsoleChars(
HANDLE hConsole,
WCHAR *lpBuffer,
RingSizeT nChars,
RingSizeT *nCharsReadPtr)
Tcl_Size nChars,
Tcl_Size *nCharsReadPtr)
{
DWORD nRead;
BOOL result;
@@ -589,8 +582,8 @@ static DWORD
WriteConsoleChars(
HANDLE hConsole,
const WCHAR *lpBuffer,
RingSizeT nChars,
RingSizeT *nCharsWrittenPtr)
Tcl_Size nChars,
Tcl_Size *nCharsWrittenPtr)
{
DWORD nCharsWritten;
BOOL result;
@@ -1090,7 +1083,7 @@ ConsoleInputProc(
{
ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
ConsoleHandleInfo *handleInfoPtr;
RingSizeT numRead;
Tcl_Size numRead;
if (chanInfoPtr->handle == INVALID_HANDLE_VALUE) {
return 0; /* EOF */
@@ -1160,7 +1153,7 @@ ConsoleInputProc(
&& bufSize > 1 /* Not single byte read */
) {
DWORD lastError;
RingSizeT numChars;
Tcl_Size numChars;
ReleaseSRWLockExclusive(&handleInfoPtr->lock);
lastError = ReadConsoleChars(chanInfoPtr->handle,
(WCHAR *)bufPtr,
@@ -1242,7 +1235,7 @@ ConsoleOutputProc(
{
ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
ConsoleHandleInfo *handleInfoPtr;
RingSizeT numWritten;
Tcl_Size numWritten;
*errorCode = 0;
@@ -1638,8 +1631,8 @@ ConsoleReaderThread(
ConsoleHandleInfo *handleInfoPtr = (ConsoleHandleInfo *) arg;
ConsoleHandleInfo **iterator;
char inputChars[200]; /* Temporary buffer */
RingSizeT inputLen = 0;
RingSizeT inputOffset = 0;
Tcl_Size inputLen = 0;
Tcl_Size inputOffset = 0;
/*
* Keep looping until one of the following happens.
@@ -1670,7 +1663,7 @@ ConsoleReaderThread(
HANDLE consoleHandle;
if (inputLen > 0) {
/* Private buffer has data. Copy it over. */
RingSizeT nStored;
Tcl_Size nStored;
assert((inputLen - inputOffset) > 0);
@@ -1833,7 +1826,7 @@ ConsoleWriterThread(LPVOID arg)
ConsoleHandleInfo *handleInfoPtr = (ConsoleHandleInfo *) arg;
ConsoleHandleInfo **iterator;
BOOL success;
RingSizeT numBytes;
Tcl_Size numBytes;
/*
* This buffer size has no relation really with the size of the shared
* buffer. Could be bigger or smaller. Make larger as multiple threads
@@ -1904,7 +1897,7 @@ ConsoleWriterThread(LPVOID arg)
ReleaseSRWLockExclusive(&handleInfoPtr->lock);
offset = 0;
while (numBytes > 0) {
RingSizeT numWChars = numBytes / sizeof(WCHAR);
Tcl_Size numWChars = numBytes / sizeof(WCHAR);
DWORD status;
status = WriteConsoleChars(handleInfoPtr->console,
(WCHAR *)(offset + buffer),
+1 -1
View File
@@ -1536,7 +1536,7 @@ GetWinFileAttributes(
* We test for, and fix that case, here.
*/
size_t len;
Tcl_Size len;
const char *str = Tcl_GetStringFromObj(fileName, &len);
if (len < 4) {
+5 -5
View File
@@ -921,7 +921,7 @@ TclpMatchInDirectory(
DWORD attr;
WIN32_FILE_ATTRIBUTE_DATA data;
size_t len = 0;
Tcl_Size len = 0;
const char *str = Tcl_GetStringFromObj(norm, &len);
native = (const WCHAR *)Tcl_FSGetNativePath(pathPtr);
@@ -943,7 +943,7 @@ TclpMatchInDirectory(
WIN32_FIND_DATAW data;
const char *dirName; /* UTF-8 dir name, later with pattern
* appended. */
size_t dirLength;
Tcl_Size dirLength;
int matchSpecialDots;
Tcl_DString ds; /* Native encoding of dir, also used
* temporarily for other things. */
@@ -2796,7 +2796,7 @@ TclpObjNormalizePath(
*/
Tcl_Obj *tmpPathPtr;
size_t len;
Tcl_Size len;
tmpPathPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
nextCheckpoint);
@@ -2885,7 +2885,7 @@ TclWinVolumeRelativeNormalize(
* also on drive C.
*/
size_t cwdLen;
Tcl_Size cwdLen;
const char *drive = Tcl_GetStringFromObj(useThisCwd, &cwdLen);
char drive_cur = path[0];
@@ -3022,7 +3022,7 @@ TclNativeCreateNativeRep(
WCHAR *nativePathPtr = NULL;
const char *str;
Tcl_Obj *validPathPtr;
size_t len;
Tcl_Size len;
WCHAR *wp;
if (TclFSCwdIsNative()) {
+1 -1
View File
@@ -131,7 +131,7 @@ TclpInitLibraryPath(
Tcl_Obj *pathPtr;
char installLib[LIBRARY_SIZE];
const char *bytes;
size_t length;
Tcl_Size length;
TclNewObj(pathPtr);
+1 -1
View File
@@ -3191,7 +3191,7 @@ TclpOpenTemporaryFile(
char *namePtr;
HANDLE handle;
DWORD flags = FILE_ATTRIBUTE_TEMPORARY;
size_t length;
Tcl_Size length;
int counter, counter2;
Tcl_DString buf;
+244 -246
View File
@@ -21,109 +21,51 @@
_CRTIMP unsigned int __cdecl _controlfp (unsigned int unNew, unsigned int unMask);
#endif
/*
* This is the global lock used to serialize access to other serialization
* data structures.
*/
static struct tclWinGlobals {
INIT_ONCE init_once; /* must be first member,
because of static initialziation */
static CRITICAL_SECTION globalLock;
static int initialized = 0;
/*
* This is the global lock used to serialize access to other serialization
* data structures.
*/
CRITICAL_SECTION globalLock;
/*
* This is the global lock used to serialize initialization and finalization
* of Tcl as a whole.
*/
/*
* This is the global lock used to serialize initialization and finalization
* of Tcl as a whole.
*/
static CRITICAL_SECTION initLock;
CRITICAL_SECTION initLock;
/*
* allocLock is used by Tcl's version of malloc for synchronization. For
* obvious reasons, cannot use any dyamically allocated storage.
*/
/* holds the TLS key for the Tcl Thread_ID */
DWORD tls_thread_id;
/*
* allocLock is used by Tcl's version of malloc for synchronization. For
* obvious reasons, cannot use any dyamically allocated storage.
*/
#if TCL_THREADS
static struct Tcl_Mutex_ {
CRITICAL_SECTION crit;
} allocLock;
static Tcl_Mutex allocLockPtr = &allocLock;
static int allocOnce = 0;
struct Tcl_Mutex_ {
CRITICAL_SECTION crit;
} allocLock;
Tcl_Mutex allocLockPtr;
#endif /* TCL_THREADS */
/*
* The joinLock serializes Create- and ExitThread. This is necessary to
* prevent a race where a new joinable thread exits before the creating thread
* had the time to create the necessary data structures in the emulation
* layer.
*/
static CRITICAL_SECTION joinLock;
/*
* Condition variables are implemented with a combination of a per-thread
* Windows Event and a per-condition waiting queue. The idea is that each
* thread has its own Event that it waits on when it is doing a ConditionWait;
* it uses the same event for all condition variables because it only waits on
* one at a time. Each condition variable has a queue of waiting threads, and
* a mutex used to serialize access to this queue.
*
* Special thanks to David Nichols and Jim Davidson for advice on the
* Condition Variable implementation.
*/
/*
* The per-thread event and queue pointers.
*/
} TclWinGlobals = {
INIT_ONCE_STATIC_INIT
};
#if TCL_THREADS
typedef struct ThreadSpecificData {
HANDLE condEvent; /* Per-thread condition event */
struct ThreadSpecificData *nextPtr; /* Queue pointers */
struct ThreadSpecificData *prevPtr;
int flags; /* See flags below */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
#endif /* TCL_THREADS */
/*
* State bits for the thread.
* WIN_THREAD_UNINIT Uninitialized. Must be zero because of the way
* ThreadSpecificData is created.
* WIN_THREAD_RUNNING Running, not waiting.
* WIN_THREAD_BLOCKED Waiting, or trying to wait.
*/
#define WIN_THREAD_UNINIT 0x0
#define WIN_THREAD_RUNNING 0x1
#define WIN_THREAD_BLOCKED 0x2
/*
* The per condition queue pointers and the Mutex used to serialize access to
* the queue.
*/
typedef struct {
CRITICAL_SECTION condLock; /* Lock to serialize queuing on the
* condition. */
struct ThreadSpecificData *firstPtr; /* Queue pointers */
struct ThreadSpecificData *lastPtr;
typedef struct Tcl_Condition_ {
CONDITION_VARIABLE cv;
} WinCondition;
/*
* Additions by AOL for specialized thread memory allocator.
*/
#endif /* TCL_THREADS */
#ifdef USE_THREAD_ALLOC
static DWORD tlsKey;
typedef struct {
Tcl_Mutex tlock;
CRITICAL_SECTION wlock;
} allocMutex;
#endif /* USE_THREAD_ALLOC */
/*
* The per thread data passed from TclpThreadCreate
@@ -135,8 +77,50 @@ typedef struct {
LPVOID lpParameter; /* Original startup data */
unsigned int fpControl; /* Floating point control word from the
* main thread */
HANDLE tHandle; /* used to wait on thread completion */
# if defined(_MSC_VER) || defined(__MSVCRT__)
unsigned
# else
DWORD
# endif
thread_id; /* initialized but unused,
possibly useful for debugging */
} WinThread;
/* assuming alignment constraints result in lsb being constant 0 */
# define TCL_WIN_THREAD_JOIN_FLAG ((size_t) 1 << 0)
# define TCL_WIN_THREAD_ID(PTR, JOINABLE)\
((Tcl_ThreadId) ((sizeof ((PTR) - (WinThread *) 0),\
(size_t) (PTR)) | ((JOINABLE)? TCL_WIN_THREAD_JOIN_FLAG: 0)))
# define TCL_WIN_THREAD_PTR(ID)\
((WinThread *) ((sizeof ((ID) == (Tcl_ThreadId) 0),\
(size_t) (ID) & ~TCL_WIN_THREAD_JOIN_FLAG)))
# define TCL_WIN_THREAD_JOINABLE(ID)\
(((sizeof ((ID) == (Tcl_ThreadId) 0),\
(size_t) (ID) & TCL_WIN_THREAD_JOIN_FLAG)))
/*
*----------------------------------------------------------------------
*
* TclWinFailure --
*
* Call this when an unexpected WIN32 error occurs
*
* Does not return
*
*----------------------------------------------------------------------
*/
void TCL_NORETURN WINAPI
TclWinFailure (
char const *const routine)
{
Tcl_Panic ("%s failed, last error = %#x\n", routine, GetLastError ());
}
/*
*----------------------------------------------------------------------
@@ -161,9 +145,8 @@ TclWinThreadStart(
LPVOID lpParameter) /* The WinThread structure pointer passed
* from TclpThreadCreate */
{
WinThread *winThreadPtr = (WinThread *) lpParameter;
LPTHREAD_START_ROUTINE lpOrigStartAddress;
LPVOID lpOrigParameter;
WinThread *const winThreadPtr = (WinThread *) lpParameter;
static DWORD result;
if (!winThreadPtr) {
return TCL_ERROR;
@@ -175,11 +158,12 @@ TclWinThreadStart(
#endif
);
lpOrigStartAddress = winThreadPtr->lpStartAddress;
lpOrigParameter = winThreadPtr->lpParameter;
Tcl_Free(winThreadPtr);
return lpOrigStartAddress(lpOrigParameter);
if (!TlsSetValue (TclWinGlobals.tls_thread_id, winThreadPtr))
TclWinFailure ("TlsSetValue");
result = winThreadPtr->lpStartAddress (winThreadPtr->lpParameter);
if (!winThreadPtr->tHandle)
TclpSysFree (winThreadPtr);
return result;
}
/*
@@ -211,41 +195,50 @@ TclpThreadCreate(
WinThread *winThreadPtr; /* Per-thread startup info */
HANDLE tHandle;
winThreadPtr = (WinThread *)Tcl_Alloc(sizeof(WinThread));
winThreadPtr = (WinThread *) TclpSysAlloc (sizeof *winThreadPtr);
if (!winThreadPtr)
TclWinFailure ("memory allocation");
winThreadPtr->lpStartAddress = (LPTHREAD_START_ROUTINE) proc;
winThreadPtr->lpParameter = clientData;
winThreadPtr->fpControl = _controlfp(0, 0);
EnterCriticalSection(&joinLock);
*idPtr = 0; /* must initialize as Tcl_Thread is a pointer and
* on WIN64 sizeof void* != sizeof unsigned
*/
#if defined(_MSC_VER) || defined(__MSVCRT__)
tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize,
(Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr,
0, (unsigned *)idPtr);
0 /* flags */, &winThreadPtr->thread_id);
#else
tHandle = CreateThread(NULL, (DWORD) stackSize,
TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr);
TclWinThreadStart, winThreadPtr, 0 /* flags */,
&winThreadPtr->thread_id);
#endif
if (tHandle == NULL) {
LeaveCriticalSection(&joinLock);
if (!tHandle) {
TclpSysFree (winThreadPtr);
# if 1
TclWinFailure ("CreateThread");
# else
return TCL_ERROR;
# endif
} else {
if (flags & TCL_THREAD_JOINABLE) {
TclRememberJoinableThread(*idPtr);
if (!(flags & TCL_THREAD_JOINABLE)) {
/*
* The only purpose of this is to decrement the reference count
* so the OS resources will be reacquired when the thread closes.
*/
if (!CloseHandle (tHandle))
TclWinFailure ("ClosseHandle");
/* note: the WIN32 OpenHandle() can be used to open a HANDLE
from the given threadID. However, if the thread
terminates with a HANDLE count of zero, the kernel may clean up
the thread, in particular its return status, immediately.
Hence, joining the thread requires keeping a HANDLE open
until the thread has been successfully joined. */
tHandle = 0;
}
winThreadPtr->tHandle = tHandle;
/*
* The only purpose of this is to decrement the reference count so the
* OS resources will be reacquired when the thread closes.
*/
CloseHandle(tHandle);
LeaveCriticalSection(&joinLock);
*idPtr = TCL_WIN_THREAD_ID (winThreadPtr, 0 != tHandle);
return TCL_OK;
}
}
@@ -273,7 +266,26 @@ Tcl_JoinThread(
int *result) /* Reference to the storage the result of the
* thread we wait upon will be written into. */
{
return TclJoinThread(threadId, result);
if (!TCL_WIN_THREAD_JOINABLE (threadId))
return TCL_ERROR;
WinThread *winThreadPtr = TCL_WIN_THREAD_PTR (threadId);
HANDLE const tHandle = winThreadPtr->tHandle;
switch (WaitForSingleObject (tHandle, INFINITE)) {
DWORD exit_code;
default:
return TCL_ERROR;
case WAIT_FAILED:
TclWinFailure ("WaitForSingleObject");
case WAIT_OBJECT_0:
if (!GetExitCodeThread (tHandle, &exit_code))
TclWinFailure ("GetExitCodeThread");
*result = exit_code;
if (!CloseHandle (tHandle))
TclWinFailure ("CloseHandle");
TclpSysFree (winThreadPtr);
return TCL_OK;
}
}
/*
@@ -296,10 +308,12 @@ void
TclpThreadExit(
int status)
{
EnterCriticalSection(&joinLock);
TclSignalExitThread(Tcl_GetCurrentThread(), status);
LeaveCriticalSection(&joinLock);
WinThread *winThreadPtr;
if (winThreadPtr = (WinThread *) TlsGetValue (
TclWinGlobals.tls_thread_id)) {
if (!winThreadPtr->tHandle)
TclpSysFree (winThreadPtr);
}
#if defined(_MSC_VER) || defined(__MSVCRT__)
_endthreadex((unsigned) status);
#else
@@ -326,8 +340,64 @@ TclpThreadExit(
Tcl_ThreadId
Tcl_GetCurrentThread(void)
{
return (Tcl_ThreadId)INT2PTR(GetCurrentThreadId());
WinThread *winThreadPtr;
if (!(winThreadPtr = (WinThread *) TlsGetValue (
TclWinGlobals.tls_thread_id))) {
if (ERROR_SUCCESS != GetLastError ())
TclWinFailure ("TlsGetValue in Tcl_GetCurrentThread");
/* this is an initial thread */
/* can't use TclAlloc, as the USE_THREAD_ALLOC per-thread allocator
calls Tcl_GetCurrentThread() */
if (!(winThreadPtr = (WinThread *) TclpSysAlloc (sizeof *winThreadPtr)))
TclWinFailure ("memory allocation");
winThreadPtr->tHandle = 0;
winThreadPtr->thread_id = GetCurrentThreadId ();
if (!TlsSetValue (TclWinGlobals.tls_thread_id, winThreadPtr))
TclWinFailure ("TlsSetValue");
}
return TCL_WIN_THREAD_ID (winThreadPtr, 0 != winThreadPtr->tHandle);
}
/*
*----------------------------------------------------------------------
*
* TclWinInitOnce
*
* Perform module initialization exactly once
* storage keys.
*
* Results:
* None.
*
*
*----------------------------------------------------------------------
*/
static BOOL
TclWinInitOnce (
INIT_ONCE *init_once,
void *parameter,
void *context)
{
struct tclWinGlobals *const twg = parameter;
InitializeCriticalSection(&twg->initLock);
InitializeCriticalSection(&twg->globalLock);
twg->tls_thread_id = TlsAlloc ();
#if TCL_THREADS
InitializeCriticalSection(&twg->allocLock.crit);
twg->allocLockPtr = &twg->allocLock;
#endif /* TCL_THREADS */
return TRUE;
}
# define TCL_WIN_INITIALIZE_ONCE()\
InitOnceExecuteOnce (&TclWinGlobals.init_once,\
TclWinInitOnce,\
&TclWinGlobals,\
0)
/*
*----------------------------------------------------------------------
@@ -351,20 +421,9 @@ Tcl_GetCurrentThread(void)
void
TclpInitLock(void)
{
if (!initialized) {
/*
* There is a fundamental race here that is solved by creating the
* first Tcl interpreter in a single threaded environment. Once the
* interpreter has been created, it is safe to create more threads
* that create interpreters in parallel.
*/
initialized = 1;
InitializeCriticalSection(&joinLock);
InitializeCriticalSection(&initLock);
InitializeCriticalSection(&globalLock);
}
EnterCriticalSection(&initLock);
if (!TCL_WIN_INITIALIZE_ONCE ())
TclWinFailure ("InitOnceExecuteOnce");
EnterCriticalSection(&TclWinGlobals.initLock);
}
/*
@@ -387,7 +446,7 @@ TclpInitLock(void)
void
TclpInitUnlock(void)
{
LeaveCriticalSection(&initLock);
LeaveCriticalSection(&TclWinGlobals.initLock);
}
/*
@@ -413,20 +472,9 @@ TclpInitUnlock(void)
void
TclpGlobalLock(void)
{
if (!initialized) {
/*
* There is a fundamental race here that is solved by creating the
* first Tcl interpreter in a single threaded environment. Once the
* interpreter has been created, it is safe to create more threads
* that create interpreters in parallel.
*/
initialized = 1;
InitializeCriticalSection(&joinLock);
InitializeCriticalSection(&initLock);
InitializeCriticalSection(&globalLock);
}
EnterCriticalSection(&globalLock);
if (!TCL_WIN_INITIALIZE_ONCE ())
TclWinFailure ("InitOnceExecuteOnce");
EnterCriticalSection(&TclWinGlobals.globalLock);
}
/*
@@ -449,7 +497,7 @@ TclpGlobalLock(void)
void
TclpGlobalUnlock(void)
{
LeaveCriticalSection(&globalLock);
LeaveCriticalSection(&TclWinGlobals.globalLock);
}
/*
@@ -475,11 +523,9 @@ Tcl_Mutex *
Tcl_GetAllocMutex(void)
{
#if TCL_THREADS
if (!allocOnce) {
InitializeCriticalSection(&allocLock.crit);
allocOnce = 1;
}
return &allocLockPtr;
if (!TCL_WIN_INITIALIZE_ONCE ())
TclWinFailure ("InitOnceExecuteOnce");
return &TclWinGlobals.allocLockPtr;
#else
return NULL;
#endif
@@ -506,36 +552,35 @@ Tcl_GetAllocMutex(void)
void
TclFinalizeLock(void)
{
struct tclWinGlobals *const twg = &TclWinGlobals;
TclpGlobalLock();
DeleteCriticalSection(&joinLock);
if (!TlsFree (twg->tls_thread_id))
TclWinFailure ("TlsFree");
/*
* Destroy the critical section that we are holding!
*/
DeleteCriticalSection(&globalLock);
initialized = 0;
DeleteCriticalSection(&twg->globalLock);
#if TCL_THREADS
if (allocOnce) {
DeleteCriticalSection(&allocLock.crit);
allocOnce = 0;
}
DeleteCriticalSection(&twg->allocLock.crit);
#endif
LeaveCriticalSection(&initLock);
LeaveCriticalSection(&twg->initLock);
/*
* Destroy the critical section that we were holding.
*/
DeleteCriticalSection(&initLock);
DeleteCriticalSection(&twg->initLock);
InitOnceInitialize (&twg->init_once); /* assuming we want to
re-initialize at some point -- dubious */
}
#if TCL_THREADS
/* locally used prototype */
static void FinalizeConditionEvent(void *data);
/*
*----------------------------------------------------------------------
@@ -558,25 +603,25 @@ void
Tcl_MutexLock(
Tcl_Mutex *mutexPtr) /* The lock */
{
CRITICAL_SECTION *csPtr;
struct Tcl_Mutex_ *mp;
if (*mutexPtr == NULL) {
TclpGlobalLock();
/*
* Double inside global lock check to avoid a race.
* BROKEN: does work in relaxed memory models
*/
if (*mutexPtr == NULL) {
csPtr = (CRITICAL_SECTION *)Tcl_Alloc(sizeof(CRITICAL_SECTION));
InitializeCriticalSection(csPtr);
*mutexPtr = (Tcl_Mutex)csPtr;
mp = Tcl_Alloc (sizeof *mp);
InitializeCriticalSection (&mp->crit);
*mutexPtr = mp;
TclRememberMutex(mutexPtr);
}
TclpGlobalUnlock();
}
csPtr = *((CRITICAL_SECTION **)mutexPtr);
EnterCriticalSection(csPtr);
EnterCriticalSection (&(*mutexPtr)->crit);
}
/*
@@ -599,9 +644,7 @@ void
Tcl_MutexUnlock(
Tcl_Mutex *mutexPtr) /* The lock */
{
CRITICAL_SECTION *csPtr = *((CRITICAL_SECTION **)mutexPtr);
LeaveCriticalSection(csPtr);
LeaveCriticalSection (&(*mutexPtr)->crit);
}
/*
@@ -625,11 +668,9 @@ void
TclpFinalizeMutex(
Tcl_Mutex *mutexPtr)
{
CRITICAL_SECTION *csPtr = *(CRITICAL_SECTION **)mutexPtr;
if (csPtr != NULL) {
DeleteCriticalSection(csPtr);
Tcl_Free(csPtr);
if (*mutexPtr) {
DeleteCriticalSection(&(*mutexPtr)->crit);
Tcl_Free(*mutexPtr);
*mutexPtr = NULL;
}
}
@@ -808,8 +849,8 @@ Tcl_ConditionWait(
*
* This procedure is invoked to signal a condition variable.
*
* The mutex must be held during this call to avoid races, but this
* interface does not enforce that.
* The mutex does not need to be held during this call to avoid races
* and should not be, to minimize the number of context switches
*
* Results:
* None.
@@ -824,68 +865,19 @@ void
Tcl_ConditionNotify(
Tcl_Condition *condPtr)
{
WinCondition *winCondPtr;
ThreadSpecificData *tsdPtr;
/* double checked locking, i.e., BROKEN */
if (*condPtr == NULL) {
TclpGlobalLock();
if (*condPtr != NULL) {
winCondPtr = *((WinCondition **)condPtr);
if (winCondPtr == NULL) {
return;
if (*condPtr == NULL) {
WinCondition *winCondPtr;
winCondPtr = (WinCondition *)Tcl_Alloc(sizeof *winCondPtr);
InitializeConditionVariable (&winCondPtr->cv);
*condPtr = winCondPtr;
}
/*
* Loop through all the threads waiting on the condition and notify
* them (i.e., broadcast semantics). The queue manipulation is guarded
* by the per-condition coordinating mutex.
*/
EnterCriticalSection(&winCondPtr->condLock);
while (winCondPtr->firstPtr != NULL) {
tsdPtr = winCondPtr->firstPtr;
winCondPtr->firstPtr = tsdPtr->nextPtr;
if (winCondPtr->lastPtr == tsdPtr) {
winCondPtr->lastPtr = NULL;
}
tsdPtr->flags = WIN_THREAD_RUNNING;
tsdPtr->nextPtr = NULL;
tsdPtr->prevPtr = NULL; /* Not strictly necessary, see A: */
SetEvent(tsdPtr->condEvent);
}
LeaveCriticalSection(&winCondPtr->condLock);
} else {
/*
* No-one has used the condition variable, so there are no waiters.
*/
TclpGlobalUnlock();
}
}
/*
*----------------------------------------------------------------------
*
* FinalizeConditionEvent --
*
* This procedure is invoked to clean up the per-thread event used to
* implement condition waiting. This is only safe to call at the end of
* time.
*
* Results:
* None.
*
* Side effects:
* The per-thread event is closed.
*
*----------------------------------------------------------------------
*/
static void
FinalizeConditionEvent(
void *data)
{
ThreadSpecificData *tsdPtr = (ThreadSpecificData *) data;
tsdPtr->flags = WIN_THREAD_UNINIT;
CloseHandle(tsdPtr->condEvent);
WakeAllConditionVariable (&(*condPtr)->cv);
}
/*
@@ -911,7 +903,7 @@ void
TclpFinalizeCondition(
Tcl_Condition *condPtr)
{
WinCondition *winCondPtr = *(WinCondition **)condPtr;
WinCondition *winCondPtr = *condPtr;
/*
* Note - this is called long after the thread-local storage is reclaimed.
@@ -921,7 +913,6 @@ TclpFinalizeCondition(
*/
if (winCondPtr != NULL) {
DeleteCriticalSection(&winCondPtr->condLock);
Tcl_Free(winCondPtr);
*condPtr = NULL;
}
@@ -935,6 +926,13 @@ TclpFinalizeCondition(
*/
#ifdef USE_THREAD_ALLOC
static DWORD tlsKey;
typedef struct {
Tcl_Mutex tlock;
CRITICAL_SECTION wlock;
} allocMutex;
Tcl_Mutex *
TclpNewAllocMutex(void)
{