Compare commits
474
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa12f7d709 | ||
|
|
a7909595ec | ||
|
|
0cd0bb6862 | ||
|
|
0714cd9321 | ||
|
|
e9d4e1005e | ||
|
|
74c17b45b2 | ||
|
|
c4e63fa109 | ||
|
|
ef88cbd89e | ||
|
|
674aeae3b0 | ||
|
|
72c1f925db | ||
|
|
e42f5d61b2 | ||
|
|
a8e3472731 | ||
|
|
95d020a657 | ||
|
|
6d7abfd8a9 | ||
|
|
bbaecb023a | ||
|
|
c25e21b7bb | ||
|
|
3489a76210 | ||
|
|
357515037a | ||
|
|
a435d9e14b | ||
|
|
df537d0dfb | ||
|
|
1000af34fa | ||
|
|
d37425bc05 | ||
|
|
5e9f624428 | ||
|
|
7d753e316a | ||
|
|
c2f9601344 | ||
|
|
c8d9ab8790 | ||
|
|
f096df2170 | ||
|
|
990d6fd6f1 | ||
|
|
da608f8c61 | ||
|
|
c58016090f | ||
|
|
e7f46501e2 | ||
|
|
13a2801fd7 | ||
|
|
995aaf8bfd | ||
|
|
d7da846591 | ||
|
|
2287394ba1 | ||
|
|
8d1caeae4d | ||
|
|
1be35f340f | ||
|
|
ca471eb748 | ||
|
|
538960215f | ||
|
|
1375c96d2f | ||
|
|
8f07b4a94c | ||
|
|
2edb1dcd83 | ||
|
|
37f6932c0a | ||
|
|
9e7c15f53e | ||
|
|
f850132635 | ||
|
|
f10147dbfe | ||
|
|
0dd529776d | ||
|
|
ea1423a2ab | ||
|
|
5b71bf5ea8 | ||
|
|
a5538d84c4 | ||
|
|
addd1694e0 | ||
|
|
7cdd87e4f1 | ||
|
|
0b9cb76206 | ||
|
|
99fd1215e2 | ||
|
|
6e380ef6e9 | ||
|
|
ae6e14e33c | ||
|
|
bc5ffbb3b2 | ||
|
|
92b58040dd | ||
|
|
fcc907b2a6 | ||
|
|
25ba428ff9 | ||
|
|
2020e9be61 | ||
|
|
6497c6c6ee | ||
|
|
31647bcceb | ||
|
|
3555752d45 | ||
|
|
37fb43ad48 | ||
|
|
cd2858d1d0 | ||
|
|
790b302275 | ||
|
|
dc11ffbbdb | ||
|
|
1571dc01bb | ||
|
|
4dc2505e43 | ||
|
|
18a2ebc51d | ||
|
|
da3723c942 | ||
|
|
27ef344b9c | ||
|
|
885ced5608 | ||
|
|
b1fe66323b | ||
|
|
a188ceee21 | ||
|
|
eb87ed60f6 | ||
|
|
bc94a394c9 | ||
|
|
46d871617f | ||
|
|
d654ce6429 | ||
|
|
452f14ebb5 | ||
|
|
0a7d5ef6ed | ||
|
|
f785a01764 | ||
|
|
274f081025 | ||
|
|
76ed3d5b55 | ||
|
|
fba10e8615 | ||
|
|
1f0c1b800d | ||
|
|
a7e97de50a | ||
|
|
ea11870f5b | ||
|
|
95b511bac2 | ||
|
|
17e1ea228c | ||
|
|
53abdcc518 | ||
|
|
d963b1acb7 | ||
|
|
04432d4dd1 | ||
|
|
3e4f5907b6 | ||
|
|
4a159c5199 | ||
|
|
b53cf6d38c | ||
|
|
779b8dad76 | ||
|
|
cd428c1a44 | ||
|
|
16dbe3f5a2 | ||
|
|
7b989f0312 | ||
|
|
994e1d8062 | ||
|
|
de8e3be492 | ||
|
|
d44a63b65b | ||
|
|
423d995e0d | ||
|
|
5c37d95180 | ||
|
|
970922295a | ||
|
|
31690ce7fb | ||
|
|
630d4b9211 | ||
|
|
7faf4f27a4 | ||
|
|
dd1c28a788 | ||
|
|
afd6d5649f | ||
|
|
e9d7b07476 | ||
|
|
b8ffbb14c4 | ||
|
|
39dbbd57af | ||
|
|
bbfc83c86f | ||
|
|
d31beb3e7f | ||
|
|
aa3b157338 | ||
|
|
bf27b64405 | ||
|
|
76b6b03be7 | ||
|
|
c205f272f7 | ||
|
|
0551ecffd6 | ||
|
|
13967f965d | ||
|
|
79ff282b02 | ||
|
|
9afdf28497 | ||
|
|
bfae5bf492 | ||
|
|
925bd5794e | ||
|
|
ae54e070a1 | ||
|
|
8b894ab295 | ||
|
|
e35292f314 | ||
|
|
7f0e6652c7 | ||
|
|
7634bdaef2 | ||
|
|
9cb330963b | ||
|
|
4dc1a8a588 | ||
|
|
66f257a588 | ||
|
|
36825d23b9 | ||
|
|
326e0a8fdf | ||
|
|
29fdaa6dcd | ||
|
|
ae0ad313fd | ||
|
|
ec64cc0418 | ||
|
|
c482675d84 | ||
|
|
7dd13b72b6 | ||
|
|
54c0881e9d | ||
|
|
d81daf76bd | ||
|
|
11e9b6a9a5 | ||
|
|
8fe7f3fcdf | ||
|
|
f3e9f9caa3 | ||
|
|
28d5ff4eb5 | ||
|
|
71c2d1a883 | ||
|
|
c8597887e4 | ||
|
|
05009534ee | ||
|
|
f50a4eed54 | ||
|
|
90813dfce8 | ||
|
|
a16868a54c | ||
|
|
c4eac3e8eb | ||
|
|
7b78869343 | ||
|
|
ab8a39e6b9 | ||
|
|
870f61c05d | ||
|
|
6585306973 | ||
|
|
b1d510f1db | ||
|
|
111f52e7ed | ||
|
|
6548fc4ad1 | ||
|
|
a629b0ba31 | ||
|
|
8c066a970f | ||
|
|
29b9de871c | ||
|
|
a9dbadf46a | ||
|
|
02e79b9ec1 | ||
|
|
5aa514f49a | ||
|
|
2bc8d915a2 | ||
|
|
c4f7e08fc6 | ||
|
|
008c7038cb | ||
|
|
dfb2a3f2e2 | ||
|
|
e8aa220d08 | ||
|
|
8d3c0c2e81 | ||
|
|
3adfe07f74 | ||
|
|
7aae664d12 | ||
|
|
cdb1ef8aac | ||
|
|
e7e4c74b7f | ||
|
|
3d6c6683bb | ||
|
|
bf9e61ca6a | ||
|
|
db811061d4 | ||
|
|
63a316c43b | ||
|
|
3da8f74e75 | ||
|
|
3833c42f54 | ||
|
|
2bfb7b96c0 | ||
|
|
35141afcc9 | ||
|
|
6053836b97 | ||
|
|
e13460b1fb | ||
|
|
41512fe1fa | ||
|
|
4ef0c69aaa | ||
|
|
7660c04aff | ||
|
|
7ca470456b | ||
|
|
ab18c108f7 | ||
|
|
7ccdd3657b | ||
|
|
98dbefe2cc | ||
|
|
b748232291 | ||
|
|
d35a5023da | ||
|
|
c4b6cab579 | ||
|
|
cf8c1e7bdc | ||
|
|
6f860bc18d | ||
|
|
2bd794f7cc | ||
|
|
5b7e79f851 | ||
|
|
3b2cb79ab1 | ||
|
|
0cce018c67 | ||
|
|
f2115ca085 | ||
|
|
ac673f63d0 | ||
|
|
5001d7d18c | ||
|
|
a134b03eda | ||
|
|
d823d4a2d5 | ||
|
|
27696b490b | ||
|
|
b37c60fe43 | ||
|
|
d0af5aa92c | ||
|
|
d4eb48d90f | ||
|
|
9faead9d18 | ||
|
|
404eadfdaf | ||
|
|
722ba1aa44 | ||
|
|
4cead413c9 | ||
|
|
2501dbb8d0 | ||
|
|
0050652afb | ||
|
|
4704b442fb | ||
|
|
5b8d20e6de | ||
|
|
2151838b5b | ||
|
|
acb9c613f1 | ||
|
|
ee54cd02de | ||
|
|
ad4538af95 | ||
|
|
c2e7b1ce36 | ||
|
|
a8f05c5339 | ||
|
|
e26431e0f3 | ||
|
|
23a34a26fe | ||
|
|
3cd3541039 | ||
|
|
f846b3f965 | ||
|
|
a22b8736ec | ||
|
|
87a97e0609 | ||
|
|
f5bf1de995 | ||
|
|
6f9ac81ae9 | ||
|
|
c947326c4a | ||
|
|
9b1a5dc878 | ||
|
|
4bc50a0a12 | ||
|
|
26532df53f | ||
|
|
0b8d92332a | ||
|
|
0cf3369f9f | ||
|
|
8f28138f6e | ||
|
|
c0d0df8550 | ||
|
|
67a6300cc4 | ||
|
|
fd72878261 | ||
|
|
9df68a3879 | ||
|
|
bd8c790e2e | ||
|
|
5c3b0101a2 | ||
|
|
fed06f2292 | ||
|
|
2edc274601 | ||
|
|
f68e18d159 | ||
|
|
66a18f91c0 | ||
|
|
4c4629d5fd | ||
|
|
89796adf9c | ||
|
|
11b61660d2 | ||
|
|
d214692a28 | ||
|
|
eec270dc08 | ||
|
|
34d3a97939 | ||
|
|
1f93e78598 | ||
|
|
c3c52cf7b0 | ||
|
|
b11d2bb62d | ||
|
|
96d7deb99b | ||
|
|
e0a4741204 | ||
|
|
0ceae7a885 | ||
|
|
e19d125606 | ||
|
|
9b324cef64 | ||
|
|
68432b7ed1 | ||
|
|
f1f3820560 | ||
|
|
363cf0a6f1 | ||
|
|
508b6fc60d | ||
|
|
75f3cb9d07 | ||
|
|
31ec149e21 | ||
|
|
6076256c3f | ||
|
|
77e9a375ff | ||
|
|
25f7d3b86e | ||
|
|
464153fecd | ||
|
|
139a16f600 | ||
|
|
600487a9d6 | ||
|
|
a2962cc586 | ||
|
|
d6ae741f7f | ||
|
|
48e3873f19 | ||
|
|
57a42f683c | ||
|
|
b2e1bb03b1 | ||
|
|
d8785b8358 | ||
|
|
7de7029fa5 | ||
|
|
47620e4ba8 | ||
|
|
f290d19b27 | ||
|
|
1446838d71 | ||
|
|
8c8c1a6415 | ||
|
|
07f3d3e393 | ||
|
|
1e5db76cc1 | ||
|
|
85d1666247 | ||
|
|
bf0a1dc6c5 | ||
|
|
31e1e2a8c4 | ||
|
|
8f4ed81159 | ||
|
|
966906b7ae | ||
|
|
20e8eaedc8 | ||
|
|
d65776f03f | ||
|
|
7b6eaf23e9 | ||
|
|
bf33e5524b | ||
|
|
2ee0bbf7fb | ||
|
|
23c3438aee | ||
|
|
21124cf6ab | ||
|
|
1694cf05a6 | ||
|
|
8e39be1340 | ||
|
|
4110638cdd | ||
|
|
65bd912b77 | ||
|
|
dd879c794d | ||
|
|
e68b3d0183 | ||
|
|
1481e6f3da | ||
|
|
42c2792287 | ||
|
|
08826b79fe | ||
|
|
d5617720bb | ||
|
|
e95143affd | ||
|
|
a67b58390b | ||
|
|
ced0d271ff | ||
|
|
b6f5ea3c8f | ||
|
|
38e85a2dbe | ||
|
|
680d1a1513 | ||
|
|
f2718ded6d | ||
|
|
221b47806c | ||
|
|
286034431c | ||
|
|
c1ce97106f | ||
|
|
c8212c36e9 | ||
|
|
964477ea36 | ||
|
|
88fc841203 | ||
|
|
04633c731b | ||
|
|
75a582f357 | ||
|
|
b28ae0fbb5 | ||
|
|
6c2c1397ff | ||
|
|
73124928ba | ||
|
|
cc2f6f6a7d | ||
|
|
bf285438a2 | ||
|
|
844c8c3016 | ||
|
|
16dc425318 | ||
|
|
7a41668df0 | ||
|
|
9c058fa5d4 | ||
|
|
6c2f2fec8a | ||
|
|
0cb6ad07c6 | ||
|
|
ef99853da4 | ||
|
|
cb9a441bb9 | ||
|
|
bf46c5018d | ||
|
|
3619c13393 | ||
|
|
e577cd8cf8 | ||
|
|
f05e229780 | ||
|
|
ff29c56ea4 | ||
|
|
5cae882ff3 | ||
|
|
0592038cf9 | ||
|
|
5207d2fe71 | ||
|
|
fab681eb11 | ||
|
|
01e94e53ed | ||
|
|
7f038e4db7 | ||
|
|
e5320ae0d5 | ||
|
|
8290f077d2 | ||
|
|
eccf18644f | ||
|
|
e4b872fc07 | ||
|
|
df9f4ed74f | ||
|
|
8445a00210 | ||
|
|
345d7cf628 | ||
|
|
b300fecc27 | ||
|
|
482ab2e9dc | ||
|
|
751453253c | ||
|
|
7b7647f1ab | ||
|
|
fa88074963 | ||
|
|
d418226edb | ||
|
|
bdfafd3539 | ||
|
|
819b87f1df | ||
|
|
b36880503c | ||
|
|
3c2b67a4d3 | ||
|
|
08c3a9b76b | ||
|
|
dd519c7dac | ||
|
|
f67a341fce | ||
|
|
c755ef0815 | ||
|
|
be577d6027 | ||
|
|
99d3f3c9f3 | ||
|
|
0b3a8804eb | ||
|
|
92a9b04a12 | ||
|
|
a4532de5a0 | ||
|
|
ed326ae9b5 | ||
|
|
710ec0ef20 | ||
|
|
b4024d86d1 | ||
|
|
58f5175075 | ||
|
|
0789d80b7a | ||
|
|
5aee84a3f3 | ||
|
|
e52789c557 | ||
|
|
c0e9c99a1c | ||
|
|
67cfc8e178 | ||
|
|
47115ff565 | ||
|
|
dca8fae05f | ||
|
|
5512629c55 | ||
|
|
cb6e9135f2 | ||
|
|
af7e16b8e4 | ||
|
|
63e94b434f | ||
|
|
41a668a515 | ||
|
|
20619d8334 | ||
|
|
d0a8ae5cf7 | ||
|
|
7f43feafd5 | ||
|
|
2b502a4b2b | ||
|
|
f95100b44a | ||
|
|
0d4e358f5e | ||
|
|
5f7157f3a2 | ||
|
|
7cde8a22a1 | ||
|
|
535895e577 | ||
|
|
366828918a | ||
|
|
7e85a50a46 | ||
|
|
0e5bc322f1 | ||
|
|
1195cdbd77 | ||
|
|
5330c4e5d3 | ||
|
|
52799e58d6 | ||
|
|
46d0e89d6e | ||
|
|
c9bd1f3334 | ||
|
|
6d990b9c83 | ||
|
|
84f95a3ef4 | ||
|
|
3a20c7912b | ||
|
|
008944a5c3 | ||
|
|
e0c7416333 | ||
|
|
7a4ad0872e | ||
|
|
7f12c0adfa | ||
|
|
885379e2cc | ||
|
|
76d0eb32fc | ||
|
|
76f6131b81 | ||
|
|
1438a1b7f7 | ||
|
|
5789574f89 | ||
|
|
f705798ed7 | ||
|
|
024bab4116 | ||
|
|
8e26969a34 | ||
|
|
ee742713d1 | ||
|
|
00f3aef9ac | ||
|
|
54a8b02774 | ||
|
|
a9f506ce21 | ||
|
|
8c36db11d0 | ||
|
|
a3838de0f9 | ||
|
|
9c0f41cdde | ||
|
|
012caa867f | ||
|
|
2d7c30cea8 | ||
|
|
dbf87bdccf | ||
|
|
8e5a574ac0 | ||
|
|
097a0bb6e2 | ||
|
|
bbc790ccac | ||
|
|
689cee14b2 | ||
|
|
42eab451a6 | ||
|
|
a52a0147b7 | ||
|
|
d243959c21 | ||
|
|
dba0cd17dc | ||
|
|
3f2f704c28 | ||
|
|
71ae050a68 | ||
|
|
dcf6957535 | ||
|
|
9a27611f89 | ||
|
|
ac974ca777 | ||
|
|
7210b03f81 | ||
|
|
820909f2f1 | ||
|
|
6a82cdfc6a | ||
|
|
3611f9be2c | ||
|
|
c8ff1de738 | ||
|
|
73c4c7d5e5 | ||
|
|
1e5e66b31f | ||
|
|
4315a57ac4 | ||
|
|
89b344e544 | ||
|
|
496861c695 | ||
|
|
92a18f28ec | ||
|
|
1a7bb8dae4 | ||
|
|
e1173969e6 | ||
|
|
8597e498b4 | ||
|
|
f44a15f93f | ||
|
|
8920f52cc1 | ||
|
|
abb02f83eb | ||
|
|
f816bb2a60 | ||
|
|
40a37e9b4a | ||
|
|
99ac77fd22 | ||
|
|
32d41dcbb5 | ||
|
|
a3eb84e8cb | ||
|
|
d5b999af66 | ||
|
|
4878f1b6a4 | ||
|
|
c5e0f27a28 |
@@ -17,8 +17,26 @@
|
||||
*/tclsh*
|
||||
*/tcltest*
|
||||
*/versions.vc
|
||||
libtommath/bn.ilg
|
||||
libtommath/bn.ind
|
||||
libtommath/pretty.build
|
||||
libtommath/tommath.src
|
||||
libtommath/*.pdf
|
||||
libtommath/*.pl
|
||||
libtommath/*.sh
|
||||
libtommath/tombc/*
|
||||
libtommath/pre_gen/*
|
||||
libtommath/pics/*
|
||||
libtommath/mtest/*
|
||||
libtommath/logs/*
|
||||
libtommath/etc/*
|
||||
libtommath/demo/*
|
||||
libtommath/*.out
|
||||
libtommath/*.tex
|
||||
unix/autoMkindex.tcl
|
||||
unix/dltest.marker
|
||||
unix/tcl.pc
|
||||
unix/tclIndex
|
||||
unix/pkgs/*
|
||||
win/pkgs/*
|
||||
win/tcl.hpj
|
||||
|
||||
+1
-1
@@ -414,7 +414,7 @@
|
||||
Tcl_IsChannelExisting, and Tcl_ClearChannelHandlers to conform to the
|
||||
new stacked channel implementation. Their stub slots were also moved
|
||||
to give preference to the new 8.3.2 stub functions. This will cause an
|
||||
incompatability with 8.4a1 only.
|
||||
incompatibility with 8.4a1 only.
|
||||
(StopCopy): 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 side. [Bug: 6261]
|
||||
|
||||
+3
-3
@@ -847,7 +847,7 @@
|
||||
exit.
|
||||
|
||||
* tests/exec.test: marked exec-18.1 unixOnly until the Windows
|
||||
incompatability (in the test, not the core) can be resolved.
|
||||
incompatibility (in the test, not the core) can be resolved.
|
||||
|
||||
* tests/http.test (http-3.11): added close $fp that was causing an
|
||||
error on Windows because the file was not closed before deleting.
|
||||
@@ -3642,7 +3642,7 @@
|
||||
* compat/strtoll.c (strtoll):
|
||||
* compat/strtoull.c (strtoull):
|
||||
* unix/tclUnixPort.h:
|
||||
* win/tclWinPort.h: Const-ing 64-bit compatability declarations. Note
|
||||
* win/tclWinPort.h: Const-ing 64-bit compatibility declarations. Note
|
||||
that the return pointer is non-const because it is entirely legal for
|
||||
the functions to be called from somewhere that owns the string being
|
||||
passed. Fixes problem reported by Larry Virden.
|
||||
@@ -3779,7 +3779,7 @@
|
||||
|
||||
There are a lot of changes from this TIP, so please see
|
||||
http://purl.org/tcl/tip/72.html for discussion of
|
||||
backward-compatability issues, but the main ones modifications are in:
|
||||
backward-compatibility issues, but the main ones modifications are in:
|
||||
|
||||
* generic/tcl.h: New types.
|
||||
* generic/tcl.decls: New public functions.
|
||||
|
||||
+2
-2
@@ -947,7 +947,7 @@
|
||||
declarations match and will end up using the declarations in the
|
||||
public code from now on because of #include ordering. Keeping the old
|
||||
declarations in tclInt.decls; there's no need to gratuitously break
|
||||
compatability for those extensions which are already clients of the
|
||||
compatibility for those extensions which are already clients of the
|
||||
namespace code.
|
||||
|
||||
2003-08-23 Zoran Vasiljevic <zoran@archiwrae.com>
|
||||
@@ -1278,7 +1278,7 @@
|
||||
|
||||
* generic/tclVar.c (Tcl_ArrayObjCmd, TclArraySet): Made [array get]
|
||||
and [array set] work with dictionaries, producing them and consuming
|
||||
them. Note that for compatability reasons, you will never get a dict
|
||||
them. Note that for compatibility reasons, you will never get a dict
|
||||
from feeding a string literal to [array set] since that alters the
|
||||
trace behaviour of "multi-key" sets. [Bug 759935]
|
||||
|
||||
|
||||
+1
-1
@@ -1356,7 +1356,7 @@
|
||||
2004-10-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
|
||||
|
||||
* *.3: Convert CONST to const and VOID to void so we document how
|
||||
people should actually use the Tcl API and not the compatability hacks
|
||||
people should actually use the Tcl API and not the compatibility hacks
|
||||
that it has to have.
|
||||
|
||||
* doc/man.macros, *.3: Update .AS macro so it can know how wide to
|
||||
|
||||
+1
-1
@@ -106,5 +106,5 @@ closedir(
|
||||
close(dirp->dd_fd);
|
||||
dirp->dd_fd = -1;
|
||||
dirp->dd_loc = 0;
|
||||
ckfree((char *) dirp);
|
||||
ckfree(dirp);
|
||||
}
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ waitpid(
|
||||
} else {
|
||||
prevPtr->nextPtr = waitPtr->nextPtr;
|
||||
}
|
||||
ckfree((char *) waitPtr);
|
||||
ckfree(waitPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ retrieve the stack trace when script evaluation returns
|
||||
\fBTCL_ERROR\fR, like so:
|
||||
.PP
|
||||
.CS
|
||||
int code = Tcl_Eval(interp, script);
|
||||
int code = Tcl_EvalEx(interp, script, -1, 0);
|
||||
if (code == TCL_ERROR) {
|
||||
Tcl_Obj *options = \fBTcl_GetReturnOptions\fR(interp, code);
|
||||
Tcl_Obj *key = Tcl_NewStringObj("-errorinfo", -1);
|
||||
|
||||
+23
-8
@@ -51,27 +51,42 @@ in the interpreter's result, and nothing is stored at *\fIintPtr\fR
|
||||
or *\fIdoublePtr\fR or *\fIboolPtr\fR.
|
||||
.PP
|
||||
\fBTcl_GetInt\fR expects \fIsrc\fR to consist of a collection
|
||||
of integer digits, optionally signed and optionally preceded by
|
||||
white space. If the first two characters of \fIsrc\fR
|
||||
of integer digits, optionally signed and optionally preceded and
|
||||
followed by white space. If the first two characters of \fIsrc\fR
|
||||
after the optional white space and sign are
|
||||
.QW 0x
|
||||
.QW \fB0x\fR
|
||||
then \fIsrc\fR is expected to be in hexadecimal form; otherwise,
|
||||
if the first such characters are
|
||||
.QW \fB0o\fR
|
||||
then \fIsrc\fR is expected to be in octal form; otherwise,
|
||||
if the first such characters are
|
||||
.QW \fB0b\fR
|
||||
then \fIsrc\fR is expected to be in binary form; otherwise,
|
||||
if the first such character is
|
||||
.QW 0
|
||||
.QW \fB0\fR
|
||||
then \fIsrc\fR
|
||||
is expected to be in octal form; otherwise, \fIsrc\fR is
|
||||
expected to be in decimal form.
|
||||
.PP
|
||||
\fBTcl_GetDouble\fR expects \fIsrc\fR to consist of a floating-point
|
||||
number, which is: white space; a sign; a sequence of digits; a
|
||||
decimal point; a sequence of digits; the letter
|
||||
.QW e ;
|
||||
decimal point
|
||||
.QW \fB.\fR ;
|
||||
a sequence of digits; the letter
|
||||
.QW \fBe\fR ;
|
||||
a signed decimal exponent; and more white space.
|
||||
Any of the fields may be omitted, except that
|
||||
the digits either before or after the decimal point must be present
|
||||
and if the
|
||||
.QW e
|
||||
is present then it must be followed by the exponent number.
|
||||
.QW \fBe\fR
|
||||
is present then it must be followed by the exponent number. If there
|
||||
are no fields apart from the sign and initial sequence of digits
|
||||
(i.e., no decimal point or exponent indicator), that
|
||||
initial sequence of digits should take one of the forms that
|
||||
\fBTcl_GetInt\fR supports, described above. The use of
|
||||
.QW \fB,\fR
|
||||
as a decimal point is not supported nor should any other sort of
|
||||
inter-digit separator be present.
|
||||
.PP
|
||||
\fBTcl_GetBoolean\fR expects \fIsrc\fR to specify a boolean
|
||||
value. If \fIsrc\fR is any of \fB0\fR, \fBfalse\fR,
|
||||
|
||||
+1
-1
@@ -281,7 +281,7 @@ The \fIhashKeyProc\fR member contains the address of a function called to
|
||||
calculate a hash value for the key.
|
||||
.PP
|
||||
.CS
|
||||
typedef unsigned int \fBTcl_HashKeyProc\fR(
|
||||
typedef TCL_HASH_TYPE \fBTcl_HashKeyProc\fR(
|
||||
Tcl_HashTable *\fItablePtr\fR,
|
||||
void *\fIkeyPtr\fR);
|
||||
.CE
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ The source interpreter will have its result reset by this operation.
|
||||
.SH "DEPRECATED INTERFACES"
|
||||
.SS "OLD STRING PROCEDURES"
|
||||
.PP
|
||||
Use of the following procedures (is deprecated
|
||||
Use of the following procedures is deprecated
|
||||
since they manipulate the Tcl result as a string.
|
||||
Procedures such as \fBTcl_SetObjResult\fR
|
||||
that manipulate the result as a value
|
||||
|
||||
@@ -47,6 +47,13 @@ been the return value from a previous invocation of
|
||||
Returns 1 if \fIarrayName\fR is an array variable, 0 if there
|
||||
is no variable by that name or if it is a scalar variable.
|
||||
.TP
|
||||
\fBarray for {\fIkeyVariable ?valueVariable?\fB} \fIarrayName body\fR
|
||||
The first argument is a one or two element list of variable names for the
|
||||
key and value of each entry in the array. The second argument is the
|
||||
array name to iterate over. The third argument is the body to execute
|
||||
for each key and value returned.
|
||||
The ordering of the returned keys is undefined.
|
||||
.TP
|
||||
\fBarray get \fIarrayName\fR ?\fIpattern\fR?
|
||||
Returns a list containing pairs of elements. The first
|
||||
element in each pair is the name of an element in \fIarrayName\fR
|
||||
|
||||
+20
-6
@@ -287,12 +287,14 @@ slow destinations like network sockets.
|
||||
.RS
|
||||
.PP
|
||||
The \fBchan copy\fR command transfers data from \fIinputChan\fR until
|
||||
end of file or \fIsize\fR bytes have been transferred. If no
|
||||
\fB\-size\fR argument is given, then the copy goes until end of file.
|
||||
All the data read from \fIinputChan\fR is copied to \fIoutputChan\fR.
|
||||
Without the \fB\-command\fR option, \fBchan copy\fR blocks until the
|
||||
copy is complete and returns the number of bytes written to
|
||||
\fIoutputChan\fR.
|
||||
end of file or \fIsize\fR bytes or characters have been transferred;
|
||||
\fIsize\fR is in bytes if the two channels are using the same encoding,
|
||||
and is in characters otherwise. If no \fB\-size\fR argument is given,
|
||||
then the copy goes until end of file. All the data read from
|
||||
\fIinputChan\fR is copied to \fIoutputChan\fR. Without the
|
||||
\fB\-command\fR option, \fBchan copy\fR blocks until the copy is
|
||||
complete and returns the number of bytes or characters (using the same
|
||||
rules as for the \fB\-size\fR option) written to \fIoutputChan\fR.
|
||||
.PP
|
||||
The \fB\-command\fR argument makes \fBchan copy\fR work in the
|
||||
background. In this case it returns immediately and the
|
||||
@@ -547,6 +549,18 @@ this, spawn with "2>@" or
|
||||
">@" redirection operators onto the write side of a pipe, and then
|
||||
immediately close it in the parent. This is necessary to get an EOF on
|
||||
the read side once the child has exited or otherwise closed its output.
|
||||
.RS
|
||||
.PP
|
||||
Note that the pipe buffering semantics can vary at the operating system level
|
||||
substantially; it is not safe to assume that a write performed on the output
|
||||
side of the pipe will appear instantly to the input side. This is a
|
||||
fundamental difference and Tcl cannot conceal it. The overall stream semantics
|
||||
\fIare\fR compatible, so blocking reads and writes will not see most of the
|
||||
differences, but the details of what exactly gets written when are not. This
|
||||
is most likely to show up when using pipelines for testing; care should be
|
||||
taken to ensure that deadlocks do not occur and that potential short reads are
|
||||
allowed for.
|
||||
.RE
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBchan pop \fIchannelId\fR
|
||||
|
||||
@@ -20,6 +20,7 @@ This command joins each of its arguments together with spaces after
|
||||
trimming leading and trailing white-space from each of them. If all of the
|
||||
arguments are lists, this has the same effect as concatenating them
|
||||
into a single list.
|
||||
Arguments that are empty (after trimming) are ignored entirely.
|
||||
It permits any number of arguments;
|
||||
if no \fIarg\fRs are supplied, the result is an empty string.
|
||||
.SH EXAMPLES
|
||||
|
||||
+3
-2
@@ -271,8 +271,9 @@ limitation as \fBexec\fR wants to communicate over pipes. The Expect
|
||||
extension addresses this issue when communicating with a TUI application.
|
||||
.PP
|
||||
When attempting to execute an application, \fBexec\fR first searches for
|
||||
the name as it was specified. Then, in order, \fB.com\fR, \fB.exe\fR, and
|
||||
\fB.bat\fR are appended to the end of the specified name and it searches
|
||||
the name as it was specified. Then, in order,
|
||||
\fB.com\fR, \fB.exe\fR, \fB.bat\fR and \fB.cmd\fR
|
||||
are appended to the end of the specified name and it searches
|
||||
for the longer name. If a directory name was not specified as part of the
|
||||
application name, the following directories are automatically searched in
|
||||
order when attempting to locate the application:
|
||||
|
||||
+171
-214
@@ -17,14 +17,14 @@ expr \- Evaluate an expression
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Concatenates \fIarg\fRs (adding separator spaces between them),
|
||||
evaluates the result as a Tcl expression, and returns the value.
|
||||
The operators permitted in Tcl expressions include a subset of
|
||||
Concatenates \fIarg\fRs, separated by a space, into an expression, and evaluates
|
||||
that expression, returning its value.
|
||||
The operators permitted in an expression include a subset of
|
||||
the operators permitted in C expressions. For those operators
|
||||
common to both Tcl and C, Tcl applies the same meaning and precedence
|
||||
as the corresponding C operators.
|
||||
Expressions almost always yield numeric results
|
||||
(integer or floating-point values).
|
||||
The value of an expression is often a numeric result, either an integer or a
|
||||
floating-point value, but may also be a non-numeric value.
|
||||
For example, the expression
|
||||
.PP
|
||||
.CS
|
||||
@@ -32,78 +32,68 @@ For example, the expression
|
||||
.CE
|
||||
.PP
|
||||
evaluates to 14.2.
|
||||
Tcl expressions differ from C expressions in the way that
|
||||
operands are specified. Also, Tcl expressions support
|
||||
non-numeric operands and string comparisons, as well as some
|
||||
Expressions differ from C expressions in the way that
|
||||
operands are specified. Expressions also support
|
||||
non-numeric operands, string comparisons, and some
|
||||
additional operators not found in C.
|
||||
.PP
|
||||
When an expression evaluates to an integer, the value is the decimal form of
|
||||
the integer, and when an expression evaluates to a floating-point number, the
|
||||
value is the form produced by the \fB%g\fR format specifier of Tcl's
|
||||
\fBformat\fR command.
|
||||
.SS OPERANDS
|
||||
.PP
|
||||
A Tcl expression consists of a combination of operands, operators,
|
||||
parentheses and commas.
|
||||
White space may be used between the operands and operators and
|
||||
parentheses (or commas); it is ignored by the expression's instructions.
|
||||
Where possible, operands are interpreted as integer values.
|
||||
Integer values may be specified in decimal (the normal case), in binary
|
||||
(if the first two characters of the operand are \fB0b\fR), in octal
|
||||
(if the first two characters of the operand are \fB0o\fR), or in hexadecimal
|
||||
(if the first two characters of the operand are \fB0x\fR). For
|
||||
compatibility with older Tcl releases, an octal integer value is also
|
||||
indicated simply when the first character of the operand is \fB0\fR,
|
||||
whether or not the second character is also \fBo\fR.
|
||||
If an operand does not have one of the integer formats given
|
||||
above, then it is treated as a floating-point number if that is
|
||||
possible. Floating-point numbers may be specified in any of several
|
||||
common formats making use of the decimal digits, the decimal point \fB.\fR,
|
||||
the characters \fBe\fR or \fBE\fR indicating scientific notation, and
|
||||
the sign characters \fB+\fR or \fB\-\fR. For example, all of the
|
||||
following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16.
|
||||
Also recognized as floating point values are the strings \fBInf\fR
|
||||
and \fBNaN\fR making use of any case for each character.
|
||||
If no numeric interpretation is possible (note that all literal
|
||||
operands that are not numeric or boolean must be quoted with either
|
||||
braces or with double quotes), then an operand is left as a string
|
||||
(and only a limited set of operators may be applied to it).
|
||||
An expression consists of a combination of operands, operators, parentheses and
|
||||
commas, possibly with whitespace between any of these elements, which is
|
||||
ignored.
|
||||
An integer operand may be specified in decimal, binary
|
||||
(the first two characters are \fB0b\fR), octal
|
||||
(the first two characters are \fB0o\fR), or hexadecimal
|
||||
(the first two characters are \fB0x\fR) form. For
|
||||
compatibility with older Tcl releases, an operand that begins with \fB0\fR is
|
||||
interpreted as an octal integer even if the second character is not \fBo\fR.
|
||||
A floating-point number may be specified in any of several
|
||||
common decimal formats, and may use the decimal point \fB.\fR,
|
||||
\fBe\fR or \fBE\fR for scientific notation, and
|
||||
the sign characters \fB+\fR and \fB\-\fR. The
|
||||
following are all valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16.
|
||||
The strings \fBInf\fR
|
||||
and \fBNaN\fR, in any combination of case, are also recognized as floating point
|
||||
values. An operand that doesn't have a numeric interpretation must be quoted
|
||||
with either braces or with double quotes.
|
||||
.PP
|
||||
Operands may be specified in any of the following ways:
|
||||
An operand may be specified in any of the following ways:
|
||||
.IP [1]
|
||||
As a numeric value, either integer or floating-point.
|
||||
.IP [2]
|
||||
As a boolean value, using any form understood by \fBstring is\fR
|
||||
\fBboolean\fR.
|
||||
.IP [3]
|
||||
As a Tcl variable, using standard \fB$\fR notation.
|
||||
The variable's value will be used as the operand.
|
||||
As a variable, using standard \fB$\fR notation.
|
||||
The value of the variable is then the value of the operand.
|
||||
.IP [4]
|
||||
As a string enclosed in double-quotes.
|
||||
The expression parser will perform backslash, variable, and
|
||||
command substitutions on the information between the quotes,
|
||||
and use the resulting value as the operand
|
||||
Backslash, variable, and command substitution are performed as described in
|
||||
\fBTcl\fR.
|
||||
.IP [5]
|
||||
As a string enclosed in braces.
|
||||
The characters between the open brace and matching close brace
|
||||
will be used as the operand without any substitutions.
|
||||
The operand is treated as a braced value as described in \fBTcl\fR.
|
||||
.IP [6]
|
||||
As a Tcl command enclosed in brackets.
|
||||
The command will be executed and its result will be used as
|
||||
the operand.
|
||||
Command substitution is performed as described in \fBTcl\fR.
|
||||
.IP [7]
|
||||
As a mathematical function whose arguments have any of the above
|
||||
forms for operands, such as \fBsin($x)\fR. See \fBMATH FUNCTIONS\fR below for
|
||||
As a mathematical function such as \fBsin($x)\fR, whose arguments have any of the above
|
||||
forms for operands. See \fBMATH FUNCTIONS\fR below for
|
||||
a discussion of how mathematical functions are handled.
|
||||
.PP
|
||||
Where the above substitutions occur (e.g. inside quoted strings), they
|
||||
are performed by the expression's instructions.
|
||||
However, the command parser may already have performed one round of
|
||||
substitution before the expression processor was called.
|
||||
As discussed below, it is usually best to enclose expressions
|
||||
in braces to prevent the command parser from performing substitutions
|
||||
on the contents.
|
||||
Because \fBexpr\fR parses and performs substitutions on values that have
|
||||
already been parsed and substituted by \fBTcl\fR, it is usually best to enclose
|
||||
expressions in braces to avoid the first round of substitutions by
|
||||
\fBTcl\fR.
|
||||
.PP
|
||||
For some examples of simple expressions, suppose the variable
|
||||
\fBa\fR has the value 3 and
|
||||
the variable \fBb\fR has the value 6.
|
||||
Then the command on the left side of each of the lines below
|
||||
will produce the value on the right side of the line:
|
||||
Below are some examples of simple expressions where the value of \fBa\fR is 3
|
||||
and the value of \fBb\fR is 6. The command on the left side of each line
|
||||
produces the value on the right side.
|
||||
.PP
|
||||
.CS
|
||||
.ta 6c
|
||||
@@ -114,34 +104,41 @@ will produce the value on the right side of the line:
|
||||
.CE
|
||||
.SS OPERATORS
|
||||
.PP
|
||||
The valid operators (most of which are also available as commands in
|
||||
the \fBtcl::mathop\fR namespace; see the \fBmathop\fR(n) manual page
|
||||
for details) are listed below, grouped in decreasing order of precedence:
|
||||
For operators having both a numeric mode and a string mode, the numeric mode is
|
||||
chosen when all operands have a numeric interpretation. The integer
|
||||
interpretation of an operand is preferred over the floating-point
|
||||
interpretation. To ensure string operations on arbitrary values it is generally a
|
||||
good idea to use \fBeq\fR, \fBne\fR, or the \fBstring\fR command instead of
|
||||
more versatile operators such as \fB==\fR.
|
||||
.PP
|
||||
Unless otherwise specified, operators accept non-numeric operands. The value
|
||||
of a boolean operation is 1 if true, 0 otherwise. See also \fBstring is\fR
|
||||
\fBboolean\fR. The valid operators, most of which are also available as
|
||||
commands in the \fBtcl::mathop\fR namespace (see \fBmathop\fR(n)), are listed
|
||||
below, grouped in decreasing order of precedence:
|
||||
.TP 20
|
||||
\fB\-\0\0+\0\0~\0\0!\fR
|
||||
.
|
||||
Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operators
|
||||
may be applied to string operands, and bit-wise NOT may be
|
||||
applied only to integers.
|
||||
Unary minus, unary plus, bit-wise NOT, logical NOT. These operators
|
||||
may only be applied to numeric operands, and bit-wise NOT may only be
|
||||
applied to integers.
|
||||
.TP 20
|
||||
\fB**\fR
|
||||
.
|
||||
Exponentiation. Valid for any numeric operands.
|
||||
Exponentiation. Valid for numeric operands.
|
||||
.TP 20
|
||||
\fB*\0\0/\0\0%\fR
|
||||
.
|
||||
Multiply, divide, remainder. None of these operators may be
|
||||
applied to string operands, and remainder may be applied only
|
||||
to integers.
|
||||
The remainder will always have the same sign as the divisor and
|
||||
an absolute value smaller than the absolute value of the divisor.
|
||||
Multiply and divide, which are valid for numeric operands, and remainder, which
|
||||
is valid for integers. The remainder, an absolute value smaller than the
|
||||
absolute value of the divisor, has the same sign as the divisor.
|
||||
.RS
|
||||
.PP
|
||||
When applied to integers, the division and remainder operators can be
|
||||
considered to partition the number line into a sequence of equal-sized
|
||||
adjacent non-overlapping pieces where each piece is the size of the divisor;
|
||||
the division result identifies which piece the divisor lay within, and the
|
||||
remainder result identifies where within that piece the divisor lay. A
|
||||
When applied to integers, division and remainder can be
|
||||
considered to partition the number line into a sequence of
|
||||
adjacent non-overlapping pieces, where each piece is the size of the divisor;
|
||||
the quotient identifies which piece the dividend lies within, and the
|
||||
remainder identifies where within that piece the dividend lies. A
|
||||
consequence of this is that the result of
|
||||
.QW "-57 \fB/\fR 10"
|
||||
is always -6, and the result of
|
||||
@@ -151,177 +148,157 @@ is always 3.
|
||||
.TP 20
|
||||
\fB+\0\0\-\fR
|
||||
.
|
||||
Add and subtract. Valid for any numeric operands.
|
||||
Add and subtract. Valid for numeric operands.
|
||||
.TP 20
|
||||
\fB<<\0\0>>\fR
|
||||
.
|
||||
Left and right shift. Valid for integer operands only.
|
||||
Left and right shift. Valid for integers.
|
||||
A right shift always propagates the sign bit.
|
||||
.TP 20
|
||||
\fB<\0\0>\0\0<=\0\0>=\fR
|
||||
.
|
||||
Boolean less, greater, less than or equal, and greater than or equal.
|
||||
Each operator produces 1 if the condition is true, 0 otherwise.
|
||||
These operators may be applied to strings as well as numeric operands,
|
||||
in which case string comparison is used.
|
||||
Boolean less than, greater than, less than or equal, and greater than or equal.
|
||||
.TP 20
|
||||
\fB==\0\0!=\fR
|
||||
.
|
||||
Boolean equal and not equal. Each operator produces a zero/one result.
|
||||
Valid for all operand types.
|
||||
Boolean equal and not equal.
|
||||
.TP 20
|
||||
\fBeq\0\0ne\fR
|
||||
.
|
||||
Boolean string equal and string not equal. Each operator produces a
|
||||
zero/one result. The operand types are interpreted only as strings.
|
||||
Boolean string equal and string not equal.
|
||||
.TP 20
|
||||
\fBin\0\0ni\fR
|
||||
.
|
||||
List containment and negated list containment. Each operator produces
|
||||
a zero/one result and treats its first argument as a string and its
|
||||
second argument as a Tcl list. The \fBin\fR operator indicates
|
||||
whether the first argument is a member of the second argument list;
|
||||
the \fBni\fR operator inverts the sense of the result.
|
||||
List containment and negated list containment. The first argument is
|
||||
interpreted as a string, the second as a list. \fBin\fR tests for membership
|
||||
in the list, and \fBni\fR is the inverse.
|
||||
.TP 20
|
||||
\fB&\fR
|
||||
.
|
||||
Bit-wise AND. Valid for integer operands only.
|
||||
Bit-wise AND. Valid for integer operands.
|
||||
.TP 20
|
||||
\fB^\fR
|
||||
.
|
||||
Bit-wise exclusive OR. Valid for integer operands only.
|
||||
Bit-wise exclusive OR. Valid for integer operands.
|
||||
.TP 20
|
||||
\fB|\fR
|
||||
.
|
||||
Bit-wise OR. Valid for integer operands only.
|
||||
Bit-wise OR. Valid for integer operands.
|
||||
.TP 20
|
||||
\fB&&\fR
|
||||
.
|
||||
Logical AND. Produces a 1 result if both operands are non-zero,
|
||||
0 otherwise.
|
||||
Valid for boolean and numeric (integers or floating-point) operands only.
|
||||
Logical AND. If both operands are true, the result is 1, or 0 otherwise.
|
||||
|
||||
.TP 20
|
||||
\fB||\fR
|
||||
.
|
||||
Logical OR. Produces a 0 result if both operands are zero, 1 otherwise.
|
||||
Valid for boolean and numeric (integers or floating-point) operands only.
|
||||
Logical OR. If both operands are false, the result is 0, or 1 otherwise.
|
||||
.TP 20
|
||||
\fIx\fB?\fIy\fB:\fIz\fR
|
||||
.
|
||||
If-then-else, as in C. If \fIx\fR
|
||||
evaluates to non-zero, then the result is the value of \fIy\fR.
|
||||
Otherwise the result is the value of \fIz\fR.
|
||||
The \fIx\fR operand must have a boolean or numeric value.
|
||||
If-then-else, as in C. If \fIx\fR is false , the result is the value of
|
||||
\fIy\fR. Otherwise the result is the value of \fIz\fR.
|
||||
.PP
|
||||
See the C manual for more details on the results
|
||||
produced by each operator.
|
||||
The exponentiation operator promotes types like the multiply and
|
||||
divide operators, and produces a result that is the same as the output
|
||||
of the \fBpow\fR function (after any type conversions.)
|
||||
All of the binary operators but exponentiation group left-to-right
|
||||
within the same precedence level; exponentiation groups right-to-left. For example, the command
|
||||
The exponentiation operator promotes types in the same way that the multiply
|
||||
and divide operators do, and the result is is the same as the result of
|
||||
\fBpow\fR.
|
||||
Exponentiation groups right-to-left within a precedence level. Other binary
|
||||
operators group left-to-right. For example, the value of
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {4*2 < 7}
|
||||
.CE
|
||||
.PP
|
||||
returns 0, while
|
||||
is 0, while the value of
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {2**3**2}
|
||||
.CE
|
||||
.PP
|
||||
returns 512.
|
||||
is 512.
|
||||
.PP
|
||||
The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have
|
||||
As in C, \fB&&\fR, \fB||\fR, and \fB?:\fR feature
|
||||
.QW "lazy evaluation" ,
|
||||
just as in C, which means that operands are not evaluated if they are
|
||||
not needed to determine the outcome. For example, in the command
|
||||
which means that operands are not evaluated if they are
|
||||
not needed to determine the outcome. For example, in
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {$v ? [a] : [b]}
|
||||
.CE
|
||||
.PP
|
||||
only one of
|
||||
.QW \fB[a]\fR
|
||||
or
|
||||
.QW \fB[b]\fR
|
||||
will actually be evaluated,
|
||||
depending on the value of \fB$v\fR. Note, however, that this is
|
||||
only true if the entire expression is enclosed in braces; otherwise
|
||||
the Tcl parser will evaluate both
|
||||
.QW \fB[a]\fR
|
||||
and
|
||||
.QW \fB[b]\fR
|
||||
before invoking the \fBexpr\fR command.
|
||||
only one of \fB[a]\fR or \fB[b]\fR is evaluated,
|
||||
depending on the value of \fB$v\fR. This is not true of the normal Tcl parser,
|
||||
so it is normally recommended to enclose the arguments to \fBexpr\fR in braces.
|
||||
Without braces, as in
|
||||
\fBexpr\fR $v ? [a] : [b]
|
||||
both \fB[a]\fR and \fB[b]\fR are evaluated before \fBexpr\fR is even called.
|
||||
.PP
|
||||
For more details on the results
|
||||
produced by each operator, see the documentation for C.
|
||||
.SS "MATH FUNCTIONS"
|
||||
.PP
|
||||
When the expression parser encounters a mathematical function
|
||||
such as \fBsin($x)\fR, it replaces it with a call to an ordinary
|
||||
Tcl function in the \fBtcl::mathfunc\fR namespace. The processing
|
||||
of an expression such as:
|
||||
A mathematical function such as \fBsin($x)\fR is replaced with a call to an ordinary
|
||||
Tcl command in the \fBtcl::mathfunc\fR namespace. The evaluation
|
||||
of an expression such as
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {sin($x+$y)}
|
||||
.CE
|
||||
.PP
|
||||
is the same in every way as the processing of:
|
||||
is the same in every way as the evaluation of
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {[tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]]}
|
||||
.CE
|
||||
.PP
|
||||
which in turn is the same as the processing of:
|
||||
which in turn is the same as the evaluation of
|
||||
.PP
|
||||
.CS
|
||||
tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]
|
||||
.CE
|
||||
.PP
|
||||
The executor will search for \fBtcl::mathfunc::sin\fR using the usual
|
||||
rules for resolving functions in namespaces. Either
|
||||
\fB::tcl::mathfunc::sin\fR or \fB[namespace
|
||||
current]::tcl::mathfunc::sin\fR will satisfy the request, and others
|
||||
may as well (depending on the current \fBnamespace path\fR setting).
|
||||
\fBtcl::mathfunc::sin\fR is resolved as described in
|
||||
\fBNAMESPACE RESOLUTION\fR in the \fBnamespace\fR(n) documentation. Given the
|
||||
default value of \fBnamespace path\fR, \fB[namespace
|
||||
current]::tcl::mathfunc::sin\fR or \fB::tcl::mathfunc::sin\fR are the typical
|
||||
resolutions.
|
||||
.PP
|
||||
Some mathematical functions have several arguments, separated by commas like in C. Thus:
|
||||
As in C, a mathematical function may accept multiple arguments separated by commas. Thus,
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {hypot($x,$y)}
|
||||
.CE
|
||||
.PP
|
||||
ends up as
|
||||
becomes
|
||||
.PP
|
||||
.CS
|
||||
tcl::mathfunc::hypot $x $y
|
||||
.CE
|
||||
.PP
|
||||
See the \fBmathfunc\fR(n) manual page for the math functions that are
|
||||
See the \fBmathfunc\fR(n) documentation for the math functions that are
|
||||
available by default.
|
||||
.SS "TYPES, OVERFLOW, AND PRECISION"
|
||||
.PP
|
||||
All internal computations involving integers are done calling on the
|
||||
LibTomMath multiple precision integer library as required so that all
|
||||
integer calculations are performed exactly. Note that in Tcl releases
|
||||
prior to 8.5, integer calculations were performed with one of the C types
|
||||
When needed to guarantee exact performance, internal computations involving
|
||||
integers use the LibTomMath multiple precision integer library. In Tcl releases
|
||||
prior to 8.5, integer calculations were performed using one of the C types
|
||||
\fIlong int\fR or \fITcl_WideInt\fR, causing implicit range truncation
|
||||
in those calculations where values overflowed the range of those types.
|
||||
Any code that relied on these implicit truncations will need to explicitly
|
||||
add \fBint()\fR or \fBwide()\fR function calls to expressions at the points
|
||||
where such truncation is required to take place.
|
||||
Any code that relied on these implicit truncations should instead call
|
||||
\fBint()\fR or \fBwide()\fR, which do truncate.
|
||||
.PP
|
||||
All internal computations involving floating-point are
|
||||
done with the C type \fIdouble\fR.
|
||||
When converting a string to floating-point, exponent overflow is
|
||||
Internal floating-point computations are
|
||||
performed using the \fIdouble\fR C type.
|
||||
When converting a string to floating-point value, exponent overflow is
|
||||
detected and results in the \fIdouble\fR value of \fBInf\fR or
|
||||
\fB\-Inf\fR as appropriate. Floating-point overflow and underflow
|
||||
are detected to the degree supported by the hardware, which is generally
|
||||
pretty reliable.
|
||||
fairly reliable.
|
||||
.PP
|
||||
Conversion among internal representations for integer, floating-point,
|
||||
and string operands is done automatically as needed.
|
||||
For arithmetic computations, integers are used until some
|
||||
floating-point number is introduced, after which floating-point is used.
|
||||
For example,
|
||||
Conversion among internal representations for integer, floating-point, and
|
||||
string operands is done automatically as needed. For arithmetic computations,
|
||||
integers are used until some floating-point number is introduced, after which
|
||||
floating-point values are used. For example,
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {5 / 4}
|
||||
@@ -335,82 +312,62 @@ returns 1, while
|
||||
.CE
|
||||
.PP
|
||||
both return 1.25.
|
||||
Floating-point values are always returned with a
|
||||
A floating-point result can be distinguished from an integer result by the
|
||||
presence of either
|
||||
.QW \fB.\fR
|
||||
or an
|
||||
or
|
||||
.QW \fBe\fR
|
||||
so that they will not look like integer values. For example,
|
||||
.PP
|
||||
. For example,
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {20.0/5.0}
|
||||
.CE
|
||||
.PP
|
||||
returns \fB4.0\fR, not \fB4\fR.
|
||||
.SS "STRING OPERATIONS"
|
||||
.PP
|
||||
String values may be used as operands of the comparison operators,
|
||||
although the expression evaluator tries to do comparisons as integer
|
||||
or floating-point when it can,
|
||||
i.e., when all arguments to the operator allow numeric interpretations,
|
||||
except in the case of the \fBeq\fR and \fBne\fR operators.
|
||||
If one of the operands of a comparison is a string and the other
|
||||
has a numeric value, a canonical string representation of the numeric
|
||||
operand value is generated to compare with the string operand.
|
||||
Canonical string representation for integer values is a decimal string
|
||||
format. Canonical string representation for floating-point values
|
||||
is that produced by the \fB%g\fR format specifier of Tcl's
|
||||
\fBformat\fR command. For example, the commands
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {"0x03" > "2"}
|
||||
\fBexpr\fR {"0y" > "0x12"}
|
||||
.CE
|
||||
.PP
|
||||
both return 1. The first comparison is done using integer
|
||||
comparison, and the second is done using string comparison.
|
||||
Because of Tcl's tendency to treat values as numbers whenever
|
||||
possible, it is not generally a good idea to use operators like \fB==\fR
|
||||
when you really want string comparison and the values of the
|
||||
operands could be arbitrary; it is better in these cases to use
|
||||
the \fBeq\fR or \fBne\fR operators, or the \fBstring\fR command instead.
|
||||
.SH "PERFORMANCE CONSIDERATIONS"
|
||||
.PP
|
||||
Enclose expressions in braces for the best speed and the smallest
|
||||
storage requirements.
|
||||
This allows the Tcl bytecode compiler to generate the best code.
|
||||
.PP
|
||||
As mentioned above, expressions are substituted twice:
|
||||
once by the Tcl parser and once by the \fBexpr\fR command.
|
||||
For example, the commands
|
||||
Where an expression contains syntax that Tcl would otherwise perform
|
||||
substitutions on, enclosing an expression in braces or otherwise quoting it
|
||||
so that it's a static value allows the Tcl compiler to generate bytecode for
|
||||
the expression, resulting in better speed and smaller storage requirements.
|
||||
This also avoids issues that can arise if Tcl is allowed to perform
|
||||
substitution on the value before \fBexpr\fR is called.
|
||||
.PP
|
||||
In the following example, the value of the expression is 11 because the Tcl parser first
|
||||
substitutes \fB$b\fR and \fBexpr\fR then substitutes \fB$a\fR. Enclosing the
|
||||
expression in braces would result in a syntax error.
|
||||
.CS
|
||||
set a 3
|
||||
set b {$a + 2}
|
||||
\fBexpr\fR $b*4
|
||||
.CE
|
||||
.PP
|
||||
return 11, not a multiple of 4.
|
||||
This is because the Tcl parser will first substitute \fB$a + 2\fR for
|
||||
the variable \fBb\fR,
|
||||
then the \fBexpr\fR command will evaluate the expression \fB$a + 2*4\fR.
|
||||
.PP
|
||||
Most expressions do not require a second round of substitutions.
|
||||
Either they are enclosed in braces or, if not,
|
||||
their variable and command substitutions yield numbers or strings
|
||||
that do not themselves require substitutions.
|
||||
However, because a few unbraced expressions
|
||||
need two rounds of substitutions,
|
||||
the bytecode compiler must emit
|
||||
additional instructions to handle this situation.
|
||||
The most expensive code is required for
|
||||
unbraced expressions that contain command substitutions.
|
||||
These expressions must be implemented by generating new code
|
||||
each time the expression is executed.
|
||||
When the expression is unbraced to allow the substitution of a function or
|
||||
operator, consider using the commands documented in the \fBmathfunc\fR(n) or
|
||||
\fBmathop\fR(n) manual pages directly instead.
|
||||
|
||||
When an expression is generated at runtime, like the one above is, the bytcode
|
||||
compiler must ensure that new code is generated each time the expression
|
||||
is evaluated. This is the most costly kind of expression from a performance
|
||||
perspective. In such cases, consider directly using the commands described in
|
||||
the \fBmathfunc\fR(n) or \fBmathop\fR(n) documentation instead of \fBexpr\fR.
|
||||
|
||||
Most expressions are not formed at runtime, but are literal strings or contain
|
||||
substitutions that don't introduce other substitutions. To allow the bytecode
|
||||
compiler to work with an expression as a string literal at compilation time,
|
||||
ensure that it contains no substitutions or that it is enclosed in braces or
|
||||
otherwise quoted to prevent Tcl from performing substitutions, allowing
|
||||
\fBexpr\fR to perform them instead.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
A numeric comparison whose result is 1:
|
||||
.CS
|
||||
\fBexpr\fR {"0x03" > "2"}
|
||||
.CE
|
||||
.PP
|
||||
A string comparison whose result is 1:
|
||||
.CS
|
||||
\fBexpr\fR {"0y" > "0x12"}
|
||||
.CE
|
||||
.PP
|
||||
Define a procedure that computes an
|
||||
.QW interesting
|
||||
mathematical function:
|
||||
@@ -444,8 +401,8 @@ each other:
|
||||
puts "a and b are [\fBexpr\fR {$a eq $b ? {equal} : {different}}]"
|
||||
.CE
|
||||
.PP
|
||||
Set a variable to whether an environment variable is both defined at
|
||||
all and also set to a true boolean value:
|
||||
Set a variable indicating whether an environment variable is defined and has
|
||||
value of true:
|
||||
.PP
|
||||
.CS
|
||||
set isTrue [\fBexpr\fR {
|
||||
|
||||
+9
-3
@@ -25,12 +25,15 @@ network sockets.
|
||||
.PP
|
||||
The \fBfcopy\fR
|
||||
command transfers data from \fIinchan\fR until end of file
|
||||
or \fIsize\fR bytes have been
|
||||
transferred. If no \fB\-size\fR argument is given,
|
||||
or \fIsize\fR bytes or characters have been
|
||||
transferred; \fIsize\fR is in bytes if the two channels are using the
|
||||
same encoding, and is in characters otherwise.
|
||||
If no \fB\-size\fR argument is given,
|
||||
then the copy goes until end of file.
|
||||
All the data read from \fIinchan\fR is copied to \fIoutchan\fR.
|
||||
Without the \fB\-command\fR option, \fBfcopy\fR blocks until the copy is complete
|
||||
and returns the number of bytes written to \fIoutchan\fR.
|
||||
and returns the number of bytes or characters (using the same rules as
|
||||
for the \fB\-size\fR option) written to \fIoutchan\fR.
|
||||
.PP
|
||||
The \fB\-command\fR argument makes \fBfcopy\fR work in the background.
|
||||
In this case it returns immediately and the \fIcallback\fR is invoked
|
||||
@@ -174,3 +177,6 @@ vwait done
|
||||
eof(n), fblocked(n), fconfigure(n), file(n)
|
||||
.SH KEYWORDS
|
||||
blocking, channel, end of line, end of file, nonblocking, read, translation
|
||||
'\" Local Variables:
|
||||
'\" mode: nroff
|
||||
'\" End:
|
||||
|
||||
+7
-6
@@ -162,7 +162,9 @@ returns \fB/home\fR (or something similar).
|
||||
\fBfile executable \fIname\fR
|
||||
.
|
||||
Returns \fB1\fR if file \fIname\fR is executable by the current user,
|
||||
\fB0\fR otherwise.
|
||||
\fB0\fR otherwise. On Windows, which does not have an executable attribute,
|
||||
the command treats all directories and any files with extensions
|
||||
\fBexe\fR, \fBcom\fR, \fBcmd\fR or \fBbat\fR as executable.
|
||||
.TP
|
||||
\fBfile exists \fIname\fR
|
||||
.
|
||||
@@ -388,7 +390,7 @@ that use the third component do not attempt to perform tilde
|
||||
substitution.
|
||||
.RE
|
||||
.TP
|
||||
\fBfile stat \fIname varName\fR
|
||||
\fBfile stat \fIname varName\fR
|
||||
.
|
||||
Invokes the \fBstat\fR kernel call on \fIname\fR, and uses the variable
|
||||
given by \fIvarName\fR to hold information returned from the kernel call.
|
||||
@@ -482,10 +484,9 @@ not the effective ones.
|
||||
.TP
|
||||
\fBWindows\fR\0\0\0\0
|
||||
.
|
||||
The \fBfile owned\fR subcommand currently always reports that the current user
|
||||
is the owner of the file, without regard for what the operating system
|
||||
believes to be true, making an ownership test useless. This issue (#3613671)
|
||||
may be fixed in a future release of Tcl.
|
||||
The \fBfile owned\fR subcommand uses the user identifier (SID) of
|
||||
the process token, not the thread token which may be impersonating
|
||||
some other user.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
This procedure shows how to search for C files in a given directory
|
||||
|
||||
+4
-1
@@ -418,7 +418,10 @@ set token [::http::geturl https://my.secure.site/]
|
||||
\fB::http::unregister\fR \fIproto\fR
|
||||
.
|
||||
This procedure unregisters a protocol handler that was previously
|
||||
registered via \fB::http::register\fR.
|
||||
registered via \fB::http::register\fR, returning a two-item list of
|
||||
the default port and handler command that was previously installed
|
||||
(via \fB::http::register\fR) if there was such a handler, and an error if
|
||||
there was no such handler.
|
||||
.SH ERRORS
|
||||
The \fB::http::geturl\fR procedure will raise errors in the following cases:
|
||||
invalid command line options,
|
||||
|
||||
+23
-5
@@ -34,8 +34,9 @@ one or two fields. If there is only a single field in the specifier
|
||||
then it is the name of the argument; if there are two fields, then
|
||||
the first is the argument name and the second is its default value.
|
||||
Arguments with default values that are followed by non-defaulted
|
||||
arguments become required arguments. In 8.6 this will be considered an
|
||||
error.
|
||||
arguments become required arguments; enough actual arguments must be
|
||||
supplied to allow all arguments up to and including the last required
|
||||
formal argument.
|
||||
.PP
|
||||
When \fIname\fR is invoked a local variable
|
||||
will be created for each of the formal arguments to the procedure; its
|
||||
@@ -48,11 +49,14 @@ actual arguments for all the
|
||||
formal arguments that do not have defaults, and there must not be any extra
|
||||
actual arguments.
|
||||
Arguments with default values that are followed by non-defaulted
|
||||
arguments become required arguments (in 8.6 it will be considered an
|
||||
error).
|
||||
arguments become de-facto required arguments, though this may change
|
||||
in a future version of Tcl; portable code should ensure that all
|
||||
optional arguments come after all required arguments.
|
||||
.PP
|
||||
There is one special case to permit procedures with
|
||||
variable numbers of arguments. If the last formal argument has the name
|
||||
\fBargs\fR, then a call to the procedure may contain more actual arguments
|
||||
.QW \fBargs\fR ,
|
||||
then a call to the procedure may contain more actual arguments
|
||||
than the procedure has formal arguments. In this case, all of the actual arguments
|
||||
starting at the one that would be assigned to \fBargs\fR are combined into
|
||||
a list (as if the \fBlist\fR command had been used); this combined value
|
||||
@@ -80,6 +84,20 @@ If an error occurs while executing the procedure
|
||||
body, then the procedure-as-a-whole will return that same error.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
This is a procedure that takes two arguments and prints both their sum
|
||||
and their product. It also returns the string
|
||||
.QW OK
|
||||
to the caller as an explicit result.
|
||||
.PP
|
||||
.CS
|
||||
\fBproc\fR printSumProduct {x y} {
|
||||
set sum [expr {$x + $y}]
|
||||
set prod [expr {$x * $y}]
|
||||
puts "sum is $sum, product is $prod"
|
||||
return "OK"
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
This is a procedure that accepts arbitrarily many arguments and prints
|
||||
them out, one by one.
|
||||
.PP
|
||||
|
||||
+1
-3
@@ -123,9 +123,7 @@ with conversion character \fBu\fR.
|
||||
.TP
|
||||
\fBi\fR
|
||||
.
|
||||
The input substring must be an integer. The base (i.e. decimal, binary,
|
||||
octal, or hexadecimal) is determined in the same fashion as described in
|
||||
\fBexpr\fR. The integer value is stored in the variable,
|
||||
The input substring must be an integer. The base (i.e. decimal, octal, or hexadecimal) is determined by the C convention (leading 0 for octal; prefix 0x for hexadecimal). The integer value is stored in the variable,
|
||||
truncated as required by the size modifier value.
|
||||
.TP
|
||||
\fBc\fR
|
||||
|
||||
+12
-2
@@ -872,8 +872,8 @@ harness are doing.
|
||||
.
|
||||
Sets the type of output verbosity desired to \fIlevel\fR,
|
||||
a list of zero or more of the elements \fBbody\fR, \fBpass\fR,
|
||||
\fBskip\fR, \fBstart\fR, \fBerror\fR and \fBline\fR. Default value
|
||||
is
|
||||
\fBskip\fR, \fBstart\fR, \fBerror\fR, \fBline\fR, \fBmsec\fR and \fBusec\fR.
|
||||
Default value is
|
||||
.QW "\fBbody error\fR" .
|
||||
Levels are defined as:
|
||||
.RS
|
||||
@@ -890,6 +890,16 @@ Print errorInfo and errorCode, if they exist, when a test return code
|
||||
does not match its expected return code
|
||||
.IP "line (\fBl\fR)"
|
||||
Print source file line information of failed tests
|
||||
.IP "msec (\fBm\fR)"
|
||||
Print each test's execution time in milliseconds
|
||||
.IP "usec (\fBu\fR)"
|
||||
Print each test's execution time in microseconds
|
||||
.PP
|
||||
Note that the \fBmsec\fR and \fBusec\fR verbosity levels are provided as
|
||||
indicative measures only. They do not tackle the problem of repeatibility which
|
||||
should be considered in performance tests or benchmarks. To use these verbosity
|
||||
levels to thoroughly track performance degradations, consider wrapping your
|
||||
test bodies with \fBtime\fR commands.
|
||||
.PP
|
||||
The single letter abbreviations noted above are also recognized
|
||||
so that
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ tell \- Return current access position for an open channel
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Returns an integer string giving the current access position in
|
||||
Returns an integer giving the current access position in
|
||||
\fIchannelId\fR. This value returned is a byte offset that can be passed to
|
||||
\fBseek\fR in order to set the channel to a particular position. Note
|
||||
that this value is in terms of bytes, not characters like \fBread\fR.
|
||||
|
||||
+6
-1
@@ -45,7 +45,8 @@ linked to the corresponding namespace variables (and therefore these
|
||||
variables are listed by \fBinfo vars\fR.)
|
||||
In this way the \fBvariable\fR command resembles the \fBglobal\fR command,
|
||||
although the \fBglobal\fR command
|
||||
only links to variables in the global namespace.
|
||||
resolves variable names with respect to the global namespace instead
|
||||
of the current namespace of the procedure.
|
||||
If any \fIvalue\fRs are given,
|
||||
they are used to modify the values of the associated namespace variables.
|
||||
If a namespace variable does not exist,
|
||||
@@ -98,3 +99,7 @@ namespace eval foo {
|
||||
global(n), namespace(n), upvar(n)
|
||||
.SH KEYWORDS
|
||||
global, namespace, procedure, variable
|
||||
.\" Local variables:
|
||||
.\" mode: nroff
|
||||
.\" fill-column: 78
|
||||
.\" End:
|
||||
|
||||
+12
-6
@@ -174,7 +174,11 @@ to the \fBzlib push\fR command:
|
||||
.VS "TIP 400"
|
||||
Sets the compression dictionary to use when working with compressing or
|
||||
decompressing the data to be \fIbinData\fR. Not valid for transformations that
|
||||
work with gzip-format data.
|
||||
work with gzip-format data. The dictionary should consist of strings (byte
|
||||
sequences) that are likely to be encountered later in the data to be compressed,
|
||||
with the most commonly used strings preferably put towards the end of the
|
||||
dictionary. Tcl provides no mechanism for choosing a good such dictionary for
|
||||
a particular data sequence.
|
||||
.VE
|
||||
.TP
|
||||
\fB\-header\fI dictionary\fR
|
||||
@@ -207,11 +211,13 @@ compression algorithm depends on what format is being produced or consumed.
|
||||
.TP
|
||||
\fB\-dictionary\fI binData\fR
|
||||
.VS "TIP 400"
|
||||
This read-write options gets or sets the compression dictionary to use when
|
||||
working with compressing or decompressing the data to be \fIbinData\fR. It is
|
||||
not valid for transformations that work with gzip-format data, and should not
|
||||
normally be set on compressing transformations other than at the point where
|
||||
the transformation is stacked.
|
||||
This read-write options gets or sets the initial compression dictionary to use
|
||||
when working with compressing or decompressing the data to be \fIbinData\fR.
|
||||
It is not valid for transformations that work with gzip-format data, and should
|
||||
not normally be set on compressing transformations other than at the point where
|
||||
the transformation is stacked. Note that this cannot be used to get the
|
||||
current active compression dictionary mid-stream, as that information is not
|
||||
exposed by the underlying library.
|
||||
.VE
|
||||
.TP
|
||||
\fB\-flush\fI type\fR
|
||||
|
||||
+19
-6
@@ -256,20 +256,33 @@ static const chr brbacks[] = { /* \s within brackets */
|
||||
CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
|
||||
CHR(':'), CHR(']')
|
||||
};
|
||||
|
||||
#define PUNCT_CONN \
|
||||
CHR('_'), \
|
||||
0x203f /* UNDERTIE */, \
|
||||
0x2040 /* CHARACTER TIE */,\
|
||||
0x2054 /* INVERTED UNDERTIE */,\
|
||||
0xfe33 /* PRESENTATION FORM FOR VERTICAL LOW LINE */, \
|
||||
0xfe34 /* PRESENTATION FORM FOR VERTICAL WAVY LOW LINE */, \
|
||||
0xfe4d /* DASHED LOW LINE */, \
|
||||
0xfe4e /* CENTRELINE LOW LINE */, \
|
||||
0xfe4f /* WAVY LOW LINE */, \
|
||||
0xff3f /* FULLWIDTH LOW LINE */
|
||||
|
||||
static const chr backw[] = { /* \w */
|
||||
CHR('['), CHR('['), CHR(':'),
|
||||
CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
|
||||
CHR(':'), CHR(']'), CHR('_'), CHR(']')
|
||||
CHR(':'), CHR(']'), PUNCT_CONN, CHR(']')
|
||||
};
|
||||
static const chr backW[] = { /* \W */
|
||||
CHR('['), CHR('^'), CHR('['), CHR(':'),
|
||||
CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
|
||||
CHR(':'), CHR(']'), CHR('_'), CHR(']')
|
||||
CHR(':'), CHR(']'), PUNCT_CONN, CHR(']')
|
||||
};
|
||||
static const chr brbackw[] = { /* \w within brackets */
|
||||
CHR('['), CHR(':'),
|
||||
CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
|
||||
CHR(':'), CHR(']'), CHR('_')
|
||||
CHR(':'), CHR(']'), PUNCT_CONN
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -444,7 +457,7 @@ next(
|
||||
if (ATEOS()) {
|
||||
FAILW(REG_EESCAPE);
|
||||
}
|
||||
(DISCARD)lexescape(v);
|
||||
(void)lexescape(v);
|
||||
switch (v->nexttype) { /* not all escapes okay here */
|
||||
case PLAIN:
|
||||
return 1;
|
||||
@@ -703,7 +716,7 @@ next(
|
||||
}
|
||||
RETV(PLAIN, *v->now++);
|
||||
}
|
||||
(DISCARD)lexescape(v);
|
||||
(void)lexescape(v);
|
||||
if (ISERR()) {
|
||||
FAILW(REG_EESCAPE);
|
||||
}
|
||||
@@ -1130,7 +1143,7 @@ skip(
|
||||
/*
|
||||
- newline - return the chr for a newline
|
||||
* This helps confine use of CHR to this source file.
|
||||
^ static chr newline(NOPARMS);
|
||||
^ static chr newline(void);
|
||||
*/
|
||||
static chr
|
||||
newline(void)
|
||||
|
||||
+203
-192
@@ -140,35 +140,36 @@ static const crange alphaRangeTable[] = {
|
||||
{0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x561, 0x587},
|
||||
{0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3},
|
||||
{0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea},
|
||||
{0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b4}, {0x904, 0x939},
|
||||
{0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c}, {0x993, 0x9a8},
|
||||
{0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1}, {0xa05, 0xa0a},
|
||||
{0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c}, {0xa72, 0xa74},
|
||||
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
|
||||
{0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30},
|
||||
{0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a}, {0xb8e, 0xb90},
|
||||
{0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xc05, 0xc0c},
|
||||
{0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc58, 0xc5a},
|
||||
{0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3},
|
||||
{0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd3a},
|
||||
{0xd5f, 0xd61}, {0xd7a, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1},
|
||||
{0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe40, 0xe46},
|
||||
{0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb0},
|
||||
{0xec0, 0xec4}, {0xedc, 0xedf}, {0xf40, 0xf47}, {0xf49, 0xf6c},
|
||||
{0xf88, 0xf8c}, {0x1000, 0x102a}, {0x1050, 0x1055}, {0x105a, 0x105d},
|
||||
{0x106e, 0x1070}, {0x1075, 0x1081}, {0x10a0, 0x10c5}, {0x10d0, 0x10fa},
|
||||
{0x10fc, 0x1248}, {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d},
|
||||
{0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5},
|
||||
{0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310},
|
||||
{0x1312, 0x1315}, {0x1318, 0x135a}, {0x1380, 0x138f}, {0x13a0, 0x13f5},
|
||||
{0x13f8, 0x13fd}, {0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a},
|
||||
{0x16a0, 0x16ea}, {0x16f1, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1711},
|
||||
{0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770},
|
||||
{0x1780, 0x17b3}, {0x1820, 0x1877}, {0x1880, 0x18a8}, {0x18b0, 0x18f5},
|
||||
{0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},
|
||||
{0x19b0, 0x19c9}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33},
|
||||
{0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23},
|
||||
{0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1},
|
||||
{0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b4}, {0x8b6, 0x8bd},
|
||||
{0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c},
|
||||
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1},
|
||||
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c},
|
||||
{0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8},
|
||||
{0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28},
|
||||
{0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a},
|
||||
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
|
||||
{0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39},
|
||||
{0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8},
|
||||
{0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
|
||||
{0xd12, 0xd3a}, {0xd54, 0xd56}, {0xd5f, 0xd61}, {0xd7a, 0xd7f},
|
||||
{0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6},
|
||||
{0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97}, {0xe99, 0xe9f},
|
||||
{0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4}, {0xedc, 0xedf},
|
||||
{0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c}, {0x1000, 0x102a},
|
||||
{0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070}, {0x1075, 0x1081},
|
||||
{0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248}, {0x124a, 0x124d},
|
||||
{0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d},
|
||||
{0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5},
|
||||
{0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a},
|
||||
{0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1401, 0x166c},
|
||||
{0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x16f1, 0x16f8},
|
||||
{0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751},
|
||||
{0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3}, {0x1820, 0x1877},
|
||||
{0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5}, {0x1900, 0x191e},
|
||||
{0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9},
|
||||
{0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33}, {0x1b45, 0x1b4b},
|
||||
{0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23}, {0x1c4d, 0x1c4f},
|
||||
{0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1},
|
||||
{0x1d00, 0x1dbf}, {0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45},
|
||||
{0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4},
|
||||
{0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3},
|
||||
@@ -183,7 +184,7 @@ static const crange alphaRangeTable[] = {
|
||||
{0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5},
|
||||
{0x4e00, 0x9fd5}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c},
|
||||
{0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5},
|
||||
{0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ad}, {0xa7b0, 0xa7b7},
|
||||
{0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ae}, {0xa7b0, 0xa7b7},
|
||||
{0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a}, {0xa80c, 0xa822},
|
||||
{0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7}, {0xa90a, 0xa925},
|
||||
{0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2}, {0xa9e0, 0xa9e4},
|
||||
@@ -193,6 +194,8 @@ static const crange alphaRangeTable[] = {
|
||||
{0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
|
||||
{0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2}, {0xac00, 0xd7a3},
|
||||
{0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e},
|
||||
{0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e}, {0xdd40, 0xdd7e},
|
||||
{0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e}, {0xde40, 0xde7e},
|
||||
{0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e},
|
||||
{0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9},
|
||||
{0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36},
|
||||
@@ -205,36 +208,38 @@ static const crange alphaRangeTable[] = {
|
||||
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0},
|
||||
{0x10300, 0x1031f}, {0x10330, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
|
||||
{0x10380, 0x1039d}, {0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d},
|
||||
{0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
|
||||
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
|
||||
{0x10860, 0x10876}, {0x10880, 0x1089e}, {0x108e0, 0x108f2}, {0x10900, 0x10915},
|
||||
{0x10920, 0x10939}, {0x10980, 0x109b7}, {0x10a10, 0x10a13}, {0x10a15, 0x10a17},
|
||||
{0x10a19, 0x10a33}, {0x10a60, 0x10a7c}, {0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7},
|
||||
{0x10ac9, 0x10ae4}, {0x10b00, 0x10b35}, {0x10b40, 0x10b55}, {0x10b60, 0x10b72},
|
||||
{0x10b80, 0x10b91}, {0x10c00, 0x10c48}, {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2},
|
||||
{0x11003, 0x11037}, {0x11083, 0x110af}, {0x110d0, 0x110e8}, {0x11103, 0x11126},
|
||||
{0x11150, 0x11172}, {0x11183, 0x111b2}, {0x111c1, 0x111c4}, {0x11200, 0x11211},
|
||||
{0x11213, 0x1122b}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d},
|
||||
{0x1129f, 0x112a8}, {0x112b0, 0x112de}, {0x11305, 0x1130c}, {0x11313, 0x11328},
|
||||
{0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1135d, 0x11361}, {0x11480, 0x114af},
|
||||
{0x104b0, 0x104d3}, {0x104d8, 0x104fb}, {0x10500, 0x10527}, {0x10530, 0x10563},
|
||||
{0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
|
||||
{0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10860, 0x10876}, {0x10880, 0x1089e},
|
||||
{0x108e0, 0x108f2}, {0x10900, 0x10915}, {0x10920, 0x10939}, {0x10980, 0x109b7},
|
||||
{0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a60, 0x10a7c},
|
||||
{0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4}, {0x10b00, 0x10b35},
|
||||
{0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91}, {0x10c00, 0x10c48},
|
||||
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x11003, 0x11037}, {0x11083, 0x110af},
|
||||
{0x110d0, 0x110e8}, {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2},
|
||||
{0x111c1, 0x111c4}, {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286},
|
||||
{0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de},
|
||||
{0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339},
|
||||
{0x1135d, 0x11361}, {0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af},
|
||||
{0x11580, 0x115ae}, {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa},
|
||||
{0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x12000, 0x12399},
|
||||
{0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38},
|
||||
{0x16a40, 0x16a5e}, {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43},
|
||||
{0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f},
|
||||
{0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
|
||||
{0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9},
|
||||
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
|
||||
{0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
|
||||
{0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0}, {0x1d6c2, 0x1d6da},
|
||||
{0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, {0x1d736, 0x1d74e},
|
||||
{0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8}, {0x1d7aa, 0x1d7c2},
|
||||
{0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f},
|
||||
{0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a},
|
||||
{0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89},
|
||||
{0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb},
|
||||
{0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1},
|
||||
{0x2f800, 0x2fa1d}
|
||||
{0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08},
|
||||
{0x11c0a, 0x11c2e}, {0x11c72, 0x11c8f}, {0x12000, 0x12399}, {0x12480, 0x12543},
|
||||
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
|
||||
{0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77},
|
||||
{0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f}, {0x17000, 0x187ec},
|
||||
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
|
||||
{0x1bc90, 0x1bc99}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
|
||||
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
|
||||
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
|
||||
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0},
|
||||
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734},
|
||||
{0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8},
|
||||
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943},
|
||||
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
|
||||
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
|
||||
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
|
||||
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
|
||||
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -249,24 +254,24 @@ static const chr alphaCharTable[] = {
|
||||
0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1, 0xaf9,
|
||||
0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71, 0xb83,
|
||||
0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0, 0xc3d,
|
||||
0xc60, 0xc61, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2, 0xd3d,
|
||||
0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84, 0xe87, 0xe88,
|
||||
0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2, 0xeb3, 0xebd,
|
||||
0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e, 0x10c7, 0x10cd,
|
||||
0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae, 0x1baf, 0x1cf5,
|
||||
0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102, 0x2107,
|
||||
0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2, 0x2cf3,
|
||||
0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c, 0xa62a,
|
||||
0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6, 0xaac0,
|
||||
0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
|
||||
0xc60, 0xc61, 0xc80, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2,
|
||||
0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84, 0xe87,
|
||||
0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2, 0xeb3,
|
||||
0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e, 0x10c7,
|
||||
0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae, 0x1baf,
|
||||
0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102,
|
||||
0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2,
|
||||
0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c,
|
||||
0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6,
|
||||
0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
|
||||
#if TCL_UTF_MAX > 4
|
||||
,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be,
|
||||
0x109bf, 0x10a00, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, 0x11310, 0x11332,
|
||||
0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x16f50,
|
||||
0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546,
|
||||
0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49,
|
||||
0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f,
|
||||
0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
|
||||
0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x11c40,
|
||||
0x16f50, 0x16fe0, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6,
|
||||
0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42,
|
||||
0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b,
|
||||
0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -289,7 +294,7 @@ static const crange controlRangeTable[] = {
|
||||
#define NUM_CONTROL_RANGE (sizeof(controlRangeTable)/sizeof(crange))
|
||||
|
||||
static const chr controlCharTable[] = {
|
||||
0xad, 0x61c, 0x6dd, 0x70f, 0x180e, 0xfeff
|
||||
0xad, 0x61c, 0x6dd, 0x70f, 0x8e2, 0x180e, 0xfeff
|
||||
#if TCL_UTF_MAX > 4
|
||||
,0x110bd, 0xe0001
|
||||
#endif
|
||||
@@ -314,9 +319,10 @@ static const crange digitRangeTable[] = {
|
||||
{0xff10, 0xff19}
|
||||
#if TCL_UTF_MAX > 4
|
||||
,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f},
|
||||
{0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x114d0, 0x114d9}, {0x11650, 0x11659},
|
||||
{0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9}, {0x16a60, 0x16a69},
|
||||
{0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff}
|
||||
{0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459}, {0x114d0, 0x114d9},
|
||||
{0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9},
|
||||
{0x11c50, 0x11c59}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff},
|
||||
{0x1e950, 0x1e959}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -339,7 +345,7 @@ static const crange punctRangeTable[] = {
|
||||
{0x1b5a, 0x1b60}, {0x1bfc, 0x1bff}, {0x1c3b, 0x1c3f}, {0x1cc0, 0x1cc7},
|
||||
{0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205e},
|
||||
{0x2308, 0x230b}, {0x2768, 0x2775}, {0x27e6, 0x27ef}, {0x2983, 0x2998},
|
||||
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e42},
|
||||
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e44},
|
||||
{0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f},
|
||||
{0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd},
|
||||
{0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61},
|
||||
@@ -348,9 +354,9 @@ static const crange punctRangeTable[] = {
|
||||
#if TCL_UTF_MAX > 4
|
||||
,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f},
|
||||
{0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143},
|
||||
{0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x115c1, 0x115d7},
|
||||
{0x11641, 0x11643}, {0x1173c, 0x1173e}, {0x12470, 0x12474}, {0x16b37, 0x16b3b},
|
||||
{0x1da87, 0x1da8b}
|
||||
{0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x1144b, 0x1144f},
|
||||
{0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c}, {0x1173c, 0x1173e},
|
||||
{0x11c41, 0x11c45}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x1da87, 0x1da8b}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -371,8 +377,8 @@ static const chr punctCharTable[] = {
|
||||
0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d
|
||||
#if TCL_UTF_MAX > 4
|
||||
,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc,
|
||||
0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x114c6, 0x16a6e, 0x16a6f, 0x16af5,
|
||||
0x16b44, 0x1bc9f
|
||||
0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x11c70,
|
||||
0x11c71, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f, 0x1e95e, 0x1e95f
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -404,24 +410,24 @@ static const crange lowerRangeTable[] = {
|
||||
{0x199, 0x19b}, {0x1bd, 0x1bf}, {0x233, 0x239}, {0x24f, 0x293},
|
||||
{0x295, 0x2af}, {0x37b, 0x37d}, {0x3ac, 0x3ce}, {0x3d5, 0x3d7},
|
||||
{0x3ef, 0x3f3}, {0x430, 0x45f}, {0x561, 0x587}, {0x13f8, 0x13fd},
|
||||
{0x1d00, 0x1d2b}, {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a}, {0x1e95, 0x1e9d},
|
||||
{0x1eff, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37},
|
||||
{0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d},
|
||||
{0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4},
|
||||
{0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4},
|
||||
{0x2146, 0x2149}, {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, {0x2d00, 0x2d25},
|
||||
{0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a},
|
||||
{0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17},
|
||||
{0xff41, 0xff5a}
|
||||
{0x1c80, 0x1c88}, {0x1d00, 0x1d2b}, {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a},
|
||||
{0x1e95, 0x1e9d}, {0x1eff, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27},
|
||||
{0x1f30, 0x1f37}, {0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67},
|
||||
{0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7},
|
||||
{0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7},
|
||||
{0x1ff2, 0x1ff4}, {0x2146, 0x2149}, {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b},
|
||||
{0x2d00, 0x2d25}, {0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795},
|
||||
{0xab30, 0xab5a}, {0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06},
|
||||
{0xfb13, 0xfb17}, {0xff41, 0xff5a}
|
||||
#if TCL_UTF_MAX > 4
|
||||
,{0x10428, 0x1044f}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df}, {0x1d41a, 0x1d433},
|
||||
{0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9},
|
||||
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537},
|
||||
{0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607},
|
||||
{0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da},
|
||||
{0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b}, {0x1d736, 0x1d74e},
|
||||
{0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2},
|
||||
{0x1d7c4, 0x1d7c9}
|
||||
,{0x10428, 0x1044f}, {0x104d8, 0x104fb}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df},
|
||||
{0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b},
|
||||
{0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503},
|
||||
{0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3},
|
||||
{0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5},
|
||||
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b},
|
||||
{0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f},
|
||||
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, {0x1e922, 0x1e943}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -513,15 +519,15 @@ static const crange upperRangeTable[] = {
|
||||
{0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb},
|
||||
{0x210b, 0x210d}, {0x2110, 0x2112}, {0x2119, 0x211d}, {0x212a, 0x212d},
|
||||
{0x2130, 0x2133}, {0x2c00, 0x2c2e}, {0x2c62, 0x2c64}, {0x2c6d, 0x2c70},
|
||||
{0x2c7e, 0x2c80}, {0xa7aa, 0xa7ad}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a}
|
||||
{0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a}
|
||||
#if TCL_UTF_MAX > 4
|
||||
,{0x10400, 0x10427}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf}, {0x1d400, 0x1d419},
|
||||
{0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5},
|
||||
{0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c},
|
||||
{0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d56c, 0x1d585},
|
||||
{0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621}, {0x1d63c, 0x1d655},
|
||||
{0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734},
|
||||
{0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}
|
||||
,{0x10400, 0x10427}, {0x104b0, 0x104d3}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf},
|
||||
{0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac},
|
||||
{0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
|
||||
{0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550},
|
||||
{0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621},
|
||||
{0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa},
|
||||
{0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}, {0x1e900, 0x1e921}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -610,26 +616,26 @@ static const crange graphRangeTable[] = {
|
||||
{0x5d0, 0x5ea}, {0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc},
|
||||
{0x6de, 0x70d}, {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa},
|
||||
{0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x8a0, 0x8b4},
|
||||
{0x8e3, 0x983}, {0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0},
|
||||
{0x9b6, 0x9b9}, {0x9bc, 0x9c4}, {0x9cb, 0x9ce}, {0x9df, 0x9e3},
|
||||
{0x9e6, 0x9fb}, {0xa01, 0xa03}, {0xa05, 0xa0a}, {0xa13, 0xa28},
|
||||
{0xa2a, 0xa30}, {0xa3e, 0xa42}, {0xa4b, 0xa4d}, {0xa59, 0xa5c},
|
||||
{0xa66, 0xa75}, {0xa81, 0xa83}, {0xa85, 0xa8d}, {0xa8f, 0xa91},
|
||||
{0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xabc, 0xac5},
|
||||
{0xac7, 0xac9}, {0xacb, 0xacd}, {0xae0, 0xae3}, {0xae6, 0xaf1},
|
||||
{0xb01, 0xb03}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30},
|
||||
{0xb35, 0xb39}, {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63},
|
||||
{0xb66, 0xb77}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95},
|
||||
{0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8},
|
||||
{0xbca, 0xbcd}, {0xbe6, 0xbfa}, {0xc00, 0xc03}, {0xc05, 0xc0c},
|
||||
{0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc3d, 0xc44},
|
||||
{0xc46, 0xc48}, {0xc4a, 0xc4d}, {0xc58, 0xc5a}, {0xc60, 0xc63},
|
||||
{0xc66, 0xc6f}, {0xc78, 0xc7f}, {0xc81, 0xc83}, {0xc85, 0xc8c},
|
||||
{0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9},
|
||||
{0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3},
|
||||
{0xce6, 0xcef}, {0xd01, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
|
||||
{0xd12, 0xd3a}, {0xd3d, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4e},
|
||||
{0xd5f, 0xd63}, {0xd66, 0xd75}, {0xd79, 0xd7f}, {0xd85, 0xd96},
|
||||
{0x8b6, 0x8bd}, {0x8d4, 0x8e1}, {0x8e3, 0x983}, {0x985, 0x98c},
|
||||
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4},
|
||||
{0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fb}, {0xa01, 0xa03},
|
||||
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42},
|
||||
{0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75}, {0xa81, 0xa83},
|
||||
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
|
||||
{0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd},
|
||||
{0xae0, 0xae3}, {0xae6, 0xaf1}, {0xb01, 0xb03}, {0xb05, 0xb0c},
|
||||
{0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb3c, 0xb44},
|
||||
{0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77}, {0xb85, 0xb8a},
|
||||
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
|
||||
{0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, {0xbe6, 0xbfa},
|
||||
{0xc00, 0xc03}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
|
||||
{0xc2a, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48}, {0xc4a, 0xc4d},
|
||||
{0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc83},
|
||||
{0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3},
|
||||
{0xcb5, 0xcb9}, {0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd},
|
||||
{0xce0, 0xce3}, {0xce6, 0xcef}, {0xd01, 0xd03}, {0xd05, 0xd0c},
|
||||
{0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd3d, 0xd44}, {0xd46, 0xd48},
|
||||
{0xd4a, 0xd4f}, {0xd54, 0xd63}, {0xd66, 0xd7f}, {0xd85, 0xd96},
|
||||
{0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xdcf, 0xdd4},
|
||||
{0xdd8, 0xddf}, {0xde6, 0xdef}, {0xdf2, 0xdf4}, {0xe01, 0xe3a},
|
||||
{0xe3f, 0xe5b}, {0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3},
|
||||
@@ -650,25 +656,25 @@ static const crange graphRangeTable[] = {
|
||||
{0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, {0x1a60, 0x1a7c}, {0x1a7f, 0x1a89},
|
||||
{0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, {0x1ab0, 0x1abe}, {0x1b00, 0x1b4b},
|
||||
{0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37}, {0x1c3b, 0x1c49},
|
||||
{0x1c4d, 0x1c7f}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6}, {0x1d00, 0x1df5},
|
||||
{0x1dfc, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
|
||||
{0x1c4d, 0x1c88}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6}, {0x1d00, 0x1df5},
|
||||
{0x1dfb, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
|
||||
{0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4},
|
||||
{0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4},
|
||||
{0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e},
|
||||
{0x2090, 0x209c}, {0x20a0, 0x20be}, {0x20d0, 0x20f0}, {0x2100, 0x218b},
|
||||
{0x2190, 0x23fa}, {0x2400, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73},
|
||||
{0x2190, 0x23fe}, {0x2400, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73},
|
||||
{0x2b76, 0x2b95}, {0x2b98, 0x2bb9}, {0x2bbd, 0x2bc8}, {0x2bca, 0x2bd1},
|
||||
{0x2bec, 0x2bef}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3},
|
||||
{0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96}, {0x2da0, 0x2da6},
|
||||
{0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6},
|
||||
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e42},
|
||||
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e44},
|
||||
{0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb},
|
||||
{0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312d},
|
||||
{0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3}, {0x31f0, 0x321e},
|
||||
{0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fd5}, {0xa000, 0xa48c},
|
||||
{0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ad},
|
||||
{0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ae},
|
||||
{0xa7b0, 0xa7b7}, {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877},
|
||||
{0xa880, 0xa8c4}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953},
|
||||
{0xa880, 0xa8c5}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953},
|
||||
{0xa95f, 0xa97c}, {0xa980, 0xa9cd}, {0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe},
|
||||
{0xaa00, 0xaa36}, {0xaa40, 0xaa4d}, {0xaa50, 0xaa59}, {0xaa5c, 0xaac2},
|
||||
{0xaadb, 0xaaf6}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16},
|
||||
@@ -687,54 +693,59 @@ static const crange graphRangeTable[] = {
|
||||
#if TCL_UTF_MAX > 4
|
||||
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
|
||||
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133},
|
||||
{0x10137, 0x1018c}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
|
||||
{0x10137, 0x1018e}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
|
||||
{0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x10330, 0x1034a},
|
||||
{0x10350, 0x1037a}, {0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5},
|
||||
{0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x10500, 0x10527}, {0x10530, 0x10563},
|
||||
{0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
|
||||
{0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10857, 0x1089e}, {0x108a7, 0x108af},
|
||||
{0x108e0, 0x108f2}, {0x108fb, 0x1091b}, {0x1091f, 0x10939}, {0x10980, 0x109b7},
|
||||
{0x109bc, 0x109cf}, {0x109d2, 0x10a03}, {0x10a0c, 0x10a13}, {0x10a15, 0x10a17},
|
||||
{0x10a19, 0x10a33}, {0x10a38, 0x10a3a}, {0x10a3f, 0x10a47}, {0x10a50, 0x10a58},
|
||||
{0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6}, {0x10aeb, 0x10af6}, {0x10b00, 0x10b35},
|
||||
{0x10b39, 0x10b55}, {0x10b58, 0x10b72}, {0x10b78, 0x10b91}, {0x10b99, 0x10b9c},
|
||||
{0x10ba9, 0x10baf}, {0x10c00, 0x10c48}, {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2},
|
||||
{0x10cfa, 0x10cff}, {0x10e60, 0x10e7e}, {0x11000, 0x1104d}, {0x11052, 0x1106f},
|
||||
{0x1107f, 0x110bc}, {0x110be, 0x110c1}, {0x110d0, 0x110e8}, {0x110f0, 0x110f9},
|
||||
{0x11100, 0x11134}, {0x11136, 0x11143}, {0x11150, 0x11176}, {0x11180, 0x111cd},
|
||||
{0x111d0, 0x111df}, {0x111e1, 0x111f4}, {0x11200, 0x11211}, {0x11213, 0x1123d},
|
||||
{0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a9},
|
||||
{0x112b0, 0x112ea}, {0x112f0, 0x112f9}, {0x11300, 0x11303}, {0x11305, 0x1130c},
|
||||
{0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1133c, 0x11344},
|
||||
{0x1134b, 0x1134d}, {0x1135d, 0x11363}, {0x11366, 0x1136c}, {0x11370, 0x11374},
|
||||
{0x11480, 0x114c7}, {0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd},
|
||||
{0x11600, 0x11644}, {0x11650, 0x11659}, {0x11680, 0x116b7}, {0x116c0, 0x116c9},
|
||||
{0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x104b0, 0x104d3}, {0x104d8, 0x104fb},
|
||||
{0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
|
||||
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
|
||||
{0x10857, 0x1089e}, {0x108a7, 0x108af}, {0x108e0, 0x108f2}, {0x108fb, 0x1091b},
|
||||
{0x1091f, 0x10939}, {0x10980, 0x109b7}, {0x109bc, 0x109cf}, {0x109d2, 0x10a03},
|
||||
{0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a38, 0x10a3a},
|
||||
{0x10a3f, 0x10a47}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6},
|
||||
{0x10aeb, 0x10af6}, {0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72},
|
||||
{0x10b78, 0x10b91}, {0x10b99, 0x10b9c}, {0x10ba9, 0x10baf}, {0x10c00, 0x10c48},
|
||||
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10cff}, {0x10e60, 0x10e7e},
|
||||
{0x11000, 0x1104d}, {0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1},
|
||||
{0x110d0, 0x110e8}, {0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11143},
|
||||
{0x11150, 0x11176}, {0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4},
|
||||
{0x11200, 0x11211}, {0x11213, 0x1123e}, {0x11280, 0x11286}, {0x1128a, 0x1128d},
|
||||
{0x1128f, 0x1129d}, {0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9},
|
||||
{0x11300, 0x11303}, {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330},
|
||||
{0x11335, 0x11339}, {0x1133c, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363},
|
||||
{0x11366, 0x1136c}, {0x11370, 0x11374}, {0x11400, 0x11459}, {0x11480, 0x114c7},
|
||||
{0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644},
|
||||
{0x11650, 0x11659}, {0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9},
|
||||
{0x11700, 0x11719}, {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x118a0, 0x118f2},
|
||||
{0x11ac0, 0x11af8}, {0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474},
|
||||
{0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38},
|
||||
{0x16a40, 0x16a5e}, {0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5},
|
||||
{0x16b00, 0x16b45}, {0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77},
|
||||
{0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f},
|
||||
{0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
|
||||
{0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172},
|
||||
{0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356}, {0x1d360, 0x1d371},
|
||||
{0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9},
|
||||
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
|
||||
{0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
|
||||
{0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb}, {0x1d7ce, 0x1da8b},
|
||||
{0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e800, 0x1e8c4}, {0x1e8c7, 0x1e8d6},
|
||||
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
|
||||
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
|
||||
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
|
||||
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093},
|
||||
{0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5},
|
||||
{0x1f100, 0x1f10c}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f19a},
|
||||
{0x1f1e6, 0x1f202}, {0x1f210, 0x1f23a}, {0x1f240, 0x1f248}, {0x1f300, 0x1f579},
|
||||
{0x1f57b, 0x1f5a3}, {0x1f5a5, 0x1f6d0}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f3},
|
||||
{0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847},
|
||||
{0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x1f910, 0x1f918},
|
||||
{0x1f980, 0x1f984}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
|
||||
{0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
|
||||
{0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45},
|
||||
{0x11c50, 0x11c6c}, {0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6},
|
||||
{0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474}, {0x12480, 0x12543},
|
||||
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
|
||||
{0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45},
|
||||
{0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f},
|
||||
{0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x17000, 0x187ec},
|
||||
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
|
||||
{0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126},
|
||||
{0x1d129, 0x1d172}, {0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356},
|
||||
{0x1d360, 0x1d371}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
|
||||
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
|
||||
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
|
||||
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb},
|
||||
{0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006},
|
||||
{0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, {0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4},
|
||||
{0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, {0x1e950, 0x1e959}, {0x1ee00, 0x1ee03},
|
||||
{0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f},
|
||||
{0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c},
|
||||
{0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9},
|
||||
{0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae},
|
||||
{0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f10c},
|
||||
{0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202},
|
||||
{0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f300, 0x1f6d2}, {0x1f6e0, 0x1f6ec},
|
||||
{0x1f6f0, 0x1f6f6}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b},
|
||||
{0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad},
|
||||
{0x1f910, 0x1f91e}, {0x1f920, 0x1f927}, {0x1f933, 0x1f93e}, {0x1f940, 0x1f94b},
|
||||
{0x1f950, 0x1f95e}, {0x1f980, 0x1f991}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
|
||||
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -747,20 +758,20 @@ static const chr graphCharTable[] = {
|
||||
0xad0, 0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56,
|
||||
0xb57, 0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e,
|
||||
0xb9f, 0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6,
|
||||
0xcde, 0xcf1, 0xcf2, 0xd57, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6,
|
||||
0xe81, 0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7,
|
||||
0xeaa, 0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773,
|
||||
0x1940, 0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27,
|
||||
0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc,
|
||||
0xfffd
|
||||
0xcde, 0xcf1, 0xcf2, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81,
|
||||
0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa,
|
||||
0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940,
|
||||
0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d,
|
||||
0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd
|
||||
#if TCL_UTF_MAX > 4
|
||||
,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4,
|
||||
0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333,
|
||||
0x11347, 0x11348, 0x11350, 0x11357, 0x118ff, 0x16a6e, 0x16a6f, 0x1b000, 0x1b001,
|
||||
0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22,
|
||||
0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51,
|
||||
0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62,
|
||||
0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f9c0
|
||||
0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x118ff, 0x16a6e, 0x16a6f,
|
||||
0x16fe0, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb,
|
||||
0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27,
|
||||
0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54,
|
||||
0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e,
|
||||
0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f930, 0x1f9c0
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1216,7 +1227,7 @@ cmp(
|
||||
const chr *x, const chr *y, /* strings to compare */
|
||||
size_t len) /* exact length of comparison */
|
||||
{
|
||||
return memcmp(VS(x), VS(y), len*sizeof(chr));
|
||||
return memcmp((void*)(x), (void*)(y), len*sizeof(chr));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-2
@@ -843,7 +843,7 @@ moveins(
|
||||
|
||||
/*
|
||||
- copyins - copy in arcs of a state to another state
|
||||
^ static VOID copyins(struct nfa *, struct state *, struct state *, int);
|
||||
^ static void copyins(struct nfa *, struct state *, struct state *, int);
|
||||
*/
|
||||
static void
|
||||
copyins(
|
||||
@@ -1100,7 +1100,7 @@ moveouts(
|
||||
|
||||
/*
|
||||
- copyouts - copy out arcs of a state to another state
|
||||
^ static VOID copyouts(struct nfa *, struct state *, struct state *, int);
|
||||
^ static void copyouts(struct nfa *, struct state *, struct state *, int);
|
||||
*/
|
||||
static void
|
||||
copyouts(
|
||||
|
||||
+6
-6
@@ -82,7 +82,7 @@ static int lexescape(struct vars *);
|
||||
static int lexdigits(struct vars *, int, int, int);
|
||||
static int brenext(struct vars *, pchr);
|
||||
static void skip(struct vars *);
|
||||
static chr newline(NOPARMS);
|
||||
static chr newline(void);
|
||||
static chr chrnamed(struct vars *, const chr *, const chr *, pchr);
|
||||
/* === regc_color.c === */
|
||||
static void initcm(struct vars *, struct colormap *);
|
||||
@@ -341,13 +341,13 @@ compile(
|
||||
re->re_info = 0; /* bits get set during parse */
|
||||
re->re_csize = sizeof(chr);
|
||||
re->re_guts = NULL;
|
||||
re->re_fns = VS(&functions);
|
||||
re->re_fns = (void*)(&functions);
|
||||
|
||||
/*
|
||||
* More complex setup, malloced things.
|
||||
*/
|
||||
|
||||
re->re_guts = VS(MALLOC(sizeof(struct guts)));
|
||||
re->re_guts = (void*)(MALLOC(sizeof(struct guts)));
|
||||
if (re->re_guts == NULL) {
|
||||
return freev(v, REG_ESPACE);
|
||||
}
|
||||
@@ -434,7 +434,7 @@ compile(
|
||||
* Can sacrifice main NFA now, so use it as work area.
|
||||
*/
|
||||
|
||||
(DISCARD) optimize(v->nfa, debug);
|
||||
(void) optimize(v->nfa, debug);
|
||||
CNOERR();
|
||||
makesearch(v, v->nfa);
|
||||
CNOERR();
|
||||
@@ -1920,10 +1920,10 @@ nfatree(
|
||||
assert(t != NULL && t->begin != NULL);
|
||||
|
||||
if (t->left != NULL) {
|
||||
(DISCARD) nfatree(v, t->left, f);
|
||||
(void) nfatree(v, t->left, f);
|
||||
}
|
||||
if (t->right != NULL) {
|
||||
(DISCARD) nfatree(v, t->right, f);
|
||||
(void) nfatree(v, t->right, f);
|
||||
}
|
||||
|
||||
return nfanode(v, t, f);
|
||||
|
||||
+3
-4
@@ -36,10 +36,9 @@
|
||||
* Overrides for regguts.h definitions, if any.
|
||||
*/
|
||||
|
||||
#define FUNCPTR(name, args) (*name)args
|
||||
#define MALLOC(n) VS(attemptckalloc(n))
|
||||
#define FREE(p) ckfree(VS(p))
|
||||
#define REALLOC(p,n) VS(attemptckrealloc(VS(p),n))
|
||||
#define MALLOC(n) (void*)(attemptckalloc(n))
|
||||
#define FREE(p) ckfree((void*)(p))
|
||||
#define REALLOC(p,n) (void*)(attemptckrealloc((void*)(p),n))
|
||||
|
||||
/*
|
||||
* Do not insert extras between the "begin" and "end" lines - this chunk is
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ struct sset { /* state set */
|
||||
unsigned hash; /* hash of bitvector */
|
||||
#define HASH(bv, nw) (((nw) == 1) ? *(bv) : hash(bv, nw))
|
||||
#define HIT(h,bv,ss,nw) ((ss)->hash == (h) && ((nw) == 1 || \
|
||||
memcmp(VS(bv), VS((ss)->states), (nw)*sizeof(unsigned)) == 0))
|
||||
memcmp((void*)(bv), (void*)((ss)->states), (nw)*sizeof(unsigned)) == 0))
|
||||
int flags;
|
||||
#define STARTER 01 /* the initial state set */
|
||||
#define POSTSTATE 02 /* includes the goal state */
|
||||
@@ -268,7 +268,7 @@ exec(
|
||||
if (st == REG_OKAY && v->pmatch != pmatch && nmatch > 0) {
|
||||
zapallsubs(pmatch, nmatch);
|
||||
n = (nmatch < v->nmatch) ? nmatch : v->nmatch;
|
||||
memcpy(VS(pmatch), VS(v->pmatch), n*sizeof(regmatch_t));
|
||||
memcpy((void*)(pmatch), (void*)(v->pmatch), n*sizeof(regmatch_t));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+4
-30
@@ -49,41 +49,15 @@
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* voids */
|
||||
#ifndef VOID
|
||||
#define VOID void /* for function return values */
|
||||
#endif
|
||||
#ifndef DISCARD
|
||||
#define DISCARD void /* for throwing values away */
|
||||
#endif
|
||||
#ifndef PVOID
|
||||
#define PVOID void * /* generic pointer */
|
||||
#endif
|
||||
#ifndef VS
|
||||
#define VS(x) ((void*)(x)) /* cast something to generic ptr */
|
||||
#endif
|
||||
#ifndef NOPARMS
|
||||
#define NOPARMS void /* for empty parm lists */
|
||||
#endif
|
||||
|
||||
/* function-pointer declarator */
|
||||
#ifndef FUNCPTR
|
||||
#if __STDC__ >= 1
|
||||
#define FUNCPTR(name, args) (*name)args
|
||||
#else
|
||||
#define FUNCPTR(name, args) (*name)()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* memory allocation */
|
||||
#ifndef MALLOC
|
||||
#define MALLOC(n) malloc(n)
|
||||
#endif
|
||||
#ifndef REALLOC
|
||||
#define REALLOC(p, n) realloc(VS(p), n)
|
||||
#define REALLOC(p, n) realloc(p, n)
|
||||
#endif
|
||||
#ifndef FREE
|
||||
#define FREE(p) free(VS(p))
|
||||
#define FREE(p) free(p)
|
||||
#endif
|
||||
|
||||
/* want size of a char in bits, and max value in bounded quantifiers */
|
||||
@@ -408,7 +382,7 @@ struct subre {
|
||||
*/
|
||||
|
||||
struct fns {
|
||||
void FUNCPTR(free, (regex_t *));
|
||||
void (*free) (regex_t *);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -425,7 +399,7 @@ struct guts {
|
||||
struct cnfa search; /* for fast preliminary search */
|
||||
int ntree; /* number of subre's, plus one */
|
||||
struct colormap cmap;
|
||||
int FUNCPTR(compare, (const chr *, const chr *, size_t));
|
||||
int (*compare) (const chr *, const chr *, size_t);
|
||||
struct subre *lacons; /* lookahead-constraint vector */
|
||||
int nlacons; /* size of lacons */
|
||||
};
|
||||
|
||||
@@ -2324,6 +2324,19 @@ declare 630 {
|
||||
Tcl_Obj *compressionDictionaryObj)
|
||||
}
|
||||
|
||||
# TIP #421
|
||||
declare 632 {
|
||||
void Tcl_ArrayObjFirst(Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayObj,
|
||||
Tcl_ArraySearch *searchPtr)
|
||||
}
|
||||
declare 633 {
|
||||
int Tcl_ArrayObjNext(Tcl_Interp *interp,
|
||||
Tcl_ArraySearch *searchPtr,
|
||||
Tcl_Obj **keyPtrPtr,
|
||||
Tcl_Obj **valuePtrPtr)
|
||||
}
|
||||
|
||||
# ----- BASELINE -- FOR -- 8.6.0 ----- #
|
||||
|
||||
##############################################################################
|
||||
|
||||
+58
-18
@@ -144,6 +144,7 @@ extern "C" {
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
# define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))
|
||||
# define TCL_NORETURN __attribute__ ((noreturn))
|
||||
# define TCL_NOINLINE __attribute__ ((noinline))
|
||||
# if defined(BUILD_tcl) || defined(BUILD_tk)
|
||||
# define TCL_NORETURN1 __attribute__ ((noreturn))
|
||||
# else
|
||||
@@ -153,8 +154,10 @@ extern "C" {
|
||||
# define TCL_FORMAT_PRINTF(a,b)
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1310)
|
||||
# define TCL_NORETURN _declspec(noreturn)
|
||||
# define TCL_NOINLINE __declspec(noinline)
|
||||
# else
|
||||
# define TCL_NORETURN /* nothing */
|
||||
# define TCL_NOINLINE /* nothing */
|
||||
# endif
|
||||
# define TCL_NORETURN1 /* nothing */
|
||||
#endif
|
||||
@@ -828,19 +831,20 @@ typedef struct Tcl_Obj {
|
||||
union { /* The internal representation: */
|
||||
long longValue; /* - an long integer value. */
|
||||
double doubleValue; /* - a double-precision floating value. */
|
||||
void *otherValuePtr; /* - another, type-specific value,
|
||||
not used internally any more. */
|
||||
void *otherValuePtr; /* - another, type-specific value, not used
|
||||
* internally any more. */
|
||||
Tcl_WideInt wideValue; /* - a long long value. */
|
||||
struct { /* - internal rep as two pointers.
|
||||
* the main use of which is a bignum's
|
||||
* Many uses in Tcl, including a bignum's
|
||||
* tightly packed fields, where the alloc,
|
||||
* used and signum flags are packed into
|
||||
* ptr2 with everything else hung off ptr1. */
|
||||
* ptr2 with everything else hung off
|
||||
* ptr1. */
|
||||
void *ptr1;
|
||||
void *ptr2;
|
||||
} twoPtrValue;
|
||||
struct { /* - internal rep as a pointer and a long,
|
||||
not used internally any more. */
|
||||
* not used internally any more. */
|
||||
void *ptr;
|
||||
unsigned long value;
|
||||
} ptrAndLongRep;
|
||||
@@ -1154,11 +1158,15 @@ typedef struct Tcl_DString {
|
||||
* Forward declarations of Tcl_HashTable and related types.
|
||||
*/
|
||||
|
||||
#ifndef TCL_HASH_TYPE
|
||||
# define TCL_HASH_TYPE unsigned
|
||||
#endif
|
||||
|
||||
typedef struct Tcl_HashKeyType Tcl_HashKeyType;
|
||||
typedef struct Tcl_HashTable Tcl_HashTable;
|
||||
typedef struct Tcl_HashEntry Tcl_HashEntry;
|
||||
|
||||
typedef unsigned (Tcl_HashKeyProc) (Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
typedef TCL_HASH_TYPE (Tcl_HashKeyProc) (Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
typedef int (Tcl_CompareHashKeysProc) (void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
typedef Tcl_HashEntry * (Tcl_AllocHashEntryProc) (Tcl_HashTable *tablePtr,
|
||||
void *keyPtr);
|
||||
@@ -1312,9 +1320,9 @@ typedef struct Tcl_HashSearch {
|
||||
* TCL_CUSTOM_PTR_KEYS: The keys are pointers to arbitrary types, the
|
||||
* pointer is stored in the entry.
|
||||
*
|
||||
* While maintaining binary compatability the above have to be distinct values
|
||||
* While maintaining binary compatibility the above have to be distinct values
|
||||
* as they are used to differentiate between old versions of the hash table
|
||||
* which don't have a typePtr and new ones which do. Once binary compatability
|
||||
* which don't have a typePtr and new ones which do. Once binary compatibility
|
||||
* is discarded in favour of making more wide spread changes TCL_STRING_KEYS
|
||||
* can be the same as TCL_CUSTOM_TYPE_KEYS, and TCL_ONE_WORD_KEYS can be the
|
||||
* same as TCL_CUSTOM_PTR_KEYS because they simply determine how the key is
|
||||
@@ -1326,6 +1334,37 @@ typedef struct Tcl_HashSearch {
|
||||
#define TCL_CUSTOM_TYPE_KEYS (-2)
|
||||
#define TCL_CUSTOM_PTR_KEYS (-1)
|
||||
|
||||
/*
|
||||
* The following structure describes an enumerative search in progress on an
|
||||
* array variable; this are invoked with options to the "array" command.
|
||||
*/
|
||||
|
||||
# define TCL_ARRAYSEARCH_FOR_VALUE 0x0001
|
||||
typedef struct ArraySearch {
|
||||
Tcl_Obj *name; /* Name of this search */
|
||||
int id; /* Integer id used to distinguish among
|
||||
* multiple concurrent searches for the same
|
||||
* array. */
|
||||
struct Var *varPtr; /* Pointer to array variable that's being
|
||||
* searched. */
|
||||
Tcl_Obj *arrayNameObj; /* Name of the array variable in the current
|
||||
* resolution context. Usually NULL except for
|
||||
* in "array for". */
|
||||
int flags; /* Used by 'array for' to check if the
|
||||
* value is wanted. */
|
||||
Tcl_HashSearch search; /* Info kept by the hash module about progress
|
||||
* through the array. */
|
||||
Tcl_HashEntry *nextEntry; /* Non-null means this is the next element to
|
||||
* be enumerated (it's leftover from the
|
||||
* Tcl_FirstHashEntry call or from an "array
|
||||
* anymore" command). NULL means must call
|
||||
* Tcl_NextHashEntry to get value to
|
||||
* return. */
|
||||
struct ArraySearch *nextPtr;/* Next in list of all active searches for
|
||||
* this variable, or NULL if this is the last
|
||||
* one. */
|
||||
} Tcl_ArraySearch;
|
||||
|
||||
/*
|
||||
* Structure definition for information used to keep track of searches through
|
||||
* dictionaries. These fields should not be accessed by code outside
|
||||
@@ -2374,9 +2413,6 @@ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp,
|
||||
*----------------------------------------------------------------------------
|
||||
* The following constant is used to test for older versions of Tcl in the
|
||||
* stubs tables.
|
||||
*
|
||||
* Jan Nijtman's plus patch uses 0xFCA1BACF, so we need to pick a different
|
||||
* value since the stubs tables don't match.
|
||||
*/
|
||||
|
||||
#define TCL_STUB_MAGIC ((int) 0xFCA3BACF)
|
||||
@@ -2389,17 +2425,19 @@ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp,
|
||||
*/
|
||||
|
||||
const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version,
|
||||
int exact);
|
||||
int exact, int magic);
|
||||
const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
|
||||
const char *version, int epoch, int revision);
|
||||
|
||||
/*
|
||||
* When not using stubs, make it a macro.
|
||||
*/
|
||||
|
||||
#ifndef USE_TCL_STUBS
|
||||
#ifdef USE_TCL_STUBS
|
||||
#define Tcl_InitStubs(interp, version, exact) \
|
||||
Tcl_PkgInitStubsCheck(interp, version, exact)
|
||||
(Tcl_InitStubs)(interp, version, \
|
||||
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16), \
|
||||
TCL_STUB_MAGIC)
|
||||
#else
|
||||
#define Tcl_InitStubs(interp, version, exact) \
|
||||
Tcl_PkgInitStubsCheck(interp, version, \
|
||||
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2613,7 +2651,9 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
# define Tcl_Ckrealloc Tcl_Realloc
|
||||
# define Tcl_Return Tcl_SetResult
|
||||
# define Tcl_TildeSubst Tcl_TranslateFileName
|
||||
#if !defined(__APPLE__) /* On OSX, there is a conflict with "mach/mach.h" */
|
||||
# define panic Tcl_Panic
|
||||
#endif
|
||||
# define panicVA Tcl_PanicVA
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
|
||||
+15
-19
@@ -866,7 +866,7 @@ CompileAssembleObj(
|
||||
* Not valid, so free it and regenerate.
|
||||
*/
|
||||
|
||||
FreeAssembleCodeInternalRep(objPtr);
|
||||
TclFreeIntRep(objPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -891,15 +891,13 @@ CompileAssembleObj(
|
||||
*/
|
||||
|
||||
TclEmitOpcode(INST_DONE, &compEnv);
|
||||
TclInitByteCodeObj(objPtr, &compEnv);
|
||||
objPtr->typePtr = &assembleCodeType;
|
||||
codePtr = TclInitByteCodeObj(objPtr, &assembleCodeType, &compEnv);
|
||||
TclFreeCompileEnv(&compEnv);
|
||||
|
||||
/*
|
||||
* Record the local variable context to which the bytecode pertains
|
||||
*/
|
||||
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (iPtr->varFramePtr->localCachePtr) {
|
||||
codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
|
||||
codePtr->localCachePtr->refCount++;
|
||||
@@ -1301,8 +1299,8 @@ AssembleOneLine(
|
||||
if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len);
|
||||
litIndex = TclRegisterNewLiteral(envPtr, operand1, operand1Len);
|
||||
operand1 = TclGetStringFromObj(operand1Obj, &operand1Len);
|
||||
litIndex = TclRegisterLiteral(envPtr, operand1, operand1Len, 0);
|
||||
BBEmitInst1or4(assemEnvPtr, tblIdx, litIndex, 0);
|
||||
break;
|
||||
|
||||
@@ -1450,8 +1448,8 @@ AssembleOneLine(
|
||||
&operand1Obj) != TCL_OK) {
|
||||
goto cleanup;
|
||||
} else {
|
||||
operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len);
|
||||
litIndex = TclRegisterNewLiteral(envPtr, operand1, operand1Len);
|
||||
operand1 = TclGetStringFromObj(operand1Obj, &operand1Len);
|
||||
litIndex = TclRegisterLiteral(envPtr, operand1, operand1Len, 0);
|
||||
|
||||
/*
|
||||
* Assumes that PUSH is the first slot!
|
||||
@@ -2290,7 +2288,7 @@ FindLocalVar(
|
||||
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &varNameObj) != TCL_OK) {
|
||||
return -1;
|
||||
}
|
||||
varNameStr = Tcl_GetStringFromObj(varNameObj, &varNameLen);
|
||||
varNameStr = TclGetStringFromObj(varNameObj, &varNameLen);
|
||||
if (CheckNamespaceQualifiers(interp, varNameStr, varNameLen)) {
|
||||
Tcl_DecrRefCount(varNameObj);
|
||||
return -1;
|
||||
@@ -3543,7 +3541,7 @@ StackCheckExit(
|
||||
* Emit a 'push' of the empty literal.
|
||||
*/
|
||||
|
||||
litIndex = TclRegisterNewLiteral(envPtr, "", 0);
|
||||
litIndex = TclRegisterLiteral(envPtr, "", 0, 0);
|
||||
|
||||
/*
|
||||
* Assumes that 'push' is at slot 0 in TalInstructionTable.
|
||||
@@ -3984,10 +3982,12 @@ UnstackExpiredCatches(
|
||||
|
||||
while (catchDepth > bbPtr->catchDepth) {
|
||||
--catchDepth;
|
||||
range = envPtr->exceptArrayPtr + catchIndices[catchDepth];
|
||||
range->numCodeBytes = bbPtr->startOffset - range->codeOffset;
|
||||
catches[catchDepth] = NULL;
|
||||
catchIndices[catchDepth] = -1;
|
||||
if (catches[catchDepth] != NULL) {
|
||||
range = envPtr->exceptArrayPtr + catchIndices[catchDepth];
|
||||
range->numCodeBytes = bbPtr->startOffset - range->codeOffset;
|
||||
catches[catchDepth] = NULL;
|
||||
catchIndices[catchDepth] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4313,11 +4313,7 @@ FreeAssembleCodeInternalRep(
|
||||
{
|
||||
ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
codePtr->refCount--;
|
||||
if (codePtr->refCount <= 0) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
}
|
||||
objPtr->typePtr = NULL;
|
||||
TclReleaseByteCode(codePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+54
-43
@@ -128,7 +128,7 @@ static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected,
|
||||
int actual, Tcl_Obj *const *objv);
|
||||
static Tcl_NRPostProc NRCoroutineCallerCallback;
|
||||
static Tcl_NRPostProc NRCoroutineExitCallback;
|
||||
static int NRCommand(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc NRCommand;
|
||||
|
||||
static Tcl_ObjCmdProc OldMathFuncProc;
|
||||
static void OldMathFuncDeleteProc(ClientData clientData);
|
||||
@@ -146,7 +146,6 @@ static int TEOV_RunEnterTraces(Tcl_Interp *interp,
|
||||
Command **cmdPtrPtr, Tcl_Obj *commandPtr, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static Tcl_NRPostProc RewindCoroutineCallback;
|
||||
static Tcl_NRPostProc TailcallCleanup;
|
||||
static Tcl_NRPostProc TEOEx_ByteCodeCallback;
|
||||
static Tcl_NRPostProc TEOEx_ListCallback;
|
||||
static Tcl_NRPostProc TEOV_Error;
|
||||
@@ -589,7 +588,7 @@ Tcl_CreateInterp(void)
|
||||
|
||||
iPtr->cmdCount = 0;
|
||||
TclInitLiteralTable(&iPtr->literalTable);
|
||||
iPtr->compileEpoch = 0;
|
||||
iPtr->compileEpoch = 1;
|
||||
iPtr->compiledProcPtr = NULL;
|
||||
iPtr->resolverPtr = NULL;
|
||||
iPtr->evalFlags = 0;
|
||||
@@ -724,9 +723,7 @@ Tcl_CreateInterp(void)
|
||||
* Initialize the ensemble error message rewriting support.
|
||||
*/
|
||||
|
||||
iPtr->ensembleRewrite.sourceObjs = NULL;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = 0;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 0;
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
|
||||
/*
|
||||
* TIP#143: Initialise the resource limit support.
|
||||
@@ -943,8 +940,8 @@ Tcl_CreateInterp(void)
|
||||
* Set up other variables such as tcl_version and tcl_library
|
||||
*/
|
||||
|
||||
Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "tcl_patchLevel", NULL, TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "tcl_version", NULL, TCL_VERSION, TCL_GLOBAL_ONLY);
|
||||
Tcl_TraceVar2(interp, "tcl_precision", NULL,
|
||||
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||||
TclPrecTraceProc, NULL);
|
||||
@@ -969,11 +966,11 @@ Tcl_CreateInterp(void)
|
||||
Tcl_PkgProvideEx(interp, "Tcl", TCL_PATCH_LEVEL, &tclStubs);
|
||||
|
||||
if (TclTommath_Init(interp) != TCL_OK) {
|
||||
Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp)));
|
||||
Tcl_Panic("%s", TclGetString(Tcl_GetObjResult(interp)));
|
||||
}
|
||||
|
||||
if (TclOOInit(interp) != TCL_OK) {
|
||||
Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp)));
|
||||
Tcl_Panic("%s", TclGetString(Tcl_GetObjResult(interp)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -983,7 +980,7 @@ Tcl_CreateInterp(void)
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
if (TclZlibInit(interp) != TCL_OK) {
|
||||
Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp)));
|
||||
Tcl_Panic("%s", TclGetString(Tcl_GetObjResult(interp)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1638,7 +1635,7 @@ DeleteInterpProc(
|
||||
}
|
||||
|
||||
Tcl_DeleteHashTable(iPtr->lineLAPtr);
|
||||
ckfree((char *) iPtr->lineLAPtr);
|
||||
ckfree(iPtr->lineLAPtr);
|
||||
iPtr->lineLAPtr = NULL;
|
||||
|
||||
if (iPtr->lineLABCPtr->numEntries && !TclInExit()) {
|
||||
@@ -2406,7 +2403,7 @@ TclInvokeStringCommand(
|
||||
TclStackAlloc(interp, (unsigned)(objc + 1) * sizeof(char *));
|
||||
|
||||
for (i = 0; i < objc; i++) {
|
||||
argv[i] = Tcl_GetString(objv[i]);
|
||||
argv[i] = TclGetString(objv[i]);
|
||||
}
|
||||
argv[objc] = 0;
|
||||
|
||||
@@ -2660,7 +2657,7 @@ TclRenameCommand(
|
||||
}
|
||||
Tcl_DStringAppend(&newFullName, newTail, -1);
|
||||
cmdPtr->refCount++;
|
||||
CallCommandTraces(iPtr, cmdPtr, Tcl_GetString(oldFullName),
|
||||
CallCommandTraces(iPtr, cmdPtr, TclGetString(oldFullName),
|
||||
Tcl_DStringValue(&newFullName), TCL_TRACE_RENAME);
|
||||
Tcl_DStringFree(&newFullName);
|
||||
|
||||
@@ -3026,13 +3023,6 @@ Tcl_DeleteCommandFromToken(
|
||||
ImportRef *refPtr, *nextRefPtr;
|
||||
Tcl_Command importCmd;
|
||||
|
||||
/*
|
||||
* Bump the command epoch counter. This will invalidate all cached
|
||||
* references that point to this command.
|
||||
*/
|
||||
|
||||
cmdPtr->cmdEpoch++;
|
||||
|
||||
/*
|
||||
* The code here is tricky. We can't delete the hash table entry before
|
||||
* invoking the deletion callback because there are cases where the
|
||||
@@ -3055,6 +3045,14 @@ Tcl_DeleteCommandFromToken(
|
||||
Tcl_DeleteHashEntry(cmdPtr->hPtr);
|
||||
cmdPtr->hPtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bump the command epoch counter. This will invalidate all cached
|
||||
* references that point to this command.
|
||||
*/
|
||||
|
||||
cmdPtr->cmdEpoch++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3157,6 +3155,13 @@ Tcl_DeleteCommandFromToken(
|
||||
if (cmdPtr->hPtr != NULL) {
|
||||
Tcl_DeleteHashEntry(cmdPtr->hPtr);
|
||||
cmdPtr->hPtr = NULL;
|
||||
|
||||
/*
|
||||
* Bump the command epoch counter. This will invalidate all cached
|
||||
* references that point to this command.
|
||||
*/
|
||||
|
||||
cmdPtr->cmdEpoch++;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3403,8 +3408,7 @@ TclCleanupCommand(
|
||||
register Command *cmdPtr) /* Points to the Command structure to
|
||||
* be freed. */
|
||||
{
|
||||
cmdPtr->refCount--;
|
||||
if (cmdPtr->refCount <= 0) {
|
||||
if (cmdPtr->refCount-- <= 1) {
|
||||
ckfree(cmdPtr);
|
||||
}
|
||||
}
|
||||
@@ -3526,7 +3530,7 @@ OldMathFuncProc(
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"argument to math function didn't have numeric value",
|
||||
-1));
|
||||
TclCheckBadOctal(interp, Tcl_GetString(valuePtr));
|
||||
TclCheckBadOctal(interp, TclGetString(valuePtr));
|
||||
ckfree(args);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -3946,7 +3950,7 @@ Tcl_Canceled(
|
||||
*/
|
||||
|
||||
if (iPtr->asyncCancelMsg != NULL) {
|
||||
message = Tcl_GetStringFromObj(iPtr->asyncCancelMsg, &length);
|
||||
message = TclGetStringFromObj(iPtr->asyncCancelMsg, &length);
|
||||
} else {
|
||||
length = 0;
|
||||
}
|
||||
@@ -4045,7 +4049,7 @@ Tcl_CancelEval(
|
||||
*/
|
||||
|
||||
if (resultObjPtr != NULL) {
|
||||
result = Tcl_GetStringFromObj(resultObjPtr, &cancelInfo->length);
|
||||
result = TclGetStringFromObj(resultObjPtr, &cancelInfo->length);
|
||||
cancelInfo->result = ckrealloc(cancelInfo->result,cancelInfo->length);
|
||||
memcpy(cancelInfo->result, result, (size_t) cancelInfo->length);
|
||||
TclDecrRefCount(resultObjPtr); /* Discard their result object. */
|
||||
@@ -4221,7 +4225,7 @@ EvalObjvCore(
|
||||
* TCL_EVAL_INVOKE was not set: clear rewrite rules
|
||||
*/
|
||||
|
||||
iPtr->ensembleRewrite.sourceObjs = NULL;
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
|
||||
if (flags & TCL_EVAL_GLOBAL) {
|
||||
TEOV_SwitchVarFrame(interp);
|
||||
@@ -4557,7 +4561,7 @@ TEOV_Error(
|
||||
*/
|
||||
|
||||
listPtr = Tcl_NewListObj(objc, objv);
|
||||
cmdString = Tcl_GetStringFromObj(listPtr, &cmdLen);
|
||||
cmdString = TclGetStringFromObj(listPtr, &cmdLen);
|
||||
Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
}
|
||||
@@ -4703,7 +4707,7 @@ TEOV_RunEnterTraces(
|
||||
Command *cmdPtr = *cmdPtrPtr;
|
||||
int newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
|
||||
int length, traceCode = TCL_OK;
|
||||
const char *command = Tcl_GetStringFromObj(commandPtr, &length);
|
||||
const char *command = TclGetStringFromObj(commandPtr, &length);
|
||||
|
||||
/*
|
||||
* Call trace functions.
|
||||
@@ -4755,7 +4759,7 @@ TEOV_RunLeaveTraces(
|
||||
Command *cmdPtr = data[2];
|
||||
Tcl_Obj **objv = data[3];
|
||||
int length;
|
||||
const char *command = Tcl_GetStringFromObj(commandPtr, &length);
|
||||
const char *command = TclGetStringFromObj(commandPtr, &length);
|
||||
|
||||
if (!(cmdPtr->flags & CMD_IS_DELETED)) {
|
||||
if (cmdPtr->flags & CMD_HAS_EXEC_TRACES){
|
||||
@@ -5581,8 +5585,7 @@ TclArgumentRelease(
|
||||
}
|
||||
cfwPtr = Tcl_GetHashValue(hPtr);
|
||||
|
||||
cfwPtr->refCount--;
|
||||
if (cfwPtr->refCount > 0) {
|
||||
if (cfwPtr->refCount-- > 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -6120,7 +6123,7 @@ TclNREvalObjEx(
|
||||
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
|
||||
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
|
||||
script = TclGetStringFromObj(objPtr, &numSrcBytes);
|
||||
result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
|
||||
|
||||
TclDecrRefCount(objPtr);
|
||||
@@ -6151,7 +6154,7 @@ TEOEx_ByteCodeCallback(
|
||||
|
||||
ProcessUnexpectedResult(interp, result);
|
||||
result = TCL_ERROR;
|
||||
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
|
||||
script = TclGetStringFromObj(objPtr, &numSrcBytes);
|
||||
Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
|
||||
}
|
||||
|
||||
@@ -6850,7 +6853,7 @@ Tcl_VarEvalVA(
|
||||
Tcl_DStringAppend(&buf, string, -1);
|
||||
}
|
||||
|
||||
result = Tcl_Eval(interp, Tcl_DStringValue(&buf));
|
||||
result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
|
||||
Tcl_DStringFree(&buf);
|
||||
return result;
|
||||
}
|
||||
@@ -6920,7 +6923,7 @@ Tcl_GlobalEval(
|
||||
|
||||
savedVarFramePtr = iPtr->varFramePtr;
|
||||
iPtr->varFramePtr = iPtr->rootFramePtr;
|
||||
result = Tcl_Eval(interp, command);
|
||||
result = Tcl_EvalEx(interp, command, -1, 0);
|
||||
iPtr->varFramePtr = savedVarFramePtr;
|
||||
return result;
|
||||
}
|
||||
@@ -7887,7 +7890,7 @@ MathFuncWrongNumArgs(
|
||||
int found, /* Actual parameter count. */
|
||||
Tcl_Obj *const *objv) /* Actual parameter vector. */
|
||||
{
|
||||
const char *name = Tcl_GetString(objv[0]);
|
||||
const char *name = TclGetString(objv[0]);
|
||||
const char *tail = name + strlen(name);
|
||||
|
||||
while (tail > name+1) {
|
||||
@@ -8374,7 +8377,7 @@ TclNRTailcallEval(
|
||||
* a now-gone namespace: cleanup and return.
|
||||
*/
|
||||
|
||||
TailcallCleanup(data, interp, result);
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -8383,18 +8386,26 @@ TclNRTailcallEval(
|
||||
*/
|
||||
|
||||
TclMarkTailcall(interp);
|
||||
TclNRAddCallback(interp, TailcallCleanup, listPtr, NULL, NULL,NULL);
|
||||
TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
|
||||
iPtr->lookupNsPtr = (Namespace *) nsPtr;
|
||||
return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
TailcallCleanup(
|
||||
int
|
||||
TclNRReleaseValues(
|
||||
ClientData data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
Tcl_DecrRefCount((Tcl_Obj *) data[0]);
|
||||
int i = 0;
|
||||
while (i < 4) {
|
||||
if (data[i]) {
|
||||
Tcl_DecrRefCount((Tcl_Obj *) data[i]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -8812,7 +8823,7 @@ TclNRInterpCoroutine(
|
||||
if (!COR_IS_SUSPENDED(corPtr)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"coroutine \"%s\" is already running",
|
||||
Tcl_GetString(objv[0])));
|
||||
TclGetString(objv[0])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BUSY", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
+132
-44
@@ -155,35 +155,108 @@ static const EnsembleImplMap decodeMap[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
* The following object type represents an array of bytes. An array of bytes
|
||||
* is not equivalent to an internationalized string. Conceptually, a string is
|
||||
* an array of 16-bit quantities organized as a sequence of properly formed
|
||||
* UTF-8 characters, while a ByteArray is an array of 8-bit quantities.
|
||||
* Accessor functions are provided to convert a ByteArray to a String or a
|
||||
* String to a ByteArray. Two or more consecutive bytes in an array of bytes
|
||||
* may look like a single UTF-8 character if the array is casually treated as
|
||||
* a string. But obtaining the String from a ByteArray is guaranteed to
|
||||
* produced properly formed UTF-8 sequences so that there is a one-to-one map
|
||||
* between bytes and characters.
|
||||
* The following object types represent an array of bytes. The intent is
|
||||
* to allow arbitrary binary data to pass through Tcl as a Tcl value
|
||||
* without loss or damage. Such values are useful for things like
|
||||
* encoded strings or Tk images to name just two.
|
||||
*
|
||||
* Converting a ByteArray to a String proceeds by casting each byte in the
|
||||
* array to a 16-bit quantity, treating that number as a Unicode character,
|
||||
* and storing the UTF-8 version of that Unicode character in the String. For
|
||||
* ByteArrays consisting entirely of values 1..127, the corresponding String
|
||||
* representation is the same as the ByteArray representation.
|
||||
* It's strange to have two Tcl_ObjTypes in place for this task when
|
||||
* one would do, so a bit of detail and history how we got to this point
|
||||
* and where we might go from here.
|
||||
*
|
||||
* Converting a String to a ByteArray proceeds by getting the Unicode
|
||||
* representation of each character in the String, casting it to a byte by
|
||||
* truncating the upper 8 bits, and then storing the byte in the ByteArray.
|
||||
* Converting from ByteArray to String and back to ByteArray is not lossy, but
|
||||
* converting an arbitrary String to a ByteArray may be.
|
||||
* A bytearray is an ordered sequence of bytes. Each byte is an integer
|
||||
* value in the range [0-255]. To be a Tcl value type, we need a way to
|
||||
* encode each value in the value set as a Tcl string. The simplest
|
||||
* encoding is to represent each byte value as the same codepoint value.
|
||||
* A bytearray of N bytes is encoded into a Tcl string of N characters
|
||||
* where the codepoint of each character is the value of corresponding byte.
|
||||
* This approach creates a one-to-one map between all bytearray values
|
||||
* and a subset of Tcl string values.
|
||||
*
|
||||
* When converting a Tcl string value to the bytearray internal rep, the
|
||||
* question arises what to do with strings outside that subset? That is,
|
||||
* those Tcl strings containing at least one codepoint greater than 255?
|
||||
* The obviously correct answer is to raise an error! That string value
|
||||
* does not represent any valid bytearray value. Full Stop. The
|
||||
* setFromAnyProc signature has a completion code return value for just
|
||||
* this reason, to reject invalid inputs.
|
||||
*
|
||||
* Unfortunately this was not the path taken by the authors of the
|
||||
* original tclByteArrayType. They chose to accept all Tcl string values
|
||||
* as acceptable string encodings of the bytearray values that result
|
||||
* from masking away the high bits of any codepoint value at all. This
|
||||
* meant that every bytearray value had multiple accepted string
|
||||
* representations.
|
||||
*
|
||||
* The implications of this choice are truly ugly. When a Tcl value has
|
||||
* a string representation, we are required to accept that as the true
|
||||
* value. Bytearray values that possess a string representation cannot
|
||||
* be processed as bytearrays because we cannot know which true value
|
||||
* that bytearray represents. The consequence is that we drag around
|
||||
* an internal rep that we cannot make any use of. This painful price
|
||||
* is extracted at any point after a string rep happens to be generated
|
||||
* for the value. This happens even when the troublesome codepoints
|
||||
* outside the byte range never show up. This happens rather routinely
|
||||
* in normal Tcl operations unless we burden the script writer with the
|
||||
* cognitive burden of avoiding it. The price is also paid by callers
|
||||
* of the C interface. The routine
|
||||
*
|
||||
* unsigned char *Tcl_GetByteArrayFromObj(objPtr, lenPtr)
|
||||
*
|
||||
* has a guarantee to always return a non-NULL value, but that value
|
||||
* points to a byte sequence that cannot be used by the caller to
|
||||
* process the Tcl value absent some sideband testing that objPtr
|
||||
* is "pure". Tcl offers no public interface to perform this test,
|
||||
* so callers either break encapsulation or are unavoidably buggy. Tcl
|
||||
* has defined a public interface that cannot be used correctly. The
|
||||
* Tcl source code itself suffers the same problem, and has been buggy,
|
||||
* but progressively less so as more and more portions of the code have
|
||||
* been retrofitted with the required "purity testing". The set of values
|
||||
* able to pass the purity test can be increased via the introduction of
|
||||
* a "canonical" flag marker, but the only way the broken interface itself
|
||||
* can be discarded is to start over and define the Tcl_ObjType properly.
|
||||
* Bytearrays should simply be usable as bytearrays without a kabuki
|
||||
* dance of testing.
|
||||
*
|
||||
* The Tcl_ObjType "properByteArrayType" is (nearly) a correct
|
||||
* implementation of bytearrays. Any Tcl value with the type
|
||||
* properByteArrayType can have its bytearray value fetched and
|
||||
* used with confidence that acting on that value is equivalent to
|
||||
* acting on the true Tcl string value. This still implies a side
|
||||
* testing burden -- past mistakes will not let us avoid that
|
||||
* immediately, but it is at least a conventional test of type, and
|
||||
* can be implemented entirely by examining the objPtr fields, with
|
||||
* no need to query the intrep, as a canonical flag would require.
|
||||
*
|
||||
* Until Tcl_GetByteArrayFromObj() and Tcl_SetByteArrayLength() can
|
||||
* be revised to admit the possibility of returning NULL when the true
|
||||
* value is not a valid bytearray, we need a mechanism to retain
|
||||
* compatibility with the deployed callers of the broken interface.
|
||||
* That's what the retained "tclByteArrayType" provides. In those
|
||||
* unusual circumstances where we convert an invalid bytearray value
|
||||
* to a bytearray type, it is to this legacy type. Essentially any
|
||||
* time this legacy type gets used, it's a signal of a bug being ignored.
|
||||
* A TIP should be drafted to remove this connection to the broken past
|
||||
* so that Tcl 9 will no longer have any trace of it. Prescribing a
|
||||
* migration path will be the key element of that work. The internal
|
||||
* changes now in place are the limit of what can be done short of
|
||||
* interface repair. They provide a great expansion of the histories
|
||||
* over which bytearray values can be useful in the meanwhile.
|
||||
*/
|
||||
|
||||
static const Tcl_ObjType properByteArrayType = {
|
||||
"bytearray",
|
||||
FreeByteArrayInternalRep,
|
||||
DupByteArrayInternalRep,
|
||||
UpdateStringOfByteArray,
|
||||
NULL
|
||||
};
|
||||
|
||||
const Tcl_ObjType tclByteArrayType = {
|
||||
"bytearray",
|
||||
FreeByteArrayInternalRep,
|
||||
DupByteArrayInternalRep,
|
||||
UpdateStringOfByteArray,
|
||||
NULL,
|
||||
SetByteArrayFromAny
|
||||
};
|
||||
|
||||
@@ -211,6 +284,12 @@ typedef struct ByteArray {
|
||||
#define SET_BYTEARRAY(objPtr, baPtr) \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (baPtr)
|
||||
|
||||
int
|
||||
TclIsPureByteArray(
|
||||
Tcl_Obj * objPtr)
|
||||
{
|
||||
return (objPtr->typePtr == &properByteArrayType);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -341,7 +420,7 @@ Tcl_SetByteArrayObj(
|
||||
if ((bytes != NULL) && (length > 0)) {
|
||||
memcpy(byteArrayPtr->bytes, bytes, (size_t) length);
|
||||
}
|
||||
objPtr->typePtr = &tclByteArrayType;
|
||||
objPtr->typePtr = &properByteArrayType;
|
||||
SET_BYTEARRAY(objPtr, byteArrayPtr);
|
||||
}
|
||||
|
||||
@@ -371,7 +450,8 @@ Tcl_GetByteArrayFromObj(
|
||||
{
|
||||
ByteArray *baPtr;
|
||||
|
||||
if (objPtr->typePtr != &tclByteArrayType) {
|
||||
if ((objPtr->typePtr != &properByteArrayType)
|
||||
&& (objPtr->typePtr != &tclByteArrayType)) {
|
||||
SetByteArrayFromAny(NULL, objPtr);
|
||||
}
|
||||
baPtr = GET_BYTEARRAY(objPtr);
|
||||
@@ -414,7 +494,8 @@ Tcl_SetByteArrayLength(
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
|
||||
}
|
||||
if (objPtr->typePtr != &tclByteArrayType) {
|
||||
if ((objPtr->typePtr != &properByteArrayType)
|
||||
&& (objPtr->typePtr != &tclByteArrayType)) {
|
||||
SetByteArrayFromAny(NULL, objPtr);
|
||||
}
|
||||
|
||||
@@ -450,29 +531,35 @@ SetByteArrayFromAny(
|
||||
Tcl_Interp *interp, /* Not used. */
|
||||
Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */
|
||||
{
|
||||
int length;
|
||||
int length, improper = 0;
|
||||
const char *src, *srcEnd;
|
||||
unsigned char *dst;
|
||||
ByteArray *byteArrayPtr;
|
||||
Tcl_UniChar ch;
|
||||
|
||||
if (objPtr->typePtr != &tclByteArrayType) {
|
||||
src = TclGetStringFromObj(objPtr, &length);
|
||||
srcEnd = src + length;
|
||||
|
||||
byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length));
|
||||
for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
|
||||
src += Tcl_UtfToUniChar(src, &ch);
|
||||
*dst++ = UCHAR(ch);
|
||||
}
|
||||
|
||||
byteArrayPtr->used = dst - byteArrayPtr->bytes;
|
||||
byteArrayPtr->allocated = length;
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &tclByteArrayType;
|
||||
SET_BYTEARRAY(objPtr, byteArrayPtr);
|
||||
if (objPtr->typePtr == &properByteArrayType) {
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclByteArrayType) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
src = TclGetStringFromObj(objPtr, &length);
|
||||
srcEnd = src + length;
|
||||
|
||||
byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length));
|
||||
for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
|
||||
src += Tcl_UtfToUniChar(src, &ch);
|
||||
improper = improper || (ch > 255);
|
||||
*dst++ = UCHAR(ch);
|
||||
}
|
||||
|
||||
byteArrayPtr->used = dst - byteArrayPtr->bytes;
|
||||
byteArrayPtr->allocated = length;
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = improper ? &tclByteArrayType : &properByteArrayType;
|
||||
SET_BYTEARRAY(objPtr, byteArrayPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -535,7 +622,7 @@ DupByteArrayInternalRep(
|
||||
memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, (size_t) length);
|
||||
SET_BYTEARRAY(copyPtr, copyArrayPtr);
|
||||
|
||||
copyPtr->typePtr = &tclByteArrayType;
|
||||
copyPtr->typePtr = srcPtr->typePtr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -642,7 +729,8 @@ TclAppendBytesToByteArray(
|
||||
/* Append zero bytes is a no-op. */
|
||||
return;
|
||||
}
|
||||
if (objPtr->typePtr != &tclByteArrayType) {
|
||||
if ((objPtr->typePtr != &properByteArrayType)
|
||||
&& (objPtr->typePtr != &tclByteArrayType)) {
|
||||
SetByteArrayFromAny(NULL, objPtr);
|
||||
}
|
||||
byteArrayPtr = GET_BYTEARRAY(objPtr);
|
||||
@@ -2500,7 +2588,7 @@ BinaryEncode64(
|
||||
}
|
||||
break;
|
||||
case OPT_WRAPCHAR:
|
||||
wrapchar = Tcl_GetStringFromObj(objv[i+1], &wrapcharlen);
|
||||
wrapchar = TclGetStringFromObj(objv[i+1], &wrapcharlen);
|
||||
if (wrapcharlen == 0) {
|
||||
maxlen = 0;
|
||||
}
|
||||
|
||||
+27
-28
@@ -34,14 +34,14 @@
|
||||
*/
|
||||
|
||||
typedef struct MemTag {
|
||||
int refCount; /* Number of mem_headers referencing this
|
||||
size_t refCount; /* Number of mem_headers referencing this
|
||||
* tag. */
|
||||
char string[1]; /* Actual size of string will be as large as
|
||||
* needed for actual tag. This must be the
|
||||
* last field in the structure. */
|
||||
} MemTag;
|
||||
|
||||
#define TAG_SIZE(bytesInString) ((unsigned) ((TclOffset(MemTag, string) + 1) + bytesInString))
|
||||
#define TAG_SIZE(bytesInString) ((TclOffset(MemTag, string) + 1) + bytesInString)
|
||||
|
||||
static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers (set
|
||||
* by "memory tag" command). */
|
||||
@@ -52,14 +52,14 @@ static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers (set
|
||||
* to help detect chunk under-runs.
|
||||
*/
|
||||
|
||||
#define LOW_GUARD_SIZE (8 + (32 - (sizeof(long) + sizeof(int)))%8)
|
||||
#define LOW_GUARD_SIZE (8 + (32 - (sizeof(size_t) + sizeof(int)))%8)
|
||||
struct mem_header {
|
||||
struct mem_header *flink;
|
||||
struct mem_header *blink;
|
||||
MemTag *tagPtr; /* Tag from "memory tag" command; may be
|
||||
* NULL. */
|
||||
const char *file;
|
||||
long length;
|
||||
size_t length;
|
||||
int line;
|
||||
unsigned char low_guard[LOW_GUARD_SIZE];
|
||||
/* Aligns body on 8-byte boundary, plus
|
||||
@@ -251,10 +251,10 @@ ValidateMemory(
|
||||
}
|
||||
if (guard_failed) {
|
||||
TclDumpMemoryInfo((ClientData) stderr, 0);
|
||||
fprintf(stderr, "low guard failed at %lx, %s %d\n",
|
||||
(long unsigned) memHeaderP->body, file, line);
|
||||
fprintf(stderr, "low guard failed at %p, %s %d\n",
|
||||
memHeaderP->body, file, line);
|
||||
fflush(stderr); /* In case name pointer is bad. */
|
||||
fprintf(stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length,
|
||||
fprintf(stderr, "%" TCL_LL_MODIFIER "d bytes allocated at (%s %d)\n", (Tcl_WideInt) memHeaderP->length,
|
||||
memHeaderP->file, memHeaderP->line);
|
||||
Tcl_Panic("Memory validation failure");
|
||||
}
|
||||
@@ -273,11 +273,11 @@ ValidateMemory(
|
||||
|
||||
if (guard_failed) {
|
||||
TclDumpMemoryInfo((ClientData) stderr, 0);
|
||||
fprintf(stderr, "high guard failed at %lx, %s %d\n",
|
||||
(long unsigned) memHeaderP->body, file, line);
|
||||
fprintf(stderr, "high guard failed at %p, %s %d\n",
|
||||
memHeaderP->body, file, line);
|
||||
fflush(stderr); /* In case name pointer is bad. */
|
||||
fprintf(stderr, "%ld bytes allocated at (%s %d)\n",
|
||||
memHeaderP->length, memHeaderP->file,
|
||||
fprintf(stderr, "%" TCL_LL_MODIFIER "d bytes allocated at (%s %d)\n",
|
||||
(Tcl_WideInt)memHeaderP->length, memHeaderP->file,
|
||||
memHeaderP->line);
|
||||
Tcl_Panic("Memory validation failure");
|
||||
}
|
||||
@@ -359,10 +359,10 @@ Tcl_DumpActiveMemory(
|
||||
Tcl_MutexLock(ckallocMutexPtr);
|
||||
for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
|
||||
address = &memScanP->body[0];
|
||||
fprintf(fileP, "%8lx - %8lx %7ld @ %s %d %s",
|
||||
(long unsigned) address,
|
||||
(long unsigned) address + memScanP->length - 1,
|
||||
memScanP->length, memScanP->file, memScanP->line,
|
||||
fprintf(fileP, "%8" TCL_LL_MODIFIER "x - %8" TCL_LL_MODIFIER "x %7" TCL_LL_MODIFIER "d @ %s %d %s",
|
||||
(Tcl_WideInt)(size_t)address,
|
||||
(Tcl_WideInt)((size_t)address + memScanP->length - 1),
|
||||
(Tcl_WideInt)memScanP->length, memScanP->file, memScanP->line,
|
||||
(memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
|
||||
(void) fputc('\n', fileP);
|
||||
}
|
||||
@@ -458,8 +458,8 @@ Tcl_DbCkalloc(
|
||||
}
|
||||
|
||||
if (alloc_tracing) {
|
||||
fprintf(stderr,"ckalloc %lx %u %s %d\n",
|
||||
(long unsigned int) result->body, size, file, line);
|
||||
fprintf(stderr,"ckalloc %p %u %s %d\n",
|
||||
result->body, size, file, line);
|
||||
}
|
||||
|
||||
if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
|
||||
@@ -547,8 +547,8 @@ Tcl_AttemptDbCkalloc(
|
||||
}
|
||||
|
||||
if (alloc_tracing) {
|
||||
fprintf(stderr,"ckalloc %lx %u %s %d\n",
|
||||
(long unsigned int) result->body, size, file, line);
|
||||
fprintf(stderr,"ckalloc %p %u %s %d\n",
|
||||
result->body, size, file, line);
|
||||
}
|
||||
|
||||
if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
|
||||
@@ -612,8 +612,8 @@ Tcl_DbCkfree(
|
||||
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
|
||||
|
||||
if (alloc_tracing) {
|
||||
fprintf(stderr, "ckfree %lx %ld %s %d\n",
|
||||
(long unsigned int) memp->body, memp->length, file, line);
|
||||
fprintf(stderr, "ckfree %p %" TCL_LL_MODIFIER "d %s %d\n",
|
||||
memp->body, (Tcl_WideInt) memp->length, file, line);
|
||||
}
|
||||
|
||||
if (validate_memory) {
|
||||
@@ -623,7 +623,7 @@ Tcl_DbCkfree(
|
||||
Tcl_MutexLock(ckallocMutexPtr);
|
||||
ValidateMemory(memp, file, line, TRUE);
|
||||
if (init_malloced_bodies) {
|
||||
memset(ptr, GUARD_VALUE, (size_t) memp->length);
|
||||
memset(ptr, GUARD_VALUE, memp->length);
|
||||
}
|
||||
|
||||
total_frees++;
|
||||
@@ -631,8 +631,7 @@ Tcl_DbCkfree(
|
||||
current_bytes_malloced -= memp->length;
|
||||
|
||||
if (memp->tagPtr != NULL) {
|
||||
memp->tagPtr->refCount--;
|
||||
if ((memp->tagPtr->refCount == 0) && (curTagPtr != memp->tagPtr)) {
|
||||
if ((memp->tagPtr->refCount-- <= 1) && (curTagPtr != memp->tagPtr)) {
|
||||
TclpFree((char *) memp->tagPtr);
|
||||
}
|
||||
}
|
||||
@@ -675,7 +674,7 @@ Tcl_DbCkrealloc(
|
||||
int line)
|
||||
{
|
||||
char *newPtr;
|
||||
unsigned int copySize;
|
||||
size_t copySize;
|
||||
struct mem_header *memp;
|
||||
|
||||
if (ptr == NULL) {
|
||||
@@ -689,7 +688,7 @@ Tcl_DbCkrealloc(
|
||||
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
|
||||
|
||||
copySize = size;
|
||||
if (copySize > (unsigned int) memp->length) {
|
||||
if (copySize > memp->length) {
|
||||
copySize = memp->length;
|
||||
}
|
||||
newPtr = Tcl_DbCkalloc(size, file, line);
|
||||
@@ -706,7 +705,7 @@ Tcl_AttemptDbCkrealloc(
|
||||
int line)
|
||||
{
|
||||
char *newPtr;
|
||||
unsigned int copySize;
|
||||
size_t copySize;
|
||||
struct mem_header *memp;
|
||||
|
||||
if (ptr == NULL) {
|
||||
@@ -720,7 +719,7 @@ Tcl_AttemptDbCkrealloc(
|
||||
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
|
||||
|
||||
copySize = size;
|
||||
if (copySize > (unsigned int) memp->length) {
|
||||
if (copySize > memp->length) {
|
||||
copySize = memp->length;
|
||||
}
|
||||
newPtr = Tcl_AttemptDbCkalloc(size, file, line);
|
||||
|
||||
@@ -1499,7 +1499,19 @@ GetJulianDayFromEraYearMonthDay(
|
||||
* Try an initial conversion in the Gregorian calendar.
|
||||
*/
|
||||
|
||||
#if 0 /* BUG http://core.tcl.tk/tcl/tktview?name=da340d4f32 */
|
||||
ym1o4 = ym1 / 4;
|
||||
#else
|
||||
/*
|
||||
* Have to make sure quotient is truncated towards 0 when negative.
|
||||
* See above bug for details. The casts are necessary.
|
||||
*/
|
||||
if (ym1 >= 0)
|
||||
ym1o4 = ym1 / 4;
|
||||
else {
|
||||
ym1o4 = - (int) (((unsigned int) -ym1) / 4);
|
||||
}
|
||||
#endif
|
||||
if (ym1 % 4 < 0) {
|
||||
ym1o4--;
|
||||
}
|
||||
|
||||
+31
-12
@@ -12,6 +12,9 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#ifdef _WIN32
|
||||
# include "tclWinInt.h"
|
||||
#endif
|
||||
#include <locale.h>
|
||||
|
||||
/*
|
||||
@@ -1157,6 +1160,16 @@ FileAttrAccessTimeCmd(
|
||||
if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
/* We use a value of 0 to indicate the access time not available */
|
||||
if (buf.st_atime == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"could not get access time for file \"%s\"",
|
||||
TclGetString(objv[1])));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (objc == 3) {
|
||||
/*
|
||||
* Need separate variable for reading longs from an object on 64-bit
|
||||
@@ -1229,6 +1242,15 @@ FileAttrModifyTimeCmd(
|
||||
if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
/* We use a value of 0 to indicate the modification time not available */
|
||||
if (buf.st_mtime == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"could not get modification time for file \"%s\"",
|
||||
TclGetString(objv[1])));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#endif
|
||||
if (objc == 3) {
|
||||
/*
|
||||
* Need separate variable for reading longs from an object on 64-bit
|
||||
@@ -1574,28 +1596,25 @@ FileAttrIsOwnedCmd(
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
#ifdef __CYGWIN__
|
||||
#define geteuid() (short)(geteuid)()
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
Tcl_StatBuf buf;
|
||||
#endif
|
||||
int value = 0;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "name");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) {
|
||||
/*
|
||||
* For Windows, there are no user ids associated with a file, so we
|
||||
* always return 1.
|
||||
*
|
||||
* TODO: use GetSecurityInfo to get the real owner of the file and
|
||||
* test for equivalence to the current user.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
value = 1;
|
||||
#if defined(_WIN32)
|
||||
value = TclWinFileOwned(objv[1]);
|
||||
#else
|
||||
if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) {
|
||||
value = (geteuid() == buf.st_uid);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+43
-16
@@ -105,8 +105,7 @@ typedef struct SortInfo {
|
||||
*/
|
||||
|
||||
static int DictionaryCompare(const char *left, const char *right);
|
||||
static int IfConditionCallback(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc IfConditionCallback;
|
||||
static int InfoArgsCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const objv[]);
|
||||
static int InfoBodyCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
@@ -1203,7 +1202,7 @@ InfoFrameCmd(
|
||||
levelError:
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad level \"%s\"", TclGetString(objv[1])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_FRAME",
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
|
||||
TclGetString(objv[1]), NULL);
|
||||
code = TCL_ERROR;
|
||||
goto done;
|
||||
@@ -1638,7 +1637,7 @@ InfoLevelCmd(
|
||||
levelError:
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad level \"%s\"", TclGetString(objv[1])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_LEVEL",
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
|
||||
TclGetString(objv[1]), NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1678,7 +1677,7 @@ InfoLibraryCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
libDirName = Tcl_GetVar(interp, "tcl_library", TCL_GLOBAL_ONLY);
|
||||
libDirName = Tcl_GetVar2(interp, "tcl_library", NULL, TCL_GLOBAL_ONLY);
|
||||
if (libDirName != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(libDirName, -1));
|
||||
return TCL_OK;
|
||||
@@ -1804,7 +1803,7 @@ InfoPatchLevelCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
patchlevel = Tcl_GetVar(interp, "tcl_patchLevel",
|
||||
patchlevel = Tcl_GetVar2(interp, "tcl_patchLevel", NULL,
|
||||
(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
|
||||
if (patchlevel != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(patchlevel, -1));
|
||||
@@ -2156,8 +2155,8 @@ Tcl_JoinObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* The argument objects. */
|
||||
{
|
||||
int listLen, i;
|
||||
Tcl_Obj *resObjPtr, *joinObjPtr, **elemPtrs;
|
||||
int listLen;
|
||||
Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs;
|
||||
|
||||
if ((objc < 2) || (objc > 3)) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
|
||||
@@ -2174,19 +2173,47 @@ Tcl_JoinObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (listLen == 0) {
|
||||
/* No elements to join; default empty result is correct. */
|
||||
return TCL_OK;
|
||||
}
|
||||
if (listLen == 1) {
|
||||
/* One element; return it */
|
||||
Tcl_SetObjResult(interp, elemPtrs[0]);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
|
||||
Tcl_IncrRefCount(joinObjPtr);
|
||||
|
||||
resObjPtr = Tcl_NewObj();
|
||||
for (i = 0; i < listLen; i++) {
|
||||
if (i > 0) {
|
||||
Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
|
||||
if (Tcl_GetCharLength(joinObjPtr) == 0) {
|
||||
TclStringCatObjv(interp, /* inPlace */ 0, listLen, elemPtrs,
|
||||
&resObjPtr);
|
||||
} else {
|
||||
int i;
|
||||
|
||||
resObjPtr = Tcl_NewObj();
|
||||
for (i = 0; i < listLen; i++) {
|
||||
if (i > 0) {
|
||||
|
||||
/*
|
||||
* NOTE: This code is relying on Tcl_AppendObjToObj() **NOT**
|
||||
* to shimmer joinObjPtr. If it did, then the case where
|
||||
* objv[1] and objv[2] are the same value would not be safe.
|
||||
* Accessing elemPtrs would crash.
|
||||
*/
|
||||
|
||||
Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
|
||||
}
|
||||
Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]);
|
||||
}
|
||||
Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]);
|
||||
}
|
||||
Tcl_DecrRefCount(joinObjPtr);
|
||||
Tcl_SetObjResult(interp, resObjPtr);
|
||||
return TCL_OK;
|
||||
if (resObjPtr) {
|
||||
Tcl_SetObjResult(interp, resObjPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2755,7 +2782,7 @@ Tcl_LreplaceObjCmd(
|
||||
* (to allow for replacing the last elem).
|
||||
*/
|
||||
|
||||
if ((first >= listLen) && (listLen > 0)) {
|
||||
if ((first > listLen) && (listLen > 0)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %s", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPLACE", "BADIDX",
|
||||
|
||||
+40
-206
@@ -22,14 +22,10 @@
|
||||
|
||||
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
|
||||
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
|
||||
static int SwitchPostProc(ClientData data[], Tcl_Interp *interp,
|
||||
int result);
|
||||
static int TryPostBody(ClientData data[], Tcl_Interp *interp,
|
||||
int result);
|
||||
static int TryPostFinal(ClientData data[], Tcl_Interp *interp,
|
||||
int result);
|
||||
static int TryPostHandler(ClientData data[], Tcl_Interp *interp,
|
||||
int result);
|
||||
static Tcl_NRPostProc SwitchPostProc;
|
||||
static Tcl_NRPostProc TryPostBody;
|
||||
static Tcl_NRPostProc TryPostFinal;
|
||||
static Tcl_NRPostProc TryPostHandler;
|
||||
static int UniCharIsAscii(int character);
|
||||
static int UniCharIsHexDigit(int character);
|
||||
|
||||
@@ -327,7 +323,7 @@ Tcl_RegexpObjCmd(
|
||||
|
||||
if (match == 0) {
|
||||
/*
|
||||
* We want to set the value of the intepreter result only when
|
||||
* We want to set the value of the interpreter result only when
|
||||
* this is the first time through the loop.
|
||||
*/
|
||||
|
||||
@@ -1180,8 +1176,7 @@ StringFirstCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar *needleStr, *haystackStr;
|
||||
int match, start, needleLen, haystackLen;
|
||||
int start = 0;
|
||||
|
||||
if (objc < 3 || objc > 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
@@ -1189,82 +1184,23 @@ StringFirstCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are searching haystackStr for the sequence needleStr.
|
||||
*/
|
||||
|
||||
match = -1;
|
||||
start = 0;
|
||||
haystackLen = -1;
|
||||
|
||||
needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen);
|
||||
haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen);
|
||||
|
||||
if (objc == 4) {
|
||||
/*
|
||||
* If a startIndex is specified, we will need to fast forward to that
|
||||
* point in the string before we think about a match.
|
||||
*/
|
||||
int size = Tcl_GetCharLength(objv[2]);
|
||||
|
||||
if (TclGetIntForIndexM(interp, objv[3], haystackLen-1,
|
||||
&start) != TCL_OK){
|
||||
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &start)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reread to prevent shimmering problems.
|
||||
*/
|
||||
|
||||
needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen);
|
||||
haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen);
|
||||
|
||||
if (start >= haystackLen) {
|
||||
goto str_first_done;
|
||||
} else if (start > 0) {
|
||||
haystackStr += start;
|
||||
haystackLen -= start;
|
||||
} else if (start < 0) {
|
||||
/*
|
||||
* Invalid start index mapped to string start; Bug #423581
|
||||
*/
|
||||
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the length of the needle is more than the length of the haystack, it
|
||||
* cannot be contained in there so we can avoid searching. [Bug 2960021]
|
||||
*/
|
||||
|
||||
if (needleLen > 0 && needleLen <= haystackLen) {
|
||||
register Tcl_UniChar *p, *end;
|
||||
|
||||
end = haystackStr + haystackLen - needleLen + 1;
|
||||
for (p = haystackStr; p < end; p++) {
|
||||
/*
|
||||
* Scan forward to find the first character.
|
||||
*/
|
||||
|
||||
if ((*p == *needleStr) && (TclUniCharNcmp(needleStr, p,
|
||||
(unsigned long) needleLen) == 0)) {
|
||||
match = p - haystackStr;
|
||||
break;
|
||||
}
|
||||
if (start >= size) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the character index of the matching string by counting the
|
||||
* number of characters before the match.
|
||||
*/
|
||||
|
||||
if ((match != -1) && (objc == 4)) {
|
||||
match += start;
|
||||
}
|
||||
|
||||
str_first_done:
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(match));
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFind(objv[1],
|
||||
objv[2], start)));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -1293,76 +1229,31 @@ StringLastCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar *needleStr, *haystackStr, *p;
|
||||
int match, start, needleLen, haystackLen;
|
||||
int last = INT_MAX - 1;
|
||||
|
||||
if (objc < 3 || objc > 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"needleString haystackString ?startIndex?");
|
||||
"needleString haystackString ?lastIndex?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are searching haystackString for the sequence needleString.
|
||||
*/
|
||||
|
||||
match = -1;
|
||||
start = 0;
|
||||
haystackLen = -1;
|
||||
|
||||
needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen);
|
||||
haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen);
|
||||
|
||||
if (objc == 4) {
|
||||
/*
|
||||
* If a startIndex is specified, we will need to restrict the string
|
||||
* range to that char index in the string
|
||||
*/
|
||||
int size = Tcl_GetCharLength(objv[2]);
|
||||
|
||||
if (TclGetIntForIndexM(interp, objv[3], haystackLen-1,
|
||||
&start) != TCL_OK){
|
||||
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &last)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reread to prevent shimmering problems.
|
||||
*/
|
||||
|
||||
needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen);
|
||||
haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen);
|
||||
|
||||
if (start < 0) {
|
||||
goto str_last_done;
|
||||
} else if (start < haystackLen) {
|
||||
p = haystackStr + start + 1 - needleLen;
|
||||
} else {
|
||||
p = haystackStr + haystackLen - needleLen;
|
||||
if (last < 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
return TCL_OK;
|
||||
}
|
||||
} else {
|
||||
p = haystackStr + haystackLen - needleLen;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the length of the needle is more than the length of the haystack, it
|
||||
* cannot be contained in there so we can avoid searching. [Bug 2960021]
|
||||
*/
|
||||
|
||||
if (needleLen > 0 && needleLen <= haystackLen) {
|
||||
for (; p >= haystackStr; p--) {
|
||||
/*
|
||||
* Scan backwards to find the first character.
|
||||
*/
|
||||
|
||||
if ((*p == *needleStr) && !memcmp(needleStr, p,
|
||||
sizeof(Tcl_UniChar) * (size_t)needleLen)) {
|
||||
match = p - haystackStr;
|
||||
break;
|
||||
}
|
||||
if (last >= size) {
|
||||
last = size - 1;
|
||||
}
|
||||
}
|
||||
|
||||
str_last_done:
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(match));
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringLast(objv[1],
|
||||
objv[2], last)));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -1877,7 +1768,7 @@ StringMapCmd(
|
||||
|
||||
/*
|
||||
* This test is tricky, but has to be that way or you get other strange
|
||||
* inconsistencies (see test string-10.20 for illustration why!)
|
||||
* inconsistencies (see test string-10.20.1 for illustration why!)
|
||||
*/
|
||||
|
||||
if (objv[objc-2]->typePtr == &tclDictType && objv[objc-2]->bytes == NULL){
|
||||
@@ -2227,9 +2118,7 @@ StringReptCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
const char *string1;
|
||||
char *string2;
|
||||
int count, index, length1, length2;
|
||||
int count;
|
||||
Tcl_Obj *resultPtr;
|
||||
|
||||
if (objc != 3) {
|
||||
@@ -2247,70 +2136,15 @@ StringReptCmd(
|
||||
|
||||
if (count == 1) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
goto done;
|
||||
return TCL_OK;
|
||||
} else if (count < 1) {
|
||||
goto done;
|
||||
}
|
||||
string1 = TclGetStringFromObj(objv[1], &length1);
|
||||
if (length1 <= 0) {
|
||||
goto done;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only build up a string that has data. Instead of building it up with
|
||||
* repeated appends, we just allocate the necessary space once and copy
|
||||
* the string value in.
|
||||
*
|
||||
* We have to worry about overflow [Bugs 714106, 2561746].
|
||||
* At this point we know 1 <= length1 <= INT_MAX and 2 <= count <= INT_MAX.
|
||||
* We need to keep 2 <= length2 <= INT_MAX.
|
||||
*/
|
||||
|
||||
if (count > INT_MAX/length1) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"result exceeds max size for a Tcl value (%d bytes)",
|
||||
INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
if (TCL_OK != TclStringRepeat(interp, objv[1], count, &resultPtr)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
length2 = length1 * count;
|
||||
|
||||
/*
|
||||
* Include space for the NUL.
|
||||
*/
|
||||
|
||||
string2 = attemptckalloc((unsigned) length2 + 1);
|
||||
if (string2 == NULL) {
|
||||
/*
|
||||
* Alloc failed. Note that in this case we try to do an error message
|
||||
* since this is a case that's most likely when the alloc is large and
|
||||
* that's easy to do with this API. Note that if we fail allocating a
|
||||
* short string, this will likely keel over too (and fatally).
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"string size overflow, out of memory allocating %u bytes",
|
||||
length2 + 1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (index = 0; index < count; index++) {
|
||||
memcpy(string2 + (length1 * index), string1, (size_t) length1);
|
||||
}
|
||||
string2[length2] = '\0';
|
||||
|
||||
/*
|
||||
* We have to directly assign this instead of using Tcl_SetStringObj (and
|
||||
* indirectly TclInitStringRep) because that makes another copy of the
|
||||
* data.
|
||||
*/
|
||||
|
||||
TclNewObj(resultPtr);
|
||||
resultPtr->bytes = string2;
|
||||
resultPtr->length = length2;
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
|
||||
done:
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2859,7 +2693,7 @@ StringCatCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int i;
|
||||
int code;
|
||||
Tcl_Obj *objResultPtr;
|
||||
|
||||
if (objc < 2) {
|
||||
@@ -2876,16 +2710,16 @@ StringCatCmd(
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
objResultPtr = objv[1];
|
||||
if (Tcl_IsShared(objResultPtr)) {
|
||||
objResultPtr = Tcl_DuplicateObj(objResultPtr);
|
||||
}
|
||||
for(i = 2;i < objc;i++) {
|
||||
Tcl_AppendObjToObj(objResultPtr, objv[i]);
|
||||
}
|
||||
Tcl_SetObjResult(interp, objResultPtr);
|
||||
|
||||
return TCL_OK;
|
||||
code = TclStringCatObjv(interp, /* inPlace */ 1, objc-1, objv+1,
|
||||
&objResultPtr);
|
||||
|
||||
if (code == TCL_OK) {
|
||||
Tcl_SetObjResult(interp, objResultPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+224
-17
@@ -49,6 +49,9 @@ static int CompileEachloopCmd(Tcl_Interp *interp,
|
||||
static int CompileDictEachCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr, int collect);
|
||||
static int CompileArrayEachCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
|
||||
/*
|
||||
* The structures below define the AuxData types defined in this file.
|
||||
@@ -287,6 +290,221 @@ TclCompileArrayExistsCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileArrayForCmd(
|
||||
Tcl_Interp *interp, /* Used for looking up stuff. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
return CompileArrayEachCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
CompileArrayEachCmd(
|
||||
Tcl_Interp *interp, /* Used for looking up stuff. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr /* Holds resulting instructions. */
|
||||
)
|
||||
{
|
||||
DefineLineInformation;
|
||||
Tcl_Token *varsTokenPtr, *arrayTokenPtr, *bodyTokenPtr;
|
||||
int keyVarIndex, valueVarIndex, nameChars, loopRange, catchRange;
|
||||
int infoIndex, jumpDisplacement, bodyTargetOffset, emptyTargetOffset;
|
||||
int numVars, endTargetOffset;
|
||||
const char **argv;
|
||||
Tcl_DString buffer;
|
||||
|
||||
/*
|
||||
* There must be three arguments after the command.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 4) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
varsTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
arrayTokenPtr = TokenAfter(varsTokenPtr);
|
||||
bodyTokenPtr = TokenAfter(arrayTokenPtr);
|
||||
if (varsTokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
|
||||
arrayTokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
|
||||
bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check we've got one or two variables and that they are local variables.
|
||||
* Then extract their indices in the LVT.
|
||||
*/
|
||||
|
||||
Tcl_DStringInit(&buffer);
|
||||
TclDStringAppendToken(&buffer, &varsTokenPtr[1]);
|
||||
if (Tcl_SplitList(NULL, Tcl_DStringValue(&buffer), &numVars,
|
||||
&argv) != TCL_OK) {
|
||||
Tcl_DStringFree(&buffer);
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
Tcl_DStringFree(&buffer);
|
||||
/*
|
||||
* both
|
||||
* array for {k} a {}
|
||||
* array for {k v} a {}
|
||||
* are supported.
|
||||
*/
|
||||
if (numVars != 1 && numVars != 2) {
|
||||
ckfree(argv);
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
nameChars = strlen(argv[0]);
|
||||
keyVarIndex = LocalScalar(argv[0], nameChars, envPtr);
|
||||
valueVarIndex = -1;
|
||||
if (numVars == 2) {
|
||||
nameChars = strlen(argv[1]);
|
||||
valueVarIndex = LocalScalar(argv[1], nameChars, envPtr);
|
||||
}
|
||||
ckfree(argv);
|
||||
|
||||
if ((keyVarIndex < 0) || (numVars == 2 && valueVarIndex < 0)) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a temporary variable to store the iterator reference. The
|
||||
* variable will contain a Tcl_ArraySearch reference which will be
|
||||
* allocated by INST_ARRAY_FIRST and disposed when the variable is unset
|
||||
* (at which point it should also have been finished with).
|
||||
*/
|
||||
|
||||
infoIndex = AnonymousLocal(envPtr);
|
||||
if (infoIndex < 0) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Preparation complete; issue instructions. Note that this code issues
|
||||
* fixed-sized jumps. That simplifies things a lot!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get the array and start the iteration. No catching of errors at
|
||||
* this point.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, arrayTokenPtr, interp, 2);
|
||||
|
||||
/*
|
||||
* Now we catch errors from here on
|
||||
*/
|
||||
|
||||
TclEmitInstInt4( INST_ARRAY_FIRST, infoIndex, envPtr);
|
||||
|
||||
catchRange = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
|
||||
TclEmitInstInt4( INST_BEGIN_CATCH4, catchRange, envPtr);
|
||||
ExceptionRangeStarts(envPtr, catchRange);
|
||||
|
||||
/*
|
||||
* Set up the loop exception targets.
|
||||
*/
|
||||
|
||||
loopRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
|
||||
ExceptionRangeStarts(envPtr, loopRange);
|
||||
|
||||
/*
|
||||
* Inside the iteration, fetch and write the loop variables.
|
||||
*/
|
||||
|
||||
bodyTargetOffset = CurrentOffset(envPtr);
|
||||
|
||||
TclEmitInstInt4( INST_ARRAY_NEXT, infoIndex, envPtr);
|
||||
emptyTargetOffset = CurrentOffset(envPtr);
|
||||
|
||||
Emit14Inst( INST_STORE_SCALAR, keyVarIndex, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
if (valueVarIndex != -1) {
|
||||
Emit14Inst( INST_STORE_SCALAR, valueVarIndex, envPtr);
|
||||
}
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
|
||||
/*
|
||||
* Compile the loop body itself. It should be stack-neutral.
|
||||
*/
|
||||
|
||||
BODY(bodyTokenPtr, 3);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
|
||||
/*
|
||||
* Both exception target ranges (error and loop) end here.
|
||||
*/
|
||||
|
||||
ExceptionRangeEnds(envPtr, loopRange);
|
||||
ExceptionRangeEnds(envPtr, catchRange);
|
||||
|
||||
/*
|
||||
* Continue (or just normally process) by getting the next pair of items
|
||||
* from the dictionary and jumping back to the code to write them into
|
||||
* variables if there is another pair.
|
||||
*/
|
||||
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
ExceptionRangeTarget(envPtr, loopRange, continueOffset);
|
||||
TclEmitInstInt4( INST_ARRAY_NEXT, infoIndex, envPtr);
|
||||
jumpDisplacement = bodyTargetOffset - CurrentOffset(envPtr);
|
||||
/*
|
||||
* checks the 'done' boolean on the stack and if false,
|
||||
* goes back to the top of the loop
|
||||
*/
|
||||
TclEmitInstInt4( INST_JUMP_FALSE4, jumpDisplacement, envPtr);
|
||||
endTargetOffset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP1, 0, envPtr);
|
||||
|
||||
/*
|
||||
* Error handler "finally" clause, which force-terminates the iteration
|
||||
* and rethrows the error.
|
||||
*/
|
||||
|
||||
ExceptionRangeTarget(envPtr, catchRange, catchOffset);
|
||||
TclEmitOpcode( INST_END_CATCH, envPtr);
|
||||
TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr);
|
||||
TclEmitInt4( infoIndex, envPtr);
|
||||
TclEmitOpcode( INST_RETURN_STK, envPtr);
|
||||
|
||||
/*
|
||||
* Otherwise we're done and we
|
||||
* need to pop the bogus key/value pair (pushed to keep stack calculations
|
||||
* easy!) Note that we skip the END_CATCH. [Bug 1382528]
|
||||
*/
|
||||
|
||||
jumpDisplacement = CurrentOffset(envPtr) - emptyTargetOffset;
|
||||
TclUpdateInstInt4AtPc(INST_JUMP_TRUE4, jumpDisplacement,
|
||||
envPtr->codeStart + emptyTargetOffset);
|
||||
jumpDisplacement = CurrentOffset(envPtr) - endTargetOffset;
|
||||
TclUpdateInstInt1AtPc(INST_JUMP1, jumpDisplacement,
|
||||
envPtr->codeStart + endTargetOffset);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
ExceptionRangeTarget(envPtr, loopRange, breakOffset);
|
||||
TclFinalizeLoopExceptionRange(envPtr, loopRange);
|
||||
TclEmitOpcode( INST_END_CATCH, envPtr);
|
||||
|
||||
/*
|
||||
* Final stage of the command (normal case) is that we push an empty
|
||||
* object (or push the accumulator as the result object). This is done
|
||||
* last to promote peephole optimization when it's dropped immediately.
|
||||
*/
|
||||
|
||||
TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr);
|
||||
TclEmitInt4( infoIndex, envPtr);
|
||||
PushStringLiteral(envPtr, "");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
TclCompileArraySetCmd(
|
||||
Tcl_Interp *interp, /* Used for looking up stuff. */
|
||||
@@ -801,7 +1019,7 @@ TclCompileConcatCmd(
|
||||
Tcl_ListObjGetElements(NULL, listObj, &len, &objs);
|
||||
objPtr = Tcl_ConcatObj(len, objs);
|
||||
Tcl_DecrRefCount(listObj);
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &len);
|
||||
bytes = TclGetStringFromObj(objPtr, &len);
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
return TCL_OK;
|
||||
@@ -1209,7 +1427,7 @@ TclCompileDictCreateCmd(
|
||||
* We did! Excellent. The "verifyDict" is to do type forcing.
|
||||
*/
|
||||
|
||||
bytes = Tcl_GetStringFromObj(dictObj, &len);
|
||||
bytes = TclGetStringFromObj(dictObj, &len);
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_DICT_VERIFY, envPtr);
|
||||
@@ -2650,7 +2868,7 @@ CompileEachloopCmd(
|
||||
int numBytes, varIndex;
|
||||
|
||||
Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
|
||||
bytes = Tcl_GetStringFromObj(varNameObj, &numBytes);
|
||||
bytes = TclGetStringFromObj(varNameObj, &numBytes);
|
||||
varIndex = LocalScalar(bytes, numBytes, envPtr);
|
||||
if (varIndex < 0) {
|
||||
code = TCL_ERROR;
|
||||
@@ -3087,7 +3305,7 @@ TclCompileFormatCmd(
|
||||
* literal. Job done.
|
||||
*/
|
||||
|
||||
bytes = Tcl_GetStringFromObj(tmpObj, &len);
|
||||
bytes = TclGetStringFromObj(tmpObj, &len);
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
return TCL_OK;
|
||||
@@ -3158,7 +3376,7 @@ TclCompileFormatCmd(
|
||||
if (*++bytes == '%') {
|
||||
Tcl_AppendToObj(tmpObj, "%", 1);
|
||||
} else {
|
||||
char *b = Tcl_GetStringFromObj(tmpObj, &len);
|
||||
char *b = TclGetStringFromObj(tmpObj, &len);
|
||||
|
||||
/*
|
||||
* If there is a non-empty literal from the format string,
|
||||
@@ -3192,7 +3410,7 @@ TclCompileFormatCmd(
|
||||
*/
|
||||
|
||||
Tcl_AppendToObj(tmpObj, start, bytes - start);
|
||||
bytes = Tcl_GetStringFromObj(tmpObj, &len);
|
||||
bytes = TclGetStringFromObj(tmpObj, &len);
|
||||
if (len > 0) {
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
i++;
|
||||
@@ -3206,17 +3424,6 @@ TclCompileFormatCmd(
|
||||
*/
|
||||
|
||||
TclEmitInstInt1(INST_STR_CONCAT1, i, envPtr);
|
||||
} else {
|
||||
/*
|
||||
* EVIL HACK! Force there to be a string representation in the case
|
||||
* where there's just a "%s" in the format; case covered by the test
|
||||
* format-20.1 (and it is horrible...)
|
||||
*/
|
||||
|
||||
TclEmitOpcode(INST_DUP, envPtr);
|
||||
PushStringLiteral(envPtr, "");
|
||||
TclEmitOpcode(INST_STR_EQ, envPtr);
|
||||
TclEmitOpcode(INST_POP, envPtr);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+43
-10
@@ -1488,6 +1488,15 @@ TclCompileLreplaceCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* idx1, idx2 are now in canonical form:
|
||||
*
|
||||
* - integer: [0,len+1]
|
||||
* - end index: INDEX_END
|
||||
* - -ive offset: INDEX_END-[len-1,0]
|
||||
* - +ive offset: INDEX_END+1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compilation fails when one index is end-based but the other isn't.
|
||||
* Fixing this will require more bytecodes, but this is a workaround for
|
||||
@@ -1521,6 +1530,9 @@ TclCompileLreplaceCmd(
|
||||
idx1 = 0;
|
||||
goto dropEnd;
|
||||
} else {
|
||||
if (idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
}
|
||||
if (idx1 > 0) {
|
||||
tmpObj = Tcl_NewIntObj(idx1);
|
||||
Tcl_IncrRefCount(tmpObj);
|
||||
@@ -1548,9 +1560,7 @@ TclCompileLreplaceCmd(
|
||||
idx1 = 0;
|
||||
goto replaceTail;
|
||||
} else {
|
||||
if (idx1 > 0 && idx2 > 0 && idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
} else if (idx1 < 0 && idx2 < 0 && idx2 < idx1) {
|
||||
if (idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
}
|
||||
if (idx1 > 0) {
|
||||
@@ -1566,7 +1576,7 @@ TclCompileLreplaceCmd(
|
||||
* operate on.
|
||||
*/
|
||||
|
||||
dropAll:
|
||||
dropAll: /* This just ensures the arg is a list. */
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
PushStringLiteral(envPtr, "");
|
||||
@@ -1579,12 +1589,21 @@ TclCompileLreplaceCmd(
|
||||
|
||||
dropRange:
|
||||
if (tmpObj != NULL) {
|
||||
/*
|
||||
* Emit bytecode to check the list length.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
|
||||
TclEmitOpcode( INST_GT, envPtr);
|
||||
TclEmitOpcode( INST_GE, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
|
||||
/*
|
||||
* Emit an error if we've been given an empty list.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
@@ -1635,16 +1654,30 @@ TclCompileLreplaceCmd(
|
||||
|
||||
replaceRange:
|
||||
if (tmpObj != NULL) {
|
||||
/*
|
||||
* Emit bytecode to check the list length.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
|
||||
/*
|
||||
* Check the list length vs idx1.
|
||||
*/
|
||||
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
|
||||
TclEmitOpcode( INST_GT, envPtr);
|
||||
TclEmitOpcode( INST_GE, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
|
||||
/*
|
||||
* Emit an error if we've been given an empty list.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %d", idx1), NULL), envPtr);
|
||||
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
|
||||
@@ -2418,7 +2451,7 @@ TclCompileRegsubCmd(
|
||||
* replacement "simple"?
|
||||
*/
|
||||
|
||||
bytes = Tcl_GetStringFromObj(patternObj, &len);
|
||||
bytes = TclGetStringFromObj(patternObj, &len);
|
||||
if (TclReToGlob(NULL, bytes, len, &pattern, &exact, &quantified)
|
||||
!= TCL_OK || exact || quantified) {
|
||||
goto done;
|
||||
@@ -2466,7 +2499,7 @@ TclCompileRegsubCmd(
|
||||
result = TCL_OK;
|
||||
bytes = Tcl_DStringValue(&pattern) + 1;
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
bytes = Tcl_GetStringFromObj(replacementObj, &len);
|
||||
bytes = TclGetStringFromObj(replacementObj, &len);
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords-2);
|
||||
TclEmitOpcode( INST_STR_MAP, envPtr);
|
||||
@@ -2728,7 +2761,7 @@ TclCompileSyntaxError(
|
||||
const char *bytes = TclGetStringFromObj(msg, &numBytes);
|
||||
|
||||
TclErrorStackResetIf(interp, bytes, numBytes);
|
||||
TclEmitPush(TclRegisterNewLiteral(envPtr, bytes, numBytes), envPtr);
|
||||
TclEmitPush(TclRegisterLiteral(envPtr, bytes, numBytes, 0), envPtr);
|
||||
CompileReturnInternal(envPtr, INST_SYNTAX, TCL_ERROR, 0,
|
||||
TclNoErrorStack(interp, Tcl_GetReturnOptions(interp, TCL_ERROR)));
|
||||
Tcl_ResetResult(interp);
|
||||
|
||||
+16
-16
@@ -312,7 +312,7 @@ TclCompileStringCatCmd(
|
||||
Tcl_DecrRefCount(obj);
|
||||
if (folded) {
|
||||
int len;
|
||||
const char *bytes = Tcl_GetStringFromObj(folded, &len);
|
||||
const char *bytes = TclGetStringFromObj(folded, &len);
|
||||
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
Tcl_DecrRefCount(folded);
|
||||
@@ -330,7 +330,7 @@ TclCompileStringCatCmd(
|
||||
}
|
||||
if (folded) {
|
||||
int len;
|
||||
const char *bytes = Tcl_GetStringFromObj(folded, &len);
|
||||
const char *bytes = TclGetStringFromObj(folded, &len);
|
||||
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
Tcl_DecrRefCount(folded);
|
||||
@@ -948,12 +948,12 @@ TclCompileStringMapCmd(
|
||||
* correct semantics for mapping.
|
||||
*/
|
||||
|
||||
bytes = Tcl_GetStringFromObj(objv[0], &len);
|
||||
bytes = TclGetStringFromObj(objv[0], &len);
|
||||
if (len == 0) {
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 2);
|
||||
} else {
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
bytes = Tcl_GetStringFromObj(objv[1], &len);
|
||||
bytes = TclGetStringFromObj(objv[1], &len);
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 2);
|
||||
OP(STR_MAP);
|
||||
@@ -1456,8 +1456,8 @@ TclSubstCompile(
|
||||
|
||||
switch (tokenPtr->type) {
|
||||
case TCL_TOKEN_TEXT:
|
||||
literal = TclRegisterNewLiteral(envPtr,
|
||||
tokenPtr->start, tokenPtr->size);
|
||||
literal = TclRegisterLiteral(envPtr,
|
||||
tokenPtr->start, tokenPtr->size, 0);
|
||||
TclEmitPush(literal, envPtr);
|
||||
TclAdvanceLines(&bline, tokenPtr->start,
|
||||
tokenPtr->start + tokenPtr->size);
|
||||
@@ -1466,7 +1466,7 @@ TclSubstCompile(
|
||||
case TCL_TOKEN_BS:
|
||||
length = TclParseBackslash(tokenPtr->start, tokenPtr->size,
|
||||
NULL, buf);
|
||||
literal = TclRegisterNewLiteral(envPtr, buf, length);
|
||||
literal = TclRegisterLiteral(envPtr, buf, length, 0);
|
||||
TclEmitPush(literal, envPtr);
|
||||
count++;
|
||||
continue;
|
||||
@@ -1902,10 +1902,10 @@ TclCompileSwitchCmd(
|
||||
}
|
||||
if (numWords % 2) {
|
||||
abort:
|
||||
ckfree((char *) bodyToken);
|
||||
ckfree((char *) bodyTokenArray);
|
||||
ckfree((char *) bodyLines);
|
||||
ckfree((char *) bodyContLines);
|
||||
ckfree(bodyToken);
|
||||
ckfree(bodyTokenArray);
|
||||
ckfree(bodyLines);
|
||||
ckfree(bodyContLines);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else if (numWords % 2 || numWords == 0) {
|
||||
@@ -2825,7 +2825,7 @@ TclCompileTryCmd(
|
||||
}
|
||||
if (objc > 0) {
|
||||
int len;
|
||||
const char *varname = Tcl_GetStringFromObj(objv[0], &len);
|
||||
const char *varname = TclGetStringFromObj(objv[0], &len);
|
||||
|
||||
resultVarIndices[i] = LocalScalar(varname, len, envPtr);
|
||||
if (resultVarIndices[i] < 0) {
|
||||
@@ -2837,7 +2837,7 @@ TclCompileTryCmd(
|
||||
}
|
||||
if (objc == 2) {
|
||||
int len;
|
||||
const char *varname = Tcl_GetStringFromObj(objv[1], &len);
|
||||
const char *varname = TclGetStringFromObj(objv[1], &len);
|
||||
|
||||
optionVarIndices[i] = LocalScalar(varname, len, envPtr);
|
||||
if (optionVarIndices[i] < 0) {
|
||||
@@ -3040,7 +3040,7 @@ IssueTryClausesInstructions(
|
||||
OP4( DICT_GET, 1);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
OP44( LIST_RANGE_IMM, 0, len-1);
|
||||
p = Tcl_GetStringFromObj(matchClauses[i], &len);
|
||||
p = TclGetStringFromObj(matchClauses[i], &len);
|
||||
PushLiteral(envPtr, p, len);
|
||||
OP( STR_EQ);
|
||||
JUMP4( JUMP_FALSE, notECJumpSource);
|
||||
@@ -3251,7 +3251,7 @@ IssueTryClausesFinallyInstructions(
|
||||
OP4( DICT_GET, 1);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
OP44( LIST_RANGE_IMM, 0, len-1);
|
||||
p = Tcl_GetStringFromObj(matchClauses[i], &len);
|
||||
p = TclGetStringFromObj(matchClauses[i], &len);
|
||||
PushLiteral(envPtr, p, len);
|
||||
OP( STR_EQ);
|
||||
JUMP4( JUMP_FALSE, notECJumpSource);
|
||||
@@ -3579,7 +3579,7 @@ TclCompileUnsetCmd(
|
||||
const char *bytes;
|
||||
int len;
|
||||
|
||||
bytes = Tcl_GetStringFromObj(leadingWord, &len);
|
||||
bytes = TclGetStringFromObj(leadingWord, &len);
|
||||
if (i == 1 && len == 11 && !strncmp("-nocomplain", bytes, 11)) {
|
||||
flags = 0;
|
||||
haveFlags++;
|
||||
|
||||
+11
-14
@@ -2181,7 +2181,6 @@ ExecConstantExprTree(
|
||||
CompileEnv *envPtr;
|
||||
ByteCode *byteCodePtr;
|
||||
int code;
|
||||
Tcl_Obj *byteCodeObj = Tcl_NewObj();
|
||||
NRE_callback *rootPtr = TOP_CB(interp);
|
||||
|
||||
/*
|
||||
@@ -2195,14 +2194,12 @@ ExecConstantExprTree(
|
||||
CompileExprTree(interp, nodes, index, litObjvPtr, NULL, NULL, envPtr,
|
||||
0 /* optimize */);
|
||||
TclEmitOpcode(INST_DONE, envPtr);
|
||||
Tcl_IncrRefCount(byteCodeObj);
|
||||
TclInitByteCodeObj(byteCodeObj, envPtr);
|
||||
byteCodePtr = TclInitByteCode(envPtr);
|
||||
TclFreeCompileEnv(envPtr);
|
||||
TclStackFree(interp, envPtr);
|
||||
byteCodePtr = byteCodeObj->internalRep.twoPtrValue.ptr1;
|
||||
TclNRExecuteByteCode(interp, byteCodePtr);
|
||||
code = TclNRRunCallbacks(interp, TCL_OK, rootPtr);
|
||||
Tcl_DecrRefCount(byteCodeObj);
|
||||
TclReleaseByteCode(byteCodePtr);
|
||||
return code;
|
||||
}
|
||||
|
||||
@@ -2270,9 +2267,9 @@ CompileExprTree(
|
||||
p = TclGetStringFromObj(*funcObjv, &length);
|
||||
funcObjv++;
|
||||
Tcl_DStringAppend(&cmdName, p, length);
|
||||
TclEmitPush(TclRegisterNewCmdLiteral(envPtr,
|
||||
TclEmitPush(TclRegisterLiteral(envPtr,
|
||||
Tcl_DStringValue(&cmdName),
|
||||
Tcl_DStringLength(&cmdName)), envPtr);
|
||||
Tcl_DStringLength(&cmdName), LITERAL_CMD_NAME), envPtr);
|
||||
Tcl_DStringFree(&cmdName);
|
||||
|
||||
/*
|
||||
@@ -2379,8 +2376,8 @@ CompileExprTree(
|
||||
pc1 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1((nodePtr->lexeme == AND) ? INST_JUMP_FALSE1
|
||||
: INST_JUMP_TRUE1, 0, envPtr);
|
||||
TclEmitPush(TclRegisterNewLiteral(envPtr,
|
||||
(nodePtr->lexeme == AND) ? "1" : "0", 1), envPtr);
|
||||
TclEmitPush(TclRegisterLiteral(envPtr,
|
||||
(nodePtr->lexeme == AND) ? "1" : "0", 1, 0), envPtr);
|
||||
pc2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1(INST_JUMP1, 0, envPtr);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
@@ -2389,8 +2386,8 @@ CompileExprTree(
|
||||
if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) {
|
||||
pc2 += 3;
|
||||
}
|
||||
TclEmitPush(TclRegisterNewLiteral(envPtr,
|
||||
(nodePtr->lexeme == AND) ? "0" : "1", 1), envPtr);
|
||||
TclEmitPush(TclRegisterLiteral(envPtr,
|
||||
(nodePtr->lexeme == AND) ? "0" : "1", 1, 0), envPtr);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc2,
|
||||
envPtr->codeStart + pc2 + 1);
|
||||
convert = 0;
|
||||
@@ -2424,7 +2421,7 @@ CompileExprTree(
|
||||
if (optimize) {
|
||||
int length;
|
||||
const char *bytes = TclGetStringFromObj(literal, &length);
|
||||
int index = TclRegisterNewLiteral(envPtr, bytes, length);
|
||||
int index = TclRegisterLiteral(envPtr, bytes, length, 0);
|
||||
Tcl_Obj *objPtr = TclFetchLiteral(envPtr, index);
|
||||
|
||||
if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
|
||||
@@ -2482,8 +2479,8 @@ CompileExprTree(
|
||||
if (objPtr->bytes) {
|
||||
Tcl_Obj *tableValue;
|
||||
|
||||
index = TclRegisterNewLiteral(envPtr, objPtr->bytes,
|
||||
objPtr->length);
|
||||
index = TclRegisterLiteral(envPtr, objPtr->bytes,
|
||||
objPtr->length, 0);
|
||||
tableValue = TclFetchLiteral(envPtr, index);
|
||||
if ((tableValue->typePtr == NULL) &&
|
||||
(objPtr->typePtr != NULL)) {
|
||||
|
||||
+120
-70
@@ -522,7 +522,6 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
{"arrayMakeImm", 5, 0, 1, {OPERAND_LVT4}},
|
||||
/* Forces the variable indexed by opnd to be an array. Does not touch
|
||||
* the stack. */
|
||||
|
||||
{"invokeReplace", 6, INT_MIN, 2, {OPERAND_UINT4,OPERAND_UINT1}},
|
||||
/* Invoke command named objv[0], replacing the first two words with
|
||||
* the word at the top of the stack;
|
||||
@@ -653,7 +652,11 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
{"lappendListStk", 1, -1, 0, {OPERAND_NONE}},
|
||||
/* Lappend list to general variable.
|
||||
* Stack: ... varName list => ... listVarContents */
|
||||
|
||||
{"arrayFirst", 5, 0, 1, {OPERAND_LVT4}},
|
||||
/* Set up iteration over the array
|
||||
* no stack effect */
|
||||
{"arrayNext", 5, +3, 1, {OPERAND_LVT4}},
|
||||
/* Stack: key value done */
|
||||
{NULL, 0, 0, 0, {OPERAND_NONE}}
|
||||
};
|
||||
|
||||
@@ -661,6 +664,7 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
* Prototypes for procedures defined later in this file:
|
||||
*/
|
||||
|
||||
static void CleanupByteCode(ByteCode *codePtr);
|
||||
static ByteCode * CompileSubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int flags);
|
||||
static void DupByteCodeInternalRep(Tcl_Obj *srcPtr,
|
||||
@@ -676,6 +680,7 @@ static void FreeSubstCodeInternalRep(Tcl_Obj *objPtr);
|
||||
static int GetCmdLocEncodingSize(CompileEnv *envPtr);
|
||||
static int IsCompactibleCompileEnv(Tcl_Interp *interp,
|
||||
CompileEnv *envPtr);
|
||||
static void PreventCycle(Tcl_Obj *objPtr, CompileEnv *envPtr);
|
||||
#ifdef TCL_COMPILE_STATS
|
||||
static void RecordByteCodeStats(ByteCode *codePtr);
|
||||
#endif /* TCL_COMPILE_STATS */
|
||||
@@ -866,7 +871,7 @@ TclSetByteCodeFromAny(
|
||||
#endif /*TCL_COMPILE_DEBUG*/
|
||||
|
||||
if (result == TCL_OK) {
|
||||
TclInitByteCodeObj(objPtr, &compEnv);
|
||||
(void) TclInitByteCodeObj(objPtr, &tclByteCodeType, &compEnv);
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (tclTraceCompile >= 2) {
|
||||
TclPrintByteCodeObj(interp, objPtr);
|
||||
@@ -967,16 +972,13 @@ FreeByteCodeInternalRep(
|
||||
{
|
||||
register ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
if (codePtr->refCount-- <= 1) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
}
|
||||
TclReleaseByteCode(codePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCleanupByteCode --
|
||||
* TclReleaseByteCode --
|
||||
*
|
||||
* This procedure does all the real work of freeing up a bytecode
|
||||
* object's ByteCode structure. It's called only when the structure's
|
||||
@@ -993,7 +995,26 @@ FreeByteCodeInternalRep(
|
||||
*/
|
||||
|
||||
void
|
||||
TclCleanupByteCode(
|
||||
TclPreserveByteCode(
|
||||
register ByteCode *codePtr)
|
||||
{
|
||||
codePtr->refCount++;
|
||||
}
|
||||
|
||||
void
|
||||
TclReleaseByteCode(
|
||||
register ByteCode *codePtr)
|
||||
{
|
||||
if (codePtr->refCount-- > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Just dropped to refcount==0. Clean up. */
|
||||
CleanupByteCode(codePtr);
|
||||
}
|
||||
|
||||
static void
|
||||
CleanupByteCode(
|
||||
register ByteCode *codePtr) /* Points to the ByteCode to free. */
|
||||
{
|
||||
Tcl_Interp *interp = (Tcl_Interp *) *codePtr->interpHandle;
|
||||
@@ -1260,8 +1281,6 @@ Tcl_NRSubstObj(
|
||||
*
|
||||
* Results:
|
||||
* A (ByteCode *) is returned pointing to the resulting ByteCode.
|
||||
* The caller must manage its refCount and arrange for a call to
|
||||
* TclCleanupByteCode() when the last reference disappears.
|
||||
*
|
||||
* Side effects:
|
||||
* The Tcl_ObjType of objPtr is changed to the "substcode" type, and the
|
||||
@@ -1292,13 +1311,13 @@ CompileSubstObj(
|
||||
|| (codePtr->nsEpoch != nsPtr->resolverEpoch)
|
||||
|| (codePtr->localCachePtr !=
|
||||
iPtr->varFramePtr->localCachePtr)) {
|
||||
FreeSubstCodeInternalRep(objPtr);
|
||||
TclFreeIntRep(objPtr);
|
||||
}
|
||||
}
|
||||
if (objPtr->typePtr != &substCodeType) {
|
||||
CompileEnv compEnv;
|
||||
int numBytes;
|
||||
const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes);
|
||||
const char *bytes = TclGetStringFromObj(objPtr, &numBytes);
|
||||
|
||||
/* TODO: Check for more TIP 280 */
|
||||
TclInitCompileEnv(interp, &compEnv, bytes, numBytes, NULL, 0);
|
||||
@@ -1306,11 +1325,9 @@ CompileSubstObj(
|
||||
TclSubstCompile(interp, bytes, numBytes, flags, 1, &compEnv);
|
||||
|
||||
TclEmitOpcode(INST_DONE, &compEnv);
|
||||
TclInitByteCodeObj(objPtr, &compEnv);
|
||||
objPtr->typePtr = &substCodeType;
|
||||
codePtr = TclInitByteCodeObj(objPtr, &substCodeType, &compEnv);
|
||||
TclFreeCompileEnv(&compEnv);
|
||||
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = codePtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(flags);
|
||||
if (iPtr->varFramePtr->localCachePtr) {
|
||||
@@ -1353,10 +1370,7 @@ FreeSubstCodeInternalRep(
|
||||
{
|
||||
register ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
if (codePtr->refCount-- <= 1) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
}
|
||||
TclReleaseByteCode(codePtr);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1369,14 +1383,14 @@ ReleaseCmdWordData(
|
||||
Tcl_DecrRefCount(eclPtr->path);
|
||||
}
|
||||
for (i=0 ; i<eclPtr->nuloc ; i++) {
|
||||
ckfree((char *) eclPtr->loc[i].line);
|
||||
ckfree(eclPtr->loc[i].line);
|
||||
}
|
||||
|
||||
if (eclPtr->loc != NULL) {
|
||||
ckfree((char *) eclPtr->loc);
|
||||
ckfree(eclPtr->loc);
|
||||
}
|
||||
|
||||
ckfree((char *) eclPtr);
|
||||
ckfree(eclPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1781,9 +1795,17 @@ CompileCmdLiteral(
|
||||
CompileEnv *envPtr)
|
||||
{
|
||||
int numBytes;
|
||||
const char *bytes = Tcl_GetStringFromObj(cmdObj, &numBytes);
|
||||
int cmdLitIdx = TclRegisterNewCmdLiteral(envPtr, bytes, numBytes);
|
||||
Command *cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj);
|
||||
const char *bytes;
|
||||
Command *cmdPtr;
|
||||
int cmdLitIdx, extraLiteralFlags = LITERAL_CMD_NAME;
|
||||
|
||||
cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj);
|
||||
if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
|
||||
extraLiteralFlags |= LITERAL_UNSHARED;
|
||||
}
|
||||
|
||||
bytes = TclGetStringFromObj(cmdObj, &numBytes);
|
||||
cmdLitIdx = TclRegisterLiteral(envPtr, bytes, numBytes, extraLiteralFlags);
|
||||
|
||||
if (cmdPtr) {
|
||||
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLitIdx), cmdPtr);
|
||||
@@ -1818,8 +1840,8 @@ TclCompileInvocation(
|
||||
continue;
|
||||
}
|
||||
|
||||
objIdx = TclRegisterNewLiteral(envPtr,
|
||||
tokenPtr[1].start, tokenPtr[1].size);
|
||||
objIdx = TclRegisterLiteral(envPtr,
|
||||
tokenPtr[1].start, tokenPtr[1].size, 0);
|
||||
if (envPtr->clNext) {
|
||||
TclContinuationsEnterDerived(TclFetchLiteral(envPtr, objIdx),
|
||||
tokenPtr[1].start - envPtr->source, envPtr->clNext);
|
||||
@@ -1868,8 +1890,8 @@ CompileExpanded(
|
||||
continue;
|
||||
}
|
||||
|
||||
objIdx = TclRegisterNewLiteral(envPtr,
|
||||
tokenPtr[1].start, tokenPtr[1].size);
|
||||
objIdx = TclRegisterLiteral(envPtr,
|
||||
tokenPtr[1].start, tokenPtr[1].size, 0);
|
||||
if (envPtr->clNext) {
|
||||
TclContinuationsEnterDerived(TclFetchLiteral(envPtr, objIdx),
|
||||
tokenPtr[1].start - envPtr->source, envPtr->clNext);
|
||||
@@ -2697,11 +2719,40 @@ TclCompileNoOp(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TclInitByteCodeObj(
|
||||
Tcl_Obj *objPtr, /* Points object that should be initialized,
|
||||
* and whose string rep contains the source
|
||||
* code. */
|
||||
static void
|
||||
PreventCycle(
|
||||
Tcl_Obj *objPtr,
|
||||
CompileEnv *envPtr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < envPtr->literalArrayNext; i++) {
|
||||
if (objPtr == TclFetchLiteral(envPtr, i)) {
|
||||
/*
|
||||
* Prevent circular reference where the bytecode intrep of
|
||||
* a value contains a literal which is that same value.
|
||||
* If this is allowed to happen, refcount decrements may not
|
||||
* reach zero, and memory may leak. Bugs 467523, 3357771
|
||||
*
|
||||
* NOTE: [Bugs 3392070, 3389764] We make a copy based completely
|
||||
* on the string value, and do not call Tcl_DuplicateObj() so we
|
||||
* can be sure we do not have any lingering cycles hiding in
|
||||
* the intrep.
|
||||
*/
|
||||
int numBytes;
|
||||
const char *bytes = TclGetStringFromObj(objPtr, &numBytes);
|
||||
Tcl_Obj *copyPtr = Tcl_NewStringObj(bytes, numBytes);
|
||||
|
||||
Tcl_IncrRefCount(copyPtr);
|
||||
TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, objPtr);
|
||||
|
||||
envPtr->literalArrayPtr[i].objPtr = copyPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteCode *
|
||||
TclInitByteCode(
|
||||
register CompileEnv *envPtr)/* Points to the CompileEnv structure from
|
||||
* which to create a ByteCode structure. */
|
||||
{
|
||||
@@ -2752,7 +2803,8 @@ TclInitByteCodeObj(
|
||||
codePtr->compileEpoch = iPtr->compileEpoch;
|
||||
codePtr->nsPtr = namespacePtr;
|
||||
codePtr->nsEpoch = namespacePtr->resolverEpoch;
|
||||
codePtr->refCount = 1;
|
||||
codePtr->refCount = 0;
|
||||
TclPreserveByteCode(codePtr);
|
||||
if (namespacePtr->compiledVarResProc || iPtr->resolverPtr) {
|
||||
codePtr->flags = TCL_BYTECODE_RESOLVE_VARS;
|
||||
} else {
|
||||
@@ -2778,29 +2830,7 @@ TclInitByteCodeObj(
|
||||
p += TCL_ALIGN(codeBytes); /* align object array */
|
||||
codePtr->objArrayPtr = (Tcl_Obj **) p;
|
||||
for (i = 0; i < numLitObjects; i++) {
|
||||
Tcl_Obj *fetched = TclFetchLiteral(envPtr, i);
|
||||
|
||||
if (objPtr == fetched) {
|
||||
/*
|
||||
* Prevent circular reference where the bytecode intrep of
|
||||
* a value contains a literal which is that same value.
|
||||
* If this is allowed to happen, refcount decrements may not
|
||||
* reach zero, and memory may leak. Bugs 467523, 3357771
|
||||
*
|
||||
* NOTE: [Bugs 3392070, 3389764] We make a copy based completely
|
||||
* on the string value, and do not call Tcl_DuplicateObj() so we
|
||||
* can be sure we do not have any lingering cycles hiding in
|
||||
* the intrep.
|
||||
*/
|
||||
int numBytes;
|
||||
const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes);
|
||||
|
||||
codePtr->objArrayPtr[i] = Tcl_NewStringObj(bytes, numBytes);
|
||||
Tcl_IncrRefCount(codePtr->objArrayPtr[i]);
|
||||
TclReleaseLiteral((Tcl_Interp *)iPtr, objPtr);
|
||||
} else {
|
||||
codePtr->objArrayPtr[i] = fetched;
|
||||
}
|
||||
codePtr->objArrayPtr[i] = TclFetchLiteral(envPtr, i);
|
||||
}
|
||||
|
||||
p += TCL_ALIGN(objArrayBytes); /* align exception range array */
|
||||
@@ -2842,15 +2872,6 @@ TclInitByteCodeObj(
|
||||
RecordByteCodeStats(codePtr);
|
||||
#endif /* TCL_COMPILE_STATS */
|
||||
|
||||
/*
|
||||
* Free the old internal rep then convert the object to a bytecode object
|
||||
* by making its internal rep point to the just compiled ByteCode.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = codePtr;
|
||||
objPtr->typePtr = &tclByteCodeType;
|
||||
|
||||
/*
|
||||
* TIP #280. Associate the extended per-word line information with the
|
||||
* byte code object (internal rep), for use with the bc compiler.
|
||||
@@ -2864,6 +2885,33 @@ TclInitByteCodeObj(
|
||||
envPtr->iPtr = NULL;
|
||||
|
||||
codePtr->localCachePtr = NULL;
|
||||
return codePtr;
|
||||
}
|
||||
|
||||
ByteCode *
|
||||
TclInitByteCodeObj(
|
||||
Tcl_Obj *objPtr, /* Points object that should be initialized,
|
||||
* and whose string rep contains the source
|
||||
* code. */
|
||||
const Tcl_ObjType *typePtr,
|
||||
register CompileEnv *envPtr)/* Points to the CompileEnv structure from
|
||||
* which to create a ByteCode structure. */
|
||||
{
|
||||
ByteCode *codePtr;
|
||||
|
||||
PreventCycle(objPtr, envPtr);
|
||||
|
||||
codePtr = TclInitByteCode(envPtr);
|
||||
|
||||
/*
|
||||
* Free the old internal rep then convert the object to a bytecode object
|
||||
* by making its internal rep point to the just compiled ByteCode.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = codePtr;
|
||||
objPtr->typePtr = typePtr;
|
||||
return codePtr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2931,7 +2979,7 @@ TclFindCompiledLocal(
|
||||
varNamePtr = &cachePtr->varName0;
|
||||
for (i=0; i < cachePtr->numVars; varNamePtr++, i++) {
|
||||
if (*varNamePtr) {
|
||||
localName = Tcl_GetStringFromObj(*varNamePtr, &len);
|
||||
localName = TclGetStringFromObj(*varNamePtr, &len);
|
||||
if ((len == nameBytes) && !strncmp(name, localName, len)) {
|
||||
return i;
|
||||
}
|
||||
@@ -3239,8 +3287,10 @@ EnterCmdWordData(
|
||||
TclAdvanceLines(&wordLine, last, tokenPtr->start);
|
||||
TclAdvanceContinuations(&wordLine, &wordNext,
|
||||
tokenPtr->start - envPtr->source);
|
||||
/* See Ticket 4b61afd660 */
|
||||
wwlines[wordIdx] =
|
||||
(TclWordKnownAtCompileTime(tokenPtr, NULL) ? wordLine : -1);
|
||||
((wordIdx == 0) || TclWordKnownAtCompileTime(tokenPtr, NULL))
|
||||
? wordLine : -1;
|
||||
ePtr->line[wordIdx] = wordLine;
|
||||
ePtr->next[wordIdx] = wordNext;
|
||||
last = tokenPtr->start;
|
||||
|
||||
+15
-32
@@ -417,7 +417,7 @@ typedef struct ByteCode {
|
||||
* procs are specific to an interpreter so the
|
||||
* code emitted will depend on the
|
||||
* interpreter. */
|
||||
int compileEpoch; /* Value of iPtr->compileEpoch when this
|
||||
unsigned int compileEpoch; /* Value of iPtr->compileEpoch when this
|
||||
* ByteCode was compiled. Used to invalidate
|
||||
* code when, e.g., commands with compile
|
||||
* procs are redefined. */
|
||||
@@ -821,8 +821,11 @@ typedef struct ByteCode {
|
||||
#define INST_LAPPEND_LIST_ARRAY_STK 187
|
||||
#define INST_LAPPEND_LIST_STK 188
|
||||
|
||||
#define INST_ARRAY_FIRST 189
|
||||
#define INST_ARRAY_NEXT 190
|
||||
|
||||
/* The last opcode */
|
||||
#define LAST_INST_OPCODE 188
|
||||
#define LAST_INST_OPCODE 190
|
||||
|
||||
/*
|
||||
* Table describing the Tcl bytecode instructions: their name (for displaying
|
||||
@@ -1067,7 +1070,6 @@ MODULE_SCOPE ByteCode * TclCompileObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
MODULE_SCOPE int TclAttemptCompileProc(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, int depth, Command *cmdPtr,
|
||||
CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclCleanupByteCode(ByteCode *codePtr);
|
||||
MODULE_SCOPE void TclCleanupStackForBreakContinue(CompileEnv *envPtr,
|
||||
ExceptionAux *auxPtr);
|
||||
MODULE_SCOPE void TclCompileCmdWord(Tcl_Interp *interp,
|
||||
@@ -1096,7 +1098,7 @@ MODULE_SCOPE int TclCreateAuxData(ClientData clientData,
|
||||
MODULE_SCOPE int TclCreateExceptRange(ExceptionRangeType type,
|
||||
CompileEnv *envPtr);
|
||||
MODULE_SCOPE ExecEnv * TclCreateExecEnv(Tcl_Interp *interp, int size);
|
||||
MODULE_SCOPE Tcl_Obj * TclCreateLiteral(Interp *iPtr, char *bytes,
|
||||
MODULE_SCOPE Tcl_Obj * TclCreateLiteral(Interp *iPtr, const char *bytes,
|
||||
int length, unsigned int hash, int *newPtr,
|
||||
Namespace *nsPtr, int flags,
|
||||
LiteralEntry **globalPtrPtr);
|
||||
@@ -1119,8 +1121,9 @@ MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr,
|
||||
int distThreshold);
|
||||
MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr);
|
||||
MODULE_SCOPE void TclInitByteCodeObj(Tcl_Obj *objPtr,
|
||||
CompileEnv *envPtr);
|
||||
MODULE_SCOPE ByteCode * TclInitByteCode(CompileEnv *envPtr);
|
||||
MODULE_SCOPE ByteCode * TclInitByteCodeObj(Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr, CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp,
|
||||
CompileEnv *envPtr, const char *string,
|
||||
int numBytes, const CmdFrame *invoker, int word);
|
||||
@@ -1157,6 +1160,8 @@ MODULE_SCOPE void TclPushVarName(Tcl_Interp *interp,
|
||||
Tcl_Token *varTokenPtr, CompileEnv *envPtr,
|
||||
int flags, int *localIndexPtr,
|
||||
int *isScalarPtr);
|
||||
MODULE_SCOPE void TclPreserveByteCode(ByteCode *codePtr);
|
||||
MODULE_SCOPE void TclReleaseByteCode(ByteCode *codePtr);
|
||||
MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE void TclInvalidateCmdLiteral(Tcl_Interp *interp,
|
||||
const char *name, Namespace *nsPtr);
|
||||
@@ -1208,29 +1213,7 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
|
||||
|
||||
#define LITERAL_ON_HEAP 0x01
|
||||
#define LITERAL_CMD_NAME 0x02
|
||||
|
||||
/*
|
||||
* Form of TclRegisterLiteral with flags == 0. In that case, it is safe to
|
||||
* cast away constness, and it is cleanest to do that here, all in one place.
|
||||
*
|
||||
* int TclRegisterNewLiteral(CompileEnv *envPtr, const char *bytes,
|
||||
* int length);
|
||||
*/
|
||||
|
||||
#define TclRegisterNewLiteral(envPtr, bytes, length) \
|
||||
TclRegisterLiteral(envPtr, (char *)(bytes), length, /*flags*/ 0)
|
||||
|
||||
/*
|
||||
* Form of TclRegisterLiteral with flags == LITERAL_CMD_NAME. In that case, it
|
||||
* is safe to cast away constness, and it is cleanest to do that here, all in
|
||||
* one place.
|
||||
*
|
||||
* int TclRegisterNewNSLiteral(CompileEnv *envPtr, const char *bytes,
|
||||
* int length);
|
||||
*/
|
||||
|
||||
#define TclRegisterNewCmdLiteral(envPtr, bytes, length) \
|
||||
TclRegisterLiteral(envPtr, (char *)(bytes), length, LITERAL_CMD_NAME)
|
||||
#define LITERAL_UNSHARED 0x04
|
||||
|
||||
/*
|
||||
* Macro used to manually adjust the stack requirements; used in cases where
|
||||
@@ -1261,7 +1244,7 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
|
||||
int dd = (depth); \
|
||||
if (dd != (envPtr)->currStackDepth) { \
|
||||
Tcl_Panic("bad stack depth computations: is %i, should be %i", \
|
||||
(envPtr)->currStackDepth, dd); \
|
||||
(envPtr)->currStackDepth, dd); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -1547,9 +1530,9 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
|
||||
*/
|
||||
|
||||
#define PushLiteral(envPtr, string, length) \
|
||||
TclEmitPush(TclRegisterNewLiteral((envPtr), (string), (length)), (envPtr))
|
||||
TclEmitPush(TclRegisterLiteral(envPtr, string, length, 0), (envPtr))
|
||||
#define PushStringLiteral(envPtr, string) \
|
||||
PushLiteral((envPtr), (string), (int) (sizeof(string "") - 1))
|
||||
PushLiteral(envPtr, string, (int) (sizeof(string "") - 1))
|
||||
|
||||
/*
|
||||
* Macro to advance to the next token; it is more mnemonic than the address
|
||||
|
||||
+4
-4
@@ -232,7 +232,7 @@ QueryConfigObjCmd(
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("package not known", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "FATAL", "PKGCFG_BASE",
|
||||
Tcl_GetString(pkgName), NULL);
|
||||
TclGetString(pkgName), NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ QueryConfigObjCmd(
|
||||
|| val == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("key not known", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONFIG",
|
||||
Tcl_GetString(objv[2]), NULL);
|
||||
TclGetString(objv[2]), NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -333,9 +333,9 @@ QueryConfigDelete(
|
||||
Tcl_DictObjRemove(NULL, pDB, pkgName);
|
||||
Tcl_DecrRefCount(pkgName);
|
||||
if (cdPtr->encoding) {
|
||||
ckfree((char *)cdPtr->encoding);
|
||||
ckfree(cdPtr->encoding);
|
||||
}
|
||||
ckfree((char *)cdPtr);
|
||||
ckfree(cdPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-7
@@ -359,14 +359,8 @@ typedef short int yytype_int16;
|
||||
#ifndef YYSIZE_T
|
||||
# ifdef __SIZE_TYPE__
|
||||
# define YYSIZE_T __SIZE_TYPE__
|
||||
# elif defined size_t
|
||||
# define YYSIZE_T size_t
|
||||
# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
|
||||
|| defined __cplusplus || defined _MSC_VER)
|
||||
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
|
||||
# define YYSIZE_T size_t
|
||||
# else
|
||||
# define YYSIZE_T unsigned int
|
||||
# define YYSIZE_T size_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1816,6 +1816,15 @@ EXTERN int Tcl_FSUnloadFile(Tcl_Interp *interp,
|
||||
EXTERN void Tcl_ZlibStreamSetCompressionDictionary(
|
||||
Tcl_ZlibStream zhandle,
|
||||
Tcl_Obj *compressionDictionaryObj);
|
||||
/* Slot 631 is reserved */
|
||||
/* 632 */
|
||||
EXTERN void Tcl_ArrayObjFirst(Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayObj,
|
||||
Tcl_ArraySearch *searchPtr);
|
||||
/* 633 */
|
||||
EXTERN int Tcl_ArrayObjNext(Tcl_Interp *interp,
|
||||
Tcl_ArraySearch *searchPtr,
|
||||
Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr);
|
||||
|
||||
typedef struct {
|
||||
const struct TclPlatStubs *tclPlatStubs;
|
||||
@@ -2482,6 +2491,9 @@ typedef struct TclStubs {
|
||||
void * (*tcl_FindSymbol) (Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol); /* 628 */
|
||||
int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */
|
||||
void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */
|
||||
void (*reserved631)(void);
|
||||
void (*tcl_ArrayObjFirst) (Tcl_Interp *interp, Tcl_Obj *arrayObj, Tcl_ArraySearch *searchPtr); /* 632 */
|
||||
int (*tcl_ArrayObjNext) (Tcl_Interp *interp, Tcl_ArraySearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr); /* 633 */
|
||||
} TclStubs;
|
||||
|
||||
extern const TclStubs *tclStubsPtr;
|
||||
@@ -3774,6 +3786,11 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_FSUnloadFile) /* 629 */
|
||||
#define Tcl_ZlibStreamSetCompressionDictionary \
|
||||
(tclStubsPtr->tcl_ZlibStreamSetCompressionDictionary) /* 630 */
|
||||
/* Slot 631 is reserved */
|
||||
#define Tcl_ArrayObjFirst \
|
||||
(tclStubsPtr->tcl_ArrayObjFirst) /* 632 */
|
||||
#define Tcl_ArrayObjNext \
|
||||
(tclStubsPtr->tcl_ArrayObjNext) /* 633 */
|
||||
|
||||
#endif /* defined(USE_TCL_STUBS) */
|
||||
|
||||
|
||||
+51
-32
@@ -70,18 +70,12 @@ static inline void DeleteChainTable(struct Dict *dict);
|
||||
static inline Tcl_HashEntry *CreateChainEntry(struct Dict *dict,
|
||||
Tcl_Obj *keyPtr, int *newPtr);
|
||||
static inline int DeleteChainEntry(struct Dict *dict, Tcl_Obj *keyPtr);
|
||||
static int FinalizeDictUpdate(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int FinalizeDictWith(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int DictForNRCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static int DictMapNRCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static int DictForLoopCallback(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int DictMapLoopCallback(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc FinalizeDictUpdate;
|
||||
static Tcl_NRPostProc FinalizeDictWith;
|
||||
static Tcl_ObjCmdProc DictForNRCmd;
|
||||
static Tcl_ObjCmdProc DictMapNRCmd;
|
||||
static Tcl_NRPostProc DictForLoopCallback;
|
||||
static Tcl_NRPostProc DictMapLoopCallback;
|
||||
|
||||
/*
|
||||
* Table of dict subcommand names and implementations.
|
||||
@@ -148,7 +142,7 @@ typedef struct Dict {
|
||||
* the entries in the order that they are
|
||||
* created. */
|
||||
int epoch; /* Epoch counter */
|
||||
int refcount; /* Reference counter (see above) */
|
||||
size_t refCount; /* Reference counter (see above) */
|
||||
Tcl_Obj *chain; /* Linked list used for invalidating the
|
||||
* string representations of updated nested
|
||||
* dictionaries. */
|
||||
@@ -398,7 +392,7 @@ DupDictInternalRep(
|
||||
|
||||
newDict->epoch = 0;
|
||||
newDict->chain = NULL;
|
||||
newDict->refcount = 1;
|
||||
newDict->refCount = 1;
|
||||
|
||||
/*
|
||||
* Store in the object.
|
||||
@@ -433,8 +427,7 @@ FreeDictInternalRep(
|
||||
{
|
||||
Dict *dict = DICT(dictPtr);
|
||||
|
||||
dict->refcount--;
|
||||
if (dict->refcount <= 0) {
|
||||
if (dict->refCount-- <= 1) {
|
||||
DeleteDict(dict);
|
||||
}
|
||||
dictPtr->typePtr = NULL;
|
||||
@@ -719,7 +712,7 @@ SetDictFromAny(
|
||||
TclFreeIntRep(objPtr);
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
dict->refCount = 1;
|
||||
DICT(objPtr) = dict;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = &tclDictType;
|
||||
@@ -1123,7 +1116,7 @@ Tcl_DictObjFirst(
|
||||
searchPtr->dictionaryPtr = (Tcl_Dict) dict;
|
||||
searchPtr->epoch = dict->epoch;
|
||||
searchPtr->next = cPtr->nextPtr;
|
||||
dict->refcount++;
|
||||
dict->refCount++;
|
||||
if (keyPtrPtr != NULL) {
|
||||
*keyPtrPtr = Tcl_GetHashKey(&dict->table, &cPtr->entry);
|
||||
}
|
||||
@@ -1237,8 +1230,7 @@ Tcl_DictObjDone(
|
||||
if (searchPtr->epoch != -1) {
|
||||
searchPtr->epoch = -1;
|
||||
dict = (Dict *) searchPtr->dictionaryPtr;
|
||||
dict->refcount--;
|
||||
if (dict->refcount <= 0) {
|
||||
if (dict->refCount-- <= 1) {
|
||||
DeleteDict(dict);
|
||||
}
|
||||
}
|
||||
@@ -1390,7 +1382,7 @@ Tcl_NewDictObj(void)
|
||||
InitChainTable(dict);
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
dict->refCount = 1;
|
||||
DICT(dictPtr) = dict;
|
||||
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
dictPtr->typePtr = &tclDictType;
|
||||
@@ -1440,7 +1432,7 @@ Tcl_DbNewDictObj(
|
||||
InitChainTable(dict);
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
dict->refCount = 1;
|
||||
DICT(dictPtr) = dict;
|
||||
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
dictPtr->typePtr = &tclDictType;
|
||||
@@ -2288,7 +2280,7 @@ DictAppendCmd(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
|
||||
int i, allocatedDict = 0;
|
||||
int allocatedDict = 0;
|
||||
|
||||
if (objc < 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?");
|
||||
@@ -2311,17 +2303,44 @@ DictAppendCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (valuePtr == NULL) {
|
||||
TclNewObj(valuePtr);
|
||||
} else if (Tcl_IsShared(valuePtr)) {
|
||||
valuePtr = Tcl_DuplicateObj(valuePtr);
|
||||
if ((objc > 3) || (valuePtr == NULL)) {
|
||||
/* Only go through append activites when something will change. */
|
||||
Tcl_Obj *appendObjPtr = NULL;
|
||||
|
||||
if (objc > 3) {
|
||||
/* Something to append */
|
||||
|
||||
if (objc == 4) {
|
||||
appendObjPtr = objv[3];
|
||||
} else if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1,
|
||||
objc-3, objv+3, &appendObjPtr)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (appendObjPtr == NULL) {
|
||||
/* => (objc == 3) => (valuePtr == NULL) */
|
||||
TclNewObj(valuePtr);
|
||||
} else if (valuePtr == NULL) {
|
||||
valuePtr = appendObjPtr;
|
||||
appendObjPtr = NULL;
|
||||
}
|
||||
|
||||
if (appendObjPtr) {
|
||||
if (Tcl_IsShared(valuePtr)) {
|
||||
valuePtr = Tcl_DuplicateObj(valuePtr);
|
||||
}
|
||||
|
||||
Tcl_AppendObjToObj(valuePtr, appendObjPtr);
|
||||
}
|
||||
|
||||
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
|
||||
}
|
||||
|
||||
for (i=3 ; i<objc ; i++) {
|
||||
Tcl_AppendObjToObj(valuePtr, objv[i]);
|
||||
}
|
||||
|
||||
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
|
||||
/*
|
||||
* Even if nothing changed, we still overwrite so that variable
|
||||
* trace expectations are met.
|
||||
*/
|
||||
|
||||
resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
|
||||
TCL_LEAVE_ERR_MSG);
|
||||
|
||||
+136
-3
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
|
||||
* Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
|
||||
* Copyright (c) 2013 Donal K. Fellows.
|
||||
* Copyright (c) 2013-2016 Donal K. Fellows.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -193,7 +193,7 @@ TclPrintObject(
|
||||
char *bytes;
|
||||
int length;
|
||||
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
bytes = TclGetStringFromObj(objPtr, &length);
|
||||
TclPrintSource(outFile, bytes, TclMin(length, maxChars));
|
||||
}
|
||||
|
||||
@@ -650,7 +650,7 @@ FormatInstruction(
|
||||
int length;
|
||||
|
||||
Tcl_AppendToObj(bufferObj, "\t# ", -1);
|
||||
bytes = Tcl_GetStringFromObj(codePtr->objArrayPtr[opnd], &length);
|
||||
bytes = TclGetStringFromObj(codePtr->objArrayPtr[opnd], &length);
|
||||
PrintSourceToObj(bufferObj, bytes, TclMin(length, 40));
|
||||
} else if (suffixBuffer[0]) {
|
||||
Tcl_AppendPrintfToObj(bufferObj, "\t# %s", suffixBuffer);
|
||||
@@ -1279,9 +1279,11 @@ Tcl_DisassembleObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
static const char *const types[] = {
|
||||
"constructor", "destructor",
|
||||
"lambda", "method", "objmethod", "proc", "script", NULL
|
||||
};
|
||||
enum Types {
|
||||
DISAS_CLASS_CONSTRUCTOR, DISAS_CLASS_DESTRUCTOR,
|
||||
DISAS_LAMBDA, DISAS_CLASS_METHOD, DISAS_OBJECT_METHOD, DISAS_PROC,
|
||||
DISAS_SCRIPT
|
||||
};
|
||||
@@ -1290,6 +1292,7 @@ Tcl_DisassembleObjCmd(
|
||||
Proc *procPtr = NULL;
|
||||
Tcl_HashEntry *hPtr;
|
||||
Object *oPtr;
|
||||
Method *methodPtr;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "type ...");
|
||||
@@ -1384,6 +1387,136 @@ Tcl_DisassembleObjCmd(
|
||||
codeObjPtr = objv[2];
|
||||
break;
|
||||
|
||||
case DISAS_CLASS_CONSTRUCTOR:
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "className");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the body of a constructor.
|
||||
*/
|
||||
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr->classPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" is not a class", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
|
||||
TclGetString(objv[2]), NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
methodPtr = oPtr->classPtr->constructorPtr;
|
||||
if (methodPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" has no defined constructor",
|
||||
TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
|
||||
"CONSRUCTOR", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
procPtr = TclOOGetProcFromMethod(methodPtr);
|
||||
if (procPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"body not available for this kind of constructor", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
|
||||
"METHODTYPE", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile if necessary.
|
||||
*/
|
||||
|
||||
if (procPtr->bodyPtr->typePtr != &tclByteCodeType) {
|
||||
Command cmd;
|
||||
|
||||
/*
|
||||
* Yes, this is ugly, but we need to pass the namespace in to the
|
||||
* compiler in two places.
|
||||
*/
|
||||
|
||||
cmd.nsPtr = (Namespace *) oPtr->namespacePtr;
|
||||
procPtr->cmdPtr = &cmd;
|
||||
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
|
||||
(Namespace *) oPtr->namespacePtr, "body of constructor",
|
||||
TclGetString(objv[2]));
|
||||
procPtr->cmdPtr = NULL;
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
codeObjPtr = procPtr->bodyPtr;
|
||||
break;
|
||||
|
||||
case DISAS_CLASS_DESTRUCTOR:
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "className");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the body of a destructor.
|
||||
*/
|
||||
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr->classPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" is not a class", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
|
||||
TclGetString(objv[2]), NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
methodPtr = oPtr->classPtr->destructorPtr;
|
||||
if (methodPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" has no defined destructor",
|
||||
TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
|
||||
"DESRUCTOR", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
procPtr = TclOOGetProcFromMethod(methodPtr);
|
||||
if (procPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"body not available for this kind of destructor", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
|
||||
"METHODTYPE", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile if necessary.
|
||||
*/
|
||||
|
||||
if (procPtr->bodyPtr->typePtr != &tclByteCodeType) {
|
||||
Command cmd;
|
||||
|
||||
/*
|
||||
* Yes, this is ugly, but we need to pass the namespace in to the
|
||||
* compiler in two places.
|
||||
*/
|
||||
|
||||
cmd.nsPtr = (Namespace *) oPtr->namespacePtr;
|
||||
procPtr->cmdPtr = &cmd;
|
||||
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
|
||||
(Namespace *) oPtr->namespacePtr, "body of destructor",
|
||||
TclGetString(objv[2]));
|
||||
procPtr->cmdPtr = NULL;
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
codeObjPtr = procPtr->bodyPtr;
|
||||
break;
|
||||
|
||||
case DISAS_CLASS_METHOD:
|
||||
if (objc != 4) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "className methodName");
|
||||
|
||||
+14
-12
@@ -305,7 +305,7 @@ Tcl_GetEncodingFromObj(
|
||||
Tcl_Obj *objPtr,
|
||||
Tcl_Encoding *encodingPtr)
|
||||
{
|
||||
const char *name = Tcl_GetString(objPtr);
|
||||
const char *name = TclGetString(objPtr);
|
||||
|
||||
if (objPtr->typePtr != &encodingType) {
|
||||
Tcl_Encoding encoding = Tcl_GetEncoding(interp, name);
|
||||
@@ -355,6 +355,7 @@ DupEncodingIntRep(
|
||||
Tcl_Obj *dupPtr)
|
||||
{
|
||||
dupPtr->internalRep.twoPtrValue.ptr1 = Tcl_GetEncoding(NULL, srcPtr->bytes);
|
||||
dupPtr->typePtr = &encodingType;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -704,7 +705,7 @@ Tcl_GetDefaultEncodingDir(void)
|
||||
}
|
||||
Tcl_ListObjIndex(NULL, searchPath, 0, &first);
|
||||
|
||||
return Tcl_GetString(first);
|
||||
return TclGetString(first);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -976,7 +977,7 @@ Tcl_GetEncodingNames(
|
||||
* Side effects:
|
||||
* The reference count of the new system encoding is incremented. The
|
||||
* reference count of the old system encoding is decremented and it may
|
||||
* be freed.
|
||||
* be freed. All VFS cached information is invalidated.
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1007,6 +1008,7 @@ Tcl_SetSystemEncoding(
|
||||
FreeEncoding(systemEncoding);
|
||||
systemEncoding = encoding;
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
Tcl_FSMountsChanged(NULL);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1517,10 +1519,10 @@ OpenEncodingFileChannel(
|
||||
}
|
||||
}
|
||||
if (!verified) {
|
||||
const char *dirString = Tcl_GetString(directory);
|
||||
const char *dirString = TclGetString(directory);
|
||||
|
||||
for (i=0; i<numDirs && !verified; i++) {
|
||||
if (strcmp(dirString, Tcl_GetString(dir[i])) == 0) {
|
||||
if (strcmp(dirString, TclGetString(dir[i])) == 0) {
|
||||
verified = 1;
|
||||
}
|
||||
}
|
||||
@@ -1761,7 +1763,7 @@ LoadTableEncoding(
|
||||
const char *p;
|
||||
|
||||
Tcl_ReadChars(chan, objPtr, 3 + 16 * (16 * 4 + 1), 0);
|
||||
p = Tcl_GetString(objPtr);
|
||||
p = TclGetString(objPtr);
|
||||
hi = (staticHex[UCHAR(p[0])] << 4) + staticHex[UCHAR(p[1])];
|
||||
dataPtr->toUnicode[hi] = pageMemPtr;
|
||||
p += 2;
|
||||
@@ -3598,11 +3600,11 @@ unilen(
|
||||
static void
|
||||
InitializeEncodingSearchPath(
|
||||
char **valuePtr,
|
||||
int *lengthPtr,
|
||||
size_t *lengthPtr,
|
||||
Tcl_Encoding *encodingPtr)
|
||||
{
|
||||
const char *bytes;
|
||||
int i, numDirs, numBytes;
|
||||
int i, numDirs;
|
||||
Tcl_Obj *libPathObj, *encodingObj, *searchPathObj;
|
||||
|
||||
TclNewLiteralStringObj(encodingObj, "encoding");
|
||||
@@ -3632,11 +3634,11 @@ InitializeEncodingSearchPath(
|
||||
if (*encodingPtr) {
|
||||
((Encoding *)(*encodingPtr))->refCount++;
|
||||
}
|
||||
bytes = Tcl_GetStringFromObj(searchPathObj, &numBytes);
|
||||
bytes = TclGetString(searchPathObj);
|
||||
|
||||
*lengthPtr = numBytes;
|
||||
*valuePtr = ckalloc(numBytes + 1);
|
||||
memcpy(*valuePtr, bytes, (size_t) numBytes + 1);
|
||||
*lengthPtr = searchPathObj->length;
|
||||
*valuePtr = ckalloc(*lengthPtr + 1);
|
||||
memcpy(*valuePtr, bytes, *lengthPtr + 1);
|
||||
Tcl_DecrRefCount(searchPathObj);
|
||||
}
|
||||
|
||||
|
||||
+255
-160
@@ -30,11 +30,10 @@ static int NsEnsembleStringOrder(const void *strPtr1,
|
||||
const void *strPtr2);
|
||||
static void DeleteEnsembleConfig(ClientData clientData);
|
||||
static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr,
|
||||
EnsembleConfig *ensemblePtr,
|
||||
const char *subcmdName, Tcl_Obj *prefixObjPtr);
|
||||
EnsembleConfig *ensemblePtr, Tcl_HashEntry *hPtr,
|
||||
Tcl_Obj *fix);
|
||||
static void FreeEnsembleCmdRep(Tcl_Obj *objPtr);
|
||||
static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
|
||||
static void StringOfEnsembleCmdRep(Tcl_Obj *objPtr);
|
||||
static void CompileToInvokedCommand(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Tcl_Obj *replacements,
|
||||
Command *cmdPtr, CompileEnv *envPtr);
|
||||
@@ -42,6 +41,8 @@ static int CompileBasicNArgCommand(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
CompileEnv *envPtr);
|
||||
|
||||
static Tcl_NRPostProc FreeER;
|
||||
|
||||
/*
|
||||
* The lists of subcommands and options for the [namespace ensemble] command.
|
||||
*/
|
||||
@@ -77,14 +78,30 @@ enum EnsConfigOpts {
|
||||
* that implements it.
|
||||
*/
|
||||
|
||||
const Tcl_ObjType tclEnsembleCmdType = {
|
||||
static const Tcl_ObjType ensembleCmdType = {
|
||||
"ensembleCommand", /* the type's name */
|
||||
FreeEnsembleCmdRep, /* freeIntRepProc */
|
||||
DupEnsembleCmdRep, /* dupIntRepProc */
|
||||
StringOfEnsembleCmdRep, /* updateStringProc */
|
||||
NULL, /* updateStringProc */
|
||||
NULL /* setFromAnyProc */
|
||||
};
|
||||
|
||||
/*
|
||||
* The internal rep for caching ensemble subcommand lookups and
|
||||
* spell corrections.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int epoch; /* Used to confirm when the data in this
|
||||
* really structure matches up with the
|
||||
* ensemble. */
|
||||
Command *token; /* Reference to the command for which this
|
||||
* structure is a cache of the resolution. */
|
||||
Tcl_Obj *fix; /* Corrected spelling, if needed. */
|
||||
Tcl_HashEntry *hPtr; /* Direct link to entry in the subcommand
|
||||
* hash table. */
|
||||
} EnsembleCmdRep;
|
||||
|
||||
|
||||
static inline Tcl_Obj *
|
||||
NewNsObj(
|
||||
@@ -1588,7 +1605,7 @@ TclMakeEnsemble(
|
||||
Tcl_DStringFree(&buf);
|
||||
Tcl_DStringFree(&hiddenBuf);
|
||||
if (nameParts != NULL) {
|
||||
ckfree((char *) nameParts);
|
||||
ckfree(nameParts);
|
||||
}
|
||||
return ensemble;
|
||||
}
|
||||
@@ -1643,6 +1660,8 @@ NsEnsembleImplementationCmdNR(
|
||||
* names. */
|
||||
int reparseCount = 0; /* Number of reparses. */
|
||||
Tcl_Obj *errorObj; /* Used for building error messages. */
|
||||
Tcl_Obj *subObj;
|
||||
int subIdx;
|
||||
|
||||
/*
|
||||
* Must recheck objc, since numParameters might have changed. Cf. test
|
||||
@@ -1650,24 +1669,18 @@ NsEnsembleImplementationCmdNR(
|
||||
*/
|
||||
|
||||
restartEnsembleParse:
|
||||
if (objc < 2 + ensemblePtr->numParameters) {
|
||||
subIdx = 1 + ensemblePtr->numParameters;
|
||||
if (objc < subIdx + 1) {
|
||||
/*
|
||||
* We don't have a subcommand argument. Make error message.
|
||||
*/
|
||||
|
||||
Tcl_DString buf; /* Message being built */
|
||||
Tcl_Obj **elemPtrs; /* Parameter names */
|
||||
int len; /* Number of parameters to append */
|
||||
|
||||
Tcl_DStringInit(&buf);
|
||||
if (ensemblePtr->parameterList == NULL) {
|
||||
len = 0;
|
||||
} else if (TclListObjGetElements(NULL, ensemblePtr->parameterList,
|
||||
&len, &elemPtrs) != TCL_OK) {
|
||||
Tcl_Panic("List of ensemble parameters is not a list");
|
||||
}
|
||||
for (; len>0; len--,elemPtrs++) {
|
||||
TclDStringAppendObj(&buf, *elemPtrs);
|
||||
if (ensemblePtr->parameterList) {
|
||||
Tcl_DStringAppend(&buf,
|
||||
TclGetString(ensemblePtr->parameterList), -1);
|
||||
TclDStringAppendLiteral(&buf, " ");
|
||||
}
|
||||
TclDStringAppendLiteral(&buf, "subcommand ?arg ...?");
|
||||
@@ -1695,6 +1708,8 @@ NsEnsembleImplementationCmdNR(
|
||||
* up in there and go straight to dispatch.
|
||||
*/
|
||||
|
||||
subObj = objv[subIdx];
|
||||
|
||||
if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) {
|
||||
/*
|
||||
* Table of subcommands is still valid; therefore there might be a
|
||||
@@ -1703,15 +1718,16 @@ NsEnsembleImplementationCmdNR(
|
||||
* part where we do the invocation of the subcommand.
|
||||
*/
|
||||
|
||||
if (objv[1+ensemblePtr->numParameters]->typePtr==&tclEnsembleCmdType){
|
||||
EnsembleCmdRep *ensembleCmd = objv[1+ensemblePtr->numParameters]
|
||||
->internalRep.twoPtrValue.ptr1;
|
||||
if (subObj->typePtr==&ensembleCmdType){
|
||||
EnsembleCmdRep *ensembleCmd = subObj->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
if (ensembleCmd->nsPtr == ensemblePtr->nsPtr &&
|
||||
ensembleCmd->epoch == ensemblePtr->epoch &&
|
||||
ensembleCmd->token == ensemblePtr->token) {
|
||||
prefixObj = ensembleCmd->realPrefixObj;
|
||||
if (ensembleCmd->epoch == ensemblePtr->epoch &&
|
||||
ensembleCmd->token == (Command *)ensemblePtr->token) {
|
||||
prefixObj = Tcl_GetHashValue(ensembleCmd->hPtr);
|
||||
Tcl_IncrRefCount(prefixObj);
|
||||
if (ensembleCmd->fix) {
|
||||
TclSpellFix(interp, objv, objc, subIdx, subObj, ensembleCmd->fix);
|
||||
}
|
||||
goto runResultingSubcommand;
|
||||
}
|
||||
}
|
||||
@@ -1726,18 +1742,14 @@ NsEnsembleImplementationCmdNR(
|
||||
*/
|
||||
|
||||
hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable,
|
||||
TclGetString(objv[1 + ensemblePtr->numParameters]));
|
||||
TclGetString(subObj));
|
||||
if (hPtr != NULL) {
|
||||
char *fullName = Tcl_GetHashKey(&ensemblePtr->subcommandTable, hPtr);
|
||||
|
||||
prefixObj = Tcl_GetHashValue(hPtr);
|
||||
|
||||
/*
|
||||
* Cache for later in the subcommand object.
|
||||
*/
|
||||
|
||||
MakeCachedEnsembleCommand(objv[1 + ensemblePtr->numParameters],
|
||||
ensemblePtr, fullName, prefixObj);
|
||||
MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, NULL);
|
||||
} else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) {
|
||||
/*
|
||||
* Could not map, no prefixing, go to unknown/error handling.
|
||||
@@ -1757,9 +1769,9 @@ NsEnsembleImplementationCmdNR(
|
||||
char *fullName = NULL; /* Full name of the subcommand. */
|
||||
int stringLength, i;
|
||||
int tableLength = ensemblePtr->subcommandTable.numEntries;
|
||||
Tcl_Obj *fix;
|
||||
|
||||
subcmdName = TclGetString(objv[1 + ensemblePtr->numParameters]);
|
||||
stringLength = objv[1 + ensemblePtr->numParameters]->length;
|
||||
subcmdName = TclGetStringFromObj(subObj, &stringLength);
|
||||
for (i=0 ; i<tableLength ; i++) {
|
||||
register int cmp = strncmp(subcmdName,
|
||||
ensemblePtr->subcommandArrayPtr[i],
|
||||
@@ -1799,16 +1811,22 @@ NsEnsembleImplementationCmdNR(
|
||||
Tcl_Panic("full name %s not found in supposedly synchronized hash",
|
||||
fullName);
|
||||
}
|
||||
prefixObj = Tcl_GetHashValue(hPtr);
|
||||
|
||||
/*
|
||||
* Record the spelling correction for usage message.
|
||||
*/
|
||||
|
||||
fix = Tcl_NewStringObj(fullName, -1);
|
||||
|
||||
/*
|
||||
* Cache for later in the subcommand object.
|
||||
*/
|
||||
|
||||
MakeCachedEnsembleCommand(objv[1 + ensemblePtr->numParameters],
|
||||
ensemblePtr, fullName, prefixObj);
|
||||
MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, fix);
|
||||
TclSpellFix(interp, objv, objc, subIdx, subObj, fix);
|
||||
}
|
||||
|
||||
prefixObj = Tcl_GetHashValue(hPtr);
|
||||
Tcl_IncrRefCount(prefixObj);
|
||||
runResultingSubcommand:
|
||||
|
||||
@@ -1827,47 +1845,26 @@ NsEnsembleImplementationCmdNR(
|
||||
*/
|
||||
|
||||
{
|
||||
Tcl_Obj **prefixObjv; /* The list of objects to substitute in as the
|
||||
* target command prefix. */
|
||||
Tcl_Obj *copyPtr; /* The actual list of words to dispatch to.
|
||||
* Will be freed by the dispatch engine. */
|
||||
int prefixObjc, copyObjc;
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Obj **copyObjv;
|
||||
int copyObjc, prefixObjc;
|
||||
|
||||
/*
|
||||
* Get the prefix that we're rewriting to. To do this we need to
|
||||
* ensure that the internal representation of the list does not change
|
||||
* so that we can safely keep the internal representations of the
|
||||
* elements in the list.
|
||||
*
|
||||
* TODO: Use conventional list operations to make this code sane!
|
||||
*/
|
||||
Tcl_ListObjLength(NULL, prefixObj, &prefixObjc);
|
||||
|
||||
TclListObjGetElements(NULL, prefixObj, &prefixObjc, &prefixObjv);
|
||||
|
||||
copyObjc = objc - 2 + prefixObjc;
|
||||
copyPtr = Tcl_NewListObj(copyObjc, NULL);
|
||||
if (copyObjc > 0) {
|
||||
register Tcl_Obj **copyObjv;
|
||||
/* Space used to construct the list of
|
||||
* arguments to pass to the command that
|
||||
* implements the ensemble subcommand. */
|
||||
register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1;
|
||||
register int i;
|
||||
|
||||
listRepPtr->elemCount = copyObjc;
|
||||
copyObjv = &listRepPtr->elements;
|
||||
memcpy(copyObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc);
|
||||
memcpy(copyObjv+prefixObjc, objv+1,
|
||||
sizeof(Tcl_Obj *) * ensemblePtr->numParameters);
|
||||
memcpy(copyObjv+prefixObjc+ensemblePtr->numParameters,
|
||||
objv+ensemblePtr->numParameters+2,
|
||||
sizeof(Tcl_Obj *) * (objc-ensemblePtr->numParameters-2));
|
||||
|
||||
for (i=0; i < copyObjc; i++) {
|
||||
Tcl_IncrRefCount(copyObjv[i]);
|
||||
}
|
||||
if (objc == 2) {
|
||||
copyPtr = TclListObjCopy(NULL, prefixObj);
|
||||
} else {
|
||||
copyPtr = Tcl_NewListObj(objc - 2 + prefixObjc, NULL);
|
||||
Tcl_ListObjAppendList(NULL, copyPtr, prefixObj);
|
||||
Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
|
||||
ensemblePtr->numParameters, objv + 1);
|
||||
Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
|
||||
objc - 2 - ensemblePtr->numParameters,
|
||||
objv + 2 + ensemblePtr->numParameters);
|
||||
}
|
||||
Tcl_IncrRefCount(copyPtr);
|
||||
TclNRAddCallback(interp, TclNRReleaseValues, copyPtr, NULL, NULL, NULL);
|
||||
TclDecrRefCount(prefixObj);
|
||||
|
||||
/*
|
||||
@@ -1876,25 +1873,10 @@ NsEnsembleImplementationCmdNR(
|
||||
* count both as inserted and removed arguments.
|
||||
*/
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs =
|
||||
2 + ensemblePtr->numParameters;
|
||||
iPtr->ensembleRewrite.numInsertedObjs =
|
||||
prefixObjc + ensemblePtr->numParameters;
|
||||
if (TclInitRewriteEnsemble(interp, 2 + ensemblePtr->numParameters,
|
||||
prefixObjc + ensemblePtr->numParameters, objv)) {
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL,
|
||||
NULL);
|
||||
} else {
|
||||
register int ni = 2 + ensemblePtr->numParameters
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
/* Position in objv of new front of insertion
|
||||
* relative to old one. */
|
||||
if (ni > 0) {
|
||||
iPtr->ensembleRewrite.numRemovedObjs += ni;
|
||||
iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-1;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1902,7 +1884,8 @@ NsEnsembleImplementationCmdNR(
|
||||
*/
|
||||
|
||||
TclSkipTailcall(interp);
|
||||
return TclNREvalObjEx(interp, copyPtr, TCL_EVAL_INVOKE, NULL,INT_MIN);
|
||||
Tcl_ListObjGetElements(NULL, copyPtr, ©Objc, ©Objv);
|
||||
return TclNREvalObjv(interp, copyObjc, copyObjv, TCL_EVAL_INVOKE, NULL);
|
||||
}
|
||||
|
||||
unknownOrAmbiguousSubcommand:
|
||||
@@ -1934,20 +1917,17 @@ NsEnsembleImplementationCmdNR(
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
|
||||
TclGetString(objv[1+ensemblePtr->numParameters]), NULL);
|
||||
TclGetString(subObj), NULL);
|
||||
if (ensemblePtr->subcommandTable.numEntries == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"unknown subcommand \"%s\": namespace %s does not"
|
||||
" export any commands",
|
||||
TclGetString(objv[1+ensemblePtr->numParameters]),
|
||||
" export any commands", TclGetString(subObj),
|
||||
ensemblePtr->nsPtr->fullName));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
|
||||
TclGetString(objv[1+ensemblePtr->numParameters]), NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
errorObj = Tcl_ObjPrintf("unknown%s subcommand \"%s\": must be ",
|
||||
(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX ? " or ambiguous" : ""),
|
||||
TclGetString(objv[1+ensemblePtr->numParameters]));
|
||||
TclGetString(subObj));
|
||||
if (ensemblePtr->subcommandTable.numEntries == 1) {
|
||||
Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[0], -1);
|
||||
} else {
|
||||
@@ -2013,7 +1993,7 @@ TclInitRewriteEnsemble(
|
||||
|
||||
if (numIns < numRemoved) {
|
||||
iPtr->ensembleRewrite.numRemovedObjs += numRemoved - numIns;
|
||||
iPtr->ensembleRewrite.numInsertedObjs += numInserted - 1;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = numInserted;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs += numInserted - numRemoved;
|
||||
}
|
||||
@@ -2053,6 +2033,149 @@ TclResetRewriteEnsemble(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclSpellFix --
|
||||
*
|
||||
* Record a spelling correction that needs making in the
|
||||
* generation of the WrongNumArgs usage message.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Can create an alternative ensemble rewrite structure.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
FreeER(
|
||||
ClientData data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
Tcl_Obj **tmp = (Tcl_Obj **)data[0];
|
||||
|
||||
ckfree(tmp[2]);
|
||||
ckfree(tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
TclSpellFix(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *const *objv,
|
||||
int objc,
|
||||
int badIdx,
|
||||
Tcl_Obj *bad,
|
||||
Tcl_Obj *fix)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Obj *const *search;
|
||||
Tcl_Obj **store;
|
||||
int idx;
|
||||
int size;
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = 0;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 0;
|
||||
}
|
||||
|
||||
/* Compute the valid length of the ensemble root */
|
||||
|
||||
size = iPtr->ensembleRewrite.numRemovedObjs + objc
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
|
||||
search = iPtr->ensembleRewrite.sourceObjs;
|
||||
if (search[0] == NULL) {
|
||||
/* Awful casting abuse here */
|
||||
search = (Tcl_Obj *const *) search[1];
|
||||
}
|
||||
|
||||
if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) {
|
||||
/*
|
||||
* Misspelled value was inserted. We cannot directly jump
|
||||
* to the bad value, but have to search.
|
||||
*/
|
||||
idx = 1;
|
||||
while (idx < size) {
|
||||
if (search[idx] == bad) {
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if (idx == size) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* Jump to the misspelled value. */
|
||||
idx = iPtr->ensembleRewrite.numRemovedObjs + badIdx
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
|
||||
/* Verify */
|
||||
if (search[idx] != bad) {
|
||||
Tcl_Panic("SpellFix: programming error");
|
||||
}
|
||||
}
|
||||
|
||||
search = iPtr->ensembleRewrite.sourceObjs;
|
||||
if (search[0] == NULL) {
|
||||
store = (Tcl_Obj **)search[2];
|
||||
} else {
|
||||
Tcl_Obj **tmp = ckalloc(3 * sizeof(Tcl_Obj *));
|
||||
tmp[0] = NULL;
|
||||
tmp[1] = (Tcl_Obj *)iPtr->ensembleRewrite.sourceObjs;
|
||||
tmp[2] = (Tcl_Obj *)ckalloc(size * sizeof(Tcl_Obj *));
|
||||
memcpy(tmp[2], tmp[1], size*sizeof(Tcl_Obj *));
|
||||
|
||||
iPtr->ensembleRewrite.sourceObjs = (Tcl_Obj *const *) tmp;
|
||||
TclNRAddCallback(interp, FreeER, tmp, NULL, NULL, NULL);
|
||||
store = (Tcl_Obj **)tmp[2];
|
||||
}
|
||||
|
||||
store[idx] = fix;
|
||||
Tcl_IncrRefCount(fix);
|
||||
TclNRAddCallback(interp, TclNRReleaseValues, fix, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclFetchEnsembleRoot --
|
||||
*
|
||||
* Returns the root of ensemble rewriting, if any.
|
||||
* If no root exists, returns objv instead.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *const *
|
||||
TclFetchEnsembleRoot(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *const *objv,
|
||||
int objc,
|
||||
int *objcPtr)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs) {
|
||||
*objcPtr = objc + iPtr->ensembleRewrite.numRemovedObjs
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
return iPtr->ensembleRewrite.sourceObjs;
|
||||
}
|
||||
*objcPtr = objc;
|
||||
return objv;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -2218,17 +2341,17 @@ static void
|
||||
MakeCachedEnsembleCommand(
|
||||
Tcl_Obj *objPtr,
|
||||
EnsembleConfig *ensemblePtr,
|
||||
const char *subcommandName,
|
||||
Tcl_Obj *prefixObjPtr)
|
||||
Tcl_HashEntry *hPtr,
|
||||
Tcl_Obj *fix)
|
||||
{
|
||||
register EnsembleCmdRep *ensembleCmd;
|
||||
int length;
|
||||
|
||||
if (objPtr->typePtr == &tclEnsembleCmdType) {
|
||||
if (objPtr->typePtr == &ensembleCmdType) {
|
||||
ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
|
||||
TclNsDecrRefCount(ensembleCmd->nsPtr);
|
||||
ckfree(ensembleCmd->fullSubcmdName);
|
||||
TclCleanupCommandMacro(ensembleCmd->token);
|
||||
if (ensembleCmd->fix) {
|
||||
Tcl_DecrRefCount(ensembleCmd->fix);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Kill the old internal rep, and replace it with a brand new one of
|
||||
@@ -2238,22 +2361,21 @@ MakeCachedEnsembleCommand(
|
||||
TclFreeIntRep(objPtr);
|
||||
ensembleCmd = ckalloc(sizeof(EnsembleCmdRep));
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = ensembleCmd;
|
||||
objPtr->typePtr = &tclEnsembleCmdType;
|
||||
objPtr->typePtr = &ensembleCmdType;
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate the internal rep.
|
||||
*/
|
||||
|
||||
ensembleCmd->nsPtr = ensemblePtr->nsPtr;
|
||||
ensembleCmd->epoch = ensemblePtr->epoch;
|
||||
ensembleCmd->token = ensemblePtr->token;
|
||||
ensemblePtr->nsPtr->refCount++;
|
||||
ensembleCmd->realPrefixObj = prefixObjPtr;
|
||||
length = strlen(subcommandName)+1;
|
||||
ensembleCmd->fullSubcmdName = ckalloc(length);
|
||||
memcpy(ensembleCmd->fullSubcmdName, subcommandName, (unsigned) length);
|
||||
Tcl_IncrRefCount(ensembleCmd->realPrefixObj);
|
||||
ensembleCmd->token = (Command *) ensemblePtr->token;
|
||||
ensembleCmd->token->refCount++;
|
||||
if (fix) {
|
||||
Tcl_IncrRefCount(fix);
|
||||
}
|
||||
ensembleCmd->fix = fix;
|
||||
ensembleCmd->hPtr = hPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2634,9 +2756,10 @@ FreeEnsembleCmdRep(
|
||||
{
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
|
||||
ckfree(ensembleCmd->fullSubcmdName);
|
||||
TclNsDecrRefCount(ensembleCmd->nsPtr);
|
||||
TclCleanupCommandMacro(ensembleCmd->token);
|
||||
if (ensembleCmd->fix) {
|
||||
Tcl_DecrRefCount(ensembleCmd->fix);
|
||||
}
|
||||
ckfree(ensembleCmd);
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
@@ -2666,48 +2789,17 @@ DupEnsembleCmdRep(
|
||||
{
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
EnsembleCmdRep *ensembleCopy = ckalloc(sizeof(EnsembleCmdRep));
|
||||
int length = strlen(ensembleCmd->fullSubcmdName);
|
||||
|
||||
copyPtr->typePtr = &tclEnsembleCmdType;
|
||||
copyPtr->typePtr = &ensembleCmdType;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = ensembleCopy;
|
||||
ensembleCopy->nsPtr = ensembleCmd->nsPtr;
|
||||
ensembleCopy->epoch = ensembleCmd->epoch;
|
||||
ensembleCopy->token = ensembleCmd->token;
|
||||
ensembleCopy->nsPtr->refCount++;
|
||||
ensembleCopy->realPrefixObj = ensembleCmd->realPrefixObj;
|
||||
Tcl_IncrRefCount(ensembleCopy->realPrefixObj);
|
||||
ensembleCopy->fullSubcmdName = ckalloc(length + 1);
|
||||
memcpy(ensembleCopy->fullSubcmdName, ensembleCmd->fullSubcmdName,
|
||||
(unsigned) length+1);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* StringOfEnsembleCmdRep --
|
||||
*
|
||||
* Creates a string representation of a Tcl_Obj that holds a subcommand
|
||||
* of an ensemble.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The object gains a string (UTF-8) representation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
StringOfEnsembleCmdRep(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
int length = strlen(ensembleCmd->fullSubcmdName);
|
||||
|
||||
objPtr->length = length;
|
||||
objPtr->bytes = ckalloc(length + 1);
|
||||
memcpy(objPtr->bytes, ensembleCmd->fullSubcmdName, (unsigned) length+1);
|
||||
ensembleCopy->token->refCount++;
|
||||
ensembleCopy->fix = ensembleCmd->fix;
|
||||
if (ensembleCopy->fix) {
|
||||
Tcl_IncrRefCount(ensembleCopy->fix);
|
||||
}
|
||||
ensembleCopy->hPtr = ensembleCmd->hPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2825,7 +2917,7 @@ TclCompileEnsemble(
|
||||
goto failed;
|
||||
}
|
||||
for (i=0 ; i<len ; i++) {
|
||||
str = Tcl_GetStringFromObj(elems[i], &sclen);
|
||||
str = TclGetStringFromObj(elems[i], &sclen);
|
||||
if ((sclen == (int) numBytes) && !memcmp(word, str, numBytes)) {
|
||||
/*
|
||||
* Exact match! Excellent!
|
||||
@@ -3043,7 +3135,7 @@ TclCompileEnsemble(
|
||||
* any extra elements that might have been appended by failing
|
||||
* pathways above.
|
||||
*/
|
||||
(void) Tcl_ListObjReplace(NULL, replaced, depth-1, INT_MAX, 0, NULL);
|
||||
(void) Tcl_ListObjReplace(NULL, replaced, depth-1, LIST_MAX, 0, NULL);
|
||||
|
||||
/*
|
||||
* TODO: Reconsider whether we ought to call CompileToInvokedCommand()
|
||||
@@ -3214,7 +3306,7 @@ CompileToInvokedCommand(
|
||||
Tcl_Token *tokPtr;
|
||||
Tcl_Obj *objPtr, **words;
|
||||
char *bytes;
|
||||
int length, i, numWords, cmdLit;
|
||||
int length, i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
|
||||
DefineLineInformation;
|
||||
|
||||
/*
|
||||
@@ -3227,15 +3319,15 @@ CompileToInvokedCommand(
|
||||
for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;
|
||||
i++, tokPtr = TokenAfter(tokPtr)) {
|
||||
if (i > 0 && i < numWords+1) {
|
||||
bytes = Tcl_GetStringFromObj(words[i-1], &length);
|
||||
bytes = TclGetStringFromObj(words[i-1], &length);
|
||||
PushLiteral(envPtr, bytes, length);
|
||||
continue;
|
||||
}
|
||||
|
||||
SetLineInformation(i);
|
||||
if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) {
|
||||
int literal = TclRegisterNewLiteral(envPtr,
|
||||
tokPtr[1].start, tokPtr[1].size);
|
||||
int literal = TclRegisterLiteral(envPtr,
|
||||
tokPtr[1].start, tokPtr[1].size, 0);
|
||||
|
||||
if (envPtr->clNext) {
|
||||
TclContinuationsEnterDerived(
|
||||
@@ -3257,7 +3349,10 @@ CompileToInvokedCommand(
|
||||
objPtr = Tcl_NewObj();
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
cmdLit = TclRegisterNewCmdLiteral(envPtr, bytes, length);
|
||||
if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
|
||||
extraLiteralFlags |= LITERAL_UNSHARED;
|
||||
}
|
||||
cmdLit = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags);
|
||||
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);
|
||||
TclEmitPush(cmdLit, envPtr);
|
||||
TclDecrRefCount(objPtr);
|
||||
|
||||
@@ -1465,6 +1465,8 @@ VwaitVarProc(
|
||||
int *donePtr = clientData;
|
||||
|
||||
*donePtr = 1;
|
||||
Tcl_UntraceVar(interp, name1, TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||||
VwaitVarProc, clientData);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+212
-332
@@ -19,7 +19,6 @@
|
||||
#include "tclCompile.h"
|
||||
#include "tclOOInt.h"
|
||||
#include "tommath.h"
|
||||
#include "tclStringRep.h"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -767,6 +766,7 @@ static void IllegalExprOperandType(Tcl_Interp *interp,
|
||||
static void InitByteCodeExecution(Tcl_Interp *interp);
|
||||
static inline int wordSkip(void *ptr);
|
||||
static void ReleaseDictIterator(Tcl_Obj *objPtr);
|
||||
static void ReleaseArrayIterator(Tcl_Obj *objPtr);
|
||||
/* Useful elsewhere, make available in tclInt.h or stubs? */
|
||||
static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords);
|
||||
static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords);
|
||||
@@ -799,6 +799,11 @@ static const Tcl_ObjType dictIteratorType = {
|
||||
ReleaseDictIterator,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
static const Tcl_ObjType arrayIteratorType = {
|
||||
"arrayIterator",
|
||||
ReleaseArrayIterator,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -838,6 +843,45 @@ ReleaseDictIterator(
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* ReleaseArrayIterator --
|
||||
*
|
||||
* This takes apart an array iterator that is stored in the given Tcl
|
||||
* object.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Deallocates memory, marks the object as being untyped.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
ReleaseArrayIterator(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
Tcl_ArraySearch *searchPtr;
|
||||
Tcl_Obj *arrayPtr;
|
||||
|
||||
/*
|
||||
* First kill the search, and then release the reference to the dictionary
|
||||
* that we were holding.
|
||||
*/
|
||||
|
||||
searchPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
ckfree(searchPtr);
|
||||
|
||||
arrayPtr = objPtr->internalRep.twoPtrValue.ptr2;
|
||||
TclDecrRefCount(arrayPtr);
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -1275,7 +1319,7 @@ TclStackFree(
|
||||
Tcl_Obj **markerPtr, *marker;
|
||||
|
||||
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
|
||||
ckfree((char *) freePtr);
|
||||
ckfree(freePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1499,11 +1543,9 @@ ExprObjCallback(
|
||||
*
|
||||
* Results:
|
||||
* A (ByteCode *) is returned pointing to the resulting ByteCode.
|
||||
* The caller must manage its refCount and arrange for a call to
|
||||
* TclCleanupByteCode() when the last reference disappears.
|
||||
*
|
||||
* Side effects:
|
||||
* The Tcl_ObjType of objPtr is changed to the "bytecode" type,
|
||||
* The Tcl_ObjType of objPtr is changed to the "exprcode" type,
|
||||
* and the ByteCode is kept in the internal rep (along with context
|
||||
* data for checking validity) for faster operations the next time
|
||||
* CompileExprObj is called on the same value.
|
||||
@@ -1536,7 +1578,7 @@ CompileExprObj(
|
||||
|| (codePtr->nsPtr != namespacePtr)
|
||||
|| (codePtr->nsEpoch != namespacePtr->resolverEpoch)
|
||||
|| (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)) {
|
||||
FreeExprCodeInternalRep(objPtr);
|
||||
TclFreeIntRep(objPtr);
|
||||
}
|
||||
}
|
||||
if (objPtr->typePtr != &exprCodeType) {
|
||||
@@ -1556,7 +1598,7 @@ CompileExprObj(
|
||||
*/
|
||||
|
||||
if (compEnv.codeNext == compEnv.codeStart) {
|
||||
TclEmitPush(TclRegisterNewLiteral(&compEnv, "0", 1),
|
||||
TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, 0),
|
||||
&compEnv);
|
||||
}
|
||||
|
||||
@@ -1567,10 +1609,8 @@ CompileExprObj(
|
||||
*/
|
||||
|
||||
TclEmitOpcode(INST_DONE, &compEnv);
|
||||
TclInitByteCodeObj(objPtr, &compEnv);
|
||||
objPtr->typePtr = &exprCodeType;
|
||||
codePtr = TclInitByteCodeObj(objPtr, &exprCodeType, &compEnv);
|
||||
TclFreeCompileEnv(&compEnv);
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (iPtr->varFramePtr->localCachePtr) {
|
||||
codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
|
||||
codePtr->localCachePtr->refCount++;
|
||||
@@ -1644,10 +1684,7 @@ FreeExprCodeInternalRep(
|
||||
{
|
||||
ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
if (codePtr->refCount-- <= 1) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
}
|
||||
TclReleaseByteCode(codePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2033,7 +2070,7 @@ TclNRExecuteByteCode(
|
||||
* sizeof(void *);
|
||||
int numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *);
|
||||
|
||||
codePtr->refCount++;
|
||||
TclPreserveByteCode(codePtr);
|
||||
|
||||
/*
|
||||
* Reserve the stack, setup the TEBCdataPtr (TD) and CallFrame
|
||||
@@ -2077,6 +2114,13 @@ TclNRExecuteByteCode(
|
||||
iPtr->stats.numExecutions++;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Test namespace-50.9 demonstrates the need for this call.
|
||||
* Use a --enable-symbols=mem bug to see.
|
||||
*/
|
||||
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
|
||||
/*
|
||||
* Push the callback for bytecode execution
|
||||
*/
|
||||
@@ -2115,9 +2159,14 @@ TEBCresume(
|
||||
* sporadically: no special need for speed.
|
||||
*/
|
||||
|
||||
int instructionCount = ASYNC_CHECK_COUNT;
|
||||
unsigned interruptCounter = 1;
|
||||
/* Counter that is used to work out when to
|
||||
* call Tcl_AsyncReady() */
|
||||
* call Tcl_AsyncReady(). This must be 1
|
||||
* initially so that we call the async-check
|
||||
* stanza early, otherwise there are command
|
||||
* sequences that can make the interpreter
|
||||
* busy-loop without an opportunity to
|
||||
* recognise an interrupt. */
|
||||
const char *curInstName;
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
int traceInstructions; /* Whether we are doing instruction-level
|
||||
@@ -2318,8 +2367,8 @@ TEBCresume(
|
||||
* ASYNC_CHECK_COUNT instructions.
|
||||
*/
|
||||
|
||||
if (!(--instructionCount)) {
|
||||
instructionCount = ASYNC_CHECK_COUNT;
|
||||
if ((--interruptCounter) == 0) {
|
||||
interruptCounter = ASYNC_CHECK_COUNT;
|
||||
DECACHE_STACK_INFO();
|
||||
if (TclAsyncReady(iPtr)) {
|
||||
result = Tcl_AsyncInvoke(interp, result);
|
||||
@@ -2533,7 +2582,7 @@ TEBCresume(
|
||||
/* FIXME: What is the right thing to trace? */
|
||||
fprintf(stdout, "%d: (%u) yielding to [%.30s]\n",
|
||||
iPtr->numLevels, (unsigned)(pc - codePtr->codeStart),
|
||||
Tcl_GetString(valuePtr));
|
||||
TclGetString(valuePtr));
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -2680,154 +2729,18 @@ TEBCresume(
|
||||
NEXT_INST_F(5, 0, 0);
|
||||
}
|
||||
|
||||
case INST_STR_CONCAT1: {
|
||||
int appendLen = 0;
|
||||
char *bytes, *p;
|
||||
Tcl_Obj **currPtr;
|
||||
int onlyb = 1;
|
||||
case INST_STR_CONCAT1:
|
||||
|
||||
opnd = TclGetUInt1AtPtr(pc+1);
|
||||
|
||||
/*
|
||||
* Detect only-bytearray-or-null case.
|
||||
*/
|
||||
|
||||
for (currPtr=&OBJ_AT_DEPTH(opnd-1); currPtr<=&OBJ_AT_TOS; currPtr++) {
|
||||
if (((*currPtr)->typePtr != &tclByteArrayType)
|
||||
&& ((*currPtr)->bytes != tclEmptyStringRep)) {
|
||||
onlyb = 0;
|
||||
break;
|
||||
} else if (((*currPtr)->typePtr == &tclByteArrayType) &&
|
||||
((*currPtr)->bytes != NULL)) {
|
||||
onlyb = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the length to be appended.
|
||||
*/
|
||||
|
||||
if (onlyb) {
|
||||
for (currPtr = &OBJ_AT_DEPTH(opnd-2);
|
||||
appendLen >= 0 && currPtr <= &OBJ_AT_TOS; currPtr++) {
|
||||
if ((*currPtr)->bytes != tclEmptyStringRep) {
|
||||
Tcl_GetByteArrayFromObj(*currPtr, &length);
|
||||
appendLen += length;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (currPtr = &OBJ_AT_DEPTH(opnd-2);
|
||||
appendLen >= 0 && currPtr <= &OBJ_AT_TOS; currPtr++) {
|
||||
bytes = TclGetStringFromObj(*currPtr, &length);
|
||||
if (bytes != NULL) {
|
||||
appendLen += length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appendLen < 0) {
|
||||
/* TODO: convert panic to error ? */
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
* If nothing is to be appended, just return the first object by
|
||||
* dropping all the others from the stack; this saves both the
|
||||
* computation and copy of the string rep of the first object,
|
||||
* enabling the fast '$x[set x {}]' idiom for 'K $x [set x {}]'.
|
||||
*/
|
||||
|
||||
if (appendLen == 0) {
|
||||
TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
|
||||
NEXT_INST_V(2, (opnd-1), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the first object is shared, we need a new obj for the result;
|
||||
* otherwise, we can reuse the first object. In any case, make sure it
|
||||
* has enough room to accomodate all the concatenated bytes. Note that
|
||||
* if it is unshared its bytes are copied by ckrealloc, so that we set
|
||||
* the loop parameters to avoid copying them again: p points to the
|
||||
* end of the already copied bytes, currPtr to the second object.
|
||||
*/
|
||||
|
||||
objResultPtr = OBJ_AT_DEPTH(opnd-1);
|
||||
if (!onlyb) {
|
||||
bytes = TclGetStringFromObj(objResultPtr, &length);
|
||||
if (length + appendLen < 0) {
|
||||
/* TODO: convert panic to error ? */
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
|
||||
INT_MAX);
|
||||
}
|
||||
#ifndef TCL_COMPILE_DEBUG
|
||||
if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) {
|
||||
TclFreeIntRep(objResultPtr);
|
||||
objResultPtr->bytes = ckrealloc(bytes, length+appendLen+1);
|
||||
objResultPtr->length = length + appendLen;
|
||||
p = TclGetString(objResultPtr) + length;
|
||||
currPtr = &OBJ_AT_DEPTH(opnd - 2);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
p = ckalloc(length + appendLen + 1);
|
||||
TclNewObj(objResultPtr);
|
||||
objResultPtr->bytes = p;
|
||||
objResultPtr->length = length + appendLen;
|
||||
currPtr = &OBJ_AT_DEPTH(opnd - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append the remaining characters.
|
||||
*/
|
||||
|
||||
for (; currPtr <= &OBJ_AT_TOS; currPtr++) {
|
||||
bytes = TclGetStringFromObj(*currPtr, &length);
|
||||
if (bytes != NULL) {
|
||||
memcpy(p, bytes, (size_t) length);
|
||||
p += length;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
} else {
|
||||
bytes = (char *) Tcl_GetByteArrayFromObj(objResultPtr, &length);
|
||||
if (length + appendLen < 0) {
|
||||
/* TODO: convert panic to error ? */
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
|
||||
INT_MAX);
|
||||
}
|
||||
#ifndef TCL_COMPILE_DEBUG
|
||||
if (!Tcl_IsShared(objResultPtr)) {
|
||||
bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,
|
||||
length + appendLen);
|
||||
p = bytes + length;
|
||||
currPtr = &OBJ_AT_DEPTH(opnd - 2);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
TclNewObj(objResultPtr);
|
||||
bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,
|
||||
length + appendLen);
|
||||
p = bytes;
|
||||
currPtr = &OBJ_AT_DEPTH(opnd - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append the remaining characters.
|
||||
*/
|
||||
|
||||
for (; currPtr <= &OBJ_AT_TOS; currPtr++) {
|
||||
if ((*currPtr)->bytes != tclEmptyStringRep) {
|
||||
bytes = (char *) Tcl_GetByteArrayFromObj(*currPtr,&length);
|
||||
memcpy(p, bytes, (size_t) length);
|
||||
p += length;
|
||||
}
|
||||
}
|
||||
if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1,
|
||||
opnd, &OBJ_AT_DEPTH(opnd-1), &objResultPtr)) {
|
||||
TRACE_ERROR(interp);
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
|
||||
NEXT_INST_V(2, opnd, 1);
|
||||
}
|
||||
|
||||
case INST_CONCAT_STK:
|
||||
/*
|
||||
@@ -3155,35 +3068,34 @@ TEBCresume(
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif /*TCL_COMPILE_DEBUG*/
|
||||
{
|
||||
Tcl_Obj *copyPtr = Tcl_NewListObj(objc - opnd + 1, NULL);
|
||||
register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1;
|
||||
Tcl_Obj **copyObjv = &listRepPtr->elements;
|
||||
int i;
|
||||
|
||||
listRepPtr->elemCount = objc - opnd + 1;
|
||||
copyObjv[0] = objPtr;
|
||||
memcpy(copyObjv+1, objv+opnd, sizeof(Tcl_Obj *) * (objc - opnd));
|
||||
for (i=1 ; i<objc-opnd+1 ; i++) {
|
||||
Tcl_IncrRefCount(copyObjv[i]);
|
||||
}
|
||||
objPtr = copyPtr;
|
||||
}
|
||||
bcFramePtr->data.tebc.pc = (char *) pc;
|
||||
iPtr->cmdFramePtr = bcFramePtr;
|
||||
if (iPtr->flags & INTERP_DEBUG_FRAME) {
|
||||
ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv);
|
||||
}
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = opnd;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 1;
|
||||
|
||||
TclInitRewriteEnsemble(interp, opnd, 1, objv);
|
||||
|
||||
{
|
||||
Tcl_Obj *copyPtr = Tcl_NewListObj(objc - opnd + 1, NULL);
|
||||
|
||||
Tcl_ListObjAppendElement(NULL, copyPtr, objPtr);
|
||||
Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
|
||||
objc - opnd, objv + opnd);
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
objPtr = copyPtr;
|
||||
}
|
||||
|
||||
DECACHE_STACK_INFO();
|
||||
pc += 6;
|
||||
TEBC_YIELD();
|
||||
|
||||
TclMarkTailcall(interp);
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL);
|
||||
return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE, NULL, INT_MIN);
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv);
|
||||
TclNRAddCallback(interp, TclNRReleaseValues, objPtr, NULL, NULL, NULL);
|
||||
return TclNREvalObjv(interp, objc, objv, TCL_EVAL_INVOKE, NULL);
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------
|
||||
@@ -4313,6 +4225,60 @@ TEBCresume(
|
||||
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
|
||||
NEXT_INST_V(pcAdjustment, cleanup, 1);
|
||||
|
||||
{
|
||||
int done;
|
||||
Tcl_Obj *arrayObj, *statePtr, *keyPtr, *valuePtr;
|
||||
Tcl_Obj *emptyPtr;
|
||||
Tcl_ArraySearch *searchPtr;
|
||||
|
||||
case INST_ARRAY_FIRST:
|
||||
pcAdjustment = 1;
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
TRACE(("%u => ", opnd));
|
||||
arrayObj = POP_OBJECT();
|
||||
searchPtr = ckalloc(sizeof(Tcl_ArraySearch));
|
||||
Tcl_ArrayObjFirst(interp, arrayObj, searchPtr);
|
||||
TclNewObj(statePtr);
|
||||
statePtr->typePtr = &arrayIteratorType;
|
||||
statePtr->internalRep.twoPtrValue.ptr1 = searchPtr;
|
||||
statePtr->internalRep.twoPtrValue.ptr2 = arrayObj;
|
||||
varPtr = LOCAL(opnd);
|
||||
if (varPtr->value.objPtr) {
|
||||
if (varPtr->value.objPtr->typePtr == &arrayIteratorType) {
|
||||
Tcl_Panic("mis-issued arrayFirst!");
|
||||
}
|
||||
TclDecrRefCount(varPtr->value.objPtr);
|
||||
}
|
||||
varPtr->value.objPtr = statePtr;
|
||||
Tcl_IncrRefCount(statePtr);
|
||||
NEXT_INST_F(1, 0, 0); /*### ??? */
|
||||
|
||||
case INST_ARRAY_NEXT:
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
TRACE(("%u => ", opnd));
|
||||
statePtr = (*LOCAL(opnd)).value.objPtr;
|
||||
if (statePtr == NULL || statePtr->typePtr != &arrayIteratorType) {
|
||||
Tcl_Panic("mis-issued dictNext!");
|
||||
}
|
||||
searchPtr = statePtr->internalRep.twoPtrValue.ptr1;
|
||||
done = Tcl_ArrayObjNext(interp, searchPtr, &keyPtr, &valuePtr);
|
||||
if (done) {
|
||||
TclNewObj(emptyPtr);
|
||||
PUSH_OBJECT(emptyPtr);
|
||||
PUSH_OBJECT(emptyPtr);
|
||||
} else {
|
||||
if (valuePtr != NULL) {
|
||||
PUSH_OBJECT(valuePtr);
|
||||
} else {
|
||||
PUSH_OBJECT(emptyPtr);
|
||||
}
|
||||
PUSH_OBJECT(keyPtr);
|
||||
}
|
||||
TRACE_APPEND(("\"%.30s\" \"%.30s\" %d\n",
|
||||
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done));
|
||||
JUMP_PEEPHOLE_F(done, 5, 0); /* ### ??? */
|
||||
}
|
||||
|
||||
case INST_ARRAY_MAKE_IMM:
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
pcAdjustment = 5;
|
||||
@@ -4416,8 +4382,8 @@ TEBCresume(
|
||||
savedNsPtr = iPtr->varFramePtr->nsPtr;
|
||||
iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr;
|
||||
otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL,
|
||||
(TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
|
||||
/*createPart1*/ 1, /*createPart2*/ 1, &varPtr);
|
||||
(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
|
||||
"access", /*createPart1*/ 1, /*createPart2*/ 1, &varPtr);
|
||||
iPtr->varFramePtr->nsPtr = savedNsPtr;
|
||||
if (!otherPtr) {
|
||||
TRACE_ERROR(interp);
|
||||
@@ -5279,23 +5245,10 @@ TEBCresume(
|
||||
toIdx = objc-1;
|
||||
}
|
||||
if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) {
|
||||
/*
|
||||
* BEWARE! This is looking inside the implementation of the
|
||||
* list type.
|
||||
*/
|
||||
|
||||
List *listPtr = valuePtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
if (listPtr->refCount == 1) {
|
||||
for (index=toIdx+1; index<objc ; index++) {
|
||||
TclDecrRefCount(objv[index]);
|
||||
}
|
||||
listPtr->elemCount = toIdx+1;
|
||||
listPtr->canonicalFlag = 1;
|
||||
TclInvalidateStringRep(valuePtr);
|
||||
TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
|
||||
NEXT_INST_F(9, 0, 0);
|
||||
}
|
||||
Tcl_ListObjReplace(interp, valuePtr,
|
||||
toIdx + 1, LIST_MAX, 0, NULL);
|
||||
TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
|
||||
NEXT_INST_F(9, 0, 0);
|
||||
}
|
||||
objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx);
|
||||
} else {
|
||||
@@ -5720,17 +5673,6 @@ TEBCresume(
|
||||
|
||||
length3 = Tcl_GetCharLength(value3Ptr);
|
||||
|
||||
/*
|
||||
* Remove substring. In-place.
|
||||
*/
|
||||
|
||||
if (length3 == 0 && !Tcl_IsShared(valuePtr) && toIdx == length) {
|
||||
TclDecrRefCount(value3Ptr);
|
||||
Tcl_SetObjLength(valuePtr, fromIdx);
|
||||
TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
|
||||
NEXT_INST_F(1, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we can splice in place. This happens when the number of
|
||||
* characters being replaced is the same as the number of characters
|
||||
@@ -5740,51 +5682,29 @@ TEBCresume(
|
||||
if (length3 - 1 == toIdx - fromIdx) {
|
||||
unsigned char *bytes1, *bytes2;
|
||||
|
||||
/*
|
||||
* Flush the info in the string internal rep that refers to the
|
||||
* about-to-be-invalidated UTF-8 rep. This indicates that a new
|
||||
* buffer needs to be allocated, and assumes that the value is
|
||||
* already of tclStringTypePtr type, which should be true provided
|
||||
* we call it after Tcl_GetUnicodeFromObj.
|
||||
*/
|
||||
#define MarkStringInternalRepForFlush(objPtr) \
|
||||
(GET_STRING(objPtr)->allocated = 0)
|
||||
|
||||
if (Tcl_IsShared(valuePtr)) {
|
||||
objResultPtr = Tcl_DuplicateObj(valuePtr);
|
||||
if (TclIsPureByteArray(objResultPtr)
|
||||
&& TclIsPureByteArray(value3Ptr)) {
|
||||
bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL);
|
||||
bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL);
|
||||
memcpy(bytes1 + fromIdx, bytes2, length3);
|
||||
} else {
|
||||
ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL);
|
||||
ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL);
|
||||
memcpy(ustring1 + fromIdx, ustring2,
|
||||
length3 * sizeof(Tcl_UniChar));
|
||||
MarkStringInternalRepForFlush(objResultPtr);
|
||||
}
|
||||
Tcl_InvalidateStringRep(objResultPtr);
|
||||
TclDecrRefCount(value3Ptr);
|
||||
TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
|
||||
NEXT_INST_F(1, 1, 1);
|
||||
} else {
|
||||
if (TclIsPureByteArray(valuePtr)
|
||||
&& TclIsPureByteArray(value3Ptr)) {
|
||||
bytes1 = Tcl_GetByteArrayFromObj(valuePtr, NULL);
|
||||
bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL);
|
||||
memcpy(bytes1 + fromIdx, bytes2, length3);
|
||||
} else {
|
||||
ustring1 = Tcl_GetUnicodeFromObj(valuePtr, NULL);
|
||||
ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL);
|
||||
memcpy(ustring1 + fromIdx, ustring2,
|
||||
length3 * sizeof(Tcl_UniChar));
|
||||
MarkStringInternalRepForFlush(valuePtr);
|
||||
}
|
||||
Tcl_InvalidateStringRep(valuePtr);
|
||||
TclDecrRefCount(value3Ptr);
|
||||
TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
|
||||
objResultPtr = valuePtr;
|
||||
}
|
||||
if (TclIsPureByteArray(objResultPtr)
|
||||
&& TclIsPureByteArray(value3Ptr)) {
|
||||
bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL);
|
||||
bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL);
|
||||
memcpy(bytes1 + fromIdx, bytes2, length3);
|
||||
} else {
|
||||
ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL);
|
||||
ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL);
|
||||
memcpy(ustring1 + fromIdx, ustring2,
|
||||
length3 * sizeof(Tcl_UniChar));
|
||||
}
|
||||
Tcl_InvalidateStringRep(objResultPtr);
|
||||
TclDecrRefCount(value3Ptr);
|
||||
TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
|
||||
if (objResultPtr == valuePtr) {
|
||||
NEXT_INST_F(1, 0, 0);
|
||||
} else {
|
||||
NEXT_INST_F(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5800,54 +5720,38 @@ TEBCresume(
|
||||
* Remove substring using copying.
|
||||
*/
|
||||
|
||||
if (length3 == 0) {
|
||||
if (fromIdx > 0) {
|
||||
objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx);
|
||||
if (toIdx < length) {
|
||||
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
|
||||
length - toIdx);
|
||||
}
|
||||
objResultPtr = NULL;
|
||||
if (fromIdx > 0) {
|
||||
objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx);
|
||||
}
|
||||
if (length3 > 0) {
|
||||
if (objResultPtr) {
|
||||
Tcl_AppendObjToObj(objResultPtr, value3Ptr);
|
||||
} else if (Tcl_IsShared(value3Ptr)) {
|
||||
objResultPtr = Tcl_DuplicateObj(value3Ptr);
|
||||
} else {
|
||||
objResultPtr = value3Ptr;
|
||||
}
|
||||
}
|
||||
if (toIdx < length) {
|
||||
if (objResultPtr) {
|
||||
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
|
||||
length - toIdx);
|
||||
} else {
|
||||
objResultPtr = Tcl_NewUnicodeObj(ustring1 + toIdx + 1,
|
||||
length - toIdx);
|
||||
}
|
||||
TclDecrRefCount(value3Ptr);
|
||||
TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
|
||||
NEXT_INST_F(1, 1, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Splice string pieces by full copying.
|
||||
*/
|
||||
|
||||
if (fromIdx > 0) {
|
||||
objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx);
|
||||
Tcl_AppendObjToObj(objResultPtr, value3Ptr);
|
||||
if (toIdx < length) {
|
||||
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
|
||||
length - toIdx);
|
||||
}
|
||||
} else if (Tcl_IsShared(value3Ptr)) {
|
||||
objResultPtr = Tcl_DuplicateObj(value3Ptr);
|
||||
if (toIdx < length) {
|
||||
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
|
||||
length - toIdx);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Be careful with splicing the stack in this case; we have a
|
||||
* refCount:1 object in value3Ptr and we want to append to it and
|
||||
* make it be the refCount:1 object at the top of the stack
|
||||
* afterwards. [Bug 82e7f67325]
|
||||
*/
|
||||
|
||||
if (toIdx < length) {
|
||||
Tcl_AppendUnicodeToObj(value3Ptr, ustring1 + toIdx + 1,
|
||||
length - toIdx);
|
||||
}
|
||||
if (objResultPtr == NULL) {
|
||||
/* This has to be the case [string replace $s 0 end {}] */
|
||||
/* which has result {} which is same as value3Ptr. */
|
||||
objResultPtr = value3Ptr;
|
||||
}
|
||||
if (objResultPtr == value3Ptr) {
|
||||
/* See [Bug 82e7f67325] */
|
||||
TclDecrRefCount(OBJ_AT_TOS);
|
||||
OBJ_AT_TOS = value3Ptr;
|
||||
TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr)));
|
||||
TclDecrRefCount(valuePtr);
|
||||
OBJ_AT_TOS = value3Ptr; /* Tricky! */
|
||||
NEXT_INST_F(1, 0, 0);
|
||||
}
|
||||
TclDecrRefCount(value3Ptr);
|
||||
@@ -5915,20 +5819,7 @@ TEBCresume(
|
||||
NEXT_INST_V(1, 3, 1);
|
||||
|
||||
case INST_STR_FIND:
|
||||
ustring1 = Tcl_GetUnicodeFromObj(OBJ_AT_TOS, &length); /* Haystack */
|
||||
ustring2 = Tcl_GetUnicodeFromObj(OBJ_UNDER_TOS, &length2);/* Needle */
|
||||
|
||||
match = -1;
|
||||
if (length2 > 0 && length2 <= length) {
|
||||
end = ustring1 + length - length2 + 1;
|
||||
for (p=ustring1 ; p<end ; p++) {
|
||||
if ((*p == *ustring2) &&
|
||||
memcmp(ustring2,p,sizeof(Tcl_UniChar)*length2) == 0) {
|
||||
match = p - ustring1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
match = TclStringFind(OBJ_UNDER_TOS, OBJ_AT_TOS, 0);
|
||||
|
||||
TRACE(("%.20s %.20s => %d\n",
|
||||
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match));
|
||||
@@ -5936,23 +5827,10 @@ TEBCresume(
|
||||
NEXT_INST_F(1, 2, 1);
|
||||
|
||||
case INST_STR_FIND_LAST:
|
||||
ustring1 = Tcl_GetUnicodeFromObj(OBJ_AT_TOS, &length); /* Haystack */
|
||||
ustring2 = Tcl_GetUnicodeFromObj(OBJ_UNDER_TOS, &length2);/* Needle */
|
||||
|
||||
match = -1;
|
||||
if (length2 > 0 && length2 <= length) {
|
||||
for (p=ustring1+length-length2 ; p>=ustring1 ; p--) {
|
||||
if ((*p == *ustring2) &&
|
||||
memcmp(ustring2,p,sizeof(Tcl_UniChar)*length2) == 0) {
|
||||
match = p - ustring1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
match = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, INT_MAX - 1);
|
||||
|
||||
TRACE(("%.20s %.20s => %d\n",
|
||||
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match));
|
||||
|
||||
TclNewIntObj(objResultPtr, match);
|
||||
NEXT_INST_F(1, 2, 1);
|
||||
|
||||
@@ -7708,6 +7586,7 @@ TEBCresume(
|
||||
goto gotError;
|
||||
}
|
||||
}
|
||||
Tcl_IncrRefCount(dictPtr);
|
||||
if (TclListObjGetElements(interp, OBJ_AT_TOS, &length,
|
||||
&keyPtrPtr) != TCL_OK) {
|
||||
TRACE_ERROR(interp);
|
||||
@@ -7720,6 +7599,7 @@ TEBCresume(
|
||||
if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i],
|
||||
&valuePtr) != TCL_OK) {
|
||||
TRACE_ERROR(interp);
|
||||
Tcl_DecrRefCount(dictPtr);
|
||||
goto gotError;
|
||||
}
|
||||
varPtr = LOCAL(duiPtr->varIndices[i]);
|
||||
@@ -7736,10 +7616,12 @@ TEBCresume(
|
||||
duiPtr->varIndices[i]) == NULL) {
|
||||
CACHE_STACK_INFO();
|
||||
TRACE_ERROR(interp);
|
||||
Tcl_DecrRefCount(dictPtr);
|
||||
goto gotError;
|
||||
}
|
||||
CACHE_STACK_INFO();
|
||||
}
|
||||
TclDecrRefCount(dictPtr);
|
||||
TRACE_APPEND(("OK\n"));
|
||||
NEXT_INST_F(9, 0, 0);
|
||||
|
||||
@@ -8184,9 +8066,7 @@ TEBCresume(
|
||||
}
|
||||
|
||||
iPtr->cmdFramePtr = bcFramePtr->nextPtr;
|
||||
if (codePtr->refCount-- <= 1) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
}
|
||||
TclReleaseByteCode(codePtr);
|
||||
TclStackFree(interp, TD); /* free my stack */
|
||||
|
||||
return result;
|
||||
@@ -9154,7 +9034,7 @@ ExecuteExtendedBinaryMathOp(
|
||||
}
|
||||
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
|
||||
mp_init(&bigResult);
|
||||
mp_expt_d(&big1, big2.dp[0], &bigResult);
|
||||
mp_expt_d_ex(&big1, big2.dp[0], &bigResult, 1);
|
||||
mp_clear(&big1);
|
||||
mp_clear(&big2);
|
||||
BIG_RESULT(&bigResult);
|
||||
@@ -9678,9 +9558,9 @@ PrintByteCodeInfo(
|
||||
Proc *procPtr = codePtr->procPtr;
|
||||
Interp *iPtr = (Interp *) *codePtr->interpHandle;
|
||||
|
||||
fprintf(stdout, "\nExecuting ByteCode 0x%p, refCt %u, epoch %u, interp 0x%p (epoch %u)\n",
|
||||
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
|
||||
iPtr->compileEpoch);
|
||||
fprintf(stdout, "\nExecuting ByteCode 0x%p, refCt %" TCL_LL_MODIFIER "u, epoch %" TCL_LL_MODIFIER "u, interp 0x%p (epoch %" TCL_LL_MODIFIER "u)\n",
|
||||
codePtr, (Tcl_WideInt)codePtr->refCount, (Tcl_WideInt)codePtr->compileEpoch, iPtr,
|
||||
(Tcl_WideInt)iPtr->compileEpoch);
|
||||
|
||||
fprintf(stdout, " Source: ");
|
||||
TclPrintSource(stdout, codePtr->source, 60);
|
||||
@@ -9777,7 +9657,7 @@ ValidatePcAndStackTop(
|
||||
TclNewLiteralStringObj(message, "\n executing ");
|
||||
Tcl_IncrRefCount(message);
|
||||
Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL);
|
||||
fprintf(stderr,"%s\n", Tcl_GetString(message));
|
||||
fprintf(stderr,"%s\n", TclGetString(message));
|
||||
Tcl_DecrRefCount(message);
|
||||
} else {
|
||||
fprintf(stderr, "\n");
|
||||
@@ -9827,7 +9707,7 @@ IllegalExprOperandType(
|
||||
|
||||
if (GetNumberFromObj(NULL, opndPtr, &ptr, &type) != TCL_OK) {
|
||||
int numBytes;
|
||||
const char *bytes = Tcl_GetStringFromObj(opndPtr, &numBytes);
|
||||
const char *bytes = TclGetStringFromObj(opndPtr, &numBytes);
|
||||
|
||||
if (numBytes == 0) {
|
||||
description = "empty string";
|
||||
@@ -10240,7 +10120,7 @@ TclExprFloatError(
|
||||
"unknown floating-point error, errno = %d", errno);
|
||||
|
||||
Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN",
|
||||
Tcl_GetString(objPtr), NULL);
|
||||
TclGetString(objPtr), NULL);
|
||||
Tcl_SetObjResult(interp, objPtr);
|
||||
}
|
||||
}
|
||||
@@ -10456,7 +10336,7 @@ EvalStatsCmd(
|
||||
if (entryPtr->objPtr->typePtr == &tclByteCodeType) {
|
||||
numByteCodeLits++;
|
||||
}
|
||||
(void) Tcl_GetStringFromObj(entryPtr->objPtr, &length);
|
||||
(void) TclGetStringFromObj(entryPtr->objPtr, &length);
|
||||
refCountSum += entryPtr->refCount;
|
||||
objBytesIfUnshared += (entryPtr->refCount * sizeof(Tcl_Obj));
|
||||
strBytesIfUnshared += (entryPtr->refCount * (length+1));
|
||||
@@ -10678,7 +10558,7 @@ EvalStatsCmd(
|
||||
Tcl_SetObjResult(interp, objPtr);
|
||||
} else {
|
||||
Tcl_Channel outChan;
|
||||
char *str = Tcl_GetStringFromObj(objv[1], &length);
|
||||
char *str = TclGetStringFromObj(objv[1], &length);
|
||||
|
||||
if (length) {
|
||||
if (strcmp(str, "stdout") == 0) {
|
||||
|
||||
+2
-8
@@ -1079,12 +1079,9 @@ TclFileAttrsCmd(
|
||||
}
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[0], attributeStrings,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
"option", INDEX_TEMP_TABLE, &index) != TCL_OK) {
|
||||
goto end;
|
||||
}
|
||||
if (attributeStringsAllocated != NULL) {
|
||||
TclFreeIntRep(objv[0]);
|
||||
}
|
||||
if (Tcl_FSFileAttrsGet(interp, index, filePtr,
|
||||
&objPtr) != TCL_OK) {
|
||||
goto end;
|
||||
@@ -1107,12 +1104,9 @@ TclFileAttrsCmd(
|
||||
|
||||
for (i = 0; i < objc ; i += 2) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], attributeStrings,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
"option", INDEX_TEMP_TABLE, &index) != TCL_OK) {
|
||||
goto end;
|
||||
}
|
||||
if (attributeStringsAllocated != NULL) {
|
||||
TclFreeIntRep(objv[i]);
|
||||
}
|
||||
if (i + 1 == objc) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"value for \"%s\" missing", TclGetString(objv[i])));
|
||||
|
||||
+18
-17
@@ -387,7 +387,7 @@ TclpGetNativePathType(
|
||||
{
|
||||
Tcl_PathType type = TCL_PATH_ABSOLUTE;
|
||||
int pathLen;
|
||||
const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen);
|
||||
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
|
||||
|
||||
if (path[0] == '~') {
|
||||
/*
|
||||
@@ -578,7 +578,7 @@ Tcl_SplitPath(
|
||||
size = 1;
|
||||
for (i = 0; i < *argcPtr; i++) {
|
||||
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
|
||||
Tcl_GetStringFromObj(eltPtr, &len);
|
||||
TclGetStringFromObj(eltPtr, &len);
|
||||
size += len + 1;
|
||||
}
|
||||
|
||||
@@ -597,7 +597,7 @@ Tcl_SplitPath(
|
||||
p = (char *) &(*argvPtr)[(*argcPtr) + 1];
|
||||
for (i = 0; i < *argcPtr; i++) {
|
||||
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
|
||||
str = Tcl_GetStringFromObj(eltPtr, &len);
|
||||
str = TclGetStringFromObj(eltPtr, &len);
|
||||
memcpy(p, str, (size_t) len+1);
|
||||
p += len+1;
|
||||
}
|
||||
@@ -857,7 +857,7 @@ TclpNativeJoinPath(
|
||||
const char *p;
|
||||
const char *start;
|
||||
|
||||
start = Tcl_GetStringFromObj(prefix, &length);
|
||||
start = TclGetStringFromObj(prefix, &length);
|
||||
|
||||
/*
|
||||
* Remove the ./ from tilde prefixed elements, and drive-letter prefixed
|
||||
@@ -885,7 +885,7 @@ TclpNativeJoinPath(
|
||||
|
||||
if (length > 0 && (start[length-1] != '/')) {
|
||||
Tcl_AppendToObj(prefix, "/", 1);
|
||||
Tcl_GetStringFromObj(prefix, &length);
|
||||
TclGetStringFromObj(prefix, &length);
|
||||
}
|
||||
needsSep = 0;
|
||||
|
||||
@@ -921,7 +921,7 @@ TclpNativeJoinPath(
|
||||
if ((length > 0) &&
|
||||
(start[length-1] != '/') && (start[length-1] != ':')) {
|
||||
Tcl_AppendToObj(prefix, "/", 1);
|
||||
Tcl_GetStringFromObj(prefix, &length);
|
||||
TclGetStringFromObj(prefix, &length);
|
||||
}
|
||||
needsSep = 0;
|
||||
|
||||
@@ -1003,7 +1003,7 @@ Tcl_JoinPath(
|
||||
* Store the result.
|
||||
*/
|
||||
|
||||
resultStr = Tcl_GetStringFromObj(resultObj, &len);
|
||||
resultStr = TclGetStringFromObj(resultObj, &len);
|
||||
Tcl_DStringAppend(resultPtr, resultStr, len);
|
||||
Tcl_DecrRefCount(resultObj);
|
||||
|
||||
@@ -1249,7 +1249,7 @@ Tcl_GlobObjCmd(
|
||||
for (i = 1; i < objc; i++) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
|
||||
&index) != TCL_OK) {
|
||||
string = Tcl_GetStringFromObj(objv[i], &length);
|
||||
string = TclGetStringFromObj(objv[i], &length);
|
||||
if (string[0] == '-') {
|
||||
/*
|
||||
* It looks like the command contains an option so signal an
|
||||
@@ -1357,7 +1357,7 @@ Tcl_GlobObjCmd(
|
||||
if (dir == PATH_GENERAL) {
|
||||
int pathlength;
|
||||
const char *last;
|
||||
const char *first = Tcl_GetStringFromObj(pathOrDir,&pathlength);
|
||||
const char *first = TclGetStringFromObj(pathOrDir,&pathlength);
|
||||
|
||||
/*
|
||||
* Find the last path separator in the path
|
||||
@@ -1460,7 +1460,7 @@ Tcl_GlobObjCmd(
|
||||
const char *str;
|
||||
|
||||
Tcl_ListObjIndex(interp, typePtr, length, &look);
|
||||
str = Tcl_GetStringFromObj(look, &len);
|
||||
str = TclGetStringFromObj(look, &len);
|
||||
if (strcmp("readonly", str) == 0) {
|
||||
globTypes->perm |= TCL_GLOB_PERM_RONLY;
|
||||
} else if (strcmp("hidden", str) == 0) {
|
||||
@@ -1595,8 +1595,9 @@ Tcl_GlobObjCmd(
|
||||
} else if (dir == PATH_GENERAL) {
|
||||
Tcl_DString str;
|
||||
|
||||
Tcl_DStringInit(&str);
|
||||
for (i = 0; i < objc; i++) {
|
||||
Tcl_DStringInit(&str);
|
||||
Tcl_DStringSetLength(&str, 0);
|
||||
if (dir == PATH_GENERAL) {
|
||||
TclDStringAppendDString(&str, &prefix);
|
||||
}
|
||||
@@ -1991,7 +1992,7 @@ TclGlob(
|
||||
Tcl_Panic("Called TclGlob with TCL_GLOBMODE_TAILS and pathPrefix==NULL");
|
||||
}
|
||||
|
||||
pre = Tcl_GetStringFromObj(pathPrefix, &prefixLen);
|
||||
pre = TclGetStringFromObj(pathPrefix, &prefixLen);
|
||||
if (prefixLen > 0
|
||||
&& (strchr(separators, pre[prefixLen-1]) == NULL)) {
|
||||
/*
|
||||
@@ -2009,7 +2010,7 @@ TclGlob(
|
||||
Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv);
|
||||
for (i = 0; i< objc; i++) {
|
||||
int len;
|
||||
const char *oldStr = Tcl_GetStringFromObj(objv[i], &len);
|
||||
const char *oldStr = TclGetStringFromObj(objv[i], &len);
|
||||
Tcl_Obj *elem;
|
||||
|
||||
if (len == prefixLen) {
|
||||
@@ -2361,7 +2362,7 @@ DoGlob(
|
||||
Tcl_Obj *fixme, *newObj;
|
||||
|
||||
Tcl_ListObjIndex(NULL, matchesObj, repair, &fixme);
|
||||
bytes = Tcl_GetStringFromObj(fixme, &numBytes);
|
||||
bytes = TclGetStringFromObj(fixme, &numBytes);
|
||||
newObj = Tcl_NewStringObj(bytes+2, numBytes-2);
|
||||
Tcl_ListObjReplace(NULL, matchesObj, repair, 1,
|
||||
1, &newObj);
|
||||
@@ -2399,7 +2400,7 @@ DoGlob(
|
||||
Tcl_DStringAppend(&append, pattern, p-pattern);
|
||||
|
||||
if (pathPtr != NULL) {
|
||||
(void) Tcl_GetStringFromObj(pathPtr, &length);
|
||||
(void) TclGetStringFromObj(pathPtr, &length);
|
||||
} else {
|
||||
length = 0;
|
||||
}
|
||||
@@ -2445,7 +2446,7 @@ DoGlob(
|
||||
*/
|
||||
|
||||
int len;
|
||||
const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);
|
||||
const char *joined = TclGetStringFromObj(joinedPtr,&len);
|
||||
|
||||
if (strchr(separators, joined[len-1]) == NULL) {
|
||||
Tcl_AppendToObj(joinedPtr, "/", 1);
|
||||
@@ -2482,7 +2483,7 @@ DoGlob(
|
||||
*/
|
||||
|
||||
int len;
|
||||
const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);
|
||||
const char *joined = TclGetStringFromObj(joinedPtr,&len);
|
||||
|
||||
if (strchr(separators, joined[len-1]) == NULL) {
|
||||
if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) {
|
||||
|
||||
+8
-8
@@ -43,7 +43,7 @@
|
||||
|
||||
static Tcl_HashEntry * AllocArrayEntry(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
static int CompareArrayKeys(void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
static unsigned int HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
static TCL_HASH_TYPE HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
|
||||
/*
|
||||
* Prototypes for the one word hash key methods. Not actually declared because
|
||||
@@ -65,7 +65,7 @@ static unsigned int HashOneWordKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
static Tcl_HashEntry * AllocStringEntry(Tcl_HashTable *tablePtr,
|
||||
void *keyPtr);
|
||||
static int CompareStringKeys(void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
static unsigned int HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
static TCL_HASH_TYPE HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
|
||||
/*
|
||||
* Function prototypes for static functions in this file:
|
||||
@@ -774,7 +774,7 @@ CompareArrayKeys(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static unsigned int
|
||||
static TCL_HASH_TYPE
|
||||
HashArrayKey(
|
||||
Tcl_HashTable *tablePtr, /* Hash table. */
|
||||
void *keyPtr) /* Key from which to compute hash value. */
|
||||
@@ -787,7 +787,7 @@ HashArrayKey(
|
||||
count--, array++) {
|
||||
result += *array;
|
||||
}
|
||||
return result;
|
||||
return (TCL_HASH_TYPE) result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -870,7 +870,7 @@ CompareStringKeys(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static unsigned
|
||||
static TCL_HASH_TYPE
|
||||
HashStringKey(
|
||||
Tcl_HashTable *tablePtr, /* Hash table. */
|
||||
void *keyPtr) /* Key from which to compute hash value. */
|
||||
@@ -916,7 +916,7 @@ HashStringKey(
|
||||
result += (result << 3) + UCHAR(c);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return (TCL_HASH_TYPE) result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -924,7 +924,7 @@ HashStringKey(
|
||||
*
|
||||
* BogusFind --
|
||||
*
|
||||
* This function is invoked when an Tcl_FindHashEntry is called on a
|
||||
* This function is invoked when Tcl_FindHashEntry is called on a
|
||||
* table that has been deleted.
|
||||
*
|
||||
* Results:
|
||||
@@ -951,7 +951,7 @@ BogusFind(
|
||||
*
|
||||
* BogusCreate --
|
||||
*
|
||||
* This function is invoked when an Tcl_CreateHashEntry is called on a
|
||||
* This function is invoked when Tcl_CreateHashEntry is called on a
|
||||
* table that has been deleted.
|
||||
*
|
||||
* Results:
|
||||
|
||||
+74
-87
@@ -313,15 +313,20 @@ static int WillRead(Channel *chanPtr);
|
||||
&& (strncmp(optionName, (nameString), len) == 0))
|
||||
|
||||
/*
|
||||
* The ChannelObjType type. We actually store the ChannelState structure
|
||||
* as that lives longest and we want to return the bottomChanPtr when
|
||||
* requested (consistent with Tcl_GetChannel). The setFromAny and
|
||||
* updateString can be NULL as they should not be called.
|
||||
* The ChannelObjType type. Used to store the result of looking up
|
||||
* a channel name in the context of an interp. Saves the lookup
|
||||
* result and values needed to check its continued validity.
|
||||
*/
|
||||
|
||||
typedef struct ResolvedChanName {
|
||||
ChannelState *statePtr; /* The saved lookup result */
|
||||
Tcl_Interp *interp; /* The interp in which the lookup was done. */
|
||||
int epoch; /* The epoch of the channel when the lookup
|
||||
* was done. Use to verify validity. */
|
||||
int refCount; /* Share this struct among many Tcl_Obj. */
|
||||
} ResolvedChanName;
|
||||
|
||||
static void DupChannelIntRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
|
||||
static int SetChannelFromAny(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
static void FreeChannelIntRep(Tcl_Obj *objPtr);
|
||||
|
||||
static const Tcl_ObjType chanObjType = {
|
||||
@@ -329,18 +334,9 @@ static const Tcl_ObjType chanObjType = {
|
||||
FreeChannelIntRep, /* freeIntRepProc */
|
||||
DupChannelIntRep, /* dupIntRepProc */
|
||||
NULL, /* updateStringProc */
|
||||
NULL /* setFromAnyProc SetChannelFromAny */
|
||||
NULL /* setFromAnyProc */
|
||||
};
|
||||
|
||||
#define GET_CHANNELSTATE(objPtr) \
|
||||
((ChannelState *) (objPtr)->internalRep.twoPtrValue.ptr1)
|
||||
#define SET_CHANNELSTATE(objPtr, storePtr) \
|
||||
((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (storePtr))
|
||||
#define GET_CHANNELINTERP(objPtr) \
|
||||
((Tcl_Interp *) (objPtr)->internalRep.twoPtrValue.ptr2)
|
||||
#define SET_CHANNELINTERP(objPtr, storePtr) \
|
||||
((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (storePtr))
|
||||
|
||||
#define BUSY_STATE(st, fl) \
|
||||
((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
|
||||
(((st)->csPtrW) && ((fl) & TCL_WRITABLE)))
|
||||
@@ -1021,7 +1017,7 @@ DeleteChannelTable(
|
||||
*/
|
||||
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
SetFlag(statePtr, CHANNEL_TAINTED);
|
||||
statePtr->epoch++;
|
||||
if (statePtr->refCount-- <= 1) {
|
||||
if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
|
||||
(void) Tcl_Close(interp, (Tcl_Channel) chanPtr);
|
||||
@@ -1365,7 +1361,7 @@ DetachChannel(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
SetFlag(statePtr, CHANNEL_TAINTED);
|
||||
statePtr->epoch++;
|
||||
|
||||
/*
|
||||
* Remove channel handlers that refer to this interpreter, so that
|
||||
@@ -1498,12 +1494,57 @@ TclGetChannelFromObj(
|
||||
int flags)
|
||||
{
|
||||
ChannelState *statePtr;
|
||||
ResolvedChanName *resPtr = NULL;
|
||||
Tcl_Channel chan;
|
||||
|
||||
if (SetChannelFromAny(interp, objPtr) != TCL_OK) {
|
||||
if (interp == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
statePtr = GET_CHANNELSTATE(objPtr);
|
||||
if (objPtr->typePtr == &chanObjType) {
|
||||
/*
|
||||
* Confirm validity of saved lookup results.
|
||||
*/
|
||||
|
||||
resPtr = (ResolvedChanName *) objPtr->internalRep.twoPtrValue.ptr1;
|
||||
statePtr = resPtr->statePtr;
|
||||
if ((resPtr->interp == interp) /* Same interp context */
|
||||
/* No epoch change in channel since lookup */
|
||||
&& (resPtr->epoch == statePtr->epoch)) {
|
||||
|
||||
/* Have a valid saved lookup. Jump to end to return it. */
|
||||
goto valid;
|
||||
}
|
||||
}
|
||||
|
||||
chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL);
|
||||
|
||||
if (chan == NULL) {
|
||||
if (resPtr) {
|
||||
FreeChannelIntRep(objPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (resPtr && resPtr->refCount == 1) {
|
||||
/* Re-use the ResolvedCmdName struct */
|
||||
Tcl_Release((ClientData) resPtr->statePtr);
|
||||
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
|
||||
resPtr = (ResolvedChanName *) ckalloc(sizeof(ResolvedChanName));
|
||||
resPtr->refCount = 1;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = (ClientData) resPtr;
|
||||
objPtr->typePtr = &chanObjType;
|
||||
}
|
||||
statePtr = ((Channel *)chan)->state;
|
||||
resPtr->statePtr = statePtr;
|
||||
Tcl_Preserve((ClientData) statePtr);
|
||||
resPtr->interp = interp;
|
||||
resPtr->epoch = statePtr->epoch;
|
||||
|
||||
valid:
|
||||
*channelPtr = (Tcl_Channel) statePtr->bottomChanPtr;
|
||||
|
||||
if (modePtr != NULL) {
|
||||
@@ -1676,6 +1717,8 @@ Tcl_CreateChannel(
|
||||
statePtr->chanMsg = NULL;
|
||||
statePtr->unreportedMsg = NULL;
|
||||
|
||||
statePtr->epoch = 0;
|
||||
|
||||
/*
|
||||
* Link the channel into the list of all channels; create an on-exit
|
||||
* handler if there is not one already, to close off all the channels in
|
||||
@@ -7086,7 +7129,7 @@ Tcl_Tell(
|
||||
*
|
||||
* Tcl_SeekOld, Tcl_TellOld --
|
||||
*
|
||||
* Backward-compatability versions of the seek/tell interface that do not
|
||||
* Backward-compatibility versions of the seek/tell interface that do not
|
||||
* support 64-bit offsets. This interface is not documented or expected
|
||||
* to be supported indefinitely.
|
||||
*
|
||||
@@ -11121,75 +11164,13 @@ DupChannelIntRep(
|
||||
register Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not
|
||||
* currently have an internal rep.*/
|
||||
{
|
||||
ChannelState *statePtr = GET_CHANNELSTATE(srcPtr);
|
||||
ResolvedChanName *resPtr = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
SET_CHANNELSTATE(copyPtr, statePtr);
|
||||
SET_CHANNELINTERP(copyPtr, GET_CHANNELINTERP(srcPtr));
|
||||
Tcl_Preserve(statePtr);
|
||||
resPtr->refCount++;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = resPtr;
|
||||
copyPtr->typePtr = srcPtr->typePtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* SetChannelFromAny --
|
||||
*
|
||||
* Create an internal representation of type "Channel" for an object.
|
||||
*
|
||||
* Results:
|
||||
* This operation always succeeds and returns TCL_OK.
|
||||
*
|
||||
* Side effects:
|
||||
* Any old internal reputation for objPtr is freed and the internal
|
||||
* representation is set to "Channel".
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
SetChannelFromAny(
|
||||
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
|
||||
register Tcl_Obj *objPtr) /* The object to convert. */
|
||||
{
|
||||
ChannelState *statePtr;
|
||||
|
||||
if (interp == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objPtr->typePtr == &chanObjType) {
|
||||
/*
|
||||
* TODO: TAINT Flag and dup'd channel values?
|
||||
* The channel is valid until any call to DetachChannel occurs.
|
||||
* Ensure consistency checks are done.
|
||||
*/
|
||||
|
||||
statePtr = GET_CHANNELSTATE(objPtr);
|
||||
if (GotFlag(statePtr, CHANNEL_TAINTED|CHANNEL_CLOSED)) {
|
||||
ResetFlag(statePtr, CHANNEL_TAINTED);
|
||||
Tcl_Release(statePtr);
|
||||
objPtr->typePtr = NULL;
|
||||
} else if (interp != GET_CHANNELINTERP(objPtr)) {
|
||||
Tcl_Release(statePtr);
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
}
|
||||
if (objPtr->typePtr != &chanObjType) {
|
||||
Tcl_Channel chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL);
|
||||
|
||||
if (chan == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
statePtr = ((Channel *) chan)->state;
|
||||
Tcl_Preserve(statePtr);
|
||||
SET_CHANNELSTATE(objPtr, statePtr);
|
||||
SET_CHANNELINTERP(objPtr, interp);
|
||||
objPtr->typePtr = &chanObjType;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -11210,8 +11191,14 @@ static void
|
||||
FreeChannelIntRep(
|
||||
Tcl_Obj *objPtr) /* Object with internal rep to free. */
|
||||
{
|
||||
Tcl_Release(GET_CHANNELSTATE(objPtr));
|
||||
ResolvedChanName *resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
if (--resPtr->refCount) {
|
||||
return;
|
||||
}
|
||||
Tcl_Release(resPtr->statePtr);
|
||||
ckfree(resPtr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
+2
-4
@@ -214,6 +214,8 @@ typedef struct ChannelState {
|
||||
* because it happened in the background. The
|
||||
* value is the chanMg, if any. #219's
|
||||
* companion to 'unreportedError'. */
|
||||
int epoch; /* Used to test validity of stored channelname
|
||||
* lookup results. */
|
||||
} ChannelState;
|
||||
|
||||
/*
|
||||
@@ -275,10 +277,6 @@ typedef struct ChannelState {
|
||||
* usable, but it may not be closed
|
||||
* again from within the close
|
||||
* handler. */
|
||||
#define CHANNEL_TAINTED (1<<20) /* Channel stack structure has changed.
|
||||
* Used by Channel Tcl_Obj type to
|
||||
* determine if we have to revalidate
|
||||
* the channel. */
|
||||
#define CHANNEL_CLOSEDWRITE (1<<21) /* Channel write side has been closed.
|
||||
* No further Tcl-level write IO on
|
||||
* the channel is allowed. */
|
||||
|
||||
+2
-2
@@ -211,7 +211,7 @@ struct TransformChannelData {
|
||||
* a transformation of incoming data. Also
|
||||
* serves as buffer of all data not yet
|
||||
* consumed by the reader. */
|
||||
int refCount;
|
||||
size_t refCount;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -225,7 +225,7 @@ static void
|
||||
ReleaseData(
|
||||
TransformChannelData *dataPtr)
|
||||
{
|
||||
if (--dataPtr->refCount) {
|
||||
if (dataPtr->refCount-- > 1) {
|
||||
return;
|
||||
}
|
||||
ResultClear(&dataPtr->result);
|
||||
|
||||
+13
-13
@@ -591,7 +591,7 @@ TclChanCreateObjCmd(
|
||||
if (Tcl_ListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s initialize\" returned non-list: %s",
|
||||
Tcl_GetString(cmdObj), Tcl_GetString(resObj)));
|
||||
TclGetString(cmdObj), TclGetString(resObj)));
|
||||
Tcl_DecrRefCount(resObj);
|
||||
goto error;
|
||||
}
|
||||
@@ -617,35 +617,35 @@ TclChanCreateObjCmd(
|
||||
if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" does not support all required methods",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((mode & TCL_READABLE) && !HAS(methods, METH_READ)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" lacks a \"read\" method",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((mode & TCL_WRITABLE) && !HAS(methods, METH_WRITE)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" lacks a \"write\" method",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!IMPLIES(HAS(methods, METH_CGET), HAS(methods, METH_CGETALL))) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" supports \"cget\" but not \"cgetall\"",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!IMPLIES(HAS(methods, METH_CGETALL), HAS(methods, METH_CGET))) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" supports \"cgetall\" but not \"cget\"",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1152,7 +1152,7 @@ ReflectClose(
|
||||
|
||||
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
|
||||
if (tctPtr && tctPtr != &tclRChannelType) {
|
||||
ckfree((char *)tctPtr);
|
||||
ckfree(tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
}
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
@@ -1221,7 +1221,7 @@ ReflectClose(
|
||||
#endif
|
||||
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
|
||||
if (tctPtr && tctPtr != &tclRChannelType) {
|
||||
ckfree((char *)tctPtr);
|
||||
ckfree(tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
}
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
@@ -1946,7 +1946,7 @@ ReflectGetOption(
|
||||
goto error;
|
||||
} else {
|
||||
int len;
|
||||
const char *str = Tcl_GetStringFromObj(resObj, &len);
|
||||
const char *str = TclGetStringFromObj(resObj, &len);
|
||||
|
||||
if (len) {
|
||||
TclDStringAppendLiteral(dsPtr, " ");
|
||||
@@ -2319,7 +2319,7 @@ InvokeTclMethod(
|
||||
|
||||
if (result != TCL_ERROR) {
|
||||
int cmdLen;
|
||||
const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen);
|
||||
const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);
|
||||
|
||||
Tcl_IncrRefCount(cmd);
|
||||
Tcl_ResetResult(rcPtr->interp);
|
||||
@@ -2398,7 +2398,7 @@ ErrnoReturn(
|
||||
|
||||
if (((Tcl_GetIntFromObj(rcPtr->interp, resObj, &code) != TCL_OK)
|
||||
|| (code >= 0))) {
|
||||
if (strcmp("EAGAIN", Tcl_GetString(resObj)) == 0) {
|
||||
if (strcmp("EAGAIN", TclGetString(resObj)) == 0) {
|
||||
code = -EAGAIN;
|
||||
} else {
|
||||
code = 0;
|
||||
@@ -3174,7 +3174,7 @@ ForwardProc(
|
||||
ForwardSetDynamicError(paramPtr, buf);
|
||||
} else {
|
||||
int len;
|
||||
const char *str = Tcl_GetStringFromObj(resObj, &len);
|
||||
const char *str = TclGetStringFromObj(resObj, &len);
|
||||
|
||||
if (len) {
|
||||
TclDStringAppendLiteral(paramPtr->getOpt.value, " ");
|
||||
@@ -3273,7 +3273,7 @@ ForwardSetObjError(
|
||||
Tcl_Obj *obj)
|
||||
{
|
||||
int len;
|
||||
const char *msgStr = Tcl_GetStringFromObj(obj, &len);
|
||||
const char *msgStr = TclGetStringFromObj(obj, &len);
|
||||
|
||||
len++;
|
||||
ForwardSetDynamicError(paramPtr, ckalloc(len));
|
||||
|
||||
+15
-15
@@ -554,7 +554,7 @@ TclChanPushObjCmd(
|
||||
*/
|
||||
|
||||
chanObj = objv[CHAN];
|
||||
parentChan = Tcl_GetChannel(interp, Tcl_GetString(chanObj), &mode);
|
||||
parentChan = Tcl_GetChannel(interp, TclGetString(chanObj), &mode);
|
||||
if (parentChan == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -608,7 +608,7 @@ TclChanPushObjCmd(
|
||||
if (Tcl_ListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s initialize\" returned non-list: %s",
|
||||
Tcl_GetString(cmdObj), Tcl_GetString(resObj)));
|
||||
TclGetString(cmdObj), TclGetString(resObj)));
|
||||
Tcl_DecrRefCount(resObj);
|
||||
goto error;
|
||||
}
|
||||
@@ -619,7 +619,7 @@ TclChanPushObjCmd(
|
||||
"method", TCL_EXACT, &methIndex) != TCL_OK) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s initialize\" returned %s",
|
||||
Tcl_GetString(cmdObj),
|
||||
TclGetString(cmdObj),
|
||||
Tcl_GetString(Tcl_GetObjResult(interp))));
|
||||
Tcl_DecrRefCount(resObj);
|
||||
goto error;
|
||||
@@ -633,7 +633,7 @@ TclChanPushObjCmd(
|
||||
if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" does not support all required methods",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -655,7 +655,7 @@ TclChanPushObjCmd(
|
||||
if (!mode) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" makes the channel inaccessible",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -666,14 +666,14 @@ TclChanPushObjCmd(
|
||||
if (!IMPLIES(HAS(methods, METH_DRAIN), HAS(methods, METH_READ))) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" supports \"drain\" but not \"read\"",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!IMPLIES(HAS(methods, METH_FLUSH), HAS(methods, METH_WRITE))) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"chan handler \"%s\" supports \"flush\" but not \"write\"",
|
||||
Tcl_GetString(cmdObj)));
|
||||
TclGetString(cmdObj)));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -694,14 +694,14 @@ TclChanPushObjCmd(
|
||||
*/
|
||||
|
||||
rtmPtr = GetReflectedTransformMap(interp);
|
||||
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, Tcl_GetString(rtId), &isNew);
|
||||
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), &isNew);
|
||||
if (!isNew && rtPtr != Tcl_GetHashValue(hPtr)) {
|
||||
Tcl_Panic("TclChanPushObjCmd: duplicate transformation handle");
|
||||
}
|
||||
Tcl_SetHashValue(hPtr, rtPtr);
|
||||
#ifdef TCL_THREADS
|
||||
rtmPtr = GetThreadReflectedTransformMap();
|
||||
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, Tcl_GetString(rtId), &isNew);
|
||||
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), &isNew);
|
||||
Tcl_SetHashValue(hPtr, rtPtr);
|
||||
#endif /* TCL_THREADS */
|
||||
|
||||
@@ -1027,7 +1027,7 @@ ReflectClose(
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
rtmPtr = GetThreadReflectedTransformMap();
|
||||
hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle));
|
||||
hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle));
|
||||
if (hPtr) {
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
}
|
||||
@@ -2043,7 +2043,7 @@ InvokeTclMethod(
|
||||
if (result != TCL_ERROR) {
|
||||
Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rtPtr->argv);
|
||||
int cmdLen;
|
||||
const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen);
|
||||
const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);
|
||||
|
||||
Tcl_IncrRefCount(cmd);
|
||||
Tcl_ResetResult(rtPtr->interp);
|
||||
@@ -2568,7 +2568,7 @@ ForwardProc(
|
||||
*/
|
||||
|
||||
rtmPtr = GetReflectedTransformMap(interp);
|
||||
hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle));
|
||||
hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle));
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
|
||||
/*
|
||||
@@ -2578,7 +2578,7 @@ ForwardProc(
|
||||
*/
|
||||
|
||||
rtmPtr = GetThreadReflectedTransformMap();
|
||||
hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle));
|
||||
hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle));
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
|
||||
FreeReflectedTransformArgs(rtPtr);
|
||||
@@ -2807,7 +2807,7 @@ ForwardSetObjError(
|
||||
Tcl_Obj *obj)
|
||||
{
|
||||
int len;
|
||||
const char *msgStr = Tcl_GetStringFromObj(obj, &len);
|
||||
const char *msgStr = TclGetStringFromObj(obj, &len);
|
||||
|
||||
len++;
|
||||
ForwardSetDynamicError(paramPtr, ckalloc(len));
|
||||
@@ -2955,7 +2955,7 @@ ResultClear(
|
||||
return;
|
||||
}
|
||||
|
||||
ckfree((char *) rPtr->buf);
|
||||
ckfree(rPtr->buf);
|
||||
rPtr->buf = NULL;
|
||||
rPtr->allocated = 0;
|
||||
}
|
||||
|
||||
+26
-24
@@ -56,8 +56,8 @@ static const char *gai_strerror(int code) {
|
||||
int
|
||||
TclSockGetPort(
|
||||
Tcl_Interp *interp,
|
||||
const char *string, /* Integer or service name */
|
||||
const char *proto, /* "tcp" or "udp", typically */
|
||||
const char *string, /* Integer or service name */
|
||||
const char *proto, /* "tcp" or "udp", typically */
|
||||
int *portPtr) /* Return port number */
|
||||
{
|
||||
struct servent *sp; /* Protocol info for named services */
|
||||
@@ -154,15 +154,15 @@ TclSockMinimumBuffers(
|
||||
|
||||
int
|
||||
TclCreateSocketAddress(
|
||||
Tcl_Interp *interp, /* Interpreter for querying
|
||||
* the desired socket family */
|
||||
struct addrinfo **addrlist, /* Socket address list */
|
||||
const char *host, /* Host. NULL implies INADDR_ANY */
|
||||
int port, /* Port number */
|
||||
int willBind, /* Is this an address to bind() to or
|
||||
* to connect() to? */
|
||||
const char **errorMsgPtr) /* Place to store the error message
|
||||
* detail, if available. */
|
||||
Tcl_Interp *interp, /* Interpreter for querying the desired socket
|
||||
* family */
|
||||
struct addrinfo **addrlist, /* Socket address list */
|
||||
const char *host, /* Host. NULL implies INADDR_ANY */
|
||||
int port, /* Port number */
|
||||
int willBind, /* Is this an address to bind() to or to
|
||||
* connect() to? */
|
||||
const char **errorMsgPtr) /* Place to store the error message detail, if
|
||||
* available. */
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *p;
|
||||
@@ -181,30 +181,31 @@ TclCreateSocketAddress(
|
||||
* Workaround for OSX's apparent inability to resolve "localhost", "0"
|
||||
* when the loopback device is the only available network interface.
|
||||
*/
|
||||
|
||||
if (host != NULL && port == 0) {
|
||||
portstring = NULL;
|
||||
portstring = NULL;
|
||||
} else {
|
||||
TclFormatInt(portbuf, port);
|
||||
portstring = portbuf;
|
||||
TclFormatInt(portbuf, port);
|
||||
portstring = portbuf;
|
||||
}
|
||||
|
||||
(void) memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
/*
|
||||
* Magic variable to enforce a certain address family - to be superseded
|
||||
* by a TIP that adds explicit switches to [socket]
|
||||
* Magic variable to enforce a certain address family; to be superseded
|
||||
* by a TIP that adds explicit switches to [socket].
|
||||
*/
|
||||
|
||||
if (interp != NULL) {
|
||||
family = Tcl_GetVar(interp, "::tcl::unsupported::socketAF", 0);
|
||||
if (family != NULL) {
|
||||
if (strcmp(family, "inet") == 0) {
|
||||
hints.ai_family = AF_INET;
|
||||
} else if (strcmp(family, "inet6") == 0) {
|
||||
hints.ai_family = AF_INET6;
|
||||
}
|
||||
}
|
||||
family = Tcl_GetVar2(interp, "::tcl::unsupported::socketAF", NULL, 0);
|
||||
if (family != NULL) {
|
||||
if (strcmp(family, "inet") == 0) {
|
||||
hints.ai_family = AF_INET;
|
||||
} else if (strcmp(family, "inet6") == 0) {
|
||||
hints.ai_family = AF_INET6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
@@ -251,6 +252,7 @@ TclCreateSocketAddress(
|
||||
*
|
||||
* There might be more elegant/efficient ways to do this.
|
||||
*/
|
||||
|
||||
if (willBind) {
|
||||
for (p = *addrlist; p != NULL; p = p->ai_next) {
|
||||
if (p->ai_family == AF_INET) {
|
||||
|
||||
+17
-18
@@ -71,8 +71,7 @@ typedef struct ThreadSpecificData {
|
||||
* Prototypes for functions defined later in this file.
|
||||
*/
|
||||
|
||||
static int EvalFileCallback(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc EvalFileCallback;
|
||||
static FilesystemRecord*FsGetFirstFilesystem(void);
|
||||
static void FsThrExitProc(ClientData cd);
|
||||
static Tcl_Obj * FsListMounts(Tcl_Obj *pathPtr, const char *pattern);
|
||||
@@ -545,8 +544,8 @@ TclFSCwdPointerEquals(
|
||||
int len1, len2;
|
||||
const char *str1, *str2;
|
||||
|
||||
str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1);
|
||||
str2 = Tcl_GetStringFromObj(*pathPtrPtr, &len2);
|
||||
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
|
||||
str2 = TclGetStringFromObj(*pathPtrPtr, &len2);
|
||||
if ((len1 == len2) && !memcmp(str1, str2, len1)) {
|
||||
/*
|
||||
* They are equal, but different objects. Update so they will be
|
||||
@@ -639,8 +638,8 @@ FsGetFirstFilesystem(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* The epoch can be changed both by filesystems being added or removed and by
|
||||
* env(HOME) changing.
|
||||
* The epoch can be changed by filesystems being added or removed, by changing
|
||||
* the "system encoding" and by env(HOME) changing.
|
||||
*/
|
||||
|
||||
int
|
||||
@@ -689,7 +688,7 @@ FsUpdateCwd(
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
|
||||
|
||||
if (cwdObj != NULL) {
|
||||
str = Tcl_GetStringFromObj(cwdObj, &len);
|
||||
str = TclGetStringFromObj(cwdObj, &len);
|
||||
}
|
||||
|
||||
Tcl_MutexLock(&cwdMutex);
|
||||
@@ -1225,8 +1224,8 @@ FsAddMountsToGlobResult(
|
||||
if (norm != NULL) {
|
||||
const char *path, *mount;
|
||||
|
||||
mount = Tcl_GetStringFromObj(mElt, &mlen);
|
||||
path = Tcl_GetStringFromObj(norm, &len);
|
||||
mount = TclGetStringFromObj(mElt, &mlen);
|
||||
path = TclGetStringFromObj(norm, &len);
|
||||
if (path[len-1] == '/') {
|
||||
/*
|
||||
* Deal with the root of the volume.
|
||||
@@ -1817,7 +1816,7 @@ Tcl_FSEvalFileEx(
|
||||
oldScriptFile = iPtr->scriptFile;
|
||||
iPtr->scriptFile = pathPtr;
|
||||
Tcl_IncrRefCount(iPtr->scriptFile);
|
||||
string = Tcl_GetStringFromObj(objPtr, &length);
|
||||
string = TclGetStringFromObj(objPtr, &length);
|
||||
|
||||
/*
|
||||
* TIP #280 Force the evaluator to open a frame for a sourced file.
|
||||
@@ -1844,7 +1843,7 @@ Tcl_FSEvalFileEx(
|
||||
* Record information telling where the error occurred.
|
||||
*/
|
||||
|
||||
const char *pathString = Tcl_GetStringFromObj(pathPtr, &length);
|
||||
const char *pathString = TclGetStringFromObj(pathPtr, &length);
|
||||
int limit = 150;
|
||||
int overflow = (length > limit);
|
||||
|
||||
@@ -1995,7 +1994,7 @@ EvalFileCallback(
|
||||
*/
|
||||
|
||||
int length;
|
||||
const char *pathString = Tcl_GetStringFromObj(pathPtr, &length);
|
||||
const char *pathString = TclGetStringFromObj(pathPtr, &length);
|
||||
const int limit = 150;
|
||||
int overflow = (length > limit);
|
||||
|
||||
@@ -2847,8 +2846,8 @@ Tcl_FSGetCwd(
|
||||
int len1, len2;
|
||||
const char *str1, *str2;
|
||||
|
||||
str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1);
|
||||
str2 = Tcl_GetStringFromObj(norm, &len2);
|
||||
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
|
||||
str2 = TclGetStringFromObj(norm, &len2);
|
||||
if ((len1 == len2) && (strcmp(str1, str2) == 0)) {
|
||||
/*
|
||||
* If the paths were equal, we can be more efficient and
|
||||
@@ -4116,7 +4115,7 @@ TclGetPathType(
|
||||
* caller. */
|
||||
{
|
||||
int pathLen;
|
||||
const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen);
|
||||
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
|
||||
Tcl_PathType type;
|
||||
|
||||
type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr,
|
||||
@@ -4228,7 +4227,7 @@ TclFSNonnativePathType(
|
||||
|
||||
numVolumes--;
|
||||
Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
|
||||
strVol = Tcl_GetStringFromObj(vol,&len);
|
||||
strVol = TclGetStringFromObj(vol,&len);
|
||||
if (pathLen < len) {
|
||||
continue;
|
||||
}
|
||||
@@ -4575,8 +4574,8 @@ Tcl_FSRemoveDirectory(
|
||||
Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
|
||||
|
||||
if (normPath != NULL) {
|
||||
normPathStr = Tcl_GetStringFromObj(normPath, &normLen);
|
||||
cwdStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
|
||||
normPathStr = TclGetStringFromObj(normPath, &normLen);
|
||||
cwdStr = TclGetStringFromObj(cwdPtr, &cwdLen);
|
||||
if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr,
|
||||
(size_t) normLen) == 0)) {
|
||||
/*
|
||||
|
||||
+28
-35
@@ -114,14 +114,13 @@ Tcl_GetIndexFromObj(
|
||||
int flags, /* 0 or TCL_EXACT */
|
||||
int *indexPtr) /* Place to store resulting integer index. */
|
||||
{
|
||||
|
||||
/*
|
||||
* See if there is a valid cached result from a previous lookup (doing the
|
||||
* check here saves the overhead of calling Tcl_GetIndexFromObjStruct in
|
||||
* the common case where the result is cached).
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &indexType) {
|
||||
if (!(flags & INDEX_TEMP_TABLE) && objPtr->typePtr == &indexType) {
|
||||
IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
/*
|
||||
@@ -211,13 +210,8 @@ GetIndexFromObjList(
|
||||
tablePtr[objc] = NULL;
|
||||
|
||||
result = Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr,
|
||||
sizeof(char *), msg, flags, indexPtr);
|
||||
sizeof(char *), msg, flags | INDEX_TEMP_TABLE, indexPtr);
|
||||
|
||||
/*
|
||||
* The internal rep must be cleared since tablePtr will go away.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
ckfree(tablePtr);
|
||||
|
||||
return result;
|
||||
@@ -279,7 +273,7 @@ Tcl_GetIndexFromObjStruct(
|
||||
* See if there is a valid cached result from a previous lookup.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &indexType) {
|
||||
if (!(flags & INDEX_TEMP_TABLE) && objPtr->typePtr == &indexType) {
|
||||
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
|
||||
*indexPtr = indexRep->index;
|
||||
@@ -340,17 +334,19 @@ Tcl_GetIndexFromObjStruct(
|
||||
* operation.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &indexType) {
|
||||
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
indexRep = ckalloc(sizeof(IndexRep));
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = indexRep;
|
||||
objPtr->typePtr = &indexType;
|
||||
if (!(flags & INDEX_TEMP_TABLE)) {
|
||||
if (objPtr->typePtr == &indexType) {
|
||||
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
indexRep = ckalloc(sizeof(IndexRep));
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = indexRep;
|
||||
objPtr->typePtr = &indexType;
|
||||
}
|
||||
indexRep->tablePtr = (void *) tablePtr;
|
||||
indexRep->offset = offset;
|
||||
indexRep->index = index;
|
||||
}
|
||||
indexRep->tablePtr = (void *) tablePtr;
|
||||
indexRep->offset = offset;
|
||||
indexRep->index = index;
|
||||
|
||||
*indexPtr = index;
|
||||
return TCL_OK;
|
||||
@@ -712,10 +708,10 @@ PrefixAllObjCmd(
|
||||
return result;
|
||||
}
|
||||
resultPtr = Tcl_NewListObj(0, NULL);
|
||||
string = Tcl_GetStringFromObj(objv[2], &length);
|
||||
string = TclGetStringFromObj(objv[2], &length);
|
||||
|
||||
for (t = 0; t < tableObjc; t++) {
|
||||
elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength);
|
||||
elemString = TclGetStringFromObj(tableObjv[t], &elemLength);
|
||||
|
||||
/*
|
||||
* A prefix cannot match if it is longest.
|
||||
@@ -768,13 +764,13 @@ PrefixLongestObjCmd(
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
string = Tcl_GetStringFromObj(objv[2], &length);
|
||||
string = TclGetStringFromObj(objv[2], &length);
|
||||
|
||||
resultString = NULL;
|
||||
resultLength = 0;
|
||||
|
||||
for (t = 0; t < tableObjc; t++) {
|
||||
elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength);
|
||||
elemString = TclGetStringFromObj(tableObjv[t], &elemLength);
|
||||
|
||||
/*
|
||||
* First check if the prefix string matches the element. A prefix
|
||||
@@ -924,6 +920,14 @@ Tcl_WrongNumArgs(
|
||||
int toPrint = iPtr->ensembleRewrite.numRemovedObjs;
|
||||
Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;
|
||||
|
||||
/*
|
||||
* Check for spelling fixes, and substitute the fixed values.
|
||||
*/
|
||||
|
||||
if (origObjv[0] == NULL) {
|
||||
origObjv = (Tcl_Obj *const *)origObjv[2];
|
||||
}
|
||||
|
||||
/*
|
||||
* We only know how to do rewriting if all the replaced objects are
|
||||
* actually arguments (in objv) to this function. Otherwise it just
|
||||
@@ -957,12 +961,6 @@ Tcl_WrongNumArgs(
|
||||
|
||||
elementStr = EXPAND_OF(indexRep);
|
||||
elemLen = strlen(elementStr);
|
||||
} else if (origObjv[i]->typePtr == &tclEnsembleCmdType) {
|
||||
register EnsembleCmdRep *ecrPtr =
|
||||
origObjv[i]->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
elementStr = ecrPtr->fullSubcmdName;
|
||||
elemLen = strlen(elementStr);
|
||||
} else {
|
||||
elementStr = TclGetStringFromObj(origObjv[i], &elemLen);
|
||||
}
|
||||
@@ -1011,11 +1009,6 @@ Tcl_WrongNumArgs(
|
||||
register IndexRep *indexRep = objv[i]->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL);
|
||||
} else if (objv[i]->typePtr == &tclEnsembleCmdType) {
|
||||
register EnsembleCmdRep *ecrPtr =
|
||||
objv[i]->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
Tcl_AppendStringsToObj(objPtr, ecrPtr->fullSubcmdName, NULL);
|
||||
} else {
|
||||
/*
|
||||
* Quote the argument if it contains spaces (Bug 942757).
|
||||
@@ -1151,7 +1144,7 @@ Tcl_ParseArgsObjv(
|
||||
curArg = objv[srcIndex];
|
||||
srcIndex++;
|
||||
objc--;
|
||||
str = Tcl_GetStringFromObj(curArg, &length);
|
||||
str = TclGetStringFromObj(curArg, &length);
|
||||
if (length > 0) {
|
||||
c = str[1];
|
||||
} else {
|
||||
|
||||
@@ -1009,7 +1009,7 @@ declare 250 {
|
||||
# Allow extensions for optimization
|
||||
declare 251 {
|
||||
int TclRegisterLiteral(void *envPtr,
|
||||
char *bytes, int length, int flags)
|
||||
const char *bytes, int length, int flags)
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
@@ -1246,7 +1246,7 @@ declare 19 macosx {
|
||||
}
|
||||
|
||||
declare 29 {win unix} {
|
||||
int TclWinCPUID(unsigned int index, unsigned int *regs)
|
||||
int TclWinCPUID(int index, int *regs)
|
||||
}
|
||||
# Added in 8.6; core of TclpOpenTemporaryFile
|
||||
declare 30 {win unix} {
|
||||
|
||||
+81
-46
@@ -25,6 +25,19 @@
|
||||
|
||||
#undef ACCEPT_NAN
|
||||
|
||||
/*
|
||||
* In Tcl 8.7, stop supporting special hacks for legacy Itcl 3.
|
||||
* Itcl 4 doesn't need them. Itcl 3 can be updated to not need them
|
||||
* using the Tcl(Init|Reset)RewriteEnsemble() routines in all Tcl 8.6+
|
||||
* releases. Perhaps Tcl 8.7 will add even better public interfaces
|
||||
* supporting all the re-invocation mechanisms extensions like Itcl 3
|
||||
* need. As an absolute last resort, folks who must make Itcl 3 work
|
||||
* unchanged with Tcl 8.7 can remove this line to regain the migration
|
||||
* support. Tcl 9 will no longer offer even that option.
|
||||
*/
|
||||
|
||||
#define AVOID_HACKS_FOR_ITCL 1
|
||||
|
||||
/*
|
||||
* Common include files needed by most of the Tcl source files are included
|
||||
* here, so that system-dependent personalizations for the include files only
|
||||
@@ -48,7 +61,8 @@
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef STDC_HEADERS
|
||||
#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \
|
||||
|| defined(__cplusplus) || defined(_MSC_VER)
|
||||
#include <stddef.h>
|
||||
#else
|
||||
typedef int ptrdiff_t;
|
||||
@@ -168,6 +182,21 @@ typedef struct Tcl_ResolverInfo {
|
||||
* at compile time. */
|
||||
} Tcl_ResolverInfo;
|
||||
|
||||
/*
|
||||
* This flag bit should not interfere with TCL_GLOBAL_ONLY,
|
||||
* TCL_NAMESPACE_ONLY, or TCL_LEAVE_ERR_MSG; it signals that the variable
|
||||
* lookup is performed for upvar (or similar) purposes, with slightly
|
||||
* different rules:
|
||||
* - Bug #696893 - variable is either proc-local or in the current
|
||||
* namespace; never follow the second (global) resolution path
|
||||
* - Bug #631741 - do not use special namespace or interp resolvers
|
||||
*
|
||||
* It should also not collide with the (deprecated) TCL_PARSE_PART1 flag
|
||||
* (Bug #835020)
|
||||
*/
|
||||
|
||||
#define TCL_AVOID_RESOLVERS 0x40000
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Data structures related to namespaces.
|
||||
@@ -388,27 +417,6 @@ struct NamespacePathEntry {
|
||||
#define TCL_CREATE_NS_IF_UNKNOWN 0x800
|
||||
#define TCL_FIND_ONLY_NS 0x1000
|
||||
|
||||
/*
|
||||
* The data cached in an ensemble subcommand's Tcl_Obj rep (reference in
|
||||
* twoPtrValue.ptr1 field). This structure is not shared between Tcl_Objs
|
||||
* referring to the same subcommand, even where one is a duplicate of another.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
Namespace *nsPtr; /* The namespace backing the ensemble which
|
||||
* this is a subcommand of. */
|
||||
int epoch; /* Used to confirm when the data in this
|
||||
* really structure matches up with the
|
||||
* ensemble. */
|
||||
Tcl_Command token; /* Reference to the comamnd for which this
|
||||
* structure is a cache of the resolution. */
|
||||
char *fullSubcmdName; /* The full (local) name of the subcommand,
|
||||
* allocated with ckalloc(). */
|
||||
Tcl_Obj *realPrefixObj; /* Object containing the prefix words of the
|
||||
* command that implements this ensemble
|
||||
* subcommand. */
|
||||
} EnsembleCmdRep;
|
||||
|
||||
/*
|
||||
* The client data for an ensemble command. This consists of the table of
|
||||
* commands that are actually exported by the namespace, and an epoch counter
|
||||
@@ -1682,11 +1690,13 @@ typedef struct Command {
|
||||
* (these last two flags are defined in tcl.h)
|
||||
*/
|
||||
|
||||
#define CMD_IS_DELETED 0x1
|
||||
#define CMD_TRACE_ACTIVE 0x2
|
||||
#define CMD_HAS_EXEC_TRACES 0x4
|
||||
#define CMD_COMPILES_EXPANDED 0x8
|
||||
#define CMD_IS_DELETED 0x01
|
||||
#define CMD_TRACE_ACTIVE 0x02
|
||||
#define CMD_HAS_EXEC_TRACES 0x04
|
||||
#define CMD_COMPILES_EXPANDED 0x08
|
||||
#define CMD_REDEF_IN_PROGRESS 0x10
|
||||
#define CMD_VIA_RESOLVER 0x20
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -1888,7 +1898,7 @@ typedef struct Interp {
|
||||
* compiled by the interpreter. Indexed by the
|
||||
* string representations of literals. Used to
|
||||
* avoid creating duplicate objects. */
|
||||
int compileEpoch; /* Holds the current "compilation epoch" for
|
||||
unsigned int compileEpoch; /* Holds the current "compilation epoch" for
|
||||
* this interpreter. This is incremented to
|
||||
* invalidate existing ByteCodes when, e.g., a
|
||||
* command with a compile procedure is
|
||||
@@ -2539,6 +2549,15 @@ typedef struct TclFileAttrProcs {
|
||||
TclSetFileAttrProc *setProc;/* The procedure for setting attrs. */
|
||||
} TclFileAttrProcs;
|
||||
|
||||
/*
|
||||
* Private flag value which controls Tcl_GetIndexFromObj*() routines
|
||||
* to instruct them not to cache lookups because the table will not
|
||||
* live long enough to make it worthwhile. Must not clash with public
|
||||
* flag value TCL_EXACT.
|
||||
*/
|
||||
|
||||
#define INDEX_TEMP_TABLE 2
|
||||
|
||||
/*
|
||||
* Opaque handle used in pipeline routines to encapsulate platform-dependent
|
||||
* state.
|
||||
@@ -2589,7 +2608,7 @@ typedef Tcl_ObjCmdProc *TclObjCmdProcType;
|
||||
*----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, int *lengthPtr,
|
||||
typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, size_t *lengthPtr,
|
||||
Tcl_Encoding *encodingPtr);
|
||||
|
||||
/*
|
||||
@@ -2601,9 +2620,9 @@ typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, int *lengthPtr,
|
||||
*/
|
||||
|
||||
typedef struct ProcessGlobalValue {
|
||||
int epoch; /* Epoch counter to detect changes in the
|
||||
size_t epoch; /* Epoch counter to detect changes in the
|
||||
* master value. */
|
||||
int numBytes; /* Length of the master string. */
|
||||
size_t numBytes; /* Length of the master string. */
|
||||
char *value; /* The master string value. */
|
||||
Tcl_Encoding encoding; /* system encoding when master string was
|
||||
* initialized. */
|
||||
@@ -2690,7 +2709,6 @@ MODULE_SCOPE const Tcl_ObjType tclListType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclDictType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclProcBodyType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclStringType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclArraySearchType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclEnsembleCmdType;
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
MODULE_SCOPE const Tcl_ObjType tclWideIntType;
|
||||
@@ -2761,6 +2779,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRInvoke;
|
||||
MODULE_SCOPE Tcl_NRPostProc TclNRReleaseValues;
|
||||
|
||||
MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp, Tcl_Obj *tailcallPtr);
|
||||
MODULE_SCOPE void TclPushTailcallPoint(Tcl_Interp *interp);
|
||||
@@ -2871,8 +2890,7 @@ MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp,
|
||||
Tcl_Channel chan);
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd;
|
||||
MODULE_SCOPE int TclClearRootEnsemble(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
MODULE_SCOPE Tcl_NRPostProc TclClearRootEnsemble;
|
||||
MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, int num,
|
||||
int *loc);
|
||||
MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr,
|
||||
@@ -2908,6 +2926,8 @@ MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr,
|
||||
MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr,
|
||||
Tcl_DString *toAppendPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr);
|
||||
MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp,
|
||||
Tcl_Obj *const *objv, int objc, int *objcPtr);
|
||||
MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
|
||||
MODULE_SCOPE void TclFinalizeAsync(void);
|
||||
MODULE_SCOPE void TclFinalizeDoubleConversion(void);
|
||||
@@ -3052,7 +3072,7 @@ MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr,
|
||||
int stackSize, int flags);
|
||||
MODULE_SCOPE int TclpFindVariable(const char *name, int *lengthPtr);
|
||||
MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr,
|
||||
int *lengthPtr, Tcl_Encoding *encodingPtr);
|
||||
size_t *lengthPtr, Tcl_Encoding *encodingPtr);
|
||||
MODULE_SCOPE void TclpInitLock(void);
|
||||
MODULE_SCOPE void TclpInitPlatform(void);
|
||||
MODULE_SCOPE void TclpInitUnlock(void);
|
||||
@@ -3110,13 +3130,25 @@ MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr,
|
||||
Tcl_Obj *newValue, Tcl_Encoding encoding);
|
||||
MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result);
|
||||
MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp,
|
||||
Tcl_Obj *const *objv, int objc, int subIdx,
|
||||
Tcl_Obj *bad, Tcl_Obj *fix);
|
||||
MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
|
||||
int numBytes);
|
||||
MODULE_SCOPE int TclStringCatObjv(Tcl_Interp *interp, int inPlace,
|
||||
int objc, Tcl_Obj *const objv[],
|
||||
Tcl_Obj **objPtrPtr);
|
||||
MODULE_SCOPE int TclStringFind(Tcl_Obj *needle, Tcl_Obj *haystack,
|
||||
int start);
|
||||
MODULE_SCOPE int TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack,
|
||||
int last);
|
||||
MODULE_SCOPE int TclStringMatch(const char *str, int strLen,
|
||||
const char *pattern, int ptnLen, int flags);
|
||||
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
|
||||
Tcl_Obj *patternObj, int flags);
|
||||
MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE int TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int count, Tcl_Obj **objPtrPtr);
|
||||
MODULE_SCOPE void TclSubstCompile(Tcl_Interp *interp, const char *bytes,
|
||||
int numBytes, int flags, int line,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3133,6 +3165,7 @@ MODULE_SCOPE int TclTrimLeft(const char *bytes, int numBytes,
|
||||
MODULE_SCOPE int TclTrimRight(const char *bytes, int numBytes,
|
||||
const char *trim, int numTrim);
|
||||
MODULE_SCOPE int TclUtfCasecmp(const char *cs, const char *ct);
|
||||
MODULE_SCOPE int TclUtfCount(int ch);
|
||||
MODULE_SCOPE Tcl_Obj * TclpNativeToNormalized(ClientData clientData);
|
||||
MODULE_SCOPE Tcl_Obj * TclpFilesystemPathType(Tcl_Obj *pathPtr);
|
||||
MODULE_SCOPE int TclpDlopen(Tcl_Interp *interp, Tcl_Obj *pathPtr,
|
||||
@@ -3466,6 +3499,9 @@ MODULE_SCOPE int TclCompileAppendCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileArrayExistsCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileArrayForCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileArraySetCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3963,7 +3999,7 @@ MODULE_SCOPE int TclObjCallVarTraces(Interp *iPtr, Var *arrayPtr,
|
||||
|
||||
MODULE_SCOPE int TclCompareObjKeys(void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
MODULE_SCOPE void TclFreeObjEntry(Tcl_HashEntry *hPtr);
|
||||
MODULE_SCOPE unsigned TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
MODULE_SCOPE TCL_HASH_TYPE TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
|
||||
MODULE_SCOPE int TclFullFinalizationRequested(void);
|
||||
|
||||
@@ -4043,7 +4079,7 @@ typedef const char *TclDTraceStr;
|
||||
TCL_DTRACE_OBJ_FREE(objPtr); \
|
||||
if ((objPtr)->bytes \
|
||||
&& ((objPtr)->bytes != tclEmptyStringRep)) { \
|
||||
ckfree((char *) (objPtr)->bytes); \
|
||||
ckfree((objPtr)->bytes); \
|
||||
} \
|
||||
(objPtr)->length = -1; \
|
||||
TclFreeObjStorage(objPtr); \
|
||||
@@ -4066,7 +4102,7 @@ typedef const char *TclDTraceStr;
|
||||
(objPtr) = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj))
|
||||
|
||||
# define TclFreeObjStorageEx(interp, objPtr) \
|
||||
ckfree((char *) (objPtr))
|
||||
ckfree(objPtr)
|
||||
|
||||
#undef USE_THREAD_ALLOC
|
||||
#undef USE_TCLALLOC
|
||||
@@ -4225,7 +4261,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
*/
|
||||
|
||||
#define TclGetString(objPtr) \
|
||||
((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr)))
|
||||
((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString(objPtr))
|
||||
|
||||
#define TclGetStringFromObj(objPtr, lenPtr) \
|
||||
((objPtr)->bytes \
|
||||
@@ -4260,11 +4296,11 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
*/
|
||||
|
||||
#define TclInvalidateStringRep(objPtr) \
|
||||
if (objPtr->bytes != NULL) { \
|
||||
if (objPtr->bytes != tclEmptyStringRep) { \
|
||||
ckfree((char *) objPtr->bytes); \
|
||||
if ((objPtr)->bytes != NULL) { \
|
||||
if ((objPtr)->bytes != tclEmptyStringRep) { \
|
||||
ckfree((objPtr)->bytes); \
|
||||
} \
|
||||
objPtr->bytes = NULL; \
|
||||
(objPtr)->bytes = NULL; \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4394,8 +4430,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
*----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define TclIsPureByteArray(objPtr) \
|
||||
(((objPtr)->typePtr==&tclByteArrayType) && ((objPtr)->bytes==NULL))
|
||||
MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -4675,7 +4710,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
|
||||
#define TclCleanupCommandMacro(cmdPtr) \
|
||||
if ((cmdPtr)->refCount-- <= 1) { \
|
||||
ckfree((char *) (cmdPtr));\
|
||||
ckfree(cmdPtr);\
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4833,7 +4868,7 @@ typedef struct NRE_callback {
|
||||
#else
|
||||
#define TCLNR_ALLOC(interp, ptr) \
|
||||
(ptr = ((ClientData) ckalloc(sizeof(NRE_callback))))
|
||||
#define TCLNR_FREE(interp, ptr) ckfree((char *) (ptr))
|
||||
#define TCLNR_FREE(interp, ptr) ckfree(ptr)
|
||||
#endif
|
||||
|
||||
#if NRE_ENABLE_ASSERTS
|
||||
|
||||
@@ -615,7 +615,7 @@ EXTERN char * TclDoubleDigits(double dv, int ndigits, int flags,
|
||||
EXTERN void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags,
|
||||
int force);
|
||||
/* 251 */
|
||||
EXTERN int TclRegisterLiteral(void *envPtr, char *bytes,
|
||||
EXTERN int TclRegisterLiteral(void *envPtr, const char *bytes,
|
||||
int length, int flags);
|
||||
|
||||
typedef struct TclIntStubs {
|
||||
@@ -873,7 +873,7 @@ typedef struct TclIntStubs {
|
||||
int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 248 */
|
||||
char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */
|
||||
void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */
|
||||
int (*tclRegisterLiteral) (void *envPtr, char *bytes, int length, int flags); /* 251 */
|
||||
int (*tclRegisterLiteral) (void *envPtr, const char *bytes, int length, int flags); /* 251 */
|
||||
} TclIntStubs;
|
||||
|
||||
extern const TclIntStubs *tclIntStubsPtr;
|
||||
|
||||
@@ -98,7 +98,7 @@ EXTERN int TclUnixCopyFile(const char *src, const char *dst,
|
||||
/* Slot 27 is reserved */
|
||||
/* Slot 28 is reserved */
|
||||
/* 29 */
|
||||
EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs);
|
||||
EXTERN int TclWinCPUID(int index, int *regs);
|
||||
/* 30 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
@@ -173,7 +173,7 @@ EXTERN void TclWinFlushDirtyChannels(void);
|
||||
/* 28 */
|
||||
EXTERN void TclWinResetInterfaces(void);
|
||||
/* 29 */
|
||||
EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs);
|
||||
EXTERN int TclWinCPUID(int index, int *regs);
|
||||
/* 30 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
@@ -247,7 +247,7 @@ EXTERN void TclMacOSXNotifierAddRunLoopMode(
|
||||
/* Slot 27 is reserved */
|
||||
/* Slot 28 is reserved */
|
||||
/* 29 */
|
||||
EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs);
|
||||
EXTERN int TclWinCPUID(int index, int *regs);
|
||||
/* 30 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
@@ -288,7 +288,7 @@ typedef struct TclIntPlatStubs {
|
||||
void (*reserved26)(void);
|
||||
void (*reserved27)(void);
|
||||
void (*reserved28)(void);
|
||||
int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */
|
||||
int (*tclWinCPUID) (int index, int *regs); /* 29 */
|
||||
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
|
||||
#endif /* UNIX */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
@@ -321,7 +321,7 @@ typedef struct TclIntPlatStubs {
|
||||
void (*tclWinSetInterfaces) (int wide); /* 26 */
|
||||
void (*tclWinFlushDirtyChannels) (void); /* 27 */
|
||||
void (*tclWinResetInterfaces) (void); /* 28 */
|
||||
int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */
|
||||
int (*tclWinCPUID) (int index, int *regs); /* 29 */
|
||||
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
@@ -354,7 +354,7 @@ typedef struct TclIntPlatStubs {
|
||||
void (*reserved26)(void);
|
||||
void (*reserved27)(void);
|
||||
void (*reserved28)(void);
|
||||
int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */
|
||||
int (*tclWinCPUID) (int index, int *regs); /* 29 */
|
||||
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
|
||||
#endif /* MACOSX */
|
||||
} TclIntPlatStubs;
|
||||
|
||||
+18
-47
@@ -336,7 +336,7 @@ Tcl_Init(
|
||||
Tcl_Interp *interp) /* Interpreter to initialize. */
|
||||
{
|
||||
if (tclPreInitScript != NULL) {
|
||||
if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
|
||||
if (Tcl_EvalEx(interp, tclPreInitScript, -1, 0) == TCL_ERROR) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -382,7 +382,7 @@ Tcl_Init(
|
||||
* alternate tclInit command before calling Tcl_Init().
|
||||
*/
|
||||
|
||||
return Tcl_Eval(interp,
|
||||
return Tcl_EvalEx(interp,
|
||||
"if {[namespace which -command tclInit] eq \"\"} {\n"
|
||||
" proc tclInit {} {\n"
|
||||
" global tcl_libPath tcl_library env tclDefaultLibrary\n"
|
||||
@@ -444,7 +444,7 @@ Tcl_Init(
|
||||
" error $msg\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"tclInit");
|
||||
"tclInit", -1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -660,14 +660,9 @@ NRInterpCmd(
|
||||
if (masterInterp == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (TclGetString(objv[5])[0] == '\0') {
|
||||
if (objc == 6) {
|
||||
return AliasDelete(interp, slaveInterp, objv[3]);
|
||||
}
|
||||
} else {
|
||||
return AliasCreate(interp, slaveInterp, masterInterp, objv[3],
|
||||
objv[5], objc - 6, objv + 6);
|
||||
}
|
||||
|
||||
return AliasCreate(interp, slaveInterp, masterInterp, objv[3],
|
||||
objv[5], objc - 6, objv + 6);
|
||||
}
|
||||
goto aliasArgs;
|
||||
}
|
||||
@@ -1795,11 +1790,9 @@ AliasNRCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument vector. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Alias *aliasPtr = clientData;
|
||||
int prefc, cmdc, i;
|
||||
Tcl_Obj **prefv, **cmdv;
|
||||
int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
|
||||
Tcl_Obj *listPtr;
|
||||
List *listRep;
|
||||
int flags = TCL_EVAL_INVOKE;
|
||||
@@ -1831,21 +1824,7 @@ AliasNRCmd(
|
||||
* only the source command should show, not the full target prefix.
|
||||
*/
|
||||
|
||||
if (isRootEnsemble) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = 1;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = prefc;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs += prefc - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are sending a 0-refCount obj, do not need a callback: it will be
|
||||
* cleaned up automatically. But we may need to clear the rootEnsemble
|
||||
* stuff ...
|
||||
*/
|
||||
|
||||
if (isRootEnsemble) {
|
||||
if (TclInitRewriteEnsemble(interp, 1, prefc, objv)) {
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
TclSkipTailcall(interp);
|
||||
@@ -1866,7 +1845,7 @@ AliasObjCmd(
|
||||
Tcl_Obj **prefv, **cmdv;
|
||||
Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC];
|
||||
Interp *tPtr = (Interp *) targetInterp;
|
||||
int isRootEnsemble = (tPtr->ensembleRewrite.sourceObjs == NULL);
|
||||
int isRootEnsemble;
|
||||
|
||||
/*
|
||||
* Append the arguments to the command prefix and invoke the command in
|
||||
@@ -1896,13 +1875,7 @@ AliasObjCmd(
|
||||
* only the source command should show, not the full target prefix.
|
||||
*/
|
||||
|
||||
if (isRootEnsemble) {
|
||||
tPtr->ensembleRewrite.sourceObjs = objv;
|
||||
tPtr->ensembleRewrite.numRemovedObjs = 1;
|
||||
tPtr->ensembleRewrite.numInsertedObjs = prefc;
|
||||
} else {
|
||||
tPtr->ensembleRewrite.numInsertedObjs += prefc - 1;
|
||||
}
|
||||
isRootEnsemble = TclInitRewriteEnsemble((Tcl_Interp *)tPtr, 1, prefc, objv);
|
||||
|
||||
/*
|
||||
* Protect the target interpreter if it isn't the same as the source
|
||||
@@ -1925,9 +1898,7 @@ AliasObjCmd(
|
||||
*/
|
||||
|
||||
if (isRootEnsemble) {
|
||||
tPtr->ensembleRewrite.sourceObjs = NULL;
|
||||
tPtr->ensembleRewrite.numRemovedObjs = 0;
|
||||
tPtr->ensembleRewrite.numInsertedObjs = 0;
|
||||
TclResetRewriteEnsemble((Tcl_Interp *)tPtr, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2392,7 +2363,7 @@ SlaveCreate(
|
||||
SlaveObjCmd, NRSlaveCmd, slaveInterp, SlaveObjCmdDeleteProc);
|
||||
Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);
|
||||
Tcl_SetHashValue(hPtr, slavePtr);
|
||||
Tcl_SetVar(slaveInterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(slaveInterp, "tcl_interactive", NULL, "0", TCL_GLOBAL_ONLY);
|
||||
|
||||
/*
|
||||
* Inherit the recursion limit.
|
||||
@@ -3219,8 +3190,8 @@ Tcl_MakeSafe(
|
||||
* Assume these functions all work. [Bug 2895741]
|
||||
*/
|
||||
|
||||
(void) Tcl_Eval(interp,
|
||||
"namespace eval ::tcl {namespace eval mathfunc {}}");
|
||||
(void) Tcl_EvalEx(interp,
|
||||
"namespace eval ::tcl {namespace eval mathfunc {}}", -1, 0);
|
||||
(void) Tcl_CreateAlias(interp, "::tcl::mathfunc::min", master,
|
||||
"::tcl::mathfunc::min", 0, NULL);
|
||||
(void) Tcl_CreateAlias(interp, "::tcl::mathfunc::max", master,
|
||||
@@ -4526,7 +4497,7 @@ SlaveCommandLimitCmd(
|
||||
switch ((enum Options) index) {
|
||||
case OPT_CMD:
|
||||
scriptObj = objv[i+1];
|
||||
(void) Tcl_GetStringFromObj(objv[i+1], &scriptLen);
|
||||
(void) TclGetStringFromObj(scriptObj, &scriptLen);
|
||||
break;
|
||||
case OPT_GRAN:
|
||||
granObj = objv[i+1];
|
||||
@@ -4543,7 +4514,7 @@ SlaveCommandLimitCmd(
|
||||
break;
|
||||
case OPT_VAL:
|
||||
limitObj = objv[i+1];
|
||||
(void) Tcl_GetStringFromObj(objv[i+1], &limitLen);
|
||||
(void) TclGetStringFromObj(objv[i+1], &limitLen);
|
||||
if (limitLen == 0) {
|
||||
break;
|
||||
}
|
||||
@@ -4735,7 +4706,7 @@ SlaveTimeLimitCmd(
|
||||
switch ((enum Options) index) {
|
||||
case OPT_CMD:
|
||||
scriptObj = objv[i+1];
|
||||
(void) Tcl_GetStringFromObj(objv[i+1], &scriptLen);
|
||||
(void) TclGetStringFromObj(objv[i+1], &scriptLen);
|
||||
break;
|
||||
case OPT_GRAN:
|
||||
granObj = objv[i+1];
|
||||
@@ -4752,7 +4723,7 @@ SlaveTimeLimitCmd(
|
||||
break;
|
||||
case OPT_MILLI:
|
||||
milliObj = objv[i+1];
|
||||
(void) Tcl_GetStringFromObj(objv[i+1], &milliLen);
|
||||
(void) TclGetStringFromObj(objv[i+1], &milliLen);
|
||||
if (milliLen == 0) {
|
||||
break;
|
||||
}
|
||||
@@ -4770,7 +4741,7 @@ SlaveTimeLimitCmd(
|
||||
break;
|
||||
case OPT_SEC:
|
||||
secObj = objv[i+1];
|
||||
(void) Tcl_GetStringFromObj(objv[i+1], &secLen);
|
||||
(void) TclGetStringFromObj(objv[i+1], &secLen);
|
||||
if (secLen == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -526,7 +526,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_STRING:
|
||||
value = Tcl_GetStringFromObj(valueObj, &valueLength);
|
||||
value = TclGetStringFromObj(valueObj, &valueLength);
|
||||
valueLength++;
|
||||
pp = (char **) linkPtr->addr;
|
||||
|
||||
|
||||
@@ -897,18 +897,18 @@ Tcl_ListObjReplace(
|
||||
}
|
||||
if (count < 0) {
|
||||
count = 0;
|
||||
} else if (numElems < first+count || first+count < 0) {
|
||||
/*
|
||||
* The 'first+count < 0' condition here guards agains integer
|
||||
* overflow in determining 'first+count'.
|
||||
*/
|
||||
} else if (first > INT_MAX - count /* Handle integer overflow */
|
||||
|| numElems < first+count) {
|
||||
|
||||
count = numElems - first;
|
||||
}
|
||||
|
||||
if (objc > LIST_MAX - (numElems - count)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max length of a Tcl list (%d elements) exceeded", LIST_MAX));
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max length of a Tcl list (%d elements) exceeded",
|
||||
LIST_MAX));
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
isShared = (listRepPtr->refCount > 1);
|
||||
@@ -1898,7 +1898,7 @@ SetListFromAny(
|
||||
while (--elemPtrs >= &listRepPtr->elements) {
|
||||
Tcl_DecrRefCount(*elemPtrs);
|
||||
}
|
||||
ckfree((char *) listRepPtr);
|
||||
ckfree(listRepPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (elemStart == limit) {
|
||||
|
||||
+32
-23
@@ -174,7 +174,7 @@ TclDeleteLiteralTable(
|
||||
Tcl_Obj *
|
||||
TclCreateLiteral(
|
||||
Interp *iPtr,
|
||||
char *bytes, /* The start of the string. Note that this is
|
||||
const char *bytes, /* The start of the string. Note that this is
|
||||
* not a NUL-terminated string. */
|
||||
int length, /* Number of bytes in the string. */
|
||||
unsigned hash, /* The string's hash. If -1, it will be
|
||||
@@ -214,7 +214,7 @@ TclCreateLiteral(
|
||||
if (globalPtrPtr) {
|
||||
*globalPtrPtr = globalPtr;
|
||||
}
|
||||
if (flags & LITERAL_ON_HEAP) {
|
||||
if ((flags & LITERAL_ON_HEAP)) {
|
||||
ckfree(bytes);
|
||||
}
|
||||
globalPtr->refCount++;
|
||||
@@ -222,26 +222,40 @@ TclCreateLiteral(
|
||||
}
|
||||
}
|
||||
if (!newPtr) {
|
||||
if (flags & LITERAL_ON_HEAP) {
|
||||
if ((flags & LITERAL_ON_HEAP)) {
|
||||
ckfree(bytes);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The literal is new to the interpreter. Add it to the global literal
|
||||
* table.
|
||||
* The literal is new to the interpreter.
|
||||
*/
|
||||
|
||||
TclNewObj(objPtr);
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
if (flags & LITERAL_ON_HEAP) {
|
||||
objPtr->bytes = bytes;
|
||||
if ((flags & LITERAL_ON_HEAP)) {
|
||||
objPtr->bytes = (char *) bytes;
|
||||
objPtr->length = length;
|
||||
} else {
|
||||
TclInitStringRep(objPtr, bytes, length);
|
||||
}
|
||||
|
||||
/* Should the new literal be shared globally? */
|
||||
|
||||
if ((flags & LITERAL_UNSHARED)) {
|
||||
/*
|
||||
* No, do *not* add it the global literal table
|
||||
* Make clear, that no global value is returned
|
||||
*/
|
||||
if (globalPtrPtr != NULL) {
|
||||
*globalPtrPtr = NULL;
|
||||
}
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Yes, add it to the global literal table.
|
||||
*/
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (LookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
|
||||
Tcl_Panic("%s: literal \"%.*s\" found globally but shouldn't be",
|
||||
@@ -251,6 +265,7 @@ TclCreateLiteral(
|
||||
|
||||
globalPtr = ckalloc(sizeof(LiteralEntry));
|
||||
globalPtr->objPtr = objPtr;
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
globalPtr->refCount = 1;
|
||||
globalPtr->nsPtr = nsPtr;
|
||||
globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
|
||||
@@ -360,7 +375,7 @@ int
|
||||
TclRegisterLiteral(
|
||||
void *ePtr, /* Points to the CompileEnv in whose object
|
||||
* array an object is found or created. */
|
||||
register char *bytes, /* Points to string for which to find or
|
||||
register const char *bytes, /* Points to string for which to find or
|
||||
* create an object in CompileEnv's object
|
||||
* array. */
|
||||
int length, /* Number of bytes in the string. If < 0, the
|
||||
@@ -398,7 +413,7 @@ TclRegisterLiteral(
|
||||
if ((objPtr->length == length) && ((length == 0)
|
||||
|| ((objPtr->bytes[0] == bytes[0])
|
||||
&& (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
|
||||
if (flags & LITERAL_ON_HEAP) {
|
||||
if ((flags & LITERAL_ON_HEAP)) {
|
||||
ckfree(bytes);
|
||||
}
|
||||
objIndex = (localPtr - envPtr->literalArrayPtr);
|
||||
@@ -417,7 +432,7 @@ TclRegisterLiteral(
|
||||
* the namespace as the interp's global NS.
|
||||
*/
|
||||
|
||||
if (flags & LITERAL_CMD_NAME) {
|
||||
if ((flags & LITERAL_CMD_NAME)) {
|
||||
if ((length >= 2) && (bytes[0] == ':') && (bytes[1] == ':')) {
|
||||
nsPtr = iPtr->globalNsPtr;
|
||||
} else {
|
||||
@@ -431,12 +446,13 @@ TclRegisterLiteral(
|
||||
* Is it in the interpreter's global literal table? If not, create it.
|
||||
*/
|
||||
|
||||
globalPtr = NULL;
|
||||
objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &new, nsPtr, flags,
|
||||
&globalPtr);
|
||||
objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash);
|
||||
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (globalPtr->refCount < 1) {
|
||||
if (globalPtr != NULL && globalPtr->refCount < 1) {
|
||||
Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
|
||||
"TclRegisterLiteral", (length>60? 60 : length), bytes,
|
||||
globalPtr->refCount);
|
||||
@@ -671,7 +687,7 @@ AddLocalLiteralEntry(
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
bytes = TclGetStringFromObj(objPtr, &length);
|
||||
Tcl_Panic("%s: literal \"%.*s\" wasn't found locally",
|
||||
"AddLocalLiteralEntry", (length>60? 60 : length), bytes);
|
||||
}
|
||||
@@ -1025,7 +1041,7 @@ TclInvalidateCmdLiteral(
|
||||
* invalidate a cmd literal. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, (char *) name,
|
||||
Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, name,
|
||||
strlen(name), -1, NULL, nsPtr, 0, NULL);
|
||||
|
||||
if (literalObjPtr != NULL) {
|
||||
@@ -1147,18 +1163,11 @@ TclVerifyLocalLiteralTable(
|
||||
localPtr=localPtr->nextPtr) {
|
||||
count++;
|
||||
if (localPtr->refCount != -1) {
|
||||
bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
|
||||
bytes = TclGetStringFromObj(localPtr->objPtr, &length);
|
||||
Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %d",
|
||||
"TclVerifyLocalLiteralTable",
|
||||
(length>60? 60 : length), bytes, localPtr->refCount);
|
||||
}
|
||||
if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
|
||||
localPtr->objPtr) == NULL) {
|
||||
bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
|
||||
Tcl_Panic("%s: local literal \"%.*s\" is not global",
|
||||
"TclVerifyLocalLiteralTable",
|
||||
(length>60? 60 : length), bytes);
|
||||
}
|
||||
if (localPtr->objPtr->bytes == NULL) {
|
||||
Tcl_Panic("%s: literal has NULL string rep",
|
||||
"TclVerifyLocalLiteralTable");
|
||||
@@ -1205,7 +1214,7 @@ TclVerifyGlobalLiteralTable(
|
||||
globalPtr=globalPtr->nextPtr) {
|
||||
count++;
|
||||
if (globalPtr->refCount < 1) {
|
||||
bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
|
||||
bytes = TclGetStringFromObj(globalPtr->objPtr, &length);
|
||||
Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
|
||||
"TclVerifyGlobalLiteralTable",
|
||||
(length>60? 60 : length), bytes, globalPtr->refCount);
|
||||
|
||||
+1
-1
@@ -1015,7 +1015,7 @@ Tcl_StaticPackage(
|
||||
* TclGetLoadedPackages --
|
||||
*
|
||||
* This function returns information about all of the files that are
|
||||
* loaded (either in a particular intepreter, or for all interpreters).
|
||||
* loaded (either in a particular interpreter, or for all interpreters).
|
||||
*
|
||||
* Results:
|
||||
* The return value is a standard Tcl completion code. If successful, a
|
||||
|
||||
+12
-23
@@ -112,7 +112,7 @@ typedef enum {
|
||||
PROMPT_CONTINUE /* Print prompt for command continuation */
|
||||
} PromptType;
|
||||
|
||||
typedef struct InteractiveState {
|
||||
typedef struct {
|
||||
Tcl_Channel input; /* The standard input channel from which lines
|
||||
* are read. */
|
||||
int tty; /* Non-zero means standard input is a
|
||||
@@ -246,7 +246,7 @@ Tcl_SourceRCFile(
|
||||
const char *fileName;
|
||||
Tcl_Channel chan;
|
||||
|
||||
fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
|
||||
fileName = Tcl_GetVar2(interp, "tcl_rcFileName", NULL, TCL_GLOBAL_ONLY);
|
||||
if (fileName != NULL) {
|
||||
Tcl_Channel c;
|
||||
const char *fullName;
|
||||
@@ -266,14 +266,18 @@ Tcl_SourceRCFile(
|
||||
|
||||
c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
|
||||
if (c != NULL) {
|
||||
Tcl_Obj *fullNameObj = Tcl_NewStringObj(fullName, -1);
|
||||
|
||||
Tcl_Close(NULL, c);
|
||||
if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
|
||||
Tcl_IncrRefCount(fullNameObj);
|
||||
if (Tcl_FSEvalFileEx(interp, fullNameObj, NULL) != TCL_OK) {
|
||||
chan = Tcl_GetStdChannel(TCL_STDERR);
|
||||
if (chan) {
|
||||
Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
|
||||
Tcl_WriteChars(chan, "\n", 1);
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(fullNameObj);
|
||||
}
|
||||
}
|
||||
Tcl_DStringFree(&temp);
|
||||
@@ -283,7 +287,7 @@ Tcl_SourceRCFile(
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_Main, Tcl_MainEx --
|
||||
* Tcl_MainEx --
|
||||
*
|
||||
* Main program for tclsh and most other Tcl-based applications.
|
||||
*
|
||||
@@ -532,7 +536,7 @@ Tcl_MainEx(
|
||||
* error messages troubles deeper in, so lop it back off.
|
||||
*/
|
||||
|
||||
Tcl_GetStringFromObj(is.commandPtr, &length);
|
||||
TclGetStringFromObj(is.commandPtr, &length);
|
||||
Tcl_SetObjLength(is.commandPtr, --length);
|
||||
code = Tcl_RecordAndEvalObj(interp, is.commandPtr,
|
||||
TCL_EVAL_GLOBAL);
|
||||
@@ -549,7 +553,7 @@ Tcl_MainEx(
|
||||
} else if (is.tty) {
|
||||
resultPtr = Tcl_GetObjResult(interp);
|
||||
Tcl_IncrRefCount(resultPtr);
|
||||
Tcl_GetStringFromObj(resultPtr, &length);
|
||||
TclGetStringFromObj(resultPtr, &length);
|
||||
chan = Tcl_GetStdChannel(TCL_STDOUT);
|
||||
if ((length > 0) && chan) {
|
||||
Tcl_WriteObj(chan, resultPtr);
|
||||
@@ -634,21 +638,6 @@ Tcl_MainEx(
|
||||
|
||||
Tcl_Exit(exitCode);
|
||||
}
|
||||
|
||||
#if (TCL_MAJOR_VERSION == 8) && !defined(UNICODE)
|
||||
#undef Tcl_Main
|
||||
extern DLLEXPORT void
|
||||
Tcl_Main(
|
||||
int argc, /* Number of arguments. */
|
||||
char **argv, /* Array of argument strings. */
|
||||
Tcl_AppInitProc *appInitProc)
|
||||
/* Application-specific initialization
|
||||
* function to call after most initialization
|
||||
* but before starting to execute commands. */
|
||||
{
|
||||
Tcl_MainEx(argc, argv, appInitProc, Tcl_CreateInterp());
|
||||
}
|
||||
#endif /* TCL_MAJOR_VERSION == 8 && !UNICODE */
|
||||
|
||||
#ifndef TCL_ASCII_MAIN
|
||||
|
||||
@@ -808,7 +797,7 @@ StdinProc(
|
||||
goto prompt;
|
||||
}
|
||||
isPtr->prompt = PROMPT_START;
|
||||
Tcl_GetStringFromObj(commandPtr, &length);
|
||||
TclGetStringFromObj(commandPtr, &length);
|
||||
Tcl_SetObjLength(commandPtr, --length);
|
||||
|
||||
/*
|
||||
@@ -839,7 +828,7 @@ StdinProc(
|
||||
chan = Tcl_GetStdChannel(TCL_STDOUT);
|
||||
|
||||
Tcl_IncrRefCount(resultPtr);
|
||||
Tcl_GetStringFromObj(resultPtr, &length);
|
||||
TclGetStringFromObj(resultPtr, &length);
|
||||
if ((length > 0) && (chan != NULL)) {
|
||||
Tcl_WriteObj(chan, resultPtr);
|
||||
Tcl_WriteChars(chan, "\n", 1);
|
||||
|
||||
+79
-51
@@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
long numNsCreated; /* Count of the number of namespaces created
|
||||
size_t numNsCreated; /* Count of the number of namespaces created
|
||||
* within the thread. This value is used as a
|
||||
* unique id for each namespace. Cannot be
|
||||
* per-interp because the nsId is used to
|
||||
@@ -59,7 +59,7 @@ typedef struct ResolvedNsName {
|
||||
* the name was resolved. NULL if the name is
|
||||
* fully qualified and thus the resolution
|
||||
* does not depend on the context. */
|
||||
int refCount; /* Reference count: 1 for each nsName object
|
||||
size_t refCount; /* Reference count: 1 for each nsName object
|
||||
* that has a pointer to this ResolvedNsName
|
||||
* structure as its internal rep. This
|
||||
* structure can be freed when refCount
|
||||
@@ -1105,8 +1105,6 @@ TclTeardownNamespace(
|
||||
Interp *iPtr = (Interp *) nsPtr->interp;
|
||||
register Tcl_HashEntry *entryPtr;
|
||||
Tcl_HashSearch search;
|
||||
Tcl_Namespace *childNsPtr;
|
||||
Tcl_Command cmd;
|
||||
int i;
|
||||
|
||||
/*
|
||||
@@ -1121,16 +1119,31 @@ TclTeardownNamespace(
|
||||
/*
|
||||
* Delete all commands in this namespace. Be careful when traversing the
|
||||
* hash table: when each command is deleted, it removes itself from the
|
||||
* command table.
|
||||
*
|
||||
* Don't optimize to Tcl_NextHashEntry() because of traces.
|
||||
* command table. Because of traces (and the desire to avoid the quadratic
|
||||
* problems of just using Tcl_FirstHashEntry over and over, [Bug
|
||||
* f97d4ee020]) we copy to a temporary array and then delete all those
|
||||
* commands.
|
||||
*/
|
||||
|
||||
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
|
||||
entryPtr != NULL;
|
||||
entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) {
|
||||
cmd = Tcl_GetHashValue(entryPtr);
|
||||
Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd);
|
||||
while (nsPtr->cmdTable.numEntries > 0) {
|
||||
int length = nsPtr->cmdTable.numEntries;
|
||||
Command **cmds = TclStackAlloc((Tcl_Interp *) iPtr,
|
||||
sizeof(Command *) * length);
|
||||
|
||||
i = 0;
|
||||
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
|
||||
entryPtr != NULL;
|
||||
entryPtr = Tcl_NextHashEntry(&search)) {
|
||||
cmds[i] = Tcl_GetHashValue(entryPtr);
|
||||
cmds[i]->refCount++;
|
||||
i++;
|
||||
}
|
||||
for (i = 0 ; i < length ; i++) {
|
||||
Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr,
|
||||
(Tcl_Command) cmds[i]);
|
||||
TclCleanupCommandMacro(cmds[i]);
|
||||
}
|
||||
TclStackFree((Tcl_Interp *) iPtr, cmds);
|
||||
}
|
||||
Tcl_DeleteHashTable(&nsPtr->cmdTable);
|
||||
Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
|
||||
@@ -1175,25 +1188,54 @@ TclTeardownNamespace(
|
||||
*
|
||||
* BE CAREFUL: When each child is deleted, it will divorce itself from its
|
||||
* parent. You can't traverse a hash table properly if its elements are
|
||||
* being deleted. We use only the Tcl_FirstHashEntry function to be safe.
|
||||
* being deleted. Because of traces (and the desire to avoid the
|
||||
* quadratic problems of just using Tcl_FirstHashEntry over and over, [Bug
|
||||
* f97d4ee020]) we copy to a temporary array and then delete all those
|
||||
* namespaces.
|
||||
*
|
||||
* Don't optimize to Tcl_NextHashEntry() because of traces.
|
||||
* Important: leave the hash table itself still live.
|
||||
*/
|
||||
|
||||
#ifndef BREAK_NAMESPACE_COMPAT
|
||||
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
|
||||
entryPtr != NULL;
|
||||
entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) {
|
||||
childNsPtr = Tcl_GetHashValue(entryPtr);
|
||||
Tcl_DeleteNamespace(childNsPtr);
|
||||
while (nsPtr->childTable.numEntries > 0) {
|
||||
int length = nsPtr->childTable.numEntries;
|
||||
Namespace **children = TclStackAlloc((Tcl_Interp *) iPtr,
|
||||
sizeof(Namespace *) * length);
|
||||
|
||||
i = 0;
|
||||
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
|
||||
entryPtr != NULL;
|
||||
entryPtr = Tcl_NextHashEntry(&search)) {
|
||||
children[i] = Tcl_GetHashValue(entryPtr);
|
||||
children[i]->refCount++;
|
||||
i++;
|
||||
}
|
||||
for (i = 0 ; i < length ; i++) {
|
||||
Tcl_DeleteNamespace((Tcl_Namespace *) children[i]);
|
||||
TclNsDecrRefCount(children[i]);
|
||||
}
|
||||
TclStackFree((Tcl_Interp *) iPtr, children);
|
||||
}
|
||||
#else
|
||||
if (nsPtr->childTablePtr != NULL) {
|
||||
for (entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search);
|
||||
entryPtr != NULL;
|
||||
entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr,&search)) {
|
||||
childNsPtr = Tcl_GetHashValue(entryPtr);
|
||||
Tcl_DeleteNamespace(childNsPtr);
|
||||
while (nsPtr->childTablePtr->numEntries > 0) {
|
||||
int length = nsPtr->childTablePtr->numEntries;
|
||||
Namespace **children = TclStackAlloc((Tcl_Interp *) iPtr,
|
||||
sizeof(Namespace *) * length);
|
||||
|
||||
i = 0;
|
||||
for (entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search);
|
||||
entryPtr != NULL;
|
||||
entryPtr = Tcl_NextHashEntry(&search)) {
|
||||
children[i] = Tcl_GetHashValue(entryPtr);
|
||||
children[i]->refCount++;
|
||||
i++;
|
||||
}
|
||||
for (i = 0 ; i < length ; i++) {
|
||||
Tcl_DeleteNamespace((Tcl_Namespace *) children[i]);
|
||||
TclNsDecrRefCount(children[i]);
|
||||
}
|
||||
TclStackFree((Tcl_Interp *) iPtr, children);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1284,8 +1326,7 @@ void
|
||||
TclNsDecrRefCount(
|
||||
Namespace *nsPtr)
|
||||
{
|
||||
nsPtr->refCount--;
|
||||
if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
|
||||
if ((nsPtr->refCount-- <= 1) && (nsPtr->flags & NS_DEAD)) {
|
||||
NamespaceFree(nsPtr);
|
||||
}
|
||||
}
|
||||
@@ -2524,7 +2565,9 @@ Tcl_FindCommand(
|
||||
}
|
||||
|
||||
if (result == TCL_OK) {
|
||||
((Command *)cmd)->flags |= CMD_VIA_RESOLVER;
|
||||
return cmd;
|
||||
|
||||
} else if (result != TCL_CONTINUE) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -2616,6 +2659,7 @@ Tcl_FindCommand(
|
||||
}
|
||||
|
||||
if (cmdPtr != NULL) {
|
||||
cmdPtr->flags &= ~CMD_VIA_RESOLVER;
|
||||
return (Tcl_Command) cmdPtr;
|
||||
}
|
||||
|
||||
@@ -2841,9 +2885,9 @@ GetNamespaceFromObj(
|
||||
resNamePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
nsPtr = resNamePtr->nsPtr;
|
||||
refNsPtr = resNamePtr->refNsPtr;
|
||||
if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp) &&
|
||||
(!refNsPtr || ((interp == refNsPtr->interp) &&
|
||||
(refNsPtr== (Namespace *) Tcl_GetCurrentNamespace(interp))))){
|
||||
if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp)
|
||||
&& (!refNsPtr || (refNsPtr ==
|
||||
(Namespace *) TclGetCurrentNamespace(interp)))) {
|
||||
*nsPtrPtr = (Tcl_Namespace *) nsPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -3312,14 +3356,7 @@ NRNamespaceEvalCmd(
|
||||
(void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
|
||||
namespacePtr, /*isProcCallFrame*/ 0);
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
|
||||
framePtr->objc = objc;
|
||||
framePtr->objv = objv;
|
||||
} else {
|
||||
framePtr->objc = objc + iPtr->ensembleRewrite.numRemovedObjs
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
framePtr->objv = iPtr->ensembleRewrite.sourceObjs;
|
||||
}
|
||||
framePtr->objv = TclFetchEnsembleRoot(interp, objv, objc, &framePtr->objc);
|
||||
|
||||
if (objc == 3) {
|
||||
/*
|
||||
@@ -3726,7 +3763,6 @@ NRNamespaceInscopeCmd(
|
||||
{
|
||||
Tcl_Namespace *namespacePtr;
|
||||
CallFrame *framePtr, **framePtrPtr;
|
||||
register Interp *iPtr = (Interp *) interp;
|
||||
int i;
|
||||
Tcl_Obj *cmdObjPtr;
|
||||
|
||||
@@ -3752,14 +3788,7 @@ NRNamespaceInscopeCmd(
|
||||
(void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
|
||||
namespacePtr, /*isProcCallFrame*/ 0);
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
|
||||
framePtr->objc = objc;
|
||||
framePtr->objv = objv;
|
||||
} else {
|
||||
framePtr->objc = objc + iPtr->ensembleRewrite.numRemovedObjs
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
framePtr->objv = iPtr->ensembleRewrite.sourceObjs;
|
||||
}
|
||||
framePtr->objv = TclFetchEnsembleRoot(interp, objv, objc, &framePtr->objc);
|
||||
|
||||
/*
|
||||
* Execute the command. If there is just one argument, just treat it as a
|
||||
@@ -4511,8 +4540,8 @@ NamespaceUpvarCmd(
|
||||
savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
|
||||
iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr;
|
||||
otherPtr = TclObjLookupVarEx(interp, objv[0], NULL,
|
||||
(TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
|
||||
/*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
|
||||
(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
|
||||
"access", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
|
||||
iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr;
|
||||
if (otherPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
@@ -4641,8 +4670,7 @@ FreeNsNameInternalRep(
|
||||
* references, free it up.
|
||||
*/
|
||||
|
||||
resNamePtr->refCount--;
|
||||
if (resNamePtr->refCount == 0) {
|
||||
if (resNamePtr->refCount-- <= 1) {
|
||||
/*
|
||||
* Decrement the reference count for the cached namespace. If the
|
||||
* namespace is dead, and there are no more references to it, free
|
||||
@@ -4752,7 +4780,7 @@ SetNsNameFromAny(
|
||||
if ((name[0] == ':') && (name[1] == ':')) {
|
||||
resNamePtr->refNsPtr = NULL;
|
||||
} else {
|
||||
resNamePtr->refNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
|
||||
resNamePtr->refNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
|
||||
}
|
||||
resNamePtr->refCount = 1;
|
||||
TclFreeIntRep(objPtr);
|
||||
|
||||
+13
-16
@@ -68,12 +68,9 @@ static int CloneObjectMethod(Tcl_Interp *interp, Object *oPtr,
|
||||
static void DeletedDefineNamespace(ClientData clientData);
|
||||
static void DeletedObjdefNamespace(ClientData clientData);
|
||||
static void DeletedHelpersNamespace(ClientData clientData);
|
||||
static int FinalizeAlloc(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int FinalizeNext(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int FinalizeObjectCall(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc FinalizeAlloc;
|
||||
static Tcl_NRPostProc FinalizeNext;
|
||||
static Tcl_NRPostProc FinalizeObjectCall;
|
||||
static int InitFoundation(Tcl_Interp *interp);
|
||||
static void KillFoundation(ClientData clientData,
|
||||
Tcl_Interp *interp);
|
||||
@@ -269,7 +266,7 @@ TclOOInit(
|
||||
* to be fully provided.
|
||||
*/
|
||||
|
||||
if (Tcl_Eval(interp, initScript) != TCL_OK) {
|
||||
if (Tcl_EvalEx(interp, initScript, -1, 0) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -463,7 +460,7 @@ InitFoundation(
|
||||
if (TclOODefineSlots(fPtr) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return Tcl_Eval(interp, slotScript);
|
||||
return Tcl_EvalEx(interp, slotScript, -1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1687,7 +1684,7 @@ Tcl_NewObjectInstance(
|
||||
TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL);
|
||||
|
||||
if (contextPtr != NULL) {
|
||||
int result;
|
||||
int isRoot, result;
|
||||
Tcl_InterpState state;
|
||||
|
||||
state = Tcl_SaveInterpState(interp, TCL_OK);
|
||||
@@ -1698,13 +1695,14 @@ Tcl_NewObjectInstance(
|
||||
* Adjust the ensmble tracking record if necessary. [Bug 3514761]
|
||||
*/
|
||||
|
||||
if (((Interp*) interp)->ensembleRewrite.sourceObjs) {
|
||||
((Interp*) interp)->ensembleRewrite.numInsertedObjs += skip-1;
|
||||
((Interp*) interp)->ensembleRewrite.numRemovedObjs += skip-1;
|
||||
}
|
||||
isRoot = TclInitRewriteEnsemble(interp, skip, skip, objv);
|
||||
result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr,
|
||||
objc, objv);
|
||||
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* It's an error if the object was whacked in the constructor.
|
||||
* Force this if it isn't already an error (don't want to lose
|
||||
@@ -1827,9 +1825,8 @@ TclNRNewObjectInstance(
|
||||
* Adjust the ensmble tracking record if necessary. [Bug 3514761]
|
||||
*/
|
||||
|
||||
if (((Interp *) interp)->ensembleRewrite.sourceObjs) {
|
||||
((Interp *) interp)->ensembleRewrite.numInsertedObjs += skip - 1;
|
||||
((Interp *) interp)->ensembleRewrite.numRemovedObjs += skip - 1;
|
||||
if (TclInitRewriteEnsemble(interp, skip, skip, objv)) {
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+4
-6
@@ -70,15 +70,12 @@ static void AddSimpleClassChainToCallContext(Class *classPtr,
|
||||
Class *const filterDecl);
|
||||
static int CmpStr(const void *ptr1, const void *ptr2);
|
||||
static void DupMethodNameRep(Tcl_Obj *srcPtr, Tcl_Obj *dstPtr);
|
||||
static int FinalizeMethodRefs(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc FinalizeMethodRefs;
|
||||
static void FreeMethodNameRep(Tcl_Obj *objPtr);
|
||||
static inline int IsStillValid(CallChain *callPtr, Object *oPtr,
|
||||
int flags, int reuseMask);
|
||||
static int ResetFilterFlags(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int SetFilterFlags(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc ResetFilterFlags;
|
||||
static Tcl_NRPostProc SetFilterFlags;
|
||||
static inline void StashCallChain(Tcl_Obj *objPtr, CallChain *callPtr);
|
||||
|
||||
/*
|
||||
@@ -182,6 +179,7 @@ StashCallChain(
|
||||
CallChain *callPtr)
|
||||
{
|
||||
callPtr->refCount++;
|
||||
TclGetString(objPtr);
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &methodNameType;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = callPtr;
|
||||
|
||||
+27
-53
@@ -525,7 +525,7 @@ TclOOUnknownDefinition(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
soughtStr = Tcl_GetStringFromObj(objv[1], &soughtLen);
|
||||
soughtStr = TclGetStringFromObj(objv[1], &soughtLen);
|
||||
if (soughtLen == 0) {
|
||||
goto noMatch;
|
||||
}
|
||||
@@ -585,7 +585,7 @@ FindCommand(
|
||||
Tcl_Namespace *const namespacePtr)
|
||||
{
|
||||
int length;
|
||||
const char *nameStr, *string = Tcl_GetStringFromObj(stringObj, &length);
|
||||
const char *nameStr, *string = TclGetStringFromObj(stringObj, &length);
|
||||
register Namespace *const nsPtr = (Namespace *) namespacePtr;
|
||||
FOREACH_HASH_DECLS;
|
||||
Tcl_Command cmd, cmd2;
|
||||
@@ -774,7 +774,7 @@ GenerateErrorInfo(
|
||||
int length;
|
||||
Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr)
|
||||
? savedNameObj : TclOOObjectName(interp, oPtr);
|
||||
const char *objName = Tcl_GetStringFromObj(realNameObj, &length);
|
||||
const char *objName = TclGetStringFromObj(realNameObj, &length);
|
||||
int limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT;
|
||||
int overflow = (length > limit);
|
||||
|
||||
@@ -847,9 +847,8 @@ TclOODefineObjCmd(
|
||||
TclDecrRefCount(objNameObj);
|
||||
} else {
|
||||
Tcl_Obj *objPtr, *obj2Ptr, **objs;
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Command cmd;
|
||||
int dummy;
|
||||
int isRoot, dummy;
|
||||
|
||||
/*
|
||||
* More than one argument: fire them through the ensemble processing
|
||||
@@ -861,18 +860,7 @@ TclOODefineObjCmd(
|
||||
* the moment. Ugly!
|
||||
*/
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = 3;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 1;
|
||||
} else {
|
||||
int ni = iPtr->ensembleRewrite.numInsertedObjs;
|
||||
if (ni < 3) {
|
||||
iPtr->ensembleRewrite.numRemovedObjs += 3 - ni;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs -= 2;
|
||||
}
|
||||
}
|
||||
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
|
||||
|
||||
/*
|
||||
* Build the list of arguments using a Tcl_Obj as a workspace. See
|
||||
@@ -894,6 +882,9 @@ TclOODefineObjCmd(
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
|
||||
|
||||
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
@@ -927,7 +918,7 @@ TclOOObjDefObjCmd(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Foundation *fPtr = TclOOGetFoundation(interp);
|
||||
int result;
|
||||
int isRoot, result;
|
||||
Object *oPtr;
|
||||
|
||||
if (objc < 3) {
|
||||
@@ -962,7 +953,6 @@ TclOOObjDefObjCmd(
|
||||
TclDecrRefCount(objNameObj);
|
||||
} else {
|
||||
Tcl_Obj *objPtr, *obj2Ptr, **objs;
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Command cmd;
|
||||
int dummy;
|
||||
|
||||
@@ -976,18 +966,7 @@ TclOOObjDefObjCmd(
|
||||
* the moment. Ugly!
|
||||
*/
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = 3;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 1;
|
||||
} else {
|
||||
int ni = iPtr->ensembleRewrite.numInsertedObjs;
|
||||
if (ni < 3) {
|
||||
iPtr->ensembleRewrite.numRemovedObjs += 3 - ni;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs -= 2;
|
||||
}
|
||||
}
|
||||
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
|
||||
|
||||
/*
|
||||
* Build the list of arguments using a Tcl_Obj as a workspace. See
|
||||
@@ -1009,6 +988,10 @@ TclOOObjDefObjCmd(
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
|
||||
|
||||
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
|
||||
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
@@ -1077,9 +1060,8 @@ TclOODefineSelfObjCmd(
|
||||
TclDecrRefCount(objNameObj);
|
||||
} else {
|
||||
Tcl_Obj *objPtr, *obj2Ptr, **objs;
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Command cmd;
|
||||
int dummy;
|
||||
int isRoot, dummy;
|
||||
|
||||
/*
|
||||
* More than one argument: fire them through the ensemble processing
|
||||
@@ -1091,18 +1073,7 @@ TclOODefineSelfObjCmd(
|
||||
* the moment. Ugly!
|
||||
*/
|
||||
|
||||
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = 2;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 1;
|
||||
} else {
|
||||
int ni = iPtr->ensembleRewrite.numInsertedObjs;
|
||||
if (ni < 2) {
|
||||
iPtr->ensembleRewrite.numRemovedObjs += 2 - ni;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs -= 1;
|
||||
}
|
||||
}
|
||||
isRoot = TclInitRewriteEnsemble(interp, 2, 1, objv);
|
||||
|
||||
/*
|
||||
* Build the list of arguments using a Tcl_Obj as a workspace. See
|
||||
@@ -1124,6 +1095,9 @@ TclOODefineSelfObjCmd(
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
|
||||
|
||||
result = Tcl_EvalObjv(interp, objc-1, objs, TCL_EVAL_INVOKE);
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
@@ -1265,7 +1239,7 @@ TclOODefineConstructorObjCmd(
|
||||
}
|
||||
clsPtr = oPtr->classPtr;
|
||||
|
||||
Tcl_GetStringFromObj(objv[2], &bodyLength);
|
||||
TclGetStringFromObj(objv[2], &bodyLength);
|
||||
if (bodyLength > 0) {
|
||||
/*
|
||||
* Create the method structure.
|
||||
@@ -1384,7 +1358,7 @@ TclOODefineDestructorObjCmd(
|
||||
}
|
||||
clsPtr = oPtr->classPtr;
|
||||
|
||||
Tcl_GetStringFromObj(objv[1], &bodyLength);
|
||||
TclGetStringFromObj(objv[1], &bodyLength);
|
||||
if (bodyLength > 0) {
|
||||
/*
|
||||
* Create the method structure.
|
||||
@@ -2243,7 +2217,7 @@ ClassSuperSet(
|
||||
"attempt to form circular dependency graph", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
|
||||
failedAfterAlloc:
|
||||
ckfree((char *) superclasses);
|
||||
ckfree(superclasses);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -2260,7 +2234,7 @@ ClassSuperSet(
|
||||
FOREACH(superPtr, oPtr->classPtr->superclasses) {
|
||||
TclOORemoveFromSubclasses(oPtr->classPtr, superPtr);
|
||||
}
|
||||
ckfree((char *) oPtr->classPtr->superclasses.list);
|
||||
ckfree(oPtr->classPtr->superclasses.list);
|
||||
}
|
||||
oPtr->classPtr->superclasses.list = superclasses;
|
||||
oPtr->classPtr->superclasses.num = superc;
|
||||
@@ -2349,7 +2323,7 @@ ClassVarsSet(
|
||||
}
|
||||
|
||||
for (i=0 ; i<varc ; i++) {
|
||||
const char *varName = Tcl_GetString(varv[i]);
|
||||
const char *varName = TclGetString(varv[i]);
|
||||
|
||||
if (strstr(varName, "::") != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
@@ -2375,7 +2349,7 @@ ClassVarsSet(
|
||||
}
|
||||
if (i != varc) {
|
||||
if (varc == 0) {
|
||||
ckfree((char *) oPtr->classPtr->variables.list);
|
||||
ckfree(oPtr->classPtr->variables.list);
|
||||
} else if (i) {
|
||||
oPtr->classPtr->variables.list = (Tcl_Obj **)
|
||||
ckrealloc((char *) oPtr->classPtr->variables.list,
|
||||
@@ -2630,7 +2604,7 @@ ObjVarsSet(
|
||||
}
|
||||
|
||||
for (i=0 ; i<varc ; i++) {
|
||||
const char *varName = Tcl_GetString(varv[i]);
|
||||
const char *varName = TclGetString(varv[i]);
|
||||
|
||||
if (strstr(varName, "::") != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
@@ -2656,7 +2630,7 @@ ObjVarsSet(
|
||||
}
|
||||
if (i != varc) {
|
||||
if (varc == 0) {
|
||||
ckfree((char *) oPtr->variables.list);
|
||||
ckfree(oPtr->variables.list);
|
||||
} else if (i) {
|
||||
oPtr->variables.list = (Tcl_Obj **)
|
||||
ckrealloc((char *) oPtr->variables.list,
|
||||
|
||||
+1
-1
@@ -592,7 +592,7 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
|
||||
#define AddRef(ptr) ((ptr)->refCount++)
|
||||
#define DelRef(ptr) do { \
|
||||
if ((ptr)->refCount-- <= 1) { \
|
||||
ckfree((char *) (ptr)); \
|
||||
ckfree(ptr); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
+11
-24
@@ -70,10 +70,8 @@ static Tcl_Obj ** InitEnsembleRewrite(Tcl_Interp *interp, int objc,
|
||||
static int InvokeProcedureMethod(ClientData clientData,
|
||||
Tcl_Interp *interp, Tcl_ObjectContext context,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static int FinalizeForwardCall(ClientData data[], Tcl_Interp *interp,
|
||||
int result);
|
||||
static int FinalizePMCall(ClientData data[], Tcl_Interp *interp,
|
||||
int result);
|
||||
static Tcl_NRPostProc FinalizeForwardCall;
|
||||
static Tcl_NRPostProc FinalizePMCall;
|
||||
static int PushMethodCallFrame(Tcl_Interp *interp,
|
||||
CallContext *contextPtr, ProcedureMethod *pmPtr,
|
||||
int objc, Tcl_Obj *const *objv,
|
||||
@@ -1168,7 +1166,7 @@ MethodErrorHandler(
|
||||
CallContext *contextPtr = ((Interp *) interp)->varFramePtr->clientData;
|
||||
Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
|
||||
const char *objectName, *kindName, *methodName =
|
||||
Tcl_GetStringFromObj(mPtr->namePtr, &nameLen);
|
||||
TclGetStringFromObj(mPtr->namePtr, &nameLen);
|
||||
Object *declarerPtr;
|
||||
|
||||
if (mPtr->declaringObjectPtr != NULL) {
|
||||
@@ -1458,6 +1456,11 @@ InvokeForwardMethod(
|
||||
argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
|
||||
numPrefixes, prefixObjs, &len);
|
||||
Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
|
||||
/*
|
||||
* NOTE: The combination of direct set of iPtr->lookupNsPtr and the use
|
||||
* of the TCL_EVAL_NOERR flag results in an evaluation configuration
|
||||
* very much like TCL_EVAL_INVOKE.
|
||||
*/
|
||||
((Interp *)interp)->lookupNsPtr
|
||||
= (Namespace *) contextPtr->oPtr->namespacePtr;
|
||||
return TclNREvalObjv(interp, len, argObjs, TCL_EVAL_NOERR, NULL);
|
||||
@@ -1594,12 +1597,9 @@ InitEnsembleRewrite(
|
||||
int *lengthPtr) /* Where to write the resulting length of the
|
||||
* array of rewritten arguments. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
|
||||
Tcl_Obj **argObjs;
|
||||
unsigned len = rewriteLength + objc - toRewrite;
|
||||
Tcl_Obj **argObjs = TclStackAlloc(interp, sizeof(Tcl_Obj *) * len);
|
||||
|
||||
argObjs = TclStackAlloc(interp, sizeof(Tcl_Obj *) * len);
|
||||
memcpy(argObjs, rewriteObjs, rewriteLength * sizeof(Tcl_Obj *));
|
||||
memcpy(argObjs + rewriteLength, objv + toRewrite,
|
||||
sizeof(Tcl_Obj *) * (objc - toRewrite));
|
||||
@@ -1613,22 +1613,9 @@ InitEnsembleRewrite(
|
||||
* (and unavoidably).
|
||||
*/
|
||||
|
||||
if (isRootEnsemble) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = toRewrite;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = rewriteLength;
|
||||
} else {
|
||||
int numIns = iPtr->ensembleRewrite.numInsertedObjs;
|
||||
|
||||
if (numIns < toRewrite) {
|
||||
iPtr->ensembleRewrite.numRemovedObjs += toRewrite - numIns;
|
||||
iPtr->ensembleRewrite.numInsertedObjs += rewriteLength - 1;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs +=
|
||||
rewriteLength - toRewrite;
|
||||
}
|
||||
if (TclInitRewriteEnsemble(interp, toRewrite, rewriteLength, objv)) {
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
*lengthPtr = len;
|
||||
return argObjs;
|
||||
}
|
||||
|
||||
+88
-101
@@ -320,7 +320,7 @@ const Tcl_HashKeyType tclObjHashKeyType = {
|
||||
* does allow them to delete a command when references to it are gone, which
|
||||
* is fragile but useful given their somewhat-OO style. Because of this, this
|
||||
* structure MUST NOT be const so that the C compiler puts the data in
|
||||
* writable memory. [Bug 2558422]
|
||||
* writable memory. [Bug 2558422] [Bug 07d13d99b0a9]
|
||||
* TODO: Provide a better API for those extensions so that they can coexist...
|
||||
*/
|
||||
|
||||
@@ -361,7 +361,7 @@ typedef struct ResolvedCmdName {
|
||||
* incremented; if so, the cmd was renamed,
|
||||
* deleted, hidden, or exposed, and so the
|
||||
* pointer is invalid. */
|
||||
int refCount; /* Reference count: 1 for each cmdName object
|
||||
size_t refCount; /* Reference count: 1 for each cmdName object
|
||||
* that has a pointer to this ResolvedCmdName
|
||||
* structure as its internal rep. This
|
||||
* structure can be freed when refCount
|
||||
@@ -402,7 +402,6 @@ TclInitObjSubsystem(void)
|
||||
Tcl_RegisterObjType(&tclListType);
|
||||
Tcl_RegisterObjType(&tclDictType);
|
||||
Tcl_RegisterObjType(&tclByteCodeType);
|
||||
Tcl_RegisterObjType(&tclArraySearchType);
|
||||
Tcl_RegisterObjType(&tclCmdNameType);
|
||||
Tcl_RegisterObjType(&tclRegexpType);
|
||||
Tcl_RegisterObjType(&tclProcBodyType);
|
||||
@@ -663,7 +662,7 @@ TclContinuationsEnterDerived(
|
||||
* better way which doesn't shimmer?)
|
||||
*/
|
||||
|
||||
Tcl_GetStringFromObj(objPtr, &length);
|
||||
TclGetStringFromObj(objPtr, &length);
|
||||
end = start + length; /* First char after the word */
|
||||
|
||||
/*
|
||||
@@ -1989,7 +1988,7 @@ TclSetBooleanFromAny(
|
||||
badBoolean:
|
||||
if (interp != NULL) {
|
||||
int length;
|
||||
const char *str = Tcl_GetStringFromObj(objPtr, &length);
|
||||
const char *str = TclGetStringFromObj(objPtr, &length);
|
||||
Tcl_Obj *msg;
|
||||
|
||||
TclNewLiteralStringObj(msg, "expected boolean value but got \"");
|
||||
@@ -3253,13 +3252,11 @@ UpdateStringOfBignum(
|
||||
if (status != MP_OKAY) {
|
||||
Tcl_Panic("radix size failure in UpdateStringOfBignum");
|
||||
}
|
||||
if (size == 3) {
|
||||
if (size < 2) {
|
||||
/*
|
||||
* mp_radix_size() returns 3 when more than INT_MAX bytes would be
|
||||
* mp_radix_size() returns < 2 when more than INT_MAX bytes would be
|
||||
* needed to hold the string rep (because mp_radix_size ignores
|
||||
* integer overflow issues). When we know the string rep will be more
|
||||
* than 3, we can conclude the string rep would overflow our string
|
||||
* length limits.
|
||||
* integer overflow issues).
|
||||
*
|
||||
* Note that so long as we enforce our bignums to the size that fits
|
||||
* in a packed bignum, this branch will never be taken.
|
||||
@@ -4048,7 +4045,7 @@ TclFreeObjEntry(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
TCL_HASH_TYPE
|
||||
TclHashObjKey(
|
||||
Tcl_HashTable *tablePtr, /* Hash table. */
|
||||
void *keyPtr) /* Key from which to compute hash value. */
|
||||
@@ -4098,7 +4095,7 @@ TclHashObjKey(
|
||||
result += (result << 3) + UCHAR(*++string);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return (TCL_HASH_TYPE) result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4152,11 +4149,10 @@ Tcl_GetCommandFromObj(
|
||||
*/
|
||||
|
||||
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if ((objPtr->typePtr == &tclCmdNameType) && (resPtr != NULL)) {
|
||||
if (objPtr->typePtr == &tclCmdNameType) {
|
||||
register Command *cmdPtr = resPtr->cmdPtr;
|
||||
|
||||
if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch)
|
||||
&& !(cmdPtr->flags & CMD_IS_DELETED)
|
||||
&& (interp == cmdPtr->nsPtr->interp)
|
||||
&& !(cmdPtr->nsPtr->flags & NS_DYING)) {
|
||||
register Namespace *refNsPtr = (Namespace *)
|
||||
@@ -4176,7 +4172,8 @@ Tcl_GetCommandFromObj(
|
||||
* had is invalid one way or another.
|
||||
*/
|
||||
|
||||
if (SetCmdNameFromAny(interp, objPtr) != TCL_OK) {
|
||||
/* See [07d13d99b0a9] why we cannot call SetCmdNameFromAny() directly here. */
|
||||
if (tclCmdNameType.setFromAnyProc(interp, objPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
@@ -4203,6 +4200,59 @@ Tcl_GetCommandFromObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
SetCmdNameObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr,
|
||||
Command *cmdPtr,
|
||||
ResolvedCmdName *resPtr)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
ResolvedCmdName *fillPtr;
|
||||
const char *name = TclGetString(objPtr);
|
||||
|
||||
if (resPtr) {
|
||||
fillPtr = resPtr;
|
||||
} else {
|
||||
fillPtr = ckalloc(sizeof(ResolvedCmdName));
|
||||
fillPtr->refCount = 1;
|
||||
}
|
||||
|
||||
fillPtr->cmdPtr = cmdPtr;
|
||||
cmdPtr->refCount++;
|
||||
fillPtr->cmdEpoch = cmdPtr->cmdEpoch;
|
||||
|
||||
/* NOTE: relying on NULL termination here. */
|
||||
if ((name[0] == ':') && (name[1] == ':')) {
|
||||
/*
|
||||
* Fully qualified names always resolve to same thing. No need
|
||||
* to record resolution context information.
|
||||
*/
|
||||
|
||||
fillPtr->refNsPtr = NULL;
|
||||
fillPtr->refNsId = 0; /* Will not be read */
|
||||
fillPtr->refNsCmdEpoch = 0; /* Will not be read */
|
||||
} else {
|
||||
/*
|
||||
* Record current state of current namespace as the resolution
|
||||
* context of this command name lookup.
|
||||
*/
|
||||
Namespace *currNsPtr = iPtr->varFramePtr->nsPtr;
|
||||
|
||||
fillPtr->refNsPtr = currNsPtr;
|
||||
fillPtr->refNsId = currNsPtr->nsId;
|
||||
fillPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
|
||||
}
|
||||
|
||||
if (resPtr == NULL) {
|
||||
TclFreeIntRep(objPtr);
|
||||
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = fillPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = &tclCmdNameType;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TclSetCmdNameObj(
|
||||
Tcl_Interp *interp, /* Points to interpreter containing command
|
||||
@@ -4212,45 +4262,16 @@ TclSetCmdNameObj(
|
||||
Command *cmdPtr) /* Points to Command structure that the
|
||||
* CmdName object should refer to. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
register ResolvedCmdName *resPtr;
|
||||
register Namespace *currNsPtr;
|
||||
const char *name;
|
||||
|
||||
if (objPtr->typePtr == &tclCmdNameType) {
|
||||
return;
|
||||
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (resPtr != NULL && resPtr->cmdPtr == cmdPtr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cmdPtr->refCount++;
|
||||
resPtr = ckalloc(sizeof(ResolvedCmdName));
|
||||
resPtr->cmdPtr = cmdPtr;
|
||||
resPtr->cmdEpoch = cmdPtr->cmdEpoch;
|
||||
resPtr->refCount = 1;
|
||||
|
||||
name = TclGetString(objPtr);
|
||||
if ((*name++ == ':') && (*name == ':')) {
|
||||
/*
|
||||
* The name is fully qualified: set the referring namespace to
|
||||
* NULL.
|
||||
*/
|
||||
|
||||
resPtr->refNsPtr = NULL;
|
||||
} else {
|
||||
/*
|
||||
* Get the current namespace.
|
||||
*/
|
||||
|
||||
currNsPtr = iPtr->varFramePtr->nsPtr;
|
||||
|
||||
resPtr->refNsPtr = currNsPtr;
|
||||
resPtr->refNsId = currNsPtr->nsId;
|
||||
resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
|
||||
}
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = resPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = &tclCmdNameType;
|
||||
SetCmdNameObj(interp, objPtr, cmdPtr, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4281,13 +4302,12 @@ FreeCmdNameInternalRep(
|
||||
{
|
||||
register ResolvedCmdName *resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
if (resPtr != NULL) {
|
||||
/*
|
||||
* Decrement the reference count of the ResolvedCmdName structure. If
|
||||
* there are no more uses, free the ResolvedCmdName structure.
|
||||
*/
|
||||
|
||||
if (resPtr->refCount-- == 1) {
|
||||
if (resPtr->refCount-- <= 1) {
|
||||
/*
|
||||
* Now free the cached command, unless it is still in its hash
|
||||
* table or if there are other references to it from other cmdName
|
||||
@@ -4299,7 +4319,6 @@ FreeCmdNameInternalRep(
|
||||
TclCleanupCommandMacro(cmdPtr);
|
||||
ckfree(resPtr);
|
||||
}
|
||||
}
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
@@ -4332,9 +4351,7 @@ DupCmdNameInternalRep(
|
||||
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = resPtr;
|
||||
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
if (resPtr != NULL) {
|
||||
resPtr->refCount++;
|
||||
}
|
||||
copyPtr->typePtr = &tclCmdNameType;
|
||||
}
|
||||
|
||||
@@ -4364,10 +4381,8 @@ SetCmdNameFromAny(
|
||||
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
|
||||
register Tcl_Obj *objPtr) /* The object to convert. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
const char *name;
|
||||
register Command *cmdPtr;
|
||||
Namespace *currNsPtr;
|
||||
register ResolvedCmdName *resPtr;
|
||||
|
||||
if (interp == NULL) {
|
||||
@@ -4387,59 +4402,31 @@ SetCmdNameFromAny(
|
||||
Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0);
|
||||
|
||||
/*
|
||||
* Free the old internalRep before setting the new one. Do this after
|
||||
* getting the string rep to allow the conversion code (in particular,
|
||||
* Tcl_GetStringFromObj) to use that old internalRep.
|
||||
* Stop shimmering and caching nothing when we found nothing. Just
|
||||
* report the failure to find the command as an error.
|
||||
*/
|
||||
|
||||
if (cmdPtr) {
|
||||
cmdPtr->refCount++;
|
||||
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if ((objPtr->typePtr == &tclCmdNameType)
|
||||
&& resPtr && (resPtr->refCount == 1)) {
|
||||
/*
|
||||
* Reuse the old ResolvedCmdName struct instead of freeing it
|
||||
*/
|
||||
if (cmdPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Command *oldCmdPtr = resPtr->cmdPtr;
|
||||
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if ((objPtr->typePtr == &tclCmdNameType) && (resPtr->refCount == 1)) {
|
||||
/*
|
||||
* Re-use existing ResolvedCmdName struct when possible.
|
||||
* Cleanup the old fields that need it.
|
||||
*/
|
||||
|
||||
if (--oldCmdPtr->refCount == 0) {
|
||||
TclCleanupCommandMacro(oldCmdPtr);
|
||||
}
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
resPtr = ckalloc(sizeof(ResolvedCmdName));
|
||||
resPtr->refCount = 1;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = resPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = &tclCmdNameType;
|
||||
}
|
||||
resPtr->cmdPtr = cmdPtr;
|
||||
resPtr->cmdEpoch = cmdPtr->cmdEpoch;
|
||||
if ((*name++ == ':') && (*name == ':')) {
|
||||
/*
|
||||
* The name is fully qualified: set the referring namespace to
|
||||
* NULL.
|
||||
*/
|
||||
Command *oldCmdPtr = resPtr->cmdPtr;
|
||||
|
||||
resPtr->refNsPtr = NULL;
|
||||
} else {
|
||||
/*
|
||||
* Get the current namespace.
|
||||
*/
|
||||
|
||||
currNsPtr = iPtr->varFramePtr->nsPtr;
|
||||
|
||||
resPtr->refNsPtr = currNsPtr;
|
||||
resPtr->refNsId = currNsPtr->nsId;
|
||||
resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
|
||||
if (oldCmdPtr->refCount-- <= 1) {
|
||||
TclCleanupCommandMacro(oldCmdPtr);
|
||||
}
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = &tclCmdNameType;
|
||||
resPtr = NULL;
|
||||
}
|
||||
|
||||
SetCmdNameObj(interp, objPtr, cmdPtr, resPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ ConvertZeroEffectToNOP(
|
||||
TclGetUInt1AtPtr(currentInstPtr + 1));
|
||||
int numBytes;
|
||||
|
||||
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
|
||||
(void) TclGetStringFromObj(litPtr, &numBytes);
|
||||
if (numBytes == 0) {
|
||||
blank = size + InstLength(nextInst);
|
||||
}
|
||||
@@ -248,7 +248,7 @@ ConvertZeroEffectToNOP(
|
||||
TclGetUInt4AtPtr(currentInstPtr + 1));
|
||||
int numBytes;
|
||||
|
||||
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
|
||||
(void) TclGetStringFromObj(litPtr, &numBytes);
|
||||
if (numBytes == 0) {
|
||||
blank = size + InstLength(nextInst);
|
||||
}
|
||||
|
||||
+77
-101
@@ -167,6 +167,8 @@ static int ParseTokens(const char *src, int numBytes, int mask,
|
||||
int flags, Tcl_Parse *parsePtr);
|
||||
static int ParseWhiteSpace(const char *src, int numBytes,
|
||||
int *incompletePtr, char *typePtr);
|
||||
static int ParseAllWhiteSpace(const char *src, int numBytes,
|
||||
int *incompletePtr);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -298,9 +300,43 @@ Tcl_ParseCommand(
|
||||
*/
|
||||
|
||||
parsePtr->commandStart = src;
|
||||
type = CHAR_TYPE(*src);
|
||||
scanned = 1; /* Can't have missing whitepsace before first word. */
|
||||
while (1) {
|
||||
int expandWord = 0;
|
||||
|
||||
/* Are we at command termination? */
|
||||
|
||||
if ((numBytes == 0) || (type & terminators) != 0) {
|
||||
parsePtr->term = src;
|
||||
parsePtr->commandSize = src + (numBytes != 0)
|
||||
- parsePtr->commandStart;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* Are we missing white space after previous word? */
|
||||
|
||||
if (scanned == 0) {
|
||||
if (src[-1] == '"') {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"extra characters after close-quote", -1));
|
||||
}
|
||||
parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA;
|
||||
} else {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"extra characters after close-brace", -1));
|
||||
}
|
||||
parsePtr->errorType = TCL_PARSE_BRACE_EXTRA;
|
||||
}
|
||||
parsePtr->term = src;
|
||||
error:
|
||||
Tcl_FreeParse(parsePtr);
|
||||
parsePtr->commandSize = parsePtr->end - parsePtr->commandStart;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the token for the word.
|
||||
*/
|
||||
@@ -310,23 +346,6 @@ Tcl_ParseCommand(
|
||||
tokenPtr = &parsePtr->tokenPtr[wordIndex];
|
||||
tokenPtr->type = TCL_TOKEN_WORD;
|
||||
|
||||
/*
|
||||
* Skip white space before the word. Also skip a backslash-newline
|
||||
* sequence: it should be treated just like white space.
|
||||
*/
|
||||
|
||||
scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type);
|
||||
src += scanned;
|
||||
numBytes -= scanned;
|
||||
if (numBytes == 0) {
|
||||
parsePtr->term = src;
|
||||
break;
|
||||
}
|
||||
if ((type & terminators) != 0) {
|
||||
parsePtr->term = src;
|
||||
src++;
|
||||
break;
|
||||
}
|
||||
tokenPtr->start = src;
|
||||
parsePtr->numTokens++;
|
||||
parsePtr->numWords++;
|
||||
@@ -546,52 +565,12 @@ Tcl_ParseCommand(
|
||||
tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do two additional checks: (a) make sure we're really at the end of
|
||||
* a word (there might have been garbage left after a quoted or braced
|
||||
* word), and (b) check for the end of the command.
|
||||
*/
|
||||
/* Parse the whitespace between words. */
|
||||
|
||||
scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type);
|
||||
if (scanned) {
|
||||
src += scanned;
|
||||
numBytes -= scanned;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numBytes == 0) {
|
||||
parsePtr->term = src;
|
||||
break;
|
||||
}
|
||||
if ((type & terminators) != 0) {
|
||||
parsePtr->term = src;
|
||||
src++;
|
||||
break;
|
||||
}
|
||||
if (src[-1] == '"') {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"extra characters after close-quote", -1));
|
||||
}
|
||||
parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA;
|
||||
} else {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"extra characters after close-brace", -1));
|
||||
}
|
||||
parsePtr->errorType = TCL_PARSE_BRACE_EXTRA;
|
||||
}
|
||||
parsePtr->term = src;
|
||||
goto error;
|
||||
src += scanned;
|
||||
numBytes -= scanned;
|
||||
}
|
||||
|
||||
parsePtr->commandSize = src - parsePtr->commandStart;
|
||||
return TCL_OK;
|
||||
|
||||
error:
|
||||
Tcl_FreeParse(parsePtr);
|
||||
parsePtr->commandSize = parsePtr->end - parsePtr->commandStart;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -733,22 +712,31 @@ ParseWhiteSpace(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ParseAllWhiteSpace(
|
||||
const char *src, /* First character to parse. */
|
||||
int numBytes, /* Max number of byes to scan */
|
||||
int *incompletePtr) /* Set true if parse is incomplete. */
|
||||
{
|
||||
char type;
|
||||
const char *p = src;
|
||||
|
||||
do {
|
||||
int scanned = ParseWhiteSpace(p, numBytes, incompletePtr, &type);
|
||||
|
||||
p += scanned;
|
||||
numBytes -= scanned;
|
||||
} while (numBytes && (*p == '\n') && (p++, --numBytes));
|
||||
return (p-src);
|
||||
}
|
||||
|
||||
int
|
||||
TclParseAllWhiteSpace(
|
||||
const char *src, /* First character to parse. */
|
||||
int numBytes) /* Max number of byes to scan */
|
||||
{
|
||||
int dummy;
|
||||
char type;
|
||||
const char *p = src;
|
||||
|
||||
do {
|
||||
int scanned = ParseWhiteSpace(p, numBytes, &dummy, &type);
|
||||
|
||||
p += scanned;
|
||||
numBytes -= scanned;
|
||||
} while (numBytes && (*p == '\n') && (p++, --numBytes));
|
||||
return (p-src);
|
||||
return ParseAllWhiteSpace(src, numBytes, &dummy);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1021,17 +1009,12 @@ ParseComment(
|
||||
* command. */
|
||||
{
|
||||
register const char *p = src;
|
||||
int incomplete = parsePtr->incomplete;
|
||||
|
||||
while (numBytes) {
|
||||
char type;
|
||||
int scanned;
|
||||
|
||||
do {
|
||||
scanned = ParseWhiteSpace(p, numBytes,
|
||||
&parsePtr->incomplete, &type);
|
||||
p += scanned;
|
||||
numBytes -= scanned;
|
||||
} while (numBytes && (*p == '\n') && (p++,numBytes--));
|
||||
int scanned = ParseAllWhiteSpace(p, numBytes, &incomplete);
|
||||
p += scanned;
|
||||
numBytes -= scanned;
|
||||
|
||||
if ((numBytes == 0) || (*p != '#')) {
|
||||
break;
|
||||
@@ -1040,35 +1023,28 @@ ParseComment(
|
||||
parsePtr->commentStart = p;
|
||||
}
|
||||
|
||||
p++;
|
||||
numBytes--;
|
||||
while (numBytes) {
|
||||
if (*p == '\\') {
|
||||
scanned = ParseWhiteSpace(p, numBytes, &parsePtr->incomplete,
|
||||
&type);
|
||||
if (scanned) {
|
||||
p += scanned;
|
||||
numBytes -= scanned;
|
||||
} else {
|
||||
/*
|
||||
* General backslash substitution in comments isn't part
|
||||
* of the formal spec, but test parse-15.47 and history
|
||||
* indicate that it has been the de facto rule. Don't
|
||||
* change it now.
|
||||
*/
|
||||
|
||||
TclParseBackslash(p, numBytes, &scanned, NULL);
|
||||
p += scanned;
|
||||
numBytes -= scanned;
|
||||
}
|
||||
} else {
|
||||
if (*p == '\n') {
|
||||
p++;
|
||||
numBytes--;
|
||||
if (p[-1] == '\n') {
|
||||
break;
|
||||
}
|
||||
if (*p == '\\') {
|
||||
p++;
|
||||
numBytes--;
|
||||
if (numBytes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
incomplete = (*p == '\n');
|
||||
p++;
|
||||
numBytes--;
|
||||
}
|
||||
parsePtr->commentSize = p - parsePtr->commentStart;
|
||||
}
|
||||
parsePtr->incomplete = incomplete;
|
||||
return (p - src);
|
||||
}
|
||||
|
||||
@@ -2244,7 +2220,7 @@ TclSubstTokens(
|
||||
if (result == 0) {
|
||||
clPos = 0;
|
||||
} else {
|
||||
Tcl_GetStringFromObj(result, &clPos);
|
||||
TclGetStringFromObj(result, &clPos);
|
||||
}
|
||||
|
||||
if (numCL >= maxNumCL) {
|
||||
@@ -2520,7 +2496,7 @@ TclObjCommandComplete(
|
||||
* check. */
|
||||
{
|
||||
int length;
|
||||
const char *script = Tcl_GetStringFromObj(objPtr, &length);
|
||||
const char *script = TclGetStringFromObj(objPtr, &length);
|
||||
|
||||
return CommandComplete(script, length);
|
||||
}
|
||||
|
||||
+33
-29
@@ -231,7 +231,7 @@ TclFSNormalizeAbsolutePath(
|
||||
retVal = Tcl_NewStringObj(path, dirSep - path);
|
||||
Tcl_IncrRefCount(retVal);
|
||||
}
|
||||
Tcl_GetStringFromObj(retVal, &curLen);
|
||||
TclGetStringFromObj(retVal, &curLen);
|
||||
if (curLen == 0) {
|
||||
Tcl_AppendToObj(retVal, dirSep, 1);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ TclFSNormalizeAbsolutePath(
|
||||
retVal = Tcl_NewStringObj(path, dirSep - path);
|
||||
Tcl_IncrRefCount(retVal);
|
||||
}
|
||||
Tcl_GetStringFromObj(retVal, &curLen);
|
||||
TclGetStringFromObj(retVal, &curLen);
|
||||
if (curLen == 0) {
|
||||
Tcl_AppendToObj(retVal, dirSep, 1);
|
||||
}
|
||||
@@ -288,7 +288,7 @@ TclFSNormalizeAbsolutePath(
|
||||
*/
|
||||
|
||||
const char *path =
|
||||
Tcl_GetStringFromObj(retVal, &curLen);
|
||||
TclGetStringFromObj(retVal, &curLen);
|
||||
|
||||
while (--curLen >= 0) {
|
||||
if (IsSeparatorOrNull(path[curLen])) {
|
||||
@@ -303,7 +303,7 @@ TclFSNormalizeAbsolutePath(
|
||||
Tcl_SetObjLength(retVal, curLen+1);
|
||||
Tcl_AppendObjToObj(retVal, linkObj);
|
||||
TclDecrRefCount(linkObj);
|
||||
linkStr = Tcl_GetStringFromObj(retVal, &curLen);
|
||||
linkStr = TclGetStringFromObj(retVal, &curLen);
|
||||
} else {
|
||||
/*
|
||||
* Absolute link.
|
||||
@@ -316,7 +316,7 @@ TclFSNormalizeAbsolutePath(
|
||||
} else {
|
||||
retVal = linkObj;
|
||||
}
|
||||
linkStr = Tcl_GetStringFromObj(retVal, &curLen);
|
||||
linkStr = TclGetStringFromObj(retVal, &curLen);
|
||||
|
||||
/*
|
||||
* Convert to forward-slashes on windows.
|
||||
@@ -333,7 +333,7 @@ TclFSNormalizeAbsolutePath(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
linkStr = Tcl_GetStringFromObj(retVal, &curLen);
|
||||
linkStr = TclGetStringFromObj(retVal, &curLen);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -404,7 +404,7 @@ TclFSNormalizeAbsolutePath(
|
||||
|
||||
if (tclPlatform == TCL_PLATFORM_WINDOWS) {
|
||||
int len;
|
||||
const char *path = Tcl_GetStringFromObj(retVal, &len);
|
||||
const char *path = TclGetStringFromObj(retVal, &len);
|
||||
|
||||
if (len == 2 && path[0] != 0 && path[1] == ':') {
|
||||
if (Tcl_IsShared(retVal)) {
|
||||
@@ -579,7 +579,7 @@ TclPathPart(
|
||||
|
||||
int numBytes;
|
||||
const char *rest =
|
||||
Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
|
||||
TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
|
||||
|
||||
if (strchr(rest, '/') != NULL) {
|
||||
goto standardPath;
|
||||
@@ -617,7 +617,7 @@ TclPathPart(
|
||||
|
||||
int numBytes;
|
||||
const char *rest =
|
||||
Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
|
||||
TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
|
||||
|
||||
if (strchr(rest, '/') != NULL) {
|
||||
goto standardPath;
|
||||
@@ -646,7 +646,7 @@ TclPathPart(
|
||||
const char *fileName, *extension;
|
||||
int length;
|
||||
|
||||
fileName = Tcl_GetStringFromObj(fsPathPtr->normPathPtr,
|
||||
fileName = TclGetStringFromObj(fsPathPtr->normPathPtr,
|
||||
&length);
|
||||
extension = TclGetExtension(fileName);
|
||||
if (extension == NULL) {
|
||||
@@ -698,7 +698,7 @@ TclPathPart(
|
||||
int length;
|
||||
const char *fileName, *extension;
|
||||
|
||||
fileName = Tcl_GetStringFromObj(pathPtr, &length);
|
||||
fileName = TclGetStringFromObj(pathPtr, &length);
|
||||
extension = TclGetExtension(fileName);
|
||||
if (extension == NULL) {
|
||||
Tcl_IncrRefCount(pathPtr);
|
||||
@@ -869,19 +869,23 @@ TclJoinPath(
|
||||
* object which can be normalized more efficiently. Currently we only
|
||||
* use the special case when we have exactly two elements, but we
|
||||
* could expand that in the future.
|
||||
*
|
||||
* Bugfix [a47641a0]. TclNewFSPathObj requires first argument
|
||||
* to be an absolute path. Added a check for that elt is absolute.
|
||||
*/
|
||||
|
||||
if ((i == (elements-2)) && (i == 0)
|
||||
&& (elt->typePtr == &tclFsPathType)
|
||||
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))) {
|
||||
Tcl_Obj *tailObj = objv[i+1];
|
||||
&& (elt->typePtr == &tclFsPathType)
|
||||
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
|
||||
&& TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
|
||||
Tcl_Obj *tailObj = objv[i+1];
|
||||
|
||||
type = TclGetPathType(tailObj, NULL, NULL, NULL);
|
||||
if (type == TCL_PATH_RELATIVE) {
|
||||
const char *str;
|
||||
int len;
|
||||
|
||||
str = Tcl_GetStringFromObj(tailObj, &len);
|
||||
str = TclGetStringFromObj(tailObj, &len);
|
||||
if (len == 0) {
|
||||
/*
|
||||
* This happens if we try to handle the root volume '/'.
|
||||
@@ -943,7 +947,7 @@ TclJoinPath(
|
||||
}
|
||||
}
|
||||
}
|
||||
strElt = Tcl_GetStringFromObj(elt, &strEltLen);
|
||||
strElt = TclGetStringFromObj(elt, &strEltLen);
|
||||
type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
|
||||
if (type != TCL_PATH_RELATIVE) {
|
||||
/*
|
||||
@@ -1030,9 +1034,9 @@ TclJoinPath(
|
||||
noQuickReturn:
|
||||
if (res == NULL) {
|
||||
res = Tcl_NewObj();
|
||||
ptr = Tcl_GetStringFromObj(res, &length);
|
||||
ptr = TclGetStringFromObj(res, &length);
|
||||
} else {
|
||||
ptr = Tcl_GetStringFromObj(res, &length);
|
||||
ptr = TclGetStringFromObj(res, &length);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1077,7 +1081,7 @@ TclJoinPath(
|
||||
|
||||
if (length > 0 && ptr[length -1] != '/') {
|
||||
Tcl_AppendToObj(res, &separator, 1);
|
||||
Tcl_GetStringFromObj(res, &length);
|
||||
TclGetStringFromObj(res, &length);
|
||||
}
|
||||
Tcl_SetObjLength(res, length + (int) strlen(strElt));
|
||||
|
||||
@@ -1372,7 +1376,7 @@ AppendPath(
|
||||
* intrep produce the same results; that is, bugward compatibility. If
|
||||
* we need to fix that bug here, it needs fixing in TclJoinPath() too.
|
||||
*/
|
||||
bytes = Tcl_GetStringFromObj(tail, &numBytes);
|
||||
bytes = TclGetStringFromObj(tail, &numBytes);
|
||||
if (numBytes == 0) {
|
||||
Tcl_AppendToObj(copy, "/", 1);
|
||||
} else {
|
||||
@@ -1431,7 +1435,7 @@ TclFSMakePathRelative(
|
||||
* too little below, leading to wrong answers returned by glob.
|
||||
*/
|
||||
|
||||
tempStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
|
||||
tempStr = TclGetStringFromObj(cwdPtr, &cwdLen);
|
||||
|
||||
/*
|
||||
* Should we perhaps use 'Tcl_FSPathSeparator'? But then what about the
|
||||
@@ -1451,7 +1455,7 @@ TclFSMakePathRelative(
|
||||
}
|
||||
break;
|
||||
}
|
||||
tempStr = Tcl_GetStringFromObj(pathPtr, &len);
|
||||
tempStr = TclGetStringFromObj(pathPtr, &len);
|
||||
|
||||
return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen);
|
||||
}
|
||||
@@ -1715,7 +1719,7 @@ Tcl_FSGetTranslatedStringPath(
|
||||
|
||||
if (transPtr != NULL) {
|
||||
int len;
|
||||
const char *orig = Tcl_GetStringFromObj(transPtr, &len);
|
||||
const char *orig = TclGetStringFromObj(transPtr, &len);
|
||||
char *result = ckalloc(len+1);
|
||||
|
||||
memcpy(result, orig, (size_t) len+1);
|
||||
@@ -1776,7 +1780,7 @@ Tcl_FSGetNormalizedPath(
|
||||
UpdateStringOfFsPath(pathPtr);
|
||||
}
|
||||
|
||||
Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &tailLen);
|
||||
TclGetStringFromObj(fsPathPtr->normPathPtr, &tailLen);
|
||||
if (tailLen) {
|
||||
copy = AppendPath(dir, fsPathPtr->normPathPtr);
|
||||
} else {
|
||||
@@ -1789,7 +1793,7 @@ Tcl_FSGetNormalizedPath(
|
||||
* We now own a reference on both 'dir' and 'copy'
|
||||
*/
|
||||
|
||||
(void) Tcl_GetStringFromObj(dir, &cwdLen);
|
||||
(void) TclGetStringFromObj(dir, &cwdLen);
|
||||
cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
|
||||
|
||||
/* Normalize the combined string. */
|
||||
@@ -1883,7 +1887,7 @@ Tcl_FSGetNormalizedPath(
|
||||
|
||||
copy = AppendPath(fsPathPtr->cwdPtr, pathPtr);
|
||||
|
||||
(void) Tcl_GetStringFromObj(fsPathPtr->cwdPtr, &cwdLen);
|
||||
(void) TclGetStringFromObj(fsPathPtr->cwdPtr, &cwdLen);
|
||||
cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
|
||||
|
||||
/*
|
||||
@@ -2333,7 +2337,7 @@ SetFsPathFromAny(
|
||||
* cmdAH.test exercise most of the code).
|
||||
*/
|
||||
|
||||
name = Tcl_GetStringFromObj(pathPtr, &len);
|
||||
name = TclGetStringFromObj(pathPtr, &len);
|
||||
|
||||
/*
|
||||
* Handle tilde substitutions, if needed.
|
||||
@@ -2602,7 +2606,7 @@ UpdateStringOfFsPath(
|
||||
|
||||
copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr);
|
||||
|
||||
pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
|
||||
pathPtr->bytes = TclGetStringFromObj(copy, &cwdLen);
|
||||
pathPtr->length = cwdLen;
|
||||
copy->bytes = tclEmptyStringRep;
|
||||
copy->length = 0;
|
||||
@@ -2663,7 +2667,7 @@ TclNativePathInFilesystem(
|
||||
|
||||
int len;
|
||||
|
||||
(void) Tcl_GetStringFromObj(pathPtr, &len);
|
||||
(void) TclGetStringFromObj(pathPtr, &len);
|
||||
if (len == 0) {
|
||||
/*
|
||||
* We reject the empty path "".
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ static TclFile FileForRedirect(Tcl_Interp *interp, const char *spec,
|
||||
|
||||
static TclFile
|
||||
FileForRedirect(
|
||||
Tcl_Interp *interp, /* Intepreter to use for error reporting. */
|
||||
Tcl_Interp *interp, /* Interpreter to use for error reporting. */
|
||||
const char *spec, /* Points to character just after redirection
|
||||
* character. */
|
||||
int atOK, /* Non-zero means that '@' notation can be
|
||||
|
||||
+5
-5
@@ -842,7 +842,7 @@ Tcl_PackageObjCmd(
|
||||
} else {
|
||||
pkgPtr = FindPackage(interp, argv2);
|
||||
}
|
||||
argv3 = Tcl_GetStringFromObj(objv[3], &length);
|
||||
argv3 = TclGetStringFromObj(objv[3], &length);
|
||||
|
||||
for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
|
||||
prevPtr = availPtr, availPtr = availPtr->nextPtr) {
|
||||
@@ -883,7 +883,7 @@ Tcl_PackageObjCmd(
|
||||
prevPtr->nextPtr = availPtr;
|
||||
}
|
||||
}
|
||||
argv4 = Tcl_GetStringFromObj(objv[4], &length);
|
||||
argv4 = TclGetStringFromObj(objv[4], &length);
|
||||
DupBlock(availPtr->script, argv4, (unsigned) length + 1);
|
||||
break;
|
||||
}
|
||||
@@ -1034,7 +1034,7 @@ Tcl_PackageObjCmd(
|
||||
if (iPtr->packageUnknown != NULL) {
|
||||
ckfree(iPtr->packageUnknown);
|
||||
}
|
||||
argv2 = Tcl_GetStringFromObj(objv[2], &length);
|
||||
argv2 = TclGetStringFromObj(objv[2], &length);
|
||||
if (argv2[0] == 0) {
|
||||
iPtr->packageUnknown = NULL;
|
||||
} else {
|
||||
@@ -1682,7 +1682,7 @@ AddRequirementsToResult(
|
||||
int i, length;
|
||||
|
||||
for (i = 0; i < reqc; i++) {
|
||||
const char *v = Tcl_GetStringFromObj(reqv[i], &length);
|
||||
const char *v = TclGetStringFromObj(reqv[i], &length);
|
||||
|
||||
if ((length & 0x1) && (v[length/2] == '-')
|
||||
&& (strncmp(v, v+((length+1)/2), length/2) == 0)) {
|
||||
@@ -1895,7 +1895,7 @@ Tcl_PkgInitStubsCheck(
|
||||
{
|
||||
const char *actualVersion = Tcl_PkgPresent(interp, "Tcl", version, 0);
|
||||
|
||||
if (exact && actualVersion) {
|
||||
if ((exact&1) && actualVersion) {
|
||||
const char *p = version;
|
||||
int count = 0;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
typedef struct {
|
||||
ClientData clientData; /* Address of preserved block. */
|
||||
int refCount; /* Number of Tcl_Preserve calls in effect for
|
||||
size_t refCount; /* Number of Tcl_Preserve calls in effect for
|
||||
* block. */
|
||||
int mustFree; /* Non-zero means Tcl_EventuallyFree was
|
||||
* called while a Tcl_Preserve call was in
|
||||
@@ -63,7 +63,7 @@ typedef struct HandleStruct {
|
||||
* ensure that the contents of the handle are
|
||||
* not changed by anyone else. */
|
||||
#endif
|
||||
int refCount; /* Number of TclHandlePreserve() calls in
|
||||
size_t refCount; /* Number of TclHandlePreserve() calls in
|
||||
* effect on this handle. */
|
||||
} HandleStruct;
|
||||
|
||||
@@ -195,7 +195,7 @@ Tcl_Release(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (--refPtr->refCount != 0) {
|
||||
if (refPtr->refCount-- > 1) {
|
||||
Tcl_MutexUnlock(&preserveMutex);
|
||||
return;
|
||||
}
|
||||
@@ -459,7 +459,7 @@ TclHandleRelease(
|
||||
handlePtr, handlePtr->ptr2, handlePtr->ptr);
|
||||
}
|
||||
#endif
|
||||
if ((--handlePtr->refCount == 0) && (handlePtr->ptr == NULL)) {
|
||||
if ((handlePtr->refCount-- <= 1) && (handlePtr->ptr == NULL)) {
|
||||
ckfree(handlePtr);
|
||||
}
|
||||
}
|
||||
|
||||
+63
-127
@@ -22,7 +22,6 @@
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int isRootEnsemble;
|
||||
Command cmd;
|
||||
ExtraFrameInfo efi;
|
||||
} ApplyExtraData;
|
||||
@@ -69,9 +68,8 @@ const Tcl_ObjType tclProcBodyType = {
|
||||
};
|
||||
|
||||
/*
|
||||
* The [upvar]/[uplevel] level reference type. Uses the twoPtrValue field,
|
||||
* encoding the type of level reference in ptr and the actual parsed out
|
||||
* offset in ptr2.
|
||||
* The [upvar]/[uplevel] level reference type. Uses the longValue field
|
||||
* to remember the integer value of a parsed #<integer> format.
|
||||
*
|
||||
* Uses the default behaviour throughout, and never disposes of the string
|
||||
* rep; it's just a cache type.
|
||||
@@ -345,7 +343,7 @@ Tcl_ProcObjCmd(
|
||||
* The argument list is just "args"; check the body
|
||||
*/
|
||||
|
||||
procBody = Tcl_GetStringFromObj(objv[3], &numBytes);
|
||||
procBody = TclGetStringFromObj(objv[3], &numBytes);
|
||||
if (TclParseAllWhiteSpace(procBody, numBytes) < numBytes) {
|
||||
goto done;
|
||||
}
|
||||
@@ -785,7 +783,7 @@ TclGetFrame(
|
||||
* Results:
|
||||
* The return value is -1 if an error occurred in finding the frame (in
|
||||
* this case an error message is left in the interp's result). 1 is
|
||||
* returned if objPtr was either a number or a number preceded by "#" and
|
||||
* returned if objPtr was either an int or an int preceded by "#" and
|
||||
* it specified a valid frame. 0 is returned if objPtr isn't one of the
|
||||
* two things above (in this case, the lookup acts as if objPtr were
|
||||
* "1"). The variable pointed to by framePtrPtr is filled in with the
|
||||
@@ -807,97 +805,71 @@ TclObjGetFrame(
|
||||
{
|
||||
register Interp *iPtr = (Interp *) interp;
|
||||
int curLevel, level, result;
|
||||
CallFrame *framePtr;
|
||||
const char *name;
|
||||
const char *name = NULL;
|
||||
|
||||
/*
|
||||
* Parse object to figure out which level number to go to.
|
||||
*/
|
||||
|
||||
result = 1;
|
||||
result = 0;
|
||||
curLevel = iPtr->varFramePtr->level;
|
||||
if (objPtr == NULL) {
|
||||
name = "1";
|
||||
goto haveLevel1;
|
||||
}
|
||||
|
||||
name = TclGetString(objPtr);
|
||||
if (objPtr->typePtr == &levelReferenceType) {
|
||||
if (objPtr->internalRep.twoPtrValue.ptr1) {
|
||||
level = curLevel - PTR2INT(objPtr->internalRep.twoPtrValue.ptr2);
|
||||
} else {
|
||||
level = PTR2INT(objPtr->internalRep.twoPtrValue.ptr2);
|
||||
}
|
||||
if (level < 0) {
|
||||
goto levelError;
|
||||
}
|
||||
/* TODO: Consider skipping the typePtr checks */
|
||||
} else if (objPtr->typePtr == &tclIntType
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
|| objPtr->typePtr == &tclWideIntType
|
||||
#endif
|
||||
) {
|
||||
if (TclGetIntFromObj(NULL, objPtr, &level) != TCL_OK || level < 0) {
|
||||
goto levelError;
|
||||
}
|
||||
level = curLevel - level;
|
||||
} else if (*name == '#') {
|
||||
if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) {
|
||||
goto levelError;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache for future reference.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &levelReferenceType;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = (void *) 0;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(level);
|
||||
} else if (isdigit(UCHAR(*name))) { /* INTL: digit */
|
||||
if (Tcl_GetInt(interp, name, &level) != TCL_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache for future reference.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &levelReferenceType;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = (void *) 1;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(level);
|
||||
level = curLevel - level;
|
||||
} else {
|
||||
/*
|
||||
* Don't cache as the object *isn't* a level reference (might even be
|
||||
* NULL...)
|
||||
*/
|
||||
|
||||
haveLevel1:
|
||||
level = curLevel - 1;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out which frame to use, and return it to the caller.
|
||||
* Check for integer first, since that has potential to spare us
|
||||
* a generation of a stringrep.
|
||||
*/
|
||||
|
||||
for (framePtr = iPtr->varFramePtr; framePtr != NULL;
|
||||
framePtr = framePtr->callerVarPtr) {
|
||||
if (framePtr->level == level) {
|
||||
break;
|
||||
if (objPtr == NULL) {
|
||||
/* Do nothing */
|
||||
} else if (TCL_OK == Tcl_GetIntFromObj(NULL, objPtr, &level)
|
||||
&& (level >= 0)) {
|
||||
level = curLevel - level;
|
||||
result = 1;
|
||||
} else if (objPtr->typePtr == &levelReferenceType) {
|
||||
level = (int) objPtr->internalRep.longValue;
|
||||
result = 1;
|
||||
} else {
|
||||
name = TclGetString(objPtr);
|
||||
if (name[0] == '#') {
|
||||
if (TCL_OK == Tcl_GetInt(NULL, name+1, &level) && level >= 0) {
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &levelReferenceType;
|
||||
objPtr->internalRep.longValue = level;
|
||||
result = 1;
|
||||
} else {
|
||||
result = -1;
|
||||
}
|
||||
} else if (isdigit(UCHAR(name[0]))) { /* INTL: digit */
|
||||
/*
|
||||
* If this were an integer, we'd have succeeded already.
|
||||
* Docs say we have to treat this as a 'bad level' error.
|
||||
*/
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
level = curLevel - 1;
|
||||
name = "1";
|
||||
}
|
||||
if (result != -1) {
|
||||
if (level >= 0) {
|
||||
CallFrame *framePtr;
|
||||
for (framePtr = iPtr->varFramePtr; framePtr != NULL;
|
||||
framePtr = framePtr->callerVarPtr) {
|
||||
if (framePtr->level == level) {
|
||||
*framePtrPtr = framePtr;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name == NULL) {
|
||||
name = TclGetString(objPtr);
|
||||
}
|
||||
}
|
||||
if (framePtr == NULL) {
|
||||
goto levelError;
|
||||
}
|
||||
*framePtrPtr = framePtr;
|
||||
return result;
|
||||
|
||||
levelError:
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "STACKLEVEL", NULL);
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1115,12 +1087,10 @@ ProcWrongNumArgs(
|
||||
if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) {
|
||||
desiredObjs[0] = Tcl_NewStringObj("lambdaExpr", -1);
|
||||
} else {
|
||||
((Interp *) interp)->ensembleRewrite.numInsertedObjs -= skip - 1;
|
||||
|
||||
#ifdef AVOID_HACKS_FOR_ITCL
|
||||
desiredObjs[0] = framePtr->objv[skip-1];
|
||||
#else
|
||||
desiredObjs[0] = Tcl_NewListObj(skip, framePtr->objv);
|
||||
desiredObjs[0] = Tcl_NewListObj(1, framePtr->objv + skip - 1);
|
||||
#endif /* AVOID_HACKS_FOR_ITCL */
|
||||
}
|
||||
Tcl_IncrRefCount(desiredObjs[0]);
|
||||
@@ -1555,6 +1525,10 @@ InitArgsAndLocals(
|
||||
*/
|
||||
|
||||
incorrectArgs:
|
||||
if ((skip != 1) &&
|
||||
TclInitRewriteEnsemble(interp, skip-1, 0, framePtr->objv)) {
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
memset(varPtr, 0,
|
||||
((framePtr->compiledLocals + localCt)-varPtr) * sizeof(Var));
|
||||
return ProcWrongNumArgs(interp, skip);
|
||||
@@ -2109,7 +2083,7 @@ MakeProcError(
|
||||
* messages and trace information. */
|
||||
{
|
||||
int overflow, limit = 60, nameLen;
|
||||
const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen);
|
||||
const char *procName = TclGetStringFromObj(procNameObj, &nameLen);
|
||||
|
||||
overflow = (nameLen > limit);
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
@@ -2661,7 +2635,7 @@ TclNRApplyObjCmd(
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Proc *procPtr = NULL;
|
||||
Tcl_Obj *lambdaPtr, *nsObjPtr;
|
||||
int result, isRootEnsemble;
|
||||
int result;
|
||||
Tcl_Namespace *nsPtr;
|
||||
ApplyExtraData *extraPtr;
|
||||
|
||||
@@ -2680,30 +2654,6 @@ TclNRApplyObjCmd(
|
||||
procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
|
||||
#define JOE_EXTENSION 0
|
||||
/*
|
||||
* Note: this code is NOT FUNCTIONAL due to the NR implementation; DO NOT
|
||||
* ENABLE! Leaving here as reminder to (a) TIP the suggestion, and (b) adapt
|
||||
* the code. (MS)
|
||||
*/
|
||||
|
||||
#if JOE_EXTENSION
|
||||
else {
|
||||
/*
|
||||
* Joe English's suggestion to allow cmdNames to function as lambdas.
|
||||
*/
|
||||
|
||||
Tcl_Obj *elemPtr;
|
||||
int numElem;
|
||||
|
||||
if ((lambdaPtr->typePtr == &tclCmdNameType) ||
|
||||
(TclListObjGetElements(interp, lambdaPtr, &numElem,
|
||||
&elemPtr) == TCL_OK && numElem == 1)) {
|
||||
return Tcl_EvalObjv(interp, objc-1, objv+1, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((procPtr == NULL) || (procPtr->iPtr != iPtr)) {
|
||||
result = SetLambdaFromAny(interp, lambdaPtr);
|
||||
if (result != TCL_OK) {
|
||||
@@ -2744,16 +2694,6 @@ TclNRApplyObjCmd(
|
||||
extraPtr->efi.fields[0].clientData = lambdaPtr;
|
||||
extraPtr->cmd.clientData = &extraPtr->efi;
|
||||
|
||||
isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
|
||||
if (isRootEnsemble) {
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = 1;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 0;
|
||||
} else {
|
||||
iPtr->ensembleRewrite.numInsertedObjs -= 1;
|
||||
}
|
||||
extraPtr->isRootEnsemble = isRootEnsemble;
|
||||
|
||||
result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1);
|
||||
if (result == TCL_OK) {
|
||||
TclNRAddCallback(interp, ApplyNR2, extraPtr, NULL, NULL, NULL);
|
||||
@@ -2770,10 +2710,6 @@ ApplyNR2(
|
||||
{
|
||||
ApplyExtraData *extraPtr = data[0];
|
||||
|
||||
if (extraPtr->isRootEnsemble) {
|
||||
((Interp *) interp)->ensembleRewrite.sourceObjs = NULL;
|
||||
}
|
||||
|
||||
TclStackFree(interp, extraPtr);
|
||||
return result;
|
||||
}
|
||||
@@ -2804,7 +2740,7 @@ MakeLambdaError(
|
||||
* messages and trace information. */
|
||||
{
|
||||
int overflow, limit = 60, nameLen;
|
||||
const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen);
|
||||
const char *procName = TclGetStringFromObj(procNameObj, &nameLen);
|
||||
|
||||
overflow = (nameLen > limit);
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
|
||||
+10
-3
@@ -502,9 +502,16 @@ Tcl_RegExpMatchObj(
|
||||
{
|
||||
Tcl_RegExp re;
|
||||
|
||||
re = Tcl_GetRegExpFromObj(interp, patternObj,
|
||||
TCL_REG_ADVANCED | TCL_REG_NOSUB);
|
||||
if (re == NULL) {
|
||||
/*
|
||||
* For performance reasons, first try compiling the RE without support for
|
||||
* subexpressions. On failure, try again without TCL_REG_NOSUB in case the
|
||||
* RE has backreferences in it. Closely related to [Bug 1366683]. If this
|
||||
* still fails, an error message will be left in the interpreter.
|
||||
*/
|
||||
|
||||
if (!(re = Tcl_GetRegExpFromObj(interp, patternObj,
|
||||
TCL_REG_ADVANCED | TCL_REG_NOSUB))
|
||||
&& !(re = Tcl_GetRegExpFromObj(interp, patternObj, TCL_REG_ADVANCED))) {
|
||||
return -1;
|
||||
}
|
||||
return Tcl_RegExpExecObj(interp, re, textObj, 0 /* offset */,
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ typedef struct TclRegexp {
|
||||
* of subexpressions. */
|
||||
rm_detail_t details; /* Detailed information on match (currently
|
||||
* used only for REG_EXPECT). */
|
||||
int refCount; /* Count of number of references to this
|
||||
unsigned int refCount; /* Count of number of references to this
|
||||
* compiled regexp. */
|
||||
} TclRegexp;
|
||||
|
||||
|
||||
@@ -396,6 +396,9 @@ static Tcl_WideUInt Nokia770Twiddle(Tcl_WideUInt w);
|
||||
* - TCL_PARSE_SCAN_PREFIXES: ignore the prefixes 0b and 0o that are
|
||||
* not part of the [scan] command's vocabulary. Use only in
|
||||
* combination with TCL_PARSE_INTEGER_ONLY.
|
||||
* - TCL_PARSE_BINARY_ONLY: parse only in the binary format, whether
|
||||
* or not a prefix is present that would lead to binary parsing.
|
||||
* Use only in combination with TCL_PARSE_INTEGER_ONLY.
|
||||
* - TCL_PARSE_OCTAL_ONLY: parse only in the octal format, whether
|
||||
* or not a prefix is present that would lead to octal parsing.
|
||||
* Use only in combination with TCL_PARSE_INTEGER_ONLY.
|
||||
@@ -627,6 +630,9 @@ TclParseNumber(
|
||||
acceptPoint = p;
|
||||
acceptLen = len;
|
||||
if (c == 'x' || c == 'X') {
|
||||
if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY)) {
|
||||
goto endgame;
|
||||
}
|
||||
state = ZERO_X;
|
||||
break;
|
||||
}
|
||||
@@ -637,6 +643,9 @@ TclParseNumber(
|
||||
goto zeroo;
|
||||
}
|
||||
if (c == 'b' || c == 'B') {
|
||||
if (flags & TCL_PARSE_OCTAL_ONLY) {
|
||||
goto endgame;
|
||||
}
|
||||
state = ZERO_B;
|
||||
break;
|
||||
}
|
||||
|
||||
+640
-5
@@ -408,6 +408,15 @@ Tcl_GetCharLength(
|
||||
String *stringPtr;
|
||||
int numChars;
|
||||
|
||||
/*
|
||||
* Quick, no-shimmer return for short string reps.
|
||||
*/
|
||||
|
||||
if ((objPtr->bytes) && (objPtr->length < 2)) {
|
||||
/* 0 bytes -> 0 chars; 1 byte -> 1 char */
|
||||
return objPtr->length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Optimize the case where we're really dealing with a bytearray object
|
||||
* without string representation; we don't need to convert to a string to
|
||||
@@ -1173,6 +1182,8 @@ Tcl_AppendUnicodeToObj(
|
||||
* Side effects:
|
||||
* The string rep of appendObjPtr is appended to the string
|
||||
* representation of objPtr.
|
||||
* IMPORTANT: This routine does not and MUST NOT shimmer appendObjPtr.
|
||||
* Callers are counting on that.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2285,7 +2296,7 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_GetStringFromObj(segment, &segmentNumBytes);
|
||||
TclGetStringFromObj(segment, &segmentNumBytes);
|
||||
if (segmentNumBytes > limit) {
|
||||
if (allocSegment) {
|
||||
Tcl_DecrRefCount(segment);
|
||||
@@ -2461,6 +2472,10 @@ AppendPrintfToObjVA(
|
||||
Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj(
|
||||
va_arg(argList, long)));
|
||||
break;
|
||||
case 2:
|
||||
Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj(
|
||||
va_arg(argList, Tcl_WideInt)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
@@ -2489,9 +2504,9 @@ AppendPrintfToObjVA(
|
||||
gotPrecision = 1;
|
||||
p++;
|
||||
break;
|
||||
/* TODO: support for wide (and bignum?) arguments */
|
||||
/* TODO: support for bignum arguments */
|
||||
case 'l':
|
||||
size = 1;
|
||||
++size;
|
||||
p++;
|
||||
break;
|
||||
case 'h':
|
||||
@@ -2598,6 +2613,616 @@ TclGetStringStorage(
|
||||
*sizePtr = stringPtr->allocated;
|
||||
return objPtr->bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringRepeat --
|
||||
*
|
||||
* Performs the [string repeat] function.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Writes to *objPtrPtr the address of Tcl_Obj that is concatenation
|
||||
* of count copies of the value in objPtr.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclStringRepeat(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr,
|
||||
int count,
|
||||
Tcl_Obj **objPtrPtr)
|
||||
{
|
||||
Tcl_Obj *objResultPtr;
|
||||
int length = 0, unichar = 0, done = 1;
|
||||
int binary = TclIsPureByteArray(objPtr);
|
||||
|
||||
/* assert (count >= 2) */
|
||||
|
||||
/*
|
||||
* Analyze to determine what representation result should be.
|
||||
* GOALS: Avoid shimmering & string rep generation.
|
||||
* Produce pure bytearray when possible.
|
||||
* Error on overflow.
|
||||
*/
|
||||
|
||||
if (!binary) {
|
||||
if (objPtr->typePtr == &tclStringType) {
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
if (stringPtr->hasUnicode) {
|
||||
unichar = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (binary) {
|
||||
/* Result will be pure byte array. Pre-size it */
|
||||
Tcl_GetByteArrayFromObj(objPtr, &length);
|
||||
} else if (unichar) {
|
||||
/* Result will be pure Tcl_UniChar array. Pre-size it. */
|
||||
Tcl_GetUnicodeFromObj(objPtr, &length);
|
||||
} else {
|
||||
/* Result will be concat of string reps. Pre-size it. */
|
||||
Tcl_GetStringFromObj(objPtr, &length);
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
/* Any repeats of empty is empty. */
|
||||
*objPtrPtr = objPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (count > INT_MAX/length) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max size for a Tcl value (%d bytes) exceeded", INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (binary) {
|
||||
/* Efficiently produce a pure byte array result */
|
||||
objResultPtr = Tcl_IsShared(objPtr) ? Tcl_DuplicateObj(objPtr)
|
||||
: objPtr;
|
||||
|
||||
Tcl_SetByteArrayLength(objResultPtr, count*length); /* PANIC? */
|
||||
Tcl_SetByteArrayLength(objResultPtr, length);
|
||||
while (count - done > done) {
|
||||
Tcl_AppendObjToObj(objResultPtr, objResultPtr);
|
||||
done *= 2;
|
||||
}
|
||||
TclAppendBytesToByteArray(objResultPtr,
|
||||
Tcl_GetByteArrayFromObj(objResultPtr, NULL),
|
||||
(count - done) * length);
|
||||
} else if (unichar) {
|
||||
/* Efficiently produce a pure Tcl_UniChar array result */
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
objResultPtr = Tcl_NewUnicodeObj(Tcl_GetUnicode(objPtr), length);
|
||||
} else {
|
||||
TclInvalidateStringRep(objPtr);
|
||||
objResultPtr = objPtr;
|
||||
}
|
||||
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"string size overflow: unable to alloc %"
|
||||
TCL_LL_MODIFIER "u bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(count*length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjLength(objResultPtr, length);
|
||||
while (count - done > done) {
|
||||
Tcl_AppendObjToObj(objResultPtr, objResultPtr);
|
||||
done *= 2;
|
||||
}
|
||||
Tcl_AppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr),
|
||||
(count - done) * length);
|
||||
} else {
|
||||
/* Efficiently concatenate string reps */
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
objResultPtr = Tcl_NewStringObj(Tcl_GetString(objPtr), length);
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
objResultPtr = objPtr;
|
||||
}
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"string size overflow: unable to alloc %u bytes",
|
||||
count*length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjLength(objResultPtr, length);
|
||||
while (count - done > done) {
|
||||
Tcl_AppendObjToObj(objResultPtr, objResultPtr);
|
||||
done *= 2;
|
||||
}
|
||||
Tcl_AppendToObj(objResultPtr, Tcl_GetString(objResultPtr),
|
||||
(count - done) * length);
|
||||
}
|
||||
*objPtrPtr = objResultPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringCatObjv --
|
||||
*
|
||||
* Performs the [string cat] function.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Writes to *objPtrPtr the address of Tcl_Obj that is concatenation
|
||||
* of all objc values in objv.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclStringCatObjv(
|
||||
Tcl_Interp *interp,
|
||||
int inPlace,
|
||||
int objc,
|
||||
Tcl_Obj * const objv[],
|
||||
Tcl_Obj **objPtrPtr)
|
||||
{
|
||||
Tcl_Obj *objPtr, *objResultPtr, * const *ov;
|
||||
int oc, length = 0, binary = 1, first = 0;
|
||||
int allowUniChar = 1, requestUniChar = 0;
|
||||
|
||||
/* assert (objc >= 2) */
|
||||
|
||||
/*
|
||||
* Analyze to determine what representation result should be.
|
||||
* GOALS: Avoid shimmering & string rep generation.
|
||||
* Produce pure bytearray when possible.
|
||||
* Error on overflow.
|
||||
*/
|
||||
|
||||
ov = objv, oc = objc;
|
||||
while (oc-- && (binary || allowUniChar)) {
|
||||
objPtr = *ov++;
|
||||
|
||||
if (objPtr->bytes) {
|
||||
/* Value has a string rep. */
|
||||
if (objPtr->length) {
|
||||
/*
|
||||
* Non-empty string rep. Not a pure bytearray, so we
|
||||
* won't create a pure bytearray
|
||||
*/
|
||||
binary = 0;
|
||||
if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) {
|
||||
/* Prevent shimmer of non-string types. */
|
||||
allowUniChar = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* assert (objPtr->typePtr != NULL) -- stork! */
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
allowUniChar = 0;
|
||||
} else {
|
||||
binary = 0;
|
||||
if (objPtr->typePtr == &tclStringType) {
|
||||
/* Have a pure Unicode value; ask to preserve it */
|
||||
requestUniChar = 1;
|
||||
} else {
|
||||
/* Have another type; prevent shimmer */
|
||||
allowUniChar = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (binary) {
|
||||
/* Result will be pure byte array. Pre-size it */
|
||||
ov = objv; oc = objc;
|
||||
while (oc-- && (length >= 0)) {
|
||||
objPtr = *ov++;
|
||||
|
||||
if (objPtr->bytes == NULL) {
|
||||
int numBytes;
|
||||
|
||||
Tcl_GetByteArrayFromObj(objPtr, &numBytes); /* PANIC? */
|
||||
if (length == 0) {
|
||||
first = objc - oc - 1;
|
||||
}
|
||||
length += numBytes;
|
||||
}
|
||||
}
|
||||
} else if (allowUniChar && requestUniChar) {
|
||||
/* Result will be pure Tcl_UniChar array. Pre-size it. */
|
||||
ov = objv; oc = objc;
|
||||
while (oc-- && (length >= 0)) {
|
||||
objPtr = *ov++;
|
||||
|
||||
if ((objPtr->bytes == NULL) || (objPtr->length)) {
|
||||
int numChars;
|
||||
|
||||
Tcl_GetUnicodeFromObj(objPtr, &numChars); /* PANIC? */
|
||||
if (length == 0) {
|
||||
first = objc - oc - 1;
|
||||
}
|
||||
length += numChars;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Result will be concat of string reps. Pre-size it. */
|
||||
ov = objv; oc = objc;
|
||||
while (oc-- && (length >= 0)) {
|
||||
int numBytes;
|
||||
|
||||
objPtr = *ov++;
|
||||
|
||||
Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */
|
||||
if ((length == 0) && numBytes) {
|
||||
first = objc - oc - 1;
|
||||
}
|
||||
length += numBytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (length < 0) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max size for a Tcl value (%d bytes) exceeded", INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
/* Total length of zero means every value has length zero */
|
||||
*objPtrPtr = objv[0];
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
objv += first; objc -= first;
|
||||
|
||||
if (binary) {
|
||||
/* Efficiently produce a pure byte array result */
|
||||
unsigned char *dst;
|
||||
|
||||
/*
|
||||
* Broken interface! Byte array value routines offer no way
|
||||
* to handle failure to allocate enough space. Following
|
||||
* stanza may panic.
|
||||
*/
|
||||
if (inPlace && !Tcl_IsShared(*objv)) {
|
||||
int start;
|
||||
|
||||
objResultPtr = *objv++; objc--;
|
||||
Tcl_GetByteArrayFromObj(objResultPtr, &start);
|
||||
dst = Tcl_SetByteArrayLength(objResultPtr, length) + start;
|
||||
} else {
|
||||
objResultPtr = Tcl_NewByteArrayObj(NULL, length);
|
||||
dst = Tcl_SetByteArrayLength(objResultPtr, length);
|
||||
}
|
||||
while (objc--) {
|
||||
Tcl_Obj *objPtr = *objv++;
|
||||
|
||||
if (objPtr->bytes == NULL) {
|
||||
int more;
|
||||
unsigned char *src = Tcl_GetByteArrayFromObj(objPtr, &more);
|
||||
memcpy(dst, src, (size_t) more);
|
||||
dst += more;
|
||||
}
|
||||
}
|
||||
} else if (allowUniChar && requestUniChar) {
|
||||
/* Efficiently produce a pure Tcl_UniChar array result */
|
||||
Tcl_UniChar *dst;
|
||||
|
||||
if (inPlace && !Tcl_IsShared(*objv)) {
|
||||
int start;
|
||||
|
||||
objResultPtr = *objv++; objc--;
|
||||
|
||||
/* Ugly interface! Force resize of the unicode array. */
|
||||
Tcl_GetUnicodeFromObj(objResultPtr, &start);
|
||||
Tcl_InvalidateStringRep(objResultPtr);
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %"
|
||||
TCL_LL_MODIFIER "u bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
dst = Tcl_GetUnicode(objResultPtr) + start;
|
||||
} else {
|
||||
Tcl_UniChar ch = 0;
|
||||
|
||||
/* Ugly interface! No scheme to init array size. */
|
||||
objResultPtr = Tcl_NewUnicodeObj(&ch, 0); /* PANIC? */
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %"
|
||||
TCL_LL_MODIFIER "u bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
dst = Tcl_GetUnicode(objResultPtr);
|
||||
}
|
||||
while (objc--) {
|
||||
Tcl_Obj *objPtr = *objv++;
|
||||
|
||||
if ((objPtr->bytes == NULL) || (objPtr->length)) {
|
||||
int more;
|
||||
Tcl_UniChar *src = Tcl_GetUnicodeFromObj(objPtr, &more);
|
||||
memcpy(dst, src, more * sizeof(Tcl_UniChar));
|
||||
dst += more;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Efficiently concatenate string reps */
|
||||
char *dst;
|
||||
|
||||
if (inPlace && !Tcl_IsShared(*objv)) {
|
||||
int start;
|
||||
|
||||
objResultPtr = *objv++; objc--;
|
||||
|
||||
Tcl_GetStringFromObj(objResultPtr, &start);
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %u bytes",
|
||||
length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
dst = Tcl_GetString(objResultPtr) + start;
|
||||
if (length > start) {
|
||||
TclFreeIntRep(objResultPtr);
|
||||
}
|
||||
} else {
|
||||
objResultPtr = Tcl_NewObj(); /* PANIC? */
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %u bytes",
|
||||
length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
dst = Tcl_GetString(objResultPtr);
|
||||
}
|
||||
while (objc--) {
|
||||
Tcl_Obj *objPtr = *objv++;
|
||||
|
||||
if ((objPtr->bytes == NULL) || (objPtr->length)) {
|
||||
int more;
|
||||
char *src = Tcl_GetStringFromObj(objPtr, &more);
|
||||
memcpy(dst, src, (size_t) more);
|
||||
dst += more;
|
||||
}
|
||||
}
|
||||
}
|
||||
*objPtrPtr = objResultPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringFind --
|
||||
*
|
||||
* Implements the [string first] operation.
|
||||
*
|
||||
* Results:
|
||||
* If needle is found as a substring of haystack, the index of the
|
||||
* first instance of such a find is returned. If needle is not present
|
||||
* as a substring of haystack, -1 is returned.
|
||||
*
|
||||
* Side effects:
|
||||
* needle and haystack may have their Tcl_ObjType changed.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclStringFind(
|
||||
Tcl_Obj *needle,
|
||||
Tcl_Obj *haystack,
|
||||
int start)
|
||||
{
|
||||
int lh, ln = Tcl_GetCharLength(needle);
|
||||
|
||||
if (ln == 0) {
|
||||
/*
|
||||
* We don't find empty substrings. Bizarre!
|
||||
*
|
||||
* TODO: When we one day make this a true substring
|
||||
* finder, change this to "return 0"
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) {
|
||||
unsigned char *end, *try, *bh;
|
||||
unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln);
|
||||
|
||||
bh = Tcl_GetByteArrayFromObj(haystack, &lh);
|
||||
end = bh + lh;
|
||||
|
||||
try = bh + start;
|
||||
while (try + ln <= end) {
|
||||
try = memchr(try, bn[0], end - try);
|
||||
|
||||
if (try == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (0 == memcmp(try+1, bn+1, ln-1)) {
|
||||
return (try - bh);
|
||||
}
|
||||
try++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
lh = Tcl_GetCharLength(haystack);
|
||||
if (haystack->bytes && (lh == haystack->length)) {
|
||||
/* haystack is all single-byte chars */
|
||||
|
||||
if (needle->bytes && (ln == needle->length)) {
|
||||
/* needle is also all single-byte chars */
|
||||
char *found = strstr(haystack->bytes + start, needle->bytes);
|
||||
|
||||
if (found) {
|
||||
return (found - haystack->bytes);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Cannot find substring with a multi-byte char inside
|
||||
* a string with no multi-byte chars.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
Tcl_UniChar *try, *end, *uh;
|
||||
Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln);
|
||||
|
||||
uh = Tcl_GetUnicodeFromObj(haystack, &lh);
|
||||
end = uh + lh;
|
||||
|
||||
try = uh + start;
|
||||
while (try + ln <= end) {
|
||||
if ((*try == *un)
|
||||
&& (0 == memcmp(try+1, un+1, (ln-1)*sizeof(Tcl_UniChar)))) {
|
||||
return (try - uh);
|
||||
}
|
||||
try++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringLast --
|
||||
*
|
||||
* Implements the [string last] operation.
|
||||
*
|
||||
* Results:
|
||||
* If needle is found as a substring of haystack, the index of the
|
||||
* last instance of such a find is returned. If needle is not present
|
||||
* as a substring of haystack, -1 is returned.
|
||||
*
|
||||
* Side effects:
|
||||
* needle and haystack may have their Tcl_ObjType changed.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclStringLast(
|
||||
Tcl_Obj *needle,
|
||||
Tcl_Obj *haystack,
|
||||
int last)
|
||||
{
|
||||
int lh, ln = Tcl_GetCharLength(needle);
|
||||
|
||||
if (ln == 0) {
|
||||
/*
|
||||
* We don't find empty substrings. Bizarre!
|
||||
*
|
||||
* TODO: When we one day make this a true substring
|
||||
* finder, change this to "return 0"
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ln > last + 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) {
|
||||
unsigned char *try, *bh;
|
||||
unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln);
|
||||
|
||||
bh = Tcl_GetByteArrayFromObj(haystack, &lh);
|
||||
|
||||
if (last + 1 > lh) {
|
||||
last = lh - 1;
|
||||
}
|
||||
try = bh + last + 1 - ln;
|
||||
while (try >= bh) {
|
||||
if ((*try == bn[0])
|
||||
&& (0 == memcmp(try+1, bn+1, ln-1))) {
|
||||
return (try - bh);
|
||||
}
|
||||
try--;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
lh = Tcl_GetCharLength(haystack);
|
||||
if (last + 1 > lh) {
|
||||
last = lh - 1;
|
||||
}
|
||||
if (haystack->bytes && (lh == haystack->length)) {
|
||||
/* haystack is all single-byte chars */
|
||||
|
||||
if (needle->bytes && (ln == needle->length)) {
|
||||
/* needle is also all single-byte chars */
|
||||
|
||||
char *try = haystack->bytes + last + 1 - ln;
|
||||
while (try >= haystack->bytes) {
|
||||
if ((*try == needle->bytes[0])
|
||||
&& (0 == memcmp(try+1, needle->bytes + 1, ln - 1))) {
|
||||
return (try - haystack->bytes);
|
||||
}
|
||||
try--;
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
/*
|
||||
* Cannot find substring with a multi-byte char inside
|
||||
* a string with no multi-byte chars.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
Tcl_UniChar *try, *uh;
|
||||
Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln);
|
||||
|
||||
uh = Tcl_GetUnicodeFromObj(haystack, &lh);
|
||||
|
||||
try = uh + last + 1 - ln;
|
||||
while (try >= uh) {
|
||||
if ((*try == un[0])
|
||||
&& (0 == memcmp(try+1, un+1, (ln-1)*sizeof(Tcl_UniChar)))) {
|
||||
return (try - uh);
|
||||
}
|
||||
try--;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
@@ -2948,6 +3573,16 @@ UpdateStringOfString(
|
||||
{
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
|
||||
/*
|
||||
* This routine is only called when we need to generate the
|
||||
* string rep objPtr->bytes because it does not exist -- it is NULL.
|
||||
* In that circumstance, any lingering claim about the size of
|
||||
* memory pointed to by that NULL pointer is clearly bogus, and
|
||||
* needs a reset.
|
||||
*/
|
||||
|
||||
stringPtr->allocated = 0;
|
||||
|
||||
if (stringPtr->numChars == 0) {
|
||||
TclInitStringRep(objPtr, tclEmptyStringRep, 0);
|
||||
} else {
|
||||
@@ -2967,7 +3602,7 @@ ExtendStringRepWithUnicode(
|
||||
*/
|
||||
|
||||
int i, origLength, size = 0;
|
||||
char *dst, buf[TCL_UTF_MAX];
|
||||
char *dst;
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
|
||||
if (numChars < 0) {
|
||||
@@ -2993,7 +3628,7 @@ ExtendStringRepWithUnicode(
|
||||
}
|
||||
|
||||
for (i = 0; i < numChars && size >= 0; i++) {
|
||||
size += Tcl_UniCharToUtf((int) unicode[i], buf);
|
||||
size += TclUtfCount(unicode[i]);
|
||||
}
|
||||
if (size < 0) {
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
* tcl.h, but do not do that unless you are sure what you're doing!
|
||||
*/
|
||||
|
||||
typedef struct String {
|
||||
typedef struct {
|
||||
int numChars; /* The number of chars in the string. -1 means
|
||||
* this value has not been calculated. >= 0
|
||||
* means that there is a valid Unicode rep, or
|
||||
@@ -72,17 +72,17 @@ typedef struct String {
|
||||
do { \
|
||||
if ((numChars) < 0 || (numChars) > STRING_MAXCHARS) { \
|
||||
Tcl_Panic("max length for a Tcl unicode value (%d chars) exceeded", \
|
||||
STRING_MAXCHARS); \
|
||||
(int)STRING_MAXCHARS); \
|
||||
} \
|
||||
} while (0)
|
||||
#define stringAttemptAlloc(numChars) \
|
||||
(String *) attemptckalloc((unsigned) STRING_SIZE(numChars))
|
||||
(String *) attemptckalloc(STRING_SIZE(numChars))
|
||||
#define stringAlloc(numChars) \
|
||||
(String *) ckalloc((unsigned) STRING_SIZE(numChars))
|
||||
(String *) ckalloc(STRING_SIZE(numChars))
|
||||
#define stringRealloc(ptr, numChars) \
|
||||
(String *) ckrealloc((ptr), (unsigned) STRING_SIZE(numChars))
|
||||
(String *) ckrealloc((ptr), STRING_SIZE(numChars))
|
||||
#define stringAttemptRealloc(ptr, numChars) \
|
||||
(String *) attemptckrealloc((ptr), (unsigned) STRING_SIZE(numChars))
|
||||
(String *) attemptckrealloc((ptr), STRING_SIZE(numChars))
|
||||
#define GET_STRING(objPtr) \
|
||||
((String *) (objPtr)->internalRep.twoPtrValue.ptr1)
|
||||
#define SET_STRING(objPtr, stringPtr) \
|
||||
|
||||
@@ -749,6 +749,7 @@ const TclTomMathStubs tclTomMathStubs = {
|
||||
TclBNInitBignumFromLong, /* 64 */
|
||||
TclBNInitBignumFromWideInt, /* 65 */
|
||||
TclBNInitBignumFromWideUInt, /* 66 */
|
||||
TclBN_mp_expt_d_ex, /* 67 */
|
||||
};
|
||||
|
||||
static const TclStubHooks tclStubHooks = {
|
||||
@@ -1415,6 +1416,9 @@ const TclStubs tclStubs = {
|
||||
Tcl_FindSymbol, /* 628 */
|
||||
Tcl_FSUnloadFile, /* 629 */
|
||||
Tcl_ZlibStreamSetCompressionDictionary, /* 630 */
|
||||
0, /* 631 */
|
||||
Tcl_ArrayObjFirst, /* 632 */
|
||||
Tcl_ArrayObjNext, /* 633 */
|
||||
};
|
||||
|
||||
/* !END!: Do not edit above this line. */
|
||||
|
||||
+9
-11
@@ -24,13 +24,10 @@ const TclIntStubs *tclIntStubsPtr = NULL;
|
||||
const TclIntPlatStubs *tclIntPlatStubsPtr = NULL;
|
||||
|
||||
/*
|
||||
* Use our own isDigit to avoid linking to libc on windows
|
||||
* Use our own ISDIGIT to avoid linking to libc on windows
|
||||
*/
|
||||
|
||||
static int isDigit(const int c)
|
||||
{
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
#define ISDIGIT(c) (((unsigned)((c)-'0')) <= 9)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -54,7 +51,8 @@ MODULE_SCOPE const char *
|
||||
Tcl_InitStubs(
|
||||
Tcl_Interp *interp,
|
||||
const char *version,
|
||||
int exact)
|
||||
int exact,
|
||||
int magic)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
const char *actualVersion = NULL;
|
||||
@@ -67,8 +65,8 @@ Tcl_InitStubs(
|
||||
* times. [Bug 615304]
|
||||
*/
|
||||
|
||||
if (!stubsPtr || (stubsPtr->magic != TCL_STUB_MAGIC)) {
|
||||
iPtr->result = "interpreter uses an incompatible stubs mechanism";
|
||||
if (!stubsPtr || (stubsPtr->magic != (((exact&0xff00) >= 0x900) ? magic : TCL_STUB_MAGIC))) {
|
||||
iPtr->result = (char *)"interpreter uses an incompatible stubs mechanism";
|
||||
iPtr->freeProc = TCL_STATIC;
|
||||
return NULL;
|
||||
}
|
||||
@@ -77,12 +75,12 @@ Tcl_InitStubs(
|
||||
if (actualVersion == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (exact) {
|
||||
if (exact&1) {
|
||||
const char *p = version;
|
||||
int count = 0;
|
||||
|
||||
while (*p) {
|
||||
count += !isDigit(*p++);
|
||||
count += !ISDIGIT(*p++);
|
||||
}
|
||||
if (count == 1) {
|
||||
const char *q = actualVersion;
|
||||
@@ -91,7 +89,7 @@ Tcl_InitStubs(
|
||||
while (*p && (*p == *q)) {
|
||||
p++; q++;
|
||||
}
|
||||
if (*p || isDigit(*q)) {
|
||||
if (*p || ISDIGIT(*q)) {
|
||||
/* Construct error message */
|
||||
stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
|
||||
return NULL;
|
||||
|
||||
+100
-43
@@ -42,16 +42,8 @@
|
||||
* Declare external functions used in Windows tests.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
|
||||
* Tcltest_Init declaration is in the source file itself, which is only
|
||||
* accessed when we are building a library.
|
||||
*/
|
||||
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#define TCL_STORAGE_CLASS DLLEXPORT
|
||||
EXTERN int Tcltest_Init(Tcl_Interp *interp);
|
||||
EXTERN int Tcltest_SafeInit(Tcl_Interp *interp);
|
||||
DLLEXPORT int Tcltest_Init(Tcl_Interp *interp);
|
||||
DLLEXPORT int Tcltest_SafeInit(Tcl_Interp *interp);
|
||||
|
||||
/*
|
||||
* Dynamic string shared by TestdcallCmd and DelCallbackProc; used to collect
|
||||
@@ -416,8 +408,7 @@ static int TestHashSystemHashCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
|
||||
static int NREUnwind_callback(ClientData data[], Tcl_Interp *interp,
|
||||
int result);
|
||||
static Tcl_NRPostProc NREUnwind_callback;
|
||||
static int TestNREUnwind(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -1294,7 +1285,7 @@ TestcmdtraceCmd(
|
||||
cmdTrace = Tcl_CreateObjTrace(interp, 50000,
|
||||
TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc,
|
||||
(ClientData) &deleteCalled, ObjTraceDeleteProc);
|
||||
result = Tcl_Eval(interp, argv[2]);
|
||||
result = Tcl_EvalEx(interp, argv[2], -1, 0);
|
||||
Tcl_DeleteTrace(interp, cmdTrace);
|
||||
if (!deleteCalled) {
|
||||
Tcl_SetResult(interp, "Delete wasn't called", TCL_STATIC);
|
||||
@@ -1308,7 +1299,7 @@ TestcmdtraceCmd(
|
||||
Tcl_DStringInit(&buffer);
|
||||
t1 = Tcl_CreateTrace(interp, 1, CmdTraceProc, &buffer);
|
||||
t2 = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
|
||||
result = Tcl_Eval(interp, argv[2]);
|
||||
result = Tcl_EvalEx(interp, argv[2], -1, 0);
|
||||
if (result == TCL_OK) {
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
|
||||
@@ -1637,7 +1628,7 @@ DelDeleteProc(
|
||||
{
|
||||
DelCmd *dPtr = clientData;
|
||||
|
||||
Tcl_Eval(dPtr->interp, dPtr->deleteCmd);
|
||||
Tcl_EvalEx(dPtr->interp, dPtr->deleteCmd, -1, 0);
|
||||
Tcl_ResetResult(dPtr->interp);
|
||||
ckfree(dPtr->deleteCmd);
|
||||
ckfree(dPtr);
|
||||
@@ -3972,7 +3963,7 @@ TestregexpObjCmd(
|
||||
varName = Tcl_GetString(objv[2]);
|
||||
TclRegExpRangeUniChar(regExpr, -1, &start, &end);
|
||||
sprintf(resinfo, "%d %d", start, end-1);
|
||||
value = Tcl_SetVar(interp, varName, resinfo, 0);
|
||||
value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
|
||||
if (value == NULL) {
|
||||
Tcl_AppendResult(interp, "couldn't set variable \"",
|
||||
varName, "\"", NULL);
|
||||
@@ -3986,7 +3977,7 @@ TestregexpObjCmd(
|
||||
Tcl_RegExpGetInfo(regExpr, &info);
|
||||
varName = Tcl_GetString(objv[2]);
|
||||
sprintf(resinfo, "%ld", info.extendStart);
|
||||
value = Tcl_SetVar(interp, varName, resinfo, 0);
|
||||
value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
|
||||
if (value == NULL) {
|
||||
Tcl_AppendResult(interp, "couldn't set variable \"",
|
||||
varName, "\"", NULL);
|
||||
@@ -4329,7 +4320,7 @@ StaticInitProc(
|
||||
Tcl_Interp *interp) /* Interpreter in which package is supposedly
|
||||
* being loaded. */
|
||||
{
|
||||
Tcl_SetVar(interp, "x", "loaded", TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "x", NULL, "loaded", TCL_GLOBAL_ONLY);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -4413,7 +4404,7 @@ TestupvarCmd(
|
||||
} else if (strcmp(argv[4], "namespace") == 0) {
|
||||
flags = TCL_NAMESPACE_ONLY;
|
||||
}
|
||||
return Tcl_UpVar(interp, argv[1], argv[2], argv[3], flags);
|
||||
return Tcl_UpVar2(interp, argv[1], argv[2], NULL, argv[3], flags);
|
||||
} else {
|
||||
if (strcmp(argv[5], "global") == 0) {
|
||||
flags = TCL_GLOBAL_ONLY;
|
||||
@@ -4907,10 +4898,10 @@ GetTimesObjCmd(
|
||||
timePer/100000);
|
||||
|
||||
/* Tcl_SetVar 100000 times */
|
||||
fprintf(stderr, "Tcl_SetVar of \"12345\" 100000 times\n");
|
||||
fprintf(stderr, "Tcl_SetVar2 of \"12345\" 100000 times\n");
|
||||
Tcl_GetTime(&start);
|
||||
for (i = 0; i < 100000; i++) {
|
||||
s = Tcl_SetVar(interp, "a", "12345", TCL_LEAVE_ERR_MSG);
|
||||
s = Tcl_SetVar2(interp, "a", NULL, "12345", TCL_LEAVE_ERR_MSG);
|
||||
if (s == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -4924,7 +4915,7 @@ GetTimesObjCmd(
|
||||
fprintf(stderr, "Tcl_GetVar of a==\"12345\" 100000 times\n");
|
||||
Tcl_GetTime(&start);
|
||||
for (i = 0; i < 100000; i++) {
|
||||
s = Tcl_GetVar(interp, "a", TCL_LEAVE_ERR_MSG);
|
||||
s = Tcl_GetVar2(interp, "a", NULL, TCL_LEAVE_ERR_MSG);
|
||||
if (s == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -5194,7 +5185,7 @@ TestsaveresultCmd(
|
||||
if (((enum options) index) == RESULT_OBJECT) {
|
||||
result = Tcl_EvalObjEx(interp, objv[2], 0);
|
||||
} else {
|
||||
result = Tcl_Eval(interp, Tcl_GetString(objv[2]));
|
||||
result = Tcl_EvalEx(interp, Tcl_GetString(objv[2]), -1, 0);
|
||||
}
|
||||
|
||||
if (discard) {
|
||||
@@ -6297,7 +6288,7 @@ TestReport(
|
||||
savedResult = Tcl_GetObjResult(interp);
|
||||
Tcl_IncrRefCount(savedResult);
|
||||
Tcl_SetObjResult(interp, Tcl_NewObj());
|
||||
Tcl_Eval(interp, Tcl_DStringValue(&ds));
|
||||
Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, 0);
|
||||
Tcl_DStringFree(&ds);
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetObjResult(interp, savedResult);
|
||||
@@ -6760,7 +6751,7 @@ TestcpuidCmd(
|
||||
Tcl_Obj *const * objv) /* Parameter vector */
|
||||
{
|
||||
int status, index, i;
|
||||
unsigned int regs[4];
|
||||
int regs[4];
|
||||
Tcl_Obj *regsObjs[4];
|
||||
|
||||
if (objc != 2) {
|
||||
@@ -6770,14 +6761,14 @@ TestcpuidCmd(
|
||||
if (Tcl_GetIntFromObj(interp, objv[1], &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
status = TclWinCPUID((unsigned) index, regs);
|
||||
status = TclWinCPUID(index, regs);
|
||||
if (status != TCL_OK) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("operation not available", -1));
|
||||
return status;
|
||||
}
|
||||
for (i=0 ; i<4 ; ++i) {
|
||||
regsObjs[i] = Tcl_NewIntObj((int) regs[i]);
|
||||
regsObjs[i] = Tcl_NewIntObj(regs[i]);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(4, regsObjs));
|
||||
return TCL_OK;
|
||||
@@ -7335,23 +7326,82 @@ InterpCmdResolver(
|
||||
CallFrame *varFramePtr = iPtr->varFramePtr;
|
||||
Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ?
|
||||
varFramePtr->procPtr : NULL;
|
||||
Namespace *ns2NsPtr = (Namespace *)
|
||||
Tcl_FindNamespace(interp, "::ns2", NULL, 0);
|
||||
Namespace *callerNsPtr = varFramePtr->nsPtr;
|
||||
Tcl_Command resolvedCmdPtr = NULL;
|
||||
|
||||
if (procPtr && (procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr
|
||||
|| (ns2NsPtr && procPtr->cmdPtr->nsPtr == ns2NsPtr))) {
|
||||
const char *callingCmdName =
|
||||
/*
|
||||
* Just do something special on a cmd literal "z" in two cases:
|
||||
* A) when the caller is a proc "x", and the proc is either in "::" or in "::ns2".
|
||||
* B) the caller's namespace is "ctx1" or "ctx2"
|
||||
*/
|
||||
if ( (name[0] == 'z') && (name[1] == '\0') ) {
|
||||
Namespace *ns2NsPtr = (Namespace *) Tcl_FindNamespace(interp, "::ns2", NULL, 0);
|
||||
|
||||
if (procPtr != NULL
|
||||
&& ((procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr)
|
||||
|| (ns2NsPtr != NULL && procPtr->cmdPtr->nsPtr == ns2NsPtr)
|
||||
)
|
||||
) {
|
||||
/*
|
||||
* Case A)
|
||||
*
|
||||
* - The context, in which this resolver becomes active, is
|
||||
* determined by the name of the caller proc, which has to be
|
||||
* named "x".
|
||||
*
|
||||
* - To determine the name of the caller proc, the proc is taken
|
||||
* from the topmost stack frame.
|
||||
*
|
||||
* - Note that the context is NOT provided during byte-code
|
||||
* compilation (e.g. in TclProcCompileProc)
|
||||
*
|
||||
* When these conditions hold, this function resolves the
|
||||
* passed-in cmd literal into a cmd "y", which is taken from the
|
||||
* the global namespace (for simplicity).
|
||||
*/
|
||||
|
||||
const char *callingCmdName =
|
||||
Tcl_GetCommandName(interp, (Tcl_Command) procPtr->cmdPtr);
|
||||
|
||||
if ((callingCmdName[0] == 'x') && (callingCmdName[1] == '\0')
|
||||
&& (name[0] == 'z') && (name[1] == '\0')) {
|
||||
Tcl_Command sourceCmdPtr = Tcl_FindCommand(interp, "y", NULL,
|
||||
TCL_GLOBAL_ONLY);
|
||||
|
||||
if (sourceCmdPtr != NULL) {
|
||||
*rPtr = sourceCmdPtr;
|
||||
return TCL_OK;
|
||||
if ( callingCmdName[0] == 'x' && callingCmdName[1] == '\0' ) {
|
||||
resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
|
||||
}
|
||||
} else if (callerNsPtr != NULL) {
|
||||
/*
|
||||
* Case B)
|
||||
*
|
||||
* - The context, in which this resolver becomes active, is
|
||||
* determined by the name of the parent namespace, which has
|
||||
* to be named "ctx1" or "ctx2".
|
||||
*
|
||||
* - To determine the name of the parent namesace, it is taken
|
||||
* from the 2nd highest stack frame.
|
||||
*
|
||||
* - Note that the context can be provided during byte-code
|
||||
* compilation (e.g. in TclProcCompileProc)
|
||||
*
|
||||
* When these conditions hold, this function resolves the
|
||||
* passed-in cmd literal into a cmd "y" or "Y" depending on the
|
||||
* context. The resolved procs are taken from the the global
|
||||
* namespace (for simplicity).
|
||||
*/
|
||||
|
||||
CallFrame *parentFramePtr = varFramePtr->callerPtr;
|
||||
char *context = parentFramePtr != NULL ? parentFramePtr->nsPtr->name : "(NULL)";
|
||||
|
||||
if (strcmp(context, "ctx1") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
|
||||
resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
|
||||
/* fprintf(stderr, "... y ==> %p\n", resolvedCmdPtr);*/
|
||||
|
||||
} else if (strcmp(context, "ctx2") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
|
||||
resolvedCmdPtr = Tcl_FindCommand(interp, "Y", NULL, TCL_GLOBAL_ONLY);
|
||||
/*fprintf(stderr, "... Y ==> %p\n", resolvedCmdPtr);*/
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedCmdPtr != NULL) {
|
||||
*rPtr = resolvedCmdPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
return TCL_CONTINUE;
|
||||
@@ -7485,9 +7535,16 @@ TestInterpResolverCmd(
|
||||
int idx;
|
||||
#define RESOLVER_KEY "testInterpResolver"
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "up|down");
|
||||
return TCL_ERROR;
|
||||
if ((objc < 2) || (objc > 3)) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "up|down ?interp?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 3) {
|
||||
interp = Tcl_GetSlave(interp, Tcl_GetString(objv[2]));
|
||||
if (interp == NULL) {
|
||||
Tcl_AppendResult(interp, "provided interpreter not found", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT,
|
||||
&idx) != TCL_OK) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user