Compare commits

...
Author SHA1 Message Date
dkf 0d59c187fe merge trunk 2013-06-09 17:38:20 +00:00
dkf d8bed612b0 [779d38b996]: Make the 'try' compiler handle -during right and compile some
more cases than it did before.
2013-06-09 17:34:10 +00:00
dkf 41da12e756 Fix the problems with code generation; behavior now appears correct. 2013-06-09 17:21:07 +00:00
dkf 18fcba4c82 Improving tests, fixed one case. 2013-06-09 08:15:43 +00:00
dkf 41462bf4fa Working on a better compiler for [try]; found some bugs in previous compilation
code which aren't resolved yet.
2013-06-08 23:43:29 +00:00
dkf 4e13219dfb More informative comment describing INST_SYNTAX. 2013-06-08 23:35:02 +00:00
dkf 4d2add8f0f merge trunk 2013-06-08 13:42:46 +00:00
dkf 854eec9e0f Factor out stereotypical ways of getting variable indices. 2013-06-08 13:17:26 +00:00
dkf 849acd6e96 Simplify stack depth management. 2013-06-07 12:48:58 +00:00
dkf b5c0305e8b More efficient instruction sequence for [dict for] with correct exception depth handling. 2013-06-06 21:01:04 +00:00
dgp a8ee0b7831 3614382 Fix stack management of compiled [dict for] by shifting limits
of the catch range.
2013-06-06 16:55:08 +00:00
dgp a989f1616a 3614360 Repair stack demands of optimized compiled [return LITERAL]. 2013-06-06 14:24:35 +00:00
dkf af76b69dcd Working on the optimizer. 2013-06-06 09:09:48 +00:00
dkf ab224ed8ee Minor grammar fix. 2013-06-06 06:56:20 +00:00
dkf 68dfdc609e Split the optimizer up. Remove the dreaded 'goto' from which doesn't need it. 2013-06-06 06:53:55 +00:00
dkf 10ccda4936 Added optimizing of jump-to-nop and jump-to-jump cases. Ta to AK for suggesting. 2013-06-05 23:05:58 +00:00
dkf c718bb66ac Working on the optimizer, and finding a few bugs in bytecode generation. 2013-06-05 21:42:29 +00:00
dkf 5dad1c5205 Added the optimizer... 2013-06-05 21:05:41 +00:00
dkf 270a615a09 Corrected wrong information about instruction width that was causing an optimizer crash. 2013-06-05 20:55:29 +00:00
dkf 4a21f51055 merge fixes 2013-06-05 20:23:41 +00:00
dgp 532b8988c1 [Bugs 2835313, 3614226, 3614342]: Complete the construction of break/continue
compilers that get the stack cleanup right, even when there's expansion going
on.
2013-06-05 15:22:53 +00:00
dgp b2423f72cf Repair TCL_COMPILE_DEBUG guards 2013-06-05 15:07:40 +00:00
dgp 3903b017ec Stack Depth fixups. 2013-06-05 14:50:39 +00:00
dkf 3c76eb88e8 More cleaning up; factor out optimizer to new file. Some weird problems still. 2013-06-05 12:34:21 +00:00
dkf 544626ba84 [Bugs 2835313, 3614226]: Complete the construction of break/continue compilers
that get the stack cleanup right, even when there's expansion going on.
2013-06-05 08:11:06 +00:00
dkf b5f51d5007 merge trunk 2013-06-05 07:57:06 +00:00
dkf a20873ddab Even better tests 2013-06-05 07:51:06 +00:00
dkf 68d7745b27 Stack cleanup works now even in the most evil expansion cases. 2013-06-05 07:19:02 +00:00
jan.nijtmans c8b0ad64d1 Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN in stead.
One more last-moment fix for FreeBSD by Pietro Cerutti
2013-06-04 08:33:16 +00:00
dgp a097532afd merge 8.5 2013-06-03 20:31:58 +00:00
dgp 7b43d03c2b merge 8.4 2013-06-03 20:31:31 +00:00
mig fdf63d1e28 fix for perf bug detected by Kieran (https://groups.google.com/forum/?fromgroups#!topic/comp.lang.tcl/vfpI3bc-DkQ) 2013-06-03 16:52:48 +00:00
mig 17f4b04d10 fix for perf bug detected by Kieran (https://groups.google.com/forum/?fromgroups#!topic/comp.lang.tcl/vfpI3bc-DkQ) 2013-06-03 16:10:30 +00:00
dkf 2a3000c25e Next stage of fixing the break/continue generation. 2013-06-03 14:57:48 +00:00
jan.nijtmans 546d781de9 last-moment fix for FreeBSD from Pietro Cerutti 2013-06-03 14:19:43 +00:00
dgp e7d31b9449 Improve reliability of test httpold-4.12. Thanks AF! 2013-06-03 14:01:24 +00:00
dkf d2b951b436 merge back from trunk 2013-06-03 12:55:05 +00:00
dkf 79f58ebfb3 Merge back the improved [break] and [continue] compilation. 2013-06-03 09:46:10 +00:00
dkf 2797b611e3 Generate [continue] optimally in [for] next clauses. Add tests for Bug 3614226. 2013-06-03 09:37:14 +00:00
dkf 7da4d96216 Fix a stack depth calculation. 2013-06-02 21:32:16 +00:00
dkf 15425ace0b Remove useless macro, use existing macro where it makes sense. 2013-06-02 18:54:09 +00:00
dkf 7390940817 Many improvements to code generation of efficient break and continue. 2013-06-02 17:41:14 +00:00
dkf 7484715183 Getting better at doing more efficient break/continue instruction handling. 2013-06-01 21:05:55 +00:00
dkf bcc14fb740 derp 2013-05-30 10:57:13 +00:00
dkf 90dba8327c Working towards the next batch of optimizations. 2013-05-30 10:55:39 +00:00
dkf db5a66dd2c Corrected code generation when doing the second run with an 'infinite' loop. 2013-05-30 10:29:41 +00:00
dgp 82c027f092 Simplifications and tidying up of stack management issues. Work in progress. 2013-05-29 20:36:05 +00:00
dgp e7da373e0c 3614102 - Reset stack housekeeping when compileProc fails. 2013-05-29 17:20:29 +00:00
andreask 2a26edf602 Fix C99 comment-ism breaking the native AIX compiler. HPUX likely as well. 2013-05-29 16:24:34 +00:00
dgp c929650e2f Stop emitting the instructions INST_*_SCALAR_STK*. They are identical to
their INST_*_STK* counterparts.
Having done that, it is clear the "simpleVarName" return from TclPushVarName
provides nothing of use to any of its callers.  Eliminate that.  Also make
TPVN return void, instead of int.
Bring the TPVN header comments up to date; they were quite rotten.
2013-05-29 14:37:58 +00:00
dgp b1a3a83b3d Use the routines that provide "basic compile" instead of reinventing them. 2013-05-28 19:21:22 +00:00
dgp fb728f1f53 Plug the memory leak. Greater ambitions to improve this routine are proving
more difficult than expected.
2013-05-28 14:29:01 +00:00
dgp b3b9cb8d35 Missed bits of dup code elimination. 2013-05-28 14:04:02 +00:00
jan.nijtmans 251b09c99a Move changelog entry to correct date. 2013-05-28 07:24:08 +00:00
jan.nijtmans 43cea24ef3 3036566 - Get msgcat locale for Win Vista+ first from gui language registry key.
Bumped msgcat to version 1.5.2.
Minor manpage corrections.
2013-05-28 07:18:42 +00:00
oehhar 2debf51b24 3036566 - Get msgcat locale for Win Vista+ first from gui language registry key.
Bumped msgcat to version 1.5.2.
Minor manpage corrections.
2013-05-27 20:45:08 +00:00
dgp f677af67e2 Repair some stack depth housekeeping. 2013-05-25 03:26:21 +00:00
dgp 622cb44fa4 3613854 - Fixup stack maintenance /code generation for [array set x $oddList].
Postscript - I see that this commit created a memory leak.
Will commit a fix within a few days.
2013-05-24 18:37:19 +00:00
dgp 50c73b80d3 Spare developers the burden and error risk of counting bytes in string
literals, or having to type them twice.
2013-05-23 20:24:56 +00:00
dgp b24c54bed3 Eliminate code duplication. 2013-05-23 18:32:19 +00:00
jan.nijtmans c74bb69040 merge-mark 2013-05-23 11:40:40 +00:00
jan.nijtmans 4b5869de07 merge-mark 2013-05-23 11:39:08 +00:00
jan.nijtmans d421fc1bdf When compiling Tcl with mingw32/wsl-4.0, make sure that no 64-bit time functions are used, which don't exist in Win95/98/ME. 2013-05-23 11:28:18 +00:00
andreask 6c3b503dbd Removed const qualifier causing the HP native cc to error out (error 1675: Duplicate type qualifier "const"). 2013-05-22 16:39:01 +00:00
dgp 68afad0c67 silence compiler warning 2013-05-22 13:34:46 +00:00
dgp 7965559c05 silence compiler warning 2013-05-22 13:14:18 +00:00
dkf 18b0700dbe [3613609]: Replace strcasecmp() with UTF-8-aware version. 2013-05-22 13:07:33 +00:00
dkf 4ee4a959b9 [3613609]: Replace strcasecmp() with UTF-8-aware version. 2013-05-22 12:59:45 +00:00
dkf 0a18b6e286 Fixed the weird edge case. 2013-05-22 12:55:50 +00:00
dkf 5c0e6b295a Improved tests. 2013-05-22 12:32:28 +00:00
dkf 45e4dfd471 * doc/file.n: [Bug 3613671]: Added note to portability section on the
fact that [file owned] does not produce useful results on Windows.
2013-05-22 10:36:55 +00:00
jan.nijtmans 89acc1c033 Slight improvement: if cs = "\xC0\x80" and ct = "\x00", loop would continue after NUL-byte, this should not happen. 2013-05-21 09:38:05 +00:00
jan.nijtmans be69161b43 Proposed solution for 3613609: lsort -nocase does not sort non-ASCII correctly 2013-05-21 09:27:15 +00:00
dgp 025d1997eb 3613569 Handle case when TclpTempFileNameForLibrary returns NULL. 2013-05-20 15:10:18 +00:00
dkf 648841a413 [3613567]: Corrected sense of test on results of access() in temp file creation. 2013-05-20 14:17:06 +00:00
jan.nijtmans 276bcea418 Don't #define VOID on VxWorks, as it is already typdef'd to void. Eliminate possibly conflicting LOCAL/OFFSET 2013-05-19 20:37:08 +00:00
jan.nijtmans 1ac9419646 Don't #define VOID on VxWorks, as it is already typdef'd to void. Eliminate possibly conflicting LOCAL/OFFSET 2013-05-19 20:26:29 +00:00
jan.nijtmans c0b55c5efd Fix for FreeBSD, and remove support for older FreeBSD versions. Patch by Pietro Cerutti 2013-05-19 19:09:25 +00:00
jan.nijtmans 643a9ae4b0 Fix for FreeBSD, and remove support for older FreeBSD versions. Patch by Pietro Cerutti 2013-05-19 19:03:05 +00:00
jan.nijtmans 6880761727 Don't #define VOID on VxWorks, as it is already typdef'd to void
Eliminate possibly conflicting LOCAL #define
2013-05-19 14:04:07 +00:00
jan.nijtmans 119cc47a41 Fix for FreeBSD, and remove support for older FreeBSD versions. Patch by Pietro Cerutti. 2013-05-19 13:36:42 +00:00
dkf 72a0fab411 Split tclCompCmds.c into two roughly-equal-sized pieces. 2013-05-18 13:25:11 +00:00
jan.nijtmans 7f79d3446c <sys/stat.h> inclusion is only needed when compiling for Win32, don't bother for other platforms. 2013-05-17 15:12:27 +00:00
jan.nijtmans c7e9f685b7 - eliminate compiler warning when compiling with Visual Studio.
- Make sure that _ftime() from msvcrt.dll is used, not ftime() from mingw (which might use 64-bit time_t)
2013-05-17 15:08:48 +00:00
dkf 06cfc15d05 Remove useless variables. 2013-05-17 11:02:40 +00:00
jan.nijtmans c52117cb0c Revert defining _HAVE_32BIT_TIME_T especially for mingw-4.0-rc1: Although it works, it has the side-effect that tcl8?.dll depends on msvcrt.dll symbols which are only available in later versions of msvcrt.dll. This is undesired, it really should be fixed in the mingw headers. 2013-05-17 07:24:31 +00:00
jan.nijtmans 143dd064c6 Revert defining _HAVE_32BIT_TIME_T especially for mingw-4.0-rc1: Although it works, it has the side-effect that tcl8?.dll depends on msvcrt.dll symbols which are only available in later versions of msvcrt.dll. This is undesired, it really should be fixed in the mingw headers. 2013-05-17 07:21:27 +00:00
jan.nijtmans 43d07e03c7 Revert defining _HAVE_32BIT_TIME_T especially for mingw-4.0-rc1: Although it works, it has the side-effect that tcl8?.dll depends on msvcrt.dll symbols which are only available in later versions of msvcrt.dll. This is undesired, it really should be fixed in the mingw headers. 2013-05-17 07:14:13 +00:00
andreask a425618034 Sigh. Fix version number of package "platform" in the Makefile.n files. Future: Write a small tcl script tool to extract the version information directly from the code. 2013-05-16 17:43:23 +00:00
andreask b5f1bdb187 Sigh. Fix version number of package "platform" in the Makefile.n files. Future: Write a small tcl script tool to extract the version information directly from the code. 2013-05-16 17:39:44 +00:00
dgp 007c00ed28 Confirmed that every caller of TclProcCompileProc() arranges for the
procPtr and nsPtr arguments: nsPtr == procPtr->cmdPtr->nsPtr.
This makes the test in TclCompileScript() useless. TCS() will always
compile in the current namespace of the interp.  Remove the code that
obfuscates that fact.
2013-05-16 13:24:28 +00:00
jan.nijtmans 13a2a82c81 Add support for the latest mingw-4.0-rc1. See: [http://sourceforge.net/p/mingw/mingw-org-wsl/ci/4.0-rc1/tree/NEWS] 2013-05-16 12:33:05 +00:00
jan.nijtmans b55a06a8a5 _USE_32BIT_TIME_T is already defined in tclWinPort.h 2013-05-16 12:28:33 +00:00
jan.nijtmans 87d602d36b Add support for the latest mingw-4.0-rc1. See: [http://sourceforge.net/p/mingw/mingw-org-wsl/ci/4.0-rc1/tree/NEWS] 2013-05-16 12:22:51 +00:00
jan.nijtmans 472c40ee51 Add support for the latest mingw-4.0-rc1. See: [http://sourceforge.net/p/mingw/mingw-org-wsl/ci/4.0-rc1/tree/NEWS] 2013-05-16 08:20:16 +00:00
andreask 06130c47bf Fix platform version mismatch between code and index. 2013-05-15 16:55:43 +00:00
andreask bf048c0574 Fix platform version mismatch between code and index. 2013-05-15 16:49:49 +00:00
andreask 8654042602 Fix platform version mismatch between code and index. 2013-05-15 16:46:15 +00:00
dgp 11832ca791 Disabled some code in TclCompileScript(). Test suite results are unaffected.
Does this indicate a gap in the test suite, or is this code truly useless?
2013-05-15 15:18:00 +00:00
dkf e516af3ee3 Removing a few changes that were not actually needed, and correcting comments. 2013-05-15 10:56:41 +00:00
dkf 27e4c0fd0a merge-mark 2013-05-15 10:44:17 +00:00
dkf 5f10b318a9 A better technique for [list {*}blah]. Remove the INST_LIST_EXPANDED opcode (and the complex machinery associated with it) as as it is no longer needed. 2013-05-15 10:41:52 +00:00
jan.nijtmans 45f9ea1e07 merge-mark 2013-05-15 10:41:42 +00:00
jan.nijtmans 9cebbfe5c2 merge-mark 2013-05-15 10:37:06 +00:00
jan.nijtmans 15f3cf55c9 Add missing "platform" package to the distribution as well. Reported by Pietro Cerutti. 2013-05-15 10:27:55 +00:00
oehhar b12676f0d0 Corrected args -> arg arg ... in msgcat doc 2013-05-08 15:47:31 +00:00
oehhar cac74426e8 Document mcunknown format parameters 2013-05-08 14:52:51 +00:00
oehhar 41c4cbfb48 Add install references and changes entry 2013-05-08 08:40:22 +00:00
oehhar 64e39b2d5a Also get msgcat locale from Vista+ registry key "HCU/Control Panel/Desktop : PreferredUILanguages" to honor installed language packs. msgcat now 1.5.2 2013-05-08 08:24:54 +00:00
40 changed files with 5156 additions and 4304 deletions
+109 -28
View File
@@ -1,3 +1,87 @@
2013-06-09 Donal K. Fellows <dkf@users.sf.net>
* generic/tclCompCmdsSZ.c (TclCompileTryCmd): [Bug 779d38b996]:
Rewrote the [try] compiler to generate better code in some cases and
to behave correctly in others; when an error happens during the
processing of an exception-trap clause or a finally clause, the
*original* return options are now captured in a -during option, even
when fully compiled.
2013-06-05 Donal K. Fellows <dkf@users.sf.net>
* generic/tclExecute.c (INST_EXPAND_DROP): [Bugs 2835313, 3614226]:
New opcode to allow resetting the stack to get rid of an expansion,
restoring the stack to a known state in the process.
* generic/tclCompile.c, generic/tclCompCmds.c: Adjusted the compilers
for [break] and [continue] to get stack cleanup right in the majority
of cases.
* tests/for.test (for-7.*): Set of tests for these evil cases.
2013-06-04 Jan Nijtmans <nijtmans@users.sf.net>
* unix/tcl.m4: Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN
instead. One more last-moment fix for FreeBSD by Pietro Cerutti
2013-06-03 Miguel Sofer <msofer@users.sf.net>
* generic/tclExecute.c: fix for perf bug detected by Kieran
(https://groups.google.com/forum/?fromgroups#!topic/comp.lang.tcl/vfpI3bc-DkQ),
diagnosed by dgp to be a close relative of [Bug 781585], which was
fixed by commit [f46fb50cb3]. This bug was introduced by myself in
commit [cbfe055d8c].
2013-06-03 Donal K. Fellows <dkf@users.sf.net>
* generic/tclCompCmds.c (TclCompileBreakCmd, TclCompileContinueCmd):
Added code to allow [break] and [continue] to be issued as a jump (in
the most common cases) rather than using the more expensive exception
processing path in the bytecode engine. [Bug 3614226]: Partial fix for
the issues relating to cleaning up the stack when dealing with [break]
and [continue].
2013-05-27 Harald Oehlmann <oehhar@users.sf.net>
* library/msgcat/msgcat.tcl: [Bug 3036566]: Also get locale from
registry key HCU\Control Panel\Desktop : PreferredUILanguages to honor
installed language packs on Vista+.
Bumped msgcat version to 1.5.2
2013-05-22 Andreas Kupries <andreask@activestate.com>
* tclCompile.c: Removed duplicate const qualifier causing the HP
native cc to error out.
2013-05-22 Donal K. Fellows <dkf@users.sf.net>
* generic/tclUtf.c (TclUtfCasecmp): [Bug 3613609]: Replace problematic
uses of strcasecmp with a proper UTF-8-aware version. Affects both
[lsearch -nocase] and [lsort -nocase].
2013-05-22 Donal K. Fellows <dkf@users.sf.net>
* doc/file.n: [Bug 3613671]: Added note to portability section on the
fact that [file owned] does not produce useful results on Windows.
2013-05-20 Donal K. Fellows <dkf@users.sf.net>
* unix/tclUnixFCmd.c (DefaultTempDir): [Bug 3613567]: Corrected logic
for checking return code of access() system call, which was inverted.
2013-05-19 Jan Nijtmans <nijtmans@users.sf.net>
* unix/tcl.m4: Fix for FreeBSD, and remove support for older
* unix/configure: FreeBSD versions. Patch by Pietro Cerutti.
2013-05-18 Donal K. Fellows <dkf@users.sf.net>
* generic/tclCompCmdsGR.c: Split tclCompCmds.c again to keep size of
code down.
2013-05-16 Jan Nijtmans <nijtmans@users.sf.net>
* generic/tclBasic.c: Add panic in order to detect incompatible
mingw32 sys/stat.h and sys/time.h headers.
2013-05-13 Jan Nijtmans <nijtmans@users.sf.net>
* compat/zlib/*: Upgrade to zlib 1.2.8
@@ -27,10 +111,9 @@
2013-04-30 Andreas Kupries <andreask@activestate.com>
* library/platform/platform.tcl (::platform::LibcVersion):
* library/platform/pkgIndex.tcl: Followup to the 2013-01-30
change. The RE become too restrictive again. SuSe added a
timestamp after the version. Loosened up a bit. Bumped package
to version 1.0.12.
* library/platform/pkgIndex.tcl: Followup to the 2013-01-30 change.
The RE become too restrictive again. SuSe added a timestamp after the
version. Loosened up a bit. Bumped package to version 1.0.12.
2013-04-29 Donal K. Fellows <dkf@users.sf.net>
@@ -49,8 +132,8 @@
2013-04-19 Jan Nijtmans <nijtmans@users.sf.net>
* generic/tclDecls.h: Implement many Tcl_*Var* functions and
Tcl_GetIndexFromObj as (faster/stack-saving) macros around resp
their Tcl_*Var*2 equivalent and Tcl_GetIndexFromObjStruct.
Tcl_GetIndexFromObj as (faster/stack-saving) macros around resp their
Tcl_*Var*2 equivalent and Tcl_GetIndexFromObjStruct.
2013-04-12 Jan Nijtmans <nijtmans@users.sf.net>
@@ -59,16 +142,16 @@
2013-04-08 Don Porter <dgp@users.sourceforge.net>
* generic/regc_color.c: [Bug 3610026] Stop crash when the number of
* generic/regerrs.h: "colors" in a regular expression overflows
* generic/regex.h: a short int. Thanks to Heikki Linnakangas
* generic/regguts.h: for the report and the patch.
* generic/regc_color.c: [Bug 3610026]: Stop crash when the number of
* generic/regerrs.h: "colors" in a regular expression overflows a
* generic/regex.h: short int. Thanks to Heikki Linnakangas for
* generic/regguts.h: the report and the patch.
* tests/regexp.test:
2013-04-04 Reinhard Max <max@suse.de>
* library/http/http.tcl (http::geturl): Allow URLs that don't have
a path, but a query query, e.g. http://example.com?foo=bar .
* library/http/http.tcl (http::geturl): Allow URLs that don't have a
path, but a query query, e.g. http://example.com?foo=bar
* Bump the http package to 2.8.7.
2013-03-22 Venkat Iyer <venkat@comit.com>
@@ -100,12 +183,12 @@
2013-03-21 Don Porter <dgp@users.sourceforge.net>
* library/auto.tcl: [Bug 2102614] Add ensemble indexing support
* tests/autoMkindex.test: to [auto_mkindex]. Thanks Brian Griffin.
* library/auto.tcl: [Bug 2102614]: Add ensemble indexing support to
* tests/autoMkindex.test: [auto_mkindex]. Thanks Brian Griffin.
2013-03-19 Don Porter <dgp@users.sourceforge.net>
* generic/tclFCmd.c: [Bug 3597000] Consistent [file copy] result.
* generic/tclFCmd.c: [Bug 3597000]: Consistent [file copy] result.
* tests/fileSystem.test:
2013-03-19 Jan Nijtmans <nijtmans@users.sf.net>
@@ -125,20 +208,20 @@
2013-03-11 Don Porter <dgp@users.sourceforge.net>
* generic/tclCompile.c: [Bugs 3607246,3607372] Unbalanced refcounts
* generic/tclCompile.c: [Bugs 3607246,3607372]: Unbalanced refcounts
* generic/tclLiteral.c: of literals in the global literal table.
2013-03-06 Don Porter <dgp@users.sourceforge.net>
* generic/regc_nfa.c: [Bugs 3604074,3606683] Rewrite of the
* generic/regcomp.c: fixempties() routine (and supporting
routines) to completely eliminate the infinite loop hazard.
Thanks to Tom Lane for the much improved solution.
* generic/regc_nfa.c: [Bugs 3604074,3606683]: Rewrite of the
* generic/regcomp.c: fixempties() routine (and supporting routines)
to completely eliminate the infinite loop hazard. Thanks to Tom Lane
for the much improved solution.
2013-02-28 Don Porter <dgp@users.sourceforge.net>
* generic/tclLiteral.c: Revise TclReleaseLiteral() to tolerate a
NULL interp argument.
* generic/tclLiteral.c: Revise TclReleaseLiteral() to tolerate a NULL
interp argument.
* generic/tclCompile.c: Update callers and revise mistaken comments.
* generic/tclProc.c:
@@ -4833,8 +4916,7 @@
2010-05-19 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
* tests/dict.test: Add missing tests for [Bug 3004007], fixed under
the radar on 2010-02-24 (dkf): EIAS violation in
list-dict conversions.
the radar on 2010-02-24 (dkf): EIAS violation in list-dict conversions
2010-05-19 Jan Nijtmans <nijtmans@users.sf.net>
@@ -6688,10 +6770,9 @@
2009-11-11 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
* generic/tclIO.c: Fix [Bug 2888099] (close discards ENOSPC error)
by saving the errno from the first of two
FlushChannel()s. Uneasy to test; might need
specific channel drivers. Four-hands with aku.
* generic/tclIO.c: Fix [Bug 2888099] (close discards ENOSPC error) by
saving the errno from the first of two FlushChannel()s. Uneasy to
test; might need specific channel drivers. Four-hands with aku.
2009-11-10 Pat Thoyts <patthoyts@users.sourceforge.net>
+4
View File
@@ -8163,3 +8163,7 @@ Dropped support for OS X versions less than 10.4 (Tiger) (fellows)
2012-12-13 (bug fix) crash: [zlib gunzip $data -header noSuchNs::var] (porter)
--- Released 8.6.0, December 20, 2012 --- See ChangeLog for details ---
2013-05-08 (bug fix)[3036566] Honor language packs on Vista+ to get initial locale (oehlmann)
=> msgcat 1.5.2
+7
View File
@@ -481,6 +481,13 @@ Returns \fB1\fR if file \fIname\fR is writable by the current user,
.
These commands always operate using the real user and group identifiers,
not the effective ones.
.TP
\fBWindows\fR\0\0\0\0
.
The \fbfile owned\fR subcommand currently always reports that the current user
is the owner of the file, without regard for what the operating system
believes to be true, making an ownership test useless. This issue (#3613671)
may be fixed in a future release of Tcl.
.SH EXAMPLES
.PP
This procedure shows how to search for C files in a given directory
+4 -3
View File
@@ -35,7 +35,7 @@ msgcat \- Tcl message catalog
\fB::msgcat::mcflmset \fIsrc-trans-list\fR
.VE "TIP 404"
.sp
\fB::msgcat::mcunknown \fIlocale src-string\fR
\fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
@@ -157,12 +157,13 @@ translate-string\fR ?\fIsrc-string translate-string ...\fR?}
of \fB::msgcat::mcflset\fR. The function returns the number of translations set.
.VE "TIP 404"
.TP
\fB::msgcat::mcunknown \fIlocale src-string\fR
\fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR?
.
This routine is called by \fB::msgcat::mc\fR in the case when
a translation for \fIsrc-string\fR is not defined in the
current locale. The default action is to return
\fIsrc-string\fR. This procedure can be redefined by the
\fIsrc-string\fR passed by format if there are any arguments. This
procedure can be redefined by the
application, for example to log error messages for each unknown
string. The \fB::msgcat::mcunknown\fR procedure is invoked at the
same stack context as the call to \fB::msgcat::mc\fR. The return value
+3 -3
View File
@@ -341,12 +341,12 @@ struct subre {
#define CAP 010 /* capturing parens below */
#define BACKR 020 /* back reference below */
#define INUSE 0100 /* in use in final tree */
#define LOCAL 03 /* bits which may not propagate up */
#define NOPROP 03 /* bits which may not propagate up */
#define LMIX(f) ((f)<<2) /* LONGER -> MIXED */
#define SMIX(f) ((f)<<1) /* SHORTER -> MIXED */
#define UP(f) (((f)&~LOCAL) | (LMIX(f) & SMIX(f) & MIXED))
#define UP(f) (((f)&~NOPROP) | (LMIX(f) & SMIX(f) & MIXED))
#define MESSY(f) ((f)&(MIXED|CAP|BACKR))
#define PREF(f) ((f)&LOCAL)
#define PREF(f) ((f)&NOPROP)
#define PREF2(f1, f2) ((PREF(f1) != 0) ? PREF(f1) : PREF(f2))
#define COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2))
short retry; /* index into retry memory */
+6 -4
View File
@@ -329,10 +329,12 @@ typedef long LONG;
* in ANSI C; maps them to type "char *" in non-ANSI systems.
*/
#ifndef NO_VOID
# define VOID void
#else
# define VOID char
#ifndef __VXWORKS__
# ifndef NO_VOID
# define VOID void
# else
# define VOID char
# endif
#endif
/*
+7 -31
View File
@@ -20,7 +20,7 @@
*- break and continue - if exception ranges can be sorted out.
*- foreach_start4, foreach_step4
*- returnImm, returnStk
*- expandStart, expandStkTop, invokeExpanded, listExpanded
*- expandStart, expandStkTop, invokeExpanded, expandDrop
*- dictFirst, dictNext, dictDone
*- dictUpdateStart, dictUpdateEnd
*- jumpTable testing
@@ -323,29 +323,6 @@ static const Tcl_ObjType assembleCodeType = {
NULL /* setFromAnyProc */
};
/*
* TIP #280: Remember the per-word line information of the current command. An
* index is used instead of a pointer as recursive compilation may reallocate,
* i.e. move, the array. This is also the reason to save the nuloc now, it may
* change during the course of the function.
*
* Macro to encapsulate the variable definition and setup.
*/
#define DefineLineInformation \
ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr; \
int eclIndex = mapPtr->nuloc - 1
#define SetLineInformation(word) \
envPtr->line = mapPtr->loc[eclIndex].line[(word)]; \
envPtr->clNext = mapPtr->loc[eclIndex].next[(word)]
/*
* Flags bits used by PushVarName.
*/
#define TCL_NO_LARGE_INDEX 1 /* Do not return localIndex value > 255 */
/*
* Source instructions recognized in the Tcl Assembly Language (TAL)
*/
@@ -410,9 +387,8 @@ static const TalInstDesc TalInstructionTable[] = {
{"incrArrayStkImm", ASSEM_SINT1, INST_INCR_ARRAY_STK_IMM,2, 1},
{"incrImm", ASSEM_LVT1_SINT1,
INST_INCR_SCALAR1_IMM, 0, 1},
{"incrStk", ASSEM_1BYTE, INST_INCR_SCALAR_STK, 2, 1},
{"incrStkImm", ASSEM_SINT1, INST_INCR_SCALAR_STK_IMM,
1, 1},
{"incrStk", ASSEM_1BYTE, INST_INCR_STK, 2, 1},
{"incrStkImm", ASSEM_SINT1, INST_INCR_STK_IMM, 1, 1},
{"infoLevelArgs", ASSEM_1BYTE, INST_INFO_LEVEL_ARGS, 1, 1},
{"infoLevelNumber", ASSEM_1BYTE, INST_INFO_LEVEL_NUM, 0, 1},
{"invokeStk", ASSEM_INVOKE, (INST_INVOKE_STK1 << 8
@@ -448,7 +424,7 @@ static const TalInstDesc TalInstructionTable[] = {
{"loadArray", ASSEM_LVT, (INST_LOAD_ARRAY1<<8
| INST_LOAD_ARRAY4), 1, 1},
{"loadArrayStk", ASSEM_1BYTE, INST_LOAD_ARRAY_STK, 2, 1},
{"loadStk", ASSEM_1BYTE, INST_LOAD_SCALAR_STK, 1, 1},
{"loadStk", ASSEM_1BYTE, INST_LOAD_STK, 1, 1},
{"lor", ASSEM_1BYTE, INST_LOR, 2, 1},
{"lsetFlat", ASSEM_LSET_FLAT,INST_LSET_FLAT, INT_MIN,1},
{"lsetList", ASSEM_1BYTE, INST_LSET_LIST, 3, 1},
@@ -475,7 +451,7 @@ static const TalInstDesc TalInstructionTable[] = {
{"storeArray", ASSEM_LVT, (INST_STORE_ARRAY1<<8
| INST_STORE_ARRAY4), 2, 1},
{"storeArrayStk", ASSEM_1BYTE, INST_STORE_ARRAY_STK, 3, 1},
{"storeStk", ASSEM_1BYTE, INST_STORE_SCALAR_STK, 2, 1},
{"storeStk", ASSEM_1BYTE, INST_STORE_STK, 2, 1},
{"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1},
{"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1},
{"strfind", ASSEM_1BYTE, INST_STR_FIND, 2, 1},
@@ -674,7 +650,7 @@ BBEmitOpcode(
}
TclEmitInt1(op, envPtr);
envPtr->atCmdStart = ((op) == INST_START_CMD);
TclUpdateAtCmdStart(op, envPtr);
BBUpdateStackReqs(bbPtr, tblIdx, count);
}
@@ -735,7 +711,7 @@ BBEmitInst1or4(
} else {
TclEmitInt4(param, envPtr);
}
envPtr->atCmdStart = ((op) == INST_START_CMD);
TclUpdateAtCmdStart(op, envPtr);
BBUpdateStackReqs(bbPtr, tblIdx, count);
}
+11
View File
@@ -486,6 +486,17 @@ Tcl_CreateInterp(void)
Tcl_Panic("Tcl_CallFrame must not be smaller than CallFrame");
}
#if defined(_WIN32) && !defined(_WIN64)
if (sizeof(time_t) != 4) {
/*NOTREACHED*/
Tcl_Panic("sys/time.h is not compatible with MSVC");
}
if (sizeof(Tcl_StatBuf) != 48) {
/*NOTREACHED*/
Tcl_Panic("sys/stat.h is not compatible with MSVC");
}
#endif
if (cancelTableInitialized == 0) {
Tcl_MutexLock(&cancelLock);
if (cancelTableInitialized == 0) {
+7 -6
View File
@@ -3005,7 +3005,7 @@ Tcl_LsearchObjCmd(
dataType = INTEGER;
break;
case LSEARCH_NOCASE: /* -nocase */
strCmpFn = strcasecmp;
strCmpFn = TclUtfCasecmp;
noCase = 1;
break;
case LSEARCH_NOT: /* -not */
@@ -3400,7 +3400,7 @@ Tcl_LsearchObjCmd(
*/
if (noCase) {
match = (strcasecmp(bytes, patternBytes) == 0);
match = (TclUtfCasecmp(bytes, patternBytes) == 0);
} else {
match = (memcmp(bytes, patternBytes,
(size_t) length) == 0);
@@ -3645,7 +3645,8 @@ Tcl_LsortObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument values. */
{
int i, j, index, indices, length, nocase = 0, sortMode, indexc;
int i, j, index, indices, length, nocase = 0, indexc;
int sortMode = SORTMODE_ASCII;
int group, groupSize, groupOffset, idx, allocatedIndexVector = 0;
Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
SortElement *elementArray, *elementPtr;
@@ -3991,7 +3992,7 @@ Tcl_LsortObjCmd(
goto done1;
}
elementArray[i].collationKey.intValue = a;
} else if (sortInfo.sortMode == SORTMODE_REAL) {
} else if (sortMode == SORTMODE_REAL) {
double a;
if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr,
@@ -4088,7 +4089,7 @@ Tcl_LsortObjCmd(
TclStackFree(interp, elementArray);
done:
if (sortInfo.sortMode == SORTMODE_COMMAND) {
if (sortMode == SORTMODE_COMMAND) {
TclDecrRefCount(sortInfo.compareCmdPtr);
TclDecrRefCount(listObj);
sortInfo.compareCmdPtr = NULL;
@@ -4233,7 +4234,7 @@ SortCompare(
order = strcmp(elemPtr1->collationKey.strValuePtr,
elemPtr2->collationKey.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
order = strcasecmp(elemPtr1->collationKey.strValuePtr,
order = TclUtfCasecmp(elemPtr1->collationKey.strValuePtr,
elemPtr2->collationKey.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
order = DictionaryCompare(elemPtr1->collationKey.strValuePtr,
+1 -1
View File
@@ -3527,7 +3527,7 @@ TclNRSwitchObjCmd(
i++;
goto finishedOptions;
case OPT_NOCASE:
strCmpFn = strcasecmp;
strCmpFn = TclUtfCasecmp;
noCase = 1;
break;
+267 -3338
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+402 -502
View File
File diff suppressed because it is too large Load Diff
+387 -190
View File
@@ -51,7 +51,7 @@ static int traceInitialized = 0;
* existence of a procedure call frame to distinguish these.
*/
const InstructionDesc const tclInstructionTable[] = {
InstructionDesc const tclInstructionTable[] = {
/* Name Bytes stackEffect #Opnds Operand types */
{"done", 1, -1, 0, {OPERAND_NONE}},
/* Finish ByteCode execution and return stktop (top stack item) */
@@ -283,8 +283,9 @@ const InstructionDesc const tclInstructionTable[] = {
* NOTE: the stack effects of expandStkTop and invokeExpanded are wrong -
* but it cannot be done right at compile time, the stack effect is only
* known at run time. The value for invokeExpanded is estimated better at
* compile time. See the comments further down in this file, where
* INST_INVOKE_EXPANDED is emitted.
* compile time.
* See the comments further down in this file, where INST_INVOKE_EXPANDED
* is emitted.
*/
{"expandStart", 1, 0, 0, {OPERAND_NONE}},
/* Start of command with {*} (expanded) arguments */
@@ -309,7 +310,7 @@ const InstructionDesc const tclInstructionTable[] = {
{"pushReturnOpts", 1, +1, 0, {OPERAND_NONE}},
/* Push the interpreter's return option dictionary as an object on the
* stack. */
{"returnStk", 1, -2, 0, {OPERAND_NONE}},
{"returnStk", 1, -1, 0, {OPERAND_NONE}},
/* Compiled [return]; options and result are on the stack, code and
* level are in the options. */
@@ -382,7 +383,8 @@ const InstructionDesc const tclInstructionTable[] = {
/* finds namespace and otherName in stack, links to local variable at
* index op1. Leaves the namespace on stack. */
{"syntax", 9, -1, 2, {OPERAND_INT4, OPERAND_UINT4}},
/* Compiled bytecodes to signal syntax error. */
/* Compiled bytecodes to signal syntax error. Equivalent to returnImm
* except for the ERR_ALREADY_LOGGED flag in the interpreter. */
{"reverse", 5, 0, 1, {OPERAND_UINT4}},
/* Reverse the order of the arg elements at the top of stack */
@@ -430,7 +432,7 @@ const InstructionDesc const tclInstructionTable[] = {
/* Map variable contents back into a dictionary in a variable. Part of
* [dict with].
* Stack: ... dictVarName path keyList => ... */
{"dictRecombineImm", 1, -2, 1, {OPERAND_LVT4}},
{"dictRecombineImm", 5, -2, 1, {OPERAND_LVT4}},
/* Map variable contents back into a dictionary in the local variable
* indicated by the LVT index. Part of [dict with].
* Stack: ... path keyList => ... */
@@ -539,6 +541,10 @@ const InstructionDesc const tclInstructionTable[] = {
* list and pushes that resulting list onto the stack.
* Stack: ... list1 list2 => ... [lconcat list1 list2] */
{"expandDrop", 1, 0, 0, {OPERAND_NONE}},
/* Drops an element from the auxiliary stack, popping stack elements
* until the matching stack depth is reached. */
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
@@ -556,20 +562,20 @@ static void EnterCmdExtentData(CompileEnv *envPtr,
int cmdNumber, int numSrcBytes, int numCodeBytes);
static void EnterCmdStartData(CompileEnv *envPtr,
int cmdNumber, int srcOffset, int codeOffset);
static Command * FindCommandFromToken(Tcl_Interp *interp,
Tcl_Token *tokenPtr, Tcl_Namespace *namespacePtr);
static Command * FindCompiledCommandFromToken(Tcl_Interp *interp,
Tcl_Token *tokenPtr);
static void FreeByteCodeInternalRep(Tcl_Obj *objPtr);
static void FreeSubstCodeInternalRep(Tcl_Obj *objPtr);
static int GetCmdLocEncodingSize(CompileEnv *envPtr);
static int IsCompactibleCompileEnv(Tcl_Interp *interp,
CompileEnv *envPtr);
static void PeepholeOptimize(CompileEnv *envPtr);
#ifdef TCL_COMPILE_STATS
static void RecordByteCodeStats(ByteCode *codePtr);
#endif /* TCL_COMPILE_STATS */
static void RegisterAuxDataType(const AuxDataType *typePtr);
static int SetByteCodeFromAny(Tcl_Interp *interp,
Tcl_Obj *objPtr);
static void StartExpanding(CompileEnv *envPtr);
static int FormatInstruction(ByteCode *codePtr,
const unsigned char *pc, Tcl_Obj *bufferObj);
static void PrintSourceToObj(Tcl_Obj *appendObj,
@@ -624,6 +630,13 @@ static const Tcl_ObjType tclInstNameType = {
UpdateStringOfInstName, /* updateStringProc */
NULL, /* setFromAnyProc */
};
/*
* Helper macros.
*/
#define TclIncrUInt4AtPtr(ptr, delta) \
TclStoreInt4AtPtr(TclGetUInt4AtPtr(ptr)+(delta), (ptr));
/*
*----------------------------------------------------------------------
@@ -737,7 +750,9 @@ TclSetByteCodeFromAny(
}
compEnv.atCmdStart = 2; /* The disabling magic. */
TclCompileScript(interp, stringPtr, length, &compEnv);
assert (compEnv.atCmdStart > 1);
TclEmitOpcode(INST_DONE, &compEnv);
assert (compEnv.atCmdStart > 1);
}
/*
@@ -745,7 +760,7 @@ TclSetByteCodeFromAny(
* instruction generator boundaries.
*/
PeepholeOptimize(&compEnv);
TclOptimizeBytecode(&compEnv);
/*
* Invoke the compilation hook procedure if one exists.
@@ -1076,141 +1091,16 @@ IsCompactibleCompileEnv(
case INST_NSUPVAR:
case INST_VARIABLE:
return 0;
default:
size = tclInstructionTable[*pc].numBytes;
assert (size > 0);
break;
}
size = tclInstructionTable[*pc].numBytes;
assert (size > 0);
}
return 1;
}
/*
* ----------------------------------------------------------------------
*
* PeepholeOptimize --
*
* A very simple peephole optimizer for bytecode.
*
* ----------------------------------------------------------------------
*/
static void
PeepholeOptimize(
CompileEnv *envPtr)
{
unsigned char *pc, *prev1 = NULL, *prev2 = NULL, *target;
int size, isNew;
Tcl_HashTable targets;
Tcl_HashEntry *hPtr;
Tcl_HashSearch hSearch;
/*
* Find places where we should be careful about replacing instructions
* because they are the targets of various types of jumps.
*/
Tcl_InitHashTable(&targets, TCL_ONE_WORD_KEYS);
for (pc = envPtr->codeStart ; pc < envPtr->codeNext ; pc += size) {
size = tclInstructionTable[*pc].numBytes;
switch (*pc) {
case INST_JUMP1:
case INST_JUMP_TRUE1:
case INST_JUMP_FALSE1:
target = pc + TclGetInt1AtPtr(pc+1);
goto storeTarget;
case INST_JUMP4:
case INST_JUMP_TRUE4:
case INST_JUMP_FALSE4:
target = pc + TclGetInt4AtPtr(pc+1);
goto storeTarget;
case INST_BEGIN_CATCH4:
target = envPtr->codeStart + envPtr->exceptArrayPtr[
TclGetUInt4AtPtr(pc+1)].codeOffset;
storeTarget:
(void) Tcl_CreateHashEntry(&targets, (void *) target, &isNew);
break;
case INST_JUMP_TABLE:
hPtr = Tcl_FirstHashEntry(
&JUMPTABLEINFO(envPtr, pc+1)->hashTable, &hSearch);
for (; hPtr ; hPtr = Tcl_NextHashEntry(&hSearch)) {
target = pc + PTR2INT(Tcl_GetHashValue(hPtr));
(void) Tcl_CreateHashEntry(&targets, (void *) target, &isNew);
}
break;
}
}
/*
* Replace PUSH/POP sequences (when non-hazardous) with NOPs.
*/
(void) Tcl_CreateHashEntry(&targets, (void *) pc, &isNew);
for (pc = envPtr->codeStart ; pc < envPtr->codeNext ; pc += size) {
int blank = 0, i;
size = tclInstructionTable[*pc].numBytes;
prev2 = prev1;
prev1 = pc;
if (Tcl_FindHashEntry(&targets, (void *) (pc + size))) {
continue;
}
switch (*pc) {
case INST_PUSH1:
while (*(pc+size) == INST_NOP) {
size++;
}
if (*(pc+size) == INST_POP) {
blank = size + 1;
} else if (*(pc+size) == INST_CONCAT1
&& TclGetUInt1AtPtr(pc + size + 1) == 2) {
Tcl_Obj *litPtr = TclFetchLiteral(envPtr,
TclGetUInt1AtPtr(pc + 1));
int numBytes;
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
if (numBytes == 0) {
blank = size + 2;
}
}
break;
case INST_PUSH4:
while (*(pc+size) == INST_NOP) {
size++;
}
if (*(pc+size) == INST_POP) {
blank = size + 1;
} else if (*(pc+size) == INST_CONCAT1
&& TclGetUInt1AtPtr(pc + size + 1) == 2) {
Tcl_Obj *litPtr = TclFetchLiteral(envPtr,
TclGetUInt4AtPtr(pc + 1));
int numBytes;
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
if (numBytes == 0) {
blank = size + 2;
}
}
break;
}
if (blank > 0) {
for (i=0 ; i<blank ; i++) {
*(pc + i) = INST_NOP;
}
size = blank;
}
}
/*
* Trim a trailing double DONE.
*/
if (prev1 && prev2 && *prev1 == INST_DONE && *prev2 == INST_DONE
&& !Tcl_FindHashEntry(&targets, (void *) prev1)) {
envPtr->codeNext--;
}
Tcl_DeleteHashTable(&targets);
}
/*
*----------------------------------------------------------------------
*
@@ -1458,6 +1348,7 @@ TclInitCompileEnv(
envPtr->mallocedLiteralArray = 0;
envPtr->exceptArrayPtr = envPtr->staticExceptArraySpace;
envPtr->exceptAuxArrayPtr = envPtr->staticExAuxArraySpace;
envPtr->exceptArrayNext = 0;
envPtr->exceptArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES;
envPtr->mallocedExceptArray = 0;
@@ -1466,6 +1357,7 @@ TclInitCompileEnv(
envPtr->cmdMapEnd = COMPILEENV_INIT_CMD_MAP_SIZE;
envPtr->mallocedCmdMap = 0;
envPtr->atCmdStart = 1;
envPtr->expandCount = 0;
/*
* TIP #280: Set up the extended command location information, based on
@@ -1670,6 +1562,7 @@ TclFreeCompileEnv(
}
if (envPtr->mallocedExceptArray) {
ckfree(envPtr->exceptArrayPtr);
ckfree(envPtr->exceptAuxArrayPtr);
}
if (envPtr->mallocedCmdMap) {
ckfree(envPtr->cmdMapPtr);
@@ -1776,7 +1669,7 @@ TclWordKnownAtCompileTime(
/*
* ---------------------------------------------------------------------
*
* FindCommandFromToken --
* FindCompiledCommandFromToken --
*
* A simple helper that looks up a command's compiler from its token.
*
@@ -1784,15 +1677,20 @@ TclWordKnownAtCompileTime(
*/
static Command *
FindCommandFromToken(
FindCompiledCommandFromToken(
Tcl_Interp *interp,
Tcl_Token *tokenPtr,
Tcl_Namespace *namespacePtr)
Tcl_Token *tokenPtr)
{
Tcl_DString ds;
Command *cmdPtr;
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
/*
* If we have a non-trivial token or are suppressing compilation, we stop
* right now.
*/
if ((tokenPtr->type != TCL_TOKEN_SIMPLE_WORD)
|| (((Interp *) interp)->flags & DONT_COMPILE_CMDS_INLINE)) {
return NULL;
}
@@ -1805,8 +1703,8 @@ FindCommandFromToken(
Tcl_DStringInit(&ds);
TclDStringAppendToken(&ds, &tokenPtr[1]);
cmdPtr = (Command *) Tcl_FindCommand(interp, Tcl_DStringValue(&ds),
namespacePtr, /*flags*/ 0);
cmdPtr = (Command *) Tcl_FindCommand(interp, Tcl_DStringValue(&ds), NULL,
/*flags*/ 0);
if (cmdPtr != NULL && (cmdPtr->compileProc == NULL
|| (cmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION)
|| (cmdPtr->flags & CMD_HAS_EXEC_TRACES))) {
@@ -1845,7 +1743,6 @@ TclCompileScript(
* first null character. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
Interp *iPtr = (Interp *) interp;
int lastTopLevelCmdIndex = -1;
/* Index of most recent toplevel command in
* the command location table. Initialized to
@@ -1854,7 +1751,6 @@ TclCompileScript(
* code. Init. to avoid compiler warning. */
unsigned char *entryCodeNext = envPtr->codeNext;
const char *p, *next;
Namespace *cmdNsPtr;
Command *cmdPtr;
Tcl_Token *tokenPtr;
int bytesLeft, isFirstCmd, wordIdx, currCmdIndex, commandLength, objIndex;
@@ -1873,12 +1769,6 @@ TclCompileScript(
Tcl_ResetResult(interp);
isFirstCmd = 1;
if (envPtr->procPtr != NULL) {
cmdNsPtr = envPtr->procPtr->cmdPtr->nsPtr;
} else {
cmdNsPtr = NULL; /* use current NS */
}
/*
* Each iteration through the following loop compiles the next command
* from the script.
@@ -1916,8 +1806,7 @@ TclCompileScript(
parsePtr->commandStart - envPtr->source);
if (parsePtr->numWords > 0) {
int expand = 0; /* Set to the relevant expansion instruction
* if there are dynamic expansions to
int expand = 0; /* Set if there are dynamic expansions to
* handle */
/*
@@ -1971,7 +1860,7 @@ TclCompileScript(
wordIdx < parsePtr->numWords;
wordIdx++, tokenPtr += tokenPtr->numComponents + 1) {
if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
expand = INST_INVOKE_EXPANDED;
expand = 1;
break;
}
}
@@ -1980,13 +1869,13 @@ TclCompileScript(
* If expansion was requested, check if the command declares that
* it knows how to compile it. Note that if expansion is requested
* for the first word, this check will fail as the token type will
* inhibit it. (That check is done inside FindCommandFromToken.)
* This is as it should be.
* inhibit it. (Checked inside FindCompiledCommandFromToken.) This
* is as it should be.
*/
if (expand) {
cmdPtr = FindCommandFromToken(interp, parsePtr->tokenPtr,
(Tcl_Namespace *) cmdNsPtr);
cmdPtr = FindCompiledCommandFromToken(interp,
parsePtr->tokenPtr);
if (cmdPtr && (cmdPtr->flags & CMD_COMPILES_EXPANDED)) {
expand = 0;
}
@@ -2005,7 +1894,7 @@ TclCompileScript(
*/
if (expand) {
TclEmitOpcode(INST_EXPAND_START, envPtr);
StartExpanding(envPtr);
}
/*
@@ -2030,9 +1919,13 @@ TclCompileScript(
for (wordIdx = 0, tokenPtr = parsePtr->tokenPtr;
wordIdx < parsePtr->numWords; wordIdx++,
tokenPtr += tokenPtr->numComponents + 1) {
/*
* Note the parse location information.
*/
envPtr->line = eclPtr->loc[wlineat].line[wordIdx];
envPtr->clNext = eclPtr->loc[wlineat].next[wordIdx];
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
/*
* The word is not a simple string of characters.
@@ -2055,26 +1948,21 @@ TclCompileScript(
*/
if ((wordIdx == 0) && !expand) {
cmdPtr = FindCommandFromToken(interp, tokenPtr,
(Tcl_Namespace *) cmdNsPtr);
if ((cmdPtr != NULL)
&& !(iPtr->flags & DONT_COMPILE_CMDS_INLINE)) {
int code, savedNumCmds = envPtr->numCommands;
cmdPtr = FindCompiledCommandFromToken(interp, tokenPtr);
if (cmdPtr) {
int savedNumCmds = envPtr->numCommands;
unsigned savedCodeNext =
envPtr->codeNext - envPtr->codeStart;
int update = 0;
#ifdef TCL_COMPILE_DEBUG
int startStackDepth = envPtr->currStackDepth;
#endif
/*
* Mark the start of the command; the proper bytecode
* length will be updated later. There is no need to
* do this for the first bytecode in the compile env,
* as the check is done before calling
* TclNRExecuteByteCode(). Do emit an INST_START_CMD in
* special cases where the first bytecode is in a
* TclNRExecuteByteCode(). Do emit an INST_START_CMD
* in special cases where the first bytecode is in a
* loop, to insure that the corresponding command is
* counted properly. Compilers for commands able to
* produce such a beast (currently 'while 1' only) set
@@ -2095,10 +1983,7 @@ TclCompileScript(
* INST_START_CMD's operands, so be careful!
*/
unsigned char *fixPtr = envPtr->codeNext - 4;
TclStoreInt4AtPtr(TclGetUInt4AtPtr(fixPtr)+1,
fixPtr);
TclIncrUInt4AtPtr(envPtr->codeNext - 4, 1)
}
} else if (envPtr->atCmdStart == 0) {
TclEmitInstInt4(INST_START_CMD, 0, envPtr);
@@ -2106,10 +1991,8 @@ TclCompileScript(
update = 1;
}
code = cmdPtr->compileProc(interp, parsePtr, cmdPtr,
envPtr);
if (code == TCL_OK) {
if (cmdPtr->compileProc(interp, parsePtr, cmdPtr,
envPtr) == TCL_OK) {
/*
* Confirm that the command compiler generated a
* single value on the stack as its result. This
@@ -2152,10 +2035,7 @@ TclCompileScript(
* operands, so be careful!
*/
unsigned char *fixPtr = envPtr->codeNext - 4;
TclStoreInt4AtPtr(TclGetUInt4AtPtr(fixPtr)-1,
fixPtr);
TclIncrUInt4AtPtr(envPtr->codeNext - 4, -1);
}
/*
@@ -2167,6 +2047,12 @@ TclCompileScript(
envPtr->numCommands = savedNumCmds;
envPtr->codeNext = envPtr->codeStart + savedCodeNext;
/*
* And the stack depth too!! [Bug 3614102].
*/
envPtr->currStackDepth = startStackDepth;
}
/*
@@ -2178,7 +2064,7 @@ TclCompileScript(
objIndex = TclRegisterNewCmdLiteral(envPtr,
tokenPtr[1].start, tokenPtr[1].size);
if (cmdPtr != NULL) {
if (cmdPtr) {
TclSetCmdNameObj(interp,
TclFetchLiteral(envPtr, objIndex), cmdPtr);
}
@@ -2225,12 +2111,10 @@ TclCompileScript(
* Note that the estimates are not correct while the command
* is being prepared and run, INST_EXPAND_STKTOP is not
* stack-neutral in general.
*
* The opcode that may be issued here (assumed to be non-zero)
* is INST_INVOKE_EXPANDED.
*/
TclEmitOpcode(expand, envPtr);
TclEmitOpcode(INST_INVOKE_EXPANDED, envPtr);
envPtr->expandCount--;
TclAdjustStackDepth(1 - wordIdx, envPtr);
} else if (wordIdx > 0) {
/*
@@ -2382,7 +2266,7 @@ TclCompileVarSubst(
if (tokenPtr->numComponents == 1) {
if (localVar < 0) {
TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
TclEmitOpcode(INST_LOAD_STK, envPtr);
} else if (localVar <= 255) {
TclEmitInstInt1(INST_LOAD_SCALAR1, localVar, envPtr);
} else {
@@ -3362,6 +3246,7 @@ TclCreateExceptRange(
* new ExceptionRange structure. */
{
register ExceptionRange *rangePtr;
register ExceptionAux *auxPtr;
int index = envPtr->exceptArrayNext;
if (index >= envPtr->exceptArrayEnd) {
@@ -3373,12 +3258,16 @@ TclCreateExceptRange(
size_t currBytes =
envPtr->exceptArrayNext * sizeof(ExceptionRange);
size_t currBytes2 = envPtr->exceptArrayNext * sizeof(ExceptionAux);
int newElems = 2*envPtr->exceptArrayEnd;
size_t newBytes = newElems * sizeof(ExceptionRange);
size_t newBytes2 = newElems * sizeof(ExceptionAux);
if (envPtr->mallocedExceptArray) {
envPtr->exceptArrayPtr =
ckrealloc(envPtr->exceptArrayPtr, newBytes);
envPtr->exceptAuxArrayPtr =
ckrealloc(envPtr->exceptAuxArrayPtr, newBytes2);
} else {
/*
* envPtr->exceptArrayPtr isn't a ckalloc'd pointer, so we must
@@ -3386,9 +3275,12 @@ TclCreateExceptRange(
*/
ExceptionRange *newPtr = ckalloc(newBytes);
ExceptionAux *newPtr2 = ckalloc(newBytes2);
memcpy(newPtr, envPtr->exceptArrayPtr, currBytes);
memcpy(newPtr2, envPtr->exceptAuxArrayPtr, currBytes2);
envPtr->exceptArrayPtr = newPtr;
envPtr->exceptAuxArrayPtr = newPtr2;
envPtr->mallocedExceptArray = 1;
}
envPtr->exceptArrayEnd = newElems;
@@ -3403,9 +3295,298 @@ TclCreateExceptRange(
rangePtr->breakOffset = -1;
rangePtr->continueOffset = -1;
rangePtr->catchOffset = -1;
auxPtr = &envPtr->exceptAuxArrayPtr[index];
auxPtr->supportsContinue = 1;
auxPtr->stackDepth = envPtr->currStackDepth;
auxPtr->expandTarget = envPtr->expandCount;
auxPtr->expandTargetDepth = -1;
auxPtr->numBreakTargets = 0;
auxPtr->breakTargets = NULL;
auxPtr->allocBreakTargets = 0;
auxPtr->numContinueTargets = 0;
auxPtr->continueTargets = NULL;
auxPtr->allocContinueTargets = 0;
return index;
}
/*
* ---------------------------------------------------------------------
*
* TclGetInnermostExceptionRange --
*
* Returns the innermost exception range that covers the current code
* creation point, and (optionally) the stack depth that is expected at
* that point. Relies on the fact that the range has a numCodeBytes = -1
* when it is being populated and that inner ranges come after outer
* ranges.
*
* ---------------------------------------------------------------------
*/
ExceptionRange *
TclGetInnermostExceptionRange(
CompileEnv *envPtr,
int returnCode,
ExceptionAux **auxPtrPtr)
{
int exnIdx = -1, i;
for (i=0 ; i<envPtr->exceptArrayNext ; i++) {
ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i];
if (CurrentOffset(envPtr) >= rangePtr->codeOffset &&
(rangePtr->numCodeBytes == -1 || CurrentOffset(envPtr) <
rangePtr->codeOffset+rangePtr->numCodeBytes) &&
(returnCode != TCL_CONTINUE ||
envPtr->exceptAuxArrayPtr[i].supportsContinue)) {
exnIdx = i;
}
}
if (exnIdx == -1) {
return NULL;
}
if (auxPtrPtr) {
*auxPtrPtr = &envPtr->exceptAuxArrayPtr[exnIdx];
}
return &envPtr->exceptArrayPtr[exnIdx];
}
/*
* ---------------------------------------------------------------------
*
* TclAddLoopBreakFixup, TclAddLoopContinueFixup --
*
* Adds a place that wants to break/continue to the loop exception range
* tracking that will be fixed up once the loop can be finalized. These
* functions will generate an INST_JUMP4 that will be fixed up during the
* loop finalization.
*
* ---------------------------------------------------------------------
*/
void
TclAddLoopBreakFixup(
CompileEnv *envPtr,
ExceptionAux *auxPtr)
{
int range = auxPtr - envPtr->exceptAuxArrayPtr;
if (envPtr->exceptArrayPtr[range].type != LOOP_EXCEPTION_RANGE) {
Tcl_Panic("trying to add 'break' fixup to full exception range");
}
if (++auxPtr->numBreakTargets > auxPtr->allocBreakTargets) {
auxPtr->allocBreakTargets *= 2;
auxPtr->allocBreakTargets += 2;
if (auxPtr->breakTargets) {
auxPtr->breakTargets = ckrealloc(auxPtr->breakTargets,
sizeof(int) * auxPtr->allocBreakTargets);
} else {
auxPtr->breakTargets =
ckalloc(sizeof(int) * auxPtr->allocBreakTargets);
}
}
auxPtr->breakTargets[auxPtr->numBreakTargets - 1] = CurrentOffset(envPtr);
TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}
void
TclAddLoopContinueFixup(
CompileEnv *envPtr,
ExceptionAux *auxPtr)
{
int range = auxPtr - envPtr->exceptAuxArrayPtr;
if (envPtr->exceptArrayPtr[range].type != LOOP_EXCEPTION_RANGE) {
Tcl_Panic("trying to add 'continue' fixup to full exception range");
}
if (++auxPtr->numContinueTargets > auxPtr->allocContinueTargets) {
auxPtr->allocContinueTargets *= 2;
auxPtr->allocContinueTargets += 2;
if (auxPtr->continueTargets) {
auxPtr->continueTargets = ckrealloc(auxPtr->continueTargets,
sizeof(int) * auxPtr->allocContinueTargets);
} else {
auxPtr->continueTargets =
ckalloc(sizeof(int) * auxPtr->allocContinueTargets);
}
}
auxPtr->continueTargets[auxPtr->numContinueTargets - 1] =
CurrentOffset(envPtr);
TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}
/*
* ---------------------------------------------------------------------
*
* TclCleanupStackForBreakContinue --
*
* Ditch the extra elements from the auxiliary stack and the main
* stack. How to do this exactly depends on whether there are any
* elements on the auxiliary stack to pop.
*
* ---------------------------------------------------------------------
*/
void
TclCleanupStackForBreakContinue(
CompileEnv *envPtr,
ExceptionAux *auxPtr)
{
int toPop = envPtr->expandCount - auxPtr->expandTarget;
if (toPop > 0) {
while (toPop > 0) {
TclEmitOpcode(INST_EXPAND_DROP, envPtr);
toPop--;
}
toPop = auxPtr->expandTargetDepth - auxPtr->stackDepth;
while (toPop > 0) {
TclEmitOpcode(INST_POP, envPtr);
TclAdjustStackDepth(1, envPtr);
toPop--;
}
} else {
toPop = envPtr->currStackDepth - auxPtr->stackDepth;
while (toPop > 0) {
TclEmitOpcode(INST_POP, envPtr);
TclAdjustStackDepth(1, envPtr);
toPop--;
}
}
}
/*
* ---------------------------------------------------------------------
*
* StartExpanding --
*
* Pushes an INST_EXPAND_START and does some additional housekeeping so
* that the [break] and [continue] compilers can use an exception-free
* issue to discard it.
*
* ---------------------------------------------------------------------
*/
static void
StartExpanding(
CompileEnv *envPtr)
{
int i;
TclEmitOpcode(INST_EXPAND_START, envPtr);
/*
* Update inner exception ranges with information about the environment
* where this expansion started.
*/
for (i=0 ; i<envPtr->exceptArrayNext ; i++) {
ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i];
ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[i];
/*
* Ignore loops unless they're still being built.
*/
if (rangePtr->codeOffset > CurrentOffset(envPtr)) {
continue;
}
if (rangePtr->numCodeBytes != -1) {
continue;
}
/*
* Adequate condition: further out loops and further in exceptions
* don't actually need this information.
*/
if (auxPtr->expandTarget == envPtr->expandCount) {
auxPtr->expandTargetDepth = envPtr->currStackDepth;
}
}
/*
* There's now one more expansion being processed on the auxiliary stack.
*/
envPtr->expandCount++;
}
/*
* ---------------------------------------------------------------------
*
* TclFinalizeLoopExceptionRange --
*
* Finalizes a loop exception range, binding the registered [break] and
* [continue] implementations so that they jump to the correct place.
* Note that this must only be called after *all* the exception range
* target offsets have been set.
*
* ---------------------------------------------------------------------
*/
void
TclFinalizeLoopExceptionRange(
CompileEnv *envPtr,
int range)
{
ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[range];
ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[range];
int i, offset;
unsigned char *site;
if (rangePtr->type != LOOP_EXCEPTION_RANGE) {
Tcl_Panic("trying to finalize a loop exception range");
}
/*
* Do the jump fixups. Note that these are always issued as INST_JUMP4 so
* there is no need to fuss around with updating code offsets.
*/
for (i=0 ; i<auxPtr->numBreakTargets ; i++) {
site = envPtr->codeStart + auxPtr->breakTargets[i];
offset = rangePtr->breakOffset - auxPtr->breakTargets[i];
TclUpdateInstInt4AtPc(INST_JUMP4, offset, site);
}
for (i=0 ; i<auxPtr->numContinueTargets ; i++) {
site = envPtr->codeStart + auxPtr->continueTargets[i];
if (rangePtr->continueOffset == -1) {
int j;
/*
* WTF? Can't bind, so revert to an INST_CONTINUE. Not enough
* space to do anything else.
*/
*site = INST_CONTINUE;
for (j=0 ; j<4 ; j++) {
*++site = INST_NOP;
}
} else {
offset = rangePtr->continueOffset - auxPtr->continueTargets[i];
TclUpdateInstInt4AtPc(INST_JUMP4, offset, site);
}
}
/*
* Drop the arrays we were holding the only reference to.
*/
if (auxPtr->breakTargets) {
ckfree(auxPtr->breakTargets);
auxPtr->breakTargets = NULL;
auxPtr->numBreakTargets = 0;
}
if (auxPtr->continueTargets) {
ckfree(auxPtr->continueTargets);
auxPtr->continueTargets = NULL;
auxPtr->numContinueTargets = 0;
}
}
/*
*----------------------------------------------------------------------
*
@@ -3766,6 +3947,22 @@ TclFixupForwardJump(
}
}
for (k = 0 ; k < envPtr->exceptArrayNext ; k++) {
ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[k];
int i;
for (i=0 ; i<auxPtr->numBreakTargets ; i++) {
if (jumpFixupPtr->codeOffset < auxPtr->breakTargets[i]) {
auxPtr->breakTargets[i] += 3;
}
}
for (i=0 ; i<auxPtr->numContinueTargets ; i++) {
if (jumpFixupPtr->codeOffset < auxPtr->continueTargets[i]) {
auxPtr->continueTargets[i] += 3;
}
}
}
/*
* TIP #280: Adjust the mapping from PC values to the per-command
* information about arguments and their line numbers.
+158 -6
View File
@@ -99,6 +99,54 @@ typedef struct ExceptionRange {
* offset for any "exception" in range. */
} ExceptionRange;
/*
* Auxiliary data used when issuing (currently just loop) exception ranges,
* but which is not required during execution.
*/
typedef struct ExceptionAux {
int supportsContinue; /* Whether this exception range will have a
* continueOffset created for it; if it is a
* loop exception range that *doesn't* have
* one (see [for] next-clause) then we must
* not pick up the range when scanning for a
* target to continue to. */
int stackDepth; /* The stack depth at the point where the
* exception range was created. This is used
* to calculate the number of POPs required to
* restore the stack to its prior state. */
int expandTarget; /* The number of expansions expected on the
* auxData stack at the time the loop starts;
* we can't currently discard them except by
* doing INST_INVOKE_EXPANDED; this is a known
* problem. */
int expandTargetDepth; /* The stack depth expected at the outermost
* expansion within the loop. Not meaningful
* if there are no open expansions between the
* looping level and the point of jump
* issue. */
int numBreakTargets; /* The number of [break]s that want to be
* targeted to the place where this loop
* exception will be bound to. */
int *breakTargets; /* The offsets of the INST_JUMP4 instructions
* issued by the [break]s that we must
* update. Note that resizing a jump (via
* TclFixupForwardJump) can cause the contents
* of this array to be updated. When
* numBreakTargets==0, this is NULL. */
int allocBreakTargets; /* The size of the breakTargets array. */
int numContinueTargets; /* The number of [continue]s that want to be
* targeted to the place where this loop
* exception will be bound to. */
int *continueTargets; /* The offsets of the INST_JUMP4 instructions
* issued by the [continue]s that we must
* update. Note that resizing a jump (via
* TclFixupForwardJump) can cause the contents
* of this array to be updated. When
* numContinueTargets==0, this is NULL. */
int allocContinueTargets; /* The size of the continueTargets array. */
} ExceptionAux;
/*
* Structure used to map between instruction pc and source locations. It
* defines for each compiled Tcl command its code's starting offset and its
@@ -275,6 +323,11 @@ typedef struct CompileEnv {
* entry. */
int mallocedExceptArray; /* 1 if ExceptionRange array was expanded and
* exceptArrayPtr points in heap, else 0. */
ExceptionAux *exceptAuxArrayPtr;
/* Array of information used to restore the
* state when processing BREAK/CONTINUE
* exceptions. Must be the same size as the
* exceptArrayPtr. */
CmdLocation *cmdMapPtr; /* Points to start of CmdLocation array.
* numCommands is the index of the next entry
* to use; (numCommands-1) is the entry index
@@ -296,6 +349,9 @@ typedef struct CompileEnv {
/* Initial storage of LiteralEntry array. */
ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
/* Initial ExceptionRange array storage. */
ExceptionAux staticExAuxArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
/* Initial static except auxiliary info array
* storage. */
CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];
/* Initial storage for cmd location map. */
AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE];
@@ -312,6 +368,10 @@ typedef struct CompileEnv {
* inefficient. If set to 2, that instruction
* should not be issued at all (by the generic
* part of the command compiler). */
int expandCount; /* Number of INST_EXPAND_START instructions
* encountered that have not yet been paired
* with a corresponding
* INST_INVOKE_EXPANDED. */
ContLineLoc *clLoc; /* If not NULL, the table holding the
* locations of the invisible continuation
* lines in the input script, to adjust the
@@ -717,8 +777,10 @@ typedef struct ByteCode {
#define INST_LIST_CONCAT 164
#define INST_EXPAND_DROP 165
/* The last opcode */
#define LAST_INST_OPCODE 164
#define LAST_INST_OPCODE 165
/*
* Table describing the Tcl bytecode instructions: their name (for displaying
@@ -930,6 +992,8 @@ MODULE_SCOPE ByteCode * TclCompileObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
*/
MODULE_SCOPE void TclCleanupByteCode(ByteCode *codePtr);
MODULE_SCOPE void TclCleanupStackForBreakContinue(CompileEnv *envPtr,
ExceptionAux *auxPtr);
MODULE_SCOPE void TclCompileCmdWord(Tcl_Interp *interp,
Tcl_Token *tokenPtr, int count,
CompileEnv *envPtr);
@@ -984,10 +1048,19 @@ MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp,
int numBytes, const CmdFrame *invoker, int word);
MODULE_SCOPE void TclInitJumpFixupArray(JumpFixupArray *fixupArrayPtr);
MODULE_SCOPE void TclInitLiteralTable(LiteralTable *tablePtr);
MODULE_SCOPE ExceptionRange *TclGetInnermostExceptionRange(CompileEnv *envPtr,
int returnCode, ExceptionAux **auxPtrPtr);
MODULE_SCOPE void TclAddLoopBreakFixup(CompileEnv *envPtr,
ExceptionAux *auxPtr);
MODULE_SCOPE void TclAddLoopContinueFixup(CompileEnv *envPtr,
ExceptionAux *auxPtr);
MODULE_SCOPE void TclFinalizeLoopExceptionRange(CompileEnv *envPtr,
int range);
#ifdef TCL_COMPILE_STATS
MODULE_SCOPE char * TclLiteralStats(LiteralTable *tablePtr);
MODULE_SCOPE int TclLog2(int value);
#endif
MODULE_SCOPE void TclOptimizeBytecode(CompileEnv *envPtr);
#ifdef TCL_COMPILE_DEBUG
MODULE_SCOPE void TclPrintByteCodeObj(Tcl_Interp *interp,
Tcl_Obj *objPtr);
@@ -998,6 +1071,10 @@ MODULE_SCOPE void TclPrintObject(FILE *outFile,
Tcl_Obj *objPtr, int maxChars);
MODULE_SCOPE void TclPrintSource(FILE *outFile,
const char *string, int maxChars);
MODULE_SCOPE void TclPushVarName(Tcl_Interp *interp,
Tcl_Token *varTokenPtr, CompileEnv *envPtr,
int flags, int *localIndexPtr,
int *isScalarPtr, int line, int *clNext);
MODULE_SCOPE int TclRegisterLiteral(CompileEnv *envPtr,
char *bytes, int length, int flags);
MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
@@ -1353,15 +1430,19 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst);
TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \
(envPtr));
/*
* Convenience macro for use when pushing literals. The ANSI C "prototype" for
* this macro is:
* Convenience macros for use when pushing literals. The ANSI C "prototype" for
* these macros are:
*
* static void PushLiteral(CompileEnv *envPtr,
* const char *string, int length);
* static void PushStringLiteral(CompileEnv *envPtr,
* const char *string);
*/
#define PushLiteral(envPtr, string, length) \
TclEmitPush(TclRegisterNewLiteral((envPtr), (string), (length)), (envPtr))
#define PushStringLiteral(envPtr, string) \
PushLiteral((envPtr), (string), (int) (sizeof(string "") - 1))
/*
* Macro to advance to the next token; it is more mnemonic than the address
@@ -1390,14 +1471,11 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst);
* of LOOP ranges is an interesting datum for debugging purposes, and that is
* what we compute now.
*
* static int DeclareExceptionRange(CompileEnv *envPtr, int type);
* static int ExceptionRangeStarts(CompileEnv *envPtr, int index);
* static void ExceptionRangeEnds(CompileEnv *envPtr, int index);
* static void ExceptionRangeTarget(CompileEnv *envPtr, int index, LABEL);
*/
#define DeclareExceptionRange(envPtr, type) \
(TclCreateExceptRange((type), (envPtr)))
#define ExceptionRangeStarts(envPtr, index) \
(((envPtr)->exceptDepth++), \
((envPtr)->maxExceptDepth = \
@@ -1427,6 +1505,80 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst);
TclRegisterLiteral(envPtr, Tcl_DStringValue(dsPtr), \
Tcl_DStringLength(dsPtr), /*flags*/ 0)
/*
* Macro that encapsulates an efficiency trick that avoids a function call for
* the simplest of compiles. The ANSI C "prototype" for this macro is:
*
* static void CompileWord(CompileEnv *envPtr, Tcl_Token *tokenPtr,
* Tcl_Interp *interp, int word);
*/
#define CompileWord(envPtr, tokenPtr, interp, word) \
if ((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD) { \
TclEmitPush(TclRegisterNewLiteral((envPtr), (tokenPtr)[1].start, \
(tokenPtr)[1].size), (envPtr)); \
} else { \
envPtr->line = mapPtr->loc[eclIndex].line[word]; \
envPtr->clNext = mapPtr->loc[eclIndex].next[word]; \
TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \
(envPtr)); \
}
/*
* TIP #280: Remember the per-word line information of the current command. An
* index is used instead of a pointer as recursive compilation may reallocate,
* i.e. move, the array. This is also the reason to save the nuloc now, it may
* change during the course of the function.
*
* Macro to encapsulate the variable definition and setup.
*/
#define DefineLineInformation \
ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr; \
int eclIndex = mapPtr->nuloc - 1
#define SetLineInformation(word) \
envPtr->line = mapPtr->loc[eclIndex].line[(word)]; \
envPtr->clNext = mapPtr->loc[eclIndex].next[(word)]
#define PushVarNameWord(i,v,e,f,l,sc,word) \
TclPushVarName(i,v,e,f,l,sc, \
mapPtr->loc[eclIndex].line[(word)], \
mapPtr->loc[eclIndex].next[(word)])
/*
* Often want to issue one of two versions of an instruction based on whether
* the argument will fit in a single byte or not. This makes it much clearer.
*/
#define Emit14Inst(nm,idx,envPtr) \
if (idx <= 255) { \
TclEmitInstInt1(nm##1,idx,envPtr); \
} else { \
TclEmitInstInt4(nm##4,idx,envPtr); \
}
/*
* How to get an anonymous local variable (used for holding temporary values
* off the stack) or a local simple scalar.
*/
#define AnonymousLocal(envPtr) \
(TclFindCompiledLocal(NULL, /*nameChars*/ 0, /*create*/ 1, (envPtr)))
#define LocalScalar(chars,len,envPtr) \
(!TclIsLocalScalar((chars), (len)) ? -1 : \
TclFindCompiledLocal((chars), (len), /*create*/ 1, (envPtr)))
#define LocalScalarFromToken(tokenPtr,envPtr) \
((tokenPtr)->type != TCL_TOKEN_SIMPLE_WORD ? -1 : \
LocalScalar((tokenPtr)[1].start, (tokenPtr)[1].size, (envPtr)))
/*
* Flags bits used by TclPushVarName.
*/
#define TCL_NO_LARGE_INDEX 1 /* Do not return localIndex value > 255 */
#define TCL_NO_ELEMENT 2 /* Do not push the array element. */
/*
* DTrace probe macros (NOPs if DTrace support is not enabled).
*/
+33 -17
View File
@@ -257,7 +257,7 @@ VarHashCreateVar(
/* Verify the stack depth, only when no expansion is in progress */
#if TCL_COMPILE_DEBUG
#ifdef TCL_COMPILE_DEBUG
#define CHECK_STACK() \
do { \
ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, \
@@ -724,7 +724,7 @@ static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, int growth,
static void IllegalExprOperandType(Tcl_Interp *interp,
const unsigned char *pc, Tcl_Obj *opndPtr);
static void InitByteCodeExecution(Tcl_Interp *interp);
static inline int OFFSET(void *ptr);
static inline int wordSkip(void *ptr);
static void ReleaseDictIterator(Tcl_Obj *objPtr);
/* Useful elsewhere, make available in tclInt.h or stubs? */
static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords);
@@ -1001,13 +1001,13 @@ TclFinalizeExecution(void)
(TCL_ALLOCALIGN/sizeof(Tcl_Obj *))
/*
* OFFSET computes how many words have to be skipped until the next aligned
* wordSkip computes how many words have to be skipped until the next aligned
* word. Note that we are only interested in the low order bits of ptr, so
* that any possible information loss in PTR2INT is of no consequence.
*/
static inline int
OFFSET(
wordSkip(
void *ptr)
{
int mask = TCL_ALLOCALIGN-1;
@@ -1020,7 +1020,7 @@ OFFSET(
*/
#define MEMSTART(markerPtr) \
((markerPtr) + OFFSET(markerPtr))
((markerPtr) + wordSkip(markerPtr))
/*
*----------------------------------------------------------------------
@@ -1065,7 +1065,7 @@ GrowEvaluationStack(
} else {
#ifndef PURIFY
Tcl_Obj **tmpMarkerPtr = esPtr->tosPtr + 1;
int offset = OFFSET(tmpMarkerPtr);
int offset = wordSkip(tmpMarkerPtr);
if (needed + offset < 0) {
/*
@@ -2142,11 +2142,6 @@ TEBCresume(
CACHE_STACK_INFO();
if (result == TCL_OK) {
#ifndef TCL_COMPILE_DEBUG
if (*pc == INST_POP) {
NEXT_INST_V(1, cleanup, 0);
}
#endif
/*
* Push the call's object result and continue execution with the
* next instruction.
@@ -2155,8 +2150,6 @@ TEBCresume(
TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=",
objc, cmdNameBuf), Tcl_GetObjResult(interp));
objResultPtr = Tcl_GetObjResult(interp);
/*
* Reset the interp's result to avoid possible duplications of
* large objects [Bug 781585]. We do not call Tcl_ResetResult to
@@ -2168,9 +2161,16 @@ TEBCresume(
* the refCount it had in its role of iPtr->objResultPtr.
*/
objResultPtr = Tcl_GetObjResult(interp);
TclNewObj(objPtr);
Tcl_IncrRefCount(objPtr);
iPtr->objResultPtr = objPtr;
#ifndef TCL_COMPILE_DEBUG
if (*pc == INST_POP) {
TclDecrRefCount(objResultPtr);
NEXT_INST_V(1, cleanup, 0);
}
#endif
NEXT_INST_V(0, cleanup, -1);
}
@@ -2630,7 +2630,7 @@ TEBCresume(
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
#if !TCL_COMPILE_DEBUG
#ifndef TCL_COMPILE_DEBUG
if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) {
TclFreeIntRep(objResultPtr);
objResultPtr->bytes = ckrealloc(bytes, length+appendLen+1);
@@ -2666,7 +2666,7 @@ TEBCresume(
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
#if !TCL_COMPILE_DEBUG
#ifndef TCL_COMPILE_DEBUG
if (!Tcl_IsShared(objResultPtr)) {
bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,
length + appendLen);
@@ -2718,6 +2718,22 @@ TEBCresume(
PUSH_TAUX_OBJ(objPtr);
NEXT_INST_F(1, 0, 0);
case INST_EXPAND_DROP:
/*
* Drops an element of the auxObjList, popping stack elements to
* restore the stack to the state before the point where the aux
* element was created.
*/
CLANG_ASSERT(auxObjList);
objc = CURR_DEPTH - auxObjList->internalRep.ptrAndLongRep.value;
POP_TAUX_OBJ();
#ifdef TCL_COMPILE_DEBUG
/* Ugly abuse! */
starting = 1;
#endif
NEXT_INST_V(1, objc, 0);
case INST_EXPAND_STKTOP: {
int i;
ptrdiff_t moved;
@@ -6824,7 +6840,7 @@ TEBCresume(
*/
processExceptionReturn:
#if TCL_COMPILE_DEBUG
#ifdef TCL_COMPILE_DEBUG
switch (*pc) {
case INST_INVOKE_STK1:
opnd = TclGetUInt1AtPtr(pc+1);
@@ -6881,7 +6897,7 @@ TEBCresume(
rangePtr->codeOffset, rangePtr->continueOffset));
NEXT_INST_F(0, 0, 0);
}
#if TCL_COMPILE_DEBUG
#ifdef TCL_COMPILE_DEBUG
if (traceInstructions) {
objPtr = Tcl_GetObjResult(interp);
if ((result != TCL_ERROR) && (result != TCL_RETURN)) {
+3
View File
@@ -3225,6 +3225,9 @@ Tcl_LoadFile(
*/
copyToPtr = TclpTempFileNameForLibrary(interp, pathPtr);
if (copyToPtr == NULL) {
return TCL_ERROR;
}
Tcl_IncrRefCount(copyToPtr);
copyFsPtr = Tcl_FSGetFileSystemForPath(copyToPtr);
+1
View File
@@ -3094,6 +3094,7 @@ MODULE_SCOPE int TclTrimLeft(const char *bytes, int numBytes,
const char *trim, int numTrim);
MODULE_SCOPE int TclTrimRight(const char *bytes, int numBytes,
const char *trim, int numTrim);
MODULE_SCOPE int TclUtfCasecmp(const char *cs, const char *ct);
MODULE_SCOPE Tcl_Obj * TclpNativeToNormalized(ClientData clientData);
MODULE_SCOPE Tcl_Obj * TclpFilesystemPathType(Tcl_Obj *pathPtr);
MODULE_SCOPE int TclpDlopen(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+428
View File
@@ -0,0 +1,428 @@
/*
* tclOptimize.c --
*
* This file contains the bytecode optimizer.
*
* Copyright (c) 2013 by Donal Fellows.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#include "tclCompile.h"
#include <assert.h>
/*
* Forward declarations.
*/
static void AdvanceJumps(CompileEnv *envPtr);
static void ConvertZeroEffectToNOP(CompileEnv *envPtr);
static void LocateTargetAddresses(CompileEnv *envPtr,
Tcl_HashTable *tablePtr);
static void TrimUnreachable(CompileEnv *envPtr);
/*
* Helper macros.
*/
#define DefineTargetAddress(tablePtr, address) \
((void) Tcl_CreateHashEntry((tablePtr), (void *) (address), &isNew))
#define IsTargetAddress(tablePtr, address) \
(Tcl_FindHashEntry((tablePtr), (void *) (address)) != NULL)
#define AddrLength(address) \
(tclInstructionTable[*(unsigned char *)(address)].numBytes)
#define InstLength(instruction) \
(tclInstructionTable[(unsigned char)(instruction)].numBytes)
/*
* ----------------------------------------------------------------------
*
* LocateTargetAddresses --
*
* Populate a hash table with places that we need to be careful around
* because they're the targets of various kinds of jumps and other
* non-local behavior.
*
* ----------------------------------------------------------------------
*/
static void
LocateTargetAddresses(
CompileEnv *envPtr,
Tcl_HashTable *tablePtr)
{
unsigned char *currentInstPtr, *targetInstPtr;
int isNew, i;
Tcl_HashEntry *hPtr;
Tcl_HashSearch hSearch;
Tcl_InitHashTable(tablePtr, TCL_ONE_WORD_KEYS);
/*
* The starts of commands represent target addresses.
*/
for (i=0 ; i<envPtr->numCommands ; i++) {
DefineTargetAddress(tablePtr,
envPtr->codeStart + envPtr->cmdMapPtr[i].codeOffset);
}
/*
* Find places where we should be careful about replacing instructions
* because they are the targets of various types of jumps.
*/
for (currentInstPtr = envPtr->codeStart ;
currentInstPtr < envPtr->codeNext ;
currentInstPtr += AddrLength(currentInstPtr)) {
switch (*currentInstPtr) {
case INST_JUMP1:
case INST_JUMP_TRUE1:
case INST_JUMP_FALSE1:
targetInstPtr = currentInstPtr+TclGetInt1AtPtr(currentInstPtr+1);
goto storeTarget;
case INST_JUMP4:
case INST_JUMP_TRUE4:
case INST_JUMP_FALSE4:
targetInstPtr = currentInstPtr+TclGetInt4AtPtr(currentInstPtr+1);
goto storeTarget;
case INST_BEGIN_CATCH4:
targetInstPtr = envPtr->codeStart + envPtr->exceptArrayPtr[
TclGetUInt4AtPtr(currentInstPtr+1)].codeOffset;
storeTarget:
DefineTargetAddress(tablePtr, targetInstPtr);
break;
case INST_JUMP_TABLE:
hPtr = Tcl_FirstHashEntry(
&JUMPTABLEINFO(envPtr, currentInstPtr+1)->hashTable,
&hSearch);
for (; hPtr ; hPtr = Tcl_NextHashEntry(&hSearch)) {
targetInstPtr = currentInstPtr +
PTR2INT(Tcl_GetHashValue(hPtr));
DefineTargetAddress(tablePtr, targetInstPtr);
}
break;
case INST_RETURN_CODE_BRANCH:
for (i=TCL_ERROR ; i<TCL_CONTINUE+1 ; i++) {
DefineTargetAddress(tablePtr, currentInstPtr + 2*i - 1);
}
break;
case INST_START_CMD:
assert (envPtr->atCmdStart < 2);
}
}
/*
* Add a marker *after* the last bytecode instruction. WARNING: points to
* one past the end!
*/
DefineTargetAddress(tablePtr, currentInstPtr);
/*
* Enter in the targets of exception ranges.
*/
for (i=0 ; i<envPtr->exceptArrayNext ; i++) {
ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i];
if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
targetInstPtr = envPtr->codeStart + rangePtr->catchOffset;
DefineTargetAddress(tablePtr, targetInstPtr);
} else {
targetInstPtr = envPtr->codeStart + rangePtr->breakOffset;
DefineTargetAddress(tablePtr, targetInstPtr);
if (rangePtr->continueOffset >= 0) {
targetInstPtr = envPtr->codeStart + rangePtr->continueOffset;
DefineTargetAddress(tablePtr, targetInstPtr);
}
}
}
}
/*
* ----------------------------------------------------------------------
*
* TrimUnreachable --
*
* Converts code that provably can't be executed into NOPs and reduces
* the overall reported length of the bytecode where that is possible.
*
* ----------------------------------------------------------------------
*/
static void
TrimUnreachable(
CompileEnv *envPtr)
{
unsigned char *currentInstPtr;
Tcl_HashTable targets;
LocateTargetAddresses(envPtr, &targets);
for (currentInstPtr = envPtr->codeStart ;
currentInstPtr < envPtr->codeNext-1 ;
currentInstPtr += AddrLength(currentInstPtr)) {
int clear = 0;
if (*currentInstPtr != INST_DONE) {
continue;
}
while (!IsTargetAddress(&targets, currentInstPtr + 1 + clear)) {
clear += AddrLength(currentInstPtr + 1 + clear);
}
if (currentInstPtr + 1 + clear == envPtr->codeNext) {
envPtr->codeNext -= clear;
} else {
while (clear --> 0) {
*(currentInstPtr + 1 + clear) = INST_NOP;
}
}
}
Tcl_DeleteHashTable(&targets);
}
/*
* ----------------------------------------------------------------------
*
* ConvertZeroEffectToNOP --
*
* Replace PUSH/POP sequences (when non-hazardous) with NOPs. Also
* replace PUSH empty/CONCAT and TRY_CVT_NUMERIC (when followed by an
* operation that guarantees the check for arithmeticity) and eliminate
* LNOT when we can invert the following JUMP condition.
*
* ----------------------------------------------------------------------
*/
static void
ConvertZeroEffectToNOP(
CompileEnv *envPtr)
{
unsigned char *currentInstPtr;
int size;
Tcl_HashTable targets;
LocateTargetAddresses(envPtr, &targets);
for (currentInstPtr = envPtr->codeStart ;
currentInstPtr < envPtr->codeNext ; currentInstPtr += size) {
int blank = 0, i, nextInst;
size = AddrLength(currentInstPtr);
while (*(currentInstPtr+size) == INST_NOP) {
if (IsTargetAddress(&targets, currentInstPtr + size)) {
break;
}
size += InstLength(INST_NOP);
}
if (IsTargetAddress(&targets, currentInstPtr + size)) {
continue;
}
nextInst = *(currentInstPtr + size);
switch (*currentInstPtr) {
case INST_PUSH1:
if (nextInst == INST_POP) {
blank = size + InstLength(nextInst);
} else if (nextInst == INST_CONCAT1
&& TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) {
Tcl_Obj *litPtr = TclFetchLiteral(envPtr,
TclGetUInt1AtPtr(currentInstPtr + 1));
int numBytes;
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
if (numBytes == 0) {
blank = size + InstLength(nextInst);
}
}
break;
case INST_PUSH4:
if (nextInst == INST_POP) {
blank = size + 1;
} else if (nextInst == INST_CONCAT1
&& TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) {
Tcl_Obj *litPtr = TclFetchLiteral(envPtr,
TclGetUInt4AtPtr(currentInstPtr + 1));
int numBytes;
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
if (numBytes == 0) {
blank = size + InstLength(nextInst);
}
}
break;
case INST_LNOT:
switch (nextInst) {
case INST_JUMP_TRUE1:
blank = size;
*(currentInstPtr + size) = INST_JUMP_FALSE1;
break;
case INST_JUMP_FALSE1:
blank = size;
*(currentInstPtr + size) = INST_JUMP_TRUE1;
break;
case INST_JUMP_TRUE4:
blank = size;
*(currentInstPtr + size) = INST_JUMP_FALSE4;
break;
case INST_JUMP_FALSE4:
blank = size;
*(currentInstPtr + size) = INST_JUMP_TRUE4;
break;
}
break;
case INST_TRY_CVT_TO_NUMERIC:
switch (nextInst) {
case INST_JUMP_TRUE1:
case INST_JUMP_TRUE4:
case INST_JUMP_FALSE1:
case INST_JUMP_FALSE4:
case INST_INCR_SCALAR1:
case INST_INCR_ARRAY1:
case INST_INCR_ARRAY_STK:
case INST_INCR_SCALAR_STK:
case INST_INCR_STK:
case INST_LOR:
case INST_LAND:
case INST_EQ:
case INST_NEQ:
case INST_LT:
case INST_LE:
case INST_GT:
case INST_GE:
case INST_MOD:
case INST_LSHIFT:
case INST_RSHIFT:
case INST_BITOR:
case INST_BITXOR:
case INST_BITAND:
case INST_EXPON:
case INST_ADD:
case INST_SUB:
case INST_DIV:
case INST_MULT:
case INST_LNOT:
case INST_BITNOT:
case INST_UMINUS:
case INST_UPLUS:
case INST_TRY_CVT_TO_NUMERIC:
blank = size;
break;
}
break;
}
if (blank > 0) {
for (i=0 ; i<blank ; i++) {
*(currentInstPtr + i) = INST_NOP;
}
size = blank;
}
}
Tcl_DeleteHashTable(&targets);
}
/*
* ----------------------------------------------------------------------
*
* AdvanceJumps --
*
* Advance jumps past NOPs and chained JUMPs. After this runs, the only
* JUMPs that jump to a NOP or a JUMP will be length-1 ones that run out
* of room in their opcode to be targeted to where they really belong.
*
* ----------------------------------------------------------------------
*/
static void
AdvanceJumps(
CompileEnv *envPtr)
{
unsigned char *currentInstPtr;
for (currentInstPtr = envPtr->codeStart ;
currentInstPtr < envPtr->codeNext-1 ;
currentInstPtr += AddrLength(currentInstPtr)) {
int offset, delta;
switch (*currentInstPtr) {
case INST_JUMP1:
case INST_JUMP_TRUE1:
case INST_JUMP_FALSE1:
offset = TclGetInt1AtPtr(currentInstPtr + 1);
for (delta=0 ; offset+delta != 0 ;) {
if (offset + delta < -128 || offset + delta > 127) {
break;
}
offset += delta;
switch (*(currentInstPtr + offset)) {
case INST_NOP:
delta = InstLength(INST_NOP);
continue;
case INST_JUMP1:
delta = TclGetInt1AtPtr(currentInstPtr + offset + 1);
continue;
case INST_JUMP4:
delta = TclGetInt4AtPtr(currentInstPtr + offset + 1);
continue;
}
break;
}
TclStoreInt1AtPtr(offset, currentInstPtr + 1);
continue;
case INST_JUMP4:
case INST_JUMP_TRUE4:
case INST_JUMP_FALSE4:
for (offset = TclGetInt4AtPtr(currentInstPtr + 1); offset!=0 ;) {
switch (*(currentInstPtr + offset)) {
case INST_NOP:
offset += InstLength(INST_NOP);
continue;
case INST_JUMP1:
offset += TclGetInt1AtPtr(currentInstPtr + offset + 1);
continue;
case INST_JUMP4:
offset += TclGetInt4AtPtr(currentInstPtr + offset + 1);
continue;
}
break;
}
TclStoreInt4AtPtr(offset, currentInstPtr + 1);
continue;
}
}
}
/*
* ----------------------------------------------------------------------
*
* TclOptimizeBytecode --
*
* A very simple peephole optimizer for bytecode.
*
* ----------------------------------------------------------------------
*/
void
TclOptimizeBytecode(
CompileEnv *envPtr)
{
ConvertZeroEffectToNOP(envPtr);
AdvanceJumps(envPtr);
TrimUnreachable(envPtr);
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* tab-width: 8
* End:
*/
+40
View File
@@ -1102,6 +1102,46 @@ Tcl_UtfNcasecmp(
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* Tcl_UtfNcasecmp --
*
* Compare UTF chars of string cs to string ct case insensitively.
* Replacement for strcasecmp in Tcl core, in places where UTF-8 should
* be handled.
*
* Results:
* Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclUtfCasecmp(
const char *cs, /* UTF string to compare to ct. */
const char *ct) /* UTF string cs is compared to. */
{
while (*cs && *ct) {
Tcl_UniChar ch1, ch2;
cs += TclUtfToUniChar(cs, &ch1);
ct += TclUtfToUniChar(ct, &ch2);
if (ch1 != ch2) {
ch1 = Tcl_UniCharToLower(ch1);
ch2 = Tcl_UniCharToLower(ch2);
if (ch1 != ch2) {
return ch1 - ch2;
}
}
}
return UCHAR(*cs) - UCHAR(*ct);
}
/*
*----------------------------------------------------------------------
+22 -17
View File
@@ -13,7 +13,7 @@
package require Tcl 8.5
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the installation directory in the Makefiles.
package provide msgcat 1.5.1
package provide msgcat 1.5.2
namespace eval msgcat {
namespace export mc mcload mclocale mcmax mcmset mcpreferences mcset \
@@ -541,8 +541,11 @@ proc msgcat::Init {} {
# settings, or fall back on locale of "C".
#
# First check registry value LocalName present from Windows Vista
# which contains the local string as RFC5646, composed of:
# On Vista and later:
# HCU/Control Panel/Desktop : PreferredUILanguages is for language packs,
# HCU/Control Pannel/International : localName is the default locale.
#
# They contain the local string as RFC5646, composed of:
# [a-z]{2,3} : language
# -[a-z]{4} : script (optional, translated by table Latn->latin)
# -[a-z]{2}|[0-9]{3} : territory (optional, numerical region codes not used)
@@ -550,23 +553,25 @@ proc msgcat::Init {} {
# Those are translated to local strings.
# Examples: de-CH -> de_ch, sr-Latn-CS -> sr_cs@latin, es-419 -> es
#
set key {HKEY_CURRENT_USER\Control Panel\International}
if {![catch {registry get $key LocaleName} localeName]
&& [regexp {^([a-z]{2,3})(?:-([a-z]{4}))?(?:-([a-z]{2}))?(?:-.+)?$}\
[string tolower $localeName] match locale script territory]} {
if {"" ne $territory} {
append locale _ $territory
}
set modifierDict [dict create latn latin cyrl cyrillic]
if {[dict exists $modifierDict $script]} {
append locale @ [dict get $modifierDict $script]
}
if {![catch {mclocale [ConvertLocale $locale]}]} {
return
foreach key {{HKEY_CURRENT_USER\Control Panel\Desktop} {HKEY_CURRENT_USER\Control Panel\International}}\
value {PreferredUILanguages localeName} {
if {![catch {registry get $key $value} localeName]
&& [regexp {^([a-z]{2,3})(?:-([a-z]{4}))?(?:-([a-z]{2}))?(?:-.+)?$}\
[string tolower $localeName] match locale script territory]} {
if {"" ne $territory} {
append locale _ $territory
}
set modifierDict [dict create latn latin cyrl cyrillic]
if {[dict exists $modifierDict $script]} {
append locale @ [dict get $modifierDict $script]
}
if {![catch {mclocale [ConvertLocale $locale]}]} {
return
}
}
}
# then check key locale which contains a numerical language ID
# then check value locale which contains a numerical language ID
if {[catch {
set locale [registry get $key "locale"]
}]} {
+1 -1
View File
@@ -1,2 +1,2 @@
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded msgcat 1.5.1 [list source [file join $dir msgcat.tcl]]
package ifneeded msgcat 1.5.2 [list source [file join $dir msgcat.tcl]]
+1 -1
View File
@@ -1,3 +1,3 @@
package ifneeded platform 1.0.11 [list source [file join $dir platform.tcl]]
package ifneeded platform 1.0.12 [list source [file join $dir platform.tcl]]
package ifneeded platform::shell 1.1.4 [list source [file join $dir shell.tcl]]
+9
View File
@@ -417,6 +417,15 @@ test cmdIL-4.34 {SortCompare procedure, -ascii option with -nocase option} {
test cmdIL-4.35 {SortCompare procedure, -ascii option with -nocase option} {
lsort -ascii -nocase {d E c B a D35 d300 100 20}
} {100 20 a B c d d300 D35 E}
test cmdIL-4.36 {SortCompare procedure, UTF-8 with -nocase option} {
scan [lsort -ascii -nocase [list \u101 \u100]] %c%c%c
} {257 32 256}
test cmdIL-4.37 {SortCompare procedure, UTF-8 with -nocase option} {
scan [lsort -ascii -nocase [list a\u0000a a]] %c%c%c%c%c
} {97 32 97 0 97}
test cmdIL-4.38 {SortCompare procedure, UTF-8 with -nocase option} {
scan [lsort -ascii -nocase [list a a\u0000a]] %c%c%c%c%c
} {97 32 97 0 97}
test cmdIL-5.1 {lsort with list style index} {
lsort -ascii -decreasing -index {0 1} {
+6
View File
@@ -707,6 +707,12 @@ test compile-18.19 {disassembler - basics} -setup {
} -cleanup {
foo destroy
} -match glob -result *
test compile-19.0 {Bug 3614102: reset stack housekeeping} -body {
# This will panic in a --enable-symbols=compile build, unless bug is fixed.
apply {{} {list [if 1]}}
} -returnCodes error -match glob -result *
# TODO sometime - check that bytecode from tbcload is *not* disassembled.
# cleanup
+18
View File
@@ -668,6 +668,24 @@ test dict-14.20 {dict for stack space compilation: bug 1903325} {
concat "c=$y,$args"
}} {} 1 2 3
} {c=1,2 3}
test dict-14.21 {compiled dict for and break} {
apply {{} {
dict for {a b} {c d e f} {
lappend result $a,$b
break
}
return $result
}}
} c,d
test dict-14.22 {dict for and exception range depths: Bug 3614382} {
apply {{} {
dict for {a b} {c d} {
dict for {e f} {g h} {
return 5
}
}
}}
} 5
# There's probably a lot more tests to add here. Really ought to use a
# coverage tool for this job...
+137 -9
View File
@@ -17,6 +17,9 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
}
testConstraint memory [llength [info commands memory]]
customMatch pairwise {apply {{a b} {
string equal [lindex $b 0] [lindex $b 1]
}}}
namespace eval ::tcl::test::error {
if {[testConstraint memory]} {
proc getbytes {} {
@@ -601,21 +604,21 @@ test error-16.7 {try with variable assignment and propagation #2} {
}
list $em [dict get $opts -errorcode]
} {bar FOO}
test error-16.8 {exception chaining (try=ok, handler=error)} {
test error-16.8 {exception chaining (try=ok, handler=error)} -body {
#FIXME is the intent of this test correct?
catch {
try { list a b c } on ok {em opts} { throw BAR baz }
} tryem tryopts
string equal $opts [dict get $tryopts -during]
} {1}
test error-16.9 {exception chaining (try=error, handler=error)} {
list $opts [dict get $tryopts -during]
} -match pairwise -result equal
test error-16.9 {exception chaining (try=error, handler=error)} -body {
# The exception off the handler should chain to the exception off the
# try-body (using the -during option)
catch {
try { throw FOO bar } trap {} {em opts} { throw BAR baz }
} tryem tryopts
string equal $opts [dict get $tryopts -during]
} {1}
list $opts [dict get $tryopts -during]
} -match pairwise -result equal
test error-16.10 {no exception chaining when handler is successful} {
catch {
try { throw FOO bar } trap {} {em opts} { list d e f }
@@ -628,6 +631,131 @@ test error-16.11 {no exception chaining when handler is a non-error exception} {
} tryem tryopts
dict exists $tryopts -during
} {0}
test error-16.12 {compiled try with successfully executed handler} {
apply {{} {
try { throw FOO bar } trap FOO {} { list a b c }
}}
} {a b c}
test error-16.13 {compiled try with exception (error) in handler} -body {
apply {{} {
try { throw FOO bar } trap FOO {} { throw BAR foo }
}}
} -returnCodes error -result {foo}
test error-16.14 {compiled try with exception (return) in handler} -body {
apply {{} {
list [catch {
try { throw FOO bar } trap FOO {} { return BAR }
} msg] $msg
}}
} -result {2 BAR}
test error-16.15 {compiled try with exception (break) in handler} {
apply {{} {
for { set i 5 } { $i < 10 } { incr i } {
try { throw FOO bar } trap FOO {} { break }
}
return $i
}}
} {5}
test error-16.16 {compiled try with exception (continue) in handler} {
apply {{} {
for { set i 5 } { $i < 10 } { incr i } {
try { throw FOO bar } trap FOO {} { continue }
incr i 20
}
return $i
}}
} {10}
test error-16.17 {compiled try with variable assignment and propagation #1} {
# Ensure that the handler variables preserve the exception off the
# try-body, and are not modified by the exception off the handler
apply {{} {
catch {
try { throw FOO bar } trap FOO {em} { throw BAR baz }
}
return $em
}}
} {bar}
test error-16.18 {compiled try with variable assignment and propagation #2} {
apply {{} {
catch {
try { throw FOO bar } trap FOO {em opts} { throw BAR baz }
}
list $em [dict get $opts -errorcode]
}}
} {bar FOO}
test error-16.19 {compiled try exception chaining (try=ok, handler=error)} -body {
#FIXME is the intent of this test correct?
apply {{} {
catch {
try { list a b c } on ok {em opts} { throw BAR baz }
} tryem tryopts
list $opts [dict get $tryopts -during]
}}
} -match pairwise -result equal
test error-16.20 {compiled try exception chaining (try=error, handler=error)} -body {
# The exception off the handler should chain to the exception off the
# try-body (using the -during option)
apply {{} {
catch {
try { throw FOO bar } trap {} {em opts} { throw BAR baz }
} tryem tryopts
list $opts [dict get $tryopts -during]
}}
} -match pairwise -result equal
test error-16.21 {compiled try exception chaining (try=error, finally=error)} {
# The exception off the handler should chain to the exception off the
# try-body (using the -during option)
apply {{} {
catch {
try { throw FOO bar } finally { throw BAR baz }
} tryem tryopts
dict get $tryopts -during -errorcode
}}
} FOO
test error-16.22 {compiled try: no exception chaining when handler is successful} {
apply {{} {
catch {
try { throw FOO bar } trap {} {em opts} { list d e f }
} tryem tryopts
dict exists $tryopts -during
}}
} {0}
test error-16.23 {compiled try: no exception chaining when handler is a non-error exception} {
apply {{} {
catch {
try { throw FOO bar } trap {} {em opts} { break }
} tryem tryopts
dict exists $tryopts -during
}}
} {0}
test error-16.24 {compiled try exception chaining (try=ok, handler=error, finally=error)} -body {
apply {{} {
catch {
try {
list a b c
} on ok {em opts} {
throw BAR baz
} finally {
throw DING dong
}
} tryem tryopts
list $opts [dict get $tryopts -during -during]
}}
} -match pairwise -result equal
test error-16.25 {compiled try exception chaining (all errors)} -body {
apply {{} {
catch {
try {
throw FOO bar
} on error {em opts} {
throw BAR baz
} finally {
throw DING dong
}
} tryem tryopts
list $opts [dict get $tryopts -during -during]
}}
} -match pairwise -result equal
# try tests - finally
@@ -709,15 +837,15 @@ test error-18.5 {exception in finally doesn't affect variable assignment} {
}
list $em [dict get $opts -errorcode]
} {bar FOO}
test error-18.6 {exception chaining in finally (try=ok)} {
test error-18.6 {exception chaining in finally (try=ok)} -body {
catch {
list a b c
} em expopts
catch {
try { list a b c } finally { throw BAR foo }
} em opts
string equal $expopts [dict get $opts -during]
} {1}
list $expopts [dict get $opts -during]
} -match pairwise -result equal
test error-18.7 {exception chaining in finally (try=error)} {
catch {
try { throw FOO bar } finally { throw BAR baz }
+128 -6
View File
@@ -14,6 +14,12 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
proc meminfo {} {lindex [split [memory info] "\n"] 3 3}
}
# Basic "for" operation.
test for-1.1 {TclCompileForCmd: missing initial command} {
@@ -345,7 +351,6 @@ proc formatMail {} {
64 { UNIX (Solaris 2.* and SunOS, other systems soon to follow). Easy to install} \
65 { binary packages are now for sale at the Sun Labs Tcl/Tk Shop. Check it out!} \
}
set result ""
set NL "
"
@@ -365,7 +370,6 @@ proc formatMail {} {
} else {
set break 1
}
set xmailer 0
set inheaders 1
set last [array size lines]
@@ -386,9 +390,7 @@ proc formatMail {} {
set limit 55
} else {
set limit 55
# Decide whether or not to break the body line
if {$plen > 0} {
if {[string first {> } $line] == 0} {
# This is quoted text from previous message, don't reformat
@@ -431,7 +433,7 @@ proc formatMail {} {
set climit [expr $limit-1]
set cutoff 50
set continuation 0
while {[string length $line] > $limit} {
for {set c [expr $limit-1]} {$c >= $cutoff} {incr c -1} {
set char [string index $line $c]
@@ -824,7 +826,127 @@ test for-6.18 {Tcl_ForObjCmd: for command result} {
1 {invoked "continue" outside of a loop} \
]
test for-7.1 {Bug 3614226: ensure that break cleans up the stack} memory {
apply {{} {
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {$x < 5} {incr x} {
list a b c [break] d e f
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.2 {Bug 3614226: ensure that continue cleans up the stack} memory {
apply {{} {
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {$x < 5} {incr x} {
list a b c [continue] d e f
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.3 {Bug 3614226: ensure that break cleans up the expansion stack} memory {
apply {{} {
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts {*}[puts a b c {*}[break] d e f]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.4 {Bug 3614226: ensure that continue cleans up the expansion stack} memory {
apply {{} {
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts {*}[puts a b c {*}[continue] d e f]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.5 {Bug 3614226: ensure that break cleans up the combination of main and expansion stack} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[break] d e f]]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.6 {Bug 3614226: ensure that continue cleans up the combination of main and expansion stack} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[continue] d e f]]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.7 {Bug 3614226: ensure that break only cleans up the right amount} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
unset -nocomplain {*}[for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[break] d e f]]
}]
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.8 {Bug 3614226: ensure that continue only cleans up the right amount} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
unset -nocomplain {*}[for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[continue] d e f]]
}]
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
# cleanup
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End:
+1 -1
View File
@@ -40,7 +40,7 @@ proc httpdAccept {newsock ipaddr port} {
fconfigure $newsock -blocking 0 -translation {auto crlf}
httpd_log $newsock Connect $ipaddr $port
set data(ipaddr) $ipaddr
fileevent $newsock readable [list httpdRead $newsock]
after 50 [list fileevent $newsock readable [list httpdRead $newsock]]
}
# read data from a client request
+18 -10
View File
@@ -291,24 +291,24 @@ XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o
GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o tclClock.o \
tclCmdAH.o tclCmdIL.o tclCmdMZ.o tclCompCmds.o tclCompCmdsSZ.o \
tclCompExpr.o tclCompile.o tclConfig.o tclDate.o tclDictObj.o \
tclAssembly.o tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o \
tclClock.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \
tclCompCmds.o tclCompCmdsGR.o tclCompCmdsSZ.o tclCompExpr.o \
tclCompile.o tclConfig.o tclDate.o tclDictObj.o \
tclEncoding.o tclEnsemble.o \
tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \
tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \
tclIORChan.o tclIORTrans.o tclIOGT.o tclIOSock.o tclIOUtil.o \
tclLink.o tclListObj.o \
tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \
tclObj.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \
tclObj.o tclOptimize.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \
tclPkg.o tclPkgConfig.o tclPosixStr.o \
tclPreserve.o tclProc.o tclRegexp.o \
tclResolve.o tclResult.o tclScan.o tclStringObj.o \
tclStrToD.o tclThread.o \
tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \
tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o tclZlib.o \
tclTomMathInterface.o \
tclAssembly.o
tclTomMathInterface.o
OO_OBJS = tclOO.o tclOOBasic.o tclOOCall.o tclOODefineCmds.o tclOOInfo.o \
tclOOMethod.o tclOOStubInit.o
@@ -395,6 +395,7 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclCmdIL.c \
$(GENERIC_DIR)/tclCmdMZ.c \
$(GENERIC_DIR)/tclCompCmds.c \
$(GENERIC_DIR)/tclCompCmdsGR.c \
$(GENERIC_DIR)/tclCompCmdsSZ.c \
$(GENERIC_DIR)/tclCompExpr.c \
$(GENERIC_DIR)/tclCompile.c \
@@ -428,6 +429,7 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclNamesp.c \
$(GENERIC_DIR)/tclNotify.c \
$(GENERIC_DIR)/tclObj.c \
$(GENERIC_DIR)/tclOptimize.c \
$(GENERIC_DIR)/tclParse.c \
$(GENERIC_DIR)/tclPathObj.c \
$(GENERIC_DIR)/tclPipe.c \
@@ -838,13 +840,13 @@ install-libraries: libraries
do \
$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \
done;
@echo "Installing package msgcat 1.5.1 as a Tcl Module";
@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/msgcat-1.5.1.tm;
@echo "Installing package msgcat 1.5.2 as a Tcl Module";
@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/msgcat-1.5.2.tm;
@echo "Installing package tcltest 2.3.5 as a Tcl Module";
@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/tcltest-2.3.5.tm;
@echo "Installing package platform 1.0.11 as a Tcl Module";
@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform-1.0.11.tm;
@echo "Installing package platform 1.0.12 as a Tcl Module";
@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform-1.0.12.tm;
@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform/shell-1.1.4.tm;
@@ -1077,6 +1079,9 @@ tclDate.o: $(GENERIC_DIR)/tclDate.c
tclCompCmds.o: $(GENERIC_DIR)/tclCompCmds.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmds.c
tclCompCmdsGR.o: $(GENERIC_DIR)/tclCompCmdsGR.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsGR.c
tclCompCmdsSZ.o: $(GENERIC_DIR)/tclCompCmdsSZ.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsSZ.c
@@ -1161,6 +1166,9 @@ tclLiteral.o: $(GENERIC_DIR)/tclLiteral.c $(COMPILEHDR)
tclObj.o: $(GENERIC_DIR)/tclObj.c $(COMPILEHDR) $(MATHHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclObj.c
tclOptimize.o: $(GENERIC_DIR)/tclOptimize.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOptimize.c
tclLoad.o: $(GENERIC_DIR)/tclLoad.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclLoad.c
+9 -75
View File
@@ -6617,6 +6617,11 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
cat >>confdefs.h <<\_ACEOF
#define HAVE_HIDDEN 1
_ACEOF
fi
@@ -7719,63 +7724,6 @@ fi
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
NetBSD-1.*|FreeBSD-[1-2].*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="ld -Bshareable -x"
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
if test $doRpath = yes; then
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
echo "$as_me:$LINENO: checking for ELF" >&5
echo $ECHO_N "checking for ELF... $ECHO_C" >&6
if test "${tcl_cv_ld_elf+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#ifdef __ELF__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then
tcl_cv_ld_elf=yes
else
tcl_cv_ld_elf=no
fi
rm -f conftest*
fi
echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5
echo "${ECHO_T}$tcl_cv_ld_elf" >&6
if test $tcl_cv_ld_elf = yes; then
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
else
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
fi
# Ancient FreeBSD doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
OpenBSD-*)
arch=`arch -s`
case "$arch" in
@@ -7861,9 +7809,8 @@ fi
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
NetBSD-*|FreeBSD-[3-4].*)
# FreeBSD 3.* and greater have ELF.
# NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs
NetBSD-*)
# NetBSD has ELF and can use 'cc -shared' to build shared libs
SHLIB_CFLAGS="-fPIC"
SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
SHLIB_SUFFIX=".so"
@@ -7885,20 +7832,12 @@ fi
fi
case $system in
FreeBSD-3.*)
# FreeBSD-3 doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
TCL_LIB_VERSIONS_OK=nodots
;;
esac
;;
FreeBSD-*)
# This configuration from FreeBSD Ports.
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="${CC} -shared"
TCL_SHLIB_LD_EXTRAS="-soname \$@"
TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$@"
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
@@ -7906,7 +7845,7 @@ fi
if test $doRpath = yes; then
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi
if test "${TCL_THREADS}" = "1"; then
@@ -9115,11 +9054,6 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
cat >>confdefs.h <<\_ACEOF
#define NO_VIZ
_ACEOF
fi
+5 -40
View File
@@ -1067,6 +1067,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
AC_DEFINE(MODULE_SCOPE,
[extern __attribute__((__visibility__("hidden")))],
[Compiler support for module scope symbols])
AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
])
])
@@ -1469,32 +1470,6 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
NetBSD-1.*|FreeBSD-[[1-2]].*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="ld -Bshareable -x"
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
AS_IF([test $doRpath = yes], [
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [
AC_EGREP_CPP(yes, [
#ifdef __ELF__
yes
#endif
], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])
AS_IF([test $tcl_cv_ld_elf = yes], [
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
], [
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
])
# Ancient FreeBSD doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
OpenBSD-*)
arch=`arch -s`
case "$arch" in
@@ -1546,9 +1521,8 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
NetBSD-*|FreeBSD-[[3-4]].*)
# FreeBSD 3.* and greater have ELF.
# NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs
NetBSD-*)
# NetBSD has ELF and can use 'cc -shared' to build shared libs
SHLIB_CFLAGS="-fPIC"
SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
SHLIB_SUFFIX=".so"
@@ -1564,27 +1538,19 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
CFLAGS="$CFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
])
case $system in
FreeBSD-3.*)
# FreeBSD-3 doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
TCL_LIB_VERSIONS_OK=nodots
;;
esac
;;
FreeBSD-*)
# This configuration from FreeBSD Ports.
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="${CC} -shared"
TCL_SHLIB_LD_EXTRAS="-soname \$[@]"
TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]"
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
LDFLAGS=""
AS_IF([test $doRpath = yes], [
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
AS_IF([test "${TCL_THREADS}" = "1"], [
# The -pthread needs to go in the LDFLAGS, not LIBS
LIBS=`echo $LIBS | sed s/-pthread//`
@@ -2075,7 +2041,6 @@ dnl # preprocessing tests use only CPPFLAGS.
AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
AC_DEFINE(MODULE_SCOPE, [extern],
[No Compiler support for module scope symbols])
AC_DEFINE(NO_VIZ, [], [No visibility attribute])
])
AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
+2 -2
View File
@@ -343,8 +343,8 @@
/* Do we have <values.h>? */
#undef NO_VALUES_H
/* No visibility attribute */
#undef NO_VIZ
/* Compiler support for module scope symbols */
#undef HAVE_HIDDEN
/* Do we have wait3() */
#undef NO_WAIT3
+2 -2
View File
@@ -2226,13 +2226,13 @@ DefaultTempDir(void)
dir = getenv("TMPDIR");
if (dir && dir[0] && stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode)
&& access(dir, W_OK)) {
&& access(dir, W_OK) == 0) {
return dir;
}
#ifdef P_tmpdir
dir = P_tmpdir;
if (stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode) && access(dir, W_OK)) {
if (stat(dir, &buf)==0 && S_ISDIR(buf.st_mode) && access(dir, W_OK)==0) {
return dir;
}
#endif
+6 -4
View File
@@ -225,6 +225,7 @@ GENERIC_OBJS = \
tclCmdIL.$(OBJEXT) \
tclCmdMZ.$(OBJEXT) \
tclCompCmds.$(OBJEXT) \
tclCompCmdsGR.$(OBJEXT) \
tclCompCmdsSZ.$(OBJEXT) \
tclCompExpr.$(OBJEXT) \
tclCompile.$(OBJEXT) \
@@ -266,6 +267,7 @@ GENERIC_OBJS = \
tclOOMethod.$(OBJEXT) \
tclOOStubInit.$(OBJEXT) \
tclObj.$(OBJEXT) \
tclOptimize.$(OBJEXT) \
tclPanic.$(OBJEXT) \
tclParse.$(OBJEXT) \
tclPathObj.$(OBJEXT) \
@@ -646,12 +648,12 @@ install-libraries: libraries install-tzdata install-msgs
do \
$(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
done;
@echo "Installing package msgcat 1.5.1 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/msgcat-1.5.1.tm;
@echo "Installing package msgcat 1.5.2 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/msgcat-1.5.2.tm;
@echo "Installing package tcltest 2.3.5 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/tcltest-2.3.5.tm;
@echo "Installing package platform 1.0.11 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform-1.0.11.tm;
@echo "Installing package platform 1.0.12 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform-1.0.12.tm;
@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform/shell-1.1.4.tm;
@echo "Installing encodings";
-4
View File
@@ -4377,10 +4377,6 @@ else
ZLIB_OBJS=\${ZLIB_OBJS}
cat >>confdefs.h <<_ACEOF
#define NO_VIZ 1
_ACEOF
fi
-1
View File
@@ -135,7 +135,6 @@ AS_IF([test "$tcl_ok" = "yes"], [
])
], [
AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}])
AC_DEFINE_UNQUOTED(NO_VIZ, 1)
])
AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])
+2
View File
@@ -200,6 +200,7 @@ TCLOBJS = \
$(TMPDIR)\tclCmdIL.obj \
$(TMPDIR)\tclCmdMZ.obj \
$(TMPDIR)\tclCompCmds.obj \
$(TMPDIR)\tclCompCmdsGR.obj \
$(TMPDIR)\tclCompCmdsSZ.obj \
$(TMPDIR)\tclCompExpr.obj \
$(TMPDIR)\tclCompile.obj \
@@ -238,6 +239,7 @@ TCLOBJS = \
$(TMPDIR)\tclOOMethod.obj \
$(TMPDIR)\tclOOStubInit.obj \
$(TMPDIR)\tclObj.obj \
$(TMPDIR)\tclOptimize.obj \
$(TMPDIR)\tclPanic.obj \
$(TMPDIR)\tclParse.obj \
$(TMPDIR)\tclPipe.obj \
+2
View File
@@ -274,6 +274,7 @@ COREOBJS = \
$(TMP_DIR)\tclCmdIL.obj \
$(TMP_DIR)\tclCmdMZ.obj \
$(TMP_DIR)\tclCompCmds.obj \
$(TMP_DIR)\tclCompCmdsGR.obj \
$(TMP_DIR)\tclCompCmdsSZ.obj \
$(TMP_DIR)\tclCompExpr.obj \
$(TMP_DIR)\tclCompile.obj \
@@ -315,6 +316,7 @@ COREOBJS = \
$(TMP_DIR)\tclOOMethod.obj \
$(TMP_DIR)\tclOOStubInit.obj \
$(TMP_DIR)\tclObj.obj \
$(TMP_DIR)\tclOptimize.obj \
$(TMP_DIR)\tclPanic.obj \
$(TMP_DIR)\tclParse.obj \
$(TMP_DIR)\tclPathObj.obj \
+2 -2
View File
@@ -280,7 +280,7 @@ NativeGetTime(
Tcl_Time *timePtr,
ClientData clientData)
{
struct timeb t;
struct _timeb t;
int useFtime = 1; /* Flag == TRUE if we need to fall back on
* ftime rather than using the perf counter. */
@@ -446,7 +446,7 @@ NativeGetTime(
* High resolution timer is not available. Just use ftime.
*/
ftime(&t);
_ftime(&t);
timePtr->sec = (long)t.time;
timePtr->usec = t.millitm * 1000;
}