Compare commits

...
Author SHA1 Message Date
dkf 2021349249 Make fundamental mutation work. MAGICAL MAGIC MAGICS MAGIC. Abracadabra. 2018-10-18 21:38:08 +00:00
dkf e006418946 Tests for advanced object mutation issues. 2018-10-18 14:58:28 +00:00
jan.nijtmans 2881b5c3df Fix test-cases running on Windows 10: [string index $tcl_platform(osVersion) 0] doesn't give the correct answer then.
Also backport genStubs.tcl from 8.7: The "deprecated" mark is not used in Tcl 8.6, but it is used by Tk 8.7 when doing "make genstubs" against Tcl 8.6.
2018-10-17 19:55:17 +00:00
jan.nijtmans e0209e39ea Fix test-cases running on Windows 10: [string index $tcl_platform(osVersion) 0] doesn't give the correct answer then (it gives "1", but "10" was expected) 2018-10-17 19:51:47 +00:00
dgp e1196c53f2 Revert addition of "slowTest" as built-in constraint. (no TIP; no version bump).
Let the test file that needs the constraint define it with existing facilities.
2018-10-17 16:12:42 +00:00
dgp 56b431c4c2 Mark test macOSXFCmf-2.8 non-portable. It appears to pass when the older
HFS+ filesystem is in use, often on disk drives in older systems. It appears
to fail when APFS is in use, more typical on newer SSD storage.
2018-10-17 16:06:38 +00:00
dgp ac4291f473 Backport test fix. 2018-10-17 16:03:54 +00:00
dgp bbdb1f12a0 Use the 4 argument form of [makeFile]. 2018-10-09 18:24:57 +00:00
dkf f9a4d9f781 Balance the [makeFile/makeDirectory] and [removeFile/removeDirectory] calls (conditional now, so avoids warnings in filter/constraint cases). 2018-10-09 17:55:20 +00:00
sebres 1a664df87f Balance the [makeFile/makeDirectory] and [removeFile/removeDirectory] calls (conditional now, so avoids warnings in filter/constraint cases). 2018-10-09 16:59:13 +00:00
jan.nijtmans cc4dae5c0f Streamline: Tcl_WinTCharToUtf/Tcl_WinUtfToTChar(): Always initialize DString, and let it return NULL when imput is NULL. That's what seem to assume the callers. 2018-10-07 20:26:33 +00:00
jan.nijtmans 8985ee2114 Better implementations of Tcl_WinTCharToUtf() and Tcl_WinUtfToTChar(). They don't make any assumption on whether encodings are initialized, or specific win32 handling of special characters. 2018-10-05 20:54:59 +00:00
jan.nijtmans 85aac3aef7 Fix wrong usage of Tcl_WinTCharToUtf() contract: nativePath should never be NULL, but actually it can be. 2018-10-05 19:37:38 +00:00
dgp c3c71b5f3c Post-TIP 505 editing of [lreplace] documentation. 2018-10-05 17:20:40 +00:00
jan.nijtmans 9feb8b7c29 In registry, protect "keyName" from being NULL: This actually can lead to crashed (I experienced this ...). Update version to 1.3.3, and align implementation in all branches (core-8-6-branch and higher) 2018-10-04 19:22:37 +00:00
jan.nijtmans 50a1375461 Tcl_UniCharToUtfDString: Don't allocate too much memory for this function.
Tcl_UtfToUniCharDString: Don't allocate too much memory for this function. And make sure that we never access more than 'length' bytes from the string, not even when encountering invalid UTF-8.
2018-10-03 19:24:13 +00:00
jan.nijtmans 3d5f129cb0 Another patch contributed by Gustaf Neumann: shifting negative numbers is undefined behavior in the C standard
https://stackoverflow.com/questions/8415895/is-left-and-right-shifting-negative-integers-defined-behavior
2018-09-28 18:45:34 +00:00
dkf 6cdb3193ec Implementation of TIP 505: Make [lreplace] Accept All Out-of-Range Index Values 2018-09-27 08:19:18 +00:00
dkf bf46b6a1da Updated documentation 2018-09-27 07:44:50 +00:00
jan.nijtmans d5583552c0 Contributed patch from Gustaf Neumann, preventing problems where "localCachePtr" can be NULL 2018-09-25 21:16:32 +00:00
dgp 338b9ec9d2 Silence debugging message in test suite. 2018-09-24 16:15:25 +00:00
jan.nijtmans 6d3aeef45e Give lambda function a name "ReceiveChunked" for easier testing. New function quoteString and code cleanup 2018-09-23 13:27:14 +00:00
jan.nijtmans 63ef0e3d26 Update http version number, and fix some related test-cases 2018-09-22 10:20:28 +00:00
kjnash 39318d91b7 merge bug-46b6edad51-concurrent-http 2018-09-20 13:41:13 +00:00
kjnash d24a3eb2ba merge 8.6 2018-09-15 18:41:23 +00:00
dgp cdce5491b3 Rebase TIP 505 implementation a patch for 8.6. 2018-09-10 15:28:23 +00:00
sebres 9a15a1b586 small code review (duplicate code removed) 2018-09-07 14:24:49 +00:00
dgp 95db69f27b Added test for [631b4c45df]. 2018-09-07 12:04:32 +00:00
sebres e80eaec4d3 amend to [e8ab4d85fa], proc.test: extended with new test-case to cover situation like [631b4c45df] 2018-09-07 11:55:01 +00:00
sebres b9577c0641 closes [631b4c45df]: segfault by usage of wrong length (no string representation) 2018-09-07 10:45:30 +00:00
sebres cb9f3f9268 merge 8.5 2018-08-30 11:13:09 +00:00
sebres 6d88b01d1e test-cases to cover quoting of the newline character, and the documentation extended. 2018-08-30 11:08:51 +00:00
sebres 77a26f5c95 merge 8.5 2018-08-29 16:59:10 +00:00
sebres 9cec6bac27 tcltest: forgotten built-in constraint "slowTest" 2018-08-29 16:58:06 +00:00
sebres 2f19b0f346 small amend to [cae24931ed] (no _CRT_glob in both cases __GNUC__ || TCL_BROKEN_MAINARGS). 2018-08-29 16:55:36 +00:00
sebres 265c9d416f partially cherry-picking of [5099a81b50], never reached 8.6, so for example build for MINGW breaks tests winpipe-8.1 etc, because "*" will be expanded. 2018-08-29 15:55:13 +00:00
sebres db610f91eb code review after merge with 8.5 (restore usage of some functions, after lost by conflict resolving) 2018-08-29 15:49:19 +00:00
sebres afb5bf5583 merge 8.5 ([21b0629c81] 0-day vulnerability - insufficient escape by exec of batch-files for windows) 2018-08-29 15:41:55 +00:00
sebres 9b7ce068fe closes [21b0629c81] 0-day vulnerability - insufficient escape by exec of batch-files for windows 2018-08-29 14:45:57 +00:00
sebres 820a737a2f code review, skip slow test winpipe-8.2 executed args from injectList particularly (normally winpipe-8.3 covers the same but jointly), to enable use parameter -constraints slowTest, added new test with randomly generated potentially dangerous args 2018-08-23 10:26:03 +00:00
sebres c2d61d8dbc code review, restored backwards compatibility of the simplest escape of quote-chars (so reverted several tests winpipe-7.x) 2018-08-23 08:00:32 +00:00
sebres fb0bf9d1b9 fixes escape for special cases (+ more test-cases):
- `%` char to be escaped (quoted) in any case (regardless pairing flag), otherwise `%username%` will be interpolated as username.
- escape of multiple backslashes before quote is different (as without following quote) in unpaired quote syntax (upaired flag set)
2018-08-21 18:52:21 +00:00
sebres 01dd016ad8 because executable (1st argument) always proper escaped now, don't need to replace long path name of batch-executable with short path name (reduced to 16-bit applications only). 2018-08-20 19:58:44 +00:00
sebres d660b325b5 small amend: avoid reset of unpaired quote flag between arguments (previous affects next) + test cases extended with several injection checks. 2018-08-20 16:15:37 +00:00
sebres 26b477b907 win: fixes [21b0629c81] - exec/open process pipe under windows (0-day vulnerability - insufficient escape) 2018-08-20 14:35:44 +00:00
jan.nijtmans 89ff80fbdd merge-mark 2018-08-19 09:16:30 +00:00
jan.nijtmans 90afac281e Minor fix to entier(): Allow it to convert to "wideInt" as well when range is appropriate 2018-08-17 22:15:49 +00:00
sebres aed158b518 win: TclpCreateProcess or [exec process ...] - search for application extended with ".cmd" extension:
automatically tries appending ".com", ".exe", ".bat" and ".cmd", in that order, to the name, looking for an executable.
(partially cherry-picked from 8.6 branch)
2018-08-17 18:26:10 +00:00
dgp 6c78bf0adc Repair breakage in recent refactoring of env.test 2018-08-08 20:48:06 +00:00
jan.nijtmans 8346cad0dd Fix harmless gcc warning 2018-08-08 06:45:29 +00:00
sebres de5637f853 ioTrans.test: fixed cleanup - avoids error deleting "tempchanfile": permission denied: file seems to be locked/opened inside interp $idb 2018-08-03 13:46:30 +00:00
jan.nijtmans c1ae69114b Remove some actually dead code 2018-07-31 19:49:51 +00:00
sebres 5902889825 amend after merge: 8.6th provide additionally an error-code (so missing errCode = "OVERFLOW") 2018-07-26 18:56:41 +00:00
sebres 04c687936c merge 8.5 - bug [d051b77fc1] fixed 2018-07-26 18:51:03 +00:00
sebres 2133e40e58 amend to [d498578df4], still one test for [Bug ba921a8d98] with inplace by subst inside string (compiled as "strcat" instruction) 2018-07-26 18:07:34 +00:00
sebres c7cdc550c4 test cases added to cover width overflow by format (should cause limit exceeded) 2018-07-26 16:46:47 +00:00
sebres 7e727bed70 closes [d051b77fc18d7340]: fixed segfault by integer overflow (if width by format like "%4000000000g" overflows to negative values by scan of length) 2018-07-26 15:57:38 +00:00
dgp 164a7f04c0 New test for [Bug ba921a8d98]. 2018-07-26 15:51:28 +00:00
Kevin B Kenny 814c867db4 Add a note in the 'clock' man page about the interpretation of impossible values on [clock scan] 2018-07-21 18:45:09 +00:00
sebres d00a212e82 win: avoids warning by x64-build in function 'TclWinCPUID' - pointer targets in passing argument 1 of '__cpuid' differ in signedness [-Wpointer-sign] (int* vs unsigned int*) 2018-07-20 15:58:56 +00:00
sebres 7fb72851e8 win: fixes x64-build within gcc-compile runtime env for (mingw64, etc): "$do64bit" may be "amd64|x64|yes", so it could find & copy wrong zlib.dll. 2018-07-20 15:54:11 +00:00
sebres 4a3f32b84a win: fixed test-cases (see [525ccacaef]) running under windows outside of temp-folder 2018-07-16 13:59:29 +00:00
sebres a1790a1683 merge 8.5 2018-07-12 14:25:09 +00:00
sebres 885a163b3c win: closes [3f7af0e21e13f1f5] - avoid "permissions denied" by file delete, if file stat (TclpObjStat) used internally in other worker, for example by usage of file mkdir etc. 2018-07-12 14:17:57 +00:00
sebres 2a46a48670 merge 8.5 2018-07-09 18:15:34 +00:00
sebres 51aecf205d closes [270f78ca95b642fb]: fix the race condition for file mkdir if some worker deletes directory immediately after the succeded create inside 3rd worker. 2018-07-09 17:18:07 +00:00
jan.nijtmans 367ce9ad48 tclDictObj.c:366: warning: dereferencing type-punned pointer will break strict-aliasing rules
Prevent this warning, which gcc 4.4 (a.o.) gives on this construct. void pointers work well already in whatever assignment.
2018-07-05 19:39:19 +00:00
dgp 9da2aebeae Use a thread exit handler, and not a custom exit proc for package cleanup. 2018-06-26 17:00:29 +00:00
dgp ed5ed756bc Restore lost tests. 2018-06-26 14:22:08 +00:00
jan.nijtmans 0839047d8b Simplify ToUtf(), expecially for TCL_UTF_MAX>3 (with correct surrogate handling).
Fix various typo's
2018-06-25 07:22:19 +00:00
pooryorick e2a79c2604 Fix for [3592747]: Let TclNRTailcallEval handle namespace problems. 2018-06-24 07:17:46 +00:00
pooryorick 6cbfdcc4a3 Add a test for no generation of a string representation when comparing with the
empty string.
2018-06-23 14:18:06 +00:00
pooryorick 94ec3d9431 Add another suppress rule for valgrind, factor test code into
tests/tcltests.tcl, and constrained a some tests in the valgrind case.
2018-06-22 15:10:04 +00:00
pooryorick 6c1e9f2b0c merge pyk-tcltest-exit 2018-06-21 22:44:04 +00:00
pooryorick 563bd6e4dd Fix function signature of TclThreadTestFinalize. 2018-06-21 22:43:18 +00:00
pooryorick b418ff1759 merge pyk-tcltest-exit 2018-06-21 22:23:04 +00:00
pooryorick 56ca35e8a9 Add custom exit procedure for tcltests executable. 2018-06-21 22:21:31 +00:00
pooryorick 107fb1eb33 Suppress more valgrind "still reachable" reports and ensure that threads are
fully finalized in thread tests.
2018-06-21 22:16:29 +00:00
pooryorick c911dc937f Add valgrind suppression for dlopen and ensure that processes are reaped in
http11.test.
2018-06-20 19:06:40 +00:00
pooryorick 645241afc1 Remove recent auto_path modification in tests/all.tcl and suppress more
valgrind reports.
2018-06-20 08:03:22 +00:00
pooryorick 03a3c09b1f new file: tools/valgrind_suppress. num-callers bumped from 8 to 24. Valgrind
now issues no "still reachable" reports for cmdAH.test.
2018-06-19 11:47:08 +00:00
jan.nijtmans 3c57d80efe Fix [53cad613d8]: TIP 389 implementation makes Tk tests font-4.12 and font-4.15 fail. One more situation in which high surrogate causes problem 2018-06-18 15:54:38 +00:00
jan.nijtmans 04004f3abc Unbreak build on Windows (and - most likely - some other platforms too) 2018-06-18 15:51:43 +00:00
pooryorick 155e8a1ad5 Avoid valgrind "still reachable" reports stemming from early termination of
threads.
2018-06-18 08:09:32 +00:00
pooryorick 625aca976a Full cleanup of env cache when in a PURIFY build. 2018-06-18 07:06:04 +00:00
pooryorick e9c0ec1219 Plug leak in TclSetEnv. 2018-06-18 05:59:22 +00:00
jan.nijtmans 8047a470ef Fix [53cad613d8a4de166e680f09a6c6399ebddbc17c|53cad613d8]: TIP 389 implementation makes Tk tests font-4.12 and font-4.15 fail. (Fix it in 8.6 too, for benefit of androwish) 2018-06-17 16:07:09 +00:00
pooryorick 2b739c838a Remove dependencies between tests in env.test. 2018-06-17 08:47:29 +00:00
pooryorick 983854ad7b Add tests/tcltests.tcl as a place to store common code for tests. 2018-06-16 22:56:07 +00:00
pooryorick 41a6159754 new package
tcltests
exclude some exec.test tests when running under valgrind
2018-06-16 17:55:31 +00:00
jan.nijtmans df97278634 merge 8.5 2018-06-15 18:35:56 +00:00
jan.nijtmans 06fc5fb636 Align common install locations in SC_PATH_TCLCONFIG and SC_PATH_TKCONFIG. Add FreeBSD (closes [d6d60efd35]) and OpenBSD 8.5 paths 2018-06-15 18:31:24 +00:00
dgp e393000b1d merge 8.5 2018-06-13 16:06:38 +00:00
dgp 83d92bd747 Stop creating a stray child process. 2018-06-13 15:59:15 +00:00
dgp 5a05e0d782 merge 8.5 2018-06-12 17:53:19 +00:00
dgp 9c8f784329 [860a9f1945] Remove test safe-8.8; Mac OS 9 tests are no longer useful. 2018-06-12 17:10:03 +00:00
jan.nijtmans 1efbaebb6a Merge 8.5 (= update Unicode data to Unicode version 11.0) 2018-06-09 07:44:33 +00:00
jan.nijtmans ac47e6953d Update all Unicode tables to Unicode version 11.0 2018-06-09 07:42:42 +00:00
jan.nijtmans 400feb302b Update to latest tzdata (backported from 8.6) 2018-06-09 07:41:47 +00:00
sebres 9c9b3d93f9 merge 8.5 (empty merge point, no functional changes, because does not affect 8.6) 2018-06-08 13:02:59 +00:00
sebres 04d1270786 resolves some warnings by compiling with new gcc-versions (>= 7.x):
- '*' in boolean context, suggest '&&' instead [-Wint-in-bool-context]
  - passing argument 1 of 'Tcl_CreateExitHandler' from incompatible pointer type [-Wincompatible-pointer-types]
2018-06-08 12:50:43 +00:00
sebres b89a3efc56 merge 8.5 2018-06-04 13:52:19 +00:00
sebres 240e6b50d2 fixes [92564326a9] if compiled on some x86 systems (with dirent64 but without DIR64, partially cherry-picked from https://www.androwish.org/index.html/info/6119b8ac2aee8411). 2018-06-04 13:49:38 +00:00
kjnash 754bb107b4 Bugfix - always cleanup persistent socket. 2018-06-01 18:34:07 +00:00
sebres a2ce3dab9b merge 8.5 2018-05-28 13:17:18 +00:00
sebres 6a4d06759e win: searching for FQDN in user-name should be utf-8 safe (user-name could contain non-ascii utf-8 chars) 2018-05-28 13:13:39 +00:00
sebres 6966f0a2b1 merge 8.5 (conflicts resolved, rewritten without winapi-stubs) 2018-05-28 12:26:20 +00:00
sebres 89a84af271 merge-integrate sebres-bug-9e6b569963-8-5-branch to 8.5 2018-05-28 12:05:15 +00:00
sebres 5e7a1545a6 minor indentation fix (no functional changes) 2018-05-25 15:51:23 +00:00
sebres f4651a5660 avoid dual init of stubs (possible race condition, 8.5th only) 2018-05-25 15:48:50 +00:00
sebres a0290b85c5 optimized winapi-stubs loading (8.5th only); if user name specified without domain and equals the current user - try safest and fastest way to get current user-home path (without usage of netapi) 2018-05-25 15:04:27 +00:00
sebres 8145564d30 merge/reintegrate test-cases from bug-9e6b569963 2018-05-25 10:04:01 +00:00
fvogel 6d943ef7b5 Remove test filesystem-1.30.3, this is unstestable 2018-05-24 20:51:45 +00:00
sebres 1c13d543f4 [9e6b569963] win: if user specified without domain (and local user was not found), try to resolve user-home using current domain, so following code's are similar:
file normalize ~$::tcl_platform(user)@$::env(USERDOMAIN)
  file normalize ~$::tcl_platform(user)
2018-05-24 20:49:12 +00:00
sebres 263de53394 merge 8.5, conflicts resolved (rewritten without winapi-stubs) 2018-05-24 20:36:32 +00:00
sebres a410c0d8d5 fixed typo in winFCmd-12.6.2: unneeded extra-bracket removed 2018-05-24 20:20:26 +00:00
sebres ecec1703aa win: TclpGetUserHome should return normalized path (also in case we find domain and NetUserGetInfo returns path), PoC:
file normalize ~$::tcl_platform(user)@$::env(USERDOMAIN)
2018-05-24 20:12:43 +00:00
fvogel 36a1a69178 Add support for ~domain\user style user names, with new test test filesystem-1.30.3. Warning: does not yet work. 2018-05-23 21:08:01 +00:00
fvogel dffe6bc7f1 Add test filesystem-1.30.2 {normalisation of nonexistent user specified as user@domain} 2018-05-19 07:10:43 +00:00
fvogel 423f761169 Fix [9e6b569963]: file normalize ~user fails on Windows 2018-05-18 19:54:56 +00:00
fvogel ba42e43e97 Add test filesystem-1.30.1 checking file normalize ~$::tcl_platform(user). This test should currently fail when the computer is connected to a Windows domain controller, due to [9e6b569963]: file normalize ~user fails on Windows 2018-05-18 06:18:56 +00:00
jan.nijtmans 7672af7212 merge 8.5 2018-05-14 19:16:24 +00:00
jan.nijtmans eae621b175 Unbreak build when HAVE_FTS is not set.
Move definitions of Tcl_DirEntry and TclDIR to tclWinPort.h, where it actually belongs
2018-05-14 19:14:40 +00:00
jan.nijtmans 6d0cc0c589 Merge 8.5. This adds Emoji 11.0 support, when Tcl is compiled with TCL_UTF_MAX>3. Useful for Androwish, for example. 2018-05-11 09:20:59 +00:00
jan.nijtmans d9bc6cbae2 Add emoji 11.0 to the set. Only active when compiled with TCL_UTF_MAX>3. Also prepare tooling for Unicode 11.0 (while being on it) 2018-05-11 09:14:42 +00:00
jan.nijtmans ede72e80ac merge 8.5 2018-05-11 08:10:17 +00:00
jan.nijtmans 7bf3f83abd Rename Tcl_Dir to TclDIR, making it clear that this macro is not part of the public API 2018-05-11 07:53:20 +00:00
sebres f7f4cbb151 merge 8.5 2018-05-09 10:34:44 +00:00
sebres f5e8751307 amend to [85bcf84100]: replaces DIR with Tcl_Dir (DIR/DIR64 regarding HAVE_STRUCT_DIRENT64) 2018-05-09 10:29:33 +00:00
sebres 47e9dbdc37 prevents UB/segfault by unexpected return-code (not -1/0/1) and avoid warnings like:
tclCmdMZ.c:2815:15: warning: `s1` may be used uninitialized in this function [-Wmaybe-uninitialized]
  s1len = Tcl_NumUtfChars(s1, s1len);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~
2018-05-08 10:16:26 +00:00
sebres 8fd1568405 merge fix for [92564326a98b5510] from 8.5 2018-05-08 09:56:35 +00:00
sebres 78ee8c697e fixes [92564326a98b5510]: wrong x64-aligned handle from readdir64 by opendir/rewinddir/closedir, if HAVE_STRUCT_DIRENT64 used. 2018-05-08 09:49:16 +00:00
pooryorick 5f0cf291f5 Deduplicate code in INST_STR_CMP, StringCmpCmd, and StringEqualCmd. 2018-05-07 07:43:00 +00:00
pooryorick db133f0144 Factor options handling out of StringCmpCmd. 2018-05-06 18:13:54 +00:00
pooryorick 86c6a11cdb Preparation to deduplicate code between byte-compiled and legacy
implementations of [string compare].
2018-05-06 13:45:21 +00:00
pooryorick e383cd7b26 Avoid generating string representation when comparing the empty string. 2018-05-05 17:04:08 +00:00
pooryorick 3a3fd2954f Avoid generating string representation when comparing the empty string. 2018-05-05 16:38:27 +00:00
José Ignacio Marín 096a011c43 Update TZ info to tzdata2018e. 2018-05-04 19:06:09 +00:00
dgp 71938f034c merge 8.5 2018-04-30 12:14:25 +00:00
dgp 0fc27b893e Contain platform-specific things in the constraint-controlled parts of the test. 2018-04-30 12:11:14 +00:00
sebres debcb2bf01 amend after merge 8.5 2018-04-30 11:52:12 +00:00
sebres 6ef77228ca merge core-8-5-branch (fix-1613456fff) 2018-04-30 11:36:31 +00:00
sebres ddfce0ed3f merge fix-1613456fff, closes [1613456fffffffff] and [27b682284974d0cd] 2018-04-30 11:10:14 +00:00
dgp c876decde3 Doc typo fix from Andy Goth. 2018-04-25 11:48:14 +00:00
jan.nijtmans 4519681dcd Bug-fix in Tcl_UtfAtIndex (for TCL_UTF_MAX=4 only). With test-case (in "string totitle") demonstrating the bug. 2018-04-23 23:23:00 +00:00
jan.nijtmans 9acb063268 Add some state to encodings, so we can do better surrogate handling for TCL_UTF_MAX >= 4. Backported from TIP #389. 2018-04-23 14:56:44 +00:00
dgp 8e06fd796b [46a2410650] compiled [unset] was bypassing cleanup of active array search.
Overdue thanks to Andy Goth for tests and report.
2018-04-22 13:22:20 +00:00
kjnash 227db01958 Restore production test settings: set tests/httpPipeline.test to non-verbose, and comment out most Log calls in library/http/http.tcl 2018-04-21 14:22:35 +00:00
kjnash 41954059c4 merge 8.6 2018-04-21 13:47:09 +00:00
kjnash b169c964e6 Amend httpPipeline.test tests to use stdout not stderr, and thus avoid the report {Test files exiting with errors} even when all tests pass. 2018-04-21 13:31:16 +00:00
dgp ae76fbd559 DeleteArray has only one caller. It is called on the "dummy" variable
that is created during unset, and which cannot be reached by resolving
any name. It cannot have VAR_SEARCH_ACTIVE set because the sole thing that
sets that flag is an [array startsearch] applied to a named variable.
2018-04-20 20:17:17 +00:00
kjnash 3771e638b0 Document the new proc http::registerError in http.n 2018-04-20 20:06:30 +00:00
jan.nijtmans 1734eed89f Slightly improved (more fail-safe) surrogate handling for TCL_UTF_MAX>3. Backported from latest TIP 389 implementation. (to be used for androwish) 2018-04-19 22:29:00 +00:00
dgp 75bd116527 Fold TclArraySet() into its only caller. tclEnv.c no longer calls it 2018-04-19 02:01:29 +00:00
dgp 7ac6487eda merge 8.5 2018-04-19 01:41:13 +00:00
dgp df94eecf11 An [array set] from a dict can only take shortcuts when the dict is "pure",
that is, has no string rep.
2018-04-19 01:39:38 +00:00
dgp 8d0340e39e Refactor error reporting when value is not an expected array variable name. 2018-04-18 23:41:48 +00:00
dgp 61f580bd36 Refactor to bring the test for existence of an array variable into
LocateArray().
2018-04-18 23:31:07 +00:00
dgp 08c1a8dd34 cleanup of refactor 2018-04-18 21:03:53 +00:00
dgp fb91d4b68b Refactor the common operations of looking up and checking traces on an array
variable into a single routine LocateArray().
2018-04-18 19:21:33 +00:00
oehhar 327595170b http::geturl now returns full error stack information if the initial socket command fails Ticket [ff82755e15] 2018-04-18 11:59:57 +00:00
dgp 6b8039a952 Refactor array trace handling into a common routine TclCheckArrayTraces(). 2018-04-17 20:29:02 +00:00
dgp 62ea5e49a1 Array trace firing must come before argument checking might raise error. 2018-04-17 19:14:01 +00:00
dgp 5dff80f2fe Gentler fallback. 2018-04-17 18:54:36 +00:00
dgp f316d7539c [array set] must fire array traces. Don't disrupt that by reporting argument
errors too early.
2018-04-17 18:34:41 +00:00
dgp 05845fbe5f merge 8.5 2018-04-17 14:38:28 +00:00
dgp 80e5aed49e Restore build success to the TCL_REMOVE_OBSOLETE_TRACES configuration. 2018-04-17 14:32:30 +00:00
kjnash 4588d7300e Restore Tcl 8+4 tab convention 2018-04-13 15:48:13 +00:00
kjnash d690b84738 Improve detection and reporting of TLS errors. New command http::registerError to assist the latter. Ensure that http::cleanup cancels any timeout event if not already done. Add comments on non-blocking read/gets. 2018-04-13 15:41:00 +00:00
sebres 9856afd590 win: some test-cases missing constraint for testexcept (if compiled without test) 2018-04-11 11:28:41 +00:00
sebres a9ef86f152 win: fix several test-cases for windows platform 2018-04-09 19:50:12 +00:00
sebres 24a04c0819 amend to [5acb57c7aec45e05]: set code to TCL_ERROR, because primitives from tclIOUtil return -1 2018-04-09 10:04:23 +00:00
dgp ff7812fe97 merge 8.5 2018-04-07 16:56:53 +00:00
dgp 689f5653f9 Correct out-of-date documentation for [string is]. 2018-04-07 16:55:53 +00:00
sebres 9077b8ce60 [27b682284974d0cd] command "file delete": avoid possible race condition if file/directory deleted after call of lstat, so bypass ENOENT error code.
Thanks to Rainer Müller (aka raimue)
2018-04-06 17:28:56 +00:00
kjnash 6bc8c27b7f Restore most lines to 80 columns 2018-04-04 13:37:37 +00:00
kjnash 6a58a0cab2 Use coroutines to remove blocking on HTTP connections 2018-04-04 12:00:03 +00:00
kjnash 1357172367 Increase test timeout to 10s. Remove commenting from Log calls that report long delay for [socket]. 2018-04-01 01:09:57 +00:00
kjnash 466fd1d930 Chasing timeout bug: reduce client timeout to 4s in tests; more sanity checking in non-keep-alive tests; tidying; more logging in http.tcl. 2018-03-31 15:27:52 +00:00
kjnash 441e4f6796 For thorough testing, set test file to verbose, and uncomment Log calls in http.tcl. 2018-03-30 10:13:57 +00:00
kjnash 3117af219f Bugfixes. Details in ticket 46b6edad51. 2018-03-30 10:02:44 +00:00
kjnash a0e1b18138 Adapt tests/httpPipeline.test for test without installation. Comment out some Log calls from tests/httpTestScript.tcl 2018-03-29 18:20:56 +00:00
kjnash 70af5c2b82 Implement queuing and pipelining for HTTP requests over a persistent connection. 2018-03-27 14:20:23 +00:00
kjnash d38ae8f974 Adapt fconfigure -translation for two-way pipelined operation. 2018-03-27 08:56:16 +00:00
kjnash 0d887fa465 Define variable tk used in Log calls for testing. 2018-03-27 08:55:21 +00:00
kjnash e9bb0992b0 First step for implementing concurrent requests using the same connection. Define namespace variables socket* and http where they will (eventually) be used. Leave them unused except in http::init where they are initialised. 2018-03-27 08:52:40 +00:00
kjnash f35c0dc2ed Revise tests/http11.test for use with commits from 78b23edb6b onwards. Adjust proc "handler" to conform to http(n) 2018-03-27 08:49:13 +00:00
kjnash e80e214673 BUGFIX. Send "Connection: keep-alive" even if HTTP/1.1. Some servers (including Apache 2.2 on RHEL6) use the discretion granted by RFCs and will close the connection unless this header is sent. 2018-03-27 08:37:06 +00:00
kjnash 731f40c6d9 New http::config option -zip to control whether to send an "Accept-Encoding" request-header for a zipped response. Default true for backward compatibility. 2018-03-27 08:32:37 +00:00
kjnash 767cf6314a Workaround for bug with https and unchunked response. A [read] does not deliver until the server closes the socket. The workaround is to specify the buffer size as the precise length required. 2018-03-27 08:29:43 +00:00
kjnash b00317d174 Changes to response handling in Finish, Eot and Event. Carefully distinguish expected and premature eof. Stricter handling of errors, minor bugfixes. Details in ticket 46b6edad51. 2018-03-27 08:25:14 +00:00
kjnash a8408767a4 Add "array unset socketMapping" in http::init. The sockets are closed and therefore do not belong in socketMapping, which should be unset. 2018-03-27 08:20:14 +00:00
kjnash 4f8b177250 Tidying - add empty else clauses, omit :: at start of command name http::CloseSocket in proc definition, use two lines instead of "return [Finish ...]" because there is no return value! 2018-03-27 08:17:38 +00:00
kjnash 25aad1ab18 Update some Log calls, mainly to specify token. 2018-03-27 08:15:26 +00:00
kjnash 3b48db4a90 Update some comments and a Log. 2018-03-27 08:12:47 +00:00
kjnash 58eff8f224 Rename some variables and commands. Details in ticket 46b6edad51. 2018-03-27 08:10:50 +00:00
kjnash 97721e9675 Add parentheses to some "if" tests; transform one test without changing its outcome. 2018-03-27 08:08:19 +00:00
kjnash d88d33f74d Give all procs an explicit return, except where commented as "Implicit Return". 2018-03-27 08:07:05 +00:00
kjnash 0a9706f48f Adjust to 80 columns except one 82-column line which would be less intelligible. 2018-03-27 08:05:42 +00:00
kjnash 45f91441a5 Adjust whitespace to Tcl 8+4 tab convention. 2018-03-27 08:03:58 +00:00
kjnash 38781266d3 Create new branch named "bug-46b6edad51-concurrent-http" 2018-03-27 07:48:33 +00:00
dgp 843d29b448 Rest of TIP 505 implementation -- mostly undoing dumb things. 2018-03-26 18:59:00 +00:00
dgp 1a73baff09 Work in progress implementing TIP 505. 2018-03-26 16:27:40 +00:00
José Ignacio Marín 05c789647a Update TZ info to tzdata2018d. 2018-03-24 10:20:43 +00:00
sebres da169b1600 minor fix on comment (restored getFileSecurityProc back, because getNamedSecurityInfoProc not used) 2018-03-22 17:45:32 +00:00
sebres 570af63547 win: fixes check of file permissions (readable, writable, executable) - more faster and stable solution without direct check of security permissions by optimal terms;
additionally corrected executable extensions (missing .ps1/.cmd) in useWide case.
2018-03-22 16:22:04 +00:00
dgp c5e979695a Missing test cleanups that break later tests. 2018-03-15 10:58:13 +00:00
dgp 99ab923ed5 Memleak and lifetime management fixes for components of the OO system. 2018-03-14 22:17:51 +00:00
dgp 72c721f3e7 merge 8.6 2018-03-14 21:51:13 +00:00
dgp 6d4320b5fb A few test hygiene fixes. 2018-03-14 20:59:01 +00:00
pooryorick 73de582148 Further work to improve Object reference accounting in order to plug leaks. 2018-03-14 20:43:20 +00:00
sebres 1bf60bab3c optimize compiled (INST_STR_TRIM): use new function TclTrim instead of combination of TclTrimLeft/TclTrimRight 2018-03-14 17:23:24 +00:00
sebres 77ab9f868a merge 8.5 2018-03-14 17:19:23 +00:00
sebres 6e7c474da7 TclTrim: special case for TrimRight on single char result of TrimLeft (this char is already verified within TrimLeft, so bypass TrimRight at all) 2018-03-14 17:17:44 +00:00
dgp b16ec6f23b Backout recent patch working on Object and Namespace refcounts.
It creates new leaks and memory corruption according to valgrind,
and the preceding checkin did not.  Keep developing on the memleak branch
and it can merge again when valgrind and memleak tests both like it.
2018-03-14 04:26:41 +00:00
dgp 0d0b8e03ed merge 8.5 2018-03-14 00:53:13 +00:00
dgp fd2d896c8f TclTrim must write to *trimRight even when making a quick exit. 2018-03-14 00:45:14 +00:00
dgp f597744c5f Make TclTrim* routines robust against some malformation in inputs.
Better than access violations and panics!
2018-03-14 00:03:59 +00:00
dgp 261fbdac7e A few minor revisions. 2018-03-13 23:56:22 +00:00
pooryorick ec5288cc2e Audit and correct Object reference counting issues. 2018-03-13 20:46:08 +00:00
pooryorick 90f38b1023 Audit and correct Object reference counting issues. 2018-03-13 20:41:23 +00:00
sebres 64eaafad72 remove unexpected panic by TclTrimLeft/TclTrimRight, handling rewritten:
- instead of check the NTS-byte after string (may cause segfault by access violation if out of range),
  it checks now the end-character is well-formed utf8-sequence;
- both work well now on non-NTS strings (without null character at end);
- additionally fixed wrong offsets (trim-length if last char malformed in case of out of range);
new function TclTrim introduced (as combination of TclTrimLeft/TclTrimRight).
2018-03-13 18:52:45 +00:00
dgp a275b8a5ea Rewrite the [string replace] compiler to take advantage of the richer
set of encoded index values.
2018-03-13 16:03:39 +00:00
dgp debafda1e7 Repair the INST_STR_REPLACE instruction. 2018-03-13 04:01:03 +00:00
dgp 1af314024c Merge new test and comments from 8.5 to demo that INST_STR_REPLACE is bad. 2018-03-13 03:26:42 +00:00
dgp 23178bb208 Tidy up and comment [string replace] and its corner cases. 2018-03-13 03:15:28 +00:00
dgp a28f176470 It is confusingly stupid to use variable "length" to hold an actual length
in part of a routine, and hold an end index value later.
2018-03-12 02:48:59 +00:00
dgp de9c1aff4a plug memleaks 2018-03-11 21:15:27 +00:00
dgp e7a5b8aaa5 Prevent leaks of the Object structs of oo::object and oo::class. 2018-03-11 21:14:41 +00:00
dgp cd39f34fa5 Attempt at providing the missing instance squelcher. 2018-03-11 18:08:00 +00:00
dgp a0374a6e61 plug memleak of constructed package requirement. 2018-03-11 12:14:05 +00:00
dgp 3f3c89a947 Screen out empty list value so that assertions are true. 2018-03-11 12:13:11 +00:00
dgp d9dbcf5afb Remove unused argument. 2018-03-10 15:41:04 +00:00
dgp e7a86d967c Use LIST_MAX instead of computing an end index. 2018-03-10 14:44:05 +00:00
dgp 6fce39545c rename tests to make room for new tests in 8.7 2018-03-10 14:37:36 +00:00
dgp 87fd09e44a [db36fa5122] Upgrade the index value parsing and encoding machinery.
Refactor many systems to make consistent use of it. Repairs many indexing
errors in corner cases.
2018-03-09 22:18:30 +00:00
dgp cd4e0ec5de Restore safety for legacy bytecode. 2018-03-09 21:18:19 +00:00
dgp 954522812e Return routine to file scope. 2018-03-09 21:07:12 +00:00
dgp db9b0eccf3 merge 8.6 2018-03-09 20:58:20 +00:00
dgp 06c3fd0c5b Newer utility routine is more suitable. 2018-03-09 20:46:54 +00:00
dgp c13e34da37 Update the command compilers and bytecode execution engine to use new machinery. 2018-03-09 20:34:33 +00:00
dgp a9d546dfbc Use new machinery to repair index value flaws in [lsort]. 2018-03-09 19:40:01 +00:00
dgp 6798b2404f Refactor the index value encode/decode machinery for broader use.
Make use of it to fix index value flaws in [lsearch].
2018-03-09 19:23:42 +00:00
dgp 5fd318bc35 More demonstration tests of index value encoding flaws. 2018-03-09 17:30:30 +00:00
dgp 88812125b1 New tests demonstrating index value encoding flaws in [lsearch]. 2018-03-09 15:28:35 +00:00
dgp 947fb98db5 Stop failing error ordering tests in compiled [lreplace]. 2018-03-08 21:58:30 +00:00
dgp ed53b715ac Another error ordering test. 2018-03-08 19:43:57 +00:00
dgp b8b87e5280 New test expose flaw in error ordering. 2018-03-08 19:28:58 +00:00
dgp 0c5bd7480e Streamline index decoding in INST_LIST_RANGE_IMM execution.
Eliminte the internals intrusion in the unshared in-place operations case.
Tcl_ListObjReplace() really ought to be good enough.
2018-03-08 18:57:16 +00:00
dgp 64038c5656 Rollback the stealth change to [lreplace a 1 1] in Tcl 8.6.6. [409ea17e37].
Scratch rewrite of the [lreplace] compiler.
2018-03-08 17:26:49 +00:00
dgp 101ac8bca7 Reduce the "clever" factor. (Fine line between clever and stupid.) 2018-03-08 02:28:49 +00:00
dgp 30e7e05895 Streamline index decoding in INST_STR_RANGE_IMM execution. 2018-03-07 21:45:12 +00:00
dgp ce6aa3ea08 When index parsing alone tells you a [string range] is empty, just push it. 2018-03-07 21:02:44 +00:00
dgp d7f41b448c Express INST_LIST_INDEX_IMM index processinig in terms of TCL_INDEX_END so
that consistencies are maintained, and hardcoded values are a bit demystified.
2018-03-07 19:55:23 +00:00
dgp 2c44354d13 Establish 4 symbols for categories of parsed index values:
TCL_INDEX_START = 0		The start index.
    TCL_INDEX_END = -2		The "end" index.
    TCL_INDEX_BEFORE = -1	All indices less than start.
    TCL_INDEX_AFTER = INT_MAX	All indices greater than "end".

Then use these symbols among callers of TclGetIndexFromToken() so that
index value parsing can directly implement the callers sense of when
out of range indices ought to be treated the same as start or end positions.
2018-03-07 18:39:44 +00:00
dgp 612199cbe9 Rework TclGetIndexFromToken to make use of TclGetEndOffsetFromObj, and
to lay out the index value encoding cases.
2018-03-07 17:02:50 +00:00
sebres f337281f75 amend to [58716e0e92]: now the duplication is really pointless, so eliminated 2018-03-07 15:10:44 +00:00
dgp 7fe003f8d2 Remove pointless duplication. 2018-03-07 14:16:08 +00:00
dgp f003df5624 Tests of [assemble] use of compiled index values. 2018-03-07 13:40:54 +00:00
dgp 9fb9471807 Incorporate sebres work on the same ticket. Good stuff! 2018-03-07 12:08:40 +00:00
sebres 8c2cbf3211 test cases for "lsort": coverage for "missing from sublist" error case with negative index (-1-1, -2) 2018-03-06 22:27:47 +00:00
sebres c68d043691 try to fix [db36fa5122]: better compiled variants of several indices-related commands, test-cases extended 2018-03-06 21:59:53 +00:00
dgp 720c8de452 rework error handling to keep test suite happy. 2018-03-06 20:59:44 +00:00
dgp 596e89b17d Have assembler use same index value parser as the bytecode compiler. 2018-03-06 20:27:39 +00:00
dgp 847a048c18 New internal routine TclGetEndOffsetFromObj. 2018-03-06 20:09:00 +00:00
dgp da8fbb89c4 various bits of ranting commentary 2018-03-06 17:38:44 +00:00
sebres 465d28aa75 merge core-8-5-branch (fixes [1873ea0ee4f01b26]: wrong initialization of std-channels ...) 2018-03-05 17:43:42 +00:00
sebres 6c0170972f fixes [1873ea0ee4f01b26]: wrong initialization of std-channels, if no std-handles available at all (e. g. non-console application, like "tk") 2018-03-05 17:37:21 +00:00
dgp 683dada217 Some comments info for the next folks who come wandering in. 2018-03-01 20:07:29 +00:00
dgp 2cd8bf554e Refactor to eliminate duplicate routine parsing tokens as indices. 2018-03-01 16:48:55 +00:00
dgp 468041eef8 [8e6a9ac221] Stop false matching with bytearrays. (string-11.55) 2018-02-23 17:00:03 +00:00
dgp 85233a4693 [8e6a9ac221] Stop false matching with bytearrays. (string-11.55) 2018-02-23 16:55:49 +00:00
dgp 455b61dce3 [89dfecb6b7] Make thread IDs in testing commands consistent. 2018-02-22 18:57:20 +00:00
dgp dda81853f3 Stop seeking out the libieee.a library and linking to it when found.
The latest release of the GNU C library, glibc-2.27 has done away with
the libieee.a library. This prompts a review of why Tcl has been using it.

Since Tcl 8.4.0, Tcl has stopped using the matherr() machinery, so we don't
need it anymore for that.

Since Tcl 8.5.0, Tcl post-processes ERANGE for itself when floating point
underflow or overflow can sensibly produce a 0.0 or Inf result instead of
raising an error. We no longer need to configure the system math library to
silence these reports.

A conseqeunce of this change is that TCL_LIBS will no longer include the
linker option -lieee .  This can potentially change the behavior of programs
that embed libtcl.  If so, though, those same programs are going to also have
behavior changed as the new glibc release gets into routine use. We're doing
those programs a favor by stopping masking the discovery that they need to
be updated.
2018-02-15 15:08:17 +00:00
pooryorick 919808c6a5 merge pyk-backport-to-8-6
DGP: This checkin creates two memleaks, detected by test compile-12.1

That test leaks the allocations at

    tclOO.c, line 401   AllocObject(...)

    tclOODefineCmds.c, line 8143    Tcl_NewObjectInstance()
2018-02-15 10:52:44 +00:00
pooryorick beff988e79 Rearrange a few lines TclRenameCommand to reduce operations. 2018-02-15 10:23:53 +00:00
pooryorick e8f10bd44e merge pyk-TclOO 2018-02-15 10:14:14 +00:00
pooryorick fa3a1e4638 Udate Tcl_ObjectDeleted to reflect recent changes. 2018-02-15 10:05:27 +00:00
pooryorick 74c5043b5a TclOO: Remove unneeded name manipulation from TclOOCopyObjectCmd. 2018-02-15 09:47:35 +00:00
pooryorick dafcde1702 Fix syntax error in previous commit. 2018-02-15 09:40:40 +00:00
pooryorick e16817b409 Add the check for wrong arguments back to TclOO_Object_Destroy, remove
inadvertant increment of Namespace->refCount.
2018-02-15 09:34:49 +00:00
pooryorick 03a4436237 Streamline TclOO object cleanup routines. 2018-02-15 09:30:29 +00:00
pooryorick e52e074e4f Add TCL_CREATE_NS_IF_UNKNOWN back into Tcl_CreateEnsemble(). 2018-02-15 09:20:50 +00:00
pooryorick 0b5a1c79b7 Fix for [6bca38d59b], TclOO segmentation fault cleaning up objects that that
have mixed themselves into themselves.
2018-02-15 09:10:02 +00:00
pooryorick 0c44c5003d Fix for issue [6cf568a21b]: Tcl_Eval() causes new segfault (TclOO object
creation by qualified name).
2018-02-15 08:53:15 +00:00
pooryorick 2b9b50b436 Minor refactoring of TclOO object reference count booking during object
creation.
2018-02-15 08:38:27 +00:00
pooryorick 80fc86a116 Eliminate some duplicate code in tclOO.c/Tcl_NewObjectInstance(). 2018-02-15 06:45:34 +00:00
pooryorick 1da12398f2 Streamline TclOO object cleanup routines. 2018-02-15 06:35:02 +00:00
pooryorick 4322dab97e merge pyk-command-named-colon 2018-02-15 06:01:09 +00:00
pooryorick 3243dfedd1 Move return type to its own line. 2018-02-15 05:11:15 +00:00
pooryorick fa5058cbca merge (cherrypick): Add missing parenthesis to an expression in TclEnsureNamespace. 2018-02-15 04:56:48 +00:00
pooryorick ade95255b9 Fix segmentation fault in TclOO that was noted in [16fe1b5807]. Update
coroutine and TclOO object creation routines to use TclCreateObjCommandInNs.
2018-02-14 21:47:57 +00:00
pooryorick e6dd74e90e Lift the restriction on command names names that begin with ":". 2018-02-14 19:07:16 +00:00
pooryorick cf4de002dc New empty branch for other branches that bring changes from core-8-branch back
to core-8-6-branch.
2018-02-14 19:07:14 +00:00
pooryorick b9b319fad2 merge pyk-backport-to-8-6 2018-02-14 14:19:31 +00:00
pooryorick 5d5bd4cd55 Modify TclCreateProc to handle arbitrary argument names, not just ASCII. 2018-02-14 14:05:04 +00:00
pooryorick 1e854210b7 Rewrite documentation in comments for brevity and clarity. 2018-02-14 13:37:27 +00:00
pooryorick 7d25e385a2 Modify test oo-11.6 to not use [self], which is not avaiable until 8.7. 2018-02-14 13:00:28 +00:00
dgp 40e9ab2e65 More tests for bignum modules regressions. 2018-02-14 12:52:06 +00:00
pooryorick c6eb0cc51d Unit test for issue 3c32a3f8bd, Segmentation fault in
TclOO.c/ReleaseClassContents() for a class mixed into one of its instances.
2018-02-14 12:31:33 +00:00
pooryorick a7c17bc224 Fix bug 3c32a3f8bd, segmentation fault in TclOO.c/ReleaseClassContents()
for a class mixed into one of its instances.
2018-02-14 12:14:38 +00:00
pooryorick 2606a3a7db Fix for issue 9fd5c629c1, TclOO - aborts when a trace on command deletion
deletes the object's namespace.
2018-02-14 10:57:38 +00:00
pooryorick ea6e8c9dcd Fix for issue 9fd5c629c1, TclOO - aborts when a trace on command deletion
deletes the object's namespace.
2018-02-14 10:46:08 +00:00
dgp 396c1a637c New test expr-32.7 for bignum modulus range. 2018-02-13 20:51:57 +00:00
pooryorick 1553090bc3 Add remaining wrapper to the NR functions, remaining calls to
TCL_NRAddCallback, and a test for a package require script that yields.

DGP: This checkin introduces a memleak, detected by test compExpr-7.1.
2018-02-12 12:40:34 +00:00
pooryorick f4babdb0ac Adapt signature of PkgRequireCore to conform to Tcl_ObjCmdProc, and call it in
Tcl_PkgRequireProc on an NRE trampoline via Tcl_NRCallObjProc.  Additional
callbacks still needed to fully NRE-enable [package require].
2018-02-12 10:44:44 +00:00
pooryorick 4c79bcbe64 Preparation to provide TclNRPackageObjectCmd: Eliminate the loop in
PkgRequireCore so that TclNRAddCallback can be added at the needed spots.
2018-02-12 10:14:02 +00:00
pooryorick 568724e468 Change the signature of PkgRequireCore in preparation to provide
TclNRPackageObjCmd.
2018-02-11 19:35:27 +00:00
pooryorick ad022e6d3b Remove restriction on defining the class of a TclOO object not explicitly
instantiated from ::oo::class.
2018-02-11 19:29:08 +00:00
pooryorick 5765c1e392 Refine documentation for Tcl_NR* functions. 2018-02-11 19:19:46 +00:00
sebres 4f65558ad0 win/nmakehlp.c: removed unneeded dependencies to shlwapi (the same is easily implemented by standard win-api) 2018-02-08 14:02:15 +00:00
José Ignacio Marín b618278c9f Update TZ info to tzdata2018c. 2018-02-02 09:19:41 +00:00
apnadkarni adf9cf5543 Fixed def for INCLUDE_INSTALL_DIR when building against Tcl source. Bumped to 1.2. 2018-02-02 06:07:26 +00:00
dgp a0c6bf8d92 Regression test for shimmering danger in [join]. 2018-01-27 01:38:21 +00:00
dgp 19c0142741 lifetime management of files generated by tests 2018-01-25 21:28:41 +00:00
dgp 189d0a83d2 lifetime management of files generated by tests 2018-01-25 21:15:36 +00:00
dgp aa4c401952 test name continuity 2018-01-25 20:41:26 +00:00
dgp f08ea44564 Dup test names 2018-01-25 20:28:15 +00:00
jan.nijtmans e403ff8f45 Documentation fix: there is no "O" conversion, just "o" for octal. Also, "b" conversions normally don't produce a sign. 2018-01-24 09:59:15 +00:00
jan.nijtmans 5fea88381c typo's (found by Gustaf Neumann). Thanks! 2018-01-17 10:06:30 +00:00
jan.nijtmans 45e646472d Fix behavior of Tcl_GetRange() and "string range" regarding surrogates, when Tcl is compiled with -DTCL_UTF_MAX=4. Partial fix for bug [11ae2be95dac9417]. Also, fix typo. 2018-01-11 15:44:05 +00:00
jan.nijtmans 063db11523 (cherry-pick): Use http 2 instead of http 1 for Safe Base testing. 2018-01-04 13:00:22 +00:00
jan.nijtmans 26b5bf3eca (cherry-pick): Use http 2 instead of http 1 for Safe Base testing. 2018-01-04 12:58:31 +00:00
jan.nijtmans ad43c617e3 Fix bug introduced in [0dd0d14489258621] (only for TCL_UTF_MAX > 3): If len parameter = -1, returned size includes terminating 0-byte. So, account for that.
Also, fix some comments which were not accurate any more, now that Windows 95/98 is not supported any more.
2017-12-28 21:14:40 +00:00
jan.nijtmans 301f6bcb83 Fix handling of surrogates (when TCL_UTF_MAX > 3) in Tcl_UtfNcmp()/Tcl_UtfNcasecmp()/TclUtfCasecmp(). Backported from core-8-branch, where this was fixed already. 2017-12-28 18:49:24 +00:00
jan.nijtmans 9a7ce78e96 Make Tcl_WinTCharToUtf/Tcl_WinUtfToTChar work when TCL_UTF_MAX > 3, mainly when sizeof(Tcl_UniChar) != 2. 2017-12-28 18:45:16 +00:00
apnadkarni 82cd662f00 Safer to compare TCLDIR against "" rather than ifdef as recursive nmakes
can pass TCLDIR as defined but with an empty value.
2017-12-26 03:30:22 +00:00
jan.nijtmans f2f7b85f88 merge release 2017-12-23 18:33:36 +00:00
apnadkarni 71df313773 Look for Tcl and Tk import libraries with or without "t" suffix convention
when building extensions. Bump nmake rules version to 1.1 accordingly.
2017-12-23 07:56:49 +00:00
pooryorick 28361a2bfe Further fix for issue [ba1419303b4c]: Delete a namespace for an ensemble having a
deletion trace deletes its namespace: segmentation fault.
2017-12-20 18:28:10 +00:00
pooryorick c1f84789ba Fix for issue [ba1419303b4c]: Delete a namespace for an ensemble having a deletion
trace deletes its namespace: segmentation fault.
2017-12-20 18:26:40 +00:00
dgp 1725b74695 merge 8.6; update changes 2017-12-19 20:53:27 +00:00
dgp e10cd2e0a5 [586e71dce4] Exeception handling at level #0 by EvalObjv 2017-12-19 20:48:52 +00:00
dgp f4cc39572c update changes 2017-12-19 14:46:31 +00:00
dgp 9acbab2c0e merge 8.6 2017-12-18 14:06:37 +00:00
jan.nijtmans 0fb81cb5dd (cherry-pick): Added assoc, ftype and move as auto_execok shell built-ins on Windows. 2017-12-18 13:56:30 +00:00
jan.nijtmans e0360a8c34 Add win/rules-ext.vc and win/targets.vc to "make dist". Reported by Paul Overmeier. Thanks! 2017-12-18 11:41:31 +00:00
dgp 50bb6253da merge 8.6 2017-12-14 13:32:50 +00:00
apnadkarni 48549d55b0 Updated nmake system to make use of the new nmakehlp -L option for
locating dependencies.
2017-12-13 10:03:54 +00:00
apnadkarni 8c866ee6be Add -L option to nmakehlp to locate directories 2017-12-12 17:32:21 +00:00
apnadkarni c220b0dcfa Allow standard targets to be selectively disabled.
Automatic install for extension stubs and public headers if present.
Print installation dir, remove useless partial print of preprocessor defines.
2017-12-11 16:26:24 +00:00
jan.nijtmans 5cddfdcda6 Undo latest change to tcl.rc, since the autoconf-based windows build doesn't know about PRJLIBNAME 2017-12-09 15:31:58 +00:00
apnadkarni a2c5ea2c08 Merge TIP 477 implementation 2017-12-08 13:54:42 +00:00
dgp 6c313a5846 update changes 2017-12-07 02:01:30 +00:00
dgp bbaba520ab changes WIP 2017-12-06 21:59:13 +00:00
dgp a0a62d119d merge 8.6 2017-12-06 21:03:02 +00:00
dgp 5d11ad1e8a Plug memleak recently put into [package require]. 2017-12-06 20:46:47 +00:00
dgp cd525c7bb1 Plug memleak recently put into [package require]. 2017-12-06 20:44:32 +00:00
dgp 0af956fe7e merge 8.6 2017-12-06 19:58:40 +00:00
dgp 9ba4b4f901 [0e4d88b650] Added enough refcounting to stop make valgrind complaints about
"Invalid read".  This is not a complete fix. Things are still broken.
A working system of Namespace lifetime management looks like an 8.7 project.
2017-12-06 19:57:59 +00:00
jan.nijtmans cf3348e41c (cherry-pick from core-8-6-8-rc): Duplicate test names 2017-12-06 16:04:22 +00:00
dgp 7b04f399b0 Duplicate test names 2017-12-06 15:30:27 +00:00
dgp 3aab0c568b Start RC branch for Tcl 8.6.8 2017-12-06 15:27:28 +00:00
dgp 07aa7381a9 [ce3a211dcb] Failed file normalize when tail is empty string. 2017-12-06 13:05:51 +00:00
dgp bb1c5fe833 [ce3a211dcb] Failed file normalize when tail is empty string. 2017-12-06 13:02:32 +00:00
dgp f3af86c67e [4f6a1ebd64] Stop crash when same value passed to the -map and -subcommands options of ensemble configuration. 2017-12-05 15:27:21 +00:00
dgp 3eef9fcea1 Factor clearing of ensemble subcommand table into utility routine. 2017-12-05 15:12:05 +00:00
dgp 906cf353b2 [4f6a1ebd64] Stop crash when same value passed to the -map and -subcommands options of ensemble configuration. 2017-12-05 14:57:05 +00:00
dgp 8a44c35e8c Another revised fix, much closer to sebres' patch now. 2017-12-05 14:36:33 +00:00
apnadkarni 3e34d38b2d Use PRJ_PACKAGE_TCLNAME instead of PROJECT when generating TEA based pkgindex 2017-12-05 14:29:47 +00:00
dgp 92f8ce13df [4f6a1ebd64] Different fix for the problem. Re-order the filling of the
subcommand table so there is no longer a conflict where multiple intreps of
a single value are sought. If the mapDict and exportList are the same,
then each key in the mapDict is known to be an element of the exportList
without needing to check.
2017-12-04 18:36:14 +00:00
jan.nijtmans b8fbe8c1d3 Fix [4f51e1c5dcf75de22f5907f7b66361e4bcab02e2|4f51e1c5dc]: patch to correct linker flag sequence 2017-12-01 12:47:12 +00:00
dgp 4bbfdee3db [5808081213] Permit all bytearrays (including impure ones) to report length without shimmering 2017-11-30 17:10:37 +00:00
jan.nijtmans d7d31d6041 Don't provide the setFromAnyProc through the invalidRealType objType. This is a Tcl internal type, extensions shouldn't be able to convert their own Tcl_Obj to this. This shouldn't have been exposed to begin with. Tcl itself never calls it this way. 2017-11-30 14:14:01 +00:00
sebres e68b491806 Cherry-picked test-cases from [046a5af026]: fix for issue [4f6a1ebd64]: ensemble: segmentation fault when -subcommand and
-map values are the same object.
2017-11-29 13:59:42 +00:00
jan.nijtmans e87d0bcdf4 Fix Tcl_UtfFindFirst()/Tcl_UtfFindLast(), which were broken by [83c0c569d6]. Not detected, because those functions aren't used anywhere in Tcl.
So, added new test-cases, makeing sure this doesn't happen again.
2017-11-29 12:27:22 +00:00
jan.nijtmans 4fc9a4c991 Update some functions in tclUtf.c to handle surrogate pairs when TCL_UTF_MAX == 4. Also update documentation to distinguish better between "Tcl_UniChar" and "Unicode character": Those are not necessary the same when TCL_UTF_MAX == 4.
No change when TCL_UTF_MAX == 4 or TCL_UTF_MAX == 6.
2017-11-29 11:04:20 +00:00
pooryorick 14c8dabffe merge (cherrypick): Add missing parenthesis to an expression in TclEnsureNamespace. 2017-11-25 21:40:19 +00:00
pooryorick 9b1ecce298 Move return type to its own line. 2017-11-23 18:24:09 +00:00
pooryorick 75924256c1 Fix segmentation fault in TclOO that was noted in [16fe1b5807]. Update
coroutine and TclOO object creation routines to use TclCreateObjCommandInNs.
2017-11-19 00:06:51 +00:00
pooryorick 42c80667fd Lift the restriction on command names names that begin with ":". 2017-11-17 23:42:16 +00:00
pooryorick 3c942c50d9 Fix [16fe1b5807]: namespace ensemble command named ":" is mistakenly given the
empty string as its name.
2017-11-17 22:30:06 +00:00
apnadkarni 335305de9c Added back nothreads option. 2017-11-17 15:46:23 +00:00
jan.nijtmans 48047bb120 merge core-8-6-branch 2017-11-17 15:30:02 +00:00
jan.nijtmans b44ffcf5e2 Fix [fab92486a1b05ba6f7cfe8677da95b9efb3beff0|fab92486a1]: Windows error 14 "Out of memory" mapping to Posix EFAULT "Bad address in system call argument" feels wrong 2017-11-17 15:29:07 +00:00
jan.nijtmans ff436137df Fix [fab92486a1b05ba6f7cfe8677da95b9efb3beff0|fab92486a1]: Windows error 14 "Out of memory" mapping to Posix EFAULT "Bad address in system call argument" feels wrong 2017-11-17 15:28:09 +00:00
jan.nijtmans 42236b435f Fix ignore-glob versioned setting (something went wrong in previous merge). Also convert rules-ext.vc and targets.vc to CRLF line-endings. 2017-11-17 11:35:26 +00:00
jan.nijtmans a27501598a merge core-8-6-branch 2017-11-17 11:27:13 +00:00
jan.nijtmans 28017c14e3 TIP #422, Tcl 8.7 part: Mark all *VA functions as deprecated. They will be removed in Tcl 9.0. 2017-11-17 10:23:14 +00:00
jan.nijtmans ac3259b669 Suggested patch for [4f51e1c5dc]: patch to correct linker flag sequence. Same change done for a few other platforms where it might matter. 2017-11-17 08:32:16 +00:00
apnadkarni 5560b9198b Check for existence of targets.vc, not rules.vc to determine nmake support dir. 2017-11-17 07:05:23 +00:00
apnadkarni 51319d2cae Add PRJ_PACKAGE_TCLNAME and other minor changes.
Also:
Change ifdef checks to check for empty string instead.
Quote include paths.
2017-11-17 06:52:48 +00:00
jan.nijtmans 5ff5853a6e merge core-8-6-branch 2017-11-16 08:45:54 +00:00
jan.nijtmans 24d7fa6401 No longer document (even though it's only in an example) that Tcl_SavedResult is a struct, and that the internal representation of an int is stored in the object's internalRep.longValue member. That might no longer be true in the future. 2017-11-16 08:42:32 +00:00
jan.nijtmans 65007a4d02 No longer document (even though it's only in an example) that Tcl_SavedResult is a struct, and that the internal representation of an int is stored in the object's internalRep.longValue member. That might no longer be true in the future. 2017-11-16 08:39:41 +00:00
apnadkarni c4d4363abd Loosen restriction on where rules-ext.vc file is located. 2017-11-15 13:18:00 +00:00
apnadkarni 0197a30845 Include PKGNAMEFLAGS in stubscflags as some extension stubs use it 2017-11-15 11:47:16 +00:00
jan.nijtmans 346cce5745 Remove compat/float.h and related machinery. The last system known where this was needed was SunOS-4, which is not supported by Tcl any more for a long ... long time ....
Also, fix a typo in generic/tclInt.h and remove some end-of-line spacing.
2017-11-15 09:42:07 +00:00
jan.nijtmans e3439b6af2 Change signature of (internal) TclScanElement() function. This saves memory allocation and the possibility for panic's in dict and list handling, requiring 1/4 of memory for internal allocation of temporary storage. No change to external API. 2017-11-15 08:55:18 +00:00
jan.nijtmans 59ebc49f0f Change signature of (internal) TclScanElement() function. This saves memory allocation and the possibility for panic's in dict and list handling, requiring 1/4 of memory for internal allocation of temporary storage. No change to external API. 2017-11-15 08:54:13 +00:00
apnadkarni ca86fd3219 Added default-install-stubs target.
Make presence of nmake support files in extension directory optional
(except for rules-ext.vc). This requires them to only build against
a Tcl with the new nmake build system.
2017-11-15 07:54:08 +00:00
dgp 9f65735813 Repair lost of broken [package prefer] testing. 2017-11-14 17:09:49 +00:00
dgp 2ea108ae28 [5d6de65036] [package require] with [package prefer stable] was not choosing available stable package. 2017-11-14 14:48:21 +00:00
dgp d7b5cde35f [5d6de65036] [package require] with [package prefer stable] was not choosing available stable package. 2017-11-14 14:17:57 +00:00
dgp ba9e81068e [5d6de65036] [package require] with [package prefer stable] was not choosing
available stable package.
2017-11-14 13:36:59 +00:00
aku a7b6d60948 Ticket [5d65e65036]. My fix. Do not skip the second check for stable versions even when the main check fails. Avoided radical changes to the structure (kept single search loop, with selection after). 2017-11-13 18:58:16 +00:00
jan.nijtmans eb2a9484b8 Merge core-8-6-branch 2017-11-13 11:15:44 +00:00
jan.nijtmans a92e1c508f No longer mark Tcl_EvalFile() as obsolete, since it will continue to be supported in Tcl 9.0 2017-11-13 10:51:39 +00:00
jan.nijtmans 0fc6533fcb No longer mark Tcl_EvalFile() as obsolete, since it will continue to be supported in Tcl 9.0 2017-11-13 10:49:25 +00:00
jan.nijtmans 01fd6594cf Add a lot of "deprecation" marks to internal API which will be removed in Tcl 9.0 (see also tcl-9-cleanup branch). Extensions still using this API will get a compiler warning, but everything will continue to work fine for all future 8.x releases. 2017-11-13 08:37:55 +00:00
jan.nijtmans 752cfbe04c merge core-8-6-branch 2017-11-10 08:49:54 +00:00
jan.nijtmans 1ffeaf24ef Make "string split" and "string is (alpha|graph|...)" work as expected with Unicode chars > U+ffff, when Tcl is compiled with TCL_UTF_MAX == 4. No effect when TCL_UTF_MAX == 3 or TCL_UTF_MAX == 6.
Test-case added for "string split".
2017-11-10 08:40:45 +00:00
jan.nijtmans 78374f18a4 merge core-8-6-branch 2017-11-09 12:50:43 +00:00
jan.nijtmans 729fcd5f09 Make "scan %c" and the internal function ExtendUnicodeRepWithString() work as expected for TCL_UTF_MAX == 4 when handling characters > U+ffff. No effect when TCL_UTF_MAX == 3 or TCL_UTF_MAX == 6 2017-11-09 12:48:54 +00:00
jan.nijtmans c59b3f3bc1 For alpha/beta versions of Tcl, stub-enabled extensions are only allowed to run on the EXACT the same Tcl versions as compiled: The stubs might still be in flux, they are not guaranteed to work on future Tcl versions anyway.
Backported from "novem" (which already had this special protection). For final releases (8.7.0) everything works as before.
2017-11-09 12:37:20 +00:00
jan.nijtmans 12d3a7d307 Change "epoch" field for dicts from "int" to "unsigned int". This doubles the number of available epoch's before overflow. Also make 0 the special value in stead of -1, meaning "dict search done". That also means that epoch counting starts with 1. 2017-11-08 09:37:31 +00:00
dgp 5188d1d927 compiler warning 2017-11-08 02:57:58 +00:00
dgp b8bf04f5ec compiler warning 2017-11-08 02:53:57 +00:00
dgp f31af075d0 compiler warning 2017-11-08 02:50:28 +00:00
dgp a2d6ec1119 merge 8.6 2017-11-08 02:26:07 +00:00
dgp 2ba5fab30e Modify TclCreateProc to handle arbitrary argument names, not just ASCII. 2017-11-08 02:25:40 +00:00
dgp f74bde3e62 [3298012] Stop RebuildTable asking ckalloc for more than it can give. 2017-11-08 02:23:46 +00:00
dgp 98c6b22c10 TclOO object allocation: Set classPtr to NULL if it wasn't otherwise set. 2017-11-08 02:21:49 +00:00
dgp be0c5786a0 [3298012] Stop RebuildTable asking ckalloc for more than it can give. 2017-11-08 02:18:25 +00:00
dgp fd61a8e89e Attempted bug fix. 2017-11-07 21:32:04 +00:00
apnadkarni c7530621ad Fix inclusion of custom resource files to match TIP spec 2017-11-07 16:47:35 +00:00
jan.nijtmans d0665d7a12 merge core-8-6-branch 2017-11-07 13:29:28 +00:00
jan.nijtmans ac4fb39a73 Don't use Unicode character \udead in test-cases, because it is an invalid Unicode code-point (lower surrogate). This will cause test-failures with TIP #389. Just use \ud0ad in stead. Also fix some other test-cases which fail for TCL_UTF_MAX == 4. 2017-11-07 13:19:37 +00:00
jan.nijtmans 45808db8dc TIP #422 implementation, Tcl 8.7 part. 2017-11-07 09:08:48 +00:00
jan.nijtmans c06751fdf8 Fix version number of Windows Help file (not sure if it's actually used, but better safe than sorry) 2017-11-06 14:46:49 +00:00
dgp 22719c6596 Test case for Bug 5d65e65036. 2017-11-06 00:10:21 +00:00
jan.nijtmans ded2a79966 update .project file with branch name. Make clear that optparse doesnt work with 8.4 any more 2017-11-05 14:14:23 +00:00
dkf 4030616bbf [0d902eadd6] Ensure that [string first] handles ASCII in Unicode correctly. 2017-11-04 00:44:14 +00:00
dkf b55d5cc57e Fix for the weird [string first] behaviour. 2017-11-04 00:34:48 +00:00
dkf e4356f7d64 Detected bug in [string first] with unicode. Pat Thoyts found it. 2017-11-04 00:25:43 +00:00
dgp 0480b5d79b Revise a few stray packages not yet ready to tolerate a Tcl 9 bump. 2017-11-03 17:02:49 +00:00
dgp 10a9305777 TIP 345 Implementation. 2017-11-03 16:48:44 +00:00
jan.nijtmans d8596e5583 merge core-8-6-branch 2017-11-03 12:59:07 +00:00
jan.nijtmans 5528e1c1a2 Fix [6f2f83cc149e9918884faffefebc8dfa695f4ea0|6f2f83cc14]: tclWinload.c robustness. And fix a minor possible memory leak in TclSetupEnv() as well. Thanks to Christian Werner for both suggestions, backported from Androwish. 2017-11-03 12:57:15 +00:00
jan.nijtmans 785f1059e4 merge core-8-6-branch 2017-11-03 12:15:08 +00:00
jan.nijtmans 274ab123a8 Better versions of TclGetIntFromObj and TclGetIntForIndexM macro's, which give advantage for platforms where longs are not ints (e.g. linux64) 2017-11-03 12:14:01 +00:00
pooryorick d33ee7bc07 Unit test for issue 3c32a3f8bd, Segmentation fault in
TclOO.c/ReleaseClassContents() for a class mixed into one of its instances.
2017-11-01 22:21:50 +00:00
pooryorick 8bb421f959 Fix bug 3c32a3f8bd, segmentation fault in TclOO.c/ReleaseClassContents()
for a class mixed into one of its instances.
2017-11-01 21:05:32 +00:00
dgp 2ff3ecb534 merge trunk 2017-10-30 12:02:48 +00:00
pooryorick e0578530b0 merge bug-fc1409fc91. 2017-10-30 05:25:19 +00:00
pooryorick a79bc3c8ce Fix for issue 9fd5c629c1, TclOO - aborts when a trace on command deletion
deletes the object's namespace.
2017-10-30 05:19:55 +00:00
dgp 30c40c4540 merge 8.6 2017-10-30 03:23:59 +00:00
dgp c5865fcd24 More test rewrites for robust var resolution. 2017-10-30 03:23:28 +00:00
dgp c8342af338 merge 8.6 2017-10-30 03:01:46 +00:00
dgp 1d0751deb7 Revise tests that relied on deprecated variable resolution rules. 2017-10-30 02:55:30 +00:00
apnadkarni 2318b70929 Minor edits 2017-10-28 17:18:58 +00:00
dgp bed6e18d15 merge trunk 2017-10-27 13:12:09 +00:00
dgp c668ed46ec oops 2017-10-27 12:57:45 +00:00
dgp 0a3f9ca6fc oops 2017-10-27 12:57:15 +00:00
dgp 261012ce98 Update tests that were still written on the outdated premise that Tcl's encoding subsystem had to initialize starting in the identity encoding. 2017-10-27 12:51:14 +00:00
dgp 2f8bbbe141 Update tests that were still written on the outdated premise that Tcl's encoding subsystem had to initialize starting in the identity encoding. 2017-10-27 12:50:38 +00:00
dgp 4ab9cb5418 Update tests that were still written on the outdated premise that Tcl's
encoding subsystem had to initialize starting in the identity encoding.
2017-10-27 12:23:28 +00:00
dgp 3888c4fda4 merge mark 2017-10-27 12:04:53 +00:00
jan.nijtmans fa2e7e8949 Fix timeout calculation in epoll-based notifier. Proposed fix for [1a6a36d901dedead248ea96df09d5dc159532652|1a6a36d901]. Patch by Lucio Andrés Illanes Albornoz. Thanks! 2017-10-27 07:26:15 +00:00
apnadkarni c324bb3eff Reworked build command macros (MAKEBINCMD, CCPKGCMD etc.) and purged old comments. 2017-10-26 15:07:16 +00:00
dgp 053a74e0fa Create new testing command [teststringbytes] to probe the things that
otherwise require [encoding convertto identity]. adapt encoding-15.3 to use.
2017-10-26 02:08:27 +00:00
apnadkarni ff1c348970 Updated comments. 2017-10-25 02:59:46 +00:00
dgp 30c6827ee1 Convert remaining tests to use [testbytestring].
encoding-15.3 still needs replacement for [encoding convertto identity].
That is, some testing command to expose objPtr->bytes.
2017-10-25 02:54:24 +00:00
dgp eb2cfa3e6f Repair Tcl_CreateEncoding(); Modernize [testencoding];
Update most tests toying with identity encoding.
2017-10-25 02:23:12 +00:00
dgp 40d9b81e23 Stop using "identity" as an encoding to test basic functionng of the
[encoding] command. "iso8859-1" is another one always available.
2017-10-24 23:30:35 +00:00
dgp 1552384787 Extend Tcl_CreateEncoding() to be able to create an encoding without
registering it when it has no name.  Then use this to create "identity"
encoding without naming it "identity". Then no one can look it up by that name.
2017-10-24 23:16:23 +00:00
dkf 9306fa604c Cherrypick: [fc1409fc91] Method cloning needs to be careful with body representations. 2017-10-24 14:11:16 +00:00
jan.nijtmans d5f679a3f6 Change (internal) refCount field from TclRegexp to type size_t: this allows more references on 64-bit platforms. Remove unused macro "xxx" in regguts.h. Remove superflouous eol-space in oo.test. 2017-10-24 13:56:26 +00:00
Kevin B Kenny e532a0de84 Historical change affecting tests: Detroit did not observe Daylight Saving Time in 1967 2017-10-24 13:32:54 +00:00
Kevin B Kenny 745b43f627 Historical change affecting tests: Detroit did not observe Daylight Saving Time in 1967 2017-10-24 13:30:41 +00:00
Kevin B Kenny f18d453679 Historical change affecting tests: Detroit did not observe Daylight Saving Time in 1967 2017-10-24 13:24:25 +00:00
Kevin B Kenny 2332ac45ca Update to tzdata2017c 2017-10-24 13:18:51 +00:00
dkf 634213a9c8 [fc1409fc91] Method cloning needs to be careful with body representations. 2017-10-24 11:25:29 +00:00
dkf 8e537759cf Added test case. 2017-10-24 11:23:54 +00:00
pooryorick fada619052 [fc1409fc91]: TclOO method with non-literal value for body argument causes segmentation fault 2017-10-24 08:38:17 +00:00
dgp 319b71965b backout initial commit; need more care.
Binary writes internally make use of this encoding.  Need to hide it
instead of destroy it.
2017-10-23 17:58:07 +00:00
José Ignacio Marín 47a0727695 Update TZ info to tzcode2017c. 2017-10-23 17:10:19 +00:00
dgp 45d0977a5c Implementation branch for TIP 345: Kill the "identity" encoding.
This checkin, completely does that.  Bad news is it causes huge failures.
We're still making a lot of use of this encoding, and cannot complete
this TIP until the branch is repaired.
2017-10-23 17:06:57 +00:00
José Ignacio Marín 4407704316 Update TZ info to tzcode2017c. 2017-10-23 16:59:20 +00:00
apnadkarni fe8915122a Eliminate loimpact and tclalloc options. 2017-10-23 13:53:51 +00:00
jan.nijtmans e9b584f81b merge core-8-6-branch 2017-10-23 12:10:42 +00:00
jan.nijtmans cdb25d8946 Fix [b58e6897034fc5292c9d36ba8099d9a835c98172|b58e689703]: Return value of 'Tcl_Flush' 2017-10-23 12:09:48 +00:00
apnadkarni 7db056b75a Fully qualify OUT_DIR and TMP_DIR paths so that the test target can
change directories and not break relative paths to the built extension.
2017-10-21 12:14:25 +00:00
apnadkarni 6f23316c4a Added test and shell targets. 2017-10-20 15:32:22 +00:00
dkf 56d6e9480f [1a56550e96] Ensure that method list introspection finds methods from mixins in all cases. 2017-10-19 09:30:16 +00:00
dkf df974e71f9 Oops; put the code in the wrong place. Mixins have priority when deciding method visibility. 2017-10-19 09:28:16 +00:00
dkf 7393032d5e [1a56550e96] Ensure that method list introspection finds methods from mixins in all cases. 2017-10-19 09:24:12 +00:00
dkf 252f75d8c8 Ensure that method list introspection finds methods from mixins in all cases. Use better approach for preventing excessive iteration. 2017-10-19 09:22:05 +00:00
dkf 69030a86c8 [1a56550e96] Mixins aren't being searched correctly by [info class methods -all] 2017-10-18 18:23:38 +00:00
apnadkarni fa7141288f Update RCFILE to PRJ_RCFILE. 2017-10-18 16:04:13 +00:00
apnadkarni 63a9fcf2e7 Fix resource file compilation when makefile specifies PRJ_RCFILE 2017-10-18 16:03:08 +00:00
apnadkarni b6f90aaf1f Add PRJ_MANIFEST to support manifest generation. 2017-10-17 15:01:56 +00:00
apnadkarni 4ef03a8950 Fixed reversed check for implicit rules 2017-10-16 12:46:53 +00:00
apnadkarni 823edbf0ab Permit application makefile to define RCFILE.
Change PROJECT_REQUIRES_TK to use value instead of ifdef.
Change MAKERESCMD macro not to specify included input files.
2017-10-15 06:58:20 +00:00
dgp 8a910c1a53 Plug some memleaks. 2017-10-13 16:15:52 +00:00
jan.nijtmans e7582d10c6 Eliminate variable which is only used once. And a minor end-of-line space reduction. No functional change. 2017-10-12 15:20:42 +00:00
jan.nijtmans 5064777d16 merge core-8-6-branch 2017-10-09 14:27:31 +00:00
jan.nijtmans 5b74714749 In nmakehlp -v, return non-0 exit code if version is not found. (taken from vc-reform branch) 2017-10-09 14:25:24 +00:00
jan.nijtmans 15a7950c9e In nmakehlp -v, return non-0 exit code if version is not found. (taken from vc-reform branch) 2017-10-09 14:23:39 +00:00
jan.nijtmans c925a86988 Merge core-8-6-branch 2017-10-09 12:54:39 +00:00
jan.nijtmans 75ecb090c6 Add visual-studio related entries to ignore-glob. Taken over from reform-vc branch 2017-10-09 12:53:46 +00:00
jan.nijtmans b8e5e2909e Add visual-studio related entries to ignore-glob. Taken over from reform-vc branch 2017-10-09 12:52:14 +00:00
apnadkarni 0c646bc3d1 Fix RC template dependency to not generate it every time 2017-10-08 16:12:23 +00:00
apnadkarni f4e4349cad Fix htmlhelp generation on 64-bit systems 2017-10-08 14:25:19 +00:00
apnadkarni 9845cc7c9c Add default rc template so extensions do not have to write their own 2017-10-08 13:18:15 +00:00
apnadkarni fdc29e53d3 Was not setting VERSION for extensions. 2017-10-07 17:16:20 +00:00
apnadkarni a0f84e1b73 Fix ignore glob for Visual C++ output directories. 2017-10-07 13:33:13 +00:00
apnadkarni 21379b0cf5 Move standard predefined targets to targets.vc as this allows the master
makefile to modify macros if required before the targets are defined.
2017-10-06 13:38:26 +00:00
apnadkarni 65895760ea Added standard target for generating pkgIndex.tcl.
Added PKGNAMEFLAGS to pass PACKAGE_NAME and PACKAGE_VERSION.
2017-10-05 17:00:39 +00:00
apnadkarni 20730e0afb Added default-pkgindex target and split DISABLE_DEFAULT_TARGETS to
DISABLE_{STANDARD,CLEAN}_TARGETS.
2017-10-05 14:19:50 +00:00
apnadkarni c0295836a8 Add default-* targets 2017-10-04 01:57:51 +00:00
apnadkarni 8c50df7bbf Extract version numbers from TEA files so do not have to be separately defined. 2017-10-03 13:44:49 +00:00
apnadkarni ec0fc7f816 Have nmakehlp return non-0 exit code if version string not located with -V option 2017-10-03 13:41:53 +00:00
jan.nijtmans fd6a064ee7 Merge latest 'const'ification changes from libtommath (develop branch, will be in next release). None of those are used in Tcl. 2017-10-03 09:11:05 +00:00
apnadkarni f5c6b07246 Remove use of any macros used in rules.vc from rules-ext.vc
Added USE_WIDECHAR_API to control usage of Windows wide API's.
2017-10-03 08:06:30 +00:00
apnadkarni 35256f809e Introduce rules-ext.vc file for extensions to select most recent rules.vc 2017-10-02 17:09:56 +00:00
jan.nijtmans 6881a1a274 'const'ify all libtommath functions, will appear in next libtommath version. See: pull request [https://github.com/libtom/libtommath/pull/88|88] 2017-10-02 15:22:27 +00:00
apnadkarni 01201582b7 Fix initialization of _TCLDIR and use MAKE*CMD macros in makefile.vc
Fixed initialization of _TCLDIR when it is not defined by caller when
building an extension. _INSTALLDIR is modified AFTER it is used to
initialize _TCLDIR. However, nmake expands late so we have to init
_TCLDIR relative to the *modified* _INSTALLDIR.
2017-09-30 14:11:08 +00:00
apnadkarni 24b65fbe41 Added MAKEEXTCMD macro.
Fixed couple of syntax errors when building extensions.
2017-09-30 08:34:31 +00:00
apnadkarni 457587f033 Added standard macros LIBDIR and DEMODIR. Also set common Tk related names and paths 2017-09-30 06:20:33 +00:00
apnadkarni 78cf383197 Permit definition of implicit rules and standard targets to be disabled 2017-09-29 14:23:17 +00:00
apnadkarni 71c784c8bc Added implicit rule for compiling resources.
Added Tcl import libraries to link macro.
2017-09-29 12:41:02 +00:00
apnadkarni e4269a7140 Updated for Tk compatibility.
Removed extraneous quotes in macro definitions. Macros should be quoted at 
*use* time, not *definition* time.
Added _nostubs versions of pkgcflags and appcflags.
2017-09-29 06:12:04 +00:00
apnadkarni 3734937878 Add pkgcflags, appcflags and stubscflags to reflect different compilation modes.
Packages compile (at least) three types of objects files - the shared library
extension (e.g. tk86.dll), application programs (e.g. wish) and a static 
stubs library (tkstub86.lib). Thus we need to construct three different sets
of compilation flags accordingly.

Also updated makefile header comments to reflect modern usage.
2017-09-28 12:22:41 +00:00
apnadkarni 07c1c221cb Include rules.vc and nmakehlp.c as part of install.
Work toward not having to keep updating extensions with the latest version
of rules.vc and nmakehlp. Extension makefiles can instead use the 
installed files instead.

Also added some basic sanity checks to rules.vc to warn if extensions are
being compiled with options incompatible with those used to build Tcl.
2017-09-26 12:22:42 +00:00
apnadkarni 246e599142 Eliminate obsolete winhelp style documentation and fix Html Help doc build
to work on 64-bit systems.
2017-09-25 17:35:29 +00:00
apnadkarni f1aa04858d Eliminated /base option on linking as not recommended with ASLR 2017-09-25 16:33:20 +00:00
apnadkarni 301208c889 Unify build commands with MAKE{LIB,DLL,CON,GUI}CMD macros 2017-09-25 16:23:34 +00:00
apnadkarni b5e3779cf2 Move TCLSH and TCLSH_NATIVE macros to rules.vc 2017-09-25 13:45:34 +00:00
apnadkarni 56e2bd0be4 Added project-specific include paths and preprocessor defines. 2017-09-25 10:41:22 +00:00
apnadkarni 34cb030c7b Move clean target to rules.vc to avoid repetition in every extension 2017-09-24 14:25:48 +00:00
apnadkarni a91099b33b Move installation dir macros to rules.vc 2017-09-24 12:13:29 +00:00
apnadkarni ad9a3b8b45 Moved generic compiler and linker flags completely into rules.vc so
extensions do not have to repeat the verbage.

Special case Tk as a Tcl extension and add default for locating Tcl source.

Both Tcl and Tk compile with new rules.
2017-09-24 06:03:34 +00:00
apnadkarni c7e43807bf More refactoring. Moved defines that are Tcl-specific to makefile.vc as
rules.vc is common to extensions. Reworked parsing of STATS and CHECKS.
2017-09-23 07:35:32 +00:00
apnadkarni d8e7cf09b1 First step in complete refactoring.
Breaking up into logical sections with comments.
Fix floating point option selection to be the same on debug and release.
Pick up nmakehlp.c from installed Tcl if available when building extensions.
Mods to allow extensions to use the same exact rules.vc file.
2017-09-22 13:26:14 +00:00
jan.nijtmans b0fe49c36d Make libtommath's "make" work in Tcl environment (for testing). Eliminate internal s_is_power_of_two(), which can better be done inline. Fix tommath.h for _MSC_VER. 2017-09-22 08:48:23 +00:00
apnadkarni a52f0db3e4 Merged core-8-6-branch to pick up 32/64-bit DLL mismatch error message.
Actually already cherrypicked but redoing because that does not show
up on timeline and a full merge recommended on the chat.
2017-09-22 02:17:02 +00:00
apnadkarni 4bf8f43b3a RFE [566a999189] - better error message for 32/64 bit mismatch on load. 2017-09-21 19:05:11 +00:00
apnadkarni d45863129f RFE [566a999189] - better error message for 32/64 bit mismatch on load. 2017-09-21 18:47:45 +00:00
apnadkarni 4f406d752d First cut at making application-independent compile and link flags
common to all extensions defined in a single place - rules.vc -
instead of having each extension cut and paste the same code.
2017-09-20 12:58:59 +00:00
jan.nijtmans 1b28405773 Move fast return from s_is_power_of_two() to mp_div_d(). This saves a function call in the common case where b is not a power of 2. 2017-09-20 09:21:54 +00:00
jan.nijtmans 65703d1f87 Further astyle formatting of libtommath. No functional changes. 2017-09-20 09:07:35 +00:00
apnadkarni 6d85564696 Disable pointer<->int warnings related to cast between different sizes
There are a gadzillion of these due to use of ClientData and clutter up compiler
output increasing chance of a real warning getting lost. So disable them.
Eventually some day, Tcl will be 64-bit clean.
2017-09-19 16:43:19 +00:00
apnadkarni 071f38c482 Eliminated some obsolete checks (Win98, IA64 etc.) to reduce the noise. 2017-09-19 16:07:14 +00:00
apnadkarni b81c66b4c7 Do not permit nothreads in OPTS as sockets, registry and dde require threading. 2017-09-19 15:12:52 +00:00
apnadkarni 0e5d15e072 Fix mapping of VCVERSION to VCVER. The simplistic calculation no longer
holds for new versions of the compiler. Instead directly use the internal
compiler version for these.
2017-09-19 12:50:25 +00:00
apnadkarni 78a20a11b2 Remove /Gs which enables _chkstk on *every* function call. The normal default
behaviour (without the option) checks only local variable space exceeds
page size. This is what Microsoft recommends.

Also moved -O2 to rules.vc file so as to keep all optimization flags 
in one location. 

Removed optimizations switches subsumed by -O2.
2017-09-19 12:10:25 +00:00
apnadkarni 54431f3360 Create new branch named "vc-reform" 2017-09-19 10:49:37 +00:00
jan.nijtmans f75f76c9d4 Finish libtommath's constification work. All done (hopefully). And make sure that C preprocessor directives have the '#' as first character on the line. 2017-09-18 14:38:26 +00:00
jan.nijtmans f5ea63343e Another round of libtommath const'ification. To be submitted to the libtommath folks 2017-09-18 12:53:48 +00:00
jan.nijtmans a708ae2da2 Merge libtommath upstream changes (astyle formatting only). No functional changes. All Tcl-specific modifications are kept. 2017-09-18 08:31:55 +00:00
jan.nijtmans d4e73bcab5 re-format everything through astyle. Taken from libtom/libtommath (pull request [https://github.com/libtom/libtommath/pull/85|85]) 2017-09-15 14:44:00 +00:00
jan.nijtmans 8f339500a2 'const'ify more libtommath functions. All functions in generic/tclTomMath.decls (used by Tcl) are done now. 2017-09-15 13:08:31 +00:00
dgp bf01a303da Move new declarations to more conventional place for tidier merging. 2017-09-14 14:02:12 +00:00
jan.nijtmans 99d940211c Remove some unnecessary #if 0 sections. Fix comments and panic messages. No functional changes. 2017-09-14 08:05:32 +00:00
jan.nijtmans 7b8b406719 Fix [f5da3d30e096a1c3486fbc480a6ece01fcb277a6|f5da3d30e0]: clerical error in comments 2017-09-14 07:42:38 +00:00
jan.nijtmans db3273f346 Fix [f5da3d30e096a1c3486fbc480a6ece01fcb277a6|f5da3d30e0]: clerical error in comments 2017-09-14 07:41:09 +00:00
jan.nijtmans c659b044b1 Make mp_get_long and mp_set_long available to tommath-enabled Tcl extensions. Deprecate the internal TclBNInitBignumFrom* functions, in favor of the official tommath functions with the same purpose. 2017-09-13 10:14:31 +00:00
jan.nijtmans 3e55dbb18c Many 'const' addtions in libtommath where it makes sense. To be submitted back to the libtommath guys. 2017-09-11 10:38:07 +00:00
jan.nijtmans b2446d8d41 Add some more functions from libtommath for availability within Tcl (mainly the 'long long' variants). Add more 'const' keywords there too. 2017-09-08 14:15:13 +00:00
gahr e86e8a501d Be consistent about how I am referred to. 2017-09-08 13:30:29 +00:00
dgp d03a4dcc88 Bump to 8.7a2 to distinguish trunk from 8.7a1 release. 2017-09-08 13:13:15 +00:00
dgp 4ce5b276eb merge release 2017-09-08 12:50:06 +00:00
dgp 877e9d6b11 merge trunk; rc1 2017-09-07 12:59:14 +00:00
jan.nijtmans 413fe66650 Fix use of "long long" (manually) in MSVC 2017-09-06 15:02:24 +00:00
dgp ca70072a99 update changes 2017-09-05 15:38:02 +00:00
dgp d9f2bf1d17 merge trunk 2017-09-05 12:41:10 +00:00
jan.nijtmans c2846c0f5c Merge core-8-6-branch to trunk, especially the 1.6.0 -> 1.6.1 renumbering from msgcat 2017-09-04 14:01:45 +00:00
jan.nijtmans a15279ffd1 Make pkgIndex.tcl from msgcat work for Tcl 9.0 (not really necessary, but for consistancy) 2017-09-04 13:59:04 +00:00
jan.nijtmans b74f59a5b4 merge core-8-6-branch 2017-09-04 12:38:14 +00:00
jan.nijtmans e08c86934d Typo's (Thanks to Gustaf Neumann), nothing functional. 2017-09-04 12:37:04 +00:00
dgp a3dfc55957 [0e4d88b650] Allow command overwrite when deletion callback deletes namespace. 2017-09-02 22:10:59 +00:00
dgp e3f7bc2783 [0e4d88b650] Allow command overwrite when deletion callback deletes namespace. 2017-09-02 22:03:03 +00:00
dgp 564b991088 [0e4d88b650] Allow command overwrite when deletion callback deletes namespace. 2017-09-02 21:48:05 +00:00
dgp 0ff317501d merge 8.5 2017-09-02 21:36:57 +00:00
dgp f42f0060be Add test 2017-09-02 21:14:55 +00:00
dgp 3ec5b35deb Similar fix to Tcl_CreateCommand(). 2017-09-02 20:40:44 +00:00
dgp 7afc6b1c17 Tidy up. 2017-09-02 20:17:26 +00:00
dgp ce58cdff9f [Bug 0e4d88b650] First draft fix. Re-resolve namespace after cmd deletion. 2017-09-02 19:35:22 +00:00
jan.nijtmans 4b9e6d92be Merge core-8-6-branch 2017-09-01 13:49:55 +00:00
jan.nijtmans e28f1eece4 Handle Unicode surrogates correctly in Tcl_AppendFormatToObj() and BuildCharSet(). Only makes a difference for TCL_UTF_MAX=4, when surrogates are used in the format string ... highly unlikely corner-case. 2017-09-01 13:48:56 +00:00
dgp 4ce83fdb43 merge trunk 2017-09-01 01:44:09 +00:00
jan.nijtmans ce32fdecb2 Ignore libtommath/doc directory. Add some VS-related makefiles, useful for testing 2017-08-31 15:07:57 +00:00
jan.nijtmans 105a61c09b Merge core-8-6-branch. Remove all git tag information for libtommath, so we don't have useless file differences with every libtommath release. 2017-08-31 13:56:30 +00:00
jan.nijtmans 25b97a7df9 Adapt .fossil-settings/crlf-glob, for 5 libtommath-related files which have crlf ending 2017-08-31 13:43:17 +00:00
jan.nijtmans 432e75210f Undo tag removal (just get libtommath directly from GitHUB), so we don't have useless file changes with every new release 2017-08-31 13:32:52 +00:00
jan.nijtmans 595e613479 (merge-mark core-8-6-branch).
Give state to UtfToUtfProc() and UnicodeToUtfProc() in which the last (intermediate) Tcl_UniChar can be remembered: This way those functions can produce 4-byte UTF-8 sequences built from surrogate pairs if Tcl is compiled with TCL_UTF_MAX=4. For TCL_UTF_MAX=3 and TCL_UTF_MAX=6 this has no effect.
2017-08-31 12:21:43 +00:00
oehhar c0e413055e http state 100 continue handling broken [2a94652ee1] 2017-08-31 09:35:52 +00:00
oehhar 11719ccf59 http state 100 continue handling broken [2a94652ee1] 2017-08-31 09:32:05 +00:00
oehhar 7c7a396fc5 http state 100 continue handling broken [2a94652ee1] 2017-08-31 06:31:05 +00:00
andy 7aafa756ac Cherrypick string.test [de104ef5ab] 2017-08-30 15:29:16 +00:00
jan.nijtmans 6d8b0c705f Tweak libtommath building, such that it doesn't depend on uint64_t any more. (handle mp_word in the same way as mp_digit) 2017-08-30 12:37:50 +00:00
jan.nijtmans faaf0a0fe6 Adapt libtommath's "changes.txt", and other text-files. Adapt bn_mp_read_radix.c to latest libtommaths 'tcl-fixes' commit (harmless for Tcl). 2017-08-30 11:46:33 +00:00
jan.nijtmans 07bcf919d6 Cherry-pick [https://github.com/libtom/libtommath/commit/a0a86c696a7182f8be4b10bb79a1c5c971dc9561]: Merge branch 'tcl-fixes' into develop
Remove many files, which are not used in Tcl.
Modify "changelog.txt", with real release-date of 1.0.1 version
2017-08-30 11:20:19 +00:00
jan.nijtmans f70c0ac860 a few missing bits after previous commit 2017-08-29 21:27:56 +00:00
jan.nijtmans 97d25d7902 Forgot a few files from libtommath 1.0.1 2017-08-29 21:16:54 +00:00
jan.nijtmans c3d5808cdd upgrade to libtommath 1.0.1 (With all Tcl-specific changes - as far as needed - intact) 2017-08-29 20:45:34 +00:00
jan.nijtmans 187a67149b Merge libtommath 1.0.1 final 2017-08-29 20:43:48 +00:00
jan.nijtmans 2d65cb7514 libtommath 1.0.1 2017-08-29 20:39:15 +00:00
jan.nijtmans 92a05930af libtommath 1.0.1 rc2, for test purposes only 2017-08-29 20:25:53 +00:00
jan.nijtmans 1ef0babc38 Fix eol-style (fossil warning: mixed line endings) 2017-08-29 19:55:52 +00:00
jan.nijtmans 92265d56a3 libtommath 1.0.1 rc 2 2017-08-29 19:52:35 +00:00
jan.nijtmans 4264a4f6ab merge-mark 2017-08-29 09:25:17 +00:00
jan.nijtmans a95a7dd265 (cherry-pick): Fix [b50fb21410dababca95baa122964b2e312cb9d8a|b50fb214] : exec redirection to append stdout and stderr to the same file 2017-08-29 09:24:29 +00:00
ferrieux 2e9194366a Fix [b50fb214] : add to 2>> the same O_APPEND that was added to >> back in 2005. 2017-08-24 16:56:51 +00:00
jan.nijtmans ce72664606 merge core-8-6-branch 2017-08-22 12:41:18 +00:00
jan.nijtmans 5210283d10 Fix [d2612a2fa193196787aab33bb57f69b1eef9e30c|d2612a2fa1]: Build breaks because of gcc error. Only use "#pragma GCC diagnostic" if the compiler supports this.
Also re-format tclUnixSock.c without further functional changes.
2017-08-22 12:12:11 +00:00
jan.nijtmans 0eb18d8f91 merge core-8-6-branch 2017-08-18 22:06:54 +00:00
jan.nijtmans 29be40bf89 RFE [http://core.tcl.tk/tk/info/6c0d7aec67|6c0d7aec67]: Better surrogate handling for TCL_UTF_MAX==4. No change when TCL_UTF_MAX==3. (This commit is actually meant for androwish, in order to improve surrogate handling for TCL_UTF_MAX==4) 2017-08-18 21:39:16 +00:00
jan.nijtmans e6336bb806 Merge core-8-6-branch. Update outdated comment (cherry-pick [d5dec2b0514639f44929cbbba9c4130798a8a54a|d5dec2b051]) 2017-08-17 22:50:16 +00:00
jan.nijtmans a04094e9a5 Adopt some harmless changes from the 'irontcl' branch. Left 2 changes behind which I'm not so sure about (but I could be convinced ...). Ticket with explanation would be appreciated! 2017-08-17 22:26:48 +00:00
jan.nijtmans 922d8a71a5 merge core-8-6-branch 2017-08-17 21:56:51 +00:00
jan.nijtmans 13d9910fd6 '#if' -> '#ifdef' in tclUnixPort.h. Suggested by Gustaf Neumann. Reduces the number of gcc warnings, when compiling Tcl with -Wundef. Harmless. 2017-08-17 21:52:42 +00:00
dgp 277f101d7f [f2336c116b] Move pragmas to make gcc happy; it is pickier than clang. 2017-08-14 15:33:03 +00:00
Joe Mistachkin a50a381b04 The 'clean' target should delete the generated 'nmhlp-out.txt' file as well. 2017-08-13 22:31:19 +00:00
Joe Mistachkin e513ec3916 Always define '_USING_V110_SDK71_', in case targeting the pre-Windows 8.x SDKs. 2017-08-13 22:15:30 +00:00
Joe Mistachkin 89fcfadbbf Support cross-compiling Tcl for 'Win32 on ARM' using Visual Studio. 2017-08-13 22:05:25 +00:00
andy 89ce4defb5 Correct longstanding typo in continue man page 2017-08-12 19:45:04 +00:00
dgp ad9bc7297d Add 8.7 -only changes to the changes file. 2017-08-10 19:14:15 +00:00
dgp 0079285837 Update outdated comment. 2017-08-10 17:34:31 +00:00
dgp 8ccd8d10ef Backport [array names -regexp] should support backrefs 2017-08-10 17:03:53 +00:00
dgp aedd652645 Bring changes up to the 8.6.7 release. 2017-08-10 14:56:23 +00:00
dgp 4056a4dc4b Release candidate branch for Tcl 8.7a1. 2017-08-10 14:29:11 +00:00
dgp ffaeeeddaa merge 8.6 2017-08-10 14:17:01 +00:00
dgp c2982f8f62 Silence compiler warning in --disable-threads build 2017-08-10 13:28:48 +00:00
dgp 587206a660 merge mark 2017-08-09 16:38:35 +00:00
dgp 545f5e64be merge mark 2017-08-09 16:29:45 +00:00
dgp 385b618c74 merge release 2017-08-09 16:28:33 +00:00
dgp 3a07a6d26f bump release date 2017-08-09 14:41:19 +00:00
andy df9ea61fbf Cherrypick [527d354828] 2017-08-08 16:45:47 +00:00
andy 5f7ca471e4 Merge core-8-6-branch 2017-08-08 16:42:24 +00:00
andy ac8ddf5d4a Cherrypick [527d354828] 2017-08-08 16:42:05 +00:00
andy 664774bec4 [5bfe3de008]: Modify [source] to set input EOF character but not output EOF character. This avoids having ^Z being appended to the sourced file when it is an always-writable [tcl::chan::variable] in a custom VFS. Tested by adding this same change as a patch to Tcl 8.6.6 in KitCreator because that seems to be the easiest way to get custom VFS capability exposed as script commands. Original problem introduced by [03cdfc3a86] 2000-05-11 00:16:52. 2017-08-07 01:16:39 +00:00
dgp 3cf11a1ce9 merge 8.6 2017-08-04 13:18:37 +00:00
dgp 6da97c627b merge 8.6 2017-08-03 14:40:48 +00:00
dgp 735ca3d3a8 Improved test http-4.16. 2017-08-03 14:39:59 +00:00
dkf 72396a1929 Fix weird hangs in macOS Sierra on some networks. Name resolution timeouts not what we want to test in the http package. 2017-08-02 23:38:20 +00:00
dgp 816674cdb7 update changes 2017-08-01 16:05:13 +00:00
dgp 6bcfd54d3a merge 8.6 2017-07-18 12:58:27 +00:00
jan.nijtmans bb331bf1d8 merge core-8-6-branch 2017-07-17 08:04:57 +00:00
jan.nijtmans b095f046e6 Fix [fb2208172c671f29d60e9ac928d9ded45d01d8b8|fb2208172c]: tclIndex varies across builds from auto_mkindex 2017-07-17 08:04:15 +00:00
jan.nijtmans cee94b0658 Fix [fb2208172c671f29d60e9ac928d9ded45d01d8b8|fb2208172c]: tclIndex varies across builds from auto_mkindex 2017-07-17 08:01:11 +00:00
jan.nijtmans f94f5914a8 merge core-8-6-branch 2017-07-14 14:48:17 +00:00
jan.nijtmans 9dd9b629b3 merge core-8-6-branch 2017-07-13 15:07:39 +00:00
jan.nijtmans 440dbbf620 Fix [293344d4f3]: Regression in SQLite test-suite. Long-standing bug in implementation of TclUtfToUniChar() macro. 2017-07-13 15:06:07 +00:00
jan.nijtmans b1243f2603 Fix [293344d4f3]: Regression in SQLite test-suite. Long-standing bug in implementation of TclUtfToUniChar() macro. 2017-07-13 15:03:27 +00:00
dgp f553fe3b01 merge 8.6 2017-07-06 16:47:21 +00:00
dgp 457f43e25b merge 8.6 2017-07-06 16:40:38 +00:00
dgp 578eeb06bc [adb198c256] Switch to an alternative fix for file join memleaks. 2017-07-06 16:34:56 +00:00
dgp 515f0f32c0 Pull out of the loop a block of code that can only run in first iteration. 2017-07-06 16:00:46 +00:00
dgp bcb9c34521 Alternative fix for memleaks in fs path join machinery. 2017-07-06 15:46:58 +00:00
jan.nijtmans af0816e0ca merge core-8-6-branch 2017-07-03 12:45:44 +00:00
jan.nijtmans ac0fdb5bf8 merge core-8-6-branch 2017-07-03 12:32:38 +00:00
sebres 2ee7180448 resolve 8.6-fork 2017-07-03 09:23:17 +00:00
sebres 5541cc57f7 tclPathObj: fixed TclJoinPath - usage of released object and object leakage.
closes [adb198c256df8c4192838cc3c1112fb2821314e9]
2017-07-03 09:19:41 +00:00
sebres 692ea37c40 tclPathObj: fixed TclJoinPath (backported from 8.6) - usage of released object and object leakage.
closes [adb198c256df8c4192838cc3c1112fb2821314e9]
2017-07-03 09:15:23 +00:00
jan.nijtmans 58dd15c51d merge core-8-6-branch 2017-07-03 08:30:43 +00:00
jan.nijtmans d0996f3402 'inline static' -> 'static inline' and 'INLINE' -> 'inline', for consistancy. 2017-07-03 08:27:42 +00:00
dgp 39356c4079 merge 8.6 2017-06-29 11:19:39 +00:00
jan.nijtmans a646f081bc merge core-8-6-branch 2017-06-28 13:44:23 +00:00
jan.nijtmans 89f6884455 Eliminate use of (expensive) Tcl_UtfToUpper() from "format": Just generate the expected uppercase characters right away from the start. No change in functionality, just code optimization. 2017-06-28 13:32:16 +00:00
dgp 45cf14ed03 Merge 8.6; Bump to TclOO 1.2.0. 2017-06-26 20:00:35 +00:00
dgp 5314bbe0ef update changes 2017-06-26 19:56:37 +00:00
dgp 5b2c81a0f3 merge 8.6 2017-06-26 19:51:48 +00:00
dgp f242dd36bd Bump to TclOO 1.1.0 2017-06-26 19:37:34 +00:00
dgp fb2aa596ab merge 8.6 2017-06-26 19:22:29 +00:00
dgp 5621809b18 [46f801ea5a] Make autoloader less fragile when it cannot manufacture a
known consistent stack trace. Value inconsistency over failure.
2017-06-26 19:18:42 +00:00
dgp 7a8a4b15c4 Try to make good stack trace. Fallback to making not-so-good stack trace.
Stop failing altogether. Test in test suite, not program fragility.
2017-06-26 19:17:12 +00:00
dgp f4615ea166 Test demonstrating autoloader fragility. 2017-06-26 17:30:15 +00:00
jan.nijtmans 2bd7095b87 No longer split tests for longIs32bit/longIs64bit, since the results should be identical 2017-06-23 15:04:44 +00:00
dgp 400f9d27f5 typo fix 2017-06-23 13:11:37 +00:00
dgp 5d68b7ef56 Rewrite the documentation of [regsub -command] so it's not quite such a mess. 2017-06-23 13:09:23 +00:00
dgp ba387de8cd repair broken tests 2017-06-23 12:39:13 +00:00
dgp 70d12096d5 Repair compiler warning about uninitialized value. 2017-06-23 12:28:57 +00:00
jan.nijtmans 3dedad17ed TIP #472 implementation: Add Support for 0d Radix Prefix to Integer Literals 2017-06-23 08:11:42 +00:00
dkf a9c238476a Add [regsub -command] case that wasn't actively tested for. 2017-06-22 22:54:32 +00:00
dkf cfafc391f2 Implement TIP #473: Allow a Defined Target Namespace in oo::copy 2017-06-22 22:03:06 +00:00
dkf 0fbade1cf8 Implement TIP #473: Allow a Defined Target Namespace in oo::copy 2017-06-22 22:02:14 +00:00
dkf dd54301fb6 Documentation correction; issue pointed out by DGP. 2017-06-22 22:00:39 +00:00
dkf 6352a07912 Rebase for final implementation work 2017-06-22 21:55:45 +00:00
dkf 440f85800c Implement TIP #470: Reliable Access to OO Definition Context Object 2017-06-22 21:50:08 +00:00
dkf 2a11adb848 merge trunk 2017-06-22 21:48:48 +00:00
dkf 77f95f38bf Implement TIP #463: Command-Driven Substitutions for regsub 2017-06-22 21:46:40 +00:00
dgp 2710235273 merge trunk 2017-06-22 12:25:35 +00:00
jan.nijtmans 042e99227a merge core-8-6-branch 2017-06-22 08:59:59 +00:00
jan.nijtmans 64c9b509b0 Upgrade all internal character tables to Unicode 10 2017-06-22 08:59:14 +00:00
jan.nijtmans d39c33303f Upgrade all internal character tables to Unicode 10 2017-06-22 08:58:14 +00:00
jan.nijtmans 6454bee19b Merge core-8-6-branch 2017-06-22 08:16:41 +00:00
jan.nijtmans 45175dd264 Add test-cases, testing the legacy behavior of "format %#d" 2017-06-22 08:15:13 +00:00
dgp 9983a05a80 merge 8.6 2017-06-19 17:31:17 +00:00
dkf 20b4459b9d Factor out chunk of non-obvious code in the guts of [oo::define] into one place. 2017-06-18 18:02:34 +00:00
dkf c488b70a47 Factor out chunk of non-obvious code in the guts of [oo::define] into one place. 2017-06-18 14:01:00 +00:00
dgp 952acc3754 Merge 8.6; update changes. 2017-06-16 20:17:33 +00:00
dgp 73f548527a Another reworking, now with comments. 2017-06-16 19:54:57 +00:00
dgp 3923106cf7 Simplify the final loop when we know we're generating strings for all. 2017-06-16 16:23:22 +00:00
dgp 17711009b6 Split loop into two cases for further simplification. 2017-06-16 16:07:48 +00:00
dgp b3bda726c1 Factor out and simplify loop scanning leading known empty values. 2017-06-16 15:51:12 +00:00
dgp e1b4ae0798 Use local variables. 2017-06-16 14:46:56 +00:00
dgp aca86a46ff Rework the logic. Equivalent function. 2017-06-16 14:43:16 +00:00
jan.nijtmans 94754be1d7 merge core-8-6-branch 2017-06-16 14:31:47 +00:00
dgp 9ddb31d522 Extend cases where string rep generation can be prevented. 2017-06-16 12:56:03 +00:00
dgp 6123ba004c Better define the meaning of "first" and "last". 2017-06-16 11:47:46 +00:00
jan.nijtmans 56ea73145f Merge core-8-6-branch.
Fix gcc warning: tclStrToD.c:1180:2: warning: enumeration value ‘ZERO_D’ not handled in switch [-Wswitch]
  switch (acceptState) {
2017-06-15 11:01:58 +00:00
jan.nijtmans bc4db4d40e merge core-8-6-branch 2017-06-15 09:38:09 +00:00
jan.nijtmans 0f0ca3d932 Make panic in TclParseNumber() work when IEEE_FLOATING_POINT is not defined. 2017-06-15 09:13:51 +00:00
dkf 2cdd3134ab [9c058c5803e30d02] Correction to cross linking in dict(n)'s SEE ALSO section. 2017-06-14 21:51:36 +00:00
dkf 107760e1da [9c058c5803e30d02] Correction to cross linking in dict(n)'s SEE ALSO section. 2017-06-14 21:49:08 +00:00
dkf d453cdacec [f2336c116b] Move pragmas to make gcc happy; it is pickier than clang. 2017-06-14 21:42:38 +00:00
jan.nijtmans e8d9fe8ebe Rebase to core-8-6-branch (who told that fossil doesn't know how to rebase ....) 2017-06-14 07:54:51 +00:00
jan.nijtmans 6168d91b0e merge core-8-6-branch 2017-06-13 12:18:16 +00:00
dkf ad34457a54 Add tests and docs. 2017-06-13 11:10:11 +00:00
griffin 2712a556fb Add support of 0d in the format %# conversion flag. Add tests for same. 2017-06-12 14:04:29 +00:00
dgp 3f2eb64de8 Another TclStringCatObjv optimization to delay/avoid string rep generation. 2017-06-08 21:15:25 +00:00
dgp 4b81f6ff43 Don't test the impossible. 2017-06-08 21:10:01 +00:00
dgp cc72d116bd Modernize overflow checks. 2017-06-08 21:05:22 +00:00
dgp 94b635d569 merge trunk 2017-06-08 20:58:10 +00:00
dgp de1c1f0f47 More streamlining 2017-06-08 20:57:06 +00:00
dkf a4f7145579 Make read and write operations on Tcl_Var handles available in tclInt API. 2017-06-08 20:49:51 +00:00
dkf bbcbd64e3b Make read and write operations on Tcl_Var handles available in tclInt API.
(This will be useful for tclquadcode, and it addresses a basic omission in Tcl's API that made working with Tcl_Vars rather more specialized than it was ever really intended to be. However, this also closes off the part of the API that was not reasonably usable by ordinary external code; LVT indices require too deep an entanglement into Tcl's implementation.)
2017-06-08 20:49:04 +00:00
dgp 36d9205d97 More streamlining. 2017-06-08 20:40:45 +00:00
dgp 7673d614a9 pendingPtr == NULL implies (last == first) implies early out 2017-06-08 20:31:47 +00:00
dgp c348386388 Tests for string rep generation suppression 2017-06-08 19:35:05 +00:00
dgp 878c874975 merge trunk 2017-06-08 16:48:33 +00:00
dgp b796f3dee7 When possible delay string rep generation until necessary. 2017-06-08 16:44:51 +00:00
jan.nijtmans dd96539335 merge core-8-6-branch 2017-06-08 12:53:31 +00:00
jan.nijtmans 23ab25afdc Revert part of [95d096e0378b460c6c5168bb55bb2ca8b2fd799e|95d096e037]: Missed the fact that tolower() was optimized for the ASCII case as well, so this was a mistake! 2017-06-08 12:50:00 +00:00
jan.nijtmans 192d5ccf32 merge core-8-6-branch 2017-06-08 12:38:56 +00:00
jan.nijtmans 9ce3a23afe Fix [2738427]: Tcl_NumUtfChars(...) no overflow check. 2017-06-08 12:37:23 +00:00
jan.nijtmans c2e241f3cd Fix [2738427]: Tcl_NumUtfChars(...) no overflow check. 2017-06-08 12:34:08 +00:00
jan.nijtmans 9562ecd7fa tclUtil.c: Use TclUtfToUniChar() in stead of handling ASCII characters separately: This macro already does that.
Add new test-case for Tcl_NumUtfChars(), for a knownBug still to be fixed.
2017-06-08 11:48:13 +00:00
jan.nijtmans 16f3f234e8 Better UTF-8 surrogate handling, only functional when TCL_UTF_MAX>3 2017-06-08 08:26:58 +00:00
jan.nijtmans fbfe81cc7b merge core-8-6-branch 2017-06-07 15:23:11 +00:00
jan.nijtmans 73a3dfdeea Tcl_GetWideIntFromObj() -> TclGetWideIntFromObj(), and minor other simplifications/optimizations. No functional change. 2017-06-07 15:18:38 +00:00
dkf 4cf238f3c3 Expose some of the core variable access APIs.
(Cherrypick from [b4dfc30083])
2017-06-06 17:51:12 +00:00
jan.nijtmans 1b667ef114 merge core-8-6-branch 2017-06-06 14:35:02 +00:00
jan.nijtmans 0aa0da515c Add more test-cases for UTF-8 parser, including test-cases for TCL_UTF_MAX=4 or TCL_UTF_MAX=6 2017-06-06 14:33:16 +00:00
dgp 5667bb5f8e [716b427f76] Optimize TclStringCatObjv when only one non-empty argument. 2017-06-06 13:14:16 +00:00
dgp f8bc248cc3 merge 8.6 2017-06-06 13:03:31 +00:00
dgp b0146fbd50 A few more tweaks to streamline and clarify. 2017-06-06 12:56:37 +00:00
sebres 615771f0b6 makes TclStringCatObjv safe accepting objc = 0 (or 1), then fast exits with new object / first; check-cycles rewritten to be still more faster. 2017-06-06 09:25:00 +00:00
jan.nijtmans 8d78b23f96 merge core-8-6-branch 2017-06-06 09:24:28 +00:00
jan.nijtmans fab7d970af Follow-up to [67aa9a2070]: Use uppercase consistantly, slight optimization in character tests, comment fixes. No change in functionality. 2017-06-06 09:23:23 +00:00
jan.nijtmans 617e92d7b4 [67aa9a2070] Tcl_UtfToUniChar returns single byte for invalid UTF-8 input as documented. 2017-06-06 09:02:28 +00:00
sebres 7edce7686e amend to [eac4656f1e8cf793] (moved to scope where numChars != 0 in Unicode case) 2017-06-06 09:01:18 +00:00
sebres 3d8a0152af small code review: don't need to check length if unchanged + the same case if 0 length 2017-06-06 08:34:00 +00:00
dgp cb68061d12 Optimize TclStringCatObjv() for case when only one argument is non-empty. 2017-06-05 20:03:19 +00:00
dgp 5c4bb0f4e9 Revert performance optimization as first step to providing a refactored one. 2017-06-05 17:57:33 +00:00
dgp f165025992 Merge 8.6; update changes. 2017-06-05 17:22:31 +00:00
dgp 8129d3e1c3 [67aa9a2070] Tcl_UtfToUniChar returns single byte for invalid UTF-8 input as documented. 2017-06-05 17:15:11 +00:00
dgp 3cdd3064b5 [67aa9a2070] Tcl_UtfToUniChar returns single byte for invalid UTF-8 input
as documented.
2017-06-05 16:56:08 +00:00
jan.nijtmans 708ca98ace merge core-8-6-branch 2017-06-02 11:10:28 +00:00
jan.nijtmans f5f03750c8 merge core-8-6-branch 2017-06-02 10:59:19 +00:00
jan.nijtmans 901f58f13b Change refCount field in DictObj from int to size_t. Cherry-picked from "sebres-8-6-clock-speedup-cr1" branch. 2017-06-02 10:34:45 +00:00
jan.nijtmans c688e0737c Fix [67aa9a207037ae67f9014b544c3db34fa732f2dc|67aa9a2070]: Security: Invalid UTF-8 can inject unexpected characters 2017-06-02 08:17:26 +00:00
jan.nijtmans 21dfa74b03 Merge core-8-6-branch. This removes the work currently being done in "sebres-8-6-clock-speedup-cr1" branch, but that will be merged again as soon as the work is done.
All other changes in "trunk" since then (e.g. the INST_STR_CONCAT1 performance improvement, and the removal of SunOS-4) are retained.
2017-06-02 08:12:38 +00:00
jan.nijtmans 3f0e8d6265 Fix [83a3d869722fab9caaae3b6728215fb2507a6f0d|83a3d86972]: tclEpollNotfy.c fails to compile on Linux 2.6.<22 due to unconditionally including <sys/eventfd.h>
Also re-generate regc_locale.c with Unicode 10 tables: previous generation went horribly wrong somehow...
2017-05-31 13:03:54 +00:00
jan.nijtmans aaca962ffe merge core-8-6-branch 2017-05-31 12:06:51 +00:00
jan.nijtmans ca9d6593d1 merge core-8-6-branch (except: the "timerate" command and the clock performance-tests are kept) 2017-05-31 09:19:21 +00:00
sebres bbb13bf577 performance of INST_STR_CONCAT1: closes [716b427f76f8f97a8d9a06043903c53bb2b592c2]: minor optimization in simplest cases,
fixed performance regression of TclStringCatObjv usage from [fc9ed1e751180816384d569101950c1f8c4582ad],
optimizes patterns like "$v[unset v]", "$v[set v {}]" etc.
2017-05-31 08:24:42 +00:00
stu c05da96a35 Unbreak on OpenBSD, again. Put back the old SHLIB_VERSION doings.
On OpenBSD, Tcl's libs will need the extra version numbers probably forever.
There's no point to adding the extra knob.

On OpenBSD, the extra version numbers are used for dependency tracking.
The extra version numbers must be on linkable libs
(code will be linked to them, they have a corresponding .h file).
Loadable libs
(no code will be linked to them, they don't have a corresponding .h file.
Usually a Tcl extension)
don't need the burden (OpenBSD has to track the libs' dependencies)
of the extra version numbers.
Libs that are loadable and linkable are treated as linkable.
I hope that clears things up.
2017-05-31 06:10:46 +00:00
stu 73b3bf53ad Fully remove SunOS-4* from tcl.m4. 2017-05-31 05:39:57 +00:00
sebres e06e0c8625 merge core-8-6-branch (resolves warnings) 2017-05-30 08:49:24 +00:00
sebres b63d3d703e 3-way merge sebres-trunk-clock-speedup / core-8-6-branch (clock speed-up / flightaware Tcl-bounties#4, see RFE [ddc948cff9781daac7ad95a3077b3c1b4f07cf93]) 2017-05-29 21:13:05 +00:00
sebres a59ccae461 merge sebres-8-6-clock-speedup 2017-05-29 20:37:35 +00:00
sebres c922cc78a8 merge core-8-6-branch 2017-05-29 19:44:55 +00:00
jan.nijtmans 3be2fece8c merge core-8-6-branch 2017-05-29 13:14:38 +00:00
griffin 919fc57599 0d in LinkVar 2017-05-28 16:06:29 +00:00
griffin 5badb6535f Implement proposed 0d decimal radix prefix to compliment 0x,0b,0o. 2017-05-27 22:17:21 +00:00
dgp cf0cf6ad90 [19a8c9399d] Plug mem leak in TIP 459 machinery. 2017-05-23 16:00:29 +00:00
jan.nijtmans f3ea991996 Update internal tables to Unicode 10.0. Still in Beta, but to be released soon. 2017-05-23 14:48:58 +00:00
dgp 8a90be9a10 merge 8.6 2017-05-23 13:25:07 +00:00
jan.nijtmans 14949f27a3 Merge core-8-6-branch.
Obsolete a number of systems, which were already obsoleted by TEA: We cannot even create a "battery-included" release any more for those systems.
2017-05-22 09:16:12 +00:00
stu 62e71e311e Fix build on OpenBSD. [82701b94c4] missed a couple of bits.
Tcl/Tk's tcl.m4 isn't identical to TEA's tcl.m4 - be careful!
2017-05-20 12:45:31 +00:00
aspect df664778c8 merge core-8-6-branch 2017-05-19 14:23:06 +00:00
dgp 2f9e40fef1 merge 8.6 2017-05-19 12:53:52 +00:00
jan.nijtmans 34189452da merge core-8-6-branch 2017-05-18 13:27:10 +00:00
jan.nijtmans 2a5ae4319f TIP #458 implementation: Add Support for epoll() and kqueue() in the Notifier 2017-05-18 12:33:15 +00:00
jan.nijtmans dea5aab977 merge core-8-6-branch 2017-05-18 09:24:30 +00:00
sebres c6484de085 merge sebres-8-6-clock-speedup 2017-05-15 18:35:36 +00:00
jan.nijtmans 5d20272000 Don't test Tcl_GetDefaultEncodingDir() any more (which is obsolete), test Tcl_GetEncodingSearchPath() in stead. 2017-05-12 14:31:17 +00:00
sebres a6c79230c3 merge sebres-8-6-clock-speedup 2017-05-11 21:55:12 +00:00
sebres d6de0fb46b reintegrate sebres-8-6-clock-speedup back to sebres-clock-speedup (trunk clock-speedup, 3-way merge) 2017-05-11 19:44:01 +00:00
sebres 6b33bdad03 reintergrate (merge back) "sebres-8-6-timerate" into "sebres-trunk-timerate" 2017-05-11 19:06:53 +00:00
sebres 5171d6b4ef merge trunk (to sebres-trunk-timerate) 2017-05-11 18:53:21 +00:00
dgp 0d218fca03 Merge 8.6; update changes. 2017-05-09 12:12:26 +00:00
jan.nijtmans 2130fd8582 merge core-8-6-branch 2017-05-09 11:31:14 +00:00
jan.nijtmans 1ed15145a6 merge core-8-6-branch 2017-05-09 09:49:23 +00:00
dgp f9d42ebf8c Merge 8.6; update changes. 2017-05-08 16:07:58 +00:00
dgp ca65694482 [6015221f59] Segfault after overflow of [binary] field specifier numeric count. 2017-05-05 19:11:33 +00:00
dgp 0177abb172 merge 8.6 2017-05-04 20:40:15 +00:00
dgp dd53d408e3 merge trunk 2017-05-04 14:51:22 +00:00
jan.nijtmans ce501f14c5 merge core-8-6-branch 2017-05-04 12:28:44 +00:00
jan.nijtmans 63cf0366bd merge core-8-6-branch 2017-05-04 09:51:00 +00:00
jan.nijtmans 52e520be10 merge trunk 2017-05-04 08:55:28 +00:00
jan.nijtmans af718696fb merge core-8-6-branch 2017-05-03 15:28:37 +00:00
jan.nijtmans 709366bdfe slightly better formatting, both in genStubs.tcl and in the generated XXX_DEPRECATED functions. 2017-05-03 10:03:00 +00:00
jan.nijtmans 910200b637 Extend "deprecated" functionality of genStubs.tcl: XX_DEPRECATED macro now accepts a message text, which will be used in the compiler's error message.
Not used (yet) in Tcl.
2017-05-02 12:36:42 +00:00
dgp be831d7ecb Revert the colorful debug garbage mistakenly committed. 2017-05-01 20:29:02 +00:00
dgp 44c544160a [f9fe90d0fa] [file join] normalization. See filesystem-1.52* 2017-05-01 20:25:27 +00:00
jan.nijtmans 799554b1c5 merge core-8-6-branch 2017-05-01 08:22:56 +00:00
fvogel 90ffbb4170 Make trunk compile on MSVC (problem was: warning C4554: '&' : check operator precedence for possible error; use parentheses to clarify precedence) 2017-04-29 14:41:20 +00:00
dgp 77822d9462 merge 8.6; update changes 2017-04-28 18:09:46 +00:00
dgp adfd841d9d [f34cf83dd0] An optimization was being taken in a case where it produced the wrong result, failing to collapse multiple /// into /. Testing on Windows where path expectations may vary would be a good idea, but since this is just an optimization avoidance, I suspect we're ok. 2017-04-28 17:57:34 +00:00
dgp 198407b5ba Test for [f34cf83dd0]. 2017-04-28 17:46:11 +00:00
dgp 83495af5ce silence uninit variable warnings 2017-04-28 14:15:56 +00:00
jan.nijtmans 10ab52081d merge core-8-6-branch 2017-04-28 13:21:26 +00:00
dgp 0b9703a36f [04e26c02c0] Remove useless condition that raises warnings. 2017-04-27 17:26:10 +00:00
dkf e3a9350e58 Start of implementation of TIP #470. 2017-04-27 12:38:21 +00:00
dgp 78a7a5b561 merge 8.6 2017-04-27 12:06:47 +00:00
dkf 04086099d0 [50750c735a] Fix broken test and stop reading uninit-but-allocated memory in zlib channel transform. 2017-04-27 10:51:50 +00:00
jan.nijtmans fbbc93906e Move some variable declarations closer to where they are used. No change in functionality. 2017-04-26 13:48:13 +00:00
dgp 7fde7fcf7b merge 8.6 2017-04-21 12:19:07 +00:00
jan.nijtmans 2f99ece694 merge core-8-6-branch 2017-04-20 14:47:01 +00:00
jan.nijtmans c1b1e9af62 Remove unused functions like TclWinSetSockOpt()/Tcl_DStringTrunc() if compiled with -DTCL_NO_DEPRECATED 2017-04-20 11:44:05 +00:00
gcramer bcbbf6dacf Entry for text.n into exclude_refs_map inserted. 2017-04-20 10:13:02 +00:00
dgp cdccb19d1c merge 8.6 2017-04-19 15:22:22 +00:00
jan.nijtmans 93a924d020 merge core-8-6-branch 2017-04-18 19:02:51 +00:00
dgp a3fdca376e merge 8.6 2017-04-17 12:10:42 +00:00
dgp bfdfb7479d Repair revised tests that failed. 2017-04-17 12:05:02 +00:00
jan.nijtmans 2c5d1036db merge trunk 2017-04-14 13:00:46 +00:00
jan.nijtmans 15b0a7813d merge core-8-6-branch 2017-04-14 09:06:34 +00:00
dgp d2595ccfea Bump TclOO 1.0.6; finish changes. 2017-04-13 16:39:15 +00:00
jan.nijtmans 6be0cf66e0 Translate all \u???? sequences to their UTF-8 counterpart in *.msg files: It is faster during parsing (since no backslash-sequences have to be handled) and makes the msg-files better readable by humans.
TODO: adapt tools/loadICU.tcl to generate UTF-8 in stead of those sequences. This tools seems to be out-of-date a long time already, I couldn't make it run with latest ICU.
2017-04-13 12:20:37 +00:00
dgp 5b059dfd6b Bump msgcat and tcl tests and continue updates to changes. 2017-04-12 20:23:56 +00:00
dgp 1a3c0d9be9 merge 8.6 2017-04-12 19:19:05 +00:00
jan.nijtmans 5ba18ec98d If %llu is considered invalid, it means that "%" TCL_LL_MODIFIER "u" cannot be used Tcl_ObjPrintf(), but only in sprintf(). That's unfortunate, clearly an oversight in TIP #237. Conclusion: new TIP must be written to correct this.
I'll read a TIP and see what case you have, but TCL_LL_MODIFIER was never
meant to play any role in [format] or in Tcl_ObjPrintf(). TCL_LL_MODIFIER
exists to help deal with platform differences in sprintf() calls.

Tcl_ObjPrintf() in contrast ought to be consistent in its behavior
across platforms and should not need such things. If that's false,
then fixes to Tcl_ObjPrintf() are in order.
2017-04-12 13:43:15 +00:00
dgp 62b2b9bf45 Revert recent commit. TIP 237 is clear that %llu is invalid. 2017-04-12 13:15:39 +00:00
jan.nijtmans e006ff39be merge core-8-6-branch 2017-04-12 12:33:07 +00:00
jan.nijtmans 9b4213bb3f merge core-8-6-branch 2017-04-12 09:35:18 +00:00
dgp 1e22d92c69 More changes work 2017-04-11 19:11:27 +00:00
jan.nijtmans cd48f2d313 Remove some unnecessary "struct" definitions and some type casts no longer necessary. No functional changes. 2017-04-11 15:20:07 +00:00
jan.nijtmans 26f98a5e56 unbreak windows build (by previous commit) 2017-04-11 11:30:47 +00:00
dkf bbfc7b1ea2 More minor style fixes. 2017-04-10 16:21:31 +00:00
jan.nijtmans 1e3fa455c9 Merge Harald's "robust-async-connect-tests" branch. Thanks! 2017-04-10 12:39:54 +00:00
dkf d00198bd14 Minor style issues through the socket implementation code. 2017-04-09 16:51:27 +00:00
jan.nijtmans ff4b11441b Minor simplification in tcl.h: For the Tcl_WideAsLong/Tcl_LongAsWide/Tcl_WideAsDouble/Tcl_DoubleAsWide #defines, one set suffices: No need to have two versions depending on TCL_WIDE_INT_IS_LONG. 2017-04-07 15:11:47 +00:00
jan.nijtmans 904733362e Some more (internal) stub entries which can be cleaned up with -DTCL_NO_DEPRECATED, because they are not used any more. 2017-04-06 15:25:44 +00:00
jan.nijtmans 44de3dd8da If compiled with TCL_NO_DEPRECATED, the functions TclpGetDate/TclpLocaltime/TclpGmtime can be removed: They are internal and not used for anything any more. 2017-04-06 11:13:22 +00:00
max 55edd253ff Use a random unused port for the dummy http server to avoid conflicts
with local services running on port 8010.
2017-04-05 14:47:45 +00:00
jan.nijtmans 19719bf57f Fix [4b12ccb3363e81b132e8dbe12aeec596102be1a8|4b12ccb336]: format/scan %llu doesn't work. Also added new test-cases showing the expected behavior. 2017-04-05 09:09:20 +00:00
dgp f3a4ae987d merge 8.6 2017-04-03 16:53:26 +00:00
jan.nijtmans 85397cf893 Merge core-8-6-branch.
Add test-cases showing that the (undocumented) %p format (and also %zd/%td) are harmless, since they are equivalent to other already existing formats.
2017-04-03 12:54:36 +00:00
jan.nijtmans ce7746b49e Since Tcl_AppendPrintfToObj() now understands the %p format, we can use it. Eliminating some internal string buffers. 2017-03-31 14:44:08 +00:00
dgp 5e45fd7662 merge 8.6 2017-03-31 12:30:27 +00:00
jan.nijtmans 354e08673b Extend Tcl_DumpActiveMemory() and related functions for handling 64-bit memory. Only effective with TCL_MEM_DEBUG.
Merge-mark core-8-6-branch (this doesn't bring in any changes)
2017-03-31 09:19:05 +00:00
dkf 810395f913 [900cb0284bc] Ensure that masking pseudo-methods used for export management are not introspectable directly. 2017-03-29 19:07:44 +00:00
dkf 8dfdec39fd Tweak to make tests a little clearer. 2017-03-29 19:05:17 +00:00
jan.nijtmans 0abecbc87d Fix [4768eb5c166a1b923e3472d18d75fdccc1a47513|4768eb5c16]: format-8.20 failure. Since "%q" now is a valid length specifier, we cannot use it any more to test for "bad field specifier" 2017-03-29 14:53:54 +00:00
jan.nijtmans efbb62b5bd In comments and documentation, distinguish between __int64 (a Microsoft 64-bit integer type) and int64_t (C99 equivalent) 2017-03-29 12:19:02 +00:00
jan.nijtmans dd5e309d31 Improve comment on TCL_WIDE_INT_IS_LONG, making it less misleading.
In tclThreadTest.c, allow mainThreadId to be >32 bits.
2017-03-27 13:02:39 +00:00
aspect 0c0b1e1498 Correct this use of isWanted to ensure NO_IMPLEMENTATION methods are not listed (bug [900cb0284bc]) 2017-03-27 13:02:22 +00:00
jan.nijtmans 920aa8280f Supply more C99-compatible (and MSVC) format options: '%p' for pointers, 'z'/'j'/'I' for size_t/intptr_diff, 'j'/'q' for long long. Also add "I32" froom MSVC.
Remove TCL_LL_MODIFIER specified as "L" for Borland: This must be wrong as "L" is meant for long double. Just assume that later Borland compilers are MSVC-compatible.
2017-03-24 15:52:42 +00:00
jan.nijtmans 8a2c820213 Merge trunk 2017-03-24 10:30:56 +00:00
jan.nijtmans ab08379d1c Add TCL_NORETURN attribute to TclpThreadExit() and Tcl_ExitThread() 2017-03-24 09:33:00 +00:00
jan.nijtmans 321cd769b7 Use portable %p modifier in "generic/tclThreadTest.c", in stead of more complicated TCL_LL_MODIFIER. 2017-03-23 16:35:08 +00:00
José Ignacio Marín 91cb892574 merge with trunk 2017-03-23 08:42:38 +00:00
dgp e58e9e1fb9 New(ish) test interp-14.11 was missing its -cleanup. 2017-03-22 19:46:56 +00:00
dgp d7802b428a New(ish) test interp-14.11 was missing its -cleanup. 2017-03-22 19:45:41 +00:00
jan.nijtmans dc25a1a62b Addendum to previous commit: If compiled with TCL_NO_DEPRECATED, remove a few more stub entries which are not used any more. 2017-03-21 09:01:09 +00:00
jan.nijtmans 754b233873 If compiled with TCL_NO_DEPRECATED, remove some more stub entries which are not used any more. 2017-03-20 10:24:11 +00:00
dgp b8d35358ad merge 8.6 2017-03-17 12:51:53 +00:00
jan.nijtmans 5617ad7c18 If Tcl is compiled with -DTCL_NO_DEPRECATED, make sure that iPtr->(resultSpace|appendResult|appendAvl|appendUsed) are not used any more. 2017-03-17 10:57:24 +00:00
dkf 909f1a1a30 Fixes to docs made possible by recent HTML rendering fixes for Tk. 2017-03-16 09:07:19 +00:00
jan.nijtmans f6837a8ef4 redundant end-of-line spacing 2017-03-15 15:15:50 +00:00
Kevin B Kenny 488735e4a2 Compile [clock clicks], [clock microseconds], [clock milliseconds] and [clock seconds]. 2017-03-15 02:40:56 +00:00
Kevin B Kenny a3f676461c Make 'clock' and 'encoding' into compilable ensembles that play with safe interps 2017-03-14 22:22:40 +00:00
dgp daac4e5d34 Different solution to silencing the non-useful valgrind alerts. 2017-03-13 17:03:50 +00:00
jan.nijtmans 6f905e1f0f Eliminate internal use of TclNewBooleanObj()/TclSetBooleanObj()/TclSetIntObj(). Replace Tcl_DbNewBooleanObj() with trivial macro. 2017-03-13 08:38:18 +00:00
dkf 4ccedfaec4 Add back missing significant character 2017-03-13 06:16:45 +00:00
fvogel c010901ea9 Fix error in formatting in info.n 2017-03-12 19:45:00 +00:00
dkf c0bedd810f Add mappings for groff-style character naming, used in experimental branches of Tk. 2017-03-12 18:36:21 +00:00
dgp 57ceb807ca merge 8.6 2017-03-10 17:22:26 +00:00
José Ignacio Marín 5d66bf5a1f Merge the update of TZ info with trunk. 2017-03-10 17:07:44 +00:00
dgp 91d32c4556 Silence valgrind complaints from [representation]. 2017-03-10 16:41:32 +00:00
dgp e9e0f57d92 Dup test name 2017-03-10 15:28:46 +00:00
dgp f090fee89b Start RC branch for Tcl 8.6.7 2017-03-10 15:22:08 +00:00
jan.nijtmans f55296bdf0 minor simplification 2017-03-08 14:50:44 +00:00
jan.nijtmans bed000d72e A few more end-of-line spacings 2017-03-08 14:32:15 +00:00
jan.nijtmans b2181df698 Fix compile error on Cygwin, and double definition of TclUnixWaitForFile() 2017-03-08 13:56:55 +00:00
jan.nijtmans 6469ae095f Re-base to trunk, and get latest code from here: [https://github.com/lalbornoz/tcl/tree/tip458]. Untested. 2017-03-08 13:35:23 +00:00
sebres 636e904b09 merge core-8-6-branch 2017-03-07 18:21:24 +00:00
jan.nijtmans da85dcc288 Fix [e14d152114efee10394a7e0b4b1c0478efff52c5|e14d152114]: bundled zlib documentation is under a potentially non-free license 2017-03-07 11:08:47 +00:00
jan.nijtmans ac3cb936ee Merge core-8-6-branch 2017-03-07 09:47:41 +00:00
dkf 874b8643e0 Add documentation of [regsub -command]. 2017-02-18 18:38:52 +00:00
dkf d18329a21e Testing for some error cases. 2017-02-18 16:24:09 +00:00
dkf 82296abf08 Add more representation smashing testing and a memleak test. 2017-02-18 14:26:34 +00:00
dkf 5772e32729 Stop problems with representation smashes. 2017-02-17 09:20:49 +00:00
dkf 3ef7160d41 Switch to using command prefixes properly. This is quite a bit faster. 2017-02-17 06:08:18 +00:00
dkf efa3ec6939 Proposed implementation of [regsub -command]. 2017-02-11 21:36:36 +00:00
dkf cdb6b73776 Implementation of improved notifier from Lucio Andrés Illanes Albornoz. 2016-11-25 15:44:43 +00:00
jan.nijtmans fad7a0e23d merge trunk 2014-07-31 08:39:50 +00:00
jan.nijtmans da7cc28446 Make sure the "sockettest" command is available even when running socket.test individually. 2014-07-18 10:00:52 +00:00
jan.nijtmans e6e391530f merge trunk 2014-07-18 07:32:43 +00:00
oehhar a0256cda63 Replaced option "-unsupported1" by test command "testsocket debugflags" (thanks Donal, Donald). 2014-07-17 09:53:36 +00:00
oehhar 85daeb5e16 Robust async connect tests by temporarely switching off auto continuation. Ticket [13d3af3ad5] 2014-06-05 19:09:51 +00:00
310 changed files with 23237 additions and 20981 deletions
+5
View File
@@ -3,12 +3,17 @@ compat/zlib/contrib/vstudio/readme.txt
compat/zlib/contrib/vstudio/*/zlib.rc
compat/zlib/win32/*.txt
compat/zlib/win64/*.txt
libtommath/*.dsp
libtommath/*.sln
libtommath/*.vcproj
tools/tcl.hpj.in
tools/tcl.wse.in
win/buildall.vc.bat
win/coffbase.txt
win/makefile.vc
win/rules.vc
win/rules-ext.vc
win/targets.vc
win/tcl.dsp
win/tcl.dsw
win/tcl.hpj.in
+5
View File
@@ -3,12 +3,17 @@ compat/zlib/contrib/vstudio/readme.txt
compat/zlib/contrib/vstudio/*/zlib.rc
compat/zlib/win32/*.txt
compat/zlib/win64/*.txt
libtommath/*.dsp
libtommath/*.sln
libtommath/*.vcproj
tools/tcl.hpj.in
tools/tcl.wse.in
win/buildall.vc.bat
win/coffbase.txt
win/makefile.vc
win/rules.vc
win/rules-ext.vc
win/targets.vc
win/tcl.dsp
win/tcl.dsw
win/tcl.hpj.in
+5 -3
View File
@@ -18,6 +18,7 @@
*/tclsh*
*/tcltest*
*/versions.vc
*/version.vc
html
libtommath/bn.ilg
libtommath/bn.ind
@@ -40,7 +41,8 @@ unix/dltest.marker
unix/tcl.pc
unix/tclIndex
unix/pkgs/*
win/Debug_VC*
win/Release_VC*
win/Debug*
win/Release*
win/pkgs/*
win/tcl.hpj
win/tcl.hpj
win/nmhlp-out.txt
+1 -1
View File
@@ -1,5 +1,5 @@
README: Tcl
This is the Tcl 8.6.6 source distribution.
This is the Tcl 8.6.8 source distribution.
http://sourceforge.net/projects/tcl/files/Tcl/
You can get any source release of Tcl from the URL above.
+132
View File
@@ -8698,3 +8698,135 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich)
2016-07-20 tzdata updated to Olson's tzdata2016f (venkat)
--- Released 8.6.6, July 27, 2016 --- http://core.tcl.tk/tcl/ for details
2016-09-07 (bug)[c09edf] Bad caching with custom resolver (neumann,nijtmans)
2016-09-07 (bug)[4dbdd9] Memleak in test var-8.3 (mr_calvin,porter)
2016-10-03 (bug)[2bf561] Allow empty command as alias target (yorick,nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2016-10-04 (bug)[4d5ae7] Crash in async connects host no address (gahr,fellows)
2016-10-08 (bug)[838e99] treat application/xml as text (gahr,fellows)
=> http 2.8.10
2016-10-11 (bug)[3cc1d9] Thread finalization crash in zippy (neumann)
2016-10-12 (bug)[be003d] Fix [scan 0x1 %b], [scan 0x1 %o] (porter)
2016-10-14 (bug)[eb6b68] Fix stringComp-14.5 (porter)
2016-10-30 (bug)[b26e38] Fix zlib-7.8 (fellows)
2016-10-30 (bug)[1ae129] Fix memleak in [history] destruction (fellows)
2016-11-04 (feature) Provisional Tcl 9 support in msgcat and tcltest (nijtmans)
=> msgcat 1.6.1
=> tcltest 2.4.1
2016-11-04 (bug)[824752] Crash in Tcl_ListObjReplace() (gahr,porter)
2016-11-11 (bug)[79614f] invalidate VFS mounts on sytem encoding change (yorick)
2016-11-14 OSX: End panic() as legacy support macro; system conflicts (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2016-11-15 (bug) TclOO fix stops crash mixing Itcl and snit (fellows)
2016-11-17 (update) Reconcile libtommath updates; purge unused files (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2017-01-09 (bug)[b87ad7] Repair drifts in timer clock (sebres)
2017-01-17 (update) => zlib 1.2.11 (nijtmans)
2017-01-31 (bug)[39f630] Revise Tcl_LinkVar to tolerate some prefixes (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2017-02-01 (bug)[d0f7ba] Improper NAN optimization. expr-22.1[01] (aspect)
2017-02-26 (bug)[25842c] zlib stream finalization (aspect)
2017-03-07 (deprecate) Remove unmaintained makefile.bc file (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2017-03-14 (enhancement) [clock] and [encoding] are now ensembles (kenny)
2017-03-15 (enhancement) several [clock] subcommands bytecoded (kenny)
2017-03-23 tzdata updated to Olson's tzdata2017b (jima)
2017-03-29 (bug)[900cb0] Fix OO unexport introspection (napier)
2017-04-12 (bug)[42202b] Nesting imbalance in coro injection (nadkarni,sebres)
2017-04-18 (bug)[bc4322] http package support for safe interps (nash,nijtmans)
2017-04-28 (bug)[f34cf8] [file join a //b] => /b (neumann,porter)
2017-05-01 (bug)[8bd13f] Windows threads and pipes (sebres,nijtmans)
2017-05-01 (bug)[f9fe90] [file join //a b] EIAS violation (aspect,porter)
2017-05-04 (bug) Make test filesystem-1.52 pass on Windows (nijtmans)
2017-05-05 (bug)[601522] [binary] field spec overflow -> segfault (porter)
2017-05-08 (bug)[6ca52a] http memleak handling keep-alive (aspect,nijtmans)
=> http 2.8.11
2017-05-29 (bug)[a3fb33] crash in [lsort] on long lists (sebres)
2017-06-05 (bug)[67aa9a] Tcl_UtfToUniChar() revised handling invalid UTF-8 (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2017-06-08 (bug)[2738427] Tcl_NumUtfChars() corner case utf-4.9 (nijtmans)
2017-06-22 (update) Update Unicode data to 10.0 (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2017-06-22 (TIP 473) Let [oo::copy] specify target namespace (fellows)
2017-06-26 (bug)[46f801] Repair autoloader fragility (porter)
2017-07-06 (bug)[adb198] Plug memleak in TclJoinPath (sebres,porter)
2017-07-17 (bug)[fb2208] Repeatable tclIndex generation (wiedemann,nijtmans)
--- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tcl/ for details
2017-08-10 [array names -regexp] supports backrefs (goth)
2017-08-10 Fix gcc build failures due to #pragma placement (cassoff,fellows)
2017-08-29 (bug)[b50fb2] exec redir append stdout and stderr to file (coulter)
2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann)
=> http 2.8.12
2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter)
2017-10-19 (bug)[1a5655] [info * methods] includes mixins (fellows)
2017-10-23 tzdata updated to Olson's tzdata2017c (jima)
2017-10-24 (bug)[fc1409] segfault in method cloning, oo-15.15 (coulter,fellows)
2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS (werner)
2017-11-08 (bug)[3298012] Stop crash when hash tables overflow 32 bits (porter)
2017-11-14 (bug)[5d6de6] Close failing case of [package prefer stable] (kupries)
2017-11-17 (bug)[fab924] Fix misleading [load] message on Windows (oehlmann)
2017-12-05 (bug)[4f6a1e] Crash when ensemble map and list are same (sebres)
2017-12-06 (bug)[ce3a21] file normalize failure when tail is empty (porter)
2017-12-08 (new)[TIP 477] nmake build system reform (nadkarni)
2017-12-19 (bug)[586e71] EvalObjv exception handling at level #0 (sebres,porter)
--- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tcl/ for details
-4
View File
@@ -260,10 +260,6 @@ Windows-only convenience
functions for converting between UTF-8 and Windows strings
based on the TCHAR type which is by convention
a Unicode character on Windows NT.
These functions are essentially wrappers around
\fBTcl_UtfToExternalDString\fR and
\fBTcl_ExternalToUtfDString\fR that convert to and from the
Unicode encoding.
.PP
\fBTcl_GetEncodingName\fR is roughly the inverse of \fBTcl_GetEncoding\fR.
Given an \fIencoding\fR, the return value is the \fIname\fR argument that
+4 -4
View File
@@ -176,10 +176,10 @@ it is faster to execute the script directly.
.TP 23
\fBTCL_EVAL_GLOBAL\fR
.
If this flag is set, the script is processed at global level. This
means that it is evaluated in the global namespace and its variable
context consists of global variables only (it ignores any Tcl
procedures that are active).
If this flag is set, the script is evaluated in the global namespace instead of
the current namespace and its variable context consists of global variables
only (it ignores any Tcl procedures that are active).
.\" TODO: document TCL_EVAL_INVOKE and TCL_EVAL_NOERR.
.SH "MISCELLANEOUS DETAILS"
.PP
+1 -1
View File
@@ -4,7 +4,7 @@
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\"
.TH Tcl_GetInt 3 "" Tcl "Tcl Library Procedures"
.so man.macros
.BS
+76 -168
View File
@@ -1,5 +1,6 @@
.\"
.\" Copyright (c) 2008 by Kevin B. Kenny.
.\" Copyright (c) 2018 by Nathan Coulter.
.\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -38,43 +39,39 @@ void
.SH ARGUMENTS
.AS Tcl_CmdDeleteProc *interp in
.AP Tcl_Interp *interp in
Interpreter in which to create or evaluate a command.
The relevant Interpreter.
.AP char *cmdName in
Name of a new command to create.
Name of the command to create.
.AP Tcl_ObjCmdProc *proc in
Implementation of a command that will be called whenever \fIcmdName\fR
is invoked as a command in the unoptimized way.
Called in order to evaluate a command. Is often just a small wrapper that uses
\fBTcl_NRCallObjProc\fR to call \fInreProc\fR using a new trampoline. Behaves
in the same way as the \fIproc\fR argument to \fBTcl_CreateObjCommand\fR(3)
(\fIq.v.\fR).
.AP Tcl_ObjCmdProc *nreProc in
Implementation of a command that will be called whenever \fIcmdName\fR
is invoked and requested to conserve the C stack.
Called instead of \fIproc\fR when a trampoline is already in use.
.AP ClientData clientData in
Arbitrary one-word value that will be passed to \fIproc\fR, \fInreProc\fR,
\fIdeleteProc\fR and \fIobjProc\fR.
Arbitrary one-word value passed to \fIproc\fR, \fInreProc\fR, \fIdeleteProc\fR
and \fIobjProc\fR.
.AP Tcl_CmdDeleteProc *deleteProc in/out
Procedure to call before \fIcmdName\fR is deleted from the interpreter.
This procedure allows for command-specific cleanup. If \fIdeleteProc\fR
is \fBNULL\fR, then no procedure is called before the command is deleted.
Called before \fIcmdName\fR is deleted from the interpreter, allowing for
command-specific cleanup. May be NULL.
.AP int objc in
Count of parameters provided to the implementation of a command.
Number of items in \fIobjv\fR.
.AP Tcl_Obj **objv in
Pointer to an array of Tcl values. Each value holds the value of a
single word in the command to execute.
Words in the command.
.AP Tcl_Obj *objPtr in
Pointer to a Tcl_Obj whose value is a script or expression to execute.
A script or expression to evaluate.
.AP int flags in
ORed combination of flag bits that specify additional options.
\fBTCL_EVAL_GLOBAL\fR is the only flag that is currently supported.
.\" TODO: This is a lie. But kbk didn't grasp TCL_EVAL_INVOKE and
.\" TCL_EVAL_NOERR well enough to document them.
As described for \fITcl_EvalObjv\fR.
.PP
.AP Tcl_Command cmd in
Token for a command that is to be used instead of the currently
executing command.
Token to use instead of one derived from the first word of \fIobjv\fR in order
to evaluate a command.
.AP Tcl_Obj *resultPtr out
Pointer to an unshared Tcl_Obj where the result of expression
evaluation is written.
Pointer to an unshared Tcl_Obj where the result of the evaluation is stored if
the return code is TCL_OK.
.AP Tcl_NRPostProc *postProcPtr in
Pointer to a function that will be invoked when the command currently
executing in the interpreter designated by \fIinterp\fR completes.
A function to push.
.AP ClientData data0 in
.AP ClientData data1 in
.AP ClientData data2 in
@@ -84,98 +81,51 @@ to the function designated by \fIpostProcPtr\fR when it is invoked.
.BE
.SH DESCRIPTION
.PP
This series of C functions provides an interface whereby commands that
are implemented in C can be evaluated, and invoke Tcl commands scripts
and scripts, without consuming space on the C stack. The non-recursive
evaluation is done by installing a \fItrampoline\fR, a small piece of
code that invokes a command or script, and then executes a series of
callbacks when the command or script returns.
These functions provide an interface to the function stack that an interpreter
iterates through to evaluate commands. The routine behind a command is
implemented by an initial function and any additional functions that the
routine pushes onto the stack as it progresses. The interpreter itself pushes
functions onto the stack to react to the end of a routine and to exercise other
forms of control such as switching between in-progress stacks and the
evaluation of other scripts at additional levels without adding frames to the C
stack. To execute a routine, the initial function for the routine is called
and then a small bit of code called a \fItrampoline\fR iteratively takes
functions off the stack and calls them, using the value of the last call as the
value of the routine.
.PP
The \fBTcl_NRCreateCommand\fR function creates a Tcl command in the
interpreter designated by \fIinterp\fR that is prepared to handle
nonrecursive evaluation with a trampoline. The \fIcmdName\fR argument
gives the name of the new command. If \fIcmdName\fR contains any
namespace qualifiers, then the new command is added to the specified
namespace; otherwise, it is added to the global namespace. \fIproc\fR
gives the procedure that will be called when the interpreter wishes to
evaluate the command in an unoptimized manner, and \fInreProc\fR is
the procedure that will be called when the interpreter wishes to
evaluate the command using a trampoline. \fIdeleteProc\fR is a
function that will be called before the command is deleted from the
interpreter. When any of the three functions is invoked, it is passed
the \fIclientData\fR parameter.
\fBTcl_NRCallObjProc\fR calls \fInreProc\fR using a new trampoline.
.PP
\fBTcl_NRCreateCommand\fR deletes any existing command
\fIname\fR already associated with the interpreter
(however see below for an exception where the existing command
is not deleted).
It returns a token that may be used to refer
to the command in subsequent calls to \fBTcl_GetCommandName\fR.
If \fBTcl_NRCreateCommand\fR is called for an interpreter that is in
the process of being deleted, then it does not create a new command,
does not delete any existing command of the same name, and returns NULL.
\fBTcl_NRCreateCommand\fR, an alternative to \fBTcl_CreateObjCommand\fR,
resolves \fIcmdName\fR, which may contain namespace qualifiers, relative to the
current namespace, creates a command by that name, and returns a token for the
command which may be used in subsequent calls to \fBTcl_GetCommandName\fR.
Except for a few cases noted below any existing command by the same name is
first deleted. If \fIinterp\fR is in the process of being deleted
\fBTcl_NRCreateCommand\fR does not create any command, does not delete any
command, and returns NULL.
.PP
The \fIproc\fR and \fInreProc\fR function are expected to conform to
all the rules set forth for the \fIproc\fR argument to
\fBTcl_CreateObjCommand\fR(3) (\fIq.v.\fR).
\fBTcl_NREvalObj\fR pushes a function that is like \fBTcl_EvalObjEx\fR but
consumes no space on the C stack.
.PP
When a command that is written to cope with evaluation via trampoline
is invoked without a trampoline on the stack, it will usually respond
to the invocation by creating a trampoline and calling the
trampoline-enabled implementation of the same command. This call is done by
means of \fBTcl_NRCallObjProc\fR. In the call to
\fBTcl_NRCallObjProc\fR, the \fIinterp\fR, \fIclientData\fR,
\fIobjc\fR and \fIobjv\fR parameters should be the same ones that were
passed to \fIproc\fR. The \fInreProc\fR parameter should designate the
trampoline-enabled implementation of the command.
\fBTcl_NREvalObjv\fR pushes a function that is like \fBTcl_EvalObjv\fR but
consumes no space on the C stack.
.PP
\fBTcl_NREvalObj\fR arranges for the script contained in \fIobjPtr\fR
to be evaluated in the interpreter designated by \fIinterp\fR after
the current command (which must be trampoline-enabled) returns. It is
the method by which a command may invoke a script without consuming
space on the C stack. Similarly, \fBTcl_NREvalObjv\fR arranges to
invoke a single Tcl command whose words have already been separated
and substituted. The \fIobjc\fR and \fIobjv\fR parameters give the
words of the command to be evaluated when execution reaches the
trampoline.
\fBTcl_NRCmdSwap\fR is like \fBTcl_NREvalObjv\fR, but uses \fIcmd\fR, a token
previously returned by \fBTcl_CreateObjCommand\fR or
\fBTcl_GetCommandFromObj\fR, instead of resolving the first word of \fIobjv\fR.
. The name of this command must be the same as \fIobjv[0]\fR.
.PP
\fBTcl_NRCmdSwap\fR allows for trampoline evaluation of a command whose
resolution is already known. The \fIcmd\fR parameter gives a
\fBTcl_Command\fR token (returned from \fBTcl_CreateObjCommand\fR or
\fBTcl_GetCommandFromObj\fR) identifying the command to be invoked in
the trampoline; this command must match the word in \fIobjv[0]\fR.
The remaining arguments are as for \fBTcl_NREvalObjv\fR.
\fBTcl_NRExprObj\fR pushes a function that evaluates \fIobjPtr\fR as an
expression in the same manner as \fBTcl_ExprObj\fR but without consuming space
on the C stack.
.PP
\fBTcl_NREvalObj\fR, \fBTcl_NREvalObjv\fR and \fBTcl_NRCmdSwap\fR
all accept a \fIflags\fR parameter, which is an OR-ed-together set of
bits to control evaluation. At the present time, the only supported flag
available to callers is \fBTCL_EVAL_GLOBAL\fR.
.\" TODO: Again, this is a lie. Do we want to explain TCL_EVAL_INVOKE
.\" and TCL_EVAL_NOERR?
If the \fBTCL_EVAL_GLOBAL\fR flag is set, the script or command is
evaluated in the global namespace. If it is not set, it is evaluated
in the current namespace.
All of the functions return \fBTCL_OK\fR if the evaluation of the script,
command, or expression has been scheduled successfully. Otherwise (for example
if the command name cannot be resolved), they return \fBTCL_ERROR\fR and store
a message as the interpreter's result.
.PP
\fBTcl_NRExprObj\fR arranges for the expression contained in \fIobjPtr\fR
to be evaluated in the interpreter designated by \fIinterp\fR after
the current command (which must be trampoline-enabled) returns. It is
the method by which a command may evaluate a Tcl expression without consuming
space on the C stack. The argument \fIresultPtr\fR is a pointer to an
unshared Tcl_Obj where the result of expression evaluation is to be written.
If expression evaluation returns any code other than TCL_OK, the
\fIresultPtr\fR value is left untouched.
.PP
All of the routines return \fBTCL_OK\fR if command or expression invocation
has been scheduled successfully. If for any reason the scheduling cannot
be completed (for example, if the interpreter is unable to find
the requested command), they return \fBTCL_ERROR\fR with an
appropriate message left in the interpreter's result.
.PP
\fBTcl_NRAddCallback\fR arranges to have a C function called when the
current trampoline-enabled command in the Tcl interpreter designated
by \fIinterp\fR returns. The \fIpostProcPtr\fR argument is a pointer
to the callback function, which must have arguments and return value
consistent with the \fBTcl_NRPostProc\fR data type:
\fBTcl_NRAddCallback\fR pushes \fIpostProcPtr\fR. The signature for
\fBTcl_NRPostProc\fR is:
.PP
.CS
typedef int
@@ -185,25 +135,13 @@ typedef int
int \fIresult\fR);
.CE
.PP
When the trampoline invokes the callback function, the \fIdata\fR
parameter will point to an array containing the four one-word
quantities that were passed to \fBTcl_NRAddCallback\fR in the
\fIdata0\fR through \fIdata3\fR parameters. The Tcl interpreter will
be designated by the \fIinterp\fR parameter, and the \fIresult\fR
parameter will contain the result (\fBTCL_OK\fR, \fBTCL_ERROR\fR,
\fBTCL_RETURN\fR, \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR) that was
returned by the command evaluation. The callback function is expected,
in turn, either to return a \fIresult\fR to control further evaluation.
.PP
Multiple \fBTcl_NRAddCallback\fR invocations may request multiple
callbacks, which may be to the same or different callback
functions. If multiple callbacks are requested, they are executed in
last-in, first-out order, that is, the most recently requested
callback is executed first.
\fIdata\fR is a pointer to an array containing \fIdata0\fR through \fIdata3\fR.
\fIresult\fR is the value returned by the previous function implementing part
the routine.
.SH EXAMPLE
.PP
The usual pattern for Tcl commands that invoke other Tcl commands
is something like:
The following command uses \fBTcl_EvalObjEx\fR, which consumes space on the C
stack, to evalute a script:
.PP
.CS
int
@@ -228,28 +166,17 @@ int
\fITheCmdOldObjProc\fR, clientData, TheCmdDeleteProc);
.CE
.PP
To enable a command like this one for trampoline-based evaluation,
it must be split into three pieces:
.IP \(bu
A non-trampoline implementation, \fITheCmdNewObjProc\fR,
which will simply create a trampoline
and invoke the trampoline-based implementation.
.IP \(bu
A trampoline-enabled implementation, \fITheCmdNRObjProc\fR. This
function will perform the initialization, request that the trampoline
call the postprocessing routine after command evaluation, and finally,
request that the trampoline call the inner command.
.IP \(bu
A postprocessing routine, \fITheCmdPostProc\fR. This function will
perform the postprocessing formerly done after the return from the
inner command in \fITheCmdObjProc\fR.
.PP
The non-trampoline implementation is simple and stylized, containing
a single statement:
To avoid consuming space on the C stack, \fITheCmdOldObjProc\fR is renamed to
\fITheCmdNRObjProc\fR and the postprocessing step is split into a separate
function, \fITheCmdPostProc\fR, which is pushed onto the function stack.
\fITcl_EvalObjEx\fR is replaced with \fITcl_NREvalObj\fR, which uses a
trampoline instead of consuming space on the C stack. A new version of
\fITheCmdOldObjProc\fR is just a a wrapper that uses \fBTcl_NRCallObjProc\fR to
call \fITheCmdNRObjProc\fR:
.PP
.CS
int
\fITheCmdNewObjProc\fR(
\fITheCmdOldObjProc\fR(
ClientData clientData,
Tcl_Interp *interp,
int objc,
@@ -260,9 +187,6 @@ int
}
.CE
.PP
The trampoline-enabled implementation requests postprocessing,
and returns to the trampoline requesting command evaluation.
.PP
.CS
int
\fITheCmdNRObjProc\fR
@@ -284,9 +208,6 @@ int
}
.CE
.PP
The postprocessing procedure does whatever the original command did
upon return from the inner evaluation.
.PP
.CS
int
\fITheCmdNRPostProc\fR(
@@ -303,26 +224,13 @@ int
}
.CE
.PP
If \fItheCommand\fR is a command that results in multiple commands or
scripts being evaluated, its postprocessing routine may schedule
additional postprocessing and then request another command evaluation
by means of \fBTcl_NREvalObj\fR or one of the other evaluation
routines. Looping and sequencing constructs may be implemented in this way.
Any function comprising a routine can push other functions, making it possible
implement looping and sequencing constructs using the function stack.
.PP
Finally, to install a trampoline-enabled command in the interpreter,
\fBTcl_NRCreateCommand\fR is used in place of
\fBTcl_CreateObjCommand\fR. It accepts two command procedures instead
of one. The first is for use when no trampoline is yet on the stack,
and the second is for use when there is already a trampoline in place.
.PP
.CS
\fBTcl_NRCreateCommand\fR(interp, "theCommand",
\fITheCmdNewObjProc\fR, \fITheCmdNRObjProc\fR, clientData,
TheCmdDeleteProc);
.CE
.SH "SEE ALSO"
Tcl_CreateCommand(3), Tcl_CreateObjCommand(3), Tcl_EvalObjEx(3), Tcl_GetCommandFromObj(3), Tcl_ExprObj(3)
.SH KEYWORDS
stackless, nonrecursive, execute, command, global, value, result, script
.SH COPYRIGHT
Copyright (c) 2008 by Kevin B. Kenny
Copyright (c) 2008 by Kevin B. Kenny.
Copyright (c) 2018 by Nathan Coulter.
+1 -1
View File
@@ -257,7 +257,7 @@ The \fBincr\fR command first gets an integer from \fIx\fR's value
by calling \fBTcl_GetIntFromObj\fR.
This procedure checks whether the value is already an integer value.
Since it is not, it converts the value
by setting the value's \fIinternalRep.longValue\fR member
by setting the value's internal representation
to the integer \fB123\fR
and setting the value's \fItypePtr\fR
to point to the integer Tcl_ObjType structure.
+2 -2
View File
@@ -54,9 +54,9 @@ is called, Tcl will take care of memory management.
.PP
The second triplet stores the snapshot of only the interpreter
result (not its complete state) in memory allocated by the caller.
These routines are passed a pointer to a \fBTcl_SavedResult\fR structure
These routines are passed a pointer to \fBTcl_SavedResult\fR
that is used to store enough information to restore the interpreter result.
This structure can be allocated on the stack of the calling
\fBTcl_SavedResult\fR can be allocated on the stack of the calling
procedure. These routines do not save the state of any error
information in the interpreter (e.g. the \fB\-errorcode\fR or
\fB\-errorinfo\fR return options, when an error is in progress).
+1 -1
View File
@@ -33,7 +33,7 @@ int
.SH ARGUMENTS
.AS char *str in/out
.AP int ch in
The Tcl_UniChar to be converted.
The Unicode character to be converted.
.AP char *str in/out
Pointer to UTF-8 string to be converted in place.
.BE
+1 -4
View File
@@ -53,14 +53,11 @@ The Tcl_UniChar to be examined.
.SH DESCRIPTION
.PP
All of the routines described examine Tcl_UniChars and return a
All of the routines described examine Unicode characters and return a
boolean value. A non-zero return value means that the character does
belong to the character class associated with the called routine. The
rest of this document just describes the character classes associated
with the various routines.
.PP
Note: A Tcl_UniChar is a Unicode character represented as an unsigned,
fixed-size quantity.
.SH "CHARACTER CLASSES"
.PP
+1 -1
View File
@@ -77,7 +77,7 @@ int
Buffer in which the UTF-8 representation of the Tcl_UniChar is stored. At most
\fBTCL_UTF_MAX\fR bytes are stored in the buffer.
.AP int ch in
The Tcl_UniChar to be converted or examined.
The Unicode character to be converted or examined.
.AP Tcl_UniChar *chPtr out
Filled with the Tcl_UniChar represented by the head of the UTF-8 string.
.AP "const char" *src in
+15 -37
View File
@@ -87,15 +87,6 @@ slowing its clock by a tiny fraction for some minutes until it is
back in sync with UTC; its data model does not represent minutes that
have 59 or 61 seconds.
.TP
\fI\-now\fR
Instead of \fItimeVal\fR a non-integer option \fI\-now\fR can be used as
replacement for today, which is simply interpolated to the runt-time as value
of \fBclock seconds\fR. For example:
.sp
\fBclock format -now -f %a; # current day of the week\fR
.sp
\fBclock add -now 1 month; # next month\fR
.TP
\fIunit\fR
One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR,
\fBdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR, or
@@ -462,6 +453,19 @@ If this situation occurs, the first occurrence of the time is chosen.
(For this reason, it is wise to have the input string contain the
time zone when converting local times. This caveat does not apply to
UTC times.)
.PP
If the interpretation of the groups yields an impossible time because
a field is out of range, enough of that field's unit will be added to
or subtracted from the time to bring it in range. Thus, if attempting to
scan or format day 0 of the month, one day will be subtracted from day
1 of the month, yielding the last day of the previous month.
.PP
If the interpretation of the groups yields an impossible time because
a Daylight Saving Time change skips over that time, or an ambiguous
time because a Daylight Saving Time change skips back so that the clock
observes the given time twice, and no time zone specifier (\fB%z\fR
or \fB%Z\fR) is present in the format, the time is interpreted as
if the clock had not changed.
.SH "FORMAT GROUPS"
.PP
The following format groups are recognized by the \fBclock scan\fR and
@@ -537,12 +541,6 @@ abbreviation appropriate to the current locale, and uses it to fix
whether \fB%Y\fR refers to years before or after Year 1 of the
Common Era.
.TP
\fB%Es\fR
This affects similar to \fB%s\fR, but in opposition to \fB%s\fR it parses
or formats local seconds (not the posix seconds).
Because \fB%s\fR has the same precedence as \fB%s\fR (uniquely determines
a point in time), it overrides all other input formats.
.TP
\fB%Ex\fR
On output, produces a locale-dependent representation of the date
in the locale's alternative calendar. On input, matches
@@ -737,15 +735,13 @@ week number \fB%V\fR; programs should use \fB%G\fR for that purpose.
On output, produces the current time zone, expressed in hours and
minutes east (+hhmm) or west (\-hhmm) of Greenwich. On input, accepts a
time zone specifier (see \fBTIME ZONES\fR below) that will be used to
determine the time zone (this token is optionally applicable on input,
so the value is not mandatory and can be missing in input).
determine the time zone.
.TP
\fB%Z\fR
On output, produces the current time zone's name, possibly
translated to the given locale. On input, accepts a time zone
specifier (see \fBTIME ZONES\fR below) that will be used to determine the
time zone (token is also like \fB%z\fR optionally applicable on input).
This option should, in general, be used on input only when
time zone. This option should, in general, be used on input only when
parsing RFC822 dates. Other uses are fraught with ambiguity; for
instance, the string \fBBST\fR may represent British Summer Time or
Brazilian Standard Time. It is recommended that date/time strings for
@@ -944,24 +940,6 @@ used. Finally, a correction is applied so that the correct hour of
the day is produced after allowing for daylight savings time
differences and the correct date is given when going from the end
of a long month to a short month.
.PP
The precedence of the applying of single tokens resp. which sequence will be
used by calculating of the time is complex, e. g. heavily dependent on the
precision of type of the token.
.sp
In example below the second date-string contains "next January", therefore
it results in next year but in January. And third date-string besides "January"
contains also additionally "Fri", so it results in the nearest Friday.
Thus both win before "385 days" resp. make it more precise, because of higher
precision of this token types.
.CS
% clock format [clock scan "5 years 18 months 385 days" -base 0 -gmt 1] -gmt 1
Thu Jul 21 00:00:00 GMT 1977
% clock format [clock scan "5 years 18 months 385 days next January" -base 0 -gmt 1] -gmt 1
Sat Jan 21 00:00:00 GMT 1978
% clock format [clock scan "5 years 18 months 385 days next January Fri" -base 0 -gmt 1] -gmt 1
Fri Jan 27 00:00:00 GMT 1978
.CE
.SH "SEE ALSO"
msgcat(n)
.SH KEYWORDS
+16 -6
View File
@@ -14,7 +14,7 @@ oo::copy \- create copies of objects and classes
.nf
package require TclOO
\fBoo::copy\fI sourceObject \fR?\fItargetObject\fR?
\fBoo::copy\fI sourceObject \fR?\fItargetObject\fR? ?\fItargetNamespace\fR?
.fi
.BE
.SH DESCRIPTION
@@ -22,11 +22,21 @@ package require TclOO
The \fBoo::copy\fR command creates a copy of an object or class. It takes the
name of the object or class to be copied, \fIsourceObject\fR, and optionally
the name of the object or class to create, \fItargetObject\fR, which will be
resolved relative to the current namespace if not an absolute qualified name.
If \fItargetObject\fR is omitted, a new name is chosen. The copied object will
be of the same class as the source object, and will have all its per-object
methods copied. If it is a class, it will also have all the class methods in
the class copied, but it will not have any of its instances copied.
resolved relative to the current namespace if not an absolute qualified name
and
.VS TIP473
\fItargetNamespace\fR which is the name of the namespace that will hold the
internal state of the object (\fBmy\fR command, etc.); it \fImust not\fR
refer to an existing namespace.
If either \fItargetObject\fR or \fItargetNamespace\fR is omitted or is given
as the empty string, a new name is chosen. Names, unless specified, are
chosen with the same algorithm used by the \fBnew\fR method of
\fBoo::class\fR.
.VE TIP473
The copied object will be of the same class as the source object, and will have
all its per-object methods copied. If it is a class, it will also have all the
class methods in the class copied, but it will not have any of its instances
copied.
.PP
.VS
After the \fItargetObject\fR has been created and all definitions of its
+1 -1
View File
@@ -50,7 +50,7 @@ being constructed. Within the constructor, the \fBnext\fR command should be
used to call the superclasses' constructors. If \fIbodyScript\fR is the empty
string, the constructor will be deleted.
.TP
\fBdeletemethod\fI name\fR ?\fIname ...\fR
\fBdeletemethod\fI name\fR ?\fIname ...\fR?
.
This deletes each of the methods called \fIname\fR from a class. The methods
must have previously existed in that class. Does not affect the superclasses
+1 -1
View File
@@ -437,7 +437,7 @@ puts $foo
# prints: \fIa b foo {a b} bar 2 baz 3\fR
.CE
.SH "SEE ALSO"
append(n), array(n), foreach(n), mapeach(n), incr(n), list(n), lappend(n), set(n)
append(n), array(n), foreach(n), incr(n), list(n), lappend(n), lmap(n), set(n)
.SH KEYWORDS
dictionary, create, update, lookup, iterate, filter, map
'\" Local Variables:
+17
View File
@@ -217,6 +217,19 @@ information is instead sent to the console, if one is present, or is
discarded.
.RS
.PP
Note that the current escape resp. quoting of arguments for windows works only
with executables using CommandLineToArgv, CRT-library or similar, as well as
with the windows batch files (excepting the newline, see below).
Although it is the common escape algorithm, but, in fact, the way how the
executable parses the command-line (resp. splits it into single arguments)
is decisive.
.PP
Unfortunately, there is currently no way to supply newline character within
an argument to the batch files (\fB.cmd\fR or \fB.bat\fR) or to the command
processor (\fBcmd.exe /c\fR), because this causes truncation of command-line
(also the argument chain) on the first newline character.
But it works properly with an executable (using CommandLineToArgv, etc).
.PP
The Tk console text widget does not provide real standard IO capabilities.
Under Tk, when redirecting from standard input, all applications will see an
immediate end-of-file; information redirected to standard output or standard
@@ -409,6 +422,10 @@ that sometimes pop up:
With the file \fIcmp.bat\fR looking something like:
.PP
.CS
@gcc %*
.CE
or like another variant using single parameters:
.CS
@gcc %1 %2 %3 %4 %5 %6 %7 %8 %9
.CE
.SS "WORKING WITH COMMAND BUILT-INS"
+2 -2
View File
@@ -83,7 +83,7 @@ Specifies that the number should be padded on the left with
zeroes instead of spaces.
.TP 10
\fB#\fR
Requests an alternate output form. For \fBo\fR and \fBO\fR
Requests an alternate output form. For \fBo\fR
conversions it guarantees that the first digit is always \fB0\fR.
For \fBx\fR or \fBX\fR conversions, \fB0x\fR or \fB0X\fR (respectively)
will be added to the beginning of the result unless it is zero.
@@ -169,7 +169,7 @@ for \fBx\fR and
for \fBX\fR).
.TP 10
\fBb\fR
Convert integer to binary string, using digits 0 and 1.
Convert integer to unsigned binary string, using digits 0 and 1.
.TP 10
\fBc\fR
Convert integer to the Unicode character it represents.
+177 -9
View File
@@ -6,14 +6,14 @@
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH "http" n 2.7 http "Tcl Bundled Packages"
.TH "http" n 2.9 http "Tcl Bundled Packages"
.so man.macros
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
http \- Client-side implementation of the HTTP/1.1 protocol
.SH SYNOPSIS
\fBpackage require http ?2.7?\fR
\fBpackage require http ?2.8?\fR
.\" See Also -useragent option documentation in body!
.sp
\fB::http::config ?\fI\-option value\fR ...?
@@ -22,6 +22,8 @@ http \- Client-side implementation of the HTTP/1.1 protocol
.sp
\fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...?
.sp
\fB::http::quoteString\fR \fIvalue\fR
.sp
\fB::http::reset\fR \fItoken\fR ?\fIwhy\fR?
.sp
\fB::http::wait \fItoken\fR
@@ -44,12 +46,14 @@ http \- Client-side implementation of the HTTP/1.1 protocol
.sp
\fB::http::register \fIproto port command\fR
.sp
\fB::http::registerError \fIport\fR ?\fImessage\fR?
.sp
\fB::http::unregister \fIproto\fR
.BE
.SH DESCRIPTION
.PP
The \fBhttp\fR package provides the client side of the HTTP/1.1
protocol, as defined in RFC 2616.
protocol, as defined in RFC 7230 to RFC 7235, which supersede RFC 2616.
The package implements the GET, POST, and HEAD operations
of HTTP/1.1. It allows configuration of a proxy host to get through
firewalls. The package is compatible with the \fBSafesock\fR security
@@ -95,6 +99,19 @@ comma-separated list of mime type patterns that you are
willing to receive. For example,
.QW "image/gif, image/jpeg, text/*" .
.TP
\fB\-pipeline\fR \fIboolean\fR
.
Specifies whether HTTP/1.1 transactions on a persistent socket will be
pipelined. See the \fBPERSISTENT SOCKETS\fR section for details. The default
is 1.
.TP
\fB\-postfresh\fR \fIboolean\fR
.
Specifies whether requests that use the \fBPOST\fR method will always use a
fresh socket, overriding the \fB-keepalive\fR option of
command \fBhttp::geturl\fR. See the \fBPERSISTENT SOCKETS\fR section for details.
The default is 0.
.TP
\fB\-proxyhost\fR \fIhostname\fR
.
The name of the proxy host, if any. If this value is the
@@ -116,20 +133,47 @@ an empty list. The default filter returns the values of the
\fB\-proxyhost\fR and \fB\-proxyport\fR settings if they are
non-empty.
.TP
\fB\-repost\fR \fIboolean\fR
.
Specifies what to do if a POST request over a persistent connection fails
because the server has half-closed the connection. If boolean \fBtrue\fR, the
request
will be automatically retried; if boolean \fBfalse\fR it will not, and the
application
that uses \fBhttp::geturl\fR is expected to seek user confirmation before
retrying the POST. The value \fBtrue\fR should be used only under certain
conditions. See the \fBPERSISTENT SOCKETS\fR section for details. The
default is 0.
.TP
\fB\-urlencoding\fR \fIencoding\fR
.
The \fIencoding\fR used for creating the x-url-encoded URLs with
\fB::http::formatQuery\fR. The default is \fButf-8\fR, as specified by RFC
\fB::http::formatQuery\fR and \fB::http::quoteString\fR.
The default is \fButf-8\fR, as specified by RFC
2718. Prior to http 2.5 this was unspecified, and that behavior can be
returned by specifying the empty string (\fB{}\fR), although
\fIiso8859-1\fR is recommended to restore similar behavior but without the
\fB::http::formatQuery\fR throwing an error processing non-latin-1
characters.
\fB::http::formatQuery\fR or \fB::http::quoteString\fR
throwing an error processing non-latin-1 characters.
.TP
\fB\-useragent\fR \fIstring\fR
.
The value of the User-Agent header in the HTTP request. The default is
.QW "\fBTcl http client package 2.7\fR" .
The value of the User-Agent header in the HTTP request. In an unsafe
interpreter, the default value depends upon the operating system, and
the version numbers of \fBhttp\fR and \fBTcl\fR, and is (for example)
.QW "\fBMozilla/5.0 (Windows; U; Windows NT 10.0) http/2.8.12 Tcl/8.6.8\fR" .
A safe interpreter cannot determine its operating system, and so the default
in a safe interpreter is to use a Windows 10 value with the current version
numbers of \fBhttp\fR and \fBTcl\fR.
.TP
\fB\-zip\fR \fIboolean\fR
.
If the value is boolean \fBtrue\fR, then by default requests will send a header
.QW "\fBAccept-Encoding: gzip,deflate,compress\fR" .
If the value is boolean \fBfalse\fR, then by default this header will not be sent.
In either case the default can be overridden for an individual request by
supplying a custom \fBAccept-Encoding\fR header in the \fB-headers\fR option
of \fBhttp::geturl\fR. The default is 1.
.RE
.TP
\fB::http::geturl\fR \fIurl\fR ?\fIoptions\fR?
@@ -227,7 +271,7 @@ Pragma: no-cache
.TP
\fB\-keepalive\fR \fIboolean\fR
.
If true, attempt to keep the connection open for servicing
If boolean \fBtrue\fR, attempt to keep the connection open for servicing
multiple requests. Default is 0.
.TP
\fB\-method\fR \fItype\fR
@@ -334,6 +378,11 @@ encodes the keys and values, and generates one string that has the
proper & and = separators. The result is suitable for the
\fB\-query\fR value passed to \fB::http::geturl\fR.
.TP
\fB::http::quoteString\fR \fIvalue\fR
.
This procedure does x-url-encoding of string. It takes a single argument and
encodes it.
.TP
\fB::http::reset\fR \fItoken\fR ?\fIwhy\fR?
.
This command resets the HTTP transaction identified by \fItoken\fR, if any.
@@ -415,6 +464,17 @@ set token [::http::geturl https://my.secure.site/]
.CE
.RE
.TP
\fB::http::registerError\fR \fIport\fR ?\fImessage\fR?
.
This procedure allows a registered protocol handler to deliver an error
message for use by \fBhttp\fR. Calling this command does not raise an
error. The command is useful when a registered protocol detects an problem
(for example, an invalid TLS certificate) that will cause an error to
propagate to \fBhttp\fR. The command allows \fBhttp\fR to provide a
precise error message rather than a general one. The command returns the
value provided by the last call with argument \fImessage\fR, or the empty
string if no such call has been made.
.TP
\fB::http::unregister\fR \fIproto\fR
.
This procedure unregisters a protocol handler that was previously
@@ -504,6 +564,14 @@ The following elements of
the array are supported:
.RS
.TP
\fBbinary\fR
.
This is boolean \fBtrue\fR if (after decoding any compression specified
by the
.QW "Content-Encoding"
response header) the HTTP response is binary. It is boolean \fBfalse\fR
if the HTTP response is text.
.TP
\fBbody\fR
.
The contents of the URL. This will be empty if the \fB\-channel\fR
@@ -602,6 +670,106 @@ A copy of the \fBContent-Type\fR meta-data value.
.
The requested URL.
.RE
.SH "PERSISTENT CONNECTIONS"
.PP
.SS "BASICS"
.PP
See RFC 7230 Sec 6, which supersedes RFC 2616 Sec 8.1.
.PP
A persistent connection allows multiple HTTP/1.1 transactions to be
carried over the same TCP connection. Pipelining allows a
client to make multiple requests over a persistent connection without
waiting for each response. The server sends responses in the same order
that the requests were received.
.PP
If a POST request fails to complete, typically user confirmation is
needed before sending the request again. The user may wish to verify
whether the server was modified by the failed POST request, before
sending the same request again.
.PP
A HTTP request will use a persistent socket if the call to
\fBhttp::geturl\fR has the option \fB-keepalive true\fR. It will use
pipelining where permitted if the \fBhttp::config\fR option
\fB-pipeline\fR is boolean \fBtrue\fR (its default value).
.PP
The http package maintains no more than one persistent connection to each
server (i.e. each value of
.QW "domain:port" ).
If \fBhttp::geturl\fR is called to make a request over a persistent
connection while the connection is busy with another request, the new
request will be held in a queue until the connection is free.
.PP
The http package does not support HTTP/1.0 persistent connections
controlled by the \fBKeep-Alive\fR header.
.SS "SPECIAL CASES"
.PP
This subsection discusses issues related to closure of the
persistent connection by the server, automatic retry of failed requests,
the special treatment necessary for POST requests, and the options for
dealing with these cases.
.PP
In accordance with RFC 7230, \fBhttp::geturl\fR does not pipeline
requests that use the POST method. If a POST uses a persistent
connection and is not the first request on that connection,
\fBhttp::geturl\fR waits until it has received the response for the previous
request; or (if \fBhttp::config\fR option \fB-postfresh\fR is boolean \fBtrue\fR) it
uses a new connection for each POST.
.PP
If the server is processing a number of pipelined requests, and sends a
response header
.QW "\fBConnection: close\fR"
with one of the responses (other than the last), then subsequent responses
are unfulfilled. \fBhttp::geturl\fR will send the unfulfilled requests again
over a new connection.
.PP
A difficulty arises when a HTTP client sends a request over a persistent
connection that has been idle for a while. The HTTP server may
half-close an apparently idle connection while the client is sending a
request, but before the request arrives at the server: in this case (an
.QW "asynchronous close event" )
the request will fail. The difficulty arises because the client cannot
be certain whether the POST modified the state of the server. For HEAD or
GET requests, \fBhttp::geturl\fR opens another connection and retransmits
the failed request. However, if the request was a POST, RFC 7230 forbids
automatic retry by default, suggesting either user confirmation, or
confirmation by user-agent software that has semantic understanding of
the application. The \fBhttp::config\fR option \fB-repost\fR allows for
either possibility.
.PP
Asynchronous close events can occur only in a short interval of time. The
\fBhttp\fR package monitors each persistent connection for closure by the
server. Upon detection, the connection is also closed at the client end,
and subsequent requests will use a fresh connection.
.PP
If the \fBhttp::geturl\fR command is called with option \fB-keepalive true\fR,
then it will both try to use an existing persistent connection
(if one is available), and it will send the server a
.QW "\fBConnection: keep-alive\fR"
request header asking to keep the connection open for future requests.
.PP
The \fBhttp::config\fR options \fB-pipeline\fR, \fB-postfresh\fR, and
\fB-repost\fR relate to persistent connections.
.PP
Option \fB-pipeline\fR, if boolean \fBtrue\fR, will pipeline GET and HEAD requests
made
over a persistent connection. POST requests will not be pipelined - if the
POST is not the first transaction on the connection, its request will not
be sent until the previous response has finished. GET and HEAD requests
made after a POST will not be sent until the POST response has been
delivered, and will not be sent if the POST fails.
.PP
Option \fB-postfresh\fR, if boolean \fBtrue\fR, will override the \fBhttp::geturl\fR option
\fB-keepalive\fR, and always open a fresh connection for a POST request.
.PP
Option \fB-repost\fR, if \fBtrue\fR, permits automatic retry of a POST request
that fails because it uses a persistent connection that the server has
half-closed (an
.QW "asynchronous close event" ).
Subsequent GET and HEAD requests in a failed pipeline will also be retried.
\fIThe -repost option should be used only if the application understands
that the retry is appropriate\fR - specifically, the application must know
that if the failed POST successfully modified the state of the server, a repeat POST
would have no adverse effect.
.SH EXAMPLE
.PP
This example creates a procedure to copy a URL to a file while printing a
+30 -10
View File
@@ -17,7 +17,7 @@ lreplace \- Replace elements in a list with new elements
.BE
.SH DESCRIPTION
.PP
\fBlreplace\fR returns a new list formed by replacing one or more elements of
\fBlreplace\fR returns a new list formed by replacing zero or more elements of
\fIlist\fR with the \fIelement\fR arguments.
\fIfirst\fR and \fIlast\fR are index values specifying the first and
last elements of the range to replace.
@@ -27,23 +27,26 @@ supporting simple index arithmetic and indices relative to the
end of the list.
0 refers to the first element of the
list, and \fBend\fR refers to the last element of the list.
If \fIlist\fR is empty, then \fIfirst\fR and \fIlast\fR are ignored.
.PP
If \fIfirst\fR is less than zero, it is considered to refer to before the
first element of the list. For non-empty lists, the element indicated
by \fIfirst\fR must exist or \fIfirst\fR must indicate before the
start of the list.
If either \fIfirst\fR or \fIlast\fR is less than zero, it is considered
to refer to before the first element of the list. This allows \fBlreplace\fR
to prepend elements to \fIlist\fR.
.VS TIP505
If either \fIfirst\fR or \fIlast\fR indicates a position greater than the
index of the last element of the list, it is treated as if it is an
index one greater than the last element. This allows \fBlreplace\fR to
append elements to \fIlist\fR.
.VE TIP505
.PP
If \fIlast\fR is less than \fIfirst\fR, then any specified elements
will be inserted into the list before the point specified by \fIfirst\fR
will be inserted into the list before the element specified by \fIfirst\fR
with no elements being deleted.
.PP
The \fIelement\fR arguments specify zero or more new arguments to
The \fIelement\fR arguments specify zero or more new elements to
be added to the list in place of those that were deleted.
Each \fIelement\fR argument will become a separate element of
the list. If no \fIelement\fR arguments are specified, then the elements
between \fIfirst\fR and \fIlast\fR are simply deleted. If \fIlist\fR
is empty, any \fIelement\fR arguments are added to the end of the list.
between \fIfirst\fR and \fIlast\fR are simply deleted.
.SH EXAMPLES
.PP
Replacing an element of a list with another:
@@ -78,9 +81,26 @@ proc lremove {listVariable value} {
set var [\fBlreplace\fR $var $idx $idx]
}
.CE
.PP
.VS TIP505
Appending elements to the list; note that \fBend+2\fR will initially
be treated as if it is \fB6\fR here, but both that and \fB12345\fR are greater
than the index of the final item so they behave identically:
.PP
.CS
% set var {a b c d e}
a b c d e
% set var [\fBlreplace\fR $var 12345 end+2 f g h i]
a b c d e f g h i
.CE
.VE TIP505
.SH "SEE ALSO"
list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n),
lset(n), lrange(n), lsort(n),
string(n)
.SH KEYWORDS
element, list, replace
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:
+3 -5
View File
@@ -115,9 +115,7 @@ Any Unicode control character.
Any Unicode digit character. Note that this includes characters
outside of the [0\-9] range.
.IP \fBdouble\fR 12
Any of the valid forms for a double in Tcl, with optional surrounding
whitespace. In case of under/overflow in the value, 0 is returned and
the \fIvarname\fR will contain \-1.
Any of the forms allowed to \fBTcl_GetDoubleFromObj\fR.
.IP \fBentier\fR 12
.VS 8.6
Any of the valid string formats for an integer value of arbitrary size
@@ -131,7 +129,7 @@ false.
Any Unicode printing character, except space.
.IP \fBinteger\fR 12
Any of the valid string formats for a 32-bit integer value in Tcl,
with optional surrounding whitespace. In case of under/overflow in
with optional surrounding whitespace. In case of overflow in
the value, 0 is returned and the \fIvarname\fR will contain \-1.
.IP \fBlist\fR 12
Any proper list structure, with optional surrounding whitespace. In
@@ -156,7 +154,7 @@ true.
Any upper case alphabet character in the Unicode character set.
.IP \fBwideinteger\fR 12
Any of the valid forms for a wide integer in Tcl, with optional
surrounding whitespace. In case of under/overflow in the value, 0 is
surrounding whitespace. In case of overflow in the value, 0 is
returned and the \fIvarname\fR will contain \-1.
.IP \fBwordchar\fR 12
Any Unicode word character. That is any alphanumeric character, and
-114
View File
@@ -1,114 +0,0 @@
'\"
'\" Copyright (c) 2005 Sergey Brester aka sebres.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH timerate n "" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
timerate \- Time-related execution resp. performance measurement of a script
.SH SYNOPSIS
\fBtimerate \fIscript\fR \fI?time?\fR
.sp
\fBtimerate \fI?-direct?\fR \fI?-overhead double?\fR \fIscript\fR \fI?time?\fR
.sp
\fBtimerate \fI?-calibrate?\fR \fI?-direct?\fR \fIscript\fR \fI?time?\fR
.BE
.SH DESCRIPTION
.PP
The first and second form will evaluate \fIscript\fR until the interval
\fItime\fR given in milliseconds elapses, or for 1000 milliseconds (1 second)
if \fItime\fR is not specified.
.sp
It will then return a canonical tcl-list of the form
.PP
.CS
\f0.095977 µs/# 52095836 # 10419167 #/sec 5000.000 nett-ms\fR
.CE
.PP
which indicates:
.IP \(bu
the average amount of time required per iteration, in microseconds (lindex $result 0)
.IP \(bu
the count how many times it was executed (lindex $result 2)
.IP \(bu
the estimated rate per second (lindex $result 4)
.IP \(bu
the estimated real execution time without measurement overhead (lindex $result 6)
.PP
Time is measured in elapsed time using heighest timer resolution as possible, not CPU time.
This command may be used to provide information as to how well the script or a tcl-command
is performing and can help determine bottlenecks and fine-tune application performance.
.PP
\fI-calibrate\fR
.
To measure very fast scripts as exact as posible the calibration process
may be required.
This parameter used to calibrate \fBtimerate\fR calculating the estimated overhead
of given \fIscript\fR as default overhead for further execution of \fBtimerate\fR.
It can take up to 10 seconds if parameter \fItime\fR is not specified.
.PP
\fI-overhead double\fR
.
This parameter used to supply the measurement overhead of single iteration
(in microseconds) that should be ignored during whole evaluation process.
.PP
\fI-direct\fR
.
Causes direct execution per iteration (not compiled variant of evaluation used).
.PP
In opposition to \fBtime\fR the execution limited here by fixed time instead of
repetition count.
Additionally the compiled variant of the script will be used during whole evaluation
(as if it were part of a compiled \fBproc\fR), if parameter \fI-direct\fR is not specified.
Therefore it provides more precise results and prevents very long execution time
by slow scripts resp. scripts with unknown speed.
.SH EXAMPLE
Estimate how fast it takes for a simple Tcl \fBfor\fR loop (including
operations on variable \fIi\fR) to count to a ten:
.PP
.CS
# calibrate:
timerate -calibrate {}
# measure:
timerate { for {set i 0} {$i<10} {incr i} {} } 5000
.CE
.PP
Estimate how fast it takes for a simple Tcl \fBfor\fR loop only (ignoring the
overhead for operations on variable \fIi\fR) to count to a ten:
.PP
.CS
# calibrate for overhead of variable operations:
set i 0; timerate -calibrate {expr {$i<10}; incr i} 1000
# measure:
timerate { for {set i 0} {$i<10} {incr i} {} } 5000
.CE
.PP
Estimate the rate of calculating the hour using \fBclock format\fR only, ignoring
overhead of the rest, without measurement how fast it takes for a whole script:
.PP
.CS
# calibrate:
timerate -calibrate {}
# estimate overhead:
set tm 0
set ovh [lindex [timerate { incr tm [expr {24*60*60}] }] 0]
# measure using esimated overhead:
set tm 0
timerate -overhead $ovh {
clock format $tm -format %H
incr tm [expr {24*60*60}]; # overhead for this is ignored
} 5000
.CE
.SH "SEE ALSO"
time(n)
.SH KEYWORDS
script, timerate, time
.\" Local Variables:
.\" mode: nroff
.\" End:
+306 -293
View File
@@ -137,109 +137,110 @@ static const crange alphaRangeTable[] = {
{0x41, 0x5a}, {0x61, 0x7a}, {0xc0, 0xd6}, {0xd8, 0xf6},
{0xf8, 0x2c1}, {0x2c6, 0x2d1}, {0x2e0, 0x2e4}, {0x370, 0x374},
{0x37a, 0x37d}, {0x388, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x3f5},
{0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x561, 0x587},
{0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3},
{0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x560, 0x588},
{0x5d0, 0x5ea}, {0x5ef, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3},
{0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea},
{0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b4}, {0x8b6, 0x8bd},
{0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c},
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1},
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c},
{0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8},
{0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28},
{0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a},
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
{0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39},
{0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8},
{0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
{0xd12, 0xd3a}, {0xd54, 0xd56}, {0xd5f, 0xd61}, {0xd7a, 0xd7f},
{0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6},
{0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97}, {0xe99, 0xe9f},
{0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4}, {0xedc, 0xedf},
{0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c}, {0x1000, 0x102a},
{0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070}, {0x1075, 0x1081},
{0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248}, {0x124a, 0x124d},
{0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d},
{0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5},
{0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a},
{0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1401, 0x166c},
{0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x16f1, 0x16f8},
{0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751},
{0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3}, {0x1820, 0x1877},
{0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5}, {0x1900, 0x191e},
{0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9},
{0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33}, {0x1b45, 0x1b4b},
{0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23}, {0x1c4d, 0x1c4f},
{0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1},
{0x1d00, 0x1dbf}, {0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45},
{0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4},
{0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3},
{0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc},
{0x2090, 0x209c}, {0x210a, 0x2113}, {0x2119, 0x211d}, {0x212a, 0x212d},
{0x212f, 0x2139}, {0x213c, 0x213f}, {0x2145, 0x2149}, {0x2c00, 0x2c2e},
{0x2c30, 0x2c5e}, {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee}, {0x2d00, 0x2d25},
{0x2d30, 0x2d67}, {0x2d80, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae},
{0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce},
{0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x3031, 0x3035}, {0x3041, 0x3096},
{0x309d, 0x309f}, {0x30a1, 0x30fa}, {0x30fc, 0x30ff}, {0x3105, 0x312d},
{0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5},
{0x4e00, 0x9fd5}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c},
{0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5},
{0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ae}, {0xa7b0, 0xa7b7},
{0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a}, {0xa80c, 0xa822},
{0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7}, {0xa90a, 0xa925},
{0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2}, {0xa9e0, 0xa9e4},
{0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe}, {0xaa00, 0xaa28}, {0xaa40, 0xaa42},
{0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, {0xaa7e, 0xaaaf}, {0xaab9, 0xaabd},
{0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4}, {0xab01, 0xab06},
{0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
{0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2}, {0xac00, 0xd7a3},
{0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e},
{0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e}, {0xdd40, 0xdd7e},
{0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e}, {0xde40, 0xde7e},
{0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e},
{0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9},
{0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36},
{0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f},
{0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc},
{0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe}, {0xffc2, 0xffc7},
{0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}
#if TCL_UTF_MAX > 4
{0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86a}, {0x8a0, 0x8b4},
{0x8b6, 0x8bd}, {0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980},
{0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9},
{0x9df, 0x9e1}, {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30},
{0xa59, 0xa5c}, {0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91},
{0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c},
{0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61},
{0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa},
{0xbae, 0xbb9}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
{0xc2a, 0xc39}, {0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90},
{0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c},
{0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd54, 0xd56}, {0xd5f, 0xd61},
{0xd7a, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb},
{0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97},
{0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4},
{0xedc, 0xedf}, {0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c},
{0x1000, 0x102a}, {0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070},
{0x1075, 0x1081}, {0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248},
{0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288},
{0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be},
{0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315},
{0x1318, 0x135a}, {0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd},
{0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea},
{0x16f1, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731},
{0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3},
{0x1820, 0x1878}, {0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5},
{0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},
{0x19b0, 0x19c9}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33},
{0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23},
{0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1c90, 0x1cba},
{0x1cbd, 0x1cbf}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1}, {0x1d00, 0x1dbf},
{0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
{0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc},
{0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb},
{0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, {0x2090, 0x209c},
{0x210a, 0x2113}, {0x2119, 0x211d}, {0x212a, 0x212d}, {0x212f, 0x2139},
{0x213c, 0x213f}, {0x2145, 0x2149}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e},
{0x2c60, 0x2ce4}, {0x2ceb, 0x2cee}, {0x2d00, 0x2d25}, {0x2d30, 0x2d67},
{0x2d80, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6},
{0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6},
{0x2dd8, 0x2dde}, {0x3031, 0x3035}, {0x3041, 0x3096}, {0x309d, 0x309f},
{0x30a1, 0x30fa}, {0x30fc, 0x30ff}, {0x3105, 0x312f}, {0x3131, 0x318e},
{0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5}, {0x4e00, 0x9fef},
{0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c}, {0xa610, 0xa61f},
{0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5}, {0xa717, 0xa71f},
{0xa722, 0xa788}, {0xa78b, 0xa7b9}, {0xa7f7, 0xa801}, {0xa803, 0xa805},
{0xa807, 0xa80a}, {0xa80c, 0xa822}, {0xa840, 0xa873}, {0xa882, 0xa8b3},
{0xa8f2, 0xa8f7}, {0xa90a, 0xa925}, {0xa930, 0xa946}, {0xa960, 0xa97c},
{0xa984, 0xa9b2}, {0xa9e0, 0xa9e4}, {0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe},
{0xaa00, 0xaa28}, {0xaa40, 0xaa42}, {0xaa44, 0xaa4b}, {0xaa60, 0xaa76},
{0xaa7e, 0xaaaf}, {0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea},
{0xaaf2, 0xaaf4}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16},
{0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab65},
{0xab70, 0xabe2}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb},
{0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17},
{0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1},
{0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb},
{0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a},
{0xff66, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7},
{0xffda, 0xffdc}
#if CHRBITS > 16
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0},
{0x10300, 0x1031f}, {0x10330, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
{0x10300, 0x1031f}, {0x1032d, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
{0x10380, 0x1039d}, {0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d},
{0x104b0, 0x104d3}, {0x104d8, 0x104fb}, {0x10500, 0x10527}, {0x10530, 0x10563},
{0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
{0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10860, 0x10876}, {0x10880, 0x1089e},
{0x108e0, 0x108f2}, {0x10900, 0x10915}, {0x10920, 0x10939}, {0x10980, 0x109b7},
{0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a60, 0x10a7c},
{0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a35}, {0x10a60, 0x10a7c},
{0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4}, {0x10b00, 0x10b35},
{0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91}, {0x10c00, 0x10c48},
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x11003, 0x11037}, {0x11083, 0x110af},
{0x110d0, 0x110e8}, {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2},
{0x111c1, 0x111c4}, {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286},
{0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de},
{0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339},
{0x1135d, 0x11361}, {0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af},
{0x11580, 0x115ae}, {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa},
{0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08},
{0x11c0a, 0x11c2e}, {0x11c72, 0x11c8f}, {0x12000, 0x12399}, {0x12480, 0x12543},
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10d00, 0x10d23}, {0x10f00, 0x10f1c},
{0x10f30, 0x10f45}, {0x11003, 0x11037}, {0x11083, 0x110af}, {0x110d0, 0x110e8},
{0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2}, {0x111c1, 0x111c4},
{0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286}, {0x1128a, 0x1128d},
{0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de}, {0x11305, 0x1130c},
{0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1135d, 0x11361},
{0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af}, {0x11580, 0x115ae},
{0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa}, {0x11700, 0x1171a},
{0x11800, 0x1182b}, {0x118a0, 0x118df}, {0x11a0b, 0x11a32}, {0x11a5c, 0x11a83},
{0x11a86, 0x11a89}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c2e},
{0x11c72, 0x11c8f}, {0x11d00, 0x11d06}, {0x11d0b, 0x11d30}, {0x11d60, 0x11d65},
{0x11d6a, 0x11d89}, {0x11ee0, 0x11ef2}, {0x12000, 0x12399}, {0x12480, 0x12543},
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
{0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77},
{0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f}, {0x17000, 0x187ec},
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
{0x1bc90, 0x1bc99}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0},
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734},
{0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8},
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943},
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}
{0x16b7d, 0x16b8f}, {0x16e40, 0x16e7f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f},
{0x17000, 0x187f1}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb},
{0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
{0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9},
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
{0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
{0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0}, {0x1d6c2, 0x1d6da},
{0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, {0x1d736, 0x1d74e},
{0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8}, {0x1d7aa, 0x1d7c2},
{0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943}, {0x1ee00, 0x1ee03},
{0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f},
{0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c},
{0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9},
{0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
{0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}
#endif
};
@@ -250,28 +251,30 @@ static const chr alphaCharTable[] = {
0x38c, 0x559, 0x66e, 0x66f, 0x6d5, 0x6e5, 0x6e6, 0x6ee, 0x6ef,
0x6ff, 0x710, 0x7b1, 0x7f4, 0x7f5, 0x7fa, 0x81a, 0x824, 0x828,
0x93d, 0x950, 0x98f, 0x990, 0x9b2, 0x9bd, 0x9ce, 0x9dc, 0x9dd,
0x9f0, 0x9f1, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38,
0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1, 0xaf9,
0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71, 0xb83,
0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0, 0xc3d,
0xc60, 0xc61, 0xc80, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2,
0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84, 0xe87,
0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2, 0xeb3,
0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e, 0x10c7,
0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae, 0x1baf,
0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102,
0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2,
0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c,
0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6,
0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
#if TCL_UTF_MAX > 4
0x9f0, 0x9f1, 0x9fc, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36,
0xa38, 0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1,
0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71,
0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0,
0xc3d, 0xc60, 0xc61, 0xc80, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1,
0xcf2, 0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84,
0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2,
0xeb3, 0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e,
0x10c7, 0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae,
0x1baf, 0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f,
0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184,
0x2cf2, 0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b,
0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa8fe, 0xa9cf, 0xaa7a, 0xaab1,
0xaab5, 0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43,
0xfb44
#if CHRBITS > 16
,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be,
0x109bf, 0x10a00, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, 0x11310, 0x11332,
0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x11c40,
0x16f50, 0x16fe0, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6,
0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42,
0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b,
0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
0x109bf, 0x10a00, 0x10f27, 0x11144, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f,
0x11310, 0x11332, 0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644,
0x118ff, 0x11a00, 0x11a3a, 0x11a50, 0x11a9d, 0x11c40, 0x11d08, 0x11d09, 0x11d46,
0x11d67, 0x11d68, 0x11d98, 0x16f50, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f, 0x1d4a2,
0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39,
0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57,
0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
#endif
};
@@ -285,7 +288,7 @@ static const crange controlRangeTable[] = {
{0x0, 0x1f}, {0x7f, 0x9f}, {0x600, 0x605}, {0x200b, 0x200f},
{0x202a, 0x202e}, {0x2060, 0x2064}, {0x2066, 0x206f}, {0xe000, 0xf8ff},
{0xfff9, 0xfffb}
#if TCL_UTF_MAX > 4
#if CHRBITS > 16
,{0x1bca0, 0x1bca3}, {0x1d173, 0x1d17a}, {0xe0020, 0xe007f}, {0xf0000, 0xffffd},
{0x100000, 0x10fffd}
#endif
@@ -295,8 +298,8 @@ static const crange controlRangeTable[] = {
static const chr controlCharTable[] = {
0xad, 0x61c, 0x6dd, 0x70f, 0x8e2, 0x180e, 0xfeff
#if TCL_UTF_MAX > 4
,0x110bd, 0xe0001
#if CHRBITS > 16
,0x110bd, 0x110cd, 0xe0001
#endif
};
@@ -317,12 +320,12 @@ static const crange digitRangeTable[] = {
{0x1c50, 0x1c59}, {0xa620, 0xa629}, {0xa8d0, 0xa8d9}, {0xa900, 0xa909},
{0xa9d0, 0xa9d9}, {0xa9f0, 0xa9f9}, {0xaa50, 0xaa59}, {0xabf0, 0xabf9},
{0xff10, 0xff19}
#if TCL_UTF_MAX > 4
,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f},
{0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459}, {0x114d0, 0x114d9},
{0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9},
{0x11c50, 0x11c59}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff},
{0x1e950, 0x1e959}
#if CHRBITS > 16
,{0x104a0, 0x104a9}, {0x10d30, 0x10d39}, {0x11066, 0x1106f}, {0x110f0, 0x110f9},
{0x11136, 0x1113f}, {0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459},
{0x114d0, 0x114d9}, {0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739},
{0x118e0, 0x118e9}, {0x11c50, 0x11c59}, {0x11d50, 0x11d59}, {0x11da0, 0x11da9},
{0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff}, {0x1e950, 0x1e959}
#endif
};
@@ -345,18 +348,20 @@ static const crange punctRangeTable[] = {
{0x1b5a, 0x1b60}, {0x1bfc, 0x1bff}, {0x1c3b, 0x1c3f}, {0x1cc0, 0x1cc7},
{0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205e},
{0x2308, 0x230b}, {0x2768, 0x2775}, {0x27e6, 0x27ef}, {0x2983, 0x2998},
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e44},
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e4e},
{0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f},
{0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd},
{0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61},
{0xff01, 0xff03}, {0xff05, 0xff0a}, {0xff0c, 0xff0f}, {0xff3b, 0xff3d},
{0xff5f, 0xff65}
#if TCL_UTF_MAX > 4
#if CHRBITS > 16
,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f},
{0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143},
{0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x1144b, 0x1144f},
{0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c}, {0x1173c, 0x1173e},
{0x11c41, 0x11c45}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x1da87, 0x1da8b}
{0x10b99, 0x10b9c}, {0x10f55, 0x10f59}, {0x11047, 0x1104d}, {0x110be, 0x110c1},
{0x11140, 0x11143}, {0x111c5, 0x111c8}, {0x111dd, 0x111df}, {0x11238, 0x1123d},
{0x1144b, 0x1144f}, {0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c},
{0x1173c, 0x1173e}, {0x11a3f, 0x11a46}, {0x11a9a, 0x11a9c}, {0x11a9e, 0x11aa2},
{0x11c41, 0x11c45}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x16e97, 0x16e9a},
{0x1da87, 0x1da8b}
#endif
};
@@ -367,18 +372,20 @@ static const chr punctCharTable[] = {
0xab, 0xb6, 0xb7, 0xbb, 0xbf, 0x37e, 0x387, 0x589, 0x58a,
0x5be, 0x5c0, 0x5c3, 0x5c6, 0x5f3, 0x5f4, 0x609, 0x60a, 0x60c,
0x60d, 0x61b, 0x61e, 0x61f, 0x6d4, 0x85e, 0x964, 0x965, 0x970,
0xaf0, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14, 0xf85, 0xfd9, 0xfda,
0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x1735, 0x1736, 0x1944,
0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3, 0x207d, 0x207e, 0x208d,
0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc, 0x29fd, 0x2cfe, 0x2cff,
0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, 0xa4ff, 0xa673, 0xa67e,
0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9de, 0xa9df, 0xaade,
0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, 0xfe63, 0xfe68, 0xfe6a,
0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d
#if TCL_UTF_MAX > 4
0x9fd, 0xa76, 0xaf0, 0xc84, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14,
0xf85, 0xfd9, 0xfda, 0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c,
0x1735, 0x1736, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3,
0x207d, 0x207e, 0x208d, 0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc,
0x29fd, 0x2cfe, 0x2cff, 0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe,
0xa4ff, 0xa673, 0xa67e, 0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f,
0xa9de, 0xa9df, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f,
0xfe63, 0xfe68, 0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f,
0xff5b, 0xff5d
#if CHRBITS > 16
,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc,
0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x11c70,
0x11c71, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f, 0x1e95e, 0x1e95f
0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x1183b,
0x11c70, 0x11c71, 0x11ef7, 0x11ef8, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f,
0x1e95e, 0x1e95f
#endif
};
@@ -409,25 +416,25 @@ static const crange lowerRangeTable[] = {
{0x61, 0x7a}, {0xdf, 0xf6}, {0xf8, 0xff}, {0x17e, 0x180},
{0x199, 0x19b}, {0x1bd, 0x1bf}, {0x233, 0x239}, {0x24f, 0x293},
{0x295, 0x2af}, {0x37b, 0x37d}, {0x3ac, 0x3ce}, {0x3d5, 0x3d7},
{0x3ef, 0x3f3}, {0x430, 0x45f}, {0x561, 0x587}, {0x13f8, 0x13fd},
{0x1c80, 0x1c88}, {0x1d00, 0x1d2b}, {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a},
{0x1e95, 0x1e9d}, {0x1eff, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27},
{0x1f30, 0x1f37}, {0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67},
{0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7},
{0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7},
{0x1ff2, 0x1ff4}, {0x2146, 0x2149}, {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b},
{0x2d00, 0x2d25}, {0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795},
{0xab30, 0xab5a}, {0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06},
{0xfb13, 0xfb17}, {0xff41, 0xff5a}
#if TCL_UTF_MAX > 4
{0x3ef, 0x3f3}, {0x430, 0x45f}, {0x560, 0x588}, {0x10d0, 0x10fa},
{0x10fd, 0x10ff}, {0x13f8, 0x13fd}, {0x1c80, 0x1c88}, {0x1d00, 0x1d2b},
{0x1d6b, 0x1d77}, {0x1d79, 0x1d9a}, {0x1e95, 0x1e9d}, {0x1eff, 0x1f07},
{0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37}, {0x1f40, 0x1f45},
{0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d}, {0x1f80, 0x1f87},
{0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4},
{0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4}, {0x2146, 0x2149},
{0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, {0x2d00, 0x2d25}, {0xa72f, 0xa731},
{0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a}, {0xab60, 0xab65},
{0xab70, 0xabbf}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xff41, 0xff5a}
#if CHRBITS > 16
,{0x10428, 0x1044f}, {0x104d8, 0x104fb}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df},
{0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b},
{0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503},
{0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3},
{0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5},
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b},
{0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f},
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, {0x1e922, 0x1e943}
{0x16e60, 0x16e7f}, {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467},
{0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf},
{0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f},
{0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f},
{0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714},
{0x1d716, 0x1d71b}, {0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788},
{0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, {0x1e922, 0x1e943}
#endif
};
@@ -497,8 +504,8 @@ static const chr lowerCharTable[] = {
0xa763, 0xa765, 0xa767, 0xa769, 0xa76b, 0xa76d, 0xa76f, 0xa77a, 0xa77c,
0xa77f, 0xa781, 0xa783, 0xa785, 0xa787, 0xa78c, 0xa78e, 0xa791, 0xa797,
0xa799, 0xa79b, 0xa79d, 0xa79f, 0xa7a1, 0xa7a3, 0xa7a5, 0xa7a7, 0xa7a9,
0xa7b5, 0xa7b7, 0xa7fa
#if TCL_UTF_MAX > 4
0xa7af, 0xa7b5, 0xa7b7, 0xa7b9, 0xa7fa
#if CHRBITS > 16
,0x1d4bb, 0x1d7cb
#endif
};
@@ -514,20 +521,22 @@ static const crange upperRangeTable[] = {
{0x18e, 0x191}, {0x196, 0x198}, {0x1b1, 0x1b3}, {0x1f6, 0x1f8},
{0x243, 0x246}, {0x388, 0x38a}, {0x391, 0x3a1}, {0x3a3, 0x3ab},
{0x3d2, 0x3d4}, {0x3fd, 0x42f}, {0x531, 0x556}, {0x10a0, 0x10c5},
{0x13a0, 0x13f5}, {0x1f08, 0x1f0f}, {0x1f18, 0x1f1d}, {0x1f28, 0x1f2f},
{0x1f38, 0x1f3f}, {0x1f48, 0x1f4d}, {0x1f68, 0x1f6f}, {0x1fb8, 0x1fbb},
{0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb},
{0x210b, 0x210d}, {0x2110, 0x2112}, {0x2119, 0x211d}, {0x212a, 0x212d},
{0x2130, 0x2133}, {0x2c00, 0x2c2e}, {0x2c62, 0x2c64}, {0x2c6d, 0x2c70},
{0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a}
#if TCL_UTF_MAX > 4
{0x13a0, 0x13f5}, {0x1c90, 0x1cba}, {0x1cbd, 0x1cbf}, {0x1f08, 0x1f0f},
{0x1f18, 0x1f1d}, {0x1f28, 0x1f2f}, {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d},
{0x1f68, 0x1f6f}, {0x1fb8, 0x1fbb}, {0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb},
{0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb}, {0x210b, 0x210d}, {0x2110, 0x2112},
{0x2119, 0x211d}, {0x212a, 0x212d}, {0x2130, 0x2133}, {0x2c00, 0x2c2e},
{0x2c62, 0x2c64}, {0x2c6d, 0x2c70}, {0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae},
{0xa7b0, 0xa7b4}, {0xff21, 0xff3a}
#if CHRBITS > 16
,{0x10400, 0x10427}, {0x104b0, 0x104d3}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf},
{0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
{0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550},
{0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621},
{0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa},
{0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}, {0x1e900, 0x1e921}
{0x16e40, 0x16e5f}, {0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481},
{0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
{0x1d54a, 0x1d550}, {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed},
{0x1d608, 0x1d621}, {0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0},
{0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8},
{0x1e900, 0x1e921}
#endif
};
@@ -596,8 +605,9 @@ static const chr upperCharTable[] = {
0xa756, 0xa758, 0xa75a, 0xa75c, 0xa75e, 0xa760, 0xa762, 0xa764, 0xa766,
0xa768, 0xa76a, 0xa76c, 0xa76e, 0xa779, 0xa77b, 0xa77d, 0xa77e, 0xa780,
0xa782, 0xa784, 0xa786, 0xa78b, 0xa78d, 0xa790, 0xa792, 0xa796, 0xa798,
0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b6
#if TCL_UTF_MAX > 4
0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b6,
0xa7b8
#if CHRBITS > 16
,0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d504, 0x1d505, 0x1d538,
0x1d539, 0x1d546, 0x1d7ca
#endif
@@ -612,166 +622,169 @@ static const chr upperCharTable[] = {
static const crange graphRangeTable[] = {
{0x21, 0x7e}, {0xa1, 0xac}, {0xae, 0x377}, {0x37a, 0x37f},
{0x384, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x52f}, {0x531, 0x556},
{0x559, 0x55f}, {0x561, 0x587}, {0x58d, 0x58f}, {0x591, 0x5c7},
{0x5d0, 0x5ea}, {0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc},
{0x6de, 0x70d}, {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa},
{0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x8a0, 0x8b4},
{0x8b6, 0x8bd}, {0x8d4, 0x8e1}, {0x8e3, 0x983}, {0x985, 0x98c},
{0x559, 0x58a}, {0x58d, 0x58f}, {0x591, 0x5c7}, {0x5d0, 0x5ea},
{0x5ef, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc}, {0x6de, 0x70d},
{0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa}, {0x7fd, 0x82d},
{0x830, 0x83e}, {0x840, 0x85b}, {0x860, 0x86a}, {0x8a0, 0x8b4},
{0x8b6, 0x8bd}, {0x8d3, 0x8e1}, {0x8e3, 0x983}, {0x985, 0x98c},
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4},
{0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fb}, {0xa01, 0xa03},
{0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fe}, {0xa01, 0xa03},
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42},
{0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75}, {0xa81, 0xa83},
{0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa76}, {0xa81, 0xa83},
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
{0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd},
{0xae0, 0xae3}, {0xae6, 0xaf1}, {0xb01, 0xb03}, {0xb05, 0xb0c},
{0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb3c, 0xb44},
{0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77}, {0xb85, 0xb8a},
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
{0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, {0xbe6, 0xbfa},
{0xc00, 0xc03}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
{0xae0, 0xae3}, {0xae6, 0xaf1}, {0xaf9, 0xaff}, {0xb01, 0xb03},
{0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39},
{0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77},
{0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa},
{0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd},
{0xbe6, 0xbfa}, {0xc00, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
{0xc2a, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48}, {0xc4a, 0xc4d},
{0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc83},
{0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3},
{0xcb5, 0xcb9}, {0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd},
{0xce0, 0xce3}, {0xce6, 0xcef}, {0xd01, 0xd03}, {0xd05, 0xd0c},
{0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd3d, 0xd44}, {0xd46, 0xd48},
{0xd4a, 0xd4f}, {0xd54, 0xd63}, {0xd66, 0xd7f}, {0xd85, 0xd96},
{0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xdcf, 0xdd4},
{0xdd8, 0xddf}, {0xde6, 0xdef}, {0xdf2, 0xdf4}, {0xe01, 0xe3a},
{0xe3f, 0xe5b}, {0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3},
{0xead, 0xeb9}, {0xebb, 0xebd}, {0xec0, 0xec4}, {0xec8, 0xecd},
{0xed0, 0xed9}, {0xedc, 0xedf}, {0xf00, 0xf47}, {0xf49, 0xf6c},
{0xf71, 0xf97}, {0xf99, 0xfbc}, {0xfbe, 0xfcc}, {0xfce, 0xfda},
{0x1000, 0x10c5}, {0x10d0, 0x1248}, {0x124a, 0x124d}, {0x1250, 0x1256},
{0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0},
{0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6},
{0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a}, {0x135d, 0x137c},
{0x1380, 0x1399}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1400, 0x167f},
{0x1681, 0x169c}, {0x16a0, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1714},
{0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176c}, {0x176e, 0x1770},
{0x1780, 0x17dd}, {0x17e0, 0x17e9}, {0x17f0, 0x17f9}, {0x1800, 0x180d},
{0x1810, 0x1819}, {0x1820, 0x1877}, {0x1880, 0x18aa}, {0x18b0, 0x18f5},
{0x1900, 0x191e}, {0x1920, 0x192b}, {0x1930, 0x193b}, {0x1944, 0x196d},
{0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9}, {0x19d0, 0x19da},
{0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, {0x1a60, 0x1a7c}, {0x1a7f, 0x1a89},
{0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, {0x1ab0, 0x1abe}, {0x1b00, 0x1b4b},
{0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37}, {0x1c3b, 0x1c49},
{0x1c4d, 0x1c88}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6}, {0x1d00, 0x1df5},
{0x1dfb, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
{0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4},
{0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4},
{0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e},
{0x2090, 0x209c}, {0x20a0, 0x20be}, {0x20d0, 0x20f0}, {0x2100, 0x218b},
{0x2190, 0x23fe}, {0x2400, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73},
{0x2b76, 0x2b95}, {0x2b98, 0x2bb9}, {0x2bbd, 0x2bc8}, {0x2bca, 0x2bd1},
{0x2bec, 0x2bef}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3},
{0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc8c},
{0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9},
{0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3},
{0xce6, 0xcef}, {0xd00, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
{0xd12, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4f}, {0xd54, 0xd63},
{0xd66, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb},
{0xdc0, 0xdc6}, {0xdcf, 0xdd4}, {0xdd8, 0xddf}, {0xde6, 0xdef},
{0xdf2, 0xdf4}, {0xe01, 0xe3a}, {0xe3f, 0xe5b}, {0xe94, 0xe97},
{0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb9}, {0xebb, 0xebd},
{0xec0, 0xec4}, {0xec8, 0xecd}, {0xed0, 0xed9}, {0xedc, 0xedf},
{0xf00, 0xf47}, {0xf49, 0xf6c}, {0xf71, 0xf97}, {0xf99, 0xfbc},
{0xfbe, 0xfcc}, {0xfce, 0xfda}, {0x1000, 0x10c5}, {0x10d0, 0x1248},
{0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288},
{0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be},
{0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315},
{0x1318, 0x135a}, {0x135d, 0x137c}, {0x1380, 0x1399}, {0x13a0, 0x13f5},
{0x13f8, 0x13fd}, {0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f8},
{0x1700, 0x170c}, {0x170e, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753},
{0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17dd}, {0x17e0, 0x17e9},
{0x17f0, 0x17f9}, {0x1800, 0x180d}, {0x1810, 0x1819}, {0x1820, 0x1878},
{0x1880, 0x18aa}, {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1920, 0x192b},
{0x1930, 0x193b}, {0x1944, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},
{0x19b0, 0x19c9}, {0x19d0, 0x19da}, {0x19de, 0x1a1b}, {0x1a1e, 0x1a5e},
{0x1a60, 0x1a7c}, {0x1a7f, 0x1a89}, {0x1a90, 0x1a99}, {0x1aa0, 0x1aad},
{0x1ab0, 0x1abe}, {0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3},
{0x1bfc, 0x1c37}, {0x1c3b, 0x1c49}, {0x1c4d, 0x1c88}, {0x1c90, 0x1cba},
{0x1cbd, 0x1cc7}, {0x1cd0, 0x1cf9}, {0x1d00, 0x1df9}, {0x1dfb, 0x1f15},
{0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57},
{0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3},
{0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe},
{0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e}, {0x2090, 0x209c},
{0x20a0, 0x20bf}, {0x20d0, 0x20f0}, {0x2100, 0x218b}, {0x2190, 0x2426},
{0x2440, 0x244a}, {0x2460, 0x2b73}, {0x2b76, 0x2b95}, {0x2b98, 0x2bc8},
{0x2bca, 0x2bfe}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3},
{0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96}, {0x2da0, 0x2da6},
{0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6},
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e44},
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e4e},
{0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb},
{0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312d},
{0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312f},
{0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3}, {0x31f0, 0x321e},
{0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fd5}, {0xa000, 0xa48c},
{0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ae},
{0xa7b0, 0xa7b7}, {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877},
{0xa880, 0xa8c5}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953},
{0xa95f, 0xa97c}, {0xa980, 0xa9cd}, {0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe},
{0xaa00, 0xaa36}, {0xaa40, 0xaa4d}, {0xaa50, 0xaa59}, {0xaa5c, 0xaac2},
{0xaadb, 0xaaf6}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16},
{0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab65}, {0xab70, 0xabed},
{0xabf0, 0xabf9}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb},
{0xdc00, 0xdc3e}, {0xdc40, 0xdc7e}, {0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe},
{0xdd00, 0xdd3e}, {0xdd40, 0xdd7e}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe},
{0xde00, 0xde3e}, {0xde40, 0xde7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe},
{0xdf00, 0xdf3e}, {0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe},
{0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17},
{0xfb1d, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f},
{0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19},
{0xfe20, 0xfe52}, {0xfe54, 0xfe66}, {0xfe68, 0xfe6b}, {0xfe70, 0xfe74},
{0xfe76, 0xfefc}, {0xff01, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf},
{0xffd2, 0xffd7}, {0xffda, 0xffdc}, {0xffe0, 0xffe6}, {0xffe8, 0xffee}
#if TCL_UTF_MAX > 4
{0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fef}, {0xa000, 0xa48c},
{0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7b9},
{0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877}, {0xa880, 0xa8c5},
{0xa8ce, 0xa8d9}, {0xa8e0, 0xa953}, {0xa95f, 0xa97c}, {0xa980, 0xa9cd},
{0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe}, {0xaa00, 0xaa36}, {0xaa40, 0xaa4d},
{0xaa50, 0xaa59}, {0xaa5c, 0xaac2}, {0xaadb, 0xaaf6}, {0xab01, 0xab06},
{0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
{0xab30, 0xab65}, {0xab70, 0xabed}, {0xabf0, 0xabf9}, {0xac00, 0xd7a3},
{0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9},
{0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1d, 0xfb36}, {0xfb38, 0xfb3c},
{0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7},
{0xfdf0, 0xfdfd}, {0xfe00, 0xfe19}, {0xfe20, 0xfe52}, {0xfe54, 0xfe66},
{0xfe68, 0xfe6b}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff01, 0xffbe},
{0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc},
{0xffe0, 0xffe6}, {0xffe8, 0xffee}
#if CHRBITS > 16
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133},
{0x10137, 0x1018e}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
{0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x10330, 0x1034a},
{0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x1032d, 0x1034a},
{0x10350, 0x1037a}, {0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5},
{0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x104b0, 0x104d3}, {0x104d8, 0x104fb},
{0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
{0x10857, 0x1089e}, {0x108a7, 0x108af}, {0x108e0, 0x108f2}, {0x108fb, 0x1091b},
{0x1091f, 0x10939}, {0x10980, 0x109b7}, {0x109bc, 0x109cf}, {0x109d2, 0x10a03},
{0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a38, 0x10a3a},
{0x10a3f, 0x10a47}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6},
{0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a35}, {0x10a38, 0x10a3a},
{0x10a3f, 0x10a48}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6},
{0x10aeb, 0x10af6}, {0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72},
{0x10b78, 0x10b91}, {0x10b99, 0x10b9c}, {0x10ba9, 0x10baf}, {0x10c00, 0x10c48},
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10cff}, {0x10e60, 0x10e7e},
{0x11000, 0x1104d}, {0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1},
{0x110d0, 0x110e8}, {0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11143},
{0x11150, 0x11176}, {0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4},
{0x11200, 0x11211}, {0x11213, 0x1123e}, {0x11280, 0x11286}, {0x1128a, 0x1128d},
{0x1128f, 0x1129d}, {0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9},
{0x11300, 0x11303}, {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330},
{0x11335, 0x11339}, {0x1133c, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363},
{0x11366, 0x1136c}, {0x11370, 0x11374}, {0x11400, 0x11459}, {0x11480, 0x114c7},
{0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9},
{0x11700, 0x11719}, {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x118a0, 0x118f2},
{0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45},
{0x11c50, 0x11c6c}, {0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6},
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10d27}, {0x10d30, 0x10d39},
{0x10e60, 0x10e7e}, {0x10f00, 0x10f27}, {0x10f30, 0x10f59}, {0x11000, 0x1104d},
{0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1}, {0x110d0, 0x110e8},
{0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11146}, {0x11150, 0x11176},
{0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4}, {0x11200, 0x11211},
{0x11213, 0x1123e}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d},
{0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9}, {0x11300, 0x11303},
{0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339},
{0x1133b, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363}, {0x11366, 0x1136c},
{0x11370, 0x11374}, {0x11400, 0x11459}, {0x11480, 0x114c7}, {0x114d0, 0x114d9},
{0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644}, {0x11650, 0x11659},
{0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9}, {0x11700, 0x1171a},
{0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x11800, 0x1183b}, {0x118a0, 0x118f2},
{0x11a00, 0x11a47}, {0x11a50, 0x11a83}, {0x11a86, 0x11aa2}, {0x11ac0, 0x11af8},
{0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45}, {0x11c50, 0x11c6c},
{0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6}, {0x11d00, 0x11d06},
{0x11d0b, 0x11d36}, {0x11d3f, 0x11d47}, {0x11d50, 0x11d59}, {0x11d60, 0x11d65},
{0x11d6a, 0x11d8e}, {0x11d93, 0x11d98}, {0x11da0, 0x11da9}, {0x11ee0, 0x11ef8},
{0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474}, {0x12480, 0x12543},
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
{0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45},
{0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f},
{0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x17000, 0x187ec},
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
{0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126},
{0x1d129, 0x1d172}, {0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356},
{0x1d360, 0x1d371}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x16e40, 0x16e9a}, {0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f},
{0x17000, 0x187f1}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb},
{0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
{0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172},
{0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d2e0, 0x1d2f3}, {0x1d300, 0x1d356},
{0x1d360, 0x1d378}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb},
{0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006},
{0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, {0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4},
{0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, {0x1e950, 0x1e959}, {0x1ee00, 0x1ee03},
{0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f},
{0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c},
{0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9},
{0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae},
{0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f10c},
{0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202},
{0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f300, 0x1f6d2}, {0x1f6e0, 0x1f6ec},
{0x1f6f0, 0x1f6f6}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b},
{0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad},
{0x1f910, 0x1f91e}, {0x1f920, 0x1f927}, {0x1f933, 0x1f93e}, {0x1f940, 0x1f94b},
{0x1f950, 0x1f95e}, {0x1f980, 0x1f991}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
{0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, {0x1e950, 0x1e959}, {0x1ec71, 0x1ecb4},
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093},
{0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5},
{0x1f100, 0x1f10c}, {0x1f110, 0x1f16b}, {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202},
{0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f260, 0x1f265}, {0x1f300, 0x1f6d4},
{0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f9}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d8},
{0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887},
{0x1f890, 0x1f8ad}, {0x1f900, 0x1f90b}, {0x1f910, 0x1f93e}, {0x1f940, 0x1f970},
{0x1f973, 0x1f976}, {0x1f97c, 0x1f9a2}, {0x1f9b0, 0x1f9b9}, {0x1f9c0, 0x1f9c2},
{0x1f9d0, 0x1f9ff}, {0x1fa60, 0x1fa6d}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d},
{0xe0100, 0xe01ef}
#endif
};
#define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange))
static const chr graphCharTable[] = {
0x38c, 0x589, 0x58a, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8,
0x9d7, 0x9dc, 0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36,
0xa38, 0xa39, 0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3,
0xad0, 0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56,
0xb57, 0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e,
0xb9f, 0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6,
0xcde, 0xcf1, 0xcf2, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81,
0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa,
0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940,
0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d,
0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd
#if TCL_UTF_MAX > 4
0x38c, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8, 0x9d7, 0x9dc,
0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38, 0xa39,
0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3, 0xad0, 0xb0f,
0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56, 0xb57, 0xb5c, 0xb5d,
0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4,
0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6, 0xcde, 0xcf1, 0xcf2,
0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81, 0xe82, 0xe84, 0xe87,
0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xec6, 0x10c7,
0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1f59, 0x1f5b, 0x1f5d,
0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41,
0xfb43, 0xfb44, 0xfffc, 0xfffd
#if CHRBITS > 16
,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4,
0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333,
0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x118ff, 0x16a6e, 0x16a6f,
0x16fe0, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb,
0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x1145e, 0x118ff, 0x11d08,
0x11d09, 0x11d3a, 0x11d3c, 0x11d3d, 0x11d67, 0x11d68, 0x11d90, 0x11d91, 0x16a6e,
0x16a6f, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb,
0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27,
0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54,
0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e,
0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f930, 0x1f9c0
0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f97a
#endif
};
+4 -1
View File
@@ -469,7 +469,6 @@ declare 128 {
declare 129 {
int Tcl_Eval(Tcl_Interp *interp, const char *script)
}
# This is obsolete, use Tcl_FSEvalFile
declare 130 {
int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName)
}
@@ -2370,6 +2369,10 @@ declare 1 macosx {
export {
void Tcl_Main(int argc, char **argv, Tcl_AppInitProc *appInitProc)
}
export {
void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc,
Tcl_Interp *interp)
}
export {
const char *Tcl_InitStubs(Tcl_Interp *interp, const char *version,
int exact)
+4 -4
View File
@@ -55,10 +55,10 @@ extern "C" {
#define TCL_MAJOR_VERSION 8
#define TCL_MINOR_VERSION 6
#define TCL_RELEASE_LEVEL TCL_FINAL_RELEASE
#define TCL_RELEASE_SERIAL 6
#define TCL_RELEASE_SERIAL 8
#define TCL_VERSION "8.6"
#define TCL_PATCH_LEVEL "8.6.6"
#define TCL_PATCH_LEVEL "8.6.8"
/*
*----------------------------------------------------------------------------
@@ -1986,7 +1986,7 @@ typedef struct Tcl_Token {
* TCL_TOKEN_OPERATOR - The token describes one expression operator.
* An operator might be the name of a math
* function such as "abs". A TCL_TOKEN_OPERATOR
* token is always preceeded by one
* token is always preceded by one
* TCL_TOKEN_SUB_EXPR token for the operator's
* subexpression, and is followed by zero or more
* TCL_TOKEN_SUB_EXPR tokens for the operator's
@@ -2622,7 +2622,7 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
#ifndef TCL_NO_DEPRECATED
/*
* These function have been renamed. The old names are deprecated, but we
* define these macros for backwards compatibilty.
* define these macros for backwards compatibility.
*/
# define Tcl_Ckalloc Tcl_Alloc
+12 -11
View File
@@ -2248,23 +2248,24 @@ GetListIndexOperand(
Tcl_Token* tokenPtr = *tokenPtrPtr;
/* INOUT: Pointer to the next token in the
* source code */
Tcl_Obj* intObj; /* Integer from the source code */
int status; /* Tcl status return */
Tcl_Obj *value;
int status;
/*
* Extract the next token as a string.
*/
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &intObj) != TCL_OK) {
/* General operand validity check */
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &value) != TCL_OK) {
return TCL_ERROR;
}
/* Convert to an integer, advance to the next token and return. */
/*
* Convert to an integer, advance to the next token and return.
* NOTE: Indexing a list with an index before it yields the
* same result as indexing after it, and might be more easily portable
* when list size limits grow.
*/
status = TclIndexEncode(interp, value,
TCL_INDEX_BEFORE,TCL_INDEX_BEFORE, result);
status = TclGetIntForIndex(interp, intObj, -2, result);
Tcl_DecrRefCount(intObj);
Tcl_DecrRefCount(value);
*tokenPtrPtr = TokenAfter(tokenPtr);
return status;
}
+187 -120
View File
@@ -234,7 +234,7 @@ static const CmdInfo builtInCmds[] = {
{"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE},
{"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE},
{"package", Tcl_PackageObjCmd, NULL, NULL, CMD_IS_SAFE},
{"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE},
{"proc", Tcl_ProcObjCmd, NULL, NULL, CMD_IS_SAFE},
{"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE},
{"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE},
@@ -2042,11 +2042,11 @@ Tcl_CreateCommand(
{
Interp *iPtr = (Interp *) interp;
ImportRef *oldRefPtr = NULL;
Namespace *nsPtr, *dummy1, *dummy2;
Command *cmdPtr, *refCmdPtr;
Namespace *nsPtr;
Command *cmdPtr;
Tcl_HashEntry *hPtr;
const char *tail;
int isNew;
int isNew = 0, deleted = 0;
ImportedCmdData *dataPtr;
if (iPtr->flags & DELETED) {
@@ -2059,32 +2059,52 @@ Tcl_CreateCommand(
}
/*
* Determine where the command should reside. If its name contains
* namespace qualifiers, we put it in the specified namespace; otherwise,
* we always put it in the global namespace.
* If the command name we seek to create already exists, we need to
* delete that first. That can be tricky in the presence of traces.
* Loop until we no longer find an existing command in the way, or
* until we've deleted one command and that didn't finish the job.
*/
if (strstr(cmdName, "::") != NULL) {
TclGetNamespaceForQualName(interp, cmdName, NULL,
TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
if ((nsPtr == NULL) || (tail == NULL)) {
return (Tcl_Command) NULL;
while (1) {
/*
* Determine where the command should reside. If its name contains
* namespace qualifiers, we put it in the specified namespace;
* otherwise, we always put it in the global namespace.
*/
if (strstr(cmdName, "::") != NULL) {
Namespace *dummy1, *dummy2;
TclGetNamespaceForQualName(interp, cmdName, NULL,
TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
if ((nsPtr == NULL) || (tail == NULL)) {
return (Tcl_Command) NULL;
}
} else {
nsPtr = iPtr->globalNsPtr;
tail = cmdName;
}
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
if (isNew || deleted) {
/*
* isNew - No conflict with existing command.
* deleted - We've already deleted a conflicting command
*/
break;
}
} else {
nsPtr = iPtr->globalNsPtr;
tail = cmdName;
}
/* An existing command conflicts. Try to delete it.. */
cmdPtr = Tcl_GetHashValue(hPtr);
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
if (!isNew) {
/*
* Command already exists. Delete the old one. Be careful to preserve
* Be careful to preserve
* any existing import links so we can restore them down below. That
* way, you can redefine a command and its import status will remain
* intact.
*/
cmdPtr = Tcl_GetHashValue(hPtr);
cmdPtr->refCount++;
if (cmdPtr->importRefPtr) {
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
@@ -2097,18 +2117,21 @@ Tcl_CreateCommand(
cmdPtr->importRefPtr = NULL;
}
TclCleanupCommandMacro(cmdPtr);
deleted = 1;
}
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
if (!isNew) {
/*
* If the deletion callback recreated the command, just throw away
* the new command (if we try to delete it again, we could get
* stuck in an infinite loop).
*/
if (!isNew) {
/*
* If the deletion callback recreated the command, just throw away
* the new command (if we try to delete it again, we could get
* stuck in an infinite loop).
*/
ckfree(Tcl_GetHashValue(hPtr));
}
if (!deleted) {
ckfree(Tcl_GetHashValue(hPtr));
}
} else {
/*
* Command resolvers (per-interp, per-namespace) might have resolved
* to a command for the given namespace scope with this command not
@@ -2156,7 +2179,7 @@ Tcl_CreateCommand(
if (oldRefPtr != NULL) {
cmdPtr->importRefPtr = oldRefPtr;
while (oldRefPtr != NULL) {
refCmdPtr = oldRefPtr->importedCmdPtr;
Command *refCmdPtr = oldRefPtr->importedCmdPtr;
dataPtr = refCmdPtr->objClientData;
dataPtr->realCmdPtr = cmdPtr;
oldRefPtr = oldRefPtr->nextPtr;
@@ -2211,37 +2234,34 @@ Tcl_CreateObjCommand(
* name. */
ClientData clientData, /* Arbitrary value to pass to object
* function. */
Tcl_CmdDeleteProc *deleteProc)
Tcl_CmdDeleteProc *deleteProc
/* If not NULL, gives a function to call when
* this command is deleted. */
)
{
Interp *iPtr = (Interp *) interp;
ImportRef *oldRefPtr = NULL;
Namespace *nsPtr, *dummy1, *dummy2;
Command *cmdPtr, *refCmdPtr;
Tcl_HashEntry *hPtr;
Namespace *nsPtr;
const char *tail;
int isNew;
ImportedCmdData *dataPtr;
if (iPtr->flags & DELETED) {
/*
* The interpreter is being deleted. Don't create any new commands;
* it's not safe to muck with the interpreter anymore.
*/
return (Tcl_Command) NULL;
}
/*
* Determine where the command should reside. If its name contains
* namespace qualifiers, we put it in the specified namespace; otherwise,
* we always put it in the global namespace.
* namespace qualifiers, we put it in the specified namespace;
* otherwise, we always put it in the global namespace.
*/
if (strstr(cmdName, "::") != NULL) {
Namespace *dummy1, *dummy2;
TclGetNamespaceForQualName(interp, cmdName, NULL,
TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
if ((nsPtr == NULL) || (tail == NULL)) {
return (Tcl_Command) NULL;
}
@@ -2250,12 +2270,49 @@ Tcl_CreateObjCommand(
tail = cmdName;
}
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
TclInvalidateNsPath(nsPtr);
if (!isNew) {
cmdPtr = Tcl_GetHashValue(hPtr);
return TclCreateObjCommandInNs(interp, tail, (Tcl_Namespace *) nsPtr,
proc, clientData, deleteProc);
}
/* Command already exists. */
Tcl_Command
TclCreateObjCommandInNs (
Tcl_Interp *interp,
const char *cmdName, /* Name of command, without any namespace components */
Tcl_Namespace *namespace, /* The namespace to create the command in */
Tcl_ObjCmdProc *proc, /* Object-based function to associate with
* name. */
ClientData clientData, /* Arbitrary value to pass to object
* function. */
Tcl_CmdDeleteProc *deleteProc
/* If not NULL, gives a function to call when
* this command is deleted. */
) {
int deleted = 0, isNew = 0;
Command *cmdPtr;
ImportRef *oldRefPtr = NULL;
ImportedCmdData *dataPtr;
Tcl_HashEntry *hPtr;
Namespace *nsPtr = (Namespace *) namespace;
/*
* If the command name we seek to create already exists, we need to
* delete that first. That can be tricky in the presence of traces.
* Loop until we no longer find an existing command in the way, or
* until we've deleted one command and that didn't finish the job.
*/
while (1) {
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew);
if (isNew || deleted) {
/*
* isNew - No conflict with existing command.
* deleted - We've already deleted a conflicting command
*/
break;
}
/* An existing command conflicts. Try to delete it.. */
cmdPtr = Tcl_GetHashValue(hPtr);
/*
* [***] This is wrong. See Tcl Bug a16752c252.
@@ -2286,25 +2343,32 @@ Tcl_CreateObjCommand(
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
}
/* Make sure namespace doesn't get deallocated. */
cmdPtr->nsPtr->refCount++;
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
nsPtr = (Namespace *) TclEnsureNamespace(interp,
(Tcl_Namespace *)cmdPtr->nsPtr);
TclNsDecrRefCount(cmdPtr->nsPtr);
if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) {
oldRefPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = NULL;
}
TclCleanupCommandMacro(cmdPtr);
deleted = 1;
}
if (!isNew) {
/*
* If the deletion callback recreated the command, just throw away
* the new command (if we try to delete it again, we could get
* stuck in an infinite loop).
*/
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
if (!isNew) {
/*
* If the deletion callback recreated the command, just throw away
* the new command (if we try to delete it again, we could get
* stuck in an infinite loop).
*/
ckfree(Tcl_GetHashValue(hPtr));
}
ckfree(Tcl_GetHashValue(hPtr));
}
} else {
if (!deleted) {
/*
* Command resolvers (per-interp, per-namespace) might have resolved
* to a command for the given namespace scope with this command not
@@ -2315,7 +2379,7 @@ Tcl_CreateObjCommand(
* commands.
*/
TclInvalidateCmdLiteral(interp, tail, nsPtr);
TclInvalidateCmdLiteral(interp, cmdName, nsPtr);
/*
* The list of command exported from the namespace might have changed.
@@ -2324,6 +2388,7 @@ Tcl_CreateObjCommand(
*/
TclInvalidateNsCmdLookup(nsPtr);
TclInvalidateNsPath(nsPtr);
}
cmdPtr = ckalloc(sizeof(Command));
Tcl_SetHashValue(hPtr, cmdPtr);
@@ -2351,7 +2416,7 @@ Tcl_CreateObjCommand(
if (oldRefPtr != NULL) {
cmdPtr->importRefPtr = oldRefPtr;
while (oldRefPtr != NULL) {
refCmdPtr = oldRefPtr->importedCmdPtr;
Command *refCmdPtr = oldRefPtr->importedCmdPtr;
dataPtr = refCmdPtr->objClientData;
dataPtr->realCmdPtr = cmdPtr;
oldRefPtr = oldRefPtr->nextPtr;
@@ -2544,10 +2609,6 @@ TclRenameCommand(
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, NULL);
return TCL_ERROR;
}
cmdNsPtr = cmdPtr->nsPtr;
oldFullName = Tcl_NewObj();
Tcl_IncrRefCount(oldFullName);
Tcl_GetCommandFullName(interp, cmd, oldFullName);
/*
* If the new command name is NULL or empty, delete the command. Do this
@@ -2556,10 +2617,14 @@ TclRenameCommand(
if ((newName == NULL) || (*newName == '\0')) {
Tcl_DeleteCommandFromToken(interp, cmd);
result = TCL_OK;
goto done;
return TCL_OK;
}
cmdNsPtr = cmdPtr->nsPtr;
oldFullName = Tcl_NewObj();
Tcl_IncrRefCount(oldFullName);
Tcl_GetCommandFullName(interp, cmd, oldFullName);
/*
* Make sure that the destination command does not already exist. The
* rename operation is like creating a command, so we should automatically
@@ -3058,7 +3123,7 @@ Tcl_DeleteCommandFromToken(
/*
* We must delete this command, even though both traces and delete procs
* may try to avoid this (renaming the command etc). Also traces and
* delete procs may try to delete the command themsevles. This flag
* delete procs may try to delete the command themselves. This flag
* declares that a delete is in progress and that recursive deletes should
* be ignored.
*/
@@ -3070,6 +3135,8 @@ Tcl_DeleteCommandFromToken(
* traces.
*/
cmdPtr->nsPtr->refCount++;
if (cmdPtr->tracePtr != NULL) {
CommandTrace *tracePtr;
CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);
@@ -3097,6 +3164,7 @@ Tcl_DeleteCommandFromToken(
*/
TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
TclNsDecrRefCount(cmdPtr->nsPtr);
/*
* If the command being deleted has a compile function, increment the
@@ -3543,7 +3611,7 @@ OldMathFuncProc(
args[k].type = TCL_INT;
break;
}
if (Tcl_GetWideIntFromObj(interp, valuePtr, &args[k].wideValue)
if (TclGetWideIntFromObj(interp, valuePtr, &args[k].wideValue)
== TCL_OK) {
args[k].type = TCL_WIDE_INT;
break;
@@ -3569,7 +3637,7 @@ OldMathFuncProc(
return TCL_ERROR;
}
valuePtr = Tcl_GetObjResult(interp);
Tcl_GetWideIntFromObj(NULL, valuePtr, &args[k].wideValue);
TclGetWideIntFromObj(NULL, valuePtr, &args[k].wideValue);
Tcl_ResetResult(interp);
break;
}
@@ -4384,6 +4452,8 @@ TclNRRunCallbacks(
(void) Tcl_GetObjResult(interp);
}
/* This is the trampoline. */
while (TOP_CB(interp) != rootPtr) {
callbackPtr = TOP_CB(interp);
procPtr = callbackPtr->procPtr;
@@ -4517,7 +4587,7 @@ TEOV_Exception(
if (result == TCL_RETURN) {
result = TclUpdateReturnInfo(iPtr);
}
if ((result != TCL_ERROR) && !allowExceptions) {
if ((result != TCL_OK) && (result != TCL_ERROR) && !allowExceptions) {
ProcessUnexpectedResult(interp, result);
result = TCL_ERROR;
}
@@ -7174,7 +7244,7 @@ ExprIsqrtFunc(
}
break;
default:
if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
if (TclGetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
return TCL_ERROR;
}
if (w < 0) {
@@ -7536,7 +7606,19 @@ ExprEntierFunc(
if (type == TCL_NUMBER_DOUBLE) {
d = *((const double *) ptr);
if ((d >= (double)LONG_MAX) || (d <= (double)LONG_MIN)) {
if ((d < (double)LONG_MAX) && (d > (double)LONG_MIN)) {
long result = (long) d;
Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
return TCL_OK;
#ifndef TCL_WIDE_INT_IS_LONG
} else if ((d < (double)LLONG_MAX) && (d > (double)LLONG_MIN)) {
Tcl_WideInt result = (Tcl_WideInt) d;
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result));
return TCL_OK;
#endif
} else {
mp_int big;
if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
@@ -7545,11 +7627,6 @@ ExprEntierFunc(
}
Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
return TCL_OK;
} else {
long result = (long) d;
Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
return TCL_OK;
}
}
@@ -7617,7 +7694,7 @@ ExprWideFunc(
return TCL_ERROR;
}
objPtr = Tcl_GetObjResult(interp);
if (Tcl_GetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) {
if (TclGetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) {
/*
* Truncate the bignum; keep only bits in wide int range.
*/
@@ -7628,7 +7705,7 @@ ExprWideFunc(
mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big);
objPtr = Tcl_NewBignumObj(&big);
Tcl_IncrRefCount(objPtr);
Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
TclGetWideIntFromObj(NULL, objPtr, &wResult);
Tcl_DecrRefCount(objPtr);
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
@@ -7658,8 +7735,8 @@ ExprRandFunc(
iPtr->flags |= RAND_SEED_INITIALIZED;
/*
* Take into consideration the thread this interp is running in order
* to insure different seeds in different threads (bug #416643)
* To ensure different seeds in different threads (bug #416643),
* take into consideration the thread this interp is running in.
*/
iPtr->randSeed = TclpGetClicks() + (PTR2INT(Tcl_GetCurrentThread())<<12);
@@ -8123,6 +8200,22 @@ Tcl_NRCreateCommand(
cmdPtr->nreProc = nreProc;
return (Tcl_Command) cmdPtr;
}
Tcl_Command
TclNRCreateCommandInNs (
Tcl_Interp *interp,
const char *cmdName,
Tcl_Namespace *nsPtr,
Tcl_ObjCmdProc *proc,
Tcl_ObjCmdProc *nreProc,
ClientData clientData,
Tcl_CmdDeleteProc *deleteProc) {
Command *cmdPtr = (Command *)
TclCreateObjCommandInNs(interp,cmdName,nsPtr,proc,clientData,deleteProc);
cmdPtr->nreProc = nreProc;
return (Tcl_Command) cmdPtr;
}
/****************************************************************************
* Stuff for the public api
@@ -8316,18 +8409,12 @@ TclNRTailcallObjCmd(
if (objc > 1) {
Tcl_Obj *listPtr, *nsObjPtr;
Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
Tcl_Namespace *ns1Ptr;
/* The tailcall data is in a Tcl list: the first element is the
* namespace, the rest the command to be tailcalled. */
listPtr = Tcl_NewListObj(objc, objv);
nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr))
|| (nsPtr != ns1Ptr)) {
Tcl_Panic("Tailcall failed to find the proper namespace");
}
listPtr = Tcl_NewListObj(objc, objv);
TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
iPtr->varFramePtr->tailcallPtr = listPtr;
@@ -8908,9 +8995,9 @@ TclNRCoroutineObjCmd(
{
Command *cmdPtr;
CoroutineData *corPtr;
const char *fullName, *procName;
Namespace *nsPtr, *altNsPtr, *cxtNsPtr;
Tcl_DString ds;
const char *procName, *simpleName;
Namespace *nsPtr, *altNsPtr, *cxtNsPtr,
*inNsPtr = (Namespace *)TclGetCurrentNamespace(interp);
Namespace *lookupNsPtr = iPtr->varFramePtr->nsPtr;
if (objc < 3) {
@@ -8918,34 +9005,21 @@ TclNRCoroutineObjCmd(
return TCL_ERROR;
}
/*
* FIXME: this is copy/pasted from Tcl_ProcObjCommand. Should have
* something in tclUtil.c to find the FQ name.
*/
fullName = TclGetString(objv[1]);
TclGetNamespaceForQualName(interp, fullName, NULL, 0,
&nsPtr, &altNsPtr, &cxtNsPtr, &procName);
procName = TclGetString(objv[1]);
TclGetNamespaceForQualName(interp, procName, inNsPtr, 0,
&nsPtr, &altNsPtr, &cxtNsPtr, &simpleName);
if (nsPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\": unknown namespace",
fullName));
procName));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", NULL);
return TCL_ERROR;
}
if (procName == NULL) {
if (simpleName == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\": bad procedure name",
fullName));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", fullName, NULL);
return TCL_ERROR;
}
if ((nsPtr != iPtr->globalNsPtr)
&& (procName != NULL) && (procName[0] == ':')) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\" in non-global namespace with"
" name starting with \":\"", procName));
procName));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", procName, NULL);
return TCL_ERROR;
}
@@ -8957,16 +9031,9 @@ TclNRCoroutineObjCmd(
corPtr = ckalloc(sizeof(CoroutineData));
Tcl_DStringInit(&ds);
if (nsPtr != iPtr->globalNsPtr) {
Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
TclDStringAppendLiteral(&ds, "::");
}
Tcl_DStringAppend(&ds, procName, -1);
cmdPtr = (Command *) Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds),
/*objProc*/ NULL, TclNRInterpCoroutine, corPtr, DeleteCoroutine);
Tcl_DStringFree(&ds);
cmdPtr = (Command *) TclNRCreateCommandInNs(interp, simpleName,
(Tcl_Namespace *)nsPtr, /*objProc*/ NULL, TclNRInterpCoroutine,
corPtr, DeleteCoroutine);
corPtr->cmdPtr = cmdPtr;
cmdPtr->refCount++;
@@ -9027,7 +9094,7 @@ TclNRCoroutineObjCmd(
TclNRAddCallback(interp, NRCoroutineExitCallback, corPtr,
NULL, NULL, NULL);
/* insure that the command is looked up in the correct namespace */
/* ensure that the command is looked up in the correct namespace */
iPtr->lookupNsPtr = lookupNsPtr;
Tcl_NREvalObj(interp, Tcl_NewListObj(objc-2, objv+2), 0);
iPtr->numLevels--;
+3 -3
View File
@@ -454,7 +454,7 @@ SetByteArrayFromAny(
const char *src, *srcEnd;
unsigned char *dst;
ByteArray *byteArrayPtr;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
if (objPtr->typePtr != &tclByteArrayType) {
src = TclGetStringFromObj(objPtr, &length);
@@ -1210,7 +1210,7 @@ BinaryFormatCmd(
badField:
{
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
char buf[TCL_UTF_MAX + 1];
TclUtfToUniChar(errorString, &ch);
@@ -1580,7 +1580,7 @@ BinaryScanCmd(
badField:
{
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
char buf[TCL_UTF_MAX + 1];
TclUtfToUniChar(errorString, &ch);
+282 -2301
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-57
View File
@@ -512,63 +512,6 @@ Tcl_ContinueObjCmd(
return TCL_CONTINUE;
}
/*
*----------------------------------------------------------------------
*
* Tcl_EncodingObjCmd --
*
* This command manipulates encodings.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
int
Tcl_EncodingObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
int index;
static const char *const optionStrings[] = {
"convertfrom", "convertto", "dirs", "names", "system",
NULL
};
enum options {
ENC_CONVERTFROM, ENC_CONVERTTO, ENC_DIRS, ENC_NAMES, ENC_SYSTEM
};
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum options) index) {
case ENC_CONVERTTO:
return EncodingConverttoObjCmd(dummy, interp, objc, objv);
case ENC_CONVERTFROM:
return EncodingConvertfromObjCmd(dummy, interp, objc, objv);
case ENC_DIRS:
return EncodingDirsObjCmd(dummy, interp, objc, objv);
case ENC_NAMES:
return EncodingNamesObjCmd(dummy, interp, objc, objv);
case ENC_SYSTEM:
return EncodingSystemObjCmd(dummy, interp, objc, objv);
}
return TCL_OK;
}
/*
*-----------------------------------------------------------------------------
*
+50 -50
View File
@@ -64,8 +64,9 @@ typedef struct SortInfo {
* SORTMODE_COMMAND. Pre-initialized to hold
* base of command. */
int *indexv; /* If the -index option was specified, this
* holds the indexes contained in the list
* supplied as an argument to that option.
* holds an encoding of the indexes contained
* in the list supplied as an argument to
* that option.
* NULL if no indexes supplied, and points to
* singleIndex field when only one
* supplied. */
@@ -92,14 +93,6 @@ typedef struct SortInfo {
#define SORTMODE_DICTIONARY 4
#define SORTMODE_ASCII_NC 8
/*
* Magic values for the index field of the SortInfo structure. Note that the
* index "end-1" will be translated to SORTIDX_END-1, etc.
*/
#define SORTIDX_NONE -1 /* Not indexed; use whole value. */
#define SORTIDX_END -2 /* Indexed from end. */
/*
* Forward declarations for procedures defined in this file:
*/
@@ -2754,21 +2747,10 @@ Tcl_LreplaceObjCmd(
if (first < 0) {
first = 0;
}
/*
* Complain if the user asked for a start element that is greater than the
* list length. This won't ever trigger for the "end-*" case as that will
* be properly constrained by TclGetIntForIndex because we use listLen-1
* (to allow for replacing the last elem).
*/
if ((first > listLen) && (listLen > 0)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"list doesn't contain element %s", TclGetString(objv[2])));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPLACE", "BADIDX",
NULL);
return TCL_ERROR;
if (first > listLen) {
first = listLen;
}
if (last >= listLen) {
last = listLen - 1;
}
@@ -2913,7 +2895,7 @@ Tcl_LsearchObjCmd(
Tcl_Obj *const objv[]) /* Argument values. */
{
const char *bytes, *patternBytes;
int i, match, index, result, listc, length, elemLen, bisect;
int i, match, index, result=TCL_OK, listc, length, elemLen, bisect;
int dataType, isIncreasing, lower, upper, offset;
Tcl_WideInt patWide, objWide;
int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
@@ -3113,13 +3095,26 @@ Tcl_LsearchObjCmd(
*/
for (j=0 ; j<sortInfo.indexc ; j++) {
if (TclGetIntForIndexM(interp, indices[j], SORTIDX_END,
&sortInfo.indexv[j]) != TCL_OK) {
int encoded = 0;
if (TclIndexEncode(interp, indices[j], TCL_INDEX_BEFORE,
TCL_INDEX_AFTER, &encoded) != TCL_OK) {
result = TCL_ERROR;
}
if ((encoded == TCL_INDEX_BEFORE)
|| (encoded == TCL_INDEX_AFTER)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"index \"%s\" cannot select an element "
"from any list", Tcl_GetString(indices[j])));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
"OUTOFRANGE", NULL);
result = TCL_ERROR;
}
if (result == TCL_ERROR) {
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (-index option item number %d)", j));
result = TCL_ERROR;
goto done;
}
sortInfo.indexv[j] = encoded;
}
break;
}
@@ -3492,8 +3487,8 @@ Tcl_LsearchObjCmd(
itemPtr = Tcl_NewIntObj(i);
for (j=0 ; j<sortInfo.indexc ; j++) {
Tcl_ListObjAppendElement(interp, itemPtr,
Tcl_NewIntObj(sortInfo.indexv[j]));
Tcl_ListObjAppendElement(interp, itemPtr, Tcl_NewIntObj(
TclIndexDecode(sortInfo.indexv[j], listc)));
}
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
} else {
@@ -3514,8 +3509,8 @@ Tcl_LsearchObjCmd(
itemPtr = Tcl_NewIntObj(index);
for (j=0 ; j<sortInfo.indexc ; j++) {
Tcl_ListObjAppendElement(interp, itemPtr,
Tcl_NewIntObj(sortInfo.indexv[j]));
Tcl_ListObjAppendElement(interp, itemPtr, Tcl_NewIntObj(
TclIndexDecode(sortInfo.indexv[j], listc)));
}
Tcl_SetObjResult(interp, itemPtr);
} else {
@@ -3732,7 +3727,7 @@ Tcl_LsortObjCmd(
sortInfo.isIncreasing = 1;
break;
case LSORT_INDEX: {
int indexc, dummy;
int indexc;
Tcl_Obj **indexv;
if (i == objc-2) {
@@ -3758,8 +3753,20 @@ Tcl_LsortObjCmd(
*/
for (j=0 ; j<indexc ; j++) {
if (TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
&dummy) != TCL_OK) {
int encoded = 0;
int result = TclIndexEncode(interp, indexv[j],
TCL_INDEX_BEFORE, TCL_INDEX_AFTER, &encoded);
if ((result == TCL_OK) && ((encoded == TCL_INDEX_BEFORE)
|| (encoded == TCL_INDEX_AFTER))) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"index \"%s\" cannot select an element "
"from any list", Tcl_GetString(indexv[j])));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
"OUTOFRANGE", NULL);
result = TCL_ERROR;
}
if (result == TCL_ERROR) {
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (-index option item number %d)", j));
sortInfo.resultCode = TCL_ERROR;
@@ -3839,8 +3846,8 @@ Tcl_LsortObjCmd(
* might be decreased by 1 later. */
}
for (j=0 ; j<sortInfo.indexc ; j++) {
TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
&sortInfo.indexv[j]);
/* Prescreened values, no errors or out of range possible */
TclIndexEncode(NULL, indexv[j], 0, 0, &sortInfo.indexv[j]);
}
}
@@ -3911,10 +3918,7 @@ Tcl_LsortObjCmd(
* offset of the element within each group by which to sort.
*/
groupOffset = sortInfo.indexv[0];
if (groupOffset <= SORTIDX_END) {
groupOffset = (groupOffset - SORTIDX_END) + groupSize - 1;
}
groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1);
if (groupOffset < 0 || groupOffset >= groupSize) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"when used with \"-stride\", the leading \"-index\""
@@ -3933,6 +3937,9 @@ Tcl_LsortObjCmd(
/*
* Do not shrink the actual memory block used; that doesn't
* work with TclStackAlloc-allocated memory. [Bug 2918962]
*
* TODO: Consider a pointer increment to replace this
* array shift.
*/
for (i = 0; i < sortInfo.indexc; i++) {
@@ -4345,7 +4352,7 @@ static int
DictionaryCompare(
const char *left, const char *right) /* The strings to compare. */
{
Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
Tcl_UniChar uniLeft = 0, uniRight = 0, uniLeftLower, uniRightLower;
int diff, zeros;
int secondaryDiff = 0;
@@ -4501,15 +4508,8 @@ SelectObjFromSublist(
infoPtr->resultCode = TCL_ERROR;
return NULL;
}
index = infoPtr->indexv[i];
/*
* Adjust for end-based indexing.
*/
if (index < SORTIDX_NONE) {
index += listLen + 1;
}
index = TclIndexDecode(infoPtr->indexv[i], listLen - 1);
if (Tcl_ListObjIndex(infoPtr->interp, objPtr, index,
&currentObj) != TCL_OK) {
+251 -187
View File
@@ -309,7 +309,7 @@ Tcl_RegexpObjCmd(
eflags = 0;
} else if (offset > stringLength) {
eflags = TCL_REG_NOTBOL;
} else if (Tcl_GetUniChar(objPtr, offset-1) == (Tcl_UniChar)'\n') {
} else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') {
eflags = 0;
} else {
eflags = TCL_REG_NOTBOL;
@@ -1037,7 +1037,7 @@ Tcl_SplitObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
int len;
const char *splitChars;
const char *stringPtr;
@@ -1080,13 +1080,22 @@ Tcl_SplitObjCmd(
Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);
for ( ; stringPtr < end; stringPtr += len) {
int fullchar;
len = TclUtfToUniChar(stringPtr, &ch);
fullchar = ch;
#if TCL_UTF_MAX == 4
if (!len) {
len += TclUtfToUniChar(stringPtr, &ch);
fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000;
}
#endif
/*
* Assume Tcl_UniChar is an integral type...
*/
hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR((int) ch),
hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(fullchar),
&isNew);
if (isNew) {
TclNewStringObj(objPtr, stringPtr, len);
@@ -1122,7 +1131,7 @@ Tcl_SplitObjCmd(
} else {
const char *element, *p, *splitEnd;
int splitLen;
Tcl_UniChar splitChar;
Tcl_UniChar splitChar = 0;
/*
* Normal case: split on any of a given set of characters. Discard
@@ -1451,7 +1460,7 @@ StringIsCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
const char *string1, *end, *stop;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
int (*chcomp)(int) = NULL; /* The UniChar comparison function. */
int i, failat = 0, result = 1, strict = 0, index, length1, length2;
Tcl_Obj *objPtr, *failVarObj = NULL;
@@ -1562,7 +1571,6 @@ StringIsCmd(
chcomp = Tcl_UniCharIsDigit;
break;
case STR_IS_DOUBLE: {
/* TODO */
if ((objPtr->typePtr == &tclDoubleType) ||
(objPtr->typePtr == &tclIntType) ||
#ifndef TCL_WIDE_INT_IS_LONG
@@ -1646,7 +1654,7 @@ StringIsCmd(
}
break;
case STR_IS_WIDE:
if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) {
if (TCL_OK == TclGetWideIntFromObj(NULL, objPtr, &w)) {
break;
}
@@ -1783,8 +1791,16 @@ StringIsCmd(
}
end = string1 + length1;
for (; string1 < end; string1 += length2, failat++) {
int fullchar;
length2 = TclUtfToUniChar(string1, &ch);
if (!chcomp(ch)) {
fullchar = ch;
#if TCL_UTF_MAX == 4
if (!length2) {
length2 = TclUtfToUniChar(string1, &ch);
fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000;
}
#endif
if (!chcomp(fullchar)) {
result = 0;
break;
}
@@ -2336,7 +2352,7 @@ StringRplcCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_UniChar *ustring;
int first, last, length;
int first, last, length, end;
if (objc < 4 || objc > 5) {
Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?");
@@ -2344,20 +2360,38 @@ StringRplcCmd(
}
ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
length--;
end = length - 1;
if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK ||
TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK){
if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK ||
TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK){
return TCL_ERROR;
}
if ((last < first) || (last < 0) || (first > length)) {
/*
* The following test screens out most empty substrings as
* candidates for replacement. When they are detected, no
* replacement is done, and the result is the original string,
*/
if ((last < 0) || /* Range ends before start of string */
(first > end) || /* Range begins after end of string */
(last < first)) { /* Range begins after it starts */
/*
* BUT!!! when (end < 0) -- an empty original string -- we can
* have (first <= end < 0 <= last) and an empty string is permitted
* to be replaced.
*/
Tcl_SetObjResult(interp, objv[1]);
} else {
Tcl_Obj *resultPtr;
/*
* We are re-fetching in case the string argument is same value as
* an index argument, and shimmering cost us our ustring.
*/
ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
length--;
end = length-1;
if (first < 0) {
first = 0;
@@ -2367,9 +2401,9 @@ StringRplcCmd(
if (objc == 5) {
Tcl_AppendObjToObj(resultPtr, objv[4]);
}
if (last < length) {
if (last < end) {
Tcl_AppendUnicodeToObj(resultPtr, ustring + last + 1,
length - last);
end - last);
}
Tcl_SetObjResult(interp, resultPtr);
}
@@ -2436,7 +2470,7 @@ StringStartCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
const char *p, *string;
int cur, index, length, numChars;
@@ -2497,7 +2531,7 @@ StringEndCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
const char *p, *end, *string;
int cur, index, length, numChars;
@@ -2565,10 +2599,8 @@ StringEqualCmd(
* the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
*/
const char *string1, *string2;
int length1, length2, i, match, length, nocase = 0, reqlength = -1;
typedef int (*strCmpFn_t)(const char *, const char *, unsigned int);
strCmpFn_t strCmpFn;
const char *string2;
int length2, i, match, nocase = 0, reqlength = -1;
if (objc < 3 || objc > 6) {
str_cmp_args:
@@ -2607,78 +2639,7 @@ StringEqualCmd(
objv += objc-2;
if ((reqlength == 0) || (objv[0] == objv[1])) {
/*
* Always match at 0 chars of if it is the same obj.
*/
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
return TCL_OK;
}
if (!nocase && TclIsPureByteArray(objv[0]) &&
TclIsPureByteArray(objv[1])) {
/*
* Use binary versions of comparisons since that won't cause undue
* type conversions and it is much faster. Only do this if we're
* case-sensitive (which is all that really makes sense with byte
* arrays anyway, and we have no memcasecmp() for some reason... :^)
*/
string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1);
string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2);
strCmpFn = (strCmpFn_t) memcmp;
} else if ((objv[0]->typePtr == &tclStringType)
&& (objv[1]->typePtr == &tclStringType)) {
/*
* Do a unicode-specific comparison if both of the args are of String
* type. In benchmark testing this proved the most efficient check
* between the unicode and string comparison operations.
*/
string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1);
string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2);
strCmpFn = (strCmpFn_t)
(nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp);
} else {
/*
* As a catch-all we will work with UTF-8. We cannot use memcmp() as
* that is unsafe with any string containing NUL (\xC0\x80 in Tcl's
* utf rep). We can use the more efficient TclpUtfNcmp2 if we are
* case-sensitive and no specific length was requested.
*/
string1 = (char *) TclGetStringFromObj(objv[0], &length1);
string2 = (char *) TclGetStringFromObj(objv[1], &length2);
if ((reqlength < 0) && !nocase) {
strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
} else {
length1 = Tcl_NumUtfChars(string1, length1);
length2 = Tcl_NumUtfChars(string2, length2);
strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
}
}
if ((reqlength < 0) && (length1 != length2)) {
match = 1; /* This will be reversed below. */
} else {
length = (length1 < length2) ? length1 : length2;
if (reqlength > 0 && reqlength < length) {
length = reqlength;
} else if (reqlength < 0) {
/*
* The requested length is negative, so we ignore it by setting it
* to length + 1 so we correct the match var.
*/
reqlength = length + 1;
}
match = strCmpFn(string1, string2, (unsigned) length);
if ((match == 0) && (reqlength > length)) {
match = length1 - length2;
}
}
match = TclStringCmp (objv[0], objv[1], 0, nocase, reqlength);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1));
return TCL_OK;
@@ -2715,11 +2676,194 @@ StringCmpCmd(
* the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
*/
const char *string1, *string2;
int length1, length2, i, match, length, nocase = 0, reqlength = -1;
typedef int (*strCmpFn_t)(const char *, const char *, unsigned int);
strCmpFn_t strCmpFn;
int match, nocase, reqlength, status;
if ((status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength))
!= TCL_OK) {
return status;
}
objv += objc-2;
match = TclStringCmp (objv[0], objv[1], 0, nocase, reqlength);
Tcl_SetObjResult(interp, Tcl_NewIntObj(match));
return TCL_OK;
}
int TclStringCmp (
Tcl_Obj *value1Ptr,
Tcl_Obj *value2Ptr,
int checkEq, /* comparison is only for equality */
int nocase, /* comparison is not case sensitive */
int reqlength /* requested length */
) {
char *s1, *s2;
int empty, length, match, s1len, s2len;
memCmpFn_t memCmpFn;
if ((reqlength == 0) || (value1Ptr == value2Ptr)) {
/*
* Always match at 0 chars of if it is the same obj.
*/
match = 0;
} else {
if (!nocase && TclIsPureByteArray(value1Ptr)
&& TclIsPureByteArray(value2Ptr)) {
/*
* Use binary versions of comparisons since that won't cause undue
* type conversions and it is much faster. Only do this if we're
* case-sensitive (which is all that really makes sense with byte
* arrays anyway, and we have no memcasecmp() for some reason... :^)
*/
s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len);
s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
memCmpFn = memcmp;
} else if ((value1Ptr->typePtr == &tclStringType)
&& (value2Ptr->typePtr == &tclStringType)) {
/*
* Do a unicode-specific comparison if both of the args are of
* String type. If the char length == byte length, we can do a
* memcmp. In benchmark testing this proved the most efficient
* check between the unicode and string comparison operations.
*/
if (nocase) {
s1 = (char *) Tcl_GetUnicodeFromObj(value1Ptr, &s1len);
s2 = (char *) Tcl_GetUnicodeFromObj(value2Ptr, &s2len);
memCmpFn = (memCmpFn_t)Tcl_UniCharNcasecmp;
} else {
s1len = Tcl_GetCharLength(value1Ptr);
s2len = Tcl_GetCharLength(value2Ptr);
if ((s1len == value1Ptr->length)
&& (value1Ptr->bytes != NULL)
&& (s2len == value2Ptr->length)
&& (value2Ptr->bytes != NULL)) {
s1 = value1Ptr->bytes;
s2 = value2Ptr->bytes;
memCmpFn = memcmp;
} else {
s1 = (char *) Tcl_GetUnicode(value1Ptr);
s2 = (char *) Tcl_GetUnicode(value2Ptr);
if (
#ifdef WORDS_BIGENDIAN
1
#else
checkEq
#endif
) {
memCmpFn = memcmp;
s1len *= sizeof(Tcl_UniChar);
s2len *= sizeof(Tcl_UniChar);
} else {
memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp;
}
}
}
} else {
if ((empty = TclCheckEmptyString(value1Ptr)) > 0) {
switch (TclCheckEmptyString(value2Ptr)) {
case -1:
s1 = "";
s1len = 0;
s2 = TclGetStringFromObj(value2Ptr, &s2len);
break;
case 0:
match = -1;
goto matchdone;
case 1:
default: /* avoid warn: `s2` may be used uninitialized */
match = 0;
goto matchdone;
}
} else if (TclCheckEmptyString(value2Ptr) > 0) {
switch (empty) {
case -1:
s2 = "";
s2len = 0;
s1 = TclGetStringFromObj(value1Ptr, &s1len);
break;
case 0:
match = 1;
goto matchdone;
case 1:
default: /* avoid warn: `s1` may be used uninitialized */
match = 0;
goto matchdone;
}
} else {
s1 = TclGetStringFromObj(value1Ptr, &s1len);
s2 = TclGetStringFromObj(value2Ptr, &s2len);
}
if (!nocase && checkEq) {
/*
* When we have equal-length we can check only for (in)equality.
* We can use memcmp in all (n)eq cases because we
* don't need to worry about lexical LE/BE variance.
*/
memCmpFn = memcmp;
} else {
/*
* As a catch-all we will work with UTF-8. We cannot use memcmp() as
* that is unsafe with any string containing NUL (\xC0\x80 in Tcl's
* utf rep). We can use the more efficient TclpUtfNcmp2 if we are
* case-sensitive and no specific length was requested.
*/
if ((reqlength < 0) && !nocase) {
memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
} else {
s1len = Tcl_NumUtfChars(s1, s1len);
s2len = Tcl_NumUtfChars(s2, s2len);
memCmpFn = (memCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
}
}
}
length = (s1len < s2len) ? s1len : s2len;
if (reqlength > 0 && reqlength < length) {
length = reqlength;
} else if (reqlength < 0) {
/*
* The requested length is negative, so we ignore it by setting it to
* length + 1 so we correct the match var.
*/
reqlength = length + 1;
}
if (checkEq && (s1len != s2len)) {
match = 1; /* This will be reversed below. */
} else {
/*
* The comparison function should compare up to the minimum
* byte length only.
*/
match = memCmpFn(s1, s2, (size_t) length);
}
if ((match == 0) && (reqlength > length)) {
match = s1len - s2len;
}
match = (match > 0) ? 1 : (match < 0) ? -1 : 0;
}
matchdone:
return match;
}
int TclStringCmpOpts (
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[], /* Argument objects. */
int *nocase,
int *reqlength
)
{
int i, length;
const char *string;
*reqlength = -1;
*nocase = 0;
if (objc < 3 || objc > 6) {
str_cmp_args:
Tcl_WrongNumArgs(interp, 1, objv,
@@ -2728,106 +2872,27 @@ StringCmpCmd(
}
for (i = 1; i < objc-2; i++) {
string2 = TclGetStringFromObj(objv[i], &length2);
if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) {
nocase = 1;
} else if ((length2 > 1)
&& !strncmp(string2, "-length", (size_t)length2)) {
string = TclGetStringFromObj(objv[i], &length);
if ((length > 1) && !strncmp(string, "-nocase", (size_t)length)) {
*nocase = 1;
} else if ((length > 1)
&& !strncmp(string, "-length", (size_t)length)) {
if (i+1 >= objc-2) {
goto str_cmp_args;
}
i++;
if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) {
return TCL_ERROR;
}
} else {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad option \"%s\": must be -nocase or -length",
string2));
string));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
string2, NULL);
string, NULL);
return TCL_ERROR;
}
}
/*
* From now on, we only access the two objects at the end of the argument
* array.
*/
objv += objc-2;
if ((reqlength == 0) || (objv[0] == objv[1])) {
/*
* Always match at 0 chars of if it is the same obj.
*/
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
return TCL_OK;
}
if (!nocase && TclIsPureByteArray(objv[0]) &&
TclIsPureByteArray(objv[1])) {
/*
* Use binary versions of comparisons since that won't cause undue
* type conversions and it is much faster. Only do this if we're
* case-sensitive (which is all that really makes sense with byte
* arrays anyway, and we have no memcasecmp() for some reason... :^)
*/
string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1);
string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2);
strCmpFn = (strCmpFn_t) memcmp;
} else if ((objv[0]->typePtr == &tclStringType)
&& (objv[1]->typePtr == &tclStringType)) {
/*
* Do a unicode-specific comparison if both of the args are of String
* type. In benchmark testing this proved the most efficient check
* between the unicode and string comparison operations.
*/
string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1);
string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2);
strCmpFn = (strCmpFn_t)
(nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp);
} else {
/*
* As a catch-all we will work with UTF-8. We cannot use memcmp() as
* that is unsafe with any string containing NUL (\xC0\x80 in Tcl's
* utf rep). We can use the more efficient TclpUtfNcmp2 if we are
* case-sensitive and no specific length was requested.
*/
string1 = (char *) TclGetStringFromObj(objv[0], &length1);
string2 = (char *) TclGetStringFromObj(objv[1], &length2);
if ((reqlength < 0) && !nocase) {
strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
} else {
length1 = Tcl_NumUtfChars(string1, length1);
length2 = Tcl_NumUtfChars(string2, length2);
strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
}
}
length = (length1 < length2) ? length1 : length2;
if (reqlength > 0 && reqlength < length) {
length = reqlength;
} else if (reqlength < 0) {
/*
* The requested length is negative, so we ignore it by setting it to
* length + 1 so we correct the match var.
*/
reqlength = length + 1;
}
match = strCmpFn(string1, string2, (unsigned) length);
if ((match == 0) && (reqlength > length)) {
match = length1 - length2;
}
Tcl_SetObjResult(interp,
Tcl_NewIntObj((match > 0) ? 1 : (match < 0) ? -1 : 0));
return TCL_OK;
}
@@ -3250,8 +3315,7 @@ StringTrimCmd(
}
string1 = TclGetStringFromObj(objv[1], &length1);
triml = TclTrimLeft(string1, length1, string2, length2);
trimr = TclTrimRight(string1 + triml, length1 - triml, string2, length2);
triml = TclTrim(string1, length1, string2, length2, &trimr);
Tcl_SetObjResult(interp,
Tcl_NewStringObj(string1 + triml, length1 - triml - trimr));
+15 -3
View File
@@ -322,11 +322,22 @@ TclCompileArraySetCmd(
*/
if (isDataValid && !isDataEven) {
/* Abandon custom compile and let invocation raise the error */
code = TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
goto done;
/*
* We used to compile to the bytecode that would throw the error,
* but that was wrong because it would not invoke the array trace
* on the variable.
*
PushStringLiteral(envPtr, "list must have an even number of elements");
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
TclEmitInt4( 0, envPtr);
goto done;
*
*/
}
/*
@@ -404,6 +415,10 @@ TclCompileArraySetCmd(
* Start issuing instructions to write to the array.
*/
TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr);
TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr);
TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr);
CompileWord(envPtr, dataTokenPtr, interp, 2);
if (!isDataLiteral || !isDataValid) {
/*
@@ -428,9 +443,6 @@ TclCompileArraySetCmd(
TclStoreInt1AtPtr(fwd, envPtr->codeStart+offsetFwd+1);
}
TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr);
TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr);
TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr);
TclEmitInstInt4(INST_FOREACH_START, infoIndex, envPtr);
offsetBack = CurrentOffset(envPtr);
Emit14Inst( INST_LOAD_SCALAR, keyVar, envPtr);
+145 -271
View File
@@ -28,56 +28,39 @@ static void CompileReturnInternal(CompileEnv *envPtr,
static int IndexTailVarIfKnown(Tcl_Interp *interp,
Tcl_Token *varTokenPtr, CompileEnv *envPtr);
#define INDEX_END (-2)
/*
*----------------------------------------------------------------------
*
* GetIndexFromToken --
* TclGetIndexFromToken --
*
* Parse a token and get the encoded version of the index (as understood
* by TEBC), assuming it is at all knowable at compile time. Only handles
* indices that are integers or 'end' or 'end-integer'.
* Parse a token to determine if an index value is known at
* compile time.
*
* Returns:
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
*
* Side effects:
* Sets *index to the index value if successful.
* When TCL_OK is returned, the encoded index value is written
* to *index.
*
*----------------------------------------------------------------------
*/
static inline int
GetIndexFromToken(
int
TclGetIndexFromToken(
Tcl_Token *tokenPtr,
int *index)
int before,
int after,
int *indexPtr)
{
Tcl_Obj *tmpObj = Tcl_NewObj();
int result, idx;
int result = TCL_ERROR;
if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
Tcl_DecrRefCount(tmpObj);
return TCL_ERROR;
}
result = TclGetIntFromObj(NULL, tmpObj, &idx);
if (result == TCL_OK) {
if (idx < 0) {
result = TCL_ERROR;
}
} else {
result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx);
if (result == TCL_OK && idx > INDEX_END) {
result = TCL_ERROR;
}
if (TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
result = TclIndexEncode(NULL, tmpObj, before, after, indexPtr);
}
Tcl_DecrRefCount(tmpObj);
if (result == TCL_OK) {
*index = idx;
}
return result;
}
@@ -144,7 +127,7 @@ TclCompileGlobalCmd(
return TCL_ERROR;
}
/* TODO: Consider what value can pass throug the
/* TODO: Consider what value can pass through the
* IndexTailVarIfKnown() screen. Full CompileWord()
* likely does not apply here. Push known value instead. */
CompileWord(envPtr, varTokenPtr, interp, i);
@@ -1053,7 +1036,7 @@ TclCompileLassignCmd(
*/
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
TclEmitInt4( INDEX_END, envPtr);
TclEmitInt4( TCL_INDEX_END, envPtr);
return TCL_OK;
}
@@ -1104,14 +1087,14 @@ TclCompileLindexCmd(
}
idxTokenPtr = TokenAfter(valTokenPtr);
if (GetIndexFromToken(idxTokenPtr, &idx) == TCL_OK) {
if (TclGetIndexFromToken(idxTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_BEFORE,
&idx) == TCL_OK) {
/*
* All checks have been completed, and we have exactly one of these
* constructs:
* lindex <arbitraryValue> <posInt>
* lindex <arbitraryValue> end-<posInt>
* This is best compiled as a push of the arbitrary value followed by
* an "immediate lindex" which is the most efficient variety.
* The idxTokenPtr parsed as a valid index value and was
* encoded as expected by INST_LIST_INDEX_IMM.
*
* NOTE: that we rely on indexing before a list producing the
* same result as indexing after a list.
*/
CompileWord(envPtr, valTokenPtr, interp, 1);
@@ -1258,7 +1241,7 @@ TclCompileListCmd(
if (concat && numWords == 2) {
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
TclEmitInt4( INDEX_END, envPtr);
TclEmitInt4( TCL_INDEX_END, envPtr);
}
return TCL_OK;
}
@@ -1332,21 +1315,25 @@ TclCompileLrangeCmd(
}
listTokenPtr = TokenAfter(parsePtr->tokenPtr);
tokenPtr = TokenAfter(listTokenPtr);
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
&idx1) != TCL_OK) {
return TCL_ERROR;
}
/*
* Parse the indices. Will only compile if both are constants and not an
* _integer_ less than zero (since we reserve negative indices here for
* end-relative indexing) or an end-based index greater than 'end' itself.
* Token was an index value, and we treat all "first" indices
* before the list same as the start of the list.
*/
tokenPtr = TokenAfter(listTokenPtr);
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(tokenPtr);
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
&idx2) != TCL_OK) {
return TCL_ERROR;
}
/*
* Token was an index value, and we treat all "last" indices
* after the list same as the end of the list.
*/
/*
* Issue instructions. It's not safe to skip doing the LIST_RANGE, as
@@ -1396,21 +1383,30 @@ TclCompileLinsertCmd(
*/
tokenPtr = TokenAfter(listTokenPtr);
if (GetIndexFromToken(tokenPtr, &idx) != TCL_OK) {
/*
* NOTE: This command treats all inserts at indices before the list
* the same as inserts at the start of the list, and all inserts
* after the list the same as inserts at the end of the list. We
* make that transformation here so we can use the optimized bytecode
* as much as possible.
*/
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_END,
&idx) != TCL_OK) {
return TCL_ERROR;
}
/*
* There are four main cases. If there are no values to insert, this is
* just a confirm-listiness check. If the index is '0', this is a prepend.
* If the index is 'end' (== INDEX_END), this is an append. Otherwise,
* If the index is 'end' (== TCL_INDEX_END), this is an append. Otherwise,
* this is a splice (== split, insert values as list, concat-3).
*/
CompileWord(envPtr, listTokenPtr, interp, 1);
if (parsePtr->numWords == 3) {
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
TclEmitInt4( INDEX_END, envPtr);
TclEmitInt4( TCL_INDEX_END, envPtr);
return TCL_OK;
}
@@ -1420,13 +1416,25 @@ TclCompileLinsertCmd(
}
TclEmitInstInt4( INST_LIST, i-3, envPtr);
if (idx == 0 /*start*/) {
if (idx == TCL_INDEX_START) {
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
} else if (idx == INDEX_END /*end*/) {
} else if (idx == TCL_INDEX_END) {
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
} else {
if (idx < 0) {
/*
* Here we handle two ranges for idx. First when idx > 0, we
* want the first half of the split to end at index idx-1 and
* the second half to start at index idx.
* Second when idx < TCL_INDEX_END, indicating "end-N" indexing,
* we want the first half of the split to end at index end-N and
* the second half to start at index end-N+1. We accomplish this
* with a pre-adjustment of the end-N value.
* The root of this is that the commands [lrange] and [linsert]
* differ in their interpretation of the "end" index.
*/
if (idx < TCL_INDEX_END) {
idx++;
}
TclEmitInstInt4( INST_OVER, 1, envPtr);
@@ -1434,7 +1442,7 @@ TclCompileLinsertCmd(
TclEmitInt4( idx-1, envPtr);
TclEmitInstInt4( INST_REVERSE, 3, envPtr);
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
TclEmitInt4( INDEX_END, envPtr);
TclEmitInt4( TCL_INDEX_END, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
}
@@ -1464,250 +1472,116 @@ TclCompileLreplaceCmd(
{
Tcl_Token *tokenPtr, *listTokenPtr;
DefineLineInformation; /* TIP #280 */
Tcl_Obj *tmpObj;
int idx1, idx2, i, offset, offset2;
int idx1, idx2, i;
int emptyPrefix=1, suffixStart = 0;
if (parsePtr->numWords < 4) {
return TCL_ERROR;
}
listTokenPtr = TokenAfter(parsePtr->tokenPtr);
/*
* Parse the indices. Will only compile if both are constants and not an
* _integer_ less than zero (since we reserve negative indices here for
* end-relative indexing) or an end-based index greater than 'end' itself.
*/
tokenPtr = TokenAfter(listTokenPtr);
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
&idx1) != TCL_OK) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(tokenPtr);
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
&idx2) != TCL_OK) {
return TCL_ERROR;
}
/*
* idx1, idx2 are now in canonical form:
* General structure of the [lreplace] result is
* prefix replacement suffix
* In a few cases we can predict various parts will be empty and
* take advantage.
*
* - integer: [0,len+1]
* - end index: INDEX_END
* - -ive offset: INDEX_END-[len-1,0]
* - +ive offset: INDEX_END+1
* The proper suffix begins with the greater of indices idx1 or
* idx2 + 1. If we cannot tell at compile time which is greater,
* we must defer to direct evaluation.
*/
/*
* Compilation fails when one index is end-based but the other isn't.
* Fixing this will require more bytecodes, but this is a workaround for
* now. [Bug 47ac84309b]
*/
if ((idx1 <= INDEX_END) != (idx2 <= INDEX_END)) {
if (idx1 == TCL_INDEX_AFTER) {
suffixStart = idx1;
} else if (idx2 == TCL_INDEX_BEFORE) {
suffixStart = idx1;
} else if (idx2 == TCL_INDEX_END) {
suffixStart = TCL_INDEX_AFTER;
} else if (((idx2 < TCL_INDEX_END) && (idx1 <= TCL_INDEX_END))
|| ((idx2 >= TCL_INDEX_START) && (idx1 >= TCL_INDEX_START))) {
suffixStart = (idx1 > idx2 + 1) ? idx1 : idx2 + 1;
} else {
return TCL_ERROR;
}
if (idx2 != INDEX_END && idx2 >= 0 && idx2 < idx1) {
idx2 = idx1 - 1;
}
/*
* Work out what this [lreplace] is actually doing.
*/
tmpObj = NULL;
/* All paths start with computing/pushing the original value. */
CompileWord(envPtr, listTokenPtr, interp, 1);
if (parsePtr->numWords == 4) {
if (idx1 == 0) {
if (idx2 == INDEX_END) {
goto dropAll;
}
idx1 = idx2 + 1;
idx2 = INDEX_END;
goto dropEnd;
} else if (idx2 == INDEX_END) {
idx2 = idx1 - 1;
idx1 = 0;
goto dropEnd;
} else {
if (idx2 < idx1) {
idx2 = idx1 - 1;
}
if (idx1 > 0) {
tmpObj = Tcl_NewIntObj(idx1);
Tcl_IncrRefCount(tmpObj);
}
goto dropRange;
}
}
tokenPtr = TokenAfter(tokenPtr);
for (i=4 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
/*
* Push all the replacement values next so any errors raised in
* creating them get raised first.
*/
if (parsePtr->numWords > 4) {
/* Push the replacement arguments */
tokenPtr = TokenAfter(tokenPtr);
for (i=4 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
/* Make a list of them... */
TclEmitInstInt4( INST_LIST, i - 4, envPtr);
emptyPrefix = 0;
}
TclEmitInstInt4( INST_LIST, i - 4, envPtr);
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
if (idx1 == 0) {
if (idx2 == INDEX_END) {
goto replaceAll;
if ((idx1 == suffixStart) && (parsePtr->numWords == 4)) {
/*
* This is a "no-op". Example: [lreplace {a b c} 2 0]
* We still do a list operation to get list-verification
* and canonicalization side effects.
*/
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
TclEmitInt4( TCL_INDEX_END, envPtr);
return TCL_OK;
}
if (idx1 != TCL_INDEX_START) {
/* Prefix may not be empty; generate bytecode to push it */
if (emptyPrefix) {
TclEmitOpcode( INST_DUP, envPtr);
} else {
TclEmitInstInt4( INST_OVER, 1, envPtr);
}
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
TclEmitInt4( idx1 - 1, envPtr);
if (!emptyPrefix) {
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
}
emptyPrefix = 0;
}
if (!emptyPrefix) {
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
}
if (suffixStart == TCL_INDEX_AFTER) {
TclEmitOpcode( INST_POP, envPtr);
if (emptyPrefix) {
PushStringLiteral(envPtr, "");
}
idx1 = idx2 + 1;
idx2 = INDEX_END;
goto replaceHead;
} else if (idx2 == INDEX_END) {
idx2 = idx1 - 1;
idx1 = 0;
goto replaceTail;
} else {
if (idx2 < idx1) {
idx2 = idx1 - 1;
/* Suffix may not be empty; generate bytecode to push it */
TclEmitInstInt4( INST_LIST_RANGE_IMM, suffixStart, envPtr);
TclEmitInt4( TCL_INDEX_END, envPtr);
if (!emptyPrefix) {
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
}
if (idx1 > 0) {
tmpObj = Tcl_NewIntObj(idx1);
Tcl_IncrRefCount(tmpObj);
}
goto replaceRange;
}
/*
* Issue instructions to perform the operations relating to configurations
* that just drop. The only argument pushed on the stack is the list to
* operate on.
*/
dropAll: /* This just ensures the arg is a list. */
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
TclEmitOpcode( INST_POP, envPtr);
PushStringLiteral(envPtr, "");
goto done;
dropEnd:
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
TclEmitInt4( idx2, envPtr);
goto done;
dropRange:
if (tmpObj != NULL) {
/*
* Emit bytecode to check the list length.
*/
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
TclEmitOpcode( INST_GE, envPtr);
offset = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
/*
* Emit an error if we've been given an empty list.
*/
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
offset2 = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
"list doesn't contain element %d", idx1), NULL), envPtr);
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
envPtr->codeStart + offset + 1);
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
envPtr->codeStart + offset2 + 1);
TclAdjustStackDepth(-1, envPtr);
}
TclEmitOpcode( INST_DUP, envPtr);
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
TclEmitInt4( idx1 - 1, envPtr);
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr);
TclEmitInt4( INDEX_END, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
goto done;
/*
* Issue instructions to perform the operations relating to configurations
* that do real replacement. All arguments are pushed and assembled into a
* pair: the list of values to replace with, and the list to do the
* surgery on.
*/
replaceAll:
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
TclEmitOpcode( INST_POP, envPtr);
goto done;
replaceHead:
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
TclEmitInt4( idx2, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
goto done;
replaceTail:
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
TclEmitInt4( idx2, envPtr);
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
goto done;
replaceRange:
if (tmpObj != NULL) {
/*
* Emit bytecode to check the list length.
*/
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
/*
* Check the list length vs idx1.
*/
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
TclEmitOpcode( INST_GE, envPtr);
offset = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
/*
* Emit an error if we've been given an empty list.
*/
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
offset2 = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
"list doesn't contain element %d", idx1), NULL), envPtr);
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
envPtr->codeStart + offset + 1);
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
envPtr->codeStart + offset2 + 1);
TclAdjustStackDepth(-1, envPtr);
}
TclEmitOpcode( INST_DUP, envPtr);
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
TclEmitInt4( idx1 - 1, envPtr);
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr);
TclEmitInt4( INDEX_END, envPtr);
TclEmitInstInt4( INST_REVERSE, 3, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
goto done;
/*
* Clean up the allocated memory.
*/
done:
if (tmpObj != NULL) {
Tcl_DecrRefCount(tmpObj);
}
return TCL_OK;
}
@@ -2933,7 +2807,7 @@ TclCompileVariableCmd(
return TCL_ERROR;
}
/* TODO: Consider what value can pass throug the
/* TODO: Consider what value can pass through the
* IndexTailVarIfKnown() screen. Full CompileWord()
* likely does not apply here. Push known value instead. */
CompileWord(envPtr, varTokenPtr, interp, i);
+183 -137
View File
@@ -107,58 +107,6 @@ const AuxDataType tclJumptableInfoType = {
#define INVOKE(name) \
TclEmitInvoke(envPtr,INST_##name)
#define INDEX_END (-2)
/*
*----------------------------------------------------------------------
*
* GetIndexFromToken --
*
* Parse a token and get the encoded version of the index (as understood
* by TEBC), assuming it is at all knowable at compile time. Only handles
* indices that are integers or 'end' or 'end-integer'.
*
* Returns:
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
*
* Side effects:
* Sets *index to the index value if successful.
*
*----------------------------------------------------------------------
*/
static inline int
GetIndexFromToken(
Tcl_Token *tokenPtr,
int *index)
{
Tcl_Obj *tmpObj = Tcl_NewObj();
int result, idx;
if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
Tcl_DecrRefCount(tmpObj);
return TCL_ERROR;
}
result = TclGetIntFromObj(NULL, tmpObj, &idx);
if (result == TCL_OK) {
if (idx < 0) {
result = TCL_ERROR;
}
} else {
result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx);
if (result == TCL_OK && idx > INDEX_END) {
result = TCL_ERROR;
}
}
Tcl_DecrRefCount(tmpObj);
if (result == TCL_OK) {
*index = idx;
}
return result;
}
/*
*----------------------------------------------------------------------
@@ -982,22 +930,48 @@ TclCompileStringRangeCmd(
fromTokenPtr = TokenAfter(stringTokenPtr);
toTokenPtr = TokenAfter(fromTokenPtr);
/* Every path must push the string argument */
CompileWord(envPtr, stringTokenPtr, interp, 1);
/*
* Parse the two indices.
*/
if (GetIndexFromToken(fromTokenPtr, &idx1) != TCL_OK) {
if (TclGetIndexFromToken(fromTokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
&idx1) != TCL_OK) {
goto nonConstantIndices;
}
if (GetIndexFromToken(toTokenPtr, &idx2) != TCL_OK) {
/*
* Token parsed as an index expression. We treat all indices before
* the string the same as the start of the string.
*/
if (idx1 == TCL_INDEX_AFTER) {
/* [string range $s end+1 $last] must be empty string */
OP( POP);
PUSH( "");
return TCL_OK;
}
if (TclGetIndexFromToken(toTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
&idx2) != TCL_OK) {
goto nonConstantIndices;
}
/*
* Token parsed as an index expression. We treat all indices after
* the string the same as the end of the string.
*/
if (idx2 == TCL_INDEX_BEFORE) {
/* [string range $s $first -1] must be empty string */
OP( POP);
PUSH( "");
return TCL_OK;
}
/*
* Push the operand onto the stack and then the substring operation.
*/
CompileWord(envPtr, stringTokenPtr, interp, 1);
OP44( STR_RANGE_IMM, idx1, idx2);
return TCL_OK;
@@ -1006,7 +980,6 @@ TclCompileStringRangeCmd(
*/
nonConstantIndices:
CompileWord(envPtr, stringTokenPtr, interp, 1);
CompileWord(envPtr, fromTokenPtr, interp, 2);
CompileWord(envPtr, toTokenPtr, interp, 3);
OP( STR_RANGE);
@@ -1022,124 +995,197 @@ TclCompileStringReplaceCmd(
* compiled. */
CompileEnv *envPtr) /* Holds the resulting instructions. */
{
Tcl_Token *tokenPtr, *valueTokenPtr, *replacementTokenPtr = NULL;
Tcl_Token *tokenPtr, *valueTokenPtr;
DefineLineInformation; /* TIP #280 */
int idx1, idx2;
int first, last;
if (parsePtr->numWords < 4 || parsePtr->numWords > 5) {
return TCL_ERROR;
}
/* Bytecode to compute/push string argument being replaced */
valueTokenPtr = TokenAfter(parsePtr->tokenPtr);
if (parsePtr->numWords == 5) {
tokenPtr = TokenAfter(valueTokenPtr);
tokenPtr = TokenAfter(tokenPtr);
replacementTokenPtr = TokenAfter(tokenPtr);
}
CompileWord(envPtr, valueTokenPtr, interp, 1);
/*
* Parse the indices. Will only compile special cases if both are
* constants and not an _integer_ less than zero (since we reserve
* negative indices here for end-relative indexing) or an end-based index
* greater than 'end' itself.
* Check for first index known and useful at compile time.
*/
tokenPtr = TokenAfter(valueTokenPtr);
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
goto genericReplace;
}
tokenPtr = TokenAfter(tokenPtr);
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_AFTER,
&first) != TCL_OK) {
goto genericReplace;
}
/*
* We handle these replacements specially: first character (where
* idx1=idx2=0) and last character (where idx1=idx2=INDEX_END). Anything
* else and the semantics get rather screwy.
* Check for last index known and useful at compile time.
*/
tokenPtr = TokenAfter(tokenPtr);
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_AFTER,
&last) != TCL_OK) {
goto genericReplace;
}
/*
* [string replace] is an odd bird. For many arguments it is
* a conventional substring replacer. However it also goes out
* of its way to become a no-op for many cases where it would be
* replacing an empty substring. Precisely, it is a no-op when
*
* (last < first) OR
* (last < 0) OR
* (end < first)
*
* For some compile-time values we can detect these cases, and
* compile direct to bytecode implementing the no-op.
*/
if (idx1 == 0 && idx2 == 0) {
int notEq, end;
if ((last == TCL_INDEX_BEFORE) /* Know (last < 0) */
|| (first == TCL_INDEX_AFTER) /* Know (first > end) */
/*
* Just working with the first character.
* Tricky to determine when runtime (last < first) can be
* certainly known based on the encoded values. Consider the
* cases...
*
* (first <= TCL_INDEX_END) &&
* (last == TCL_INDEX_AFTER) => cannot tell REJECT
* (last <= TCL_INDEX END) && (last < first) => ACCEPT
* else => cannot tell REJECT
*/
CompileWord(envPtr, valueTokenPtr, interp, 1);
if (replacementTokenPtr == NULL) {
/* Drop first */
OP44( STR_RANGE_IMM, 1, INDEX_END);
return TCL_OK;
}
/* Replace first */
CompileWord(envPtr, replacementTokenPtr, interp, 4);
OP4( OVER, 1);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP_FALSE, notEq);
OP( POP);
JUMP1( JUMP, end);
FIXJUMP1(notEq);
TclAdjustStackDepth(1, envPtr);
OP4( REVERSE, 2);
OP44( STR_RANGE_IMM, 1, INDEX_END);
OP1( STR_CONCAT1, 2);
FIXJUMP1(end);
return TCL_OK;
} else if (idx1 == INDEX_END && idx2 == INDEX_END) {
int notEq, end;
|| ((first <= TCL_INDEX_END) && (last <= TCL_INDEX_END)
&& (last < first)) /* Know (last < first) */
/*
* Just working with the last character.
* (first == TCL_INDEX_BEFORE) &&
* (last == TCL_INDEX_AFTER) => (first < last) REJECT
* (last <= TCL_INDEX_END) => cannot tell REJECT
* else => (first < last) REJECT
*
* else [[first >= TCL_INDEX_START]] &&
* (last == TCL_INDEX_AFTER) => cannot tell REJECT
* (last <= TCL_INDEX_END) => cannot tell REJECT
* else [[last >= TCL_INDEX START]] && (last < first) => ACCEPT
*/
CompileWord(envPtr, valueTokenPtr, interp, 1);
if (replacementTokenPtr == NULL) {
/* Drop last */
OP44( STR_RANGE_IMM, 0, INDEX_END-1);
return TCL_OK;
|| ((first >= TCL_INDEX_START) && (last >= TCL_INDEX_START)
&& (last < first))) { /* Know (last < first) */
if (parsePtr->numWords == 5) {
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 4);
OP( POP); /* Pop newString */
}
/* Replace last */
CompileWord(envPtr, replacementTokenPtr, interp, 4);
OP4( OVER, 1);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP_FALSE, notEq);
OP( POP);
JUMP1( JUMP, end);
FIXJUMP1(notEq);
TclAdjustStackDepth(1, envPtr);
OP4( REVERSE, 2);
OP44( STR_RANGE_IMM, 0, INDEX_END-1);
OP4( REVERSE, 2);
OP1( STR_CONCAT1, 2);
FIXJUMP1(end);
/* Original string argument now on TOS as result */
return TCL_OK;
}
if (parsePtr->numWords == 5) {
/*
* When we have a string replacement, we have to take care about
* not replacing empty substrings that [string replace] promises
* not to replace
*
* The remaining index values might be suitable for conventional
* string replacement, but only if they cannot possibly meet the
* conditions described above at runtime. If there's a chance they
* might, we would have to emit bytecode to check and at that point
* we're paying more in bytecode execution time than would make
* things worthwhile. Trouble is we are very limited in
* how much we can detect that at compile time. After decoding,
* we need, first:
*
* (first <= end)
*
* The encoded indices (first <= TCL_INDEX END) and
* (first == TCL_INDEX_BEFORE) always meets this condition, but
* any other encoded first index has some list for which it fails.
*
* We also need, second:
*
* (last >= 0)
*
* The encoded indices (last >= TCL_INDEX_START) and
* (last == TCL_INDEX_AFTER) always meet this condition but any
* other encoded last index has some list for which it fails.
*
* Finally we need, third:
*
* (first <= last)
*
* Considered in combination with the constraints we already have,
* we see that we can proceed when (first == TCL_INDEX_BEFORE)
* or (last == TCL_INDEX_AFTER). These also permit simplification
* of the prefix|replace|suffix construction. The other constraints,
* though, interfere with getting a guarantee that first <= last.
*/
if ((first == TCL_INDEX_BEFORE) && (last >= TCL_INDEX_START)) {
/* empty prefix */
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 4);
OP4( REVERSE, 2);
if (last == TCL_INDEX_AFTER) {
OP( POP); /* Pop original */
} else {
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
OP1( STR_CONCAT1, 2);
}
return TCL_OK;
}
if ((last == TCL_INDEX_AFTER) && (first <= TCL_INDEX_END)) {
OP44( STR_RANGE_IMM, 0, first-1);
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 4);
OP1( STR_CONCAT1, 2);
return TCL_OK;
}
/* FLOW THROUGH TO genericReplace */
} else {
/*
* Need to process indices at runtime. This could be because the
* indices are not constants, or because we need to resolve them to
* absolute indices to work out if a replacement is going to happen.
* In any case, to runtime it is.
/*
* When we have no replacement string to worry about, we may
* have more luck, because the forbidden empty string replacements
* are harmless when they are replaced by another empty string.
*/
if ((first == TCL_INDEX_BEFORE) || (first == TCL_INDEX_START)) {
/* empty prefix - build suffix only */
if ((last == TCL_INDEX_END) || (last == TCL_INDEX_AFTER)) {
/* empty suffix too => empty result */
OP( POP); /* Pop original */
PUSH ( "");
return TCL_OK;
}
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
return TCL_OK;
} else {
if ((last == TCL_INDEX_END) || (last == TCL_INDEX_AFTER)) {
/* empty suffix - build prefix only */
OP44( STR_RANGE_IMM, 0, first-1);
return TCL_OK;
}
OP( DUP);
OP44( STR_RANGE_IMM, 0, first-1);
OP4( REVERSE, 2);
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
OP1( STR_CONCAT1, 2);
return TCL_OK;
}
}
genericReplace:
CompileWord(envPtr, valueTokenPtr, interp, 1);
tokenPtr = TokenAfter(valueTokenPtr);
CompileWord(envPtr, tokenPtr, interp, 2);
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 3);
if (replacementTokenPtr != NULL) {
CompileWord(envPtr, replacementTokenPtr, interp, 4);
if (parsePtr->numWords == 5) {
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 4);
} else {
PUSH( "");
}
OP( STR_REPLACE);
return TCL_OK;
}
}
int
+1 -1
View File
@@ -1885,7 +1885,7 @@ ParseLexeme(
{
const char *end;
int scanned;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
Tcl_Obj *literal = NULL;
unsigned char byte;
+3 -20
View File
@@ -1121,6 +1121,8 @@ MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr,
int distThreshold);
MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr);
MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr);
MODULE_SCOPE int TclGetIndexFromToken(Tcl_Token *tokenPtr,
int before, int after, int *indexPtr);
MODULE_SCOPE void TclInitByteCodeObj(Tcl_Obj *objPtr,
CompileEnv *envPtr);
MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp,
@@ -1159,25 +1161,6 @@ MODULE_SCOPE void TclPushVarName(Tcl_Interp *interp,
Tcl_Token *varTokenPtr, CompileEnv *envPtr,
int flags, int *localIndexPtr,
int *isScalarPtr);
static inline void
TclPreserveByteCode(
register ByteCode *codePtr)
{
codePtr->refCount++;
}
static inline void
TclReleaseByteCode(
register ByteCode *codePtr)
{
if (codePtr->refCount-- > 1) {
return;
}
/* Just dropped to refcount==0. Clean up. */
TclCleanupByteCode(codePtr);
}
MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
MODULE_SCOPE void TclInvalidateCmdLiteral(Tcl_Interp *interp,
const char *name, Namespace *nsPtr);
@@ -1511,7 +1494,7 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
#endif
#define TclGetInt4AtPtr(p) \
(((int) TclGetInt1AtPtr(p) << 24) | \
(((int) (TclGetUInt1AtPtr(p) << 24)) | \
(*((p)+1) << 16) | \
(*((p)+2) << 8) | \
(*((p)+3)))
+307 -247
View File
@@ -1,14 +1,14 @@
/* A Bison parser, made by GNU Bison 2.4.2. */
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton implementation for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
Foundation, Inc.
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,7 +16,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -45,7 +47,7 @@
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "2.4.2"
#define YYBISON_VERSION "2.3"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -53,24 +55,65 @@
/* Pure parsers. */
#define YYPURE 1
/* Push parsers. */
#define YYPUSH 0
/* Pull parsers. */
#define YYPULL 1
/* Using locations. */
#define YYLSP_NEEDED 1
/* Substitute the variable and function names. */
#define yyparse TclDateparse
#define yylex TclDatelex
#define yyerror TclDateerror
#define yylval TclDatelval
#define yychar TclDatechar
#define yydebug TclDatedebug
#define yynerrs TclDatenerrs
#define yylloc TclDatelloc
#define yyparse TclDateparse
#define yylex TclDatelex
#define yyerror TclDateerror
#define yylval TclDatelval
#define yychar TclDatechar
#define yydebug TclDatedebug
#define yynerrs TclDatenerrs
#define yylloc TclDatelloc
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
tAGO = 258,
tDAY = 259,
tDAYZONE = 260,
tID = 261,
tMERIDIAN = 262,
tMONTH = 263,
tMONTH_UNIT = 264,
tSTARDATE = 265,
tSEC_UNIT = 266,
tSNUMBER = 267,
tUNUMBER = 268,
tZONE = 269,
tEPOCH = 270,
tDST = 271,
tISOBASE = 272,
tDAY_UNIT = 273,
tNEXT = 274
};
#endif
/* Tokens. */
#define tAGO 258
#define tDAY 259
#define tDAYZONE 260
#define tID 261
#define tMERIDIAN 262
#define tMONTH 263
#define tMONTH_UNIT 264
#define tSTARDATE 265
#define tSEC_UNIT 266
#define tSNUMBER 267
#define tUNUMBER 268
#define tZONE 269
#define tEPOCH 270
#define tDST 271
#define tISOBASE 272
#define tDAY_UNIT 273
#define tNEXT 274
/* Copy the first part of user declarations. */
@@ -86,7 +129,6 @@
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#include "tclInt.h"
@@ -104,11 +146,73 @@
* parsed fields will be returned.
*/
#include "tclDate.h"
typedef struct DateInfo {
Tcl_Obj* messages; /* Error messages */
const char* separatrix; /* String separating messages */
time_t dateYear;
time_t dateMonth;
time_t dateDay;
int dateHaveDate;
time_t dateHour;
time_t dateMinutes;
time_t dateSeconds;
int dateMeridian;
int dateHaveTime;
time_t dateTimezone;
int dateDSTmode;
int dateHaveZone;
time_t dateRelMonth;
time_t dateRelDay;
time_t dateRelSeconds;
int dateHaveRel;
time_t dateMonthOrdinal;
int dateHaveOrdinalMonth;
time_t dateDayOrdinal;
time_t dateDayNumber;
int dateHaveDay;
const char *dateStart;
const char *dateInput;
time_t *dateRelPointer;
int dateDigitCount;
} DateInfo;
#define YYMALLOC ckalloc
#define YYFREE(x) (ckfree((void*) (x)))
#define yyDSTmode (info->dateDSTmode)
#define yyDayOrdinal (info->dateDayOrdinal)
#define yyDayNumber (info->dateDayNumber)
#define yyMonthOrdinal (info->dateMonthOrdinal)
#define yyHaveDate (info->dateHaveDate)
#define yyHaveDay (info->dateHaveDay)
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
#define yyHaveRel (info->dateHaveRel)
#define yyHaveTime (info->dateHaveTime)
#define yyHaveZone (info->dateHaveZone)
#define yyTimezone (info->dateTimezone)
#define yyDay (info->dateDay)
#define yyMonth (info->dateMonth)
#define yyYear (info->dateYear)
#define yyHour (info->dateHour)
#define yyMinutes (info->dateMinutes)
#define yySeconds (info->dateSeconds)
#define yyMeridian (info->dateMeridian)
#define yyRelMonth (info->dateRelMonth)
#define yyRelDay (info->dateRelDay)
#define yyRelSeconds (info->dateRelSeconds)
#define yyRelPointer (info->dateRelPointer)
#define yyInput (info->dateInput)
#define yyDigitCount (info->dateDigitCount)
#define EPOCH 1970
#define START_OF_TIME 1902
#define END_OF_TIME 2037
@@ -142,6 +246,13 @@ typedef enum _DSTMODE {
DSTon, DSToff, DSTmaybe
} DSTMODE;
/*
* Meridian: am, pm, or 24-hour style.
*/
typedef enum _MERIDIAN {
MERam, MERpm, MER24
} MERIDIAN;
@@ -163,49 +274,19 @@ typedef enum _DSTMODE {
# define YYTOKEN_TABLE 0
#endif
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
tAGO = 258,
tDAY = 259,
tDAYZONE = 260,
tID = 261,
tMERIDIAN = 262,
tMONTH = 263,
tMONTH_UNIT = 264,
tSTARDATE = 265,
tSEC_UNIT = 266,
tSNUMBER = 267,
tUNUMBER = 268,
tZONE = 269,
tEPOCH = 270,
tDST = 271,
tISOBASE = 272,
tDAY_UNIT = 273,
tNEXT = 274
};
#endif
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
time_t Number;
enum _MERIDIAN Meridian;
}
/* Line 187 of yacc.c. */
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
@@ -235,10 +316,14 @@ static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
DateInfo* info, const char *s);
static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
DateInfo* info);
static time_t ToSeconds(time_t Hours, time_t Minutes,
time_t Seconds, MERIDIAN Meridian);
MODULE_SCOPE int yyparse(DateInfo*);
/* Line 216 of yacc.c. */
#ifdef short
# undef short
@@ -274,21 +359,15 @@ typedef short int yytype_int16;
#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
# define YYSIZE_T unsigned int
# define YYSIZE_T size_t
# endif
#endif
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
# if YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -313,14 +392,14 @@ typedef short int yytype_int16;
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static int
YYID (int yyi)
YYID (int i)
#else
static int
YYID (yyi)
int yyi;
YYID (i)
int i;
#endif
{
return yyi;
return i;
}
#endif
@@ -402,9 +481,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
yytype_int16 yyss_alloc;
YYSTYPE yyvs_alloc;
YYLTYPE yyls_alloc;
yytype_int16 yyss;
YYSTYPE yyvs;
YYLTYPE yyls;
};
/* The size of the maximum gap between one aligned stack and the next. */
@@ -439,12 +518,12 @@ union yyalloc
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
# define YYSTACK_RELOCATE(Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
Stack = &yyptr->Stack_alloc; \
YYCOPY (&yyptr->Stack, Stack, yysize); \
Stack = &yyptr->Stack; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
@@ -545,12 +624,12 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
0, 152, 152, 153, 156, 159, 162, 165, 168, 171,
174, 178, 183, 186, 192, 198, 206, 212, 223, 227,
231, 237, 241, 245, 249, 253, 259, 263, 268, 273,
278, 283, 287, 292, 296, 301, 308, 312, 318, 327,
336, 346, 360, 365, 368, 371, 374, 377, 380, 385,
388, 393, 397, 401, 407, 425, 428
0, 225, 225, 226, 229, 232, 235, 238, 241, 244,
247, 251, 256, 259, 265, 271, 279, 285, 296, 300,
304, 310, 314, 318, 322, 326, 332, 336, 341, 346,
351, 356, 360, 365, 369, 374, 381, 385, 391, 400,
409, 419, 433, 438, 441, 444, 447, 450, 453, 458,
461, 466, 470, 474, 480, 498, 501
};
#endif
@@ -704,18 +783,9 @@ static const yytype_uint8 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
Once GCC version 2 has supplanted version 1, this can go. However,
YYFAIL appears to be in use. Nevertheless, it is formally deprecated
in Bison 2.4.2's NEWS entry, where a plan to phase it out is
discussed. */
Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
#if defined YYFAIL
/* This is here to suppress warnings from the GCC cpp's
-Wunused-macros. Normally we don't worry about that warning, but
some users do, and we want to make it easy for users to remove
YYFAIL uses, which will produce warnings from Bison 2.5. */
#endif
#define YYRECOVERING() (!!yyerrstatus)
@@ -772,7 +842,7 @@ while (YYID (0))
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
# if YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
@@ -891,20 +961,17 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, info)
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
#else
static void
yy_stack_print (yybottom, yytop)
yytype_int16 *yybottom;
yytype_int16 *yytop;
yy_stack_print (bottom, top)
yytype_int16 *bottom;
yytype_int16 *top;
#endif
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
{
int yybot = *yybottom;
YYFPRINTF (stderr, " %d", yybot);
}
for (; bottom <= top; ++bottom)
YYFPRINTF (stderr, " %d", *bottom);
YYFPRINTF (stderr, "\n");
}
@@ -940,11 +1007,11 @@ yy_reduce_print (yyvsp, yylsp, yyrule, info)
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
fprintf (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
&(yyvsp[(yyi + 1) - (yynrhs)])
, &(yylsp[(yyi + 1) - (yynrhs)]) , info);
YYFPRINTF (stderr, "\n");
fprintf (stderr, "\n");
}
}
@@ -1228,8 +1295,10 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, info)
break;
}
}
/* Prevent warnings from -Wmissing-prototypes. */
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
@@ -1248,9 +1317,10 @@ int yyparse ();
/*-------------------------.
| yyparse or yypush_parse. |
`-------------------------*/
/*----------.
| yyparse. |
`----------*/
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1274,59 +1344,24 @@ yyparse (info)
#endif
#endif
{
/* The lookahead symbol. */
/* The look-ahead symbol. */
int yychar;
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
/* The semantic value of the look-ahead symbol. */
YYSTYPE yylval = {0};
/* Location data for the lookahead symbol. */
/* Number of syntax errors so far. */
int yynerrs;
/* Location data for the look-ahead symbol. */
YYLTYPE yylloc;
/* Number of syntax errors so far. */
int yynerrs;
int yystate;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* The stacks and their tools:
`yyss': related to states.
`yyvs': related to semantic values.
`yyls': related to locations.
Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
yytype_int16 yyssa[YYINITDEPTH];
yytype_int16 *yyss;
yytype_int16 *yyssp;
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
YYSTYPE *yyvs;
YYSTYPE *yyvsp;
/* The location stack. */
YYLTYPE yylsa[YYINITDEPTH];
YYLTYPE *yyls;
YYLTYPE *yylsp;
/* The locations where the error started and ended. */
YYLTYPE yyerror_range[2];
YYSIZE_T yystacksize;
int yystate;
int yyn;
int yyresult;
/* Lookahead token as an internal (translated) token number. */
int yytoken;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
YYLTYPE yyloc;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* Look-ahead token as an internal (translated) token number. */
int yytoken = 0;
#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
@@ -1334,37 +1369,63 @@ YYLTYPE yylloc;
YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
#endif
/* Three stacks and their tools:
`yyss': related to states,
`yyvs': related to semantic values,
`yyls': related to locations.
Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
yytype_int16 yyssa[YYINITDEPTH];
yytype_int16 *yyss = yyssa;
yytype_int16 *yyssp;
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
YYSTYPE *yyvs = yyvsa;
YYSTYPE *yyvsp;
/* The location stack. */
YYLTYPE yylsa[YYINITDEPTH];
YYLTYPE *yyls = yylsa;
YYLTYPE *yylsp;
/* The locations where the error started and ended. */
YYLTYPE yyerror_range[2];
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
YYSIZE_T yystacksize = YYINITDEPTH;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
YYLTYPE yyloc;
/* The number of symbols on the RHS of the reduced rule.
Keep to zero when no symbol should be popped. */
int yylen = 0;
yytoken = 0;
yyss = yyssa;
yyvs = yyvsa;
yyls = yylsa;
yystacksize = YYINITDEPTH;
YYDPRINTF ((stderr, "Starting parse\n"));
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
yychar = YYEMPTY; /* Cause a token to be read. */
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
yyssp = yyss;
yyvsp = yyvs;
yylsp = yyls;
#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
#if YYLTYPE_IS_TRIVIAL
/* Initialize the default location before parsing starts. */
yylloc.first_line = yylloc.last_line = 1;
yylloc.first_column = yylloc.last_column = 1;
yylloc.first_column = yylloc.last_column = 0;
#endif
goto yysetstate;
@@ -1403,7 +1464,6 @@ YYLTYPE yylloc;
&yyvs1, yysize * sizeof (*yyvsp),
&yyls1, yysize * sizeof (*yylsp),
&yystacksize);
yyls = yyls1;
yyss = yyss1;
yyvs = yyvs1;
@@ -1425,9 +1485,9 @@ YYLTYPE yylloc;
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
YYSTACK_RELOCATE (yyls_alloc, yyls);
YYSTACK_RELOCATE (yyss);
YYSTACK_RELOCATE (yyvs);
YYSTACK_RELOCATE (yyls);
# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
@@ -1448,9 +1508,6 @@ YYLTYPE yylloc;
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
if (yystate == YYFINAL)
YYACCEPT;
goto yybackup;
/*-----------.
@@ -1459,16 +1516,16 @@ YYLTYPE yylloc;
yybackup:
/* Do appropriate processing given the current state. Read a
lookahead token if we need one and don't already have one. */
look-ahead token if we need one and don't already have one. */
/* First try to decide what to do without reference to lookahead token. */
/* First try to decide what to do without reference to look-ahead token. */
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
/* Not known => get a look-ahead token if don't already have one. */
/* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
/* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
@@ -1500,16 +1557,20 @@ yybackup:
goto yyreduce;
}
if (yyn == YYFINAL)
YYACCEPT;
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
/* Shift the lookahead token. */
/* Shift the look-ahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
/* Discard the shifted token. */
yychar = YYEMPTY;
/* Discard the shifted token unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
yystate = yyn;
*++yyvsp = yylval;
@@ -1817,16 +1878,16 @@ yyreduce:
case 36:
{
yyMonthOrdinalIncr = 1;
yyMonthOrdinal = (yyvsp[(2) - (2)].Number);
yyMonthOrdinal = 1;
yyMonth = (yyvsp[(2) - (2)].Number);
;}
break;
case 37:
{
yyMonthOrdinalIncr = (yyvsp[(2) - (3)].Number);
yyMonthOrdinal = (yyvsp[(3) - (3)].Number);
yyMonthOrdinal = (yyvsp[(2) - (3)].Number);
yyMonth = (yyvsp[(3) - (3)].Number);
;}
break;
@@ -2001,6 +2062,7 @@ yyreduce:
break;
/* Line 1267 of yacc.c. */
default: break;
}
@@ -2077,7 +2139,7 @@ yyerrlab:
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
/* If just tried and failed to reuse look-ahead token after an
error, discard it. */
if (yychar <= YYEOF)
@@ -2094,7 +2156,7 @@ yyerrlab:
}
}
/* Else will try to reuse lookahead token after shifting the error
/* Else will try to reuse look-ahead token after shifting the error
token. */
goto yyerrlab1;
@@ -2152,11 +2214,14 @@ yyerrlab1:
YY_STACK_PRINT (yyss, yyssp);
}
if (yyn == YYFINAL)
YYACCEPT;
*++yyvsp = yylval;
yyerror_range[1] = yylloc;
/* Using YYLLOC is tempting, but would change the location of
the lookahead. YYLOC is available though. */
the look-ahead. YYLOC is available though. */
YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
*++yylsp = yyloc;
@@ -2181,7 +2246,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
#if !defined(yyoverflow) || YYERROR_VERBOSE
#ifndef yyoverflow
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -2192,7 +2257,7 @@ yyexhaustedlab:
#endif
yyreturn:
if (yychar != YYEMPTY)
if (yychar != YYEOF && yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval, &yylloc, info);
/* Do not reclaim the symbols of the rule which action triggered
@@ -2448,11 +2513,11 @@ TclDateerror(
infoPtr->separatrix = "\n";
}
MODULE_SCOPE int
static time_t
ToSeconds(
int Hours,
int Minutes,
int Seconds,
time_t Hours,
time_t Minutes,
time_t Seconds,
MERIDIAN Meridian)
{
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
@@ -2615,7 +2680,7 @@ TclDatelex(
location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
while (isspace(UCHAR(*yyInput))) {
while (TclIsSpaceProc(*yyInput)) {
yyInput++;
}
@@ -2675,36 +2740,65 @@ TclDatelex(
} while (Count > 0);
}
}
int
TclClockFreeScan(
TclClockOldscanObjCmd(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* Tcl interpreter */
DateInfo *info) /* Input and result parameters */
int objc, /* Count of paraneters */
Tcl_Obj *const *objv) /* Parameters */
{
Tcl_Obj *result, *resultElement;
int yr, mo, da;
DateInfo dateInfo;
DateInfo* info = &dateInfo;
int status;
/*
* yyInput = stringToParse;
*
* ClockInitDateInfo(info) should be executed to pre-init info;
*/
if (objc != 5) {
Tcl_WrongNumArgs(interp, 1, objv,
"stringToParse baseYear baseMonth baseDay" );
return TCL_ERROR;
}
yyDSTmode = DSTmaybe;
yyInput = Tcl_GetString( objv[1] );
dateInfo.dateStart = yyInput;
info->messages = Tcl_NewObj();
info->separatrix = "";
Tcl_IncrRefCount(info->messages);
yyHaveDate = 0;
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
return TCL_ERROR;
}
yyYear = yr; yyMonth = mo; yyDay = da;
info->dateStart = yyInput;
status = yyparse(info);
yyHaveTime = 0;
yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
yyHaveZone = 0;
yyTimezone = 0; yyDSTmode = DSTmaybe;
yyHaveOrdinalMonth = 0;
yyMonthOrdinal = 0;
yyHaveDay = 0;
yyDayOrdinal = 0; yyDayNumber = 0;
yyHaveRel = 0;
yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
dateInfo.messages = Tcl_NewObj();
dateInfo.separatrix = "";
Tcl_IncrRefCount(dateInfo.messages);
status = yyparse(&dateInfo);
if (status == 1) {
Tcl_SetObjResult(interp, info->messages);
Tcl_DecrRefCount(info->messages);
Tcl_SetObjResult(interp, dateInfo.messages);
Tcl_DecrRefCount(dateInfo.messages);
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
return TCL_ERROR;
} else if (status == 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
Tcl_DecrRefCount(info->messages);
Tcl_DecrRefCount(dateInfo.messages);
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
return TCL_ERROR;
} else if (status != 0) {
@@ -2712,11 +2806,11 @@ TclClockFreeScan(
"from date parser. Please "
"report this error as a "
"bug in Tcl.", -1));
Tcl_DecrRefCount(info->messages);
Tcl_DecrRefCount(dateInfo.messages);
Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
return TCL_ERROR;
}
Tcl_DecrRefCount(info->messages);
Tcl_DecrRefCount(dateInfo.messages);
if (yyHaveDate > 1) {
Tcl_SetObjResult(interp,
@@ -2749,40 +2843,6 @@ TclClockFreeScan(
return TCL_ERROR;
}
return TCL_OK;
}
int
TclClockOldscanObjCmd(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* Tcl interpreter */
int objc, /* Count of paraneters */
Tcl_Obj *const *objv) /* Parameters */
{
Tcl_Obj *result, *resultElement;
int yr, mo, da;
DateInfo dateInfo;
DateInfo* info = &dateInfo;
if (objc != 5) {
Tcl_WrongNumArgs(interp, 1, objv,
"stringToParse baseYear baseMonth baseDay" );
return TCL_ERROR;
}
yyInput = Tcl_GetString( objv[1] );
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
return TCL_ERROR;
}
yyYear = yr; yyMonth = mo; yyDay = da;
if (TclClockFreeScan(interp, info) != TCL_OK) {
return TCL_ERROR;
}
result = Tcl_NewObj();
resultElement = Tcl_NewObj();
if (yyHaveDate) {
@@ -2833,10 +2893,10 @@ TclClockOldscanObjCmd(
resultElement = Tcl_NewObj();
if (yyHaveOrdinalMonth) {
Tcl_ListObjAppendElement(interp, resultElement,
Tcl_NewIntObj((int) yyMonthOrdinalIncr));
Tcl_ListObjAppendElement(interp, resultElement,
Tcl_NewIntObj((int) yyMonthOrdinal));
Tcl_ListObjAppendElement(interp, resultElement,
Tcl_NewIntObj((int) yyMonth));
}
Tcl_ListObjAppendElement(interp, result, resultElement);
-512
View File
@@ -1,512 +0,0 @@
/*
* tclDate.h --
*
* This header file handles common usage of clock primitives
* between tclDate.c (yacc), tclClock.c and tclClockFmt.c.
*
* Copyright (c) 2014 Serg G. Brester (aka sebres)
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCLCLOCK_H
#define _TCLCLOCK_H
/*
* Constants
*/
#define JULIAN_DAY_POSIX_EPOCH 2440588
#define GREGORIAN_CHANGE_DATE 2361222
#define SECONDS_PER_DAY 86400
#define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
* SECONDS_PER_DAY)
#define FOUR_CENTURIES 146097 /* days */
#define JDAY_1_JAN_1_CE_JULIAN 1721424
#define JDAY_1_JAN_1_CE_GREGORIAN 1721426
#define ONE_CENTURY_GREGORIAN 36524 /* days */
#define FOUR_YEARS 1461 /* days */
#define ONE_YEAR 365 /* days */
#define RODDENBERRY 1946 /* Another epoch (Hi, Jeff!) */
#define CLF_OPTIONAL (1 << 0) /* token is non mandatory */
#define CLF_POSIXSEC (1 << 1)
#define CLF_LOCALSEC (1 << 2)
#define CLF_JULIANDAY (1 << 3)
#define CLF_TIME (1 << 4)
#define CLF_CENTURY (1 << 6)
#define CLF_DAYOFMONTH (1 << 7)
#define CLF_DAYOFYEAR (1 << 8)
#define CLF_MONTH (1 << 9)
#define CLF_YEAR (1 << 10)
#define CLF_ISO8601YEAR (1 << 12)
#define CLF_ISO8601 (1 << 13)
#define CLF_ISO8601CENTURY (1 << 14)
#define CLF_SIGNED (1 << 15)
/* On demand (lazy) assemble flags */
#define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */
#define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */
#define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */
#define CLF_DATE (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | \
CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | CLF_ISO8601)
/*
* Enumeration of the string literals used in [clock]
*/
typedef enum ClockLiteral {
LIT__NIL,
LIT__DEFAULT_FORMAT,
LIT_SYSTEM, LIT_CURRENT, LIT_C,
LIT_BCE, LIT_CE,
LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR,
LIT_ERA, LIT_GMT, LIT_GREGORIAN,
LIT_INTEGER_VALUE_TOO_LARGE,
LIT_ISO8601WEEK, LIT_ISO8601YEAR,
LIT_JULIANDAY, LIT_LOCALSECONDS,
LIT_MONTH,
LIT_SECONDS, LIT_TZNAME, LIT_TZOFFSET,
LIT_YEAR,
LIT_TZDATA,
LIT_GETSYSTEMTIMEZONE,
LIT_SETUPTIMEZONE,
LIT_MCGET,
LIT_GETSYSTEMLOCALE, LIT_GETCURRENTLOCALE,
LIT_LOCALIZE_FORMAT,
LIT__END
} ClockLiteral;
#define CLOCK_LITERAL_ARRAY(litarr) static const char *const litarr[] = { \
"", \
"%a %b %d %H:%M:%S %Z %Y", \
"system", "current", "C", \
"BCE", "CE", \
"dayOfMonth", "dayOfWeek", "dayOfYear", \
"era", ":GMT", "gregorian", \
"integer value too large to represent", \
"iso8601Week", "iso8601Year", \
"julianDay", "localSeconds", \
"month", \
"seconds", "tzName", "tzOffset", \
"year", \
"::tcl::clock::TZData", \
"::tcl::clock::GetSystemTimeZone", \
"::tcl::clock::SetupTimeZone", \
"::tcl::clock::mcget", \
"::tcl::clock::GetSystemLocale", "::tcl::clock::mclocale", \
"::tcl::clock::LocalizeFormat" \
}
/*
* Enumeration of the msgcat literals used in [clock]
*/
typedef enum ClockMsgCtLiteral {
MCLIT__NIL, /* placeholder */
MCLIT_MONTHS_FULL, MCLIT_MONTHS_ABBREV, MCLIT_MONTHS_COMB,
MCLIT_DAYS_OF_WEEK_FULL, MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_COMB,
MCLIT_AM, MCLIT_PM,
MCLIT_LOCALE_ERAS,
MCLIT_BCE, MCLIT_CE,
MCLIT_BCE2, MCLIT_CE2,
MCLIT_BCE3, MCLIT_CE3,
MCLIT_LOCALE_NUMERALS,
MCLIT__END
} ClockMsgCtLiteral;
#define CLOCK_LOCALE_LITERAL_ARRAY(litarr, pref) static const char *const litarr[] = { \
pref "", \
pref "MONTHS_FULL", pref "MONTHS_ABBREV", pref "MONTHS_COMB", \
pref "DAYS_OF_WEEK_FULL", pref "DAYS_OF_WEEK_ABBREV", pref "DAYS_OF_WEEK_COMB", \
pref "AM", pref "PM", \
pref "LOCALE_ERAS", \
pref "BCE", pref "CE", \
pref "b.c.e.", pref "c.e.", \
pref "b.c.", pref "a.d.", \
pref "LOCALE_NUMERALS", \
}
/*
* Structure containing the fields used in [clock format] and [clock scan]
*/
typedef struct TclDateFields {
/* Cacheable fields: */
Tcl_WideInt seconds; /* Time expressed in seconds from the Posix
* epoch */
Tcl_WideInt localSeconds; /* Local time expressed in nominal seconds
* from the Posix epoch */
int tzOffset; /* Time zone offset in seconds east of
* Greenwich */
int julianDay; /* Julian Day Number in local time zone */
enum {BCE=1, CE=0} era; /* Era */
int gregorian; /* Flag == 1 if the date is Gregorian */
int year; /* Year of the era */
int dayOfYear; /* Day of the year (1 January == 1) */
int month; /* Month number */
int dayOfMonth; /* Day of the month */
int iso8601Year; /* ISO8601 week-based year */
int iso8601Week; /* ISO8601 week number */
int dayOfWeek; /* Day of the week */
int hour; /* Hours of day (in-between time only calculation) */
int minutes; /* Minutes of day (in-between time only calculation) */
int secondOfDay; /* Seconds of day (in-between time only calculation) */
/* Non cacheable fields: */
Tcl_Obj *tzName; /* Name (or corresponding DST-abbreviation) of the
* time zone, if set the refCount is incremented */
} TclDateFields;
#define ClockCacheableDateFieldsSize \
TclOffset(TclDateFields, tzName)
/*
* Structure contains return parsed fields.
*/
typedef struct DateInfo {
const char *dateStart;
const char *dateInput;
const char *dateEnd;
TclDateFields date;
int flags;
int dateHaveDate;
int dateMeridian;
int dateHaveTime;
int dateTimezone;
int dateDSTmode;
int dateHaveZone;
int dateRelMonth;
int dateRelDay;
int dateRelSeconds;
int dateHaveRel;
int dateMonthOrdinalIncr;
int dateMonthOrdinal;
int dateHaveOrdinalMonth;
int dateDayOrdinal;
int dateDayNumber;
int dateHaveDay;
int *dateRelPointer;
int dateSpaceCount;
int dateDigitCount;
int dateCentury;
Tcl_Obj* messages; /* Error messages */
const char* separatrix; /* String separating messages */
} DateInfo;
#define yydate (info->date) /* Date fields used for converting */
#define yyDay (info->date.dayOfMonth)
#define yyMonth (info->date.month)
#define yyYear (info->date.year)
#define yyHour (info->date.hour)
#define yyMinutes (info->date.minutes)
#define yySeconds (info->date.secondOfDay)
#define yyDSTmode (info->dateDSTmode)
#define yyDayOrdinal (info->dateDayOrdinal)
#define yyDayNumber (info->dateDayNumber)
#define yyMonthOrdinalIncr (info->dateMonthOrdinalIncr)
#define yyMonthOrdinal (info->dateMonthOrdinal)
#define yyHaveDate (info->dateHaveDate)
#define yyHaveDay (info->dateHaveDay)
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
#define yyHaveRel (info->dateHaveRel)
#define yyHaveTime (info->dateHaveTime)
#define yyHaveZone (info->dateHaveZone)
#define yyTimezone (info->dateTimezone)
#define yyMeridian (info->dateMeridian)
#define yyRelMonth (info->dateRelMonth)
#define yyRelDay (info->dateRelDay)
#define yyRelSeconds (info->dateRelSeconds)
#define yyRelPointer (info->dateRelPointer)
#define yyInput (info->dateInput)
#define yyDigitCount (info->dateDigitCount)
#define yySpaceCount (info->dateSpaceCount)
static inline void
ClockInitDateInfo(DateInfo *info) {
memset(info, 0, sizeof(DateInfo));
}
/*
* Structure containing the command arguments supplied to [clock format] and [clock scan]
*/
#define CLF_EXTENDED (1 << 4)
#define CLF_STRICT (1 << 8)
#define CLF_LOCALE_USED (1 << 15)
typedef struct ClockFmtScnCmdArgs {
ClientData clientData; /* Opaque pointer to literal pool, etc. */
Tcl_Interp *interp; /* Tcl interpreter */
Tcl_Obj *formatObj; /* Format */
Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */
Tcl_Obj *timezoneObj; /* Default time zone in which the time will be expressed */
Tcl_Obj *baseObj; /* Base (scan and add) or clockValue (format) */
int flags; /* Flags control scanning */
Tcl_Obj *mcDictObj; /* Current dictionary of tcl::clock package for given localeObj*/
} ClockFmtScnCmdArgs;
/*
* Structure containing the client data for [clock]
*/
typedef struct ClockClientData {
size_t refCount; /* Number of live references. */
Tcl_Obj **literals; /* Pool of object literals (common, locale independent). */
Tcl_Obj **mcLiterals; /* Msgcat object literals with mc-keys for search with locale. */
Tcl_Obj **mcLitIdxs; /* Msgcat object indices prefixed with _IDX_,
* used for quick dictionary search */
/* Cache for current clock parameters, imparted via "configure" */
unsigned long LastTZEpoch;
int currentYearCentury;
int yearOfCenturySwitch;
Tcl_Obj *SystemTimeZone;
Tcl_Obj *SystemSetupTZData;
Tcl_Obj *GMTSetupTimeZone;
Tcl_Obj *GMTSetupTZData;
Tcl_Obj *AnySetupTimeZone;
Tcl_Obj *AnySetupTZData;
Tcl_Obj *LastUnnormSetupTimeZone;
Tcl_Obj *LastSetupTimeZone;
Tcl_Obj *LastSetupTZData;
Tcl_Obj *CurrentLocale;
Tcl_Obj *CurrentLocaleDict;
Tcl_Obj *LastUnnormUsedLocale;
Tcl_Obj *LastUsedLocale;
Tcl_Obj *LastUsedLocaleDict;
/* Cache for last base (last-second fast convert if base/tz not changed) */
struct {
Tcl_Obj *timezoneObj;
TclDateFields Date;
} lastBase;
/* Las-period cache for fast UTC2Local conversion */
struct {
/* keys */
Tcl_Obj *timezoneObj;
int changeover;
Tcl_WideInt seconds;
Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */
/* values */
int tzOffset;
Tcl_Obj *tzName;
} UTC2Local;
/* Las-period cache for fast Local2UTC conversion */
struct {
/* keys */
Tcl_Obj *timezoneObj;
int changeover;
Tcl_WideInt localSeconds;
Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */
/* values */
int tzOffset;
} Local2UTC;
} ClockClientData;
#define ClockDefaultYearCentury 2000
#define ClockDefaultCenturySwitch 38
/*
* Meridian: am, pm, or 24-hour style.
*/
typedef enum _MERIDIAN {
MERam, MERpm, MER24
} MERIDIAN;
/*
* Clock scan and format facilities.
*/
#define CLOCK_FMT_SCN_STORAGE_GC_SIZE 32
#define CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE 2
typedef struct ClockScanToken ClockScanToken;
typedef int ClockScanTokenProc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok);
typedef enum _CLCKTOK_TYPE {
CTOKT_DIGIT = 1, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
CFMTT_INT, CFMTT_WIDE, CFMTT_PROC
} CLCKTOK_TYPE;
typedef struct ClockScanTokenMap {
unsigned short int type;
unsigned short int flags;
unsigned short int clearFlags;
unsigned short int minSize;
unsigned short int maxSize;
unsigned short int offs;
ClockScanTokenProc *parser;
const void *data;
} ClockScanTokenMap;
typedef struct ClockScanToken {
ClockScanTokenMap *map;
struct {
const char *start;
const char *end;
} tokWord;
unsigned short int endDistance;
unsigned short int lookAhMin;
unsigned short int lookAhMax;
unsigned short int lookAhTok;
} ClockScanToken;
#define MIN_FMT_RESULT_BLOCK_ALLOC 200
typedef struct DateFormat {
char *resMem;
char *resEnd;
char *output;
TclDateFields date;
Tcl_Obj *localeEra;
} DateFormat;
#define CLFMT_INCR (1 << 3)
#define CLFMT_DECR (1 << 4)
#define CLFMT_CALC (1 << 5)
#define CLFMT_LOCALE_INDX (1 << 8)
typedef struct ClockFormatToken ClockFormatToken;
typedef int ClockFormatTokenProc(
ClockFmtScnCmdArgs *opts,
DateFormat *dateFmt,
ClockFormatToken *tok,
int *val);
typedef struct ClockFormatTokenMap {
unsigned short int type;
const char *tostr;
unsigned short int width;
unsigned short int flags;
unsigned short int divider;
unsigned short int divmod;
unsigned short int offs;
ClockFormatTokenProc *fmtproc;
void *data;
} ClockFormatTokenMap;
typedef struct ClockFormatToken {
ClockFormatTokenMap *map;
struct {
const char *start;
const char *end;
} tokWord;
} ClockFormatToken;
typedef struct ClockFmtScnStorage ClockFmtScnStorage;
typedef struct ClockFmtScnStorage {
int objRefCount; /* Reference count shared across threads */
ClockScanToken *scnTok;
unsigned int scnTokC;
unsigned int scnSpaceCount; /* Count of mandatory spaces used in format */
ClockFormatToken *fmtTok;
unsigned int fmtTokC;
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
ClockFmtScnStorage *nextPtr;
ClockFmtScnStorage *prevPtr;
#endif
#if 0
+Tcl_HashEntry hashEntry /* ClockFmtScnStorage is a derivate of Tcl_HashEntry,
* stored by offset +sizeof(self) */
#endif
} ClockFmtScnStorage;
/*
* Prototypes of module functions.
*/
MODULE_SCOPE int ToSeconds(int Hours, int Minutes,
int Seconds, MERIDIAN Meridian);
MODULE_SCOPE int IsGregorianLeapYear(TclDateFields *);
MODULE_SCOPE void
GetJulianDayFromEraYearWeekDay(
TclDateFields *fields, int changeover);
MODULE_SCOPE void
GetJulianDayFromEraYearMonthDay(
TclDateFields *fields, int changeover);
MODULE_SCOPE void
GetJulianDayFromEraYearDay(
TclDateFields *fields, int changeover);
MODULE_SCOPE int ConvertUTCToLocal(ClientData clientData, Tcl_Interp *,
TclDateFields *, Tcl_Obj *timezoneObj, int);
MODULE_SCOPE Tcl_Obj *
LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
int, Tcl_Obj *const *, Tcl_WideInt rangesVal[2]);
MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info);
/* tclClock.c module declarations */
MODULE_SCOPE Tcl_Obj *
ClockSetupTimeZone(ClientData clientData,
Tcl_Interp *interp, Tcl_Obj *timezoneObj);
MODULE_SCOPE Tcl_Obj *
ClockMCDict(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE Tcl_Obj *
ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey);
MODULE_SCOPE Tcl_Obj *
ClockMCGetIdx(ClockFmtScnCmdArgs *opts, int mcKey);
MODULE_SCOPE int ClockMCSetIdx(ClockFmtScnCmdArgs *opts, int mcKey,
Tcl_Obj *valObj);
/* tclClockFmt.c module declarations */
MODULE_SCOPE Tcl_Obj*
ClockFrmObjGetLocFmtKey(Tcl_Interp *interp,
Tcl_Obj *objPtr);
MODULE_SCOPE ClockFmtScnStorage *
Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp,
Tcl_Obj *objPtr);
MODULE_SCOPE Tcl_Obj *
ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int ClockScan(register DateInfo *info,
Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int ClockFormat(register DateFormat *dateFmt,
ClockFmtScnCmdArgs *opts);
MODULE_SCOPE void ClockFrmScnClearCaches(void);
#endif /* _TCLCLOCK_H */
+7 -109
View File
@@ -51,8 +51,6 @@ static int DictSetCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictSizeCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictSmartRefCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictUnsetCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictUpdateCmd(ClientData dummy, Tcl_Interp *interp,
@@ -100,7 +98,6 @@ static const EnsembleImplMap implementationMap[] = {
{"replace", DictReplaceCmd, NULL, NULL, NULL, 0 },
{"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 },
{"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
{"smartref",DictSmartRefCmd,NULL, NULL, NULL, 0 },
{"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 },
{"update", DictUpdateCmd, TclCompileDictUpdateCmd, NULL, NULL, 0 },
{"values", DictValuesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
@@ -156,7 +153,7 @@ typedef struct Dict {
* must be assignable as well as readable.
*/
#define DICT(dictObj) (*((Dict **)&(dictObj)->internalRep.twoPtrValue.ptr1))
#define DICT(dictObj) ((dictObj)->internalRep.twoPtrValue.ptr1)
/*
* The structure below defines the dictionary object type by means of
@@ -490,15 +487,14 @@ static void
UpdateStringOfDict(
Tcl_Obj *dictPtr)
{
#define LOCAL_SIZE 20
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
#define LOCAL_SIZE 64
char localFlags[LOCAL_SIZE], *flagPtr = NULL;
Dict *dict = DICT(dictPtr);
ChainEntry *cPtr;
Tcl_Obj *keyPtr, *valuePtr;
int i, length, bytesNeeded = 0;
const char *elem;
char *dst;
const int maxFlags = UINT_MAX / sizeof(int);
/*
* This field is the most useful one in the whole hash structure, and it
@@ -520,10 +516,8 @@ UpdateStringOfDict(
if (numElems <= LOCAL_SIZE) {
flagPtr = localFlags;
} else if (numElems > maxFlags) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
} else {
flagPtr = ckalloc(numElems * sizeof(int));
flagPtr = ckalloc(numElems);
}
for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
/*
@@ -1958,102 +1952,6 @@ DictSizeCmd(
return result;
}
/*
*----------------------------------------------------------------------
*
* Tcl_DictObjSmartRef --
*
* This function returns new tcl-object with the smart reference to
* dictionary object.
*
* Object returned with this function is a smart reference (pointer),
* so new object of type tclDictType, that directly references given
* dictionary object (with internally increased refCount).
*
* The usage of such pointer objects allows to hold more as one
* reference to the same real dictionary object, allows to make a pointer
* to part of another dictionary, allows to change the dictionary without
* regarding of the "shared" state of the dictionary object.
*
* Prevents "called with shared object" exception if object is multiple
* referenced.
*
* Results:
* The newly create object (contains smart reference) is returned.
* The returned object has a ref count of 0.
*
* Side effects:
* Increases ref count of the referenced dictionary.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
Tcl_DictObjSmartRef(
Tcl_Interp *interp,
Tcl_Obj *dictPtr)
{
Tcl_Obj *result;
Dict *dict;
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return NULL;
}
dict = DICT(dictPtr);
result = Tcl_NewObj();
DICT(result) = dict;
dict->refCount++;
result->internalRep.twoPtrValue.ptr2 = NULL;
result->typePtr = &tclDictType;
return result;
}
/*
*----------------------------------------------------------------------
*
* DictSmartRefCmd --
*
* This function implements the "dict smartref" Tcl command.
*
* See description of Tcl_DictObjSmartRef for details.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
static int
DictSmartRefCmd(
ClientData dummy,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Tcl_Obj *result;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
return TCL_ERROR;
}
result = Tcl_DictObjSmartRef(interp, objv[1]);
if (result == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, result);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
@@ -3634,7 +3532,7 @@ TclDictWithFinish(
* If the dictionary variable doesn't exist, drop everything silently.
*/
dictPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
dictPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
TCL_LEAVE_ERR_MSG, index);
if (dictPtr == NULL) {
return TCL_OK;
@@ -3717,8 +3615,8 @@ TclDictWithFinish(
* Write back the outermost dictionary to the variable.
*/
if (TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, dictPtr,
TCL_LEAVE_ERR_MSG, index) == NULL) {
if (TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
dictPtr, TCL_LEAVE_ERR_MSG, index) == NULL) {
if (allocdict) {
TclDecrRefCount(dictPtr);
}
+62 -35
View File
@@ -2296,8 +2296,11 @@ UtfToUtfProc(
const char *srcStart, *srcEnd, *srcClose;
const char *dstStart, *dstEnd;
int result, numChars, charLimit = INT_MAX;
Tcl_UniChar ch;
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
if (flags & TCL_ENCODING_START) {
*statePtr = 0;
}
result = TCL_OK;
srcStart = src;
@@ -2329,7 +2332,7 @@ UtfToUtfProc(
}
if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && pureNullMode == 0)) {
/*
* Copy 7bit chatacters, but skip null-bytes when we are in input
* Copy 7bit characters, but skip null-bytes when we are in input
* mode, so that they get converted to 0xc080.
*/
@@ -2345,16 +2348,23 @@ UtfToUtfProc(
} else if (!Tcl_UtfCharComplete(src, srcEnd - src)) {
/*
* Always check before using TclUtfToUniChar. Not doing can so
* cause it run beyond the endof the buffer! If we happen such an
* incomplete char its byts are made to represent themselves.
* cause it run beyond the end of the buffer! If we happen such an
* incomplete char its bytes are made to represent themselves.
*/
ch = (unsigned char) *src;
*chPtr = (unsigned char) *src;
src += 1;
dst += Tcl_UniCharToUtf(ch, dst);
dst += Tcl_UniCharToUtf(*chPtr, dst);
} else {
src += TclUtfToUniChar(src, &ch);
dst += Tcl_UniCharToUtf(ch, dst);
int len = TclUtfToUniChar(src, chPtr);
src += len;
dst += Tcl_UniCharToUtf(*chPtr, dst);
#if TCL_UTF_MAX == 4
if (!len) {
src += TclUtfToUniChar(src, chPtr);
dst += Tcl_UniCharToUtf(*chPtr, dst);
}
#endif
}
}
@@ -2410,8 +2420,11 @@ UnicodeToUtfProc(
const char *srcStart, *srcEnd;
const char *dstEnd, *dstStart;
int result, numChars, charLimit = INT_MAX;
Tcl_UniChar ch;
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
if (flags & TCL_ENCODING_START) {
*statePtr = 0;
}
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
@@ -2439,11 +2452,11 @@ UnicodeToUtfProc(
* Tcl_UniChar-size data.
*/
ch = *(Tcl_UniChar *)src;
if (ch && ch < 0x80) {
*dst++ = (ch & 0xFF);
*chPtr = *(Tcl_UniChar *)src;
if (*chPtr && *chPtr < 0x80) {
*dst++ = (*chPtr & 0xFF);
} else {
dst += Tcl_UniCharToUtf(ch, dst);
dst += Tcl_UniCharToUtf(*chPtr, dst);
}
src += sizeof(Tcl_UniChar);
}
@@ -2500,8 +2513,11 @@ UtfToUnicodeProc(
{
const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
int result, numChars;
Tcl_UniChar ch;
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
if (flags & TCL_ENCODING_START) {
*statePtr = 0;
}
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
@@ -2527,7 +2543,7 @@ UtfToUnicodeProc(
result = TCL_CONVERT_NOSPACE;
break;
}
src += TclUtfToUniChar(src, &ch);
src += TclUtfToUniChar(src, chPtr);
/*
* Need to handle this in a way that won't cause misalignment by
@@ -2536,23 +2552,23 @@ UtfToUnicodeProc(
#ifdef WORDS_BIGENDIAN
#if TCL_UTF_MAX > 4
*dst++ = (ch >> 24);
*dst++ = ((ch >> 16) & 0xFF);
*dst++ = ((ch >> 8) & 0xFF);
*dst++ = (ch & 0xFF);
*dst++ = (*chPtr >> 24);
*dst++ = ((*chPtr >> 16) & 0xFF);
*dst++ = ((*chPtr >> 8) & 0xFF);
*dst++ = (*chPtr & 0xFF);
#else
*dst++ = (ch >> 8);
*dst++ = (ch & 0xFF);
*dst++ = (*chPtr >> 8);
*dst++ = (*chPtr & 0xFF);
#endif
#else
#if TCL_UTF_MAX > 4
*dst++ = (ch & 0xFF);
*dst++ = ((ch >> 8) & 0xFF);
*dst++ = ((ch >> 16) & 0xFF);
*dst++ = (ch >> 24);
*dst++ = (*chPtr & 0xFF);
*dst++ = ((*chPtr >> 8) & 0xFF);
*dst++ = ((*chPtr >> 16) & 0xFF);
*dst++ = (*chPtr >> 24);
#else
*dst++ = (ch & 0xFF);
*dst++ = (ch >> 8);
*dst++ = (*chPtr & 0xFF);
*dst++ = (*chPtr >> 8);
#endif
#endif
}
@@ -2610,7 +2626,7 @@ TableToUtfProc(
const char *srcStart, *srcEnd;
const char *dstEnd, *dstStart, *prefixBytes;
int result, byte, numChars, charLimit = INT_MAX;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
const unsigned short *const *toUnicode;
const unsigned short *pageZero;
TableEncodingData *dataPtr = clientData;
@@ -2722,7 +2738,7 @@ TableFromUtfProc(
{
const char *srcStart, *srcEnd, *srcClose;
const char *dstStart, *dstEnd, *prefixBytes;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
int result, len, word, numChars;
TableEncodingData *dataPtr = clientData;
const unsigned short *const *fromUnicode;
@@ -2754,7 +2770,7 @@ TableFromUtfProc(
}
len = TclUtfToUniChar(src, &ch);
#if TCL_UTF_MAX > 3
#if TCL_UTF_MAX > 4
/*
* This prevents a crash condition. More evaluation is required for
* full support of int Tcl_UniChar. [Bug 1004065]
@@ -2763,6 +2779,10 @@ TableFromUtfProc(
if (ch & 0xffff0000) {
word = 0;
} else
#elif TCL_UTF_MAX == 4
if (!len) {
word = 0;
} else
#endif
word = fromUnicode[(ch >> 8)][ch & 0xff];
@@ -2856,7 +2876,7 @@ Iso88591ToUtfProc(
result = TCL_OK;
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
@@ -2942,7 +2962,7 @@ Iso88591FromUtfProc(
dstEnd = dst + dstLen - 1;
for (numChars = 0; src < srcEnd; numChars++) {
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
int len;
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
@@ -2960,11 +2980,18 @@ Iso88591FromUtfProc(
* Check for illegal characters.
*/
if (ch > 0xff) {
if (ch > 0xff
#if TCL_UTF_MAX == 4
|| !len
#endif
) {
if (flags & TCL_ENCODING_STOPONERROR) {
result = TCL_CONVERT_UNKNOWN;
break;
}
#if TCL_UTF_MAX == 4
if (!len) len = 4;
#endif
/*
* Plunge on, using '?' as a fallback character.
@@ -3329,7 +3356,7 @@ EscapeFromUtfProc(
for (numChars = 0; src < srcEnd; numChars++) {
unsigned len;
int word;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
/*
@@ -3374,7 +3401,7 @@ EscapeFromUtfProc(
/*
* The state variable has the value of oldState when word is 0.
* In this case, the escape sequense should not be copied to dst
* In this case, the escape sequence should not be copied to dst
* because the current character set is not changed.
*/
+193 -170
View File
@@ -55,12 +55,11 @@ enum EnsSubcmds {
};
static const char *const ensembleCreateOptions[] = {
"-command", "-compile", "-map", "-parameters", "-prefixes",
"-subcommands", "-unknown", NULL
"-command", "-map", "-parameters", "-prefixes", "-subcommands",
"-unknown", NULL
};
enum EnsCreateOpts {
CRT_CMD, CRT_COMPILE, CRT_MAP, CRT_PARAM, CRT_PREFIX,
CRT_SUBCMDS, CRT_UNKNOWN
CRT_CMD, CRT_MAP, CRT_PARAM, CRT_PREFIX, CRT_SUBCMDS, CRT_UNKNOWN
};
static const char *const ensembleConfigOptions[] = {
@@ -147,10 +146,12 @@ TclNamespaceEnsembleCmd(
Tcl_Obj *const objv[])
{
Tcl_Namespace *namespacePtr;
Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp), *cxtPtr,
*foundNsPtr, *altFoundNsPtr, *actualCxtPtr;
Tcl_Command token;
Tcl_DictSearch search;
Tcl_Obj *listObj;
const char *simpleName;
int index, done;
if (nsPtr == NULL || nsPtr->flags & NS_DYING) {
@@ -184,7 +185,6 @@ TclNamespaceEnsembleCmd(
int permitPrefix = 1;
Tcl_Obj *unknownObj = NULL;
Tcl_Obj *paramObj = NULL;
int ensCompFlag = -1;
/*
* Check that we've got option-value pairs... [Bug 1558654]
@@ -197,13 +197,8 @@ TclNamespaceEnsembleCmd(
objv += 2;
objc -= 2;
/*
* Work out what name to use for the command to create. If supplied,
* it is either fully specified or relative to the current namespace.
* If not supplied, it is exactly the name of the current namespace.
*/
name = nsPtr->fullName;
name = nsPtr->name;
cxtPtr = (Namespace *) nsPtr->parentPtr;
/*
* Parse the option list, applying type checks as we go. Note that we
@@ -223,6 +218,7 @@ TclNamespaceEnsembleCmd(
switch ((enum EnsCreateOpts) index) {
case CRT_CMD:
name = TclGetString(objv[1]);
cxtPtr = nsPtr;
continue;
case CRT_SUBCMDS:
if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
@@ -327,12 +323,6 @@ TclNamespaceEnsembleCmd(
return TCL_ERROR;
}
continue;
case CRT_COMPILE:
if (Tcl_GetBooleanFromObj(interp, objv[1],
&ensCompFlag) != TCL_OK) {
return TCL_ERROR;
};
continue;
case CRT_UNKNOWN:
if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
if (allocatedMapFlag) {
@@ -345,6 +335,10 @@ TclNamespaceEnsembleCmd(
}
}
TclGetNamespaceForQualName(interp, name, cxtPtr,
TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr, &actualCxtPtr,
&simpleName);
/*
* Create the ensemble. Note that this might delete another ensemble
* linked to the same namespace, so we must be careful. However, we
@@ -352,18 +346,13 @@ TclNamespaceEnsembleCmd(
* we've created it (and after any deletions have occurred.)
*/
token = Tcl_CreateEnsemble(interp, name, NULL,
(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
token = TclCreateEnsembleInNs(interp, simpleName,
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr,
(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
Tcl_SetEnsembleMappingDict(interp, token, mapObj);
Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
Tcl_SetEnsembleParameterList(interp, token, paramObj);
/*
* Ensemble should be compiled if it has map (performance purposes)
*/
if (ensCompFlag > 0 && mapObj != NULL) {
Tcl_SetEnsembleFlags(interp, token, ENSEMBLE_COMPILE);
}
/*
* Tricky! Must ensure that the result is not shared (command delete
@@ -650,48 +639,38 @@ TclNamespaceEnsembleCmd(
/*
*----------------------------------------------------------------------
*
* Tcl_CreateEnsemble --
* TclCreateEnsembleInNs --
*
* Create a simple ensemble attached to the given namespace.
*
* Results:
* The token for the command created.
*
* Side effects:
* The ensemble is created and marked for compilation.
* Like Tcl_CreateEnsemble, but additionally accepts as an argument the
* name of the namespace to create the command in.
*
*----------------------------------------------------------------------
*/
Tcl_Command
Tcl_CreateEnsemble(
Tcl_Interp *interp,
const char *name,
Tcl_Namespace *namespacePtr,
int flags)
TclCreateEnsembleInNs(
Tcl_Interp *interp,
const char *name, /* Simple name of command to create (no */
/* namespace components). */
Tcl_Namespace /* Name of namespace to create the command in. */
*nameNsPtr,
Tcl_Namespace
*ensembleNsPtr, /* Name of the namespace for the ensemble. */
int flags
)
{
Namespace *nsPtr = (Namespace *) namespacePtr;
EnsembleConfig *ensemblePtr = ckalloc(sizeof(EnsembleConfig));
Tcl_Obj *nameObj = NULL;
Namespace *nsPtr = (Namespace *) ensembleNsPtr;
EnsembleConfig *ensemblePtr;
Tcl_Command token;
if (nsPtr == NULL) {
nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
}
/*
* Make the name of the ensemble into a fully qualified name. This might
* allocate a temporary object.
*/
if (!(name[0] == ':' && name[1] == ':')) {
nameObj = NewNsObj((Tcl_Namespace *) nsPtr);
if (nsPtr->parentPtr == NULL) {
Tcl_AppendStringsToObj(nameObj, name, NULL);
} else {
Tcl_AppendStringsToObj(nameObj, "::", name, NULL);
}
Tcl_IncrRefCount(nameObj);
name = TclGetString(nameObj);
ensemblePtr = ckalloc(sizeof(EnsembleConfig));
token = TclNRCreateCommandInNs(interp, name,
(Tcl_Namespace *) nameNsPtr, NsEnsembleImplementationCmd,
NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig);
if (token == NULL) {
ckfree(ensemblePtr);
return NULL;
}
ensemblePtr->nsPtr = nsPtr;
@@ -704,9 +683,7 @@ Tcl_CreateEnsemble(
ensemblePtr->numParameters = 0;
ensemblePtr->parameterList = NULL;
ensemblePtr->unknownHandler = NULL;
ensemblePtr->token = Tcl_NRCreateCommand(interp, name,
NsEnsembleImplementationCmd, NsEnsembleImplementationCmdNR,
ensemblePtr, DeleteEnsembleConfig);
ensemblePtr->token = token;
ensemblePtr->next = (EnsembleConfig *) nsPtr->ensembles;
nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr;
@@ -723,11 +700,52 @@ Tcl_CreateEnsemble(
((Command *) ensemblePtr->token)->compileProc = TclCompileEnsemble;
}
if (nameObj != NULL) {
TclDecrRefCount(nameObj);
}
return ensemblePtr->token;
}
/*
*----------------------------------------------------------------------
*
* Tcl_CreateEnsemble
*
* Create a simple ensemble attached to the given namespace.
*
* Deprecated by TclCreateEnsembleInNs.
*
* Value
*
* The token for the command created.
*
* Effect
* The ensemble is created and marked for compilation.
*
*
*----------------------------------------------------------------------
*/
Tcl_Command
Tcl_CreateEnsemble(
Tcl_Interp *interp,
const char *name,
Tcl_Namespace *namespacePtr,
int flags)
{
Namespace *nsPtr = (Namespace *)namespacePtr, *foundNsPtr, *altNsPtr,
*actualNsPtr;
const char * simpleName;
if (nsPtr == NULL) {
nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
}
TclGetNamespaceForQualName(interp, name, nsPtr, TCL_CREATE_NS_IF_UNKNOWN,
&foundNsPtr, &altNsPtr, &actualNsPtr, &simpleName);
return TclCreateEnsembleInNs(interp, simpleName,
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, flags);
}
/*
*----------------------------------------------------------------------
@@ -1899,6 +1917,7 @@ NsEnsembleImplementationCmdNR(
TclSkipTailcall(interp);
Tcl_ListObjGetElements(NULL, copyPtr, &copyObjc, &copyObjv);
((Interp *)interp)->lookupNsPtr = ensemblePtr->nsPtr;
return TclNREvalObjv(interp, copyObjc, copyObjv, TCL_EVAL_INVOKE, NULL);
}
@@ -2412,14 +2431,32 @@ MakeCachedEnsembleCommand(
*----------------------------------------------------------------------
*/
static void
ClearTable(
EnsembleConfig *ensemblePtr)
{
Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
if (hash->numEntries != 0) {
Tcl_HashSearch search;
Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(hash, &search);
while (hPtr != NULL) {
Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
Tcl_DecrRefCount(prefixObj);
hPtr = Tcl_NextHashEntry(&search);
}
ckfree((char *) ensemblePtr->subcommandArrayPtr);
}
Tcl_DeleteHashTable(hash);
}
static void
DeleteEnsembleConfig(
ClientData clientData)
{
EnsembleConfig *ensemblePtr = clientData;
Namespace *nsPtr = ensemblePtr->nsPtr;
Tcl_HashSearch search;
Tcl_HashEntry *hEnt;
/*
* Unlink from the ensemble chain if it has not been marked as having been
@@ -2453,17 +2490,7 @@ DeleteEnsembleConfig(
* Kill the pointer-containing fields.
*/
if (ensemblePtr->subcommandTable.numEntries != 0) {
ckfree(ensemblePtr->subcommandArrayPtr);
}
hEnt = Tcl_FirstHashEntry(&ensemblePtr->subcommandTable, &search);
while (hEnt != NULL) {
Tcl_Obj *prefixObj = Tcl_GetHashValue(hEnt);
Tcl_DecrRefCount(prefixObj);
hEnt = Tcl_NextHashEntry(&search);
}
Tcl_DeleteHashTable(&ensemblePtr->subcommandTable);
ClearTable(ensemblePtr);
if (ensemblePtr->subcmdList != NULL) {
Tcl_DecrRefCount(ensemblePtr->subcmdList);
}
@@ -2493,10 +2520,9 @@ DeleteEnsembleConfig(
* BuildEnsembleConfig --
*
* Create the internal data structures that describe how an ensemble
* looks, being a hash mapping from the full command name to the Tcl list
* looks, being a hash mapping from the simple command name to the Tcl list
* that describes the implementation prefix words, and a sorted array of
* all the full command names to allow for reasonably efficient
* unambiguous prefix handling.
* the names to allow for reasonably efficient unambiguous prefix handling.
*
* Results:
* None.
@@ -2519,100 +2545,101 @@ BuildEnsembleConfig(
int i, j, isNew;
Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
Tcl_HashEntry *hPtr;
Tcl_Obj *mapDict = ensemblePtr->subcommandDict;
Tcl_Obj *subList = ensemblePtr->subcmdList;
if (hash->numEntries != 0) {
/*
* Remove pre-existing table.
*/
ClearTable(ensemblePtr);
Tcl_InitHashTable(hash, TCL_STRING_KEYS);
ckfree(ensemblePtr->subcommandArrayPtr);
hPtr = Tcl_FirstHashEntry(hash, &search);
while (hPtr != NULL) {
Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
if (subList) {
int subc;
Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj;
char *name;
Tcl_DecrRefCount(prefixObj);
hPtr = Tcl_NextHashEntry(&search);
}
Tcl_DeleteHashTable(hash);
Tcl_InitHashTable(hash, TCL_STRING_KEYS);
}
/*
* There is a list of exactly what subcommands go in the table.
* Must determine the target for each.
*/
/*
* See if we've got an export list. If so, we will only export exactly
* those commands, which may be either implemented by the prefix in the
* subcommandDict or mapped directly onto the namespace's commands.
*/
Tcl_ListObjGetElements(NULL, subList, &subc, &subv);
if (subList == mapDict) {
/*
* Strange case where explicit list of subcommands is same value
* as the dict mapping to targets.
*/
if (ensemblePtr->subcmdList != NULL) {
Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj;
int subcmdc;
for (i = 0; i < subc; i += 2) {
name = TclGetString(subv[i]);
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
if (!isNew) {
cmdObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
Tcl_DecrRefCount(cmdObj);
}
Tcl_SetHashValue(hPtr, subv[i+1]);
Tcl_IncrRefCount(subv[i+1]);
TclListObjGetElements(NULL, ensemblePtr->subcmdList, &subcmdc,
&subcmdv);
for (i=0 ; i<subcmdc ; i++) {
const char *name = TclGetString(subcmdv[i]);
name = TclGetString(subv[i+1]);
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
if (isNew) {
cmdObj = Tcl_NewStringObj(name, -1);
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
Tcl_SetHashValue(hPtr, cmdPrefixObj);
Tcl_IncrRefCount(cmdPrefixObj);
}
}
} else {
/* Usual case where we can freely act on the list and dict. */
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
for (i = 0; i < subc; i++) {
name = TclGetString(subv[i]);
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
if (!isNew) {
continue;
}
/*
* Skip non-unique cases.
*/
/* Lookup target in the dictionary */
if (mapDict) {
Tcl_DictObjGet(NULL, mapDict, subv[i], &target);
if (target) {
Tcl_SetHashValue(hPtr, target);
Tcl_IncrRefCount(target);
continue;
}
}
if (!isNew) {
continue;
}
/*
* target was not in the dictionary so map onto the namespace.
* Note in this case that we do not guarantee that the
* command is actually there; that is the programmer's
* responsibility (or [::unknown] of course).
*/
cmdObj = Tcl_NewStringObj(name, -1);
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
Tcl_SetHashValue(hPtr, cmdPrefixObj);
Tcl_IncrRefCount(cmdPrefixObj);
}
}
} else if (mapDict) {
/*
* No subcmd list, but we do have a mapping dictionary so we should
* use the keys of that. Convert the dictionary's contents into the
* form required for the ensemble's internal hashtable.
*/
/*
* Look in our dictionary (if present) for the command.
*/
Tcl_DictSearch dictSearch;
Tcl_Obj *keyObj, *valueObj;
int done;
if (ensemblePtr->subcommandDict != NULL) {
Tcl_DictObjGet(NULL, ensemblePtr->subcommandDict, subcmdv[i],
&target);
if (target != NULL) {
Tcl_SetHashValue(hPtr, target);
Tcl_IncrRefCount(target);
continue;
}
}
Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
&keyObj, &valueObj, &done);
while (!done) {
char *name = TclGetString(keyObj);
/*
* Not there, so map onto the namespace. Note in this case that we
* do not guarantee that the command is actually there; that is
* the programmer's responsibility (or [::unknown] of course).
*/
cmdObj = NewNsObj((Tcl_Namespace *) ensemblePtr->nsPtr);
if (ensemblePtr->nsPtr->parentPtr != NULL) {
Tcl_AppendStringsToObj(cmdObj, "::", name, NULL);
} else {
Tcl_AppendStringsToObj(cmdObj, name, NULL);
}
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
Tcl_SetHashValue(hPtr, cmdPrefixObj);
Tcl_IncrRefCount(cmdPrefixObj);
}
} else if (ensemblePtr->subcommandDict != NULL) {
/*
* No subcmd list, but we do have a mapping dictionary so we should
* use the keys of that. Convert the dictionary's contents into the
* form required for the ensemble's internal hashtable.
*/
Tcl_DictSearch dictSearch;
Tcl_Obj *keyObj, *valueObj;
int done;
Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
&keyObj, &valueObj, &done);
while (!done) {
const char *name = TclGetString(keyObj);
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
Tcl_SetHashValue(hPtr, valueObj);
Tcl_IncrRefCount(valueObj);
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
}
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
Tcl_SetHashValue(hPtr, valueObj);
Tcl_IncrRefCount(valueObj);
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
}
} else {
/*
* Discover what commands are actually exported by the namespace.
@@ -2648,11 +2675,7 @@ BuildEnsembleConfig(
if (isNew) {
Tcl_Obj *cmdObj, *cmdPrefixObj;
TclNewObj(cmdObj);
Tcl_AppendStringsToObj(cmdObj,
ensemblePtr->nsPtr->fullName,
(ensemblePtr->nsPtr->parentPtr ? "::" : ""),
nsCmdName, NULL);
cmdObj = Tcl_NewStringObj(nsCmdName, -1);
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
Tcl_SetHashValue(hPtr, cmdPrefixObj);
Tcl_IncrRefCount(cmdPrefixObj);
+13 -10
View File
@@ -17,11 +17,6 @@
TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ. */
/* MODULE_SCOPE */
size_t TclEnvEpoch = 0; /* Epoch of the tcl environment
* (if changed with tcl-env). */
static struct {
int cacheSize; /* Number of env strings in cache. */
char **cache; /* Array containing all of the environment
@@ -135,6 +130,7 @@ TclSetupEnv(
* '='; ignore the entry.
*/
Tcl_DStringFree(&envString);
continue;
}
p2++;
@@ -376,7 +372,6 @@ Tcl_PutEnv(
value[0] = '\0';
TclSetEnv(name, value+1);
}
TclEnvEpoch++;
Tcl_DStringFree(&nameString);
return 0;
@@ -585,7 +580,6 @@ EnvTraceProc(
if (flags & TCL_TRACE_ARRAY) {
TclSetupEnv(interp);
TclEnvEpoch++;
return NULL;
}
@@ -606,7 +600,6 @@ EnvTraceProc(
value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY);
TclSetEnv(name2, value);
TclEnvEpoch++;
}
/*
@@ -630,7 +623,6 @@ EnvTraceProc(
if (flags & TCL_TRACE_UNSETS) {
TclUnsetEnv(name2);
TclEnvEpoch++;
}
return NULL;
}
@@ -731,14 +723,25 @@ TclFinalizeEnvironment(void)
* strings. This may leak more memory that strictly necessary, since some
* of the strings may no longer be in the environment. However,
* determining which ones are ok to delete is n-squared, and is pretty
* unlikely, so we don't bother.
* unlikely, so we don't bother. However, in the case of DPURIFY, just
* free all strings in the cache.
*/
if (env.cache) {
#ifdef PURIFY
int i;
for (i = 0; i < env.cacheSize; i++) {
ckfree(env.cache[i]);
}
#endif
ckfree(env.cache);
env.cache = NULL;
env.cacheSize = 0;
#ifndef USE_PUTENV
if ((env.ourEnviron != NULL)) {
ckfree(env.ourEnviron);
env.ourEnviron = NULL;
}
env.ourEnvironSize = 0;
#endif
}
+151 -200
View File
@@ -1333,12 +1333,12 @@ TclStackAlloc(
int numBytes)
{
Interp *iPtr = (Interp *) interp;
int numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
int numWords;
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
return (void *) ckalloc(numBytes);
}
numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
return (void *) StackAllocWords(interp, numWords);
}
@@ -3321,7 +3321,7 @@ TEBCresume(
*/
DECACHE_STACK_INFO();
objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr,
objResultPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr,
part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
if (!objResultPtr) {
@@ -3568,7 +3568,7 @@ TEBCresume(
doCallPtrSetVar:
DECACHE_STACK_INFO();
objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr,
objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr,
part1Ptr, part2Ptr, valuePtr, storeFlags, opnd);
CACHE_STACK_INFO();
if (!objResultPtr) {
@@ -3704,7 +3704,7 @@ TEBCresume(
VarHashRefCount(arrayPtr)++;
}
DECACHE_STACK_INFO();
objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr,
objResultPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr,
part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
if (TclIsVarInHash(varPtr)) {
@@ -3733,7 +3733,7 @@ TEBCresume(
}
}
DECACHE_STACK_INFO();
objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr,
objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr,
part2Ptr, objResultPtr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
if (!objResultPtr) {
@@ -3997,7 +3997,7 @@ TEBCresume(
Tcl_DecrRefCount(incrPtr);
} else {
DECACHE_STACK_INFO();
objResultPtr = TclPtrIncrObjVar(interp, varPtr, arrayPtr,
objResultPtr = TclPtrIncrObjVarIdx(interp, varPtr, arrayPtr,
part1Ptr, part2Ptr, incrPtr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
Tcl_DecrRefCount(incrPtr);
@@ -4152,7 +4152,7 @@ TEBCresume(
slowUnsetScalar:
DECACHE_STACK_INFO();
if (TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, flags,
if (TclPtrUnsetVarIdx(interp, varPtr, NULL, NULL, NULL, flags,
opnd) != TCL_OK && flags) {
goto errorInUnset;
}
@@ -4169,7 +4169,8 @@ TEBCresume(
}
TRACE(("%s %u \"%.30s\" => ",
(flags ? "normal" : "noerr"), opnd, O2S(part2Ptr)));
if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr)) {
if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr)
&& !(arrayPtr->flags & VAR_SEARCH_ACTIVE)) {
varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr);
if (varPtr && TclIsVarDirectUnsettable(varPtr)) {
/*
@@ -4204,7 +4205,7 @@ TEBCresume(
if (flags & TCL_LEAVE_ERR_MSG) {
goto errorInUnset;
}
} else if (TclPtrUnsetVar(interp, varPtr, arrayPtr, NULL, part2Ptr,
} else if (TclPtrUnsetVarIdx(interp, varPtr, arrayPtr, NULL, part2Ptr,
flags, opnd) != TCL_OK && (flags & TCL_LEAVE_ERR_MSG)) {
goto errorInUnset;
}
@@ -4261,7 +4262,7 @@ TEBCresume(
varPtr->value.objPtr = NULL;
} else {
DECACHE_STACK_INFO();
TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
TclPtrUnsetVarIdx(interp, varPtr, NULL, NULL, NULL, 0, opnd);
CACHE_STACK_INFO();
}
NEXT_INST_F(5, 0, 0);
@@ -4294,17 +4295,12 @@ TEBCresume(
varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, 0, NULL,
/*createPart1*/0, /*createPart2*/0, &arrayPtr);
doArrayExists:
if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
DECACHE_STACK_INFO();
result = TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr,
NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|
TCL_GLOBAL_ONLY|TCL_TRACE_ARRAY), 1, opnd);
CACHE_STACK_INFO();
if (result == TCL_ERROR) {
TRACE_ERROR(interp);
goto gotError;
}
DECACHE_STACK_INFO();
result = TclCheckArrayTraces(interp, varPtr, arrayPtr, part1Ptr, opnd);
CACHE_STACK_INFO();
if (result == TCL_ERROR) {
TRACE_ERROR(interp);
goto gotError;
}
if (varPtr && TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
objResultPtr = TCONST(1);
@@ -4477,7 +4473,7 @@ TEBCresume(
if (TclIsVarInHash(otherPtr)) {
VarHashRefCount(otherPtr)++;
}
} else if (TclPtrObjMakeUpvar(interp, otherPtr, NULL, 0,
} else if (TclPtrObjMakeUpvarIdx(interp, otherPtr, NULL, 0,
opnd) != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
@@ -5089,16 +5085,9 @@ TEBCresume(
goto gotError;
}
/*
* Select the list item based on the index. Negative operand means
* end-based indexing.
*/
/* Decode end-offset index values. */
if (opnd < -1) {
index = opnd+1 + objc;
} else {
index = opnd;
}
index = TclIndexDecode(opnd, objc - 1);
pcAdjustment = 5;
lindexFastPath:
@@ -5246,60 +5235,64 @@ TEBCresume(
}
#endif
/*
* Adjust the indices for end-based handling.
*/
if (fromIdx < -1) {
fromIdx += 1+objc;
if (fromIdx < -1) {
fromIdx = -1;
}
} else if (fromIdx > objc) {
fromIdx = objc;
}
if (toIdx < -1) {
toIdx += 1 + objc;
if (toIdx < -1) {
toIdx = -1;
}
} else if (toIdx > objc) {
toIdx = objc;
/* Every range of an empty list is an empty list */
if (objc == 0) {
TRACE_APPEND(("\n"));
NEXT_INST_F(9, 0, 0);
}
/*
* Check if we are referring to a valid, non-empty list range, and if
* so, build the list of elements in that range.
/* Decode index value operands. */
/*
assert ( toIdx != TCL_INDEX_AFTER);
*
* Extra safety for legacy bytecodes:
*/
if (toIdx == TCL_INDEX_AFTER) {
toIdx = TCL_INDEX_END;
}
if (fromIdx<=toIdx && fromIdx<objc && toIdx>=0) {
if (fromIdx < 0) {
fromIdx = 0;
}
if (toIdx >= objc) {
toIdx = objc-1;
}
if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) {
/*
* BEWARE! This is looking inside the implementation of the
* list type.
*/
if ((toIdx == TCL_INDEX_BEFORE) || (fromIdx == TCL_INDEX_AFTER)) {
goto emptyList;
}
toIdx = TclIndexDecode(toIdx, objc - 1);
if (toIdx < 0) {
goto emptyList;
} else if (toIdx >= objc) {
toIdx = objc - 1;
}
List *listPtr = valuePtr->internalRep.twoPtrValue.ptr1;
assert ( toIdx >= 0 && toIdx < objc);
/*
assert ( fromIdx != TCL_INDEX_BEFORE );
*
* Extra safety for legacy bytecodes:
*/
if (fromIdx == TCL_INDEX_BEFORE) {
fromIdx = TCL_INDEX_START;
}
if (listPtr->refCount == 1) {
for (index=toIdx+1; index<objc ; index++) {
TclDecrRefCount(objv[index]);
}
listPtr->elemCount = toIdx+1;
listPtr->canonicalFlag = 1;
TclInvalidateStringRep(valuePtr);
TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
NEXT_INST_F(9, 0, 0);
fromIdx = TclIndexDecode(fromIdx, objc - 1);
if (fromIdx < 0) {
fromIdx = 0;
}
if (fromIdx <= toIdx) {
/* Construct the subsquence list */
/* unshared optimization */
if (Tcl_IsShared(valuePtr)) {
objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx);
} else {
if (toIdx != objc - 1) {
Tcl_ListObjReplace(NULL, valuePtr, toIdx + 1, LIST_MAX,
0, NULL);
}
Tcl_ListObjReplace(NULL, valuePtr, 0, fromIdx, 0, NULL);
TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
NEXT_INST_F(9, 0, 0);
}
objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx);
} else {
emptyList:
TclNewObj(objResultPtr);
}
@@ -5391,88 +5384,10 @@ TEBCresume(
value2Ptr = OBJ_AT_TOS;
valuePtr = OBJ_UNDER_TOS;
if (valuePtr == value2Ptr) {
match = 0;
} else {
/*
* We only need to check (in)equality when we have equal length
* strings. We can use memcmp in all (n)eq cases because we
* don't need to worry about lexical LE/BE variance.
*/
typedef int (*memCmpFn_t)(const void*, const void*, size_t);
memCmpFn_t memCmpFn;
{
int checkEq = ((*pc == INST_EQ) || (*pc == INST_NEQ)
|| (*pc == INST_STR_EQ) || (*pc == INST_STR_NEQ));
if (TclIsPureByteArray(valuePtr)
&& TclIsPureByteArray(value2Ptr)) {
s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len);
s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
memCmpFn = memcmp;
} else if ((valuePtr->typePtr == &tclStringType)
&& (value2Ptr->typePtr == &tclStringType)) {
/*
* Do a unicode-specific comparison if both of the args are of
* String type. If the char length == byte length, we can do a
* memcmp. In benchmark testing this proved the most efficient
* check between the unicode and string comparison operations.
*/
s1len = Tcl_GetCharLength(valuePtr);
s2len = Tcl_GetCharLength(value2Ptr);
if ((s1len == valuePtr->length)
&& (valuePtr->bytes != NULL)
&& (s2len == value2Ptr->length)
&& (value2Ptr->bytes != NULL)) {
s1 = valuePtr->bytes;
s2 = value2Ptr->bytes;
memCmpFn = memcmp;
} else {
s1 = (char *) Tcl_GetUnicode(valuePtr);
s2 = (char *) Tcl_GetUnicode(value2Ptr);
if (
#ifdef WORDS_BIGENDIAN
1
#else
checkEq
#endif
) {
memCmpFn = memcmp;
s1len *= sizeof(Tcl_UniChar);
s2len *= sizeof(Tcl_UniChar);
} else {
memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp;
}
}
} else {
/*
* strcmp can't do a simple memcmp in order to handle the
* special Tcl \xC0\x80 null encoding for utf-8.
*/
s1 = TclGetStringFromObj(valuePtr, &s1len);
s2 = TclGetStringFromObj(value2Ptr, &s2len);
if (checkEq) {
memCmpFn = memcmp;
} else {
memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
}
}
if (checkEq && (s1len != s2len)) {
match = 1;
} else {
/*
* The comparison function should compare up to the minimum
* byte length only.
*/
match = memCmpFn(s1, s2,
(size_t) ((s1len < s2len) ? s1len : s2len));
if (match == 0) {
match = s1len - s2len;
}
}
match = TclStringCmp(valuePtr, value2Ptr, checkEq, 0, -1);
}
/*
@@ -5645,31 +5560,58 @@ TEBCresume(
length = Tcl_GetCharLength(valuePtr);
TRACE(("\"%.20s\" %d %d => ", O2S(valuePtr), fromIdx, toIdx));
/*
* Adjust indices for end-based indexing.
*/
if (fromIdx < -1) {
fromIdx += 1 + length;
if (fromIdx < 0) {
fromIdx = 0;
}
} else if (fromIdx >= length) {
fromIdx = length;
/* Every range of an empty value is an empty value */
if (length == 0) {
TRACE_APPEND(("\n"));
NEXT_INST_F(9, 0, 0);
}
if (toIdx < -1) {
toIdx += 1 + length;
/* Decode index operands. */
/*
assert ( toIdx != TCL_INDEX_BEFORE );
assert ( toIdx != TCL_INDEX_AFTER);
*
* Extra safety for legacy bytecodes:
*/
if (toIdx == TCL_INDEX_BEFORE) {
goto emptyRange;
}
if (toIdx == TCL_INDEX_AFTER) {
toIdx = TCL_INDEX_END;
}
toIdx = TclIndexDecode(toIdx, length - 1);
if (toIdx < 0) {
goto emptyRange;
} else if (toIdx >= length) {
toIdx = length - 1;
}
assert ( toIdx >= 0 && toIdx < length );
/*
* Check if we can do a sane substring.
assert ( fromIdx != TCL_INDEX_BEFORE );
assert ( fromIdx != TCL_INDEX_AFTER);
*
* Extra safety for legacy bytecodes:
*/
if (fromIdx == TCL_INDEX_BEFORE) {
fromIdx = TCL_INDEX_START;
}
if (fromIdx == TCL_INDEX_AFTER) {
goto emptyRange;
}
fromIdx = TclIndexDecode(fromIdx, length - 1);
if (fromIdx < 0) {
fromIdx = 0;
}
if (fromIdx <= toIdx) {
objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
} else {
emptyRange:
TclNewObj(objResultPtr);
}
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
@@ -5677,18 +5619,18 @@ TEBCresume(
{
Tcl_UniChar *ustring1, *ustring2, *ustring3, *end, *p;
int length3;
int length3, endIdx;
Tcl_Obj *value3Ptr;
case INST_STR_REPLACE:
value3Ptr = POP_OBJECT();
valuePtr = OBJ_AT_DEPTH(2);
length = Tcl_GetCharLength(valuePtr) - 1;
endIdx = Tcl_GetCharLength(valuePtr) - 1;
TRACE(("\"%.20s\" %s %s \"%.20s\" => ", O2S(valuePtr),
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(value3Ptr)));
if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, length,
if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, endIdx,
&fromIdx) != TCL_OK
|| TclGetIntForIndexM(interp, OBJ_AT_TOS, length,
|| TclGetIntForIndexM(interp, OBJ_AT_TOS, endIdx,
&toIdx) != TCL_OK) {
TclDecrRefCount(value3Ptr);
TRACE_ERROR(interp);
@@ -5698,21 +5640,24 @@ TEBCresume(
(void) POP_OBJECT();
TclDecrRefCount(OBJ_AT_TOS);
(void) POP_OBJECT();
if (fromIdx < 0) {
fromIdx = 0;
}
if (fromIdx > toIdx || fromIdx > length) {
if ((toIdx < 0) ||
(fromIdx > endIdx) ||
(toIdx < fromIdx)) {
TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
TclDecrRefCount(value3Ptr);
NEXT_INST_F(1, 0, 0);
}
if (toIdx > length) {
toIdx = length;
if (fromIdx < 0) {
fromIdx = 0;
}
if (fromIdx == 0 && toIdx == length) {
if (toIdx > endIdx) {
toIdx = endIdx;
}
if (fromIdx == 0 && toIdx == endIdx) {
TclDecrRefCount(OBJ_AT_TOS);
OBJ_AT_TOS = value3Ptr;
TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr)));
@@ -5995,12 +5940,7 @@ TEBCresume(
value2Ptr = OBJ_AT_TOS; /* TrimSet */
string2 = TclGetStringFromObj(value2Ptr, &length2);
string1 = TclGetStringFromObj(valuePtr, &length);
trim1 = TclTrimLeft(string1, length, string2, length2);
if (trim1 < length) {
trim2 = TclTrimRight(string1, length, string2, length2);
} else {
trim2 = 0;
}
trim1 = TclTrim(string1, length, string2, length2, &trim2);
createTrimmedString:
/*
* Careful here; trim set often contains non-ASCII characters so we
@@ -6124,6 +6064,14 @@ TEBCresume(
value2Ptr = OBJ_AT_TOS;
valuePtr = OBJ_UNDER_TOS;
/*
Try to determine, without triggering generation of a string
representation, whether one value is not a number.
*/
if (TclCheckEmptyString(valuePtr) > 0 || TclCheckEmptyString(value2Ptr) > 0) {
goto stringCompare;
}
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK
|| GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) {
/*
@@ -6938,7 +6886,7 @@ TEBCresume(
}
} else {
DECACHE_STACK_INFO();
if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
CACHE_STACK_INFO();
TRACE_APPEND((
@@ -7109,7 +7057,7 @@ TEBCresume(
}
} else {
DECACHE_STACK_INFO();
if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
CACHE_STACK_INFO();
TRACE_APPEND(("ERROR init. index temp %d: %.30s",
@@ -7332,7 +7280,8 @@ TEBCresume(
dictPtr = varPtr->value.objPtr;
} else {
DECACHE_STACK_INFO();
dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2);
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL, 0,
opnd2);
CACHE_STACK_INFO();
}
if (dictPtr == NULL) {
@@ -7406,7 +7355,7 @@ TEBCresume(
} else {
Tcl_IncrRefCount(dictPtr);
DECACHE_STACK_INFO();
objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
objResultPtr = TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
dictPtr, TCL_LEAVE_ERR_MSG, opnd2);
CACHE_STACK_INFO();
TclDecrRefCount(dictPtr);
@@ -7435,7 +7384,8 @@ TEBCresume(
dictPtr = varPtr->value.objPtr;
} else {
DECACHE_STACK_INFO();
dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL, 0,
opnd);
CACHE_STACK_INFO();
}
if (dictPtr == NULL) {
@@ -7544,7 +7494,7 @@ TEBCresume(
} else {
Tcl_IncrRefCount(dictPtr);
DECACHE_STACK_INFO();
objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
objResultPtr = TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
dictPtr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
TclDecrRefCount(dictPtr);
@@ -7638,7 +7588,7 @@ TEBCresume(
dictPtr = varPtr->value.objPtr;
} else {
DECACHE_STACK_INFO();
dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL,
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL,
TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
if (dictPtr == NULL) {
@@ -7671,7 +7621,7 @@ TEBCresume(
TclObjUnsetVar2(interp,
localName(iPtr->varFramePtr, duiPtr->varIndices[i]),
NULL, 0);
} else if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
} else if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
valuePtr, TCL_LEAVE_ERR_MSG,
duiPtr->varIndices[i]) == NULL) {
CACHE_STACK_INFO();
@@ -7698,7 +7648,8 @@ TEBCresume(
dictPtr = varPtr->value.objPtr;
} else {
DECACHE_STACK_INFO();
dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL, 0,
opnd);
CACHE_STACK_INFO();
}
if (dictPtr == NULL) {
@@ -7728,8 +7679,8 @@ TEBCresume(
valuePtr = var2Ptr->value.objPtr;
} else {
DECACHE_STACK_INFO();
valuePtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0,
duiPtr->varIndices[i]);
valuePtr = TclPtrGetVarIdx(interp, var2Ptr, NULL, NULL, NULL,
0, duiPtr->varIndices[i]);
CACHE_STACK_INFO();
}
if (valuePtr == NULL) {
@@ -7747,7 +7698,7 @@ TEBCresume(
varPtr->value.objPtr = dictPtr;
} else {
DECACHE_STACK_INFO();
objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
objResultPtr = TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
dictPtr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
if (objResultPtr == NULL) {
+30 -24
View File
@@ -240,9 +240,13 @@ TclFileMakeDirsCmd(
break;
}
for (j = 0; j < pobjc; j++) {
int errCount = 2;
target = Tcl_FSJoinPath(split, j + 1);
Tcl_IncrRefCount(target);
createDir:
/*
* Call Tcl_FSStat() so that if target is a symlink that points to
* a directory we will create subdirectories in that directory.
@@ -269,23 +273,25 @@ TclFileMakeDirsCmd(
* subdirectory.
*/
if (errno != EEXIST) {
errfile = target;
goto done;
} else if ((Tcl_FSStat(target, &statBuf) == 0)
&& S_ISDIR(statBuf.st_mode)) {
/*
* It is a directory that wasn't there before, so keep
* going without error.
*/
Tcl_ResetResult(interp);
} else {
errfile = target;
goto done;
if (errno == EEXIST) {
/* Be aware other workers could delete it immediately after
* creation, so give this worker still one chance (repeat once),
* see [270f78ca95] for description of the race-condition.
* Don't repeat the create always (to avoid endless loop). */
if (--errCount > 0) {
goto createDir;
}
/* Already tried, with delete in-between directly after
* creation, so just continue (assume created successful). */
goto nextPart;
}
/* return with error */
errfile = target;
goto done;
}
nextPart:
/*
* Forget about this sub-path.
*/
@@ -363,14 +369,7 @@ TclFileDeleteCmd(
*/
if (Tcl_FSLstat(objv[i], &statBuf) != 0) {
/*
* Trying to delete a file that does not exist is not considered
* an error, just a no-op
*/
if (errno != ENOENT) {
result = TCL_ERROR;
}
result = TCL_ERROR;
} else if (S_ISDIR(statBuf.st_mode)) {
/*
* We own a reference count on errorBuffer, if it was set as a
@@ -406,13 +405,20 @@ TclFileDeleteCmd(
}
if (result != TCL_OK) {
result = TCL_ERROR;
/*
* Avoid possible race condition (file/directory deleted after call
* of lstat), so bypass ENOENT because not an error, just a no-op
*/
if (errno == ENOENT) {
result = TCL_OK;
continue;
}
/*
* It is important that we break on error, otherwise we might end
* up owning reference counts on numerous errorBuffers.
*/
result = TCL_ERROR;
break;
}
}
+1 -1
View File
@@ -1904,7 +1904,7 @@ TclGlob(
}
/*
* To process a [glob] invokation, this function may be called multiple
* To process a [glob] invocation, this function may be called multiple
* times. Each time, the previously discovered filenames are in the
* interpreter result. We stash that away here so the result is free for
* error messsages.
+131 -65
View File
@@ -9,7 +9,6 @@
*
* Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 2015 Sergey G. Brester aka sebres.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -51,11 +50,73 @@
* parsed fields will be returned.
*/
#include "tclDate.h"
typedef struct DateInfo {
Tcl_Obj* messages; /* Error messages */
const char* separatrix; /* String separating messages */
time_t dateYear;
time_t dateMonth;
time_t dateDay;
int dateHaveDate;
time_t dateHour;
time_t dateMinutes;
time_t dateSeconds;
int dateMeridian;
int dateHaveTime;
time_t dateTimezone;
int dateDSTmode;
int dateHaveZone;
time_t dateRelMonth;
time_t dateRelDay;
time_t dateRelSeconds;
int dateHaveRel;
time_t dateMonthOrdinal;
int dateHaveOrdinalMonth;
time_t dateDayOrdinal;
time_t dateDayNumber;
int dateHaveDay;
const char *dateStart;
const char *dateInput;
time_t *dateRelPointer;
int dateDigitCount;
} DateInfo;
#define YYMALLOC ckalloc
#define YYFREE(x) (ckfree((void*) (x)))
#define yyDSTmode (info->dateDSTmode)
#define yyDayOrdinal (info->dateDayOrdinal)
#define yyDayNumber (info->dateDayNumber)
#define yyMonthOrdinal (info->dateMonthOrdinal)
#define yyHaveDate (info->dateHaveDate)
#define yyHaveDay (info->dateHaveDay)
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
#define yyHaveRel (info->dateHaveRel)
#define yyHaveTime (info->dateHaveTime)
#define yyHaveZone (info->dateHaveZone)
#define yyTimezone (info->dateTimezone)
#define yyDay (info->dateDay)
#define yyMonth (info->dateMonth)
#define yyYear (info->dateYear)
#define yyHour (info->dateHour)
#define yyMinutes (info->dateMinutes)
#define yySeconds (info->dateSeconds)
#define yyMeridian (info->dateMeridian)
#define yyRelMonth (info->dateRelMonth)
#define yyRelDay (info->dateRelDay)
#define yyRelSeconds (info->dateRelSeconds)
#define yyRelPointer (info->dateRelPointer)
#define yyInput (info->dateInput)
#define yyDigitCount (info->dateDigitCount)
#define EPOCH 1970
#define START_OF_TIME 1902
#define END_OF_TIME 2037
@@ -89,6 +150,14 @@ typedef enum _DSTMODE {
DSTon, DSToff, DSTmaybe
} DSTMODE;
/*
* Meridian: am, pm, or 24-hour style.
*/
typedef enum _MERIDIAN {
MERam, MERpm, MER24
} MERIDIAN;
%}
%union {
@@ -107,6 +176,8 @@ static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
DateInfo* info, const char *s);
static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
DateInfo* info);
static time_t ToSeconds(time_t Hours, time_t Minutes,
time_t Seconds, MERIDIAN Meridian);
MODULE_SCOPE int yyparse(DateInfo*);
%}
@@ -306,12 +377,12 @@ date : tUNUMBER '/' tUNUMBER {
;
ordMonth: tNEXT tMONTH {
yyMonthOrdinalIncr = 1;
yyMonthOrdinal = $2;
yyMonthOrdinal = 1;
yyMonth = $2;
}
| tNEXT tUNUMBER tMONTH {
yyMonthOrdinalIncr = $2;
yyMonthOrdinal = $3;
yyMonthOrdinal = $2;
yyMonth = $3;
}
;
@@ -659,11 +730,11 @@ TclDateerror(
infoPtr->separatrix = "\n";
}
MODULE_SCOPE int
static time_t
ToSeconds(
int Hours,
int Minutes,
int Seconds,
time_t Hours,
time_t Minutes,
time_t Seconds,
MERIDIAN Meridian)
{
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
@@ -886,36 +957,65 @@ TclDatelex(
} while (Count > 0);
}
}
int
TclClockFreeScan(
TclClockOldscanObjCmd(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* Tcl interpreter */
DateInfo *info) /* Input and result parameters */
int objc, /* Count of paraneters */
Tcl_Obj *const *objv) /* Parameters */
{
Tcl_Obj *result, *resultElement;
int yr, mo, da;
DateInfo dateInfo;
DateInfo* info = &dateInfo;
int status;
/*
* yyInput = stringToParse;
*
* ClockInitDateInfo(info) should be executed to pre-init info;
*/
if (objc != 5) {
Tcl_WrongNumArgs(interp, 1, objv,
"stringToParse baseYear baseMonth baseDay" );
return TCL_ERROR;
}
yyDSTmode = DSTmaybe;
yyInput = Tcl_GetString( objv[1] );
dateInfo.dateStart = yyInput;
info->messages = Tcl_NewObj();
info->separatrix = "";
Tcl_IncrRefCount(info->messages);
yyHaveDate = 0;
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
return TCL_ERROR;
}
yyYear = yr; yyMonth = mo; yyDay = da;
info->dateStart = yyInput;
status = yyparse(info);
yyHaveTime = 0;
yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
yyHaveZone = 0;
yyTimezone = 0; yyDSTmode = DSTmaybe;
yyHaveOrdinalMonth = 0;
yyMonthOrdinal = 0;
yyHaveDay = 0;
yyDayOrdinal = 0; yyDayNumber = 0;
yyHaveRel = 0;
yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
dateInfo.messages = Tcl_NewObj();
dateInfo.separatrix = "";
Tcl_IncrRefCount(dateInfo.messages);
status = yyparse(&dateInfo);
if (status == 1) {
Tcl_SetObjResult(interp, info->messages);
Tcl_DecrRefCount(info->messages);
Tcl_SetObjResult(interp, dateInfo.messages);
Tcl_DecrRefCount(dateInfo.messages);
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
return TCL_ERROR;
} else if (status == 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
Tcl_DecrRefCount(info->messages);
Tcl_DecrRefCount(dateInfo.messages);
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
return TCL_ERROR;
} else if (status != 0) {
@@ -923,11 +1023,11 @@ TclClockFreeScan(
"from date parser. Please "
"report this error as a "
"bug in Tcl.", -1));
Tcl_DecrRefCount(info->messages);
Tcl_DecrRefCount(dateInfo.messages);
Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
return TCL_ERROR;
}
Tcl_DecrRefCount(info->messages);
Tcl_DecrRefCount(dateInfo.messages);
if (yyHaveDate > 1) {
Tcl_SetObjResult(interp,
@@ -960,40 +1060,6 @@ TclClockFreeScan(
return TCL_ERROR;
}
return TCL_OK;
}
int
TclClockOldscanObjCmd(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* Tcl interpreter */
int objc, /* Count of paraneters */
Tcl_Obj *const *objv) /* Parameters */
{
Tcl_Obj *result, *resultElement;
int yr, mo, da;
DateInfo dateInfo;
DateInfo* info = &dateInfo;
if (objc != 5) {
Tcl_WrongNumArgs(interp, 1, objv,
"stringToParse baseYear baseMonth baseDay" );
return TCL_ERROR;
}
yyInput = Tcl_GetString( objv[1] );
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
return TCL_ERROR;
}
yyYear = yr; yyMonth = mo; yyDay = da;
if (TclClockFreeScan(interp, info) != TCL_OK) {
return TCL_ERROR;
}
result = Tcl_NewObj();
resultElement = Tcl_NewObj();
if (yyHaveDate) {
@@ -1044,10 +1110,10 @@ TclClockOldscanObjCmd(
resultElement = Tcl_NewObj();
if (yyHaveOrdinalMonth) {
Tcl_ListObjAppendElement(interp, resultElement,
Tcl_NewIntObj((int) yyMonthOrdinalIncr));
Tcl_ListObjAppendElement(interp, resultElement,
Tcl_NewIntObj((int) yyMonthOrdinal));
Tcl_ListObjAppendElement(interp, resultElement,
Tcl_NewIntObj((int) yyMonth));
}
Tcl_ListObjAppendElement(interp, result, resultElement);
+8 -5
View File
@@ -1014,12 +1014,18 @@ static void
RebuildTable(
register Tcl_HashTable *tablePtr) /* Table to enlarge. */
{
int oldSize, count, index;
Tcl_HashEntry **oldBuckets;
int count, index, oldSize = tablePtr->numBuckets;
Tcl_HashEntry **oldBuckets = tablePtr->buckets;
register Tcl_HashEntry **oldChainPtr, **newChainPtr;
register Tcl_HashEntry *hPtr;
const Tcl_HashKeyType *typePtr;
/* Avoid outgrowing capability of the memory allocators */
if (oldSize > (int)(UINT_MAX / (4 * sizeof(Tcl_HashEntry *)))) {
tablePtr->rebuildSize = INT_MAX;
return;
}
if (tablePtr->keyType == TCL_STRING_KEYS) {
typePtr = &tclStringHashKeyType;
} else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
@@ -1031,9 +1037,6 @@ RebuildTable(
typePtr = &tclArrayHashKeyType;
}
oldSize = tablePtr->numBuckets;
oldBuckets = tablePtr->buckets;
/*
* Allocate and initialize the new bucket array, and set up hashing
* constants for new array size.
+14 -10
View File
@@ -711,17 +711,18 @@ Tcl_SetStdChannel(
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
int init = channel ? 1 : -1;
switch (type) {
case TCL_STDIN:
tsdPtr->stdinInitialized = 1;
tsdPtr->stdinInitialized = init;
tsdPtr->stdinChannel = channel;
break;
case TCL_STDOUT:
tsdPtr->stdoutInitialized = 1;
tsdPtr->stdoutInitialized = init;
tsdPtr->stdoutChannel = channel;
break;
case TCL_STDERR:
tsdPtr->stderrInitialized = 1;
tsdPtr->stderrInitialized = init;
tsdPtr->stderrChannel = channel;
break;
}
@@ -758,8 +759,8 @@ Tcl_GetStdChannel(
switch (type) {
case TCL_STDIN:
if (!tsdPtr->stdinInitialized) {
tsdPtr->stdinInitialized = -1;
tsdPtr->stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN);
tsdPtr->stdinInitialized = 1;
/*
* Artificially bump the refcount to ensure that the channel is
@@ -771,6 +772,7 @@ Tcl_GetStdChannel(
*/
if (tsdPtr->stdinChannel != NULL) {
tsdPtr->stdinInitialized = 1;
Tcl_RegisterChannel(NULL, tsdPtr->stdinChannel);
}
}
@@ -778,9 +780,10 @@ Tcl_GetStdChannel(
break;
case TCL_STDOUT:
if (!tsdPtr->stdoutInitialized) {
tsdPtr->stdoutInitialized = -1;
tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT);
tsdPtr->stdoutInitialized = 1;
if (tsdPtr->stdoutChannel != NULL) {
tsdPtr->stdoutInitialized = 1;
Tcl_RegisterChannel(NULL, tsdPtr->stdoutChannel);
}
}
@@ -788,9 +791,10 @@ Tcl_GetStdChannel(
break;
case TCL_STDERR:
if (!tsdPtr->stderrInitialized) {
tsdPtr->stderrInitialized = -1;
tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
tsdPtr->stderrInitialized = 1;
if (tsdPtr->stderrChannel != NULL) {
tsdPtr->stderrInitialized = 1;
Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
}
}
@@ -1058,7 +1062,7 @@ CheckForStdChannelsBeingClosed(
ChannelState *statePtr = ((Channel *) chan)->state;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->stdinInitialized
if (tsdPtr->stdinInitialized == 1
&& tsdPtr->stdinChannel != NULL
&& statePtr == ((Channel *)tsdPtr->stdinChannel)->state) {
if (statePtr->refCount < 2) {
@@ -1066,7 +1070,7 @@ CheckForStdChannelsBeingClosed(
tsdPtr->stdinChannel = NULL;
return;
}
} else if (tsdPtr->stdoutInitialized
} else if (tsdPtr->stdoutInitialized == 1
&& tsdPtr->stdoutChannel != NULL
&& statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) {
if (statePtr->refCount < 2) {
@@ -1074,7 +1078,7 @@ CheckForStdChannelsBeingClosed(
tsdPtr->stdoutChannel = NULL;
return;
}
} else if (tsdPtr->stderrInitialized
} else if (tsdPtr->stderrInitialized == 1
&& tsdPtr->stderrChannel != NULL
&& statePtr == ((Channel *)tsdPtr->stderrChannel)->state) {
if (statePtr->refCount < 2) {
@@ -6660,7 +6664,7 @@ Tcl_Flush(
chanPtr = statePtr->topChanPtr;
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
return -1;
return TCL_ERROR;
}
result = FlushChannel(NULL, chanPtr, 0);
+4
View File
@@ -41,6 +41,8 @@ static void ReflectWatch(ClientData clientData, int mask);
static int ReflectBlock(ClientData clientData, int mode);
#ifdef TCL_THREADS
static void ReflectThread(ClientData clientData, int action);
static int ReflectEventRun(Tcl_Event *ev, int flags);
static int ReflectEventDelete(Tcl_Event *ev, ClientData cd);
#endif
static Tcl_WideInt ReflectSeekWide(ClientData clientData,
Tcl_WideInt offset, int mode, int *errorCodePtr);
@@ -748,6 +750,7 @@ TclChanCreateObjCmd(
*----------------------------------------------------------------------
*/
#ifdef TCL_THREADS
typedef struct ReflectEvent {
Tcl_Event header;
ReflectedChannel *rcPtr;
@@ -791,6 +794,7 @@ ReflectEventDelete(
}
return 1;
}
#endif
int
TclChanPostEventObjCmd(
+6 -28
View File
@@ -139,7 +139,6 @@ Tcl_FSRenameFileProc TclpObjRenameFile;
Tcl_FSCreateDirectoryProc TclpObjCreateDirectory;
Tcl_FSCopyDirectoryProc TclpObjCopyDirectory;
Tcl_FSRemoveDirectoryProc TclpObjRemoveDirectory;
Tcl_FSUnloadFileProc TclpUnloadFile;
Tcl_FSLinkProc TclpObjLink;
Tcl_FSListVolumesProc TclpObjListVolumes;
@@ -412,7 +411,6 @@ Tcl_GetCwd(
return Tcl_DStringValue(cwdPtr);
}
/* Obsolete */
int
Tcl_EvalFile(
Tcl_Interp *interp, /* Interpreter in which to process file. */
@@ -1762,7 +1760,7 @@ Tcl_FSEvalFileEx(
* this cross-platform to allow for scripted documents. [Bug: 2040]
*/
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32");
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
/*
* If the encoding is specified, set it for the channel. Else don't touch
@@ -1896,7 +1894,7 @@ TclNREvalFile(
* this cross-platform to allow for scripted documents. [Bug: 2040]
*/
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32");
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
/*
* If the encoding is specified, set it for the channel. Else don't touch
@@ -3160,8 +3158,8 @@ Tcl_FSLoadFile(
* present and set to true (any integer > 0) then the unlink is skipped.
*/
int
TclSkipUnlink (Tcl_Obj* shlibFile)
static int
skipUnlink (Tcl_Obj* shlibFile)
{
/* Order of testing:
* 1. On hpux we generally want to skip unlink in general
@@ -3415,7 +3413,7 @@ Tcl_LoadFile(
*/
if (
!TclSkipUnlink (copyToPtr) &&
!skipUnlink (copyToPtr) &&
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
Tcl_DecrRefCount(copyToPtr);
@@ -3684,30 +3682,10 @@ Tcl_FSUnloadFile(
}
return TCL_ERROR;
}
TclpUnloadFile(handle);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclpUnloadFile --
*
* Unloads a library given its handle
*
* This function was once filesystem-specific, but has been made portable by
* having TclpDlopen return a structure that includes procedure pointers.
*
*----------------------------------------------------------------------
*/
void
TclpUnloadFile(
Tcl_LoadHandle handle)
{
if (handle->unloadFileProcPtr != NULL) {
handle->unloadFileProcPtr(handle);
}
return TCL_OK;
}
/*
+2 -1
View File
@@ -878,7 +878,8 @@ Tcl_WrongNumArgs(
* NULL. */
{
Tcl_Obj *objPtr;
int i, len, elemLen, flags;
int i, len, elemLen;
char flags;
Interp *iPtr = (Interp *) interp;
const char *elementStr;
+28 -2
View File
@@ -1011,6 +1011,32 @@ declare 251 {
int TclRegisterLiteral(void *envPtr,
char *bytes, int length, int flags)
}
# Exporting of the internal API to variables.
declare 252 {
Tcl_Obj *TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr,
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
const int flags)
}
declare 253 {
Tcl_Obj *TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr,
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
Tcl_Obj *newValuePtr, const int flags)
}
declare 254 {
Tcl_Obj *TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr,
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
Tcl_Obj *incrPtr, const int flags)
}
declare 255 {
int TclPtrObjMakeUpvar(Tcl_Interp *interp, Tcl_Var otherPtr,
Tcl_Obj *myNamePtr, int myFlags)
}
declare 256 {
int TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr,
Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags)
}
##############################################################################
@@ -1062,7 +1088,7 @@ declare 9 win {
}
# new for 8.4.20+/8.5.12+ Cygwin only
declare 10 win {
Tcl_DirEntry *TclpReaddir(DIR *dir)
Tcl_DirEntry *TclpReaddir(TclDIR *dir)
}
# Removed in 8.3.1 (for Win32s only)
#declare 10 win {
@@ -1200,7 +1226,7 @@ declare 9 unix {
# Added in 8.4:
declare 10 unix {
Tcl_DirEntry *TclpReaddir(DIR *dir)
Tcl_DirEntry *TclpReaddir(TclDIR *dir)
}
# Slots 11 and 12 are forwarders for functions that were promoted to
# generic Stubs
+91 -42
View File
@@ -413,7 +413,7 @@ struct NamespacePathEntry {
*/
typedef struct EnsembleConfig {
Namespace *nsPtr; /* The namspace backing this ensemble up. */
Namespace *nsPtr; /* The namespace backing this ensemble up. */
Tcl_Command token; /* The token for the command that provides
* ensemble support for the namespace, or NULL
* if the command has been deleted (or never
@@ -1813,7 +1813,7 @@ typedef struct Interp {
* unused space in interp was repurposed for
* pluggable bytecode optimizers. The core
* contains one optimizer, which can be
* selectively overriden by extensions. */
* selectively overridden by extensions. */
} extra;
/*
@@ -2228,7 +2228,7 @@ typedef struct Interp {
* use the rand() or srand() functions.
* SAFE_INTERP: Non zero means that the current interp is a safe
* interp (i.e. it has only the safe commands installed,
* less priviledge than a regular interp).
* less privilege than a regular interp).
* INTERP_DEBUG_FRAME: Used for switching on various extra interpreter
* debug/info mechanisms (e.g. info frame eval/uplevel
* tracing) which are performance intensive.
@@ -2369,7 +2369,7 @@ typedef struct List {
* be ignored if there is no string rep at
* all.*/
Tcl_Obj *elements; /* First list element; the struct is grown to
* accomodate all elements. */
* accommodate all elements. */
} List;
#define LIST_MAX \
@@ -2422,8 +2422,8 @@ typedef struct List {
#define TCL_EACH_COLLECT 1 /* Collect iteration result like [lmap] */
/*
* Macros providing a faster path to integers: Tcl_GetLongFromObj everywhere,
* Tcl_GetIntFromObj and TclGetIntForIndex on platforms where longs are ints.
* Macros providing a faster path to integers: Tcl_GetLongFromObj,
* Tcl_GetIntFromObj and TclGetIntForIndex.
*
* WARNING: these macros eval their args more than once.
*/
@@ -2444,9 +2444,17 @@ typedef struct List {
: TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))
#else
#define TclGetIntFromObj(interp, objPtr, intPtr) \
Tcl_GetIntFromObj((interp), (objPtr), (intPtr))
#define TclGetIntForIndexM(interp, objPtr, ignore, idxPtr) \
TclGetIntForIndex(interp, objPtr, ignore, idxPtr)
(((objPtr)->typePtr == &tclIntType \
&& (objPtr)->internalRep.longValue >= -(Tcl_WideInt)(UINT_MAX) \
&& (objPtr)->internalRep.longValue <= (Tcl_WideInt)(UINT_MAX)) \
? ((*(intPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
: Tcl_GetIntFromObj((interp), (objPtr), (intPtr)))
#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
(((objPtr)->typePtr == &tclIntType \
&& (objPtr)->internalRep.longValue >= INT_MIN \
&& (objPtr)->internalRep.longValue <= INT_MAX) \
? ((*(idxPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
: TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))
#endif
/*
@@ -2483,13 +2491,13 @@ typedef struct List {
* tip of the path, so duplication of shared objects should be done along the
* way.
*
* DICT_PATH_EXISTS indicates that we are performing an existance test and a
* DICT_PATH_EXISTS indicates that we are performing an existence test and a
* lookup failure should therefore not be an error. If (and only if) this flag
* is set, TclTraceDictPath() will return the special value
* DICT_PATH_NON_EXISTENT if the path is not traceable.
*
* DICT_PATH_CREATE (which also requires the DICT_PATH_UPDATE bit to be set)
* indicates that we are to create non-existant dictionaries on the path.
* indicates that we are to create non-existent dictionaries on the path.
*/
#define DICT_PATH_READ 0
@@ -2727,6 +2735,10 @@ MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
MODULE_SCOPE char * tclEmptyStringRep;
MODULE_SCOPE char tclEmptyString;
enum CheckEmptyStringResult {
TCL_EMPTYSTRING_UNKNOWN = -1, TCL_EMPTYSTRING_NO, TCL_EMPTYSTRING_YES
};
/*
*----------------------------------------------------------------
* Procedures shared among Tcl modules but not used by the outside world,
@@ -2742,6 +2754,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRForObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRForeachCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRIfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRLmapCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRPackageObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRSourceObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRSubstObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRSwitchObjCmd;
@@ -2855,8 +2868,6 @@ MODULE_SCOPE void TclArgumentBCRelease(Tcl_Interp *interp,
CmdFrame *cfPtr);
MODULE_SCOPE void TclArgumentGet(Tcl_Interp *interp, Tcl_Obj *obj,
CmdFrame **cfPtrPtr, int *wordPtr);
MODULE_SCOPE int TclArraySet(Tcl_Interp *interp,
Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj);
MODULE_SCOPE double TclBignumToDouble(const mp_int *bignum);
MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string,
int strLen, const unsigned char *pattern,
@@ -2864,8 +2875,11 @@ MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string,
MODULE_SCOPE double TclCeil(const mp_int *a);
MODULE_SCOPE void TclChannelPreserve(Tcl_Channel chan);
MODULE_SCOPE void TclChannelRelease(Tcl_Channel chan);
MODULE_SCOPE int TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr,
Var *arrayPtr, Tcl_Obj *name, int index);
MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp,
const char *value);
MODULE_SCOPE int TclCheckEmptyString(Tcl_Obj *objPtr);
MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp,
Tcl_Channel chan);
MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd;
@@ -2879,12 +2893,24 @@ MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr,
Tcl_Obj *originObjPtr);
MODULE_SCOPE int TclConvertElement(const char *src, int length,
char *dst, int flags);
MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs (
Tcl_Interp *interp,
const char *cmdName,
Tcl_Namespace *nsPtr,
Tcl_ObjCmdProc *proc,
ClientData clientData,
Tcl_CmdDeleteProc *deleteProc);
MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(
Tcl_Interp *interp,
const char *name,
Tcl_Namespace *nameNamespacePtr,
Tcl_Namespace *ensembleNamespacePtr,
int flags);
MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr);
MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp,
const char *dict, int dictLength,
const char **elementPtr, const char **nextPtr,
int *sizePtr, int *literalPtr);
MODULE_SCOPE Tcl_Obj * Tcl_DictObjSmartRef(Tcl_Interp *interp, Tcl_Obj *);
/* TIP #280 - Modified token based evulation, with line information. */
MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script,
int numBytes, int flags, int line,
@@ -2908,6 +2934,10 @@ MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr,
MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr);
MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp,
Tcl_Obj *const *objv, int objc, int *objcPtr);
MODULE_SCOPE Tcl_Namespace * TclEnsureNamespace(
Tcl_Interp *interp,
Tcl_Namespace *namespacePtr);
MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
MODULE_SCOPE void TclFinalizeAsync(void);
MODULE_SCOPE void TclFinalizeDoubleConversion(void);
@@ -2933,6 +2963,15 @@ MODULE_SCOPE double TclFloor(const mp_int *a);
MODULE_SCOPE void TclFormatNaN(double value, char *buffer);
MODULE_SCOPE int TclFSFileAttrIndex(Tcl_Obj *pathPtr,
const char *attributeName, int *indexPtr);
MODULE_SCOPE Tcl_Command TclNRCreateCommandInNs (
Tcl_Interp *interp,
const char *cmdName,
Tcl_Namespace *nsPtr,
Tcl_ObjCmdProc *proc,
Tcl_ObjCmdProc *nreProc,
ClientData clientData,
Tcl_CmdDeleteProc *deleteProc);
MODULE_SCOPE int TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
const char *encodingName);
MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle);
@@ -3099,7 +3138,7 @@ MODULE_SCOPE int TclReToGlob(Tcl_Interp *interp, const char *reStr,
int reStrLen, Tcl_DString *dsPtr, int *flagsPtr,
int *quantifiersFoundPtr);
MODULE_SCOPE int TclScanElement(const char *string, int length,
int *flagPtr);
char *flagPtr);
MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp,
Tcl_Obj *cmdPrefix);
MODULE_SCOPE void TclSetBignumIntRep(Tcl_Obj *objPtr,
@@ -3116,6 +3155,12 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp,
Tcl_Obj *bad, Tcl_Obj *fix);
MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
int numBytes);
typedef int (*memCmpFn_t)(const void*, const void*, size_t);
MODULE_SCOPE int TclStringCmp (Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr,
int checkEq, int nocase, int reqlength);
MODULE_SCOPE int TclStringCmpOpts (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[],
int *nocase, int *reqlength);
MODULE_SCOPE int TclStringMatch(const char *str, int strLen,
const char *pattern, int ptnLen, int flags);
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
@@ -3132,6 +3177,8 @@ MODULE_SCOPE void TclSubstParse(Tcl_Interp *interp, const char *bytes,
MODULE_SCOPE int TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
int count, int *tokensLeftPtr, int line,
int *clNextOuter, const char *outerScript);
MODULE_SCOPE int TclTrim(const char *bytes, int numBytes,
const char *trim, int numTrim, int *trimRight);
MODULE_SCOPE int TclTrimLeft(const char *bytes, int numBytes,
const char *trim, int numTrim);
MODULE_SCOPE int TclTrimRight(const char *bytes, int numBytes,
@@ -3152,22 +3199,10 @@ MODULE_SCOPE int TclpLoadMemory(Tcl_Interp *interp, void *buffer,
MODULE_SCOPE void TclInitThreadStorage(void);
MODULE_SCOPE void TclFinalizeThreadDataThread(void);
MODULE_SCOPE void TclFinalizeThreadStorage(void);
#ifdef TCL_WIDE_CLICKS
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double TclpWideClicksToNanoseconds(Tcl_WideInt clicks);
MODULE_SCOPE double TclpWideClickInMicrosec(void);
#else
# ifdef _WIN32
# define TCL_WIDE_CLICKS 1
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double TclpWideClickInMicrosec(void);
# define TclpWideClicksToNanoseconds(clicks) \
((double)(clicks) * TclpWideClickInMicrosec() * 1000)
# endif
#endif
MODULE_SCOPE Tcl_WideInt TclpGetMicroseconds(void);
MODULE_SCOPE int TclZlibInit(Tcl_Interp *interp);
MODULE_SCOPE void * TclpThreadCreateKey(void);
MODULE_SCOPE void TclpThreadDeleteKey(void *keyPtr);
@@ -3948,20 +3983,21 @@ MODULE_SCOPE Var * TclLookupArrayElement(Tcl_Interp *interp,
const int flags, const char *msg,
const int createPart1, const int createPart2,
Var *arrayPtr, int index);
MODULE_SCOPE Tcl_Obj * TclPtrGetVar(Tcl_Interp *interp,
MODULE_SCOPE Tcl_Obj * TclPtrGetVarIdx(Tcl_Interp *interp,
Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, const int flags, int index);
MODULE_SCOPE Tcl_Obj * TclPtrSetVar(Tcl_Interp *interp,
MODULE_SCOPE Tcl_Obj * TclPtrSetVarIdx(Tcl_Interp *interp,
Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
const int flags, int index);
MODULE_SCOPE Tcl_Obj * TclPtrIncrObjVar(Tcl_Interp *interp,
MODULE_SCOPE Tcl_Obj * TclPtrIncrObjVarIdx(Tcl_Interp *interp,
Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr,
const int flags, int index);
MODULE_SCOPE int TclPtrObjMakeUpvar(Tcl_Interp *interp, Var *otherPtr,
Tcl_Obj *myNamePtr, int myFlags, int index);
MODULE_SCOPE int TclPtrUnsetVar(Tcl_Interp *interp, Var *varPtr,
MODULE_SCOPE int TclPtrObjMakeUpvarIdx(Tcl_Interp *interp,
Var *otherPtr, Tcl_Obj *myNamePtr, int myFlags,
int index);
MODULE_SCOPE int TclPtrUnsetVarIdx(Tcl_Interp *interp, Var *varPtr,
Var *arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, const int flags,
int index);
@@ -3987,6 +4023,21 @@ MODULE_SCOPE unsigned TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
MODULE_SCOPE int TclFullFinalizationRequested(void);
/*
* Utility routines for encoding index values as integers. Used by both
* some of the command compilers and by [lsort] and [lsearch].
*/
MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr,
int before, int after, int *indexPtr);
MODULE_SCOPE int TclIndexDecode(int encoded, int endValue);
/* Constants used in index value encoding routines. */
#define TCL_INDEX_END (-2)
#define TCL_INDEX_BEFORE (-1)
#define TCL_INDEX_START (0)
#define TCL_INDEX_AFTER (INT_MAX)
/*
*----------------------------------------------------------------
* Macros used by the Tcl core to create and release Tcl objects.
@@ -4371,7 +4422,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
#define TclUtfToUniChar(str, chPtr) \
((((unsigned char) *(str)) < 0xC0) ? \
((*(chPtr) = (Tcl_UniChar) *(str)), 1) \
((*(chPtr) = (unsigned char) *(str)), 1) \
: Tcl_UtfToUniChar(str, chPtr))
/*
@@ -4415,6 +4466,11 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
#define TclIsPureByteArray(objPtr) \
(((objPtr)->typePtr==&tclByteArrayType) && ((objPtr)->bytes==NULL))
#define TclIsPureDict(objPtr) \
(((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclDictType))
#define TclIsPureList(objPtr) \
(((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclListType))
/*
*----------------------------------------------------------------
@@ -4436,7 +4492,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
/*
*----------------------------------------------------------------
* Macro used by the Tcl core to increment a namespace's export export epoch
* Macro used by the Tcl core to increment a namespace's export epoch
* counter. The ANSI C "prototype" for this macro is:
*
* MODULE_SCOPE void TclInvalidateNsCmdLookup(Namespace *nsPtr);
@@ -4871,13 +4927,6 @@ typedef struct NRE_callback {
#define Tcl_Free(ptr) TclpFree(ptr)
#endif
/*
* Other externals.
*/
MODULE_SCOPE size_t TclEnvEpoch; /* Epoch of the tcl environment
* (if changed with tcl-env). */
#endif /* _TCLINT */
/*
+37
View File
@@ -617,6 +617,28 @@ EXTERN void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags,
/* 251 */
EXTERN int TclRegisterLiteral(void *envPtr, char *bytes,
int length, int flags);
/* 252 */
EXTERN Tcl_Obj * TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr,
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, const int flags);
/* 253 */
EXTERN Tcl_Obj * TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr,
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
const int flags);
/* 254 */
EXTERN Tcl_Obj * TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr,
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr,
const int flags);
/* 255 */
EXTERN int TclPtrObjMakeUpvar(Tcl_Interp *interp,
Tcl_Var otherPtr, Tcl_Obj *myNamePtr,
int myFlags);
/* 256 */
EXTERN int TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr,
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, const int flags);
typedef struct TclIntStubs {
int magic;
@@ -874,6 +896,11 @@ typedef struct TclIntStubs {
char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */
void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */
int (*tclRegisterLiteral) (void *envPtr, char *bytes, int length, int flags); /* 251 */
Tcl_Obj * (*tclPtrGetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 252 */
Tcl_Obj * (*tclPtrSetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, const int flags); /* 253 */
Tcl_Obj * (*tclPtrIncrObjVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, const int flags); /* 254 */
int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */
int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 256 */
} TclIntStubs;
extern const TclIntStubs *tclIntStubsPtr;
@@ -1305,6 +1332,16 @@ extern const TclIntStubs *tclIntStubsPtr;
(tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */
#define TclRegisterLiteral \
(tclIntStubsPtr->tclRegisterLiteral) /* 251 */
#define TclPtrGetVar \
(tclIntStubsPtr->tclPtrGetVar) /* 252 */
#define TclPtrSetVar \
(tclIntStubsPtr->tclPtrSetVar) /* 253 */
#define TclPtrIncrObjVar \
(tclIntStubsPtr->tclPtrIncrObjVar) /* 254 */
#define TclPtrObjMakeUpvar \
(tclIntStubsPtr->tclPtrObjMakeUpvar) /* 255 */
#define TclPtrUnsetVar \
(tclIntStubsPtr->tclPtrUnsetVar) /* 256 */
#endif /* defined(USE_TCL_STUBS) */
+6 -11
View File
@@ -13,11 +13,6 @@
#ifndef _TCLINTPLATDECLS
#define _TCLINTPLATDECLS
#ifdef _WIN32
# define Tcl_DirEntry void
# define DIR void
#endif
#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
# define TCL_STORAGE_CLASS DLLEXPORT
@@ -72,7 +67,7 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout);
/* 9 */
EXTERN TclFile TclpCreateTempFile(const char *contents);
/* 10 */
EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir);
/* 11 */
EXTERN struct tm * TclpLocaltime_unix(const time_t *clock);
/* 12 */
@@ -129,7 +124,7 @@ EXTERN int TclpGetPid(Tcl_Pid pid);
/* 9 */
EXTERN int TclWinGetPlatformId(void);
/* 10 */
EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir);
/* 11 */
EXTERN void TclGetAndDetachPids(Tcl_Interp *interp,
Tcl_Channel chan);
@@ -206,7 +201,7 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout);
/* 9 */
EXTERN TclFile TclpCreateTempFile(const char *contents);
/* 10 */
EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir);
/* 11 */
EXTERN struct tm * TclpLocaltime_unix(const time_t *clock);
/* 12 */
@@ -269,7 +264,7 @@ typedef struct TclIntPlatStubs {
TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */
int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */
Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */
struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */
char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */
@@ -302,7 +297,7 @@ typedef struct TclIntPlatStubs {
int (*tclWinSetSockOpt) (SOCKET s, int level, int optname, const char *optval, int optlen); /* 7 */
int (*tclpGetPid) (Tcl_Pid pid); /* 8 */
int (*tclWinGetPlatformId) (void); /* 9 */
Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */
int (*tclpCloseFile) (TclFile file); /* 12 */
Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */
@@ -335,7 +330,7 @@ typedef struct TclIntPlatStubs {
TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */
int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */
Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */
struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */
char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */
+1 -1
View File
@@ -638,7 +638,7 @@ static Tcl_ObjType invalidRealType = {
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
NULL, /* updateStringProc */
SetInvalidRealFromAny /* setFromAnyProc */
NULL /* setFromAnyProc */
};
static int
+285 -310
View File
@@ -55,20 +55,22 @@ const Tcl_ObjType tclListType = {
*
* NewListIntRep --
*
* Creates a list internal rep with space for objc elements. objc
* must be > 0. If objv!=NULL, initializes with the first objc values
* in that array. If objv==NULL, initalize list internal rep to have
* 0 elements, with space to add objc more. Flag value "p" indicates
* Creates a 'List' structure with space for 'objc' elements. 'objc' must
* be > 0. If 'objv' is not NULL, The list is initialized with first
* 'objc' values in that array. Otherwise the list is initialized to have
* 0 elements, with space to add 'objc' more. Flag value 'p' indicates
* how to behave on failure.
*
* Results:
* A new List struct with refCount 0 is returned. If some failure
* prevents this then if p=0, NULL is returned and otherwise the
* routine panics.
* Value
*
* Side effects:
* The ref counts of the elements in objv are incremented since the
* resulting list now refers to them.
* A new 'List' structure with refCount 0. If some failure
* prevents this NULL is returned if 'p' is 0 , and 'Tcl_Panic'
* is called if it is not.
*
* Effect
*
* The refCount of each value in 'objv' is incremented as it is added
* to the list.
*
*----------------------------------------------------------------------
*/
@@ -132,22 +134,10 @@ NewListIntRep(
/*
*----------------------------------------------------------------------
*
* AttemptNewList --
*
* Creates a list internal rep with space for objc elements. objc
* must be > 0. If objv!=NULL, initializes with the first objc values
* in that array. If objv==NULL, initalize list internal rep to have
* 0 elements, with space to add objc more.
*
* Results:
* A new List struct with refCount 0 is returned. If some failure
* prevents this then NULL is returned, and an error message is left
* in the interp result, unless interp is NULL.
*
* Side effects:
* The ref counts of the elements in objv are incremented since the
* resulting list now refers to them.
* AttemptNewList --
*
* Like NewListIntRep, but additionally sets an error message on failure.
*
*----------------------------------------------------------------------
*/
@@ -179,23 +169,20 @@ AttemptNewList(
*
* Tcl_NewListObj --
*
* This function is normally called when not debugging: i.e., when
* TCL_MEM_DEBUG is not defined. It creates a new list object from an
* (objc,objv) array: that is, each of the objc elements of the array
* referenced by objv is inserted as an element into a new Tcl object.
* Creates a new list object and adds values to it. When TCL_MEM_DEBUG is
* defined, 'Tcl_DbNewListObj' is called instead.
*
* When TCL_MEM_DEBUG is defined, this function just returns the result
* of calling the debugging version Tcl_DbNewListObj.
* Value
*
* Results:
* A new list object is returned that is initialized from the object
* pointers in objv. If objc is less than or equal to zero, an empty
* object is returned. The new object's string representation is left
* NULL. The resulting new list object has ref count 0.
* A new list 'Tcl_Obj' to which is appended values from 'objv', or if
* 'objc' is less than or equal to zero, a list 'Tcl_Obj' having no
* elements. The string representation of the new 'Tcl_Obj' is set to
* NULL. The refCount of the list is 0.
*
* Side effects:
* The ref counts of the elements in objv are incremented since the
* resulting list now refers to them.
* Effect
*
* The refCount of each elements in 'objv' is incremented as it is added
* to the list.
*
*----------------------------------------------------------------------
*/
@@ -246,28 +233,14 @@ Tcl_NewListObj(
/*
*----------------------------------------------------------------------
*
* Tcl_DbNewListObj --
*
* This function is normally called when debugging: i.e., when
* TCL_MEM_DEBUG is defined. It creates new list objects. It is the same
* as the Tcl_NewListObj function above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
* caller. This simplifies debugging since then the [memory active]
* command will report the correct file name and line number when
* reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, this function just returns the
* result of calling Tcl_NewListObj.
*
* Results:
* A new list object is returned that is initialized from the object
* pointers in objv. If objc is less than or equal to zero, an empty
* object is returned. The new object's string representation is left
* NULL. The new list object has ref count 0.
*
* Side effects:
* The ref counts of the elements in objv are incremented since the
* resulting list now refers to them.
* Tcl_DbNewListObj --
*
* Like 'Tcl_NewListObj', but it calls Tcl_DbCkalloc directly with the
* file name and line number from its caller. This simplifies debugging
* since the [memory active] command will report the correct file
* name and line number when reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, 'Tcl_NewListObj' is called instead.
*
*----------------------------------------------------------------------
*/
@@ -328,19 +301,8 @@ Tcl_DbNewListObj(
*
* Tcl_SetListObj --
*
* Modify an object to be a list containing each of the objc elements of
* the object array referenced by objv.
*
* Results:
* None.
*
* Side effects:
* The object is made a list object and is initialized from the object
* pointers in objv. If objc is less than or equal to zero, an empty
* object is returned. The new object's string representation is left
* NULL. The ref counts of the elements in objv are incremented since the
* list now refers to them. The object's old string and internal
* representations are freed and its type is set NULL.
* Like 'Tcl_NewListObj', but operates on an existing 'Tcl_Obj'instead of
* creating a new one.
*
*----------------------------------------------------------------------
*/
@@ -384,18 +346,20 @@ Tcl_SetListObj(
*
* TclListObjCopy --
*
* Makes a "pure list" copy of a list value. This provides for the C
* level a counterpart of the [lrange $list 0 end] command, while using
* internals details to be as efficient as possible.
* Creates a new 'Tcl_Obj' which is a pure copy of a list value. This
* provides for the C level a counterpart of the [lrange $list 0 end]
* command, while using internals details to be as efficient as possible.
*
* Results:
* Normally returns a pointer to a new Tcl_Obj, that contains the same
* list value as *listPtr does. The returned Tcl_Obj has a refCount of
* zero. If *listPtr does not hold a list, NULL is returned, and if
* interp is non-NULL, an error message is recorded there.
* Value
*
* Side effects:
* None.
* The address of the new 'Tcl_Obj' which shares its internal
* representation with 'listPtr', and whose refCount is 0. If 'listPtr'
* is not actually a list, the value is NULL, and an error message is left
* in 'interp' if it is not NULL.
*
* Effect
*
* 'listPtr' is converted to a list if it isn't one already.
*
*----------------------------------------------------------------------
*/
@@ -425,27 +389,30 @@ TclListObjCopy(
*
* Tcl_ListObjGetElements --
*
* This function returns an (objc,objv) array of the elements in a list
* object.
* Retreive the elements in a list 'Tcl_Obj'.
*
* Results:
* The return value is normally TCL_OK; in this case *objcPtr is set to
* the count of list elements and *objvPtr is set to a pointer to an
* array of (*objcPtr) pointers to each list element. If listPtr does not
* refer to a list object and the object can not be converted to one,
* TCL_ERROR is returned and an error message will be left in the
* interpreter's result if interp is not NULL.
* Value
*
* The objects referenced by the returned array should be treated as
* readonly and their ref counts are _not_ incremented; the caller must
* do that if it holds on to a reference. Furthermore, the pointer and
* length returned by this function may change as soon as any function is
* called on the list object; be careful about retaining the pointer in a
* local data structure.
* TCL_OK
*
* Side effects:
* The possible conversion of the object referenced by listPtr
* to a list object.
* A count of list elements is stored, 'objcPtr', And a pointer to the
* array of elements in the list is stored in 'objvPtr'.
*
* The elements accessible via 'objvPtr' should be treated as readonly
* and the refCount for each object is _not_ incremented; the caller
* must do that if it holds on to a reference. Furthermore, the
* pointer and length returned by this function may change as soon as
* any function is called on the list object. Be careful about
* retaining the pointer in a local data structure.
*
* TCL_ERROR
*
* 'listPtr' is not a valid list. An error message is left in the
* interpreter's result if 'interp' is not NULL.
*
* Effect
*
* 'listPtr' is converted to a list object if it isn't one already.
*
*----------------------------------------------------------------------
*/
@@ -486,20 +453,27 @@ Tcl_ListObjGetElements(
*
* Tcl_ListObjAppendList --
*
* This function appends the elements in the list value referenced by
* elemListPtr to the list value referenced by listPtr.
* Appends the elements of elemListPtr to those of listPtr.
*
* Results:
* The return value is normally TCL_OK. If listPtr or elemListPtr do not
* refer to list values, TCL_ERROR is returned and an error message is
* left in the interpreter's result if interp is not NULL.
* Value
*
* Side effects:
* The reference counts of the elements in elemListPtr are incremented
* since the list now refers to them. listPtr and elemListPtr are
* converted, if necessary, to list objects. Also, appending the new
* elements may cause listObj's array of element pointers to grow.
* listPtr's old string representation, if any, is invalidated.
* TCL_OK
*
* Success.
*
* TCL_ERROR
*
* 'listPtr' or 'elemListPtr' are not valid lists. An error
* message is left in the interpreter's result if 'interp' is not NULL.
*
* Effect
*
* The reference count of each element of 'elemListPtr' as it is added to
* 'listPtr'. 'listPtr' and 'elemListPtr' are converted to 'tclListType'
* if they are not already. Appending the new elements may cause the
* array of element pointers in 'listObj' to grow. If any objects are
* appended to 'listPtr'. Any preexisting string representation of
* 'listPtr' is invalidated.
*
*----------------------------------------------------------------------
*/
@@ -538,24 +512,27 @@ Tcl_ListObjAppendList(
*
* Tcl_ListObjAppendElement --
*
* This function is a special purpose version of Tcl_ListObjAppendList:
* it appends a single object referenced by objPtr to the list object
* referenced by listPtr. If listPtr is not already a list object, an
* attempt will be made to convert it to one.
* Like 'Tcl_ListObjAppendList', but Appends a single value to a list.
*
* Results:
* The return value is normally TCL_OK; in this case objPtr is added to
* the end of listPtr's list. If listPtr does not refer to a list object
* and the object can not be converted to one, TCL_ERROR is returned and
* an error message will be left in the interpreter's result if interp is
* not NULL.
* Value
*
* Side effects:
* The ref count of objPtr is incremented since the list now refers to
* it. listPtr will be converted, if necessary, to a list object. Also,
* appending the new element may cause listObj's array of element
* pointers to grow. listPtr's old string representation, if any, is
* invalidated.
* TCL_OK
*
* 'objPtr' is appended to the elements of 'listPtr'.
*
* TCL_ERROR
*
* listPtr does not refer to a list object and the object can not be
* converted to one. An error message will be left in the
* interpreter's result if interp is not NULL.
*
* Effect
*
* If 'listPtr' is not already of type 'tclListType', it is converted.
* The 'refCount' of 'objPtr' is incremented as it is added to 'listPtr'.
* Appending the new element may cause the the array of element pointers
* in 'listObj' to grow. Any preexisting string representation of
* 'listPtr' is invalidated.
*
*----------------------------------------------------------------------
*/
@@ -706,23 +683,27 @@ Tcl_ListObjAppendElement(
*
* Tcl_ListObjIndex --
*
* This function returns a pointer to the index'th object from the list
* referenced by listPtr. The first element has index 0. If index is
* negative or greater than or equal to the number of elements in the
* list, a NULL is returned. If listPtr is not a list object, an attempt
* will be made to convert it to a list.
* Retrieve a pointer to the element of 'listPtr' at 'index'. The index
* of the first element is 0.
*
* Results:
* The return value is normally TCL_OK; in this case objPtrPtr is set to
* the Tcl_Obj pointer for the index'th list element or NULL if index is
* out of range. This object should be treated as readonly and its ref
* count is _not_ incremented; the caller must do that if it holds on to
* the reference. If listPtr does not refer to a list and can't be
* converted to one, TCL_ERROR is returned and an error message is left
* in the interpreter's result if interp is not NULL.
* Value
*
* Side effects:
* listPtr will be converted, if necessary, to a list object.
* TCL_OK
*
* A pointer to the element at 'index' is stored in 'objPtrPtr'. If
* 'index' is out of range, NULL is stored in 'objPtrPtr'. This
* object should be treated as readonly and its 'refCount' is _not_
* incremented. The caller must do that if it holds on to the
* reference.
*
* TCL_ERROR
*
* 'listPtr' is not a valid list. An an error message is left in the
* interpreter's result if 'interp' is not NULL.
*
* Effect
*
* If 'listPtr' is not already of type 'tclListType', it is converted.
*
*----------------------------------------------------------------------
*/
@@ -764,19 +745,20 @@ Tcl_ListObjIndex(
*
* Tcl_ListObjLength --
*
* This function returns the number of elements in a list object. If the
* object is not already a list object, an attempt will be made to
* convert it to one.
* Retrieve the number of elements in a list.
*
* Results:
* The return value is normally TCL_OK; in this case *intPtr will be set
* to the integer count of list elements. If listPtr does not refer to a
* list object and the object can not be converted to one, TCL_ERROR is
* returned and an error message will be left in the interpreter's result
* if interp is not NULL.
* Value
*
* Side effects:
* The possible conversion of the argument object to a list object.
* TCL_OK
*
* A count of list elements is stored at the address provided by
* 'intPtr'. If 'listPtr' is not already of type 'tclListPtr', it is
* converted.
*
* TCL_ERROR
*
* 'listPtr' is not a valid list. An error message will be left in
* the interpreter's result if 'interp' is not NULL.
*
*----------------------------------------------------------------------
*/
@@ -812,35 +794,36 @@ Tcl_ListObjLength(
*
* Tcl_ListObjReplace --
*
* This function replaces zero or more elements of the list referenced by
* listPtr with the objects from an (objc,objv) array. The objc elements
* of the array referenced by objv replace the count elements in listPtr
* starting at first.
* Replace values in a list.
*
* If the argument first is zero or negative, it refers to the first
* element. If first is greater than or equal to the number of elements
* in the list, then no elements are deleted; the new elements are
* appended to the list. Count gives the number of elements to replace.
* If count is zero or negative then no elements are deleted; the new
* elements are simply inserted before first.
* If 'first' is zero or negative, it refers to the first element. If
* 'first' outside the range of elements in the list, no elements are
* deleted.
*
* The argument objv refers to an array of objc pointers to the new
* elements to be added to listPtr in place of those that were deleted.
* If objv is NULL, no new elements are added. If listPtr is not a list
* object, an attempt will be made to convert it to one.
* If 'count' is zero or negative no elements are deleted, and any new
* elements are inserted at the beginning of the list.
*
* Results:
* The return value is normally TCL_OK. If listPtr does not refer to a
* list object and can not be converted to one, TCL_ERROR is returned and
* an error message will be left in the interpreter's result if interp is
* not NULL.
* Value
*
* Side effects:
* The ref counts of the objc elements in objv are incremented since the
* resulting list now refers to them. Similarly, the ref counts for
* replaced objects are decremented. listPtr is converted, if necessary,
* to a list object. listPtr's old string representation, if any, is
* freed.
* TCL_OK
*
* The first 'objc' values of 'objv' replaced 'count' elements in 'listPtr'
* starting at 'first'. If 'objc' 0, no new elements are added.
*
* TCL_ERROR
*
* 'listPtr' is not a valid list. An error message is left in the
* interpreter's result if 'interp' is not NULL.
*
* Effect
*
* If 'listPtr' is not of type 'tclListType', it is converted if possible.
*
* The 'refCount' of each element appended to the list is incremented.
* Similarly, the 'refCount' for each replaced element is decremented.
*
* If 'listPtr' is modified, any previous string representation is
* invalidated.
*
*----------------------------------------------------------------------
*/
@@ -1098,22 +1081,19 @@ Tcl_ListObjReplace(
*
* TclLindexList --
*
* This procedure handles the 'lindex' command when objc==3.
* Implements the 'lindex' command when objc==3.
*
* Results:
* Returns a pointer to the object extracted, or NULL if an error
* occurred. The returned object already includes one reference count for
* the pointer returned.
* Implemented entirely as a wrapper around 'TclLindexFlat'. Reconfigures
* the argument format into required form while taking care to manage
* shimmering so as to tend to keep the most useful intreps
* and/or avoid the most expensive conversions.
*
* Side effects:
* None.
* Value
*
* Notes:
* This procedure is implemented entirely as a wrapper around
* TclLindexFlat. All it does is reconfigure the argument format into the
* form required by TclLindexFlat, while taking care to manage shimmering
* in such a way that we tend to keep the most useful intreps and/or
* avoid the most expensive conversions.
* A pointer to the specified element, with its 'refCount' incremented, or
* NULL if an error occurred.
*
* Notes
*
*----------------------------------------------------------------------
*/
@@ -1165,17 +1145,11 @@ TclLindexList(
return TclLindexFlat(interp, listPtr, 1, &argPtr);
}
if (indexListCopy->typePtr == &tclListType) {
List *listRepPtr = ListRepPtr(indexListCopy);
{
int indexCount = -1; /* Size of the array of list indices. */
Tcl_Obj **indices = NULL; /* Array of list indices. */
listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount,
&listRepPtr->elements);
} else {
int indexCount = -1; /* Size of the array of list indices. */
Tcl_Obj **indices = NULL;
/* Array of list indices. */
Tcl_ListObjGetElements(NULL, indexListCopy, &indexCount, &indices);
TclListObjGetElements(NULL, indexListCopy, &indexCount, &indices);
listPtr = TclLindexFlat(interp, listPtr, indexCount, indices);
}
Tcl_DecrRefCount(indexListCopy);
@@ -1185,25 +1159,20 @@ TclLindexList(
/*
*----------------------------------------------------------------------
*
* TclLindexFlat --
* TclLindexFlat --
*
* This procedure is the core of the 'lindex' command, with all index
* arguments presented as a flat list.
* The core of the 'lindex' command, with all index
* arguments presented as a flat list.
*
* Results:
* Returns a pointer to the object extracted, or NULL if an error
* occurred. The returned object already includes one reference count for
* the pointer returned.
* Value
*
* Side effects:
* None.
* A pointer to the object extracted, with its 'refCount' incremented, or
* NULL if an error occurred. Thus, the calling code will usually do
* something like:
*
* Tcl_SetObjResult(interp, result);
* Tcl_DecrRefCount(result);
*
* Notes:
* The reference count of the returned object includes one reference
* corresponding to the pointer returned. Thus, the calling code will
* usually do something like:
* Tcl_SetObjResult(interp, result);
* Tcl_DecrRefCount(result);
*
*----------------------------------------------------------------------
*/
@@ -1279,23 +1248,16 @@ TclLindexFlat(
*
* TclLsetList --
*
* Core of the 'lset' command when objc == 4. Objv[2] may be either a
* The core of [lset] when objc == 4. Objv[2] may be either a
* scalar index or a list of indices.
*
* Results:
* Returns the new value of the list variable, or NULL if there was an
* error. The returned object includes one reference count for the
* pointer returned.
* Implemented entirely as a wrapper around 'TclLindexFlat', as described
* for 'TclLindexList'.
*
* Side effects:
* None.
* Value
*
* Notes:
* This procedure is implemented entirely as a wrapper around
* TclLsetFlat. All it does is reconfigure the argument format into the
* form required by TclLsetFlat, while taking care to manage shimmering
* in such a way that we tend to keep the most useful intreps and/or
* avoid the most expensive conversions.
* The new list, with the 'refCount' of 'valuPtr' incremented, or NULL if
* there was an error.
*
*----------------------------------------------------------------------
*/
@@ -1357,36 +1319,39 @@ TclLsetList(
*
* Core engine of the 'lset' command.
*
* Results:
* Returns the new value of the list variable, or NULL if an error
* occurred. The returned object includes one reference count for the
* pointer returned.
* Value
*
* Side effects:
* On entry, the reference count of the variable value does not reflect
* any references held on the stack. The first action of this function is
* to determine whether the object is shared, and to duplicate it if it
* is. The reference count of the duplicate is incremented. At this
* point, the reference count will be 1 for either case, so that the
* object will appear to be unshared.
* The resulting list
*
* If an error occurs, and the object has been duplicated, the reference
* count on the duplicate is decremented so that it is now 0: this
* dismisses any memory that was allocated by this function.
* The 'refCount' of 'valuePtr' is incremented. If 'listPtr' was not
* duplicated, its 'refCount' is incremented. The reference count of
* an unduplicated object is therefore 2 (one for the returned pointer
* and one for the variable that holds it). The reference count of a
* duplicate object is 1, reflecting that result is the only active
* reference. The caller is expected to store the result in the
* variable and decrement its reference count. (INST_STORE_* does
* exactly this.)
*
* NULL
*
* An error occurred. If 'listPtr' was duplicated, the reference
* count on the duplicate is decremented so that it is 0, causing any
* memory allocated by this function to be freed.
*
* If no error occurs, the reference count of the original object is
* incremented if the object has not been duplicated, and nothing is done
* to a reference count of the duplicate. Now the reference count of an
* unduplicated object is 2 (the returned pointer, plus the one stored in
* the variable). The reference count of a duplicate object is 1,
* reflecting that the returned pointer is the only active reference. The
* caller is expected to store the returned value back in the variable
* and decrement its reference count. (INST_STORE_* does exactly this.)
*
* Surgery is performed on the unshared list value to produce the result.
* TclLsetFlat maintains a linked list of Tcl_Obj's whose string
* Effect
*
* On entry, the reference count of 'listPtr' does not reflect any
* references held on the stack. The first action of this function is to
* determine whether 'listPtr' is shared and to create a duplicate
* unshared copy if it is. The reference count of the duplicate is
* incremented. At this point, the reference count is 1 in either case so
* that the object is considered unshared.
*
* The unshared list is altered directly to produce the result.
* 'TclLsetFlat' maintains a linked list of 'Tcl_Obj' values whose string
* representations must be spoilt by threading via 'ptr2' of the
* two-pointer internal representation. On entry to TclLsetFlat, the
* two-pointer internal representation. On entry to 'TclLsetFlat', the
* values of 'ptr2' are immaterial; on exit, the 'ptr2' field of any
* Tcl_Obj that has been modified is set to NULL.
*
@@ -1601,26 +1566,38 @@ TclLsetFlat(
*
* TclListObjSetElement --
*
* Set a single element of a list to a specified value
*
* Results:
* The return value is normally TCL_OK. If listPtr does not refer to a
* list object and cannot be converted to one, TCL_ERROR is returned and
* an error message will be left in the interpreter result if interp is
* not NULL. Similarly, if index designates an element outside the range
* [0..listLength-1], where listLength is the count of elements in the
* list object designated by listPtr, TCL_ERROR is returned and an error
* message is left in the interpreter result.
*
* Side effects:
* Tcl_Panic if listPtr designates a shared object. Otherwise, attempts
* to convert it to a list with a non-shared internal rep. Decrements the
* ref count of the object at the specified index within the list,
* replaces with the object designated by valuePtr, and increments the
* ref count of the replacement object.
* Set a single element of a list to a specified value.
*
* It is the caller's responsibility to invalidate the string
* representation of the object.
* representation of the 'listPtr'.
*
* Value
*
* TCL_OK
*
* Success.
*
* TCL_ERROR
*
* 'listPtr' does not refer to a list object and cannot be converted
* to one. An error message will be left in the interpreter result if
* interp is not NULL.
*
* TCL_ERROR
*
* An index designates an element outside the range [0..listLength-1],
* where 'listLength' is the count of elements in the list object
* designated by 'listPtr'. An error message is left in the
* interpreter result.
*
* Effect
*
* If 'listPtr' designates a shared object, 'Tcl_Panic' is called. If
* 'listPtr' is not already of type 'tclListType', it is converted and the
* internal representation is unshared. The 'refCount' of the element at
* 'index' is decremented and replaced in the list with the 'valuePtr',
* whose 'refCount' in turn is incremented.
*
*
*----------------------------------------------------------------------
*/
@@ -1738,16 +1715,14 @@ TclListObjSetElement(
*
* FreeListInternalRep --
*
* Deallocate the storage associated with a list object's internal
* representation.
* Deallocate the storage associated with the internal representation of a
* a list object.
*
* Results:
* None.
* Effect
*
* Side effects:
* Frees listPtr's List* internal representation and sets listPtr's
* internalRep.twoPtrValue.ptr1 to NULL. Decrements the ref counts of all
* element objects, which may free them.
* The storage for the internal 'List' pointer of 'listPtr' is freed, the
* 'internalRep.twoPtrValue.ptr1' of 'listPtr' is set to NULL, and the 'refCount'
* of each element of the list is decremented.
*
*----------------------------------------------------------------------
*/
@@ -1776,14 +1751,12 @@ FreeListInternalRep(
*
* DupListInternalRep --
*
* Initialize the internal representation of a list Tcl_Obj to share the
* Initialize the internal representation of a list 'Tcl_Obj' to share the
* internal representation of an existing list object.
*
* Results:
* None.
* Effect
*
* Side effects:
* The reference count of the List internal rep is incremented.
* The 'refCount' of the List internal rep is incremented.
*
*----------------------------------------------------------------------
*/
@@ -1803,16 +1776,20 @@ DupListInternalRep(
*
* SetListFromAny --
*
* Attempt to generate a list internal form for the Tcl object "objPtr".
* Convert any object to a list.
*
* Results:
* The return value is TCL_OK or TCL_ERROR. If an error occurs during
* conversion, an error message is left in the interpreter's result
* unless "interp" is NULL.
* Value
*
* TCL_OK
*
* Success. The internal representation of 'objPtr' is set, and the type
* of 'objPtr' is 'tclListType'.
*
* TCL_ERROR
*
* An error occured during conversion. An error message is left in the
* interpreter's result if 'interp' is not NULL.
*
* Side effects:
* If no error occurs, a list is stored as "objPtr"s internal
* representation.
*
*----------------------------------------------------------------------
*/
@@ -1937,18 +1914,16 @@ SetListFromAny(
*
* UpdateStringOfList --
*
* Update the string representation for a list object. Note: This
* function does not invalidate an existing old string rep so storage
* will be lost if this has not already been done.
* Update the string representation for a list object.
*
* Results:
* None.
* Any previously-exising string representation is not invalidated, so
* storage is lost if this has not been taken care of.
*
* Side effects:
* The object's string is set to a valid string that results from the
* list-to-string conversion. This string will be empty if the list has
* no elements. The list internal representation should not be NULL and
* we assume it is not NULL.
* Effect
*
* The string representation of 'listPtr' is set to the resulting string.
* This string will be empty if the list has no elements. It is assumed
* that the list internal representation is not NULL.
*
*----------------------------------------------------------------------
*/
@@ -1957,8 +1932,8 @@ static void
UpdateStringOfList(
Tcl_Obj *listPtr) /* List object with string rep to update. */
{
# define LOCAL_SIZE 20
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
# define LOCAL_SIZE 64
char localFlags[LOCAL_SIZE], *flagPtr = NULL;
List *listRepPtr = ListRepPtr(listPtr);
int numElems = listRepPtr->elemCount;
int i, length, bytesNeeded = 0;
@@ -1995,7 +1970,7 @@ UpdateStringOfList(
* We know numElems <= LIST_MAX, so this is safe.
*/
flagPtr = ckalloc(numElems * sizeof(int));
flagPtr = ckalloc(numElems);
}
elemPtrs = &listRepPtr->elements;
for (i = 0; i < numElems; i++) {
+1 -1
View File
@@ -130,7 +130,7 @@ Tcl_LoadObjCmd(
Tcl_PackageInitProc *initProc;
const char *p, *fullFileName, *packageName;
Tcl_LoadHandle loadHandle;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
unsigned len;
int index, flags = 0;
Tcl_Obj *const *savedobjv = objv;
+37 -11
View File
@@ -915,6 +915,11 @@ Tcl_DeleteNamespace(
Tcl_HashSearch search;
Command *cmdPtr;
/*
* Ensure that this namespace doesn't get deallocated in the meantime.
*/
nsPtr->refCount++;
/*
* Give anyone interested - notably TclOO - a chance to use this namespace
* normally despite the fact that the namespace is going to go. Allows the
@@ -1047,16 +1052,7 @@ Tcl_DeleteNamespace(
#endif
Tcl_DeleteHashTable(&nsPtr->cmdTable);
/*
* If the reference count is 0, then discard the namespace.
* Otherwise, mark it as "dead" so that it can't be used.
*/
if (nsPtr->refCount == 0) {
NamespaceFree(nsPtr);
} else {
nsPtr->flags |= NS_DEAD;
}
nsPtr ->flags |= NS_DEAD;
} else {
/*
* Restore the ::errorInfo and ::errorCode traces.
@@ -1073,6 +1069,7 @@ Tcl_DeleteNamespace(
nsPtr->flags &= ~(NS_DYING|NS_KILLED);
}
}
TclNsDecrRefCount(nsPtr);
}
/*
@@ -2422,6 +2419,35 @@ TclGetNamespaceForQualName(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclEnsureNamespace --
*
* Provide a namespace that is not deleted.
*
* Value
*
* namespacePtr, if it is not scheduled for deletion, or a pointer to a
* new namespace with the same name otherwise.
*
* Effect
* None.
*
*----------------------------------------------------------------------
*/
Tcl_Namespace *
TclEnsureNamespace(
Tcl_Interp *interp,
Tcl_Namespace *namespacePtr)
{
Namespace *nsPtr = (Namespace *) namespacePtr;
if (!(nsPtr->flags & NS_DYING)) {
return namespacePtr;
}
return Tcl_CreateNamespace(interp, nsPtr->fullName, NULL, NULL);
}
/*
*----------------------------------------------------------------------
*
@@ -2639,7 +2665,7 @@ Tcl_FindCommand(
Namespace *nsPtr[2];
register int search;
TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
TclGetNamespaceForQualName(interp, name, cxtNsPtr,
flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
/*
+535 -607
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -24,7 +24,7 @@
* win/tclooConfig.sh
*/
#define TCLOO_VERSION "1.0.5"
#define TCLOO_VERSION "1.1.0"
#define TCLOO_PATCHLEVEL TCLOO_VERSION
#include "tcl.h"
+26 -17
View File
@@ -1183,8 +1183,9 @@ TclOOCopyObjectCmd(
{
Tcl_Object oPtr, o2Ptr;
if (objc < 2 || objc > 3) {
Tcl_WrongNumArgs(interp, 1, objv, "sourceName ?targetName?");
if (objc < 2 || objc > 4) {
Tcl_WrongNumArgs(interp, 1, objv,
"sourceName ?targetName? ?targetNamespace?");
return TCL_ERROR;
}
@@ -1204,24 +1205,32 @@ TclOOCopyObjectCmd(
if (objc == 2) {
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, NULL, NULL);
} else {
const char *name;
Tcl_DString buffer;
const char *name, *namespaceName;
name = TclGetString(objv[2]);
Tcl_DStringInit(&buffer);
if (name[0]!=':' || name[1]!=':') {
Interp *iPtr = (Interp *) interp;
if (iPtr->varFramePtr != NULL) {
Tcl_DStringAppend(&buffer,
iPtr->varFramePtr->nsPtr->fullName, -1);
}
TclDStringAppendLiteral(&buffer, "::");
Tcl_DStringAppend(&buffer, name, -1);
name = Tcl_DStringValue(&buffer);
if (name[0] == '\0') {
name = NULL;
}
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, name, NULL);
Tcl_DStringFree(&buffer);
/*
* Choose a unique namespace name if the user didn't supply one.
*/
namespaceName = NULL;
if (objc == 4) {
namespaceName = TclGetString(objv[3]);
if (namespaceName[0] == '\0') {
namespaceName = NULL;
} else if (Tcl_FindNamespace(interp, namespaceName, NULL,
0) != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s refers to an existing namespace", namespaceName));
return TCL_ERROR;
}
}
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, name, namespaceName);
}
if (o2Ptr == NULL) {
+63 -25
View File
@@ -53,7 +53,8 @@ static void AddClassFiltersToCallContext(Object *const oPtr,
Class *clsPtr, struct ChainBuilder *const cbPtr,
Tcl_HashTable *const doneFilters, int flags);
static void AddClassMethodNames(Class *clsPtr, const int flags,
Tcl_HashTable *const namesPtr);
Tcl_HashTable *const namesPtr,
Tcl_HashTable *const examinedClassesPtr);
static inline void AddMethodToCallChain(Method *const mPtr,
struct ChainBuilder *const cbPtr,
Tcl_HashTable *const doneFilters,
@@ -109,7 +110,8 @@ TclOODeleteContext(
TclOODeleteChain(contextPtr->callPtr);
if (oPtr != NULL) {
TclStackFree(oPtr->fPtr->interp, contextPtr);
DelRef(oPtr);
/* Corresponding AddRef() in TclOO.c/TclOOObjectCmdCore */
TclOODecrRefCount(oPtr);
}
}
@@ -232,7 +234,7 @@ FreeMethodNameRep(
* TclOOInvokeContext --
*
* Invokes a single step along a method call-chain context. Note that the
* invokation of a step along the chain can cause further steps along the
* invocation of a step along the chain can cause further steps along the
* chain to be invoked. Note that this function is written to be as light
* in stack usage as possible.
*
@@ -367,6 +369,10 @@ TclOOGetSortedMethodList(
{
Tcl_HashTable names; /* Tcl_Obj* method name to "wanted in list"
* mapping. */
Tcl_HashTable examinedClasses;
/* Used to track what classes have been looked
* at. Is set-like in nature and keyed by
* pointer to class. */
FOREACH_HASH_DECLS;
int i;
Class *mixinPtr;
@@ -376,6 +382,7 @@ TclOOGetSortedMethodList(
void *isWanted;
Tcl_InitObjHashTable(&names);
Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS);
/*
* Name the bits used in the names table values.
@@ -436,11 +443,14 @@ TclOOGetSortedMethodList(
* hierarchy.
*/
AddClassMethodNames(oPtr->selfCls, flags, &names);
AddClassMethodNames(oPtr->selfCls, flags, &names, &examinedClasses);
FOREACH(mixinPtr, oPtr->mixins) {
AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN, &names);
AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN, &names,
&examinedClasses);
}
Tcl_DeleteHashTable(&examinedClasses);
/*
* See how many (visible) method names there are. If none, we do not (and
* should not) try to sort the list of them.
@@ -495,18 +505,24 @@ TclOOGetSortedClassMethodList(
{
Tcl_HashTable names; /* Tcl_Obj* method name to "wanted in list"
* mapping. */
Tcl_HashTable examinedClasses;
/* Used to track what classes have been looked
* at. Is set-like in nature and keyed by
* pointer to class. */
FOREACH_HASH_DECLS;
int i;
Tcl_Obj *namePtr;
void *isWanted;
Tcl_InitObjHashTable(&names);
Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS);
/*
* Process method names from the class hierarchy and the mixin hierarchy.
*/
AddClassMethodNames(clsPtr, flags, &names);
AddClassMethodNames(clsPtr, flags, &names, &examinedClasses);
Tcl_DeleteHashTable(&examinedClasses);
/*
* See how many (visible) method names there are. If none, we do not (and
@@ -581,14 +597,28 @@ AddClassMethodNames(
Class *clsPtr, /* Class to get method names from. */
const int flags, /* Whether we are interested in just the
* public method names. */
Tcl_HashTable *const namesPtr)
Tcl_HashTable *const namesPtr,
/* Reference to the hash table to put the
* information in. The hash table maps the
* Tcl_Obj * method name to an integral value
* describing whether the method is wanted.
* This ensures that public/private override
* semantics are handled correctly.*/
* semantics are handled correctly. */
Tcl_HashTable *const examinedClassesPtr)
/* Hash table that tracks what classes have
* already been looked at. The keys are the
* pointers to the classes, and the values are
* immaterial. */
{
/*
* If we've already started looking at this class, stop working on it now
* to prevent repeated work.
*/
if (Tcl_FindHashEntry(examinedClassesPtr, (char *) clsPtr)) {
return;
}
/*
* Scope all declarations so that the compiler can stand a good chance of
* making the recursive step highly efficient. We also hand-implement the
@@ -596,24 +626,31 @@ AddClassMethodNames(
* tail-recursion optimization usefully.
*/
if (clsPtr->mixins.num != 0) {
Class *mixinPtr;
int i;
/* TODO: Beware of infinite loops! */
FOREACH(mixinPtr, clsPtr->mixins) {
AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN, namesPtr);
}
}
while (1) {
FOREACH_HASH_DECLS;
Tcl_Obj *namePtr;
Method *mPtr;
int isNew;
(void) Tcl_CreateHashEntry(examinedClassesPtr, (char *) clsPtr,
&isNew);
if (!isNew) {
break;
}
if (clsPtr->mixins.num != 0) {
Class *mixinPtr;
int i;
FOREACH(mixinPtr, clsPtr->mixins) {
if (mixinPtr != clsPtr) {
AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN,
namesPtr, examinedClassesPtr);
}
}
}
FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) {
int isNew;
hPtr = Tcl_CreateHashEntry(namesPtr, (char *) namePtr, &isNew);
if (isNew) {
int isWanted = (!(flags & PUBLIC_METHOD)
@@ -640,7 +677,8 @@ AddClassMethodNames(
int i;
FOREACH(superPtr, clsPtr->superclasses) {
AddClassMethodNames(superPtr, flags, namesPtr);
AddClassMethodNames(superPtr, flags, namesPtr,
examinedClassesPtr);
}
}
}
@@ -793,7 +831,7 @@ AddMethodToCallChain(
* Call chain semantics states that methods come as *late* in the
* call chain as possible. This is done by copying down the
* following methods. Note that this does not change the number of
* method invokations in the call chain; it just rearranges them.
* method invocations in the call chain; it just rearranges them.
*/
Class *declCls = callPtr->chain[i].filterDeclarer;
@@ -898,7 +936,7 @@ IsStillValid(
* TclOOGetCallContext --
*
* Responsible for constructing the call context, an ordered list of all
* method implementations to be called as part of a method invokation.
* method implementations to be called as part of a method invocation.
* This method is central to the whole operation of the OO system.
*
* ----------------------------------------------------------------------
@@ -1134,6 +1172,7 @@ TclOOGetCallContext(
returnContext:
contextPtr = TclStackAlloc(oPtr->fPtr->interp, sizeof(CallContext));
contextPtr->oPtr = oPtr;
/* Corresponding TclOODecrRefCount() in TclOODeleteContext */
AddRef(oPtr);
contextPtr->callPtr = callPtr;
contextPtr->skip = 2;
@@ -1405,7 +1444,6 @@ AddSimpleClassChainToCallContext(
if (flags & CONSTRUCTOR) {
AddMethodToCallChain(classPtr->constructorPtr, cbPtr, doneFilters,
filterDecl, flags);
} else if (flags & DESTRUCTOR) {
AddMethodToCallChain(classPtr->destructorPtr, cbPtr, doneFilters,
filterDecl, flags);
@@ -1480,7 +1518,7 @@ TclOORenderCallChain(
/*
* Do the actual construction of the descriptions. They consist of a list
* of triples that describe the details of how a method is understood. For
* each triple, the first word is the type of invokation ("method" is
* each triple, the first word is the type of invocation ("method" is
* normal, "unknown" is special because it adds the method name as an
* extra argument when handled by some method types, and "filter" is
* special because it's a filter method). The second word is the name of
+130 -213
View File
@@ -47,8 +47,11 @@ struct DeclaredSlot {
static inline void BumpGlobalEpoch(Tcl_Interp *interp, Class *classPtr);
static Tcl_Command FindCommand(Tcl_Interp *interp, Tcl_Obj *stringObj,
Tcl_Namespace *const namespacePtr);
static void GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr,
static inline void GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr,
Tcl_Obj *savedNameObj, const char *typeOfSubject);
static inline int MagicDefinitionInvoke(Tcl_Interp *interp,
Tcl_Namespace *nsPtr, int cmdIndex,
int objc, Tcl_Obj *const *objv);
static inline Class * GetClassInOuterContext(Tcl_Interp *interp,
Tcl_Obj *className, const char *errMsg);
static inline int InitDefineContext(Tcl_Interp *interp,
@@ -323,9 +326,8 @@ TclOOObjectSetMixins(
if (numMixins == 0) {
if (oPtr->mixins.num != 0) {
FOREACH(mixinPtr, oPtr->mixins) {
if (mixinPtr) {
TclOORemoveFromInstances(oPtr, mixinPtr);
}
TclOORemoveFromInstances(oPtr, mixinPtr);
TclOODecrRefCount(mixinPtr->thisPtr);
}
ckfree(oPtr->mixins.list);
oPtr->mixins.num = 0;
@@ -337,6 +339,7 @@ TclOOObjectSetMixins(
if (mixinPtr && mixinPtr != oPtr->selfCls) {
TclOORemoveFromInstances(oPtr, mixinPtr);
}
TclOODecrRefCount(mixinPtr->thisPtr);
}
oPtr->mixins.list = ckrealloc(oPtr->mixins.list,
sizeof(Class *) * numMixins);
@@ -349,6 +352,8 @@ TclOOObjectSetMixins(
FOREACH(mixinPtr, oPtr->mixins) {
if (mixinPtr != oPtr->selfCls) {
TclOOAddToInstances(oPtr, mixinPtr);
/* For the new copy created by memcpy */
AddRef(mixinPtr->thisPtr);
}
}
}
@@ -378,6 +383,7 @@ TclOOClassSetMixins(
if (classPtr->mixins.num != 0) {
FOREACH(mixinPtr, classPtr->mixins) {
TclOORemoveFromMixinSubs(classPtr, mixinPtr);
TclOODecrRefCount(mixinPtr->thisPtr);
}
ckfree(classPtr->mixins.list);
classPtr->mixins.num = 0;
@@ -386,6 +392,7 @@ TclOOClassSetMixins(
if (classPtr->mixins.num != 0) {
FOREACH(mixinPtr, classPtr->mixins) {
TclOORemoveFromMixinSubs(classPtr, mixinPtr);
TclOODecrRefCount(mixinPtr->thisPtr);
}
classPtr->mixins.list = ckrealloc(classPtr->mixins.list,
sizeof(Class *) * numMixins);
@@ -396,6 +403,8 @@ TclOOClassSetMixins(
memcpy(classPtr->mixins.list, mixins, sizeof(Class *) * numMixins);
FOREACH(mixinPtr, classPtr->mixins) {
TclOOAddToMixinSubs(classPtr, mixinPtr);
/* For the new copy created by memcpy */
AddRef(mixinPtr->thisPtr);
}
}
BumpGlobalEpoch(interp, classPtr);
@@ -755,7 +764,7 @@ GetClassInOuterContext(
* ----------------------------------------------------------------------
*/
static void
static inline void
GenerateErrorInfo(
Tcl_Interp *interp, /* Where to store the error info trace. */
Object *oPtr, /* What object (or class) was being configured
@@ -784,6 +793,69 @@ GenerateErrorInfo(
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}
/*
* ----------------------------------------------------------------------
*
* MagicDefinitionInvoke --
* Part of the implementation of the "oo::define" and "oo::objdefine"
* commands that is used to implement the more-than-one-argument case,
* applying ensemble-like tricks with dispatch so that error messages are
* clearer. Doesn't handle the management of the stack frame.
*
* ----------------------------------------------------------------------
*/
static inline int
MagicDefinitionInvoke(
Tcl_Interp *interp,
Tcl_Namespace *nsPtr,
int cmdIndex,
int objc,
Tcl_Obj *const *objv)
{
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Tcl_Command cmd;
int isRoot, dummy, result, offset = cmdIndex + 1;
/*
* More than one argument: fire them through the ensemble processing
* engine so that everything appears to be good and proper in error
* messages. Note that we cannot just concatenate and send through
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we cannot go
* through Tcl_EvalObjv without the extra work to pre-find the command, as
* that finds command names in the wrong namespace at the moment. Ugly!
*/
isRoot = TclInitRewriteEnsemble(interp, offset, 1, objv);
/*
* Build the list of arguments using a Tcl_Obj as a workspace. See
* comments above for why these contortions are necessary.
*/
objPtr = Tcl_NewObj();
obj2Ptr = Tcl_NewObj();
cmd = FindCommand(interp, objv[cmdIndex], nsPtr);
if (cmd == NULL) {
/* punt this case! */
Tcl_AppendObjToObj(obj2Ptr, objv[cmdIndex]);
} else {
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
}
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
/* TODO: overflow? */
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-offset, objv+offset);
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
result = Tcl_EvalObjv(interp, objc-cmdIndex, objs, TCL_EVAL_INVOKE);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
Tcl_DecrRefCount(objPtr);
return result;
}
/*
* ----------------------------------------------------------------------
*
@@ -805,8 +877,8 @@ TclOODefineObjCmd(
Tcl_Obj *const *objv)
{
Foundation *fPtr = TclOOGetFoundation(interp);
int result;
Object *oPtr;
int result;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "className arg ?arg ...?");
@@ -846,48 +918,9 @@ TclOODefineObjCmd(
}
TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Tcl_Command cmd;
int isRoot, dummy;
/*
* More than one argument: fire them through the ensemble processing
* engine so that everything appears to be good and proper in error
* messages. Note that we cannot just concatenate and send through
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we
* cannot go through Tcl_EvalObjv without the extra work to pre-find
* the command, as that finds command names in the wrong namespace at
* the moment. Ugly!
*/
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
/*
* Build the list of arguments using a Tcl_Obj as a workspace. See
* comments above for why these contortions are necessary.
*/
objPtr = Tcl_NewObj();
obj2Ptr = Tcl_NewObj();
cmd = FindCommand(interp, objv[2], fPtr->defineNs);
if (cmd == NULL) {
/* punt this case! */
Tcl_AppendObjToObj(obj2Ptr, objv[2]);
} else {
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
}
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
/* TODO: overflow? */
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-3, objv+3);
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
Tcl_DecrRefCount(objPtr);
result = MagicDefinitionInvoke(interp, fPtr->defineNs, 2, objc, objv);
}
DelRef(oPtr);
TclOODecrRefCount(oPtr);
/*
* Restore the previous "current" namespace.
@@ -918,8 +951,8 @@ TclOOObjDefObjCmd(
Tcl_Obj *const *objv)
{
Foundation *fPtr = TclOOGetFoundation(interp);
int isRoot, result;
Object *oPtr;
int result;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "objectName arg ?arg ...?");
@@ -952,49 +985,9 @@ TclOOObjDefObjCmd(
}
TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Tcl_Command cmd;
int dummy;
/*
* More than one argument: fire them through the ensemble processing
* engine so that everything appears to be good and proper in error
* messages. Note that we cannot just concatenate and send through
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we
* cannot go through Tcl_EvalObjv without the extra work to pre-find
* the command, as that finds command names in the wrong namespace at
* the moment. Ugly!
*/
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
/*
* Build the list of arguments using a Tcl_Obj as a workspace. See
* comments above for why these contortions are necessary.
*/
objPtr = Tcl_NewObj();
obj2Ptr = Tcl_NewObj();
cmd = FindCommand(interp, objv[2], fPtr->objdefNs);
if (cmd == NULL) {
/* punt this case! */
Tcl_AppendObjToObj(obj2Ptr, objv[2]);
} else {
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
}
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
/* TODO: overflow? */
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-3, objv+3);
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
Tcl_DecrRefCount(objPtr);
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 2, objc, objv);
}
DelRef(oPtr);
TclOODecrRefCount(oPtr);
/*
* Restore the previous "current" namespace.
@@ -1025,8 +1018,8 @@ TclOODefineSelfObjCmd(
Tcl_Obj *const *objv)
{
Foundation *fPtr = TclOOGetFoundation(interp);
int result;
Object *oPtr;
int result;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?");
@@ -1059,48 +1052,9 @@ TclOODefineSelfObjCmd(
}
TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Tcl_Command cmd;
int isRoot, dummy;
/*
* More than one argument: fire them through the ensemble processing
* engine so that everything appears to be good and proper in error
* messages. Note that we cannot just concatenate and send through
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we
* cannot go through Tcl_EvalObjv without the extra work to pre-find
* the command, as that finds command names in the wrong namespace at
* the moment. Ugly!
*/
isRoot = TclInitRewriteEnsemble(interp, 2, 1, objv);
/*
* Build the list of arguments using a Tcl_Obj as a workspace. See
* comments above for why these contortions are necessary.
*/
objPtr = Tcl_NewObj();
obj2Ptr = Tcl_NewObj();
cmd = FindCommand(interp, objv[1], fPtr->objdefNs);
if (cmd == NULL) {
/* punt this case! */
Tcl_AppendObjToObj(obj2Ptr, objv[1]);
} else {
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
}
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
/* TODO: overflow? */
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-2, objv+2);
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
result = Tcl_EvalObjv(interp, objc-1, objs, TCL_EVAL_INVOKE);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
Tcl_DecrRefCount(objPtr);
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 1, objc, objv);
}
DelRef(oPtr);
TclOODecrRefCount(oPtr);
/*
* Restore the previous "current" namespace.
@@ -1130,6 +1084,7 @@ TclOODefineClassObjCmd(
Object *oPtr;
Class *clsPtr;
Foundation *fPtr = TclOOGetFoundation(interp);
int wasClass, willBeClass;
/*
* Parse the context to get the object to operate on.
@@ -1165,19 +1120,10 @@ TclOODefineClassObjCmd(
if (clsPtr == NULL) {
return TCL_ERROR;
}
/*
* Apply semantic checks. In particular, classes and non-classes are not
* interchangable (too complicated to do the conversion!) so we must
* produce an error if any attempt is made to swap from one to the other.
*/
if ((oPtr->classPtr==NULL) == TclOOIsReachable(fPtr->classCls, clsPtr)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"may not change a %sclass object into a %sclass object",
(oPtr->classPtr==NULL ? "non-" : ""),
(oPtr->classPtr==NULL ? "" : "non-")));
Tcl_SetErrorCode(interp, "TCL", "OO", "TRANSMUTATION", NULL);
if (oPtr == clsPtr->thisPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"may not change classes into an instance of themselves", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1185,13 +1131,36 @@ TclOODefineClassObjCmd(
* Set the object's class.
*/
wasClass = (oPtr->classPtr != NULL);
willBeClass = (TclOOIsReachable(fPtr->classCls, clsPtr));
if (oPtr->selfCls != clsPtr) {
TclOORemoveFromInstances(oPtr, oPtr->selfCls);
TclOODecrRefCount(oPtr->selfCls->thisPtr);
oPtr->selfCls = clsPtr;
AddRef(oPtr->selfCls->thisPtr);
TclOOAddToInstances(oPtr, oPtr->selfCls);
if (!(clsPtr->thisPtr->flags & OBJECT_DELETED)) {
oPtr->flags &= ~CLASS_GONE;
/*
* Create or delete the class guts if necessary.
*/
if (wasClass && !willBeClass) {
/*
* This is the most global of all epochs. Bump it! No cache can be
* trusted!
*/
TclOORemoveFromMixins(oPtr->classPtr, oPtr);
oPtr->fPtr->epoch++;
oPtr->flags |= DONT_DELETE;
TclOODeleteDescendants(interp, oPtr);
oPtr->flags &= ~DONT_DELETE;
TclOOReleaseClassContents(interp, oPtr);
} else if (!wasClass && willBeClass) {
TclOOAllocClass(interp, oPtr);
}
if (oPtr->classPtr != NULL) {
BumpGlobalEpoch(interp, oPtr->classPtr);
} else {
@@ -1600,69 +1569,6 @@ TclOODefineMethodObjCmd(
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOODefineMixinObjCmd --
* Implementation of the "mixin" subcommand of the "oo::define" and
* "oo::objdefine" commands.
*
* ----------------------------------------------------------------------
*/
int
TclOODefineMixinObjCmd(
ClientData clientData,
Tcl_Interp *interp,
const int objc,
Tcl_Obj *const *objv)
{
int isInstanceMixin = (clientData != NULL);
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
Class **mixins;
int i;
if (oPtr == NULL) {
return TCL_ERROR;
}
if (!isInstanceMixin && !oPtr->classPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
mixins = TclStackAlloc(interp, sizeof(Class *) * (objc-1));
for (i=1 ; i<objc ; i++) {
Class *clsPtr = GetClassInOuterContext(interp, objv[i],
"may only mix in classes");
if (clsPtr == NULL) {
goto freeAndError;
}
if (!isInstanceMixin && TclOOIsReachable(oPtr->classPtr, clsPtr)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"may not mix a class into itself", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL);
goto freeAndError;
}
mixins[i-1] = clsPtr;
}
if (isInstanceMixin) {
TclOOObjectSetMixins(oPtr, objc-1, mixins);
} else {
TclOOClassSetMixins(interp, oPtr->classPtr, objc-1, mixins);
}
TclStackFree(interp, mixins);
return TCL_OK;
freeAndError:
TclStackFree(interp, mixins);
return TCL_ERROR;
}
/*
* ----------------------------------------------------------------------
*
@@ -2074,6 +1980,7 @@ ClassMixinSet(
mixins[i] = GetClassInOuterContext(interp, mixinv[i],
"may only mix in classes");
if (mixins[i] == NULL) {
i--;
goto freeAndError;
}
if (TclOOIsReachable(oPtr->classPtr, mixins[i])) {
@@ -2191,16 +2098,19 @@ ClassSuperSet(
if (superc == 0) {
superclasses = ckrealloc(superclasses, sizeof(Class *));
superclasses[0] = oPtr->fPtr->objectCls;
superc = 1;
if (TclOOIsReachable(oPtr->fPtr->classCls, oPtr->classPtr)) {
superclasses[0] = oPtr->fPtr->classCls;
} else {
superclasses[0] = oPtr->fPtr->objectCls;
}
superc = 1;
AddRef(superclasses[0]->thisPtr);
} else {
for (i=0 ; i<superc ; i++) {
superclasses[i] = GetClassInOuterContext(interp, superv[i],
"only a class can be a superclass");
if (superclasses[i] == NULL) {
i--;
goto failedAfterAlloc;
}
for (j=0 ; j<i ; j++) {
@@ -2217,9 +2127,15 @@ ClassSuperSet(
"attempt to form circular dependency graph", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
failedAfterAlloc:
ckfree((char *) superclasses);
for (; i > 0; i--) {
TclOODecrRefCount(superclasses[i]->thisPtr);
}
ckfree(superclasses);
return TCL_ERROR;
}
/* Corresponding TclOODecrRefCount() is near the end of this
* function */
AddRef(superclasses[i]->thisPtr);
}
}
@@ -2233,6 +2149,7 @@ ClassSuperSet(
if (oPtr->classPtr->superclasses.num != 0) {
FOREACH(superPtr, oPtr->classPtr->superclasses) {
TclOORemoveFromSubclasses(oPtr->classPtr, superPtr);
TclOODecrRefCount(superPtr->thisPtr);
}
ckfree((char *) oPtr->classPtr->superclasses.list);
}
+38 -36
View File
@@ -149,8 +149,8 @@ typedef struct Object {
struct Foundation *fPtr; /* The basis for the object system. Putting
* this here allows the avoidance of quite a
* lot of hash lookups on the critical path
* for object invokation and creation. */
Tcl_Namespace *namespacePtr;/* This object's tame namespace. */
* for object invocation and creation. */
Tcl_Namespace *namespacePtr;/* This object's namespace. */
Tcl_Command command; /* Reference to this object's public
* command. */
Tcl_Command myCommand; /* Reference to this object's internal
@@ -162,12 +162,12 @@ typedef struct Object {
/* Classes mixed into this object. */
LIST_STATIC(Tcl_Obj *) filters;
/* List of filter names. */
struct Class *classPtr; /* All classes have this non-NULL; it points
* to the class structure. Everything else has
* this NULL. */
struct Class *classPtr; /* This is non-NULL for all classes, and NULL
* for everything else. It points to the class
* structure. */
int refCount; /* Number of strong references to this object.
* Note that there may be many more weak
* references; this mechanism is there to
* references; this mechanism exists to
* avoid Tcl_Preserve. */
int flags;
int creationEpoch; /* Unique value to make comparisons of objects
@@ -193,9 +193,10 @@ typedef struct Object {
* destroyed. */
#define DESTRUCTOR_CALLED 2 /* Flag to say that the destructor has been
* called. */
#define CLASS_GONE 4 /* Indicates that the class of this object has
* been deleted, and so the object should not
* attempt to remove itself from its class. */
#define CLASS_GONE 4 /* Obsolete. Indicates that the class of this
* object has been deleted, and so the object
* should not attempt to remove itself from its
* class. */
#define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of
* the class hierarchy and should be treated
* specially during teardown. */
@@ -213,6 +214,7 @@ typedef struct Object {
* other spots). */
#define FORCE_UNKNOWN 0x10000 /* States that we are *really* looking up the
* unknown method handler at that point. */
#define DONT_DELETE 0x20000 /* Inhibit deletion of this object. */
/*
* And the definition of a class. Note that every class also has an associated
@@ -222,10 +224,6 @@ typedef struct Object {
typedef struct Class {
Object *thisPtr; /* Reference to the object associated with
* this class. */
int refCount; /* Number of strong references to this class.
* Weak references are not counted; the
* purpose of this is to avoid Tcl_Preserve as
* that is quite slow. */
int flags; /* Assorted flags. */
LIST_STATIC(struct Class *) superclasses;
/* List of superclasses, used for generation
@@ -323,7 +321,7 @@ typedef struct Foundation {
} Foundation;
/*
* A call context structure is built when a method is called. They contain the
* A call context structure is built when a method is called. It contains the
* chain of method implementations that are to be invoked by a particular
* call, and the process of calling walks the chain, with the [next] command
* proceeding to the next entry in the chain.
@@ -334,7 +332,7 @@ typedef struct Foundation {
struct MInvoke {
Method *mPtr; /* Reference to the method implementation
* record. */
int isFilter; /* Whether this is a filter invokation. */
int isFilter; /* Whether this is a filter invocation. */
Class *filterDeclarer; /* What class decided to add the filter; if
* NULL, it was added by the object. */
};
@@ -487,15 +485,24 @@ MODULE_SCOPE int TclOO_Object_VarName(ClientData clientData,
MODULE_SCOPE void TclOOAddToInstances(Object *oPtr, Class *clsPtr);
MODULE_SCOPE void TclOOAddToMixinSubs(Class *subPtr, Class *mixinPtr);
MODULE_SCOPE void TclOOAddToSubclasses(Class *subPtr, Class *superPtr);
MODULE_SCOPE Class * TclOOAllocClass(Tcl_Interp *interp,
Object *useThisObj);
MODULE_SCOPE int TclNRNewObjectInstance(Tcl_Interp *interp,
Tcl_Class cls, const char *nameStr,
const char *nsNameStr, int objc,
Tcl_Obj *const *objv, int skip,
Tcl_Object *objectPtr);
MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp,
Class *classPtr,
const char *nameStr,
const char *nsNameStr);
MODULE_SCOPE int TclOODecrRefCount(Object *oPtr);
MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr);
MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr);
MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr);
MODULE_SCOPE void TclOODeleteContext(CallContext *contextPtr);
MODULE_SCOPE void TclOODeleteDescendants(Tcl_Interp *interp,
Object *oPtr);
MODULE_SCOPE void TclOODelMethodRef(Method *method);
MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr,
Tcl_Obj *methodNameObj, int flags,
@@ -521,10 +528,13 @@ MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp,
MODULE_SCOPE void TclOONewBasicMethod(Tcl_Interp *interp, Class *clsPtr,
const DeclaredClassMethod *dcm);
MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr);
MODULE_SCOPE void TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
MODULE_SCOPE void TclOORemoveFromMixinSubs(Class *subPtr,
MODULE_SCOPE void TclOOReleaseClassContents(Tcl_Interp *interp,
Object *oPtr);
MODULE_SCOPE int TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
MODULE_SCOPE int TclOORemoveFromMixins(Class *mixinPtr, Object *oPtr);
MODULE_SCOPE int TclOORemoveFromMixinSubs(Class *subPtr,
Class *mixinPtr);
MODULE_SCOPE void TclOORemoveFromSubclasses(Class *subPtr,
MODULE_SCOPE int TclOORemoveFromSubclasses(Class *subPtr,
Class *superPtr);
MODULE_SCOPE Tcl_Obj * TclOORenderCallChain(Tcl_Interp *interp,
CallChain *callPtr);
@@ -538,19 +548,22 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
#include "tclOOIntDecls.h"
/*
* Alternatives to Tcl_Preserve/Tcl_EventuallyFree/Tcl_Release.
*/
#define AddRef(ptr) ((ptr)->refCount++)
/*
* A convenience macro for iterating through the lists used in the internal
* memory management of objects. This is a bit gnarly because we want to do
* the assignment of the picked-out value only when the body test succeeds,
* but we cannot rely on the assigned value being useful, forcing us to do
* some nasty stuff with the comma operator. The compiler's optimizer should
* be able to sort it all out!
*
* memory management of objects.
* REQUIRES DECLARATION: int i;
*/
#define FOREACH(var,ary) \
for(i=0 ; (i<(ary).num?((var=(ary).list[i]),1):0) ; i++)
for(i=0 ; i<(ary).num; i++) if ((ary).list[i] == NULL) { \
continue; \
} else if (var = (ary).list[i], 1)
/*
* Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS
@@ -585,17 +598,6 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
} \
} while(0)
/*
* Alternatives to Tcl_Preserve/Tcl_EventuallyFree/Tcl_Release.
*/
#define AddRef(ptr) ((ptr)->refCount++)
#define DelRef(ptr) do { \
if ((ptr)->refCount-- <= 1) { \
ckfree((char *) (ptr)); \
} \
} while(0)
#endif /* TCL_OO_INTERNAL_H */
/*
+1
View File
@@ -1314,6 +1314,7 @@ CloneProcedureMethod(
*/
bodyObj = Tcl_DuplicateObj(pmPtr->procPtr->bodyPtr);
Tcl_GetString(bodyObj);
TclFreeIntRep(bodyObj);
/*
+35 -14
View File
@@ -2467,23 +2467,26 @@ Tcl_SetIntObj(
*
* Tcl_GetIntFromObj --
*
* Attempt to return an int from the Tcl object "objPtr". If the object
* is not already an int, an attempt will be made to convert it to one.
* Retrieve the integer value of 'objPtr'.
*
* Integer and long integer objects share the same "integer" type
* implementation. We store all integers as longs and Tcl_GetIntFromObj
* checks whether the current value of the long can be represented by an
* int.
* Value
*
* Results:
* The return value is a standard Tcl object result. If an error occurs
* during conversion or if the long integer held by the object can not be
* represented by an int, an error message is left in the interpreter's
* result unless "interp" is NULL.
* TCL_OK
*
* Side effects:
* If the object is not already an int, the conversion will free any old
* internal representation.
* Success.
*
* TCL_ERROR
*
* An error occurred during conversion or the integral value can not
* be represented as an integer (it might be too large). An error
* message is left in the interpreter's result if 'interp' is not
* NULL.
*
* Effect
*
* 'objPtr' is converted to an integer if necessary if it is not one
* already. The conversion frees any previously-existing internal
* representation.
*
*----------------------------------------------------------------------
*/
@@ -4488,6 +4491,24 @@ Tcl_RepresentationCmd(
objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
objv[1]->refCount, ptrBuffer);
/*
* This is a workaround to silence reports from `make valgrind`
* on 64-bit systems. The problem is that the test suite
* includes calling the [represenation] command on values of
* &tclDoubleType. When these values are created, the "doubleValue"
* is set, but when the "twoPtrValue" is examined, its "ptr2"
* field has never been initialized. Since [representation]
* presents the value of the ptr2 value in its output, valgrind
* alerts about the read of uninitialized memory.
*
* The general problem with [representation], that it can read
* and report uninitialized fields, is still present. This is
* just the minimal workaround to silence one particular test.
*/
if ((sizeof(void *) > 4) && objv[1]->typePtr == &tclDoubleType) {
objv[1]->internalRep.twoPtrValue.ptr2 = NULL;
}
if (objv[1]->typePtr) {
sprintf(ptrBuffer, "%p:%p",
(void *) objv[1]->internalRep.twoPtrValue.ptr1,
+1 -1
View File
@@ -111,7 +111,7 @@ Tcl_PanicVA(
__builtin_trap();
# elif defined(_WIN64)
__debugbreak();
# elif defined(_MSC_VER)
# elif defined(_MSC_VER) && defined (_M_IX86)
_asm {int 3}
# else
DebugBreak();
+8 -2
View File
@@ -841,7 +841,7 @@ TclParseBackslash(
* written there. */
{
register const char *p = src+1;
Tcl_UniChar unichar;
Tcl_UniChar unichar = 0;
int result;
int count;
char buf[TCL_UTF_MAX];
@@ -991,7 +991,13 @@ TclParseBackslash(
if (readPtr != NULL) {
*readPtr = count;
}
return Tcl_UniCharToUtf(result, dst);
count = Tcl_UniCharToUtf(result, dst);
#if TCL_UTF_MAX > 3
if (!count) {
count = Tcl_UniCharToUtf(-1, dst);
}
#endif
return count;
}
/*
+32 -33
View File
@@ -13,6 +13,7 @@
#include "tclInt.h"
#include "tclFileSystem.h"
#include <assert.h>
/*
* Prototypes for functions defined later in this file.
@@ -849,18 +850,20 @@ TclJoinPath(
int elements,
Tcl_Obj * const objv[])
{
Tcl_Obj *res;
Tcl_Obj *res = NULL;
int i;
const Tcl_Filesystem *fsPtr = NULL;
res = NULL;
assert ( elements >= 0 );
for (i = 0; i < elements; i++) {
int driveNameLength, strEltLen, length;
Tcl_PathType type;
char *strElt, *ptr;
Tcl_Obj *driveName = NULL;
Tcl_Obj *elt = objv[i];
if (elements == 0) {
return Tcl_NewObj();
}
assert ( elements > 0 );
if (elements == 2) {
Tcl_Obj *elt = objv[0];
/*
* This is a special case where we can be much more efficient, where
@@ -869,18 +872,17 @@ TclJoinPath(
* object which can be normalized more efficiently. Currently we only
* use the special case when we have exactly two elements, but we
* could expand that in the future.
*
* Bugfix [a47641a0]. TclNewFSPathObj requires first argument
* to be an absolute path. Added a check for that elt is absolute.
*
* Bugfix [a47641a0]. TclNewFSPathObj requires first argument
* to be an absolute path. Added a check for that elt is absolute.
*/
if ((i == (elements-2)) && (i == 0)
&& (elt->typePtr == &tclFsPathType)
if ((elt->typePtr == &tclFsPathType)
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
&& TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
Tcl_Obj *tailObj = objv[i+1];
Tcl_Obj *tailObj = objv[1];
Tcl_PathType type = TclGetPathType(tailObj, NULL, NULL, NULL);
type = TclGetPathType(tailObj, NULL, NULL, NULL);
if (type == TCL_PATH_RELATIVE) {
const char *str;
int len;
@@ -893,9 +895,6 @@ TclJoinPath(
* the base itself is just fine!
*/
if (res != NULL) {
TclDecrRefCount(res);
}
return elt;
}
@@ -918,9 +917,6 @@ TclJoinPath(
if ((tclPlatform != TCL_PLATFORM_WINDOWS)
|| (strchr(Tcl_GetString(elt), '\\') == NULL)) {
if (res != NULL) {
TclDecrRefCount(res);
}
if (PATHFLAGS(elt)) {
return TclNewFSPathObj(elt, str, len);
@@ -940,23 +936,28 @@ TclJoinPath(
* more general code below handle things.
*/
} else if (tclPlatform == TCL_PLATFORM_UNIX) {
if (res != NULL) {
TclDecrRefCount(res);
}
return tailObj;
} else {
const char *str = TclGetString(tailObj);
if (tclPlatform == TCL_PLATFORM_WINDOWS) {
if (strchr(str, '\\') == NULL) {
if (res != NULL) {
TclDecrRefCount(res);
}
return tailObj;
}
}
}
}
}
assert ( res == NULL );
for (i = 0; i < elements; i++) {
int driveNameLength, strEltLen, length;
Tcl_PathType type;
char *strElt, *ptr;
Tcl_Obj *driveName = NULL;
Tcl_Obj *elt = objv[i];
strElt = Tcl_GetStringFromObj(elt, &strEltLen);
driveNameLength = 0;
type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
@@ -1087,6 +1088,7 @@ TclJoinPath(
if (sep != NULL) {
separator = TclGetString(sep)[0];
Tcl_DecrRefCount(sep);
}
/* Safety check in case the VFS driver caused sharing */
if (Tcl_IsShared(res)) {
@@ -1122,9 +1124,7 @@ TclJoinPath(
Tcl_SetObjLength(res, length);
}
}
if (res == NULL) {
res = Tcl_NewObj();
}
assert ( res != NULL );
return res;
}
@@ -1811,7 +1811,6 @@ Tcl_FSGetNormalizedPath(
*/
(void) Tcl_GetStringFromObj(dir, &cwdLen);
cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
/* Normalize the combined string. */
@@ -1833,12 +1832,12 @@ Tcl_FSGetNormalizedPath(
* normalized head, we can more efficiently normalize the combined
* path by passing over only the unnormalized tail portion. When
* this is sufficient, prior developers claim this should be much
* faster. We use 'cwdLen-1' so that we are already pointing at
* faster. We use 'cwdLen' so that we are already pointing at
* the dir-separator that we know about. The normalization code
* will actually start off directly after that separator.
*/
TclFSNormalizeToUniquePath(interp, copy, cwdLen-1);
TclFSNormalizeToUniquePath(interp, copy, cwdLen);
}
/* Now we need to construct the new path object. */
+7 -1
View File
@@ -668,7 +668,13 @@ TclCreatePipeline(
if (*p == '>') {
p++;
atOK = 0;
flags = O_WRONLY | O_CREAT;
/*
* Note that the O_APPEND flag only has an effect on POSIX
* platforms. On Windows, we just have to carry on regardless.
*/
flags = O_WRONLY | O_CREAT | O_APPEND;
}
if (errorClose != 0) {
errorClose = 0;
+444 -297
View File
@@ -49,6 +49,18 @@ typedef struct Package {
const void *clientData; /* Client data. */
} Package;
typedef struct Require {
void * clientDataPtr;
const char *name;
Package *pkgPtr;
char *versionToProvide;
} Require;
typedef struct RequireProcArgs {
const char *name;
void *clientDataPtr;
} RequireProcArgs;
/*
* Prototypes for functions defined in this file:
*/
@@ -69,9 +81,15 @@ static void AddRequirementsToResult(Tcl_Interp *interp, int reqc,
static void AddRequirementsToDString(Tcl_DString *dstring,
int reqc, Tcl_Obj *const reqv[]);
static Package * FindPackage(Tcl_Interp *interp, const char *name);
static const char * PkgRequireCore(Tcl_Interp *interp, const char *name,
int reqc, Tcl_Obj *const reqv[],
void *clientDataPtr);
static int PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result);
static int PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result);
static int PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result);
static int PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result);
static int PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result);
static int TclNRPkgRequireProc(ClientData clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]);
static int SelectPackage(ClientData data[], Tcl_Interp *interp, int result);
static int SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result);
static int TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result);
/*
* Helper macros.
@@ -299,7 +317,10 @@ Tcl_PkgRequireEx(
*/
if (version == NULL) {
result = PkgRequireCore(interp, name, 0, NULL, clientDataPtr);
if (Tcl_PkgRequireProc(interp, name, 0, NULL, clientDataPtr) == TCL_OK) {
result = Tcl_GetStringResult(interp);
Tcl_ResetResult(interp);
}
} else {
if (exact && TCL_OK
!= CheckVersionAndConvert(interp, version, NULL, NULL)) {
@@ -310,10 +331,12 @@ Tcl_PkgRequireEx(
Tcl_AppendStringsToObj(ov, "-", version, NULL);
}
Tcl_IncrRefCount(ov);
result = PkgRequireCore(interp, name, 1, &ov, clientDataPtr);
if (Tcl_PkgRequireProc(interp, name, 1, &ov, clientDataPtr) == TCL_OK) {
result = Tcl_GetStringResult(interp);
Tcl_ResetResult(interp);
}
TclDecrRefCount(ov);
}
return result;
}
@@ -328,306 +351,130 @@ Tcl_PkgRequireProc(
* available. */
void *clientDataPtr)
{
const char *result =
PkgRequireCore(interp, name, reqc, reqv, clientDataPtr);
RequireProcArgs args;
args.name = name;
args.clientDataPtr = clientDataPtr;
return Tcl_NRCallObjProc(interp, TclNRPkgRequireProc, (void *)&args, reqc, reqv);
}
if (result == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1));
static int
TclNRPkgRequireProc(
ClientData clientData,
Tcl_Interp *interp,
int reqc,
Tcl_Obj *const reqv[]) {
RequireProcArgs *args = clientData;
Tcl_NRAddCallback(interp, PkgRequireCore, (void *)args->name, INT2PTR(reqc), (void *)reqv, args->clientDataPtr);
return TCL_OK;
}
static const char *
PkgRequireCore(
Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
const char *name, /* Name of desired package. */
int reqc, /* Requirements constraining the desired
* version. */
Tcl_Obj *const reqv[], /* 0 means to use the latest version
* available. */
void *clientDataPtr)
static int
PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result)
{
Interp *iPtr = (Interp *) interp;
Package *pkgPtr;
PkgAvail *availPtr, *bestPtr, *bestStablePtr;
char *availVersion, *bestVersion;
/* Internal rep. of versions */
int availStable, code, satisfies, pass;
char *script, *pkgVersionI;
const char *name = data[0];
int reqc = PTR2INT(data[1]);
Tcl_Obj *const *reqv = data[2];
int code = CheckAllRequirements(interp, reqc, reqv);
Require *reqPtr;
if (code != TCL_OK) {
return code;
}
reqPtr = ckalloc(sizeof(Require));
Tcl_NRAddCallback(interp, PkgRequireCoreCleanup, reqPtr, NULL, NULL, NULL);
reqPtr->clientDataPtr = data[3];
reqPtr->name = name;
reqPtr->pkgPtr = FindPackage(interp, name);
if (reqPtr->pkgPtr->version == NULL) {
Tcl_NRAddCallback(interp, SelectPackage, reqPtr, INT2PTR(reqc), (void *)reqv, PkgRequireCoreStep1);
} else {
Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
}
return TCL_OK;
}
static int
PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result) {
Tcl_DString command;
char *script;
Require *reqPtr = data[0];
int reqc = PTR2INT(data[1]);
Tcl_Obj **const reqv = data[2];
const char *name = reqPtr->name /* Name of desired package. */;
if (reqPtr->pkgPtr->version == NULL) {
/*
* The package is not in the database. If there is a "package unknown"
* command, invoke it.
*/
if (TCL_OK != CheckAllRequirements(interp, reqc, reqv)) {
return NULL;
script = ((Interp *) interp)->packageUnknown;
if (script == NULL) {
Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
} else {
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command, script, -1);
Tcl_DStringAppendElement(&command, name);
AddRequirementsToDString(&command, reqc, reqv);
Tcl_NRAddCallback(interp, PkgRequireCoreStep2, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
Tcl_NREvalObj(interp,
Tcl_NewStringObj(Tcl_DStringValue(&command), Tcl_DStringLength(&command)),
TCL_EVAL_GLOBAL
);
Tcl_DStringFree(&command);
}
return TCL_OK;
} else {
Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
}
return TCL_OK;
}
/*
* It can take up to three passes to find the package: one pass to run the
* "package unknown" script, one to run the "package ifneeded" script for
* a specific version, and a final pass to lookup the package loaded by
* the "package ifneeded" script.
*/
for (pass=1 ;; pass++) {
pkgPtr = FindPackage(interp, name);
if (pkgPtr->version != NULL) {
break;
}
/*
* Check whether we're already attempting to load some version of this
* package (circular dependency detection).
*/
if (pkgPtr->clientData != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"circular package dependency:"
" attempt to provide %s %s requires %s",
name, (char *) pkgPtr->clientData, name));
AddRequirementsToResult(interp, reqc, reqv);
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL);
return NULL;
}
/*
* The package isn't yet present. Search the list of available
* versions and invoke the script for the best available version. We
* are actually locating the best, and the best stable version. One of
* them is then chosen based on the selection mode.
*/
bestPtr = NULL;
bestStablePtr = NULL;
bestVersion = NULL;
for (availPtr = pkgPtr->availPtr; availPtr != NULL;
availPtr = availPtr->nextPtr) {
if (CheckVersionAndConvert(interp, availPtr->version,
&availVersion, &availStable) != TCL_OK) {
/*
* The provided version number has invalid syntax. This
* should not happen. This should have been caught by the
* 'package ifneeded' registering the package.
*/
continue;
}
if (bestPtr != NULL) {
int res = CompareVersions(availVersion, bestVersion, NULL);
/*
* Note: Use internal reps!
*/
if (res <= 0) {
/*
* The version of the package sought is not as good as the
* currently selected version. Ignore it.
*/
ckfree(availVersion);
availVersion = NULL;
continue;
}
}
/*
* We have found a version which is better than our max.
*/
if (reqc > 0) {
/* Check satisfaction of requirements. */
satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv);
if (!satisfies) {
ckfree(availVersion);
availVersion = NULL;
continue;
}
}
bestPtr = availPtr;
if (bestVersion != NULL) {
ckfree(bestVersion);
}
bestVersion = availVersion;
/*
* If this new best version is stable then it also has to be
* better than the max stable version found so far.
*/
if (availStable) {
bestStablePtr = availPtr;
}
}
if (bestVersion != NULL) {
ckfree(bestVersion);
}
/*
* Now choose a version among the two best. For 'latest' we simply
* take (actually keep) the best. For 'stable' we take the best
* stable, if there is any, or the best if there is nothing stable.
*/
if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
&& (bestStablePtr != NULL)) {
bestPtr = bestStablePtr;
}
if (bestPtr != NULL) {
/*
* We found an ifneeded script for the package. Be careful while
* executing it: this could cause reentrancy, so (a) protect the
* script itself from deletion and (b) don't assume that bestPtr
* will still exist when the script completes.
*/
char *versionToProvide = bestPtr->version;
script = bestPtr->script;
pkgPtr->clientData = versionToProvide;
Tcl_Preserve(script);
Tcl_Preserve(versionToProvide);
code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);
Tcl_Release(script);
pkgPtr = FindPackage(interp, name);
if (code == TCL_OK) {
Tcl_ResetResult(interp);
if (pkgPtr->version == NULL) {
code = TCL_ERROR;
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"attempt to provide package %s %s failed:"
" no version of package %s provided",
name, versionToProvide, name));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED",
NULL);
} else {
char *pvi, *vi;
if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi,
NULL) != TCL_OK) {
code = TCL_ERROR;
} else if (CheckVersionAndConvert(interp,
versionToProvide, &vi, NULL) != TCL_OK) {
ckfree(pvi);
code = TCL_ERROR;
} else {
int res = CompareVersions(pvi, vi, NULL);
ckfree(pvi);
ckfree(vi);
if (res != 0) {
code = TCL_ERROR;
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"attempt to provide package %s %s failed:"
" package %s %s provided instead",
name, versionToProvide,
name, pkgPtr->version));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE",
"WRONGPROVIDE", NULL);
}
}
}
} else if (code != TCL_ERROR) {
Tcl_Obj *codePtr = Tcl_NewIntObj(code);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"attempt to provide package %s %s failed:"
" bad return code: %s",
name, versionToProvide, TclGetString(codePtr)));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
TclDecrRefCount(codePtr);
code = TCL_ERROR;
}
if (code == TCL_ERROR) {
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (\"package ifneeded %s %s\" script)",
name, versionToProvide));
}
Tcl_Release(versionToProvide);
if (code != TCL_OK) {
/*
* Take a non-TCL_OK code from the script as an indication the
* package wasn't loaded properly, so the package system
* should not remember an improper load.
*
* This is consistent with our returning NULL. If we're not
* willing to tell our caller we got a particular version, we
* shouldn't store that version for telling future callers
* either.
*/
if (pkgPtr->version != NULL) {
ckfree(pkgPtr->version);
pkgPtr->version = NULL;
}
pkgPtr->clientData = NULL;
return NULL;
}
break;
}
/*
* The package is not in the database. If there is a "package unknown"
* command, invoke it (but only on the first pass; after that, we
* should not get here in the first place).
*/
if (pass > 1) {
break;
}
script = ((Interp *) interp)->packageUnknown;
if (script != NULL) {
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command, script, -1);
Tcl_DStringAppendElement(&command, name);
AddRequirementsToDString(&command, reqc, reqv);
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
Tcl_DStringFree(&command);
if ((code != TCL_OK) && (code != TCL_ERROR)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad return code: %d", code));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
code = TCL_ERROR;
}
if (code == TCL_ERROR) {
Tcl_AddErrorInfo(interp,
"\n (\"package unknown\" script)");
return NULL;
}
Tcl_ResetResult(interp);
}
static int
PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result) {
Require *reqPtr = data[0];
int reqc = PTR2INT(data[1]);
Tcl_Obj **const reqv = data[2];
const char *name = reqPtr->name /* Name of desired package. */;
if ((result != TCL_OK) && (result != TCL_ERROR)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad return code: %d", result));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
result = TCL_ERROR;
}
if (result == TCL_ERROR) {
Tcl_AddErrorInfo(interp,
"\n (\"package unknown\" script)");
return result;
}
Tcl_ResetResult(interp);
/* pkgPtr may now be invalid, so refresh it. */
reqPtr->pkgPtr = FindPackage(interp, name);
Tcl_NRAddCallback(interp, SelectPackage, reqPtr, INT2PTR(reqc), (void *)reqv, PkgRequireCoreFinal);
return TCL_OK;
}
if (pkgPtr->version == NULL) {
static int
PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result) {
Require *reqPtr = data[0];
int reqc = PTR2INT(data[1]), satisfies;
Tcl_Obj **const reqv = data[2];
char *pkgVersionI;
void *clientDataPtr = reqPtr->clientDataPtr;
const char *name = reqPtr->name /* Name of desired package. */;
if (reqPtr->pkgPtr->version == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't find package %s", name));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL);
AddRequirementsToResult(interp, reqc, reqv);
return NULL;
return TCL_ERROR;
}
/*
* At this point we know that the package is present. Make sure that the
* provided version meets the current requirements.
* Ensure that the provided version meets the current requirements.
*/
if (reqc != 0) {
CheckVersionAndConvert(interp, pkgPtr->version, &pkgVersionI, NULL);
CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pkgVersionI, NULL);
satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv);
ckfree(pkgVersionI);
@@ -635,20 +482,283 @@ PkgRequireCore(
if (!satisfies) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"version conflict for package \"%s\": have %s, need",
name, pkgPtr->version));
name, reqPtr->pkgPtr->version));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT",
NULL);
AddRequirementsToResult(interp, reqc, reqv);
return NULL;
return TCL_ERROR;
}
}
if (clientDataPtr) {
const void **ptr = (const void **) clientDataPtr;
*ptr = pkgPtr->clientData;
*ptr = reqPtr->pkgPtr->clientData;
}
return pkgPtr->version;
Tcl_SetObjResult(interp, Tcl_NewStringObj(reqPtr->pkgPtr->version, -1));
return TCL_OK;
}
static int
PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result) {
ckfree(data[0]);
return result;
}
static int
SelectPackage(ClientData data[], Tcl_Interp *interp, int result) {
PkgAvail *availPtr, *bestPtr, *bestStablePtr;
char *availVersion, *bestVersion, *bestStableVersion;
/* Internal rep. of versions */
int availStable, satisfies;
Require *reqPtr = data[0];
int reqc = PTR2INT(data[1]);
Tcl_Obj **const reqv = data[2];
const char *name = reqPtr->name;
Package *pkgPtr = reqPtr->pkgPtr;
Interp *iPtr = (Interp *) interp;
/*
* Check whether we're already attempting to load some version of this
* package (circular dependency detection).
*/
if (pkgPtr->clientData != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"circular package dependency:"
" attempt to provide %s %s requires %s",
name, (char *) pkgPtr->clientData, name));
AddRequirementsToResult(interp, reqc, reqv);
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL);
return TCL_ERROR;
}
/*
* The package isn't yet present. Search the list of available
* versions and invoke the script for the best available version. We
* are actually locating the best, and the best stable version. One of
* them is then chosen based on the selection mode.
*/
bestPtr = NULL;
bestStablePtr = NULL;
bestVersion = NULL;
bestStableVersion = NULL;
for (availPtr = pkgPtr->availPtr; availPtr != NULL;
availPtr = availPtr->nextPtr) {
if (CheckVersionAndConvert(interp, availPtr->version,
&availVersion, &availStable) != TCL_OK) {
/*
* The provided version number has invalid syntax. This
* should not happen. This should have been caught by the
* 'package ifneeded' registering the package.
*/
continue;
}
/* Check satisfaction of requirements before considering the current version further. */
if (reqc > 0) {
satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv);
if (!satisfies) {
ckfree(availVersion);
availVersion = NULL;
continue;
}
}
if (bestPtr != NULL) {
int res = CompareVersions(availVersion, bestVersion, NULL);
/*
* Note: Used internal reps in the comparison!
*/
if (res > 0) {
/*
* The version of the package sought is better than the
* currently selected version.
*/
ckfree(bestVersion);
bestVersion = NULL;
goto newbest;
}
} else {
newbest:
/* We have found a version which is better than our max. */
bestPtr = availPtr;
CheckVersionAndConvert(interp, bestPtr->version, &bestVersion, NULL);
}
if (!availStable) {
ckfree(availVersion);
availVersion = NULL;
continue;
}
if (bestStablePtr != NULL) {
int res = CompareVersions(availVersion, bestStableVersion, NULL);
/*
* Note: Used internal reps in the comparison!
*/
if (res > 0) {
/*
* This stable version of the package sought is better
* than the currently selected stable version.
*/
ckfree(bestStableVersion);
bestStableVersion = NULL;
goto newstable;
}
} else {
newstable:
/* We have found a stable version which is better than our max stable. */
bestStablePtr = availPtr;
CheckVersionAndConvert(interp, bestStablePtr->version, &bestStableVersion, NULL);
}
ckfree(availVersion);
availVersion = NULL;
} /* end for */
/*
* Clean up memorized internal reps, if any.
*/
if (bestVersion != NULL) {
ckfree(bestVersion);
bestVersion = NULL;
}
if (bestStableVersion != NULL) {
ckfree(bestStableVersion);
bestStableVersion = NULL;
}
/*
* Now choose a version among the two best. For 'latest' we simply
* take (actually keep) the best. For 'stable' we take the best
* stable, if there is any, or the best if there is nothing stable.
*/
if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
&& (bestStablePtr != NULL)) {
bestPtr = bestStablePtr;
}
if (bestPtr == NULL) {
Tcl_NRAddCallback(interp, data[3], reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
} else {
/*
* We found an ifneeded script for the package. Be careful while
* executing it: this could cause reentrancy, so (a) protect the
* script itself from deletion and (b) don't assume that bestPtr
* will still exist when the script completes.
*/
char *versionToProvide = bestPtr->version;
pkgPtr->clientData = versionToProvide;
Tcl_Preserve(versionToProvide);
reqPtr->versionToProvide = versionToProvide;
Tcl_NRAddCallback(interp, SelectPackageFinal, reqPtr, INT2PTR(reqc), (void *)reqv, data[3]);
Tcl_NREvalObj(interp, Tcl_NewStringObj(bestPtr->script, -1), TCL_EVAL_GLOBAL);
}
return TCL_OK;
}
static int
SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result) {
Require *reqPtr = data[0];
int reqc = PTR2INT(data[1]);
Tcl_Obj **const reqv = data[2];
const char *name = reqPtr->name;
char *versionToProvide = reqPtr->versionToProvide;
reqPtr->pkgPtr = FindPackage(interp, name);
if (result == TCL_OK) {
Tcl_ResetResult(interp);
if (reqPtr->pkgPtr->version == NULL) {
result = TCL_ERROR;
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"attempt to provide package %s %s failed:"
" no version of package %s provided",
name, versionToProvide, name));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED",
NULL);
} else {
char *pvi, *vi;
if (CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pvi,
NULL) != TCL_OK) {
result = TCL_ERROR;
} else if (CheckVersionAndConvert(interp,
versionToProvide, &vi, NULL) != TCL_OK) {
ckfree(pvi);
result = TCL_ERROR;
} else {
int res = CompareVersions(pvi, vi, NULL);
ckfree(pvi);
ckfree(vi);
if (res != 0) {
result = TCL_ERROR;
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"attempt to provide package %s %s failed:"
" package %s %s provided instead",
name, versionToProvide,
name, reqPtr->pkgPtr->version));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE",
"WRONGPROVIDE", NULL);
}
}
}
} else if (result != TCL_ERROR) {
Tcl_Obj *codePtr = Tcl_NewIntObj(result);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"attempt to provide package %s %s failed:"
" bad return code: %s",
name, versionToProvide, TclGetString(codePtr)));
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
TclDecrRefCount(codePtr);
result = TCL_ERROR;
}
if (result == TCL_ERROR) {
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (\"package ifneeded %s %s\" script)",
name, versionToProvide));
}
Tcl_Release(versionToProvide);
if (result != TCL_OK) {
/*
* Take a non-TCL_OK code from the script as an indication the
* package wasn't loaded properly, so the package system
* should not remember an improper load.
*
* This is consistent with our returning NULL. If we're not
* willing to tell our caller we got a particular version, we
* shouldn't store that version for telling future callers
* either.
*/
if (reqPtr->pkgPtr->version != NULL) {
ckfree(reqPtr->pkgPtr->version);
reqPtr->pkgPtr->version = NULL;
}
reqPtr->pkgPtr->clientData = NULL;
return result;
}
Tcl_NRAddCallback(interp, data[3], reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
return TCL_OK;
}
/*
@@ -754,10 +864,19 @@ Tcl_PkgPresentEx(
*
*----------------------------------------------------------------------
*/
int
Tcl_PackageObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
return Tcl_NRCallObjProc(interp, TclNRPackageObjCmd, NULL, objc, objv);
}
/* ARGSUSED */
int
Tcl_PackageObjCmd(
TclNRPackageObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
@@ -774,7 +893,7 @@ Tcl_PackageObjCmd(
PKG_VSATISFIES
};
Interp *iPtr = (Interp *) interp;
int optionIndex, exact, i, satisfies;
int optionIndex, exact, i, newobjc, satisfies;
PkgAvail *availPtr, *prevPtr;
Package *pkgPtr;
Tcl_HashEntry *hPtr;
@@ -783,6 +902,7 @@ Tcl_PackageObjCmd(
const char *version;
const char *argv2, *argv3, *argv4;
char *iva = NULL, *ivb = NULL;
Tcl_Obj *objvListPtr, **newObjvPtr;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
@@ -989,7 +1109,6 @@ Tcl_PackageObjCmd(
argv2 = TclGetString(objv[2]);
if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
Tcl_Obj *ov;
int res;
if (objc != 5) {
goto requireSyntax;
@@ -1009,17 +1128,38 @@ Tcl_PackageObjCmd(
Tcl_AppendStringsToObj(ov, "-", version, NULL);
version = NULL;
argv3 = TclGetString(objv[3]);
Tcl_IncrRefCount(objv[3]);
Tcl_IncrRefCount(ov);
res = Tcl_PkgRequireProc(interp, argv3, 1, &ov, NULL);
TclDecrRefCount(ov);
return res;
objvListPtr = Tcl_NewListObj(0, NULL);
Tcl_IncrRefCount(objvListPtr);
Tcl_ListObjAppendElement(interp, objvListPtr, ov);
Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[3], objvListPtr, NULL, NULL);
Tcl_NRAddCallback(interp, PkgRequireCore, (void *)argv3, INT2PTR(newobjc), newObjvPtr, NULL);
return TCL_OK;
} else {
int i, newobjc = objc-3;
Tcl_Obj *const *newobjv = objv + 3;
if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
return TCL_ERROR;
}
objvListPtr = Tcl_NewListObj(0, NULL);
Tcl_IncrRefCount(objvListPtr);
Tcl_IncrRefCount(objv[2]);
for (i = 0; i < newobjc; i++) {
return Tcl_PkgRequireProc(interp, argv2, objc-3, objv+3, NULL);
/*
* Tcl_Obj structures may have come from another interpreter,
* so duplicate them.
*/
Tcl_ListObjAppendElement(interp, objvListPtr, Tcl_DuplicateObj(newobjv[i]));
}
Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[2], objvListPtr, NULL, NULL);
Tcl_NRAddCallback(interp, PkgRequireCore, (void *)argv2, INT2PTR(newobjc), newObjvPtr, NULL);
return TCL_OK;
}
break;
case PKG_UNKNOWN: {
@@ -1159,6 +1299,13 @@ Tcl_PackageObjCmd(
}
return TCL_OK;
}
static int
TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result) {
TclDecrRefCount((Tcl_Obj *)data[0]);
TclDecrRefCount((Tcl_Obj *)data[1]);
return result;
}
/*
*----------------------------------------------------------------------
+71 -105
View File
@@ -124,11 +124,10 @@ Tcl_ProcObjCmd(
{
register Interp *iPtr = (Interp *) interp;
Proc *procPtr;
const char *fullName;
const char *procName, *procArgs, *procBody;
const char *procName;
const char *simpleName, *procArgs, *procBody;
Namespace *nsPtr, *altNsPtr, *cxtNsPtr;
Tcl_Command cmd;
Tcl_DString ds;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "name args body");
@@ -141,29 +140,21 @@ Tcl_ProcObjCmd(
* namespace.
*/
fullName = TclGetString(objv[1]);
TclGetNamespaceForQualName(interp, fullName, NULL, 0,
&nsPtr, &altNsPtr, &cxtNsPtr, &procName);
procName = TclGetString(objv[1]);
TclGetNamespaceForQualName(interp, procName, NULL, 0,
&nsPtr, &altNsPtr, &cxtNsPtr, &simpleName);
if (nsPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\": unknown namespace",
fullName));
procName));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
return TCL_ERROR;
}
if (procName == NULL) {
if (simpleName == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\": bad procedure name",
fullName));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
return TCL_ERROR;
}
if ((nsPtr != iPtr->globalNsPtr)
&& (procName != NULL) && (procName[0] == ':')) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\" in non-global namespace with"
" name starting with \":\"", procName));
procName));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
return TCL_ERROR;
}
@@ -172,31 +163,16 @@ Tcl_ProcObjCmd(
* Create the data structure to represent the procedure.
*/
if (TclCreateProc(interp, nsPtr, procName, objv[2], objv[3],
if (TclCreateProc(interp, nsPtr, simpleName, objv[2], objv[3],
&procPtr) != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (creating proc \"");
Tcl_AddErrorInfo(interp, procName);
Tcl_AddErrorInfo(interp, simpleName);
Tcl_AddErrorInfo(interp, "\")");
return TCL_ERROR;
}
/*
* Now create a command for the procedure. This will initially be in the
* current namespace unless the procedure's name included namespace
* qualifiers. To create the new command in the right namespace, we
* generate a fully qualified name for it.
*/
Tcl_DStringInit(&ds);
if (nsPtr != iPtr->globalNsPtr) {
Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
TclDStringAppendLiteral(&ds, "::");
}
Tcl_DStringAppend(&ds, procName, -1);
cmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds), TclObjInterpProc,
TclNRInterpProc, procPtr, TclProcDeleteProc);
Tcl_DStringFree(&ds);
cmd = TclNRCreateCommandInNs(interp, simpleName, (Tcl_Namespace *) nsPtr,
TclObjInterpProc, TclNRInterpProc, procPtr, TclProcDeleteProc);
/*
* Now initialize the new procedure's cmdPtr field. This will be used
@@ -393,13 +369,13 @@ TclCreateProc(
Proc **procPtrPtr) /* Returns: pointer to proc data. */
{
Interp *iPtr = (Interp *) interp;
const char **argArray = NULL;
register Proc *procPtr;
int i, length, result, numArgs;
const char *args, *bytes, *p;
int i, result, numArgs, plen;
const char *bytes, *argname, *argnamei;
char argnamelast;
register CompiledLocal *localPtr = NULL;
Tcl_Obj *defPtr;
Tcl_Obj *defPtr, *errorObj, **argArray;
int precompiled = 0;
if (bodyPtr->typePtr == &tclProcBodyType) {
@@ -436,6 +412,7 @@ TclCreateProc(
*/
if (Tcl_IsShared(bodyPtr)) {
int length;
Tcl_Obj *sharedBodyPtr = bodyPtr;
bytes = TclGetStringFromObj(bodyPtr, &length);
@@ -473,12 +450,9 @@ TclCreateProc(
* argument specifier. If the body is precompiled, processing is limited
* to checking that the parsed argument is consistent with the one stored
* in the Proc.
*
* THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULS.
*/
args = TclGetStringFromObj(argsPtr, &length);
result = Tcl_SplitList(interp, args, &numArgs, &argArray);
result = Tcl_ListObjGetElements(interp , argsPtr ,&numArgs ,&argArray);
if (result != TCL_OK) {
goto procError;
}
@@ -501,28 +475,28 @@ TclCreateProc(
for (i = 0; i < numArgs; i++) {
int fieldCount, nameLength, valueLength;
const char **fieldValues;
Tcl_Obj **fieldValues;
/*
* Now divide the specifier up into name and default.
*/
result = Tcl_SplitList(interp, argArray[i], &fieldCount,
result = Tcl_ListObjGetElements(interp, argArray[i], &fieldCount,
&fieldValues);
if (result != TCL_OK) {
goto procError;
}
if (fieldCount > 2) {
ckfree(fieldValues);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"too many fields in argument specifier \"%s\"",
argArray[i]));
errorObj = Tcl_NewStringObj(
"too many fields in argument specifier \"", -1);
Tcl_AppendObjToObj(errorObj, argArray[i]);
Tcl_AppendToObj(errorObj, "\"", -1);
Tcl_SetObjResult(interp, errorObj);
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
"FORMALARGUMENTFORMAT", NULL);
goto procError;
}
if ((fieldCount == 0) || (*fieldValues[0] == 0)) {
ckfree(fieldValues);
if ((fieldCount == 0) || (fieldValues[0]->length == 0)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"argument with no name", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
@@ -530,9 +504,11 @@ TclCreateProc(
goto procError;
}
nameLength = strlen(fieldValues[0]);
argname = Tcl_GetStringFromObj(fieldValues[0], &plen);
nameLength = Tcl_NumUtfChars(argname, plen);
if (fieldCount == 2) {
valueLength = strlen(fieldValues[1]);
const char * value = TclGetString(fieldValues[1]);
valueLength = Tcl_NumUtfChars(value, fieldValues[1]->length);
} else {
valueLength = 0;
}
@@ -541,33 +517,28 @@ TclCreateProc(
* Check that the formal parameter name is a scalar.
*/
p = fieldValues[0];
while (*p != '\0') {
if (*p == '(') {
const char *q = p;
do {
q++;
} while (*q != '\0');
q--;
if (*q == ')') { /* We have an array element. */
argnamei = argname;
argnamelast = argname[plen-1];
while (plen--) {
if (argnamei[0] == '(') {
if (argnamelast == ')') { /* We have an array element. */
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"formal parameter \"%s\" is an array element",
fieldValues[0]));
ckfree(fieldValues);
Tcl_GetString(fieldValues[0])));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
"FORMALARGUMENTFORMAT", NULL);
goto procError;
}
} else if ((*p == ':') && (*(p+1) == ':')) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"formal parameter \"%s\" is not a simple name",
fieldValues[0]));
ckfree(fieldValues);
} else if ((argnamei[0] == ':') && (argnamei[1] == ':')) {
errorObj = Tcl_NewStringObj("formal parameter \"", -1);
Tcl_AppendObjToObj(errorObj, fieldValues[0]);
Tcl_AppendToObj(errorObj, "\" is not a simple name", -1);
Tcl_SetObjResult(interp, errorObj);
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
"FORMALARGUMENTFORMAT", NULL);
goto procError;
}
p++;
argnamei = Tcl_UtfNext(argnamei);
}
if (precompiled) {
@@ -583,7 +554,7 @@ TclCreateProc(
*/
if ((localPtr->nameLength != nameLength)
|| (strcmp(localPtr->name, fieldValues[0]))
|| (Tcl_UtfNcmp(localPtr->name, argname, nameLength))
|| (localPtr->frameIndex != i)
|| !(localPtr->flags & VAR_ARGUMENT)
|| (localPtr->defValuePtr == NULL && fieldCount == 2)
@@ -591,7 +562,6 @@ TclCreateProc(
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"procedure \"%s\": formal parameter %d is "
"inconsistent with precompiled body", procName, i));
ckfree(fieldValues);
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
"BYTECODELIES", NULL);
goto procError;
@@ -607,12 +577,13 @@ TclCreateProc(
&tmpLength);
if ((valueLength != tmpLength) ||
strncmp(fieldValues[1], tmpPtr, (size_t) tmpLength)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"procedure \"%s\": formal parameter \"%s\" has "
"default value inconsistent with precompiled body",
procName, fieldValues[0]));
ckfree(fieldValues);
Tcl_UtfNcmp(Tcl_GetString(fieldValues[1]), tmpPtr, tmpLength)) {
errorObj = Tcl_ObjPrintf(
"procedure \"%s\": formal parameter \"" ,procName);
Tcl_AppendObjToObj(errorObj, fieldValues[0]);
Tcl_AppendToObj(errorObj, "\" has "
"default value inconsistent with precompiled body", -1);
Tcl_SetObjResult(interp, errorObj);
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
"BYTECODELIES", NULL);
goto procError;
@@ -632,7 +603,7 @@ TclCreateProc(
* local variables for the argument.
*/
localPtr = ckalloc(TclOffset(CompiledLocal, name) + nameLength+1);
localPtr = ckalloc(TclOffset(CompiledLocal, name) + fieldValues[0]->length +1);
if (procPtr->firstLocalPtr == NULL) {
procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
} else {
@@ -646,13 +617,12 @@ TclCreateProc(
localPtr->resolveInfo = NULL;
if (fieldCount == 2) {
localPtr->defValuePtr =
Tcl_NewStringObj(fieldValues[1], valueLength);
localPtr->defValuePtr = fieldValues[1];
Tcl_IncrRefCount(localPtr->defValuePtr);
} else {
localPtr->defValuePtr = NULL;
}
memcpy(localPtr->name, fieldValues[0], nameLength + 1);
memcpy(localPtr->name, argname, fieldValues[0]->length + 1);
if ((i == numArgs - 1)
&& (localPtr->nameLength == 4)
&& (localPtr->name[0] == 'a')
@@ -660,12 +630,9 @@ TclCreateProc(
localPtr->flags |= VAR_IS_ARGS;
}
}
ckfree(fieldValues);
}
*procPtrPtr = procPtr;
ckfree(argArray);
return TCL_OK;
procError:
@@ -686,9 +653,6 @@ TclCreateProc(
}
ckfree(procPtr);
}
if (argArray != NULL) {
ckfree(argArray);
}
return TCL_ERROR;
}
@@ -1071,7 +1035,6 @@ ProcWrongNumArgs(
{
CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
register Proc *procPtr = framePtr->procPtr;
register Var *defPtr;
int localCt = procPtr->numCompiledLocals, numArgs, i;
Tcl_Obj **desiredObjs;
const char *final = NULL;
@@ -1095,23 +1058,26 @@ ProcWrongNumArgs(
}
Tcl_IncrRefCount(desiredObjs[0]);
defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt);
for (i=1 ; i<=numArgs ; i++, defPtr++) {
Tcl_Obj *argObj;
Tcl_Obj *namePtr = localName(framePtr, i-1);
if (localCt > 0) {
register Var *defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt);
if (defPtr->value.objPtr != NULL) {
TclNewObj(argObj);
Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", NULL);
} else if (defPtr->flags & VAR_IS_ARGS) {
numArgs--;
final = "?arg ...?";
break;
} else {
argObj = namePtr;
Tcl_IncrRefCount(namePtr);
for (i=1 ; i<=numArgs ; i++, defPtr++) {
Tcl_Obj *argObj;
Tcl_Obj *namePtr = localName(framePtr, i-1);
if (defPtr->value.objPtr != NULL) {
TclNewObj(argObj);
Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", NULL);
} else if (defPtr->flags & VAR_IS_ARGS) {
numArgs--;
final = "?arg ...?";
break;
} else {
argObj = namePtr;
Tcl_IncrRefCount(namePtr);
}
desiredObjs[i] = argObj;
}
desiredObjs[i] = argObj;
}
Tcl_ResetResult(interp);
+11 -4
View File
@@ -502,10 +502,17 @@ Tcl_RegExpMatchObj(
{
Tcl_RegExp re;
re = Tcl_GetRegExpFromObj(interp, patternObj,
TCL_REG_ADVANCED | TCL_REG_NOSUB);
if (re == NULL) {
return -1;
/*
* For performance reasons, first try compiling the RE without support for
* subexpressions. On failure, try again without TCL_REG_NOSUB in case the
* RE has backreferences in it. Closely related to [Bug 1366683]. If this
* still fails, an error message will be left in the interpreter.
*/
if (!(re = Tcl_GetRegExpFromObj(interp, patternObj,
TCL_REG_ADVANCED | TCL_REG_NOSUB))
&& !(re = Tcl_GetRegExpFromObj(interp, patternObj, TCL_REG_ADVANCED))) {
return -1;
}
return Tcl_RegExpExecObj(interp, re, textObj, 0 /* offset */,
0 /* nmatches */, 0 /* flags */);
+13 -5
View File
@@ -72,7 +72,7 @@ BuildCharSet(
CharSet *cset,
const char *format) /* Points to first char of set. */
{
Tcl_UniChar ch, start;
Tcl_UniChar ch = 0, start;
int offset, nranges;
const char *end;
@@ -257,7 +257,7 @@ ValidateFormat(
{
int gotXpg, gotSequential, value, i, flags;
char *end;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
int objIndex, xpgSize, nspace = numVars;
int *nassign = TclStackAlloc(interp, nspace * sizeof(int));
char buf[TCL_UTF_MAX+1];
@@ -582,7 +582,7 @@ Tcl_ScanObjCmd(
char op = 0;
int width, underflow = 0;
Tcl_WideInt wideValue;
Tcl_UniChar ch, sch;
Tcl_UniChar ch = 0, sch = 0;
Tcl_Obj **objs = NULL, *objPtr = NULL;
int flags;
char buf[513]; /* Temporary buffer to hold scanned number
@@ -885,9 +885,17 @@ Tcl_ScanObjCmd(
* Scan a single Unicode character.
*/
string += TclUtfToUniChar(string, &sch);
offset = TclUtfToUniChar(string, &sch);
i = (int)sch;
#if TCL_UTF_MAX == 4
if (!offset) {
offset = Tcl_UtfToUniChar(string, &sch);
i = (((i<<10) & 0x0FFC00) + 0x10000) + (sch & 0x3FF);
}
#endif
string += offset;
if (!(flags & SCAN_SUPPRESS)) {
objPtr = Tcl_NewIntObj((int)sch);
objPtr = Tcl_NewIntObj(i);
Tcl_IncrRefCount(objPtr);
CLANG_ASSERT(objs);
objs[objIndex++] = objPtr;
-527
View File
@@ -1,527 +0,0 @@
/*
* tclStrIdxTree.c --
*
* Contains the routines for managing string index tries in Tcl.
*
* This code is back-ported from the tclSE engine, by Serg G. Brester.
*
* Copyright (c) 2016 by Sergey G. Brester aka sebres. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* -----------------------------------------------------------------------
*
* String index tries are prepaired structures used for fast greedy search of the string
* (index) by unique string prefix as key.
*
* Index tree build for two lists together can be explained in the following datagram
*
* Lists:
*
* {Januar Februar Maerz April Mai Juni Juli August September Oktober November Dezember}
* {Jnr Fbr Mrz Apr Mai Jni Jli Agt Spt Okt Nvb Dzb}
*
* Index-Tree:
*
* j 0 * ...
* anuar 1 *
* u 0 * a 0
* ni 6 * pril 4
* li 7 * ugust 8
* n 0 * gt 8
* r 1 * s 9
* i 6 * eptember 9
* li 7 * pt 9
* f 2 * oktober 10
* ebruar 2 * n 11
* br 2 * ovember 11
* m 0 * vb 11
* a 0 * d 12
* erz 3 * ezember 12
* i 5 * zb 12
* rz 3 *
* ...
*
* Thereby value 0 shows pure group items (corresponding ambigous matches).
* But the group may have a value if it contains only same values
* (see for example group "f" above).
*
* StrIdxTree's are very fast, so:
* build of above-mentioned tree takes about 10 microseconds.
* search of string index in this tree takes fewer as 0.1 microseconds.
*
*/
#include "tclInt.h"
#include "tclStrIdxTree.h"
/*
*----------------------------------------------------------------------
*
* TclStrIdxTreeSearch --
*
* Find largest part of string "start" in indexed tree (case sensitive).
*
* Also used for building of string index tree.
*
* Results:
* Return position of UTF character in start after last equal character
* and found item (with parent).
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE const char*
TclStrIdxTreeSearch(
TclStrIdxTree **foundParent, /* Return value of found sub tree (used for tree build) */
TclStrIdx **foundItem, /* Return value of found item */
TclStrIdxTree *tree, /* Index tree will be browsed */
const char *start, /* UTF string to find in tree */
const char *end) /* End of string */
{
TclStrIdxTree *parent = tree, *prevParent = tree;
TclStrIdx *item = tree->firstPtr, *prevItem = NULL;
const char *s = start, *f, *cin, *cinf, *prevf;
int offs = 0;
if (item == NULL) {
goto done;
}
/* search in tree */
do {
cinf = cin = TclGetString(item->key) + offs;
f = TclUtfFindEqualNCInLwr(s, end, cin, cin + item->length, &cinf);
/* if something was found */
if (f > s) {
/* if whole string was found */
if (f >= end) {
start = f;
goto done;
};
/* set new offset and shift start string */
offs += cinf - cin;
s = f;
/* if match item, go deeper as long as possible */
if (offs >= item->length && item->childTree.firstPtr) {
/* save previuosly found item (if not ambigous) for
* possible fallback (few greedy match) */
if (item->value != NULL) {
prevf = f;
prevItem = item;
prevParent = parent;
}
parent = &item->childTree;
item = item->childTree.firstPtr;
continue;
}
/* no children - return this item and current chars found */
start = f;
goto done;
}
item = item->nextPtr;
} while (item != NULL);
/* fallback (few greedy match) not ambigous (has a value) */
if (prevItem != NULL) {
item = prevItem;
parent = prevParent;
start = prevf;
}
done:
if (foundParent)
*foundParent = parent;
if (foundItem)
*foundItem = item;
return start;
}
MODULE_SCOPE void
TclStrIdxTreeFree(
TclStrIdx *tree)
{
while (tree != NULL) {
TclStrIdx *t;
Tcl_DecrRefCount(tree->key);
if (tree->childTree.firstPtr != NULL) {
TclStrIdxTreeFree(tree->childTree.firstPtr);
}
t = tree, tree = tree->nextPtr;
ckfree(t);
}
}
/*
* Several bidirectional list primitives
*/
inline void
TclStrIdxTreeInsertBranch(
TclStrIdxTree *parent,
register TclStrIdx *item,
register TclStrIdx *child)
{
if (parent->firstPtr == child)
parent->firstPtr = item;
if (parent->lastPtr == child)
parent->lastPtr = item;
if ( (item->nextPtr = child->nextPtr) ) {
item->nextPtr->prevPtr = item;
child->nextPtr = NULL;
}
if ( (item->prevPtr = child->prevPtr) ) {
item->prevPtr->nextPtr = item;
child->prevPtr = NULL;
}
item->childTree.firstPtr = child;
item->childTree.lastPtr = child;
}
inline void
TclStrIdxTreeAppend(
register TclStrIdxTree *parent,
register TclStrIdx *item)
{
if (parent->lastPtr != NULL) {
parent->lastPtr->nextPtr = item;
}
item->prevPtr = parent->lastPtr;
item->nextPtr = NULL;
parent->lastPtr = item;
if (parent->firstPtr == NULL) {
parent->firstPtr = item;
}
}
/*
*----------------------------------------------------------------------
*
* TclStrIdxTreeBuildFromList --
*
* Build or extend string indexed tree from tcl list.
* If the values not given the values of built list are indices starts with 1.
* Value of 0 is thereby reserved to the ambigous values.
*
* Important: by multiple lists, optimal tree can be created only if list with
* larger strings used firstly.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE int
TclStrIdxTreeBuildFromList(
TclStrIdxTree *idxTree,
int lstc,
Tcl_Obj **lstv,
ClientData *values)
{
Tcl_Obj **lwrv;
int i, ret = TCL_ERROR;
ClientData val;
const char *s, *e, *f;
TclStrIdx *item;
/* create lowercase reflection of the list keys */
lwrv = ckalloc(sizeof(Tcl_Obj*) * lstc);
if (lwrv == NULL) {
return TCL_ERROR;
}
for (i = 0; i < lstc; i++) {
lwrv[i] = Tcl_DuplicateObj(lstv[i]);
if (lwrv[i] == NULL) {
return TCL_ERROR;
}
Tcl_IncrRefCount(lwrv[i]);
lwrv[i]->length = Tcl_UtfToLower(TclGetString(lwrv[i]));
}
/* build index tree of the list keys */
for (i = 0; i < lstc; i++) {
TclStrIdxTree *foundParent = idxTree;
e = s = TclGetString(lwrv[i]);
e += lwrv[i]->length;
val = values ? values[i] : INT2PTR(i+1);
/* ignore empty keys (impossible to index it) */
if (lwrv[i]->length == 0) continue;
item = NULL;
if (idxTree->firstPtr != NULL) {
TclStrIdx *foundItem;
f = TclStrIdxTreeSearch(&foundParent, &foundItem,
idxTree, s, e);
/* if common prefix was found */
if (f > s) {
/* ignore element if fulfilled or ambigous */
if (f == e) {
continue;
}
/* if shortest key was found with the same value,
* just replace its current key with longest key */
if ( foundItem->value == val
&& foundItem->length < lwrv[i]->length
&& foundItem->childTree.firstPtr == NULL
) {
Tcl_SetObjRef(foundItem->key, lwrv[i]);
foundItem->length = lwrv[i]->length;
continue;
}
/* split tree (e. g. j->(jan,jun) + jul == j->(jan,ju->(jun,jul)) )
* but don't split by fulfilled child of found item ( ii->iii->iiii ) */
if (foundItem->length != (f - s)) {
/* first split found item (insert one between parent and found + new one) */
item = ckalloc(sizeof(*item));
if (item == NULL) {
goto done;
}
Tcl_InitObjRef(item->key, foundItem->key);
item->length = f - s;
/* set value or mark as ambigous if not the same value of both */
item->value = (foundItem->value == val) ? val : NULL;
/* insert group item between foundParent and foundItem */
TclStrIdxTreeInsertBranch(foundParent, item, foundItem);
foundParent = &item->childTree;
} else {
/* the new item should be added as child of found item */
foundParent = &foundItem->childTree;
}
}
}
/* append item at end of found parent */
item = ckalloc(sizeof(*item));
if (item == NULL) {
goto done;
}
item->childTree.lastPtr = item->childTree.firstPtr = NULL;
Tcl_InitObjRef(item->key, lwrv[i]);
item->length = lwrv[i]->length;
item->value = val;
TclStrIdxTreeAppend(foundParent, item);
};
ret = TCL_OK;
done:
if (lwrv != NULL) {
for (i = 0; i < lstc; i++) {
Tcl_DecrRefCount(lwrv[i]);
}
ckfree(lwrv);
}
if (ret != TCL_OK) {
if (idxTree->firstPtr != NULL) {
TclStrIdxTreeFree(idxTree->firstPtr);
}
}
return ret;
}
static void
StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void
StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr);
static void
StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr);
Tcl_ObjType StrIdxTreeObjType = {
"str-idx-tree", /* name */
StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */
StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */
StrIdxTreeObj_UpdateStringProc, /* updateStringProc */
NULL /* setFromAnyProc */
};
MODULE_SCOPE Tcl_Obj*
TclStrIdxTreeNewObj()
{
Tcl_Obj *objPtr = Tcl_NewObj();
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &StrIdxTreeObjType;
/* return tree root in internal representation */
return objPtr;
}
static void
StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
{
/* follow links (smart pointers) */
if ( srcPtr->internalRep.twoPtrValue.ptr1 != NULL
&& srcPtr->internalRep.twoPtrValue.ptr2 == NULL
) {
srcPtr = (Tcl_Obj*)srcPtr->internalRep.twoPtrValue.ptr1;
}
/* create smart pointer to it (ptr1 != NULL, ptr2 = NULL) */
Tcl_InitObjRef(*((Tcl_Obj **)&copyPtr->internalRep.twoPtrValue.ptr1),
srcPtr);
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
copyPtr->typePtr = &StrIdxTreeObjType;
}
static void
StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr)
{
/* follow links (smart pointers) */
if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL
&& objPtr->internalRep.twoPtrValue.ptr2 == NULL
) {
/* is a link */
Tcl_UnsetObjRef(*((Tcl_Obj **)&objPtr->internalRep.twoPtrValue.ptr1));
} else {
/* is a tree */
TclStrIdxTree *tree = (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1;
if (tree->firstPtr != NULL) {
TclStrIdxTreeFree(tree->firstPtr);
}
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
}
objPtr->typePtr = NULL;
};
static void
StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr)
{
/* currently only dummy empty string possible */
objPtr->length = 0;
objPtr->bytes = &tclEmptyString;
};
MODULE_SCOPE TclStrIdxTree *
TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr) {
/* follow links (smart pointers) */
if (objPtr->typePtr != &StrIdxTreeObjType) {
return NULL;
}
if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL
&& objPtr->internalRep.twoPtrValue.ptr2 == NULL
) {
objPtr = (Tcl_Obj*)objPtr->internalRep.twoPtrValue.ptr1;
}
/* return tree root in internal representation */
return (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1;
}
/*
* Several debug primitives
*/
#if 0
/* currently unused, debug resp. test purposes only */
void
TclStrIdxTreePrint(
Tcl_Interp *interp,
TclStrIdx *tree,
int offs)
{
Tcl_Obj *obj[2];
const char *s;
Tcl_InitObjRef(obj[0], Tcl_NewStringObj("::puts", -1));
while (tree != NULL) {
s = TclGetString(tree->key) + offs;
Tcl_InitObjRef(obj[1], Tcl_ObjPrintf("%*s%.*s\t:%d",
offs, "", tree->length - offs, s, tree->value));
Tcl_PutsObjCmd(NULL, interp, 2, obj);
Tcl_UnsetObjRef(obj[1]);
if (tree->childTree.firstPtr != NULL) {
TclStrIdxTreePrint(interp, tree->childTree.firstPtr, tree->length);
}
tree = tree->nextPtr;
}
Tcl_UnsetObjRef(obj[0]);
}
MODULE_SCOPE int
TclStrIdxTreeTestObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[])
{
const char *cs, *cin, *ret;
static const char *const options[] = {
"index", "puts-index", "findequal",
NULL
};
enum optionInd {
O_INDEX, O_PUTS_INDEX, O_FINDEQUAL
};
int optionIndex;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], options,
"option", 0, &optionIndex) != TCL_OK) {
Tcl_SetErrorCode(interp, "CLOCK", "badOption",
Tcl_GetString(objv[1]), NULL);
return TCL_ERROR;
}
switch (optionIndex) {
case O_FINDEQUAL:
if (objc < 4) {
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
cs = TclGetString(objv[2]);
cin = TclGetString(objv[3]);
ret = TclUtfFindEqual(
cs, cs + objv[1]->length, cin, cin + objv[2]->length);
Tcl_SetObjResult(interp, Tcl_NewIntObj(ret - cs));
break;
case O_INDEX:
case O_PUTS_INDEX:
if (1) {
Tcl_Obj **lstv;
int i, lstc;
TclStrIdxTree idxTree = {NULL, NULL};
i = 1;
while (++i < objc) {
if (TclListObjGetElements(interp, objv[i],
&lstc, &lstv) != TCL_OK) {
return TCL_ERROR;
};
TclStrIdxTreeBuildFromList(&idxTree, lstc, lstv, NULL);
}
if (optionIndex == O_PUTS_INDEX) {
TclStrIdxTreePrint(interp, idxTree.firstPtr, 0);
}
TclStrIdxTreeFree(idxTree.firstPtr);
}
break;
}
return TCL_OK;
}
#endif
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
-169
View File
@@ -1,169 +0,0 @@
/*
* tclStrIdxTree.h --
*
* Declarations of string index tries and other primitives currently
* back-ported from tclSE.
*
* Copyright (c) 2016 Serg G. Brester (aka sebres)
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCLSTRIDXTREE_H
#define _TCLSTRIDXTREE_H
/*
* Main structures declarations of index tree and entry
*/
typedef struct TclStrIdxTree {
struct TclStrIdx *firstPtr;
struct TclStrIdx *lastPtr;
} TclStrIdxTree;
typedef struct TclStrIdx {
struct TclStrIdxTree childTree;
struct TclStrIdx *nextPtr;
struct TclStrIdx *prevPtr;
Tcl_Obj *key;
int length;
ClientData value;
} TclStrIdx;
/*
*----------------------------------------------------------------------
*
* TclUtfFindEqual, TclUtfFindEqualNC --
*
* Find largest part of string cs in string cin (case sensitive and not).
*
* Results:
* Return position of UTF character in cs after last equal character.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static inline const char *
TclUtfFindEqual(
register const char *cs, /* UTF string to find in cin. */
register const char *cse, /* End of cs */
register const char *cin, /* UTF string will be browsed. */
register const char *cine) /* End of cin */
{
register const char *ret = cs;
Tcl_UniChar ch1, ch2;
do {
cs += TclUtfToUniChar(cs, &ch1);
cin += TclUtfToUniChar(cin, &ch2);
if (ch1 != ch2) break;
} while ((ret = cs) < cse && cin < cine);
return ret;
}
static inline const char *
TclUtfFindEqualNC(
register const char *cs, /* UTF string to find in cin. */
register const char *cse, /* End of cs */
register const char *cin, /* UTF string will be browsed. */
register const char *cine, /* End of cin */
const char **cinfnd) /* Return position in cin */
{
register const char *ret = cs;
Tcl_UniChar ch1, ch2;
do {
cs += TclUtfToUniChar(cs, &ch1);
cin += TclUtfToUniChar(cin, &ch2);
if (ch1 != ch2) {
ch1 = Tcl_UniCharToLower(ch1);
ch2 = Tcl_UniCharToLower(ch2);
if (ch1 != ch2) break;
}
*cinfnd = cin;
} while ((ret = cs) < cse && cin < cine);
return ret;
}
static inline const char *
TclUtfFindEqualNCInLwr(
register const char *cs, /* UTF string (in anycase) to find in cin. */
register const char *cse, /* End of cs */
register const char *cin, /* UTF string (in lowercase) will be browsed. */
register const char *cine, /* End of cin */
const char **cinfnd) /* Return position in cin */
{
register const char *ret = cs;
Tcl_UniChar ch1, ch2;
do {
cs += TclUtfToUniChar(cs, &ch1);
cin += TclUtfToUniChar(cin, &ch2);
if (ch1 != ch2) {
ch1 = Tcl_UniCharToLower(ch1);
if (ch1 != ch2) break;
}
*cinfnd = cin;
} while ((ret = cs) < cse && cin < cine);
return ret;
}
static inline const char *
TclUtfNext(
register const char *src) /* The current location in the string. */
{
if (((unsigned char) *(src)) < 0xC0) {
return ++src;
} else {
Tcl_UniChar ch;
return src + TclUtfToUniChar(src, &ch);
}
}
/*
* Primitives to safe set, reset and free references.
*/
#define Tcl_UnsetObjRef(obj) \
if (obj != NULL) { Tcl_DecrRefCount(obj); obj = NULL; }
#define Tcl_InitObjRef(obj, val) \
obj = val; if (obj) { Tcl_IncrRefCount(obj); }
#define Tcl_SetObjRef(obj, val) \
if (1) { \
Tcl_Obj *nval = val; \
if (obj != nval) { \
Tcl_Obj *prev = obj; \
Tcl_InitObjRef(obj, nval); \
if (prev != NULL) { Tcl_DecrRefCount(prev); }; \
} \
}
/*
* Prototypes of module functions.
*/
MODULE_SCOPE const char*
TclStrIdxTreeSearch(TclStrIdxTree **foundParent,
TclStrIdx **foundItem, TclStrIdxTree *tree,
const char *start, const char *end);
MODULE_SCOPE int TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree,
int lstc, Tcl_Obj **lstv, ClientData *values);
MODULE_SCOPE Tcl_Obj*
TclStrIdxTreeNewObj();
MODULE_SCOPE TclStrIdxTree*
TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr);
#if 1
MODULE_SCOPE int TclStrIdxTreeTestObjCmd(ClientData, Tcl_Interp *,
int, Tcl_Obj *const objv[]);
#endif
#endif /* _TCLSTRIDXTREE_H */
+27 -27
View File
@@ -1183,9 +1183,9 @@ TclParseNumber(
case sNA:
case sNANPAREN:
case sNANHEX:
#endif
Tcl_Panic("TclParseNumber: bad acceptState %d parsing '%s'",
acceptState, bytes);
#endif
case BINARY:
shift = numTrailZeros;
if (!significandOverflow && significandWide != 0 &&
@@ -1973,7 +1973,7 @@ RefineApproximation(
*----------------------------------------------------------------------
*/
inline static void
static inline void
MulPow5(
mp_int *base, /* Number to multiply. */
unsigned n, /* Power of 5 to multiply by. */
@@ -2018,7 +2018,7 @@ MulPow5(
*----------------------------------------------------------------------
*/
inline static int
static inline int
NormalizeRightward(
Tcl_WideUInt *wPtr) /* INOUT: Number to shift. */
{
@@ -2109,7 +2109,7 @@ RequiredPrecision(
*----------------------------------------------------------------------
*/
inline static void
static inline void
DoubleToExpAndSig(
double dv, /* Number to convert. */
Tcl_WideUInt *significand, /* OUTPUT: Significand of the number. */
@@ -2157,7 +2157,7 @@ DoubleToExpAndSig(
*----------------------------------------------------------------------
*/
inline static void
static inline void
TakeAbsoluteValue(
Double *d, /* Number to replace with absolute value. */
int *sign) /* Place to put the signum. */
@@ -2188,7 +2188,7 @@ TakeAbsoluteValue(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
FormatInfAndNaN(
Double *d, /* Exceptional number to format. */
int *decpt, /* Decimal point to set to a bogus value. */
@@ -2230,7 +2230,7 @@ FormatInfAndNaN(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
FormatZero(
int *decpt, /* Location of the decimal point. */
char **endPtr) /* Pointer to the end of the formatted data */
@@ -2260,7 +2260,7 @@ FormatZero(
*----------------------------------------------------------------------
*/
inline static int
static inline int
ApproximateLog10(
Tcl_WideUInt bw, /* Integer significand of the number. */
int be, /* Power of two to scale bw. */
@@ -2308,7 +2308,7 @@ ApproximateLog10(
*----------------------------------------------------------------------
*/
inline static int
static inline int
BetterLog10(
double d, /* Original number to format. */
int k, /* Characteristic(Log base 10) of the
@@ -2351,7 +2351,7 @@ BetterLog10(
*----------------------------------------------------------------------
*/
inline static void
static inline void
ComputeScale(
int be, /* Exponent part of number: d = bw * 2**be. */
int k, /* Characteristic of log10(number). */
@@ -2414,7 +2414,7 @@ ComputeScale(
*----------------------------------------------------------------------
*/
inline static void
static inline void
SetPrecisionLimits(
int convType, /* Type of conversion: TCL_DD_SHORTEST,
* TCL_DD_STEELE0, TCL_DD_E_FMT,
@@ -2475,7 +2475,7 @@ SetPrecisionLimits(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
BumpUp(
char *s, /* Cursor pointing one past the end of the
* string. */
@@ -2509,7 +2509,7 @@ BumpUp(
*----------------------------------------------------------------------
*/
inline static int
static inline int
AdjustRange(
double *dPtr, /* INOUT: Number to adjust. */
int k) /* IN: floor(log10(d)) */
@@ -2582,7 +2582,7 @@ AdjustRange(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
ShorteningQuickFormat(
double d, /* Number to convert. */
int k, /* floor(log10(d)) */
@@ -2657,7 +2657,7 @@ ShorteningQuickFormat(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
StrictQuickFormat(
double d, /* Number to convert. */
int k, /* floor(log10(d)) */
@@ -2731,7 +2731,7 @@ StrictQuickFormat(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
QuickConversion(
double e, /* Number to format. */
int k, /* floor(log10(d)), approximately. */
@@ -2836,7 +2836,7 @@ QuickConversion(
*----------------------------------------------------------------------
*/
inline static void
static inline void
CastOutPowersOf2(
int *b2, /* Power of 2 to multiply the significand. */
int *m2, /* Power of 2 to multiply 1/2 ulp. */
@@ -2880,7 +2880,7 @@ CastOutPowersOf2(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
ShorteningInt64Conversion(
Double *dPtr, /* Original number to convert. */
int convType, /* Type of conversion (shortest, Steele,
@@ -3049,7 +3049,7 @@ ShorteningInt64Conversion(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
StrictInt64Conversion(
Double *dPtr, /* Original number to convert. */
int convType, /* Type of conversion (shortest, Steele,
@@ -3155,7 +3155,7 @@ StrictInt64Conversion(
*----------------------------------------------------------------------
*/
inline static int
static inline int
ShouldBankerRoundUpPowD(
mp_int *b, /* Numerator of the fraction. */
int sd, /* Denominator is 2**(sd*DIGIT_BIT). */
@@ -3193,7 +3193,7 @@ ShouldBankerRoundUpPowD(
*----------------------------------------------------------------------
*/
inline static int
static inline int
ShouldBankerRoundUpToNextPowD(
mp_int *b, /* Numerator of the fraction. */
mp_int *m, /* Numerator of the rounding tolerance. */
@@ -3256,7 +3256,7 @@ ShouldBankerRoundUpToNextPowD(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
ShorteningBignumConversionPowD(
Double *dPtr, /* Original number to convert. */
int convType, /* Type of conversion (shortest, Steele,
@@ -3449,7 +3449,7 @@ ShorteningBignumConversionPowD(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
StrictBignumConversionPowD(
Double *dPtr, /* Original number to convert. */
int convType, /* Type of conversion (shortest, Steele,
@@ -3565,7 +3565,7 @@ StrictBignumConversionPowD(
*----------------------------------------------------------------------
*/
inline static int
static inline int
ShouldBankerRoundUp(
mp_int *twor, /* 2x the remainder from thd division that
* produced the last digit. */
@@ -3600,7 +3600,7 @@ ShouldBankerRoundUp(
*----------------------------------------------------------------------
*/
inline static int
static inline int
ShouldBankerRoundUpToNext(
mp_int *b, /* Remainder from the division that produced
* the last digit. */
@@ -3654,7 +3654,7 @@ ShouldBankerRoundUpToNext(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
ShorteningBignumConversion(
Double *dPtr, /* Original number being converted. */
int convType, /* Conversion type. */
@@ -3870,7 +3870,7 @@ ShorteningBignumConversion(
*----------------------------------------------------------------------
*/
inline static char *
static inline char *
StrictBignumConversion(
Double *dPtr, /* Original number being converted. */
int convType, /* Conversion type. */
+90 -20
View File
@@ -418,18 +418,23 @@ Tcl_GetCharLength(
int numChars;
/*
* Optimize the case where we're really dealing with a bytearray object
* without string representation; we don't need to convert to a string to
* perform the get-length operation.
* Optimize the case where we're really dealing with a bytearray object;
* we don't need to convert to a string to perform the get-length operation.
*
* NOTE that we do not need the bytearray to be "pure". A ByteArray value
* with a string rep cannot be trusted to represent the same value as the
* string rep, but it *can* be trusted to have the same character length
* as the string rep, which is all this routine cares about.
*/
if (TclIsPureByteArray(objPtr)) {
if (objPtr->typePtr == &tclByteArrayType) {
int length;
(void) Tcl_GetByteArrayFromObj(objPtr, &length);
return length;
}
/*
* OK, need to work with the object as a string.
*/
@@ -460,6 +465,50 @@ Tcl_GetCharLength(
}
return numChars;
}
/*
*----------------------------------------------------------------------
*
* TclCheckEmptyString --
*
* Determine whether the string value of an object is or would be the
* empty string, without generating a string representation.
*
* Results:
* Returns 1 if empty, 0 if not, and -1 if unknown.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclCheckEmptyString (
Tcl_Obj *objPtr
) {
int length = -1;
if (objPtr->bytes == tclEmptyStringRep) {
return TCL_EMPTYSTRING_YES;
}
if (TclIsPureList(objPtr)) {
Tcl_ListObjLength(NULL, objPtr, &length);
return length == 0;
}
if (TclIsPureDict(objPtr)) {
Tcl_DictObjSize(NULL, objPtr, &length);
return length == 0;
}
if (objPtr->bytes == NULL) {
return TCL_EMPTYSTRING_UNKNOWN;
}
return objPtr->length == 0;
}
/*
*----------------------------------------------------------------------
@@ -529,7 +578,7 @@ Tcl_GetUniChar(
*
* Get the Unicode form of the String object. If the object is not
* already a String object, it will be converted to one. If the String
* object does not have a Unicode rep, then one is create from the UTF
* object does not have a Unicode rep, then one is created from the UTF
* string format.
*
* Results:
@@ -663,6 +712,17 @@ Tcl_GetRange(
stringPtr = GET_STRING(objPtr);
}
#if TCL_UTF_MAX == 4
/* See: bug [11ae2be95dac9417] */
if ((first>0) && ((stringPtr->unicode[first]&0xFC00) == 0xDC00)
&& ((stringPtr->unicode[first-1]&0xFC00) == 0xD800)) {
++first;
}
if ((last+1<stringPtr->numChars) && ((stringPtr->unicode[last+1]&0xFC00) == 0xDC00)
&& ((stringPtr->unicode[last]&0xFC00) == 0xD800)) {
++last;
}
#endif
return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1);
}
@@ -1682,6 +1742,7 @@ Tcl_AppendFormatToObj(
const char *span = format, *msg, *errCode;
int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
int originalLength, limit;
Tcl_UniChar ch = 0;
static const char *mixedXPG =
"cannot mix \"%\" and \"%n$\" conversion specifiers";
static const char *const badIndex[2] = {
@@ -1709,7 +1770,6 @@ Tcl_AppendFormatToObj(
#endif
int newXpg, numChars, allocSegment = 0, segmentLimit, segmentNumBytes;
Tcl_Obj *segment;
Tcl_UniChar ch;
int step = TclUtfToUniChar(format, &ch);
format += step;
@@ -1816,6 +1876,11 @@ Tcl_AppendFormatToObj(
width = 0;
if (isdigit(UCHAR(ch))) {
width = strtoul(format, &end, 10);
if (width < 0) {
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
format = end;
step = TclUtfToUniChar(format, &ch);
} else if (ch == '*') {
@@ -1936,6 +2001,12 @@ Tcl_AppendFormatToObj(
goto error;
}
length = Tcl_UniCharToUtf(code, buf);
#if TCL_UTF_MAX > 3
if (!length) {
/* Special case for handling upper surrogates. */
length = Tcl_UniCharToUtf(-1, buf);
}
#endif
segment = Tcl_NewStringObj(buf, length);
Tcl_IncrRefCount(segment);
allocSegment = 1;
@@ -2027,8 +2098,11 @@ Tcl_AppendFormatToObj(
segmentLimit -= 1;
precision--;
break;
case 'x':
case 'X':
Tcl_AppendToObj(segment, "0X", 2);
segmentLimit -= 2;
break;
case 'x':
Tcl_AppendToObj(segment, "0x", 2);
segmentLimit -= 2;
break;
@@ -2192,7 +2266,11 @@ Tcl_AppendFormatToObj(
}
digitOffset = (int) (bits % base);
if (digitOffset > 9) {
bytes[numDigits] = 'a' + digitOffset - 10;
if (ch == 'X') {
bytes[numDigits] = 'A' + digitOffset - 10;
} else {
bytes[numDigits] = 'a' + digitOffset - 10;
}
} else {
bytes[numDigits] = '0' + digitOffset;
}
@@ -2314,14 +2392,6 @@ Tcl_AppendFormatToObj(
goto error;
}
switch (ch) {
case 'E':
case 'G':
case 'X': {
Tcl_SetObjLength(segment, Tcl_UtfToUpper(TclGetString(segment)));
}
}
if (width>0 && numChars<0) {
numChars = Tcl_GetCharLength(segment);
}
@@ -2693,7 +2763,7 @@ TclStringObjReverse(
Tcl_Obj *objPtr)
{
String *stringPtr;
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
if (TclIsPureByteArray(objPtr)) {
int numBytes;
@@ -2721,7 +2791,6 @@ TclStringObjReverse(
* Tcl_SetObjLength into growing the unicode rep buffer.
*/
ch = 0;
objPtr = Tcl_NewUnicodeObj(&ch, 1);
Tcl_SetObjLength(objPtr, stringPtr->numChars);
to = Tcl_GetUnicode(objPtr);
@@ -2824,7 +2893,7 @@ ExtendUnicodeRepWithString(
{
String *stringPtr = GET_STRING(objPtr);
int needed, numOrigChars = 0;
Tcl_UniChar *dst;
Tcl_UniChar *dst, unichar = 0;
if (stringPtr->hasUnicode) {
numOrigChars = stringPtr->numChars;
@@ -2847,7 +2916,8 @@ ExtendUnicodeRepWithString(
numAppendChars = 0;
}
for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) {
bytes += TclUtfToUniChar(bytes, dst);
bytes += TclUtfToUniChar(bytes, &unichar);
*dst = unichar;
}
*dst = 0;
}
+23 -11
View File
@@ -12,6 +12,10 @@
#include "tclInt.h"
#include "tommath.h"
#ifdef __CYGWIN__
# include <wchar.h>
#endif
#ifdef __GNUC__
#pragma GCC dependency "tcl.decls"
#pragma GCC dependency "tclInt.decls"
@@ -106,8 +110,6 @@ static unsigned short TclWinNToHS(unsigned short ns) {
# define TclWinFlushDirtyChannels doNothing
# define TclWinResetInterfaces doNothing
static Tcl_Encoding winTCharEncoding;
static int
TclpIsAtty(int fd)
{
@@ -127,7 +129,7 @@ void *TclWinGetTclInstance()
{
void *hInstance = NULL;
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(const char *)&winTCharEncoding, &hInstance);
(const char *)&TclpIsAtty, &hInstance);
return hInstance;
}
@@ -186,11 +188,11 @@ Tcl_WinUtfToTChar(
int len,
Tcl_DString *dsPtr)
{
if (!winTCharEncoding) {
winTCharEncoding = Tcl_GetEncoding(0, "unicode");
Tcl_DStringInit(dsPtr);
if (!string) {
return NULL;
}
return Tcl_UtfToExternalDString(winTCharEncoding,
string, len, dsPtr);
return (char *)Tcl_UtfToUniCharDString(string, len, dsPtr);
}
char *
@@ -199,11 +201,16 @@ Tcl_WinTCharToUtf(
int len,
Tcl_DString *dsPtr)
{
if (!winTCharEncoding) {
winTCharEncoding = Tcl_GetEncoding(0, "unicode");
Tcl_DStringInit(dsPtr);
if (!string) {
return NULL;
}
return Tcl_ExternalToUtfDString(winTCharEncoding,
string, len, dsPtr);
if (len < 0) {
len = wcslen((wchar_t *)string);
} else {
len /= 2;
}
return Tcl_UniCharToUtfDString((Tcl_UniChar *)string, len, dsPtr);
}
#if defined(TCL_WIDE_INT_IS_LONG)
@@ -560,6 +567,11 @@ static const TclIntStubs tclIntStubs = {
TclDoubleDigits, /* 249 */
TclSetSlaveCancelFlags, /* 250 */
TclRegisterLiteral, /* 251 */
TclPtrGetVar, /* 252 */
TclPtrSetVar, /* 253 */
TclPtrIncrObjVar, /* 254 */
TclPtrObjMakeUpvar, /* 255 */
TclPtrUnsetVar, /* 256 */
};
static const TclIntPlatStubs tclIntPlatStubs = {
+58 -4
View File
@@ -407,6 +407,12 @@ static Tcl_FSMatchInDirectoryProc SimpleMatchInDirectory;
static int TestNumUtfCharsCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
static int TestFindFirstCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
static int TestFindLastCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
static int TestHashSystemHashCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
@@ -668,6 +674,10 @@ Tcltest_Init(
TestsetobjerrorcodeCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "testnumutfchars",
TestNumUtfCharsCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "testfindfirst",
TestFindFirstCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "testfindlast",
TestFindLastCmd, NULL, NULL);
Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
NULL, NULL);
Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
@@ -5224,7 +5234,7 @@ TestmainthreadCmd(
const char **argv) /* Argument strings. */
{
if (argc == 1) {
Tcl_Obj *idObj = Tcl_NewLongObj((long)(size_t)Tcl_GetCurrentThread());
Tcl_Obj *idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread());
Tcl_SetObjResult(interp, idObj);
return TCL_OK;
@@ -5621,8 +5631,8 @@ TestChannelCmd(
return TCL_ERROR;
}
TclFormatInt(buf, (size_t) Tcl_GetChannelThread(chan));
Tcl_AppendResult(interp, buf, NULL);
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
(Tcl_WideInt) (size_t) Tcl_GetChannelThread(chan)));
return TCL_OK;
}
@@ -6672,7 +6682,7 @@ TestNumUtfCharsCmd(
int len = -1;
if (objc > 2) {
(void) Tcl_GetStringFromObj(objv[1], &len);
(void) Tcl_GetIntFromObj(interp, objv[2], &len);
}
len = Tcl_NumUtfChars(Tcl_GetString(objv[1]), len);
Tcl_SetObjResult(interp, Tcl_NewIntObj(len));
@@ -6680,6 +6690,50 @@ TestNumUtfCharsCmd(
return TCL_OK;
}
/*
* Used to check correct operation of Tcl_UtfFindFirst
*/
static int
TestFindFirstCmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
if (objc > 1) {
int len = -1;
if (objc > 2) {
(void) Tcl_GetIntFromObj(interp, objv[2], &len);
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindFirst(Tcl_GetString(objv[1]), len), -1));
}
return TCL_OK;
}
/*
* Used to check correct operation of Tcl_UtfFindLast
*/
static int
TestFindLastCmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
if (objc > 1) {
int len = -1;
if (objc > 2) {
(void) Tcl_GetIntFromObj(interp, objv[2], &len);
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindLast(Tcl_GetString(objv[1]), len), -1));
}
return TCL_OK;
}
#if defined(HAVE_CPUID) || defined(_WIN32)
/*
*----------------------------------------------------------------------
+10 -3
View File
@@ -174,7 +174,6 @@ TclThread_Init(
Tcl_CreateObjCommand(interp, "testthread", ThreadObjCmd, NULL, NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
@@ -248,7 +247,7 @@ ThreadObjCmd(
switch ((enum options)option) {
case THREAD_CANCEL: {
long id;
Tcl_WideInt id;
const char *result;
int flags, arg;
@@ -264,7 +263,7 @@ ThreadObjCmd(
arg++;
}
}
if (Tcl_GetLongFromObj(interp, objv[arg], &id) != TCL_OK) {
if (Tcl_GetWideIntFromObj(interp, objv[arg], &id) != TCL_OK) {
return TCL_ERROR;
}
arg++;
@@ -1158,6 +1157,14 @@ ThreadExitProc(
Tcl_MutexLock(&threadMutex);
if (self == errorThreadId) {
if (errorProcString) { /* Extra safety */
ckfree(errorProcString);
errorProcString = NULL;
}
errorThreadId = 0;
}
if (threadEvalScript) {
ckfree(threadEvalScript);
threadEvalScript = NULL;
+52 -1
View File
@@ -191,8 +191,10 @@ Tcl_TraceObjCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
int optionIndex;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
const char *name;
const char *flagOps, *p;
#endif
/* Main sub commands to 'trace' */
static const char *const traceOptions[] = {
"add", "info", "remove",
@@ -365,12 +367,14 @@ Tcl_TraceObjCmd(
}
return TCL_OK;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
badVarOps:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad operations \"%s\": should be one or more of rwua",
flagOps));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "BADOPS", NULL);
return TCL_ERROR;
#endif
}
/*
@@ -912,9 +916,11 @@ TraceVariableObjCmd(
+ 1 + length);
ctvarPtr->traceCmdInfo.flags = flags;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
if (objv[0] == NULL) {
ctvarPtr->traceCmdInfo.flags |= TCL_TRACE_OLD_STYLE;
}
#endif
ctvarPtr->traceCmdInfo.length = length;
flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
memcpy(ctvarPtr->traceCmdInfo.command, command, length+1);
@@ -939,7 +945,11 @@ TraceVariableObjCmd(
TraceVarInfo *tvarPtr = clientData;
if ((tvarPtr->length == length)
&& ((tvarPtr->flags & ~TCL_TRACE_OLD_STYLE)==flags)
&& ((tvarPtr->flags
#ifndef TCL_REMOVE_OBSOLETE_TRACES
& ~TCL_TRACE_OLD_STYLE
#endif
)==flags)
&& (strncmp(command, tvarPtr->command,
(size_t) length) == 0)) {
Tcl_UntraceVar2(interp, name, NULL,
@@ -2465,6 +2475,47 @@ TclVarTraceExists(
return varPtr;
}
/*
*----------------------------------------------------------------------
*
* TclCheckArrayTraces --
*
* This function is invoked to when we operate on an array variable,
* to allow any array traces to fire.
*
* Results:
* Returns TCL_OK to indicate normal operation. Returns TCL_ERROR if
* invocation of a trace function indicated an error. When TCL_ERROR is
* returned, then error information is left in interp.
*
* Side effects:
* Almost anything can happen, depending on trace; this function itself
* doesn't have any side effects.
*
*----------------------------------------------------------------------
*/
int
TclCheckArrayTraces(
Tcl_Interp *interp,
Var *varPtr,
Var *arrayPtr,
Tcl_Obj *name,
int index)
{
int code = TCL_OK;
if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
Interp *iPtr = (Interp *)interp;
code = TclObjCallVarTraces(iPtr, arrayPtr, varPtr, name, NULL,
(TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY),
/* leaveErrMsg */ 1, index);
}
return code;
}
/*
*----------------------------------------------------------------------
*
+1032 -999
View File
File diff suppressed because it is too large Load Diff
+205 -94
View File
@@ -98,9 +98,9 @@ static int UtfCount(int ch);
*---------------------------------------------------------------------------
*/
INLINE static int
static inline int
UtfCount(
int ch) /* The Tcl_UniChar whose size is returned. */
int ch) /* The Unicode character whose size is returned. */
{
if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
return 1;
@@ -109,7 +109,7 @@ UtfCount(
return 2;
}
#if TCL_UTF_MAX > 3
if (((unsigned)(ch - 0x10000) <= 0xfffff)) {
if (((unsigned)(ch - 0x10000) <= 0xFFFFF)) {
return 4;
}
#endif
@@ -134,7 +134,7 @@ UtfCount(
*---------------------------------------------------------------------------
*/
INLINE int
int
Tcl_UniCharToUtf(
int ch, /* The Tcl_UniChar to be stored in the
* buffer. */
@@ -154,19 +154,26 @@ Tcl_UniCharToUtf(
return 2;
}
if (ch <= 0xFFFF) {
#if TCL_UTF_MAX == 4
#if TCL_UTF_MAX > 3
if ((ch & 0xF800) == 0xD800) {
if (ch & 0x0400) {
/* Low surrogate */
buf[3] = (char) ((ch | 0x80) & 0xBF);
buf[2] |= (char) (((ch >> 6) | 0x80) & 0x8F);
return 4;
if (((buf[0] & 0xF8) == 0xF0) && ((buf[1] & 0xC0) == 0x80)
&& ((buf[2] & 0xCF) == 0)) {
/* Previous Tcl_UniChar was a High surrogate, so combine */
buf[3] = (char) ((ch & 0x3F) | 0x80);
buf[2] |= (char) (((ch >> 6) & 0x0F) | 0x80);
return 4;
}
/* Previous Tcl_UniChar was not a High surrogate, so just output */
} else {
/* High surrogate */
ch += 0x40;
buf[2] = (char) (((ch << 4) | 0x80) & 0xB0);
buf[1] = (char) (((ch >> 2) | 0x80) & 0xBF);
buf[0] = (char) (((ch >> 8) | 0xF0) & 0xF7);
/* Fill buffer with specific 3-byte (invalid) byte combination,
so following Low surrogate can recognize it and combine */
buf[2] = (char) ((ch << 4) & 0x30);
buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80);
buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0);
return 0;
}
}
@@ -182,6 +189,13 @@ Tcl_UniCharToUtf(
buf[0] = (char) ((ch >> 18) | 0xF0);
return 4;
}
} else if (ch == -1) {
if (((buf[0] & 0xF8) == 0xF0) && ((buf[1] & 0xC0) == 0x80)
&& ((buf[2] & 0xCF) == 0)) {
ch = 0xD7C0 + ((buf[0] & 0x07) << 8) + ((buf[1] & 0x3F) << 2)
+ ((buf[2] & 0x30) >> 4);
goto three;
}
#endif
}
@@ -229,7 +243,7 @@ Tcl_UniCharToUtfDString(
*/
oldLength = Tcl_DStringLength(dsPtr);
Tcl_DStringSetLength(dsPtr, (oldLength + uniLength + 1) * TCL_UTF_MAX);
Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * TCL_UTF_MAX);
string = Tcl_DStringValue(dsPtr) + oldLength;
p = string;
@@ -259,6 +273,15 @@ Tcl_UniCharToUtfDString(
* Tcl_UtfCharComplete() before calling this routine to ensure that
* enough bytes remain in the string.
*
* If TCL_UTF_MAX == 4, special handling of Surrogate pairs is done:
* For any UTF-8 string containing a character outside of the BMP, the
* first call to this function will fill *chPtr with the high surrogate
* and generate a return value of 0. Calling Tcl_UtfToUniChar again
* will produce the low surrogate and a return value of 4. Because *chPtr
* is used to remember whether the high surrogate is already produced, it
* is recommended to initialize the variable it points to as 0 before
* the first call to Tcl_UtfToUniChar is done.
*
* Results:
* *chPtr is filled with the Tcl_UniChar, and the return value is the
* number of bytes from the UTF-8 string that were consumed.
@@ -278,7 +301,7 @@ Tcl_UtfToUniChar(
register int byte;
/*
* Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones.
* Unroll 1 to 3 (or 4) byte UTF-8 sequences.
*/
byte = *((unsigned char *) src);
@@ -298,7 +321,7 @@ Tcl_UtfToUniChar(
*/
*chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (src[1] & 0x3F));
if ((*chPtr == 0) || (*chPtr > 0x7f)) {
if ((unsigned)(*chPtr - 1) >= (UNICODE_SELF - 1)) {
return 2;
}
}
@@ -315,7 +338,7 @@ Tcl_UtfToUniChar(
*chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12)
| ((src[1] & 0x3F) << 6) | (src[2] & 0x3F));
if (*chPtr > 0x7ff) {
if (*chPtr > 0x7FF) {
return 3;
}
}
@@ -331,16 +354,34 @@ Tcl_UtfToUniChar(
/*
* Four-byte-character lead byte followed by three trail bytes.
*/
#if TCL_UTF_MAX == 4
Tcl_UniChar surrogate;
*chPtr = (Tcl_UniChar) (((byte & 0x0E) << 18) | ((src[1] & 0x3F) << 12)
| ((src[2] & 0x3F) << 6) | (src[3] & 0x3F));
if ((*chPtr <= 0x10ffff) && (*chPtr > 0xffff)) {
byte = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)
| ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)) - 0x10000;
surrogate = (Tcl_UniChar) (0xD800 + (byte >> 10));
if (byte & 0x100000) {
/* out of range, < 0x10000 or > 0x10ffff */
} else if (*chPtr != surrogate) {
/* produce high surrogate, but don't advance source pointer */
*chPtr = surrogate;
return 0;
} else {
/* produce low surrogate, and advance source pointer */
*chPtr = (Tcl_UniChar) (0xDC00 | (byte & 0x3FF));
return 4;
}
#else
*chPtr = (Tcl_UniChar) (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)
| ((src[2] & 0x3F) << 6) | (src[3] & 0x3F));
if ((unsigned)(*chPtr - 0x10000) <= 0xFFFFF) {
return 4;
}
#endif
}
/*
* A three-byte-character lead-byte not followed by two trail-bytes
* A four-byte-character lead-byte not followed by two trail-bytes
* represents itself.
*/
}
@@ -377,7 +418,7 @@ Tcl_UtfToUniCharDString(
* appended to this previously initialized
* DString. */
{
Tcl_UniChar *w, *wString;
Tcl_UniChar ch = 0, *w, *wString;
const char *p, *end;
int oldLength;
@@ -391,16 +432,26 @@ Tcl_UtfToUniCharDString(
*/
oldLength = Tcl_DStringLength(dsPtr);
/* TODO: fix overreach! */
Tcl_DStringSetLength(dsPtr,
(int) ((oldLength + length + 1) * sizeof(Tcl_UniChar)));
oldLength + (int) ((length + 1) * sizeof(Tcl_UniChar)));
wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength);
w = wString;
end = src + length;
for (p = src; p < end; ) {
p += TclUtfToUniChar(p, w);
w++;
p = src;
end = src + length - TCL_UTF_MAX;
while (p < end) {
p += TclUtfToUniChar(p, &ch);
*w++ = ch;
}
end += TCL_UTF_MAX;
while (p < end) {
if (Tcl_UtfCharComplete(p, end-p)) {
p += TclUtfToUniChar(p, &ch);
} else {
ch = UCHAR(*p++);
}
*w++ = ch;
}
*w = '\0';
Tcl_DStringSetLength(dsPtr,
@@ -434,10 +485,7 @@ Tcl_UtfCharComplete(
* a complete UTF-8 character. */
int length) /* Length of above string in bytes. */
{
int ch;
ch = *((unsigned char *) src);
return length >= totalBytes[ch];
return length >= totalBytes[(unsigned char)*src];
}
/*
@@ -464,9 +512,8 @@ Tcl_NumUtfChars(
int length) /* The length of the string in bytes, or -1
* for strlen(string). */
{
Tcl_UniChar ch;
register Tcl_UniChar *chPtr = &ch;
register int i;
Tcl_UniChar ch = 0;
register int i = 0;
/*
* The separate implementations are faster.
@@ -475,26 +522,27 @@ Tcl_NumUtfChars(
* single-byte char case specially.
*/
i = 0;
if (length < 0) {
while (*src != '\0') {
src += TclUtfToUniChar(src, chPtr);
src += TclUtfToUniChar(src, &ch);
i++;
}
if (i < 0) i = INT_MAX; /* Bug [2738427] */
} else {
register int n;
register const char *endPtr = src + length - TCL_UTF_MAX;
while (length > 0) {
if (UCHAR(*src) < 0xC0) {
length--;
src++;
} else {
n = Tcl_UtfToUniChar(src, chPtr);
length -= n;
src += n;
}
while (src < endPtr) {
src += TclUtfToUniChar(src, &ch);
i++;
}
endPtr += TCL_UTF_MAX;
while ((src < endPtr) && Tcl_UtfCharComplete(src, endPtr - src)) {
src += TclUtfToUniChar(src, &ch);
i++;
}
if (src < endPtr) {
i += endPtr - src;
}
}
return i;
}
@@ -504,13 +552,13 @@ Tcl_NumUtfChars(
*
* Tcl_UtfFindFirst --
*
* Returns a pointer to the first occurance of the given Tcl_UniChar in
* the NULL-terminated UTF-8 string. The NULL terminator is considered
* Returns a pointer to the first occurance of the given Unicode character
* in the NULL-terminated UTF-8 string. The NULL terminator is considered
* part of the UTF-8 string. Equivalent to Plan 9 utfrune().
*
* Results:
* As above. If the Tcl_UniChar does not exist in the given string, the
* return value is NULL.
* As above. If the Unicode character does not exist in the given string,
* the return value is NULL.
*
* Side effects:
* None.
@@ -521,14 +569,21 @@ Tcl_NumUtfChars(
const char *
Tcl_UtfFindFirst(
const char *src, /* The UTF-8 string to be searched. */
int ch) /* The Tcl_UniChar to search for. */
int ch) /* The Unicode character to search for. */
{
int len;
Tcl_UniChar find;
int len, fullchar;
Tcl_UniChar find = 0;
while (1) {
len = TclUtfToUniChar(src, &find);
if (find == ch) {
fullchar = find;
#if TCL_UTF_MAX == 4
if (!len) {
len += TclUtfToUniChar(src, &find);
fullchar = (((fullchar & 0x3ff) << 10) | (find & 0x3ff)) + 0x10000;
}
#endif
if (fullchar == ch) {
return src;
}
if (*src == '\0') {
@@ -543,12 +598,12 @@ Tcl_UtfFindFirst(
*
* Tcl_UtfFindLast --
*
* Returns a pointer to the last occurance of the given Tcl_UniChar in
* the NULL-terminated UTF-8 string. The NULL terminator is considered
* Returns a pointer to the last occurance of the given Unicode character
* in the NULL-terminated UTF-8 string. The NULL terminator is considered
* part of the UTF-8 string. Equivalent to Plan 9 utfrrune().
*
* Results:
* As above. If the Tcl_UniChar does not exist in the given string, the
* As above. If the Unicode character does not exist in the given string, the
* return value is NULL.
*
* Side effects:
@@ -560,16 +615,23 @@ Tcl_UtfFindFirst(
const char *
Tcl_UtfFindLast(
const char *src, /* The UTF-8 string to be searched. */
int ch) /* The Tcl_UniChar to search for. */
int ch) /* The Unicode character to search for. */
{
int len;
Tcl_UniChar find;
int len, fullchar;
Tcl_UniChar find = 0;
const char *last;
last = NULL;
while (1) {
len = TclUtfToUniChar(src, &find);
if (find == ch) {
fullchar = find;
#if TCL_UTF_MAX == 4
if (!len) {
len += TclUtfToUniChar(src, &find);
fullchar = (((fullchar & 0x3ff) << 10) | (find & 0x3ff)) + 0x10000;
}
#endif
if (fullchar == ch) {
last = src;
}
if (*src == '\0') {
@@ -603,9 +665,15 @@ const char *
Tcl_UtfNext(
const char *src) /* The current location in the string. */
{
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
int len = TclUtfToUniChar(src, &ch);
return src + TclUtfToUniChar(src, &ch);
#if TCL_UTF_MAX == 4
if (len == 0) {
len = TclUtfToUniChar(src, &ch);
}
#endif
return src + len;
}
/*
@@ -638,8 +706,7 @@ Tcl_UtfPrev(
const char *look;
int i, byte;
src--;
look = src;
look = --src;
for (i = 0; i < TCL_UTF_MAX; i++) {
if (look < start) {
if (src < start) {
@@ -664,7 +731,7 @@ Tcl_UtfPrev(
*
* Tcl_UniCharAtIndex --
*
* Returns the Unicode character represented at the specified character
* Returns the Tcl_UniChar represented at the specified character
* (not byte) position in the UTF-8 string.
*
* Results:
@@ -683,8 +750,7 @@ Tcl_UniCharAtIndex(
{
Tcl_UniChar ch = 0;
while (index >= 0) {
index--;
while (index-- >= 0) {
src += TclUtfToUniChar(src, &ch);
}
return ch;
@@ -712,12 +778,19 @@ Tcl_UtfAtIndex(
register const char *src, /* The UTF-8 string. */
register int index) /* The position of the desired character. */
{
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
int len = 1;
while (index > 0) {
index--;
while (index-- > 0) {
len = TclUtfToUniChar(src, &ch);
src += len;
}
#if TCL_UTF_MAX == 4
if (!len) {
/* Index points at character following High Surrogate */
src += TclUtfToUniChar(src, &ch);
}
#endif
return src;
}
@@ -796,7 +869,7 @@ int
Tcl_UtfToUpper(
char *str) /* String to convert in place. */
{
Tcl_UniChar ch, upChar;
Tcl_UniChar ch = 0, upChar;
char *src, *dst;
int bytes;
@@ -849,7 +922,7 @@ int
Tcl_UtfToLower(
char *str) /* String to convert in place. */
{
Tcl_UniChar ch, lowChar;
Tcl_UniChar ch = 0, lowChar;
char *src, *dst;
int bytes;
@@ -903,7 +976,7 @@ int
Tcl_UtfToTitle(
char *str) /* String to convert in place. */
{
Tcl_UniChar ch, titleChar, lowChar;
Tcl_UniChar ch = 0, titleChar, lowChar;
char *src, *dst;
int bytes;
@@ -928,7 +1001,11 @@ Tcl_UtfToTitle(
}
while (*src) {
bytes = TclUtfToUniChar(src, &ch);
lowChar = Tcl_UniCharToLower(ch);
lowChar = ch;
/* Special exception for Georgian Asomtavruli chars, no titlecase. */
if ((unsigned)(lowChar - 0x1C90) >= 0x30) {
lowChar = Tcl_UniCharToLower(lowChar);
}
if (bytes < UtfCount(lowChar)) {
memcpy(dst, src, (size_t) bytes);
@@ -1012,11 +1089,11 @@ Tcl_UtfNcmp(
const char *ct, /* UTF string cs is compared to. */
unsigned long numChars) /* Number of UTF chars to compare. */
{
Tcl_UniChar ch1, ch2;
Tcl_UniChar ch1 = 0, ch2 = 0;
/*
* Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the
* pair of bytes 0xc0,0x80) is larger than byte representation of \u0001
* pair of bytes 0xC0,0x80) is larger than byte representation of \u0001
* (the byte 0x01.)
*/
@@ -1030,6 +1107,16 @@ Tcl_UtfNcmp(
cs += TclUtfToUniChar(cs, &ch1);
ct += TclUtfToUniChar(ct, &ch2);
if (ch1 != ch2) {
#if TCL_UTF_MAX == 4
/* Surrogates always report higher than non-surrogates */
if (((ch1 & 0xFC00) == 0xD800)) {
if ((ch2 & 0xFC00) != 0xD800) {
return ch1;
}
} else if ((ch2 & 0xFC00) == 0xD800) {
return -ch2;
}
#endif
return (ch1 - ch2);
}
}
@@ -1060,7 +1147,8 @@ Tcl_UtfNcasecmp(
const char *ct, /* UTF string cs is compared to. */
unsigned long numChars) /* Number of UTF chars to compare. */
{
Tcl_UniChar ch1, ch2;
Tcl_UniChar ch1 = 0, ch2 = 0;
while (numChars-- > 0) {
/*
* n must be interpreted as chars, not bytes.
@@ -1070,6 +1158,16 @@ Tcl_UtfNcasecmp(
cs += TclUtfToUniChar(cs, &ch1);
ct += TclUtfToUniChar(ct, &ch2);
if (ch1 != ch2) {
#if TCL_UTF_MAX == 4
/* Surrogates always report higher than non-surrogates */
if (((ch1 & 0xFC00) == 0xD800)) {
if ((ch2 & 0xFC00) != 0xD800) {
return ch1;
}
} else if ((ch2 & 0xFC00) == 0xD800) {
return -ch2;
}
#endif
ch1 = Tcl_UniCharToLower(ch1);
ch2 = Tcl_UniCharToLower(ch2);
if (ch1 != ch2) {
@@ -1083,7 +1181,7 @@ Tcl_UtfNcasecmp(
/*
*----------------------------------------------------------------------
*
* Tcl_UtfNcasecmp --
* TclUtfCasecmp --
*
* Compare UTF chars of string cs to string ct case insensitively.
* Replacement for strcasecmp in Tcl core, in places where UTF-8 should
@@ -1103,12 +1201,22 @@ 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;
Tcl_UniChar ch1 = 0, ch2 = 0;
while (*cs && *ct) {
cs += TclUtfToUniChar(cs, &ch1);
ct += TclUtfToUniChar(ct, &ch2);
if (ch1 != ch2) {
#if TCL_UTF_MAX == 4
/* Surrogates always report higher than non-surrogates */
if (((ch1 & 0xFC00) == 0xD800)) {
if ((ch2 & 0xFC00) != 0xD800) {
return ch1;
}
} else if ((ch2 & 0xFC00) == 0xD800) {
return -ch2;
}
#endif
ch1 = Tcl_UniCharToLower(ch1);
ch2 = Tcl_UniCharToLower(ch2);
if (ch1 != ch2) {
@@ -1169,8 +1277,9 @@ Tcl_UniCharToLower(
int ch) /* Unicode character to convert. */
{
int info = GetUniCharInfo(ch);
int mode = GetCaseType(info);
if (GetCaseType(info) & 0x02) {
if ((mode & 0x02) && (mode != 0x7)) {
ch += GetDelta(info);
}
return (Tcl_UniChar) ch;
@@ -1204,7 +1313,9 @@ Tcl_UniCharToTitle(
* Subtract or add one depending on the original case.
*/
ch += ((mode & 0x4) ? -1 : 1);
if (mode != 0x7) {
ch += ((mode & 0x4) ? -1 : 1);
}
} else if (mode == 0x4) {
ch -= GetDelta(info);
}
@@ -1400,11 +1511,11 @@ Tcl_UniCharIsControl(
{
#if TCL_UTF_MAX > 3
if (UNICODE_OUT_OF_RANGE(ch)) {
ch &= 0x1fffff;
if ((ch == 0xe0001) || ((ch >= 0xe0020) && (ch <= 0xe007f))) {
ch &= 0x1FFFFF;
if ((ch == 0xE0001) || ((ch >= 0xE0020) && (ch <= 0xE007f))) {
return 1;
}
if ((ch >= 0xf0000) && ((ch & 0xffff) <= 0xfffd)) {
if ((ch >= 0xF0000) && ((ch & 0xFFFF) <= 0xFFFD)) {
return 1;
}
return 0;
@@ -1463,8 +1574,8 @@ Tcl_UniCharIsGraph(
{
#if TCL_UTF_MAX > 3
if (UNICODE_OUT_OF_RANGE(ch)) {
ch &= 0x1fffff;
return (ch >= 0xe0100) && (ch <= 0xe01ef);
ch &= 0x1FFFFF;
return (ch >= 0xE0100) && (ch <= 0xE01EF);
}
#endif
return ((GRAPH_BITS >> GetCategory(ch)) & 1);
@@ -1520,8 +1631,8 @@ Tcl_UniCharIsPrint(
{
#if TCL_UTF_MAX > 3
if (UNICODE_OUT_OF_RANGE(ch)) {
ch &= 0x1fffff;
return (ch >= 0xe0100) && (ch <= 0xe01ef);
ch &= 0x1FFFFF;
return (ch >= 0xE0100) && (ch <= 0xE01EF);
}
#endif
return (((GRAPH_BITS|SPACE_BITS) >> GetCategory(ch)) & 1);
@@ -1577,10 +1688,10 @@ Tcl_UniCharIsSpace(
{
#if TCL_UTF_MAX > 3
/* Ignore upper 11 bits. */
ch &= 0x1fffff;
ch &= 0x1FFFFF;
#else
/* Ignore upper 16 bits. */
ch &= 0xffff;
ch &= 0xFFFF;
#endif
/*
@@ -1594,8 +1705,8 @@ Tcl_UniCharIsSpace(
} else if (UNICODE_OUT_OF_RANGE(ch)) {
return 0;
#endif
} else if (ch == 0x0085 || ch == 0x180e || ch == 0x200b
|| ch == 0x202f || ch == 0x2060 || ch == 0xfeff) {
} else if (ch == 0x0085 || ch == 0x180E || ch == 0x200B
|| ch == 0x202F || ch == 0x2060 || ch == 0xFEFF) {
return 1;
} else {
return ((SPACE_BITS >> GetCategory(ch)) & 1);
@@ -1689,7 +1800,7 @@ Tcl_UniCharCaseMatch(
* characters. */
int nocase) /* 0 for case sensitive, 1 for insensitive */
{
Tcl_UniChar ch1, p;
Tcl_UniChar ch1 = 0, p;
while (1) {
p = *uniPattern;
+389 -117
View File
@@ -107,6 +107,8 @@ static Tcl_ThreadDataKey precisionKey;
static void ClearHash(Tcl_HashTable *tablePtr);
static void FreeProcessGlobalValue(ClientData clientData);
static void FreeThreadHash(ClientData clientData);
static int GetEndOffsetFromObj(Tcl_Obj *objPtr, int endValue,
int *indexPtr);
static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr);
static int SetEndOffsetFromAny(Tcl_Interp *interp,
Tcl_Obj *objPtr);
@@ -974,7 +976,7 @@ Tcl_ScanCountedElement(
int *flagPtr) /* Where to store information to guide
* Tcl_ConvertElement. */
{
int flags = CONVERT_ANY;
char flags = CONVERT_ANY;
int numBytes = TclScanElement(src, length, &flags);
*flagPtr = flags;
@@ -1015,7 +1017,7 @@ int
TclScanElement(
const char *src, /* String to convert to Tcl list element. */
int length, /* Number of bytes in src, or -1. */
int *flagPtr) /* Where to store information to guide
char *flagPtr) /* Where to store information to guide
* Tcl_ConvertElement. */
{
const char *p = src;
@@ -1547,11 +1549,10 @@ Tcl_Merge(
int argc, /* How many strings to merge. */
const char *const *argv) /* Array of string values. */
{
#define LOCAL_SIZE 20
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
#define LOCAL_SIZE 64
char localFlags[LOCAL_SIZE], *flagPtr = NULL;
int i, bytesNeeded = 0;
char *result, *dst;
const int maxFlags = UINT_MAX / sizeof(int);
/*
* Handle empty list case first, so logic of the general case can be
@@ -1570,22 +1571,8 @@ Tcl_Merge(
if (argc <= LOCAL_SIZE) {
flagPtr = localFlags;
} else if (argc > maxFlags) {
/*
* We cannot allocate a large enough flag array to format this list in
* one pass. We could imagine converting this routine to a multi-pass
* implementation, but for sizeof(int) == 4, the limit is a max of
* 2^30 list elements and since each element is at least one byte
* formatted, and requires one byte space between it and the next one,
* that a minimum space requirement of 2^31 bytes, which is already
* INT_MAX. If we tried to format a list of > maxFlags elements, we're
* just going to overflow the size limits on the formatted string
* anyway, so just issue that same panic early.
*/
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
} else {
flagPtr = ckalloc(argc * sizeof(int));
flagPtr = ckalloc(argc);
}
for (i = 0; i < argc; i++) {
flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
@@ -1646,7 +1633,7 @@ Tcl_Backslash(
* src, unless NULL. */
{
char buf[TCL_UTF_MAX];
Tcl_UniChar ch;
Tcl_UniChar ch = 0;
Tcl_UtfBackslash(src, readPtr, buf);
TclUtfToUniChar(buf, &ch);
@@ -1656,11 +1643,46 @@ Tcl_Backslash(
/*
*----------------------------------------------------------------------
*
* TclTrimRight --
* UtfWellFormedEnd --
* Checks the end of utf string is malformed, if yes - wraps bytes
* to the given buffer (as well-formed NTS string). The buffer
* argument should be initialized by the caller and ready to use.
*
* Takes two counted strings in the Tcl encoding which must both be null
* terminated. Conceptually trims from the right side of the first string
* all characters found in the second string.
* Results:
* The bytes with well-formed end of the string.
*
* Side effects:
* Buffer (DString) may be allocated, so must be released.
*
*----------------------------------------------------------------------
*/
static inline const char*
UtfWellFormedEnd(
Tcl_DString *buffer, /* Buffer used to hold well-formed string. */
const char *bytes, /* Pointer to the beginning of the string. */
int length) /* Length of the string. */
{
const char *l = bytes + length;
const char *p = Tcl_UtfPrev(l, bytes);
if (Tcl_UtfCharComplete(p, l - p)) {
return bytes;
}
/*
* Malformed utf-8 end, be sure we've NTS to safe compare of end-character,
* avoid segfault by access violation out of range.
*/
Tcl_DStringAppend(buffer, bytes, length);
return Tcl_DStringValue(buffer);
}
/*
*----------------------------------------------------------------------
*
* TclTrimRight --
* Takes two counted strings in the Tcl encoding. Conceptually
* finds the sub string (offset) to trim from the right side of the
* first string all characters found in the second string.
*
* Results:
* The number of bytes to be removed from the end of the string.
@@ -1671,8 +1693,8 @@ Tcl_Backslash(
*----------------------------------------------------------------------
*/
int
TclTrimRight(
static inline int
TrimRight(
const char *bytes, /* String to be trimmed... */
int numBytes, /* ...and its length in bytes */
const char *trim, /* String of trim characters... */
@@ -1681,18 +1703,6 @@ TclTrimRight(
const char *p = bytes + numBytes;
int pInc;
if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) {
Tcl_Panic("TclTrimRight works only on null-terminated strings");
}
/*
* Empty strings -> nothing to do.
*/
if ((numBytes == 0) || (numTrim == 0)) {
return 0;
}
/*
* Outer loop: iterate over string to be trimmed.
*/
@@ -1733,15 +1743,46 @@ TclTrimRight(
return numBytes - (p - bytes);
}
int
TclTrimRight(
const char *bytes, /* String to be trimmed... */
int numBytes, /* ...and its length in bytes */
const char *trim, /* String of trim characters... */
int numTrim) /* ...and its length in bytes */
{
int res;
Tcl_DString bytesBuf, trimBuf;
/* Empty strings -> nothing to do */
if ((numBytes == 0) || (numTrim == 0)) {
return 0;
}
Tcl_DStringInit(&bytesBuf);
Tcl_DStringInit(&trimBuf);
bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);
res = TrimRight(bytes, numBytes, trim, numTrim);
if (res > numBytes) {
res = numBytes;
}
Tcl_DStringFree(&bytesBuf);
Tcl_DStringFree(&trimBuf);
return res;
}
/*
*----------------------------------------------------------------------
*
* TclTrimLeft --
*
* Takes two counted strings in the Tcl encoding which must both be null
* terminated. Conceptually trims from the left side of the first string
* all characters found in the second string.
* Takes two counted strings in the Tcl encoding. Conceptually
* finds the sub string (offset) to trim from the left side of the
* first string all characters found in the second string.
*
* Results:
* The number of bytes to be removed from the start of the string.
@@ -1752,8 +1793,8 @@ TclTrimRight(
*----------------------------------------------------------------------
*/
int
TclTrimLeft(
static inline int
TrimLeft(
const char *bytes, /* String to be trimmed... */
int numBytes, /* ...and its length in bytes */
const char *trim, /* String of trim characters... */
@@ -1761,18 +1802,6 @@ TclTrimLeft(
{
const char *p = bytes;
if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) {
Tcl_Panic("TclTrimLeft works only on null-terminated strings");
}
/*
* Empty strings -> nothing to do.
*/
if ((numBytes == 0) || (numTrim == 0)) {
return 0;
}
/*
* Outer loop: iterate over string to be trimmed.
*/
@@ -1809,10 +1838,99 @@ TclTrimLeft(
p += pInc;
numBytes -= pInc;
} while (numBytes);
} while (numBytes > 0);
return p - bytes;
}
int
TclTrimLeft(
const char *bytes, /* String to be trimmed... */
int numBytes, /* ...and its length in bytes */
const char *trim, /* String of trim characters... */
int numTrim) /* ...and its length in bytes */
{
int res;
Tcl_DString bytesBuf, trimBuf;
/* Empty strings -> nothing to do */
if ((numBytes == 0) || (numTrim == 0)) {
return 0;
}
Tcl_DStringInit(&bytesBuf);
Tcl_DStringInit(&trimBuf);
bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);
res = TrimLeft(bytes, numBytes, trim, numTrim);
if (res > numBytes) {
res = numBytes;
}
Tcl_DStringFree(&bytesBuf);
Tcl_DStringFree(&trimBuf);
return res;
}
/*
*----------------------------------------------------------------------
*
* TclTrim --
* Finds the sub string (offset) to trim from both sides of the
* first string all characters found in the second string.
*
* Results:
* The number of bytes to be removed from the start of the string
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclTrim(
const char *bytes, /* String to be trimmed... */
int numBytes, /* ...and its length in bytes */
const char *trim, /* String of trim characters... */
int numTrim, /* ...and its length in bytes */
int *trimRight) /* Offset from the end of the string. */
{
int trimLeft;
Tcl_DString bytesBuf, trimBuf;
*trimRight = 0;
/* Empty strings -> nothing to do */
if ((numBytes == 0) || (numTrim == 0)) {
return 0;
}
Tcl_DStringInit(&bytesBuf);
Tcl_DStringInit(&trimBuf);
bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);
trimLeft = TrimLeft(bytes, numBytes, trim, numTrim);
if (trimLeft > numBytes) {
trimLeft = numBytes;
}
numBytes -= trimLeft;
/* have to trim yet (first char was already verified within TrimLeft) */
if (numBytes > 1) {
bytes += trimLeft;
*trimRight = TrimRight(bytes, numBytes, trim, numTrim);
if (*trimRight > numBytes) {
*trimRight = numBytes;
}
}
Tcl_DStringFree(&bytesBuf);
Tcl_DStringFree(&trimBuf);
return trimLeft;
}
/*
*----------------------------------------------------------------------
@@ -1880,30 +1998,20 @@ Tcl_Concat(
result = ckalloc((unsigned) (bytesNeeded + argc));
for (p = result, i = 0; i < argc; i++) {
int trim, elemLength;
int triml, trimr, elemLength;
const char *element;
element = argv[i];
elemLength = strlen(argv[i]);
/*
* Trim away the leading whitespace.
*/
/* Trim away the leading/trailing whitespace. */
triml = TclTrim(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE, &trimr);
element += triml;
elemLength -= triml + trimr;
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
element += trim;
elemLength -= trim;
/*
* Trim away the trailing whitespace. Do not permit trimming to expose
* a final backslash character.
*/
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
trim -= trim && (element[elemLength - trim - 1] == '\\');
elemLength -= trim;
/* Do not permit trimming to expose a final backslash character. */
elemLength += trimr && (element[elemLength - 1] == '\\');
/*
* If we're left with empty element after trimming, do nothing.
@@ -2023,28 +2131,18 @@ Tcl_ConcatObj(
Tcl_SetObjLength(resPtr, 0);
for (i = 0; i < objc; i++) {
int trim;
int triml, trimr;
element = TclGetStringFromObj(objv[i], &elemLength);
/*
* Trim away the leading whitespace.
*/
/* Trim away the leading/trailing whitespace. */
triml = TclTrim(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE, &trimr);
element += triml;
elemLength -= triml + trimr;
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
element += trim;
elemLength -= trim;
/*
* Trim away the trailing whitespace. Do not permit trimming to expose
* a final backslash character.
*/
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
trim -= trim && (element[elemLength - trim - 1] == '\\');
elemLength -= trim;
/* Do not permit trimming to expose a final backslash character. */
elemLength += trimr && (element[elemLength - 1] == '\\');
/*
* If we're left with empty element after trimming, do nothing.
@@ -2545,7 +2643,8 @@ TclStringMatchObj(
udata = Tcl_GetUnicodeFromObj(strObj, &length);
uptn = Tcl_GetUnicodeFromObj(ptnObj, &plen);
match = TclUniCharMatch(udata, length, uptn, plen, flags);
} else if (TclIsPureByteArray(strObj) && !flags) {
} else if (TclIsPureByteArray(strObj) && TclIsPureByteArray(ptnObj)
&& !flags) {
unsigned char *data, *ptn;
data = Tcl_GetByteArrayFromObj(strObj, &length);
@@ -2717,7 +2816,7 @@ Tcl_DStringAppendElement(
{
char *dst = dsPtr->string + dsPtr->length;
int needSpace = TclNeedSpace(dsPtr->string, dst);
int flags = needSpace ? TCL_DONT_QUOTE_HASH : 0;
char flags = needSpace ? TCL_DONT_QUOTE_HASH : 0;
int newSize = dsPtr->length + needSpace
+ TclScanElement(element, -1, &flags);
@@ -3545,22 +3644,27 @@ TclFormatInt(
*
* TclGetIntForIndex --
*
* This function returns an integer corresponding to the list index held
* in a Tcl object. The Tcl object's value is expected to be in the
* format integer([+-]integer)? or the format end([+-]integer)?.
*
* Results:
* The return value is normally TCL_OK, which means that the index was
* successfully stored into the location referenced by "indexPtr". If the
* Tcl object referenced by "objPtr" has the value "end", the value
* stored is "endValue". If "objPtr"s values is not of one of the
* expected formats, TCL_ERROR is returned and, if "interp" is non-NULL,
* an error message is left in the interpreter's result object.
*
* Side effects:
* The object referenced by "objPtr" might be converted to an integer,
* wide integer, or end-based-index object.
* Provides an integer corresponding to the list index held in a Tcl
* object. The string value 'objPtr' is expected have the format
* integer([+-]integer)? or end([+-]integer)?.
*
* Value
* TCL_OK
*
* The index is stored at the address given by by 'indexPtr'. If
* 'objPtr' has the value "end", the value stored is 'endValue'.
*
* TCL_ERROR
*
* The value of 'objPtr' does not have one of the expected formats. If
* 'interp' is non-NULL, an error message is left in the interpreter's
* result object.
*
* Effect
*
* The object referenced by 'objPtr' is converted, as needed, to an
* integer, wide integer, or end-based-index object.
*
*----------------------------------------------------------------------
*/
@@ -3584,13 +3688,7 @@ TclGetIntForIndex(
return TCL_OK;
}
if (SetEndOffsetFromAny(NULL, objPtr) == TCL_OK) {
/*
* If the object is already an offset from the end of the list, or can
* be converted to one, use it.
*/
*indexPtr = endValue + objPtr->internalRep.longValue;
if (GetEndOffsetFromObj(objPtr, endValue, indexPtr) == TCL_OK) {
return TCL_OK;
}
@@ -3690,6 +3788,41 @@ UpdateStringOfEndOffset(
objPtr->length = len;
}
/*
*----------------------------------------------------------------------
*
* GetEndOffsetFromObj --
*
* Look for a string of the form "end[+-]offset" and convert it to an
* internal representation holding the offset.
*
* Results:
* Tcl return code.
*
* Side effects:
* May store a Tcl_ObjType.
*
*----------------------------------------------------------------------
*/
static int
GetEndOffsetFromObj(
Tcl_Obj *objPtr, /* Pointer to the object to parse */
int endValue, /* The value to be stored at "indexPtr" if
* "objPtr" holds "end". */
int *indexPtr) /* Location filled in with an integer
* representing an index. */
{
if (SetEndOffsetFromAny(NULL, objPtr) != TCL_OK) {
return TCL_ERROR;
}
/* TODO: Handle overflow cases sensibly */
*indexPtr = endValue + (int)objPtr->internalRep.longValue;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
@@ -3759,6 +3892,8 @@ SetEndOffsetFromAny(
return TCL_ERROR;
}
if (bytes[3] == '-') {
/* TODO: Review overflow concerns here! */
offset = -offset;
}
} else {
@@ -3787,6 +3922,143 @@ SetEndOffsetFromAny(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclIndexEncode --
*
* Parse objPtr to determine if it is an index value. Two cases
* are possible. The value objPtr might be parsed as an absolute
* index value in the C signed int range. Note that this includes
* index values that are integers as presented and it includes index
* arithmetic expressions. The absolute index values that can be
* directly meaningful as an index into either a list or a string are
* those integer values >= TCL_INDEX_START (0)
* and < TCL_INDEX_AFTER (INT_MAX).
* The largest string supported in Tcl 8 has bytelength INT_MAX.
* This means the largest supported character length is also INT_MAX,
* and the index of the last character in a string of length INT_MAX
* is INT_MAX-1.
*
* Any absolute index value parsed outside that range is encoded
* using the before and after values passed in by the
* caller as the encoding to use for indices that are either
* less than or greater than the usable index range. TCL_INDEX_AFTER
* is available as a good choice for most callers to use for
* after. Likewise, the value TCL_INDEX_BEFORE is good for
* most callers to use for before. Other values are possible
* when the caller knows it is helpful in producing its own behavior
* for indices before and after the indexed item.
*
* A token can also be parsed as an end-relative index expression.
* All end-relative expressions that indicate an index larger
* than end (end+2, end--5) point beyond the end of the indexed
* collection, and can be encoded as after. The end-relative
* expressions that indicate an index less than or equal to end
* are encoded relative to the value TCL_INDEX_END (-2). The
* index "end" is encoded as -2, down to the index "end-0x7ffffffe"
* which is encoded as INT_MIN. Since the largest index into a
* string possible in Tcl 8 is 0x7ffffffe, the interpretation of
* "end-0x7ffffffe" for that largest string would be 0. Thus,
* if the tokens "end-0x7fffffff" or "end+-0x80000000" are parsed,
* they can be encoded with the before value.
*
* These details will require re-examination whenever string and
* list length limits are increased, but that will likely also
* mean a revised routine capable of returning Tcl_WideInt values.
*
* Returns:
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
*
* Side effects:
* When TCL_OK is returned, the encoded index value is written
* to *indexPtr.
*
*----------------------------------------------------------------------
*/
int
TclIndexEncode(
Tcl_Interp *interp, /* For error reporting, may be NULL */
Tcl_Obj *objPtr, /* Index value to parse */
int before, /* Value to return for index before beginning */
int after, /* Value to return for index after end */
int *indexPtr) /* Where to write the encoded answer, not NULL */
{
int idx;
if (TCL_OK == TclGetIntFromObj(NULL, objPtr, &idx)) {
/* We parsed a value in the range INT_MIN...INT_MAX */
integerEncode:
if (idx < TCL_INDEX_START) {
/* All negative absolute indices are "before the beginning" */
idx = before;
} else if (idx == INT_MAX) {
/* This index value is always "after the end" */
idx = after;
}
/* usual case, the absolute index value encodes itself */
} else if (TCL_OK == GetEndOffsetFromObj(objPtr, 0, &idx)) {
/*
* We parsed an end+offset index value.
* idx holds the offset value in the range INT_MIN...INT_MAX.
*/
if (idx > 0) {
/*
* All end+postive or end-negative expressions
* always indicate "after the end".
*/
idx = after;
} else if (idx < INT_MIN - TCL_INDEX_END) {
/* These indices always indicate "before the beginning */
idx = before;
} else {
/* Encoded end-positive (or end+negative) are offset */
idx += TCL_INDEX_END;
}
/* TODO: Consider flag to suppress repeated end-offset parse. */
} else if (TCL_OK == TclGetIntForIndexM(interp, objPtr, 0, &idx)) {
/*
* Only reach this case when the index value is a
* constant index arithmetic expression, and idx
* holds the result. Treat it the same as if it were
* parsed as an absolute integer value.
*/
goto integerEncode;
} else {
return TCL_ERROR;
}
*indexPtr = idx;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclIndexDecode --
*
* Decodes a value previously encoded by TclIndexEncode. The argument
* endValue indicates what value of "end" should be used in the
* decoding.
*
* Results:
* The decoded index value.
*
*----------------------------------------------------------------------
*/
int
TclIndexDecode(
int encoded, /* Value to decode */
int endValue) /* Meaning of "end" to use, > TCL_INDEX_END */
{
if (encoded <= TCL_INDEX_END) {
return (encoded - TCL_INDEX_END) + endValue;
}
return encoded;
}
/*
*----------------------------------------------------------------------
*
+510 -559
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -203,7 +203,7 @@ proc auto_mkindex {dir args} {
}
auto_mkindex_parser::init
foreach file [glob -- {*}$args] {
foreach file [lsort [glob -- {*}$args]] {
try {
append index [auto_mkindex_parser::mkindex $file]
} on error {msg opts} {
@@ -236,7 +236,7 @@ proc auto_mkindex_old {dir args} {
if {![llength $args]} {
set args *.tcl
}
foreach file [glob -- {*}$args] {
foreach file [lsort [glob -- {*}$args]] {
set f ""
set error [catch {
set f [open $file]
+2673 -239
View File
File diff suppressed because it is too large Load Diff
+2179 -335
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,2 +1,2 @@
if {![package vsatisfies [package provide Tcl] 8.6-]} {return}
package ifneeded http 2.8.11 [list tclPkgSetup $dir http 2.8.11 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]
package ifneeded http 2.9.0 [list tclPkgSetup $dir http 2.9.0 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]
+70 -88
View File
@@ -16,7 +16,7 @@
if {[info commands package] == ""} {
error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]"
}
package require -exact Tcl 8.6.6
package require -exact Tcl 8.6.8
# Compute the auto path to use in this interpreter.
# The values on the path come from several locations:
@@ -45,7 +45,6 @@ if {![info exists auto_path]} {
set auto_path ""
}
}
namespace eval tcl {
variable Dir
foreach Dir [list $::tcl_library [file dirname $::tcl_library]] {
@@ -67,12 +66,12 @@ namespace eval tcl {
}
if {![interp issafe]} {
variable Path [encoding dirs]
set Dir [file join $::tcl_library encoding]
if {$Dir ni $Path} {
variable Path [encoding dirs]
set Dir [file join $::tcl_library encoding]
if {$Dir ni $Path} {
lappend Path $Dir
encoding dirs $Path
}
}
}
# TIP #255 min and max functions
@@ -156,17 +155,6 @@ if {(![interp issafe]) && ($tcl_platform(platform) eq "windows")} {
if {[interp issafe]} {
package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
} else {
# Default known auto_index (avoid loading auto index implicit after interp create):
array set ::auto_index {
::tcl::tm::UnknownHandler {source [info library]/tm.tcl}
::tclPkgUnknown {source [info library]/package.tcl}
::history {source [info library]/history.tcl}
}
# The newest possibility to load whole namespace:
array set ::auto_index_ns {}
# Set up search for Tcl Modules (TIP #189).
# and setup platform specific unknown package handlers
if {$tcl_platform(os) eq "Darwin"
@@ -179,21 +167,22 @@ if {[interp issafe]} {
# Set up the 'clock' ensemble
proc clock args {
set cmdmap [dict create]
foreach cmd {add clicks format microseconds milliseconds scan seconds configure} {
dict set cmdmap $cmd ::tcl::clock::$cmd
}
namespace inscope ::tcl::clock [list namespace ensemble create -command \
[uplevel 1 [list ::namespace origin [::lindex [info level 0] 0]]] \
-map $cmdmap -compile 1]
namespace eval ::tcl::clock [list variable TclLibDir $::tcl_library]
uplevel 1 [info level 0]
proc ::tcl::initClock {} {
# Auto-loading stubs for 'clock.tcl'
foreach cmd {add format scan} {
proc ::tcl::clock::$cmd args {
variable TclLibDir
source -encoding utf-8 [file join $TclLibDir clock.tcl]
return [uplevel 1 [info level 0]]
}
}
rename ::tcl::initClock {}
}
# Auto-loading stubs for 'clock.tcl'
set ::auto_index_ns(::tcl::clock) {::namespace inscope ::tcl::clock {
::source -encoding utf-8 [::file join [info library] clock.tcl]
}}
::tcl::initClock
}
# Conditionalize for presence of exec.
@@ -295,14 +284,9 @@ proc unknown args {
}
append cinfo ...
}
append cinfo "\"\n (\"uplevel\" body line 1)"
append cinfo "\n invoked from within"
append cinfo "\n\"uplevel 1 \$args\""
#
# Try each possible form of the stack trace
# and trim the extra contribution from the matching case
#
set expect "$msg\n while executing\n\"$cinfo"
set tail "\n (\"uplevel\" body line 1)\n invoked\
from within\n\"uplevel 1 \$args\""
set expect "$msg\n while executing\n\"$cinfo\"$tail"
if {$errInfo eq $expect} {
#
# The stack has only the eval from the expanded command
@@ -316,21 +300,32 @@ proc unknown args {
# Stack trace is nested, trim off just the contribution
# from the extra "eval" of $args due to the "catch" above.
#
set expect "\n invoked from within\n\"$cinfo"
set exlen [string length $expect]
set eilen [string length $errInfo]
set i [expr {$eilen - $exlen - 1}]
set einfo [string range $errInfo 0 $i]
#
# For now verify that $errInfo consists of what we are about
# to return plus what we expected to trim off.
#
if {$errInfo ne "$einfo$expect"} {
error "Tcl bug: unexpected stack trace in \"unknown\"" {} \
[list CORE UNKNOWN BADTRACE $einfo $expect $errInfo]
set last [string last $tail $errInfo]
if {$last + [string length $tail] != [string length $errInfo]} {
# Very likely cannot happen
return -options $opts $msg
}
return -code error -errorcode $errCode \
-errorinfo $einfo $msg
set errInfo [string range $errInfo 0 $last-1]
set tail "\"$cinfo\""
set last [string last $tail $errInfo]
if {$last + [string length $tail] != [string length $errInfo]} {
return -code error -errorcode $errCode \
-errorinfo $errInfo $msg
}
set errInfo [string range $errInfo 0 $last-1]
set tail "\n invoked from within\n"
set last [string last $tail $errInfo]
if {$last + [string length $tail] == [string length $errInfo]} {
return -code error -errorcode $errCode \
-errorinfo [string range $errInfo 0 $last-1] $msg
}
set tail "\n while executing\n"
set last [string last $tail $errInfo]
if {$last + [string length $tail] == [string length $errInfo]} {
return -code error -errorcode $errCode \
-errorinfo [string range $errInfo 0 $last-1] $msg
}
return -options $opts $msg
} else {
dict incr opts -level
return -options $opts $msg
@@ -421,22 +416,18 @@ proc unknown args {
# for instance. If not given, namespace current is used.
proc auto_load {cmd {namespace {}}} {
global auto_index auto_index_ns auto_path
global auto_index auto_path
# qualify names:
if {$namespace eq ""} {
set namespace [uplevel 1 [list ::namespace current]]
}
set nameList [auto_qualify $cmd $namespace]
# workaround non canonical auto_index entries that might be around
# from older auto_mkindex versions
if {$cmd ni $nameList} {lappend nameList $cmd}
# try to load (and create sub-cmd handler "_sub_load_cmd" for further usage):
foreach name $nameList [set _sub_load_cmd {
# via auto_index:
lappend nameList $cmd
foreach name $nameList {
if {[info exists auto_index($name)]} {
namespace inscope :: $auto_index($name)
namespace eval :: $auto_index($name)
# There's a couple of ways to look for a command of a given
# name. One is to use
# info commands $name
@@ -448,31 +439,22 @@ proc auto_load {cmd {namespace {}}} {
return 1
}
}
# via auto_index_ns - resolver for the whole namespace loaders
if {[set ns [::namespace qualifiers $name]] ni {"" "::"} &&
[info exists auto_index_ns($ns)]
} {
# remove handler before loading (prevents several self-recursion cases):
set ldr $auto_index_ns($ns); unset auto_index_ns($ns)
namespace inscope :: $ldr
# if got it:
}
if {![info exists auto_path]} {
return 0
}
if {![auto_load_index]} {
return 0
}
foreach name $nameList {
if {[info exists auto_index($name)]} {
namespace eval :: $auto_index($name)
if {[namespace which -command $name] ne ""} {
return 1
}
}
}]
# load auto_index if possible:
if {![info exists auto_path]} {
return 0
}
if {![auto_load_index]} {
return 0
}
# try again (something new could be loaded):
foreach name $nameList $_sub_load_cmd
return 0
}
@@ -619,12 +601,12 @@ proc auto_import {pattern} {
auto_load_index
foreach pattern $patternList {
foreach name [array names auto_index $pattern] {
if {([namespace which -command $name] eq "")
foreach name [array names auto_index $pattern] {
if {([namespace which -command $name] eq "")
&& ([namespace qualifiers $pattern] eq [namespace qualifiers $name])} {
namespace inscope :: $auto_index($name)
}
}
namespace eval :: $auto_index($name)
}
}
}
}
@@ -642,7 +624,7 @@ proc auto_import {pattern} {
if {$tcl_platform(platform) eq "windows"} {
# Windows version.
#
# Note that info executable doesn't work under Windows, so we have to
# Note that file executable doesn't work under Windows, so we have to
# look for files with .exe, .com, or .bat extensions. Also, the path
# may be in the Path or PATH environment variables, and path
# components are separated with semicolons, not colons as under Unix.
@@ -655,8 +637,8 @@ proc auto_execok name {
}
set auto_execs($name) ""
set shellBuiltins [list cls copy date del dir echo erase md mkdir \
mklink rd ren rename rmdir start time type ver vol]
set shellBuiltins [list assoc cls copy date del dir echo erase ftype \
md mkdir mklink move rd ren rename rmdir start time type ver vol]
if {[info exists env(PATHEXT)]} {
# Add an initial ; to have the {} extension check first.
set execExtensions [split ";$env(PATHEXT)" ";"]
+1 -1
View File
@@ -14,7 +14,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.6.0
package provide msgcat 1.6.1
namespace eval msgcat {
namespace export mc mcexists mcload mclocale mcmax mcmset mcpreferences mcset\
+2 -2
View File
@@ -1,2 +1,2 @@
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded msgcat 1.6.0 [list source [file join $dir msgcat.tcl]]
if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded msgcat 1.6.1 [list source [file join $dir msgcat.tcl]]
+2 -2
View File
@@ -1,9 +1,9 @@
if {([info commands ::tcl::pkgconfig] eq "")
|| ([info sharedlibextension] ne ".dll")} return
if {[::tcl::pkgconfig get debug]} {
package ifneeded registry 1.3.2 \
package ifneeded registry 1.3.3 \
[list load [file join $dir tclreg13g.dll] registry]
} else {
package ifneeded registry 1.3.2 \
package ifneeded registry 1.3.3 \
[list load [file join $dir tclreg13.dll] registry]
}
+1 -1
View File
@@ -9,4 +9,4 @@
# full path name of this file's directory.
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded tcltest 2.4.0 [list source [file join $dir tcltest.tcl]]
package ifneeded tcltest 2.4.1 [list source [file join $dir tcltest.tcl]]

Some files were not shown because too many files have changed in this diff Show More