From 3aab0c568ba1c8c0e1663fab50043b5ccaad90b7 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 6 Dec 2017 15:27:28 +0000 Subject: Start RC branch for Tcl 8.6.8 --- README | 2 +- generic/tcl.h | 4 ++-- library/init.tcl | 2 +- unix/configure | 2 +- unix/configure.in | 2 +- unix/tcl.spec | 2 +- win/configure | 3 ++- win/configure.in | 2 +- 8 files changed, 10 insertions(+), 9 deletions(-) diff --git a/README b/README index 57985d3..adfdf97 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ README: Tcl - This is the Tcl 8.6.7 source distribution. + This is the Tcl 8.6.8 source distribution. http://sourceforge.net/projects/tcl/files/Tcl/ You can get any source release of Tcl from the URL above. diff --git a/generic/tcl.h b/generic/tcl.h index a35dd5d..b43b2d7 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -55,10 +55,10 @@ extern "C" { #define TCL_MAJOR_VERSION 8 #define TCL_MINOR_VERSION 6 #define TCL_RELEASE_LEVEL TCL_FINAL_RELEASE -#define TCL_RELEASE_SERIAL 7 +#define TCL_RELEASE_SERIAL 8 #define TCL_VERSION "8.6" -#define TCL_PATCH_LEVEL "8.6.7" +#define TCL_PATCH_LEVEL "8.6.8" /* *---------------------------------------------------------------------------- diff --git a/library/init.tcl b/library/init.tcl index c31eea3..b0d567c 100644 --- a/library/init.tcl +++ b/library/init.tcl @@ -16,7 +16,7 @@ if {[info commands package] == ""} { error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]" } -package require -exact Tcl 8.6.7 +package require -exact Tcl 8.6.8 # Compute the auto path to use in this interpreter. # The values on the path come from several locations: diff --git a/unix/configure b/unix/configure index 888fe0c..3d7fbf4 100755 --- a/unix/configure +++ b/unix/configure @@ -1335,7 +1335,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu TCL_VERSION=8.6 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=6 -TCL_PATCH_LEVEL=".7" +TCL_PATCH_LEVEL=".8" VERSION=${TCL_VERSION} EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"} diff --git a/unix/configure.in b/unix/configure.in index 220a4aa..bfa2ef7 100644 --- a/unix/configure.in +++ b/unix/configure.in @@ -25,7 +25,7 @@ m4_ifdef([SC_USE_CONFIG_HEADERS], [ TCL_VERSION=8.6 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=6 -TCL_PATCH_LEVEL=".7" +TCL_PATCH_LEVEL=".8" VERSION=${TCL_VERSION} EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"} diff --git a/unix/tcl.spec b/unix/tcl.spec index 141511d..09920dd 100644 --- a/unix/tcl.spec +++ b/unix/tcl.spec @@ -4,7 +4,7 @@ Name: tcl Summary: Tcl scripting language development environment -Version: 8.6.7 +Version: 8.6.8 Release: 2 License: BSD Group: Development/Languages diff --git a/win/configure b/win/configure index 1480a57..be38dc3 100755 --- a/win/configure +++ b/win/configure @@ -1311,7 +1311,7 @@ SHELL=/bin/sh TCL_VERSION=8.6 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=6 -TCL_PATCH_LEVEL=".7" +TCL_PATCH_LEVEL=".8" VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION TCL_DDE_VERSION=1.4 @@ -5271,6 +5271,7 @@ TCL_WIN_VERSION="$TCL_VERSION.$TCL_RELEASE_LEVEL.`echo $TCL_PATCH_LEVEL | tr -d + # win only diff --git a/win/configure.in b/win/configure.in index 0229e83..5fc17a3 100644 --- a/win/configure.in +++ b/win/configure.in @@ -14,7 +14,7 @@ SHELL=/bin/sh TCL_VERSION=8.6 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=6 -TCL_PATCH_LEVEL=".7" +TCL_PATCH_LEVEL=".8" VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION TCL_DDE_VERSION=1.4 -- cgit v0.12 From 7b04f399b059c4de76ed101728d5608247d96711 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 6 Dec 2017 15:30:27 +0000 Subject: Duplicate test names --- tests/scan.test | 2 +- tests/utf.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/scan.test b/tests/scan.test index b36b412..98c581b 100644 --- a/tests/scan.test +++ b/tests/scan.test @@ -553,7 +553,7 @@ test scan-5.18 {bigint scanning underflow} -setup { list [scan "-207698809136909011942886895" \ %llu a] $a } -returnCodes 1 -result {unsigned bignum scans are invalid} -test scan-5.18 {bigint scanning invalid} -setup { +test scan-5.19 {bigint scanning invalid} -setup { set a {}; } -body { list [scan "207698809136909011942886895" \ diff --git a/tests/utf.test b/tests/utf.test index d0fa7be..95775a8 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -124,7 +124,7 @@ test utf-4.10 {Tcl_NumUtfChars: #u0000, calc len, overcomplete} {testnumutfchars test utf-5.1 {Tcl_UtfFindFirst} {testfindfirst testbytestring} { testfindfirst [testbytestring "abcbc"] 98 } {bcbc} -test utf-5.1 {Tcl_UtfFindLast} {testfindlast testbytestring} { +test utf-5.2 {Tcl_UtfFindLast} {testfindlast testbytestring} { testfindlast [testbytestring "abcbc"] 98 } {bc} -- cgit v0.12 From bbaba520ab3333e53b984347c1841a9f8f264eca Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 6 Dec 2017 21:59:13 +0000 Subject: changes WIP --- changes | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changes b/changes index d4be350..74c1146 100644 --- a/changes +++ b/changes @@ -8796,5 +8796,25 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich) --- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tcl/ for details +2017-08-10 [array names -regexp] supports backrefs (goth) + +2017-08-10 Fix gcc build failures due to #pragma placement (cassoff,fellows) + +2017-08-29 (bug)[b50fb2] exec redir append stdout and stderr to file (coulter) + 2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann) => http 2.8.12 + +2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter) + +2017-10-19 (bug)[1a5655] [info * methods] includes mixins (fellows) + +2017-10-23 tzdata updated to Olson's tzdata2017c (jima) + +2017-10-24 (bug)[fc1409] segfault in method cloning, oo-15.15 (coulter,fellows) + +2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS + + + +--- Released 8.6.8, December XX, 2017 --- http://core.tcl.tk/tcl/ for details -- cgit v0.12 From 6c313a58460ec101decbb59630caf788b4a1610c Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 7 Dec 2017 02:01:30 +0000 Subject: update changes --- changes | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/changes b/changes index 74c1146..7a85768 100644 --- a/changes +++ b/changes @@ -8813,8 +8813,16 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich) 2017-10-24 (bug)[fc1409] segfault in method cloning, oo-15.15 (coulter,fellows) -2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS +2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS (werner) +2017-11-08 (bug)[3298012] Stop crash when hash tables overflow 32 bits (porter) +2017-11-14 (bug)[5d6de6] Close failing case of [package prefer stable] (kupries) + +2017-11-17 (bug)[fab924] Fix misleading [load] message on Windows (oehlmann) + +2017-12-05 (bug)[4f6a1e] Crash when ensemble map and list are same (sebres) + +2017-12-06 (bug)[ce3a21] file normalize failure when tail is empty (porter) --- Released 8.6.8, December XX, 2017 --- http://core.tcl.tk/tcl/ for details -- cgit v0.12 From e0360a8c349d388e4090091098507da40848e83d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Dec 2017 11:41:31 +0000 Subject: Add win/rules-ext.vc and win/targets.vc to "make dist". Reported by Paul Overmeier. Thanks! --- unix/Makefile.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/unix/Makefile.in b/unix/Makefile.in index 4814ee0..29c051d 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -2018,8 +2018,7 @@ dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in $(M cp -p $(TOP_DIR)/win/*.[ch] $(TOP_DIR)/win/*.ico $(TOP_DIR)/win/*.rc \ $(DISTDIR)/win cp -p $(TOP_DIR)/win/*.bat $(DISTDIR)/win - cp -p $(TOP_DIR)/win/makefile.* $(DISTDIR)/win - cp -p $(TOP_DIR)/win/rules.vc $(DISTDIR)/win + cp -p $(TOP_DIR)/win/*.vc $(DISTDIR)/win cp -p $(TOP_DIR)/win/coffbase.txt $(DISTDIR)/win cp -p $(TOP_DIR)/win/tcl.hpj.in $(DISTDIR)/win cp -p $(TOP_DIR)/win/tcl.ds* $(DISTDIR)/win -- cgit v0.12 From 0fb81cb5dd85b298db7f4efe9c3dbdca910cf1d5 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Dec 2017 13:56:30 +0000 Subject: (cherry-pick): Added assoc, ftype and move as auto_execok shell built-ins on Windows. --- library/init.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/init.tcl b/library/init.tcl index c31eea3..6a1f921 100644 --- a/library/init.tcl +++ b/library/init.tcl @@ -637,8 +637,8 @@ proc auto_execok name { } set auto_execs($name) "" - set shellBuiltins [list cls copy date del dir echo erase md mkdir \ - mklink rd ren rename rmdir start time type ver vol] + set shellBuiltins [list assoc cls copy date del dir echo erase ftype \ + md mkdir mklink move rd ren rename rmdir start time type ver vol] if {[info exists env(PATHEXT)]} { # Add an initial ; to have the {} extension check first. set execExtensions [split ";$env(PATHEXT)" ";"] -- cgit v0.12 From dbe18af9ea851bd0e954036eff3fcd21bccf5291 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Dec 2017 14:33:11 +0000 Subject: No need any more to check for "Windows NT" here, since the minimum is XP now. --- library/init.tcl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/init.tcl b/library/init.tcl index 794b68b..530ce58 100644 --- a/library/init.tcl +++ b/library/init.tcl @@ -653,10 +653,7 @@ proc auto_execok name { set windir $env(WINDIR) } if {[info exists windir]} { - if {$tcl_platform(os) eq "Windows NT"} { - append path "$windir/system32;" - } - append path "$windir/system;$windir;" + append path "$windir/system32;$windir/system;$windir;" } foreach var {PATH Path path} { -- cgit v0.12 From f64bba0499c121428187fe686da131dca5905e50 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 19 Dec 2017 11:21:33 +0000 Subject: Minor simplification on Cygwin, since we only support Windows NT now --- unix/tclUnixInit.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index e57136d..cc66569 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -39,11 +39,6 @@ DLLIMPORT extern __stdcall void FreeLibrary(void *); DLLIMPORT extern __stdcall void *GetProcAddress(void *, const char *); DLLIMPORT extern __stdcall void GetSystemInfo(void *); -#define NUMPLATFORMS 4 -static const char *const platforms[NUMPLATFORMS] = { - "Win32s", "Windows 95", "Windows NT", "Windows CE" -}; - #define NUMPROCESSORS 11 static const char *const processors[NUMPROCESSORS] = { "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil", @@ -890,10 +885,7 @@ TclpSetVariables( GetSystemInfo(&sysInfo); - if (osInfo.dwPlatformId < NUMPLATFORMS) { - Tcl_SetVar2(interp, "tcl_platform", "os", - platforms[osInfo.dwPlatformId], TCL_GLOBAL_ONLY); - } + Tcl_SetVar2(interp, "tcl_platform", "os", "Windows NT", TCL_GLOBAL_ONLY); sprintf(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion); Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY); if (sysInfo.wProcessorArchitecture < NUMPROCESSORS) { -- cgit v0.12 From ee66488c3683d1e2b6ac36f523638c42c5649433 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 19 Dec 2017 11:23:13 +0000 Subject: Make TclEnsureNamespace() MODULE_SCOPE. Also change some refCount fields from type "int" to "unsigned int" for increased range. --- generic/tclCompile.h | 4 ++-- generic/tclDisassemble.c | 4 ++-- generic/tclInt.h | 25 ++++++++++++------------- generic/tclNamesp.c | 4 ++-- generic/tclProc.c | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/generic/tclCompile.h b/generic/tclCompile.h index 7f01436..f20ecfd 100644 --- a/generic/tclCompile.h +++ b/generic/tclCompile.h @@ -425,11 +425,11 @@ typedef struct ByteCode { * compiled. If the code is executed if a * different namespace, it must be * recompiled. */ - unsigned int nsEpoch; /* Value of nsPtr->resolverEpoch when this + unsigned int nsEpoch; /* Value of nsPtr->resolverEpoch when this * ByteCode was compiled. Used to invalidate * code when new namespace resolution rules * are put into effect. */ - int refCount; /* Reference count: set 1 when created plus 1 + unsigned int refCount; /* Reference count: set 1 when created plus 1 * for each execution of the code currently * active. This structure can be freed when * refCount becomes zero. */ diff --git a/generic/tclDisassemble.c b/generic/tclDisassemble.c index d61ed42..e07080a 100644 --- a/generic/tclDisassemble.c +++ b/generic/tclDisassemble.c @@ -254,7 +254,7 @@ DisassembleByteCodeObj( Tcl_Obj *bufferObj, *fileObj; TclNewObj(bufferObj); - if (codePtr->refCount <= 0) { + if (!codePtr->refCount) { return bufferObj; /* Already freed. */ } @@ -312,7 +312,7 @@ DisassembleByteCodeObj( int numCompiledLocals = procPtr->numCompiledLocals; Tcl_AppendPrintfToObj(bufferObj, - " Proc %p, refCt %d, args %d, compiled locals %d\n", + " Proc %p, refCt %u, args %d, compiled locals %d\n", procPtr, procPtr->refCount, procPtr->numArgs, numCompiledLocals); if (numCompiledLocals > 0) { diff --git a/generic/tclInt.h b/generic/tclInt.h index 91deb9d..de22924 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -274,7 +274,7 @@ typedef struct Namespace { * frames for this namespace that are on the * Tcl call stack. The namespace won't be * freed until activationCount becomes zero. */ - int refCount; /* Count of references by namespaceName + unsigned int refCount; /* Count of references by namespaceName * objects. The namespace can't be freed until * refCount becomes zero. */ Tcl_HashTable cmdTable; /* Contains all the commands currently @@ -299,7 +299,7 @@ typedef struct Namespace { * registered using "namespace export". */ int maxExportPatterns; /* Mumber of export patterns for which space * is currently allocated. */ - unsigned int cmdRefEpoch; /* Incremented if a newly added command + unsigned int cmdRefEpoch; /* Incremented if a newly added command * shadows a command for which this namespace * has already cached a Command* pointer; this * causes all its cached Command* pointers to @@ -545,7 +545,7 @@ typedef struct CommandTrace { struct CommandTrace *nextPtr; /* Next in list of traces associated with a * particular command. */ - int refCount; /* Used to ensure this structure is not + unsigned int refCount; /* Used to ensure this structure is not * deleted too early. Keeps track of how many * pieces of code have a pointer to this * structure. */ @@ -618,7 +618,7 @@ typedef struct Var { typedef struct VarInHash { Var var; - int refCount; /* Counts number of active uses of this + unsigned int refCount; /* Counts number of active uses of this * variable: 1 for the entry in the hash * table, 1 for each additional variable whose * linkPtr points here, 1 for each nested @@ -950,7 +950,7 @@ typedef struct CompiledLocal { typedef struct Proc { struct Interp *iPtr; /* Interpreter for which this command is * defined. */ - int refCount; /* Reference count: 1 if still present in + unsigned int refCount; /* Reference count: 1 if still present in * command table plus 1 for each call to the * procedure that is currently active. This * structure can be freed when refCount @@ -1067,7 +1067,7 @@ typedef struct AssocData { */ typedef struct LocalCache { - int refCount; + unsigned int refCount; int numVars; Tcl_Obj *varName0; } LocalCache; @@ -1229,7 +1229,7 @@ typedef struct CmdFrame { typedef struct CFWord { CmdFrame *framePtr; /* CmdFrame to access. */ int word; /* Index of the word in the command. */ - int refCount; /* Number of times the word is on the + unsigned int refCount; /* Number of times the word is on the * stack. */ } CFWord; @@ -1634,12 +1634,12 @@ typedef struct Command { * recreated). */ Namespace *nsPtr; /* Points to the namespace containing this * command. */ - unsigned int refCount; /* 1 if in command hashtable plus 1 for each + unsigned int refCount; /* 1 if in command hashtable plus 1 for each * reference from a CmdName Tcl object * representing a command's name in a ByteCode * instruction sequence. This structure can be * freed when refCount becomes zero. */ - unsigned int cmdEpoch; /* Incremented to invalidate any references + unsigned int cmdEpoch; /* Incremented to invalidate any references * that point to this command when it is * renamed, deleted, hidden, or exposed. */ CompileProc *compileProc; /* Procedure called to compile command. NULL @@ -2384,7 +2384,7 @@ typedef enum TclEolTranslation { */ typedef struct List { - int refCount; + unsigned int refCount; int maxElemCount; /* Total number of element array slots. */ int elemCount; /* Current number of list elements. */ int canonicalFlag; /* Set if the string representation was @@ -2640,7 +2640,7 @@ typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, unsigned int *leng typedef struct ProcessGlobalValue { unsigned int epoch; /* Epoch counter to detect changes in the * master value. */ - unsigned int numBytes; /* Length of the master string. */ + unsigned int numBytes; /* Length of the master string. */ char *value; /* The master string value. */ Tcl_Encoding encoding; /* system encoding when master string was * initialized. */ @@ -2960,8 +2960,7 @@ MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr); MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp, Tcl_Obj *const *objv, int objc, int *objcPtr); -Tcl_Namespace * TclEnsureNamespace( - Tcl_Interp *interp, +MODULE_SCOPE Tcl_Namespace * TclEnsureNamespace(Tcl_Interp *interp, Tcl_Namespace *namespacePtr); MODULE_SCOPE void TclFinalizeAllocSubsystem(void); diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index d212de1..269d06b 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -402,7 +402,7 @@ Tcl_PopCallFrame( } if (framePtr->numCompiledLocals > 0) { TclDeleteCompiledLocalVars(iPtr, framePtr); - if (--framePtr->localCachePtr->refCount == 0) { + if (framePtr->localCachePtr->refCount-- <= 1) { TclFreeLocalCache(interp, framePtr->localCachePtr); } framePtr->localCachePtr = NULL; @@ -1052,7 +1052,7 @@ Tcl_DeleteNamespace( * Otherwise, mark it as "dead" so that it can't be used. */ - if (nsPtr->refCount == 0) { + if (!nsPtr->refCount) { NamespaceFree(nsPtr); } else { nsPtr->flags |= NS_DEAD; diff --git a/generic/tclProc.c b/generic/tclProc.c index b89357c..70dc4dc 100644 --- a/generic/tclProc.c +++ b/generic/tclProc.c @@ -2380,7 +2380,7 @@ FreeLambdaInternalRep( Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1; Tcl_Obj *nsObjPtr = objPtr->internalRep.twoPtrValue.ptr2; - if (procPtr->refCount-- == 1) { + if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); } TclDecrRefCount(nsObjPtr); -- cgit v0.12 From f4cc39572c905ad4837ec43edf9650d528e2b34d Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 19 Dec 2017 14:46:31 +0000 Subject: update changes --- changes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changes b/changes index 7a85768..48e4624 100644 --- a/changes +++ b/changes @@ -8825,4 +8825,6 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich) 2017-12-06 (bug)[ce3a21] file normalize failure when tail is empty (porter) ---- Released 8.6.8, December XX, 2017 --- http://core.tcl.tk/tcl/ for details +2017-12-08 (new)[TIP 477] nmake build system reform (nadkarni) + +--- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tcl/ for details -- cgit v0.12 From e10cd2e0a52b97a25e6e05658f8f96b2f53bf45c Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 19 Dec 2017 20:48:52 +0000 Subject: [586e71dce4] Exeception handling at level #0 by EvalObjv --- generic/tclBasic.c | 2 +- tests/basic.test | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 79de61e..ddc828a 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -4561,7 +4561,7 @@ TEOV_Exception( if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } - if ((result != TCL_ERROR) && !allowExceptions) { + if ((result != TCL_OK) && (result != TCL_ERROR) && !allowExceptions) { ProcessUnexpectedResult(interp, result); result = TCL_ERROR; } diff --git a/tests/basic.test b/tests/basic.test index 7ff0669..865814a 100644 --- a/tests/basic.test +++ b/tests/basic.test @@ -984,6 +984,16 @@ test basic-49.2 {Tcl_EvalEx: verify TCL_EVAL_GLOBAL operation} testevalex { set ::context } {global} +test basic-50.1 {[586e71dce4] EvalObjv level #0 exception handling} -setup { + interp create slave + interp alias {} foo slave return +} -body { + list [catch foo m] $m +} -cleanup { + unset -nocomplain m + interp delete slave +} -result {0 {}} + # Clean up after expand tests unset noComp l1 l2 constraints rename l3 {} -- cgit v0.12 From dc40e6f7975ff3abcea929e29493bdc7e44c1843 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Wed, 20 Dec 2017 11:28:25 +0000 Subject: Fix for issue [ba1419303b4c]: Delete a namespace for an ensemble having a deletion trace deletes its namespace: segmentation fault. --- generic/tclNamesp.c | 17 +++++++---------- tests/namespace.test | 13 +++++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index 269d06b..de10fae 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -916,6 +916,11 @@ Tcl_DeleteNamespace( Command *cmdPtr; /* + * Ensure that this namespace doesn't get deallocated in the meantime. + */ + nsPtr->refCount++; + + /* * Give anyone interested - notably TclOO - a chance to use this namespace * normally despite the fact that the namespace is going to go. Allows the * calling of destructors. Will only be called once (unless re-established @@ -1047,16 +1052,8 @@ Tcl_DeleteNamespace( #endif Tcl_DeleteHashTable(&nsPtr->cmdTable); - /* - * If the reference count is 0, then discard the namespace. - * Otherwise, mark it as "dead" so that it can't be used. - */ - - if (!nsPtr->refCount) { - NamespaceFree(nsPtr); - } else { - nsPtr->flags |= NS_DEAD; - } + nsPtr ->flags |= NS_DEAD; + TclNsDecrRefCount(nsPtr); } else { /* * Restore the ::errorInfo and ::errorCode traces. diff --git a/tests/namespace.test b/tests/namespace.test index 9fa9331..b9e6ead 100644 --- a/tests/namespace.test +++ b/tests/namespace.test @@ -196,6 +196,19 @@ test namespace-7.7 {Bug 1655305} -setup { interp delete slave } -result {} +test namespace-7.8 {Bug ba1419303b4c} -setup { + namespace eval ns1 { + namespace ensemble create + } + + trace add command ns1 delete { + namespace delete ns1 + } +} -body { + # No segmentation fault given --enable-symbols=mem. + namespace delete ns1 +} -result {} + test namespace-8.1 {TclTeardownNamespace, delete global namespace} { catch {interp delete test_interp} interp create test_interp -- cgit v0.12 From 5e11793221791b79a9aa3140e6a77c1fe64ec2e9 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Wed, 20 Dec 2017 18:25:08 +0000 Subject: Further fix for issue [ba1419303b4c]: Delete a namespace for an ensemble having a deletion trace deletes its namespace: segmentation fault. --- generic/tclNamesp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index de10fae..f82d23d 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -1053,7 +1053,6 @@ Tcl_DeleteNamespace( Tcl_DeleteHashTable(&nsPtr->cmdTable); nsPtr ->flags |= NS_DEAD; - TclNsDecrRefCount(nsPtr); } else { /* * Restore the ::errorInfo and ::errorCode traces. @@ -1070,6 +1069,7 @@ Tcl_DeleteNamespace( nsPtr->flags &= ~(NS_DYING|NS_KILLED); } } + TclNsDecrRefCount(nsPtr); } /* -- cgit v0.12 From c1f84789ba402e590faed95132cf3f621c9bd0bf Mon Sep 17 00:00:00 2001 From: pooryorick Date: Wed, 20 Dec 2017 18:26:40 +0000 Subject: Fix for issue [ba1419303b4c]: Delete a namespace for an ensemble having a deletion trace deletes its namespace: segmentation fault. --- generic/tclNamesp.c | 17 +++++++---------- tests/namespace.test | 13 +++++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index a8d351f..542d648 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -916,6 +916,11 @@ Tcl_DeleteNamespace( Command *cmdPtr; /* + * Ensure that this namespace doesn't get deallocated in the meantime. + */ + nsPtr->refCount++; + + /* * Give anyone interested - notably TclOO - a chance to use this namespace * normally despite the fact that the namespace is going to go. Allows the * calling of destructors. Will only be called once (unless re-established @@ -1047,16 +1052,8 @@ Tcl_DeleteNamespace( #endif Tcl_DeleteHashTable(&nsPtr->cmdTable); - /* - * If the reference count is 0, then discard the namespace. - * Otherwise, mark it as "dead" so that it can't be used. - */ - - if (nsPtr->refCount == 0) { - NamespaceFree(nsPtr); - } else { - nsPtr->flags |= NS_DEAD; - } + nsPtr ->flags |= NS_DEAD; + TclNsDecrRefCount(nsPtr); } else { /* * Restore the ::errorInfo and ::errorCode traces. diff --git a/tests/namespace.test b/tests/namespace.test index ff8cd7d..f2d7061 100644 --- a/tests/namespace.test +++ b/tests/namespace.test @@ -196,6 +196,19 @@ test namespace-7.7 {Bug 1655305} -setup { interp delete slave } -result {} +test namespace-7.8 {Bug ba1419303b4c} -setup { + namespace eval ns1 { + namespace ensemble create + } + + trace add command ns1 delete { + namespace delete ns1 + } +} -body { + # No segmentation fault given --enable-symbols=mem. + namespace delete ns1 +} -result {} + test namespace-8.1 {TclTeardownNamespace, delete global namespace} { catch {interp delete test_interp} interp create test_interp -- cgit v0.12 From 28361a2bfe9fdba5dd0effa2c67390b21649e719 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Wed, 20 Dec 2017 18:28:10 +0000 Subject: Further fix for issue [ba1419303b4c]: Delete a namespace for an ensemble having a deletion trace deletes its namespace: segmentation fault. --- generic/tclNamesp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index 542d648..ba8e8ce 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -1053,7 +1053,6 @@ Tcl_DeleteNamespace( Tcl_DeleteHashTable(&nsPtr->cmdTable); nsPtr ->flags |= NS_DEAD; - TclNsDecrRefCount(nsPtr); } else { /* * Restore the ::errorInfo and ::errorCode traces. @@ -1070,6 +1069,7 @@ Tcl_DeleteNamespace( nsPtr->flags &= ~(NS_DYING|NS_KILLED); } } + TclNsDecrRefCount(nsPtr); } /* -- cgit v0.12 From 5a190dd003f0caaee265f6664bd1bbee842a2d66 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 21 Dec 2017 13:23:38 +0000 Subject: Remove use of compiler option "opt:nowin98". Don't use "t" as suffix any more when building extensions (but still use it for Tcl and Tk). --- win/rules.vc | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/win/rules.vc b/win/rules.vc index 7fc51c1..fac9af9 100644 --- a/win/rules.vc +++ b/win/rules.vc @@ -394,7 +394,7 @@ MSG = ^ # If INSTALLDIR set to tcl installation root dir then reset to the -# lib dir for installing extensions +# lib dir for installing extensions !if exist("$(_INSTALLDIR)\include\tcl.h") _INSTALLDIR=$(_INSTALLDIR)\lib !endif @@ -547,7 +547,7 @@ NMAKEHLPC = $(_TCLDIR)\win\nmakehlp.c # The following macros are set: # OPTIMIZATIONS - the compiler flags to be used for optimized builds # DEBUGFLAGS - the compiler flags to be used for debug builds -# LINKERFLAGS - Flags passed to the linker +# LINKERFLAGS - Flags passed to the linker # # Note that these are the compiler settings *available*, not those # that will be *used*. The latter depends on the OPTS macro settings @@ -1063,7 +1063,7 @@ STUBPREFIX = $(PROJECT)stub # Set up paths to various Tcl executables and libraries needed by extensions !if $(DOING_TCL) -TCLSHNAME = $(PROJECT)sh$(TCL_VERSION)$(SUFX).exe +TCLSHNAME = $(PROJECT)sh$(VERSION)$(SUFX).exe TCLSH = $(OUT_DIR)\$(TCLSHNAME) TCLIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib TCLLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) @@ -1153,8 +1153,8 @@ tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)" !endif # $(DOING_TK) || $(NEED_TK) # Various output paths -PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib -PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) +PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX:t=).lib +PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX:t=).$(EXT) PRJLIB = $(OUT_DIR)\$(PRJLIBNAME) PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib @@ -1291,7 +1291,7 @@ USE_WIDECHAR_API = 0 !endif !if $(USE_WIDECHAR_API) -COMPILERFLAGS = $(COMPILERFLAGS) /DUNICODE /D_UNICODE +COMPILERFLAGS = $(COMPILERFLAGS) /DUNICODE /D_UNICODE !endif # Like the TEA system only set this non empty for non-Tk extensions @@ -1301,7 +1301,7 @@ COMPILERFLAGS = $(COMPILERFLAGS) /DUNICODE /D_UNICODE PKGNAMEFLAGS = -DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \ -DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \ -DPACKAGE_VERSION="\"$(DOTVERSION)\"" \ - -DMODULE_SCOPE=extern + -DMODULE_SCOPE=extern !endif # crt picks the C run time based on selected OPTS @@ -1394,7 +1394,7 @@ pkgcflags_nostubs = $(appcflags_nostubs) $(PKGNAMEFLAGS) -DBUILD_$(PROJECT) # compiled with another VC version. Check for this and fix accordingly. stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) -Zl -DSTATIC_BUILD $(INCLUDES) -# Link flags +# Link flags !if $(DEBUG) ldebug = -debug -debugtype:cv @@ -1410,25 +1410,13 @@ ldebug = $(ldebug) -debug -debugtype:cv ldebug= $(ldebug) -profile !endif -### Declarations common to all linker versions +### Declarations common to all linker versions lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug) !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900 lflags = $(lflags) -nodefaultlib:libucrt.lib !endif -# Old linkers (Visual C++ 6 in particular) will link for fast loading -# on Win98. Since we do not support Win98 any more, we specify nowin98 -# as recommended for NT and later. However, this is only required by -# IX86 on older compilers and only needed if we are not doing a static build. - -!if "$(MACHINE)" == "IX86" && !$(STATIC_BUILD) -!if [nmakehlp -l -opt:nowin98 $(LINKER_TESTFLAGS)] -# Align sections for PE size savings. -lflags = $(lflags) -opt:nowin98 -!endif -!endif - dlllflags = $(lflags) -dll conlflags = $(lflags) -subsystem:console guilflags = $(lflags) -subsystem:windows @@ -1473,9 +1461,9 @@ RESCMD = $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \ -DCOMMAVERSION=$(DOTVERSION:.=,),0 \ -DDOTVERSION=\"$(DOTVERSION)\" \ -DVERSION=\"$(VERSION)\" \ - -DSUFX=\"$(SUFX)\" \ - -DPROJECT=\"$(PROJECT)\" \ - -DPRJLIBNAME=\"$(PRJLIBNAME)\" + -DSUFX=\"$(SUFX:t=)\" \ + -DPROJECT=\"$(PROJECT)\" \ + -DPRJLIBNAME=\"$(PRJLIBNAME)\" !ifndef DEFAULT_BUILD_TARGET DEFAULT_BUILD_TARGET = $(PROJECT) @@ -1572,7 +1560,7 @@ default-shell: default-setup $(PROJECT) @if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)" $(DEBUGGER) $(TCLSH) -# Generation of Windows version resource +# Generation of Windows version resource !ifdef RCFILE # Note: don't use $** in below rule because there may be other dependencies @@ -1611,7 +1599,7 @@ BEGIN VALUE "OriginalFilename", PRJLIBNAME VALUE "FileVersion", DOTVERSION VALUE "ProductName", "Package " PROJECT " for Tcl" - VALUE "ProductVersion", DOTVERSION + VALUE "ProductVersion", DOTVERSION END END BLOCK "VarFileInfo" -- cgit v0.12 From 189c6453b43325f74f5b004694c79c5786d918c1 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 22 Dec 2017 15:45:05 +0000 Subject: Change a few (internal) refCount/mask variables to unsigned type. --- generic/tclInt.h | 9 ++++----- generic/tclLiteral.c | 23 ++++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index de22924..2ba0493 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -545,7 +545,7 @@ typedef struct CommandTrace { struct CommandTrace *nextPtr; /* Next in list of traces associated with a * particular command. */ - unsigned int refCount; /* Used to ensure this structure is not + size_t refCount; /* Used to ensure this structure is not * deleted too early. Keeps track of how many * pieces of code have a pointer to this * structure. */ @@ -1492,11 +1492,11 @@ typedef struct LiteralEntry { * NULL if end of chain. */ Tcl_Obj *objPtr; /* Points to Tcl object that holds the * literal's bytes and length. */ - int refCount; /* If in an interpreter's global literal + size_t refCount; /* If in an interpreter's global literal * table, the number of ByteCode structures * that share the literal object; the literal * entry can be freed when refCount drops to - * 0. If in a local literal table, -1. */ + * 0. If in a local literal table, (size_t)-1. */ Namespace *nsPtr; /* Namespace in which this literal is used. We * try to avoid sharing literal non-FQ command * names among different namespaces to reduce @@ -1516,7 +1516,7 @@ typedef struct LiteralTable { * table. */ int rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ - int mask; /* Mask value used in hashing function. */ + unsigned int mask; /* Mask value used in hashing function. */ } LiteralTable; /* @@ -2962,7 +2962,6 @@ MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp, Tcl_Obj *const *objv, int objc, int *objcPtr); MODULE_SCOPE Tcl_Namespace * TclEnsureNamespace(Tcl_Interp *interp, Tcl_Namespace *namespacePtr); - MODULE_SCOPE void TclFinalizeAllocSubsystem(void); MODULE_SCOPE void TclFinalizeAsync(void); MODULE_SCOPE void TclFinalizeDoubleConversion(void); diff --git a/generic/tclLiteral.c b/generic/tclLiteral.c index 7acc9ad..003884d 100644 --- a/generic/tclLiteral.c +++ b/generic/tclLiteral.c @@ -186,7 +186,7 @@ TclCreateLiteral( { LiteralTable *globalTablePtr = &iPtr->literalTable; LiteralEntry *globalPtr; - int globalHash; + unsigned int globalHash; Tcl_Obj *objPtr; /* @@ -393,7 +393,8 @@ TclRegisterLiteral( LiteralEntry *globalPtr, *localPtr; Tcl_Obj *objPtr; unsigned hash; - int localHash, objIndex, new; + unsigned int localHash; + int objIndex, new; Namespace *nsPtr; if (length < 0) { @@ -537,7 +538,8 @@ TclHideLiteral( { LiteralEntry **nextPtrPtr, *entryPtr, *lPtr; LiteralTable *localTablePtr = &envPtr->localLitTable; - int localHash, length; + unsigned int localHash; + int length; const char *bytes; Tcl_Obj *newObjPtr; @@ -556,7 +558,7 @@ TclHideLiteral( lPtr->objPtr = newObjPtr; bytes = TclGetStringFromObj(newObjPtr, &length); - localHash = (HashString(bytes, length) & localTablePtr->mask); + localHash = HashString(bytes, length) & localTablePtr->mask; nextPtrPtr = &localTablePtr->buckets[localHash]; for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) { @@ -612,7 +614,7 @@ TclAddLiteralObj( lPtr = &envPtr->literalArrayPtr[objIndex]; lPtr->objPtr = objPtr; Tcl_IncrRefCount(objPtr); - lPtr->refCount = -1; /* i.e., unused */ + lPtr->refCount = (size_t)-1; /* i.e., unused */ lPtr->nextPtr = NULL; if (litPtrPtr) { @@ -809,7 +811,8 @@ TclReleaseLiteral( LiteralTable *globalTablePtr; register LiteralEntry *entryPtr, *prevPtr; const char *bytes; - int length, index; + int length; + unsigned int index; if (iPtr == NULL) { goto done; @@ -828,15 +831,13 @@ TclReleaseLiteral( for (prevPtr=NULL, entryPtr=globalTablePtr->buckets[index]; entryPtr!=NULL ; prevPtr=entryPtr, entryPtr=entryPtr->nextPtr) { if (entryPtr->objPtr == objPtr) { - entryPtr->refCount--; - /* * If the literal is no longer being used by any ByteCode, delete * the entry then remove the reference corresponding to the global * literal table entry (decrement the ref count of the object). */ - if (entryPtr->refCount == 0) { + if (entryPtr->refCount-- <= 1) { if (prevPtr == NULL) { globalTablePtr->buckets[index] = entryPtr->nextPtr; } else { @@ -954,8 +955,8 @@ RebuildLiteralTable( register LiteralEntry *entryPtr; LiteralEntry **bucketPtr; const char *bytes; - unsigned int oldSize; - int count, index, length; + unsigned int oldSize, index; + int count, length; oldSize = tablePtr->numBuckets; oldBuckets = tablePtr->buckets; -- cgit v0.12 From 71df313773a17633c53ba346987ded358542560a Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sat, 23 Dec 2017 07:56:49 +0000 Subject: Look for Tcl and Tk import libraries with or without "t" suffix convention when building extensions. Bump nmake rules version to 1.1 accordingly. --- win/rules.vc | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/win/rules.vc b/win/rules.vc index 7fc51c1..543e959 100644 --- a/win/rules.vc +++ b/win/rules.vc @@ -24,7 +24,7 @@ _RULES_VC = 1 # For modifications that are not backward-compatible, you *must* change # the major version. RULES_VERSION_MAJOR = 1 -RULES_VERSION_MINOR = 0 +RULES_VERSION_MINOR = 1 # The PROJECT macro must be defined by parent makefile. !if "$(PROJECT)" == "" @@ -535,7 +535,6 @@ NMAKEHLPC = $(_TCLDIR)\win\nmakehlp.c # We always build nmakehlp even if it exists since we do not know # what source it was built from. -!message *** Using $(NMAKEHLPC) !if [$(cc32) -nologo "$(NMAKEHLPC)" -link -subsystem:console > nul] !endif @@ -590,7 +589,6 @@ FPOPTS = $(FPOPTS) -QI0f OPTIMIZATIONS = $(FPOPTS) !if [nmakehlp -c -O2] -!message *** Compiler has 'Optimizations' OPTIMIZING = 1 OPTIMIZATIONS = $(OPTIMIZATIONS) -O2 !else @@ -1077,12 +1075,24 @@ TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" !if $(TCLINSTALL) # Building against an installed Tcl +# When building extensions, we need to locate tclsh. Depending on version +# of Tcl we are building against, this may or may not have a "t" suffix. +# Try various possibilities in turn. TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe !if !exist("$(TCLSH)") && $(TCL_THREADS) TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe !endif +!if !exist("$(TCLSH)") +TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe +!endif + TCLSTUBLIB = $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib +# When building extensions, may be linking against Tcl that does not add +# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. +!if !exist("$(TCLIMPLIB)") +TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib +!endif TCL_LIBRARY = $(_TCLDIR)\lib TCLREGLIB = $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib TCLDDELIB = $(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib @@ -1095,8 +1105,16 @@ TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe !if !exist($(TCLSH)) && $(TCL_THREADS) TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe !endif +!if !exist($(TCLSH)) +TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe +!endif TCLSTUBLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib +# When building extensions, may be linking against Tcl that does not add +# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. +!if !exist("$(TCLIMPLIB)") +TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib +!endif TCL_LIBRARY = $(_TCLDIR)\library TCLREGLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib TCLDDELIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib @@ -1140,11 +1158,23 @@ TK_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" WISH = $(_TKDIR)\bin\$(WISHNAME) TKSTUBLIB = $(_TKDIR)\lib\$(TKSTUBLIBNAME) TKIMPLIB = $(_TKDIR)\lib\$(TKIMPLIBNAME) +# When building extensions, may be linking against Tk that does not add +# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. +!if !exist("$(TKIMPLIB)") +TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX:t=).lib +TKIMPLIB = $(_TKDIR)\lib\$(TKIMPLIBNAME) +!endif TK_INCLUDES = -I"$(_TKDIR)\include" !else # Building against Tk sources WISH = $(_TKDIR)\win\$(BUILDDIRTOP)\$(WISHNAME) TKSTUBLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSTUBLIBNAME) TKIMPLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME) +# When building extensions, may be linking against Tk that does not add +# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. +!if !exist("$(TKIMPLIB)") +TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX:t=).lib +TKIMPLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME) +!endif TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib" !endif # TKINSTALL tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)" @@ -1717,7 +1747,6 @@ TCLNMAKECONFIG = "$(OUT_DIR)\tcl.nmake" !message *** Output directory will be '$(OUT_DIR)' !message *** Installation, if selected, will be in '$(_INSTALLDIR)' !message *** Suffix for binaries will be '$(SUFX)' -!message *** Compiler version $(VCVER). Target machine is $(MACHINE) -!message *** Host architecture is $(NATIVE_ARCH) +!message *** Compiler version $(VCVER). Target $(MACHINE), host $(NATIVE_ARCH). !endif # ifdef _RULES_VC -- cgit v0.12 From 82cd662f00327eb89fa2951c3f343112b6150e36 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Tue, 26 Dec 2017 03:30:22 +0000 Subject: Safer to compare TCLDIR against "" rather than ifdef as recursive nmakes can pass TCLDIR as defined but with an empty value. --- win/rules-ext.vc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/rules-ext.vc b/win/rules-ext.vc index 58c70fa..531e070 100644 --- a/win/rules-ext.vc +++ b/win/rules-ext.vc @@ -35,7 +35,7 @@ macro to the name of the project makefile. !endif # First locate the Tcl directory that we are working with. -!ifdef TCLDIR +!if "$(TCLDIR)" != "" _RULESDIR = $(TCLDIR:/=\) -- cgit v0.12 From 9a9b619c9f29470dab9e33b0c593b7e648224515 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Tue, 26 Dec 2017 12:27:14 +0000 Subject: TclOO: Remove unneeded name manipulation from TclOOCopyObjectCmd. --- generic/tclOOBasic.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/generic/tclOOBasic.c b/generic/tclOOBasic.c index b2c06a7..d874cba 100644 --- a/generic/tclOOBasic.c +++ b/generic/tclOOBasic.c @@ -1206,22 +1206,10 @@ TclOOCopyObjectCmd( o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, NULL, NULL); } else { const char *name, *namespaceName; - Tcl_DString buffer; name = TclGetString(objv[2]); - Tcl_DStringInit(&buffer); if (name[0] == '\0') { name = NULL; - } else if (name[0]!=':' || name[1]!=':') { - Interp *iPtr = (Interp *) interp; - - if (iPtr->varFramePtr != NULL) { - Tcl_DStringAppend(&buffer, - iPtr->varFramePtr->nsPtr->fullName, -1); - } - TclDStringAppendLiteral(&buffer, "::"); - Tcl_DStringAppend(&buffer, name, -1); - name = Tcl_DStringValue(&buffer); } /* @@ -1243,7 +1231,6 @@ TclOOCopyObjectCmd( } o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, name, namespaceName); - Tcl_DStringFree(&buffer); } if (o2Ptr == NULL) { -- cgit v0.12 From 9a7ce78e965b9066530810b359b0b968667de251 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 28 Dec 2017 18:45:16 +0000 Subject: Make Tcl_WinTCharToUtf/Tcl_WinUtfToTChar work when TCL_UTF_MAX > 3, mainly when sizeof(Tcl_UniChar) != 2. --- doc/Encoding.3 | 4 ---- generic/tclStubInit.c | 34 +++++++++++++++++++++++++++++- unix/tclUnixPort.h | 4 ++-- win/tclWin32Dll.c | 57 +++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 79 insertions(+), 20 deletions(-) diff --git a/doc/Encoding.3 b/doc/Encoding.3 index 81ef508..79fca0f 100644 --- a/doc/Encoding.3 +++ b/doc/Encoding.3 @@ -260,10 +260,6 @@ Windows-only convenience functions for converting between UTF-8 and Windows strings based on the TCHAR type which is by convention a Unicode character on Windows NT. -These functions are essentially wrappers around -\fBTcl_UtfToExternalDString\fR and -\fBTcl_ExternalToUtfDString\fR that convert to and from the -Unicode encoding. .PP \fBTcl_GetEncodingName\fR is roughly the inverse of \fBTcl_GetEncoding\fR. Given an \fIencoding\fR, the return value is the \fIname\fR argument that diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index b185f04..679a12b 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -106,7 +106,9 @@ static unsigned short TclWinNToHS(unsigned short ns) { # define TclWinFlushDirtyChannels doNothing # define TclWinResetInterfaces doNothing +#if TCL_UTF_MAX < 4 static Tcl_Encoding winTCharEncoding; +#endif static int TclpIsAtty(int fd) @@ -127,7 +129,7 @@ void *TclWinGetTclInstance() { void *hInstance = NULL; GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (const char *)&winTCharEncoding, &hInstance); + (const char *)&TclpIsAtty, &hInstance); return hInstance; } @@ -186,11 +188,24 @@ Tcl_WinUtfToTChar( int len, Tcl_DString *dsPtr) { +#if TCL_UTF_MAX > 3 + WCHAR *wp; + int size = MultiByteToWideChar(CP_UTF8, 0, string, len, 0, 0); + + Tcl_DStringInit(dsPtr); + Tcl_DStringSetLength(dsPtr, 2*size+2); + wp = (WCHAR *)Tcl_DStringValue(dsPtr); + MultiByteToWideChar(CP_UTF8, 0, string, len, wp, size+1); + Tcl_DStringSetLength(dsPtr, 2*size); + wp[size] = 0; + return (char *)wp; +#else if (!winTCharEncoding) { winTCharEncoding = Tcl_GetEncoding(0, "unicode"); } return Tcl_UtfToExternalDString(winTCharEncoding, string, len, dsPtr); +#endif } char * @@ -199,11 +214,28 @@ Tcl_WinTCharToUtf( int len, Tcl_DString *dsPtr) { +#if TCL_UTF_MAX > 3 + char *p; + int size; + + if (len > 0) { + len /= 2; + } + size = WideCharToMultiByte(CP_UTF8, 0, string, len, 0, 0, NULL, NULL); + Tcl_DStringInit(dsPtr); + Tcl_DStringSetLength(dsPtr, size+1); + p = (char *)Tcl_DStringValue(dsPtr); + WideCharToMultiByte(CP_UTF8, 0, string, len, p, size, NULL, NULL); + Tcl_DStringSetLength(dsPtr, size); + p[size] = 0; + return p; +#else if (!winTCharEncoding) { winTCharEncoding = Tcl_GetEncoding(0, "unicode"); } return Tcl_ExternalToUtfDString(winTCharEncoding, string, len, dsPtr); +#endif } #if defined(TCL_WIDE_INT_IS_LONG) diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h index ba56089..4819f10 100644 --- a/unix/tclUnixPort.h +++ b/unix/tclUnixPort.h @@ -87,8 +87,8 @@ typedef off_t Tcl_SeekOffset; typedef unsigned short WCHAR; __declspec(dllimport) extern __stdcall int GetModuleHandleExW(unsigned int, const char *, void *); __declspec(dllimport) extern __stdcall int GetModuleFileNameW(void *, const char *, int); - __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int, const char *, int, - const char *, int, const char *, const char *); + __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int, const void *, int, + char *, int, const char *, void *); __declspec(dllimport) extern __stdcall int MultiByteToWideChar(int, int, const char *, int, WCHAR *, int); __declspec(dllimport) extern __stdcall void OutputDebugStringW(const WCHAR *); diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index 84c7a97..3add0d1 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -33,7 +33,9 @@ static int platformId; /* Running under NT, or 95/98? */ #define cpuid __asm __emit 0fh __asm __emit 0a2h #endif +#if TCL_UTF_MAX < 4 static Tcl_Encoding winTCharEncoding = NULL; +#endif /* * The following declaration is for the VC++ DLL entry point. @@ -49,7 +51,7 @@ BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, */ typedef struct MountPointMap { - const TCHAR *volumeName; /* Native wide string volume name. */ + TCHAR *volumeName; /* Native wide string volume name. */ TCHAR driveLetter; /* Drive letter corresponding to the volume * name. */ struct MountPointMap *nextPtr; @@ -266,7 +268,7 @@ TclWinNoBackslash( * * TclpSetInterfaces -- * - * A helper proc that initializes winTCharEncoding. + * A helper proc. * * Results: * None. @@ -280,8 +282,10 @@ TclWinNoBackslash( void TclpSetInterfaces(void) { +#if TCL_UTF_MAX < 4 TclWinResetInterfaces(); winTCharEncoding = Tcl_GetEncoding(NULL, "unicode"); +#endif } /* @@ -344,10 +348,12 @@ TclWinEncodingsCleanup(void) void TclWinResetInterfaces(void) { +#if TCL_UTF_MAX < 4 if (winTCharEncoding != NULL) { Tcl_FreeEncoding(winTCharEncoding); winTCharEncoding = NULL; } +#endif } /* @@ -532,13 +538,9 @@ TclWinDriveLetterForVolMountPoint( * (NT) or "char" strings(95). This saves you the trouble of writing the * following type of fragment over and over: * - * if (running NT) { - * encoding <- Tcl_GetEncoding("unicode"); - * nativeBuffer <- UtfToExternal(encoding, utfBuffer); - * Tcl_FreeEncoding(encoding); - * } else { - * nativeBuffer <- UtfToExternal(NULL, utfBuffer); - * } + * encoding <- Tcl_GetEncoding("unicode"); + * nativeBuffer <- UtfToExternal(encoding, utfBuffer); + * Tcl_FreeEncoding(encoding); * * By convention, in Windows a TCHAR is a character in the ANSI code page * on Windows 95, a Unicode character on Windows NT. If you plan on @@ -561,26 +563,55 @@ TclWinDriveLetterForVolMountPoint( TCHAR * Tcl_WinUtfToTChar( const char *string, /* Source string in UTF-8. */ - int len, /* Source string length in bytes, or < 0 for + int len, /* Source string length in bytes, or -1 for * strlen(). */ Tcl_DString *dsPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { +#if TCL_UTF_MAX > 3 + TCHAR *wp; + int size = MultiByteToWideChar(CP_UTF8, 0, string, len, 0, 0); + + Tcl_DStringInit(dsPtr); + Tcl_DStringSetLength(dsPtr, 2*size+2); + wp = (TCHAR *)Tcl_DStringValue(dsPtr); + MultiByteToWideChar(CP_UTF8, 0, string, len, wp, size+1); + Tcl_DStringSetLength(dsPtr, 2*size); + wp[size] = 0; + return wp; +#else return (TCHAR *) Tcl_UtfToExternalDString(winTCharEncoding, string, len, dsPtr); +#endif } char * Tcl_WinTCharToUtf( - const TCHAR *string, /* Source string in Unicode when running NT, - * ANSI when running 95. */ - int len, /* Source string length in bytes, or < 0 for + const TCHAR *string, /* Source string in Unicode. */ + int len, /* Source string length in bytes, or -1 for * platform-specific string length. */ Tcl_DString *dsPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { +#if TCL_UTF_MAX > 3 + char *p; + int size; + + if (len > 0) { + len /= 2; + } + size = WideCharToMultiByte(CP_UTF8, 0, string, len, 0, 0, NULL, NULL); + Tcl_DStringInit(dsPtr); + Tcl_DStringSetLength(dsPtr, size+1); + p = (char *)Tcl_DStringValue(dsPtr); + WideCharToMultiByte(CP_UTF8, 0, string, len, p, size, NULL, NULL); + Tcl_DStringSetLength(dsPtr, size); + p[size] = 0; + return p; +#else return Tcl_ExternalToUtfDString(winTCharEncoding, (const char *) string, len, dsPtr); +#endif } /* -- cgit v0.12 From 301f6bcb839b301e1e3d3a92e3713696780c95ca Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 28 Dec 2017 18:49:24 +0000 Subject: Fix handling of surrogates (when TCL_UTF_MAX > 3) in Tcl_UtfNcmp()/Tcl_UtfNcasecmp()/TclUtfCasecmp(). Backported from core-8-branch, where this was fixed already. --- generic/tclPkg.c | 6 +++--- generic/tclUtf.c | 57 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/generic/tclPkg.c b/generic/tclPkg.c index 4f6faa8..6d826a9 100644 --- a/generic/tclPkg.c +++ b/generic/tclPkg.c @@ -414,7 +414,7 @@ PkgRequireCore( continue; } - + /* Check satisfaction of requirements before considering the current version further. */ if (reqc > 0) { satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv); @@ -424,7 +424,7 @@ PkgRequireCore( continue; } } - + if (bestPtr != NULL) { int res = CompareVersions(availVersion, bestVersion, NULL); @@ -485,7 +485,7 @@ PkgRequireCore( /* * Clean up memorized internal reps, if any. */ - + if (bestVersion != NULL) { ckfree(bestVersion); bestVersion = NULL; diff --git a/generic/tclUtf.c b/generic/tclUtf.c index c60e99e..6255a4e 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -726,8 +726,7 @@ Tcl_UniCharAtIndex( { Tcl_UniChar ch = 0; - while (index >= 0) { - index--; + while (index-- >= 0) { src += TclUtfToUniChar(src, &ch); } return ch; @@ -757,8 +756,7 @@ Tcl_UtfAtIndex( { Tcl_UniChar ch = 0; - while (index > 0) { - index--; + while (index-- > 0) { src += TclUtfToUniChar(src, &ch); } return src; @@ -1072,16 +1070,17 @@ Tcl_UtfNcmp( cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); + if (ch1 != ch2) { #if TCL_UTF_MAX == 4 - /* map high surrogate characters to values > 0xffff */ - if ((ch1 & 0xFC00) == 0xD800) { - ch1 += 0x4000; - } - if ((ch2 & 0xFC00) == 0xD800) { - ch2 += 0x4000; - } + /* Surrogates always report higher than non-surrogates */ + if (((ch1 & 0xFC00) == 0xD800)) { + if ((ch2 & 0xFC00) != 0xD800) { + return ch1; + } + } else if ((ch2 & 0xFC00) == 0xD800) { + return -ch2; + } #endif - if (ch1 != ch2) { return (ch1 - ch2); } } @@ -1122,16 +1121,17 @@ Tcl_UtfNcasecmp( */ cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); + if (ch1 != ch2) { #if TCL_UTF_MAX == 4 - /* map high surrogate characters to values > 0xffff */ - if ((ch1 & 0xFC00) == 0xD800) { - ch1 += 0x4000; - } - if ((ch2 & 0xFC00) == 0xD800) { - ch2 += 0x4000; - } + /* Surrogates always report higher than non-surrogates */ + if (((ch1 & 0xFC00) == 0xD800)) { + if ((ch2 & 0xFC00) != 0xD800) { + return ch1; + } + } else if ((ch2 & 0xFC00) == 0xD800) { + return -ch2; + } #endif - if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); if (ch1 != ch2) { @@ -1170,16 +1170,17 @@ TclUtfCasecmp( while (*cs && *ct) { cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); + if (ch1 != ch2) { #if TCL_UTF_MAX == 4 - /* map high surrogate characters to values > 0xffff */ - if ((ch1 & 0xFC00) == 0xD800) { - ch1 += 0x4000; - } - if ((ch2 & 0xFC00) == 0xD800) { - ch2 += 0x4000; - } + /* Surrogates always report higher than non-surrogates */ + if (((ch1 & 0xFC00) == 0xD800)) { + if ((ch2 & 0xFC00) != 0xD800) { + return ch1; + } + } else if ((ch2 & 0xFC00) == 0xD800) { + return -ch2; + } #endif - if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); if (ch1 != ch2) { -- cgit v0.12 From ad43c617e3fb81c44639a400b8a6d611aa52e3f2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 28 Dec 2017 21:14:40 +0000 Subject: Fix bug introduced in [0dd0d14489258621] (only for TCL_UTF_MAX > 3): If len parameter = -1, returned size includes terminating 0-byte. So, account for that. Also, fix some comments which were not accurate any more, now that Windows 95/98 is not supported any more. --- generic/tclStubInit.c | 2 ++ win/tclWin32Dll.c | 33 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 679a12b..b28d501 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -196,6 +196,7 @@ Tcl_WinUtfToTChar( Tcl_DStringSetLength(dsPtr, 2*size+2); wp = (WCHAR *)Tcl_DStringValue(dsPtr); MultiByteToWideChar(CP_UTF8, 0, string, len, wp, size+1); + if (len == -1) --size; /* account for 0-byte at string end */ Tcl_DStringSetLength(dsPtr, 2*size); wp[size] = 0; return (char *)wp; @@ -226,6 +227,7 @@ Tcl_WinTCharToUtf( Tcl_DStringSetLength(dsPtr, size+1); p = (char *)Tcl_DStringValue(dsPtr); WideCharToMultiByte(CP_UTF8, 0, string, len, p, size, NULL, NULL); + if (len == -1) --size; /* account for 0-byte at string end */ Tcl_DStringSetLength(dsPtr, size); p[size] = 0; return p; diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index 3add0d1..6c973df 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -519,35 +519,32 @@ TclWinDriveLetterForVolMountPoint( * * Tcl_WinUtfToTChar, Tcl_WinTCharToUtf -- * - * Convert between UTF-8 and Unicode when running Windows NT or the - * current ANSI code page when running Windows 95. + * Convert between UTF-8 and Unicode when running Windows. * - * On Mac, Unix, and Windows 95, all strings exchanged between Tcl and - * the OS are "char" oriented. We need only one Tcl_Encoding to convert - * between UTF-8 and the system's native encoding. We use NULL to - * represent that encoding. + * On Mac and Unix, all strings exchanged between Tcl and the OS are + * "char" oriented. We need only one Tcl_Encoding to convert between + * UTF-8 and the system's native encoding. We use NULL to represent + * that encoding. * - * On NT, some strings exchanged between Tcl and the OS are "char" + * On Windows, some strings exchanged between Tcl and the OS are "char" * oriented, while others are in Unicode. We need two Tcl_Encoding APIs * depending on whether we are targeting a "char" or Unicode interface. * - * Calling Tcl_UtfToExternal() or Tcl_ExternalToUtf() with an encoding of - * NULL should always used to convert between UTF-8 and the system's + * Calling Tcl_UtfToExternal() or Tcl_ExternalToUtf() with an encoding + * of NULL should always used to convert between UTF-8 and the system's * "char" oriented encoding. The following two functions are used in - * Windows-specific code to convert between UTF-8 and Unicode strings - * (NT) or "char" strings(95). This saves you the trouble of writing the + * Windows-specific code to convert between UTF-8 and Unicode strings. + * This saves you the trouble of writing the * following type of fragment over and over: * * encoding <- Tcl_GetEncoding("unicode"); * nativeBuffer <- UtfToExternal(encoding, utfBuffer); * Tcl_FreeEncoding(encoding); * - * By convention, in Windows a TCHAR is a character in the ANSI code page - * on Windows 95, a Unicode character on Windows NT. If you plan on - * targeting a Unicode interfaces when running on NT and a "char" - * oriented interface while running on 95, these functions should be - * used. If you plan on targetting the same "char" oriented function on - * both 95 and NT, use Tcl_UtfToExternal() with an encoding of NULL. + * By convention, in Windows a TCHAR is a Unicode character. If you plan + * on targeting a Unicode interface when running on Windows, these + * functions should be used. If you plan on targetting a "char" oriented + * function on Windows, use Tcl_UtfToExternal() with an encoding of NULL. * * Results: * The result is a pointer to the string in the desired target encoding. @@ -576,6 +573,7 @@ Tcl_WinUtfToTChar( Tcl_DStringSetLength(dsPtr, 2*size+2); wp = (TCHAR *)Tcl_DStringValue(dsPtr); MultiByteToWideChar(CP_UTF8, 0, string, len, wp, size+1); + if (len == -1) --size; /* account for 0-byte at string end */ Tcl_DStringSetLength(dsPtr, 2*size); wp[size] = 0; return wp; @@ -605,6 +603,7 @@ Tcl_WinTCharToUtf( Tcl_DStringSetLength(dsPtr, size+1); p = (char *)Tcl_DStringValue(dsPtr); WideCharToMultiByte(CP_UTF8, 0, string, len, p, size, NULL, NULL); + if (len == -1) --size; /* account for 0-byte at string end */ Tcl_DStringSetLength(dsPtr, size); p[size] = 0; return p; -- cgit v0.12