Compare commits
335
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f85eb13554 | ||
|
|
50eb79b797 | ||
|
|
dd66ab423e | ||
|
|
7600da9e6c | ||
|
|
a1300ad826 | ||
|
|
fea0c84f2f | ||
|
|
25fb9a6a54 | ||
|
|
baf1eb36e4 | ||
|
|
6c22f6b730 | ||
|
|
2071be71b1 | ||
|
|
9cf727affb | ||
|
|
5140d2419c | ||
|
|
d716e3bd57 | ||
|
|
02f302c8cf | ||
|
|
9ef860c58c | ||
|
|
702bb9ab89 | ||
|
|
a7e21b7c56 | ||
|
|
6b77d746e1 | ||
|
|
7e152743be | ||
|
|
0513ad381a | ||
|
|
b37dff78c1 | ||
|
|
103eb015c0 | ||
|
|
73519e9804 | ||
|
|
2867ac2637 | ||
|
|
3d0413417d | ||
|
|
56d50aec7c | ||
|
|
b1ee2de573 | ||
|
|
5d5b5a4242 | ||
|
|
c8ff4cae81 | ||
|
|
6104a20928 | ||
|
|
b87d0095dc | ||
|
|
4632c037e3 | ||
|
|
28c9edc49b | ||
|
|
614c8b3360 | ||
|
|
a4f289d5b5 | ||
|
|
75bdb75689 | ||
|
|
13f6f72bb7 | ||
|
|
af838a5d52 | ||
|
|
8091425c93 | ||
|
|
4c03aeaadd | ||
|
|
69ae2a0f03 | ||
|
|
7988b3f1b6 | ||
|
|
827a1d3802 | ||
|
|
0657f97bc5 | ||
|
|
6598d2eeae | ||
|
|
29225e440c | ||
|
|
231fd112f9 | ||
|
|
70a3d08fc4 | ||
|
|
c7771a763e | ||
|
|
6c1bdd15d6 | ||
|
|
9a6a7030e8 | ||
|
|
633171eda9 | ||
|
|
2acd355f8d | ||
|
|
73ff912a1f | ||
|
|
b9722ec356 | ||
|
|
f3f254e8ba | ||
|
|
f1e62884ba | ||
|
|
e18d096bd7 | ||
|
|
54a1d7e517 | ||
|
|
c6cce703b5 | ||
|
|
f19e2665d3 | ||
|
|
96d441c29a | ||
|
|
72dfeb60e2 | ||
|
|
b27acbe84f | ||
|
|
1b8701ee3d | ||
|
|
83d22bd1f6 | ||
|
|
861c6c226a | ||
|
|
b0bd6fc251 | ||
|
|
6643ceb141 | ||
|
|
16a75f3cbf | ||
|
|
ed8816500e | ||
|
|
5ef48eba53 | ||
|
|
ee48919fcc | ||
|
|
d6a3425ec6 | ||
|
|
b0f19e41f2 | ||
|
|
00dd4a5b56 | ||
|
|
ac555b905c | ||
|
|
5990382222 | ||
|
|
c7e670b85f | ||
|
|
86e88cf233 | ||
|
|
e47cbdc798 | ||
|
|
a5297cf7c3 | ||
|
|
32ffe00c48 | ||
|
|
8f8a3bc1c0 | ||
|
|
a038d4aad3 | ||
|
|
17c92b0a7a | ||
|
|
4eb91b8e5b | ||
|
|
ebcc04616c | ||
|
|
50dde26caf | ||
|
|
6fa73194d5 | ||
|
|
49c4458a25 | ||
|
|
02563b1911 | ||
|
|
54e89ec231 | ||
|
|
8074bcec5e | ||
|
|
4db805463e | ||
|
|
45dd8baf76 | ||
|
|
f6f92fd671 | ||
|
|
f2f41b4b85 | ||
|
|
db43c8cbed | ||
|
|
062f4d0529 | ||
|
|
48d6b3d84c | ||
|
|
aafa141509 | ||
|
|
d6ed36f134 | ||
|
|
14d2bc5415 | ||
|
|
36cebb89fe | ||
|
|
4fa1fa29ae | ||
|
|
6fbc88e2a0 | ||
|
|
87ff0e4ee2 | ||
|
|
847fdd28f7 | ||
|
|
01e71bb26c | ||
|
|
ce00b07d6b | ||
|
|
363a6cc4cd | ||
|
|
180af1f9a5 | ||
|
|
c03808607b | ||
|
|
6c604517d7 | ||
|
|
6802927d5c | ||
|
|
c0c0164a71 | ||
|
|
284a501487 | ||
|
|
909827f9ee | ||
|
|
293c1ff559 | ||
|
|
e95d2eea7f | ||
|
|
2e02e1affd | ||
|
|
77b454d1b2 | ||
|
|
8f15f09491 | ||
|
|
8d076e6525 | ||
|
|
133b43a521 | ||
|
|
af5bfc68cc | ||
|
|
0d8a08dbf1 | ||
|
|
1a4e52416f | ||
|
|
4dcdd51adb | ||
|
|
73dbbaaa23 | ||
|
|
d162c9a16d | ||
|
|
ce9f04ddd1 | ||
|
|
8f269fcad1 | ||
|
|
67b780c161 | ||
|
|
f4cd60dbb4 | ||
|
|
d0ba759e2c | ||
|
|
3f84674ae3 | ||
|
|
4e92d998eb | ||
|
|
3e05a7babe | ||
|
|
5940356ced | ||
|
|
cc71607cb8 | ||
|
|
405a099384 | ||
|
|
1ea2b16a8d | ||
|
|
f976a32c62 | ||
|
|
92dd14e77c | ||
|
|
3f2bb8a029 | ||
|
|
e51f7da2ee | ||
|
|
af320fb41e | ||
|
|
e2f55284cf | ||
|
|
8a45e47c4c | ||
|
|
4dd7110019 | ||
|
|
881b147ab5 | ||
|
|
b583ea7360 | ||
|
|
d40bb9d13a | ||
|
|
688c125ec3 | ||
|
|
06cc962945 | ||
|
|
88760a8a81 | ||
|
|
aa4247d47b | ||
|
|
81b4fa2fbd | ||
|
|
7b688527d7 | ||
|
|
41aa17e389 | ||
|
|
84d939b69a | ||
|
|
60ba166da0 | ||
|
|
2dccd2a567 | ||
|
|
df75b91956 | ||
|
|
43b5729ddf | ||
|
|
1f5d09b497 | ||
|
|
eb23b011d0 | ||
|
|
03d0f99e6c | ||
|
|
694c4505cd | ||
|
|
28e5ec7db6 | ||
|
|
fea912c676 | ||
|
|
7555420166 | ||
|
|
10c71dc8b9 | ||
|
|
530e4b3bb9 | ||
|
|
b6bc736eee | ||
|
|
fe84f70800 | ||
|
|
c77055a803 | ||
|
|
3b426fffa1 | ||
|
|
782009ca67 | ||
|
|
e1f2905dbc | ||
|
|
dd6950d635 | ||
|
|
c3cb435cf4 | ||
|
|
6c4b78cfa8 | ||
|
|
75eea66ef7 | ||
|
|
251211e714 | ||
|
|
e313582726 | ||
|
|
a06189323f | ||
|
|
93f06f4469 | ||
|
|
6c973cf9a2 | ||
|
|
e393e2694c | ||
|
|
1645895629 | ||
|
|
ef51b5aacd | ||
|
|
905633199c | ||
|
|
4d289b8084 | ||
|
|
85a2a91729 | ||
|
|
947e3f8405 | ||
|
|
ad7deae634 | ||
|
|
1a819d1063 | ||
|
|
a6d654980e | ||
|
|
2fae9f1746 | ||
|
|
5eb2064b63 | ||
|
|
7f433932f6 | ||
|
|
2e9301202d | ||
|
|
8bfaaa8337 | ||
|
|
175931c905 | ||
|
|
18f61eeeeb | ||
|
|
54b8f46097 | ||
|
|
372bf74334 | ||
|
|
f9f1724b36 | ||
|
|
cd51753d86 | ||
|
|
f227a5d1ff | ||
|
|
5ddcd8fea9 | ||
|
|
fe4e51b427 | ||
|
|
bd259695f1 | ||
|
|
e5eeaadf3c | ||
|
|
3aaf8c0544 | ||
|
|
76130df460 | ||
|
|
da6df4adde | ||
|
|
1ddccee9d3 | ||
|
|
48570b93a6 | ||
|
|
025b74f7c7 | ||
|
|
51043c29db | ||
|
|
553caf0d2c | ||
|
|
87e417c1a1 | ||
|
|
e95eb57666 | ||
|
|
3a9a817f67 | ||
|
|
277effbc04 | ||
|
|
9f102b5b85 | ||
|
|
642792b1c2 | ||
|
|
ef5af05366 | ||
|
|
439a4360b3 | ||
|
|
321bff2cd5 | ||
|
|
d252076f75 | ||
|
|
26c9f5e773 | ||
|
|
466e7c47c6 | ||
|
|
eb3390224b | ||
|
|
f5125db22b | ||
|
|
6ca1315df1 | ||
|
|
b807564e68 | ||
|
|
0c2d0f0ab7 | ||
|
|
2fb58dc372 | ||
|
|
2c78daa2b0 | ||
|
|
02c0281379 | ||
|
|
dcb3b835e4 | ||
|
|
e027188168 | ||
|
|
c4c090889c | ||
|
|
01570cabab | ||
|
|
182b7f85f6 | ||
|
|
e1b3b51a8f | ||
|
|
23dd40e1a2 | ||
|
|
9af2fb9efe | ||
|
|
1a7bbea40c | ||
|
|
aec3f90f4d | ||
|
|
198dbe0117 | ||
|
|
19eccf461d | ||
|
|
ca96bc096f | ||
|
|
034957707a | ||
|
|
ce003df1ca | ||
|
|
63e2ca9905 | ||
|
|
9512351bc5 | ||
|
|
ce353e21ed | ||
|
|
fb61224892 | ||
|
|
f10942c112 | ||
|
|
62e806dc83 | ||
|
|
9831556bf7 | ||
|
|
9586d2f54c | ||
|
|
800f0a1edf | ||
|
|
2aed8b1bdf | ||
|
|
304ca9a172 | ||
|
|
d7fdb20ed5 | ||
|
|
6e4c20e3a6 | ||
|
|
704627190d | ||
|
|
a8075a956d | ||
|
|
ab1a8089de | ||
|
|
9c35850e30 | ||
|
|
55bb2e9be3 | ||
|
|
0033456148 | ||
|
|
ce60562f86 | ||
|
|
aad734db91 | ||
|
|
c1ebc6273f | ||
|
|
e08e3fbc09 | ||
|
|
c52403ad33 | ||
|
|
2b343d0207 | ||
|
|
5363b1f11f | ||
|
|
b49efc9ae0 | ||
|
|
7fe77d7ff8 | ||
|
|
f54d9a7c69 | ||
|
|
9832ae4232 | ||
|
|
388bc52075 | ||
|
|
2c039a780e | ||
|
|
5c70426f61 | ||
|
|
d2fa0702bc | ||
|
|
530d3a7f83 | ||
|
|
f98272ec1e | ||
|
|
ba64c646ee | ||
|
|
528b7b7168 | ||
|
|
0fbdd463cb | ||
|
|
dd1dc3c6e8 | ||
|
|
4a3c559932 | ||
|
|
cc185b1d76 | ||
|
|
2ef45b0593 | ||
|
|
b6ce0622a6 | ||
|
|
136b650bda | ||
|
|
65b685deca | ||
|
|
0865a0b6b0 | ||
|
|
79260bd695 | ||
|
|
1a062775d2 | ||
|
|
a855be143c | ||
|
|
5e07595538 | ||
|
|
5ed49bbc61 | ||
|
|
fa0c0e6134 | ||
|
|
f3b329dd28 | ||
|
|
496cff3ee1 | ||
|
|
0f93742804 | ||
|
|
7dd7fe1b6c | ||
|
|
bfcd8d392a | ||
|
|
004c1e1c8e | ||
|
|
99145db40b | ||
|
|
2569d6f81c | ||
|
|
dafa1487f9 | ||
|
|
743e0e4e1a | ||
|
|
8249e877df | ||
|
|
b308bd97e6 | ||
|
|
ae24dd87fa | ||
|
|
995eed36fd | ||
|
|
c4f94adb46 | ||
|
|
d4b3d3a460 | ||
|
|
6eb109c913 | ||
|
|
edb3a561eb | ||
|
|
c15b6135d5 | ||
|
|
a7a226fc49 | ||
|
|
76c3874ad8 | ||
|
|
c0eed541eb |
@@ -1,5 +1,11 @@
|
||||
name: Linux
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "core-8-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
name: macOS
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "core-8-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
name: Build Binaries
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "core-8-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
name: Windows
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "core-8-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
|
||||
-2634
File diff suppressed because it is too large
Load Diff
-2539
File diff suppressed because it is too large
Load Diff
-3629
File diff suppressed because it is too large
Load Diff
-4741
File diff suppressed because it is too large
Load Diff
-3349
File diff suppressed because it is too large
Load Diff
-4619
File diff suppressed because it is too large
Load Diff
-3822
File diff suppressed because it is too large
Load Diff
-5921
File diff suppressed because it is too large
Load Diff
-3796
File diff suppressed because it is too large
Load Diff
@@ -4650,7 +4650,7 @@ threading may still cause problems on AIX. (hobbs)
|
||||
9/21/99 (bug fix) fixed bug when setting array in non-existent
|
||||
namespace. [Bug: 2613] (hobbs)
|
||||
|
||||
--- Released 8.2.1, October 04, 1999 --- See ChangeLog for details ---
|
||||
--- Released 8.2.1, October 04, 1999
|
||||
|
||||
10/30/99 (feature enhancement) new regexp engine from Henry Spencer
|
||||
was patched in - should greatly reduce stack space usage. (spencer)
|
||||
@@ -4680,7 +4680,7 @@ when indexing into one (test case string-5.16) [Bug: 2871] (hobbs)
|
||||
|
||||
10/30/99 (bug fix) fixes for mac UTF filename handling (ingham)
|
||||
|
||||
--- Released 8.2.2, November 04, 1999 --- See ChangeLog for details ---
|
||||
--- Released 8.2.2, November 04, 1999
|
||||
|
||||
11/19/99 (feature enhancement) bug fixes for http package as well as
|
||||
patch required by TLS (SSL) extension that adds http::(un)register
|
||||
@@ -4705,7 +4705,7 @@ atexit handlers.
|
||||
12/07/99 (bug fix) fixes for 'expr + {[incr]}' and 'expr + {[error]}'
|
||||
cases (different causes).
|
||||
|
||||
--- Released 8.2.3, December 16, 1999 --- See ChangeLog for details ---
|
||||
--- Released 8.2.3, December 16, 1999
|
||||
|
||||
1999-09-14 (feature enhancement) added -start switch to regexp and regsub.
|
||||
|
||||
@@ -4762,7 +4762,7 @@ ExitThread to _endthreadex to prevent 4K mem leak (gravereaux)
|
||||
|
||||
1999-12-21 (bug fix) changed thread ids to longs (for 64bit systems)
|
||||
|
||||
--- Released 8.3b1, December 22, 1999 --- See ChangeLog for details ---
|
||||
--- Released 8.3b1, December 22, 1999
|
||||
|
||||
2000-01-10 (feature enhancement) clock scan now supports the common
|
||||
ISO 8601 date/time formats. See docs for details. (melski)
|
||||
@@ -4788,7 +4788,7 @@ symbolicly (like chmod) in [file attributes $file -permissions ...] (schoebel)
|
||||
2000-01-13 (bug fix) fixed lsort -dictionary problem when sorting
|
||||
characters between 'Z' and 'a' (flawed upper/lower comparison logic) (melski)
|
||||
|
||||
--- Released 8.3b2, January 13, 2000 --- See ChangeLog for details ---
|
||||
--- Released 8.3b2, January 13, 2000
|
||||
|
||||
2000-01-14 (feature enhancement) clock format %Q added, clock scan updated
|
||||
|
||||
@@ -4827,7 +4827,7 @@ mac panic from an error when closing an async socket (steffen, ingham)
|
||||
2000-02-10 (feature enhancement) improved error reporting for failed
|
||||
loads on Windows (dejong, hobbs)
|
||||
|
||||
--- Released 8.3.0, February 10, 2000 --- See ChangeLog for details ---
|
||||
--- Released 8.3.0, February 10, 2000
|
||||
|
||||
2000-03 (bug fixes, feature enhancement) overhaul of http package for
|
||||
proper handling of async callbacks (new options), version is now at 2.3
|
||||
@@ -4870,7 +4870,7 @@ tclLoadDyld.c dl type. (sanchez)
|
||||
2000-04-24 (bug fix) fixed hang in threaded Unix case when backgrounded
|
||||
exec process was running (dejong)
|
||||
|
||||
--- Released 8.3.1, April 26, 2000 --- See ChangeLog for details ---
|
||||
--- Released 8.3.1, April 26, 2000
|
||||
|
||||
2000-04-26 (doc fix) updated/added documentation for many API's and
|
||||
commands (melski)
|
||||
@@ -4920,7 +4920,7 @@ pattern matching for [array names] (gazetta)
|
||||
2000-05-31 (feature enhancement) added -nocomplain and -- flags to
|
||||
[unset] to allow for silent unset operation (hobbs)
|
||||
|
||||
--- Released 8.4a1, June 6, 2000 --- See ChangeLog for details ---
|
||||
--- Released 8.4a1, June 6, 2000
|
||||
|
||||
2000-05-29 (bug fix) corrected resource cleanup in http error cases.
|
||||
Improved handling of error cases in http. (tamhankar)
|
||||
@@ -4959,7 +4959,7 @@ sections. (english)
|
||||
2000-08-07 (bug fix) new man pages memory.n, TCL_MEM_DEBUG.3, Init.3 and
|
||||
DumpActiveMemory.3. (melski)
|
||||
|
||||
--- Released 8.3.2, August 9, 2000 --- See ChangeLog for details ---
|
||||
--- Released 8.3.2, August 9, 2000
|
||||
|
||||
2000-06 thru 2000-11 (build improvements) Added support for mingw (gcc on
|
||||
Windows), AIX-5 and Win64 builds (dejong, hobbs)
|
||||
@@ -5018,7 +5018,7 @@ environment (gravereaux)
|
||||
2000-11-03 (new feature) Tcl_SetMainLoop enables defining an event loop for
|
||||
tclsh. This enables Tk as a truly loadable package. (hobbs)
|
||||
|
||||
--- Released 8.4a2, November 3, 2000 --- See ChangeLog for details ---
|
||||
--- Released 8.4a2, November 3, 2000
|
||||
|
||||
2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that
|
||||
didn't set nonBlocking correctly when resetting the flags for the write
|
||||
@@ -5076,7 +5076,7 @@ Update of READMEs.
|
||||
Corrected IRIX-5* configure (english). Added support for AIX-5 (hobbs).
|
||||
Added support for Win64 (hobbs).
|
||||
|
||||
--- Released 8.3.3, April 6, 2001 --- See ChangeLog for details ---
|
||||
--- Released 8.3.3, April 6, 2001
|
||||
|
||||
2000-11-23 (new feature)[TIP 7] higher resolution timer on Windows (kenny)
|
||||
|
||||
@@ -5150,7 +5150,7 @@ system. This includes the addition of 'file normalize', 'file system',
|
||||
|
||||
* corrected several minor errors noted by Purify (hobbs)
|
||||
|
||||
--- Released 8.4a3, August 6, 2001 --- See ChangeLog for details ---
|
||||
--- Released 8.4a3, August 6, 2001
|
||||
|
||||
2001-06-27 (bug fix)[217987] corrected backslash substitution of non-ASCII
|
||||
characters. (hobbs, riefenstahl)
|
||||
@@ -5256,7 +5256,7 @@ bundles to standard .dylib dynamic libraries like on other unices.
|
||||
2001-10-18 (bug fix) corrected off-by-one-day error in clock scan with
|
||||
relative months and years during swing hours. (lavana)
|
||||
|
||||
--- Released 8.3.4, October 19, 2001 --- See ChangeLog for details ---
|
||||
--- Released 8.3.4, October 19, 2001
|
||||
|
||||
2001-08-21 (bug fix)[219184] overagressive compilation of [catch] (sofer)
|
||||
|
||||
@@ -5282,8 +5282,6 @@ compiles to 0 bytecodes (sofer)
|
||||
|
||||
2001-09-13 (new feature)[TIP 56] Tcl_EvalTokensStandard API (sofer)
|
||||
|
||||
2001-09-13 (new feature) Old ChangeLog entries => ChangeLog.1999 (hobbs)
|
||||
|
||||
2001-09-17 (new feature) compiling with TCL_COMPILE_DEBUG now required to
|
||||
enable all compile and execution tracing (sofer)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
@@ -5368,8 +5366,6 @@ of the Host: header value
|
||||
2002-01-25 (new feature)[496733] socket options -eofchar and -translation
|
||||
return read-only values (dejong)
|
||||
|
||||
2002-01-28 (new feature) Old ChangeLog entries => ChangeLog.20900 (hobbs)
|
||||
|
||||
2002-01-28 (performance enhancement) bytecompiled [regexp] for trivial cases
|
||||
that amount to string matching. Also -nocase and --. (hobbs)
|
||||
|
||||
@@ -5394,7 +5390,7 @@ errored out. (kupries, sofer)
|
||||
|
||||
2002-02-15 (new feature)[TIP 72] support for 64-bit integer values on
|
||||
32-bit platforms and ability to work with >2GiB files. Extends many
|
||||
commands. See ChangeLog and TIP for details.
|
||||
commands. See TIP for details.
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2002-02-22 (bug fix)[476537] Fix panic when loading shared library without
|
||||
@@ -5435,7 +5431,7 @@ of prior Tcl releases. Others will need to be reconciled.
|
||||
related to the handling of iso2022 text and finalization of escape-based
|
||||
encodings. (taguchi, takahashi, hobbs)
|
||||
|
||||
--- Released 8.4a4, March 5, 2002 --- See ChangeLog for details ---
|
||||
--- Released 8.4a4, March 5, 2002
|
||||
|
||||
2002-03-06 (new feature)[TIP 80] expanded [lsearch] options (wilkason, fellows)
|
||||
|
||||
@@ -5545,7 +5541,7 @@ options to configure (max)
|
||||
|
||||
2002-07-03 (bug fix)[577015] [catch] catches even compile errors (sofer)
|
||||
|
||||
--- Released 8.4b1, July 5, 2002 --- See ChangeLog for details ---
|
||||
--- Released 8.4b1, July 5, 2002
|
||||
|
||||
2002-07-08 (bug fix) restored compatibility of [viewFile] in tcltest (porter)
|
||||
|
||||
@@ -5583,7 +5579,7 @@ options to configure (max)
|
||||
Many internal bugs fixed.
|
||||
Considerable cleanup of the test suite.
|
||||
|
||||
--- Released 8.4b2, August 9, 2002 --- See ChangeLog for details ---
|
||||
--- Released 8.4b2, August 9, 2002
|
||||
|
||||
2002-08-20 (new feature) --enable-memdebug configure option (kupries)
|
||||
|
||||
@@ -5598,7 +5594,7 @@ Considerable cleanup of the test suite.
|
||||
|
||||
2002-09-02 (platfrom support) 64-bit compile on HP-11 (martin)
|
||||
|
||||
--- Released 8.4.0, September 10, 2002 --- See ChangeLog for details ---
|
||||
--- Released 8.4.0, September 10, 2002
|
||||
|
||||
2002-09-18 (platform support) Updated support for compiling with Cygwin and
|
||||
either mingw or gcc. (khan, howell, dejong)
|
||||
@@ -5661,7 +5657,7 @@ dirs to tcl_pkgPath: @executable_path/../Frameworks and
|
||||
@executable_path/../PrivateFrameworks (if they exist), as well as the dirs
|
||||
in DYLD_FRAMEWORK_PATH (if set). (steffen)
|
||||
|
||||
--- Released 8.4.1, October 22, 2002 --- See ChangeLog for details ---
|
||||
--- Released 8.4.1, October 22, 2002
|
||||
|
||||
2002-10-28 (bug fix)[627660] [package unknown] chaining for platform specifics
|
||||
|
||||
@@ -5754,7 +5750,7 @@ packages in multiple interps.
|
||||
|
||||
2003-02-27 (bug fix)[694232] stop [lsearch -start 0 {} x] segfault
|
||||
|
||||
--- Released 8.4.2, March 3, 2003 --- See ChangeLog for details ---
|
||||
--- Released 8.4.2, March 3, 2003
|
||||
|
||||
2003-03-06 (bug fix)[699042] Correct case-insensitive unicode string
|
||||
comparison in Tcl_UniCharNcasecmp
|
||||
@@ -5836,7 +5832,7 @@ encoding for the original. Most uses of gb2312 really mean euc-cn.
|
||||
2003-05-14 (bug fix)[736421] Corrected another putenv() copy behavior
|
||||
problem when compiling on Windows and using Microsoft's runtime.
|
||||
|
||||
--- Released 8.4.3, May 20, 2003 --- See ChangeLog for details ---
|
||||
--- Released 8.4.3, May 20, 2003
|
||||
|
||||
2003-05-23 (bug fix)[726018] reverted internals change to the
|
||||
'cmdName' Tcl_ObjType that broke several extensions (TclBlend, e4graph...)
|
||||
@@ -5877,7 +5873,7 @@ Improved documentation, new tests, and some code cleanup.
|
||||
[655300, 720634, 735364, 748700, 756112, 756744, 756951, 758488, 760768,
|
||||
763312, 769895, 771539, 771840, 771947, 771949, 772333]
|
||||
|
||||
--- Released 8.4.4, July 22, 2003 --- See ChangeLog for details ---
|
||||
--- Released 8.4.4, July 22, 2003
|
||||
|
||||
2003-07-23 (bug fix)[775976] fix registry compilation for VC7.
|
||||
|
||||
@@ -5923,7 +5919,7 @@ asked for writable events by the generic layer.
|
||||
2003-11-17 (bug fix)[230589, 504785, 505048, 703709, 840258] fixes to
|
||||
various odd regexp "can't happen" bugs.
|
||||
|
||||
--- Released 8.4.5, November 20, 2003 --- See ChangeLog for details ---
|
||||
--- Released 8.4.5, November 20, 2003
|
||||
|
||||
2003-12-02 (bug fix)[851747] object sharing fix in [binary scan]
|
||||
|
||||
@@ -5960,7 +5956,7 @@ various odd regexp "can't happen" bugs.
|
||||
|
||||
2004-03-01 (platform support)[218561] Allow 64-bit configure on IRIX64-6.5*
|
||||
|
||||
--- Released 8.4.6, March 1, 2004 --- See ChangeLog for details ---
|
||||
--- Released 8.4.6, March 1, 2004
|
||||
|
||||
Changes to 8.5a1 include all changes to the 8.4 line through 8.4.6,
|
||||
plus the following, which focuses on the high-level feature changes
|
||||
@@ -6046,7 +6042,7 @@ in this changeset (new minor version) rather than bug fixes:
|
||||
* [TIP #157] leading {expand} syntax on words to cause argument expansion.
|
||||
This is a safer/cleaner alternative to the use of 'eval'.
|
||||
|
||||
--- Released 8.5a1, March 3, 2004 --- See ChangeLog for details ---
|
||||
--- Released 8.5a1, March 3, 2004
|
||||
|
||||
2004-03-04 (new feature) registry package is [unload]able (thoyts)
|
||||
=> registry 1.1.4
|
||||
@@ -6070,7 +6066,7 @@ each command/interp validity before executing. (sofer)
|
||||
|
||||
2004-04-06 (clean up) refactored Tcl header file #include order. Might
|
||||
create need for changes in extensions that #include private headers.
|
||||
Changed source code files should work with older Tcl as well. See ChangeLog.
|
||||
Changed source code files should work with older Tcl as well.
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2004-04-07 (bug fix)[920667] install into any Unicode path on Win (hobbs)
|
||||
@@ -6346,7 +6342,7 @@ Doc improvements [759545,926590,935853,1017072,1018486,1022527,1027849,
|
||||
1032243,1047928,1048005,1058446,1062647,1065732,1073334,etc.]
|
||||
Test suite expansion [1036649,1001997,etc.]
|
||||
|
||||
--- Released 8.5a2, December 7, 2004 --- See ChangeLog for details ---
|
||||
--- Released 8.5a2, December 7, 2004
|
||||
|
||||
2004-12-13 (bug fix)[1083082] encoding memory leaks (ade,porter)
|
||||
|
||||
@@ -6490,7 +6486,7 @@ Can support [load] from memory as well (steffen)
|
||||
|
||||
Documentation improvements [1075433,1085127,1117017,1124160,1149605,etc.]
|
||||
|
||||
--- Released 8.5a3, June 4, 2005 --- See ChangeLog for details ---
|
||||
--- Released 8.5a3, June 4, 2005
|
||||
|
||||
2005-06-06 (bug fix)[1213678] Windows/gcc: crash in stack.test (kenny)
|
||||
|
||||
@@ -6741,7 +6737,7 @@ removed (steffen)
|
||||
Documentation improvements [1211078,1190891,1292427,1277503,1104682,1359183,
|
||||
1415725,666770]
|
||||
|
||||
--- Released 8.5a4, April 27, 2006 --- See ChangeLog for details ---
|
||||
--- Released 8.5a4, April 27, 2006
|
||||
|
||||
2006-05-04 (bug fix)[1480509] srand() accept wide input (porter,afredd)
|
||||
|
||||
@@ -6837,7 +6833,7 @@ URL validity checking against RFC 2986 (hobbs)
|
||||
|
||||
2006-10-13 (platform support) get stack size on Darwin (steffen)
|
||||
|
||||
--- Released 8.5a5, October 20, 2006 --- See ChangeLog for details ---
|
||||
--- Released 8.5a5, October 20, 2006
|
||||
|
||||
2006-10-20 (configure change) Added autodetection for OS-supplied timezone
|
||||
files (max)
|
||||
@@ -6919,7 +6915,7 @@ upvar and namespace upvar (sofer)
|
||||
|
||||
2007-04-23 (bug fix) fts_open() crash on 64bit Darwin 8 or earlier (steffen)
|
||||
|
||||
--- Released 8.5a6, April 25, 2007 --- See ChangeLog for details ---
|
||||
--- Released 8.5a6, April 25, 2007
|
||||
|
||||
2007-04-30 (bug fix)[1705778] many valgrind-detected leaks corrected
|
||||
|
||||
@@ -7022,7 +7018,7 @@ project for Xcode 3.0 (steffen)
|
||||
(bug fix)[1066755] Several stack efficiency efforts increases recursion limit
|
||||
on Windows to be larger than the default [interp recursionlimit] value
|
||||
|
||||
--- Released 8.5b1, September 26, 2007 --- See ChangeLog for details ---
|
||||
--- Released 8.5b1, September 26, 2007
|
||||
|
||||
2007-10-02 (bug fix)[1806422] proper [tcl::tm::path] autoload (porter)
|
||||
|
||||
@@ -7034,7 +7030,7 @@ on Windows to be larger than the default [interp recursionlimit] value
|
||||
|
||||
2007-10-25 (bug fix)[1726873] intermittent crash in threads (vasiljevic)
|
||||
|
||||
--- Released 8.5b2, October 26, 2007 --- See ChangeLog for details ---
|
||||
--- Released 8.5b2, October 26, 2007
|
||||
|
||||
2007-10-27 (bug fix)[1821159] fixed broken compile on x86_64 (sofer)
|
||||
|
||||
@@ -7070,7 +7066,7 @@ on Windows to be larger than the default [interp recursionlimit] value
|
||||
|
||||
Many significant documentation improvements (fellows, sofer)
|
||||
|
||||
--- Released 8.5b3, November 19, 2007 --- See ChangeLog for details ---
|
||||
--- Released 8.5b3, November 19, 2007
|
||||
|
||||
2007-11-20 (enhancement) string rep of dict has stable order (fellows)
|
||||
|
||||
@@ -7104,7 +7100,7 @@ over-consumption of resources (drewry,lane,ormandy,fellows)
|
||||
|
||||
Several documentation and release notes improvements
|
||||
|
||||
--- Released 8.5.0, December 20, 2007 --- See ChangeLog for details ---
|
||||
--- Released 8.5.0, December 20, 2007
|
||||
|
||||
2007-12-23 (bug fix)[1857126] restore backref support to regexps (hobbs)
|
||||
|
||||
@@ -7126,7 +7122,7 @@ Several documentation and release notes improvements
|
||||
|
||||
Several documentation and release notes improvements
|
||||
|
||||
--- Released 8.5.1, February 5, 2008 --- See ChangeLog for details ---
|
||||
--- Released 8.5.1, February 5, 2008
|
||||
|
||||
2008-02-06 (enhancement) [clock format] performance (kenny)
|
||||
|
||||
@@ -7187,7 +7183,7 @@ variables without "." added to customization hooks (kupries)
|
||||
|
||||
2008-03-27 clock tzdata updated to Olson's tzdata2008b (kenny)
|
||||
|
||||
--- Released 8.5.2, March 28, 2008 --- See ChangeLog for details ---
|
||||
--- Released 8.5.2, March 28, 2008
|
||||
|
||||
2008-03-30 (bug fix)[1783544] more robust TclIsNaN() (kenny,teterin)
|
||||
|
||||
@@ -7242,7 +7238,7 @@ variables without "." added to customization hooks (kupries)
|
||||
|
||||
2008-06-25 (bug fix)[1999119] Support TM packages in Safe Base (kupries)
|
||||
|
||||
--- Released 8.6a1, June 25, 2008 --- See ChangeLog for details ---
|
||||
--- Released 8.6a1, June 25, 2008
|
||||
|
||||
2008-06-29 (bug fix)[2004480] plug memory leaks (ade,porter,steffen)
|
||||
|
||||
@@ -7295,7 +7291,7 @@ in a deleted interp. (porter)
|
||||
|
||||
2008-08-21 (bug fix)[2065115] Restored ***= regexp functioning (hobbs,porter)
|
||||
|
||||
--- Released 8.6a2, August 25, 2008 --- See ChangeLog for details ---
|
||||
--- Released 8.6a2, August 25, 2008
|
||||
|
||||
2008-08-29 (bug fix)[2082299] Install TclOO header files (fellows)
|
||||
|
||||
@@ -7376,7 +7372,7 @@ Tcl_FSFileAttrStringsProc prototype. (nijtmans)
|
||||
|
||||
2008-10-10 (bug fix)[2155658] crash in oo method export (fellows)
|
||||
|
||||
--- Released 8.6a3, October 10, 2008 --- See ChangeLog for details ---
|
||||
--- Released 8.6a3, October 10, 2008
|
||||
|
||||
2008-10-13 (bug fix) Fix ability to join threads on 64-bit Windows (thoyts)
|
||||
|
||||
@@ -7446,7 +7442,7 @@ evaluation in extensions (sofer,kenny)
|
||||
|
||||
2008-12-18 (bug fix)[2444274] panic in long commands from {*} (goth,porter)
|
||||
|
||||
--- Released 8.6b1, December 19, 2008 --- See ChangeLog for details ---
|
||||
--- Released 8.6b1, December 19, 2008
|
||||
|
||||
2008-12-27 [TIP 234] Tcl_Zlib* interface revisions (fellows)
|
||||
*** INCOMPATIBILITY with interface of 8.6b1 ***
|
||||
@@ -7954,7 +7950,7 @@ memory with buffer backup (ferrieux)
|
||||
|
||||
Many more Tcl built-in command errors now set an -errorcode.
|
||||
|
||||
--- Released 8.6b2, August 8, 2011 --- See ChangeLog for details ---
|
||||
--- Released 8.6b2, August 8, 2011
|
||||
|
||||
2011-07-02 (bug fix)[3349507] correct double(1[string repeat 0 23]) (kenny)
|
||||
|
||||
@@ -8115,7 +8111,7 @@ Many revisions to better support a Cygwin environment (nijtmans)
|
||||
|
||||
Dropped support for OS X versions less than 10.4 (Tiger) (fellows)
|
||||
|
||||
--- Released 8.6b3, September 18, 2012 --- See ChangeLog for details ---
|
||||
--- Released 8.6b3, September 18, 2012
|
||||
|
||||
2012-09-20 (enhancement) full Unicode support (nijtmans)
|
||||
=> dde 1.4.0
|
||||
@@ -8162,7 +8158,7 @@ Dropped support for OS X versions less than 10.4 (Tiger) (fellows)
|
||||
|
||||
2012-12-13 (bug fix) crash: [zlib gunzip $data -header noSuchNs::var] (porter)
|
||||
|
||||
--- Released 8.6.0, December 20, 2012 --- See ChangeLog for details ---
|
||||
--- Released 8.6.0, December 20, 2012
|
||||
|
||||
2012-12-22 (bug fix)[3598150] DString to Tcl_Obj memleak (afredd)
|
||||
|
||||
|
||||
+1
-2
@@ -28,9 +28,8 @@ opendir(
|
||||
if ((fd = open(myname, 0, 0)) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
dirp = (DIR *) Tcl_Alloc(sizeof(DIR));
|
||||
dirp = (DIR *) Tcl_AttemptAlloc(sizeof(DIR));
|
||||
if (dirp == NULL) {
|
||||
/* unreachable? */
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+5
-1
@@ -156,7 +156,11 @@ waitpid(
|
||||
goto waitAgain;
|
||||
}
|
||||
}
|
||||
waitPtr = (WaitInfo *) Tcl_Alloc(sizeof(WaitInfo));
|
||||
waitPtr = (WaitInfo *) Tcl_AttemptAlloc(sizeof(WaitInfo));
|
||||
if (!waitPtr) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
waitPtr->pid = result;
|
||||
waitPtr->status = status;
|
||||
waitPtr->nextPtr = deadList;
|
||||
|
||||
@@ -67,9 +67,6 @@ The \fB\-errorcode\fR return option will be set to this value.
|
||||
.AP "const char" *element in
|
||||
String to record as one element of the \fB\-errorcode\fR return option.
|
||||
Last \fIelement\fR argument must be NULL.
|
||||
.AP va_list argList in
|
||||
An argument list which must have been initialized using
|
||||
\fBva_start\fR, and cleared using \fBva_end\fR.
|
||||
.AP int lineNum
|
||||
The line number of a script where an error occurred.
|
||||
.AP "const char" *script in
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ except its \fIproc2\fR argument is of type \fBTcl_ObjCmdProc2\fR.
|
||||
typedef int \fBTcl_ObjCmdProc2\fR(
|
||||
void *\fIclientData\fR,
|
||||
Tcl_Interp *\fIinterp\fR,
|
||||
ptrdiff_t \fIobjc\fR,
|
||||
Tcl_Size \fIobjc\fR,
|
||||
Tcl_Obj *const \fIobjv\fR[]);
|
||||
.CE
|
||||
.PP
|
||||
|
||||
+2
-2
@@ -88,10 +88,10 @@ typedef int \fBTcl_CmdObjTraceProc\fR(
|
||||
typedef int \fBTcl_CmdObjTraceProc2\fR(
|
||||
\fBvoid *\fR \fIclientData\fR,
|
||||
\fBTcl_Interp\fR* \fIinterp\fR,
|
||||
ptrdiff_t \fIlevel\fR,
|
||||
Tcl_Size \fIlevel\fR,
|
||||
const char *\fIcommand\fR,
|
||||
\fBTcl_Command\fR \fIcommandToken\fR,
|
||||
ptrdiff_t \fIobjc\fR,
|
||||
Tcl_Size \fIobjc\fR,
|
||||
\fBTcl_Obj\fR *const \fIobjv\fR[]);
|
||||
.CE
|
||||
.PP
|
||||
|
||||
+1
-1
@@ -590,7 +590,7 @@ with at most one of \fBTCL_ENCODING_PROFILE_TCL8\fR,
|
||||
\fBTCL_ENCODING_PROFILE_STRICT\fR or \fBTCL_ENCODING_PROFILE_REPLACE\fR.
|
||||
These correspond to the \fBtcl8\fR, \fBstrict\fR and \fBreplace\fR profiles
|
||||
respectively. If none are specified, a version-dependent default profile is used.
|
||||
For Tcl 8.7, the default profile is \fBtcl8\fR.
|
||||
For Tcl 9.0, the default profile is \fBtcl8\fR.
|
||||
.PP
|
||||
For details about profiles, see the \fBPROFILES\fR section in
|
||||
the documentation of the \fBencoding\fR command.
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ is true.
|
||||
.PP
|
||||
\fBTcl_Import\fR imports commands matching a pattern into a
|
||||
namespace. Note that the pattern must include the name of the
|
||||
namespace to import from. This function returns an error if
|
||||
namespace to import from. This function returns TCL_ERROR if
|
||||
an attempt to import a command over an existing command is made,
|
||||
unless the \fIallowOverwrite\fR flag has been set.
|
||||
.PP
|
||||
|
||||
+7
-5
@@ -406,8 +406,10 @@ to UTF-8 based on the channel's encoding and storing the produced data in
|
||||
\fIreadObjPtr\fR's string representation. The return value of
|
||||
\fBTcl_ReadChars\fR is the number of characters, up to \fIcharsToRead\fR,
|
||||
that were stored in \fIreadObjPtr\fR. If an error occurs while reading, the
|
||||
return value is -1 and \fBTcl_ReadChars\fR records a POSIX error code that
|
||||
can be retrieved with \fBTcl_GetErrno\fR.
|
||||
return value is -1 and \fBTcl_ReadChars\fR records a POSIX error
|
||||
code that can be retrieved with \fBTcl_GetErrno\fR. If an encoding error happens
|
||||
while the channel is in blocking mode with -profile strict, the characters
|
||||
retrieved until the encoding error happened will be stored in \fIreadObjPtr\fR.
|
||||
.PP
|
||||
Setting \fIcharsToRead\fR to -1 will cause the command to read
|
||||
all characters currently available (non-blocking) or everything until
|
||||
@@ -416,9 +418,9 @@ eof (blocking mode).
|
||||
The return value may be smaller than the value to read, indicating that less
|
||||
data than requested was available. This is called a \fIshort read\fR. In
|
||||
blocking mode, this can only happen on an end-of-file. In nonblocking mode,
|
||||
a short read can also occur if there is not enough input currently
|
||||
available: \fBTcl_ReadChars\fR returns a short count rather than waiting
|
||||
for more data.
|
||||
a short read can also occur if an encoding error is encountered (with -profile
|
||||
strict) or if there is not enough input currently available:
|
||||
\fBTcl_ReadChars\fR returns a short count rather than waiting for more data.
|
||||
.PP
|
||||
If the channel is in blocking mode, a return value of zero indicates an
|
||||
end-of-file condition. If the channel is in nonblocking mode, a return
|
||||
|
||||
@@ -27,10 +27,6 @@ void
|
||||
A printf-style format string.
|
||||
.AP "" arg in
|
||||
Arguments matching the format string.
|
||||
.AP va_list argList in
|
||||
An argument list of arguments matching the format string.
|
||||
Must have been initialized using \fBva_start\fR,
|
||||
and cleared using \fBva_end\fR.
|
||||
.AP Tcl_PanicProc *panicProc in
|
||||
Procedure to report fatal error message and abort.
|
||||
.BE
|
||||
|
||||
@@ -45,9 +45,6 @@ to the existing result of \fIinterp\fR.
|
||||
.AP Tcl_FreeProc *freeProc in
|
||||
Pointer to a procedure to call to release storage at
|
||||
\fIresult\fR.
|
||||
.AP va_list argList in
|
||||
An argument list which must have been initialized using
|
||||
\fBva_start\fR, and cleared using \fBva_end\fR.
|
||||
.AP Tcl_Interp *sourceInterp in
|
||||
The interpreter to transfer the result and return options from.
|
||||
.AP Tcl_Interp *targetInterp in
|
||||
|
||||
+1
-4
@@ -115,7 +115,7 @@ The index of the last Unicode character in the Unicode range to be
|
||||
returned as a new value. If negative, take all characters up to
|
||||
the last one available.
|
||||
.AP Tcl_Obj *objPtr in/out
|
||||
Points to a value to manipulate.
|
||||
A pointer to a value to read, or to an unshared value to modify.
|
||||
.AP Tcl_Obj *appendObjPtr in
|
||||
The value to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR.
|
||||
.AP "Tcl_Size \&| int" *lengthPtr out
|
||||
@@ -123,9 +123,6 @@ The location where \fBTcl_GetStringFromObj\fR will store the length
|
||||
of a value's string representation. May be (int *)NULL when not used.
|
||||
.AP "const char" *string in
|
||||
Null-terminated string value to append to \fIobjPtr\fR.
|
||||
.AP va_list argList in
|
||||
An argument list which must have been initialized using
|
||||
\fBva_start\fR, and cleared using \fBva_end\fR.
|
||||
.AP Tcl_Size limit in
|
||||
Maximum number of bytes to be appended.
|
||||
.AP "const char" *ellipsis in
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ is used to initialize the compression engine rather than leaving it to create
|
||||
it on the fly from the data being compressed. Setting a compression dictionary
|
||||
allows for more efficient compression in the case where the start of the data
|
||||
is highly regular, but it does require both the compressor and the
|
||||
decompressor to agreee on the value to use. Compression dictionaries are only
|
||||
decompressor to agree on the value to use. Compression dictionaries are only
|
||||
fully supported for zlib-format data; on compression, they must be set before
|
||||
any data is sent in with \fBTcl_ZlibStreamPut\fR, and on decompression they
|
||||
should be set when \fBTcl_ZlibStreamGet\fR produces an \fBerror\fR with its
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ This procedure will act as the \fBmain()\fR of the newly created
|
||||
thread. The specified \fIclientData\fR will be its sole argument.
|
||||
.AP void *clientData in
|
||||
Arbitrary information. Passed as sole argument to the \fIproc\fR.
|
||||
.AP int stackSize in
|
||||
.AP size_t stackSize in
|
||||
The size of the stack given to the new thread.
|
||||
.AP int flags in
|
||||
Bitmask containing flags allowing the caller to modify behavior of
|
||||
|
||||
+16
-3
@@ -55,7 +55,9 @@ channel is flushed in the background before finally being closed.
|
||||
.PP
|
||||
\fBchan close\fR may return an error if an error occurs while flushing
|
||||
output. If a process in a command pipeline created by \fBopen\fR returns an
|
||||
error, \fBchan close\fR generates an error in the same manner as \fBexec\fR.
|
||||
error (either by returning a non-zero exit code or writing to its standard
|
||||
error file descriptor), \fBchan close\fR generates an error in the same
|
||||
manner as \fBexec\fR.
|
||||
.PP
|
||||
Closing one side of a socket or command pipeline may lead to the shutdown() or
|
||||
close() of the underlying system resource, leading to a reaction from whatever
|
||||
@@ -70,6 +72,17 @@ description of channel sharing.
|
||||
.PP
|
||||
When the last interpreter sharing a channel is destroyed, the channel is
|
||||
switched to blocking mode and fully flushed and then closed.
|
||||
.PP
|
||||
Channels are automatically closed when an interpreter is destroyed and
|
||||
when the process exits.
|
||||
From 8.6 on (TIP#398), nonblocking channels are no longer switched to
|
||||
blocking mode when exiting; this guarantees a timely exit even when the
|
||||
peer or a communication channel is stalled. To ensure proper flushing of
|
||||
stalled nonblocking channels on exit, one must now either (a) actively
|
||||
switch them back to blocking or (b) use the environment variable
|
||||
\fBTCL_FLUSH_NONBLOCKING_ON_EXIT\fR, which when set and not equal to
|
||||
.QW \fB0\fR
|
||||
restores the previous behavior.
|
||||
.RE
|
||||
.TP
|
||||
\fBchan configure \fIchannelName\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?...
|
||||
@@ -348,8 +361,8 @@ first words of a command that provides the interface for a \fBrefchan\fR.
|
||||
\fBImode\fR is a list of one or more of the strings
|
||||
.QW \fBread\fR
|
||||
or
|
||||
.QW \fBwrite\fR
|
||||
, indicating whether the channel is a read channel, a write channel, or both.
|
||||
.QW \fBwrite\fR ,
|
||||
indicating whether the channel is a read channel, a write channel, or both.
|
||||
It is an error if the handler does not support the chosen mode.
|
||||
.PP
|
||||
The handler is called as needed from the global namespace at the top level, and
|
||||
|
||||
+15
-6
@@ -12,11 +12,12 @@
|
||||
.SH NAME
|
||||
close \- Close an open channel
|
||||
.SH SYNOPSIS
|
||||
\fBclose \fIchannelId\fR ?r(ead)|w(rite)?
|
||||
\fBclose \fIchannelId\fR ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)?
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Closes or half-closes the channel given by \fIchannelId\fR.
|
||||
Closes or half-closes the channel given by \fIchannelId\fR. \fBchan close\fR
|
||||
is another name for this command.
|
||||
.PP
|
||||
\fIChannelId\fR must be an identifier for an open channel such as a
|
||||
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
|
||||
@@ -49,12 +50,20 @@ When the last interpreter in which the channel is registered invokes
|
||||
.PP
|
||||
Channels are automatically closed when an interpreter is destroyed and
|
||||
when the process exits.
|
||||
From 8.6 on (TIP#398), nonblocking channels are no longer switched to blocking mode when exiting; this guarantees a timely exit even when the peer or a communication channel is stalled. To ensure proper flushing of stalled nonblocking channels on exit, one must now either (a) actively switch them back to blocking or (b) use the environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT, which when set and not equal to "0" restores the previous behavior.
|
||||
From 8.6 on (TIP#398), nonblocking channels are no longer switched to
|
||||
blocking mode when exiting; this guarantees a timely exit even when the
|
||||
peer or a communication channel is stalled. To ensure proper flushing of
|
||||
stalled nonblocking channels on exit, one must now either (a) actively
|
||||
switch them back to blocking or (b) use the environment variable
|
||||
\fBTCL_FLUSH_NONBLOCKING_ON_EXIT\fR, which when set and not equal to
|
||||
.QW \fB0\fR
|
||||
restores the previous behavior.
|
||||
.PP
|
||||
The command returns an empty string, and may generate an error if
|
||||
an error occurs while flushing output. If a command in a command
|
||||
pipeline created with \fBopen\fR returns an error, \fBclose\fR
|
||||
generates an error (similar to the \fBexec\fR command.)
|
||||
pipeline created with \fBopen\fR returns an error (either by returning a
|
||||
non-zero exit code or writing to its standard error file descriptor),
|
||||
\fBclose\fR generates an error (similar to the \fBexec\fR command.)
|
||||
.PP
|
||||
The two-argument form is a
|
||||
.QW "half-close" :
|
||||
@@ -95,7 +104,7 @@ proc withOpenFile {filename channelVar script} {
|
||||
}
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3)
|
||||
chan(n), file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3)
|
||||
.SH KEYWORDS
|
||||
blocking, channel, close, nonblocking, half-close
|
||||
'\" Local Variables:
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
'\"
|
||||
'\" Copyright © 2019 Donal K. Fellows
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH configurable n 0.4 TclOO "TclOO Commands"
|
||||
.so man.macros
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
oo::configurable, configure, property \- class that makes configurable classes and objects, and supports making configurable properties
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
package require TclOO
|
||||
|
||||
\fBoo::configurable create \fIclass\fR ?\fIdefinitionScript\fR?
|
||||
|
||||
\fBoo::define \fIclass\fB {\fR
|
||||
\fBproperty \fIpropName\fR ?\fIoptions...\fR? ?\fIpropName\fR ?\fIoptions...\fR?...?
|
||||
\fB}\fR
|
||||
|
||||
\fBoo::objdefine \fIobject\fB {\fR
|
||||
\fBproperty \fIpropName\fR ?\fIoptions...\fR? ?\fIpropName\fR ?\fIoptions...\fR?...?
|
||||
\fB}\fR
|
||||
|
||||
\fIobjectName \fBconfigure\fR
|
||||
\fIobjectName \fBconfigure\fR \fI\-prop\fR
|
||||
\fIobjectName \fBconfigure\fR \fI\-prop value\fR ?\fI\-prop value\fR...
|
||||
.fi
|
||||
.SH "CLASS HIERARCHY"
|
||||
.nf
|
||||
\fBoo::object\fR
|
||||
\(-> \fBoo::class\fR
|
||||
\(-> \fBoo::configurable\fR
|
||||
|
||||
\fBoo::object\fR
|
||||
\(-> \fBoo::class\fR
|
||||
\(-> \fBoo::configurablesupport::configurable\fR
|
||||
.fi
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Configurable objects are objects that support being configured with a
|
||||
\fBconfigure\fR method. Each of the configurable entities of the object is
|
||||
known as a property of the object. Properties may be defined on classes or
|
||||
instances; when configuring an object, any of the properties defined by its
|
||||
classes (direct or indirect) or by the instance itself may be configured.
|
||||
.PP
|
||||
The \fBoo::configurable\fR metaclass installs basic support for making
|
||||
configurable objects into a class. This consists of making a \fBproperty\fR
|
||||
definition command available in definition scripts for the class and instances
|
||||
(e.g., from the class's constructor, within \fBoo::define\fR and within
|
||||
\fBoo::objdefine\fR) and making a \fBconfigure\fR method available within the
|
||||
instances.
|
||||
.SS "CONFIGURE METHOD"
|
||||
.PP
|
||||
The behavior of the \fBconfigure\fR method is modelled after the
|
||||
\fBfconfigure\fR/\fBchan configure\fR command.
|
||||
.PP
|
||||
If passed no additional arguments, the \fBconfigure\fR method returns an
|
||||
alphabetically sorted dictionary of all \fIreadable\fR and \fIread-write\fR
|
||||
properties and their current values.
|
||||
.PP
|
||||
If passed a single additional argument, that argument to the \fBconfigure\fR
|
||||
method must be the name of a property to read (or an unambiguous prefix
|
||||
thereof); its value is returned.
|
||||
.PP
|
||||
Otherwise, if passed an even number of arguments then each pair of arguments
|
||||
specifies a property name (or an unambiguous prefix thereof) and the value to
|
||||
set it to. The properties will be set in the order specified, including
|
||||
duplicates. If the setting of any property fails, the overall \fBconfigure\fR
|
||||
method fails, the preceding pairs (if any) will continue to have been applied,
|
||||
and the succeeding pairs (if any) will be not applied. On success, the result
|
||||
of the \fBconfigure\fR method in this mode operation will be an empty string.
|
||||
.SS "PROPERTY DEFINITIONS"
|
||||
.PP
|
||||
When a class has been manufactured by the \fBoo::configurable\fR metaclass (or
|
||||
one of its subclasses), it gains an extra definition, \fBproperty\fR. The
|
||||
\fBproperty\fR definition defines one or more properties that will be exposed
|
||||
by the class's instances.
|
||||
.PP
|
||||
The \fBproperty\fR command takes the name of a property to define first,
|
||||
\fIwithout a leading hyphen\fR, followed by a number of option-value pairs
|
||||
that modify the basic behavior of the property. This can then be followed by
|
||||
an arbitrary number of other property definitions. The supported options are:
|
||||
.TP
|
||||
\fB\-get \fIgetterScript\fR
|
||||
.
|
||||
This defines the implementation of how to read from the property; the
|
||||
\fIgetterScript\fR will become the body of a method (taking no arguments)
|
||||
defined on the class, if the kind of the property is such that the property
|
||||
can be read from. The method will be named
|
||||
\fB<ReadProp-\fIpropertyName\fB>\fR, and will default to being a simple read
|
||||
of the instance variable with the same name as the property (e.g.,
|
||||
.QW "\fBproperty\fR xyz"
|
||||
will result in a method
|
||||
.QW <ReadProp-xyz>
|
||||
being created).
|
||||
.TP
|
||||
\fB\-kind \fIpropertyKind\fR
|
||||
.
|
||||
This defines what sort of property is being created. The \fIpropertyKind\fR
|
||||
must be exactly one of \fBreadable\fR, \fBwritable\fR, or \fBreadwrite\fR
|
||||
(which is the default) which will make the property read-only, write-only or
|
||||
read-write, respectively. Read-only properties can only ever be read from,
|
||||
write-only properties can only ever be written to, and read-write properties
|
||||
can be both read and written.
|
||||
.RS
|
||||
.PP
|
||||
Note that write-only properties are not particularly discoverable as they are
|
||||
never reported by the \fBconfigure\fR method other than by error messages when
|
||||
attempting to write to a property that does not exist.
|
||||
.RE
|
||||
.TP
|
||||
\fB\-set \fIsetterScript\fR
|
||||
.
|
||||
This defines the implementation of how to write to the property; the
|
||||
\fIsetterScript\fR will become the body of a method taking a single argument,
|
||||
\fIvalue\fR, defined on the class, if the kind of the property is such that
|
||||
the property can be written to. The method will be named
|
||||
\fB<WriteProp-\fIpropertyName\fB>\fR, and will default to being a simple write
|
||||
of the instance variable with the same name as the property (e.g.,
|
||||
.QW "\fBproperty\fR xyz"
|
||||
will result in a method
|
||||
.QW <WriteProp-xyz>
|
||||
being created).
|
||||
.PP
|
||||
Instances of the class that was created by \fBoo::configurable\fR will also
|
||||
support \fBproperty\fR definitions; the semantics will be exactly as above
|
||||
except that the properties will be defined on the instance alone.
|
||||
.PP
|
||||
Note that the property implementation methods that \fBproperty\fR defines
|
||||
should not be private, as this makes them inaccessible from the implementation
|
||||
of \fBconfigure\fR (by design; the property configuration mechanism is
|
||||
intended for use mainly from outside a class, whereas a class may access
|
||||
variables directly). The variables accessed by the default implementations of
|
||||
the properties \fImay\fR be private, if so declared.
|
||||
.SH "ADVANCED USAGE"
|
||||
.PP
|
||||
The configurable class system is comprised of several pieces. The
|
||||
\fBoo::configurable\fR metaclass works by mixing in a class and setting
|
||||
definition namespaces during object creation that provide the other bits and
|
||||
pieces of machinery. The key pieces of the implementation are enumerated here
|
||||
so that they can be used by other code:
|
||||
.TP
|
||||
\fBoo::configuresupport::configurable\fR
|
||||
.
|
||||
This is a class that provides the implementation of the \fBconfigure\fR method
|
||||
(described above in \fBCONFIGURE METHOD\fR).
|
||||
.TP
|
||||
\fBoo::configuresupport::configurableclass\fR
|
||||
.
|
||||
This is a namespace that contains the definition dialect that provides the
|
||||
\fBproperty\fR declaration for use in classes (i.e., via \fBoo::define\fR, and
|
||||
class constructors under normal circumstances), as described above in
|
||||
\fBPROPERTY DEFINITIONS\fR. It \fBnamespace export\fRs its \fBproperty\fR
|
||||
command so that it may be used easily in user definition dialects.
|
||||
.TP
|
||||
\fBoo::configuresupport::configurableobject\fR
|
||||
.
|
||||
This is a namespace that contains the definition dialect that provides the
|
||||
\fBproperty\fR declaration for use in instance objects (i.e., via
|
||||
\fBoo::objdefine\fR, and the \fBself\fR declaration in \fBoo::define\fR), as
|
||||
described above in \fBPROPERTY DEFINITIONS\fR. It \fBnamespace export\fRs its
|
||||
\fBproperty\fR command so that it may be used easily in user definition
|
||||
dialects.
|
||||
.PP
|
||||
The underlying property discovery mechanism relies on four slots (see
|
||||
\fBoo::define\fR for what that implies) that list the properties that can be
|
||||
configured. These slots do not themselves impose any semantics on what the
|
||||
slots mean other than that they have unique names, no important order, can be
|
||||
inherited and discovered on classes and instances.
|
||||
.PP
|
||||
These slots, and their intended semantics, are:
|
||||
.TP
|
||||
\fBoo::configuresupport::readableproperties\fR
|
||||
.
|
||||
The set of properties of a class (not including those from its superclasses)
|
||||
that may be read from when configuring an instance of the class. This slot can
|
||||
also be read with the \fBinfo class properties\fR command.
|
||||
.TP
|
||||
\fBoo::configuresupport::writableproperties\fR
|
||||
.
|
||||
The set of properties of a class (not including those from its superclasses)
|
||||
that may be written to when configuring an instance of the class. This slot
|
||||
can also be read with the \fBinfo class properties\fR command.
|
||||
.TP
|
||||
\fBoo::configuresupport::objreadableproperties\fR
|
||||
.
|
||||
The set of properties of an object instance (not including those from its
|
||||
classes) that may be read from when configuring the object. This slot can
|
||||
also be read with the \fBinfo object properties\fR command.
|
||||
.TP
|
||||
\fBoo::configuresupport::objwritableproperties\fR
|
||||
.
|
||||
The set of properties of an object instance (not including those from its
|
||||
classes) that may be written to when configuring the object. This slot can
|
||||
also be read with the \fBinfo object properties\fR command.
|
||||
.PP
|
||||
Note that though these are slots, they are \fInot\fR in the standard
|
||||
\fBoo::define\fR or \fBoo::objdefine\fR namespaces; in order to use them
|
||||
inside a definition script, they need to be referred to by full name. This is
|
||||
because they are intended to be building bricks of configurable property
|
||||
system, and not directly used by normal user code.
|
||||
.SS "IMPLEMENTATION NOTE"
|
||||
.PP
|
||||
The implementation of the \fBconfigure\fR method uses
|
||||
\fBinfo object properties\fR with the \fB\-all\fR option to discover what
|
||||
properties it may manipulate.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
Here we create a simple configurable class and demonstrate how it can be
|
||||
configured:
|
||||
.PP
|
||||
.CS
|
||||
\fBoo::configurable\fR create Point {
|
||||
\fBproperty\fR x y
|
||||
constructor args {
|
||||
my \fBconfigure\fR -x 0 -y 0 {*}$args
|
||||
}
|
||||
variable x y
|
||||
method print {} {
|
||||
puts "x=$x, y=$y"
|
||||
}
|
||||
}
|
||||
|
||||
set pt [Point new -x 27]
|
||||
$pt print; \fI# x=27, y=0\fR
|
||||
$pt \fBconfigure\fR -y 42
|
||||
$pt print; \fI# x=27, y=42\fR
|
||||
puts "distance from origin: [expr {
|
||||
hypot([$pt \fBconfigure\fR -x], [$pt \fBconfigure\fR -y])
|
||||
}]"; \fI# distance from origin: 49.92995093127971\fR
|
||||
puts [$pt \fBconfigure\fR]
|
||||
\fI# -x 27 -y 42\fR
|
||||
.CE
|
||||
.PP
|
||||
Such a configurable class can be extended by subclassing, though the subclass
|
||||
needs to also be created by \fBoo::configurable\fR if it will use the
|
||||
\fBproperty\fR definition:
|
||||
.PP
|
||||
.CS
|
||||
\fBoo::configurable\fR create Point3D {
|
||||
superclass Point
|
||||
\fBproperty\fR z
|
||||
constructor args {
|
||||
next -z 0 {*}$args
|
||||
}
|
||||
}
|
||||
|
||||
set pt2 [Point3D new -x 2 -y 3 -z 4]
|
||||
puts [$pt2 \fBconfigure\fR]
|
||||
\fI# -x 2 -y 3 -z 4\fR
|
||||
.CE
|
||||
.PP
|
||||
Once you have a configurable class, you can also add instance properties to
|
||||
it. (The backing variables for all properties start unset.) Note below that we
|
||||
are using an unambiguous prefix of a property name when setting it; this is
|
||||
supported for all properties though full names are normally recommended
|
||||
because subclasses will not make an unambiguous prefix become ambiguous in
|
||||
that case.
|
||||
.PP
|
||||
.CS
|
||||
oo::objdefine $pt {
|
||||
\fBproperty\fR color
|
||||
}
|
||||
$pt \fBconfigure\fR -c bisque
|
||||
puts [$pt \fBconfigure\fR]
|
||||
\fI# -color bisque -x 27 -y 42\fR
|
||||
.CE
|
||||
.PP
|
||||
You can also do derived properties by making them read-only and supplying a
|
||||
script that computes them.
|
||||
.PP
|
||||
.CS
|
||||
\fBoo::configurable\fR create PointMk2 {
|
||||
\fBproperty\fR x y
|
||||
\fBproperty\fR distance -kind readable -get {
|
||||
return [expr {hypot($x, $y)}]
|
||||
}
|
||||
variable x y
|
||||
constructor args {
|
||||
my \fBconfigure\fR -x 0 -y 0 {*}$args
|
||||
}
|
||||
}
|
||||
|
||||
set pt3 [PointMk2 new -x 3 -y 4]
|
||||
puts [$pt3 \fBconfigure\fR -distance]
|
||||
\fI# 5.0\fR
|
||||
$pt3 \fBconfigure\fR -distance 10
|
||||
\fI# ERROR: bad property "-distance": must be -x or -y\fR
|
||||
.CE
|
||||
.PP
|
||||
Setters are used to validate the type of a property:
|
||||
.PP
|
||||
.CS
|
||||
\fBoo::configurable\fR create PointMk3 {
|
||||
\fBproperty\fR x -set {
|
||||
if {![string is double -strict $value]} {
|
||||
error "-x property must be a number"
|
||||
}
|
||||
set x $value
|
||||
}
|
||||
\fBproperty\fR y -set {
|
||||
if {![string is double -strict $value]} {
|
||||
error "-y property must be a number"
|
||||
}
|
||||
set y $value
|
||||
}
|
||||
variable x y
|
||||
constructor args {
|
||||
my \fBconfigure\fR -x 0 -y 0 {*}$args
|
||||
}
|
||||
}
|
||||
|
||||
set pt4 [PointMk3 new]
|
||||
puts [$pt4 \fBconfigure\fR]
|
||||
\fI# -x 0 -y 0\fR
|
||||
$pt4 \fBconfigure\fR -x 3 -y 4
|
||||
puts [$pt4 \fBconfigure\fR]
|
||||
\fI# -x 3 -y 4\fR
|
||||
$pt4 \fBconfigure\fR -x "obviously not a number"
|
||||
\fI# ERROR: -x property must be a number\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
info(n), oo::class(n), oo::define(n)
|
||||
.SH KEYWORDS
|
||||
class, object, properties, configuration
|
||||
.\" Local variables:
|
||||
.\" mode: nroff
|
||||
.\" fill-column: 78
|
||||
.\" End:
|
||||
@@ -493,6 +493,12 @@ the slot:
|
||||
.
|
||||
This appends the given \fImember\fR elements to the slot definition.
|
||||
.TP
|
||||
\fIslot\fR \fB\-appendifnew\fR ?\fImember ...\fR?
|
||||
.VS TIP558
|
||||
This appends the given \fImember\fR elements to the slot definition if they
|
||||
do not already exist.
|
||||
.VE TIP558
|
||||
.TP
|
||||
\fIslot\fR \fB\-clear\fR
|
||||
.
|
||||
This sets the slot definition to the empty list.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'\"
|
||||
'\" Copyright (c) 1998 Scriptics Corporation.
|
||||
'\" Copyright (c) 2023 Nathan Coulter
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
|
||||
+47
@@ -490,6 +490,29 @@ be discovered with \fBinfo class forward\fR.
|
||||
This subcommand returns a list of all classes that have been mixed into the
|
||||
class named \fIclass\fR.
|
||||
.TP
|
||||
\fBinfo class properties\fI class\fR ?\fIoptions...\fR
|
||||
.VS "TIP 558"
|
||||
This subcommand returns a sorted list of properties defined on the class named
|
||||
\fIclass\fR. The \fIoptions\fR define exactly which properties are returned:
|
||||
.RS
|
||||
.TP
|
||||
\fB\-all\fR
|
||||
.
|
||||
With this option, the properties from the superclasses and mixins of the class
|
||||
are also returned.
|
||||
.TP
|
||||
\fB\-readable\fR
|
||||
.
|
||||
This option (the default behavior) asks for the readable properties to be
|
||||
returned. Only readable or writable properties are returned, not both.
|
||||
.TP
|
||||
\fB\-writable\fR
|
||||
.
|
||||
This option asks for the writable properties to be returned. Only readable or
|
||||
writable properties are returned, not both.
|
||||
.RE
|
||||
.VE "TIP 558"
|
||||
.TP
|
||||
\fBinfo class subclasses\fI class\fR ?\fIpattern\fR?
|
||||
.
|
||||
This subcommand returns a list of direct subclasses of class \fIclass\fR. If
|
||||
@@ -679,6 +702,30 @@ object named \fIobject\fR.
|
||||
This subcommand returns the name of the internal namespace of the object named
|
||||
\fIobject\fR.
|
||||
.TP
|
||||
\fBinfo object properties\fI object\fR ?\fIoptions...\fR
|
||||
.VS "TIP 558"
|
||||
This subcommand returns a sorted list of properties defined on the object
|
||||
named \fIobject\fR. The \fIoptions\fR define exactly which properties are
|
||||
returned:
|
||||
.RS
|
||||
.TP
|
||||
\fB\-all\fR
|
||||
.
|
||||
With this option, the properties from the class, superclasses and mixins of
|
||||
the object are also returned.
|
||||
.TP
|
||||
\fB\-readable\fR
|
||||
.
|
||||
This option (the default behavior) asks for the readable properties to be
|
||||
returned. Only readable or writable properties are returned, not both.
|
||||
.TP
|
||||
\fB\-writable\fR
|
||||
.
|
||||
This option asks for the writable properties to be returned. Only readable or
|
||||
writable properties are returned, not both.
|
||||
.RE
|
||||
.VE "TIP 558"
|
||||
.TP
|
||||
\fBinfo object variables\fI object\fRR ?\fB\-private\fR?
|
||||
.
|
||||
This subcommand returns a list of all variables that have been declared for
|
||||
|
||||
+13
-13
@@ -24,7 +24,7 @@ Arguments \fIfirst\fR and \fIlast\fR are index values specifying the first and
|
||||
last elements of the range to replace. They are interpreted
|
||||
the same as index values for the command \fBstring index\fR,
|
||||
supporting simple index arithmetic and indices relative to the
|
||||
end of the list. The index 0 refers to the first element of the
|
||||
end of the list. The index \fB0\fR refers to the first element of the
|
||||
list, and \fBend\fR refers to the last element of the list.
|
||||
.PP
|
||||
If either \fIfirst\fR or \fIlast\fR is less than zero, it is considered to
|
||||
@@ -49,33 +49,33 @@ between \fIfirst\fR and \fIlast\fR are simply deleted.
|
||||
Prepend to a list.
|
||||
.PP
|
||||
.CS
|
||||
% set lst {c d e f g}
|
||||
c d e f g
|
||||
% ledit lst -1 -1 a b
|
||||
a b c d e f g
|
||||
set lst {c d e f g}
|
||||
\fI\(-> c d e f g\fR
|
||||
\fBledit\fR lst -1 -1 a b
|
||||
\fI\(-> a b c d e f g\fR
|
||||
.CE
|
||||
.PP
|
||||
Append to the list.
|
||||
.PP
|
||||
.CS
|
||||
% ledit lst end+1 end+1 h i
|
||||
a b c d e f g h i
|
||||
\fBledit\fR lst end+1 end+1 h i
|
||||
\fI\(-> a b c d e f g h i\fR
|
||||
.CE
|
||||
.PP
|
||||
Delete third and fourth elements.
|
||||
.PP
|
||||
.CS
|
||||
% ledit lst 2 3
|
||||
a b e f g h i
|
||||
\fBledit\fR lst 2 3
|
||||
\fI\(-> a b e f g h i\fR
|
||||
.CE
|
||||
.PP
|
||||
Replace two elements with three.
|
||||
.PP
|
||||
.CS
|
||||
% ledit lst 2 3 x y z
|
||||
a b x y z g h i
|
||||
% set lst
|
||||
a b x y z g h i
|
||||
\fBledit\fR lst 2 3 x y z
|
||||
\fI\(-> a b x y z g h i\fR
|
||||
set lst
|
||||
\fI\(-> a b x y z g h i\fR
|
||||
.CE
|
||||
.PP
|
||||
.SH "SEE ALSO"
|
||||
|
||||
+111
-3
@@ -58,6 +58,7 @@ the auto-load mechanism defined below.
|
||||
The following procedures are provided in the Tcl library:
|
||||
.TP
|
||||
\fBauto_execok \fIcmd\fR
|
||||
.
|
||||
Determines whether there is an executable file or shell builtin
|
||||
by the name \fIcmd\fR. If so, it returns a list of arguments to be
|
||||
passed to \fBexec\fR to execute the executable file or shell builtin
|
||||
@@ -70,8 +71,30 @@ remembers information about previous searches in an array named
|
||||
\fBauto_execs\fR; this avoids the path search in future calls for the
|
||||
same \fIcmd\fR. The command \fBauto_reset\fR may be used to force
|
||||
\fBauto_execok\fR to forget its cached information.
|
||||
.RS
|
||||
.PP
|
||||
For example, to run the \fIumask\fR shell builtin on Linux, you would do:
|
||||
.PP
|
||||
.CS
|
||||
exec {*}[\fBauto_execok\fR umask]
|
||||
.CE
|
||||
.PP
|
||||
To run the \fIDIR\fR shell builtin on Windows, you would do:
|
||||
.PP
|
||||
.CS
|
||||
exec {*}[\fBauto_execok\fR dir]
|
||||
.CE
|
||||
.PP
|
||||
To discover if there is a \fIfrobnicate\fR binary on the user's PATH,
|
||||
you would do:
|
||||
.PP
|
||||
.CS
|
||||
set mayFrob [expr {[llength [\fBauto_execok\fR frobnicate]] > 0}]
|
||||
.CE
|
||||
.RE
|
||||
.TP
|
||||
\fBauto_import \fIpattern\fR
|
||||
.
|
||||
\fBAuto_import\fR is invoked during \fBnamespace import\fR to see if
|
||||
the imported commands specified by \fIpattern\fR reside in an
|
||||
autoloaded library. If so, the commands are loaded so that they will
|
||||
@@ -79,13 +102,18 @@ be available to the interpreter for creating the import links. If the
|
||||
commands do not reside in an autoloaded library, \fBauto_import\fR
|
||||
does nothing. The pattern matching is performed according to the
|
||||
matching rules of \fBnamespace import\fR.
|
||||
.RS
|
||||
.PP
|
||||
It is not normally necessary to call this command directly.
|
||||
.RE
|
||||
.TP
|
||||
\fBauto_load \fIcmd\fR
|
||||
.
|
||||
This command attempts to load the definition for a Tcl command named
|
||||
\fIcmd\fR. To do this, it searches an \fIauto-load path\fR, which is
|
||||
a list of one or more directories. The auto-load path is given by the
|
||||
global variable \fBauto_path\fR if it exists. If there is no
|
||||
\fBauto_path\fR variable, then the TCLLIBPATH environment variable is
|
||||
\fBauto_path\fR variable, then the \fBTCLLIBPATH\fR environment variable is
|
||||
used, if it exists. Otherwise the auto-load path consists of just the
|
||||
Tcl library directory. Within each directory in the auto-load path
|
||||
there must be a file \fBtclIndex\fR that describes one or more
|
||||
@@ -104,6 +132,11 @@ the array \fBauto_index\fR; future calls to \fBauto_load\fR check for
|
||||
cached index information may be deleted with the command
|
||||
\fBauto_reset\fR. This will force the next \fBauto_load\fR command to
|
||||
reload the index database from disk.
|
||||
.RS
|
||||
.PP
|
||||
It is not normally necessary to call this command directly; the
|
||||
default \fBunknown\fR handler will do so.
|
||||
.RE
|
||||
.TP
|
||||
\fBauto_mkindex \fIdir pattern pattern ...\fR
|
||||
.
|
||||
@@ -156,6 +189,7 @@ listed in the auto-load index, so that fresh copies of them will be
|
||||
loaded the next time that they are used.
|
||||
.TP
|
||||
\fBauto_qualify \fIcommand namespace\fR
|
||||
.
|
||||
Computes a list of fully qualified names for \fIcommand\fR. This list
|
||||
mirrors the path a standard Tcl interpreter follows for command
|
||||
lookups: first it looks for the command in the current namespace, and
|
||||
@@ -175,6 +209,7 @@ performing the actual auto-loading of functions at runtime.
|
||||
.RE
|
||||
.TP
|
||||
\fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR
|
||||
.
|
||||
This is a standard search procedure for use by extensions during
|
||||
their initialization. They call this procedure to look for their
|
||||
script library in several standard directories.
|
||||
@@ -197,14 +232,25 @@ relative to the executable file in the current build tree;
|
||||
relative to the executable file in a parallel build tree.
|
||||
.TP
|
||||
\fBparray \fIarrayName\fR ?\fIpattern\fR?
|
||||
.
|
||||
Prints on standard output the names and values of all the elements in the
|
||||
array \fIarrayName\fR, or just the names that match \fIpattern\fR (using the
|
||||
matching rules of \fBstring match\fR) and their values if \fIpattern\fR is
|
||||
given.
|
||||
\fIArrayName\fR must be an array accessible to the caller of \fBparray\fR.
|
||||
It may be either local or global.
|
||||
The result of this command is the empty string.
|
||||
.RS
|
||||
.PP
|
||||
For example, to print the contents of the \fBtcl_platform\fR array, do:
|
||||
.PP
|
||||
.CS
|
||||
\fBparray\fR tcl_platform
|
||||
.CE
|
||||
.RE
|
||||
.TP
|
||||
\fBtcl_endOfWord \fIstr start\fR
|
||||
.
|
||||
Returns the index of the first end-of-word location that occurs after
|
||||
a starting index \fIstart\fR in the string \fIstr\fR. An end-of-word
|
||||
location is defined to be the first non-word character following the
|
||||
@@ -215,19 +261,35 @@ for more details on how Tcl determines which characters are word
|
||||
characters.
|
||||
.TP
|
||||
\fBtcl_startOfNextWord \fIstr start\fR
|
||||
.
|
||||
Returns the index of the first start-of-word location that occurs
|
||||
after a starting index \fIstart\fR in the string \fIstr\fR. A
|
||||
start-of-word location is defined to be the first word character
|
||||
following a non-word character. Returns \-1 if there are no more
|
||||
start-of-word locations after the starting point.
|
||||
.RS
|
||||
.PP
|
||||
For example, to print the indices of the starts of each word in a
|
||||
string according to platform rules:
|
||||
.PP
|
||||
.CS
|
||||
set theString "The quick brown fox"
|
||||
for {set idx 0} {$idx >= 0} {
|
||||
set idx [\fBtcl_startOfNextWord\fR $theString $idx]} {
|
||||
puts "Word start index: $idx"
|
||||
}
|
||||
.CE
|
||||
.RE
|
||||
.TP
|
||||
\fBtcl_startOfPreviousWord \fIstr start\fR
|
||||
.
|
||||
Returns the index of the first start-of-word location that occurs
|
||||
before a starting index \fIstart\fR in the string \fIstr\fR. Returns
|
||||
\-1 if there are no more start-of-word locations before the starting
|
||||
point.
|
||||
.TP
|
||||
\fBtcl_wordBreakAfter \fIstr start\fR
|
||||
.
|
||||
Returns the index of the first word boundary after the starting index
|
||||
\fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more
|
||||
boundaries after the starting point in the given string. The index
|
||||
@@ -235,6 +297,7 @@ returned refers to the second character of the pair that comprises a
|
||||
boundary.
|
||||
.TP
|
||||
\fBtcl_wordBreakBefore \fIstr start\fR
|
||||
.
|
||||
Returns the index of the first word boundary before the starting index
|
||||
\fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more
|
||||
boundaries before the starting point in the given string. The index
|
||||
@@ -248,18 +311,30 @@ commands and packages, and determining what are words.
|
||||
.SS "AUTOLOADING AND PACKAGE MANAGEMENT VARIABLES"
|
||||
.TP
|
||||
\fBauto_execs\fR
|
||||
.
|
||||
Used by \fBauto_execok\fR to record information about whether
|
||||
particular commands exist as executable files.
|
||||
.RS
|
||||
.PP
|
||||
Not normally usefully accessed directly by user code.
|
||||
.RE
|
||||
.TP
|
||||
\fBauto_index\fR
|
||||
.
|
||||
Used by \fBauto_load\fR to save the index information read from
|
||||
disk.
|
||||
.RS
|
||||
.PP
|
||||
Not normally usefully accessed directly by user code.
|
||||
.RE
|
||||
.TP
|
||||
\fBauto_noexec\fR
|
||||
.
|
||||
If set to any value, then \fBunknown\fR will not attempt to auto-exec
|
||||
any commands.
|
||||
.TP
|
||||
\fBauto_noload\fR
|
||||
.
|
||||
If set to any value, then \fBunknown\fR will not attempt to auto-load
|
||||
any commands.
|
||||
.TP
|
||||
@@ -275,37 +350,70 @@ the parent directory of \fBtcl_library\fR,
|
||||
the directories listed in the \fBtcl_pkgPath\fR variable.
|
||||
Additional locations to look for files and package indices should
|
||||
normally be added to this variable using \fBlappend\fR.
|
||||
.RS
|
||||
.PP
|
||||
For example, to add the \fIlib\fR directory next to the running
|
||||
script, you would do:
|
||||
.PP
|
||||
.CS
|
||||
lappend \fBauto_path\fR [file dirname [info script]]/lib
|
||||
.CE
|
||||
.PP
|
||||
Note that if the script uses \fBcd\fR, it is advisable to ensure that
|
||||
entries on the \fBauto_path\fR are \fBfile normalize\fRd.
|
||||
.RE
|
||||
.TP
|
||||
\fBenv(TCL_LIBRARY)\fR
|
||||
.
|
||||
If set, then it specifies the location of the directory containing
|
||||
library scripts (the value of this variable will be
|
||||
assigned to the \fBtcl_library\fR variable and therefore returned by
|
||||
the command \fBinfo library\fR). If this variable is not set then
|
||||
a default value is used.
|
||||
.RS
|
||||
.PP
|
||||
Use of this environment variable is not recommended outside of testing.
|
||||
Tcl installations should already know where to find their own script
|
||||
files, as the value is baked in during the build or installation.
|
||||
.RE
|
||||
.TP
|
||||
\fBenv(TCLLIBPATH)\fR
|
||||
.
|
||||
If set, then it must contain a valid Tcl list giving directories to
|
||||
search during auto-load operations. Directories must be specified in
|
||||
Tcl format, using
|
||||
.QW /
|
||||
as the path separator, regardless of platform.
|
||||
This variable is only used when initializing the \fBauto_path\fR variable.
|
||||
.RS
|
||||
.PP
|
||||
A key consequence of this variable is that it gives a way to let the user
|
||||
of a script specify the list of places where that script may use
|
||||
\fBpackage require\fR to read packages from. It is not normally usefully
|
||||
settable within a Tcl script itself \fIexcept\fR to influence where other
|
||||
interpreters load from (whether made with \fBinterp create\fR or launched
|
||||
as their own threads or subprocesses).
|
||||
.RE
|
||||
.SS "WORD BOUNDARY DETERMINATION VARIABLES"
|
||||
These variables are only used in the \fBtcl_endOfWord\fR,
|
||||
\fBtcl_startOfNextWord\fR, \fBtcl_startOfPreviousWord\fR,
|
||||
\fBtcl_wordBreakAfter\fR, and \fBtcl_wordBreakBefore\fR commands.
|
||||
.TP
|
||||
\fBtcl_nonwordchars\fR
|
||||
.
|
||||
This variable contains a regular expression that is used by routines
|
||||
like \fBtcl_endOfWord\fR to identify whether a character is part of a
|
||||
word or not. If the pattern matches a character, the character is
|
||||
considered to be a non-word character. The default is "\\W".
|
||||
considered to be a non-word character. The default value is
|
||||
.QW "\\W" .
|
||||
.TP
|
||||
\fBtcl_wordchars\fR
|
||||
.
|
||||
This variable contains a regular expression that is used by routines
|
||||
like \fBtcl_endOfWord\fR to identify whether a character is part of a
|
||||
word or not. If the pattern matches a character, the character is
|
||||
considered to be a word character. The default is "\\w".
|
||||
considered to be a word character. The default value is
|
||||
.QW "\\w" .
|
||||
.SH "SEE ALSO"
|
||||
env(n), info(n), re_syntax(n)
|
||||
.SH KEYWORDS
|
||||
|
||||
+7
-7
@@ -52,11 +52,11 @@ oo::class create ABC {
|
||||
|
||||
constructor {} {
|
||||
\fBlink\fR Foo
|
||||
# The method foo is now directly accessible as foo here
|
||||
# The method Foo is now directly accessible as Foo here
|
||||
\fBlink\fR {bar Foo}
|
||||
# The method foo is now directly accessible as bar
|
||||
# The method Foo is now directly accessible as bar
|
||||
\fBlink\fR {::ExternalCall Foo}
|
||||
# The method foo is now directly accessible in the global
|
||||
# The method Foo is now directly accessible in the global
|
||||
# namespace as ExternalCall
|
||||
}
|
||||
|
||||
@@ -71,13 +71,13 @@ oo::class create ABC {
|
||||
ABC create abc
|
||||
abc grill
|
||||
\fI\(-> Step 1:\fR
|
||||
\fI\(-> This is foo in ::abc\fR
|
||||
\fI\(-> This is Foo in ::abc\fR
|
||||
\fI\(-> Step 2:\fR
|
||||
\fI\(-> This is foo in ::abc\fR
|
||||
\fI\(-> This is Foo in ::abc\fR
|
||||
# Direct access via the linked command
|
||||
puts "Step 3:"; ExternalCall
|
||||
\fI\(-> Step 3:\fR
|
||||
\fI\(-> This is foo in ::abc\fR
|
||||
\fI\(-> This is Foo in ::abc\fR
|
||||
.CE
|
||||
.PP
|
||||
This example shows that multiple linked commands can be made in a call to
|
||||
@@ -88,7 +88,7 @@ oo::class create Ex {
|
||||
constructor {} {
|
||||
\fBlink\fR a b c
|
||||
# The methods a, b, and c (defined below) are all now
|
||||
# directly acessible within methods under their own names.
|
||||
# directly accessible within methods under their own names.
|
||||
}
|
||||
|
||||
method a {} {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ lremove \- Remove elements from a list by index
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fBlremove\fR returns a new list formed by simultaneously removing zero or
|
||||
more elements of \fIlist\fR at each of the indices given by an arbirary number
|
||||
more elements of \fIlist\fR at each of the indices given by an arbitrary number
|
||||
of \fIindex\fR arguments. The indices may be in any order and may be repeated;
|
||||
the element at index will only be removed once. The index values are
|
||||
interpreted the same as index values for the command \fBstring index\fR,
|
||||
|
||||
+56
-49
@@ -11,73 +11,80 @@
|
||||
.SH NAME
|
||||
lseq \- Build a numeric sequence returned as a list
|
||||
.SH SYNOPSIS
|
||||
\fBlseq \fIStart \fR?(\fB..\fR|\fBto\fR)? \fIEnd\fR ??\fBby\fR? \fIStep\fR?
|
||||
\fBlseq \fIstart \fR?(\fB..\fR|\fBto\fR)? \fIend\fR ??\fBby\fR? \fIstep\fR?
|
||||
|
||||
\fBlseq \fIStart \fBcount\fR \fICount\fR ??\fBby\fR? \fIStep\fR?
|
||||
\fBlseq \fIstart \fBcount\fR \fIcount\fR ??\fBby\fR? \fIstep\fR?
|
||||
|
||||
\fBlseq \fICount\fR ?\fBby \fIStep\fR?
|
||||
\fBlseq \fIcount\fR ?\fBby \fIstep\fR?
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The \fBlseq\fR command creates a sequence of numeric values using the given
|
||||
parameters \fIStart\fR, \fIEnd\fR, and \fIStep\fR. The \fIoperation\fR
|
||||
argument ".." or "to" defines an inclusive range. The "count" option is used
|
||||
to define a count of the number of elements in the list. The short form with a
|
||||
single count value will create a range from 0 to count-1.
|
||||
|
||||
The numeric arguments, \fIStart\fR, \fIEnd\fR, \fIStep\fR, and \fICount\fR,
|
||||
can also be a valid expression. the lseq command will evaluate the expression
|
||||
parameters \fIstart\fR, \fIend\fR, and \fIstep\fR.
|
||||
The \fIoperation\fR argument
|
||||
.QW \fB..\fR
|
||||
or
|
||||
.QW \fBto\fR
|
||||
defines an inclusive range; if it is omitted, the range is exclusive.
|
||||
The \fBcount\fR option is used to define a count of the number of elements in
|
||||
the list.
|
||||
The \fIstep\fR (which may be preceded by \fBby\fR) is 1 if not provided.
|
||||
The short form with a
|
||||
single \fIcount\fR value will create a range from 0 to \fIcount\fR-1 (i.e.,
|
||||
\fIcount\fR values).
|
||||
.PP
|
||||
The numeric arguments, \fIstart\fR, \fIend\fR, \fIstep\fR, and \fIcount\fR,
|
||||
can also be a valid expression. the \fBlseq\fR command will evaluate the
|
||||
expression (as if with \fBexpr\fR)
|
||||
and use the numeric result, or return an error as with any invalid argument
|
||||
value. A valid expression is a valid [expr] expression, however, the result
|
||||
must be numeric; a non-numeric string will result in an error.
|
||||
value; a non-numeric expression result will result in an error.
|
||||
|
||||
.SH EXAMPLES
|
||||
.CS
|
||||
.\"
|
||||
\fBlseq\fR 3
|
||||
\fI\(-> 0 1 2\fR
|
||||
|
||||
lseq 3
|
||||
\(-> 0 1 2
|
||||
\fBlseq\fR 3 0
|
||||
\fI\(-> 3 2 1 0\fR
|
||||
|
||||
lseq 3 0
|
||||
\(-> 3 2 1 0
|
||||
\fBlseq\fR 10 .. 1 by -2
|
||||
\fI\(-> 10 8 6 4 2\fR
|
||||
|
||||
lseq 10 .. 1 by -2
|
||||
\(-> 10 8 6 4 2
|
||||
set l [\fBlseq\fR 0 -5]
|
||||
\fI\(-> 0 -1 -2 -3 -4 -5\fR
|
||||
|
||||
set l [lseq 0 -5]
|
||||
\(-> 0 -1 -2 -3 -4 -5
|
||||
|
||||
foreach i [lseq [llength $l]] {
|
||||
puts l($i)=[lindex $l $i]
|
||||
}
|
||||
\(-> l(0)=0
|
||||
l(1)=-1
|
||||
l(2)=-2
|
||||
l(3)=-3
|
||||
l(4)=-4
|
||||
l(5)=-5
|
||||
|
||||
foreach i [lseq [llength $l]-1 0] {
|
||||
foreach i [\fBlseq\fR [llength $l]] {
|
||||
puts l($i)=[lindex $l $i]
|
||||
}
|
||||
\(-> l(5)=-5
|
||||
l(4)=-4
|
||||
l(3)=-3
|
||||
l(2)=-2
|
||||
l(1)=-1
|
||||
l(0)=0
|
||||
}
|
||||
\fI\(-> l(0)=0\fR
|
||||
\fI\(-> l(1)=-1\fR
|
||||
\fI\(-> l(2)=-2\fR
|
||||
\fI\(-> l(3)=-3\fR
|
||||
\fI\(-> l(4)=-4\fR
|
||||
\fI\(-> l(5)=-5\fR
|
||||
|
||||
set i 17
|
||||
\(-> 17
|
||||
if {$i in [lseq 0 50]} { # equivalent to: (0 <= $i && $i < 50)
|
||||
puts "Ok"
|
||||
} else {
|
||||
puts "outside :("
|
||||
}
|
||||
\(-> Ok
|
||||
foreach i [\fBlseq\fR {[llength $l]-1} 0] {
|
||||
puts l($i)=[lindex $l $i]
|
||||
}
|
||||
\fI\(-> l(5)=-5\fR
|
||||
\fI\(-> l(4)=-4\fR
|
||||
\fI\(-> l(3)=-3\fR
|
||||
\fI\(-> l(2)=-2\fR
|
||||
\fI\(-> l(1)=-1\fR
|
||||
\fI\(-> l(0)=0\fR
|
||||
|
||||
set sqrs [lmap i [lseq 1 10] {expr $i*$i}]
|
||||
\(-> 1 4 9 16 25 36 49 64 81 100
|
||||
set i 17
|
||||
\fI\(-> 17\fR
|
||||
if {$i in [\fBlseq\fR 0 50]} { # equivalent to: (0 <= $i && $i < 50)
|
||||
puts "Ok"
|
||||
} else {
|
||||
puts "outside :("
|
||||
}
|
||||
\fI\(-> Ok\fR
|
||||
|
||||
set sqrs [lmap i [\fBlseq\fR 1 10] { expr {$i*$i} }]
|
||||
\fI\(-> 1 4 9 16 25 36 49 64 81 100\fR
|
||||
.\"
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
|
||||
+22
@@ -128,6 +128,28 @@ If a new file is created as part of opening it, \fIpermissions\fR
|
||||
(an integer) is used to set the permissions for the new file in
|
||||
conjunction with the process's file mode creation mask.
|
||||
\fIPermissions\fR defaults to 0666.
|
||||
.PP
|
||||
.VS "8.7, TIP 603"
|
||||
When the file opened is an ordinary disk file, the \fBchan configure\fR and
|
||||
\fBfconfigure\fR commands can be used to query this additional configuration
|
||||
option:
|
||||
.TP
|
||||
\fB\-stat\fR
|
||||
.
|
||||
This option, when read, returns a dictionary of values much as is obtained
|
||||
from the \fBfile stat\fR command, where that stat information relates to the
|
||||
real opened file. Keys in the dictionary may include \fBatime\fR, \fBctime\fR,
|
||||
\fBdev\fR, \fBgid\fR, \fBino\fR, \fBmode\fR, \fBmtime\fR, \fBnlink\fR,
|
||||
\fBsize\fR, \fBtype\fR, and \fBuid\fR among others; the \fBmtime\fR,
|
||||
\fBsize\fR and \fBtype\fR fields are guaranteed to be present and meaningful
|
||||
on all platforms; other keys may be present too.
|
||||
.RS
|
||||
.PP
|
||||
\fIImplementation note:\fR This option maps to a call to \fBfstat()\fR on
|
||||
POSIX platforms, and to a call to \fBGetFileInformationByHandle()\fR on
|
||||
Windows; the information reported is what those system calls produce.
|
||||
.RE
|
||||
.VE "8.7, TIP 603"
|
||||
.SH "COMMAND PIPELINES"
|
||||
.PP
|
||||
If the first character of \fIfileName\fR is
|
||||
|
||||
+14
-1
@@ -11,7 +11,20 @@
|
||||
.SH NAME
|
||||
refchan \- command handler API of reflected channels
|
||||
.SH SYNOPSIS
|
||||
\fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR?
|
||||
.nf
|
||||
\fBchan create \fImode cmdPrefix\fR
|
||||
|
||||
\fIcmdPrefix \fBblocking\fR \fIchannelId mode\fR
|
||||
\fIcmdPrefix \fBcget\fR \fIchannelId option\fR
|
||||
\fIcmdPrefix \fBcgetall\fR \fIchannelId\fR
|
||||
\fIcmdPrefix \fBconfigure\fR \fIchannelId option value\fR
|
||||
\fIcmdPrefix \fBfinalize\fR \fIchannelId\fR
|
||||
\fIcmdPrefix \fBinitialize\fR \fIchannelId mode\fR
|
||||
\fIcmdPrefix \fBread\fR \fIchannelId count\fR
|
||||
\fIcmdPrefix \fBseek\fR \fIchannelId offset base\fR
|
||||
\fIcmdPrefix \fBwatch\fR \fIchannelId eventspec\fR
|
||||
\fIcmdPrefix \fBwrite\fR \fIchannelId data\fR
|
||||
.fi
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
|
||||
+3
-3
@@ -35,10 +35,10 @@ if \fItime\fR is not specified.
|
||||
.sp
|
||||
The parameter \fImax-count\fR could additionally impose a further restriction
|
||||
by the maximal number of iterations to evaluate the script.
|
||||
If \fImax-count\fR is specified, the evalution will stop either this count of
|
||||
If \fImax-count\fR is specified, the evaluation will stop either this count of
|
||||
iterations is reached or the time is exceeded.
|
||||
.sp
|
||||
It will then return a canonical tcl-list of the form:
|
||||
It will then return a canonical Tcl-list of the form:
|
||||
.PP
|
||||
.CS
|
||||
\fB0.095977 \(mcs/# 52095836 # 10419167 #/sec 5000.000 net-ms\fR
|
||||
@@ -85,7 +85,7 @@ used to measure the cost of \fBTcl_EvalObjEx\fR, of the invocation of canonical
|
||||
lists, and of the uncompiled versions of bytecoded commands.
|
||||
.PP
|
||||
As opposed to the \fBtime\fR commmand, which runs the tested script for a fixed
|
||||
number of iterations, the timerate command runs it for a fixed time.
|
||||
number of iterations, the \fBtimerate\fR command runs it for a fixed time.
|
||||
Additionally, the compiled variant of the script will be used during the entire
|
||||
measurement, as if the script were part of a compiled procedure, if the \fB\-direct\fR
|
||||
option is not specified. The fixed time period and possibility of compilation allow
|
||||
|
||||
+12
-1
@@ -11,7 +11,18 @@
|
||||
.SH NAME
|
||||
transchan \- command handler API of channel transforms
|
||||
.SH SYNOPSIS
|
||||
\fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR?
|
||||
.nf
|
||||
\fBchan push \fIchannelName cmdPrefix\fR
|
||||
|
||||
\fIcmdPrefix \fBclear \fIhandle\fR
|
||||
\fIcmdPrefix \fBdrain \fIhandle\fR
|
||||
\fIcmdPrefix \fBfinalize \fIhandle\fR
|
||||
\fIcmdPrefix \fBflush \fIhandle\fR
|
||||
\fIcmdPrefix \fBinitialize \fIhandle mode\fR
|
||||
\fIcmdPrefix \fBlimit? \fIhandle\fR
|
||||
\fIcmdPrefix \fBread \fIhandle buffer\fR
|
||||
\fIcmdPrefix \fBwrite \fIhandle buffer\fR
|
||||
.fi
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
|
||||
+12
-12
@@ -146,7 +146,7 @@ declare 32 {
|
||||
}
|
||||
# Only available in Tcl 8.x, NULL in Tcl 9.0
|
||||
declare 33 {
|
||||
unsigned char *TclGetByteArrayFromObj(Tcl_Obj *objPtr, int *numBytesPtr)
|
||||
unsigned char *TclGetByteArrayFromObj(Tcl_Obj *objPtr, void *numBytesPtr)
|
||||
}
|
||||
declare 34 {
|
||||
int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr)
|
||||
@@ -173,7 +173,7 @@ declare 40 {
|
||||
const Tcl_ObjType *Tcl_GetObjType(const char *typeName)
|
||||
}
|
||||
declare 41 {
|
||||
char *TclGetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr)
|
||||
char *TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr)
|
||||
}
|
||||
declare 42 {
|
||||
void Tcl_InvalidateStringRep(Tcl_Obj *objPtr)
|
||||
@@ -188,7 +188,7 @@ declare 44 {
|
||||
}
|
||||
declare 45 {
|
||||
int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
int *objcPtr, Tcl_Obj ***objvPtr)
|
||||
void *objcPtr, Tcl_Obj ***objvPtr)
|
||||
}
|
||||
declare 46 {
|
||||
int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index,
|
||||
@@ -196,7 +196,7 @@ declare 46 {
|
||||
}
|
||||
declare 47 {
|
||||
int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
int *lengthPtr)
|
||||
void *lengthPtr)
|
||||
}
|
||||
declare 48 {
|
||||
int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first,
|
||||
@@ -881,12 +881,12 @@ declare 241 {
|
||||
void Tcl_SourceRCFile(Tcl_Interp *interp)
|
||||
}
|
||||
declare 242 {
|
||||
int TclSplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
|
||||
int TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr,
|
||||
const char ***argvPtr)
|
||||
}
|
||||
# Obsolete, use Tcl_FSSplitPath
|
||||
declare 243 {
|
||||
void TclSplitPath(const char *path, int *argcPtr, const char ***argvPtr)
|
||||
void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr)
|
||||
}
|
||||
# Removed in 9.0 (stub entry only)
|
||||
#declare 244 {
|
||||
@@ -1442,7 +1442,7 @@ declare 392 {
|
||||
}
|
||||
declare 393 {
|
||||
int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc,
|
||||
void *clientData, Tcl_Size stackSize, int flags)
|
||||
void *clientData, TCL_HASH_TYPE stackSize, int flags)
|
||||
}
|
||||
|
||||
# Introduced in 8.3.2
|
||||
@@ -1601,7 +1601,7 @@ declare 433 {
|
||||
|
||||
# introduced in 8.4a3
|
||||
declare 434 {
|
||||
Tcl_UniChar *TclGetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr)
|
||||
Tcl_UniChar *TclGetUnicodeFromObj(Tcl_Obj *objPtr, void *lengthPtr)
|
||||
}
|
||||
|
||||
# TIP#15 (math function introspection) dkf
|
||||
@@ -1702,7 +1702,7 @@ declare 460 {
|
||||
Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements)
|
||||
}
|
||||
declare 461 {
|
||||
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr)
|
||||
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr)
|
||||
}
|
||||
declare 462 {
|
||||
int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr)
|
||||
@@ -1841,7 +1841,7 @@ declare 496 {
|
||||
Tcl_Obj *keyPtr)
|
||||
}
|
||||
declare 497 {
|
||||
int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr)
|
||||
int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr)
|
||||
}
|
||||
declare 498 {
|
||||
int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr,
|
||||
@@ -2270,7 +2270,7 @@ declare 603 {
|
||||
# TIP#265 (option parser) dkf for Sam Bromley
|
||||
declare 604 {
|
||||
int TclParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable,
|
||||
int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv)
|
||||
void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv)
|
||||
}
|
||||
|
||||
# TIP#336 (manipulate the error line) dgp
|
||||
@@ -2468,7 +2468,7 @@ declare 648 {
|
||||
# TIP #568
|
||||
declare 649 {
|
||||
unsigned char *TclGetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int *numBytesPtr)
|
||||
void *numBytesPtr)
|
||||
}
|
||||
declare 650 {
|
||||
unsigned char *Tcl_GetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
|
||||
+11
-14
@@ -561,7 +561,7 @@ typedef int (Tcl_CmdObjTraceProc) (void *clientData, Tcl_Interp *interp,
|
||||
int level, const char *command, Tcl_Command commandInfo, int objc,
|
||||
struct Tcl_Obj *const *objv);
|
||||
typedef int (Tcl_CmdObjTraceProc2) (void *clientData, Tcl_Interp *interp,
|
||||
ptrdiff_t level, const char *command, Tcl_Command commandInfo, ptrdiff_t objc,
|
||||
Tcl_Size level, const char *command, Tcl_Command commandInfo, Tcl_Size objc,
|
||||
struct Tcl_Obj *const *objv);
|
||||
typedef void (Tcl_CmdObjTraceDeleteProc) (void *clientData);
|
||||
typedef void (Tcl_DupInternalRepProc) (struct Tcl_Obj *srcPtr,
|
||||
@@ -586,7 +586,7 @@ typedef void (Tcl_NamespaceDeleteProc) (void *clientData);
|
||||
typedef int (Tcl_ObjCmdProc) (void *clientData, Tcl_Interp *interp,
|
||||
int objc, struct Tcl_Obj *const *objv);
|
||||
typedef int (Tcl_ObjCmdProc2) (void *clientData, Tcl_Interp *interp,
|
||||
ptrdiff_t objc, struct Tcl_Obj *const *objv);
|
||||
Tcl_Size objc, struct Tcl_Obj *const *objv);
|
||||
typedef int (Tcl_LibraryInitProc) (Tcl_Interp *interp);
|
||||
typedef int (Tcl_LibraryUnloadProc) (Tcl_Interp *interp, int flags);
|
||||
typedef void (Tcl_PanicProc) (const char *format, ...);
|
||||
@@ -809,8 +809,8 @@ typedef struct {
|
||||
typedef struct Tcl_DString {
|
||||
char *string; /* Points to beginning of string: either
|
||||
* staticSpace below or a malloced array. */
|
||||
Tcl_Size length; /* Number of non-NULL characters in the
|
||||
* string. */
|
||||
Tcl_Size length; /* Number of bytes in string excluding
|
||||
* terminating nul */
|
||||
Tcl_Size spaceAvl; /* Total number of bytes available for the
|
||||
* string and its terminating NULL char. */
|
||||
char staticSpace[TCL_DSTRING_STATIC_SIZE];
|
||||
@@ -1933,8 +1933,6 @@ typedef struct Tcl_EncodingType {
|
||||
* reset to an initial state. If the source
|
||||
* buffer contains the entire input stream to be
|
||||
* converted, this flag should be set.
|
||||
* TCL_ENCODING_STRICT - Be more strict in accepting what
|
||||
* is considered a 'invalid byte sequence'.
|
||||
* TCL_ENCODING_STOPONERROR - Not used any more.
|
||||
* TCL_ENCODING_NO_TERMINATE - If set, Tcl_ExternalToUtf does not append a
|
||||
* terminating NUL byte. Since it does not need
|
||||
@@ -1969,16 +1967,15 @@ typedef struct Tcl_EncodingType {
|
||||
#define TCL_ENCODING_CHAR_LIMIT 0x10
|
||||
/* Internal use bits, do not define bits in this space. See above comment */
|
||||
#define TCL_ENCODING_INTERNAL_USE_MASK 0xFF00
|
||||
/* Reserve top byte for profile values (disjoint, not a mask) */
|
||||
/*
|
||||
* Reserve top byte for profile values (disjoint, not a mask). In case of
|
||||
* changes, ensure ENCODING_PROFILE_* macros in tclInt.h are modified if
|
||||
* necessary.
|
||||
*/
|
||||
#define TCL_ENCODING_PROFILE_TCL8 0x01000000
|
||||
#define TCL_ENCODING_PROFILE_STRICT 0x02000000
|
||||
#define TCL_ENCODING_PROFILE_REPLACE 0x03000000
|
||||
/* Still being argued - For Tcl9, is the default strict? TODO */
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8
|
||||
#else
|
||||
#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8 /* STRICT? REPLACE? TODO */
|
||||
#endif
|
||||
#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_STRICT
|
||||
|
||||
/*
|
||||
* The following definitions are the error codes returned by the conversion
|
||||
@@ -2343,7 +2340,7 @@ EXTERN const char *TclZipfs_AppHook(int *argc, char ***argv);
|
||||
TclStubCall((void *)4))(argc, argv, appInitProc, interp)
|
||||
#if !defined(_WIN32) || !defined(UNICODE)
|
||||
#define Tcl_MainEx(argc, argv, appInitProc, interp) \
|
||||
(void)((const char *(*)(size_t, const void *, Tcl_AppInitProc *, Tcl_Interp *)) \
|
||||
(void)((const char *(*)(Tcl_Size, const void *, Tcl_AppInitProc *, Tcl_Interp *)) \
|
||||
TclStubCall((void *)5))(argc, argv, appInitProc, interp)
|
||||
#endif
|
||||
#define Tcl_StaticLibrary(interp, pkgName, initProc, safeInitProc) \
|
||||
|
||||
+180
-107
@@ -13,36 +13,95 @@
|
||||
#include "tclInt.h"
|
||||
#include "tclArithSeries.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
/* -------------------------- ArithSeries object ---------------------------- */
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*
|
||||
* - ArithRound -- Round doubles to the number of significant fractional
|
||||
* digits
|
||||
* - ArithSeriesIndexDbl -- base list indexing operation for doubles
|
||||
* - ArithSeriesIndexInt -- " " " " " integers
|
||||
* - ArithSeriesGetInternalRep -- Return the internal rep from a Tcl_Obj
|
||||
* - Precision -- determine the number of factional digits for the given
|
||||
* double value
|
||||
* - maxPrecision -- Using the values provide, determine the longest percision
|
||||
* in the arithSeries
|
||||
*/
|
||||
static inline double
|
||||
ArithRound(double d, unsigned int n) {
|
||||
double scalefactor = pow(10, n);
|
||||
return round(d*scalefactor)/scalefactor;
|
||||
}
|
||||
|
||||
#define ArithSeriesRepPtr(arithSeriesObjPtr) \
|
||||
(ArithSeries *) ((arithSeriesObjPtr)->internalRep.twoPtrValue.ptr1)
|
||||
static inline double
|
||||
ArithSeriesIndexDbl(
|
||||
ArithSeries *arithSeriesRepPtr,
|
||||
Tcl_WideInt index)
|
||||
{
|
||||
ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
|
||||
if (arithSeriesRepPtr->isDouble) {
|
||||
double d = dblRepPtr->start + (index * dblRepPtr->step);
|
||||
unsigned n = (dblRepPtr->precision > 0 ? dblRepPtr->precision : 0);
|
||||
return ArithRound(d, n);
|
||||
} else {
|
||||
return (double)(arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step));
|
||||
}
|
||||
}
|
||||
|
||||
#define ArithSeriesIndexM(arithSeriesRepPtr, index) \
|
||||
((arithSeriesRepPtr)->isDouble ? \
|
||||
(((ArithSeriesDbl*)(arithSeriesRepPtr))->start+((index) * ((ArithSeriesDbl*)(arithSeriesRepPtr))->step)) \
|
||||
: \
|
||||
((arithSeriesRepPtr)->start+((index) * arithSeriesRepPtr->step)))
|
||||
static inline Tcl_WideInt
|
||||
ArithSeriesIndexInt(
|
||||
ArithSeries *arithSeriesRepPtr,
|
||||
Tcl_WideInt index)
|
||||
{
|
||||
ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
|
||||
if (arithSeriesRepPtr->isDouble) {
|
||||
return (Tcl_WideInt)(dblRepPtr->start + ((index) * dblRepPtr->step));
|
||||
} else {
|
||||
return (arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step));
|
||||
}
|
||||
}
|
||||
|
||||
#define ArithSeriesGetInternalRep(objPtr, arithRepPtr) \
|
||||
do { \
|
||||
const Tcl_ObjInternalRep *irPtr; \
|
||||
irPtr = TclFetchInternalRep((objPtr), &tclArithSeriesType.objType); \
|
||||
(arithRepPtr) = irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL; \
|
||||
} while (0)
|
||||
static inline ArithSeries*
|
||||
ArithSeriesGetInternalRep(Tcl_Obj *objPtr)
|
||||
{
|
||||
const Tcl_ObjInternalRep *irPtr;
|
||||
irPtr = TclFetchInternalRep((objPtr), &tclArithSeriesType.objType);
|
||||
return irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
Precision(double d)
|
||||
{
|
||||
char tmp[TCL_DOUBLE_SPACE+2], *off;
|
||||
tmp[0] = 0;
|
||||
Tcl_PrintDouble(NULL,d,tmp);
|
||||
off = strchr(tmp, '.');
|
||||
return (off ? strlen(off+1) : 0);
|
||||
}
|
||||
static inline int
|
||||
maxPrecision(double start, double end, double step)
|
||||
{
|
||||
// Find longest number of digits after the decimal point.
|
||||
int dp = Precision(step);
|
||||
int i = Precision(start);
|
||||
dp = i>dp ? i : dp;
|
||||
i = Precision(end);
|
||||
dp = i>dp ? i : dp;
|
||||
return dp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototypes for procedures defined later in this file:
|
||||
*/
|
||||
|
||||
static void DupArithSeriesInternalRep (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
|
||||
static void FreeArithSeriesInternalRep (Tcl_Obj *listPtr);
|
||||
static int SetArithSeriesFromAny (Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static void UpdateStringOfArithSeries (Tcl_Obj *arithSeriesObj);
|
||||
static Tcl_Obj *ArithSeriesObjStep(Tcl_Obj *arithSeriesPtr);
|
||||
static void DupArithSeriesInternalRep (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
|
||||
static void FreeArithSeriesInternalRep (Tcl_Obj *listPtr);
|
||||
static int SetArithSeriesFromAny (Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static void UpdateStringOfArithSeries (Tcl_Obj *arithSeriesObj);
|
||||
static Tcl_Obj* ArithSeriesObjStep(Tcl_Obj *arithSeriesPtr);
|
||||
static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesPtr);
|
||||
|
||||
/*
|
||||
@@ -107,7 +166,7 @@ const TclObjTypeWithAbstractList tclArithSeriesType = {
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static Tcl_WideInt
|
||||
ArithSeriesLen(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
|
||||
ArithSeriesLenInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
|
||||
{
|
||||
Tcl_WideInt len;
|
||||
|
||||
@@ -118,6 +177,18 @@ ArithSeriesLen(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
|
||||
return (len < 0) ? -1 : len;
|
||||
}
|
||||
|
||||
static Tcl_WideInt
|
||||
ArithSeriesLenDbl(double start, double end, double step)
|
||||
{
|
||||
Tcl_WideInt len;
|
||||
|
||||
if (step == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = ((end-start+step)/step);
|
||||
return (len < 0) ? -1 : len;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -140,10 +211,13 @@ static
|
||||
Tcl_Obj *
|
||||
NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_WideInt len)
|
||||
{
|
||||
Tcl_WideInt length = (len>=0 ? len : ArithSeriesLen(start, end, step));
|
||||
Tcl_WideInt length;
|
||||
Tcl_Obj *arithSeriesObj;
|
||||
ArithSeries *arithSeriesRepPtr;
|
||||
|
||||
length = len>=0 ? len : -1;
|
||||
if (length < 0) length = -1;
|
||||
|
||||
TclNewObj(arithSeriesObj);
|
||||
|
||||
if (length <= 0) {
|
||||
@@ -184,14 +258,20 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide
|
||||
* None.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static
|
||||
Tcl_Obj *
|
||||
NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len)
|
||||
{
|
||||
Tcl_WideInt length = (len>=0 ? len : ArithSeriesLen(start, end, step));
|
||||
Tcl_WideInt length;
|
||||
Tcl_Obj *arithSeriesObj;
|
||||
ArithSeriesDbl *arithSeriesRepPtr;
|
||||
|
||||
length = len>=0 ? len : -1;
|
||||
if (length < 0) {
|
||||
length = -1;
|
||||
}
|
||||
|
||||
TclNewObj(arithSeriesObj);
|
||||
|
||||
if (length <= 0) {
|
||||
@@ -205,11 +285,14 @@ NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len)
|
||||
arithSeriesRepPtr->step = step;
|
||||
arithSeriesRepPtr->len = length;
|
||||
arithSeriesRepPtr->elements = NULL;
|
||||
arithSeriesRepPtr->precision = maxPrecision(start,end,step);
|
||||
arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
|
||||
arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
arithSeriesObj->typePtr = &tclArithSeriesType.objType;
|
||||
if (length > 0)
|
||||
|
||||
if (length > 0) {
|
||||
Tcl_InvalidateStringRep(arithSeriesObj);
|
||||
}
|
||||
|
||||
return arithSeriesObj;
|
||||
}
|
||||
@@ -295,7 +378,7 @@ TclNewArithSeriesObj(
|
||||
{
|
||||
double dstart, dend, dstep;
|
||||
Tcl_WideInt start, end, step;
|
||||
Tcl_WideInt len;
|
||||
Tcl_WideInt len = -1;
|
||||
|
||||
if (startObj) {
|
||||
assignNumber(useDoubles, &start, &dstart, startObj);
|
||||
@@ -311,7 +394,7 @@ TclNewArithSeriesObj(
|
||||
dstep = step;
|
||||
}
|
||||
if (dstep == 0) {
|
||||
*arithSeriesObj = Tcl_NewObj();
|
||||
TclNewObj(*arithSeriesObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
@@ -337,9 +420,9 @@ TclNewArithSeriesObj(
|
||||
assert(dstep!=0);
|
||||
if (!lenObj) {
|
||||
if (useDoubles) {
|
||||
len = (dend - dstart + dstep)/dstep;
|
||||
len = ArithSeriesLenDbl(dstart, dend, dstep);
|
||||
} else {
|
||||
len = (end - start + step)/step;
|
||||
len = ArithSeriesLenInt(start, end, step);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -354,7 +437,7 @@ TclNewArithSeriesObj(
|
||||
}
|
||||
}
|
||||
|
||||
if (TCL_MAJOR_VERSION < 9 && len > ListSizeT_MAX) {
|
||||
if (len > TCL_SIZE_MAX) {
|
||||
Tcl_SetObjResult(
|
||||
interp,
|
||||
Tcl_NewStringObj("max length of a Tcl list exceeded", -1));
|
||||
@@ -398,7 +481,7 @@ ArithSeriesObjStep(
|
||||
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
|
||||
Tcl_Panic("ArithSeriesObjStep called with a not ArithSeries Obj.");
|
||||
}
|
||||
arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObj);
|
||||
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
|
||||
if (arithSeriesRepPtr->isDouble) {
|
||||
TclNewDoubleObj(stepObj, ((ArithSeriesDbl*)(arithSeriesRepPtr))->step);
|
||||
} else {
|
||||
@@ -430,7 +513,7 @@ ArithSeriesObjStep(
|
||||
|
||||
Tcl_Obj *
|
||||
TclArithSeriesObjIndex(
|
||||
Tcl_Interp *interp,
|
||||
TCL_UNUSED(Tcl_Interp *),
|
||||
Tcl_Obj *arithSeriesObj,
|
||||
Tcl_WideInt index)
|
||||
{
|
||||
@@ -439,21 +522,15 @@ TclArithSeriesObjIndex(
|
||||
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
|
||||
Tcl_Panic("TclArithSeriesObjIndex called with a not ArithSeries Obj.");
|
||||
}
|
||||
arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObj);
|
||||
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
|
||||
if (index < 0 || (Tcl_Size)index >= arithSeriesRepPtr->len) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("index %" TCL_LL_MODIFIER "d is out of bounds 0 to %"
|
||||
TCL_LL_MODIFIER "d", index, (arithSeriesRepPtr->len-1)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return NULL;
|
||||
return Tcl_NewObj();
|
||||
}
|
||||
/* List[i] = Start + (Step * index) */
|
||||
if (arithSeriesRepPtr->isDouble) {
|
||||
return Tcl_NewDoubleObj(ArithSeriesIndexM(arithSeriesRepPtr, index));
|
||||
return Tcl_NewDoubleObj(ArithSeriesIndexDbl(arithSeriesRepPtr, index));
|
||||
} else {
|
||||
return Tcl_NewWideIntObj(ArithSeriesIndexM(arithSeriesRepPtr, index));
|
||||
return Tcl_NewWideIntObj(ArithSeriesIndexInt(arithSeriesRepPtr, index));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,16 +618,25 @@ DupArithSeriesInternalRep(
|
||||
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
|
||||
{
|
||||
ArithSeries *srcArithSeriesRepPtr =
|
||||
(ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
ArithSeries *copyArithSeriesRepPtr;
|
||||
|
||||
(ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
/*
|
||||
* Allocate a new ArithSeries structure. */
|
||||
|
||||
copyArithSeriesRepPtr = (ArithSeries*) Tcl_Alloc(sizeof(ArithSeries));
|
||||
*copyArithSeriesRepPtr = *srcArithSeriesRepPtr;
|
||||
copyArithSeriesRepPtr->elements = NULL;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr;
|
||||
if (srcArithSeriesRepPtr->isDouble) {
|
||||
ArithSeriesDbl *srcArithSeriesDblRepPtr =
|
||||
(ArithSeriesDbl *)srcArithSeriesRepPtr;
|
||||
ArithSeriesDbl *copyArithSeriesDblRepPtr =
|
||||
(ArithSeriesDbl *) Tcl_Alloc(sizeof(ArithSeriesDbl));
|
||||
*copyArithSeriesDblRepPtr = *srcArithSeriesDblRepPtr;
|
||||
copyArithSeriesDblRepPtr->elements = NULL;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesDblRepPtr;
|
||||
} else {
|
||||
ArithSeries *copyArithSeriesRepPtr =
|
||||
(ArithSeries *) Tcl_Alloc(sizeof(ArithSeries));
|
||||
*copyArithSeriesRepPtr = *srcArithSeriesRepPtr;
|
||||
copyArithSeriesRepPtr->elements = NULL;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr;
|
||||
}
|
||||
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
copyPtr->typePtr = &tclArithSeriesType.objType;
|
||||
}
|
||||
@@ -591,29 +677,47 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObj)
|
||||
char *elem, *p;
|
||||
Tcl_Obj *elemObj;
|
||||
Tcl_Size i;
|
||||
Tcl_WideInt length = 0;
|
||||
Tcl_Size length = 0;
|
||||
Tcl_Size slen;
|
||||
|
||||
/*
|
||||
* Pass 1: estimate space.
|
||||
*/
|
||||
for (i = 0; i < arithSeriesRepPtr->len; i++) {
|
||||
elemObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, i);
|
||||
elem = Tcl_GetStringFromObj(elemObj, &slen);
|
||||
Tcl_DecrRefCount(elemObj);
|
||||
slen += 1; /* + 1 is for the space or the nul-term */
|
||||
length += slen;
|
||||
if (!arithSeriesRepPtr->isDouble) {
|
||||
for (i = 0; i < arithSeriesRepPtr->len; i++) {
|
||||
double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
|
||||
slen = d>0 ? log10(d)+1 : d<0 ? log10((0-d))+2 : 1;
|
||||
length += slen;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < arithSeriesRepPtr->len; i++) {
|
||||
double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
|
||||
char tmp[TCL_DOUBLE_SPACE+2];
|
||||
tmp[0] = 0;
|
||||
Tcl_PrintDouble(NULL,d,tmp);
|
||||
if ((length + strlen(tmp)) > TCL_SIZE_MAX) {
|
||||
break; // overflow
|
||||
}
|
||||
length += strlen(tmp);
|
||||
}
|
||||
}
|
||||
length += arithSeriesRepPtr->len; // Space for each separator
|
||||
|
||||
/*
|
||||
* Pass 2: generate the string repr.
|
||||
*/
|
||||
|
||||
p = Tcl_InitStringRep(arithSeriesObj, NULL, length);
|
||||
if (p == NULL) {
|
||||
Tcl_Panic("Unable to allocate string size %" TCL_Z_MODIFIER "u", length);
|
||||
}
|
||||
for (i = 0; i < arithSeriesRepPtr->len; i++) {
|
||||
elemObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, i);
|
||||
elem = Tcl_GetStringFromObj(elemObj, &slen);
|
||||
strcpy(p, elem);
|
||||
if (((p - arithSeriesObj->bytes)+slen) > length) {
|
||||
break;
|
||||
}
|
||||
strncpy(p, elem, slen);
|
||||
p[slen] = ' ';
|
||||
p += slen+1;
|
||||
Tcl_DecrRefCount(elemObj);
|
||||
@@ -653,52 +757,6 @@ SetArithSeriesFromAny(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclArithSeriesObjCopy --
|
||||
*
|
||||
* Makes a "pure arithSeries" copy of an ArithSeries 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
|
||||
* arithSeries value as *arithSeriesObj does. The returned Tcl_Obj has a
|
||||
* refCount of zero. If *arithSeriesObj does not hold an arithSeries,
|
||||
* NULL is returned, and if interp is non-NULL, an error message is
|
||||
* recorded there.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclArithSeriesObjCopy(
|
||||
Tcl_Interp *interp, /* Used to report errors if not NULL. */
|
||||
Tcl_Obj *arithSeriesObj) /* List object for which an element array is
|
||||
* to be returned. */
|
||||
{
|
||||
Tcl_Obj *copyPtr;
|
||||
ArithSeries *arithSeriesRepPtr;
|
||||
|
||||
ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
|
||||
if (NULL == arithSeriesRepPtr) {
|
||||
if (SetArithSeriesFromAny(interp, arithSeriesObj) != TCL_OK) {
|
||||
/* We know this is going to panic, but it's the message we want */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TclNewObj(copyPtr);
|
||||
TclInvalidateStringRep(copyPtr);
|
||||
DupArithSeriesInternalRep(arithSeriesObj, copyPtr);
|
||||
return copyPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -728,17 +786,30 @@ TclArithSeriesObjRange(
|
||||
ArithSeries *arithSeriesRepPtr;
|
||||
Tcl_Obj *startObj, *endObj, *stepObj;
|
||||
|
||||
ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
|
||||
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
|
||||
|
||||
if (fromIdx == TCL_INDEX_NONE) {
|
||||
fromIdx = 0;
|
||||
}
|
||||
if (fromIdx > toIdx) {
|
||||
|
||||
if (fromIdx > toIdx ||
|
||||
(toIdx > arithSeriesRepPtr->len-1 &&
|
||||
fromIdx > arithSeriesRepPtr->len-1)) {
|
||||
Tcl_Obj *obj;
|
||||
TclNewObj(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (fromIdx < 0) {
|
||||
fromIdx = 0;
|
||||
}
|
||||
if (toIdx < 0) {
|
||||
toIdx = 0;
|
||||
}
|
||||
if (toIdx > arithSeriesRepPtr->len-1) {
|
||||
toIdx = arithSeriesRepPtr->len-1;
|
||||
}
|
||||
|
||||
startObj = TclArithSeriesObjIndex(interp, arithSeriesObj, fromIdx);
|
||||
if (startObj == NULL) {
|
||||
return NULL;
|
||||
@@ -778,15 +849,17 @@ TclArithSeriesObjRange(
|
||||
TclInvalidateStringRep(arithSeriesObj);
|
||||
|
||||
if (arithSeriesRepPtr->isDouble) {
|
||||
ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesObj;
|
||||
ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
|
||||
double start, end, step;
|
||||
|
||||
Tcl_GetDoubleFromObj(NULL, startObj, &start);
|
||||
Tcl_GetDoubleFromObj(NULL, endObj, &end);
|
||||
Tcl_GetDoubleFromObj(NULL, stepObj, &step);
|
||||
arithSeriesDblRepPtr->start = start;
|
||||
arithSeriesDblRepPtr->end = end;
|
||||
arithSeriesDblRepPtr->step = step;
|
||||
arithSeriesDblRepPtr->len = (end-start+step)/step;
|
||||
arithSeriesDblRepPtr->precision = maxPrecision(start, end, step);
|
||||
arithSeriesDblRepPtr->len = ArithSeriesLenDbl(start, end, step);
|
||||
arithSeriesDblRepPtr->elements = NULL;
|
||||
|
||||
} else {
|
||||
@@ -797,7 +870,7 @@ TclArithSeriesObjRange(
|
||||
arithSeriesRepPtr->start = start;
|
||||
arithSeriesRepPtr->end = end;
|
||||
arithSeriesRepPtr->step = step;
|
||||
arithSeriesRepPtr->len = (end-start+step)/step;
|
||||
arithSeriesRepPtr->len = ArithSeriesLenInt(start, end, step);
|
||||
arithSeriesRepPtr->elements = NULL;
|
||||
}
|
||||
|
||||
@@ -852,7 +925,7 @@ TclArithSeriesGetElements(
|
||||
Tcl_Obj **objv;
|
||||
int i, objc;
|
||||
|
||||
ArithSeriesGetInternalRep(objPtr, arithSeriesRepPtr);
|
||||
arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr);
|
||||
objc = arithSeriesRepPtr->len;
|
||||
if (objc > 0) {
|
||||
if (arithSeriesRepPtr->elements) {
|
||||
@@ -927,7 +1000,7 @@ TclArithSeriesObjReverse(
|
||||
double dstart, dend, dstep;
|
||||
int isDouble;
|
||||
|
||||
ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
|
||||
arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
|
||||
|
||||
isDouble = arithSeriesRepPtr->isDouble;
|
||||
len = arithSeriesRepPtr->len;
|
||||
|
||||
@@ -30,11 +30,10 @@ typedef struct {
|
||||
double start;
|
||||
double end;
|
||||
double step;
|
||||
int precision;
|
||||
} ArithSeriesDbl;
|
||||
|
||||
|
||||
MODULE_SCOPE Tcl_Obj * TclArithSeriesObjCopy(Tcl_Interp *interp,
|
||||
Tcl_Obj *arithSeriesPtr);
|
||||
MODULE_SCOPE Tcl_Obj *TclArithSeriesObjIndex(Tcl_Interp *, Tcl_Obj *,
|
||||
Tcl_WideInt index);
|
||||
MODULE_SCOPE Tcl_Obj * TclArithSeriesObjRange(Tcl_Interp *interp,
|
||||
|
||||
@@ -2247,7 +2247,7 @@ static int
|
||||
GetListIndexOperand(
|
||||
AssemblyEnv* assemEnvPtr, /* Assembly environment */
|
||||
Tcl_Token** tokenPtrPtr, /* Current token from the parser */
|
||||
int* result) /* OUTPUT: Integer extracted from the token */
|
||||
int* result) /* OUTPUT: encoded index derived from the token */
|
||||
{
|
||||
CompileEnv* envPtr = assemEnvPtr->envPtr;
|
||||
/* Compilation environment */
|
||||
|
||||
+32
-13
@@ -805,7 +805,7 @@ Tcl_CreateInterp(void)
|
||||
iPtr->legacyFreeProc = (void (*) (void))-1;
|
||||
iPtr->errorLine = 0;
|
||||
iPtr->stubTable = &tclStubs;
|
||||
iPtr->objResultPtr = Tcl_NewObj();
|
||||
TclNewObj(iPtr->objResultPtr);
|
||||
Tcl_IncrRefCount(iPtr->objResultPtr);
|
||||
iPtr->handle = TclHandleCreate(iPtr);
|
||||
iPtr->globalNsPtr = NULL;
|
||||
@@ -890,7 +890,7 @@ Tcl_CreateInterp(void)
|
||||
iPtr->activeInterpTracePtr = NULL;
|
||||
iPtr->assocData = NULL;
|
||||
iPtr->execEnvPtr = NULL; /* Set after namespaces initialized. */
|
||||
iPtr->emptyObjPtr = Tcl_NewObj();
|
||||
TclNewObj(iPtr->emptyObjPtr);
|
||||
/* Another empty object. */
|
||||
Tcl_IncrRefCount(iPtr->emptyObjPtr);
|
||||
iPtr->threadId = Tcl_GetCurrentThread();
|
||||
@@ -954,7 +954,7 @@ Tcl_CreateInterp(void)
|
||||
* TIP #285, Script cancellation support.
|
||||
*/
|
||||
|
||||
iPtr->asyncCancelMsg = Tcl_NewObj();
|
||||
TclNewObj(iPtr->asyncCancelMsg);
|
||||
|
||||
cancelInfo = (CancelInfo *)Tcl_Alloc(sizeof(CancelInfo));
|
||||
cancelInfo->interp = interp;
|
||||
@@ -3298,7 +3298,7 @@ invokeObj2Command(
|
||||
Command *cmdPtr = (Command *) clientData;
|
||||
|
||||
if (objc > INT_MAX) {
|
||||
objc = TCL_INDEX_NONE; /* TODO - why? Should error, not truncate */
|
||||
return TclCommandWordLimitError(interp, objc);
|
||||
}
|
||||
if (cmdPtr->objProc != NULL) {
|
||||
result = cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
|
||||
@@ -3315,6 +3315,9 @@ static int cmdWrapper2Proc(void *clientData,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Command *cmdPtr = (Command *)clientData;
|
||||
if (objc > INT_MAX) {
|
||||
return TclCommandWordLimitError(interp, objc);
|
||||
}
|
||||
return cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
|
||||
}
|
||||
|
||||
@@ -5164,17 +5167,17 @@ TclEvalEx(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
const char *p, *next;
|
||||
const unsigned int minObjs = 20;
|
||||
const int minObjs = 20;
|
||||
Tcl_Obj **objv, **objvSpace;
|
||||
int *expand, *lines, *lineSpace;
|
||||
Tcl_Token *tokenPtr;
|
||||
int bytesLeft, expandRequested, code = TCL_OK;
|
||||
Tcl_Size commandLength;
|
||||
int expandRequested, code = TCL_OK;
|
||||
Tcl_Size bytesLeft, commandLength;
|
||||
CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
|
||||
* TCL_EVAL_GLOBAL was set. */
|
||||
int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
|
||||
int gotParse = 0;
|
||||
TCL_HASH_TYPE i, objectsUsed = 0;
|
||||
Tcl_Size i, objectsUsed = 0;
|
||||
/* These variables keep track of how much
|
||||
* state has been allocated while evaluating
|
||||
* the script, so that it can be freed
|
||||
@@ -5312,8 +5315,8 @@ TclEvalEx(
|
||||
Tcl_Size wordLine = line;
|
||||
const char *wordStart = parsePtr->commandStart;
|
||||
int *wordCLNext = clNext;
|
||||
unsigned int objectsNeeded = 0;
|
||||
unsigned int numWords = parsePtr->numWords;
|
||||
Tcl_Size objectsNeeded = 0;
|
||||
Tcl_Size numWords = parsePtr->numWords;
|
||||
|
||||
/*
|
||||
* Generate an array of objects for the words of the command.
|
||||
@@ -5332,6 +5335,8 @@ TclEvalEx(
|
||||
for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr;
|
||||
objectsUsed < numWords;
|
||||
objectsUsed++, tokenPtr += tokenPtr->numComponents+1) {
|
||||
Tcl_Size additionalObjsCount;
|
||||
|
||||
/*
|
||||
* TIP #280. Track lines to current word. Save the information
|
||||
* on a per-word basis, signaling dynamic words as needed.
|
||||
@@ -5381,12 +5386,22 @@ TclEvalEx(
|
||||
expandRequested = 1;
|
||||
expand[objectsUsed] = 1;
|
||||
|
||||
objectsNeeded += (numElements ? numElements : 1);
|
||||
additionalObjsCount = (numElements ? numElements : 1);
|
||||
|
||||
} else {
|
||||
expand[objectsUsed] = 0;
|
||||
objectsNeeded++;
|
||||
additionalObjsCount = 1;
|
||||
}
|
||||
|
||||
/* Currently max command words in INT_MAX */
|
||||
if (additionalObjsCount > INT_MAX ||
|
||||
objectsNeeded > (INT_MAX - additionalObjsCount)) {
|
||||
code = TclCommandWordLimitError(interp, -1);
|
||||
Tcl_DecrRefCount(objv[objectsUsed]);
|
||||
break;
|
||||
}
|
||||
objectsNeeded += additionalObjsCount;
|
||||
|
||||
if (wordCLNext) {
|
||||
TclContinuationsEnterDerived(objv[objectsUsed],
|
||||
wordStart - outerScript, wordCLNext);
|
||||
@@ -6137,7 +6152,11 @@ TclNREvalObjEx(
|
||||
*/
|
||||
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
listPtr = TclListObjCopy(interp, objPtr);
|
||||
listPtr = TclDuplicatePureObj(interp, objPtr, &tclListType.objType);
|
||||
if (!listPtr) {
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
|
||||
if (word != INT_MIN) {
|
||||
|
||||
+24
-53
@@ -386,7 +386,7 @@ unsigned char *
|
||||
TclGetBytesFromObj(
|
||||
Tcl_Interp *interp, /* For error reporting */
|
||||
Tcl_Obj *objPtr, /* Value to extract from */
|
||||
int *numBytesPtr) /* If non-NULL, write the number of bytes
|
||||
void *numBytesPtr) /* If non-NULL, write the number of bytes
|
||||
* in the array here */
|
||||
{
|
||||
Tcl_Size numBytes = 0;
|
||||
@@ -404,7 +404,7 @@ TclGetBytesFromObj(
|
||||
}
|
||||
return NULL;
|
||||
} else {
|
||||
*numBytesPtr = (int) numBytes;
|
||||
*(int *)numBytesPtr = (int) numBytes;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
@@ -767,43 +767,14 @@ TclAppendBytesToByteArray(
|
||||
}
|
||||
needed = byteArrayPtr->used + len;
|
||||
if (needed > byteArrayPtr->allocated) {
|
||||
ByteArray *ptr = NULL;
|
||||
|
||||
/*
|
||||
* Try to allocate double the total space that is needed.
|
||||
*/
|
||||
|
||||
Tcl_Size attempt;
|
||||
|
||||
/* Make sure we do not wrap when doubling */
|
||||
if (needed <= (BYTEARRAY_MAX_LEN - needed)) {
|
||||
attempt = 2 * needed;
|
||||
ptr = (ByteArray *) Tcl_AttemptRealloc(byteArrayPtr,
|
||||
BYTEARRAY_SIZE(attempt));
|
||||
}
|
||||
|
||||
if (ptr == NULL) {
|
||||
/*
|
||||
* Try to allocate double the increment that is needed.
|
||||
* (Originally TCL_MIN_GROWTH was added as well but that would
|
||||
* need one more separate overflow check so forget it.)
|
||||
*/
|
||||
if (len <= (BYTEARRAY_MAX_LEN - needed)) {
|
||||
attempt = needed + len;
|
||||
ptr = (ByteArray *)Tcl_AttemptRealloc(byteArrayPtr,
|
||||
BYTEARRAY_SIZE(attempt));
|
||||
}
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
/*
|
||||
* Last chance: Try to allocate exactly what is needed.
|
||||
*/
|
||||
|
||||
attempt = needed;
|
||||
ptr = (ByteArray *)Tcl_Realloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
|
||||
}
|
||||
byteArrayPtr = ptr;
|
||||
byteArrayPtr->allocated = attempt;
|
||||
Tcl_Size newCapacity;
|
||||
byteArrayPtr =
|
||||
(ByteArray *)TclReallocElemsEx(byteArrayPtr,
|
||||
needed,
|
||||
1,
|
||||
offsetof(ByteArray, bytes),
|
||||
&newCapacity);
|
||||
byteArrayPtr->allocated = newCapacity;
|
||||
SET_BYTEARRAY(irPtr, byteArrayPtr);
|
||||
}
|
||||
|
||||
@@ -870,7 +841,7 @@ BinaryFormatCmd(
|
||||
int value = 0; /* Current integer value to be packed.
|
||||
* Initialized to avoid compiler warning. */
|
||||
char cmd; /* Current format character. */
|
||||
Tcl_Size count; /* Count associated with current format
|
||||
Tcl_Size count; /* Count associated with current format
|
||||
* character. */
|
||||
int flags; /* Format field flags */
|
||||
const char *format; /* Pointer to current position in format
|
||||
@@ -1383,7 +1354,7 @@ BinaryScanCmd(
|
||||
int value = 0; /* Current integer value to be packed.
|
||||
* Initialized to avoid compiler warning. */
|
||||
char cmd; /* Current format character. */
|
||||
Tcl_Size count; /* Count associated with current format
|
||||
Tcl_Size count; /* Count associated with current format
|
||||
* character. */
|
||||
int flags; /* Format field flags */
|
||||
const char *format; /* Pointer to current position in format
|
||||
@@ -1795,14 +1766,14 @@ GetFormatSpec(
|
||||
(*formatPtr)++;
|
||||
*countPtr = BINARY_ALL;
|
||||
} else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
|
||||
unsigned long count;
|
||||
unsigned long long count;
|
||||
|
||||
errno = 0;
|
||||
count = strtoul(*formatPtr, (char **) formatPtr, 10);
|
||||
if (errno || (count > (unsigned long) INT_MAX)) {
|
||||
*countPtr = INT_MAX;
|
||||
count = strtoull(*formatPtr, (char **) formatPtr, 10);
|
||||
if (errno || (count > TCL_SIZE_MAX)) {
|
||||
*countPtr = TCL_SIZE_MAX;
|
||||
} else {
|
||||
*countPtr = (int) count;
|
||||
*countPtr = count;
|
||||
}
|
||||
} else {
|
||||
*countPtr = BINARY_NOCOUNT;
|
||||
@@ -2638,11 +2609,11 @@ BinaryEncode64(
|
||||
{
|
||||
Tcl_Obj *resultObj;
|
||||
unsigned char *data, *limit;
|
||||
int maxlen = 0;
|
||||
Tcl_Size maxlen = 0;
|
||||
const char *wrapchar = "\n";
|
||||
Tcl_Size wrapcharlen = 1;
|
||||
int i, index, size, outindex = 0, purewrap = 1;
|
||||
Tcl_Size offset, count = 0;
|
||||
int index, purewrap = 1;
|
||||
Tcl_Size i, offset, size, outindex = 0, count = 0;
|
||||
enum { OPT_MAXLEN, OPT_WRAPCHAR };
|
||||
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
|
||||
|
||||
@@ -2658,7 +2629,7 @@ BinaryEncode64(
|
||||
}
|
||||
switch (index) {
|
||||
case OPT_MAXLEN:
|
||||
if (Tcl_GetIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
|
||||
if (Tcl_GetSizeIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (maxlen < 0) {
|
||||
@@ -2764,12 +2735,12 @@ BinaryEncodeUu(
|
||||
{
|
||||
Tcl_Obj *resultObj;
|
||||
unsigned char *data, *start, *cursor;
|
||||
int rawLength, i, bits, index;
|
||||
int i, bits, index;
|
||||
unsigned int n;
|
||||
int lineLength = 61;
|
||||
const unsigned char SingleNewline[] = { UCHAR('\n') };
|
||||
const unsigned char *wrapchar = SingleNewline;
|
||||
Tcl_Size j, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
|
||||
Tcl_Size j, rawLength, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
|
||||
enum { OPT_MAXLEN, OPT_WRAPCHAR };
|
||||
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
|
||||
|
||||
@@ -2859,7 +2830,7 @@ BinaryEncodeUu(
|
||||
*/
|
||||
|
||||
while (offset < count) {
|
||||
int lineLen = count - offset;
|
||||
Tcl_Size lineLen = count - offset;
|
||||
|
||||
if (lineLen > rawLength) {
|
||||
lineLen = rawLength;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
@@ -1233,6 +1234,148 @@ TclDumpMemoryInfo(
|
||||
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
* TclAllocElemsEx --
|
||||
*
|
||||
* See TclAttemptAllocElemsEx. This function differs in that it panics
|
||||
* on failure.
|
||||
*
|
||||
* Results:
|
||||
* Non-NULL pointer to allocated memory block.
|
||||
*
|
||||
* Side effects:
|
||||
* Panics if memory of at least the requested size could not be
|
||||
* allocated.
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
void *
|
||||
TclAllocElemsEx(
|
||||
Tcl_Size elemCount, /* Allocation will store at least these many... */
|
||||
Tcl_Size elemSize, /* ...elements of this size */
|
||||
Tcl_Size leadSize, /* Additional leading space in bytes */
|
||||
Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
|
||||
here if non-NULL. Only modified on success */
|
||||
{
|
||||
void *ptr = TclAttemptReallocElemsEx(
|
||||
NULL, elemCount, elemSize, leadSize, capacityPtr);
|
||||
if (ptr == NULL) {
|
||||
Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER
|
||||
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
|
||||
elemCount,
|
||||
elemSize);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
* TclAttemptReallocElemsEx --
|
||||
*
|
||||
* Attempts to allocate (oldPtr == NULL) or reallocate memory of the
|
||||
* requested size plus some more for future growth. The amount of
|
||||
* reallocation is adjusted depending on on failure.
|
||||
*
|
||||
*
|
||||
* Results:
|
||||
* Pointer to allocated memory block which is at least as large
|
||||
* as the requested size or NULL if allocation failed.
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
void *
|
||||
TclAttemptReallocElemsEx(
|
||||
void *oldPtr, /* Pointer to memory block to reallocate or
|
||||
* NULL to indicate this is a new allocation */
|
||||
Tcl_Size elemCount, /* Allocation will store at least these many... */
|
||||
Tcl_Size elemSize, /* ...elements of this size */
|
||||
Tcl_Size leadSize, /* Additional leading space in bytes */
|
||||
Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
|
||||
here if non-NULL. Only modified on success */
|
||||
{
|
||||
void *ptr;
|
||||
Tcl_Size limit;
|
||||
Tcl_Size attempt;
|
||||
|
||||
assert(elemCount > 0);
|
||||
assert(elemSize > 0);
|
||||
assert(elemSize < TCL_SIZE_MAX);
|
||||
assert(leadSize >= 0);
|
||||
assert(leadSize < TCL_SIZE_MAX);
|
||||
|
||||
limit = (TCL_SIZE_MAX - leadSize) / elemSize;
|
||||
if (elemCount > limit) {
|
||||
return NULL;
|
||||
}
|
||||
/* Loop trying for extra space, reducing request each time */
|
||||
attempt = TclUpsizeAlloc(0, elemCount, limit);
|
||||
ptr = NULL;
|
||||
while (attempt > elemCount) {
|
||||
if (oldPtr) {
|
||||
ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt * elemSize);
|
||||
} else {
|
||||
ptr = Tcl_AttemptAlloc(leadSize + attempt * elemSize);
|
||||
}
|
||||
if (ptr) {
|
||||
break;
|
||||
}
|
||||
attempt = TclUpsizeRetry(elemCount, attempt);
|
||||
}
|
||||
/* Try exact size as a last resort */
|
||||
if (ptr == NULL) {
|
||||
attempt = elemCount;
|
||||
if (oldPtr) {
|
||||
ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt * elemSize);
|
||||
} else {
|
||||
ptr = Tcl_AttemptAlloc(leadSize + attempt * elemSize);
|
||||
}
|
||||
}
|
||||
if (ptr && capacityPtr) {
|
||||
*capacityPtr = attempt;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
* TclReallocElemsEx --
|
||||
*
|
||||
* See TclAttemptReallocElemsEx. This function differs in that it panics
|
||||
* on failure.
|
||||
*
|
||||
* Results:
|
||||
* Non-NULL pointer to allocated memory block.
|
||||
*
|
||||
* Side effects:
|
||||
* Panics if memory of at least the requested size could not be
|
||||
* allocated.
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
void *
|
||||
TclReallocElemsEx(
|
||||
void *oldPtr, /* Pointer to memory block to reallocate */
|
||||
Tcl_Size elemCount, /* Allocation will store at least these many... */
|
||||
Tcl_Size elemSize, /* ...elements of this size */
|
||||
Tcl_Size leadSize, /* Additional leading space in bytes */
|
||||
Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
|
||||
here if non-NULL. Only modified on success */
|
||||
{
|
||||
void *ptr = TclAttemptReallocElemsEx(
|
||||
oldPtr, elemCount, elemSize, leadSize, capacityPtr);
|
||||
if (ptr == NULL) {
|
||||
Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER
|
||||
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
|
||||
elemCount,
|
||||
elemSize);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+25
-16
@@ -435,11 +435,7 @@ EncodingConvertParseOptions (
|
||||
Tcl_Encoding encoding;
|
||||
Tcl_Obj *dataObj;
|
||||
Tcl_Obj *failVarObj;
|
||||
#if TCL_MAJOR_VERSION > 8 || defined(TCL_NO_DEPRECATED)
|
||||
int profile = TCL_ENCODING_PROFILE_TCL8; /* TODO - default for Tcl9? */
|
||||
#else
|
||||
int profile = TCL_ENCODING_PROFILE_TCL8;
|
||||
#endif
|
||||
int profile = TCL_ENCODING_PROFILE_STRICT;
|
||||
|
||||
/*
|
||||
* Possible combinations:
|
||||
@@ -2329,7 +2325,7 @@ StoreStatData(
|
||||
unsigned short mode;
|
||||
|
||||
if (varName == NULL) {
|
||||
result = Tcl_NewObj();
|
||||
TclNewObj(result);
|
||||
Tcl_IncrRefCount(result);
|
||||
#define DOBJPUT(key, objValue) \
|
||||
Tcl_DictObjPut(NULL, result, \
|
||||
@@ -2360,8 +2356,6 @@ StoreStatData(
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume Tcl_ObjSetVar2() does not keep a copy of the field name!
|
||||
*
|
||||
* Might be a better idea to call Tcl_SetVar2Ex() instead, except we want
|
||||
* to have an object (i.e. possibly cached) array variable name but a
|
||||
* string element name, so no API exists. Messy.
|
||||
@@ -2393,9 +2387,15 @@ StoreStatData(
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_RDEV
|
||||
if (S_ISCHR(statPtr->st_mode) || S_ISBLK(statPtr->st_mode)) {
|
||||
STORE_ARY("rdev", Tcl_NewWideIntObj((long) statPtr->st_rdev));
|
||||
}
|
||||
#endif
|
||||
STORE_ARY("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
|
||||
STORE_ARY("mtime", Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
STORE_ARY("mtime", Tcl_NewWideIntObj(
|
||||
Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
STORE_ARY("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
|
||||
mode = (unsigned short) statPtr->st_mode;
|
||||
STORE_ARY("mode", Tcl_NewWideIntObj(mode));
|
||||
@@ -2788,13 +2788,18 @@ EachloopCmd(
|
||||
for (i=0 ; i<numLists ; i++) {
|
||||
/* List */
|
||||
/* Variables */
|
||||
statePtr->vCopyList[i] = TclListObjCopy(interp, objv[1+i*2]);
|
||||
if (statePtr->vCopyList[i] == NULL) {
|
||||
statePtr->vCopyList[i] = TclDuplicatePureObj(
|
||||
interp, objv[1+i*2], &tclListType.objType);
|
||||
if (!statePtr->vCopyList[i]) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
TclListObjLengthM(NULL, statePtr->vCopyList[i],
|
||||
result = TclListObjLengthM(interp, statePtr->vCopyList[i],
|
||||
&statePtr->varcList[i]);
|
||||
if (result != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (statePtr->varcList[i] < 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%s varlist is empty",
|
||||
@@ -2811,7 +2816,7 @@ EachloopCmd(
|
||||
/* Values */
|
||||
if (TclHasInternalRep(objv[2+i*2],&tclArithSeriesType.objType)) {
|
||||
/* Special case for Arith Series */
|
||||
statePtr->aCopyList[i] = TclArithSeriesObjCopy(interp, objv[2+i*2]);
|
||||
statePtr->aCopyList[i] = Tcl_DuplicateObj(objv[2+i*2]);
|
||||
if (statePtr->aCopyList[i] == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
@@ -2820,13 +2825,17 @@ EachloopCmd(
|
||||
statePtr->argcList[i] = ABSTRACTLIST_PROC(statePtr->aCopyList[i], lengthProc)(statePtr->aCopyList[i]);
|
||||
} else {
|
||||
/* List values */
|
||||
statePtr->aCopyList[i] = TclListObjCopy(interp, objv[2+i*2]);
|
||||
if (statePtr->aCopyList[i] == NULL) {
|
||||
statePtr->aCopyList[i] = TclDuplicatePureObj(
|
||||
interp, objv[2+i*2], &tclListType.objType);
|
||||
if (!statePtr->aCopyList[i]) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
TclListObjGetElementsM(NULL, statePtr->aCopyList[i],
|
||||
result = TclListObjGetElementsM(interp, statePtr->aCopyList[i],
|
||||
&statePtr->argcList[i], &statePtr->argvList[i]);
|
||||
if (result != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
/* account for variable <> value mismatch */
|
||||
j = statePtr->argcList[i] / statePtr->varcList[i];
|
||||
|
||||
+85
-43
@@ -712,7 +712,7 @@ InfoCommandsCmd(
|
||||
if (entryPtr != NULL) {
|
||||
if (specificNsInPattern) {
|
||||
cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
|
||||
elemObjPtr = Tcl_NewObj();
|
||||
TclNewObj(elemObjPtr);
|
||||
Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
|
||||
} else {
|
||||
cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
|
||||
@@ -763,7 +763,7 @@ InfoCommandsCmd(
|
||||
|| Tcl_StringMatch(cmdName, simplePattern)) {
|
||||
if (specificNsInPattern) {
|
||||
cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
|
||||
elemObjPtr = Tcl_NewObj();
|
||||
TclNewObj(elemObjPtr);
|
||||
Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
|
||||
} else {
|
||||
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
|
||||
@@ -990,7 +990,8 @@ InfoDefaultCmd(
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
|
||||
} else {
|
||||
Tcl_Obj *nullObjPtr = Tcl_NewObj();
|
||||
Tcl_Obj *nullObjPtr;
|
||||
TclNewObj(nullObjPtr);
|
||||
|
||||
valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
|
||||
nullObjPtr, TCL_LEAVE_ERR_MSG);
|
||||
@@ -1906,7 +1907,7 @@ InfoProcsCmd(
|
||||
} else {
|
||||
simpleProcOK:
|
||||
if (specificNsInPattern) {
|
||||
elemObjPtr = Tcl_NewObj();
|
||||
TclNewObj(elemObjPtr);
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
|
||||
elemObjPtr);
|
||||
} else {
|
||||
@@ -1934,7 +1935,7 @@ InfoProcsCmd(
|
||||
} else {
|
||||
procOK:
|
||||
if (specificNsInPattern) {
|
||||
elemObjPtr = Tcl_NewObj();
|
||||
TclNewObj(elemObjPtr);
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
|
||||
elemObjPtr);
|
||||
} else {
|
||||
@@ -2252,7 +2253,7 @@ Tcl_JoinObjCmd(
|
||||
} else {
|
||||
Tcl_Size i;
|
||||
|
||||
resObjPtr = Tcl_NewObj();
|
||||
TclNewObj(resObjPtr);
|
||||
if (isArithSeries) {
|
||||
Tcl_Obj *valueObj;
|
||||
for (i = 0; i < listLen; i++) {
|
||||
@@ -2327,20 +2328,25 @@ Tcl_LassignObjCmd(
|
||||
Tcl_Obj **listObjv; /* The contents of the list. */
|
||||
Tcl_Size listObjc; /* The length of the list. */
|
||||
Tcl_Size origListObjc; /* Original length */
|
||||
int code = TCL_OK;
|
||||
int code;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "list ?varName ...?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
listCopyPtr = TclListObjCopy(interp, objv[1]);
|
||||
if (listCopyPtr == NULL) {
|
||||
listCopyPtr = TclDuplicatePureObj(interp, objv[1], &tclListType.objType);
|
||||
if (!listCopyPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_IncrRefCount(listCopyPtr); /* Important! fs */
|
||||
|
||||
TclListObjGetElementsM(NULL, listCopyPtr, &listObjc, &listObjv);
|
||||
code = TclListObjGetElementsM(
|
||||
interp, listCopyPtr, &listObjc, &listObjv);
|
||||
if (code != TCL_OK) {
|
||||
Tcl_DecrRefCount(listCopyPtr);
|
||||
return code;
|
||||
}
|
||||
origListObjc = listObjc;
|
||||
|
||||
objc -= 2;
|
||||
@@ -2466,7 +2472,7 @@ Tcl_LinsertObjCmd(
|
||||
{
|
||||
Tcl_Obj *listPtr;
|
||||
Tcl_Size len, index;
|
||||
int result;
|
||||
int copied = 0, result;
|
||||
|
||||
if (objc < 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?");
|
||||
@@ -2499,7 +2505,11 @@ Tcl_LinsertObjCmd(
|
||||
|
||||
listPtr = objv[1];
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
copied = 1;
|
||||
}
|
||||
|
||||
if ((objc == 4) && (index == len)) {
|
||||
@@ -2507,10 +2517,19 @@ Tcl_LinsertObjCmd(
|
||||
* Special case: insert one element at the end of the list.
|
||||
*/
|
||||
|
||||
Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);
|
||||
result = Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);
|
||||
if (result != TCL_OK) {
|
||||
if (copied) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0,
|
||||
(objc-3), &(objv[3]))) {
|
||||
if (copied) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -2634,7 +2653,7 @@ Tcl_LpopObjCmd(
|
||||
/* Argument objects. */
|
||||
{
|
||||
Tcl_Size listLen;
|
||||
int result;
|
||||
int copied = 0, result;
|
||||
Tcl_Obj *elemPtr, *stored;
|
||||
Tcl_Obj *listPtr, **elemPtrs;
|
||||
|
||||
@@ -2686,23 +2705,33 @@ Tcl_LpopObjCmd(
|
||||
|
||||
if (objc == 2) {
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
copied = 1;
|
||||
}
|
||||
result = Tcl_ListObjReplace(interp, listPtr, listLen - 1, 1, 0, NULL);
|
||||
if (result != TCL_OK) {
|
||||
if (copied) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
} else {
|
||||
listPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);
|
||||
|
||||
if (listPtr == NULL) {
|
||||
Tcl_Obj *newListPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);
|
||||
if (newListPtr == NULL) {
|
||||
if (copied) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
} else {
|
||||
listPtr = newListPtr;
|
||||
TclUndoRefCount(listPtr);
|
||||
}
|
||||
}
|
||||
|
||||
stored = Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
if (stored == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2819,6 +2848,7 @@ Tcl_LremoveObjCmd(
|
||||
Tcl_Size i, idxc, prevIdx, first, num;
|
||||
Tcl_Size *idxv, listLen;
|
||||
Tcl_Obj *listObj;
|
||||
int copied = 0, status = TCL_OK;
|
||||
|
||||
/*
|
||||
* Parse the arguments.
|
||||
@@ -2841,10 +2871,10 @@ Tcl_LremoveObjCmd(
|
||||
}
|
||||
idxv = (Tcl_Size *)Tcl_Alloc((objc - 2) * sizeof(*idxv));
|
||||
for (i = 2; i < objc; i++) {
|
||||
if (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
|
||||
&idxv[i - 2]) != TCL_OK) {
|
||||
Tcl_Free(idxv);
|
||||
return TCL_ERROR;
|
||||
status = (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
|
||||
&idxv[i - 2]) != TCL_OK);
|
||||
if (status != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2862,7 +2892,12 @@ Tcl_LremoveObjCmd(
|
||||
*/
|
||||
|
||||
if (Tcl_IsShared(listObj)) {
|
||||
listObj = TclListObjCopy(NULL, listObj);
|
||||
listObj = TclDuplicatePureObj(interp, listObj, &tclListType.objType);
|
||||
if (!listObj) {
|
||||
status = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
copied = 1;
|
||||
}
|
||||
num = 0;
|
||||
first = listLen;
|
||||
@@ -2897,18 +2932,28 @@ Tcl_LremoveObjCmd(
|
||||
* and we're only ever contracting that list.
|
||||
*/
|
||||
|
||||
(void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
|
||||
status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
|
||||
if (status != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
listLen -= num;
|
||||
num = 1;
|
||||
first = idx;
|
||||
}
|
||||
}
|
||||
if (num != 0) {
|
||||
(void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
|
||||
status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
|
||||
if (status != TCL_OK) {
|
||||
if (copied) {
|
||||
Tcl_DecrRefCount(listObj);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
Tcl_Free(idxv);
|
||||
Tcl_SetObjResult(interp, listObj);
|
||||
return TCL_OK;
|
||||
done:
|
||||
Tcl_Free(idxv);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3102,7 +3147,10 @@ Tcl_LreplaceObjCmd(
|
||||
|
||||
listPtr = objv[1];
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3115,6 +3163,7 @@ Tcl_LreplaceObjCmd(
|
||||
|
||||
if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, first, numToDelete,
|
||||
objc-4, objv+4)) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -4722,7 +4771,7 @@ Tcl_LsortObjCmd(
|
||||
* 1675116]
|
||||
*/
|
||||
|
||||
listObj = TclListObjCopy(interp, listObj);
|
||||
listObj = TclDuplicatePureObj(interp ,listObj, &tclListType.objType);
|
||||
if (listObj == NULL) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done;
|
||||
@@ -4739,8 +4788,6 @@ Tcl_LsortObjCmd(
|
||||
if (Tcl_ListObjAppendElement(interp, newCommandPtr, newObjPtr)
|
||||
!= TCL_OK) {
|
||||
TclDecrRefCount(newCommandPtr);
|
||||
TclDecrRefCount(listObj);
|
||||
Tcl_IncrRefCount(newObjPtr);
|
||||
TclDecrRefCount(newObjPtr);
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done;
|
||||
@@ -5080,7 +5127,10 @@ Tcl_LeditObjCmd(
|
||||
}
|
||||
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
listPtr = TclListObjCopy(NULL, listPtr);
|
||||
listPtr = TclDuplicatePureObj(interp, listPtr, &tclListType.objType);
|
||||
if (!listPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
createdNewObj = 1;
|
||||
} else {
|
||||
createdNewObj = 0;
|
||||
@@ -5097,18 +5147,10 @@ Tcl_LeditObjCmd(
|
||||
|
||||
/*
|
||||
* Tcl_ObjSetVar2 may return a value different from listPtr in the
|
||||
* presence of traces etc.. Note that finalValuePtr will always have a
|
||||
* reference count of at least 1 corresponding to the reference from the
|
||||
* var. If it is same as listPtr, then ref count will be at least 2
|
||||
* since we are incr'ing the latter below (safer when calling
|
||||
* Tcl_ObjSetVar2 which can release it in some cases). Note that we
|
||||
* leave the incrref of listPtr this late because we want to pass it as
|
||||
* unshared to Tcl_ListObjReplace above if possible.
|
||||
* presence of traces etc.
|
||||
*/
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
finalValuePtr =
|
||||
Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
|
||||
Tcl_DecrRefCount(listPtr); /* safe irrespective of createdNewObj */
|
||||
if (finalValuePtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
+11
-10
@@ -357,7 +357,7 @@ Tcl_RegexpObjCmd(
|
||||
|
||||
objc = info.nsubs + 1;
|
||||
if (all <= 1) {
|
||||
resultPtr = Tcl_NewObj();
|
||||
TclNewObj(resultPtr);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < objc; i++) {
|
||||
@@ -399,7 +399,7 @@ Tcl_RegexpObjCmd(
|
||||
offset + info.matches[i].start,
|
||||
offset + info.matches[i].end - 1);
|
||||
} else {
|
||||
newPtr = Tcl_NewObj();
|
||||
TclNewObj(newPtr);
|
||||
}
|
||||
}
|
||||
if (doinline) {
|
||||
@@ -1194,7 +1194,7 @@ Tcl_SplitObjCmd(
|
||||
|
||||
stringPtr = Tcl_GetStringFromObj(objv[1], &stringLen);
|
||||
end = stringPtr + stringLen;
|
||||
listPtr = Tcl_NewObj();
|
||||
TclNewObj(listPtr);
|
||||
|
||||
if (stringLen == 0) {
|
||||
/*
|
||||
@@ -2642,8 +2642,8 @@ StringEqualCmd(
|
||||
*/
|
||||
|
||||
const char *string2;
|
||||
int i, match, nocase = 0, reqlength = -1;
|
||||
Tcl_Size length;
|
||||
int i, match, nocase = 0;
|
||||
Tcl_Size length, reqlength = -1;
|
||||
|
||||
if (objc < 3 || objc > 6) {
|
||||
str_cmp_args:
|
||||
@@ -2662,7 +2662,7 @@ StringEqualCmd(
|
||||
goto str_cmp_args;
|
||||
}
|
||||
i++;
|
||||
if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
|
||||
if (TclGetSizeIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
@@ -2717,7 +2717,8 @@ StringCmpCmd(
|
||||
* the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
|
||||
*/
|
||||
|
||||
int match, nocase, reqlength, status;
|
||||
int match, nocase, status;
|
||||
Tcl_Size reqlength;
|
||||
|
||||
status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength);
|
||||
if (status != TCL_OK) {
|
||||
@@ -2736,7 +2737,7 @@ TclStringCmpOpts(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[], /* Argument objects. */
|
||||
int *nocase,
|
||||
int *reqlength)
|
||||
Tcl_Size *reqlength)
|
||||
{
|
||||
int i;
|
||||
Tcl_Size length;
|
||||
@@ -2761,7 +2762,7 @@ TclStringCmpOpts(
|
||||
goto str_cmp_args;
|
||||
}
|
||||
i++;
|
||||
if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) {
|
||||
if (TclGetSizeIntFromObj(interp, objv[i], reqlength) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
@@ -4700,7 +4701,7 @@ TclNRTryObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
bodyObj = objv[1];
|
||||
handlersObj = Tcl_NewObj();
|
||||
TclNewObj(handlersObj);
|
||||
bodyShared = 0;
|
||||
haveHandlers = 0;
|
||||
for (i=2 ; i<objc ; i++) {
|
||||
|
||||
@@ -2669,7 +2669,7 @@ TclCompileTailcallCmd(
|
||||
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
|
||||
int i;
|
||||
|
||||
if (parsePtr->numWords < 2 || parsePtr->numWords > 256
|
||||
if (parsePtr->numWords < 2 || parsePtr->numWords >= 256
|
||||
|| envPtr->procPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -2093,9 +2093,9 @@ ParseLexeme(
|
||||
if (end < start + numBytes && !TclIsBareword(*end)) {
|
||||
|
||||
number:
|
||||
TclInitStringRep(literal, start, end-start);
|
||||
*lexemePtr = NUMBER;
|
||||
if (literalPtr) {
|
||||
TclInitStringRep(literal, start, end-start);
|
||||
*literalPtr = literal;
|
||||
} else {
|
||||
Tcl_DecrRefCount(literal);
|
||||
@@ -2168,7 +2168,7 @@ ParseLexeme(
|
||||
}
|
||||
*lexemePtr = BAREWORD;
|
||||
if (literalPtr) {
|
||||
Tcl_SetStringObj(literal, start, (int) (end-start));
|
||||
Tcl_SetStringObj(literal, start, end-start);
|
||||
*literalPtr = literal;
|
||||
} else {
|
||||
Tcl_DecrRefCount(literal);
|
||||
|
||||
+33
-4
@@ -720,8 +720,8 @@ const Tcl_ObjType tclByteCodeType = {
|
||||
};
|
||||
|
||||
/*
|
||||
* subtCodeType provides the standard type managemnt procedures for the
|
||||
* substcode type, which represents substiution within a Tcl value.
|
||||
* substCodeType provides the standard type management procedures for the
|
||||
* substcode type, which represents substitution within a Tcl value.
|
||||
*/
|
||||
|
||||
static const Tcl_ObjType substCodeType = {
|
||||
@@ -869,6 +869,18 @@ TclSetByteCodeFromAny(
|
||||
result = hookProc(interp, &compEnv, clientData);
|
||||
}
|
||||
|
||||
/*
|
||||
* After optimization is all done, check that byte code length limits
|
||||
* are not exceeded. Bug [27b3ce2997].
|
||||
*/
|
||||
if ((compEnv.codeNext - compEnv.codeStart) > INT_MAX) {
|
||||
/*
|
||||
* Cannot just return TCL_ERROR as callers ignore return value.
|
||||
* TODO - May be use TclCompileSyntaxError here?
|
||||
*/
|
||||
Tcl_Panic("Maximum byte code length %d exceeded.", INT_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the object into a ByteCode object. Ownership of the literal
|
||||
* objects and aux data items passes to the ByteCode object.
|
||||
@@ -2136,7 +2148,7 @@ TclCompileScript(
|
||||
* serves as context for finding and compiling
|
||||
* commands. May not be NULL. */
|
||||
const char *script, /* The source script to compile. */
|
||||
size_t numBytes, /* Number of bytes in script. If -1, the
|
||||
Tcl_Size numBytes, /* Number of bytes in script. If < 0, the
|
||||
* script consists of all bytes up to the
|
||||
* first null character. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
@@ -2167,9 +2179,26 @@ TclCompileScript(
|
||||
return;
|
||||
}
|
||||
|
||||
if (numBytes < 0) {
|
||||
numBytes = strlen(script);
|
||||
}
|
||||
|
||||
/* Each iteration compiles one command from the script. */
|
||||
|
||||
if (numBytes + 1 > 1) {
|
||||
if (numBytes > 0) {
|
||||
if (numBytes >= INT_MAX) {
|
||||
/*
|
||||
* Note this gets -errorline as 1. Not worth figuring out which line
|
||||
* crosses the limit to get -errorline for this error case.
|
||||
*/
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Script length %" TCL_SIZE_MODIFIER
|
||||
"d exceeds max permitted length %d.",
|
||||
numBytes, (int)INT_MAX-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LIMIT", "SCRIPTLENGTH", NULL);
|
||||
TclCompileSyntaxError(interp, envPtr);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Don't use system stack (size of Tcl_Parse is ca. 400 bytes), so
|
||||
* many nested compilations (body enclosed in body) can cause abnormal
|
||||
|
||||
@@ -1100,7 +1100,7 @@ MODULE_SCOPE void TclCompileInvocation(Tcl_Interp *interp,
|
||||
Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, size_t numWords,
|
||||
CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclCompileScript(Tcl_Interp *interp,
|
||||
const char *script, size_t numBytes,
|
||||
const char *script, Tcl_Size numBytes,
|
||||
CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclCompileSyntaxError(Tcl_Interp *interp,
|
||||
CompileEnv *envPtr);
|
||||
|
||||
+50
-47
@@ -136,7 +136,7 @@ EXTERN int Tcl_GetBooleanFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, int *intPtr);
|
||||
/* 33 */
|
||||
EXTERN unsigned char * TclGetByteArrayFromObj(Tcl_Obj *objPtr,
|
||||
int *numBytesPtr);
|
||||
void *numBytesPtr);
|
||||
/* 34 */
|
||||
EXTERN int Tcl_GetDouble(Tcl_Interp *interp, const char *src,
|
||||
double *doublePtr);
|
||||
@@ -156,7 +156,7 @@ EXTERN int Tcl_GetLongFromObj(Tcl_Interp *interp,
|
||||
/* 40 */
|
||||
EXTERN const Tcl_ObjType * Tcl_GetObjType(const char *typeName);
|
||||
/* 41 */
|
||||
EXTERN char * TclGetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr);
|
||||
EXTERN char * TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr);
|
||||
/* 42 */
|
||||
EXTERN void Tcl_InvalidateStringRep(Tcl_Obj *objPtr);
|
||||
/* 43 */
|
||||
@@ -167,7 +167,7 @@ EXTERN int Tcl_ListObjAppendElement(Tcl_Interp *interp,
|
||||
Tcl_Obj *listPtr, Tcl_Obj *objPtr);
|
||||
/* 45 */
|
||||
EXTERN int TclListObjGetElements(Tcl_Interp *interp,
|
||||
Tcl_Obj *listPtr, int *objcPtr,
|
||||
Tcl_Obj *listPtr, void *objcPtr,
|
||||
Tcl_Obj ***objvPtr);
|
||||
/* 46 */
|
||||
EXTERN int Tcl_ListObjIndex(Tcl_Interp *interp,
|
||||
@@ -175,7 +175,7 @@ EXTERN int Tcl_ListObjIndex(Tcl_Interp *interp,
|
||||
Tcl_Obj **objPtrPtr);
|
||||
/* 47 */
|
||||
EXTERN int TclListObjLength(Tcl_Interp *interp,
|
||||
Tcl_Obj *listPtr, int *lengthPtr);
|
||||
Tcl_Obj *listPtr, void *lengthPtr);
|
||||
/* 48 */
|
||||
EXTERN int Tcl_ListObjReplace(Tcl_Interp *interp,
|
||||
Tcl_Obj *listPtr, Tcl_Size first,
|
||||
@@ -665,9 +665,9 @@ EXTERN const char * Tcl_SignalMsg(int sig);
|
||||
EXTERN void Tcl_SourceRCFile(Tcl_Interp *interp);
|
||||
/* 242 */
|
||||
EXTERN int TclSplitList(Tcl_Interp *interp, const char *listStr,
|
||||
int *argcPtr, const char ***argvPtr);
|
||||
void *argcPtr, const char ***argvPtr);
|
||||
/* 243 */
|
||||
EXTERN void TclSplitPath(const char *path, int *argcPtr,
|
||||
EXTERN void TclSplitPath(const char *path, void *argcPtr,
|
||||
const char ***argvPtr);
|
||||
/* Slot 244 is reserved */
|
||||
/* Slot 245 is reserved */
|
||||
@@ -1036,7 +1036,7 @@ EXTERN void Tcl_MutexFinalize(Tcl_Mutex *mutex);
|
||||
/* 393 */
|
||||
EXTERN int Tcl_CreateThread(Tcl_ThreadId *idPtr,
|
||||
Tcl_ThreadCreateProc *proc, void *clientData,
|
||||
Tcl_Size stackSize, int flags);
|
||||
TCL_HASH_TYPE stackSize, int flags);
|
||||
/* 394 */
|
||||
EXTERN Tcl_Size Tcl_ReadRaw(Tcl_Channel chan, char *dst,
|
||||
Tcl_Size bytesToRead);
|
||||
@@ -1137,7 +1137,8 @@ EXTERN int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr,
|
||||
/* 433 */
|
||||
EXTERN Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel);
|
||||
/* 434 */
|
||||
EXTERN Tcl_UniChar * TclGetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr);
|
||||
EXTERN Tcl_UniChar * TclGetUnicodeFromObj(Tcl_Obj *objPtr,
|
||||
void *lengthPtr);
|
||||
/* Slot 435 is reserved */
|
||||
/* Slot 436 is reserved */
|
||||
/* 437 */
|
||||
@@ -1209,7 +1210,7 @@ EXTERN int Tcl_FSConvertToPathType(Tcl_Interp *interp,
|
||||
/* 460 */
|
||||
EXTERN Tcl_Obj * Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements);
|
||||
/* 461 */
|
||||
EXTERN Tcl_Obj * TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr);
|
||||
EXTERN Tcl_Obj * TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr);
|
||||
/* 462 */
|
||||
EXTERN int Tcl_FSEqualPaths(Tcl_Obj *firstPtr,
|
||||
Tcl_Obj *secondPtr);
|
||||
@@ -1306,7 +1307,7 @@ EXTERN int Tcl_DictObjRemove(Tcl_Interp *interp,
|
||||
Tcl_Obj *dictPtr, Tcl_Obj *keyPtr);
|
||||
/* 497 */
|
||||
EXTERN int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
|
||||
int *sizePtr);
|
||||
void *sizePtr);
|
||||
/* 498 */
|
||||
EXTERN int Tcl_DictObjFirst(Tcl_Interp *interp,
|
||||
Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr,
|
||||
@@ -1612,7 +1613,7 @@ EXTERN int Tcl_GetEnsembleParameterList(Tcl_Interp *interp,
|
||||
Tcl_Command token, Tcl_Obj **paramListPtr);
|
||||
/* 604 */
|
||||
EXTERN int TclParseArgsObjv(Tcl_Interp *interp,
|
||||
const Tcl_ArgvInfo *argTable, int *objcPtr,
|
||||
const Tcl_ArgvInfo *argTable, void *objcPtr,
|
||||
Tcl_Obj *const *objv, Tcl_Obj ***remObjv);
|
||||
/* 605 */
|
||||
EXTERN int Tcl_GetErrorLine(Tcl_Interp *interp);
|
||||
@@ -1744,7 +1745,7 @@ EXTERN int * Tcl_UtfToUniCharDString(const char *src,
|
||||
Tcl_Size length, Tcl_DString *dsPtr);
|
||||
/* 649 */
|
||||
EXTERN unsigned char * TclGetBytesFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, int *numBytesPtr);
|
||||
Tcl_Obj *objPtr, void *numBytesPtr);
|
||||
/* 650 */
|
||||
EXTERN unsigned char * Tcl_GetBytesFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, Tcl_Size *numBytesPtr);
|
||||
@@ -1911,7 +1912,7 @@ typedef struct TclStubs {
|
||||
void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */
|
||||
int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *intPtr); /* 31 */
|
||||
int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 32 */
|
||||
unsigned char * (*tclGetByteArrayFromObj) (Tcl_Obj *objPtr, int *numBytesPtr); /* 33 */
|
||||
unsigned char * (*tclGetByteArrayFromObj) (Tcl_Obj *objPtr, void *numBytesPtr); /* 33 */
|
||||
int (*tcl_GetDouble) (Tcl_Interp *interp, const char *src, double *doublePtr); /* 34 */
|
||||
int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */
|
||||
void (*reserved36)(void);
|
||||
@@ -1919,13 +1920,13 @@ typedef struct TclStubs {
|
||||
int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */
|
||||
int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */
|
||||
const Tcl_ObjType * (*tcl_GetObjType) (const char *typeName); /* 40 */
|
||||
char * (*tclGetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */
|
||||
char * (*tclGetStringFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 41 */
|
||||
void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */
|
||||
int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */
|
||||
int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */
|
||||
int (*tclListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
|
||||
int (*tclListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
|
||||
int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj **objPtrPtr); /* 46 */
|
||||
int (*tclListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */
|
||||
int (*tclListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *lengthPtr); /* 47 */
|
||||
int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first, Tcl_Size count, Tcl_Size objc, Tcl_Obj *const objv[]); /* 48 */
|
||||
void (*reserved49)(void);
|
||||
Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes); /* 50 */
|
||||
@@ -2120,8 +2121,8 @@ typedef struct TclStubs {
|
||||
const char * (*tcl_SignalId) (int sig); /* 239 */
|
||||
const char * (*tcl_SignalMsg) (int sig); /* 240 */
|
||||
void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */
|
||||
int (*tclSplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, const char ***argvPtr); /* 242 */
|
||||
void (*tclSplitPath) (const char *path, int *argcPtr, const char ***argvPtr); /* 243 */
|
||||
int (*tclSplitList) (Tcl_Interp *interp, const char *listStr, void *argcPtr, const char ***argvPtr); /* 242 */
|
||||
void (*tclSplitPath) (const char *path, void *argcPtr, const char ***argvPtr); /* 243 */
|
||||
void (*reserved244)(void);
|
||||
void (*reserved245)(void);
|
||||
void (*reserved246)(void);
|
||||
@@ -2271,7 +2272,7 @@ typedef struct TclStubs {
|
||||
int (*tcl_ProcObjCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); /* 390 */
|
||||
void (*tcl_ConditionFinalize) (Tcl_Condition *condPtr); /* 391 */
|
||||
void (*tcl_MutexFinalize) (Tcl_Mutex *mutex); /* 392 */
|
||||
int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, Tcl_Size stackSize, int flags); /* 393 */
|
||||
int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); /* 393 */
|
||||
Tcl_Size (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, Tcl_Size bytesToRead); /* 394 */
|
||||
Tcl_Size (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 395 */
|
||||
Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */
|
||||
@@ -2312,7 +2313,7 @@ typedef struct TclStubs {
|
||||
void * (*tcl_AttemptDbCkrealloc) (void *ptr, TCL_HASH_TYPE size, const char *file, int line); /* 431 */
|
||||
int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 432 */
|
||||
Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */
|
||||
Tcl_UniChar * (*tclGetUnicodeFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 434 */
|
||||
Tcl_UniChar * (*tclGetUnicodeFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 434 */
|
||||
void (*reserved435)(void);
|
||||
void (*reserved436)(void);
|
||||
Tcl_Obj * (*tcl_SubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 437 */
|
||||
@@ -2339,7 +2340,7 @@ typedef struct TclStubs {
|
||||
int (*tcl_FSChdir) (Tcl_Obj *pathPtr); /* 458 */
|
||||
int (*tcl_FSConvertToPathType) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 459 */
|
||||
Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, Tcl_Size elements); /* 460 */
|
||||
Tcl_Obj * (*tclFSSplitPath) (Tcl_Obj *pathPtr, int *lenPtr); /* 461 */
|
||||
Tcl_Obj * (*tclFSSplitPath) (Tcl_Obj *pathPtr, void *lenPtr); /* 461 */
|
||||
int (*tcl_FSEqualPaths) (Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 462 */
|
||||
Tcl_Obj * (*tcl_FSGetNormalizedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 463 */
|
||||
Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 464 */
|
||||
@@ -2375,7 +2376,7 @@ typedef struct TclStubs {
|
||||
int (*tcl_DictObjPut) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr); /* 494 */
|
||||
int (*tcl_DictObjGet) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 495 */
|
||||
int (*tcl_DictObjRemove) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 496 */
|
||||
int (*tclDictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr); /* 497 */
|
||||
int (*tclDictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr); /* 497 */
|
||||
int (*tcl_DictObjFirst) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 498 */
|
||||
void (*tcl_DictObjNext) (Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 499 */
|
||||
void (*tcl_DictObjDone) (Tcl_DictSearch *searchPtr); /* 500 */
|
||||
@@ -2482,7 +2483,7 @@ typedef struct TclStubs {
|
||||
unsigned (*tcl_GetBlockSizeFromStat) (const Tcl_StatBuf *statPtr); /* 601 */
|
||||
int (*tcl_SetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList); /* 602 */
|
||||
int (*tcl_GetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr); /* 603 */
|
||||
int (*tclParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */
|
||||
int (*tclParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */
|
||||
int (*tcl_GetErrorLine) (Tcl_Interp *interp); /* 605 */
|
||||
void (*tcl_SetErrorLine) (Tcl_Interp *interp, int lineNum); /* 606 */
|
||||
void (*tcl_TransferResult) (Tcl_Interp *sourceInterp, int code, Tcl_Interp *targetInterp); /* 607 */
|
||||
@@ -2527,7 +2528,7 @@ typedef struct TclStubs {
|
||||
Tcl_Size (*tcl_UtfToUniChar) (const char *src, int *chPtr); /* 646 */
|
||||
char * (*tcl_UniCharToUtfDString) (const int *uniStr, Tcl_Size uniLength, Tcl_DString *dsPtr); /* 647 */
|
||||
int * (*tcl_UtfToUniCharDString) (const char *src, Tcl_Size length, Tcl_DString *dsPtr); /* 648 */
|
||||
unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *numBytesPtr); /* 649 */
|
||||
unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, void *numBytesPtr); /* 649 */
|
||||
unsigned char * (*tcl_GetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size *numBytesPtr); /* 650 */
|
||||
char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 651 */
|
||||
Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 652 */
|
||||
@@ -4040,15 +4041,15 @@ extern const TclStubs *tclStubsPtr;
|
||||
# if TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED)
|
||||
# define Tcl_GetBytesFromObj(interp, objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
tclStubsPtr->tclGetBytesFromObj(interp, objPtr, (int *)(void *)(sizePtr)) : \
|
||||
tclStubsPtr->tclGetBytesFromObj(interp, objPtr, (sizePtr)) : \
|
||||
tclStubsPtr->tcl_GetBytesFromObj(interp, objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
# define Tcl_GetStringFromObj(objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
tclStubsPtr->tclGetStringFromObj(objPtr, (int *)(void *)(sizePtr)) : \
|
||||
tclStubsPtr->tclGetStringFromObj(objPtr, (sizePtr)) : \
|
||||
tclStubsPtr->tcl_GetStringFromObj(objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
# define Tcl_GetUnicodeFromObj(objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
tclStubsPtr->tclGetUnicodeFromObj(objPtr, (int *)(void *)(sizePtr)) : \
|
||||
tclStubsPtr->tclGetUnicodeFromObj(objPtr, (sizePtr)) : \
|
||||
tclStubsPtr->tcl_GetUnicodeFromObj(objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
# endif
|
||||
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
|
||||
@@ -4063,18 +4064,18 @@ extern const TclStubs *tclStubsPtr;
|
||||
#if TCL_MAJOR_VERSION > 8
|
||||
#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
tclStubsPtr->tclGetBytesFromObj(NULL, objPtr, (int *)(void *)(sizePtr)) : \
|
||||
tclStubsPtr->tclGetBytesFromObj(NULL, objPtr, (sizePtr)) : \
|
||||
tclStubsPtr->tcl_GetBytesFromObj(NULL, objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
#else
|
||||
#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
tclStubsPtr->tclGetByteArrayFromObj(objPtr, (int *)(void *)(sizePtr)) : \
|
||||
tclStubsPtr->tclGetByteArrayFromObj(objPtr, (sizePtr)) : \
|
||||
tclStubsPtr->tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
#endif
|
||||
#else
|
||||
#define Tcl_GetBytesFromObj(interp, objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
TclGetBytesFromObj(interp, objPtr, (int *)(void *)(sizePtr)) : \
|
||||
TclGetBytesFromObj(interp, objPtr, (sizePtr)) : \
|
||||
(Tcl_GetBytesFromObj)(interp, objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
|
||||
((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), \
|
||||
@@ -4087,15 +4088,15 @@ extern const TclStubs *tclStubsPtr;
|
||||
Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
|
||||
#define Tcl_GetStringFromObj(objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
TclGetStringFromObj(objPtr, (int *)(void *)(sizePtr)) : \
|
||||
TclGetStringFromObj(objPtr, (sizePtr)) : \
|
||||
(Tcl_GetStringFromObj)(objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
TclGetBytesFromObj(NULL, objPtr, (int *)(void *)(sizePtr)) : \
|
||||
TclGetBytesFromObj(NULL, objPtr, (sizePtr)) : \
|
||||
(Tcl_GetBytesFromObj)(NULL, objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
#define Tcl_GetUnicodeFromObj(objPtr, sizePtr) \
|
||||
(sizeof(*(sizePtr)) <= sizeof(int) ? \
|
||||
TclGetUnicodeFromObj(objPtr, (int *)(void *)(sizePtr)) : \
|
||||
TclGetUnicodeFromObj(objPtr, (sizePtr)) : \
|
||||
(Tcl_GetUnicodeFromObj)(objPtr, (Tcl_Size *)(void *)(sizePtr)))
|
||||
#endif
|
||||
|
||||
@@ -4168,34 +4169,36 @@ extern const TclStubs *tclStubsPtr;
|
||||
# define Tcl_WCharLen (sizeof(wchar_t) != sizeof(short) \
|
||||
? (Tcl_Size (*)(wchar_t *))tclStubsPtr->tcl_UniCharLen \
|
||||
: (Tcl_Size (*)(wchar_t *))Tcl_Char16Len)
|
||||
#if TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED)
|
||||
# undef Tcl_ListObjGetElements
|
||||
# define Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) (sizeof(*(objcPtr)) == sizeof(int) \
|
||||
? tclStubsPtr->tclListObjGetElements((interp), (listPtr), (int *)(void *)(objcPtr), (objvPtr)) \
|
||||
? tclStubsPtr->tclListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)) \
|
||||
: tclStubsPtr->tcl_ListObjGetElements((interp), (listPtr), (Tcl_Size *)(void *)(objcPtr), (objvPtr)))
|
||||
# undef Tcl_ListObjLength
|
||||
# define Tcl_ListObjLength(interp, listPtr, lengthPtr) (sizeof(*(lengthPtr)) == sizeof(int) \
|
||||
? tclStubsPtr->tclListObjLength((interp), (listPtr), (int *)(void *)(lengthPtr)) \
|
||||
? tclStubsPtr->tclListObjLength((interp), (listPtr), (lengthPtr)) \
|
||||
: tclStubsPtr->tcl_ListObjLength((interp), (listPtr), (Tcl_Size *)(void *)(lengthPtr)))
|
||||
# undef Tcl_DictObjSize
|
||||
# define Tcl_DictObjSize(interp, dictPtr, sizePtr) (sizeof(*(sizePtr)) == sizeof(int) \
|
||||
? tclStubsPtr->tclDictObjSize((interp), (dictPtr), (int *)(void *)(sizePtr)) \
|
||||
? tclStubsPtr->tclDictObjSize((interp), (dictPtr), (sizePtr)) \
|
||||
: tclStubsPtr->tcl_DictObjSize((interp), (dictPtr), (Tcl_Size *)(void *)(sizePtr)))
|
||||
# undef Tcl_SplitList
|
||||
# define Tcl_SplitList(interp, listStr, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
|
||||
? tclStubsPtr->tclSplitList((interp), (listStr), (int *)(void *)(argcPtr), (argvPtr)) \
|
||||
? tclStubsPtr->tclSplitList((interp), (listStr), (argcPtr), (argvPtr)) \
|
||||
: tclStubsPtr->tcl_SplitList((interp), (listStr), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
|
||||
# undef Tcl_SplitPath
|
||||
# define Tcl_SplitPath(path, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
|
||||
? tclStubsPtr->tclSplitPath((path), (int *)(void *)(argcPtr), (argvPtr)) \
|
||||
? tclStubsPtr->tclSplitPath((path), (argcPtr), (argvPtr)) \
|
||||
: tclStubsPtr->tcl_SplitPath((path), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
|
||||
# undef Tcl_FSSplitPath
|
||||
# define Tcl_FSSplitPath(pathPtr, lenPtr) (sizeof(*(lenPtr)) == sizeof(int) \
|
||||
? tclStubsPtr->tclFSSplitPath((pathPtr), (int *)(void *)(lenPtr)) \
|
||||
? tclStubsPtr->tclFSSplitPath((pathPtr), (lenPtr)) \
|
||||
: tclStubsPtr->tcl_FSSplitPath((pathPtr), (Tcl_Size *)(void *)(lenPtr)))
|
||||
# undef Tcl_ParseArgsObjv
|
||||
# define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) == sizeof(int) \
|
||||
? tclStubsPtr->tclParseArgsObjv((interp), (argTable), (int *)(void *)(objcPtr), (objv), (remObjv)) \
|
||||
? tclStubsPtr->tclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) \
|
||||
: tclStubsPtr->tcl_ParseArgsObjv((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv)))
|
||||
#endif /* TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED) */
|
||||
#else
|
||||
# define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \
|
||||
? (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_UniCharToUtfDString \
|
||||
@@ -4211,25 +4214,25 @@ extern const TclStubs *tclStubsPtr;
|
||||
: (Tcl_Size (*)(wchar_t *))Tcl_Char16Len)
|
||||
#if !defined(BUILD_tcl) && !defined(TCL_NO_DEPRECATED)
|
||||
# define Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) (sizeof(*(objcPtr)) == sizeof(int) \
|
||||
? TclListObjGetElements((interp), (listPtr), (int *)(void *)(objcPtr), (objvPtr)) \
|
||||
? TclListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)) \
|
||||
: (Tcl_ListObjGetElements)((interp), (listPtr), (Tcl_Size *)(void *)(objcPtr), (objvPtr)))
|
||||
# define Tcl_ListObjLength(interp, listPtr, lengthPtr) (sizeof(*(lengthPtr)) == sizeof(int) \
|
||||
? TclListObjLength((interp), (listPtr), (int *)(void *)(lengthPtr)) \
|
||||
? TclListObjLength((interp), (listPtr), (lengthPtr)) \
|
||||
: (Tcl_ListObjLength)((interp), (listPtr), (Tcl_Size *)(void *)(lengthPtr)))
|
||||
# define Tcl_DictObjSize(interp, dictPtr, sizePtr) (sizeof(*(sizePtr)) == sizeof(int) \
|
||||
? TclDictObjSize((interp), (dictPtr), (int *)(void *)(sizePtr)) \
|
||||
? TclDictObjSize((interp), (dictPtr), (sizePtr)) \
|
||||
: (Tcl_DictObjSize)((interp), (dictPtr), (Tcl_Size *)(void *)(sizePtr)))
|
||||
# define Tcl_SplitList(interp, listStr, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
|
||||
? TclSplitList((interp), (listStr), (int *)(void *)(argcPtr), (argvPtr)) \
|
||||
? TclSplitList((interp), (listStr), (argcPtr), (argvPtr)) \
|
||||
: (Tcl_SplitList)((interp), (listStr), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
|
||||
# define Tcl_SplitPath(path, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \
|
||||
? TclSplitPath((path), (int *)(void *)(argcPtr), (argvPtr)) \
|
||||
? TclSplitPath((path), (argcPtr), (argvPtr)) \
|
||||
: (Tcl_SplitPath)((path), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
|
||||
# define Tcl_FSSplitPath(pathPtr, lenPtr) (sizeof(*(lenPtr)) == sizeof(int) \
|
||||
? TclFSSplitPath((pathPtr), (int *)(void *)(lenPtr)) \
|
||||
? TclFSSplitPath((pathPtr), (lenPtr)) \
|
||||
: (Tcl_FSSplitPath)((pathPtr), (Tcl_Size *)(void *)(lenPtr)))
|
||||
# define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) == sizeof(int) \
|
||||
? TclParseArgsObjv((interp), (argTable), (int *)(void *)(objcPtr), (objv), (remObjv)) \
|
||||
? TclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) \
|
||||
: (Tcl_ParseArgsObjv)((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv)))
|
||||
#endif /* !defined(BUILD_tcl) */
|
||||
#endif
|
||||
|
||||
@@ -1045,6 +1045,26 @@ Tcl_DictObjRemove(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_DictGetSize
|
||||
*
|
||||
* Returns the size of dictPtr. Caller must ensure that dictPtr has type
|
||||
* 'tclDicttype'.
|
||||
*
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Size
|
||||
TclDictGetSize(Tcl_Obj *dictPtr)
|
||||
{
|
||||
Dict *dict;
|
||||
DictGetInternalRep(dictPtr, dict);
|
||||
return dict->table.numEntries;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+71
-17
@@ -10,7 +10,6 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclIO.h"
|
||||
|
||||
typedef size_t (LengthProc)(const char *src);
|
||||
|
||||
@@ -200,16 +199,16 @@ static struct TclEncodingProfiles {
|
||||
{"tcl8", TCL_ENCODING_PROFILE_TCL8},
|
||||
};
|
||||
#define PROFILE_TCL8(flags_) \
|
||||
((CHANNEL_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_TCL8) \
|
||||
|| (CHANNEL_PROFILE_GET(flags_) == 0 \
|
||||
((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_TCL8) \
|
||||
|| (ENCODING_PROFILE_GET(flags_) == 0 \
|
||||
&& TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_TCL8))
|
||||
#define PROFILE_STRICT(flags_) \
|
||||
((CHANNEL_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_STRICT) \
|
||||
|| (CHANNEL_PROFILE_GET(flags_) == 0 \
|
||||
((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_STRICT) \
|
||||
|| (ENCODING_PROFILE_GET(flags_) == 0 \
|
||||
&& TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_STRICT))
|
||||
#define PROFILE_REPLACE(flags_) \
|
||||
((CHANNEL_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE) \
|
||||
|| (CHANNEL_PROFILE_GET(flags_) == 0 \
|
||||
((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE) \
|
||||
|| (ENCODING_PROFILE_GET(flags_) == 0 \
|
||||
&& TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_REPLACE))
|
||||
|
||||
#define UNICODE_REPLACE_CHAR ((Tcl_UniChar)0xFFFD)
|
||||
@@ -1155,7 +1154,7 @@ Tcl_ExternalToUtfDString(
|
||||
* converted string is stored. */
|
||||
{
|
||||
Tcl_ExternalToUtfDStringEx(
|
||||
NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL);
|
||||
NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_STRICT, dstPtr, NULL);
|
||||
return Tcl_DStringValue(dstPtr);
|
||||
}
|
||||
|
||||
@@ -1166,7 +1165,7 @@ Tcl_ExternalToUtfDString(
|
||||
* Tcl_ExternalToUtfDStringEx --
|
||||
*
|
||||
* Convert a source buffer from the specified encoding into UTF-8.
|
||||
* The parameter flags controls the behavior, if any of the bytes in
|
||||
* "flags" controls the behavior if any of the bytes in
|
||||
* the source buffer are invalid or cannot be represented in utf-8.
|
||||
* Possible flags values:
|
||||
* target encoding. It should be composed by OR-ing the following:
|
||||
@@ -2532,7 +2531,17 @@ UtfToUtfProc(
|
||||
flags |= PTR2INT(clientData);
|
||||
dstEnd = dst + dstLen - ((flags & ENCODING_UTF) ? TCL_UTF_MAX : 6);
|
||||
|
||||
profile = CHANNEL_PROFILE_GET(flags);
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(dst, 0xff, dstLen);
|
||||
#endif
|
||||
|
||||
profile = ENCODING_PROFILE_GET(flags);
|
||||
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
|
||||
|
||||
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
|
||||
@@ -2579,10 +2588,10 @@ UtfToUtfProc(
|
||||
} else if (!Tcl_UtfCharComplete(src, srcEnd - src)) {
|
||||
/*
|
||||
* Incomplete byte sequence.
|
||||
* Always check before using TclUtfToUCS4. Not doing can so
|
||||
* cause it run beyond the end of the buffer! If we happen such an
|
||||
* incomplete char its bytes are made to represent themselves
|
||||
* unless the user has explicitly asked to be told.
|
||||
* Always check before using TclUtfToUCS4. Not doing so can cause it
|
||||
* run beyond the end of the buffer! If we happen on such an incomplete
|
||||
* char its bytes are made to represent themselves unless the user has
|
||||
* explicitly asked to be told.
|
||||
*/
|
||||
|
||||
if (flags & ENCODING_INPUT) {
|
||||
@@ -2746,6 +2755,15 @@ Utf32ToUtfProc(
|
||||
}
|
||||
result = TCL_OK;
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(dst, 0xff, dstLen);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check alignment with utf-32 (4 == sizeof(UTF-32))
|
||||
*/
|
||||
@@ -3015,6 +3033,15 @@ Utf16ToUtfProc(
|
||||
}
|
||||
result = TCL_OK;
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(dst, 0xff, dstLen);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check alignment with utf-16 (2 == sizeof(UTF-16))
|
||||
*/
|
||||
@@ -3428,6 +3455,15 @@ TableToUtfProc(
|
||||
dstStart = dst;
|
||||
dstEnd = dst + dstLen - TCL_UTF_MAX;
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(dst, 0xff, dstLen);
|
||||
#endif
|
||||
|
||||
toUnicode = (const unsigned short *const *) dataPtr->toUnicode;
|
||||
prefixBytes = dataPtr->prefixBytes;
|
||||
pageZero = toUnicode[0];
|
||||
@@ -3669,6 +3705,15 @@ Iso88591ToUtfProc(
|
||||
dstStart = dst;
|
||||
dstEnd = dst + dstLen - TCL_UTF_MAX;
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(dst, 0xff, dstLen);
|
||||
#endif
|
||||
|
||||
result = TCL_OK;
|
||||
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
|
||||
Tcl_UniChar ch = 0;
|
||||
@@ -3908,6 +3953,15 @@ EscapeToUtfProc(
|
||||
dstStart = dst;
|
||||
dstEnd = dst + dstLen - TCL_UTF_MAX;
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(dst, 0xff, dstLen);
|
||||
#endif
|
||||
|
||||
state = PTR2INT(*statePtr);
|
||||
if (flags & TCL_ENCODING_START) {
|
||||
state = 0;
|
||||
@@ -4587,9 +4641,9 @@ TclEncodingProfileIdToName(
|
||||
int TclEncodingSetProfileFlags(int flags)
|
||||
{
|
||||
if (flags & TCL_ENCODING_STOPONERROR) {
|
||||
CHANNEL_PROFILE_SET(flags, TCL_ENCODING_PROFILE_STRICT);
|
||||
ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_STRICT);
|
||||
} else {
|
||||
int profile = CHANNEL_PROFILE_GET(flags);
|
||||
int profile = ENCODING_PROFILE_GET(flags);
|
||||
switch (profile) {
|
||||
case TCL_ENCODING_PROFILE_TCL8:
|
||||
case TCL_ENCODING_PROFILE_STRICT:
|
||||
@@ -4597,7 +4651,7 @@ int TclEncodingSetProfileFlags(int flags)
|
||||
break;
|
||||
case 0: /* Unspecified by caller */
|
||||
default:
|
||||
CHANNEL_PROFILE_SET(flags, TCL_ENCODING_PROFILE_DEFAULT);
|
||||
ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_DEFAULT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+34
-5
@@ -312,7 +312,17 @@ TclNamespaceEnsembleCmd(
|
||||
Tcl_AppendObjToObj(newCmd, listv[0]);
|
||||
Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd);
|
||||
if (patchedDict == NULL) {
|
||||
patchedDict = Tcl_DuplicateObj(objv[1]);
|
||||
patchedDict = TclDuplicatePureObj(
|
||||
interp, objv[1], &tclDictType);
|
||||
if (!patchedDict) {
|
||||
if (allocatedMapFlag) {
|
||||
Tcl_DecrRefCount(mapObj);
|
||||
}
|
||||
Tcl_DecrRefCount(newList);
|
||||
Tcl_DecrRefCount(newCmd);
|
||||
Tcl_DecrRefCount(patchedDict);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj,
|
||||
newList);
|
||||
@@ -596,7 +606,14 @@ TclNamespaceEnsembleCmd(
|
||||
}
|
||||
cmd = TclGetString(listv[0]);
|
||||
if (!(cmd[0] == ':' && cmd[1] == ':')) {
|
||||
Tcl_Obj *newList = Tcl_DuplicateObj(listObj);
|
||||
Tcl_Obj *newList = TclDuplicatePureObj(
|
||||
interp, listObj, &tclListType.objType);
|
||||
if (!newList) {
|
||||
if (patchedDict) {
|
||||
Tcl_DecrRefCount(patchedDict);
|
||||
}
|
||||
goto freeMapAndError;
|
||||
}
|
||||
Tcl_Obj *newCmd = NewNsObj((Tcl_Namespace*)nsPtr);
|
||||
|
||||
if (nsPtr->parentPtr) {
|
||||
@@ -606,7 +623,11 @@ TclNamespaceEnsembleCmd(
|
||||
Tcl_ListObjReplace(NULL, newList, 0, 1, 1,
|
||||
&newCmd);
|
||||
if (patchedDict == NULL) {
|
||||
patchedDict = Tcl_DuplicateObj(objv[1]);
|
||||
patchedDict = TclDuplicatePureObj(
|
||||
interp, objv[1], &tclListType.objType);
|
||||
if (!patchedDict) {
|
||||
goto freeMapAndError;
|
||||
}
|
||||
}
|
||||
Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj,
|
||||
newList);
|
||||
@@ -1904,7 +1925,11 @@ NsEnsembleImplementationCmdNR(
|
||||
TclListObjLengthM(NULL, prefixObj, &prefixObjc);
|
||||
|
||||
if (objc == 2) {
|
||||
copyPtr = TclListObjCopy(NULL, prefixObj);
|
||||
copyPtr = TclDuplicatePureObj(
|
||||
interp, prefixObj, &tclListType.objType);
|
||||
if (!copyPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
copyPtr = Tcl_NewListObj(objc - 2 + prefixObjc, NULL);
|
||||
Tcl_ListObjAppendList(NULL, copyPtr, prefixObj);
|
||||
@@ -2304,7 +2329,11 @@ EnsembleUnknownCallback(
|
||||
* Create the "unknown" command callback to determine what to do.
|
||||
*/
|
||||
|
||||
unknownCmd = Tcl_DuplicateObj(ensemblePtr->unknownHandler);
|
||||
unknownCmd = TclDuplicatePureObj(
|
||||
interp, ensemblePtr->unknownHandler, &tclListType.objType);
|
||||
if (!unknownCmd) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
TclNewObj(ensObj);
|
||||
Tcl_GetCommandFullName(interp, ensemblePtr->token, ensObj);
|
||||
Tcl_ListObjAppendElement(NULL, unknownCmd, ensObj);
|
||||
|
||||
+6
-2
@@ -232,7 +232,11 @@ HandleBgErrors(
|
||||
* support one handler setting another handler.
|
||||
*/
|
||||
|
||||
Tcl_Obj *copyObj = TclListObjCopy(NULL, assocPtr->cmdPrefix);
|
||||
Tcl_Obj *copyObj = TclDuplicatePureObj(
|
||||
interp, assocPtr->cmdPrefix, &tclListType.objType);
|
||||
if (!copyObj) {
|
||||
return;
|
||||
}
|
||||
|
||||
errPtr = assocPtr->firstBgPtr;
|
||||
|
||||
@@ -2048,7 +2052,7 @@ Tcl_CreateThread(
|
||||
Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
|
||||
Tcl_ThreadCreateProc *proc, /* Main() function of the thread */
|
||||
void *clientData, /* The one argument to Main() */
|
||||
Tcl_Size stackSize, /* Size of stack for the new thread */
|
||||
TCL_HASH_TYPE stackSize, /* Size of stack for the new thread */
|
||||
int flags) /* Flags controlling behaviour of the new
|
||||
* thread. */
|
||||
{
|
||||
|
||||
+129
-86
@@ -113,9 +113,8 @@ typedef struct {
|
||||
ByteCode *codePtr; /* Constant until the BC returns */
|
||||
/* -----------------------------------------*/
|
||||
Tcl_Obj **catchTop; /* These fields are used on return TO this */
|
||||
Tcl_Obj *auxObjList; /* this level: they record the state when a */
|
||||
CmdFrame cmdFrame; /* new codePtr was received for NR */
|
||||
/* execution. */
|
||||
Tcl_Obj *auxObjList; /* level: they record the state when a new */
|
||||
CmdFrame cmdFrame; /* codePtr was received for NR execution. */
|
||||
Tcl_Obj *stack[1]; /* Start of the actual combined catch and obj
|
||||
* stacks; the struct will be expanded as
|
||||
* necessary */
|
||||
@@ -367,7 +366,7 @@ VarHashCreateVar(
|
||||
|
||||
#define OBJ_AT_DEPTH(n) *(tosPtr-(n))
|
||||
|
||||
#define CURR_DEPTH ((size_t)(tosPtr - initTosPtr))
|
||||
#define CURR_DEPTH (tosPtr - initTosPtr)
|
||||
|
||||
#define STACK_BASE(esPtr) ((esPtr)->stackWords - 1)
|
||||
|
||||
@@ -380,9 +379,9 @@ VarHashCreateVar(
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
# define TRACE(a) \
|
||||
while (traceInstructions) { \
|
||||
fprintf(stdout, "%2" TCL_Z_MODIFIER "u: %2" TCL_Z_MODIFIER "u (%" TCL_Z_MODIFIER "u) %s ", iPtr->numLevels, \
|
||||
fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels, \
|
||||
CURR_DEPTH, \
|
||||
(size_t)(pc - codePtr->codeStart), \
|
||||
(pc - codePtr->codeStart), \
|
||||
GetOpcodeName(pc)); \
|
||||
printf a; \
|
||||
break; \
|
||||
@@ -396,9 +395,9 @@ VarHashCreateVar(
|
||||
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
|
||||
# define TRACE_WITH_OBJ(a, objPtr) \
|
||||
while (traceInstructions) { \
|
||||
fprintf(stdout, "%2" TCL_Z_MODIFIER "u: %2" TCL_Z_MODIFIER "u (%" TCL_Z_MODIFIER "u) %s ", iPtr->numLevels, \
|
||||
fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels, \
|
||||
CURR_DEPTH, \
|
||||
(size_t)(pc - codePtr->codeStart), \
|
||||
(pc - codePtr->codeStart), \
|
||||
GetOpcodeName(pc)); \
|
||||
printf a; \
|
||||
TclPrintObject(stdout, objPtr, 30); \
|
||||
@@ -637,7 +636,7 @@ static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc,
|
||||
static const char * GetSrcInfoForPc(const unsigned char *pc,
|
||||
ByteCode *codePtr, Tcl_Size *lengthPtr,
|
||||
const unsigned char **pcBeg, int *cmdIdxPtr);
|
||||
static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, size_t growth,
|
||||
static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, TCL_HASH_TYPE growth,
|
||||
int move);
|
||||
static void IllegalExprOperandType(Tcl_Interp *interp,
|
||||
const unsigned char *pc, Tcl_Obj *opndPtr);
|
||||
@@ -645,8 +644,8 @@ static void InitByteCodeExecution(Tcl_Interp *interp);
|
||||
static inline int wordSkip(void *ptr);
|
||||
static void ReleaseDictIterator(Tcl_Obj *objPtr);
|
||||
/* Useful elsewhere, make available in tclInt.h or stubs? */
|
||||
static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, size_t numWords);
|
||||
static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, size_t numWords);
|
||||
static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, TCL_HASH_TYPE numWords);
|
||||
static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, TCL_HASH_TYPE numWords);
|
||||
static Tcl_NRPostProc CopyCallback;
|
||||
static Tcl_NRPostProc ExprObjCallback;
|
||||
static Tcl_NRPostProc FinalizeOONext;
|
||||
@@ -793,7 +792,7 @@ ExecEnv *
|
||||
TclCreateExecEnv(
|
||||
Tcl_Interp *interp, /* Interpreter for which the execution
|
||||
* environment is being created. */
|
||||
size_t size) /* The initial stack size, in number of words
|
||||
TCL_HASH_TYPE size) /* The initial stack size, in number of words
|
||||
* [sizeof(Tcl_Obj*)] */
|
||||
{
|
||||
ExecEnv *eePtr = (ExecEnv *)Tcl_Alloc(sizeof(ExecEnv));
|
||||
@@ -975,16 +974,16 @@ static Tcl_Obj **
|
||||
GrowEvaluationStack(
|
||||
ExecEnv *eePtr, /* Points to the ExecEnv with an evaluation
|
||||
* stack to enlarge. */
|
||||
size_t growth1, /* How much larger than the current used
|
||||
TCL_HASH_TYPE growth1, /* How much larger than the current used
|
||||
* size. */
|
||||
int move) /* 1 if move words since last marker. */
|
||||
{
|
||||
ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL;
|
||||
size_t newBytes;
|
||||
int growth = growth1;
|
||||
int newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
|
||||
TCL_HASH_TYPE newBytes;
|
||||
Tcl_Size growth = growth1;
|
||||
Tcl_Size newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
|
||||
Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart;
|
||||
int moveWords = 0;
|
||||
Tcl_Size moveWords = 0;
|
||||
|
||||
if (move) {
|
||||
if (!markerPtr) {
|
||||
@@ -1127,7 +1126,7 @@ GrowEvaluationStack(
|
||||
static Tcl_Obj **
|
||||
StackAllocWords(
|
||||
Tcl_Interp *interp,
|
||||
size_t numWords)
|
||||
TCL_HASH_TYPE numWords)
|
||||
{
|
||||
/*
|
||||
* Note that GrowEvaluationStack sets a marker in the stack. This marker
|
||||
@@ -1145,7 +1144,7 @@ StackAllocWords(
|
||||
static Tcl_Obj **
|
||||
StackReallocWords(
|
||||
Tcl_Interp *interp,
|
||||
size_t numWords)
|
||||
TCL_HASH_TYPE numWords)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
ExecEnv *eePtr = iPtr->execEnvPtr;
|
||||
@@ -1224,13 +1223,13 @@ TclStackFree(
|
||||
void *
|
||||
TclStackAlloc(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Size numBytes)
|
||||
TCL_HASH_TYPE numBytes)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Size numWords;
|
||||
TCL_HASH_TYPE numWords;
|
||||
|
||||
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
|
||||
return (void *) Tcl_Alloc(numBytes);
|
||||
return Tcl_Alloc(numBytes);
|
||||
}
|
||||
numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
|
||||
return StackAllocWords(interp, numWords);
|
||||
@@ -1240,13 +1239,13 @@ void *
|
||||
TclStackRealloc(
|
||||
Tcl_Interp *interp,
|
||||
void *ptr,
|
||||
Tcl_Size numBytes)
|
||||
TCL_HASH_TYPE numBytes)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
ExecEnv *eePtr;
|
||||
ExecStack *esPtr;
|
||||
Tcl_Obj **markerPtr;
|
||||
Tcl_Size numWords;
|
||||
TCL_HASH_TYPE numWords;
|
||||
|
||||
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
|
||||
return Tcl_Realloc(ptr, numBytes);
|
||||
@@ -1889,10 +1888,10 @@ TclNRExecuteByteCode(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
TEBCdata *TD;
|
||||
size_t size = sizeof(TEBCdata) - 1
|
||||
TCL_HASH_TYPE size = sizeof(TEBCdata) - 1
|
||||
+ (codePtr->maxStackDepth + codePtr->maxExceptDepth)
|
||||
* sizeof(void *);
|
||||
size_t numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *);
|
||||
TCL_HASH_TYPE numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *);
|
||||
|
||||
TclPreserveByteCode(codePtr);
|
||||
|
||||
@@ -2066,7 +2065,7 @@ TEBCresume(
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (!pc && (tclTraceExec >= 2)) {
|
||||
PrintByteCodeInfo(codePtr);
|
||||
fprintf(stdout, " Starting stack top=%" TCL_Z_MODIFIER "u\n", CURR_DEPTH);
|
||||
fprintf(stdout, " Starting stack top=%" TCL_T_MODIFIER "d\n", CURR_DEPTH);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
@@ -2125,7 +2124,7 @@ TEBCresume(
|
||||
* instruction.
|
||||
*/
|
||||
|
||||
TRACE_WITH_OBJ(("%" TCL_Z_MODIFIER "u => ... after \"%.20s\": TCL_OK, result=",
|
||||
TRACE_WITH_OBJ(("%" TCL_SIZE_MODIFIER "d => ... after \"%.20s\": TCL_OK, result=",
|
||||
objc, cmdNameBuf), Tcl_GetObjResult(interp));
|
||||
|
||||
/*
|
||||
@@ -2270,7 +2269,7 @@ TEBCresume(
|
||||
|
||||
CHECK_STACK();
|
||||
if (traceInstructions) {
|
||||
fprintf(stdout, "%2" TCL_Z_MODIFIER "u: %2" TCL_Z_MODIFIER "u ", iPtr->numLevels, CURR_DEPTH);
|
||||
fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d ", iPtr->numLevels, CURR_DEPTH);
|
||||
TclPrintInstruction(codePtr, pc);
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -2390,7 +2389,7 @@ TEBCresume(
|
||||
if (traceInstructions) {
|
||||
TRACE_APPEND(("YIELD...\n"));
|
||||
} else {
|
||||
fprintf(stdout, "%" TCL_Z_MODIFIER "d: (%" TCL_T_MODIFIER "u) yielding value \"%.30s\"\n",
|
||||
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding value \"%.30s\"\n",
|
||||
iPtr->numLevels, (pc - codePtr->codeStart),
|
||||
Tcl_GetString(OBJ_AT_TOS));
|
||||
}
|
||||
@@ -2433,7 +2432,7 @@ TEBCresume(
|
||||
TRACE(("[%.30s] => YIELD...\n", O2S(valuePtr)));
|
||||
} else {
|
||||
/* FIXME: What is the right thing to trace? */
|
||||
fprintf(stdout, "%" TCL_Z_MODIFIER "d: (%" TCL_T_MODIFIER "u) yielding to [%.30s]\n",
|
||||
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding to [%.30s]\n",
|
||||
iPtr->numLevels, (pc - codePtr->codeStart),
|
||||
TclGetString(valuePtr));
|
||||
}
|
||||
@@ -2637,10 +2636,10 @@ TEBCresume(
|
||||
*/
|
||||
|
||||
TclNewObj(objPtr);
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = UINT2PTR(CURR_DEPTH);
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(CURR_DEPTH);
|
||||
objPtr->length = 0;
|
||||
PUSH_TAUX_OBJ(objPtr);
|
||||
TRACE(("=> mark depth as %" TCL_Z_MODIFIER "u\n", CURR_DEPTH));
|
||||
TRACE(("=> mark depth as %" TCL_T_MODIFIER "d\n", CURR_DEPTH));
|
||||
NEXT_INST_F(1, 0, 0);
|
||||
break;
|
||||
|
||||
@@ -2652,13 +2651,13 @@ TEBCresume(
|
||||
*/
|
||||
|
||||
CLANG_ASSERT(auxObjList);
|
||||
objc = CURR_DEPTH - PTR2UINT(auxObjList->internalRep.twoPtrValue.ptr2);
|
||||
objc = CURR_DEPTH - PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2);
|
||||
POP_TAUX_OBJ();
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
/* Ugly abuse! */
|
||||
starting = 1;
|
||||
#endif
|
||||
TRACE(("=> drop %" TCL_Z_MODIFIER "u items\n", objc));
|
||||
TRACE(("=> drop %" TCL_SIZE_MODIFIER "d items\n", objc));
|
||||
NEXT_INST_V(1, objc, 0);
|
||||
|
||||
case INST_EXPAND_STKTOP: {
|
||||
@@ -2759,7 +2758,7 @@ TEBCresume(
|
||||
|
||||
case INST_INVOKE_EXPANDED:
|
||||
CLANG_ASSERT(auxObjList);
|
||||
objc = CURR_DEPTH - PTR2UINT(auxObjList->internalRep.twoPtrValue.ptr2);
|
||||
objc = CURR_DEPTH - PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2);
|
||||
POP_TAUX_OBJ();
|
||||
if (objc) {
|
||||
pcAdjustment = 1;
|
||||
@@ -2793,9 +2792,9 @@ TEBCresume(
|
||||
|
||||
if (traceInstructions) {
|
||||
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
|
||||
TRACE(("%" TCL_Z_MODIFIER "u => call ", objc));
|
||||
TRACE(("%" TCL_SIZE_MODIFIER "d => call ", objc));
|
||||
} else {
|
||||
fprintf(stdout, "%" TCL_Z_MODIFIER "d: (%" TCL_T_MODIFIER "u) invoking ", iPtr->numLevels,
|
||||
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ", iPtr->numLevels,
|
||||
(pc - codePtr->codeStart));
|
||||
}
|
||||
for (i = 0; i < objc; i++) {
|
||||
@@ -2825,8 +2824,12 @@ TEBCresume(
|
||||
|
||||
pc += pcAdjustment;
|
||||
TEBC_YIELD();
|
||||
return TclNREvalObjv(interp, objc, objv,
|
||||
if (objc > INT_MAX) {
|
||||
return TclCommandWordLimitError(interp, objc);
|
||||
} else {
|
||||
return TclNREvalObjv(interp, objc, objv,
|
||||
TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME, NULL);
|
||||
}
|
||||
|
||||
case INST_INVOKE_REPLACE:
|
||||
objc = TclGetUInt4AtPtr(pc+1);
|
||||
@@ -3371,7 +3374,12 @@ TEBCresume(
|
||||
goto gotError;
|
||||
}
|
||||
if (Tcl_IsShared(objResultPtr)) {
|
||||
Tcl_Obj *newValue = Tcl_DuplicateObj(objResultPtr);
|
||||
Tcl_Obj *newValue = TclDuplicatePureObj(
|
||||
interp, objResultPtr, &tclListType.objType);
|
||||
if (!newValue) {
|
||||
TRACE_ERROR(interp);
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
TclDecrRefCount(objResultPtr);
|
||||
varPtr->value.objPtr = objResultPtr = newValue;
|
||||
@@ -3430,7 +3438,11 @@ TEBCresume(
|
||||
goto gotError;
|
||||
} else {
|
||||
if (Tcl_IsShared(objResultPtr)) {
|
||||
valueToAssign = Tcl_DuplicateObj(objResultPtr);
|
||||
valueToAssign = TclDuplicatePureObj(
|
||||
interp, objResultPtr, &tclListType.objType);
|
||||
if (!valueToAssign) {
|
||||
goto errorInLappendListPtr;
|
||||
}
|
||||
createdNewObj = 1;
|
||||
} else {
|
||||
valueToAssign = objResultPtr;
|
||||
@@ -4427,7 +4439,7 @@ TEBCresume(
|
||||
if (traceInstructions) {
|
||||
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
|
||||
} else {
|
||||
fprintf(stdout, "%" TCL_Z_MODIFIER "d: (%" TCL_Z_MODIFIER "u) invoking ",
|
||||
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ",
|
||||
iPtr->numLevels,
|
||||
(size_t)(pc - codePtr->codeStart));
|
||||
}
|
||||
@@ -4529,8 +4541,8 @@ TEBCresume(
|
||||
if (traceInstructions) {
|
||||
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
|
||||
} else {
|
||||
fprintf(stdout, "%" TCL_Z_MODIFIER "d: (%" TCL_Z_MODIFIER "u) invoking ",
|
||||
iPtr->numLevels, (size_t)(pc - codePtr->codeStart));
|
||||
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_Z_MODIFIER "u) invoking ",
|
||||
iPtr->numLevels, (pc - codePtr->codeStart));
|
||||
}
|
||||
for (i = 0; i < opnd; i++) {
|
||||
TclPrintObject(stdout, objv[i], 15);
|
||||
@@ -4647,8 +4659,8 @@ TEBCresume(
|
||||
TRACE_ERROR(interp);
|
||||
goto gotError;
|
||||
}
|
||||
TclNewUIntObj(objResultPtr, length);
|
||||
TRACE_APPEND(("%" TCL_Z_MODIFIER "u\n", length));
|
||||
TclNewIntObj(objResultPtr, length);
|
||||
TRACE_APPEND(("%" TCL_SIZE_MODIFIER "d\n", length));
|
||||
NEXT_INST_F(1, 1, 1);
|
||||
|
||||
case INST_LIST_INDEX: /* lindex with objc == 3 */
|
||||
@@ -4679,23 +4691,44 @@ TEBCresume(
|
||||
* Extract the desired list element.
|
||||
*/
|
||||
|
||||
if ((TclListObjGetElementsM(interp, valuePtr, &objc, &objv) == TCL_OK)
|
||||
&& !TclHasInternalRep(value2Ptr, &tclListType.objType)) {
|
||||
int code;
|
||||
{
|
||||
Tcl_Size value2Length;
|
||||
Tcl_Obj *indexListPtr = value2Ptr;
|
||||
if ((TclListObjGetElementsM(interp, valuePtr, &objc, &objv) == TCL_OK)
|
||||
&& (
|
||||
!TclHasInternalRep(value2Ptr, &tclListType.objType)
|
||||
||
|
||||
((Tcl_ListObjLength(interp,value2Ptr,&value2Length),
|
||||
value2Length == 1
|
||||
? (indexListPtr = TclListObjGetElement(value2Ptr, 0), 1)
|
||||
: 0
|
||||
))
|
||||
)
|
||||
) {
|
||||
int code;
|
||||
|
||||
DECACHE_STACK_INFO();
|
||||
code = TclGetIntForIndexM(interp, value2Ptr, objc-1, &index);
|
||||
CACHE_STACK_INFO();
|
||||
if (code == TCL_OK) {
|
||||
TclDecrRefCount(value2Ptr);
|
||||
tosPtr--;
|
||||
pcAdjustment = 1;
|
||||
goto lindexFastPath;
|
||||
/* increment the refCount of value2Ptr because TclListObjGetElement may
|
||||
* have just extracted it from a list in the condition for this block.
|
||||
*/
|
||||
Tcl_IncrRefCount(indexListPtr);
|
||||
|
||||
DECACHE_STACK_INFO();
|
||||
code = TclGetIntForIndexM(interp, indexListPtr, objc-1, &index);
|
||||
TclDecrRefCount(indexListPtr);
|
||||
CACHE_STACK_INFO();
|
||||
if (code == TCL_OK) {
|
||||
Tcl_DecrRefCount(value2Ptr);
|
||||
tosPtr--;
|
||||
pcAdjustment = 1;
|
||||
goto lindexFastPath;
|
||||
}
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclLindexList(interp, valuePtr, value2Ptr);
|
||||
CACHE_STACK_INFO();
|
||||
|
||||
lindexDone:
|
||||
if (!objResultPtr) {
|
||||
@@ -5037,7 +5070,7 @@ TEBCresume(
|
||||
|
||||
case INST_LREPLACE4:
|
||||
{
|
||||
size_t numToDelete, numNewElems;
|
||||
TCL_HASH_TYPE numToDelete, numNewElems;
|
||||
int end_indicator;
|
||||
int haveSecondIndex, flags;
|
||||
Tcl_Obj *fromIdxObj, *toIdxObj;
|
||||
@@ -5272,7 +5305,7 @@ TEBCresume(
|
||||
TclNewObj(objResultPtr);
|
||||
} else if (TclIsPureByteArray(valuePtr)) {
|
||||
objResultPtr = Tcl_NewByteArrayObj(
|
||||
Tcl_GetByteArrayFromObj(valuePtr, (size_t *)NULL)+index, 1);
|
||||
Tcl_GetByteArrayFromObj(valuePtr, (Tcl_Size *)NULL)+index, 1);
|
||||
} else if (valuePtr->bytes && slength == valuePtr->length) {
|
||||
objResultPtr = Tcl_NewStringObj((const char *)
|
||||
valuePtr->bytes+index, 1);
|
||||
@@ -5488,7 +5521,7 @@ TEBCresume(
|
||||
NEXT_INST_F(1, 2, 1);
|
||||
|
||||
case INST_STR_FIND_LAST:
|
||||
objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, INT_MAX - 1);
|
||||
objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, TCL_SIZE_MAX - 1);
|
||||
|
||||
TRACE(("%.20s %.20s => %s\n",
|
||||
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(objResultPtr)));
|
||||
@@ -5536,7 +5569,7 @@ TEBCresume(
|
||||
nocase);
|
||||
} else if (TclIsPureByteArray(valuePtr) && TclIsPureByteArray(value2Ptr) && !nocase) {
|
||||
unsigned char *bytes1, *bytes2;
|
||||
size_t wlen1 = 0, wlen2 = 0;
|
||||
Tcl_Size wlen1 = 0, wlen2 = 0;
|
||||
|
||||
bytes1 = Tcl_GetByteArrayFromObj(valuePtr, &wlen1);
|
||||
bytes2 = Tcl_GetByteArrayFromObj(value2Ptr, &wlen2);
|
||||
@@ -6402,7 +6435,11 @@ TEBCresume(
|
||||
goto gotError;
|
||||
}
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
objPtr = TclListObjCopy(NULL, listPtr);
|
||||
objPtr = TclDuplicatePureObj(
|
||||
interp, listPtr, &tclListType.objType);
|
||||
if (!objPtr) {
|
||||
goto gotError;
|
||||
}
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
OBJ_AT_DEPTH(listTmpDepth) = objPtr;
|
||||
@@ -6464,6 +6501,7 @@ TEBCresume(
|
||||
*/
|
||||
|
||||
if (iterNum < iterMax) {
|
||||
int status;
|
||||
/*
|
||||
* Set the variables and jump back to run the body
|
||||
*/
|
||||
@@ -6477,7 +6515,12 @@ TEBCresume(
|
||||
numVars = varListPtr->numVars;
|
||||
|
||||
listPtr = OBJ_AT_DEPTH(listTmpDepth);
|
||||
TclListObjGetElementsM(interp, listPtr, &listLen, &elements);
|
||||
status = TclListObjGetElementsM(
|
||||
interp, listPtr, &listLen, &elements);
|
||||
if (status != TCL_OK) {
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
|
||||
valIndex = (iterNum * numVars);
|
||||
for (j = 0; j < numVars; j++) {
|
||||
@@ -6506,7 +6549,7 @@ TEBCresume(
|
||||
if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
|
||||
CACHE_STACK_INFO();
|
||||
TRACE_APPEND(("ERROR init. index temp %" TCL_Z_MODIFIER "u: %.30s",
|
||||
TRACE_APPEND(("ERROR init. index temp %" TCL_SIZE_MODIFIER "d: %.30s",
|
||||
varIndex, O2S(Tcl_GetObjResult(interp))));
|
||||
goto gotError;
|
||||
}
|
||||
@@ -6553,7 +6596,7 @@ TEBCresume(
|
||||
tmpPtr = OBJ_AT_DEPTH(1);
|
||||
infoPtr = (ForeachInfo *)tmpPtr->internalRep.twoPtrValue.ptr1;
|
||||
numLists = infoPtr->numLists;
|
||||
TRACE_APPEND(("=> appending to list at depth %" TCL_Z_MODIFIER "u\n", 3 + numLists));
|
||||
TRACE_APPEND(("=> appending to list at depth %" TCL_SIZE_MODIFIER "d\n", 3 + numLists));
|
||||
|
||||
objPtr = OBJ_AT_DEPTH(3 + numLists);
|
||||
Tcl_ListObjAppendElement(NULL, objPtr, OBJ_AT_TOS);
|
||||
@@ -6568,9 +6611,9 @@ TEBCresume(
|
||||
* stack.
|
||||
*/
|
||||
|
||||
*(++catchTop) = (Tcl_Obj *)UINT2PTR(CURR_DEPTH);
|
||||
TRACE(("%u => catchTop=%" TCL_Z_MODIFIER "u, stackTop=%" TCL_Z_MODIFIER "u\n",
|
||||
TclGetUInt4AtPtr(pc+1), (size_t)(catchTop - initCatchTop - 1),
|
||||
*(++catchTop) = (Tcl_Obj *)INT2PTR(CURR_DEPTH);
|
||||
TRACE(("%u => catchTop=%" TCL_T_MODIFIER "d, stackTop=%" TCL_T_MODIFIER "d\n",
|
||||
TclGetUInt4AtPtr(pc+1), (catchTop - initCatchTop - 1),
|
||||
CURR_DEPTH));
|
||||
NEXT_INST_F(5, 0, 0);
|
||||
break;
|
||||
@@ -7381,7 +7424,7 @@ TEBCresume(
|
||||
if (result == TCL_BREAK) {
|
||||
result = TCL_OK;
|
||||
pc = (codePtr->codeStart + rangePtr->breakOffset);
|
||||
TRACE_APPEND(("%s, range at %" TCL_Z_MODIFIER "u, new pc %" TCL_Z_MODIFIER "u\n",
|
||||
TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
|
||||
StringForResultCode(result),
|
||||
rangePtr->codeOffset, rangePtr->breakOffset));
|
||||
NEXT_INST_F(0, 0, 0);
|
||||
@@ -7393,7 +7436,7 @@ TEBCresume(
|
||||
}
|
||||
result = TCL_OK;
|
||||
pc = (codePtr->codeStart + rangePtr->continueOffset);
|
||||
TRACE_APPEND(("%s, range at %" TCL_Z_MODIFIER "u, new pc %" TCL_Z_MODIFIER "u\n",
|
||||
TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
|
||||
StringForResultCode(result),
|
||||
rangePtr->codeOffset, rangePtr->continueOffset));
|
||||
NEXT_INST_F(0, 0, 0);
|
||||
@@ -7483,8 +7526,8 @@ TEBCresume(
|
||||
|
||||
while (auxObjList) {
|
||||
if ((catchTop != initCatchTop)
|
||||
&& (PTR2UINT(*catchTop) >
|
||||
PTR2UINT(auxObjList->internalRep.twoPtrValue.ptr2))) {
|
||||
&& (PTR2INT(*catchTop) >
|
||||
PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2))) {
|
||||
break;
|
||||
}
|
||||
POP_TAUX_OBJ();
|
||||
@@ -7559,16 +7602,16 @@ TEBCresume(
|
||||
*/
|
||||
|
||||
processCatch:
|
||||
while (CURR_DEPTH > PTR2UINT(*catchTop)) {
|
||||
while (CURR_DEPTH > PTR2INT(*catchTop)) {
|
||||
valuePtr = POP_OBJECT();
|
||||
TclDecrRefCount(valuePtr);
|
||||
}
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (traceInstructions) {
|
||||
fprintf(stdout, " ... found catch at %" TCL_Z_MODIFIER "u, catchTop=%" TCL_Z_MODIFIER "u, "
|
||||
"unwound to %" TCL_Z_MODIFIER "u, new pc %" TCL_Z_MODIFIER "u\n",
|
||||
rangePtr->codeOffset, (size_t)(catchTop - initCatchTop - 1),
|
||||
PTR2UINT(*catchTop), (size_t)rangePtr->catchOffset);
|
||||
fprintf(stdout, " ... found catch at %" TCL_SIZE_MODIFIER "d, catchTop=%" TCL_T_MODIFIER "d, "
|
||||
"unwound to %" TCL_T_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
|
||||
rangePtr->codeOffset, (catchTop - initCatchTop - 1),
|
||||
PTR2INT(*catchTop), rangePtr->catchOffset);
|
||||
}
|
||||
#endif
|
||||
pc = (codePtr->codeStart + rangePtr->catchOffset);
|
||||
@@ -7604,9 +7647,9 @@ TEBCresume(
|
||||
|
||||
if (tosPtr < initTosPtr) {
|
||||
fprintf(stderr,
|
||||
"\nTclNRExecuteByteCode: abnormal return at pc %" TCL_Z_MODIFIER "u: "
|
||||
"stack top %" TCL_Z_MODIFIER "u < entry stack top %d\n",
|
||||
(size_t)(pc - codePtr->codeStart),
|
||||
"\nTclNRExecuteByteCode: abnormal return at pc %" TCL_T_MODIFIER "d: "
|
||||
"stack top %" TCL_T_MODIFIER "d < entry stack top %d\n",
|
||||
(pc - codePtr->codeStart),
|
||||
CURR_DEPTH, 0);
|
||||
Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top");
|
||||
}
|
||||
@@ -9132,7 +9175,7 @@ GetSrcInfoForPc(
|
||||
int bestCmdIdx = -1;
|
||||
|
||||
/* The pc must point within the bytecode */
|
||||
assert (pcOffset < codePtr->numCodeBytes);
|
||||
assert ((pcOffset >= 0) && (pcOffset < codePtr->numCodeBytes));
|
||||
|
||||
/*
|
||||
* Decode the code and source offset and length for each command. The
|
||||
@@ -9620,7 +9663,7 @@ EvalStatsCmd(
|
||||
Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%" TCL_Z_MODIFIER "u\n",
|
||||
statsPtr->numLiteralsCreated);
|
||||
|
||||
Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current objects)\n",
|
||||
Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%" TCL_SIZE_MODIFIER "d (%0.1f%% of current objects)\n",
|
||||
globalTablePtr->numEntries,
|
||||
Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed));
|
||||
Tcl_AppendPrintfToObj(objPtr, " ByteCode literals\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current literals)\n",
|
||||
@@ -9712,7 +9755,7 @@ EvalStatsCmd(
|
||||
for (i = 0; i <= maxSizeDecade; i++) {
|
||||
decadeHigh = (1 << (i+1)) - 1;
|
||||
sum += statsPtr->literalCount[i];
|
||||
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n",
|
||||
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
|
||||
decadeHigh, Percent(sum, statsPtr->numLiteralsCreated));
|
||||
}
|
||||
|
||||
@@ -9745,7 +9788,7 @@ EvalStatsCmd(
|
||||
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
|
||||
decadeHigh = (1 << (i+1)) - 1;
|
||||
sum += statsPtr->srcCount[i];
|
||||
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n",
|
||||
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
|
||||
decadeHigh, Percent(sum, statsPtr->numCompilations));
|
||||
}
|
||||
|
||||
@@ -9769,7 +9812,7 @@ EvalStatsCmd(
|
||||
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
|
||||
decadeHigh = (1 << (i+1)) - 1;
|
||||
sum += statsPtr->byteCodeCount[i];
|
||||
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n",
|
||||
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
|
||||
decadeHigh, Percent(sum, statsPtr->numCompilations));
|
||||
}
|
||||
|
||||
|
||||
+71
-75
@@ -205,7 +205,7 @@ static int FlushChannel(Tcl_Interp *interp, Channel *chanPtr,
|
||||
int calledFromAsyncFlush);
|
||||
static int TclGetsObjBinary(Tcl_Channel chan, Tcl_Obj *objPtr);
|
||||
static Tcl_Encoding GetBinaryEncoding(void);
|
||||
static Tcl_ExitProc FreeBinaryEncoding;
|
||||
static void FreeBinaryEncoding(void);
|
||||
static Tcl_HashTable * GetChannelTable(Tcl_Interp *interp);
|
||||
static int GetInput(Channel *chanPtr);
|
||||
static void PeekAhead(Channel *chanPtr, char **dstEndPtr,
|
||||
@@ -223,8 +223,8 @@ static void StopCopy(CopyState *csPtr);
|
||||
static void TranslateInputEOL(ChannelState *statePtr, char *dst,
|
||||
const char *src, int *dstLenPtr, int *srcLenPtr);
|
||||
static void UpdateInterest(Channel *chanPtr);
|
||||
static int Write(Channel *chanPtr, const char *src,
|
||||
int srcLen, Tcl_Encoding encoding);
|
||||
static Tcl_Size Write(Channel *chanPtr, const char *src,
|
||||
Tcl_Size srcLen, Tcl_Encoding encoding);
|
||||
static Tcl_Obj * FixLevelCode(Tcl_Obj *msg);
|
||||
static void SpliceChannel(Tcl_Channel chan);
|
||||
static void CutChannel(Tcl_Channel chan);
|
||||
@@ -659,7 +659,7 @@ TclFinalizeIOSubsystem(void)
|
||||
statePtr->refCount--;
|
||||
}
|
||||
|
||||
if (statePtr->refCount + 1 <= 1) {
|
||||
if (statePtr->refCount <= 0) {
|
||||
/*
|
||||
* Close it only if the refcount indicates that the channel is
|
||||
* not referenced from any interpreter. If it is, that
|
||||
@@ -695,6 +695,7 @@ TclFinalizeIOSubsystem(void)
|
||||
}
|
||||
}
|
||||
|
||||
FreeBinaryEncoding();
|
||||
TclpFinalizeSockets();
|
||||
TclpFinalizePipes();
|
||||
}
|
||||
@@ -1077,7 +1078,7 @@ CheckForStdChannelsBeingClosed(
|
||||
if (tsdPtr->stdinInitialized == 1
|
||||
&& tsdPtr->stdinChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stdinChannel)->state) {
|
||||
if (statePtr->refCount + 1 < 3) {
|
||||
if (statePtr->refCount < 2) {
|
||||
statePtr->refCount = 0;
|
||||
tsdPtr->stdinChannel = NULL;
|
||||
return;
|
||||
@@ -1085,7 +1086,7 @@ CheckForStdChannelsBeingClosed(
|
||||
} else if (tsdPtr->stdoutInitialized == 1
|
||||
&& tsdPtr->stdoutChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) {
|
||||
if (statePtr->refCount + 1 < 3) {
|
||||
if (statePtr->refCount < 2) {
|
||||
statePtr->refCount = 0;
|
||||
tsdPtr->stdoutChannel = NULL;
|
||||
return;
|
||||
@@ -1093,7 +1094,7 @@ CheckForStdChannelsBeingClosed(
|
||||
} else if (tsdPtr->stderrInitialized == 1
|
||||
&& tsdPtr->stderrChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stderrChannel)->state) {
|
||||
if (statePtr->refCount + 1 < 3) {
|
||||
if (statePtr->refCount < 2) {
|
||||
statePtr->refCount = 0;
|
||||
tsdPtr->stderrChannel = NULL;
|
||||
return;
|
||||
@@ -1255,7 +1256,7 @@ Tcl_UnregisterChannel(
|
||||
* If the refCount reached zero, close the actual channel.
|
||||
*/
|
||||
|
||||
if (statePtr->refCount + 1 <= 1) {
|
||||
if (statePtr->refCount <= 0) {
|
||||
Tcl_Preserve(statePtr);
|
||||
if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
|
||||
/*
|
||||
@@ -1663,6 +1664,10 @@ Tcl_CreateChannel(
|
||||
}
|
||||
statePtr->channelName = tmp;
|
||||
statePtr->flags = mask;
|
||||
/* uncomment this to make default encoding error handling strict */
|
||||
/*
|
||||
statePtr->flags |= CHANNEL_ENCODING_STRICT;
|
||||
*/
|
||||
statePtr->maxPerms = mask; /* Save max privileges for close callback */
|
||||
|
||||
/*
|
||||
@@ -1679,11 +1684,11 @@ Tcl_CreateChannel(
|
||||
statePtr->encoding = Tcl_GetEncoding(NULL, name);
|
||||
statePtr->inputEncodingState = NULL;
|
||||
statePtr->inputEncodingFlags = TCL_ENCODING_START;
|
||||
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags,
|
||||
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags,
|
||||
TCL_ENCODING_PROFILE_DEFAULT);
|
||||
statePtr->outputEncodingState = NULL;
|
||||
statePtr->outputEncodingFlags = TCL_ENCODING_START;
|
||||
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags,
|
||||
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags,
|
||||
TCL_ENCODING_PROFILE_DEFAULT);
|
||||
|
||||
/*
|
||||
@@ -2003,7 +2008,7 @@ static void
|
||||
ChannelFree(
|
||||
Channel *chanPtr)
|
||||
{
|
||||
if (!chanPtr->refCount) {
|
||||
if (chanPtr->refCount == 0) {
|
||||
Tcl_Free(chanPtr);
|
||||
return;
|
||||
}
|
||||
@@ -2178,7 +2183,7 @@ Tcl_UnstackChannel(
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
if (statePtr->refCount + 1 <= 1) {
|
||||
if (statePtr->refCount <= 0) {
|
||||
if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) {
|
||||
/*
|
||||
* TIP #219, Tcl Channel Reflection API.
|
||||
@@ -2546,7 +2551,7 @@ static int
|
||||
IsShared(
|
||||
ChannelBuffer *bufPtr)
|
||||
{
|
||||
return bufPtr->refCount + 1 > 2;
|
||||
return bufPtr->refCount > 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2995,7 +3000,7 @@ FlushChannel(
|
||||
* current output buffer.
|
||||
*/
|
||||
|
||||
if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount + 1 <= 1) &&
|
||||
if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount <= 0) &&
|
||||
(statePtr->outQueueHead == NULL) &&
|
||||
((statePtr->curOutPtr == NULL) ||
|
||||
IsBufferEmpty(statePtr->curOutPtr))) {
|
||||
@@ -3456,7 +3461,7 @@ TclClose(
|
||||
statePtr = chanPtr->state;
|
||||
chanPtr = statePtr->topChanPtr;
|
||||
|
||||
if (statePtr->refCount + 1 > 1) {
|
||||
if (statePtr->refCount > 0) {
|
||||
Tcl_Panic("called Tcl_Close on channel with refCount > 0");
|
||||
}
|
||||
|
||||
@@ -4191,7 +4196,6 @@ Tcl_WriteChars(
|
||||
}
|
||||
|
||||
objPtr = Tcl_NewStringObj(src, len);
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len);
|
||||
if (src == NULL) {
|
||||
Tcl_SetErrno(EILSEQ);
|
||||
@@ -4240,6 +4244,7 @@ Tcl_WriteObj(
|
||||
Channel *chanPtr;
|
||||
ChannelState *statePtr; /* State info for channel */
|
||||
const char *src;
|
||||
Tcl_Size srcLen = 0;
|
||||
|
||||
statePtr = ((Channel *) chan)->state;
|
||||
chanPtr = statePtr->topChanPtr;
|
||||
@@ -4247,34 +4252,21 @@ Tcl_WriteObj(
|
||||
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
|
||||
return TCL_INDEX_NONE;
|
||||
}
|
||||
|
||||
Tcl_Size srcLen;
|
||||
if (statePtr->encoding == NULL) {
|
||||
Tcl_Size result;
|
||||
|
||||
src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen);
|
||||
if (src == NULL) {
|
||||
Tcl_SetErrno(EILSEQ);
|
||||
return TCL_INDEX_NONE;
|
||||
result = TCL_INDEX_NONE;
|
||||
} else {
|
||||
result = WriteBytes(chanPtr, src, srcLen);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
src = Tcl_GetStringFromObj(objPtr, &srcLen);
|
||||
return WriteChars(chanPtr, src, srcLen);
|
||||
}
|
||||
|
||||
size_t totalWritten = 0;
|
||||
/*
|
||||
* Note original code always called WriteChars even if srcLen 0
|
||||
* so we will too.
|
||||
*/
|
||||
do {
|
||||
int chunkSize = srcLen > INT_MAX ? INT_MAX : srcLen;
|
||||
int written;
|
||||
written = WriteChars(chanPtr, src, chunkSize);
|
||||
if (written < 0) {
|
||||
return TCL_INDEX_NONE;
|
||||
}
|
||||
totalWritten += written;
|
||||
srcLen -= chunkSize;
|
||||
} while (srcLen);
|
||||
return totalWritten;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4345,17 +4337,18 @@ WillRead(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
static Tcl_Size
|
||||
Write(
|
||||
Channel *chanPtr, /* The channel to buffer output for. */
|
||||
const char *src, /* UTF-8 string to write. */
|
||||
int srcLen, /* Length of UTF-8 string in bytes. */
|
||||
Tcl_Size srcLen, /* Length of UTF-8 string in bytes. */
|
||||
Tcl_Encoding encoding)
|
||||
{
|
||||
ChannelState *statePtr = chanPtr->state;
|
||||
/* State info for channel */
|
||||
char *nextNewLine = NULL;
|
||||
int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0;
|
||||
int endEncoding, needNlFlush = 0;
|
||||
Tcl_Size saved = 0, total = 0, flushed = 0;
|
||||
char safe[BUFFER_PADDING];
|
||||
int encodingError = 0;
|
||||
|
||||
@@ -4368,7 +4361,6 @@ Write(
|
||||
*/
|
||||
|
||||
endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);
|
||||
|
||||
if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)
|
||||
|| (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
|
||||
nextNewLine = (char *)memchr(src, '\n', srcLen);
|
||||
@@ -4377,7 +4369,8 @@ Write(
|
||||
while (srcLen + saved + endEncoding > 0 && !encodingError) {
|
||||
ChannelBuffer *bufPtr;
|
||||
char *dst;
|
||||
int result, srcRead, dstLen, dstWrote, srcLimit = srcLen;
|
||||
int result, srcRead, dstLen, dstWrote;
|
||||
Tcl_Size srcLimit = srcLen;
|
||||
|
||||
if (nextNewLine) {
|
||||
srcLimit = nextNewLine - src;
|
||||
@@ -4567,7 +4560,7 @@ Tcl_Gets(
|
||||
|
||||
TclNewObj(objPtr);
|
||||
charsStored = Tcl_GetsObj(chan, objPtr);
|
||||
if (charsStored + 1 > 1) {
|
||||
if (charsStored > 0) {
|
||||
TclDStringAppendObj(lineRead, objPtr);
|
||||
}
|
||||
TclDecrRefCount(objPtr);
|
||||
@@ -4649,7 +4642,7 @@ Tcl_GetsObj(
|
||||
if (statePtr->encoding == GetBinaryEncoding()
|
||||
&& ((statePtr->inputTranslation == TCL_TRANSLATE_LF)
|
||||
|| (statePtr->inputTranslation == TCL_TRANSLATE_CR))
|
||||
&& Tcl_GetByteArrayFromObj(objPtr, (size_t *)NULL) != NULL) {
|
||||
&& Tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)NULL) != NULL) {
|
||||
return TclGetsObjBinary(chan, objPtr);
|
||||
}
|
||||
|
||||
@@ -5301,8 +5294,7 @@ TclGetsObjBinary(
|
||||
*/
|
||||
|
||||
static void
|
||||
FreeBinaryEncoding(
|
||||
TCL_UNUSED(void *))
|
||||
FreeBinaryEncoding(void)
|
||||
{
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
@@ -5319,7 +5311,6 @@ GetBinaryEncoding(void)
|
||||
|
||||
if (tsdPtr->binaryEncoding == NULL) {
|
||||
tsdPtr->binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
|
||||
Tcl_CreateThreadExitHandler(FreeBinaryEncoding, NULL);
|
||||
}
|
||||
if (tsdPtr->binaryEncoding == NULL) {
|
||||
Tcl_Panic("binary encoding is not available");
|
||||
@@ -5942,8 +5933,9 @@ DoReadChars(
|
||||
|
||||
if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
|
||||
ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_ENCODING_ERROR);
|
||||
/* TODO: We don't need this call? */
|
||||
/* TODO: UpdateInterest not needed here? */
|
||||
UpdateInterest(chanPtr);
|
||||
|
||||
Tcl_SetErrno(EILSEQ);
|
||||
return -1;
|
||||
}
|
||||
@@ -5959,7 +5951,7 @@ DoReadChars(
|
||||
assert(statePtr->inputEncodingFlags & TCL_ENCODING_END);
|
||||
assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR));
|
||||
|
||||
/* TODO: We don't need this call? */
|
||||
/* TODO: UpdateInterest not needed here? */
|
||||
UpdateInterest(chanPtr);
|
||||
return 0;
|
||||
}
|
||||
@@ -5973,7 +5965,7 @@ DoReadChars(
|
||||
}
|
||||
ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF);
|
||||
statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
|
||||
/* TODO: We don't need this call? */
|
||||
/* TODO: UpdateInterest not needed here? */
|
||||
UpdateInterest(chanPtr);
|
||||
return 0;
|
||||
}
|
||||
@@ -5990,7 +5982,7 @@ DoReadChars(
|
||||
&& (statePtr->inEofChar == '\0');
|
||||
|
||||
if (appendFlag) {
|
||||
if (binaryMode && (NULL == Tcl_GetByteArrayFromObj(objPtr, (size_t *)NULL))) {
|
||||
if (binaryMode && (NULL == Tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)NULL))) {
|
||||
binaryMode = 0;
|
||||
}
|
||||
} else {
|
||||
@@ -6010,7 +6002,7 @@ DoReadChars(
|
||||
}
|
||||
ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF);
|
||||
statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
|
||||
for (copied = 0; toRead > 0 || toRead == TCL_INDEX_NONE; ) {
|
||||
for (copied = 0; toRead != 0 ; ) {
|
||||
int copiedNow = -1;
|
||||
if (statePtr->inQueueHead != NULL) {
|
||||
if (binaryMode) {
|
||||
@@ -6020,7 +6012,7 @@ DoReadChars(
|
||||
}
|
||||
|
||||
/*
|
||||
* If the current buffer is empty recycle it.
|
||||
* Recycle current buffer if empty.
|
||||
*/
|
||||
|
||||
bufPtr = statePtr->inQueueHead;
|
||||
@@ -6044,6 +6036,7 @@ DoReadChars(
|
||||
if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)
|
||||
&& !GotFlag(statePtr, CHANNEL_STICKY_EOF)
|
||||
&& (!GotFlag(statePtr, CHANNEL_NONBLOCKING))) {
|
||||
copied = -1;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
@@ -6123,6 +6116,9 @@ finish:
|
||||
copied = -1;
|
||||
}
|
||||
TclChannelRelease((Tcl_Channel)chanPtr);
|
||||
if (copied == TCL_INDEX_NONE) {
|
||||
ResetFlag(statePtr, CHANNEL_ENCODING_ERROR|CHANNEL_EOF);
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
@@ -7985,7 +7981,7 @@ Tcl_GetChannelOption(
|
||||
Tcl_DStringAppendElement(dsPtr, "-profile");
|
||||
}
|
||||
/* Note currently input and output profiles are same */
|
||||
profile = CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags);
|
||||
profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags);
|
||||
profileName = TclEncodingProfileIdToName(interp, profile);
|
||||
if (profileName == NULL) {
|
||||
return TCL_ERROR;
|
||||
@@ -8180,11 +8176,11 @@ Tcl_SetChannelOption(
|
||||
|
||||
if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) {
|
||||
encoding = Tcl_GetEncoding(NULL, "iso8859-1");
|
||||
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags
|
||||
,CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags)
|
||||
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags
|
||||
,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags)
|
||||
|TCL_ENCODING_PROFILE_STRICT);
|
||||
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags
|
||||
,CHANNEL_PROFILE_GET(statePtr->outputEncodingFlags)
|
||||
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags
|
||||
,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags)
|
||||
|TCL_ENCODING_PROFILE_STRICT);
|
||||
} else {
|
||||
encoding = Tcl_GetEncoding(interp, newValue);
|
||||
@@ -8207,12 +8203,12 @@ Tcl_SetChannelOption(
|
||||
Tcl_FreeEncoding(statePtr->encoding);
|
||||
statePtr->encoding = encoding;
|
||||
statePtr->inputEncodingState = NULL;
|
||||
profile = CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags);
|
||||
profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags);
|
||||
statePtr->inputEncodingFlags = TCL_ENCODING_START;
|
||||
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags, profile);
|
||||
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, profile);
|
||||
statePtr->outputEncodingState = NULL;
|
||||
statePtr->outputEncodingFlags = TCL_ENCODING_START;
|
||||
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags, profile); /* Same as input */
|
||||
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags, profile); /* Same as input */
|
||||
ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA|CHANNEL_ENCODING_ERROR);
|
||||
UpdateInterest(chanPtr);
|
||||
return TCL_OK;
|
||||
@@ -8229,7 +8225,7 @@ Tcl_SetChannelOption(
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"bad value for -eofchar: must be non-NUL ASCII"
|
||||
" character", -1));
|
||||
" character", TCL_INDEX_NONE));
|
||||
}
|
||||
Tcl_Free((void *)argv);
|
||||
return TCL_ERROR;
|
||||
@@ -8255,8 +8251,8 @@ Tcl_SetChannelOption(
|
||||
if (TclEncodingProfileNameToId(interp, newValue, &profile) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags, profile);
|
||||
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags, profile);
|
||||
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, profile);
|
||||
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags, profile);
|
||||
ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA|CHANNEL_ENCODING_ERROR);
|
||||
return TCL_OK;
|
||||
} else if (HaveOpt(1, "-translation")) {
|
||||
@@ -8294,11 +8290,11 @@ Tcl_SetChannelOption(
|
||||
statePtr->inEofChar = 0;
|
||||
Tcl_FreeEncoding(statePtr->encoding);
|
||||
statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1");
|
||||
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags
|
||||
,CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags)
|
||||
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags
|
||||
,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags)
|
||||
|TCL_ENCODING_PROFILE_STRICT);
|
||||
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags
|
||||
,CHANNEL_PROFILE_GET(statePtr->outputEncodingFlags)
|
||||
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags
|
||||
,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags)
|
||||
|TCL_ENCODING_PROFILE_STRICT);
|
||||
} else if (strcmp(readMode, "lf") == 0) {
|
||||
translation = TCL_TRANSLATE_LF;
|
||||
@@ -8349,11 +8345,11 @@ Tcl_SetChannelOption(
|
||||
statePtr->outputTranslation = TCL_TRANSLATE_LF;
|
||||
Tcl_FreeEncoding(statePtr->encoding);
|
||||
statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1");
|
||||
CHANNEL_PROFILE_SET(statePtr->inputEncodingFlags
|
||||
,CHANNEL_PROFILE_GET(statePtr->inputEncodingFlags)
|
||||
ENCODING_PROFILE_SET(statePtr->inputEncodingFlags
|
||||
,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags)
|
||||
|TCL_ENCODING_PROFILE_STRICT);
|
||||
CHANNEL_PROFILE_SET(statePtr->outputEncodingFlags
|
||||
,CHANNEL_PROFILE_GET(statePtr->outputEncodingFlags)
|
||||
ENCODING_PROFILE_SET(statePtr->outputEncodingFlags
|
||||
,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags)
|
||||
|TCL_ENCODING_PROFILE_STRICT);
|
||||
} else if (strcmp(writeMode, "lf") == 0) {
|
||||
statePtr->outputTranslation = TCL_TRANSLATE_LF;
|
||||
@@ -10217,7 +10213,7 @@ DoRead(
|
||||
== (CHANNEL_EOF|CHANNEL_BLOCKED)));
|
||||
UpdateInterest(chanPtr);
|
||||
TclChannelRelease((Tcl_Channel)chanPtr);
|
||||
return (int)(p - dst);
|
||||
return (Tcl_Size)(p - dst);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -10280,8 +10276,8 @@ Lossless(
|
||||
(
|
||||
toRead == -1
|
||||
&& inStatePtr->encoding == outStatePtr->encoding
|
||||
&& CHANNEL_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
|
||||
&& CHANNEL_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
|
||||
&& ENCODING_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
|
||||
&& ENCODING_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -10654,7 +10650,7 @@ Tcl_IsChannelShared(
|
||||
ChannelState *statePtr = ((Channel *) chan)->state;
|
||||
/* State of real channel structure. */
|
||||
|
||||
return ((statePtr->refCount + 1 > 2) ? 1 : 0);
|
||||
return ((statePtr->refCount > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -288,13 +288,6 @@ typedef struct ChannelState {
|
||||
#define CHANNEL_CLOSEDWRITE (1<<21) /* Channel write side has been closed.
|
||||
* No further Tcl-level write IO on
|
||||
* the channel is allowed. */
|
||||
#define CHANNEL_PROFILE_MASK 0xFF000000
|
||||
#define CHANNEL_PROFILE_GET(flags_) ((flags_) & CHANNEL_PROFILE_MASK)
|
||||
#define CHANNEL_PROFILE_SET(flags_, profile_) \
|
||||
do { \
|
||||
(flags_) &= ~CHANNEL_PROFILE_MASK; \
|
||||
(flags_) |= profile_; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* The length of time to wait between synthetic timer events. Must be zero or
|
||||
|
||||
+17
-5
@@ -283,7 +283,7 @@ Tcl_GetsObjCmd(
|
||||
Tcl_Channel chan; /* The channel to read from. */
|
||||
Tcl_Size lineLen; /* Length of line just read. */
|
||||
int mode; /* Mode in which channel is opened. */
|
||||
Tcl_Obj *linePtr, *chanObjPtr;
|
||||
Tcl_Obj *linePtr, *chanObjPtr, *resultDictPtr, *returnOptsPtr;
|
||||
int code = TCL_OK;
|
||||
|
||||
if ((objc != 2) && (objc != 3)) {
|
||||
@@ -306,7 +306,6 @@ Tcl_GetsObjCmd(
|
||||
lineLen = Tcl_GetsObj(chan, linePtr);
|
||||
if (lineLen == TCL_IO_FAILURE) {
|
||||
if (!Tcl_Eof(chan) && !Tcl_InputBlocked(chan)) {
|
||||
Tcl_DecrRefCount(linePtr);
|
||||
|
||||
/*
|
||||
* TIP #219.
|
||||
@@ -320,7 +319,14 @@ Tcl_GetsObjCmd(
|
||||
"error reading \"%s\": %s",
|
||||
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
|
||||
}
|
||||
resultDictPtr = Tcl_NewDictObj();
|
||||
Tcl_DictObjPut(NULL, resultDictPtr, Tcl_NewStringObj("read", -1)
|
||||
, linePtr);
|
||||
returnOptsPtr = Tcl_NewDictObj();
|
||||
Tcl_DictObjPut(NULL, returnOptsPtr, Tcl_NewStringObj("-result", -1)
|
||||
, resultDictPtr);
|
||||
code = TCL_ERROR;
|
||||
Tcl_SetReturnOptions(interp, returnOptsPtr);
|
||||
goto done;
|
||||
}
|
||||
lineLen = TCL_IO_FAILURE;
|
||||
@@ -371,7 +377,7 @@ Tcl_ReadObjCmd(
|
||||
Tcl_WideInt toRead; /* How many bytes to read? */
|
||||
Tcl_Size charactersRead; /* How many characters were read? */
|
||||
int mode; /* Mode in which channel is opened. */
|
||||
Tcl_Obj *resultPtr, *chanObjPtr;
|
||||
Tcl_Obj *resultPtr, *resultDictPtr, *returnOptsPtr, *chanObjPtr;
|
||||
|
||||
if ((objc != 2) && (objc != 3)) {
|
||||
Interp *iPtr;
|
||||
@@ -433,7 +439,6 @@ Tcl_ReadObjCmd(
|
||||
TclChannelPreserve(chan);
|
||||
charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0);
|
||||
if (charactersRead == TCL_IO_FAILURE) {
|
||||
Tcl_DecrRefCount(resultPtr);
|
||||
/*
|
||||
* TIP #219.
|
||||
* Capture error messages put by the driver into the bypass area and
|
||||
@@ -446,7 +451,14 @@ Tcl_ReadObjCmd(
|
||||
"error reading \"%s\": %s",
|
||||
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
|
||||
}
|
||||
resultDictPtr = Tcl_NewDictObj();
|
||||
Tcl_DictObjPut(NULL, resultDictPtr, Tcl_NewStringObj("read", -1)
|
||||
, resultPtr);
|
||||
returnOptsPtr = Tcl_NewDictObj();
|
||||
Tcl_DictObjPut(NULL, returnOptsPtr, Tcl_NewStringObj("-result", -1)
|
||||
, resultDictPtr);
|
||||
TclChannelRelease(chan);
|
||||
Tcl_SetReturnOptions(interp, returnOptsPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1788,9 +1800,9 @@ ChanPendingObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Channel chan;
|
||||
int mode;
|
||||
static const char *const options[] = {"input", "output", NULL};
|
||||
enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT} index;
|
||||
int mode;
|
||||
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "mode channelId");
|
||||
|
||||
+12
-3
@@ -375,11 +375,15 @@ ExecuteCallback(
|
||||
* interpreters. */
|
||||
{
|
||||
Tcl_Obj *resObj; /* See below, switch (transmit). */
|
||||
size_t resLen = 0;
|
||||
Tcl_Size resLen = 0;
|
||||
unsigned char *resBuf;
|
||||
Tcl_InterpState state = NULL;
|
||||
int res = TCL_OK;
|
||||
Tcl_Obj *command = TclListObjCopy(NULL, dataPtr->command);
|
||||
Tcl_Obj *command = TclDuplicatePureObj(
|
||||
interp, dataPtr->command, &tclListType.objType);
|
||||
if (!command) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Interp *eval = dataPtr->interp;
|
||||
|
||||
Tcl_Preserve(eval);
|
||||
@@ -397,7 +401,12 @@ ExecuteCallback(
|
||||
}
|
||||
|
||||
Tcl_IncrRefCount(command);
|
||||
Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1));
|
||||
res = Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1));
|
||||
if (res != TCL_OK) {
|
||||
Tcl_DecrRefCount(command);
|
||||
Tcl_Release(eval);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use a byte-array to prevent the misinterpretation of binary data coming
|
||||
|
||||
+11
-4
@@ -580,6 +580,9 @@ TclChanCreateObjCmd(
|
||||
|
||||
rcId = NextHandle();
|
||||
rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);
|
||||
if (!rcPtr) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke 'initialize' and validate that the handler is present and ok.
|
||||
@@ -2258,8 +2261,10 @@ NewReflectedChannel(
|
||||
rcPtr->mode = mode;
|
||||
rcPtr->interest = 0; /* Initially no interest registered */
|
||||
|
||||
/* ASSERT: cmdpfxObj is a Tcl List */
|
||||
rcPtr->cmd = TclListObjCopy(NULL, cmdpfxObj);
|
||||
rcPtr->cmd = TclDuplicatePureObj(interp, cmdpfxObj, &tclListType.objType);
|
||||
if (!rcPtr->cmd) {
|
||||
return NULL;
|
||||
}
|
||||
Tcl_IncrRefCount(rcPtr->cmd);
|
||||
rcPtr->methods = Tcl_NewListObj(METH_WRITE + 1, NULL);
|
||||
while (mn <= (int)METH_WRITE) {
|
||||
@@ -2396,8 +2401,10 @@ InvokeTclMethod(
|
||||
* before the channel id.
|
||||
*/
|
||||
|
||||
cmd = TclListObjCopy(NULL, rcPtr->cmd);
|
||||
|
||||
cmd = TclDuplicatePureObj(NULL, rcPtr->cmd, &tclListType.objType);
|
||||
if (!cmd) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_ListObjIndex(NULL, rcPtr->methods, method, &methObj);
|
||||
Tcl_ListObjAppendElement(NULL, cmd, methObj);
|
||||
Tcl_ListObjAppendElement(NULL, cmd, rcPtr->name);
|
||||
|
||||
@@ -264,7 +264,7 @@ struct ForwardParamTransform {
|
||||
ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
|
||||
char *buf; /* I: Bytes to transform,
|
||||
* O: Bytes in transform result */
|
||||
size_t size; /* I: #bytes to transform,
|
||||
Tcl_Size size; /* I: #bytes to transform,
|
||||
* O: #bytes in the transform result */
|
||||
};
|
||||
struct ForwardParamLimit {
|
||||
@@ -2562,7 +2562,7 @@ ForwardProc(
|
||||
* Sent it back to the request originator.
|
||||
*/
|
||||
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev;
|
||||
/* Array of returned bytes */
|
||||
|
||||
@@ -2596,7 +2596,7 @@ ForwardProc(
|
||||
* Sent it back to the request originator.
|
||||
*/
|
||||
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev;
|
||||
/* Array of returned bytes */
|
||||
|
||||
@@ -2626,7 +2626,7 @@ ForwardProc(
|
||||
* Sent it back to the request originator.
|
||||
*/
|
||||
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev; /* Array of returned bytes */
|
||||
|
||||
bytev = Tcl_GetByteArrayFromObj(resObj, &bytec);
|
||||
@@ -2652,7 +2652,7 @@ ForwardProc(
|
||||
* Sent it back to the request originator.
|
||||
*/
|
||||
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev;
|
||||
/* Array of returned bytes */
|
||||
|
||||
@@ -3045,7 +3045,7 @@ TransformRead(
|
||||
Tcl_Obj *bufObj)
|
||||
{
|
||||
Tcl_Obj *resObj;
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev; /* Array of returned bytes */
|
||||
|
||||
/*
|
||||
@@ -3100,7 +3100,7 @@ TransformWrite(
|
||||
{
|
||||
Tcl_Obj *bufObj;
|
||||
Tcl_Obj *resObj;
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev; /* Array of returned bytes */
|
||||
int res;
|
||||
|
||||
@@ -3167,7 +3167,7 @@ TransformDrain(
|
||||
int *errorCodePtr)
|
||||
{
|
||||
Tcl_Obj *resObj;
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev; /* Array of returned bytes */
|
||||
|
||||
/*
|
||||
@@ -3216,7 +3216,7 @@ TransformFlush(
|
||||
int op)
|
||||
{
|
||||
Tcl_Obj *resObj;
|
||||
size_t bytec = 0; /* Number of returned bytes */
|
||||
Tcl_Size bytec = 0; /* Number of returned bytes */
|
||||
unsigned char *bytev; /* Array of returned bytes */
|
||||
int res;
|
||||
|
||||
|
||||
@@ -1734,6 +1734,11 @@ Tcl_FSEvalFileEx(
|
||||
Tcl_CloseEx(interp,chan,0);
|
||||
return result;
|
||||
}
|
||||
if (Tcl_SetChannelOption(interp, chan, "-profile", "strict")
|
||||
!= TCL_OK) {
|
||||
Tcl_CloseEx(interp,chan,0);
|
||||
return result;
|
||||
}
|
||||
|
||||
TclNewObj(objPtr);
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
|
||||
@@ -537,7 +537,7 @@ declare 214 {
|
||||
void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding)
|
||||
}
|
||||
declare 215 {
|
||||
void *TclStackAlloc(Tcl_Interp *interp, Tcl_Size numBytes)
|
||||
void *TclStackAlloc(Tcl_Interp *interp, TCL_HASH_TYPE numBytes)
|
||||
}
|
||||
declare 216 {
|
||||
void TclStackFree(Tcl_Interp *interp, void *freePtr)
|
||||
|
||||
+122
-29
@@ -104,12 +104,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum *signed* value that can be stored in a Tcl_Size type. This is
|
||||
* primarily used for checking overflows in dynamically allocating memory.
|
||||
*/
|
||||
#define TCL_SIZE_SMAX ((((Tcl_Size) 1) << ((8*(Tcl_Size)sizeof(Tcl_Size)) - 1)) - 1)
|
||||
|
||||
/*
|
||||
* Macros used to cast between pointers and integers (e.g. when storing an int
|
||||
* in ClientData), on 64-bit architectures they avoid gcc warning about "cast
|
||||
@@ -2451,16 +2445,6 @@ typedef enum TclEolTranslation {
|
||||
#define TCL_INVOKE_NO_UNKNOWN (1<<1)
|
||||
#define TCL_INVOKE_NO_TRACEBACK (1<<2)
|
||||
|
||||
#if TCL_MAJOR_VERSION > 8
|
||||
/*
|
||||
* SSIZE_MAX, NOT SIZE_MAX as negative differences need to be expressed
|
||||
* between values of the Tcl_Size type so limit the range to signed
|
||||
*/
|
||||
# define ListSizeT_MAX ((Tcl_Size)PTRDIFF_MAX)
|
||||
#else
|
||||
# define ListSizeT_MAX INT_MAX
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ListStore --
|
||||
*
|
||||
@@ -2501,7 +2485,8 @@ typedef struct ListStore {
|
||||
|
||||
/* Max number of elements that can be contained in a list */
|
||||
#define LIST_MAX \
|
||||
((Tcl_Size)((ListSizeT_MAX - offsetof(ListStore, slots)) / sizeof(Tcl_Obj *)))
|
||||
((Tcl_Size)(((size_t)TCL_SIZE_MAX - offsetof(ListStore, slots)) \
|
||||
/ sizeof(Tcl_Obj *)))
|
||||
/* Memory size needed for a ListStore to hold numSlots_ elements */
|
||||
#define LIST_SIZE(numSlots_) \
|
||||
((Tcl_Size)(offsetof(ListStore, slots) + ((numSlots_) * sizeof(Tcl_Obj *))))
|
||||
@@ -2513,7 +2498,7 @@ typedef struct ListStore {
|
||||
typedef struct ListSpan {
|
||||
Tcl_Size spanStart; /* Starting index of the span */
|
||||
Tcl_Size spanLength; /* Number of elements in the span */
|
||||
Tcl_Size refCount; /* Count of references to this span record */
|
||||
size_t refCount; /* Count of references to this span record */
|
||||
} ListSpan;
|
||||
#ifndef LIST_SPAN_THRESHOLD /* May be set on build line */
|
||||
#define LIST_SPAN_THRESHOLD 101
|
||||
@@ -2593,6 +2578,7 @@ typedef struct ListRep {
|
||||
(((objv_) = &ListObjStorePtr(listObj_)->slots[ListObjStart(listObj_)]), \
|
||||
(ListObjLength(listObj_, (objc_))))
|
||||
|
||||
|
||||
/*
|
||||
* Returns 1/0 whether the internal representation (not the Tcl_Obj itself)
|
||||
* is shared. Note by intent this only checks for sharing of ListStore,
|
||||
@@ -2864,6 +2850,91 @@ typedef struct ProcessGlobalValue {
|
||||
#define TCL_PARSE_NO_UNDERSCORE 128
|
||||
/* Reject underscore digit separator */
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* Internal convenience macros for manipulating encoding flags. See
|
||||
* TCL_ENCODING_PROFILE_* in tcl.h
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define ENCODING_PROFILE_MASK 0xFF000000
|
||||
#define ENCODING_PROFILE_GET(flags_) ((flags_) & ENCODING_PROFILE_MASK)
|
||||
#define ENCODING_PROFILE_SET(flags_, profile_) \
|
||||
do { \
|
||||
(flags_) &= ~ENCODING_PROFILE_MASK; \
|
||||
(flags_) |= profile_; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* Common functions for calculating overallocation. Trivial but allows for
|
||||
* experimenting with growth factors without having to change code in
|
||||
* multiple places. See TclAttemptAllocElemsEx and similar for usage
|
||||
* examples. Best to use those functions. Direct use of TclUpsizeAlloc /
|
||||
* TclResizeAlloc is needed in special cases such as when total size of
|
||||
* memory block is limited to less than TCL_SIZE_MAX.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static inline Tcl_Size
|
||||
TclUpsizeAlloc(TCL_UNUSED(Tcl_Size) /* oldSize. For future experiments with
|
||||
* some growth algorithms that use this
|
||||
* information. */,
|
||||
Tcl_Size needed,
|
||||
Tcl_Size limit)
|
||||
{
|
||||
/* assert (oldCapacity < needed <= limit) */
|
||||
if (needed < (limit - needed/2)) {
|
||||
return needed + needed / 2;
|
||||
}
|
||||
else {
|
||||
return limit;
|
||||
}
|
||||
}
|
||||
static inline Tcl_Size TclUpsizeRetry(Tcl_Size needed, Tcl_Size lastAttempt) {
|
||||
/* assert (needed < lastAttempt) */
|
||||
if (needed < lastAttempt - 1) {
|
||||
/* (needed+lastAttempt)/2 but that formula may overflow Tcl_Size */
|
||||
return needed + (lastAttempt - needed) / 2;
|
||||
} else {
|
||||
return needed;
|
||||
}
|
||||
}
|
||||
MODULE_SCOPE void *TclAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize,
|
||||
Tcl_Size leadSize, Tcl_Size *capacityPtr);
|
||||
MODULE_SCOPE void *TclReallocElemsEx(void *oldPtr, Tcl_Size elemCount,
|
||||
Tcl_Size elemSize, Tcl_Size leadSize,
|
||||
Tcl_Size *capacityPtr);
|
||||
MODULE_SCOPE void *TclAttemptReallocElemsEx(void *oldPtr,
|
||||
Tcl_Size elemCount, Tcl_Size elemSize,
|
||||
Tcl_Size leadSize, Tcl_Size *capacityPtr);
|
||||
/* Alloc elemCount elements of size elemSize with leadSize header
|
||||
* returning actual capacity (in elements) in *capacityPtr. */
|
||||
static inline void *TclAttemptAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize,
|
||||
Tcl_Size leadSize, Tcl_Size *capacityPtr) {
|
||||
return TclAttemptReallocElemsEx(
|
||||
NULL, elemCount, elemSize, leadSize, capacityPtr);
|
||||
}
|
||||
/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */
|
||||
static inline void *TclAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr) {
|
||||
return TclAllocElemsEx(numBytes, 1, 0, capacityPtr);
|
||||
}
|
||||
/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */
|
||||
static inline void *
|
||||
TclAttemptAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr)
|
||||
{
|
||||
return TclAttemptAllocElemsEx(numBytes, 1, 0, capacityPtr);
|
||||
}
|
||||
/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */
|
||||
static inline void *TclReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) {
|
||||
return TclReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
|
||||
}
|
||||
/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */
|
||||
static inline void *TclAttemptReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) {
|
||||
return TclAttemptReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Variables shared among Tcl modules but not used by the outside world.
|
||||
@@ -3108,6 +3179,9 @@ MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp,
|
||||
Tcl_Namespace *ensembleNamespacePtr, int flags);
|
||||
MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr);
|
||||
MODULE_SCOPE void TclDeleteNamespaceChildren(Namespace *nsPtr);
|
||||
MODULE_SCOPE Tcl_Size TclDictGetSize(Tcl_Obj *dictPtr);
|
||||
MODULE_SCOPE Tcl_Obj* TclDuplicatePureObj(Tcl_Interp *interp,
|
||||
Tcl_Obj * objPtr, const Tcl_ObjType *typPtr);
|
||||
MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp,
|
||||
const char *dict, Tcl_Size dictLength,
|
||||
const char **elementPtr, const char **nextPtr,
|
||||
@@ -3234,10 +3308,10 @@ MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp,
|
||||
Tcl_Obj *listPtr, Tcl_Obj *argPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
Tcl_Size indexCount, Tcl_Obj *const indexArray[]);
|
||||
MODULE_SCOPE Tcl_Obj * TclListObjGetElement(Tcl_Obj *listObj, Tcl_Size index);
|
||||
/* TIP #280 */
|
||||
MODULE_SCOPE void TclListLines(Tcl_Obj *listObj, Tcl_Size line, int n,
|
||||
int *lines, Tcl_Obj *const *elems);
|
||||
MODULE_SCOPE Tcl_Obj * TclListObjCopy(Tcl_Interp *interp, Tcl_Obj *listPtr);
|
||||
MODULE_SCOPE int TclListObjAppendElements(Tcl_Interp *interp,
|
||||
Tcl_Obj *toObj, Tcl_Size elemCount,
|
||||
Tcl_Obj *const elemObjv[]);
|
||||
@@ -3280,6 +3354,7 @@ MODULE_SCOPE void TclParseInit(Tcl_Interp *interp, const char *string,
|
||||
MODULE_SCOPE Tcl_Size TclParseAllWhiteSpace(const char *src, Tcl_Size numBytes);
|
||||
MODULE_SCOPE int TclProcessReturn(Tcl_Interp *interp,
|
||||
int code, int level, Tcl_Obj *returnOpts);
|
||||
MODULE_SCOPE void TclUndoRefCount(Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE int TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
|
||||
MODULE_SCOPE Tcl_Obj * TclpTempFileName(void);
|
||||
MODULE_SCOPE Tcl_Obj * TclpTempFileNameForLibrary(Tcl_Interp *interp,
|
||||
@@ -3311,7 +3386,7 @@ MODULE_SCOPE int TclCreateSocketAddress(Tcl_Interp *interp,
|
||||
const char **errorMsgPtr);
|
||||
MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr,
|
||||
Tcl_ThreadCreateProc *proc, void *clientData,
|
||||
size_t stackSize, int flags);
|
||||
TCL_HASH_TYPE stackSize, int flags);
|
||||
MODULE_SCOPE Tcl_Size TclpFindVariable(const char *name, Tcl_Size *lengthPtr);
|
||||
MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr,
|
||||
TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr);
|
||||
@@ -3380,13 +3455,13 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp,
|
||||
Tcl_Obj *const *objv, Tcl_Size objc, Tcl_Size subIdx,
|
||||
Tcl_Obj *bad, Tcl_Obj *fix);
|
||||
MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
|
||||
Tcl_Size numBytes);
|
||||
TCL_HASH_TYPE 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, Tcl_Size reqlength);
|
||||
MODULE_SCOPE int TclStringCmpOpts(Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[], int *nocase,
|
||||
int *reqlength);
|
||||
Tcl_Size *reqlength);
|
||||
MODULE_SCOPE int TclStringMatch(const char *str, Tcl_Size strLen,
|
||||
const char *pattern, int ptnLen, int flags);
|
||||
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
|
||||
@@ -4173,6 +4248,12 @@ MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
MODULE_SCOPE Tcl_Size TclIndexDecode(int encoded, Tcl_Size endValue);
|
||||
MODULE_SCOPE int TclIndexInvalidError(Tcl_Interp *interp,
|
||||
const char *idxType, Tcl_Size idx);
|
||||
|
||||
/*
|
||||
* Error message utility functions
|
||||
*/
|
||||
MODULE_SCOPE int TclCommandWordLimitError(Tcl_Interp *interp, Tcl_Size count);
|
||||
|
||||
#endif /* TCL_MAJOR_VERSION > 8 */
|
||||
|
||||
/* Constants used in index value encoding routines. */
|
||||
@@ -4456,15 +4537,12 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
# define TclDecrRefCount(objPtr) \
|
||||
Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
|
||||
|
||||
# define TclNewListObjDirect(objc, objv) \
|
||||
TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)
|
||||
|
||||
#undef USE_THREAD_ALLOC
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Macro used by the Tcl core to set a Tcl_Obj's string representation to a
|
||||
* Macros used by the Tcl core to set a Tcl_Obj's string representation to a
|
||||
* copy of the "len" bytes starting at "bytePtr". The value of "len" must
|
||||
* not be negative. When "len" is 0, then it is acceptable to pass
|
||||
* "bytePtr" = NULL. When "len" > 0, "bytePtr" must not be NULL, and it
|
||||
@@ -4477,17 +4555,22 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
* Because "len" is referenced multiple times, take care that it is an
|
||||
* expression with the same value each use.
|
||||
*
|
||||
* The ANSI C "prototype" for this macro is:
|
||||
* The ANSI C "prototypes" for these macros are:
|
||||
*
|
||||
* MODULE_SCOPE void TclInitEmptyStringRep(Tcl_Obj *objPtr);
|
||||
* MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
|
||||
* MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
|
||||
*
|
||||
*----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define TclInitEmptyStringRep(objPtr) \
|
||||
((objPtr)->length = (((objPtr)->bytes = &tclEmptyString), 0))
|
||||
|
||||
|
||||
#define TclInitStringRep(objPtr, bytePtr, len) \
|
||||
if ((len) == 0) { \
|
||||
(objPtr)->bytes = &tclEmptyString; \
|
||||
(objPtr)->length = 0; \
|
||||
TclInitEmptyStringRep(objPtr); \
|
||||
} else { \
|
||||
(objPtr)->bytes = (char *)Tcl_Alloc((len) + 1U); \
|
||||
memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)); \
|
||||
@@ -4495,6 +4578,16 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
(objPtr)->length = (len); \
|
||||
}
|
||||
|
||||
#define TclAttemptInitStringRep(objPtr, bytePtr, len) \
|
||||
((((len) == 0) ? ( \
|
||||
TclInitEmptyStringRep(objPtr) \
|
||||
) : ( \
|
||||
(objPtr)->bytes = (char *)Tcl_AttemptAlloc((len) + 1U), \
|
||||
(objPtr)->length = ((objPtr)->bytes) ? \
|
||||
(memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)), \
|
||||
(objPtr)->bytes[len] = '\0', (len)) : (-1) \
|
||||
)), (objPtr)->bytes)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Macro used by the Tcl core to get the string representation's byte array
|
||||
|
||||
@@ -451,7 +451,8 @@ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void);
|
||||
EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name,
|
||||
Tcl_Encoding encoding);
|
||||
/* 215 */
|
||||
EXTERN void * TclStackAlloc(Tcl_Interp *interp, Tcl_Size numBytes);
|
||||
EXTERN void * TclStackAlloc(Tcl_Interp *interp,
|
||||
TCL_HASH_TYPE numBytes);
|
||||
/* 216 */
|
||||
EXTERN void TclStackFree(Tcl_Interp *interp, void *freePtr);
|
||||
/* 217 */
|
||||
@@ -803,7 +804,7 @@ typedef struct TclIntStubs {
|
||||
void (*tclpFindExecutable) (const char *argv0); /* 212 */
|
||||
Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */
|
||||
void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */
|
||||
void * (*tclStackAlloc) (Tcl_Interp *interp, Tcl_Size numBytes); /* 215 */
|
||||
void * (*tclStackAlloc) (Tcl_Interp *interp, TCL_HASH_TYPE numBytes); /* 215 */
|
||||
void (*tclStackFree) (Tcl_Interp *interp, void *freePtr); /* 216 */
|
||||
int (*tclPushStackFrame) (Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 217 */
|
||||
void (*tclPopStackFrame) (Tcl_Interp *interp); /* 218 */
|
||||
|
||||
+190
-196
@@ -40,7 +40,7 @@
|
||||
|
||||
#ifdef ENABLE_LIST_ASSERTS
|
||||
|
||||
#define LIST_ASSERT(cond_) assert(cond_) /* TODO - is there a Tcl-specific one? */
|
||||
#define LIST_ASSERT(cond_) assert(cond_)
|
||||
/*
|
||||
* LIST_INDEX_ASSERT is to catch errors with negative indices and counts
|
||||
* being passed AFTER validation. On Tcl9 length types are unsigned hence
|
||||
@@ -69,8 +69,7 @@
|
||||
|
||||
/* Checks for when caller should have already converted to internal list type */
|
||||
#define LIST_ASSERT_TYPE(listObj_) \
|
||||
LIST_ASSERT((listObj_)->typePtr == &tclListType.objType);
|
||||
|
||||
LIST_ASSERT(TclHasInternalRep((listObj_), &tclListType.objType))
|
||||
|
||||
/*
|
||||
* If ENABLE_LIST_INVARIANTS is enabled (-DENABLE_LIST_INVARIANTS from the
|
||||
@@ -305,12 +304,12 @@ ListSpanMerited(
|
||||
Tcl_Size allocatedStorageLength) /* Length of the currently allocation */
|
||||
{
|
||||
/*
|
||||
TODO
|
||||
- heuristics thresholds need to be determined
|
||||
- currently, information about the sharing (ref count) of existing
|
||||
storage is not passed. Perhaps it should be. For example if the
|
||||
existing storage has a "large" ref count, then it might make sense
|
||||
to do even a small span.
|
||||
* Possible optimizations for future consideration
|
||||
* - heuristic LIST_SPAN_THRESHOLD
|
||||
* - currently, information about the sharing (ref count) of existing
|
||||
* storage is not passed. Perhaps it should be. For example if the
|
||||
* existing storage has a "large" ref count, then it might make sense
|
||||
* to do even a small span.
|
||||
*/
|
||||
|
||||
if (length < LIST_SPAN_THRESHOLD) {
|
||||
@@ -326,30 +325,6 @@ ListSpanMerited(
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
* ListStoreUpSize --
|
||||
*
|
||||
* For reasons of efficiency, extra space is allocated for a ListStore
|
||||
* compared to what was requested. This function calculates how many
|
||||
* slots should actually be allocated for a given request size.
|
||||
*
|
||||
* Results:
|
||||
* Number of slots to allocate.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
static inline Tcl_Size
|
||||
ListStoreUpSize(Tcl_Size numSlotsRequested) {
|
||||
/* TODO -how much extra? May be double only for smaller requests? */
|
||||
return numSlotsRequested < (LIST_MAX / 2) ? 2 * numSlotsRequested
|
||||
: LIST_MAX;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
@@ -770,21 +745,21 @@ ListStoreNew(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
storePtr = NULL;
|
||||
if (flags & LISTREP_SPACE_FLAGS) {
|
||||
capacity = ListStoreUpSize(objc);
|
||||
/* Caller requests extra space front, back or both */
|
||||
storePtr = (ListStore *)TclAttemptAllocElemsEx(
|
||||
objc, sizeof(Tcl_Obj *), offsetof(ListStore, slots), &capacity);
|
||||
} else {
|
||||
/* Exact allocation */
|
||||
capacity = objc;
|
||||
}
|
||||
|
||||
storePtr = (ListStore *)Tcl_AttemptAlloc(LIST_SIZE(capacity));
|
||||
if (storePtr == NULL && capacity != objc) {
|
||||
capacity = objc; /* Try allocating exact size */
|
||||
storePtr = (ListStore *)Tcl_AttemptAlloc(LIST_SIZE(capacity));
|
||||
}
|
||||
if (storePtr == NULL) {
|
||||
if (flags & LISTREP_PANIC_ON_FAIL) {
|
||||
Tcl_Panic("list creation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes",
|
||||
LIST_SIZE(objc));
|
||||
Tcl_Panic("list creation failed: unable to alloc %" TCL_Z_MODIFIER
|
||||
"u bytes",
|
||||
LIST_SIZE(objc));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -827,7 +802,8 @@ ListStoreNew(
|
||||
*
|
||||
* ListStoreReallocate --
|
||||
*
|
||||
* Reallocates the memory for a ListStore.
|
||||
* Reallocates the memory for a ListStore allocating extra for
|
||||
* possible future growth.
|
||||
*
|
||||
* Results:
|
||||
* Pointer to the ListStore which may be the same as storePtr or pointer
|
||||
@@ -842,26 +818,25 @@ ListStoreNew(
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
ListStore *
|
||||
ListStoreReallocate (ListStore *storePtr, Tcl_Size numSlots)
|
||||
ListStoreReallocate (ListStore *storePtr, Tcl_Size needed)
|
||||
{
|
||||
Tcl_Size newCapacity;
|
||||
ListStore *newStorePtr;
|
||||
Tcl_Size capacity;
|
||||
|
||||
newCapacity = ListStoreUpSize(numSlots);
|
||||
newStorePtr =
|
||||
(ListStore *)Tcl_AttemptRealloc(storePtr, LIST_SIZE(newCapacity));
|
||||
if (newStorePtr == NULL) {
|
||||
newCapacity = numSlots;
|
||||
newStorePtr = (ListStore *)Tcl_AttemptRealloc(storePtr,
|
||||
LIST_SIZE(newCapacity));
|
||||
if (newStorePtr == NULL)
|
||||
return NULL;
|
||||
if (needed > LIST_MAX) {
|
||||
return NULL;
|
||||
}
|
||||
storePtr = (ListStore *)TclAttemptReallocElemsEx(storePtr,
|
||||
needed,
|
||||
sizeof(Tcl_Obj *),
|
||||
offsetof(ListStore, slots),
|
||||
&capacity);
|
||||
/* Only the capacity has changed, fix it in the header */
|
||||
newStorePtr->numAllocated = newCapacity;
|
||||
return newStorePtr;
|
||||
if (storePtr) {
|
||||
storePtr->numAllocated = capacity;
|
||||
}
|
||||
return storePtr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1341,50 +1316,6 @@ 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclListObjCopy(
|
||||
Tcl_Interp *interp, /* Used to report errors if not NULL. */
|
||||
Tcl_Obj *listObj) /* List object for which an element array is
|
||||
* to be returned. */
|
||||
{
|
||||
Tcl_Obj *copyObj;
|
||||
|
||||
if (!TclHasInternalRep(listObj, &tclListType.objType)) {
|
||||
if (TclHasInternalRep(listObj,&tclArithSeriesType.objType)) {
|
||||
return TclArithSeriesObjCopy(interp, listObj);
|
||||
}
|
||||
if (SetListFromAny(interp, listObj) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TclNewObj(copyObj);
|
||||
TclInvalidateStringRep(copyObj);
|
||||
DupListInternalRep(listObj, copyObj);
|
||||
return copyObj;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
@@ -1625,6 +1556,29 @@ TclListObjRange(
|
||||
return listObj;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclListObjGetElement --
|
||||
*
|
||||
* Returns a single element from the array of the elements in a list
|
||||
* object, without doing doing any bounds checking. Caller must ensure
|
||||
* that ObjPtr of of type 'tclListType' and that index is valid for the
|
||||
* list.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclListObjGetElement(
|
||||
Tcl_Obj *objPtr, /* List object for which an element array is
|
||||
* to be returned. */
|
||||
Tcl_Size index
|
||||
)
|
||||
{
|
||||
return ListObjStorePtr(objPtr)->slots[ListObjStart(objPtr) + index];
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1948,19 +1902,18 @@ int
|
||||
Tcl_ListObjIndex(
|
||||
Tcl_Interp *interp, /* Used to report errors if not NULL. */
|
||||
Tcl_Obj *listObj, /* List object to index into. */
|
||||
Tcl_Size index, /* Index of element to return. */
|
||||
Tcl_Size index, /* Index of element to return. */
|
||||
Tcl_Obj **objPtrPtr) /* The resulting Tcl_Obj* is stored here. */
|
||||
{
|
||||
Tcl_Obj **elemObjs;
|
||||
Tcl_Size numElems;
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* Unlike the original list code, this does not optimize for lindex'ing
|
||||
* an empty string when the internal rep is not already a list. On the
|
||||
* other hand, this code will be faster for the case where the object
|
||||
* is currently a dict. Benchmark the two cases.
|
||||
*/
|
||||
/* Empty string => empty list. Avoid unnecessary shimmering */
|
||||
if (listObj->bytes == &tclEmptyString) {
|
||||
*objPtrPtr = NULL;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (TclListObjGetElementsM(interp, listObj, &numElems, &elemObjs)
|
||||
!= TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
@@ -2005,19 +1958,19 @@ Tcl_ListObjLength(
|
||||
{
|
||||
ListRep listRep;
|
||||
|
||||
/* Empty string => empty list. Avoid unnecessary shimmering */
|
||||
if (listObj->bytes == &tclEmptyString) {
|
||||
*lenPtr = 0;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
Tcl_Size (*lengthProc)(Tcl_Obj *obj) = ABSTRACTLIST_PROC(listObj, lengthProc);
|
||||
if (lengthProc) {
|
||||
*lenPtr = lengthProc(listObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* Unlike the original list code, this does not optimize for lindex'ing
|
||||
* an empty string when the internal rep is not already a list. On the
|
||||
* other hand, this code will be faster for the case where the object
|
||||
* is currently a dict. Benchmark the two cases.
|
||||
*/
|
||||
|
||||
if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2025,7 +1978,7 @@ Tcl_ListObjLength(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
Tcl_Size
|
||||
Tcl_Size
|
||||
ListLength(Tcl_Obj *listPtr)
|
||||
{
|
||||
ListRep listRep;
|
||||
@@ -2082,12 +2035,12 @@ Tcl_ListObjReplace(
|
||||
{
|
||||
ListRep listRep;
|
||||
Tcl_Size origListLen;
|
||||
ptrdiff_t lenChange;
|
||||
ptrdiff_t leadSegmentLen;
|
||||
ptrdiff_t tailSegmentLen;
|
||||
Tcl_Size lenChange;
|
||||
Tcl_Size leadSegmentLen;
|
||||
Tcl_Size tailSegmentLen;
|
||||
Tcl_Size numFreeSlots;
|
||||
ptrdiff_t leadShift;
|
||||
ptrdiff_t tailShift;
|
||||
Tcl_Size leadShift;
|
||||
Tcl_Size tailShift;
|
||||
Tcl_Obj **listObjs;
|
||||
int favor;
|
||||
|
||||
@@ -2098,8 +2051,6 @@ Tcl_ListObjReplace(
|
||||
if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK)
|
||||
return TCL_ERROR; /* Cannot be converted to a list */
|
||||
|
||||
/* TODO - will need modification if Tcl9 sticks to unsigned indices */
|
||||
|
||||
/* Make limits sane */
|
||||
origListLen = ListRepLength(&listRep);
|
||||
if (first < 0) {
|
||||
@@ -2110,12 +2061,12 @@ Tcl_ListObjReplace(
|
||||
}
|
||||
if (numToDelete < 0) {
|
||||
numToDelete = 0;
|
||||
} else if (first > ListSizeT_MAX - numToDelete /* Handle integer overflow */
|
||||
} else if (first > LIST_MAX - numToDelete /* Handle integer overflow */
|
||||
|| origListLen < first + numToDelete) {
|
||||
numToDelete = origListLen - first;
|
||||
}
|
||||
|
||||
if (numToInsert > ListSizeT_MAX - (origListLen - numToDelete)) {
|
||||
if (numToInsert > LIST_MAX - (origListLen - numToDelete)) {
|
||||
return ListLimitExceededError(interp);
|
||||
}
|
||||
|
||||
@@ -2248,7 +2199,7 @@ Tcl_ListObjReplace(
|
||||
* be an explicit alloc and memmove which would let us redistribute
|
||||
* free space.
|
||||
*/
|
||||
if ((ptrdiff_t)numFreeSlots < lenChange && !ListRepIsShared(&listRep)) {
|
||||
if (numFreeSlots < lenChange && !ListRepIsShared(&listRep)) {
|
||||
/* T:listrep-1.{1,3,14,18,21},3.{3,10,11,14,27,32,41} */
|
||||
ListStore *newStorePtr =
|
||||
ListStoreReallocate(listRep.storePtr, origListLen + lenChange);
|
||||
@@ -2275,7 +2226,7 @@ Tcl_ListObjReplace(
|
||||
* TODO - for unshared case ONLY, consider a "move" based implementation
|
||||
*/
|
||||
if (ListRepIsShared(&listRep) || /* 3a */
|
||||
(ptrdiff_t)numFreeSlots < lenChange || /* 3b */
|
||||
numFreeSlots < lenChange || /* 3b */
|
||||
(origListLen + lenChange) < (listRep.storePtr->numAllocated / 4) /* 3c */
|
||||
) {
|
||||
ListRep newRep;
|
||||
@@ -2390,9 +2341,9 @@ Tcl_ListObjReplace(
|
||||
* or need to shift both. In the former case, favor shifting the
|
||||
* smaller segment.
|
||||
*/
|
||||
ptrdiff_t leadSpace = ListRepNumFreeHead(&listRep);
|
||||
ptrdiff_t tailSpace = ListRepNumFreeTail(&listRep);
|
||||
ptrdiff_t finalFreeSpace = leadSpace + tailSpace - lenChange;
|
||||
Tcl_Size leadSpace = ListRepNumFreeHead(&listRep);
|
||||
Tcl_Size tailSpace = ListRepNumFreeTail(&listRep);
|
||||
Tcl_Size finalFreeSpace = leadSpace + tailSpace - lenChange;
|
||||
|
||||
LIST_ASSERT((leadSpace + tailSpace) >= lenChange);
|
||||
if (leadSpace >= lenChange
|
||||
@@ -2409,7 +2360,7 @@ Tcl_ListObjReplace(
|
||||
* insertions.
|
||||
*/
|
||||
if (finalFreeSpace > 1 && (tailSpace == 0 || tailSegmentLen == 0)) {
|
||||
ptrdiff_t postShiftLeadSpace = leadSpace - lenChange;
|
||||
Tcl_Size postShiftLeadSpace = leadSpace - lenChange;
|
||||
if (postShiftLeadSpace > (finalFreeSpace/2)) {
|
||||
Tcl_Size extraShift = postShiftLeadSpace - (finalFreeSpace / 2);
|
||||
leadShift -= extraShift;
|
||||
@@ -2426,7 +2377,7 @@ Tcl_ListObjReplace(
|
||||
* See comments above. This is analogous.
|
||||
*/
|
||||
if (finalFreeSpace > 1 && (leadSpace == 0 || leadSegmentLen == 0)) {
|
||||
ptrdiff_t postShiftTailSpace = tailSpace - lenChange;
|
||||
Tcl_Size postShiftTailSpace = tailSpace - lenChange;
|
||||
if (postShiftTailSpace > (finalFreeSpace/2)) {
|
||||
/* T:listrep-1.{1,3,14,18,21},3.{2,3,26,27} */
|
||||
Tcl_Size extraShift = postShiftTailSpace - (finalFreeSpace / 2);
|
||||
@@ -2568,6 +2519,7 @@ TclLindexList(
|
||||
Tcl_Obj *indexListCopy;
|
||||
Tcl_Obj **indexObjs;
|
||||
Tcl_Size numIndexObjs;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Determine whether argPtr designates a list or a single index. We have
|
||||
@@ -2576,7 +2528,7 @@ TclLindexList(
|
||||
* see TIP#22 and TIP#33 for the details.
|
||||
*/
|
||||
if (!TclHasInternalRep(argObj, &tclListType.objType)
|
||||
&& TclGetIntForIndexM(NULL, argObj, ListSizeT_MAX - 1, &index)
|
||||
&& TclGetIntForIndexM(NULL, argObj, TCL_SIZE_MAX - 1, &index)
|
||||
== TCL_OK) {
|
||||
/*
|
||||
* argPtr designates a single index.
|
||||
@@ -2585,28 +2537,37 @@ TclLindexList(
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we make a private copy of the index list argument to avoid any
|
||||
* shimmering issues that might invalidate the indices array below while
|
||||
* we are still using it. This is probably unnecessary. It does not appear
|
||||
* that any damaging shimmering is possible, and no test has been devised
|
||||
* to show any error when this private copy is not made. But it's cheap,
|
||||
* and it offers some future-proofing insurance in case the TclLindexFlat
|
||||
* implementation changes in some unexpected way, or some new form of
|
||||
* trace or callback permits things to happen that the current
|
||||
* implementation does not.
|
||||
* Make a private copy of the index list argument to keep the internal
|
||||
* representation of th indices array unchanged while it is in use. This
|
||||
* is probably unnecessary. It does not appear that any damaging change to
|
||||
* the internal representation is possible, and no test has been devised to
|
||||
* show any error when this private copy is not made, But it's cheap, and
|
||||
* it offers some future-proofing insurance in case the TclLindexFlat
|
||||
* implementation changes in some unexpected way, or some new form of trace
|
||||
* or callback permits things to happen that the current implementation
|
||||
* does not.
|
||||
*/
|
||||
|
||||
indexListCopy = TclListObjCopy(NULL, argObj);
|
||||
if (indexListCopy == NULL) {
|
||||
indexListCopy = TclDuplicatePureObj(interp, argObj, &tclListType.objType);
|
||||
if (!indexListCopy) {
|
||||
/*
|
||||
* The argument is neither an index nor a well-formed list.
|
||||
* Report the error via TclLindexFlat.
|
||||
* TODO - This is as original. why not directly return an error?
|
||||
* TODO - This is as original code. why not directly return an error?
|
||||
*/
|
||||
return TclLindexFlat(interp, listObj, 1, &argObj);
|
||||
}
|
||||
status = TclListObjGetElementsM(
|
||||
interp, indexListCopy, &numIndexObjs, &indexObjs);
|
||||
if (status != TCL_OK) {
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
/*
|
||||
* The argument is neither an index nor a well-formed list.
|
||||
* Report the error via TclLindexFlat.
|
||||
* TODO - This is as original code. why not directly return an error?
|
||||
*/
|
||||
return TclLindexFlat(interp, listObj, 1, &argObj);
|
||||
}
|
||||
|
||||
ListObjGetElements(indexListCopy, numIndexObjs, indexObjs);
|
||||
listObj = TclLindexFlat(interp, listObj, numIndexObjs, indexObjs);
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
return listObj;
|
||||
@@ -2645,6 +2606,7 @@ TclLindexFlat(
|
||||
Tcl_Obj *const indexArray[])/* Array of pointers to Tcl objects that
|
||||
* represent the indices in the list. */
|
||||
{
|
||||
int status;
|
||||
Tcl_Size i;
|
||||
|
||||
/* Handle ArithSeries as special case */
|
||||
@@ -2673,24 +2635,13 @@ TclLindexFlat(
|
||||
|
||||
for (i=0 ; i<indexCount && listObj ; i++) {
|
||||
Tcl_Size index, listLen = 0;
|
||||
Tcl_Obj **elemPtrs = NULL, *sublistCopy;
|
||||
Tcl_Obj **elemPtrs = NULL;
|
||||
|
||||
/*
|
||||
* Here we make a private copy of the current sublist, so we avoid any
|
||||
* shimmering issues that might invalidate the elemPtr array below
|
||||
* while we are still using it. See test lindex-8.4.
|
||||
*/
|
||||
|
||||
sublistCopy = TclListObjCopy(interp, listObj);
|
||||
Tcl_DecrRefCount(listObj);
|
||||
listObj = NULL;
|
||||
|
||||
if (sublistCopy == NULL) {
|
||||
/* The sublist is not a list at all => error. */
|
||||
break;
|
||||
status = Tcl_ListObjLength(interp, listObj, &listLen);
|
||||
if (status != TCL_OK) {
|
||||
Tcl_DecrRefCount(listObj);
|
||||
return NULL;
|
||||
}
|
||||
LIST_ASSERT_TYPE(sublistCopy);
|
||||
ListObjGetElements(sublistCopy, listLen, elemPtrs);
|
||||
|
||||
if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
|
||||
&index) == TCL_OK) {
|
||||
@@ -2702,22 +2653,45 @@ TclLindexFlat(
|
||||
|
||||
while (++i < indexCount) {
|
||||
if (TclGetIntForIndexM(
|
||||
interp, indexArray[i], ListSizeT_MAX - 1, &index)
|
||||
interp, indexArray[i], TCL_SIZE_MAX - 1, &index)
|
||||
!= TCL_OK) {
|
||||
Tcl_DecrRefCount(sublistCopy);
|
||||
Tcl_DecrRefCount(listObj);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(listObj);
|
||||
TclNewObj(listObj);
|
||||
Tcl_IncrRefCount(listObj);
|
||||
} else {
|
||||
/* Extract the pointer to the appropriate element. */
|
||||
listObj = elemPtrs[index];
|
||||
}
|
||||
Tcl_IncrRefCount(listObj);
|
||||
}
|
||||
Tcl_DecrRefCount(sublistCopy);
|
||||
}
|
||||
Tcl_Obj *itemObj;
|
||||
/*
|
||||
* Must set the internal rep again because it may have been
|
||||
* changed by TclGetIntForIndexM. See test lindex-8.4.
|
||||
*/
|
||||
if (!TclHasInternalRep(listObj, &tclListType.objType)) {
|
||||
status = SetListFromAny(interp, listObj);
|
||||
if (status != TCL_OK) {
|
||||
/* The list is not a list at all => error. */
|
||||
Tcl_DecrRefCount(listObj);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ListObjGetElements(listObj, listLen, elemPtrs);
|
||||
/* increment this reference count first before decrementing
|
||||
* just in case they are the same Tcl_Obj
|
||||
*/
|
||||
itemObj = elemPtrs[index];
|
||||
Tcl_IncrRefCount(itemObj);
|
||||
Tcl_DecrRefCount(listObj);
|
||||
/* Extract the pointer to the appropriate element. */
|
||||
listObj = itemObj;
|
||||
}
|
||||
} else {
|
||||
Tcl_DecrRefCount(listObj);
|
||||
listObj = NULL;
|
||||
}
|
||||
}
|
||||
return listObj;
|
||||
}
|
||||
|
||||
@@ -2767,30 +2741,37 @@ TclLsetList(
|
||||
*/
|
||||
|
||||
if (!TclHasInternalRep(indexArgObj, &tclListType.objType)
|
||||
&& TclGetIntForIndexM(NULL, indexArgObj, ListSizeT_MAX - 1, &index)
|
||||
&& TclGetIntForIndexM(NULL, indexArgObj, TCL_SIZE_MAX - 1, &index)
|
||||
== TCL_OK) {
|
||||
/* indexArgPtr designates a single index. */
|
||||
/* T:listrep-1.{2.1,12.1,15.1,19.1},2.{2.3,9.3,10.1,13.1,16.1}, 3.{4,5,6}.3 */
|
||||
return TclLsetFlat(interp, listObj, 1, &indexArgObj, valueObj);
|
||||
}
|
||||
|
||||
indexListCopy = TclListObjCopy(NULL, indexArgObj);
|
||||
if (indexListCopy == NULL) {
|
||||
indexListCopy = TclDuplicatePureObj(
|
||||
interp, indexArgObj, &tclListType.objType);
|
||||
if (!indexListCopy) {
|
||||
/*
|
||||
* indexArgPtr designates something that is neither an index nor a
|
||||
* well formed list. Report the error via TclLsetFlat.
|
||||
*/
|
||||
return TclLsetFlat(interp, listObj, 1, &indexArgObj, valueObj);
|
||||
}
|
||||
if (TCL_OK != TclListObjGetElementsM(
|
||||
interp, indexListCopy, &indexCount, &indices)) {
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
/*
|
||||
* indexArgPtr designates something that is neither an index nor a
|
||||
* well formed list. Report the error via TclLsetFlat.
|
||||
*/
|
||||
return TclLsetFlat(interp, listObj, 1, &indexArgObj, valueObj);
|
||||
}
|
||||
LIST_ASSERT_TYPE(indexListCopy);
|
||||
ListObjGetElements(indexListCopy, indexCount, indices);
|
||||
|
||||
/*
|
||||
* Let TclLsetFlat perform the actual lset operation.
|
||||
*/
|
||||
|
||||
retValueObj = TclLsetFlat(interp, listObj, indexCount, indices, valueObj);
|
||||
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
return retValueObj;
|
||||
}
|
||||
@@ -2841,7 +2822,7 @@ TclLsetFlat(
|
||||
Tcl_Obj *valueObj) /* Value arg to 'lset' or NULL to 'lpop'. */
|
||||
{
|
||||
Tcl_Size index, len;
|
||||
int result;
|
||||
int copied = 0, result;
|
||||
Tcl_Obj *subListObj, *retValueObj;
|
||||
Tcl_Obj *pendingInvalidates[10];
|
||||
Tcl_Obj **pendingInvalidatesPtr = pendingInvalidates;
|
||||
@@ -2861,17 +2842,15 @@ TclLsetFlat(
|
||||
}
|
||||
|
||||
/*
|
||||
* If the list is shared, make a copy we can modify (copy-on-write). We
|
||||
* use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons:
|
||||
* 1) we have not yet confirmed listObj is actually a list; 2) We make a
|
||||
* verbatim copy of any existing string rep, and when we combine that with
|
||||
* the delayed invalidation of string reps of modified Tcl_Obj's
|
||||
* implemented below, the outcome is that any error condition that causes
|
||||
* this routine to return NULL, will leave the string rep of listObj and
|
||||
* all elements to be unchanged.
|
||||
* If the list is shared, make a copy to modify (copy-on-write). The string
|
||||
* representation and internal representation of listObj remains unchanged.
|
||||
*/
|
||||
|
||||
subListObj = Tcl_IsShared(listObj) ? Tcl_DuplicateObj(listObj) : listObj;
|
||||
subListObj = Tcl_IsShared(listObj)
|
||||
? TclDuplicatePureObj(interp, listObj, &tclListType.objType) : listObj;
|
||||
if (!subListObj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Anchor the linked list of Tcl_Obj's whose string reps must be
|
||||
@@ -2941,10 +2920,9 @@ TclLsetFlat(
|
||||
}
|
||||
|
||||
/*
|
||||
* No error conditions. As long as we're not yet on the last index,
|
||||
* determine the next sublist for the next pass through the loop,
|
||||
* and take steps to make sure it is an unshared copy, as we intend
|
||||
* to modify it.
|
||||
* No error conditions. If this is not the last index, determine the
|
||||
* next sublist for the next pass through the loop, and take steps to
|
||||
* make sure it is unshared in order to modify it.
|
||||
*/
|
||||
|
||||
if (--indexCount) {
|
||||
@@ -2955,7 +2933,12 @@ TclLsetFlat(
|
||||
subListObj = elemPtrs[index];
|
||||
}
|
||||
if (Tcl_IsShared(subListObj)) {
|
||||
subListObj = Tcl_DuplicateObj(subListObj);
|
||||
subListObj = TclDuplicatePureObj(
|
||||
interp, subListObj, &tclListType.objType);
|
||||
if (!subListObj) {
|
||||
return NULL;
|
||||
}
|
||||
copied = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2973,7 +2956,17 @@ TclLsetFlat(
|
||||
TclListObjSetElement(NULL, parentList, index, subListObj);
|
||||
}
|
||||
if (Tcl_IsShared(subListObj)) {
|
||||
subListObj = Tcl_DuplicateObj(subListObj);
|
||||
Tcl_Obj * newSubListObj;
|
||||
newSubListObj = TclDuplicatePureObj(
|
||||
interp, subListObj, &tclListType.objType);
|
||||
if (copied) {
|
||||
Tcl_DecrRefCount(subListObj);
|
||||
}
|
||||
if (newSubListObj) {
|
||||
subListObj = newSubListObj;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
TclListObjSetElement(NULL, parentList, index, subListObj);
|
||||
}
|
||||
|
||||
@@ -3322,6 +3315,7 @@ SetListFromAny(
|
||||
if (elemPtrs[j] == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_IncrRefCount(elemPtrs[j]);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -3545,7 +3539,7 @@ TclListTestObj(size_t length, size_t leadingSpace, size_t endSpace)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ListRepInit(capacity, NULL, 0, &listRep);
|
||||
ListRepInit(capacity, NULL, LISTREP_PANIC_ON_FAIL, &listRep);
|
||||
|
||||
ListStore *storePtr = listRep.storePtr;
|
||||
size_t i;
|
||||
|
||||
@@ -646,7 +646,7 @@ TclAddLiteralObj(
|
||||
if (litPtrPtr) {
|
||||
*litPtrPtr = lPtr;
|
||||
}
|
||||
|
||||
|
||||
return objIndex;
|
||||
}
|
||||
|
||||
|
||||
+50
-3
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file contains the object-system core (NB: not Tcl_Obj, but ::oo)
|
||||
*
|
||||
* Copyright © 2005-2012 Donal K. Fellows
|
||||
* Copyright © 2005-2019 Donal K. Fellows
|
||||
* Copyright © 2017 Nathan Coulter
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
@@ -327,6 +327,7 @@ InitFoundation(
|
||||
DeletedObjdefNamespace);
|
||||
fPtr->helpersNs = Tcl_CreateNamespace(interp, "::oo::Helpers", fPtr,
|
||||
DeletedHelpersNamespace);
|
||||
Tcl_CreateNamespace(interp, "::oo::configuresupport", NULL, NULL);
|
||||
fPtr->epoch = 1;
|
||||
fPtr->tsdPtr = tsdPtr;
|
||||
TclNewLiteralStringObj(fPtr->unknownMethodNameObj, "unknown");
|
||||
@@ -964,7 +965,7 @@ TclOOReleaseClassContents(
|
||||
Class *clsPtr = oPtr->classPtr, *tmpClsPtr;
|
||||
Method *mPtr;
|
||||
Foundation *fPtr = oPtr->fPtr;
|
||||
Tcl_Obj *variableObj;
|
||||
Tcl_Obj *variableObj, *propertyObj;
|
||||
PrivateVariableMapping *privateVariable;
|
||||
|
||||
/*
|
||||
@@ -1017,6 +1018,29 @@ TclOOReleaseClassContents(
|
||||
clsPtr->classChainCache = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Squelch the property lists.
|
||||
*/
|
||||
|
||||
if (clsPtr->properties.allReadableCache) {
|
||||
Tcl_DecrRefCount(clsPtr->properties.allReadableCache);
|
||||
}
|
||||
if (clsPtr->properties.allWritableCache) {
|
||||
Tcl_DecrRefCount(clsPtr->properties.allWritableCache);
|
||||
}
|
||||
if (clsPtr->properties.readable.num) {
|
||||
FOREACH(propertyObj, clsPtr->properties.readable) {
|
||||
Tcl_DecrRefCount(propertyObj);
|
||||
}
|
||||
Tcl_Free(clsPtr->properties.readable.list);
|
||||
}
|
||||
if (clsPtr->properties.writable.num) {
|
||||
FOREACH(propertyObj, clsPtr->properties.writable) {
|
||||
Tcl_DecrRefCount(propertyObj);
|
||||
}
|
||||
Tcl_Free(clsPtr->properties.writable.list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Squelch our filter list.
|
||||
*/
|
||||
@@ -1118,7 +1142,7 @@ ObjectNamespaceDeleted(
|
||||
FOREACH_HASH_DECLS;
|
||||
Class *mixinPtr;
|
||||
Method *mPtr;
|
||||
Tcl_Obj *filterObj, *variableObj;
|
||||
Tcl_Obj *filterObj, *variableObj, *propertyObj;
|
||||
PrivateVariableMapping *privateVariable;
|
||||
Tcl_Interp *interp = oPtr->fPtr->interp;
|
||||
Tcl_Size i;
|
||||
@@ -1271,6 +1295,29 @@ ObjectNamespaceDeleted(
|
||||
oPtr->metadataPtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Squelch the property lists.
|
||||
*/
|
||||
|
||||
if (oPtr->properties.allReadableCache) {
|
||||
Tcl_DecrRefCount(oPtr->properties.allReadableCache);
|
||||
}
|
||||
if (oPtr->properties.allWritableCache) {
|
||||
Tcl_DecrRefCount(oPtr->properties.allWritableCache);
|
||||
}
|
||||
if (oPtr->properties.readable.num) {
|
||||
FOREACH(propertyObj, oPtr->properties.readable) {
|
||||
Tcl_DecrRefCount(propertyObj);
|
||||
}
|
||||
Tcl_Free(oPtr->properties.readable.list);
|
||||
}
|
||||
if (oPtr->properties.writable.num) {
|
||||
FOREACH(propertyObj, oPtr->properties.writable) {
|
||||
Tcl_DecrRefCount(propertyObj);
|
||||
}
|
||||
Tcl_Free(oPtr->properties.writable.list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Because an object can be a class that is an instance of itself, the
|
||||
* class object's class structure should only be cleaned after most of
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ typedef struct Tcl_ObjectContext_ *Tcl_ObjectContext;
|
||||
typedef int (Tcl_MethodCallProc)(void *clientData, Tcl_Interp *interp,
|
||||
Tcl_ObjectContext objectContext, int objc, Tcl_Obj *const *objv);
|
||||
typedef int (Tcl_MethodCallProc2)(void *clientData, Tcl_Interp *interp,
|
||||
Tcl_ObjectContext objectContext, ptrdiff_t objc, Tcl_Obj *const *objv);
|
||||
Tcl_ObjectContext objectContext, Tcl_Size objc, Tcl_Obj *const *objv);
|
||||
typedef void (Tcl_MethodDeleteProc)(void *clientData);
|
||||
typedef int (Tcl_CloneProc)(Tcl_Interp *interp, void *oldClientData,
|
||||
void **newClientData);
|
||||
|
||||
+261
-6
@@ -2,9 +2,10 @@
|
||||
* tclOOCall.c --
|
||||
*
|
||||
* This file contains the method call chain management code for the
|
||||
* object-system core.
|
||||
* object-system core. It also contains everything else that does
|
||||
* inheritance hierarchy traversal.
|
||||
*
|
||||
* Copyright © 2005-2012 Donal K. Fellows
|
||||
* Copyright © 2005-2019 Donal K. Fellows
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -58,6 +59,7 @@ typedef struct {
|
||||
#define BUILDING_MIXINS 0x400000
|
||||
#define TRAVERSED_MIXIN 0x800000
|
||||
#define OBJECT_MIXIN 0x1000000
|
||||
#define DEFINE_FOR_CLASS 0x2000000
|
||||
#define MIXIN_CONSISTENT(flags) \
|
||||
(((flags) & OBJECT_MIXIN) || \
|
||||
!((flags) & BUILDING_MIXINS) == !((flags) & TRAVERSED_MIXIN))
|
||||
@@ -1907,7 +1909,7 @@ TclOOGetDefineContextNamespace(
|
||||
DefineEntry staticSpace[DEFINE_CHAIN_STATIC_SIZE];
|
||||
DefineEntry *entryPtr;
|
||||
Tcl_Namespace *nsPtr = NULL;
|
||||
int i;
|
||||
int i, flags = (forClass ? DEFINE_FOR_CLASS : 0);
|
||||
|
||||
define.list = staticSpace;
|
||||
define.num = 0;
|
||||
@@ -1918,8 +1920,8 @@ TclOOGetDefineContextNamespace(
|
||||
* class mixins right.
|
||||
*/
|
||||
|
||||
AddSimpleDefineNamespaces(oPtr, &define, forClass | BUILDING_MIXINS);
|
||||
AddSimpleDefineNamespaces(oPtr, &define, forClass);
|
||||
AddSimpleDefineNamespaces(oPtr, &define, flags | BUILDING_MIXINS);
|
||||
AddSimpleDefineNamespaces(oPtr, &define, flags);
|
||||
|
||||
/*
|
||||
* Go through the list until we find a namespace whose name we can
|
||||
@@ -2003,7 +2005,7 @@ AddSimpleClassDefineNamespaces(
|
||||
flags | TRAVERSED_MIXIN);
|
||||
}
|
||||
|
||||
if (flags & ~(TRAVERSED_MIXIN | BUILDING_MIXINS)) {
|
||||
if (flags & DEFINE_FOR_CLASS) {
|
||||
AddDefinitionNamespaceToChain(classPtr, classPtr->clsDefinitionNs,
|
||||
definePtr, flags);
|
||||
} else {
|
||||
@@ -2112,6 +2114,259 @@ AddDefinitionNamespaceToChain(
|
||||
definePtr->num++;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* FindClassProps --
|
||||
*
|
||||
* Discover the properties known to a class and its superclasses.
|
||||
* The property names become the keys in the accumulator hash table
|
||||
* (which is used as a set).
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
FindClassProps(
|
||||
Class *clsPtr, /* The object to inspect. Must exist. */
|
||||
int writable, /* Whether we're after the readable or writable
|
||||
* property set. */
|
||||
Tcl_HashTable *accumulator) /* Where to gather the names. */
|
||||
{
|
||||
int i, dummy;
|
||||
Tcl_Obj *propName;
|
||||
Class *mixin, *sup;
|
||||
|
||||
tailRecurse:
|
||||
if (writable) {
|
||||
FOREACH(propName, clsPtr->properties.writable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
}
|
||||
} else {
|
||||
FOREACH(propName, clsPtr->properties.readable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
}
|
||||
}
|
||||
if (clsPtr->thisPtr->flags & ROOT_OBJECT) {
|
||||
/*
|
||||
* We do *not* traverse upwards from the root!
|
||||
*/
|
||||
return;
|
||||
}
|
||||
FOREACH(mixin, clsPtr->mixins) {
|
||||
FindClassProps(mixin, writable, accumulator);
|
||||
}
|
||||
if (clsPtr->superclasses.num == 1) {
|
||||
clsPtr = clsPtr->superclasses.list[0];
|
||||
goto tailRecurse;
|
||||
}
|
||||
FOREACH(sup, clsPtr->superclasses) {
|
||||
FindClassProps(sup, writable, accumulator);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* FindObjectProps --
|
||||
*
|
||||
* Discover the properties known to an object and all its classes.
|
||||
* The property names become the keys in the accumulator hash table
|
||||
* (which is used as a set).
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
FindObjectProps(
|
||||
Object *oPtr, /* The object to inspect. Must exist. */
|
||||
int writable, /* Whether we're after the readable or writable
|
||||
* property set. */
|
||||
Tcl_HashTable *accumulator) /* Where to gather the names. */
|
||||
{
|
||||
int i, dummy;
|
||||
Tcl_Obj *propName;
|
||||
Class *mixin;
|
||||
|
||||
if (writable) {
|
||||
FOREACH(propName, oPtr->properties.writable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
}
|
||||
} else {
|
||||
FOREACH(propName, oPtr->properties.readable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
}
|
||||
}
|
||||
FOREACH(mixin, oPtr->mixins) {
|
||||
FindClassProps(mixin, writable, accumulator);
|
||||
}
|
||||
FindClassProps(oPtr->selfCls, writable, accumulator);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOGetAllClassProperties --
|
||||
*
|
||||
* Get the list of all properties known to a class, including to its
|
||||
* superclasses. Manages a cache so this operation is usually cheap.
|
||||
* The order of properties in the resulting list is undefined.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclOOGetAllClassProperties(
|
||||
Class *clsPtr, /* The class to inspect. Must exist. */
|
||||
int writable, /* Whether to get writable properties. If
|
||||
* false, readable properties will be returned
|
||||
* instead. */
|
||||
int *allocated) /* Address of variable to set to true if a
|
||||
* Tcl_Obj was allocated and may be safely
|
||||
* modified by the caller. */
|
||||
{
|
||||
Tcl_HashTable hashTable;
|
||||
FOREACH_HASH_DECLS;
|
||||
Tcl_Obj *propName, *result;
|
||||
void *dummy;
|
||||
|
||||
/*
|
||||
* Look in the cache.
|
||||
*/
|
||||
|
||||
if (clsPtr->properties.epoch == clsPtr->thisPtr->fPtr->epoch) {
|
||||
if (writable) {
|
||||
if (clsPtr->properties.allWritableCache) {
|
||||
*allocated = 0;
|
||||
return clsPtr->properties.allWritableCache;
|
||||
}
|
||||
} else {
|
||||
if (clsPtr->properties.allReadableCache) {
|
||||
*allocated = 0;
|
||||
return clsPtr->properties.allReadableCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gather the information. Unsorted! (Caller will sort.)
|
||||
*/
|
||||
|
||||
*allocated = 1;
|
||||
Tcl_InitObjHashTable(&hashTable);
|
||||
FindClassProps(clsPtr, writable, &hashTable);
|
||||
TclNewObj(result);
|
||||
FOREACH_HASH(propName, dummy, &hashTable) {
|
||||
Tcl_ListObjAppendElement(NULL, result, propName);
|
||||
}
|
||||
Tcl_DeleteHashTable(&hashTable);
|
||||
|
||||
/*
|
||||
* Cache the information. Also purges the cache.
|
||||
*/
|
||||
|
||||
if (clsPtr->properties.epoch != clsPtr->thisPtr->fPtr->epoch) {
|
||||
if (clsPtr->properties.allWritableCache) {
|
||||
Tcl_DecrRefCount(clsPtr->properties.allWritableCache);
|
||||
clsPtr->properties.allWritableCache = NULL;
|
||||
}
|
||||
if (clsPtr->properties.allReadableCache) {
|
||||
Tcl_DecrRefCount(clsPtr->properties.allReadableCache);
|
||||
clsPtr->properties.allReadableCache = NULL;
|
||||
}
|
||||
}
|
||||
clsPtr->properties.epoch = clsPtr->thisPtr->fPtr->epoch;
|
||||
if (writable) {
|
||||
clsPtr->properties.allWritableCache = result;
|
||||
} else {
|
||||
clsPtr->properties.allReadableCache = result;
|
||||
}
|
||||
Tcl_IncrRefCount(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOGetAllObjectProperties --
|
||||
*
|
||||
* Get the list of all properties known to a object, including to its
|
||||
* classes. Manages a cache so this operation is usually cheap.
|
||||
* The order of properties in the resulting list is undefined.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclOOGetAllObjectProperties(
|
||||
Object *oPtr, /* The object to inspect. Must exist. */
|
||||
int writable, /* Whether to get writable properties. If
|
||||
* false, readable properties will be returned
|
||||
* instead. */
|
||||
int *allocated) /* Address of variable to set to true if a
|
||||
* Tcl_Obj was allocated and may be safely
|
||||
* modified by the caller. */
|
||||
{
|
||||
Tcl_HashTable hashTable;
|
||||
FOREACH_HASH_DECLS;
|
||||
Tcl_Obj *propName, *result;
|
||||
void *dummy;
|
||||
|
||||
/*
|
||||
* Look in the cache.
|
||||
*/
|
||||
|
||||
if (oPtr->properties.epoch == oPtr->fPtr->epoch) {
|
||||
if (writable) {
|
||||
if (oPtr->properties.allWritableCache) {
|
||||
*allocated = 0;
|
||||
return oPtr->properties.allWritableCache;
|
||||
}
|
||||
} else {
|
||||
if (oPtr->properties.allReadableCache) {
|
||||
*allocated = 0;
|
||||
return oPtr->properties.allReadableCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gather the information. Unsorted! (Caller will sort.)
|
||||
*/
|
||||
|
||||
*allocated = 1;
|
||||
Tcl_InitObjHashTable(&hashTable);
|
||||
FindObjectProps(oPtr, writable, &hashTable);
|
||||
TclNewObj(result);
|
||||
FOREACH_HASH(propName, dummy, &hashTable) {
|
||||
Tcl_ListObjAppendElement(NULL, result, propName);
|
||||
}
|
||||
Tcl_DeleteHashTable(&hashTable);
|
||||
|
||||
/*
|
||||
* Cache the information.
|
||||
*/
|
||||
|
||||
if (oPtr->properties.epoch != oPtr->fPtr->epoch) {
|
||||
if (oPtr->properties.allWritableCache) {
|
||||
Tcl_DecrRefCount(oPtr->properties.allWritableCache);
|
||||
oPtr->properties.allWritableCache = NULL;
|
||||
}
|
||||
if (oPtr->properties.allReadableCache) {
|
||||
Tcl_DecrRefCount(oPtr->properties.allReadableCache);
|
||||
oPtr->properties.allReadableCache = NULL;
|
||||
}
|
||||
}
|
||||
oPtr->properties.epoch = oPtr->fPtr->epoch;
|
||||
if (writable) {
|
||||
oPtr->properties.allWritableCache = result;
|
||||
} else {
|
||||
oPtr->properties.allReadableCache = result;
|
||||
}
|
||||
Tcl_IncrRefCount(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+457
-9
@@ -4,7 +4,7 @@
|
||||
* This file contains the implementation of the ::oo::define command,
|
||||
* part of the object-system core (NB: not Tcl_Obj, but ::oo).
|
||||
*
|
||||
* Copyright © 2006-2013 Donal K. Fellows
|
||||
* Copyright © 2006-2019 Donal K. Fellows
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -60,6 +60,7 @@ struct DeclaredSlot {
|
||||
*/
|
||||
|
||||
static inline void BumpGlobalEpoch(Tcl_Interp *interp, Class *classPtr);
|
||||
static inline void BumpInstanceEpoch(Object *oPtr);
|
||||
static Tcl_Command FindCommand(Tcl_Interp *interp, Tcl_Obj *stringObj,
|
||||
Tcl_Namespace *const namespacePtr);
|
||||
static inline void GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr,
|
||||
@@ -102,6 +103,8 @@ static int ClassVarsGet(void *clientData,
|
||||
static int ClassVarsSet(void *clientData,
|
||||
Tcl_Interp *interp, Tcl_ObjectContext context,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static Tcl_MethodCallProc ClassRPropsGet, ClassRPropsSet;
|
||||
static Tcl_MethodCallProc ClassWPropsGet, ClassWPropsSet;
|
||||
static int ObjFilterGet(void *clientData,
|
||||
Tcl_Interp *interp, Tcl_ObjectContext context,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
@@ -120,6 +123,8 @@ static int ObjVarsGet(void *clientData,
|
||||
static int ObjVarsSet(void *clientData,
|
||||
Tcl_Interp *interp, Tcl_ObjectContext context,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static Tcl_MethodCallProc ObjRPropsGet, ObjRPropsSet;
|
||||
static Tcl_MethodCallProc ObjWPropsGet, ObjWPropsSet;
|
||||
static int ResolveClass(void *clientData,
|
||||
Tcl_Interp *interp, Tcl_ObjectContext context,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
@@ -136,6 +141,14 @@ static const struct DeclaredSlot slots[] = {
|
||||
SLOT("objdefine::filter", ObjFilterGet, ObjFilterSet, NULL),
|
||||
SLOT("objdefine::mixin", ObjMixinGet, ObjMixinSet, ResolveClass),
|
||||
SLOT("objdefine::variable", ObjVarsGet, ObjVarsSet, NULL),
|
||||
SLOT("configuresupport::readableproperties",
|
||||
ClassRPropsGet, ClassRPropsSet, NULL),
|
||||
SLOT("configuresupport::writableproperties",
|
||||
ClassWPropsGet, ClassWPropsSet, NULL),
|
||||
SLOT("configuresupport::objreadableproperties",
|
||||
ObjRPropsGet, ObjRPropsSet, NULL),
|
||||
SLOT("configuresupport::objwritableproperties",
|
||||
ObjWPropsGet, ObjWPropsSet, NULL),
|
||||
{NULL, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}
|
||||
};
|
||||
|
||||
@@ -201,18 +214,58 @@ BumpGlobalEpoch(
|
||||
|
||||
if (classPtr->thisPtr->mixins.num > 0) {
|
||||
classPtr->thisPtr->epoch++;
|
||||
|
||||
/*
|
||||
* Invalidate the property caches directly.
|
||||
*/
|
||||
|
||||
if (classPtr->properties.allReadableCache) {
|
||||
Tcl_DecrRefCount(classPtr->properties.allReadableCache);
|
||||
classPtr->properties.allReadableCache = NULL;
|
||||
}
|
||||
if (classPtr->properties.allWritableCache) {
|
||||
Tcl_DecrRefCount(classPtr->properties.allWritableCache);
|
||||
classPtr->properties.allWritableCache = NULL;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Either there's no class (?!) or we're reconfiguring something that is
|
||||
* in use. Force regeneration of call chains.
|
||||
* in use. Force regeneration of call chains and properties.
|
||||
*/
|
||||
|
||||
TclOOGetFoundation(interp)->epoch++;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* BumpInstanceEpoch --
|
||||
*
|
||||
* Advances the epoch and clears the property cache of an object. The
|
||||
* equivalent for classes is BumpGlobalEpoch(), as classes have a more
|
||||
* complex set of relationships to other entities.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline void
|
||||
BumpInstanceEpoch(
|
||||
Object *oPtr)
|
||||
{
|
||||
oPtr->epoch++;
|
||||
if (oPtr->properties.allReadableCache) {
|
||||
Tcl_DecrRefCount(oPtr->properties.allReadableCache);
|
||||
oPtr->properties.allReadableCache = NULL;
|
||||
}
|
||||
if (oPtr->properties.allWritableCache) {
|
||||
Tcl_DecrRefCount(oPtr->properties.allWritableCache);
|
||||
oPtr->properties.allWritableCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -292,7 +345,7 @@ TclOOObjectSetFilters(
|
||||
oPtr->filters.num = numFilters;
|
||||
oPtr->flags &= ~USE_CLASS_CACHE;
|
||||
}
|
||||
oPtr->epoch++; /* Only this object can be affected. */
|
||||
BumpInstanceEpoch(oPtr); /* Only this object can be affected. */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -415,7 +468,7 @@ TclOOObjectSetMixins(
|
||||
}
|
||||
}
|
||||
}
|
||||
oPtr->epoch++;
|
||||
BumpInstanceEpoch(oPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -482,6 +535,7 @@ TclOOClassSetMixins(
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline void
|
||||
InstallStandardVariableMapping(
|
||||
VariableNameList *vnlPtr,
|
||||
@@ -1507,7 +1561,7 @@ TclOODefineClassObjCmd(
|
||||
if (oPtr->classPtr != NULL) {
|
||||
BumpGlobalEpoch(interp, oPtr->classPtr);
|
||||
} else {
|
||||
oPtr->epoch++;
|
||||
BumpInstanceEpoch(oPtr);
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -1717,7 +1771,7 @@ TclOODefineDeleteMethodObjCmd(
|
||||
}
|
||||
|
||||
if (isInstanceDeleteMethod) {
|
||||
oPtr->epoch++;
|
||||
BumpInstanceEpoch(oPtr);
|
||||
} else {
|
||||
BumpGlobalEpoch(interp, oPtr->classPtr);
|
||||
}
|
||||
@@ -1877,7 +1931,7 @@ TclOODefineExportObjCmd(
|
||||
|
||||
if (changed) {
|
||||
if (isInstanceExport) {
|
||||
oPtr->epoch++;
|
||||
BumpInstanceEpoch(oPtr);
|
||||
} else {
|
||||
BumpGlobalEpoch(interp, clsPtr);
|
||||
}
|
||||
@@ -2095,7 +2149,7 @@ TclOODefineRenameMethodObjCmd(
|
||||
}
|
||||
|
||||
if (isInstanceRenameMethod) {
|
||||
oPtr->epoch++;
|
||||
BumpInstanceEpoch(oPtr);
|
||||
} else {
|
||||
BumpGlobalEpoch(interp, oPtr->classPtr);
|
||||
}
|
||||
@@ -2189,7 +2243,7 @@ TclOODefineUnexportObjCmd(
|
||||
|
||||
if (changed) {
|
||||
if (isInstanceUnexport) {
|
||||
oPtr->epoch++;
|
||||
BumpInstanceEpoch(oPtr);
|
||||
} else {
|
||||
BumpGlobalEpoch(interp, clsPtr);
|
||||
}
|
||||
@@ -3081,6 +3135,400 @@ ResolveClass(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ClassRPropsGet, ClassRPropsSet, ObjRPropsGet, ObjRPropsSet --
|
||||
*
|
||||
* Implementations of the "readableproperties" slot accessors for classes
|
||||
* and instances.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
InstallReadableProps(
|
||||
PropertyStorage *props,
|
||||
Tcl_Size objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Tcl_Obj *propObj;
|
||||
Tcl_Size i, n;
|
||||
int created;
|
||||
Tcl_HashTable uniqueTable;
|
||||
|
||||
if (props->allReadableCache) {
|
||||
Tcl_DecrRefCount(props->allReadableCache);
|
||||
props->allReadableCache = NULL;
|
||||
}
|
||||
|
||||
for (i=0 ; i<objc ; i++) {
|
||||
Tcl_IncrRefCount(objv[i]);
|
||||
}
|
||||
FOREACH(propObj, props->readable) {
|
||||
Tcl_DecrRefCount(propObj);
|
||||
}
|
||||
if (i != objc) {
|
||||
if (objc == 0) {
|
||||
Tcl_Free(props->readable.list);
|
||||
} else if (i) {
|
||||
props->readable.list = (Tcl_Obj **)Tcl_Realloc(props->readable.list,
|
||||
sizeof(Tcl_Obj *) * objc);
|
||||
} else {
|
||||
props->readable.list = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * objc);
|
||||
}
|
||||
}
|
||||
props->readable.num = 0;
|
||||
if (objc > 0) {
|
||||
Tcl_InitObjHashTable(&uniqueTable);
|
||||
for (i=n=0 ; i<objc ; i++) {
|
||||
Tcl_CreateHashEntry(&uniqueTable, objv[i], &created);
|
||||
if (created) {
|
||||
props->readable.list[n++] = objv[i];
|
||||
} else {
|
||||
Tcl_DecrRefCount(objv[i]);
|
||||
}
|
||||
}
|
||||
props->readable.num = n;
|
||||
|
||||
/*
|
||||
* Shouldn't be necessary, but maintain num/list invariant.
|
||||
*/
|
||||
|
||||
if (n != objc) {
|
||||
props->readable.list = (Tcl_Obj **)Tcl_Realloc(props->readable.list,
|
||||
sizeof(Tcl_Obj *) * n);
|
||||
}
|
||||
Tcl_DeleteHashTable(&uniqueTable);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ClassRPropsGet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Obj *resultObj, *propNameObj;
|
||||
int i;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
} else if (!oPtr->classPtr) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"attempt to misuse API", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclNewObj(resultObj);
|
||||
FOREACH(propNameObj, oPtr->classPtr->properties.readable) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ClassRPropsSet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Size varc;
|
||||
Tcl_Obj **varv;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
"filterList");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objv += Tcl_ObjectContextSkippedArgs(context);
|
||||
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
} else if (!oPtr->classPtr) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"attempt to misuse API", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
|
||||
return TCL_ERROR;
|
||||
} else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
|
||||
&varv) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
InstallReadableProps(&oPtr->classPtr->properties, varc, varv);
|
||||
BumpGlobalEpoch(interp, oPtr->classPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ObjRPropsGet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Obj *resultObj, *propNameObj;
|
||||
int i;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclNewObj(resultObj);
|
||||
FOREACH(propNameObj, oPtr->properties.readable) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ObjRPropsSet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Size varc;
|
||||
Tcl_Obj **varv;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
"filterList");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objv += Tcl_ObjectContextSkippedArgs(context);
|
||||
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
} else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
|
||||
&varv) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
InstallReadableProps(&oPtr->properties, varc, varv);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ClassWPropsGet, ClassWPropsSet, ObjWPropsGet, ObjWPropsSet --
|
||||
*
|
||||
* Implementations of the "writableproperties" slot accessors for classes
|
||||
* and instances.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
InstallWritableProps(
|
||||
PropertyStorage *props,
|
||||
Tcl_Size objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Tcl_Obj *propObj;
|
||||
Tcl_Size i, n;
|
||||
int created;
|
||||
Tcl_HashTable uniqueTable;
|
||||
|
||||
if (props->allWritableCache) {
|
||||
Tcl_DecrRefCount(props->allWritableCache);
|
||||
props->allWritableCache = NULL;
|
||||
}
|
||||
|
||||
for (i=0 ; i<objc ; i++) {
|
||||
Tcl_IncrRefCount(objv[i]);
|
||||
}
|
||||
FOREACH(propObj, props->writable) {
|
||||
Tcl_DecrRefCount(propObj);
|
||||
}
|
||||
if (i != objc) {
|
||||
if (objc == 0) {
|
||||
Tcl_Free(props->writable.list);
|
||||
} else if (i) {
|
||||
props->writable.list = (Tcl_Obj **)Tcl_Realloc(props->writable.list,
|
||||
sizeof(Tcl_Obj *) * objc);
|
||||
} else {
|
||||
props->writable.list = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * objc);
|
||||
}
|
||||
}
|
||||
props->writable.num = 0;
|
||||
if (objc > 0) {
|
||||
Tcl_InitObjHashTable(&uniqueTable);
|
||||
for (i=n=0 ; i<objc ; i++) {
|
||||
Tcl_CreateHashEntry(&uniqueTable, objv[i], &created);
|
||||
if (created) {
|
||||
props->writable.list[n++] = objv[i];
|
||||
} else {
|
||||
Tcl_DecrRefCount(objv[i]);
|
||||
}
|
||||
}
|
||||
props->writable.num = n;
|
||||
|
||||
/*
|
||||
* Shouldn't be necessary, but maintain num/list invariant.
|
||||
*/
|
||||
|
||||
if (n != objc) {
|
||||
props->writable.list = (Tcl_Obj **)Tcl_Realloc(props->writable.list,
|
||||
sizeof(Tcl_Obj *) * n);
|
||||
}
|
||||
Tcl_DeleteHashTable(&uniqueTable);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ClassWPropsGet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Obj *resultObj, *propNameObj;
|
||||
int i;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
} else if (!oPtr->classPtr) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"attempt to misuse API", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclNewObj(resultObj);
|
||||
FOREACH(propNameObj, oPtr->classPtr->properties.writable) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ClassWPropsSet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Size varc;
|
||||
Tcl_Obj **varv;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
"propertyList");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objv += Tcl_ObjectContextSkippedArgs(context);
|
||||
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
} else if (!oPtr->classPtr) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"attempt to misuse API", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
|
||||
return TCL_ERROR;
|
||||
} else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
|
||||
&varv) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
InstallWritableProps(&oPtr->classPtr->properties, varc, varv);
|
||||
BumpGlobalEpoch(interp, oPtr->classPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ObjWPropsGet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Obj *resultObj, *propNameObj;
|
||||
int i;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclNewObj(resultObj);
|
||||
FOREACH(propNameObj, oPtr->properties.writable) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ObjWPropsSet(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Size varc;
|
||||
Tcl_Obj **varv;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
"propertyList");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objv += Tcl_ObjectContextSkippedArgs(context);
|
||||
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
} else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
|
||||
&varv) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
InstallWritableProps(&oPtr->properties, varc, varv);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+184
-1
@@ -4,7 +4,7 @@
|
||||
* This file contains the implementation of the ::oo-related [info]
|
||||
* subcommands.
|
||||
*
|
||||
* Copyright © 2006-2011 Donal K. Fellows
|
||||
* Copyright © 2006-2019 Donal K. Fellows
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "tclOOInt.h"
|
||||
|
||||
static inline Class * GetClassFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static void SortPropList(Tcl_Obj *list);
|
||||
static Tcl_ObjCmdProc InfoObjectCallCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectClassCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectDefnCmd;
|
||||
@@ -28,6 +29,7 @@ static Tcl_ObjCmdProc InfoObjectMethodsCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectMethodTypeCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectMixinsCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectNsCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectPropCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectVarsCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectVariablesCmd;
|
||||
static Tcl_ObjCmdProc InfoClassCallCmd;
|
||||
@@ -41,6 +43,7 @@ static Tcl_ObjCmdProc InfoClassInstancesCmd;
|
||||
static Tcl_ObjCmdProc InfoClassMethodsCmd;
|
||||
static Tcl_ObjCmdProc InfoClassMethodTypeCmd;
|
||||
static Tcl_ObjCmdProc InfoClassMixinsCmd;
|
||||
static Tcl_ObjCmdProc InfoClassPropCmd;
|
||||
static Tcl_ObjCmdProc InfoClassSubsCmd;
|
||||
static Tcl_ObjCmdProc InfoClassSupersCmd;
|
||||
static Tcl_ObjCmdProc InfoClassVariablesCmd;
|
||||
@@ -61,6 +64,7 @@ static const EnsembleImplMap infoObjectCmds[] = {
|
||||
{"methodtype", InfoObjectMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"mixins", InfoObjectMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"namespace", InfoObjectNsCmd, TclCompileInfoObjectNamespaceCmd, NULL, NULL, 0},
|
||||
{"properties", InfoObjectPropCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"variables", InfoObjectVariablesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"vars", InfoObjectVarsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
@@ -82,6 +86,7 @@ static const EnsembleImplMap infoClassCmds[] = {
|
||||
{"methods", InfoClassMethodsCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"methodtype", InfoClassMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"mixins", InfoClassMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"properties", InfoClassPropCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"subclasses", InfoClassSubsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"superclasses", InfoClassSupersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"variables", InfoClassVariablesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
@@ -1716,6 +1721,184 @@ InfoClassCallCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* InfoClassPropCmd, InfoObjectPropCmd --
|
||||
*
|
||||
* Implements [info class properties $clsName ?$option...?] and
|
||||
* [info object properties $objName ?$option...?]
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
enum PropOpt {
|
||||
PROP_ALL, PROP_READABLE, PROP_WRITABLE
|
||||
};
|
||||
static const char *const propOptNames[] = {
|
||||
"-all", "-readable", "-writable",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
InfoClassPropCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Class *clsPtr;
|
||||
int i, idx, all = 0, writable = 0, allocated = 0;
|
||||
Tcl_Obj *result, *propObj;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "className ?options...?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
clsPtr = GetClassFromObj(interp, objv[1]);
|
||||
if (clsPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 2; i < objc; i++) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], propOptNames, "option", 0,
|
||||
&idx) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (idx) {
|
||||
case PROP_ALL:
|
||||
all = 1;
|
||||
break;
|
||||
case PROP_READABLE:
|
||||
writable = 0;
|
||||
break;
|
||||
case PROP_WRITABLE:
|
||||
writable = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the properties.
|
||||
*/
|
||||
|
||||
if (all) {
|
||||
result = TclOOGetAllClassProperties(clsPtr, writable, &allocated);
|
||||
if (allocated) {
|
||||
SortPropList(result);
|
||||
}
|
||||
} else {
|
||||
TclNewObj(result);
|
||||
if (writable) {
|
||||
FOREACH(propObj, clsPtr->properties.writable) {
|
||||
Tcl_ListObjAppendElement(NULL, result, propObj);
|
||||
}
|
||||
} else {
|
||||
FOREACH(propObj, clsPtr->properties.readable) {
|
||||
Tcl_ListObjAppendElement(NULL, result, propObj);
|
||||
}
|
||||
}
|
||||
SortPropList(result);
|
||||
}
|
||||
Tcl_SetObjResult(interp, result);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
InfoObjectPropCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Object *oPtr;
|
||||
int i, idx, all = 0, writable = 0, allocated = 0;
|
||||
Tcl_Obj *result, *propObj;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "objName ?options...?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 2; i < objc; i++) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], propOptNames, "option", 0,
|
||||
&idx) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (idx) {
|
||||
case PROP_ALL:
|
||||
all = 1;
|
||||
break;
|
||||
case PROP_READABLE:
|
||||
writable = 0;
|
||||
break;
|
||||
case PROP_WRITABLE:
|
||||
writable = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the properties.
|
||||
*/
|
||||
|
||||
if (all) {
|
||||
result = TclOOGetAllObjectProperties(oPtr, writable, &allocated);
|
||||
if (allocated) {
|
||||
SortPropList(result);
|
||||
}
|
||||
} else {
|
||||
TclNewObj(result);
|
||||
if (writable) {
|
||||
FOREACH(propObj, oPtr->properties.writable) {
|
||||
Tcl_ListObjAppendElement(NULL, result, propObj);
|
||||
}
|
||||
} else {
|
||||
FOREACH(propObj, oPtr->properties.readable) {
|
||||
Tcl_ListObjAppendElement(NULL, result, propObj);
|
||||
}
|
||||
}
|
||||
SortPropList(result);
|
||||
}
|
||||
Tcl_SetObjResult(interp, result);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* SortPropList --
|
||||
* Sort a list of names of properties. Simple support function. Assumes
|
||||
* that the list Tcl_Obj is unshared and doesn't have a string
|
||||
* representation.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
PropNameCompare(
|
||||
const void *a,
|
||||
const void *b)
|
||||
{
|
||||
Tcl_Obj *first = *(Tcl_Obj **) a;
|
||||
Tcl_Obj *second = *(Tcl_Obj **) b;
|
||||
|
||||
return strcmp(Tcl_GetString(first), Tcl_GetString(second));
|
||||
}
|
||||
|
||||
static void
|
||||
SortPropList(
|
||||
Tcl_Obj *list)
|
||||
{
|
||||
Tcl_Size ec;
|
||||
Tcl_Obj **ev;
|
||||
|
||||
Tcl_ListObjGetElements(NULL, list, &ec, &ev);
|
||||
qsort(ev, ec, sizeof(Tcl_Obj *), PropNameCompare);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+39
-9
@@ -160,6 +160,26 @@ typedef struct {
|
||||
typedef LIST_STATIC(Tcl_Obj *) VariableNameList;
|
||||
typedef LIST_STATIC(PrivateVariableMapping) PrivateVariableList;
|
||||
|
||||
/*
|
||||
* This type is used in various places.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
LIST_STATIC(Tcl_Obj *) readable;
|
||||
/* The readable properties slot. */
|
||||
LIST_STATIC(Tcl_Obj *) writable;
|
||||
/* The writable properties slot. */
|
||||
Tcl_Obj *allReadableCache; /* The cache of all readable properties
|
||||
* exposed by this object or class (in its
|
||||
* stereotypical instancs). Contains a sorted
|
||||
* unique list if not NULL. */
|
||||
Tcl_Obj *allWritableCache; /* The cache of all writable properties
|
||||
* exposed by this object or class (in its
|
||||
* stereotypical instances). Contains a sorted
|
||||
* unique list if not NULL. */
|
||||
int epoch; /* The epoch that the caches are valid for. */
|
||||
} PropertyStorage;
|
||||
|
||||
/*
|
||||
* Now, the definition of what an object actually is.
|
||||
*/
|
||||
@@ -182,8 +202,8 @@ typedef struct Object {
|
||||
LIST_STATIC(Tcl_Obj *) filters;
|
||||
/* List of filter names. */
|
||||
struct Class *classPtr; /* This is non-NULL for all classes, and NULL
|
||||
* for everything else. It points to the class
|
||||
* structure. */
|
||||
* for everything else. It points to the class
|
||||
* structure. */
|
||||
Tcl_Size refCount; /* Number of strong references to this object.
|
||||
* Note that there may be many more weak
|
||||
* references; this mechanism exists to
|
||||
@@ -211,12 +231,15 @@ typedef struct Object {
|
||||
* used inside methods. */
|
||||
Tcl_Command myclassCommand; /* Reference to this object's class dispatcher
|
||||
* command. */
|
||||
PropertyStorage properties; /* Information relating to the lists of
|
||||
* properties that this object *claims* to
|
||||
* support. */
|
||||
} Object;
|
||||
|
||||
#define OBJECT_DESTRUCTING 1 /* Indicates that an object is being or has
|
||||
* been destroyed */
|
||||
#define DESTRUCTOR_CALLED 2 /* Indicates that evaluation of destructor script for the
|
||||
object has began */
|
||||
#define OBJECT_DESTRUCTING 1 /* Indicates that an object is being or has
|
||||
* been destroyed */
|
||||
#define DESTRUCTOR_CALLED 2 /* Indicates that evaluation of destructor
|
||||
* script for the object has began */
|
||||
#define OO_UNUSED_4 4 /* No longer used. */
|
||||
#define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of
|
||||
* the class hierarchy and should be treated
|
||||
@@ -319,6 +342,9 @@ typedef struct Class {
|
||||
* namespace is defined but doesn't exist; we
|
||||
* also check at setting time but don't check
|
||||
* between times. */
|
||||
PropertyStorage properties; /* Information relating to the lists of
|
||||
* properties that this class *claims* to
|
||||
* support. */
|
||||
} Class;
|
||||
|
||||
/*
|
||||
@@ -521,6 +547,10 @@ MODULE_SCOPE void TclOODeleteContext(CallContext *contextPtr);
|
||||
MODULE_SCOPE void TclOODeleteDescendants(Tcl_Interp *interp,
|
||||
Object *oPtr);
|
||||
MODULE_SCOPE void TclOODelMethodRef(Method *method);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOGetAllClassProperties(Class *clsPtr,
|
||||
int writable, int *allocated);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOGetAllObjectProperties(Object *oPtr,
|
||||
int writable, int *allocated);
|
||||
MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr,
|
||||
Tcl_Obj *methodNameObj, int flags,
|
||||
Object *contextObjPtr, Class *contextClsPtr,
|
||||
@@ -589,12 +619,12 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
|
||||
/*
|
||||
* A variation where the array is an array of structs. There's no issue with
|
||||
* possible NULLs; every element of the array will be iterated over and the
|
||||
* varable set to a pointer to each of those elements in turn.
|
||||
* REQUIRES DECLARATION: Tcl_Size i;
|
||||
* variable set to a pointer to each of those elements in turn.
|
||||
* REQUIRES DECLARATION: Tcl_Size i; See [96551aca55] for more FOREACH_STRUCT details.
|
||||
*/
|
||||
|
||||
#define FOREACH_STRUCT(var,ary) \
|
||||
for(i=0 ; var=&((ary).list[i]), i<(ary).num; i++)
|
||||
if (i=0, (ary).num>0) for(; var=&((ary).list[i]), i<(ary).num; i++)
|
||||
|
||||
/*
|
||||
* Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS
|
||||
|
||||
+247
-18
@@ -19,7 +19,7 @@
|
||||
/*
|
||||
* The scripted part of the definitions of TclOO.
|
||||
*
|
||||
* Compiled from generic/tclOOScript.tcl by tools/makeHeader.tcl, which
|
||||
* Compiled from tools/tclOOScript.tcl by tools/makeHeader.tcl, which
|
||||
* contains the commented version of everything; *this* file is automatically
|
||||
* generated.
|
||||
*/
|
||||
@@ -29,7 +29,7 @@ static const char *tclOOSetupScript =
|
||||
"::namespace eval ::oo {\n"
|
||||
"\t::namespace path {}\n"
|
||||
"\tnamespace eval Helpers {\n"
|
||||
"\t\t::namespace path {}\n"
|
||||
"\t\tnamespace path {}\n"
|
||||
"\t\tproc callback {method args} {\n"
|
||||
"\t\t\tlist [uplevel 1 {::namespace which my}] $method {*}$args\n"
|
||||
"\t\t}\n"
|
||||
@@ -98,9 +98,9 @@ static const char *tclOOSetupScript =
|
||||
"\t\t\tif {![info object isa class $d]} {\n"
|
||||
"\t\t\t\tcontinue\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\tdefine $delegate ::oo::define::superclass -append $d\n"
|
||||
"\t\t\tdefine $delegate ::oo::define::superclass -appendifnew $d\n"
|
||||
"\t\t}\n"
|
||||
"\t\tobjdefine $class ::oo::objdefine::mixin -append $delegate\n"
|
||||
"\t\tobjdefine $class ::oo::objdefine::mixin -appendifnew $delegate\n"
|
||||
"\t}\n"
|
||||
"\tproc UpdateClassDelegatesAfterClone {originObject targetObject} {\n"
|
||||
"\t\tset originDelegate [DelegateName $originObject]\n"
|
||||
@@ -141,34 +141,44 @@ static const char *tclOOSetupScript =
|
||||
"\t\t::namespace delete tmp\n"
|
||||
"\t}\n"
|
||||
"\tdefine Slot {\n"
|
||||
"\t\tmethod Get {} {\n"
|
||||
"\t\tmethod Get -unexport {} {\n"
|
||||
"\t\t\treturn -code error -errorcode {TCLOO ABSTRACT_SLOT} \"unimplemented\"\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod Set list {\n"
|
||||
"\t\tmethod Set -unexport list {\n"
|
||||
"\t\t\treturn -code error -errorcode {TCLOO ABSTRACT_SLOT} \"unimplemented\"\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod Resolve list {\n"
|
||||
"\t\tmethod Resolve -unexport list {\n"
|
||||
"\t\t\treturn $list\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -set args {\n"
|
||||
"\t\tmethod -set -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\ttailcall my Set $args\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -append args {\n"
|
||||
"\t\tmethod -append -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
"\t\t\ttailcall my Set [list {*}$current {*}$args]\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -clear {} {tailcall my Set {}}\n"
|
||||
"\t\tmethod -prepend args {\n"
|
||||
"\t\tmethod -appendifnew -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
"\t\t\tset args [lmap a $args {\n"
|
||||
"\t\t\t\tset a [uplevel 1 [list $my Resolve $a]]\n"
|
||||
"\t\t\t\tif {$a in $current} continue\n"
|
||||
"\t\t\t\tset a\n"
|
||||
"\t\t\t}]\n"
|
||||
"\t\t\ttailcall my Set [list {*}$current {*}$args]\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -clear -export {} {tailcall my Set {}}\n"
|
||||
"\t\tmethod -prepend -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
"\t\t\ttailcall my Set [list {*}$args {*}$current]\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -remove args {\n"
|
||||
"\t\tmethod -remove -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
@@ -177,7 +187,7 @@ static const char *tclOOSetupScript =
|
||||
"\t\t\t}]\n"
|
||||
"\t\t}\n"
|
||||
"\t\tforward --default-operation my -append\n"
|
||||
"\t\tmethod unknown {args} {\n"
|
||||
"\t\tmethod unknown -unexport {args} {\n"
|
||||
"\t\t\tset def --default-operation\n"
|
||||
"\t\t\tif {[llength $args] == 0} {\n"
|
||||
"\t\t\t\ttailcall my $def\n"
|
||||
@@ -186,13 +196,12 @@ static const char *tclOOSetupScript =
|
||||
"\t\t\t}\n"
|
||||
"\t\t\tnext {*}$args\n"
|
||||
"\t\t}\n"
|
||||
"\t\texport -set -append -clear -prepend -remove\n"
|
||||
"\t\tunexport unknown destroy\n"
|
||||
"\t\tunexport destroy\n"
|
||||
"\t}\n"
|
||||
"\tobjdefine define::superclass forward --default-operation my -set\n"
|
||||
"\tobjdefine define::mixin forward --default-operation my -set\n"
|
||||
"\tobjdefine objdefine::mixin forward --default-operation my -set\n"
|
||||
"\tdefine object method <cloned> {originObject} {\n"
|
||||
"\tdefine object method <cloned> -unexport {originObject} {\n"
|
||||
"\t\tforeach p [info procs [info object namespace $originObject]::*] {\n"
|
||||
"\t\t\tset args [info args $p]\n"
|
||||
"\t\t\tset idx -1\n"
|
||||
@@ -219,7 +228,7 @@ static const char *tclOOSetupScript =
|
||||
"\t\t\t}\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tdefine class method <cloned> {originObject} {\n"
|
||||
"\tdefine class method <cloned> -unexport {originObject} {\n"
|
||||
"\t\tnext $originObject\n"
|
||||
"\t\t::oo::UpdateClassDelegatesAfterClone $originObject [self]\n"
|
||||
"\t}\n"
|
||||
@@ -235,7 +244,7 @@ static const char *tclOOSetupScript =
|
||||
"\t\t\t\t\t\t::return -code error -errorcode {TCLOO SINGLETON} \\\n"
|
||||
"\t\t\t\t\t\t\t\"may not destroy a singleton object\"\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\tmethod <cloned> {originObject} {\n"
|
||||
"\t\t\t\t\tmethod <cloned> -unexport {originObject} {\n"
|
||||
"\t\t\t\t\t\t::return -code error -errorcode {TCLOO SINGLETON} \\\n"
|
||||
"\t\t\t\t\t\t\t\"may not clone a singleton object\"\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
@@ -248,6 +257,226 @@ static const char *tclOOSetupScript =
|
||||
"\t\tsuperclass class\n"
|
||||
"\t\tunexport create createWithNamespace new\n"
|
||||
"\t}\n"
|
||||
"\t::namespace eval configuresupport {\n"
|
||||
"\t\tnamespace path ::tcl\n"
|
||||
"\t\tproc PropertyImpl {readslot writeslot args} {\n"
|
||||
"\t\t\tfor {set i 0} {$i < [llength $args]} {incr i} {\n"
|
||||
"\t\t\t\tset prop [lindex $args $i]\n"
|
||||
"\t\t\t\tif {[string match \"-*\" $prop]} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 \\\n"
|
||||
"\t\t\t\t\t\t-errorcode {TCLOO PROPERTY_FORMAT} \\\n"
|
||||
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must not begin with -\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tif {$prop ne [list $prop]} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 \\\n"
|
||||
"\t\t\t\t\t\t-errorcode {TCLOO PROPERTY_FORMAT} \\\n"
|
||||
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must be a simple word\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tif {[string first \"::\" $prop] != -1} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 \\\n"
|
||||
"\t\t\t\t\t\t-errorcode {TCLOO PROPERTY_FORMAT} \\\n"
|
||||
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must not contain namespace separators\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tif {[string match {*[()]*} $prop]} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 \\\n"
|
||||
"\t\t\t\t\t\t-errorcode {TCLOO PROPERTY_FORMAT} \\\n"
|
||||
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must not contain parentheses\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tset realprop [string cat \"-\" $prop]\n"
|
||||
"\t\t\t\tset getter [format {::set [my varname %s]} $prop]\n"
|
||||
"\t\t\t\tset setter [format {::set [my varname %s] $value} $prop]\n"
|
||||
"\t\t\t\tset kind readwrite\n"
|
||||
"\t\t\t\twhile {[set next [lindex $args [expr {$i + 1}]]\n"
|
||||
"\t\t\t\t\t\tstring match \"-*\" $next]} {\n"
|
||||
"\t\t\t\t\tset arg [lindex $args [incr i 2]]\n"
|
||||
"\t\t\t\t\tswitch [prefix match -error [list -level 2 -errorcode \\\n"
|
||||
"\t\t\t\t\t\t\t[list TCL LOOKUP INDEX option $next]] {-get -kind -set} $next] {\n"
|
||||
"\t\t\t\t\t\t-get {\n"
|
||||
"\t\t\t\t\t\t\tif {$i >= [llength $args]} {\n"
|
||||
"\t\t\t\t\t\t\t\treturn -code error -level 2 \\\n"
|
||||
"\t\t\t\t\t\t\t\t\t-errorcode {TCL WRONGARGS} \\\n"
|
||||
"\t\t\t\t\t\t\t\t\t\"missing body to go with -get option\"\n"
|
||||
"\t\t\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\t\t\tset getter $arg\n"
|
||||
"\t\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\t\t-set {\n"
|
||||
"\t\t\t\t\t\t\tif {$i >= [llength $args]} {\n"
|
||||
"\t\t\t\t\t\t\t\treturn -code error -level 2 \\\n"
|
||||
"\t\t\t\t\t\t\t\t\t-errorcode {TCL WRONGARGS} \\\n"
|
||||
"\t\t\t\t\t\t\t\t\t\"missing body to go with -set option\"\n"
|
||||
"\t\t\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\t\t\tset setter $arg\n"
|
||||
"\t\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\t\t-kind {\n"
|
||||
"\t\t\t\t\t\t\tif {$i >= [llength $args]} {\n"
|
||||
"\t\t\t\t\t\t\t\treturn -code error -level 2\\\n"
|
||||
"\t\t\t\t\t\t\t\t\t-errorcode {TCL WRONGARGS} \\\n"
|
||||
"\t\t\t\t\t\t\t\t\t\"missing kind value to go with -kind option\"\n"
|
||||
"\t\t\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\t\t\tset kind [prefix match -message \"kind\" -error [list \\\n"
|
||||
"\t\t\t\t\t\t\t\t\t-level 2 \\\n"
|
||||
"\t\t\t\t\t\t\t\t\t-errorcode [list TCL LOOKUP INDEX kind $arg]] {\n"
|
||||
"\t\t\t\t\t\t\t\treadable readwrite writable\n"
|
||||
"\t\t\t\t\t\t\t} $arg]\n"
|
||||
"\t\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tset reader <ReadProp$realprop>\n"
|
||||
"\t\t\t\tset writer <WriteProp$realprop>\n"
|
||||
"\t\t\t\tswitch $kind {\n"
|
||||
"\t\t\t\t\treadable {\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list $readslot -append $realprop]\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list $writeslot -remove $realprop]\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list method $reader -unexport {} $getter]\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\twritable {\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list $readslot -remove $realprop]\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list $writeslot -append $realprop]\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list method $writer -unexport {value} $setter]\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\treadwrite {\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list $readslot -append $realprop]\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list $writeslot -append $realprop]\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list method $reader -unexport {} $getter]\n"
|
||||
"\t\t\t\t\t\tuplevel 2 [list method $writer -unexport {value} $setter]\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t}\n"
|
||||
"\t\tnamespace eval configurableclass {\n"
|
||||
"\t\t\t::proc property args {\n"
|
||||
"\t\t\t\t::oo::configuresupport::PropertyImpl \\\n"
|
||||
"\t\t\t\t\t::oo::configuresupport::readableproperties \\\n"
|
||||
"\t\t\t\t\t::oo::configuresupport::writableproperties {*}$args\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
|
||||
"\t\t\t::namespace path ::oo::define\n"
|
||||
"\t\t\t::namespace export property\n"
|
||||
"\t\t}\n"
|
||||
"\t\tnamespace eval configurableobject {\n"
|
||||
"\t\t\t::proc property args {\n"
|
||||
"\t\t\t\t::oo::configuresupport::PropertyImpl \\\n"
|
||||
"\t\t\t\t\t::oo::configuresupport::objreadableproperties \\\n"
|
||||
"\t\t\t\t\t::oo::configuresupport::objwritableproperties {*}$args\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
|
||||
"\t\t\t::namespace path ::oo::objdefine\n"
|
||||
"\t\t\t::namespace export property\n"
|
||||
"\t\t}\n"
|
||||
"\t\tproc ReadAll {object my} {\n"
|
||||
"\t\t\tset result {}\n"
|
||||
"\t\t\tforeach prop [info object properties $object -all -readable] {\n"
|
||||
"\t\t\t\ttry {\n"
|
||||
"\t\t\t\t\tdict set result $prop [$my <ReadProp$prop>]\n"
|
||||
"\t\t\t\t} on error {msg opt} {\n"
|
||||
"\t\t\t\t\tdict set opt -level 2\n"
|
||||
"\t\t\t\t\treturn -options $opt $msg\n"
|
||||
"\t\t\t\t} on return {msg opt} {\n"
|
||||
"\t\t\t\t\tdict incr opt -level 2\n"
|
||||
"\t\t\t\t\treturn -options $opt $msg\n"
|
||||
"\t\t\t\t} on break {} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCLOO SHENANIGANS} \\\n"
|
||||
"\t\t\t\t\t\t\"property getter for $prop did a break\"\n"
|
||||
"\t\t\t\t} on continue {} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCLOO SHENANIGANS} \\\n"
|
||||
"\t\t\t\t\t\t\"property getter for $prop did a continue\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\treturn $result\n"
|
||||
"\t\t}\n"
|
||||
"\t\tproc ReadOne {object my propertyName} {\n"
|
||||
"\t\t\tset props [info object properties $object -all -readable]\n"
|
||||
"\t\t\ttry {\n"
|
||||
"\t\t\t\tset prop [prefix match -message \"property\" $props $propertyName]\n"
|
||||
"\t\t\t} on error {msg} {\n"
|
||||
"\t\t\t\tcatch {\n"
|
||||
"\t\t\t\t\tset wps [info object properties $object -all -writable]\n"
|
||||
"\t\t\t\t\tset wprop [prefix match $wps $propertyName]\n"
|
||||
"\t\t\t\t\tset msg \"property \\\"$wprop\\\" is write only\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\treturn -code error -level 2 -errorcode [list \\\n"
|
||||
"\t\t\t\t\t\tTCL LOOKUP INDEX property $propertyName] $msg\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\ttry {\n"
|
||||
"\t\t\t\tset value [$my <ReadProp$prop>]\n"
|
||||
"\t\t\t} on error {msg opt} {\n"
|
||||
"\t\t\t\tdict set opt -level 2\n"
|
||||
"\t\t\t\treturn -options $opt $msg\n"
|
||||
"\t\t\t} on return {msg opt} {\n"
|
||||
"\t\t\t\tdict incr opt -level 2\n"
|
||||
"\t\t\t\treturn -options $opt $msg\n"
|
||||
"\t\t\t} on break {} {\n"
|
||||
"\t\t\t\treturn -code error -level 2 -errorcode {TCLOO SHENANIGANS} \\\n"
|
||||
"\t\t\t\t\t\"property getter for $prop did a break\"\n"
|
||||
"\t\t\t} on continue {} {\n"
|
||||
"\t\t\t\treturn -code error -level 2 -errorcode {TCLOO SHENANIGANS} \\\n"
|
||||
"\t\t\t\t\t\"property getter for $prop did a continue\"\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\treturn $value\n"
|
||||
"\t\t}\n"
|
||||
"\t\tproc WriteMany {object my setterMap} {\n"
|
||||
"\t\t\tset props [info object properties $object -all -writable]\n"
|
||||
"\t\t\tforeach {prop value} $setterMap {\n"
|
||||
"\t\t\t\ttry {\n"
|
||||
"\t\t\t\t\tset prop [prefix match -message \"property\" $props $prop]\n"
|
||||
"\t\t\t\t} on error {msg} {\n"
|
||||
"\t\t\t\t\tcatch {\n"
|
||||
"\t\t\t\t\t\tset rps [info object properties $object -all -readable]\n"
|
||||
"\t\t\t\t\t\tset rprop [prefix match $rps $prop]\n"
|
||||
"\t\t\t\t\t\tset msg \"property \\\"$rprop\\\" is read only\"\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 -errorcode [list \\\n"
|
||||
"\t\t\t\t\t\t\tTCL LOOKUP INDEX property $prop] $msg\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\ttry {\n"
|
||||
"\t\t\t\t\t$my <WriteProp$prop> $value\n"
|
||||
"\t\t\t\t} on error {msg opt} {\n"
|
||||
"\t\t\t\t\tdict set opt -level 2\n"
|
||||
"\t\t\t\t\treturn -options $opt $msg\n"
|
||||
"\t\t\t\t} on return {msg opt} {\n"
|
||||
"\t\t\t\t\tdict incr opt -level 2\n"
|
||||
"\t\t\t\t\treturn -options $opt $msg\n"
|
||||
"\t\t\t\t} on break {} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCLOO SHENANIGANS} \\\n"
|
||||
"\t\t\t\t\t\t\"property setter for $prop did a break\"\n"
|
||||
"\t\t\t\t} on continue {} {\n"
|
||||
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCLOO SHENANIGANS} \\\n"
|
||||
"\t\t\t\t\t\t\"property setter for $prop did a continue\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\treturn\n"
|
||||
"\t\t}\n"
|
||||
"\t\t::oo::class create configurable {\n"
|
||||
"\t\t\tprivate variable my\n"
|
||||
"\t\t\tmethod configure -export args {\n"
|
||||
"\t\t\t\t::if {![::info exists my]} {\n"
|
||||
"\t\t\t\t\t::set my [::namespace which my]\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\t::if {[::llength $args] == 0} {\n"
|
||||
"\t\t\t\t\t::oo::configuresupport::ReadAll [self] $my\n"
|
||||
"\t\t\t\t} elseif {[::llength $args] == 1} {\n"
|
||||
"\t\t\t\t\t::oo::configuresupport::ReadOne [self] $my \\\n"
|
||||
"\t\t\t\t\t\t[::lindex $args 0]\n"
|
||||
"\t\t\t\t} elseif {[::llength $args] % 2 == 0} {\n"
|
||||
"\t\t\t\t\t::oo::configuresupport::WriteMany [self] $my $args\n"
|
||||
"\t\t\t\t} else {\n"
|
||||
"\t\t\t\t\t::return -code error -errorcode {TCL WRONGARGS} \\\n"
|
||||
"\t\t\t\t\t\t[::format {wrong # args: should be \"%s\"} \\\n"
|
||||
"\t\t\t\t\t\t\t\"[self] configure \?-option value ...\?\"]\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\tdefinitionnamespace -instance configurableobject\n"
|
||||
"\t\t\tdefinitionnamespace -class configurableclass\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tclass create configurable {\n"
|
||||
"\t\tsuperclass class\n"
|
||||
"\t\tconstructor {{definitionScript \"\"}} {\n"
|
||||
"\t\t\tnext {mixin ::oo::configuresupport::configurable}\n"
|
||||
"\t\t\tnext $definitionScript\n"
|
||||
"\t\t}\n"
|
||||
"\t\tdefinitionnamespace -class configuresupport::configurableclass\n"
|
||||
"\t}\n"
|
||||
"}\n"
|
||||
/* !END!: Do not edit above this line. */
|
||||
;
|
||||
|
||||
+161
-22
@@ -202,6 +202,9 @@ static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
|
||||
static void UpdateStringOfBignum(Tcl_Obj *objPtr);
|
||||
static int GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int copy, mp_int *bignumValue);
|
||||
static int SetDuplicatePureObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *dupPtr, Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr);
|
||||
|
||||
/*
|
||||
* Prototypes for the array hash key methods.
|
||||
@@ -996,7 +999,7 @@ TclDbDumpActiveObjects(
|
||||
tablePtr = tsdPtr->objThreadMap;
|
||||
|
||||
if (tablePtr != NULL) {
|
||||
fprintf(outFile, "total objects: %" TCL_Z_MODIFIER "u\n", tablePtr->numEntries);
|
||||
fprintf(outFile, "total objects: %" TCL_SIZE_MODIFIER "d\n", tablePtr->numEntries);
|
||||
for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL;
|
||||
hPtr = Tcl_NextHashEntry(&hSearch)) {
|
||||
ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);
|
||||
@@ -1050,7 +1053,7 @@ TclDbInitNewObj(
|
||||
{
|
||||
objPtr->refCount = 0;
|
||||
objPtr->typePtr = NULL;
|
||||
TclInitStringRep(objPtr, NULL, 0);
|
||||
TclInitEmptyStringRep(objPtr);
|
||||
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
@@ -1192,7 +1195,9 @@ Tcl_DbNewObj(
|
||||
TCL_UNUSED(const char *) /*file*/,
|
||||
TCL_UNUSED(int) /*line*/)
|
||||
{
|
||||
return Tcl_NewObj();
|
||||
Tcl_Obj *objPtr;
|
||||
TclNewObj(objPtr);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
|
||||
@@ -1523,6 +1528,14 @@ TclObjBeingDeleted(
|
||||
* Create and return a new object that is a duplicate of the argument
|
||||
* object.
|
||||
*
|
||||
* TclDuplicatePureObj --
|
||||
* Like Tcl_DuplicateObj, except that it converts the duplicate to the
|
||||
* specifid typ, does not duplicate the 'bytes'
|
||||
* field unless it is necessary, i.e. the duplicated Tcl_Obj provides no
|
||||
* updateStringProc. This can avoid an expensive memory allocation since
|
||||
* the data in the 'bytes' field of each Tcl_Obj must reside in allocated
|
||||
* memory.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to a newly created Tcl_Obj. This object
|
||||
* has reference count 0 and the same type, if any, as the source object
|
||||
@@ -1574,6 +1587,111 @@ Tcl_DuplicateObj(
|
||||
return dupPtr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclDuplicatePureObj --
|
||||
*
|
||||
* Duplicates a Tcl_Obj and converts the internal representation of the
|
||||
* duplicate to the given type, changing neither the 'bytes' field
|
||||
* nor the internal representation of the original object, and without
|
||||
* duplicating the bytes field unless necessary, i.e. unless the
|
||||
* duplicate provides no updateStringProc after conversion. This can
|
||||
* avoid an expensive memory allocation since the data in the 'bytes'
|
||||
* field of each Tcl_Obj must reside in allocated memory.
|
||||
*
|
||||
* Results:
|
||||
* A pointer to a newly-created Tcl_Obj or NULL if there was an error.
|
||||
* This object has reference count 0. Also:
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
int SetDuplicatePureObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *dupPtr,
|
||||
Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr)
|
||||
{
|
||||
char *bytes = objPtr->bytes;
|
||||
int status = TCL_OK;
|
||||
|
||||
TclInvalidateStringRep(dupPtr);
|
||||
assert(dupPtr->typePtr == NULL);
|
||||
|
||||
if (objPtr->typePtr && objPtr->typePtr->dupIntRepProc) {
|
||||
objPtr->typePtr->dupIntRepProc(objPtr, dupPtr);
|
||||
} else {
|
||||
dupPtr->internalRep = objPtr->internalRep;
|
||||
dupPtr->typePtr = objPtr->typePtr;
|
||||
}
|
||||
|
||||
if (typePtr != NULL && dupPtr->typePtr != typePtr) {
|
||||
if (bytes) {
|
||||
dupPtr->bytes = bytes;
|
||||
dupPtr->length = objPtr->length;
|
||||
}
|
||||
/* borrow bytes from original object */
|
||||
status = Tcl_ConvertToType(interp, dupPtr, typePtr);
|
||||
if (bytes) {
|
||||
dupPtr->bytes = NULL;
|
||||
dupPtr->length = 0;
|
||||
}
|
||||
if (status != TCL_OK) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* tclStringType is treated as a special case because a Tcl_Obj having this
|
||||
* type can not always update the string representation. This happens, for
|
||||
* example, when Tcl_GetCharLength() converts the internal representation
|
||||
* to tclStringType in order to store the number of characters, but does
|
||||
* not store enough information to generate the string representation.
|
||||
*
|
||||
* Perhaps in the future this can be remedied and this special treatment
|
||||
* removed.
|
||||
*/
|
||||
|
||||
|
||||
if (bytes && (dupPtr->typePtr == NULL
|
||||
|| dupPtr->typePtr->updateStringProc == NULL
|
||||
|| typePtr == &tclStringType
|
||||
)
|
||||
) {
|
||||
if (!TclAttemptInitStringRep(dupPtr, bytes, objPtr->length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"insufficient memory to initialize string", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
status = TCL_ERROR;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Tcl_Obj *
|
||||
TclDuplicatePureObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr
|
||||
) /* The object to duplicate. */
|
||||
{
|
||||
int status;
|
||||
Tcl_Obj *dupPtr;
|
||||
|
||||
TclNewObj(dupPtr);
|
||||
status = SetDuplicatePureObj(interp, dupPtr, objPtr, typePtr);
|
||||
if (status == TCL_OK) {
|
||||
return dupPtr;
|
||||
} else {
|
||||
Tcl_DecrRefCount(dupPtr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
TclSetDuplicateObj(
|
||||
Tcl_Obj *dupPtr,
|
||||
@@ -1670,7 +1788,7 @@ char *
|
||||
TclGetStringFromObj(
|
||||
Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
|
||||
* be returned. */
|
||||
int *lengthPtr) /* If non-NULL, the location where the string
|
||||
void *lengthPtr) /* If non-NULL, the location where the string
|
||||
* rep's byte array length should * be stored.
|
||||
* If NULL, no length is stored. */
|
||||
{
|
||||
@@ -1702,9 +1820,9 @@ TclGetStringFromObj(
|
||||
if (lengthPtr != NULL) {
|
||||
if (objPtr->length > INT_MAX) {
|
||||
Tcl_Panic("Tcl_GetStringFromObj with 'int' lengthPtr"
|
||||
" cannot handle such long strings. Please use 'size_t'");
|
||||
" cannot handle such long strings. Please use 'Tcl_Size'");
|
||||
}
|
||||
*lengthPtr = (int)objPtr->length;
|
||||
*(int *)lengthPtr = (int)objPtr->length;
|
||||
}
|
||||
return objPtr->bytes;
|
||||
}
|
||||
@@ -1806,7 +1924,7 @@ Tcl_InitStringRep(
|
||||
if (objPtr->bytes == NULL) {
|
||||
/* Start with no string rep */
|
||||
if (numBytes == 0) {
|
||||
TclInitStringRep(objPtr, NULL, 0);
|
||||
TclInitEmptyStringRep(objPtr);
|
||||
return objPtr->bytes;
|
||||
} else {
|
||||
objPtr->bytes = (char *)Tcl_AttemptAlloc(numBytes + 1);
|
||||
@@ -1833,7 +1951,7 @@ Tcl_InitStringRep(
|
||||
/* Start with non-empty string rep (allocated) */
|
||||
if (numBytes == 0) {
|
||||
Tcl_Free(objPtr->bytes);
|
||||
TclInitStringRep(objPtr, NULL, 0);
|
||||
TclInitEmptyStringRep(objPtr);
|
||||
return objPtr->bytes;
|
||||
} else {
|
||||
objPtr->bytes = (char *)Tcl_AttemptRealloc(objPtr->bytes,
|
||||
@@ -1901,8 +2019,9 @@ Tcl_HasStringRep(
|
||||
* Called to set the object's internal representation to match a
|
||||
* particular type.
|
||||
*
|
||||
* It is the caller's resonsibility to ensure that the given IntRep is
|
||||
* appropriate for the existing string.
|
||||
* It is the caller's responsibility to guarantee that
|
||||
* the value of the submitted internalrep is in agreement with
|
||||
* the value of any existing string rep.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1918,16 +2037,14 @@ void
|
||||
Tcl_StoreInternalRep(
|
||||
Tcl_Obj *objPtr, /* Object whose internal rep should be set. */
|
||||
const Tcl_ObjType *typePtr, /* New type for the object */
|
||||
const Tcl_ObjInternalRep *irPtr) /* New IntRep for the object */
|
||||
const Tcl_ObjInternalRep *irPtr) /* New internalrep for the object */
|
||||
{
|
||||
/* Clear out any existing IntRep. This is the point where shimmering, i.e.
|
||||
* repeated alteration of the type of the internal representation, may
|
||||
* occur. */
|
||||
/* Clear out any existing internalrep ( "shimmer" ) */
|
||||
TclFreeInternalRep(objPtr);
|
||||
|
||||
/* When irPtr == NULL, just leave objPtr with no IntRep for typePtr */
|
||||
/* When irPtr == NULL, just leave objPtr with no internalrep for typePtr */
|
||||
if (irPtr) {
|
||||
/* Copy the new IntRep into place */
|
||||
/* Copy the new internalrep into place */
|
||||
objPtr->internalRep = *irPtr;
|
||||
|
||||
/* Set the type to match */
|
||||
@@ -2163,8 +2280,8 @@ ParseBoolean(
|
||||
|
||||
if ((length == 0) || (length > 5)) {
|
||||
/*
|
||||
* Longest valid boolean string rep. is "false".
|
||||
*/
|
||||
* Longest valid boolean string rep. is "false".
|
||||
*/
|
||||
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -3398,7 +3515,7 @@ GetBignumFromObj(
|
||||
* bignum values are converted to empty string.
|
||||
*/
|
||||
if (objPtr->bytes == NULL) {
|
||||
TclInitStringRep(objPtr, NULL, 0);
|
||||
TclInitEmptyStringRep(objPtr);
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -3707,7 +3824,7 @@ Tcl_IncrRefCount(
|
||||
* Decrements the reference count of the object.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* The storage for objPtr may be freed.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -3722,6 +3839,28 @@ Tcl_DecrRefCount(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclUndoRefCount --
|
||||
*
|
||||
* Decrement the refCount of objPtr without causing it to be freed if it
|
||||
* drops from 1 to 0. This allows a function increment a refCount but
|
||||
* then decrement it and still be able to pass return it to a caller,
|
||||
* possibly with a refCount of 0. The caller must have previously
|
||||
* incremented the refCount.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
TclUndoRefCount(
|
||||
Tcl_Obj *objPtr) /* The object we are releasing a reference to. */
|
||||
{
|
||||
if (objPtr->refCount > 0) {
|
||||
--objPtr->refCount;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -3740,7 +3879,7 @@ int
|
||||
Tcl_IsShared(
|
||||
Tcl_Obj *objPtr) /* The object to test for being shared. */
|
||||
{
|
||||
return ((objPtr)->refCount + 1 > 2);
|
||||
return ((objPtr)->refCount > 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4183,7 +4322,7 @@ TclHashObjKey(
|
||||
* See [tcl-Feature Request #2958832]
|
||||
*/
|
||||
|
||||
if (length) {
|
||||
if (length > 0) {
|
||||
result = UCHAR(*string);
|
||||
while (--length) {
|
||||
result += (result << 3) + UCHAR(*++string);
|
||||
|
||||
+8
-7
@@ -214,7 +214,7 @@ Tcl_ParseCommand(
|
||||
* command. */
|
||||
char type; /* Result returned by CHAR_TYPE(*src). */
|
||||
Tcl_Token *tokenPtr; /* Pointer to token being filled in. */
|
||||
int wordIndex; /* Index of word token for current word. */
|
||||
Tcl_Size wordIndex; /* Index of word token for current word. */
|
||||
int terminators; /* CHAR_TYPE bits that indicate the end of a
|
||||
* command. */
|
||||
const char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to
|
||||
@@ -327,7 +327,7 @@ Tcl_ParseCommand(
|
||||
src = termPtr;
|
||||
numBytes = parsePtr->end - src;
|
||||
} else if (*src == '{') {
|
||||
int expIdx = wordIndex + 1;
|
||||
Tcl_Size expIdx = wordIndex + 1;
|
||||
Tcl_Token *expPtr;
|
||||
|
||||
if (Tcl_ParseBraces(interp, src, numBytes, parsePtr, 1,
|
||||
@@ -345,7 +345,7 @@ Tcl_ParseCommand(
|
||||
expPtr = &parsePtr->tokenPtr[expIdx];
|
||||
if ((0 == expandWord)
|
||||
/* Haven't seen prefix already */
|
||||
&& (expIdx + 1 == (int)parsePtr->numTokens)
|
||||
&& (expIdx + 1 == parsePtr->numTokens)
|
||||
/* Only one token */
|
||||
&& (((1 == expPtr->size)
|
||||
/* Same length as prefix */
|
||||
@@ -380,7 +380,7 @@ Tcl_ParseCommand(
|
||||
|
||||
tokenPtr = &parsePtr->tokenPtr[wordIndex];
|
||||
tokenPtr->size = src - tokenPtr->start;
|
||||
tokenPtr->numComponents = (int)parsePtr->numTokens - (wordIndex + 1);
|
||||
tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
|
||||
if (expandWord) {
|
||||
Tcl_Size i;
|
||||
int isLiteral = 1;
|
||||
@@ -407,7 +407,8 @@ Tcl_ParseCommand(
|
||||
}
|
||||
|
||||
if (isLiteral) {
|
||||
int elemCount = 0, code = TCL_OK, literal = 1;
|
||||
Tcl_Size elemCount = 0;
|
||||
int code = TCL_OK, literal = 1;
|
||||
const char *nextElem, *listEnd, *elemStart;
|
||||
|
||||
/*
|
||||
@@ -471,8 +472,8 @@ Tcl_ParseCommand(
|
||||
*/
|
||||
|
||||
const char *listStart;
|
||||
int growthNeeded = wordIndex + 2*elemCount
|
||||
- (int)parsePtr->numTokens;
|
||||
Tcl_Size growthNeeded = wordIndex + 2*elemCount
|
||||
- parsePtr->numTokens;
|
||||
|
||||
parsePtr->numWords += elemCount - 1;
|
||||
if (growthNeeded > 0) {
|
||||
|
||||
@@ -2330,10 +2330,15 @@ UpdateStringOfFsPath(
|
||||
Tcl_Obj *copy;
|
||||
|
||||
if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) {
|
||||
Tcl_Panic("Called UpdateStringOfFsPath with invalid object");
|
||||
if (fsPathPtr->translatedPathPtr == NULL) {
|
||||
Tcl_Panic("Called UpdateStringOfFsPath with invalid object");
|
||||
} else {
|
||||
copy = Tcl_DuplicateObj(fsPathPtr->translatedPathPtr);
|
||||
}
|
||||
} else {
|
||||
copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr);
|
||||
}
|
||||
|
||||
copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr);
|
||||
if (Tcl_IsShared(copy)) {
|
||||
copy = Tcl_DuplicateObj(copy);
|
||||
}
|
||||
@@ -2342,7 +2347,7 @@ UpdateStringOfFsPath(
|
||||
/* Steal copy's string rep */
|
||||
pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
|
||||
pathPtr->length = cwdLen;
|
||||
TclInitStringRep(copy, NULL, 0);
|
||||
TclInitEmptyStringRep(copy);
|
||||
TclDecrRefCount(copy);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -495,7 +495,7 @@ Tcl_SetErrorCode(
|
||||
*/
|
||||
|
||||
va_start(argList, interp);
|
||||
errorObj = Tcl_NewObj();
|
||||
TclNewObj(errorObj);
|
||||
|
||||
/*
|
||||
* Scan through the arguments one at a time, appending them to the
|
||||
|
||||
+59
-17
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclTomMath.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Flag values used by Tcl_ScanObjCmd.
|
||||
@@ -258,7 +259,7 @@ ValidateFormat(
|
||||
int *totalSubs) /* The number of variables that will be
|
||||
* required. */
|
||||
{
|
||||
int gotXpg, gotSequential, value, i, flags;
|
||||
int gotXpg, gotSequential, i, flags;
|
||||
char *end;
|
||||
Tcl_UniChar ch = 0;
|
||||
int objIndex, xpgSize, nspace = numVars;
|
||||
@@ -306,7 +307,8 @@ ValidateFormat(
|
||||
* format string.
|
||||
*/
|
||||
|
||||
value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */
|
||||
/* assert(value is >= 0) because of the isdigit() check above */
|
||||
unsigned long long ull = strtoull(format-1, &end, 10); /* INTL: "C" locale. */
|
||||
if (*end != '$') {
|
||||
goto notXpg;
|
||||
}
|
||||
@@ -316,17 +318,22 @@ ValidateFormat(
|
||||
if (gotSequential) {
|
||||
goto mixedXPG;
|
||||
}
|
||||
objIndex = value - 1;
|
||||
if ((objIndex < 0) || (numVars && (objIndex >= numVars))) {
|
||||
/* >=INT_MAX because 9.0 does not support more than INT_MAX-1 args */
|
||||
if (ull == 0 || ull >= INT_MAX) {
|
||||
goto badIndex;
|
||||
} else if (numVars == 0) {
|
||||
}
|
||||
objIndex = (int) ull - 1;
|
||||
if (numVars && (objIndex >= numVars)) {
|
||||
goto badIndex;
|
||||
}
|
||||
else if (numVars == 0) {
|
||||
/*
|
||||
* In the case where no vars are specified, the user can
|
||||
* specify %9999$ legally, so we have to consider special
|
||||
* rules for growing the assign array. 'value' is guaranteed
|
||||
* to be > 0.
|
||||
* rules for growing the assign array. 'ull' is guaranteed
|
||||
* to be > 0 and < INT_MAX as per checks above.
|
||||
*/
|
||||
xpgSize = (xpgSize > value) ? xpgSize : value;
|
||||
xpgSize = (xpgSize > (int)ull) ? xpgSize : (int)ull;
|
||||
}
|
||||
goto xpgCheckDone;
|
||||
}
|
||||
@@ -348,7 +355,22 @@ ValidateFormat(
|
||||
*/
|
||||
|
||||
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
|
||||
value = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */
|
||||
/* Note ull >= 0 because of isdigit check above */
|
||||
unsigned long long ull;
|
||||
ull = strtoull(
|
||||
format - 1, (char **)&format, 10); /* INTL: "C" locale. */
|
||||
/* Note >=, not >, to leave room for a nul */
|
||||
if (ull >= TCL_SIZE_MAX) {
|
||||
Tcl_SetObjResult(
|
||||
interp,
|
||||
Tcl_ObjPrintf("specified field width %" TCL_LL_MODIFIER
|
||||
"u exceeds limit %" TCL_SIZE_MODIFIER "d.",
|
||||
ull,
|
||||
(Tcl_Size)TCL_SIZE_MAX-1));
|
||||
Tcl_SetErrorCode(
|
||||
interp, "TCL", "FORMAT", "WIDTHLIMIT", NULL);
|
||||
goto error;
|
||||
}
|
||||
flags |= SCAN_WIDTH;
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
@@ -473,7 +495,7 @@ ValidateFormat(
|
||||
* guaranteed to be at least one larger than objIndex.
|
||||
*/
|
||||
|
||||
value = nspace;
|
||||
int nspaceOrig = nspace;
|
||||
if (xpgSize) {
|
||||
nspace = xpgSize;
|
||||
} else {
|
||||
@@ -481,7 +503,7 @@ ValidateFormat(
|
||||
}
|
||||
nassign = (int *)TclStackRealloc(interp, nassign,
|
||||
nspace * sizeof(int));
|
||||
for (i = value; i < nspace; i++) {
|
||||
for (i = nspaceOrig; i < nspace; i++) {
|
||||
nassign[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -575,7 +597,8 @@ Tcl_ScanObjCmd(
|
||||
long value;
|
||||
const char *string, *end, *baseString;
|
||||
char op = 0;
|
||||
int width, underflow = 0;
|
||||
int underflow = 0;
|
||||
Tcl_Size width;
|
||||
Tcl_WideInt wideValue;
|
||||
Tcl_UniChar ch = 0, sch = 0;
|
||||
Tcl_Obj **objs = NULL, *objPtr = NULL;
|
||||
@@ -670,6 +693,7 @@ Tcl_ScanObjCmd(
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
} else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
|
||||
char *formatEnd;
|
||||
/* Note currently XPG3 range limited to INT_MAX to match type of objc */
|
||||
value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */
|
||||
if (*formatEnd == '$') {
|
||||
format = formatEnd+1;
|
||||
@@ -683,7 +707,10 @@ Tcl_ScanObjCmd(
|
||||
*/
|
||||
|
||||
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
|
||||
width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */
|
||||
unsigned long long ull;
|
||||
ull = strtoull(format-1, (char **) &format, 10); /* INTL: "C" locale. */
|
||||
assert(ull <= TCL_SIZE_MAX); /* Else ValidateFormat should've error'ed */
|
||||
width = (Tcl_Size)ull;
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
} else {
|
||||
width = 0;
|
||||
@@ -1067,12 +1094,16 @@ Tcl_ScanObjCmd(
|
||||
} else {
|
||||
/*
|
||||
* Here no vars were specified, we want a list returned (inline scan)
|
||||
* We create an empty Tcl_Obj to fill missing values rather than
|
||||
* allocating a new Tcl_Obj every time. See test scan-bigdata-XX.
|
||||
*/
|
||||
|
||||
Tcl_Obj *emptyObj;
|
||||
TclNewObj(emptyObj);
|
||||
Tcl_IncrRefCount(emptyObj);
|
||||
TclNewObj(objPtr);
|
||||
for (i = 0; i < totalVars; i++) {
|
||||
for (i = 0; code == TCL_OK && i < totalVars; i++) {
|
||||
if (objs[i] != NULL) {
|
||||
Tcl_ListObjAppendElement(NULL, objPtr, objs[i]);
|
||||
code = Tcl_ListObjAppendElement(interp, objPtr, objs[i]);
|
||||
Tcl_DecrRefCount(objs[i]);
|
||||
} else {
|
||||
/*
|
||||
@@ -1080,9 +1111,20 @@ Tcl_ScanObjCmd(
|
||||
* empty strings for these.
|
||||
*/
|
||||
|
||||
Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewObj());
|
||||
code = Tcl_ListObjAppendElement(interp, objPtr, emptyObj);
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(emptyObj);
|
||||
if (code != TCL_OK) {
|
||||
/* If error'ed out, free up remaining. i contains last index freed */
|
||||
while (++i < totalVars) {
|
||||
if (objs[i] != NULL) {
|
||||
Tcl_DecrRefCount(objs[i]);
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
objPtr = NULL;
|
||||
}
|
||||
}
|
||||
if (objs != NULL) {
|
||||
Tcl_Free(objs);
|
||||
|
||||
+143
-126
@@ -1,29 +1,27 @@
|
||||
/*
|
||||
* tclStringObj.c --
|
||||
*
|
||||
* This file contains functions that implement string operations on Tcl
|
||||
* objects. Some string operations work with UTF strings and others
|
||||
* require Unicode format. Functions that require knowledge of the width
|
||||
* of each character, such as indexing, operate on Unicode data.
|
||||
* This file contains functions that implement string operations on Tcl
|
||||
* objects. Some string operations work with UTF-8 encoding forms.
|
||||
* Functions that require knowledge of the width of each character,
|
||||
* such as indexing, operate on fixed width encoding forms such as UTF-32.
|
||||
*
|
||||
* A Unicode string is an internationalized string. Conceptually, a
|
||||
* Unicode string is an array of 16-bit quantities organized as a
|
||||
* sequence of properly formed UTF-8 characters. There is a one-to-one
|
||||
* map between Unicode and UTF characters. Because Unicode characters
|
||||
* have a fixed width, operations such as indexing operate on Unicode
|
||||
* data. The String object is optimized for the case where each UTF char
|
||||
* Conceptually, a string is a sequence of Unicode code points. Internally
|
||||
* it may be stored in an encoding form such as a modified version of
|
||||
* UTF-8 or UTF-16 (when TCL_UTF_MAX=3) or UTF-32.
|
||||
*
|
||||
* The String object is optimized for the case where each UTF char
|
||||
* in a string is only one byte. In this case, we store the value of
|
||||
* numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
|
||||
* is explicitly called).
|
||||
* numChars, but we don't store the fixed form encoding (unless
|
||||
* Tcl_GetUnicode is explicitly called).
|
||||
*
|
||||
* The String object type stores one or both formats. The default
|
||||
* behavior is to store UTF. Once Unicode is calculated by a function, it
|
||||
* is stored in the internal rep for future access (without an additional
|
||||
* O(n) cost).
|
||||
* The String object type stores one or both formats. The default
|
||||
* behavior is to store UTF-8. Once UTF-16/UTF32 is calculated, it is
|
||||
* stored in the internal rep for future access (without an additional
|
||||
* O(n) cost).
|
||||
*
|
||||
* To allow many appends to be done to an object without constantly
|
||||
* reallocating the space for the string or Unicode representation, we
|
||||
* allocate double the space for the string or Unicode and use the
|
||||
* reallocating space, we allocate double the space and use the
|
||||
* internal representation to keep track of how much space is used vs.
|
||||
* allocated.
|
||||
*
|
||||
@@ -61,8 +59,8 @@ static void ExtendUnicodeRepWithString(Tcl_Obj *objPtr,
|
||||
Tcl_Size numAppendChars);
|
||||
static void FillUnicodeRep(Tcl_Obj *objPtr);
|
||||
static void FreeStringInternalRep(Tcl_Obj *objPtr);
|
||||
static void GrowStringBuffer(Tcl_Obj *objPtr, size_t needed, int flag);
|
||||
static void GrowUnicodeBuffer(Tcl_Obj *objPtr, size_t needed);
|
||||
static void GrowStringBuffer(Tcl_Obj *objPtr, Tcl_Size needed, int flag);
|
||||
static void GrowUnicodeBuffer(Tcl_Obj *objPtr, Tcl_Size needed);
|
||||
static int SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static void SetUnicodeObj(Tcl_Obj *objPtr,
|
||||
const Tcl_UniChar *unicode, Tcl_Size numChars);
|
||||
@@ -133,8 +131,8 @@ const Tcl_ObjType tclStringType = {
|
||||
static void
|
||||
GrowStringBuffer(
|
||||
Tcl_Obj *objPtr,
|
||||
size_t needed,
|
||||
int flag)
|
||||
Tcl_Size needed, /* Not including terminating nul */
|
||||
int flag) /* If 0, try to overallocate */
|
||||
{
|
||||
/*
|
||||
* Preconditions:
|
||||
@@ -144,45 +142,35 @@ GrowStringBuffer(
|
||||
*/
|
||||
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
char *ptr = NULL;
|
||||
size_t attempt;
|
||||
char *ptr;
|
||||
Tcl_Size capacity;
|
||||
|
||||
assert(needed <= TCL_SIZE_MAX - 1);
|
||||
needed += 1; /* Include terminating nul */
|
||||
|
||||
if (objPtr->bytes == &tclEmptyString) {
|
||||
objPtr->bytes = NULL;
|
||||
}
|
||||
/*
|
||||
* In code below, note 'capacity' and 'needed' include terminating nul,
|
||||
* while stringPtr->allocated does not.
|
||||
*/
|
||||
if (flag == 0 || stringPtr->allocated > 0) {
|
||||
attempt = 2 * needed;
|
||||
ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt + 1U);
|
||||
if (ptr == NULL) {
|
||||
/*
|
||||
* Take care computing the amount of modest growth to avoid
|
||||
* overflow into invalid argument values for attempt.
|
||||
*/
|
||||
|
||||
size_t limit = INT_MAX - needed;
|
||||
size_t extra = needed - objPtr->length + TCL_MIN_GROWTH;
|
||||
size_t growth = (extra > limit) ? limit : extra;
|
||||
|
||||
attempt = needed + growth;
|
||||
ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt + 1U);
|
||||
}
|
||||
ptr = (char *)TclReallocEx(objPtr->bytes, needed, &capacity);
|
||||
} else {
|
||||
/* Allocate exact size */
|
||||
ptr = (char *)Tcl_Realloc(objPtr->bytes, needed);
|
||||
capacity = needed;
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
/*
|
||||
* First allocation - just big enough; or last chance fallback.
|
||||
*/
|
||||
|
||||
attempt = needed;
|
||||
ptr = (char *)Tcl_Realloc(objPtr->bytes, attempt + 1U);
|
||||
}
|
||||
objPtr->bytes = ptr;
|
||||
stringPtr->allocated = attempt;
|
||||
stringPtr->allocated = capacity - 1; /* Does not include slot for end nul */
|
||||
}
|
||||
|
||||
static void
|
||||
GrowUnicodeBuffer(
|
||||
Tcl_Obj *objPtr,
|
||||
size_t needed)
|
||||
Tcl_Size needed)
|
||||
{
|
||||
/*
|
||||
* Preconditions:
|
||||
@@ -190,39 +178,32 @@ GrowUnicodeBuffer(
|
||||
* needed > stringPtr->maxChars
|
||||
*/
|
||||
|
||||
String *ptr = NULL, *stringPtr = GET_STRING(objPtr);
|
||||
size_t attempt;
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
Tcl_Size maxChars;
|
||||
|
||||
/* Note STRING_MAXCHARS already takes into account space for nul */
|
||||
if (needed > STRING_MAXCHARS) {
|
||||
Tcl_Panic("max size for a Tcl unicode rep (%" TCL_Z_MODIFIER "d bytes) exceeded",
|
||||
STRING_MAXCHARS);
|
||||
}
|
||||
if (stringPtr->maxChars > 0) {
|
||||
/*
|
||||
* Subsequent appends - apply the growth algorithm.
|
||||
*/
|
||||
|
||||
attempt = 2 * needed;
|
||||
ptr = stringAttemptRealloc(stringPtr, attempt);
|
||||
if (ptr == NULL) {
|
||||
/*
|
||||
* Take care computing the amount of modest growth to avoid
|
||||
* overflow into invalid argument values for attempt.
|
||||
*/
|
||||
|
||||
size_t extra = needed - stringPtr->numChars
|
||||
+ TCL_MIN_UNICHAR_GROWTH;
|
||||
|
||||
attempt = needed + extra;
|
||||
ptr = stringAttemptRealloc(stringPtr, attempt);
|
||||
}
|
||||
/* Expansion - try allocating extra space */
|
||||
stringPtr = (String *)TclReallocElemsEx(stringPtr,
|
||||
needed + 1, /* +1 for nul */
|
||||
sizeof(Tcl_UniChar),
|
||||
offsetof(String, unicode),
|
||||
&maxChars);
|
||||
maxChars -= 1; /* End nul not included */
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
else {
|
||||
/*
|
||||
* First allocation - just big enough; or last chance fallback.
|
||||
* First allocation - just big enough. Note needed does
|
||||
* not include terminating nul but STRING_SIZE does
|
||||
*/
|
||||
|
||||
attempt = needed;
|
||||
ptr = stringRealloc(stringPtr, attempt);
|
||||
stringPtr = (String *)Tcl_Realloc(stringPtr, STRING_SIZE(needed));
|
||||
maxChars = needed;
|
||||
}
|
||||
stringPtr = ptr;
|
||||
stringPtr->maxChars = attempt;
|
||||
stringPtr->maxChars = maxChars;
|
||||
SET_STRING(objPtr, stringPtr);
|
||||
}
|
||||
|
||||
@@ -515,6 +496,11 @@ TclCheckEmptyString(
|
||||
return TCL_EMPTYSTRING_YES;
|
||||
}
|
||||
|
||||
if (TclIsPureByteArray(objPtr)
|
||||
&& Tcl_GetCharLength(objPtr) == 0) {
|
||||
return TCL_EMPTYSTRING_YES;
|
||||
}
|
||||
|
||||
if (TclListObjIsCanonical(objPtr)) {
|
||||
TclListObjLengthM(NULL, objPtr, &length);
|
||||
return length == 0;
|
||||
@@ -624,7 +610,7 @@ Tcl_GetUniChar(
|
||||
|
||||
int
|
||||
TclGetUniChar(
|
||||
Tcl_Obj *objPtr, /* The object to get the Unicode charater
|
||||
Tcl_Obj *objPtr, /* The object to get the Unicode character
|
||||
* from. */
|
||||
Tcl_Size index) /* Get the index'th Unicode character. */
|
||||
{
|
||||
@@ -685,7 +671,7 @@ Tcl_UniChar *
|
||||
TclGetUnicodeFromObj(
|
||||
Tcl_Obj *objPtr, /* The object to find the Unicode string
|
||||
* for. */
|
||||
int *lengthPtr) /* If non-NULL, the location where the string
|
||||
void *lengthPtr) /* If non-NULL, the location where the string
|
||||
* rep's Tcl_UniChar length should be stored. If
|
||||
* NULL, no length is stored. */
|
||||
{
|
||||
@@ -704,7 +690,7 @@ TclGetUnicodeFromObj(
|
||||
Tcl_Panic("Tcl_GetUnicodeFromObj with 'int' lengthPtr"
|
||||
" cannot handle such long strings. Please use 'Tcl_Size'");
|
||||
}
|
||||
*lengthPtr = (int)stringPtr->numChars;
|
||||
*(int *)lengthPtr = (int)stringPtr->numChars;
|
||||
}
|
||||
return stringPtr->unicode;
|
||||
}
|
||||
@@ -765,7 +751,7 @@ Tcl_GetRange(
|
||||
Tcl_Size length = 0;
|
||||
|
||||
if (first < 0) {
|
||||
first = TCL_INDEX_START;
|
||||
first = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1096,9 +1082,9 @@ Tcl_AttemptSetObjLength(
|
||||
char *newBytes;
|
||||
|
||||
if (objPtr->bytes == &tclEmptyString) {
|
||||
newBytes = (char *)Tcl_AttemptAlloc(length + 1);
|
||||
newBytes = (char *)Tcl_AttemptAlloc(length + 1U);
|
||||
} else {
|
||||
newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1);
|
||||
newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1U);
|
||||
}
|
||||
if (newBytes == NULL) {
|
||||
return 0;
|
||||
@@ -1303,7 +1289,7 @@ Tcl_AppendLimitedToObj(
|
||||
Tcl_GetUnicode(objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
}
|
||||
if (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) {
|
||||
if (stringPtr->hasUnicode && (stringPtr->numChars) > 0) {
|
||||
AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
|
||||
} else {
|
||||
AppendUtfToUtfRep(objPtr, bytes, toCopy);
|
||||
@@ -1314,7 +1300,7 @@ Tcl_AppendLimitedToObj(
|
||||
}
|
||||
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
if (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) {
|
||||
if (stringPtr->hasUnicode && (stringPtr->numChars) > 0) {
|
||||
AppendUtfToUnicodeRep(objPtr, ellipsis, eLen);
|
||||
} else {
|
||||
AppendUtfToUtfRep(objPtr, ellipsis, eLen);
|
||||
@@ -1431,26 +1417,26 @@ Tcl_AppendObjToObj(
|
||||
Tcl_Size appendNumChars = TCL_INDEX_NONE;
|
||||
const char *bytes;
|
||||
|
||||
/*
|
||||
* Special case: second object is standard-empty is fast case. We know
|
||||
* that appending nothing to anything leaves that starting anything...
|
||||
*/
|
||||
|
||||
if (appendObjPtr->bytes == &tclEmptyString) {
|
||||
if (TclCheckEmptyString(appendObjPtr) == TCL_EMPTYSTRING_YES) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle append of one ByteArray object to another as a special case.
|
||||
* Note that we only do this when the objects are pure so that the
|
||||
* bytearray faithfully represent the true value; Otherwise appending the
|
||||
* byte arrays together could lose information;
|
||||
*/
|
||||
if (TclCheckEmptyString(objPtr) == TCL_EMPTYSTRING_YES) {
|
||||
TclSetDuplicateObj(objPtr, appendObjPtr);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
|
||||
&& TclIsPureByteArray(appendObjPtr)) {
|
||||
if (
|
||||
TclIsPureByteArray(appendObjPtr)
|
||||
&& (TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
|
||||
) {
|
||||
/*
|
||||
* You might expect the code here to be
|
||||
* Both bytearray objects are pure, so the second internal bytearray value
|
||||
* can be appended to the first, with no need to modify the "bytes" field.
|
||||
*/
|
||||
|
||||
/*
|
||||
* One might expect the code here to be
|
||||
*
|
||||
* bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length);
|
||||
* TclAppendBytesToByteArray(objPtr, bytes, length);
|
||||
@@ -1963,7 +1949,7 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
gotSequential = 1;
|
||||
}
|
||||
if (objIndex < 0 || objIndex >= objc) {
|
||||
if ((objIndex < 0) || (objIndex >= objc)) {
|
||||
msg = badIndex[gotXpg];
|
||||
errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH";
|
||||
goto errorMsg;
|
||||
@@ -2006,12 +1992,16 @@ Tcl_AppendFormatToObj(
|
||||
|
||||
width = 0;
|
||||
if (isdigit(UCHAR(ch))) {
|
||||
width = strtoul(format, &end, 10);
|
||||
if (width < 0) {
|
||||
/* Note ull will be >= 0 because of isdigit check above */
|
||||
unsigned long long ull;
|
||||
ull = strtoull(format, &end, 10);
|
||||
/* Comparison is >=, not >, to leave room for nul */
|
||||
if (ull >= TCL_SIZE_MAX) {
|
||||
msg = overflow;
|
||||
errCode = "OVERFLOW";
|
||||
goto errorMsg;
|
||||
}
|
||||
width = (Tcl_Size)ull;
|
||||
format = end;
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
} else if (ch == '*') {
|
||||
@@ -2048,7 +2038,16 @@ Tcl_AppendFormatToObj(
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
if (isdigit(UCHAR(ch))) {
|
||||
precision = strtoul(format, &end, 10);
|
||||
/* Note ull will be >= 0 because of isdigit check above */
|
||||
unsigned long long ull;
|
||||
ull = strtoull(format, &end, 10);
|
||||
/* Comparison is >=, not >, to leave room for nul */
|
||||
if (ull >= TCL_SIZE_MAX) {
|
||||
msg = overflow;
|
||||
errCode = "OVERFLOW";
|
||||
goto errorMsg;
|
||||
}
|
||||
precision = (Tcl_Size)ull;
|
||||
format = end;
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
} else if (ch == '*') {
|
||||
@@ -2539,7 +2538,7 @@ Tcl_AppendFormatToObj(
|
||||
goto errorMsg;
|
||||
}
|
||||
bytes = TclGetString(segment);
|
||||
if (!Tcl_AttemptSetObjLength(segment, sprintf(bytes, spec, d))) {
|
||||
if (!Tcl_AttemptSetObjLength(segment, snprintf(bytes, segment->length, spec, d))) {
|
||||
msg = overflow;
|
||||
errCode = "OVERFLOW";
|
||||
goto errorMsg;
|
||||
@@ -2735,12 +2734,16 @@ AppendPrintfToObjVA(
|
||||
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
if (sizeof(size_t) == sizeof(Tcl_WideInt)) {
|
||||
size = 2;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 'c':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 'd':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'x':
|
||||
case 'X':
|
||||
seekingConversion = 0;
|
||||
@@ -3092,7 +3095,6 @@ TclStringRepeat(
|
||||
(count - done) * length);
|
||||
}
|
||||
return objResultPtr;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3121,18 +3123,23 @@ TclStringCat(
|
||||
{
|
||||
Tcl_Obj *objResultPtr, * const *ov;
|
||||
int binary = 1;
|
||||
Tcl_Size oc;
|
||||
Tcl_Size length = 0;
|
||||
Tcl_Size oc, length = 0;
|
||||
int allowUniChar = 1, requestUniChar = 0, forceUniChar = 0;
|
||||
Tcl_Size first = objc - 1; /* Index of first value possibly not empty */
|
||||
Tcl_Size last = 0; /* Index of last value possibly not empty */
|
||||
int inPlace = flags & TCL_STRING_IN_PLACE;
|
||||
int inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);
|
||||
|
||||
/* assert ( objc >= 0 ) */
|
||||
|
||||
if (objc <= 1) {
|
||||
/* Negative (shouldn't be), one or no objects; return first or empty */
|
||||
return objc == 1 ? objv[0] : Tcl_NewObj();
|
||||
if (objc != 1) {
|
||||
/* Negative (shouldn't be) no objects; return empty */
|
||||
Tcl_Obj *obj;
|
||||
TclNewObj(obj);
|
||||
return obj;
|
||||
}
|
||||
/* One object; return first */
|
||||
return objv[0];
|
||||
}
|
||||
|
||||
/* assert ( objc >= 2 ) */
|
||||
@@ -3254,7 +3261,8 @@ TclStringCat(
|
||||
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
if (objPtr->bytes == NULL) {
|
||||
if (objPtr->bytes == NULL
|
||||
&& TclCheckEmptyString(objPtr) != TCL_EMPTYSTRING_YES) {
|
||||
/* No string rep; Take the chance we can avoid making it */
|
||||
pendingPtr = objPtr;
|
||||
} else {
|
||||
@@ -3330,6 +3338,7 @@ TclStringCat(
|
||||
}
|
||||
|
||||
objv += first; objc = (last - first + 1);
|
||||
inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);
|
||||
|
||||
if (binary) {
|
||||
/* Efficiently produce a pure byte array result */
|
||||
@@ -3340,7 +3349,7 @@ TclStringCat(
|
||||
* failure to allocate enough space. Following stanza may panic.
|
||||
*/
|
||||
|
||||
if (inPlace && !Tcl_IsShared(*objv)) {
|
||||
if (inPlace) {
|
||||
Tcl_Size start = 0;
|
||||
|
||||
objResultPtr = *objv++; objc--;
|
||||
@@ -3370,7 +3379,7 @@ TclStringCat(
|
||||
/* Efficiently produce a pure Tcl_UniChar array result */
|
||||
Tcl_UniChar *dst;
|
||||
|
||||
if (inPlace && !Tcl_IsShared(*objv)) {
|
||||
if (inPlace) {
|
||||
Tcl_Size start;
|
||||
|
||||
objResultPtr = *objv++; objc--;
|
||||
@@ -3421,7 +3430,7 @@ TclStringCat(
|
||||
/* Efficiently concatenate string reps */
|
||||
char *dst;
|
||||
|
||||
if (inPlace && !Tcl_IsShared(*objv)) {
|
||||
if (inPlace) {
|
||||
Tcl_Size start;
|
||||
|
||||
objResultPtr = *objv++; objc--;
|
||||
@@ -3430,7 +3439,7 @@ TclStringCat(
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes",
|
||||
"concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
|
||||
length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
@@ -3446,7 +3455,7 @@ TclStringCat(
|
||||
Tcl_DecrRefCount(objResultPtr);
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes",
|
||||
"concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
|
||||
length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
@@ -3512,6 +3521,7 @@ TclStringCmp(
|
||||
if ((reqlength == 0) || (value1Ptr == value2Ptr)) {
|
||||
/*
|
||||
* Always match at 0 chars of if it is the same obj.
|
||||
* Note: as documented reqlength negative means it is ignored
|
||||
*/
|
||||
match = 0;
|
||||
} else {
|
||||
@@ -3566,11 +3576,11 @@ TclStringCmp(
|
||||
memCmpFn = memcmp;
|
||||
s1len *= sizeof(Tcl_UniChar);
|
||||
s2len *= sizeof(Tcl_UniChar);
|
||||
if (reqlength != TCL_INDEX_NONE) {
|
||||
if (reqlength > 0) {
|
||||
reqlength *= sizeof(Tcl_UniChar);
|
||||
}
|
||||
} else {
|
||||
memCmpFn = (memCmpFn_t) TclUniCharNcmp;
|
||||
memCmpFn = (memCmpFn_t)(void *)TclUniCharNcmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3610,7 +3620,7 @@ TclStringCmp(
|
||||
s1 = Tcl_GetStringFromObj(value1Ptr, &s1len);
|
||||
s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
|
||||
}
|
||||
if (!nocase && checkEq && reqlength == TCL_INDEX_NONE) {
|
||||
if (!nocase && checkEq && reqlength < 0) {
|
||||
/*
|
||||
* When we have equal-length we can check only for
|
||||
* (in)equality. We can use memcmp in all (n)eq cases because
|
||||
@@ -3627,12 +3637,12 @@ TclStringCmp(
|
||||
* length was requested.
|
||||
*/
|
||||
|
||||
if ((reqlength == TCL_INDEX_NONE) && !nocase) {
|
||||
memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
|
||||
if ((reqlength < 0) && !nocase) {
|
||||
memCmpFn = (memCmpFn_t)(void *)TclpUtfNcmp2;
|
||||
} else {
|
||||
s1len = Tcl_NumUtfChars(s1, s1len);
|
||||
s2len = Tcl_NumUtfChars(s2, s2len);
|
||||
memCmpFn = (memCmpFn_t)
|
||||
memCmpFn = (memCmpFn_t)(void *)
|
||||
(nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
|
||||
}
|
||||
}
|
||||
@@ -3643,7 +3653,7 @@ TclStringCmp(
|
||||
* comparison function.
|
||||
*/
|
||||
length = (s1len < s2len) ? s1len : s2len;
|
||||
if (reqlength == TCL_INDEX_NONE) {
|
||||
if (reqlength < 0) {
|
||||
/*
|
||||
* The requested length is negative, so ignore it by setting it
|
||||
* to length + 1 to correct the match var.
|
||||
@@ -3654,7 +3664,7 @@ TclStringCmp(
|
||||
length = reqlength;
|
||||
}
|
||||
|
||||
if (checkEq && reqlength == TCL_INDEX_NONE && (s1len != s2len)) {
|
||||
if (checkEq && reqlength < 0 && (s1len != s2len)) {
|
||||
match = 1; /* This will be reversed below. */
|
||||
} else {
|
||||
/*
|
||||
@@ -4299,7 +4309,6 @@ DupStringInternalRep(
|
||||
* bother copying it. Don't even bother allocating space in which to
|
||||
* copy it. Just let the copy be untyped.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4422,7 +4431,7 @@ UpdateStringOfString(
|
||||
stringPtr->allocated = 0;
|
||||
|
||||
if (stringPtr->numChars == 0) {
|
||||
TclInitStringRep(objPtr, NULL, 0);
|
||||
TclInitEmptyStringRep(objPtr);
|
||||
} else {
|
||||
(void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode,
|
||||
stringPtr->numChars);
|
||||
@@ -4483,6 +4492,14 @@ ExtendStringRepWithUnicode(
|
||||
|
||||
copyBytes:
|
||||
dst = objPtr->bytes + origLength;
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(dst, 0xff, stringPtr->allocated - origLength);
|
||||
#endif
|
||||
for (i = 0; i < numChars; i++) {
|
||||
dst += Tcl_UniCharToUtf(unicode[i], dst);
|
||||
}
|
||||
|
||||
+16
-37
@@ -1,29 +1,12 @@
|
||||
/*
|
||||
* tclStringRep.h --
|
||||
*
|
||||
* This file contains the definition of the Unicode string internal
|
||||
* representation and macros to access it.
|
||||
* This file contains the definition of internal representations of a string
|
||||
* and macros to access it.
|
||||
*
|
||||
* A Unicode string is an internationalized string. Conceptually, a
|
||||
* Unicode string is an array of 16-bit quantities organized as a
|
||||
* sequence of properly formed UTF-8 characters. There is a one-to-one
|
||||
* map between Unicode and UTF characters. Because Unicode characters
|
||||
* have a fixed width, operations such as indexing operate on Unicode
|
||||
* data. The String object is optimized for the case where each UTF char
|
||||
* in a string is only one byte. In this case, we store the value of
|
||||
* numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
|
||||
* is explicitly called).
|
||||
*
|
||||
* The String object type stores one or both formats. The default
|
||||
* behavior is to store UTF. Once Unicode is calculated by a function, it
|
||||
* is stored in the internal rep for future access (without an additional
|
||||
* O(n) cost).
|
||||
*
|
||||
* To allow many appends to be done to an object without constantly
|
||||
* reallocating the space for the string or Unicode representation, we
|
||||
* allocate double the space for the string or Unicode and use the
|
||||
* internal representation to keep track of how much space is used vs.
|
||||
* allocated.
|
||||
* Conceptually, a string is a sequence of Unicode code points. Internally
|
||||
* it may be stored in an encoding form such as a modified version of UTF-8
|
||||
* or UTF-16 (when TCL_UTF_MAX=3) or UTF-32.
|
||||
*
|
||||
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
||||
* Copyright (c) 1999 by Scriptics Corporation.
|
||||
@@ -39,15 +22,10 @@
|
||||
/*
|
||||
* The following structure is the internal rep for a String object. It keeps
|
||||
* track of how much memory has been used and how much has been allocated for
|
||||
* the Unicode and UTF string to enable growing and shrinking of the UTF and
|
||||
* Unicode reps of the String object with fewer mallocs. To optimize string
|
||||
* the various representations to enable growing and shrinking of
|
||||
* the String object with fewer mallocs. To optimize string
|
||||
* length and indexing operations, this structure also stores the number of
|
||||
* characters (same of UTF and Unicode!) once that value has been computed.
|
||||
*
|
||||
* Under normal configurations, what Tcl calls "Unicode" is actually UTF-16
|
||||
* restricted to the Basic Multilingual Plane (i.e. U+00000 to U+0FFFF). This
|
||||
* can be officially modified by altering the definition of Tcl_UniChar in
|
||||
* tcl.h, but do not do that unless you are sure what you're doing!
|
||||
* code points (independent of encoding form) once that value has been computed.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
@@ -56,16 +34,17 @@ typedef struct {
|
||||
* calculated. Any other means that there is a valid
|
||||
* Unicode rep, or that the number of UTF bytes ==
|
||||
* the number of chars. */
|
||||
Tcl_Size allocated; /* The amount of space actually allocated for
|
||||
* the UTF string (minus 1 byte for the
|
||||
* termination char). */
|
||||
Tcl_Size allocated; /* The amount of space allocated for
|
||||
* the UTF-8 string. Does not include nul
|
||||
* terminator so actual allocation is
|
||||
* (allocated+1). */
|
||||
Tcl_Size maxChars; /* Max number of chars that can fit in the
|
||||
* space allocated for the Unicode array. */
|
||||
int hasUnicode; /* Boolean determining whether the string has
|
||||
* a Unicode representation. */
|
||||
Tcl_UniChar unicode[TCLFLEXARRAY]; /* The array of Unicode chars. The actual size
|
||||
* of this field depends on the 'maxChars'
|
||||
* field above. */
|
||||
* a Tcl_UniChar representation. */
|
||||
Tcl_UniChar unicode[TCLFLEXARRAY]; /* The array of Tcl_UniChar units.
|
||||
* The actual size of this field depends on
|
||||
* the maxChars field above. */
|
||||
} String;
|
||||
|
||||
/* Limit on string lengths. The -1 because limit does not include the nul */
|
||||
|
||||
+15
-15
@@ -123,7 +123,7 @@ static void uniCodePanic() {
|
||||
# define TclParseArgsObjv 0
|
||||
#else /* !defined(TCL_NO_DEPRECATED) */
|
||||
int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
int *objcPtr, Tcl_Obj ***objvPtr) {
|
||||
void *objcPtr, Tcl_Obj ***objvPtr) {
|
||||
Tcl_Size n = TCL_INDEX_NONE;
|
||||
int result = Tcl_ListObjGetElements(interp, listPtr, &n, objvPtr);
|
||||
if (objcPtr) {
|
||||
@@ -133,12 +133,12 @@ int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*objcPtr = n;
|
||||
*(int *)objcPtr = (int)n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
int *lengthPtr) {
|
||||
void *lengthPtr) {
|
||||
Tcl_Size n = TCL_INDEX_NONE;
|
||||
int result = Tcl_ListObjLength(interp, listPtr, &n);
|
||||
if (lengthPtr) {
|
||||
@@ -148,12 +148,12 @@ int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*lengthPtr = n;
|
||||
*(int *)lengthPtr = (int)n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
|
||||
int *sizePtr) {
|
||||
void *sizePtr) {
|
||||
Tcl_Size n = TCL_INDEX_NONE;
|
||||
int result = Tcl_DictObjSize(interp, dictPtr, &n);
|
||||
if (sizePtr) {
|
||||
@@ -163,11 +163,11 @@ int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*sizePtr = n;
|
||||
*(int *)sizePtr = (int)n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int TclSplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
|
||||
int TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr,
|
||||
const char ***argvPtr) {
|
||||
Tcl_Size n = TCL_INDEX_NONE;
|
||||
int result = Tcl_SplitList(interp, listStr, &n, argvPtr);
|
||||
@@ -179,11 +179,11 @@ int TclSplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
|
||||
Tcl_Free((void *)*argvPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*argcPtr = n;
|
||||
*(int *)argcPtr = (int)n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void TclSplitPath(const char *path, int *argcPtr, const char ***argvPtr) {
|
||||
void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr) {
|
||||
Tcl_Size n = TCL_INDEX_NONE;
|
||||
Tcl_SplitPath(path, &n, argvPtr);
|
||||
if (argcPtr) {
|
||||
@@ -192,10 +192,10 @@ void TclSplitPath(const char *path, int *argcPtr, const char ***argvPtr) {
|
||||
Tcl_Free((void *)*argvPtr);
|
||||
*argvPtr = NULL;
|
||||
}
|
||||
*argcPtr = n;
|
||||
*(int *)argcPtr = (int)n;
|
||||
}
|
||||
}
|
||||
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr) {
|
||||
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr) {
|
||||
Tcl_Size n = TCL_INDEX_NONE;
|
||||
Tcl_Obj *result = Tcl_FSSplitPath(pathPtr, &n);
|
||||
if (lenPtr) {
|
||||
@@ -203,16 +203,16 @@ Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, int *lenPtr) {
|
||||
Tcl_DecrRefCount(result);
|
||||
return NULL;
|
||||
}
|
||||
*lenPtr = n;
|
||||
*(int *)lenPtr = (int)n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int TclParseArgsObjv(Tcl_Interp *interp,
|
||||
const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv,
|
||||
const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv,
|
||||
Tcl_Obj ***remObjv) {
|
||||
Tcl_Size n = (*objcPtr < 0) ? TCL_INDEX_NONE: *objcPtr ;
|
||||
Tcl_Size n = (*(int *)objcPtr < 0) ? TCL_INDEX_NONE: (Tcl_Size)*(int *)objcPtr ;
|
||||
int result = Tcl_ParseArgsObjv(interp, argTable, &n, objv, remObjv);
|
||||
*objcPtr = (int)n;
|
||||
*(int *)objcPtr = (int)n;
|
||||
return result;
|
||||
}
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
|
||||
+141
-41
@@ -224,7 +224,8 @@ static Tcl_ObjCmdProc TestbytestringObjCmd;
|
||||
static Tcl_ObjCmdProc TestsetbytearraylengthObjCmd;
|
||||
static Tcl_ObjCmdProc TestpurebytesobjObjCmd;
|
||||
static Tcl_ObjCmdProc TeststringbytesObjCmd;
|
||||
static Tcl_CmdProc TestcmdinfoCmd;
|
||||
static Tcl_ObjCmdProc2 Testcmdobj2ObjCmd;
|
||||
static Tcl_ObjCmdProc TestcmdinfoObjCmd;
|
||||
static Tcl_CmdProc TestcmdtokenCmd;
|
||||
static Tcl_CmdProc TestcmdtraceCmd;
|
||||
static Tcl_CmdProc TestconcatobjCmd;
|
||||
@@ -586,7 +587,9 @@ Tcltest_Init(
|
||||
NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL,
|
||||
NULL);
|
||||
Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, NULL,
|
||||
Tcl_CreateObjCommand2(interp, "testcmdobj2", Testcmdobj2ObjCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testcmdinfo", TestcmdinfoObjCmd, NULL,
|
||||
NULL);
|
||||
Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
|
||||
NULL, NULL);
|
||||
@@ -1061,7 +1064,41 @@ TestbumpinterpepochObjCmd(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TestcmdinfoCmd --
|
||||
* Testcmdobj2 --
|
||||
*
|
||||
* Mock up to test the Tcl_CreateCommandObj2 functionality
|
||||
*
|
||||
* Results:
|
||||
* Standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets interpreter result to number of arguments, first arg, last arg.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
Testcmdobj2ObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
Tcl_Size objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Obj *resultObj;
|
||||
resultObj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewWideIntObj(objc));
|
||||
if (objc > 1) {
|
||||
Tcl_ListObjAppendElement(interp, resultObj, objv[1]);
|
||||
Tcl_ListObjAppendElement(interp, resultObj, objv[objc-1]);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TestcmdinfoObjCmd --
|
||||
*
|
||||
* This procedure implements the "testcmdinfo" command. It is used to
|
||||
* test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation and
|
||||
@@ -1077,28 +1114,66 @@ TestbumpinterpepochObjCmd(
|
||||
*/
|
||||
|
||||
static int
|
||||
TestcmdinfoCmd(
|
||||
TestcmdinfoObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int argc, /* Number of arguments. */
|
||||
const char **argv) /* Argument strings. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
static const char *const subcmds[] = {
|
||||
"call", "call2", "create", "delete", "get", "modify", NULL
|
||||
};
|
||||
enum options {
|
||||
CMDINFO_CALL, CMDINFO_CALL2, CMDINFO_CREATE,
|
||||
CMDINFO_DELETE, CMDINFO_GET, CMDINFO_MODIFY
|
||||
} idx;
|
||||
Tcl_CmdInfo info;
|
||||
Tcl_Obj **cmdObjv;
|
||||
Tcl_Size cmdObjc;
|
||||
|
||||
if (argc != 3) {
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" option cmdName\"", NULL);
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "command arg");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (strcmp(argv[1], "create") == 0) {
|
||||
Tcl_CreateCommand(interp, argv[2], CmdProc1, (void *) "original",
|
||||
CmdDelProc1);
|
||||
} else if (strcmp(argv[1], "delete") == 0) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
|
||||
&idx) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (idx) {
|
||||
case CMDINFO_CALL:
|
||||
case CMDINFO_CALL2:
|
||||
if (Tcl_ListObjGetElements(interp, objv[2], &cmdObjc, &cmdObjv) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (cmdObjc == 0) {
|
||||
Tcl_AppendResult(interp, "No command name given", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetCommandInfo(interp, Tcl_GetString(cmdObjv[0]), &info) == 0) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (idx == CMDINFO_CALL) {
|
||||
/*
|
||||
* Note when calling through the old 32-bit API, it is the caller's
|
||||
* responsibility to check that number of arguments is <= INT_MAX.
|
||||
* We do not do that here just so we can test what happens if the
|
||||
* caller mistakenly passes more arguments.
|
||||
*/
|
||||
return info.objProc(info.objClientData, interp, cmdObjc, cmdObjv);
|
||||
} else {
|
||||
return info.objProc2(info.objClientData2, interp, cmdObjc, cmdObjv);
|
||||
}
|
||||
case CMDINFO_CREATE:
|
||||
Tcl_CreateCommand(interp, Tcl_GetString(objv[2]), CmdProc1,
|
||||
(void *)"original", CmdDelProc1);
|
||||
break;
|
||||
case CMDINFO_DELETE:
|
||||
Tcl_DStringInit(&delString);
|
||||
Tcl_DeleteCommand(interp, argv[2]);
|
||||
Tcl_DeleteCommand(interp, Tcl_GetString(objv[2]));
|
||||
Tcl_DStringResult(interp, &delString);
|
||||
} else if (strcmp(argv[1], "get") == 0) {
|
||||
if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) {
|
||||
break;
|
||||
case CMDINFO_GET:
|
||||
if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ==0) {
|
||||
Tcl_AppendResult(interp, "??", NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1121,28 +1196,33 @@ TestcmdinfoCmd(
|
||||
Tcl_AppendResult(interp, " unknown", NULL);
|
||||
}
|
||||
Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, NULL);
|
||||
if (info.isNativeObjectProc) {
|
||||
Tcl_AppendResult(interp, " nativeObjectProc", NULL);
|
||||
} else {
|
||||
if (info.isNativeObjectProc == 0) {
|
||||
Tcl_AppendResult(interp, " stringProc", NULL);
|
||||
} else if (info.isNativeObjectProc == 1) {
|
||||
Tcl_AppendResult(interp, " nativeObjectProc", NULL);
|
||||
} else if (info.isNativeObjectProc == 2) {
|
||||
Tcl_AppendResult(interp, " nativeObjectProc2", NULL);
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid isNativeObjectProc value %d",
|
||||
info.isNativeObjectProc));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else if (strcmp(argv[1], "modify") == 0) {
|
||||
break;
|
||||
case CMDINFO_MODIFY:
|
||||
info.proc = CmdProc2;
|
||||
info.clientData = (void *) "new_command_data";
|
||||
info.objProc = NULL;
|
||||
info.objClientData = NULL;
|
||||
info.deleteProc = CmdDelProc2;
|
||||
info.deleteData = (void *) "new_delete_data";
|
||||
if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
|
||||
if (Tcl_SetCommandInfo(interp, Tcl_GetString(objv[2]), &info) == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
|
||||
}
|
||||
} else {
|
||||
Tcl_AppendResult(interp, "bad option \"", argv[1],
|
||||
"\": must be create, delete, get, or modify", NULL);
|
||||
return TCL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -3647,7 +3727,7 @@ TestlinkarrayCmd(
|
||||
static const char *LinkOption[] = {
|
||||
"update", "remove", "create", NULL
|
||||
};
|
||||
enum LinkOptionEnum {LINK_UPDATE, LINK_REMOVE, LINK_CREATE} optionIndex;
|
||||
enum LinkOptionEnum { LINK_UPDATE, LINK_REMOVE, LINK_CREATE } optionIndex;
|
||||
static const char *LinkType[] = {
|
||||
"char", "uchar", "short", "ushort", "int", "uint", "long", "ulong",
|
||||
"wide", "uwide", "float", "double", "string", "char*", "binary", NULL
|
||||
@@ -4129,7 +4209,7 @@ PrintParse(
|
||||
Tcl_Size i;
|
||||
|
||||
objPtr = Tcl_GetObjResult(interp);
|
||||
if (parsePtr->commentSize + 1 > 1) {
|
||||
if (parsePtr->commentSize > 0) {
|
||||
Tcl_ListObjAppendElement(NULL, objPtr,
|
||||
Tcl_NewStringObj(parsePtr->commentStart,
|
||||
parsePtr->commentSize));
|
||||
@@ -4567,15 +4647,15 @@ TestregexpObjCmd(
|
||||
end--;
|
||||
}
|
||||
|
||||
objs[0] = Tcl_NewWideIntObj((Tcl_WideInt)((Tcl_WideUInt)(start + 1U)) - 1);
|
||||
objs[1] = Tcl_NewWideIntObj((Tcl_WideInt)((Tcl_WideUInt)(end + 1U)) - 1);
|
||||
objs[0] = Tcl_NewWideIntObj(start);
|
||||
objs[1] = Tcl_NewWideIntObj(end);
|
||||
|
||||
newPtr = Tcl_NewListObj(2, objs);
|
||||
} else {
|
||||
if (ii == TCL_INDEX_NONE) {
|
||||
TclRegExpRangeUniChar(regExpr, ii, &start, &end);
|
||||
newPtr = Tcl_GetRange(objPtr, start, end);
|
||||
} else if (ii > info.nsubs || info.matches[ii].end + 1 <= 1) {
|
||||
} else if (ii > info.nsubs || info.matches[ii].end <= 0) {
|
||||
newPtr = Tcl_NewObj();
|
||||
} else {
|
||||
newPtr = Tcl_GetRange(objPtr, info.matches[ii].start,
|
||||
@@ -5677,7 +5757,20 @@ TestbytestringObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* The argument objects. */
|
||||
{
|
||||
Tcl_Size n = 0;
|
||||
struct {
|
||||
#if !defined(TCL_NO_DEPRECATED)
|
||||
# if defined(_MSC_VER) && !defined(NDEBUG)
|
||||
# pragma warning(disable:4133)
|
||||
# elif defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wincompatible-pointer-types"
|
||||
# endif
|
||||
int n; /* On purpose, not Tcl_Size, in order to demonstrate what happens */
|
||||
#else
|
||||
Tcl_Size n;
|
||||
#endif
|
||||
int m; /* This variable should not be overwritten */
|
||||
} x = {0, 1};
|
||||
const char *p;
|
||||
|
||||
if (objc != 2) {
|
||||
@@ -5685,11 +5778,19 @@ TestbytestringObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &n);
|
||||
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n);
|
||||
if (p == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n));
|
||||
#if !defined(TCL_NO_DEPRECATED) && defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
if (x.m != 1) {
|
||||
Tcl_AppendResult(interp, "Tcl_GetBytesFromObj() overwrites variable", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, x.n));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -6765,7 +6866,7 @@ TestWrongNumArgsObjCmd(
|
||||
Tcl_Size i, length;
|
||||
const char *msg;
|
||||
|
||||
if (objc + 1 < 4) {
|
||||
if (objc < 3) {
|
||||
goto insufArgs;
|
||||
}
|
||||
|
||||
@@ -7422,7 +7523,7 @@ TestUtfNextCmd(
|
||||
}
|
||||
bytes = Tcl_GetStringFromObj(objv[1], &numBytes);
|
||||
|
||||
if (numBytes + 4 > (Tcl_Size) sizeof(buffer)) {
|
||||
if ((size_t)numBytes > sizeof(buffer) - 4) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"testutfnext\" can only handle %" TCL_Z_MODIFIER "u bytes",
|
||||
sizeof(buffer) - 4));
|
||||
@@ -7593,8 +7694,7 @@ TestGetIntForIndexCmd(
|
||||
if (Tcl_GetIntForIndex(interp, objv[1], endvalue, &result) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/* Make sure that (size_t)-2 is output as "-2" and (size_t)-3 as "-3", even for 32-bit */
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)((Tcl_WideUInt)(result + 3U)) - 3));
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -7834,7 +7934,7 @@ TestNRELevels(
|
||||
static ptrdiff_t *refDepth = NULL;
|
||||
ptrdiff_t depth;
|
||||
Tcl_Obj *levels[6];
|
||||
size_t i = 0;
|
||||
Tcl_Size i = 0;
|
||||
NRE_callback *cbPtr = iPtr->execEnvPtr->callbackPtr;
|
||||
|
||||
if (refDepth == NULL) {
|
||||
@@ -7844,9 +7944,9 @@ TestNRELevels(
|
||||
depth = (refDepth - &depth);
|
||||
|
||||
levels[0] = Tcl_NewWideIntObj(depth);
|
||||
levels[1] = Tcl_NewWideIntObj((Tcl_WideInt)((Tcl_WideUInt)(iPtr->numLevels + 1U)) - 1);
|
||||
levels[2] = Tcl_NewWideIntObj((Tcl_WideInt)((Tcl_WideUInt)(iPtr->cmdFramePtr->level + 1U)) - 1);
|
||||
levels[3] = Tcl_NewWideIntObj((Tcl_WideInt)((Tcl_WideUInt)(iPtr->varFramePtr->level + 1U)) - 1);
|
||||
levels[1] = Tcl_NewWideIntObj(iPtr->numLevels);
|
||||
levels[2] = Tcl_NewWideIntObj(iPtr->cmdFramePtr->level);
|
||||
levels[3] = Tcl_NewWideIntObj(iPtr->varFramePtr->level);
|
||||
levels[4] = Tcl_NewWideIntObj(iPtr->execEnvPtr->execStackPtr->tosPtr
|
||||
- iPtr->execEnvPtr->execStackPtr->stackWords);
|
||||
|
||||
|
||||
+10
-8
@@ -119,8 +119,10 @@ TclObjTest_Init(
|
||||
Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testbigdata", TestbigdataCmd,
|
||||
NULL, NULL);
|
||||
if (sizeof(Tcl_Size) == sizeof(Tcl_WideInt)) {
|
||||
Tcl_CreateObjCommand(interp, "testbigdata", TestbigdataCmd,
|
||||
NULL, NULL);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -596,7 +598,7 @@ TestindexobjCmd(
|
||||
result = Tcl_GetIndexFromObj(NULL, objv[1],
|
||||
tablePtr, "token", 0, &index);
|
||||
if (result == TCL_OK) {
|
||||
Tcl_SetWideIntObj(Tcl_GetObjResult(interp), (Tcl_WideInt)((Tcl_WideUInt)(index + 1U)) - 1);
|
||||
Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -624,7 +626,7 @@ TestindexobjCmd(
|
||||
&index);
|
||||
Tcl_Free((void *)argv);
|
||||
if (result == TCL_OK) {
|
||||
Tcl_SetWideIntObj(Tcl_GetObjResult(interp), (Tcl_WideInt)((Tcl_WideUInt)(index + 1U)) - 1);
|
||||
Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1203,7 +1205,7 @@ TestobjCmd(
|
||||
if (objc != 3) {
|
||||
goto wrongNumArgs;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)((Tcl_WideUInt)(varPtr[varIndex]->refCount + 1U)) - 1));
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(varPtr[varIndex]->refCount));
|
||||
break;
|
||||
case TESTOBJ_TYPE:
|
||||
if (objc != 3) {
|
||||
@@ -1424,7 +1426,7 @@ TeststringobjCmd(
|
||||
} else {
|
||||
length = TCL_INDEX_NONE;
|
||||
}
|
||||
Tcl_SetWideIntObj(Tcl_GetObjResult(interp), (Tcl_WideInt)((Tcl_WideUInt)(length + 1U)) - 1);
|
||||
Tcl_SetWideIntObj(Tcl_GetObjResult(interp), length);
|
||||
break;
|
||||
case 10: { /* range */
|
||||
Tcl_Size first, last;
|
||||
@@ -1757,10 +1759,10 @@ CheckIfVarUnset(
|
||||
Tcl_Obj ** varPtr,
|
||||
Tcl_Size varIndex) /* Index of the test variable to check. */
|
||||
{
|
||||
if (varPtr[varIndex] == NULL) {
|
||||
if (varIndex < 0 || varPtr[varIndex] == NULL) {
|
||||
char buf[32 + TCL_INTEGER_SPACE];
|
||||
|
||||
snprintf(buf, sizeof(buf), "variable %" TCL_Z_MODIFIER "u is unset (NULL)", varIndex);
|
||||
snprintf(buf, sizeof(buf), "variable %" TCL_SIZE_MODIFIER "d is unset (NULL)", varIndex);
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
|
||||
return 1;
|
||||
|
||||
@@ -35,22 +35,22 @@
|
||||
/* Define custom memory allocation for libtommath */
|
||||
|
||||
/* MODULE_SCOPE void* TclBNAlloc( size_t ); */
|
||||
#define TclBNAlloc(s) ((void*)Tcl_Alloc(s))
|
||||
#define TclBNAlloc(s) Tcl_AttemptAlloc((size_t)(s))
|
||||
/* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */
|
||||
#define TclBNCalloc(m,s) memset(Tcl_Alloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s))
|
||||
#define TclBNCalloc(m,s) memset(Tcl_AttemptAlloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s))
|
||||
/* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */
|
||||
#define TclBNRealloc(x,s) ((void*)Tcl_Realloc((char*)(x),(size_t)(s)))
|
||||
#define TclBNRealloc(x,s) Tcl_AttemptRealloc((x),(size_t)(s))
|
||||
/* MODULE_SCOPE void TclBNFree( void* ); */
|
||||
#define TclBNFree(x) (Tcl_Free((char*)(x)))
|
||||
#define TclBNFree(x) Tcl_Free(x)
|
||||
|
||||
#undef MP_MALLOC
|
||||
#undef MP_CALLOC
|
||||
#undef MP_REALLOC
|
||||
#undef MP_FREE
|
||||
#define MP_MALLOC(size) TclBNAlloc(size)
|
||||
#define MP_CALLOC(nmemb, size) TclBNCalloc(nmemb, size)
|
||||
#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc(mem, newsize)
|
||||
#define MP_FREE(mem, size) TclBNFree(mem)
|
||||
#define MP_CALLOC(nmemb, size) TclBNCalloc((nmemb), (size))
|
||||
#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc((mem), ((void)(oldsize), (newsize)))
|
||||
#define MP_FREE(mem, size) TclBNFree(((void)(size), (mem)))
|
||||
|
||||
#ifndef MODULE_SCOPE
|
||||
# ifdef __cplusplus
|
||||
|
||||
@@ -348,6 +348,16 @@ Tcl_UniCharToUtfDString(
|
||||
|
||||
p = string;
|
||||
wEnd = uniStr + uniLength;
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Once TCL_UTF_MAX == 3 is removed and Tcl_UniCharToUtf restored to its
|
||||
* prior non-stateful nature, this call to memset can also be removed.
|
||||
*/
|
||||
memset(p, 0xff, Tcl_DStringLength(dsPtr) - oldLength);
|
||||
#endif
|
||||
|
||||
for (w = uniStr; w < wEnd; ) {
|
||||
p += Tcl_UniCharToUtf(*w, p);
|
||||
w++;
|
||||
@@ -391,6 +401,16 @@ Tcl_Char16ToUtfDString(
|
||||
|
||||
p = string;
|
||||
wEnd = uniStr + uniLength;
|
||||
|
||||
#if TCL_UTF_MAX < 4
|
||||
/* Initialize the buffer so that some random data doesn't trick
|
||||
* Tcl_UniCharToUtf() into thinking it should combine surrogate pairs.
|
||||
* Because TCL_COMBINE is used here, memset() is required even when
|
||||
* TCL_UTF_MAX == 4.
|
||||
*/
|
||||
memset(p, 0xff, Tcl_DStringLength(dsPtr) - oldLength);
|
||||
#endif
|
||||
|
||||
for (w = uniStr; w < wEnd; ) {
|
||||
if (!len && ((*w & 0xFC00) != 0xDC00)) {
|
||||
/* Special case for handling high surrogates. */
|
||||
|
||||
+89
-39
@@ -1035,10 +1035,10 @@ TclScanElement(
|
||||
* needs protection or escape. */
|
||||
int requireEscape = 0; /* Force use of CONVERT_ESCAPE mode. For some
|
||||
* reason bare or brace-quoted form fails. */
|
||||
int extra = 0; /* Count of number of extra bytes needed for
|
||||
Tcl_Size extra = 0; /* Count of number of extra bytes needed for
|
||||
* formatted element, assuming we use escape
|
||||
* sequences in formatting. */
|
||||
TCL_HASH_TYPE bytesNeeded; /* Buffer length computed to complete the
|
||||
Tcl_Size bytesNeeded; /* Buffer length computed to complete the
|
||||
* element formatting in the selected mode. */
|
||||
#if COMPAT
|
||||
int preferEscape = 0; /* Use preferences to track whether to use */
|
||||
@@ -2004,7 +2004,11 @@ Tcl_ConcatObj(
|
||||
goto slow;
|
||||
}
|
||||
} else {
|
||||
resPtr = TclListObjCopy(NULL, objPtr);
|
||||
resPtr = TclDuplicatePureObj(
|
||||
NULL, objPtr, &tclListType.objType);
|
||||
if (!resPtr) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!resPtr) {
|
||||
@@ -2602,34 +2606,35 @@ Tcl_DStringAppend(
|
||||
if (length < 0) {
|
||||
length = strlen(bytes);
|
||||
}
|
||||
newSize = length + dsPtr->length;
|
||||
|
||||
/*
|
||||
* Allocate a larger buffer for the string if the current one isn't large
|
||||
* enough. Allocate extra space in the new buffer so that there will be
|
||||
* room to grow before we have to allocate again.
|
||||
*/
|
||||
if (length > (TCL_SIZE_MAX - dsPtr->length - 1)) {
|
||||
Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER
|
||||
"d bytes) exceeded",
|
||||
TCL_SIZE_MAX);
|
||||
return NULL; /* NOTREACHED */
|
||||
}
|
||||
newSize = length + dsPtr->length + 1;
|
||||
|
||||
if (newSize >= dsPtr->spaceAvl) {
|
||||
dsPtr->spaceAvl = newSize * 2;
|
||||
|
||||
if (newSize > dsPtr->spaceAvl) {
|
||||
if (dsPtr->string == dsPtr->staticSpace) {
|
||||
char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);
|
||||
|
||||
char *newString;
|
||||
newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
|
||||
memcpy(newString, dsPtr->string, dsPtr->length);
|
||||
dsPtr->string = newString;
|
||||
} else {
|
||||
Tcl_Size index = TCL_INDEX_NONE;
|
||||
Tcl_Size offset = -1;
|
||||
|
||||
/* See [16896d49fd] */
|
||||
if (bytes >= dsPtr->string
|
||||
&& bytes <= dsPtr->string + dsPtr->length) {
|
||||
index = bytes - dsPtr->string;
|
||||
/* Source string is within this DString. Note offset */
|
||||
offset = bytes - dsPtr->string;
|
||||
}
|
||||
|
||||
dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl);
|
||||
|
||||
if (index >= 0) {
|
||||
bytes = dsPtr->string + index;
|
||||
dsPtr->string =
|
||||
(char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
|
||||
if (offset >= 0) {
|
||||
bytes = dsPtr->string + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2741,12 +2746,11 @@ Tcl_DStringAppendElement(
|
||||
* memcpy, not strcpy, to copy the string to a larger buffer, since there
|
||||
* may be embedded NULLs in the string in some cases.
|
||||
*/
|
||||
|
||||
if (newSize >= dsPtr->spaceAvl) {
|
||||
dsPtr->spaceAvl = newSize * 2;
|
||||
newSize += 1; /* For terminating nul */
|
||||
if (newSize > dsPtr->spaceAvl) {
|
||||
if (dsPtr->string == dsPtr->staticSpace) {
|
||||
char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);
|
||||
|
||||
char *newString;
|
||||
newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
|
||||
memcpy(newString, dsPtr->string, dsPtr->length);
|
||||
dsPtr->string = newString;
|
||||
} else {
|
||||
@@ -2755,11 +2759,11 @@ Tcl_DStringAppendElement(
|
||||
/* See [16896d49fd] */
|
||||
if (element >= dsPtr->string
|
||||
&& element <= dsPtr->string + dsPtr->length) {
|
||||
/* Source string is within this DString. Note offset */
|
||||
offset = element - dsPtr->string;
|
||||
}
|
||||
|
||||
dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl);
|
||||
|
||||
dsPtr->string =
|
||||
(char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
|
||||
if (offset >= 0) {
|
||||
element = dsPtr->string + offset;
|
||||
}
|
||||
@@ -2808,6 +2812,9 @@ Tcl_DStringSetLength(
|
||||
{
|
||||
Tcl_Size newsize;
|
||||
|
||||
if (length < 0) {
|
||||
length = 0;
|
||||
}
|
||||
if (length >= dsPtr->spaceAvl) {
|
||||
/*
|
||||
* There are two interesting cases here. In the first case, the user
|
||||
@@ -2815,13 +2822,16 @@ Tcl_DStringSetLength(
|
||||
* would be wasteful to overallocate that buffer, so we just allocate
|
||||
* enough for the requested size plus the trailing null byte. In the
|
||||
* second case, we are growing the buffer incrementally, so we need
|
||||
* behavior similar to Tcl_DStringAppend. The requested length will
|
||||
* usually be a small delta above the current spaceAvl, so we'll end
|
||||
* up doubling the old size. This won't grow the buffer quite as
|
||||
* quickly, but it should be close enough.
|
||||
* behavior similar to Tcl_DStringAppend.
|
||||
* TODO - the above makes no sense to me. How does the code below
|
||||
* translate into distinguishing the two cases above? IMO, if caller
|
||||
* specifically sets the length, there is no cause for overallocation.
|
||||
*/
|
||||
|
||||
newsize = dsPtr->spaceAvl * 2;
|
||||
if (length >= TCL_SIZE_MAX) {
|
||||
Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
|
||||
}
|
||||
newsize = TclUpsizeAlloc(dsPtr->spaceAvl, length + 1, TCL_SIZE_MAX);
|
||||
if (length < newsize) {
|
||||
dsPtr->spaceAvl = newsize;
|
||||
} else {
|
||||
@@ -3679,8 +3689,8 @@ GetEndOffsetFromObj(
|
||||
offset = irPtr->wideValue;
|
||||
|
||||
if (offset == WIDE_MAX) {
|
||||
/*
|
||||
* Encodes end+1. This is distinguished from end+n as noted above
|
||||
/*
|
||||
* Encodes end+1. This is distinguished from end+n as noted above
|
||||
* NOTE: this may wrap around if the caller passes (as lset does)
|
||||
* listLen-1 as endValue and and listLen is 0. The -1 will be
|
||||
* interpreted as FF...FF and adding 1 will result in 0 which
|
||||
@@ -3796,8 +3806,8 @@ TclIndexEncode(
|
||||
}
|
||||
/*
|
||||
* We passed 2*INT_MAX as the "end value" to GetWideForIndex. The computed
|
||||
* index will in one of the following ranges that need to be distinguished
|
||||
* for encoding purposes in the following code.
|
||||
* index will be in one of the following ranges that need to be
|
||||
* distinguished for encoding purposes in the following code.
|
||||
* (1) 0:INT_MAX when
|
||||
* (a) objPtr was a pure non-negative numeric value in that range
|
||||
* (b) objPtr was a numeric computation M+/-N with a result in that range
|
||||
@@ -3846,7 +3856,7 @@ TclIndexEncode(
|
||||
* error is raised. On 32-bit systems, indices in that range indicate
|
||||
* the position after the end and so do not raise an error.
|
||||
*/
|
||||
if ((sizeof(int) != sizeof(size_t)) &&
|
||||
if ((sizeof(int) != sizeof(Tcl_Size)) &&
|
||||
(wide > INT_MAX) && (wide < WIDE_MAX-1)) {
|
||||
/* 2(a,b) on 64-bit systems*/
|
||||
goto rangeerror;
|
||||
@@ -3876,7 +3886,7 @@ TclIndexEncode(
|
||||
* indices in that range indicate the position before the beginning
|
||||
* and so do not raise an error.
|
||||
*/
|
||||
if ((sizeof(int) != sizeof(size_t)) &&
|
||||
if ((sizeof(int) != sizeof(Tcl_Size)) &&
|
||||
(wide > (ENDVALUE - LIST_MAX)) && (wide <= INT_MAX)) {
|
||||
/* 1(c), 4(a,b) on 64-bit systems */
|
||||
goto rangeerror;
|
||||
@@ -3976,6 +3986,46 @@ TclIndexInvalidError (
|
||||
return TCL_ERROR; /* Always */
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
* TclCommandWordLimitErrpr --
|
||||
*
|
||||
* Generates an error message limit on number of command words exceeded.
|
||||
*
|
||||
* Results:
|
||||
* Always return TCL_ERROR.
|
||||
*
|
||||
* Side effects:
|
||||
* If interp is not-NULL, an error message is stored in it.
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclCommandWordLimitError (
|
||||
Tcl_Interp *interp, /* May be NULL */
|
||||
Tcl_Size count) /* If <= 0, "unknown" */
|
||||
{
|
||||
if (interp) {
|
||||
if (count > 0) {
|
||||
Tcl_SetObjResult(
|
||||
interp,
|
||||
Tcl_ObjPrintf("Number of words (%" TCL_SIZE_MODIFIER
|
||||
"d) in command exceeds limit %" TCL_SIZE_MODIFIER
|
||||
"d.",
|
||||
count,
|
||||
(Tcl_Size)INT_MAX));
|
||||
}
|
||||
else {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Number of words in command exceeds "
|
||||
"limit %" TCL_SIZE_MODIFIER "d.",
|
||||
(Tcl_Size)INT_MAX));
|
||||
}
|
||||
}
|
||||
return TCL_ERROR; /* Always */
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+13
-3
@@ -3097,7 +3097,10 @@ ArrayForNRCmd(
|
||||
* loop) don't vanish.
|
||||
*/
|
||||
|
||||
varListObj = TclListObjCopy(NULL, objv[1]);
|
||||
varListObj = TclDuplicatePureObj(interp, objv[1], &tclListType.objType);
|
||||
if (!varListObj) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
scriptObj = objv[3];
|
||||
Tcl_IncrRefCount(scriptObj);
|
||||
|
||||
@@ -3176,7 +3179,10 @@ ArrayForLoopCallback(
|
||||
goto arrayfordone;
|
||||
}
|
||||
|
||||
TclListObjGetElementsM(NULL, varListObj, &varc, &varv);
|
||||
result = TclListObjGetElementsM(NULL, varListObj, &varc, &varv);
|
||||
if (result != TCL_OK) {
|
||||
goto arrayfordone;
|
||||
}
|
||||
if (Tcl_ObjSetVar2(interp, varv[0], NULL, keyObj,
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
result = TCL_ERROR;
|
||||
@@ -4067,7 +4073,11 @@ ArraySetCmd(
|
||||
* the loop and return an error.
|
||||
*/
|
||||
|
||||
copyListObj = TclListObjCopy(NULL, arrayElemObj);
|
||||
copyListObj =
|
||||
TclDuplicatePureObj(interp, arrayElemObj, &tclListType.objType);
|
||||
if (!copyListObj) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i=0 ; i<elemLen ; i+=2) {
|
||||
Var *elemVarPtr = TclLookupArrayElement(interp, arrayNameObj,
|
||||
elemPtrs[i], TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr, -1);
|
||||
|
||||
+2
-2
@@ -1902,7 +1902,7 @@ ListMountPoints(
|
||||
return (ZipFS.zipHash.numEntries ? TCL_OK : TCL_BREAK);
|
||||
}
|
||||
|
||||
resultList = Tcl_NewObj();
|
||||
TclNewObj(resultList);
|
||||
for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
|
||||
hPtr = Tcl_NextHashEntry(&search)) {
|
||||
zf = (ZipFile *) Tcl_GetHashValue(hPtr);
|
||||
@@ -5140,7 +5140,7 @@ ZipFSMatchMountPoints(
|
||||
{
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_HashSearch search;
|
||||
size_t l;
|
||||
size_t l;
|
||||
Tcl_Size normLength;
|
||||
const char *path = Tcl_GetStringFromObj(normPathPtr, &normLength);
|
||||
size_t len = normLength;
|
||||
|
||||
+1
-1
@@ -3761,7 +3761,7 @@ ZlibStackChannelTransform(
|
||||
if (compDictObj != NULL) {
|
||||
cd->compDictObj = Tcl_DuplicateObj(compDictObj);
|
||||
Tcl_IncrRefCount(cd->compDictObj);
|
||||
Tcl_GetByteArrayFromObj(cd->compDictObj, (size_t *)NULL);
|
||||
Tcl_GetByteArrayFromObj(cd->compDictObj, (Tcl_Size *)NULL);
|
||||
}
|
||||
|
||||
if (format == TCL_ZLIB_FORMAT_RAW) {
|
||||
|
||||
+70
-65
@@ -310,28 +310,28 @@ proc ::tcl::clock::Initialize {} {
|
||||
{-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Kwajalein
|
||||
{-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Midway
|
||||
{-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Honolulu
|
||||
{-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage
|
||||
{-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles
|
||||
{-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana
|
||||
{-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver
|
||||
{-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua
|
||||
{-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage
|
||||
{-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles
|
||||
{-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana
|
||||
{-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver
|
||||
{-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua
|
||||
{-25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Phoenix
|
||||
{-21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Regina
|
||||
{-21600 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Chicago
|
||||
{-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City
|
||||
{-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City
|
||||
{-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/New_York
|
||||
{-18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Indianapolis
|
||||
{-14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Caracas
|
||||
{-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999}
|
||||
{-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999}
|
||||
:America/Santiago
|
||||
{-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus
|
||||
{-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax
|
||||
{-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus
|
||||
{-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax
|
||||
{-12600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/St_Johns
|
||||
{-10800 0 3600 0 2 0 2 2 0 0 0 0 10 0 3 2 0 0 0} :America/Sao_Paulo
|
||||
{-10800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Godthab
|
||||
{-10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Buenos_Aires
|
||||
{-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia
|
||||
{-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo
|
||||
{-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia
|
||||
{-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo
|
||||
{-7200 0 3600 0 9 0 5 2 0 0 0 0 3 0 5 2 0 0 0} :America/Noronha
|
||||
{-3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Atlantic/Azores
|
||||
{-3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Atlantic/Cape_Verde
|
||||
@@ -339,22 +339,22 @@ proc ::tcl::clock::Initialize {} {
|
||||
{0 0 3600 0 10 0 5 2 0 0 0 0 3 0 5 1 0 0 0} :Europe/London
|
||||
{3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Kinshasa
|
||||
{3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :CET
|
||||
{7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Harare
|
||||
{7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0}
|
||||
{7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Harare
|
||||
{7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0}
|
||||
:Africa/Cairo
|
||||
{7200 0 3600 0 10 0 5 4 0 0 0 0 3 0 5 3 0 0 0} :Europe/Helsinki
|
||||
{7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0} :Asia/Jerusalem
|
||||
{7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0} :Asia/Jerusalem
|
||||
{7200 0 3600 0 9 0 5 1 0 0 0 0 3 0 5 0 0 0 0} :Europe/Bucharest
|
||||
{7200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Athens
|
||||
{7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0} :Asia/Amman
|
||||
{7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0}
|
||||
{7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0} :Asia/Amman
|
||||
{7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0}
|
||||
:Asia/Beirut
|
||||
{7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0} :Africa/Windhoek
|
||||
{7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0} :Africa/Windhoek
|
||||
{10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Riyadh
|
||||
{10800 0 3600 0 10 0 1 4 0 0 0 0 4 0 1 3 0 0 0} :Asia/Baghdad
|
||||
{10800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Moscow
|
||||
{12600 0 3600 0 9 2 4 2 0 0 0 0 3 0 1 2 0 0 0} :Asia/Tehran
|
||||
{14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0} :Asia/Baku
|
||||
{14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0} :Asia/Baku
|
||||
{14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Muscat
|
||||
{14400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Tbilisi
|
||||
{16200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Kabul
|
||||
@@ -584,8 +584,8 @@ proc ::tcl::clock::Initialize {} {
|
||||
jst +0900 \
|
||||
kst +0900 \
|
||||
cast +0930 \
|
||||
jdt +1000 \
|
||||
kdt +1000 \
|
||||
jdt +1000 \
|
||||
kdt +1000 \
|
||||
cadt +1030 \
|
||||
east +1000 \
|
||||
eadt +1030 \
|
||||
@@ -1158,8 +1158,8 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
|
||||
}
|
||||
|
||||
proc $procName {clockval timezone} "
|
||||
$preFormatCode
|
||||
return \[::format [list $formatString] $substituents\]
|
||||
$preFormatCode
|
||||
return \[::format [list $formatString] $substituents\]
|
||||
"
|
||||
|
||||
# puts [list $procName [info args $procName] [info body $procName]]
|
||||
@@ -1173,7 +1173,7 @@ proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
|
||||
#
|
||||
# Inputs a count of seconds since the Posix Epoch as a time of day.
|
||||
#
|
||||
# The 'clock format' command scans times of day on input. Refer to the user
|
||||
# The 'clock scan' command scans times of day on input. Refer to the user
|
||||
# documentation to see what it does.
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
@@ -1189,10 +1189,10 @@ proc ::tcl::clock::scan { args } {
|
||||
return -code error \
|
||||
-errorcode [list CLOCK wrongNumArgs] \
|
||||
"wrong \# args: should be\
|
||||
\"$cmdName string\
|
||||
?-base seconds?\
|
||||
?-format string? ?-gmt boolean?\
|
||||
?-locale LOCALE? ?-timezone ZONE?\""
|
||||
\"$cmdName string\
|
||||
?-base seconds?\
|
||||
?-format string? ?-gmt boolean?\
|
||||
?-locale LOCALE? ?-timezone ZONE?\""
|
||||
}
|
||||
|
||||
# Set defaults
|
||||
@@ -1207,28 +1207,31 @@ proc ::tcl::clock::scan { args } {
|
||||
# Pick up command line options.
|
||||
|
||||
foreach { flag value } [lreplace $args 0 0] {
|
||||
set saw($flag) {}
|
||||
switch -exact -- $flag {
|
||||
-b - -ba - -bas - -base {
|
||||
set base $value
|
||||
}
|
||||
-f - -fo - -for - -form - -forma - -format {
|
||||
set saw(-format) {}
|
||||
set format $value
|
||||
}
|
||||
-g - -gm - -gmt {
|
||||
set saw(-gmt) {}
|
||||
set gmt $value
|
||||
}
|
||||
-l - -lo - -loc - -loca - -local - -locale {
|
||||
set saw(-locale) {}
|
||||
set locale [string tolower $value]
|
||||
}
|
||||
-t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone {
|
||||
set saw(-timezone) {}
|
||||
set timezone $value
|
||||
}
|
||||
default {
|
||||
return -code error \
|
||||
-errorcode [list CLOCK badOption $flag] \
|
||||
"bad option \"$flag\",\
|
||||
must be -base, -format, -gmt, -locale or -timezone"
|
||||
must be -base, -format, -gmt, -locale or -timezone"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1975,7 +1978,7 @@ proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
|
||||
# being processed - they're always absolute
|
||||
|
||||
if { ![dict exists $fieldSet seconds]
|
||||
&& ![dict exists $fieldSet starDate] } {
|
||||
&& ![dict exists $fieldSet starDate] } {
|
||||
append procBody {
|
||||
if { [dict get $date julianDay] > 5373484 } {
|
||||
return -code error -errorcode [list CLOCK dateTooLarge] \
|
||||
@@ -2379,8 +2382,8 @@ proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } {
|
||||
M %N
|
||||
yyyy %Y
|
||||
yy %y
|
||||
y %y
|
||||
gg {}
|
||||
y %y
|
||||
gg {}
|
||||
} $unquoted]
|
||||
if { $quoted eq {} } {
|
||||
set quote '
|
||||
@@ -2409,8 +2412,8 @@ proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } {
|
||||
M %N
|
||||
yyyy %Y
|
||||
yy %y
|
||||
y %y
|
||||
gg {}
|
||||
y %y
|
||||
gg {}
|
||||
} $unquoted]
|
||||
if { $quoted eq {} } {
|
||||
set quote '
|
||||
@@ -2989,19 +2992,19 @@ proc ::tcl::clock::GetSystemTimeZone {} {
|
||||
} elseif {[set result [getenv TZ]] ne {}} {
|
||||
set timezone $result
|
||||
} else {
|
||||
# Cache the time zone only if it was detected by one of the
|
||||
# expensive methods.
|
||||
if { [info exists CachedSystemTimeZone] } {
|
||||
set timezone $CachedSystemTimeZone
|
||||
} elseif { $::tcl_platform(platform) eq {windows} } {
|
||||
set timezone [GuessWindowsTimeZone]
|
||||
} elseif { [file exists /etc/localtime]
|
||||
&& ![catch {ReadZoneinfoFile \
|
||||
Tcl/Localtime /etc/localtime}] } {
|
||||
set timezone :Tcl/Localtime
|
||||
} else {
|
||||
set timezone :localtime
|
||||
}
|
||||
# Cache the time zone only if it was detected by one of the
|
||||
# expensive methods.
|
||||
if { [info exists CachedSystemTimeZone] } {
|
||||
set timezone $CachedSystemTimeZone
|
||||
} elseif { $::tcl_platform(platform) eq {windows} } {
|
||||
set timezone [GuessWindowsTimeZone]
|
||||
} elseif { [file exists /etc/localtime]
|
||||
&& ![catch {ReadZoneinfoFile \
|
||||
Tcl/Localtime /etc/localtime}] } {
|
||||
set timezone :Tcl/Localtime
|
||||
} else {
|
||||
set timezone :localtime
|
||||
}
|
||||
set CachedSystemTimeZone $timezone
|
||||
}
|
||||
if { ![dict exists $TimeZoneBad $timezone] } {
|
||||
@@ -3608,7 +3611,7 @@ proc ::tcl::clock::ParsePosixTimeZone { tz } {
|
||||
# 4 - Standard time zone offset, minutes
|
||||
: ([[:digit:]]{1,2})
|
||||
(?:
|
||||
# 5 - Standard time zone offset, seconds
|
||||
# 5 - Standard time zone offset, seconds
|
||||
: ([[:digit:]]{1,2} )
|
||||
)?
|
||||
)?
|
||||
@@ -3616,7 +3619,7 @@ proc ::tcl::clock::ParsePosixTimeZone { tz } {
|
||||
# 6 - DST time zone name
|
||||
([[:alpha:]]+ | <[-+[:alnum:]]+>)
|
||||
(?:
|
||||
(?:
|
||||
(?:
|
||||
# 7 - DST time zone offset, signum
|
||||
([-+]?)
|
||||
# 8 - DST time zone offset, hours
|
||||
@@ -3625,17 +3628,17 @@ proc ::tcl::clock::ParsePosixTimeZone { tz } {
|
||||
# 9 - DST time zone offset, minutes
|
||||
: ([[:digit:]]{1,2})
|
||||
(?:
|
||||
# 10 - DST time zone offset, seconds
|
||||
# 10 - DST time zone offset, seconds
|
||||
: ([[:digit:]]{1,2})
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
(?:
|
||||
(?:
|
||||
,
|
||||
(?:
|
||||
# 11 - Optional J in n and Jn form 12 - Day of year
|
||||
( J ? ) ( [[:digit:]]+ )
|
||||
| M
|
||||
( J ? ) ( [[:digit:]]+ )
|
||||
| M
|
||||
# 13 - Month number 14 - Week of month 15 - Day of week
|
||||
( [[:digit:]] + )
|
||||
[.] ( [[:digit:]] + )
|
||||
@@ -3644,7 +3647,7 @@ proc ::tcl::clock::ParsePosixTimeZone { tz } {
|
||||
(?:
|
||||
# 16 - Start time of DST - hours
|
||||
/ ( [[:digit:]]{1,2} )
|
||||
(?:
|
||||
(?:
|
||||
# 17 - Start time of DST - minutes
|
||||
: ( [[:digit:]]{1,2} )
|
||||
(?:
|
||||
@@ -3656,8 +3659,8 @@ proc ::tcl::clock::ParsePosixTimeZone { tz } {
|
||||
,
|
||||
(?:
|
||||
# 19 - Optional J in n and Jn form 20 - Day of year
|
||||
( J ? ) ( [[:digit:]]+ )
|
||||
| M
|
||||
( J ? ) ( [[:digit:]]+ )
|
||||
| M
|
||||
# 21 - Month number 22 - Week of month 23 - Day of week
|
||||
( [[:digit:]] + )
|
||||
[.] ( [[:digit:]] + )
|
||||
@@ -3666,7 +3669,7 @@ proc ::tcl::clock::ParsePosixTimeZone { tz } {
|
||||
(?:
|
||||
# 24 - End time of DST - hours
|
||||
/ ( [[:digit:]]{1,2} )
|
||||
(?:
|
||||
(?:
|
||||
# 25 - End time of DST - minutes
|
||||
: ( [[:digit:]]{1,2} )
|
||||
(?:
|
||||
@@ -3675,9 +3678,9 @@ proc ::tcl::clock::ParsePosixTimeZone { tz } {
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
$
|
||||
} $tz -> x(stdName) x(stdSignum) x(stdHours) x(stdMinutes) x(stdSeconds) \
|
||||
x(dstName) x(dstSignum) x(dstHours) x(dstMinutes) x(dstSeconds) \
|
||||
@@ -4243,8 +4246,8 @@ proc ::tcl::clock::add { clockval args } {
|
||||
return -code error \
|
||||
-errorcode [list CLOCK wrongNumArgs] \
|
||||
"wrong \# args: should be\
|
||||
\"$cmdName clockval ?number units?...\
|
||||
?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?\""
|
||||
\"$cmdName clockval ?number units?...\
|
||||
?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?\""
|
||||
}
|
||||
if { [catch { expr {wide($clockval)} } result] } {
|
||||
return -code error $result
|
||||
@@ -4261,6 +4264,7 @@ proc ::tcl::clock::add { clockval args } {
|
||||
} else {
|
||||
switch -exact -- $a {
|
||||
-g - -gm - -gmt {
|
||||
set saw(-gmt) {}
|
||||
set gmt $b
|
||||
}
|
||||
-l - -lo - -loc - -loca - -local - -locale {
|
||||
@@ -4268,12 +4272,13 @@ proc ::tcl::clock::add { clockval args } {
|
||||
}
|
||||
-t - -ti - -tim - -time - -timez - -timezo - -timezon -
|
||||
-timezone {
|
||||
set saw(-timezone) {}
|
||||
set timezone $b
|
||||
}
|
||||
default {
|
||||
throw [list CLOCK badOption $a] \
|
||||
"bad option \"$a\",\
|
||||
must be -gmt, -locale or -timezone"
|
||||
must be -gmt, -locale or -timezone"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4338,7 +4343,7 @@ proc ::tcl::clock::add { clockval args } {
|
||||
default {
|
||||
throw [list CLOCK badUnit $unit] \
|
||||
"unknown unit \"$unit\", must be \
|
||||
years, months, weeks, days, hours, minutes or seconds"
|
||||
years, months, weeks, days, hours, minutes or seconds"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4498,10 +4503,10 @@ proc ::tcl::clock::ChangeCurrentLocale {args} {
|
||||
variable TimeZoneBad
|
||||
|
||||
foreach p [info procs [namespace current]::scanproc'*'current] {
|
||||
rename $p {}
|
||||
rename $p {}
|
||||
}
|
||||
foreach p [info procs [namespace current]::formatproc'*'current] {
|
||||
rename $p {}
|
||||
rename $p {}
|
||||
}
|
||||
|
||||
catch {array unset FormatProc *'current}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user