Compare commits
541
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
118be26821 | ||
|
|
8474c20bc6 | ||
|
|
1197921203 | ||
|
|
911c3a02b5 | ||
|
|
1de5433c5d | ||
|
|
5cbeb42aff | ||
|
|
6b60065860 | ||
|
|
9b0ea3ca88 | ||
|
|
a0b6194b82 | ||
|
|
5c4737c8d8 | ||
|
|
f2aea5424e | ||
|
|
7bfc04bfbe | ||
|
|
f972f06872 | ||
|
|
71d2777cfd | ||
|
|
1ba9a90c6e | ||
|
|
55102c2b83 | ||
|
|
7ff52157ed | ||
|
|
2e7505ce3d | ||
|
|
93b8f2696a | ||
|
|
b6f570180b | ||
|
|
e6f4d201ce | ||
|
|
e0dbb5bd62 | ||
|
|
8b102ddebc | ||
|
|
ddfc3d80c5 | ||
|
|
2eed34dc23 | ||
|
|
b065abd46c | ||
|
|
b5b700cbbd | ||
|
|
2c3cfcfe88 | ||
|
|
bce112e425 | ||
|
|
a5be6def4c | ||
|
|
0185f66f16 | ||
|
|
5d03958f22 | ||
|
|
a411cd47dc | ||
|
|
776001cd14 | ||
|
|
f786fd625e | ||
|
|
6c3c75da93 | ||
|
|
659ee6daa5 | ||
|
|
10d04319d3 | ||
|
|
be834cf113 | ||
|
|
a76ebfc825 | ||
|
|
8f82227afd | ||
|
|
3105dcac7e | ||
|
|
79ad7f2edc | ||
|
|
6da116b888 | ||
|
|
de97184949 | ||
|
|
0c849580cb | ||
|
|
0c75115ede | ||
|
|
4c095a869b | ||
|
|
1a456da516 | ||
|
|
bbe81d1e5e | ||
|
|
52cbdda306 | ||
|
|
eea431a4b8 | ||
|
|
817b517764 | ||
|
|
0a4e67a3e5 | ||
|
|
423209e9fe | ||
|
|
88a893a388 | ||
|
|
12d983adae | ||
|
|
453c878fa9 | ||
|
|
d9db7b2587 | ||
|
|
29a0269cc5 | ||
|
|
4c35f9a03a | ||
|
|
f13a861181 | ||
|
|
4102bfec1a | ||
|
|
fff161d582 | ||
|
|
fc2ae2acaf | ||
|
|
f47c327136 | ||
|
|
09d7c9d217 | ||
|
|
4146517b3b | ||
|
|
ebd4c75aaa | ||
|
|
c988bb3c5d | ||
|
|
2c75cac14e | ||
|
|
fe3f8f0dbc | ||
|
|
06a824d706 | ||
|
|
a0b87265ce | ||
|
|
d16b233ed8 | ||
|
|
39e89c1b69 | ||
|
|
ddc36ee473 | ||
|
|
e22aa5854d | ||
|
|
dbafb5fcfc | ||
|
|
6f7bddf8cd | ||
|
|
91e20aef42 | ||
|
|
2d0dd29466 | ||
|
|
28d2c1e4cf | ||
|
|
db361019ca | ||
|
|
a01b89976f | ||
|
|
b2c63a9461 | ||
|
|
aad97a767b | ||
|
|
8a98d2846f | ||
|
|
3d4bb88f48 | ||
|
|
520932e706 | ||
|
|
f8b482aafe | ||
|
|
04b2d343ff | ||
|
|
480262ad96 | ||
|
|
cbf4785848 | ||
|
|
84d3dc55fc | ||
|
|
57769fb109 | ||
|
|
3b61982dbe | ||
|
|
132dc963f2 | ||
|
|
a3d5ba530a | ||
|
|
1ef6ae9359 | ||
|
|
852b1c4ad2 | ||
|
|
4830e0f883 | ||
|
|
b2f133f23c | ||
|
|
21601a3a4a | ||
|
|
0ffeb7dd6e | ||
|
|
57fa6f9669 | ||
|
|
1355f9df46 | ||
|
|
31f7c64e7d | ||
|
|
1bee0d67c6 | ||
|
|
139ae23a7a | ||
|
|
1d6248a516 | ||
|
|
7cd2194d47 | ||
|
|
b9e95ae529 | ||
|
|
f233a71161 | ||
|
|
1446f739b6 | ||
|
|
69524610e8 | ||
|
|
738fb82952 | ||
|
|
25986b142b | ||
|
|
648b51cf6b | ||
|
|
41cb679571 | ||
|
|
c16dc009d7 | ||
|
|
3995d93d0e | ||
|
|
7b9e7f283b | ||
|
|
2fbb537054 | ||
|
|
9980a32679 | ||
|
|
1a11145339 | ||
|
|
55174c7e8a | ||
|
|
422a712363 | ||
|
|
eb2860258b | ||
|
|
0af55d7cf3 | ||
|
|
79e3f7f55b | ||
|
|
6e6786882d | ||
|
|
86eba6192a | ||
|
|
b96c6536cb | ||
|
|
ec4c4a2957 | ||
|
|
48a03a59dc | ||
|
|
af80656fbe | ||
|
|
51f835ba96 | ||
|
|
aa05129946 | ||
|
|
5281598746 | ||
|
|
78af51451a | ||
|
|
64e9416261 | ||
|
|
8141863583 | ||
|
|
4c642c410e | ||
|
|
3562bfb14b | ||
|
|
80b3ef95a8 | ||
|
|
d98d74151e | ||
|
|
bf38d5992f | ||
|
|
cd57fb7f7d | ||
|
|
87cfb6b250 | ||
|
|
22e4896294 | ||
|
|
05d33e0fe7 | ||
|
|
82b98d6ede | ||
|
|
38d26a919e | ||
|
|
ab629d99ba | ||
|
|
4b31536c4a | ||
|
|
4ec51224f4 | ||
|
|
a30cdc4ccf | ||
|
|
09ea3ba2ca | ||
|
|
0fa1988fb0 | ||
|
|
c2f8276ec4 | ||
|
|
d3a0c83f09 | ||
|
|
5436b7c33b | ||
|
|
5efbf356ec | ||
|
|
172de00de5 | ||
|
|
4a2ab86325 | ||
|
|
6765f7766a | ||
|
|
d19847932e | ||
|
|
627504c503 | ||
|
|
19a639608f | ||
|
|
900bc4a968 | ||
|
|
d2d1deb62a | ||
|
|
7c1edfcd97 | ||
|
|
cb554d6c95 | ||
|
|
c04398e133 | ||
|
|
04cf158092 | ||
|
|
cb0252b19f | ||
|
|
268394dbb5 | ||
|
|
5789086c24 | ||
|
|
40259312fe | ||
|
|
6332e3ad60 | ||
|
|
db61e9a4be | ||
|
|
da40794df6 | ||
|
|
e3a0ad0f87 | ||
|
|
5a5ffc741f | ||
|
|
ba5b356435 | ||
|
|
71c78f086f | ||
|
|
93c840992c | ||
|
|
482a2c710e | ||
|
|
39e3f11942 | ||
|
|
e794120698 | ||
|
|
3793c27000 | ||
|
|
96417ebbb8 | ||
|
|
f974fd8969 | ||
|
|
fc262ab6bb | ||
|
|
ca06debb81 | ||
|
|
712b68cc80 | ||
|
|
1136551973 | ||
|
|
b436f14398 | ||
|
|
cf7969886b | ||
|
|
e594dd2267 | ||
|
|
ef6c187c6e | ||
|
|
1a5673d6d1 | ||
|
|
4cc2a56649 | ||
|
|
65c016d4a0 | ||
|
|
290b2159a2 | ||
|
|
6083020b04 | ||
|
|
b4dbbf2a3b | ||
|
|
eaf64a7a9c | ||
|
|
cf93250674 | ||
|
|
3e947f695b | ||
|
|
73b3a480c8 | ||
|
|
795332afad | ||
|
|
5c85215ca6 | ||
|
|
23fa2a37a9 | ||
|
|
7b382936b6 | ||
|
|
e878a050b2 | ||
|
|
4144a690cb | ||
|
|
8c18c33bb8 | ||
|
|
1973e8e40f | ||
|
|
a01b1afbdd | ||
|
|
a2fa2a169f | ||
|
|
54ab86e08c | ||
|
|
08bc505b41 | ||
|
|
76602aa738 | ||
|
|
24e58b6dcd | ||
|
|
e3bbee7b8a | ||
|
|
fd4b239676 | ||
|
|
339bf30461 | ||
|
|
2eb71ac54f | ||
|
|
c5687412d6 | ||
|
|
4396044600 | ||
|
|
f2d8afbb5b | ||
|
|
882dc5449d | ||
|
|
e03c7973a6 | ||
|
|
930ffee5b9 | ||
|
|
04d8202a78 | ||
|
|
54cce1ee0e | ||
|
|
5070f0a86a | ||
|
|
e6b2efbad8 | ||
|
|
cb19aec8e5 | ||
|
|
0158239e78 | ||
|
|
3b9c3fb04e | ||
|
|
200b0db200 | ||
|
|
deb93dc75c | ||
|
|
a5a7ae5f47 | ||
|
|
41ac300db8 | ||
|
|
9a43dd0c3b | ||
|
|
9ec95d17f8 | ||
|
|
995e26088f | ||
|
|
2015734692 | ||
|
|
9f0660744c | ||
|
|
52c2de3cb8 | ||
|
|
ae8888b894 | ||
|
|
aee7d6fea4 | ||
|
|
765de9e2ef | ||
|
|
eec7311e64 | ||
|
|
4a235274c9 | ||
|
|
1226e764ba | ||
|
|
7da7ccee61 | ||
|
|
bfab34ad8b | ||
|
|
a65850c981 | ||
|
|
2a2af35014 | ||
|
|
ccbed687ed | ||
|
|
57a9d5c7a9 | ||
|
|
e24489dcce | ||
|
|
9e6725acf0 | ||
|
|
9088907888 | ||
|
|
7ee439ce0f | ||
|
|
877a5f8149 | ||
|
|
618bdeb4c0 | ||
|
|
81d4ce37d0 | ||
|
|
271de3bc89 | ||
|
|
8f72fe1eb9 | ||
|
|
9a5465ed60 | ||
|
|
16869d9a05 | ||
|
|
cc94362836 | ||
|
|
abc1ba4c1c | ||
|
|
4eaaa750d1 | ||
|
|
8f86b72df7 | ||
|
|
6d259f9319 | ||
|
|
b9069b9577 | ||
|
|
c241c33749 | ||
|
|
37ba1458ac | ||
|
|
3c9637c2fe | ||
|
|
f034dfb455 | ||
|
|
972b9eeb07 | ||
|
|
a071678d02 | ||
|
|
9023ee32ce | ||
|
|
970473c688 | ||
|
|
7c1d7acf56 | ||
|
|
62d19c65eb | ||
|
|
aee1b56cc2 | ||
|
|
91a7a404d2 | ||
|
|
7a00fde1d2 | ||
|
|
1f7f9de685 | ||
|
|
4e523443fe | ||
|
|
16ee47efcc | ||
|
|
804b3bb41e | ||
|
|
b220f67a4e | ||
|
|
1e68029cac | ||
|
|
e87a46437e | ||
|
|
1139530e78 | ||
|
|
5887924a63 | ||
|
|
5fea85e6d3 | ||
|
|
13dcbf7d2f | ||
|
|
fedbfcec36 | ||
|
|
6fe094e1ef | ||
|
|
28bc611c7b | ||
|
|
9177f9a41b | ||
|
|
6ec16f5f96 | ||
|
|
6abe764edc | ||
|
|
a0eb86a864 | ||
|
|
f20449d17d | ||
|
|
35cf66b42d | ||
|
|
f028c958cc | ||
|
|
9663c3b502 | ||
|
|
3c5aa93c4e | ||
|
|
1a0cb53eec | ||
|
|
ba7881d6ea | ||
|
|
934f9e851f | ||
|
|
a199dc464d | ||
|
|
587cef5259 | ||
|
|
53cba5d9ba | ||
|
|
3a39b4007c | ||
|
|
56fd1342df | ||
|
|
1d751279fa | ||
|
|
8a8a8b6a83 | ||
|
|
6c54d4f137 | ||
|
|
3a2c58f0e3 | ||
|
|
342194b90d | ||
|
|
357b0f7709 | ||
|
|
9085296627 | ||
|
|
e262c66df2 | ||
|
|
98a40cff2c | ||
|
|
b6eebed4e6 | ||
|
|
21c3f3fee2 | ||
|
|
581c5b94ab | ||
|
|
6b531a4b27 | ||
|
|
816626b12f | ||
|
|
a6461e6b0d | ||
|
|
0a8b2b3150 | ||
|
|
928a5b1970 | ||
|
|
d31e503f35 | ||
|
|
43ce79f987 | ||
|
|
6949095cb4 | ||
|
|
d1e73c6065 | ||
|
|
de9162b578 | ||
|
|
f3fe26d49f | ||
|
|
423ee90c6a | ||
|
|
3bbe089a07 | ||
|
|
09c2f769ba | ||
|
|
929948bad8 | ||
|
|
eebca1b422 | ||
|
|
0da09b361f | ||
|
|
d7bd3ea929 | ||
|
|
4a942632c1 | ||
|
|
19ba6d24b8 | ||
|
|
5d8dc198ff | ||
|
|
5d071002e5 | ||
|
|
1415e8eb0e | ||
|
|
89971c7559 | ||
|
|
e267380dad | ||
|
|
0e4e7f881d | ||
|
|
9a14873b85 | ||
|
|
89369231f5 | ||
|
|
a2021967ac | ||
|
|
3327b4aa93 | ||
|
|
9822c32dd0 | ||
|
|
25ab9d5408 | ||
|
|
7715309bee | ||
|
|
b4e2d9a5f7 | ||
|
|
e81a0740ec | ||
|
|
d81457480e | ||
|
|
eff3ee2c12 | ||
|
|
e5f2221983 | ||
|
|
216a40de66 | ||
|
|
793f8e5aba | ||
|
|
ee55e0197b | ||
|
|
43988caaa2 | ||
|
|
d562dc0f60 | ||
|
|
9f0eb68928 | ||
|
|
5c3966aa9c | ||
|
|
885f2d55e3 | ||
|
|
8f2f7117fc | ||
|
|
34d5896205 | ||
|
|
24b681cb7a | ||
|
|
f1b40ee639 | ||
|
|
638edeffa4 | ||
|
|
dd0ed45dbb | ||
|
|
e4b4a00f17 | ||
|
|
ada7e74894 | ||
|
|
978558169e | ||
|
|
0d214a0a14 | ||
|
|
4087d33e18 | ||
|
|
8533669f18 | ||
|
|
8a7422b2db | ||
|
|
b2dabdc1eb | ||
|
|
4a7aba80a6 | ||
|
|
a8a9d42601 | ||
|
|
d223d51178 | ||
|
|
7fbeaf9528 | ||
|
|
2c5cd34ebe | ||
|
|
13adf38211 | ||
|
|
88af143aea | ||
|
|
9b6ebeae02 | ||
|
|
5bce11a1c8 | ||
|
|
32cc5d8d3c | ||
|
|
e2e14fde2d | ||
|
|
679963704f | ||
|
|
32df42787e | ||
|
|
0cf062c388 | ||
|
|
207412c303 | ||
|
|
bf368d9079 | ||
|
|
45c7f36909 | ||
|
|
285dd19c62 | ||
|
|
2410e50d8e | ||
|
|
240695b9f5 | ||
|
|
3aba154e26 | ||
|
|
1bef171761 | ||
|
|
a7affdff05 | ||
|
|
8ddb48c272 | ||
|
|
3ce1c8d98b | ||
|
|
ef5aee8d47 | ||
|
|
ca4329f20b | ||
|
|
8d4878fee6 | ||
|
|
b0465ff0e8 | ||
|
|
f9651e0da6 | ||
|
|
18ab8f43a0 | ||
|
|
77014e3f62 | ||
|
|
46821e04b6 | ||
|
|
51e5bda476 | ||
|
|
656b2b4f87 | ||
|
|
0fbd4e16a9 | ||
|
|
c0845253a0 | ||
|
|
38ba6bd5d4 | ||
|
|
0c64074372 | ||
|
|
53eb119d0b | ||
|
|
8751239349 | ||
|
|
bf14f11c63 | ||
|
|
d12ee9da30 | ||
|
|
78d91cb253 | ||
|
|
66c2909694 | ||
|
|
d83a20092e | ||
|
|
65013d771a | ||
|
|
4b67a9506b | ||
|
|
74cca07e35 | ||
|
|
e2e451e2e5 | ||
|
|
ed156a09fa | ||
|
|
8f40b2b313 | ||
|
|
21bd9cf5ad | ||
|
|
ebbf7144d2 | ||
|
|
fac8f9d0ae | ||
|
|
f3a3f7b9e8 | ||
|
|
a2afb09b3c | ||
|
|
81a67b9cf4 | ||
|
|
569360bf40 | ||
|
|
59e42de547 | ||
|
|
fa7a06447d | ||
|
|
b13b1c6020 | ||
|
|
d67ebaffd4 | ||
|
|
237b1ee14a | ||
|
|
8890130ab8 | ||
|
|
093fb49d43 | ||
|
|
0ccb6618bd | ||
|
|
989c5bb9a4 | ||
|
|
94ada5d31f | ||
|
|
af92fc0c28 | ||
|
|
4557297b08 | ||
|
|
1d29f93257 | ||
|
|
9918a06afa | ||
|
|
e1c8f78ed0 | ||
|
|
b9a522a6bf | ||
|
|
eace9319cb | ||
|
|
eb7f17ba98 | ||
|
|
2f1b92ba12 | ||
|
|
6428006e92 | ||
|
|
78a3c34ca2 | ||
|
|
c13ee047c8 | ||
|
|
c1784e6b4c | ||
|
|
498562a0e5 | ||
|
|
15f02f424c | ||
|
|
c20c0a1e75 | ||
|
|
6d80a782d0 | ||
|
|
2fd9e3776b | ||
|
|
16df5aebc9 | ||
|
|
8a282bbf9e | ||
|
|
5e55e0d280 | ||
|
|
bd8d73a7d5 | ||
|
|
b361c43c61 | ||
|
|
9f45d4d696 | ||
|
|
aa34213e75 | ||
|
|
b54c784f20 | ||
|
|
5af462da66 | ||
|
|
c46c79caa2 | ||
|
|
2adea0d04e | ||
|
|
7720b5d9df | ||
|
|
f894c98ebc | ||
|
|
1aa7610988 | ||
|
|
02929519ba | ||
|
|
49e8fc13b0 | ||
|
|
22f216f372 | ||
|
|
55563ee093 | ||
|
|
38ee3de94f | ||
|
|
c9c4a3ad02 | ||
|
|
43e62982f4 | ||
|
|
59aff80a90 | ||
|
|
5240308ed2 | ||
|
|
0dcab1bed4 | ||
|
|
85ca4a31a0 | ||
|
|
553348c5f3 | ||
|
|
658b4c0ee7 | ||
|
|
41d3318c10 | ||
|
|
8354804874 | ||
|
|
bf4c66a207 | ||
|
|
70d1d20609 | ||
|
|
b7ab8113fe | ||
|
|
80108bef0e | ||
|
|
e2ddd4a2fd | ||
|
|
96295b0151 | ||
|
|
7cd225ff30 | ||
|
|
fa84674fb9 | ||
|
|
a1beeadf6c | ||
|
|
fcf174f284 | ||
|
|
29dd55c971 | ||
|
|
52e06a03d8 | ||
|
|
8f22bd9be0 | ||
|
|
5d659010d2 | ||
|
|
8e1d78b43a | ||
|
|
db0645ad80 | ||
|
|
6e2667d4d2 | ||
|
|
b670d49ae2 | ||
|
|
91d791cd85 | ||
|
|
275cdefdd7 | ||
|
|
f14b389544 | ||
|
|
b8076815be | ||
|
|
6734623337 | ||
|
|
ea58b7b66f | ||
|
|
7635c56e5d | ||
|
|
ec58b631ce | ||
|
|
49dd27a4ea |
@@ -0,0 +1,3 @@
|
||||
*.bmp
|
||||
*.gif
|
||||
*.png
|
||||
@@ -0,0 +1,24 @@
|
||||
*.a
|
||||
*.dll
|
||||
*.dylib
|
||||
*.exe
|
||||
*.exp
|
||||
*.lib
|
||||
*.o
|
||||
*.obj
|
||||
*.res
|
||||
*.sl
|
||||
*.so
|
||||
*/Makefile
|
||||
*/config.cache
|
||||
*/config.log
|
||||
*/config.status
|
||||
*/tclConfig.sh
|
||||
*/tclsh*
|
||||
*/tcltest*
|
||||
*/versions.vc
|
||||
unix/dltest.marker
|
||||
unix/tcl.pc
|
||||
unix/pkgs/*
|
||||
win/pkgs/*
|
||||
win/tcl.hpj
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>tcl8.6</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
line.separator=\n
|
||||
@@ -1,3 +1,477 @@
|
||||
2013-04-19 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclDecls.h: Implement many Tcl_*Var* functions and
|
||||
Tcl_GetIndexFromObj as (faster/stack-saving) macros around resp
|
||||
their Tcl_*Var*2 equivalent and Tcl_GetIndexFromObjStruct.
|
||||
|
||||
2013-04-12 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclDecls.h: Implement Tcl_Pkg* functions as
|
||||
(faster/stack-saving) macros around Tcl_Pkg*Ex functions.
|
||||
|
||||
2013-04-08 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/regc_color.c: [Bug 3610026] Stop crash when the number of
|
||||
* generic/regerrs.h: "colors" in a regular expression overflows
|
||||
* generic/regex.h: a short int. Thanks to Heikki Linnakangas
|
||||
* generic/regguts.h: for the report and the patch.
|
||||
* tests/regexp.test:
|
||||
|
||||
2013-04-04 Reinhard Max <max@suse.de>
|
||||
|
||||
* library/http/http.tcl (http::geturl): Allow URLs that don't have
|
||||
a path, but a query query, e.g. http://example.com?foo=bar .
|
||||
* Bump the http package to 2.8.7.
|
||||
|
||||
2013-03-22 Venkat Iyer <venkat@comit.com>
|
||||
* library/tzdata/Africa/Cairo: Update to tzdata2013b.
|
||||
* library/tzdata/Africa/Casablanca:
|
||||
* library/tzdata/Africa/Gaborone:
|
||||
* library/tzdata/Africa/Tripoli:
|
||||
* library/tzdata/America/Asuncion:
|
||||
* library/tzdata/America/Barbados:
|
||||
* library/tzdata/America/Bogota:
|
||||
* library/tzdata/America/Costa_Rica:
|
||||
* library/tzdata/America/Curacao:
|
||||
* library/tzdata/America/Nassau:
|
||||
* library/tzdata/America/Port-au-Prince:
|
||||
* library/tzdata/America/Santiago:
|
||||
* library/tzdata/Antarctica/Palmer:
|
||||
* library/tzdata/Asia/Aden:
|
||||
* library/tzdata/Asia/Hong_Kong:
|
||||
* library/tzdata/Asia/Muscat:
|
||||
* library/tzdata/Asia/Rangoon:
|
||||
* library/tzdata/Asia/Shanghai:
|
||||
* library/tzdata/Atlantic/Bermuda:
|
||||
* library/tzdata/Europe/Vienna:
|
||||
* library/tzdata/Pacific/Easter:
|
||||
* library/tzdata/Pacific/Fiji:
|
||||
* library/tzdata/Asia/Khandyga: (new)
|
||||
* library/tzdata/Asia/Ust-Nera: (new)
|
||||
* library/tzdata/Europe/Busingen: (new)
|
||||
|
||||
2013-03-21 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* library/auto.tcl: [Bug 2102614] Add ensemble indexing support
|
||||
* tests/autoMkindex.test: to [auto_mkindex]. Thanks Brian Griffin.
|
||||
|
||||
2013-03-19 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/tclFCmd.c: [Bug 3597000] Consistent [file copy] result.
|
||||
* tests/fileSystem.test:
|
||||
|
||||
2013-03-19 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* win/tclWinFile.c: [Bug 3608360]: Incompatible behaviour of "file
|
||||
exists".
|
||||
|
||||
2013-03-18 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* tests/cmdAH.test (cmdAH-19.12): [Bug 3608360]: Added test to ensure
|
||||
that we never ever allow [file exists] to do globbing.
|
||||
|
||||
2013-03-12 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* unix/tcl.m4: Patch by Andrew Shadura, providing better support for
|
||||
three architectures they have in Debian.
|
||||
|
||||
2013-03-11 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/tclCompile.c: [Bugs 3607246,3607372] Unbalanced refcounts
|
||||
* generic/tclLiteral.c: of literals in the global literal table.
|
||||
|
||||
2013-03-06 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/regc_nfa.c: [Bugs 3604074,3606683] Rewrite of the
|
||||
* generic/regcomp.c: fixempties() routine (and supporting
|
||||
routines) to completely eliminate the infinite loop hazard.
|
||||
Thanks to Tom Lane for the much improved solution.
|
||||
|
||||
2013-02-28 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/tclLiteral.c: Revise TclReleaseLiteral() to tolerate a
|
||||
NULL interp argument.
|
||||
|
||||
* generic/tclCompile.c: Update callers and revise mistaken comments.
|
||||
* generic/tclProc.c:
|
||||
|
||||
2013-02-27 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/regcomp.c: [Bug 3606139]: missing error check allows
|
||||
* tests/regexp.test: regexp to crash Tcl. Thanks to Tom Lane for
|
||||
providing the test-case and the patch.
|
||||
|
||||
2013-02-26 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* tests/chanio.test (chan-io-28.7): [Bug 3605120]: Stop test from
|
||||
hanging when run standalone.
|
||||
|
||||
2013-02-26 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclObj.c: Don't panic if Tcl_ConvertToType is called for a
|
||||
type that doesn't have a setFromAnyProc, create a proper error message.
|
||||
|
||||
2013-02-25 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* tests/binary.test (binary-41.*): [Bug 3605721]: Test independence
|
||||
fixes. Thanks to Rolf Ade for pointing out the problem.
|
||||
|
||||
2013-02-25 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* tests/assocd.test: [Bugs 3605719,3605720]: Test independence.
|
||||
* tests/basic.test: Thanks Rolf Ade for patches.
|
||||
|
||||
2013-02-23 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* compat/fake-rfc2553.c: [Bug 3599194]: compat/fake-rfc2553.c is
|
||||
broken.
|
||||
|
||||
2013-02-22 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/tclAssembly.c: Shift more burden of smart cleanup
|
||||
* generic/tclCompile.c: onto the TclFreeCompileEnv() routine.
|
||||
Stop crashes when the hookProc raises an error.
|
||||
|
||||
2013-02-20 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/tclNamesp.c: [Bug 3605447]: Make sure the -clear option
|
||||
* tests/namespace.test: to [namespace export] always clears, whether
|
||||
or not new export patterns are specified.
|
||||
|
||||
2013-02-20 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* win/tclWinDde.c: [Bug 3605401]: Compiler error with latest mingw-w64
|
||||
headers.
|
||||
|
||||
2013-02-19 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclTrace.c: [Bug 2438181]: Incorrect error reporting in
|
||||
* tests/trace.test: traces. Test-case and fix provided by Poor
|
||||
Yorick.
|
||||
|
||||
2013-02-15 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/regc_nfa.c: [Bug 3604074]: Fix regexp optimization to
|
||||
* tests/regexp.test: stop hanging on the expression
|
||||
((((((((a)*)*)*)*)*)*)*)* . Thanks to Bjørn Grathwohl for discovery.
|
||||
|
||||
2013-02-14 Harald Oehlmann <oehhar@users.sf.net>
|
||||
|
||||
* library/msgcat/msgcat.tcl: [Bug 3604576]: Catch missing registry
|
||||
entry "HCU\Control Panel\International".
|
||||
Bumped msgcat version to 1.5.1
|
||||
|
||||
2013-02-11 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclZlib.c (ZlibTransformOutput): [Bug 3603553]: Ensure that
|
||||
data gets written to the underlying stream by compressing transforms
|
||||
when the amount of data to be written is one buffer's-worth; problem
|
||||
was particularly likely to occur when compressing large quantities of
|
||||
not-very-compressible data. Many thanks to Piera Poggio (vampiera) for
|
||||
reporting.
|
||||
|
||||
2013-02-09 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclOOBasic.c (TclOO_Object_VarName): [Bug 3603695]: Change
|
||||
the way that the 'varname' method is implemented so that there are no
|
||||
longer problems with interactions due to the resolver. Thanks to
|
||||
Taylor Venable <tcvena@gmail.com> for identifying the problem.
|
||||
|
||||
2013-02-08 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/regc_nfa.c (duptraverse): [Bug 3603557]: Increase the
|
||||
maximum depth of recursion used when duplicating an automaton in
|
||||
response to encountering a "wild" RE that hit the previous limit.
|
||||
Allow the limit (DUPTRAVERSE_MAX_DEPTH) to be set by defining its
|
||||
value in the Makefile. Problem reported by Jonathan Mills.
|
||||
|
||||
2013-02-05 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* win/tclWinFile.c: [Bug 3603434]: Make sure TclpObjNormalizePath()
|
||||
properly declares "a:/" to be normalized, even when no "A:" drive is
|
||||
present on the system.
|
||||
|
||||
2013-02-05 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclLoadNone.c (TclpLoadMemory): [Bug 3433012]: Added dummy
|
||||
version of this function to use in the event that a platform thinks it
|
||||
can load from memory but cannot actually do so due to it being
|
||||
disabled at configuration time.
|
||||
|
||||
2013-02-04 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclCompCmds.c (TclCompileArraySetCmd): [Bug 3603163]: Stop
|
||||
crash in weird case where [eval] is used to make [array set] get
|
||||
confused about whether there is a local variable table or not. Thanks
|
||||
to Poor Yorick for identifying a reproducible crashing case.
|
||||
|
||||
2013-01-30 Andreas Kupries <andreask@activestate.com>
|
||||
|
||||
* library/platform/platform.tcl (::platform::LibcVersion): See
|
||||
* library/platform/pkgIndex.tcl: [Bug 3599098]: Fixed the RE
|
||||
* unix/Makefile.in: extracting the version to avoid issues with
|
||||
* win/Makefile.in: recent changes to the glibc banner. Now targeting a
|
||||
less variable part of the string. Bumped package to version 1.0.11.
|
||||
|
||||
2013-01-28 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclCompCmds.c (TclCompileArraySetCmd)
|
||||
(TclCompileArrayUnsetCmd, TclCompileDictAppendCmd)
|
||||
(TclCompileDictCreateCmd, CompileDictEachCmd, TclCompileDictIncrCmd)
|
||||
(TclCompileDictLappendCmd, TclCompileDictMergeCmd)
|
||||
(TclCompileDictUnsetCmd, TclCompileDictUpdateCmd)
|
||||
(TclCompileDictWithCmd, TclCompileInfoCommandsCmd):
|
||||
* generic/tclCompCmdsSZ.c (TclCompileStringMatchCmd)
|
||||
(TclCompileStringMapCmd): Improve the code generation in cases where
|
||||
full compilation is impossible but a full ensemble invoke is provably
|
||||
not necessary.
|
||||
|
||||
2013-01-26 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* unix/tclUnixCompat.c: [Bug 3601804]: platformCPUID segmentation
|
||||
fault on Darwin.
|
||||
|
||||
2013-01-23 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* library/http/http.tcl (http::geturl): [Bug 2911139]: Do not do vwait
|
||||
for connect to avoid reentrancy problems (except when operating
|
||||
without a -command option). Internally, this means that all sockets
|
||||
created by the http package will always be operated in asynchronous
|
||||
mode.
|
||||
|
||||
2013-01-21 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclInt.decls: Put back Tcl[GS]etStartupScript(Path|FileName)
|
||||
in private stub table, so extensions using this (like Tk 8.4) will
|
||||
continue to work in all Tcl 8.x versions. Extensions using this
|
||||
still cannot be compiled against Tcl 8.6 headers.
|
||||
|
||||
2013-01-18 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclPort.h: [Bug 3598300]: unix: tcl.h does not include
|
||||
sys/stat.h
|
||||
|
||||
2013-01-17 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclCompCmds.c (PushVarName): [Bug 3600328]: Added mechanism
|
||||
for suppressing compilation of variables when we couldn't cope with
|
||||
the results. Useful for some [array] subcommands.
|
||||
* generic/tclEnsemble.c (CompileToCompiledCommand): Must restore the
|
||||
compilation environment when a command compiler fails.
|
||||
|
||||
2013-01-16 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclZlib.c (TclZlibInit): [Bug 3601086]: Register the config
|
||||
info in the iso8859-1 encoding as that is guaranteed to be present.
|
||||
|
||||
2013-01-16 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* Makefile.in: Allow win32 build with -DTCL_NO_DEPRECATED, just as
|
||||
* generic/tcl.h: in the UNIX build. Define Tcl_EvalObj and
|
||||
* generic/tclDecls.h: Tcl_GlobalEvalObj as macros, even when
|
||||
* generic/tclBasic.c: TCL_NO_DEPRECATED is defined, so Tk can benefit
|
||||
from it too.
|
||||
|
||||
2013-01-14 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* win/tcl.m4: More flexible search for win32 tclConfig.sh, backported
|
||||
from TEA (not actually used in Tcl, only for Tk)
|
||||
|
||||
2013-01-14 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclInt.decls: Put back Tcl_[GS]etStartupScript in internal
|
||||
stub table, so extensions using this, compiled against 8.5 headers
|
||||
still run in Tcl 8.6.
|
||||
|
||||
2013-01-13 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
|
||||
|
||||
* doc/fileevent.n: [Bug 3436609]: Clarify readable fileevent "false
|
||||
positives" in the case of multibyte encodings/transforms.
|
||||
|
||||
2013-01-13 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclIntDecls.h: If TCL_NO_DEPRECATED is defined, make sure
|
||||
that TIP #139 functions all are taken from the public stub table, even
|
||||
if the inclusion is through tclInt.h.
|
||||
|
||||
2013-01-12 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclInt.decls: Put back TclBackgroundException in internal
|
||||
stub table, so extensions using this, compiled against 8.5 headers
|
||||
still run in Tcl 8.6.
|
||||
|
||||
2013-01-09 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* library/http/http.tcl: [Bug 3599395]: http assumes status line is a
|
||||
proper Tcl list.
|
||||
|
||||
2013-01-08 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* win/tclWinFile.c: [Bug 3092089]: [file normalize] can remove path
|
||||
components. [Bug 3587096]: win vista/7: "can't find init.tcl" when
|
||||
called via junction without folder list access.
|
||||
|
||||
2013-01-07 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclOOStubLib.c: Restrict the stub library to only use
|
||||
* generic/tclTomMathStubLib.c: Tcl_PkgRequireEx, Tcl_ResetResult and
|
||||
Tcl_AppendResult, not any other function. This puts least restrictions
|
||||
on eventual Tcl 9 stubs re-organization, and it works on the widest
|
||||
range of Tcl versions.
|
||||
|
||||
2013-01-06 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* library/http/http.tcl: Don't depend on Spencer-specific regexp
|
||||
* tests/env.test: syntax (/u and /U) any more in unrelated places.
|
||||
* tests/exec.test:
|
||||
Bump http package to 2.8.6.
|
||||
|
||||
2013-01-04 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclEnsemble.c (CompileBasicNArgCommand): Added very simple
|
||||
compiler (which just compiles to a normal invoke of the implementation
|
||||
command) for many ensemble subcommands where we can prove that there
|
||||
is no way for scripts to detect the difference even through error
|
||||
handling or [info level]/[info frame]. This improves the code produced
|
||||
from some ensembles (e.g., [info], [string]) to the point where the
|
||||
ensemble is now not normally seen at the bytecode level at all.
|
||||
|
||||
2013-01-04 Miguel Sofer <msofer@users.sf.net>
|
||||
|
||||
* generic/tclInt.h: Insure that PURIFY builds cannot exploit the
|
||||
* generic/tclExecute.c: Tcl stack to hide mem defects.
|
||||
|
||||
2013-01-03 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* doc/fconfigure.n, doc/CrtChannel.3: Updated to reflect the fact that
|
||||
the minimum buffer size is one byte, not ten. Identified by Schelte
|
||||
Bron on the Tcler's Chat.
|
||||
|
||||
* generic/tclExecute.c (TEBCresume:INST_INVOKE_REPLACE):
|
||||
* generic/tclEnsemble.c (TclCompileEnsemble): Added new mechanism to
|
||||
allow for more efficient dispatch of non-bytecode-compiled subcommands
|
||||
of bytecode-compiled ensembles. This can provide substantial speed
|
||||
benefits in some cases.
|
||||
|
||||
2013-01-02 Miguel Sofer <msofer@users.sf.net>
|
||||
|
||||
* generic/tclEnsemble.c: Remove stray calls to Tcl_Alloc and friends:
|
||||
* generic/tclExecute.c: the core should only use ckalloc to allow
|
||||
* generic/tclIORTrans.c: MEM_DEBUG to work properly.
|
||||
* generic/tclTomMathInterface.c:
|
||||
|
||||
2012-12-31 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* doc/string.n: Noted the obsolescence of the 'bytelength',
|
||||
'wordstart' and 'wordend' subcommands, and moved them to later in the
|
||||
file.
|
||||
|
||||
2012-12-27 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tclListObj.c: [Bug 3598580]: Tcl_ListObjReplace may release
|
||||
deleted elements too early.
|
||||
|
||||
2012-12-22 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
|
||||
|
||||
* generic/tclUtil.c: [Bug 3598150]: Stop leaking allocated space when
|
||||
objifying a zero-length DString. Spotted by afredd.
|
||||
|
||||
2012-12-21 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* unix/dltest/pkgb.c: Inline compat Tcl_GetDefaultEncodingDir.
|
||||
* generic/tclStubLib.c: Eliminate unnecessary static HasStubSupport()
|
||||
and isDigit() functions, just do the same inline.
|
||||
|
||||
2012-12-18 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclCompCmdsSZ.c (TclSubstCompile): Improved the sequence of
|
||||
instructions issued for [subst] when dealing with simple variable
|
||||
references.
|
||||
|
||||
2012-12-14 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
*** 8.6.0 TAGGED FOR RELEASE ***
|
||||
|
||||
* changes: updates for 8.6.0
|
||||
|
||||
2012-12-13 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/tclZlib.c: Repair same issue with misusing the
|
||||
* tests/zlib.test: 'fire and forget' nature of Tcl_ObjSetVar2
|
||||
in the new TIP 400 implementation.
|
||||
|
||||
2012-12-13 Miguel Sofer <msofer@users.sf.net>
|
||||
|
||||
* generic/tclCmdAH.c: (CatchObjCmdCallback): do not decrRefCount
|
||||
* tests/cmdAH.test: the newValuePtr sent to Tcl_ObjSetVar2:
|
||||
TOSV2 is 'fire and forget', it decrs on its own.
|
||||
Fix for [Bug 3595576], found by andrewsh.
|
||||
|
||||
2012-12-13 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* generic/tcl.h: Fix Tcl_DecrRefCount macro such that it doesn't
|
||||
access its objPtr parameter twice any more.
|
||||
|
||||
2012-12-11 Don Porter <dgp@users.sourceforge.net>
|
||||
|
||||
* generic/tcl.h: Bump version number to 8.6.0.
|
||||
* library/init.tcl:
|
||||
* unix/configure.in:
|
||||
* win/configure.in:
|
||||
* unix/tcl.spec:
|
||||
* README:
|
||||
|
||||
* unix/configure: autoconf-2.59
|
||||
* win/configure:
|
||||
|
||||
2012-12-10 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* tools/tcltk-man2html.tcl (plus-pkgs): Increased robustness of
|
||||
version number detection code to deal with packages whose names are
|
||||
prefixes of other packages.
|
||||
* unix/Makefile.in (dist): Added pkgs/package.list.txt to distribution
|
||||
builds to ensure that 'make html' will work better.
|
||||
|
||||
2012-12-09 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
|
||||
|
||||
* tests/chan.test: Clean up unwanted eofchar side-effect of chan-4.6
|
||||
leading to a spurious "'" at end of chan.test under certain conditions
|
||||
(see [Bug 3389289] and [Bug 3389251]).
|
||||
|
||||
* doc/expr.n: [Bug 3594188]: Clarifications about commas.
|
||||
|
||||
2012-12-08 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
|
||||
|
||||
* generic/tclIO.c: Fix busyloop at exit under TCL_FINALIZE_ON_EXIT
|
||||
when there are unflushed nonblocking channels. Thanks Miguel for
|
||||
spotting.
|
||||
|
||||
2012-12-07 Jan Nijtmans <nijtmans@users.sf.net>
|
||||
|
||||
* unix/dltest/pkgb.c: Turn pkgb.so into a Tcl9 interoperability test
|
||||
library: Whatever Tcl9 looks like, loading pkgb.so in Tcl 9 should
|
||||
either result in an error-message, either succeed, but never crash.
|
||||
|
||||
2012-11-28 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclZlib.c (ZlibStreamSubcmd): [Bug 3590483]: Use a mechanism
|
||||
for complex option resolution that has fewer problems with more
|
||||
finicky compilers.
|
||||
|
||||
2012-11-26 Reinhard Max <max@suse.de>
|
||||
|
||||
* unix/tclUnixSock.c: Factor out creation of the -sockname and
|
||||
-peername lists from TcpGetOptionProc() to TcpHostPortList(). Make it
|
||||
robust against implementations of getnameinfo() that error out if
|
||||
reverse mapping fails instead of falling back to the numeric
|
||||
representation.
|
||||
|
||||
2012-11-20 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclBinary.c (BinaryDecode64): [Bug 3033307]: Corrected
|
||||
handling of trailing whitespace when decoding base64. Thanks to Anton
|
||||
Kovalenko for reporting, and Andy Goth for the fix and tests.
|
||||
|
||||
2012-11-19 Donal K. Fellows <dkf@users.sf.net>
|
||||
|
||||
* generic/tclExecute.c (INST_STR_RANGE_IMM): [Bug 3588366]: Corrected
|
||||
@@ -3940,6 +4414,7 @@
|
||||
* generic/*Decls.h: (regenerated)
|
||||
|
||||
2010-08-18 Miguel Sofer <msofer@users.sf.net>
|
||||
|
||||
* generic/tclBasic.c: New redesign of [tailcall]: find
|
||||
* generic/tclExecute.c: errors early on, so that errorInfo
|
||||
* generic/tclInt.h: contains the proper info [Bug 3047235]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
README: Tcl
|
||||
This is the Tcl 8.6b3 source distribution.
|
||||
This is the Tcl 8.6.0 source distribution.
|
||||
http://tcl.sourceforge.net/
|
||||
You can get any source release of Tcl from the file distributions
|
||||
link at the above URL.
|
||||
|
||||
@@ -8117,11 +8117,49 @@ Dropped support for OS X versions less than 10.4 (Tiger) (fellows)
|
||||
|
||||
--- Released 8.6b3, September 18, 2012 --- See ChangeLog for details ---
|
||||
|
||||
2012-09-20 (enhancement) full Unicode support (nijtmans)
|
||||
=> dde 1.4.0
|
||||
|
||||
2012-09-20 (enhancement) update bundled zlib to 1.2.7 (nijtmans)
|
||||
|
||||
2012-10-03 (bug fix) exit panic on stacked std channel (griffin,porter)
|
||||
|
||||
2012-10-14 (bug fix) [tcl::Bgerror] crash on non-dict options (nijtmans)
|
||||
|
||||
2012-10-16 (TIP 400) New [zlib] options to set compression dict (fellows)
|
||||
|
||||
2012-10-16 (TIP 405) New commands [lmap] and [dict map] (fellows)
|
||||
|
||||
2012-10-24 (enhancement) [dict unset] now bytecompiled (fellows)
|
||||
|
||||
2012-11-05 (TIP 413) Revisions to default [string trim*] trimset (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2012-11-05 (enhancement) Now bytecompiled: [array exists], [array set],
|
||||
[array unset], [dict create], [dict exists], [dict merge], [format],
|
||||
[info commands], [info coroutine], [info level], [info object],
|
||||
[namespace current], [namespace code], [namespace qualifiers], [namespace tail],
|
||||
[namespace which], [regsub], [self], [string first], [string last],
|
||||
[string map], [string range], [tailcall], [yield]. (fellows)
|
||||
|
||||
2012-11-06 (bug fix)[3581754] avoid multiple callback on keep-alive (fellows)
|
||||
=> http 2.8.5
|
||||
|
||||
--- Released 8.6.0, ??? ??, 2012 --- See ChangeLog for details ---
|
||||
2012-11-07 tzdata updated to Olson's tzdata2012i (kenny)
|
||||
|
||||
2012-11-13 (bug fix)[3567063] thread fp settings from master (mistachkin)
|
||||
|
||||
2012-11-14 (bug fix)[2933003] tempfile creation in $TMPDIR (fellows)
|
||||
|
||||
2012-11-15 (TIP 416) New [load] options -global and -lazy (nijtmans)
|
||||
|
||||
2012-11-20 (bug fix)[3033307] base64 trail whitespace (kovalenko,goth)
|
||||
|
||||
2012-12-03 (bug fix) [configure] query broke init from argv (porter)
|
||||
=> tcltest 2.3.5
|
||||
|
||||
2012-12-13 (bug fix)[3595576] crash: [catch {} -> noSuchNs::var] (sofer,porter)
|
||||
|
||||
2012-12-13 (bug fix) crash: [zlib gunzip $data -header noSuchNs::var] (porter)
|
||||
|
||||
--- Released 8.6.0, December 20, 2012 --- See ChangeLog for details ---
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#ifndef _DIRENT
|
||||
#define _DIRENT
|
||||
|
||||
#include "tcl.h"
|
||||
|
||||
/*
|
||||
* Dirent structure, which holds information about a single
|
||||
* directory entry.
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#ifndef __dlfcn_h__
|
||||
#define __dlfcn_h__
|
||||
|
||||
#include "tcl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -84,7 +84,7 @@ int fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
|
||||
|
||||
if (host != NULL) {
|
||||
if (flags & NI_NUMERICHOST) {
|
||||
int len;
|
||||
size_t len;
|
||||
Tcl_MutexLock(&netdbMutex);
|
||||
len = strlcpy(host, inet_ntoa(sin->sin_addr), hostlen);
|
||||
Tcl_MutexUnlock(&netdbMutex);
|
||||
@@ -135,7 +135,7 @@ fake_gai_strerror(int err)
|
||||
|
||||
#ifndef HAVE_FREEADDRINFO
|
||||
void
|
||||
freeaddrinfo(struct addrinfo *ai)
|
||||
fake_freeaddrinfo(struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *next;
|
||||
|
||||
@@ -199,7 +199,7 @@ fake_getaddrinfo(const char *hostname, const char *servname,
|
||||
|
||||
port = strtol(servname, &cp, 10);
|
||||
if (port > 0 && port <= 65535 && *cp == '\0')
|
||||
port = htons(port);
|
||||
port = htons((unsigned short)port);
|
||||
else if ((sp = getservbyname(servname, NULL)) != NULL)
|
||||
port = sp->s_port;
|
||||
else
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
#ifndef _STRING
|
||||
#define _STRING
|
||||
|
||||
#include "tcl.h"
|
||||
|
||||
/*
|
||||
* The following #include is needed to define size_t. (This used to include
|
||||
* sys/stdtypes.h but that doesn't exist on older versions of SunOS, e.g.
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#ifndef _UNISTD
|
||||
#define _UNISTD
|
||||
|
||||
#include "tcl.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef NULL
|
||||
|
||||
+2
-2
@@ -250,8 +250,8 @@ the default value of 4096 is returned.
|
||||
.PP
|
||||
\fBTcl_SetChannelBufferSize\fR sets the size, in bytes, of buffers that
|
||||
will be allocated in subsequent operations on the channel to store input or
|
||||
output. The \fIsize\fR argument should be between ten and one million,
|
||||
allowing buffers of ten bytes to one million bytes. If \fIsize\fR is
|
||||
output. The \fIsize\fR argument should be between one and one million,
|
||||
allowing buffers of one byte to one million bytes. If \fIsize\fR is
|
||||
outside this range, \fBTcl_SetChannelBufferSize\fR sets the buffer size to
|
||||
4096.
|
||||
.PP
|
||||
|
||||
+3
-3
@@ -63,9 +63,9 @@ Define the \fBUSE_TCL_STUBS\fR symbol. Typically, you would include the
|
||||
\fB\-DUSE_TCL_STUBS\fR flag when compiling the extension.
|
||||
.IP 3) 5
|
||||
Link the extension with the Tcl stubs library instead of the standard
|
||||
Tcl library. For example, to use the Tcl 8.1 ABI on Unix platforms,
|
||||
the library name is \fIlibtclstub8.1.a\fR; on Windows platforms, the
|
||||
library name is \fItclstub81.lib\fR.
|
||||
Tcl library. For example, to use the Tcl 8.6 ABI on Unix platforms,
|
||||
the library name is \fIlibtclstub8.6.a\fR; on Windows platforms, the
|
||||
library name is \fItclstub86.lib\fR.
|
||||
.PP
|
||||
If the extension also requires the Tk API, it must also call
|
||||
\fBTk_InitStubs\fR to initialize the Tk stubs interface and link
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ Array of names of symbols to be resolved during the load of the library, or
|
||||
NULL if no symbols are to be resolved. If an array is given, the last entry in
|
||||
the array must be NULL.
|
||||
.AP int flags in
|
||||
The value should normally be 0, but \fITCL_LOAD_GLOBALfR or \fITCL_LOAD_LAZYfR
|
||||
The value should normally be 0, but \fITCL_LOAD_GLOBAL\fR or \fITCL_LOAD_LAZY\fR
|
||||
or a combination of those two is allowed as well.
|
||||
.AP void *procPtrs out
|
||||
Points to an array that will hold the addresses of the functions described in
|
||||
|
||||
@@ -144,7 +144,7 @@ resolution is already known. The \fIcmd\fR parameter gives a
|
||||
\fBTcl_Command\fR token (returned from \fBTcl_CreateObjCommand\fR or
|
||||
\fBTcl_GetCommandFromObj\fR) identifying the command to be invoked in
|
||||
the trampoline; this command must match the word in \fIobjv[0]\fR.
|
||||
The remaining arguments are as for \fBTcl_NREvalObj\fR.
|
||||
The remaining arguments are as for \fBTcl_NREvalObjv\fR.
|
||||
.PP
|
||||
\fBTcl_NREvalObj\fR, \fBTcl_NREvalObjv\fR and \fBTcl_NRCmdSwap\fR
|
||||
all accept a \fIflags\fR parameter, which is an OR-ed-together set of
|
||||
@@ -295,7 +295,7 @@ int
|
||||
int result)
|
||||
{
|
||||
/* \fIdata[0] .. data[3]\fR are the four words of data
|
||||
* passed to \fBTcl_NREvalObj\fR */
|
||||
* passed to \fBTcl_NRAddCallback\fR */
|
||||
|
||||
\fI... postprocessing ...\fR
|
||||
|
||||
|
||||
+14
-2
@@ -39,9 +39,9 @@ additional operators not found in C.
|
||||
.SS OPERANDS
|
||||
.PP
|
||||
A Tcl expression consists of a combination of operands, operators,
|
||||
and parentheses.
|
||||
parentheses and commas.
|
||||
White space may be used between the operands and operators and
|
||||
parentheses; it is ignored by the expression's instructions.
|
||||
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
|
||||
@@ -283,6 +283,18 @@ rules for resolving functions in namespaces. Either
|
||||
current]::tcl::mathfunc::sin\fR will satisfy the request, and others
|
||||
may as well (depending on the current \fBnamespace path\fR setting).
|
||||
.PP
|
||||
Some mathematical functions have several arguments, separated by commas like in C. Thus:
|
||||
.PP
|
||||
.CS
|
||||
\fBexpr\fR {hypot($x,$y)}
|
||||
.CE
|
||||
.PP
|
||||
ends up as
|
||||
.PP
|
||||
.CS
|
||||
tcl::mathfunc::hypot $x $y
|
||||
.CE
|
||||
.PP
|
||||
See the \fBmathfunc\fR(n) manual page for the math functions that are
|
||||
available by default.
|
||||
.SS "TYPES, OVERFLOW, AND PRECISION"
|
||||
|
||||
+2
-2
@@ -72,8 +72,8 @@ initially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR.
|
||||
.
|
||||
\fINewvalue\fR must be an integer; its value is used to set the size of
|
||||
buffers, in bytes, subsequently allocated for this channel to store input
|
||||
or output. \fINewvalue\fR must be between ten and one million, allowing
|
||||
buffers of ten to one million bytes in size.
|
||||
or output. \fINewvalue\fR must be between one and one million, allowing
|
||||
buffers of one to one million bytes in size.
|
||||
.TP
|
||||
\fB\-encoding\fR \fIname\fR
|
||||
.
|
||||
|
||||
+10
-7
@@ -80,13 +80,16 @@ A channel is considered to be writable if at least one byte of data
|
||||
can be written to the underlying file or device without blocking,
|
||||
or if an error condition is present on the underlying file or device.
|
||||
.PP
|
||||
Event-driven I/O works best for channels that have been
|
||||
placed into nonblocking mode with the \fBfconfigure\fR command.
|
||||
In blocking mode, a \fBputs\fR command may block if you give it
|
||||
more data than the underlying file or device can accept, and a
|
||||
\fBgets\fR or \fBread\fR command will block if you attempt to read
|
||||
more data than is ready; no events will be processed while the
|
||||
commands block.
|
||||
Event-driven I/O works best for channels that have been placed into
|
||||
nonblocking mode with the \fBfconfigure\fR command. In blocking mode,
|
||||
a \fBputs\fR command may block if you give it more data than the
|
||||
underlying file or device can accept, and a \fBgets\fR or \fBread\fR
|
||||
command will block if you attempt to read more data than is ready; a
|
||||
readable underlying file or device may not even guarantee that a
|
||||
blocking [read 1] will succeed (counter-examples being multi-byte
|
||||
encodings, compression or encryption transforms ). In all such cases,
|
||||
no events will be processed while the commands block.
|
||||
.PP
|
||||
In nonblocking mode \fBputs\fR, \fBread\fR, and \fBgets\fR never block.
|
||||
See the documentation for the individual commands for information
|
||||
on how they handle blocking and nonblocking channels.
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ msgcat \- Tcl message catalog
|
||||
.SH SYNOPSIS
|
||||
\fBpackage require Tcl 8.5\fR
|
||||
.sp
|
||||
\fBpackage require msgcat 1.5.0\fR
|
||||
\fBpackage require msgcat 1.5\fR
|
||||
.sp
|
||||
\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
|
||||
.sp
|
||||
|
||||
+1
-1
@@ -287,7 +287,7 @@ This command is the complement of the \fBnamespace qualifiers\fR command.
|
||||
It does not check whether the namespace names are, in fact,
|
||||
the names of currently defined namespaces.
|
||||
.TP
|
||||
\fBnamespace upvar\fR \fInamespace\fR ?\fIotherVar myVar \fR...
|
||||
\fBnamespace upvar\fR \fInamespace\fR ?\fIotherVar myVar \fR...?
|
||||
.
|
||||
This command arranges for zero or more local variables in the current
|
||||
procedure to refer to variables in \fInamespace\fR. The namespace name is
|
||||
|
||||
+27
-22
@@ -19,27 +19,7 @@ string \- Manipulate strings
|
||||
Performs one of several string operations, depending on \fIoption\fR.
|
||||
The legal \fIoption\fRs (which may be abbreviated) are:
|
||||
.TP
|
||||
\fBstring bytelength \fIstring\fR
|
||||
.
|
||||
Returns a decimal string giving the number of bytes used to represent
|
||||
\fIstring\fR in memory. Because UTF\-8 uses one to three bytes to
|
||||
represent Unicode characters, the byte length will not be the same as
|
||||
the character length in general. The cases where a script cares about
|
||||
the byte length are rare.
|
||||
.RS
|
||||
.PP
|
||||
In almost all cases, you should use the
|
||||
\fBstring length\fR operation (including determining the length of a
|
||||
Tcl byte array value). Refer to the \fBTcl_NumUtfChars\fR manual
|
||||
entry for more details on the UTF\-8 representation.
|
||||
.PP
|
||||
\fICompatibility note:\fR it is likely that this subcommand will be
|
||||
withdrawn in a future version of Tcl. It is better to use the
|
||||
\fBencoding convertto\fR command to convert a string to a known
|
||||
encoding and then apply \fBstring length\fR to that.
|
||||
.RE
|
||||
.TP
|
||||
\fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length int\fR? \fIstring1 string2\fR
|
||||
\fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR
|
||||
.
|
||||
Perform a character-by-character comparison of strings \fIstring1\fR
|
||||
and \fIstring2\fR. Returns \-1, 0, or 1, depending on whether
|
||||
@@ -49,7 +29,7 @@ first \fIlength\fR characters are used in the comparison. If
|
||||
\fB\-length\fR is negative, it is ignored. If \fB\-nocase\fR is
|
||||
specified, then the strings are compared in a case-insensitive manner.
|
||||
.TP
|
||||
\fBstring equal\fR ?\fB\-nocase\fR? ?\fB\-length int\fR? \fIstring1 string2\fR
|
||||
\fBstring equal\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR
|
||||
.
|
||||
Perform a character-by-character comparison of strings \fIstring1\fR
|
||||
and \fIstring2\fR. Returns 1 if \fIstring1\fR and \fIstring2\fR are
|
||||
@@ -354,6 +334,31 @@ Returns a value equal to \fIstring\fR except that any trailing
|
||||
characters present in the string given by \fIchars\fR are removed. If
|
||||
\fIchars\fR is not specified then white space is removed (any character
|
||||
for which \fBstring is space\fR returns 1, and "\0").
|
||||
.SS "OBSOLETE SUBCOMMANDS"
|
||||
.PP
|
||||
These subcommands are currently supported, but are likely to go away in a
|
||||
future release as their functionality is either virtually never used or highly
|
||||
misleading.
|
||||
.TP
|
||||
\fBstring bytelength \fIstring\fR
|
||||
.
|
||||
Returns a decimal string giving the number of bytes used to represent
|
||||
\fIstring\fR in memory. Because UTF\-8 uses one to three bytes to
|
||||
represent Unicode characters, the byte length will not be the same as
|
||||
the character length in general. The cases where a script cares about
|
||||
the byte length are rare.
|
||||
.RS
|
||||
.PP
|
||||
In almost all cases, you should use the
|
||||
\fBstring length\fR operation (including determining the length of a
|
||||
Tcl byte array value). Refer to the \fBTcl_NumUtfChars\fR manual
|
||||
entry for more details on the UTF\-8 representation.
|
||||
.PP
|
||||
\fICompatibility note:\fR it is likely that this subcommand will be
|
||||
withdrawn in a future version of Tcl. It is better to use the
|
||||
\fBencoding convertto\fR command to convert a string to a known
|
||||
encoding and then apply \fBstring length\fR to that.
|
||||
.RE
|
||||
.TP
|
||||
\fBstring wordend \fIstring charIndex\fR
|
||||
.
|
||||
|
||||
@@ -87,7 +87,7 @@ Handle different reasons for a file to not be openable for reading:
|
||||
.PP
|
||||
.CS
|
||||
\fBtry\fR {
|
||||
set f [open /some/file/name]
|
||||
set f [open /some/file/name w]
|
||||
} \fBtrap\fR {POSIX EISDIR} {} {
|
||||
puts "failed to open /some/file/name: it's a directory"
|
||||
} \fBtrap\fR {POSIX ENOENT} {} {
|
||||
|
||||
@@ -254,7 +254,14 @@ newcolor(
|
||||
* Oops, must allocate more.
|
||||
*/
|
||||
|
||||
if (cm->max == MAX_COLOR) {
|
||||
CERR(REG_ECOLORS);
|
||||
return COLORLESS; /* too many colors */
|
||||
}
|
||||
n = cm->ncds * 2;
|
||||
if (n < MAX_COLOR + 1) {
|
||||
n = MAX_COLOR + 1;
|
||||
}
|
||||
if (cm->cd == cm->cdspace) {
|
||||
newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc));
|
||||
if (newCd != NULL) {
|
||||
|
||||
+259
-84
@@ -496,6 +496,62 @@ freearc(
|
||||
from->free = victim;
|
||||
}
|
||||
|
||||
/*
|
||||
- hasnonemptyout - Does state have a non-EMPTY out arc?
|
||||
^ static int hasnonemptyout(struct state *);
|
||||
*/
|
||||
static int
|
||||
hasnonemptyout(
|
||||
struct state *s)
|
||||
{
|
||||
struct arc *a;
|
||||
|
||||
for (a = s->outs; a != NULL; a = a->outchain) {
|
||||
if (a->type != EMPTY) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
- nonemptyouts - count non-EMPTY out arcs of a state
|
||||
^ static int nonemptyouts(struct state *);
|
||||
*/
|
||||
static int
|
||||
nonemptyouts(
|
||||
struct state *s)
|
||||
{
|
||||
int n = 0;
|
||||
struct arc *a;
|
||||
|
||||
for (a = s->outs; a != NULL; a = a->outchain) {
|
||||
if (a->type != EMPTY) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
- nonemptyins - count non-EMPTY in arcs of a state
|
||||
^ static int nonemptyins(struct state *);
|
||||
*/
|
||||
static int
|
||||
nonemptyins(
|
||||
struct state *s)
|
||||
{
|
||||
int n = 0;
|
||||
struct arc *a;
|
||||
|
||||
for (a = s->ins; a != NULL; a = a->inchain) {
|
||||
if (a->type != EMPTY) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
- findarc - find arc, if any, from given source with given type and color
|
||||
* If there is more than one such arc, the result is random.
|
||||
@@ -559,21 +615,25 @@ moveins(
|
||||
}
|
||||
|
||||
/*
|
||||
- copyins - copy all in arcs of a state to another state
|
||||
^ static void copyins(struct nfa *, struct state *, struct state *);
|
||||
- copyins - copy in arcs of a state to another state
|
||||
* Either all arcs, or only non-empty ones as determined by all value.
|
||||
^ static VOID copyins(struct nfa *, struct state *, struct state *, int);
|
||||
*/
|
||||
static void
|
||||
copyins(
|
||||
struct nfa *nfa,
|
||||
struct state *oldState,
|
||||
struct state *newState)
|
||||
struct state *newState,
|
||||
int all)
|
||||
{
|
||||
struct arc *a;
|
||||
|
||||
assert(oldState != newState);
|
||||
|
||||
for (a=oldState->ins ; a!=NULL ; a=a->inchain) {
|
||||
cparc(nfa, a, a->from, newState);
|
||||
if (all || a->type != EMPTY) {
|
||||
cparc(nfa, a, a->from, newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,21 +658,25 @@ moveouts(
|
||||
}
|
||||
|
||||
/*
|
||||
- copyouts - copy all out arcs of a state to another state
|
||||
^ static void copyouts(struct nfa *, struct state *, struct state *);
|
||||
- copyouts - copy out arcs of a state to another state
|
||||
* Either all arcs, or only non-empty ones as determined by all value.
|
||||
^ static VOID copyouts(struct nfa *, struct state *, struct state *, int);
|
||||
*/
|
||||
static void
|
||||
copyouts(
|
||||
struct nfa *nfa,
|
||||
struct state *oldState,
|
||||
struct state *newState)
|
||||
struct state *newState,
|
||||
int all)
|
||||
{
|
||||
struct arc *a;
|
||||
|
||||
assert(oldState != newState);
|
||||
|
||||
for (a=oldState->outs ; a!=NULL ; a=a->outchain) {
|
||||
cparc(nfa, a, newState, a->to);
|
||||
if (all || a->type != EMPTY) {
|
||||
cparc(nfa, a, newState, a->to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,7 +823,9 @@ duptraverse(
|
||||
* Arbitrary depth limit. Needs tuning, but this value is sufficient to
|
||||
* make all normal tests (not reg-33.14) pass.
|
||||
*/
|
||||
#define DUPTRAVERSE_MAX_DEPTH 500
|
||||
#ifndef DUPTRAVERSE_MAX_DEPTH
|
||||
#define DUPTRAVERSE_MAX_DEPTH 700
|
||||
#endif
|
||||
|
||||
if (depth++ > DUPTRAVERSE_MAX_DEPTH) {
|
||||
NERR(REG_ESPACE);
|
||||
@@ -968,9 +1034,9 @@ pull(
|
||||
if (NISERR()) {
|
||||
return 0;
|
||||
}
|
||||
assert(to != from); /* con is not an inarc */
|
||||
copyins(nfa, from, s); /* duplicate inarcs */
|
||||
cparc(nfa, con, s, to); /* move constraint arc */
|
||||
assert(to != from); /* con is not an inarc */
|
||||
copyins(nfa, from, s, 1); /* duplicate inarcs */
|
||||
cparc(nfa, con, s, to); /* move constraint arc */
|
||||
freearc(nfa, con);
|
||||
from = s;
|
||||
con = from->outs;
|
||||
@@ -1128,7 +1194,7 @@ push(
|
||||
if (NISERR()) {
|
||||
return 0;
|
||||
}
|
||||
copyouts(nfa, to, s); /* duplicate outarcs */
|
||||
copyouts(nfa, to, s, 1); /* duplicate outarcs */
|
||||
cparc(nfa, con, from, s); /* move constraint */
|
||||
freearc(nfa, con);
|
||||
to = s;
|
||||
@@ -1245,100 +1311,209 @@ fixempties(
|
||||
FILE *f) /* for debug output; NULL none */
|
||||
{
|
||||
struct state *s;
|
||||
struct state *s2;
|
||||
struct state *nexts;
|
||||
struct arc *a;
|
||||
struct arc *nexta;
|
||||
int progress;
|
||||
|
||||
/*
|
||||
* Find and eliminate empties until there are no more.
|
||||
* First, get rid of any states whose sole out-arc is an EMPTY,
|
||||
* since they're basically just aliases for their successor. The
|
||||
* parsing algorithm creates enough of these that it's worth
|
||||
* special-casing this.
|
||||
*/
|
||||
for (s = nfa->states; s != NULL && !NISERR(); s = nexts) {
|
||||
nexts = s->next;
|
||||
if (s->flag || s->nouts != 1) {
|
||||
continue;
|
||||
}
|
||||
a = s->outs;
|
||||
assert(a != NULL && a->outchain == NULL);
|
||||
if (a->type != EMPTY) {
|
||||
continue;
|
||||
}
|
||||
if (s != a->to) {
|
||||
moveins(nfa, s, a->to);
|
||||
}
|
||||
dropstate(nfa, s);
|
||||
}
|
||||
|
||||
do {
|
||||
progress = 0;
|
||||
for (s = nfa->states; s != NULL && !NISERR()
|
||||
&& s->no != FREESTATE; s = nexts) {
|
||||
nexts = s->next;
|
||||
for (a = s->outs; a != NULL && !NISERR(); a = nexta) {
|
||||
nexta = a->outchain;
|
||||
if (a->type == EMPTY && unempty(nfa, a)) {
|
||||
progress = 1;
|
||||
}
|
||||
assert(nexta == NULL || s->no != FREESTATE);
|
||||
/*
|
||||
* Similarly, get rid of any state with a single EMPTY in-arc, by
|
||||
* folding it into its predecessor.
|
||||
*/
|
||||
for (s = nfa->states; s != NULL && !NISERR(); s = nexts) {
|
||||
nexts = s->next;
|
||||
/* Ensure tmp fields are clear for next step */
|
||||
assert(s->tmp = NULL);
|
||||
if (s->flag || s->nins != 1) {
|
||||
continue;
|
||||
}
|
||||
a = s->ins;
|
||||
assert(a != NULL && a->inchain == NULL);
|
||||
if (a->type != EMPTY) {
|
||||
continue;
|
||||
}
|
||||
if (s != a->from) {
|
||||
moveouts(nfa, s, a->from);
|
||||
}
|
||||
dropstate(nfa, s);
|
||||
}
|
||||
|
||||
/*
|
||||
* For each remaining NFA state, find all other states that are
|
||||
* reachable from it by a chain of one or more EMPTY arcs. Then
|
||||
* generate new arcs that eliminate the need for each such chain.
|
||||
*
|
||||
* If we just do this straightforwardly, the algorithm gets slow in
|
||||
* complex graphs, because the same arcs get copied to all
|
||||
* intermediate states of an EMPTY chain, and then uselessly pushed
|
||||
* repeatedly to the chain's final state; we waste a lot of time in
|
||||
* newarc's duplicate checking. To improve matters, we decree that
|
||||
* any state with only EMPTY out-arcs is "doomed" and will not be
|
||||
* part of the final NFA. That can be ensured by not adding any new
|
||||
* out-arcs to such a state. Having ensured that, we need not update
|
||||
* the state's in-arcs list either; all arcs that might have gotten
|
||||
* pushed forward to it will just get pushed directly to successor
|
||||
* states. This eliminates most of the useless duplicate arcs.
|
||||
*/
|
||||
for (s = nfa->states; s != NULL && !NISERR(); s = s->next) {
|
||||
for (s2 = emptyreachable(s, s); s2 != s && !NISERR();
|
||||
s2 = nexts) {
|
||||
/*
|
||||
* If s2 is doomed, we decide that (1) we will always push
|
||||
* arcs forward to it, not pull them back to s; and (2) we
|
||||
* can optimize away the push-forward, per comment above.
|
||||
* So do nothing.
|
||||
*/
|
||||
if (s2->flag || hasnonemptyout(s2)) {
|
||||
replaceempty(nfa, s, s2);
|
||||
}
|
||||
|
||||
/* Reset the tmp fields as we walk back */
|
||||
nexts = s2->tmp;
|
||||
s2->tmp = NULL;
|
||||
}
|
||||
s->tmp = NULL;
|
||||
}
|
||||
if (NISERR()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all the EMPTY arcs, since we don't need them anymore.
|
||||
*/
|
||||
for (s = nfa->states; s != NULL; s = s->next) {
|
||||
for (a = s->outs; a != NULL; a = nexta) {
|
||||
nexta = a->outchain;
|
||||
if (a->type == EMPTY) {
|
||||
freearc(nfa, a);
|
||||
}
|
||||
}
|
||||
if (progress && f != NULL) {
|
||||
dumpnfa(nfa, f);
|
||||
}
|
||||
|
||||
/*
|
||||
* And remove any states that have become useless. (This cleanup is
|
||||
* not very thorough, and would be even less so if we tried to
|
||||
* combine it with the previous step; but cleanup() will take care
|
||||
* of anything we miss.)
|
||||
*/
|
||||
for (s = nfa->states; s != NULL; s = nexts) {
|
||||
nexts = s->next;
|
||||
if ((s->nins == 0 || s->nouts == 0) && !s->flag) {
|
||||
dropstate(nfa, s);
|
||||
}
|
||||
} while (progress && !NISERR());
|
||||
}
|
||||
|
||||
if (f != NULL) {
|
||||
dumpnfa(nfa, f);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- unempty - optimize out an EMPTY arc, if possible
|
||||
* Actually, as it stands this function always succeeds, but the return value
|
||||
* is kept with an eye on possible future changes.
|
||||
^ static int unempty(struct nfa *, struct arc *);
|
||||
- emptyreachable - recursively find all states reachable from s by EMPTY arcs
|
||||
* The return value is the last such state found. Its tmp field links back
|
||||
* to the next-to-last such state, and so on back to s, so that all these
|
||||
* states can be located without searching the whole NFA.
|
||||
* The maximum recursion depth here is equal to the length of the longest
|
||||
* loop-free chain of EMPTY arcs, which is surely no more than the size of
|
||||
* the NFA, and in practice will be a lot less than that.
|
||||
^ static struct state *emptyreachable(struct state *, struct state *);
|
||||
*/
|
||||
static int /* 0 couldn't, 1 could */
|
||||
unempty(
|
||||
struct nfa *nfa,
|
||||
struct arc *a)
|
||||
static struct state *
|
||||
emptyreachable(
|
||||
struct state *s,
|
||||
struct state *lastfound)
|
||||
{
|
||||
struct state *from = a->from;
|
||||
struct state *to = a->to;
|
||||
int usefrom; /* work on from, as opposed to to? */
|
||||
struct arc *a;
|
||||
|
||||
assert(a->type == EMPTY);
|
||||
assert(from != nfa->pre && to != nfa->post);
|
||||
s->tmp = lastfound;
|
||||
lastfound = s;
|
||||
for (a = s->outs; a != NULL; a = a->outchain) {
|
||||
if (a->type == EMPTY && a->to->tmp == NULL) {
|
||||
lastfound = emptyreachable(a->to, lastfound);
|
||||
}
|
||||
}
|
||||
return lastfound;
|
||||
}
|
||||
|
||||
/*
|
||||
- replaceempty - replace an EMPTY arc chain with some non-empty arcs
|
||||
* The EMPTY arc(s) should be deleted later, but we can't do it here because
|
||||
* they may still be needed to identify other arc chains during fixempties().
|
||||
^ static void replaceempty(struct nfa *, struct state *, struct state *);
|
||||
*/
|
||||
static void
|
||||
replaceempty(
|
||||
struct nfa *nfa,
|
||||
struct state *from,
|
||||
struct state *to)
|
||||
{
|
||||
int fromouts;
|
||||
int toins;
|
||||
|
||||
if (from == to) { /* vacuous loop */
|
||||
freearc(nfa, a);
|
||||
return 1;
|
||||
assert(from != to);
|
||||
|
||||
/*
|
||||
* Create replacement arcs that bypass the need for the EMPTY chain. We
|
||||
* can do this either by pushing arcs forward (linking directly from
|
||||
* "from"'s predecessors to "to") or by pulling them back (linking
|
||||
* directly from "from" to "to"'s successors). In general, we choose
|
||||
* whichever way creates greater fan-out or fan-in, so as to improve the
|
||||
* odds of reducing the other state to zero in-arcs or out-arcs and
|
||||
* thereby being able to delete it. However, if "from" is doomed (has no
|
||||
* non-EMPTY out-arcs), we must keep it so, so always push forward in that
|
||||
* case.
|
||||
*
|
||||
* The fan-out/fan-in comparison should count only non-EMPTY arcs. If
|
||||
* "from" is doomed, we can skip counting "to"'s arcs, since we want to
|
||||
* force taking the copynonemptyins path in that case.
|
||||
*/
|
||||
fromouts = nonemptyouts(from);
|
||||
toins = (fromouts == 0) ? 1 : nonemptyins(to);
|
||||
|
||||
if (fromouts > toins) {
|
||||
copyouts(nfa, to, from, 0);
|
||||
return;
|
||||
}
|
||||
if (fromouts < toins) {
|
||||
copyins(nfa, from, to, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide which end to work on.
|
||||
* fromouts == toins. Decide on secondary issue: copy fewest arcs.
|
||||
*
|
||||
* Doesn't seem to be worth the trouble to exclude empties from these
|
||||
* comparisons; that takes extra time and doesn't seem to improve the
|
||||
* resulting graph much.
|
||||
*/
|
||||
|
||||
usefrom = 1; /* default: attack from */
|
||||
if (from->nouts > to->nins) {
|
||||
usefrom = 0;
|
||||
} else if (from->nouts == to->nins) {
|
||||
/*
|
||||
* Decide on secondary issue: move/copy fewest arcs.
|
||||
*/
|
||||
|
||||
if (from->nins > to->nouts) {
|
||||
usefrom = 0;
|
||||
}
|
||||
if (from->nins > to->nouts) {
|
||||
copyouts(nfa, to, from, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
freearc(nfa, a);
|
||||
if (usefrom) {
|
||||
if (from->nouts == 0) {
|
||||
/*
|
||||
* Was the state's only outarc.
|
||||
*/
|
||||
|
||||
moveins(nfa, from, to);
|
||||
freestate(nfa, from);
|
||||
} else {
|
||||
copyins(nfa, from, to);
|
||||
}
|
||||
} else {
|
||||
if (to->nins == 0) {
|
||||
/*
|
||||
* Was the state's only inarc.
|
||||
*/
|
||||
|
||||
moveouts(nfa, to, from);
|
||||
freestate(nfa, to);
|
||||
} else {
|
||||
copyouts(nfa, to, from);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
copyins(nfa, from, to, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+10
-4
@@ -121,12 +121,15 @@ static void destroystate(struct nfa *, struct state *);
|
||||
static void newarc(struct nfa *, int, pcolor, struct state *, struct state *);
|
||||
static struct arc *allocarc(struct nfa *, struct state *);
|
||||
static void freearc(struct nfa *, struct arc *);
|
||||
static int hasnonemptyout(struct state *);
|
||||
static int nonemptyouts(struct state *);
|
||||
static int nonemptyins(struct state *);
|
||||
static struct arc *findarc(struct state *, int, pcolor);
|
||||
static void cparc(struct nfa *, struct arc *, struct state *, struct state *);
|
||||
static void moveins(struct nfa *, struct state *, struct state *);
|
||||
static void copyins(struct nfa *, struct state *, struct state *);
|
||||
static void copyins(struct nfa *, struct state *, struct state *, int);
|
||||
static void moveouts(struct nfa *, struct state *, struct state *);
|
||||
static void copyouts(struct nfa *, struct state *, struct state *);
|
||||
static void copyouts(struct nfa *, struct state *, struct state *, int);
|
||||
static void cloneouts(struct nfa *, struct state *, struct state *, struct state *, int);
|
||||
static void delsub(struct nfa *, struct state *, struct state *);
|
||||
static void deltraverse(struct nfa *, struct state *, struct state *);
|
||||
@@ -144,7 +147,8 @@ static int push(struct nfa *, struct arc *);
|
||||
#define COMPATIBLE 3 /* compatible but not satisfied yet */
|
||||
static int combine(struct arc *, struct arc *);
|
||||
static void fixempties(struct nfa *, FILE *);
|
||||
static int unempty(struct nfa *, struct arc *);
|
||||
static struct state *emptyreachable(struct state *, struct state *);
|
||||
static void replaceempty(struct nfa *, struct state *, struct state *);
|
||||
static void cleanup(struct nfa *);
|
||||
static void markreachable(struct nfa *, struct state *, struct state *, struct state *);
|
||||
static void markcanreach(struct nfa *, struct state *, struct state *, struct state *);
|
||||
@@ -607,7 +611,7 @@ makesearch(
|
||||
for (s=slist ; s!=NULL ; s=s2) {
|
||||
s2 = newstate(nfa);
|
||||
|
||||
copyouts(nfa, s, s2);
|
||||
copyouts(nfa, s, s2, 1);
|
||||
for (a=s->ins ; a!=NULL ; a=b) {
|
||||
b = a->inchain;
|
||||
|
||||
@@ -738,6 +742,7 @@ parsebranch(
|
||||
|
||||
/* NB, recursion in parseqatom() may swallow rest of branch */
|
||||
parseqatom(v, stopper, type, lp, right, t);
|
||||
NOERRN();
|
||||
}
|
||||
|
||||
if (!seencontent) { /* empty branch */
|
||||
@@ -1234,6 +1239,7 @@ parseqatom(
|
||||
EMPTYARC(atom->end, rp);
|
||||
t->right = subre(v, '=', 0, atom->end, rp);
|
||||
}
|
||||
NOERR();
|
||||
assert(SEE('|') || SEE(stopper) || SEE(EOS));
|
||||
t->flags |= COMBINE(t->flags, t->right->flags);
|
||||
top->flags |= COMBINE(top->flags, t->flags);
|
||||
|
||||
@@ -17,3 +17,4 @@
|
||||
{ REG_MIXED, "REG_MIXED", "character widths of regex and string differ" },
|
||||
{ REG_BADOPT, "REG_BADOPT", "invalid embedded option" },
|
||||
{ REG_ETOOBIG, "REG_ETOOBIG", "nfa has too many states" },
|
||||
{ REG_ECOLORS, "REG_ECOLORS", "too many colors" },
|
||||
|
||||
@@ -281,6 +281,7 @@ typedef struct {
|
||||
#define REG_MIXED 17 /* character widths of regex and string differ */
|
||||
#define REG_BADOPT 18 /* invalid embedded option */
|
||||
#define REG_ETOOBIG 19 /* nfa has too many states */
|
||||
#define REG_ECOLORS 20 /* too many colors */
|
||||
/* two specials for debugging and testing */
|
||||
#define REG_ATOI 101 /* convert error-code name to number */
|
||||
#define REG_ITOA 102 /* convert error-code number to name */
|
||||
|
||||
+2
-1
@@ -145,6 +145,7 @@
|
||||
|
||||
typedef short color; /* colors of characters */
|
||||
typedef int pcolor; /* what color promotes to */
|
||||
#define MAX_COLOR SHRT_MAX /* max color value */
|
||||
#define COLORLESS (-1) /* impossible color */
|
||||
#define WHITE 0 /* default color, parent of all others */
|
||||
|
||||
@@ -366,7 +367,7 @@ struct subre {
|
||||
*/
|
||||
|
||||
struct fns {
|
||||
VOID FUNCPTR(free, (regex_t *));
|
||||
void FUNCPTR(free, (regex_t *));
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+21
-26
@@ -55,11 +55,11 @@ extern "C" {
|
||||
|
||||
#define TCL_MAJOR_VERSION 8
|
||||
#define TCL_MINOR_VERSION 6
|
||||
#define TCL_RELEASE_LEVEL TCL_BETA_RELEASE
|
||||
#define TCL_RELEASE_SERIAL 3
|
||||
#define TCL_RELEASE_LEVEL TCL_FINAL_RELEASE
|
||||
#define TCL_RELEASE_SERIAL 0
|
||||
|
||||
#define TCL_VERSION "8.6"
|
||||
#define TCL_PATCH_LEVEL "8.6b3"
|
||||
#define TCL_PATCH_LEVEL "8.6.0"
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -472,7 +472,7 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
struct {long tv_sec;} st_ctim;
|
||||
/* Here is a 4-byte gap */
|
||||
} Tcl_StatBuf;
|
||||
#elif defined(HAVE_STRUCT_STAT64)
|
||||
#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
|
||||
typedef struct stat64 Tcl_StatBuf;
|
||||
#else
|
||||
typedef struct stat Tcl_StatBuf;
|
||||
@@ -504,11 +504,11 @@ typedef struct Tcl_Interp
|
||||
/* TIP #330: Strongly discourage extensions from using the string
|
||||
* result. */
|
||||
#ifdef USE_INTERP_RESULT
|
||||
char *result TCL_DEPRECATED_API("use Tcl_GetResult/Tcl_SetResult");
|
||||
char *result TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult");
|
||||
/* If the last command returned a string
|
||||
* result, this points to it. */
|
||||
void (*freeProc) (char *blockPtr)
|
||||
TCL_DEPRECATED_API("use Tcl_GetResult/Tcl_SetResult");
|
||||
TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult");
|
||||
/* Zero means the string result is statically
|
||||
* allocated. TCL_DYNAMIC means it was
|
||||
* allocated with ckalloc and should be freed
|
||||
@@ -854,10 +854,7 @@ typedef struct Tcl_Obj {
|
||||
* whether an object is shared (i.e. has reference count > 1). Note: clients
|
||||
* should use Tcl_DecrRefCount() when they are finished using an object, and
|
||||
* should never call TclFreeObj() directly. TclFreeObj() is only defined and
|
||||
* made public in tcl.h to support Tcl_DecrRefCount's macro definition. Note
|
||||
* also that Tcl_DecrRefCount() refers to the parameter "obj" twice. This
|
||||
* means that you should avoid calling it with an expression that is expensive
|
||||
* to compute or has side effects.
|
||||
* made public in tcl.h to support Tcl_DecrRefCount's macro definition.
|
||||
*/
|
||||
|
||||
void Tcl_IncrRefCount(Tcl_Obj *objPtr);
|
||||
@@ -2452,15 +2449,15 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
# define ckalloc(x) \
|
||||
((VOID *) Tcl_DbCkalloc((unsigned)(x), __FILE__, __LINE__))
|
||||
((void *) Tcl_DbCkalloc((unsigned)(x), __FILE__, __LINE__))
|
||||
# define ckfree(x) \
|
||||
Tcl_DbCkfree((char *)(x), __FILE__, __LINE__)
|
||||
# define ckrealloc(x,y) \
|
||||
((VOID *) Tcl_DbCkrealloc((char *)(x), (unsigned)(y), __FILE__, __LINE__))
|
||||
((void *) Tcl_DbCkrealloc((char *)(x), (unsigned)(y), __FILE__, __LINE__))
|
||||
# define attemptckalloc(x) \
|
||||
((VOID *) Tcl_AttemptDbCkalloc((unsigned)(x), __FILE__, __LINE__))
|
||||
((void *) Tcl_AttemptDbCkalloc((unsigned)(x), __FILE__, __LINE__))
|
||||
# define attemptckrealloc(x,y) \
|
||||
((VOID *) Tcl_AttemptDbCkrealloc((char *)(x), (unsigned)(y), __FILE__, __LINE__))
|
||||
((void *) Tcl_AttemptDbCkrealloc((char *)(x), (unsigned)(y), __FILE__, __LINE__))
|
||||
|
||||
#else /* !TCL_MEM_DEBUG */
|
||||
|
||||
@@ -2471,15 +2468,15 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
*/
|
||||
|
||||
# define ckalloc(x) \
|
||||
((VOID *) Tcl_Alloc((unsigned)(x)))
|
||||
((void *) Tcl_Alloc((unsigned)(x)))
|
||||
# define ckfree(x) \
|
||||
Tcl_Free((char *)(x))
|
||||
# define ckrealloc(x,y) \
|
||||
((VOID *) Tcl_Realloc((char *)(x), (unsigned)(y)))
|
||||
((void *) Tcl_Realloc((char *)(x), (unsigned)(y)))
|
||||
# define attemptckalloc(x) \
|
||||
((VOID *) Tcl_AttemptAlloc((unsigned)(x)))
|
||||
((void *) Tcl_AttemptAlloc((unsigned)(x)))
|
||||
# define attemptckrealloc(x,y) \
|
||||
((VOID *) Tcl_AttemptRealloc((char *)(x), (unsigned)(y)))
|
||||
((void *) Tcl_AttemptRealloc((char *)(x), (unsigned)(y)))
|
||||
# undef Tcl_InitMemory
|
||||
# define Tcl_InitMemory(x)
|
||||
# undef Tcl_DumpActiveMemory
|
||||
@@ -2504,7 +2501,12 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
* http://c2.com/cgi/wiki?TrivialDoWhileLoop
|
||||
*/
|
||||
# define Tcl_DecrRefCount(objPtr) \
|
||||
do { if (--(objPtr)->refCount <= 0) TclFreeObj(objPtr); } while(0)
|
||||
do { \
|
||||
Tcl_Obj *_objPtr = (objPtr); \
|
||||
if (--(_objPtr)->refCount <= 0) { \
|
||||
TclFreeObj(_objPtr); \
|
||||
} \
|
||||
} while(0)
|
||||
# define Tcl_IsShared(objPtr) \
|
||||
((objPtr)->refCount > 1)
|
||||
#endif
|
||||
@@ -2600,13 +2602,6 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# undef Tcl_EvalObj
|
||||
# define Tcl_EvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),0)
|
||||
# undef Tcl_GlobalEvalObj
|
||||
# define Tcl_GlobalEvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL)
|
||||
|
||||
/*
|
||||
* These function have been renamed. The old names are deprecated, but we
|
||||
* define these macros for backwards compatibilty.
|
||||
|
||||
+7
-53
@@ -798,12 +798,10 @@ TclNRAssembleObjCmd(
|
||||
|
||||
if (codePtr == NULL) {
|
||||
Tcl_AddErrorInfo(interp, "\n (\"");
|
||||
Tcl_AddErrorInfo(interp, Tcl_GetString(objv[0]));
|
||||
Tcl_AppendObjToErrorInfo(interp, objv[0]);
|
||||
Tcl_AddErrorInfo(interp, "\" body, line ");
|
||||
backtrace = Tcl_NewIntObj(Tcl_GetErrorLine(interp));
|
||||
Tcl_IncrRefCount(backtrace);
|
||||
Tcl_AddErrorInfo(interp, Tcl_GetString(backtrace));
|
||||
Tcl_DecrRefCount(backtrace);
|
||||
Tcl_AppendObjToErrorInfo(interp, backtrace);
|
||||
Tcl_AddErrorInfo(interp, ")");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -841,16 +839,11 @@ CompileAssembleObj(
|
||||
CompileEnv compEnv; /* Compilation environment structure */
|
||||
register ByteCode *codePtr = NULL;
|
||||
/* Bytecode resulting from the assembly */
|
||||
register const AuxData * auxDataPtr;
|
||||
/* Pointer to an auxiliary data element
|
||||
* in a compilation environment being
|
||||
* destroyed. */
|
||||
Namespace* namespacePtr; /* Namespace in which variable and command
|
||||
* names in the bytecode resolve */
|
||||
int status; /* Status return from Tcl_AssembleCode */
|
||||
const char* source; /* String representation of the source code */
|
||||
int sourceLen; /* Length of the source code in bytes */
|
||||
int i;
|
||||
|
||||
|
||||
/*
|
||||
@@ -860,7 +853,7 @@ CompileAssembleObj(
|
||||
|
||||
if (objPtr->typePtr == &assembleCodeType) {
|
||||
namespacePtr = iPtr->varFramePtr->nsPtr;
|
||||
codePtr = objPtr->internalRep.otherValuePtr;
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (((Interp *) *codePtr->interpHandle == iPtr)
|
||||
&& (codePtr->compileEpoch == iPtr->compileEpoch)
|
||||
&& (codePtr->nsPtr == namespacePtr)
|
||||
@@ -888,44 +881,6 @@ CompileAssembleObj(
|
||||
/*
|
||||
* Assembly failed. Clean up and report the error.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Free any literals that were constructed for the assembly.
|
||||
*/
|
||||
for (i = 0; i < compEnv.literalArrayNext; i++) {
|
||||
TclReleaseLiteral(interp, compEnv.literalArrayPtr[i].objPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free any auxiliary data that was attached to the bytecode
|
||||
* under construction.
|
||||
*/
|
||||
|
||||
for (i = 0; i < compEnv.auxDataArrayNext; i++) {
|
||||
auxDataPtr = compEnv.auxDataArrayPtr + i;
|
||||
if (auxDataPtr->type->freeProc != NULL) {
|
||||
(auxDataPtr->type->freeProc)(auxDataPtr->clientData);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TIP 280. If there is extended command line information,
|
||||
* we need to clean it up.
|
||||
*/
|
||||
|
||||
if (compEnv.extCmdMapPtr != NULL) {
|
||||
if (compEnv.extCmdMapPtr->type == TCL_LOCATION_SOURCE) {
|
||||
Tcl_DecrRefCount(compEnv.extCmdMapPtr->path);
|
||||
}
|
||||
for (i = 0; i < compEnv.extCmdMapPtr->nuloc; ++i) {
|
||||
ckfree(compEnv.extCmdMapPtr->loc[i].line);
|
||||
}
|
||||
if (compEnv.extCmdMapPtr->loc != NULL) {
|
||||
ckfree(compEnv.extCmdMapPtr->loc);
|
||||
}
|
||||
Tcl_DeleteHashTable(&(compEnv.extCmdMapPtr->litInfo));
|
||||
}
|
||||
|
||||
TclFreeCompileEnv(&compEnv);
|
||||
return NULL;
|
||||
}
|
||||
@@ -945,7 +900,7 @@ CompileAssembleObj(
|
||||
* Record the local variable context to which the bytecode pertains
|
||||
*/
|
||||
|
||||
codePtr = objPtr->internalRep.otherValuePtr;
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (iPtr->varFramePtr->localCachePtr) {
|
||||
codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
|
||||
codePtr->localCachePtr->refCount++;
|
||||
@@ -4270,11 +4225,11 @@ AddBasicBlockRangeToErrorInfo(
|
||||
Tcl_AddErrorInfo(interp, "\n in assembly code between lines ");
|
||||
lineNo = Tcl_NewIntObj(bbPtr->startLine);
|
||||
Tcl_IncrRefCount(lineNo);
|
||||
Tcl_AddErrorInfo(interp, Tcl_GetString(lineNo));
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
Tcl_AddErrorInfo(interp, " and ");
|
||||
if (bbPtr->successor1 != NULL) {
|
||||
Tcl_SetIntObj(lineNo, bbPtr->successor1->startLine);
|
||||
Tcl_AddErrorInfo(interp, Tcl_GetString(lineNo));
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
} else {
|
||||
Tcl_AddErrorInfo(interp, "end of assembly code");
|
||||
}
|
||||
@@ -4338,14 +4293,13 @@ static void
|
||||
FreeAssembleCodeInternalRep(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
ByteCode *codePtr = objPtr->internalRep.otherValuePtr;
|
||||
ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
codePtr->refCount--;
|
||||
if (codePtr->refCount <= 0) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
}
|
||||
objPtr->typePtr = NULL;
|
||||
objPtr->internalRep.otherValuePtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+85
-83
@@ -160,10 +160,7 @@ static Tcl_NRPostProc TEOV_Exception;
|
||||
static Tcl_NRPostProc TEOV_NotFoundCallback;
|
||||
static Tcl_NRPostProc TEOV_RestoreVarFrame;
|
||||
static Tcl_NRPostProc TEOV_RunLeaveTraces;
|
||||
static Tcl_NRPostProc YieldToCallback;
|
||||
|
||||
static void ClearTailcall(Tcl_Interp *interp,
|
||||
struct NRE_callback *tailcallPtr);
|
||||
static Tcl_ObjCmdProc NRCoroInjectObjCmd;
|
||||
|
||||
MODULE_SCOPE const TclStubs tclStubs;
|
||||
@@ -4161,7 +4158,8 @@ TclNREvalObjv(
|
||||
int result;
|
||||
Namespace *lookupNsPtr = iPtr->lookupNsPtr;
|
||||
Command **cmdPtrPtr;
|
||||
|
||||
NRE_callback *callbackPtr;
|
||||
|
||||
iPtr->lookupNsPtr = NULL;
|
||||
|
||||
/*
|
||||
@@ -4174,15 +4172,14 @@ TclNREvalObjv(
|
||||
* finishes the source command and not just the target.
|
||||
*/
|
||||
|
||||
if (iPtr->evalFlags & TCL_EVAL_REDIRECT) {
|
||||
TclNRAddCallback(interp, NRCommand, NULL, INT2PTR(1), INT2PTR(objc), objv);
|
||||
iPtr->evalFlags &= ~TCL_EVAL_REDIRECT;
|
||||
if (iPtr->deferredCallbacks) {
|
||||
callbackPtr = iPtr->deferredCallbacks;
|
||||
iPtr->deferredCallbacks = NULL;
|
||||
} else {
|
||||
TclNRAddCallback(interp, NRCommand, NULL, NULL, INT2PTR(objc), objv);
|
||||
TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
|
||||
callbackPtr = TOP_CB(interp);
|
||||
}
|
||||
cmdPtrPtr = (Command **) &(TOP_CB(interp)->data[0]);
|
||||
|
||||
TclNRSpliceDeferred(interp);
|
||||
cmdPtrPtr = (Command **) &(callbackPtr->data[0]);
|
||||
|
||||
iPtr->numLevels++;
|
||||
result = TclInterpReady(interp);
|
||||
@@ -4309,14 +4306,6 @@ TclNREvalObjv(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TclPushTailcallPoint(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
|
||||
((Interp *) interp)->numLevels++;
|
||||
}
|
||||
|
||||
int
|
||||
TclNRRunCallbacks(
|
||||
Tcl_Interp *interp,
|
||||
@@ -4368,6 +4357,14 @@ NRCommand(
|
||||
}
|
||||
((Interp *)interp)->numLevels--;
|
||||
|
||||
/*
|
||||
* If there is a tailcall, schedule it
|
||||
*/
|
||||
|
||||
if (data[1] && (data[1] != INT2PTR(1))) {
|
||||
TclNRAddCallback(interp, TclNRTailcallEval, data[1], NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* OPT ??
|
||||
* Do not interrupt a series of cleanups with async or limit checks:
|
||||
* just check at the end?
|
||||
@@ -4625,9 +4622,9 @@ TEOV_NotFound(
|
||||
savedNsPtr = varFramePtr->nsPtr;
|
||||
varFramePtr->nsPtr = lookupNsPtr;
|
||||
}
|
||||
TclNRDeferCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc),
|
||||
TclSkipTailcall(interp);
|
||||
TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc),
|
||||
newObjv, savedNsPtr, NULL);
|
||||
iPtr->evalFlags |= TCL_EVAL_REDIRECT;
|
||||
return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL);
|
||||
}
|
||||
|
||||
@@ -5814,6 +5811,7 @@ TclArgumentGet(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_Eval
|
||||
int
|
||||
Tcl_Eval(
|
||||
Tcl_Interp *interp, /* Token for command interpreter (returned by
|
||||
@@ -6012,7 +6010,8 @@ TclNREvalObjEx(
|
||||
iPtr->cmdFramePtr = eoFramePtr;
|
||||
}
|
||||
|
||||
TclNRDeferCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr,
|
||||
TclMarkTailcall(interp);
|
||||
TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr,
|
||||
NULL, NULL);
|
||||
|
||||
ListObjGetElements(listPtr, objc, objv);
|
||||
@@ -6745,6 +6744,7 @@ Tcl_ExprString(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_AddObjErrorInfo
|
||||
void
|
||||
Tcl_AppendObjToErrorInfo(
|
||||
Tcl_Interp *interp, /* Interpreter to which error information
|
||||
@@ -6778,6 +6778,7 @@ Tcl_AppendObjToErrorInfo(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_AddErrorInfo
|
||||
void
|
||||
Tcl_AddErrorInfo(
|
||||
Tcl_Interp *interp, /* Interpreter to which error information
|
||||
@@ -6958,6 +6959,7 @@ Tcl_VarEval(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_GlobalEval
|
||||
int
|
||||
Tcl_GlobalEval(
|
||||
Tcl_Interp *interp, /* Interpreter in which to evaluate
|
||||
@@ -8269,29 +8271,58 @@ Tcl_NRCmdSwap(
|
||||
*/
|
||||
|
||||
void
|
||||
TclSpliceTailcall(
|
||||
TclMarkTailcall(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
if (iPtr->deferredCallbacks == NULL) {
|
||||
TclNRAddCallback(interp, NRCommand, NULL, NULL,
|
||||
NULL, NULL);
|
||||
iPtr->deferredCallbacks = TOP_CB(interp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TclSkipTailcall(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
TclMarkTailcall(interp);
|
||||
iPtr->deferredCallbacks->data[1] = INT2PTR(1);
|
||||
}
|
||||
|
||||
void
|
||||
TclPushTailcallPoint(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
|
||||
((Interp *) interp)->numLevels++;
|
||||
}
|
||||
|
||||
void
|
||||
TclSetTailcall(
|
||||
Tcl_Interp *interp,
|
||||
NRE_callback *tailcallPtr)
|
||||
Tcl_Obj *listPtr)
|
||||
{
|
||||
/*
|
||||
* Find the splicing spot: right before the NRCommand of the thing
|
||||
* being tailcalled. Note that we skip NRCommands marked in data[1]
|
||||
* being tailcalled. Note that we skip NRCommands marked by a 1 in data[1]
|
||||
* (used by command redirectors).
|
||||
*/
|
||||
|
||||
NRE_callback *runPtr;
|
||||
|
||||
for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) {
|
||||
if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) {
|
||||
if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!runPtr) {
|
||||
Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!");
|
||||
}
|
||||
|
||||
tailcallPtr->nextPtr = runPtr->nextPtr;
|
||||
runPtr->nextPtr = tailcallPtr;
|
||||
runPtr->data[1] = listPtr;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -8321,7 +8352,7 @@ TclNRTailcallObjCmd(
|
||||
*/
|
||||
|
||||
if (iPtr->varFramePtr->tailcallPtr) {
|
||||
ClearTailcall(interp, iPtr->varFramePtr->tailcallPtr);
|
||||
Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr);
|
||||
iPtr->varFramePtr->tailcallPtr = NULL;
|
||||
}
|
||||
|
||||
@@ -8336,23 +8367,20 @@ TclNRTailcallObjCmd(
|
||||
Tcl_Obj *listPtr, *nsObjPtr;
|
||||
Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
|
||||
Tcl_Namespace *ns1Ptr;
|
||||
NRE_callback *tailcallPtr;
|
||||
|
||||
listPtr = Tcl_NewListObj(objc-1, objv+1);
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
/* The tailcall data is in a Tcl list: the first element is the
|
||||
* namespace, the rest the command to be tailcalled. */
|
||||
|
||||
listPtr = Tcl_NewListObj(objc, objv);
|
||||
|
||||
nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
|
||||
if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr))
|
||||
|| (nsPtr != ns1Ptr)) {
|
||||
Tcl_Panic("Tailcall failed to find the proper namespace");
|
||||
}
|
||||
Tcl_IncrRefCount(nsObjPtr);
|
||||
|
||||
TclNRAddCallback(interp, TclNRTailcallEval, listPtr, nsObjPtr,
|
||||
NULL, NULL);
|
||||
tailcallPtr = TOP_CB(interp);
|
||||
TOP_CB(interp) = tailcallPtr->nextPtr;
|
||||
iPtr->varFramePtr->tailcallPtr = tailcallPtr;
|
||||
TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
|
||||
|
||||
iPtr->varFramePtr->tailcallPtr = listPtr;
|
||||
}
|
||||
return TCL_RETURN;
|
||||
}
|
||||
@@ -8364,12 +8392,14 @@ TclNRTailcallEval(
|
||||
int result)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_Obj *listPtr = data[0];
|
||||
Tcl_Obj *nsObjPtr = data[1];
|
||||
Tcl_Obj *listPtr = data[0], *nsObjPtr;
|
||||
Tcl_Namespace *nsPtr;
|
||||
int objc;
|
||||
Tcl_Obj **objv;
|
||||
|
||||
Tcl_ListObjGetElements(interp, listPtr, &objc, &objv);
|
||||
nsObjPtr = objv[0];
|
||||
|
||||
if (result == TCL_OK) {
|
||||
result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
|
||||
}
|
||||
@@ -8388,10 +8418,10 @@ TclNRTailcallEval(
|
||||
* Perform the tailcall
|
||||
*/
|
||||
|
||||
TclNRDeferCallback(interp, TailcallCleanup, listPtr, nsObjPtr, NULL,NULL);
|
||||
TclMarkTailcall(interp);
|
||||
TclNRAddCallback(interp, TailcallCleanup, listPtr, NULL, NULL,NULL);
|
||||
iPtr->lookupNsPtr = (Namespace *) nsPtr;
|
||||
ListObjGetElements(listPtr, objc, objv);
|
||||
return TclNREvalObjv(interp, objc, objv, 0, NULL);
|
||||
return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -8401,19 +8431,9 @@ TailcallCleanup(
|
||||
int result)
|
||||
{
|
||||
Tcl_DecrRefCount((Tcl_Obj *) data[0]);
|
||||
Tcl_DecrRefCount((Tcl_Obj *) data[1]);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
ClearTailcall(
|
||||
Tcl_Interp *interp,
|
||||
NRE_callback *tailcallPtr)
|
||||
{
|
||||
TailcallCleanup(tailcallPtr->data, interp, TCL_OK);
|
||||
TCLNR_FREE(interp, tailcallPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Tcl_NRAddCallback(
|
||||
@@ -8515,50 +8535,32 @@ TclNRYieldToObjCmd(
|
||||
* This is essentially code from TclNRTailcallObjCmd
|
||||
*/
|
||||
|
||||
listPtr = Tcl_NewListObj(objc-1, objv+1);
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
/*
|
||||
* Add the tailcall in the caller env, then just yield.
|
||||
*
|
||||
* This is essentially code from TclNRTailcallObjCmd
|
||||
*/
|
||||
|
||||
listPtr = Tcl_NewListObj(objc, objv);
|
||||
|
||||
nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
|
||||
if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr))
|
||||
|| (nsPtr != ns1Ptr)) {
|
||||
Tcl_Panic("yieldto failed to find the proper namespace");
|
||||
}
|
||||
Tcl_IncrRefCount(nsObjPtr);
|
||||
TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
|
||||
|
||||
|
||||
/*
|
||||
* Add the callback in the caller's env, then instruct TEBC to yield.
|
||||
*/
|
||||
|
||||
iPtr->execEnvPtr = corPtr->callerEEPtr;
|
||||
TclNRAddCallback(interp, YieldToCallback, corPtr, listPtr, nsObjPtr,
|
||||
NULL);
|
||||
TclSetTailcall(interp, listPtr);
|
||||
iPtr->execEnvPtr = corPtr->eePtr;
|
||||
|
||||
return TclNRYieldObjCmd(INT2PTR(CORO_ACTIVATE_YIELDM), interp, 1, objv);
|
||||
}
|
||||
|
||||
static int
|
||||
YieldToCallback(
|
||||
ClientData data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
/* CoroutineData *corPtr = data[0];*/
|
||||
Tcl_Obj *listPtr = data[1];
|
||||
ClientData nsPtr = data[2];
|
||||
NRE_callback *cbPtr;
|
||||
|
||||
/*
|
||||
* yieldTo: invoke the command using tailcall tech.
|
||||
*/
|
||||
|
||||
TclNRAddCallback(interp, TclNRTailcallEval, listPtr, nsPtr, NULL, NULL);
|
||||
cbPtr = TOP_CB(interp);
|
||||
TOP_CB(interp) = cbPtr->nextPtr;
|
||||
|
||||
TclSpliceTailcall(interp, cbPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
RewindCoroutineCallback(
|
||||
|
||||
+33
-28
@@ -127,6 +127,30 @@ static const char B64Digits[65] = {
|
||||
'='
|
||||
};
|
||||
|
||||
/*
|
||||
* How to construct the ensembles.
|
||||
*/
|
||||
|
||||
static const EnsembleImplMap binaryMap[] = {
|
||||
{ "format", BinaryFormatCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 },
|
||||
{ "scan", BinaryScanCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0 },
|
||||
{ "encode", NULL, NULL, NULL, NULL, 0 },
|
||||
{ "decode", NULL, NULL, NULL, NULL, 0 },
|
||||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
static const EnsembleImplMap encodeMap[] = {
|
||||
{ "hex", BinaryEncodeHex, TclCompileBasic1ArgCmd, NULL, (ClientData)HexDigits, 0 },
|
||||
{ "uuencode", BinaryEncode64, NULL, NULL, (ClientData)UueDigits, 0 },
|
||||
{ "base64", BinaryEncode64, NULL, NULL, (ClientData)B64Digits, 0 },
|
||||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
static const EnsembleImplMap decodeMap[] = {
|
||||
{ "hex", BinaryDecodeHex, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
|
||||
{ "uuencode", BinaryDecodeUu, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
|
||||
{ "base64", BinaryDecode64, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
|
||||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* The following object type represents an array of bytes. An array of bytes
|
||||
* is not equivalent to an internationalized string. Conceptually, a string is
|
||||
@@ -180,9 +204,10 @@ typedef struct ByteArray {
|
||||
#define BYTEARRAY_SIZE(len) \
|
||||
((unsigned) (TclOffset(ByteArray, bytes) + (len)))
|
||||
#define GET_BYTEARRAY(objPtr) \
|
||||
((ByteArray *) (objPtr)->internalRep.otherValuePtr)
|
||||
((ByteArray *) (objPtr)->internalRep.twoPtrValue.ptr1)
|
||||
#define SET_BYTEARRAY(objPtr, baPtr) \
|
||||
(objPtr)->internalRep.otherValuePtr = (void *) (baPtr)
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (baPtr)
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -301,7 +326,7 @@ Tcl_SetByteArrayObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj");
|
||||
}
|
||||
TclFreeIntRep(objPtr);
|
||||
Tcl_InvalidateStringRep(objPtr);
|
||||
TclInvalidateStringRep(objPtr);
|
||||
|
||||
if (length < 0) {
|
||||
length = 0;
|
||||
@@ -396,7 +421,7 @@ Tcl_SetByteArrayLength(
|
||||
byteArrayPtr->allocated = length;
|
||||
SET_BYTEARRAY(objPtr, byteArrayPtr);
|
||||
}
|
||||
Tcl_InvalidateStringRep(objPtr);
|
||||
TclInvalidateStringRep(objPtr);
|
||||
byteArrayPtr->used = length;
|
||||
return byteArrayPtr->bytes;
|
||||
}
|
||||
@@ -667,7 +692,7 @@ TclAppendBytesToByteArray(
|
||||
if (len > 0) {
|
||||
memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
|
||||
byteArrayPtr->used += len;
|
||||
Tcl_InvalidateStringRep(objPtr);
|
||||
TclInvalidateStringRep(objPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -688,26 +713,6 @@ TclAppendBytesToByteArray(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static const EnsembleImplMap binaryMap[] = {
|
||||
{ "format", BinaryFormatCmd, NULL, NULL, NULL, 0 },
|
||||
{ "scan", BinaryScanCmd, NULL, NULL, NULL, 0 },
|
||||
{ "encode", NULL, NULL, NULL, NULL, 0 },
|
||||
{ "decode", NULL, NULL, NULL, NULL, 0 },
|
||||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
static const EnsembleImplMap encodeMap[] = {
|
||||
{ "hex", BinaryEncodeHex, NULL, NULL, (ClientData)HexDigits, 0 },
|
||||
{ "uuencode", BinaryEncode64, NULL, NULL, (ClientData)UueDigits, 0 },
|
||||
{ "base64", BinaryEncode64, NULL, NULL, (ClientData)B64Digits, 0 },
|
||||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
static const EnsembleImplMap decodeMap[] = {
|
||||
{ "hex", BinaryDecodeHex, NULL, NULL, NULL, 0 },
|
||||
{ "uuencode", BinaryDecodeUu, NULL, NULL, NULL, 0 },
|
||||
{ "base64", BinaryDecode64, NULL, NULL, NULL, 0 },
|
||||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
Tcl_Command
|
||||
TclInitBinaryCmd(
|
||||
Tcl_Interp *interp)
|
||||
@@ -2357,7 +2362,7 @@ BinaryDecodeHex(
|
||||
static const char *const optStrings[] = { "-strict", NULL };
|
||||
|
||||
if (objc < 2 || objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "data");
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?options? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 1; i < objc-1; ++i) {
|
||||
@@ -2571,7 +2576,7 @@ BinaryDecodeUu(
|
||||
static const char *const optStrings[] = { "-strict", NULL };
|
||||
|
||||
if (objc < 2 || objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "data");
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?options? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 1; i < objc-1; ++i) {
|
||||
@@ -2667,7 +2672,7 @@ BinaryDecode64(
|
||||
static const char *const optStrings[] = { "-strict", NULL };
|
||||
|
||||
if (objc < 2 || objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "data");
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?options? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 1; i < objc-1; ++i) {
|
||||
|
||||
@@ -156,6 +156,10 @@ TclInitDbCkalloc(void)
|
||||
if (!ckallocInit) {
|
||||
ckallocInit = 1;
|
||||
ckallocMutexPtr = Tcl_GetAllocMutex();
|
||||
#ifndef TCL_THREADS
|
||||
/* Silence compiler warning */
|
||||
(void)ckallocMutexPtr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+36
-35
@@ -361,7 +361,8 @@ CatchObjCmdCallback(
|
||||
|
||||
if (NULL == Tcl_ObjSetVar2(interp, optionVarNamePtr, NULL,
|
||||
options, TCL_LEAVE_ERR_MSG)) {
|
||||
Tcl_DecrRefCount(options);
|
||||
/* Do not decrRefCount 'options', it was already done by
|
||||
* Tcl_ObjSetVar2 */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -949,40 +950,40 @@ TclInitFileCmd(
|
||||
*/
|
||||
|
||||
static const EnsembleImplMap initMap[] = {
|
||||
{"atime", FileAttrAccessTimeCmd, NULL, NULL, NULL, 0},
|
||||
{"attributes", TclFileAttrsCmd, NULL, NULL, NULL, 0},
|
||||
{"channels", TclChannelNamesCmd, NULL, NULL, NULL, 0},
|
||||
{"copy", TclFileCopyCmd, NULL, NULL, NULL, 0},
|
||||
{"delete", TclFileDeleteCmd, NULL, NULL, NULL, 0},
|
||||
{"dirname", PathDirNameCmd, NULL, NULL, NULL, 0},
|
||||
{"executable", FileAttrIsExecutableCmd, NULL, NULL, NULL, 0},
|
||||
{"exists", FileAttrIsExistingCmd, NULL, NULL, NULL, 0},
|
||||
{"extension", PathExtensionCmd, NULL, NULL, NULL, 0},
|
||||
{"isdirectory", FileAttrIsDirectoryCmd, NULL, NULL, NULL, 0},
|
||||
{"isfile", FileAttrIsFileCmd, NULL, NULL, NULL, 0},
|
||||
{"join", PathJoinCmd, NULL, NULL, NULL, 0},
|
||||
{"link", TclFileLinkCmd, NULL, NULL, NULL, 0},
|
||||
{"lstat", FileAttrLinkStatCmd, NULL, NULL, NULL, 0},
|
||||
{"mtime", FileAttrModifyTimeCmd, NULL, NULL, NULL, 0},
|
||||
{"mkdir", TclFileMakeDirsCmd, NULL, NULL, NULL, 0},
|
||||
{"nativename", PathNativeNameCmd, NULL, NULL, NULL, 0},
|
||||
{"normalize", PathNormalizeCmd, NULL, NULL, NULL, 0},
|
||||
{"owned", FileAttrIsOwnedCmd, NULL, NULL, NULL, 0},
|
||||
{"pathtype", PathTypeCmd, NULL, NULL, NULL, 0},
|
||||
{"readable", FileAttrIsReadableCmd, NULL, NULL, NULL, 0},
|
||||
{"readlink", TclFileReadLinkCmd, NULL, NULL, NULL, 0},
|
||||
{"rename", TclFileRenameCmd, NULL, NULL, NULL, 0},
|
||||
{"rootname", PathRootNameCmd, NULL, NULL, NULL, 0},
|
||||
{"separator", FilesystemSeparatorCmd, NULL, NULL, NULL, 0},
|
||||
{"size", FileAttrSizeCmd, NULL, NULL, NULL, 0},
|
||||
{"split", PathSplitCmd, NULL, NULL, NULL, 0},
|
||||
{"stat", FileAttrStatCmd, NULL, NULL, NULL, 0},
|
||||
{"system", PathFilesystemCmd, NULL, NULL, NULL, 0},
|
||||
{"tail", PathTailCmd, NULL, NULL, NULL, 0},
|
||||
{"tempfile", TclFileTemporaryCmd, NULL, NULL, NULL, 0},
|
||||
{"type", FileAttrTypeCmd, NULL, NULL, NULL, 0},
|
||||
{"volumes", FilesystemVolumesCmd, NULL, NULL, NULL, 0},
|
||||
{"writable", FileAttrIsWritableCmd, NULL, NULL, NULL, 0},
|
||||
{"atime", FileAttrAccessTimeCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"attributes", TclFileAttrsCmd, NULL, NULL, NULL, 0},
|
||||
{"channels", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"copy", TclFileCopyCmd, NULL, NULL, NULL, 0},
|
||||
{"delete", TclFileDeleteCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"dirname", PathDirNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"executable", FileAttrIsExecutableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"exists", FileAttrIsExistingCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"extension", PathExtensionCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"isdirectory", FileAttrIsDirectoryCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"isfile", FileAttrIsFileCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"join", PathJoinCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"link", TclFileLinkCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
|
||||
{"lstat", FileAttrLinkStatCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"mtime", FileAttrModifyTimeCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"mkdir", TclFileMakeDirsCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"nativename", PathNativeNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"normalize", PathNormalizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"owned", FileAttrIsOwnedCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"pathtype", PathTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"readable", FileAttrIsReadableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"readlink", TclFileReadLinkCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"rename", TclFileRenameCmd, NULL, NULL, NULL, 0},
|
||||
{"rootname", PathRootNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"separator", FilesystemSeparatorCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"size", FileAttrSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"split", PathSplitCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"stat", FileAttrStatCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"system", PathFilesystemCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"tail", PathTailCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"tempfile", TclFileTemporaryCmd, TclCompileBasic0To2ArgCmd, NULL, NULL, 0},
|
||||
{"type", FileAttrTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"volumes", FilesystemVolumesCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"writable", FileAttrIsWritableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
return TclMakeEnsemble(interp, "file", initMap);
|
||||
|
||||
+20
-20
@@ -161,30 +161,30 @@ static Tcl_Obj * SelectObjFromSublist(Tcl_Obj *firstPtr,
|
||||
*/
|
||||
|
||||
static const EnsembleImplMap defaultInfoMap[] = {
|
||||
{"args", InfoArgsCmd, NULL, NULL, NULL, 0},
|
||||
{"body", InfoBodyCmd, NULL, NULL, NULL, 0},
|
||||
{"cmdcount", InfoCmdCountCmd, NULL, NULL, NULL, 0},
|
||||
{"args", InfoArgsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"body", InfoBodyCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"cmdcount", InfoCmdCountCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"commands", InfoCommandsCmd, TclCompileInfoCommandsCmd, NULL, NULL, 0},
|
||||
{"complete", InfoCompleteCmd, NULL, NULL, NULL, 0},
|
||||
{"complete", InfoCompleteCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"coroutine", TclInfoCoroutineCmd, TclCompileInfoCoroutineCmd, NULL, NULL, 0},
|
||||
{"default", InfoDefaultCmd, NULL, NULL, NULL, 0},
|
||||
{"errorstack", InfoErrorStackCmd, NULL, NULL, NULL, 0},
|
||||
{"default", InfoDefaultCmd, TclCompileBasic3ArgCmd, NULL, NULL, 0},
|
||||
{"errorstack", InfoErrorStackCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd, NULL, NULL, 0},
|
||||
{"frame", InfoFrameCmd, NULL, NULL, NULL, 0},
|
||||
{"functions", InfoFunctionsCmd, NULL, NULL, NULL, 0},
|
||||
{"globals", TclInfoGlobalsCmd, NULL, NULL, NULL, 0},
|
||||
{"hostname", InfoHostnameCmd, NULL, NULL, NULL, 0},
|
||||
{"frame", InfoFrameCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"functions", InfoFunctionsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"globals", TclInfoGlobalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"hostname", InfoHostnameCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"level", InfoLevelCmd, TclCompileInfoLevelCmd, NULL, NULL, 0},
|
||||
{"library", InfoLibraryCmd, NULL, NULL, NULL, 0},
|
||||
{"loaded", InfoLoadedCmd, NULL, NULL, NULL, 0},
|
||||
{"locals", TclInfoLocalsCmd, NULL, NULL, NULL, 0},
|
||||
{"nameofexecutable", InfoNameOfExecutableCmd, NULL, NULL, NULL, 0},
|
||||
{"patchlevel", InfoPatchLevelCmd, NULL, NULL, NULL, 0},
|
||||
{"procs", InfoProcsCmd, NULL, NULL, NULL, 0},
|
||||
{"script", InfoScriptCmd, NULL, NULL, NULL, 0},
|
||||
{"sharedlibextension", InfoSharedlibCmd, NULL, NULL, NULL, 0},
|
||||
{"tclversion", InfoTclVersionCmd, NULL, NULL, NULL, 0},
|
||||
{"vars", TclInfoVarsCmd, NULL, NULL, NULL, 0},
|
||||
{"library", InfoLibraryCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"loaded", InfoLoadedCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"locals", TclInfoLocalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"nameofexecutable", InfoNameOfExecutableCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"patchlevel", InfoPatchLevelCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"procs", InfoProcsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"script", InfoScriptCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"sharedlibextension", InfoSharedlibCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"tclversion", InfoTclVersionCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"vars", TclInfoVarsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
+13
-12
@@ -1540,7 +1540,8 @@ StringIsCmd(
|
||||
case STR_IS_BOOL:
|
||||
case STR_IS_TRUE:
|
||||
case STR_IS_FALSE:
|
||||
if (TCL_OK != Tcl_ConvertToType(NULL, objPtr, &tclBooleanType)) {
|
||||
if ((objPtr->typePtr != &tclBooleanType)
|
||||
&& (TCL_OK != TclSetBooleanFromAny(NULL, objPtr))) {
|
||||
if (strict) {
|
||||
result = 0;
|
||||
} else {
|
||||
@@ -3324,7 +3325,7 @@ TclInitStringCmd(
|
||||
Tcl_Interp *interp) /* Current interpreter. */
|
||||
{
|
||||
static const EnsembleImplMap stringImplMap[] = {
|
||||
{"bytelength", StringBytesCmd, NULL, NULL, NULL, 0},
|
||||
{"bytelength", StringBytesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"compare", StringCmpCmd, TclCompileStringCmpCmd, NULL, NULL, 0},
|
||||
{"equal", StringEqualCmd, TclCompileStringEqualCmd, NULL, NULL, 0},
|
||||
{"first", StringFirstCmd, TclCompileStringFirstCmd, NULL, NULL, 0},
|
||||
@@ -3335,17 +3336,17 @@ TclInitStringCmd(
|
||||
{"map", StringMapCmd, TclCompileStringMapCmd, NULL, NULL, 0},
|
||||
{"match", StringMatchCmd, TclCompileStringMatchCmd, NULL, NULL, 0},
|
||||
{"range", StringRangeCmd, TclCompileStringRangeCmd, NULL, NULL, 0},
|
||||
{"repeat", StringReptCmd, NULL, NULL, NULL, 0},
|
||||
{"repeat", StringReptCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"replace", StringRplcCmd, NULL, NULL, NULL, 0},
|
||||
{"reverse", StringRevCmd, NULL, NULL, NULL, 0},
|
||||
{"tolower", StringLowerCmd, NULL, NULL, NULL, 0},
|
||||
{"toupper", StringUpperCmd, NULL, NULL, NULL, 0},
|
||||
{"totitle", StringTitleCmd, NULL, NULL, NULL, 0},
|
||||
{"trim", StringTrimCmd, NULL, NULL, NULL, 0},
|
||||
{"trimleft", StringTrimLCmd, NULL, NULL, NULL, 0},
|
||||
{"trimright", StringTrimRCmd, NULL, NULL, NULL, 0},
|
||||
{"wordend", StringEndCmd, NULL, NULL, NULL, 0},
|
||||
{"wordstart", StringStartCmd, NULL, NULL, NULL, 0},
|
||||
{"reverse", StringRevCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"tolower", StringLowerCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
|
||||
{"toupper", StringUpperCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
|
||||
{"totitle", StringTitleCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
|
||||
{"trim", StringTrimCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"trimleft", StringTrimLCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"trimright", StringTrimRCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"wordend", StringEndCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"wordstart", StringStartCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
+83
-54
@@ -107,6 +107,7 @@ static int CompileDictEachCmd(Tcl_Interp *interp,
|
||||
*/
|
||||
|
||||
#define TCL_NO_LARGE_INDEX 1 /* Do not return localIndex value > 255 */
|
||||
#define TCL_NO_ELEMENT 2 /* Do not push the array element. */
|
||||
|
||||
/*
|
||||
* The structures below define the AuxData types defined in this file.
|
||||
@@ -259,7 +260,7 @@ TclCompileArrayExistsCmd(
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
PushVarNameWord(interp, tokenPtr, envPtr, 0,
|
||||
PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT,
|
||||
&localIndex, &simpleVarName, &isScalar, 1);
|
||||
if (!isScalar) {
|
||||
return TCL_ERROR;
|
||||
@@ -283,7 +284,7 @@ TclCompileArraySetCmd(
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
Tcl_Token *tokenPtr;
|
||||
Tcl_Token *varTokenPtr, *dataTokenPtr;
|
||||
int simpleVarName, isScalar, localIndex;
|
||||
int dataVar, iterVar, keyVar, valVar, infoIndex;
|
||||
int back, fwd, offsetBack, offsetFwd, savedStackDepth;
|
||||
@@ -293,20 +294,21 @@ TclCompileArraySetCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
PushVarNameWord(interp, tokenPtr, envPtr, 0,
|
||||
varTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
PushVarNameWord(interp, varTokenPtr, envPtr, TCL_NO_ELEMENT,
|
||||
&localIndex, &simpleVarName, &isScalar, 1);
|
||||
dataTokenPtr = TokenAfter(varTokenPtr);
|
||||
if (!isScalar) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
|
||||
/*
|
||||
* Special case: literal empty value argument is just an "ensure array"
|
||||
* operation.
|
||||
*/
|
||||
|
||||
if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD && tokenPtr[1].size == 0) {
|
||||
if (dataTokenPtr->type == TCL_TOKEN_SIMPLE_WORD
|
||||
&& dataTokenPtr[1].size == 0) {
|
||||
if (localIndex >= 0) {
|
||||
TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr);
|
||||
TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr);
|
||||
@@ -329,14 +331,37 @@ TclCompileArraySetCmd(
|
||||
* Prepare for the internal foreach.
|
||||
*/
|
||||
|
||||
if (envPtr->procPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
dataVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
iterVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
keyVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
valVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
|
||||
if (dataVar < 0) {
|
||||
/*
|
||||
* Right number of arguments, but not compilable as we can't allocate
|
||||
* (unnamed) local variables to manage the internal iteration.
|
||||
*/
|
||||
|
||||
Tcl_Obj *objPtr = Tcl_NewObj();
|
||||
char *bytes;
|
||||
int length, cmdLit;
|
||||
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
cmdLit = TclRegisterNewCmdLiteral(envPtr, bytes, length);
|
||||
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);
|
||||
TclEmitPush(cmdLit, envPtr);
|
||||
TclDecrRefCount(objPtr);
|
||||
if (localIndex >= 0) {
|
||||
CompileWord(envPtr, varTokenPtr, interp, 1);
|
||||
} else {
|
||||
TclEmitInstInt4(INST_REVERSE, 2, envPtr);
|
||||
}
|
||||
CompileWord(envPtr, dataTokenPtr, interp, 2);
|
||||
TclEmitInstInt1(INST_INVOKE_STK1, 3, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
infoPtr = ckalloc(sizeof(ForeachInfo) + sizeof(ForeachVarList *));
|
||||
infoPtr->numLists = 1;
|
||||
infoPtr->firstValueTemp = dataVar;
|
||||
@@ -351,7 +376,7 @@ TclCompileArraySetCmd(
|
||||
* Start issuing instructions to write to the array.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, tokenPtr, interp, 2);
|
||||
CompileWord(envPtr, dataTokenPtr, interp, 2);
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
PushLiteral(envPtr, "1", 1);
|
||||
@@ -434,10 +459,10 @@ TclCompileArrayUnsetCmd(
|
||||
int simpleVarName, isScalar, localIndex, savedStackDepth;
|
||||
|
||||
if (parsePtr->numWords != 2) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
PushVarNameWord(interp, tokenPtr, envPtr, 0,
|
||||
PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT,
|
||||
&localIndex, &simpleVarName, &isScalar, 1);
|
||||
if (!isScalar) {
|
||||
return TCL_ERROR;
|
||||
@@ -928,7 +953,7 @@ TclCompileDictIncrCmd(
|
||||
|
||||
incrTokenPtr = TokenAfter(keyTokenPtr);
|
||||
if (incrTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr);
|
||||
}
|
||||
word = incrTokenPtr[1].start;
|
||||
numBytes = incrTokenPtr[1].size;
|
||||
@@ -938,7 +963,7 @@ TclCompileDictIncrCmd(
|
||||
code = TclGetIntFromObj(NULL, intObj, &incrAmount);
|
||||
TclDecrRefCount(intObj);
|
||||
if (code != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr);
|
||||
}
|
||||
} else {
|
||||
incrAmount = 1;
|
||||
@@ -951,16 +976,16 @@ TclCompileDictIncrCmd(
|
||||
*/
|
||||
|
||||
if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2Or3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
name = varTokenPtr[1].start;
|
||||
nameChars = varTokenPtr[1].size;
|
||||
if (!TclIsLocalScalar(name, nameChars)) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2Or3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr);
|
||||
if (dictVarIndex < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2Or3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1078,16 +1103,16 @@ TclCompileDictUnsetCmd(
|
||||
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
name = tokenPtr[1].start;
|
||||
nameChars = tokenPtr[1].size;
|
||||
if (!TclIsLocalScalar(name, nameChars)) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr);
|
||||
if (dictVarIndex < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1178,7 +1203,7 @@ TclCompileDictCreateCmd(
|
||||
nonConstant:
|
||||
worker = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
if (worker < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
PushLiteral(envPtr, "", 0);
|
||||
@@ -1239,7 +1264,7 @@ TclCompileDictMergeCmd(
|
||||
|
||||
workerIndex = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
if (workerIndex < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
infoIndex = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
|
||||
@@ -1365,11 +1390,11 @@ CompileDictEachCmd(
|
||||
Tcl_DString buffer;
|
||||
|
||||
/*
|
||||
* There must be at least three argument after the command.
|
||||
* There must be three arguments after the command.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 4) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
varsTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
@@ -1377,7 +1402,7 @@ CompileDictEachCmd(
|
||||
bodyTokenPtr = TokenAfter(dictTokenPtr);
|
||||
if (varsTokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
|
||||
bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1389,7 +1414,7 @@ CompileDictEachCmd(
|
||||
collectVar = TclFindCompiledLocal(NULL, /*nameChars*/ 0, /*create*/ 1,
|
||||
envPtr);
|
||||
if (collectVar < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1403,31 +1428,31 @@ CompileDictEachCmd(
|
||||
if (Tcl_SplitList(NULL, Tcl_DStringValue(&buffer), &numVars,
|
||||
&argv) != TCL_OK) {
|
||||
Tcl_DStringFree(&buffer);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
Tcl_DStringFree(&buffer);
|
||||
if (numVars != 2) {
|
||||
ckfree(argv);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
nameChars = strlen(argv[0]);
|
||||
if (!TclIsLocalScalar(argv[0], nameChars)) {
|
||||
ckfree(argv);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
keyVarIndex = TclFindCompiledLocal(argv[0], nameChars, 1, envPtr);
|
||||
|
||||
nameChars = strlen(argv[1]);
|
||||
if (!TclIsLocalScalar(argv[1], nameChars)) {
|
||||
ckfree(argv);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
valueVarIndex = TclFindCompiledLocal(argv[1], nameChars, 1, envPtr);
|
||||
ckfree(argv);
|
||||
|
||||
if ((keyVarIndex < 0) || (valueVarIndex < 0)) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1439,7 +1464,7 @@ CompileDictEachCmd(
|
||||
|
||||
infoIndex = TclFindCompiledLocal(NULL, 0, 1, envPtr);
|
||||
if (infoIndex < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1636,16 +1661,16 @@ TclCompileDictUpdateCmd(
|
||||
|
||||
dictVarTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
if (dictVarTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
name = dictVarTokenPtr[1].start;
|
||||
nameChars = dictVarTokenPtr[1].size;
|
||||
if (!TclIsLocalScalar(name, nameChars)) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
dictIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr);
|
||||
if (dictIndex < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1696,7 +1721,7 @@ TclCompileDictUpdateCmd(
|
||||
failedUpdateInfoAssembly:
|
||||
ckfree(duiPtr);
|
||||
TclStackFree(interp, keyTokenPtrs);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
bodyTokenPtr = tokenPtr;
|
||||
|
||||
@@ -1794,17 +1819,17 @@ TclCompileDictAppendCmd(
|
||||
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
} else {
|
||||
register const char *name = tokenPtr[1].start;
|
||||
register int nameChars = tokenPtr[1].size;
|
||||
|
||||
if (!TclIsLocalScalar(name, nameChars)) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr,cmdPtr, envPtr);
|
||||
}
|
||||
dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr);
|
||||
if (dictVarIndex < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr,cmdPtr, envPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1855,16 +1880,16 @@ TclCompileDictLappendCmd(
|
||||
keyTokenPtr = TokenAfter(varTokenPtr);
|
||||
valueTokenPtr = TokenAfter(keyTokenPtr);
|
||||
if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
name = varTokenPtr[1].start;
|
||||
nameChars = varTokenPtr[1].size;
|
||||
if (!TclIsLocalScalar(name, nameChars)) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr);
|
||||
if (dictVarIndex < 0) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
CompileWord(envPtr, keyTokenPtr, interp, 3);
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 4);
|
||||
@@ -1908,7 +1933,7 @@ TclCompileDictWithCmd(
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1920,7 +1945,8 @@ TclCompileDictWithCmd(
|
||||
for (ptr=tokenPtr[1].start,end=ptr+tokenPtr[1].size ; ptr!=end ; ptr++) {
|
||||
if (*ptr!=' ' && *ptr!='\t' && *ptr!='\n' && *ptr!='\r') {
|
||||
if (envPtr->procPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr,
|
||||
envPtr);
|
||||
}
|
||||
bodyIsEmpty = 0;
|
||||
break;
|
||||
@@ -3082,7 +3108,7 @@ TclCompileFormatCmd(
|
||||
* after our attempt to spot a literal).
|
||||
*/
|
||||
|
||||
for (; --i>=0 ;) {
|
||||
for (; i>=0 ; i--) {
|
||||
Tcl_DecrRefCount(objv[i]);
|
||||
}
|
||||
ckfree(objv);
|
||||
@@ -3747,7 +3773,9 @@ TclCompileInfoCommandsCmd(
|
||||
* We require one compile-time known argument for the case we can compile.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 2) {
|
||||
if (parsePtr->numWords == 1) {
|
||||
return TclCompileBasic0ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
} else if (parsePtr->numWords != 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
@@ -3784,7 +3812,7 @@ TclCompileInfoCommandsCmd(
|
||||
|
||||
notCompilable:
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic1ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -5791,7 +5819,7 @@ TclCompileVariableCmd(
|
||||
*/
|
||||
|
||||
valueTokenPtr = parsePtr->tokenPtr;
|
||||
for (i=2; i<=numWords; i+=2) {
|
||||
for (i=1; i<numWords; i+=2) {
|
||||
varTokenPtr = TokenAfter(valueTokenPtr);
|
||||
valueTokenPtr = TokenAfter(varTokenPtr);
|
||||
|
||||
@@ -5801,15 +5829,15 @@ TclCompileVariableCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
CompileWord(envPtr, varTokenPtr, interp, 1);
|
||||
CompileWord(envPtr, varTokenPtr, interp, i);
|
||||
TclEmitInstInt4( INST_VARIABLE, localIndex, envPtr);
|
||||
|
||||
if (i != numWords) {
|
||||
if (i+1 < numWords) {
|
||||
/*
|
||||
* A value has been given: set the variable, pop the value
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
CompileWord(envPtr, valueTokenPtr, interp, i+1);
|
||||
Emit14Inst( INST_STORE_SCALAR, localIndex, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
}
|
||||
@@ -6006,7 +6034,7 @@ PushVarName(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
Tcl_Token *varTokenPtr, /* Points to a variable token. */
|
||||
CompileEnv *envPtr, /* Holds resulting instructions. */
|
||||
int flags, /* TCL_NO_LARGE_INDEX. */
|
||||
int flags, /* TCL_NO_LARGE_INDEX | TCL_NO_ELEMENT. */
|
||||
int *localIndexPtr, /* Must not be NULL. */
|
||||
int *simpleVarNamePtr, /* Must not be NULL. */
|
||||
int *isScalarPtr, /* Must not be NULL. */
|
||||
@@ -6187,10 +6215,11 @@ PushVarName(
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile the element script, if any.
|
||||
* Compile the element script, if any, and only if not inhibited. [Bug
|
||||
* 3600328]
|
||||
*/
|
||||
|
||||
if (elName != NULL) {
|
||||
if (elName != NULL && !(flags & TCL_NO_ELEMENT)) {
|
||||
if (elNameChars) {
|
||||
envPtr->line = line;
|
||||
envPtr->clNext = clNext;
|
||||
|
||||
+44
-14
@@ -448,7 +448,7 @@ TclCompileStringMatchCmd(
|
||||
|
||||
if (parsePtr->numWords == 4) {
|
||||
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
str = tokenPtr[1].start;
|
||||
length = tokenPtr[1].size;
|
||||
@@ -457,7 +457,7 @@ TclCompileStringMatchCmd(
|
||||
* Fail at run time, not in compilation.
|
||||
*/
|
||||
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
nocase = 1;
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
@@ -578,13 +578,13 @@ TclCompileStringMapCmd(
|
||||
Tcl_IncrRefCount(mapObj);
|
||||
if (!TclWordKnownAtCompileTime(mapTokenPtr, mapObj)) {
|
||||
Tcl_DecrRefCount(mapObj);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
} else if (Tcl_ListObjGetElements(NULL, mapObj, &len, &objv) != TCL_OK) {
|
||||
Tcl_DecrRefCount(mapObj);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
} else if (len != 2) {
|
||||
Tcl_DecrRefCount(mapObj);
|
||||
return TCL_ERROR;
|
||||
return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -836,6 +836,34 @@ TclSubstCompile(
|
||||
TclEmitPush(literal, envPtr);
|
||||
count++;
|
||||
continue;
|
||||
case TCL_TOKEN_VARIABLE:
|
||||
/*
|
||||
* Check for simple variable access; see if we can only generate
|
||||
* TCL_OK or TCL_ERROR from the substituted variable read; if so,
|
||||
* there is no need to generate elaborate exception-management
|
||||
* code. Note that the first component of TCL_TOKEN_VARIABLE is
|
||||
* always TCL_TOKEN_TEXT...
|
||||
*/
|
||||
|
||||
if (tokenPtr->numComponents > 1) {
|
||||
int i, foundCommand = 0;
|
||||
|
||||
for (i=2 ; i<=tokenPtr->numComponents ; i++) {
|
||||
if (tokenPtr[i].type == TCL_TOKEN_COMMAND) {
|
||||
foundCommand = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundCommand) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
envPtr->line = bline;
|
||||
TclCompileVarSubst(interp, tokenPtr, envPtr);
|
||||
bline = envPtr->line;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (count > 255) {
|
||||
@@ -1224,12 +1252,7 @@ TclCompileSwitchCmd(
|
||||
if (TCL_OK != TclFindElement(NULL, bytes, numBytes,
|
||||
&(bodyTokenArray[numWords].start), &bytes,
|
||||
&(bodyTokenArray[numWords].size), &literal) || !literal) {
|
||||
abort:
|
||||
ckfree((char *) bodyToken);
|
||||
ckfree((char *) bodyTokenArray);
|
||||
ckfree((char *) bodyLines);
|
||||
ckfree((char *) bodyContLines);
|
||||
return TCL_ERROR;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
bodyTokenArray[numWords].type = TCL_TOKEN_TEXT;
|
||||
@@ -1254,7 +1277,12 @@ TclCompileSwitchCmd(
|
||||
numWords++;
|
||||
}
|
||||
if (numWords % 2) {
|
||||
goto abort;
|
||||
abort:
|
||||
ckfree((char *) bodyToken);
|
||||
ckfree((char *) bodyTokenArray);
|
||||
ckfree((char *) bodyLines);
|
||||
ckfree((char *) bodyContLines);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else if (numWords % 2 || numWords == 0) {
|
||||
/*
|
||||
@@ -1925,11 +1953,13 @@ TclCompileTailcallCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* make room for the nsObjPtr */
|
||||
CompileWord(envPtr, tokenPtr, interp, 0);
|
||||
for (i=1 ; i<parsePtr->numWords ; i++) {
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
}
|
||||
TclEmitInstInt1( INST_TAILCALL, parsePtr->numWords-1, envPtr);
|
||||
TclEmitInstInt1( INST_TAILCALL, parsePtr->numWords, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2709,7 +2739,7 @@ TclCompileUnsetCmd(
|
||||
flags = 1;
|
||||
varTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
leadingWord = Tcl_NewObj();
|
||||
if (TclWordKnownAtCompileTime(varTokenPtr, leadingWord)) {
|
||||
if (numWords > 0 && TclWordKnownAtCompileTime(varTokenPtr, leadingWord)) {
|
||||
int len;
|
||||
const char *bytes = Tcl_GetStringFromObj(leadingWord, &len);
|
||||
|
||||
|
||||
@@ -2207,7 +2207,7 @@ ExecConstantExprTree(
|
||||
TclInitByteCodeObj(byteCodeObj, envPtr);
|
||||
TclFreeCompileEnv(envPtr);
|
||||
TclStackFree(interp, envPtr);
|
||||
byteCodePtr = byteCodeObj->internalRep.otherValuePtr;
|
||||
byteCodePtr = byteCodeObj->internalRep.twoPtrValue.ptr1;
|
||||
TclNRExecuteByteCode(interp, byteCodePtr);
|
||||
code = TclNRRunCallbacks(interp, TCL_OK, rootPtr);
|
||||
Tcl_DecrRefCount(byteCodeObj);
|
||||
@@ -2445,14 +2445,11 @@ CompileExprTree(
|
||||
Tcl_Obj *literal = *litObjv;
|
||||
|
||||
if (optimize) {
|
||||
int length, index;
|
||||
int length;
|
||||
const char *bytes = TclGetStringFromObj(literal, &length);
|
||||
LiteralEntry *lePtr;
|
||||
Tcl_Obj *objPtr;
|
||||
|
||||
index = TclRegisterNewLiteral(envPtr, bytes, length);
|
||||
lePtr = envPtr->literalArrayPtr + index;
|
||||
objPtr = lePtr->objPtr;
|
||||
int index = TclRegisterNewLiteral(envPtr, bytes, length);
|
||||
Tcl_Obj *objPtr = TclFetchLiteral(envPtr, index);
|
||||
|
||||
if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
|
||||
/*
|
||||
* Would like to do this:
|
||||
@@ -2511,7 +2508,7 @@ CompileExprTree(
|
||||
|
||||
index = TclRegisterNewLiteral(envPtr, objPtr->bytes,
|
||||
objPtr->length);
|
||||
tableValue = envPtr->literalArrayPtr[index].objPtr;
|
||||
tableValue = TclFetchLiteral(envPtr, index);
|
||||
if ((tableValue->typePtr == NULL) &&
|
||||
(objPtr->typePtr != NULL)) {
|
||||
/*
|
||||
|
||||
+107
-87
@@ -529,6 +529,11 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
/* 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;
|
||||
* <objc,objv> = <op4,top op4 after popping 1> */
|
||||
|
||||
{NULL, 0, 0, 0, {OPERAND_NONE}}
|
||||
};
|
||||
|
||||
@@ -552,6 +557,7 @@ static int GetCmdLocEncodingSize(CompileEnv *envPtr);
|
||||
#ifdef TCL_COMPILE_STATS
|
||||
static void RecordByteCodeStats(ByteCode *codePtr);
|
||||
#endif /* TCL_COMPILE_STATS */
|
||||
static void RegisterAuxDataType(const AuxDataType *typePtr);
|
||||
static int SetByteCodeFromAny(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
static int FormatInstruction(ByteCode *codePtr,
|
||||
@@ -568,6 +574,7 @@ static void EnterCmdWordData(ExtCmdLoc *eclPtr, int srcOffset,
|
||||
Tcl_Token *tokenPtr, const char *cmd, int len,
|
||||
int numWords, int line, int *clNext, int **lines,
|
||||
CompileEnv *envPtr);
|
||||
static void ReleaseCmdWordData(ExtCmdLoc *eclPtr);
|
||||
|
||||
/*
|
||||
* The structure below defines the bytecode Tcl object type by means of
|
||||
@@ -645,9 +652,6 @@ TclSetByteCodeFromAny(
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
CompileEnv compEnv; /* Compilation environment structure allocated
|
||||
* in frame. */
|
||||
register const AuxData *auxDataPtr;
|
||||
LiteralEntry *entryPtr;
|
||||
register int i;
|
||||
int length, result = TCL_OK;
|
||||
const char *stringPtr;
|
||||
ContLineLoc *clLocPtr;
|
||||
@@ -717,35 +721,14 @@ TclSetByteCodeFromAny(
|
||||
TclVerifyLocalLiteralTable(&compEnv);
|
||||
#endif /*TCL_COMPILE_DEBUG*/
|
||||
|
||||
TclInitByteCodeObj(objPtr, &compEnv);
|
||||
if (result == TCL_OK) {
|
||||
TclInitByteCodeObj(objPtr, &compEnv);
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (tclTraceCompile >= 2) {
|
||||
TclPrintByteCodeObj(interp, objPtr);
|
||||
fflush(stdout);
|
||||
}
|
||||
if (tclTraceCompile >= 2) {
|
||||
TclPrintByteCodeObj(interp, objPtr);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif /* TCL_COMPILE_DEBUG */
|
||||
|
||||
if (result != TCL_OK) {
|
||||
/*
|
||||
* Handle any error from the hookProc
|
||||
*/
|
||||
|
||||
entryPtr = compEnv.literalArrayPtr;
|
||||
for (i = 0; i < compEnv.literalArrayNext; i++) {
|
||||
TclReleaseLiteral(interp, entryPtr->objPtr);
|
||||
entryPtr++;
|
||||
}
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
TclVerifyGlobalLiteralTable(iPtr);
|
||||
#endif /*TCL_COMPILE_DEBUG*/
|
||||
|
||||
auxDataPtr = compEnv.auxDataArrayPtr;
|
||||
for (i = 0; i < compEnv.auxDataArrayNext; i++) {
|
||||
if (auxDataPtr->type->freeProc != NULL) {
|
||||
auxDataPtr->type->freeProc(auxDataPtr->clientData);
|
||||
}
|
||||
auxDataPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
TclFreeCompileEnv(&compEnv);
|
||||
@@ -784,8 +767,7 @@ SetByteCodeFromAny(
|
||||
if (interp == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
|
||||
return TCL_OK;
|
||||
return TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -839,10 +821,9 @@ static void
|
||||
FreeByteCodeInternalRep(
|
||||
register Tcl_Obj *objPtr) /* Object whose internal rep to free. */
|
||||
{
|
||||
register ByteCode *codePtr = objPtr->internalRep.otherValuePtr;
|
||||
register ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
objPtr->internalRep.otherValuePtr = NULL;
|
||||
codePtr->refCount--;
|
||||
if (codePtr->refCount <= 0) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
@@ -862,9 +843,8 @@ FreeByteCodeInternalRep(
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Frees objPtr's bytecode internal representation and sets its type and
|
||||
* objPtr->internalRep.otherValuePtr NULL. Also releases its literals and
|
||||
* frees its auxiliary data items.
|
||||
* Frees objPtr's bytecode internal representation and sets its type NULL
|
||||
* Also releases its literals and frees its auxiliary data items.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -939,7 +919,7 @@ TclCleanupByteCode(
|
||||
* released.
|
||||
*/
|
||||
|
||||
if ((codePtr->flags & TCL_BYTECODE_PRECOMPILED) || (interp == NULL)) {
|
||||
if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
|
||||
|
||||
objArrayPtr = codePtr->objArrayPtr;
|
||||
for (i = 0; i < numLitObjects; i++) {
|
||||
@@ -952,17 +932,9 @@ TclCleanupByteCode(
|
||||
codePtr->numLitObjects = 0;
|
||||
} else {
|
||||
objArrayPtr = codePtr->objArrayPtr;
|
||||
for (i = 0; i < numLitObjects; i++) {
|
||||
/*
|
||||
* TclReleaseLiteral sets a ByteCode's object array entry NULL to
|
||||
* indicate that it has already freed the literal.
|
||||
*/
|
||||
|
||||
objPtr = *objArrayPtr;
|
||||
if (objPtr != NULL) {
|
||||
TclReleaseLiteral(interp, objPtr);
|
||||
}
|
||||
objArrayPtr++;
|
||||
while (numLitObjects--) {
|
||||
/* TclReleaseLiteral calls Tcl_DecrRefCount() for us */
|
||||
TclReleaseLiteral(interp, *objArrayPtr++);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,22 +959,7 @@ TclCleanupByteCode(
|
||||
(char *) codePtr);
|
||||
|
||||
if (hePtr) {
|
||||
ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr);
|
||||
|
||||
if (eclPtr->type == TCL_LOCATION_SOURCE) {
|
||||
Tcl_DecrRefCount(eclPtr->path);
|
||||
}
|
||||
for (i=0 ; i<eclPtr->nuloc ; i++) {
|
||||
ckfree(eclPtr->loc[i].line);
|
||||
}
|
||||
|
||||
if (eclPtr->loc != NULL) {
|
||||
ckfree(eclPtr->loc);
|
||||
}
|
||||
|
||||
Tcl_DeleteHashTable(&eclPtr->litInfo);
|
||||
|
||||
ckfree(eclPtr);
|
||||
ReleaseCmdWordData(Tcl_GetHashValue(hePtr));
|
||||
Tcl_DeleteHashEntry(hePtr);
|
||||
}
|
||||
}
|
||||
@@ -1139,7 +1096,7 @@ CompileSubstObj(
|
||||
objPtr->typePtr = &substCodeType;
|
||||
TclFreeCompileEnv(&compEnv);
|
||||
|
||||
codePtr = objPtr->internalRep.otherValuePtr;
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
objPtr->internalRep.ptrAndLongRep.ptr = codePtr;
|
||||
objPtr->internalRep.ptrAndLongRep.value = flags;
|
||||
if (iPtr->varFramePtr->localCachePtr) {
|
||||
@@ -1178,12 +1135,33 @@ FreeSubstCodeInternalRep(
|
||||
register ByteCode *codePtr = objPtr->internalRep.ptrAndLongRep.ptr;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
objPtr->internalRep.otherValuePtr = NULL;
|
||||
codePtr->refCount--;
|
||||
if (codePtr->refCount <= 0) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ReleaseCmdWordData(
|
||||
ExtCmdLoc *eclPtr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (eclPtr->type == TCL_LOCATION_SOURCE) {
|
||||
Tcl_DecrRefCount(eclPtr->path);
|
||||
}
|
||||
for (i=0 ; i<eclPtr->nuloc ; i++) {
|
||||
ckfree((char *) eclPtr->loc[i].line);
|
||||
}
|
||||
|
||||
if (eclPtr->loc != NULL) {
|
||||
ckfree((char *) eclPtr->loc);
|
||||
}
|
||||
|
||||
Tcl_DeleteHashTable (&eclPtr->litInfo);
|
||||
|
||||
ckfree((char *) eclPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -1417,6 +1395,32 @@ TclFreeCompileEnv(
|
||||
ckfree(envPtr->localLitTable.buckets);
|
||||
envPtr->localLitTable.buckets = envPtr->localLitTable.staticBuckets;
|
||||
}
|
||||
if (envPtr->iPtr) {
|
||||
/*
|
||||
* We never converted to Bytecode, so free the things we would
|
||||
* have transferred to it.
|
||||
*/
|
||||
|
||||
int i;
|
||||
LiteralEntry *entryPtr = envPtr->literalArrayPtr;
|
||||
AuxData *auxDataPtr = envPtr->auxDataArrayPtr;
|
||||
|
||||
for (i = 0; i < envPtr->literalArrayNext; i++) {
|
||||
TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, entryPtr->objPtr);
|
||||
entryPtr++;
|
||||
}
|
||||
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
TclVerifyGlobalLiteralTable(envPtr->iPtr);
|
||||
#endif /*TCL_COMPILE_DEBUG*/
|
||||
|
||||
for (i = 0; i < envPtr->auxDataArrayNext; i++) {
|
||||
if (auxDataPtr->type->freeProc != NULL) {
|
||||
auxDataPtr->type->freeProc(auxDataPtr->clientData);
|
||||
}
|
||||
auxDataPtr++;
|
||||
}
|
||||
}
|
||||
if (envPtr->mallocedCodeArray) {
|
||||
ckfree(envPtr->codeStart);
|
||||
}
|
||||
@@ -1433,7 +1437,8 @@ TclFreeCompileEnv(
|
||||
ckfree(envPtr->auxDataArrayPtr);
|
||||
}
|
||||
if (envPtr->extCmdMapPtr) {
|
||||
ckfree(envPtr->extCmdMapPtr);
|
||||
ReleaseCmdWordData(envPtr->extCmdMapPtr);
|
||||
envPtr->extCmdMapPtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1575,6 +1580,10 @@ TclCompileScript(
|
||||
int *wlines, wlineat, cmdLine, *clNext;
|
||||
Tcl_Parse *parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse));
|
||||
|
||||
if (envPtr->iPtr == NULL) {
|
||||
Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv");
|
||||
}
|
||||
|
||||
Tcl_DStringInit(&ds);
|
||||
|
||||
if (numBytes < 0) {
|
||||
@@ -1887,8 +1896,7 @@ TclCompileScript(
|
||||
tokenPtr[1].start, tokenPtr[1].size);
|
||||
if (cmdPtr != NULL) {
|
||||
TclSetCmdNameObj(interp,
|
||||
envPtr->literalArrayPtr[objIndex].objPtr,
|
||||
cmdPtr);
|
||||
TclFetchLiteral(envPtr, objIndex), cmdPtr);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@@ -1905,7 +1913,7 @@ TclCompileScript(
|
||||
|
||||
if (envPtr->clNext) {
|
||||
TclContinuationsEnterDerived(
|
||||
envPtr->literalArrayPtr[objIndex].objPtr,
|
||||
TclFetchLiteral(envPtr, objIndex),
|
||||
tokenPtr[1].start - envPtr->source,
|
||||
eclPtr->loc[wlineat].next[wordIdx]);
|
||||
}
|
||||
@@ -2214,9 +2222,8 @@ TclCompileTokens(
|
||||
Tcl_DStringFree(&textBuffer);
|
||||
|
||||
if (numCL) {
|
||||
TclContinuationsEnter(
|
||||
envPtr->literalArrayPtr[literal].objPtr, numCL,
|
||||
clPosition);
|
||||
TclContinuationsEnter(TclFetchLiteral(envPtr, literal),
|
||||
numCL, clPosition);
|
||||
}
|
||||
numCL = 0;
|
||||
}
|
||||
@@ -2262,7 +2269,7 @@ TclCompileTokens(
|
||||
TclEmitPush(literal, envPtr);
|
||||
numObjsToConcat++;
|
||||
if (numCL) {
|
||||
TclContinuationsEnter(envPtr->literalArrayPtr[literal].objPtr,
|
||||
TclContinuationsEnter(TclFetchLiteral(envPtr, literal),
|
||||
numCL, clPosition);
|
||||
}
|
||||
numCL = 0;
|
||||
@@ -2509,6 +2516,10 @@ TclInitByteCodeObj(
|
||||
int i, isNew;
|
||||
Interp *iPtr;
|
||||
|
||||
if (envPtr->iPtr == NULL) {
|
||||
Tcl_Panic("TclInitByteCodeObj() called on uninitialized CompileEnv");
|
||||
}
|
||||
|
||||
iPtr = envPtr->iPtr;
|
||||
|
||||
codeBytes = envPtr->codeNext - envPtr->codeStart;
|
||||
@@ -2566,7 +2577,9 @@ TclInitByteCodeObj(
|
||||
p += TCL_ALIGN(codeBytes); /* align object array */
|
||||
codePtr->objArrayPtr = (Tcl_Obj **) p;
|
||||
for (i = 0; i < numLitObjects; i++) {
|
||||
if (objPtr == envPtr->literalArrayPtr[i].objPtr) {
|
||||
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.
|
||||
@@ -2583,9 +2596,9 @@ TclInitByteCodeObj(
|
||||
|
||||
codePtr->objArrayPtr[i] = Tcl_NewStringObj(bytes, numBytes);
|
||||
Tcl_IncrRefCount(codePtr->objArrayPtr[i]);
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
TclReleaseLiteral((Tcl_Interp *)iPtr, objPtr);
|
||||
} else {
|
||||
codePtr->objArrayPtr[i] = envPtr->literalArrayPtr[i].objPtr;
|
||||
codePtr->objArrayPtr[i] = fetched;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2634,7 +2647,7 @@ TclInitByteCodeObj(
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.otherValuePtr = codePtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = codePtr;
|
||||
objPtr->typePtr = &tclByteCodeType;
|
||||
|
||||
/*
|
||||
@@ -2646,6 +2659,9 @@ TclInitByteCodeObj(
|
||||
&isNew), envPtr->extCmdMapPtr);
|
||||
envPtr->extCmdMapPtr = NULL;
|
||||
|
||||
/* We've used up the CompileEnv. Mark as uninitialized. */
|
||||
envPtr->iPtr = NULL;
|
||||
|
||||
codePtr->localCachePtr = NULL;
|
||||
}
|
||||
|
||||
@@ -3558,7 +3574,7 @@ TclGetInstructionTable(void)
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
* TclRegisterAuxDataType --
|
||||
* RegisterAuxDataType --
|
||||
*
|
||||
* This procedure is called to register a new AuxData type in the table
|
||||
* of all AuxData types supported by Tcl.
|
||||
@@ -3574,8 +3590,8 @@ TclGetInstructionTable(void)
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TclRegisterAuxDataType(
|
||||
static void
|
||||
RegisterAuxDataType(
|
||||
const AuxDataType *typePtr) /* Information about object type; storage must
|
||||
* be statically allocated (must live forever;
|
||||
* will not be deallocated). */
|
||||
@@ -3679,9 +3695,9 @@ TclInitAuxDataTypeTable(void)
|
||||
* There are only two AuxData type at this time, so register them here.
|
||||
*/
|
||||
|
||||
TclRegisterAuxDataType(&tclForeachInfoType);
|
||||
TclRegisterAuxDataType(&tclJumptableInfoType);
|
||||
TclRegisterAuxDataType(&tclDictUpdateInfoType);
|
||||
RegisterAuxDataType(&tclForeachInfoType);
|
||||
RegisterAuxDataType(&tclJumptableInfoType);
|
||||
RegisterAuxDataType(&tclDictUpdateInfoType);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4053,7 +4069,7 @@ Tcl_Obj *
|
||||
TclDisassembleByteCodeObj(
|
||||
Tcl_Obj *objPtr) /* The bytecode object to disassemble. */
|
||||
{
|
||||
ByteCode *codePtr = objPtr->internalRep.otherValuePtr;
|
||||
ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
unsigned char *codeStart, *codeLimit, *pc;
|
||||
unsigned char *codeDeltaNext, *codeLengthNext;
|
||||
unsigned char *srcDeltaNext, *srcLengthNext;
|
||||
@@ -4558,7 +4574,11 @@ TclGetInnerContext(
|
||||
if (!objPtr) {
|
||||
Tcl_Panic("InnerContext: bad tos -- appending null object");
|
||||
}
|
||||
if (objPtr->refCount<=0 || objPtr->refCount==0x61616161) {
|
||||
if ((objPtr->refCount<=0)
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|| (objPtr->refCount==0x61616161)
|
||||
#endif
|
||||
) {
|
||||
Tcl_Panic("InnerContext: bad tos -- appending freed object %p",
|
||||
objPtr);
|
||||
}
|
||||
|
||||
@@ -711,8 +711,10 @@ typedef struct ByteCode {
|
||||
#define INST_ARRAY_MAKE_STK 161
|
||||
#define INST_ARRAY_MAKE_IMM 162
|
||||
|
||||
#define INST_INVOKE_REPLACE 163
|
||||
|
||||
/* The last opcode */
|
||||
#define LAST_INST_OPCODE 162
|
||||
#define LAST_INST_OPCODE 163
|
||||
|
||||
/*
|
||||
* Table describing the Tcl bytecode instructions: their name (for displaying
|
||||
@@ -952,11 +954,10 @@ MODULE_SCOPE ExceptionRange * TclGetExceptionRangeForPc(unsigned char *pc,
|
||||
MODULE_SCOPE void TclExpandJumpFixupArray(JumpFixupArray *fixupArrayPtr);
|
||||
MODULE_SCOPE int TclNRExecuteByteCode(Tcl_Interp *interp,
|
||||
ByteCode *codePtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclFetchLiteral(CompileEnv *envPtr, unsigned int index);
|
||||
MODULE_SCOPE void TclFinalizeAuxDataTypeTable(void);
|
||||
MODULE_SCOPE int TclFindCompiledLocal(const char *name, int nameChars,
|
||||
int create, CompileEnv *envPtr);
|
||||
MODULE_SCOPE LiteralEntry * TclLookupLiteralEntry(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr,
|
||||
JumpFixup *jumpFixupPtr, int jumpDist,
|
||||
int distThreshold);
|
||||
@@ -965,7 +966,6 @@ MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr);
|
||||
MODULE_SCOPE void TclInitAuxDataTypeTable(void);
|
||||
MODULE_SCOPE void TclInitByteCodeObj(Tcl_Obj *objPtr,
|
||||
CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclInitCompilation(void);
|
||||
MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp,
|
||||
CompileEnv *envPtr, const char *string,
|
||||
int numBytes, const CmdFrame *invoker, int word);
|
||||
@@ -985,7 +985,6 @@ MODULE_SCOPE void TclPrintObject(FILE *outFile,
|
||||
Tcl_Obj *objPtr, int maxChars);
|
||||
MODULE_SCOPE void TclPrintSource(FILE *outFile,
|
||||
const char *string, int maxChars);
|
||||
MODULE_SCOPE void TclRegisterAuxDataType(const AuxDataType *typePtr);
|
||||
MODULE_SCOPE int TclRegisterLiteral(CompileEnv *envPtr,
|
||||
char *bytes, int length, int flags);
|
||||
MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
|
||||
@@ -3783,6 +3783,7 @@ extern const TclStubs *tclStubsPtr;
|
||||
# undef Tcl_Init
|
||||
# undef Tcl_SetPanicProc
|
||||
# undef Tcl_SetVar
|
||||
# undef Tcl_ObjSetVar2
|
||||
# undef Tcl_StaticPackage
|
||||
# undef TclFSGetNativePath
|
||||
# define Tcl_CreateInterp() (tclStubsPtr->tcl_CreateInterp())
|
||||
@@ -3791,6 +3792,8 @@ extern const TclStubs *tclStubsPtr;
|
||||
# define Tcl_SetPanicProc(proc) (tclStubsPtr->tcl_SetPanicProc(proc))
|
||||
# define Tcl_SetVar(interp, varName, newValue, flags) \
|
||||
(tclStubsPtr->tcl_SetVar(interp, varName, newValue, flags))
|
||||
# define Tcl_ObjSetVar2(interp, part1, part2, newValue, flags) \
|
||||
(tclStubsPtr->tcl_ObjSetVar2(interp, part1, part2, newValue, flags))
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
@@ -3803,4 +3806,97 @@ extern const TclStubs *tclStubsPtr;
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#define TCL_STORAGE_CLASS DLLIMPORT
|
||||
|
||||
#undef Tcl_SeekOld
|
||||
#undef Tcl_TellOld
|
||||
|
||||
#undef Tcl_PkgPresent
|
||||
#define Tcl_PkgPresent(interp, name, version, exact) \
|
||||
Tcl_PkgPresentEx(interp, name, version, exact, NULL)
|
||||
#undef Tcl_PkgProvide
|
||||
#define Tcl_PkgProvide(interp, name, version) \
|
||||
Tcl_PkgProvideEx(interp, name, version, NULL)
|
||||
#undef Tcl_PkgRequire
|
||||
#define Tcl_PkgRequire(interp, name, version, exact) \
|
||||
Tcl_PkgRequireEx(interp, name, version, exact, NULL)
|
||||
#undef Tcl_GetIndexFromObj
|
||||
#define Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr) \
|
||||
Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, \
|
||||
sizeof(char *), msg, flags, indexPtr)
|
||||
#undef Tcl_NewIntObj
|
||||
#define Tcl_NewIntObj Tcl_NewLongObj
|
||||
#undef Tcl_SetIntObj
|
||||
#define Tcl_SetIntObj Tcl_SetLongObj
|
||||
#undef Tcl_NewBooleanObj
|
||||
#define Tcl_NewBooleanObj(boolValue) \
|
||||
Tcl_NewLongObj((boolValue)!=0)
|
||||
#undef Tcl_DbNewBooleanObj
|
||||
#define Tcl_DbNewBooleanObj(boolValue, file, line) \
|
||||
Tcl_DbNewLongObj((boolValue)!=0, file, line)
|
||||
#undef Tcl_SetBooleanObj
|
||||
#define Tcl_SetBooleanObj(objPtr, boolValue) \
|
||||
Tcl_SetLongObj(objPtr, (boolValue)!=0)
|
||||
#undef Tcl_SetVar
|
||||
#define Tcl_SetVar(interp, varName, newValue, flags) \
|
||||
Tcl_SetVar2(interp, varName, NULL, newValue, flags)
|
||||
#undef Tcl_UnsetVar
|
||||
#define Tcl_UnsetVar(interp, varName, flags) \
|
||||
Tcl_UnsetVar2(interp, varName, NULL, flags)
|
||||
#undef Tcl_GetVar
|
||||
#define Tcl_GetVar(interp, varName, flags) \
|
||||
Tcl_GetVar2(interp, varName, NULL, flags)
|
||||
#undef Tcl_TraceVar
|
||||
#define Tcl_TraceVar(interp, varName, flags, proc, clientData) \
|
||||
Tcl_TraceVar2(interp, varName, NULL, flags, proc, clientData)
|
||||
#undef Tcl_UntraceVar
|
||||
#define Tcl_UntraceVar(interp, varName, flags, proc, clientData) \
|
||||
Tcl_UntraceVar2(interp, varName, NULL, flags, proc, clientData)
|
||||
#undef Tcl_VarTraceInfo
|
||||
#define Tcl_VarTraceInfo(interp, varName, flags, proc, prevClientData) \
|
||||
Tcl_VarTraceInfo2(interp, varName, NULL, flags, proc, prevClientData)
|
||||
#undef Tcl_UpVar
|
||||
#define Tcl_UpVar(interp, frameName, varName, localName, flags) \
|
||||
Tcl_UpVar2(interp, frameName, varName, NULL, localName, flags)
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_Eval
|
||||
#define Tcl_Eval(interp,objPtr) \
|
||||
Tcl_EvalEx(interp,objPtr,-1,0)
|
||||
#undef Tcl_GlobalEval
|
||||
#define Tcl_GlobalEval(interp,objPtr) \
|
||||
Tcl_EvalEx(interp,objPtr,-1,TCL_EVAL_GLOBAL)
|
||||
#undef Tcl_AddErrorInfo
|
||||
#define Tcl_AddErrorInfo(interp, message) \
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, -1))
|
||||
#undef Tcl_AddObjErrorInfo
|
||||
#define Tcl_AddObjErrorInfo(interp, message, length) \
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, length))
|
||||
#undef Tcl_SaveResult
|
||||
#define Tcl_SaveResult(interp, statePtr) \
|
||||
do { \
|
||||
(statePtr)->objResultPtr = Tcl_GetObjResult(interp); \
|
||||
Tcl_IncrRefCount((statePtr)->objResultPtr); \
|
||||
Tcl_SetObjResult((interp), Tcl_NewObj()); \
|
||||
} while(0)
|
||||
#undef Tcl_RestoreResult
|
||||
#define Tcl_RestoreResult(interp, statePtr) \
|
||||
do { \
|
||||
Tcl_ResetResult(interp); \
|
||||
Tcl_SetObjResult((interp), (statePtr)->objResultPtr); \
|
||||
Tcl_DecrRefCount((statePtr)->objResultPtr); \
|
||||
} while(0)
|
||||
#undef Tcl_DiscardResult
|
||||
#define Tcl_DiscardResult(statePtr) \
|
||||
Tcl_DecrRefCount((statePtr)->objResultPtr)
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Deprecated Tcl procedures:
|
||||
*/
|
||||
#undef Tcl_EvalObj
|
||||
#define Tcl_EvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),0)
|
||||
#undef Tcl_GlobalEvalObj
|
||||
#define Tcl_GlobalEvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL)
|
||||
|
||||
#endif /* _TCLDECLS */
|
||||
|
||||
+33
-35
@@ -91,22 +91,22 @@ static const EnsembleImplMap implementationMap[] = {
|
||||
{"append", DictAppendCmd, TclCompileDictAppendCmd, NULL, NULL, 0 },
|
||||
{"create", DictCreateCmd, TclCompileDictCreateCmd, NULL, NULL, 0 },
|
||||
{"exists", DictExistsCmd, TclCompileDictExistsCmd, NULL, NULL, 0 },
|
||||
{"filter", DictFilterCmd, NULL, NULL, NULL, 0 },
|
||||
{"filter", DictFilterCmd, NULL, NULL, NULL, 0 },
|
||||
{"for", NULL, TclCompileDictForCmd, DictForNRCmd, NULL, 0 },
|
||||
{"get", DictGetCmd, TclCompileDictGetCmd, NULL, NULL, 0 },
|
||||
{"incr", DictIncrCmd, TclCompileDictIncrCmd, NULL, NULL, 0 },
|
||||
{"info", DictInfoCmd, NULL, NULL, NULL, 0 },
|
||||
{"keys", DictKeysCmd, NULL, NULL, NULL, 0 },
|
||||
{"info", DictInfoCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
|
||||
{"keys", DictKeysCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
|
||||
{"lappend", DictLappendCmd, TclCompileDictLappendCmd, NULL, NULL, 0 },
|
||||
{"map", NULL, TclCompileDictMapCmd, DictMapNRCmd, NULL, 0 },
|
||||
{"merge", DictMergeCmd, TclCompileDictMergeCmd, NULL, NULL, 0 },
|
||||
{"remove", DictRemoveCmd, NULL, NULL, NULL, 0 },
|
||||
{"remove", DictRemoveCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 },
|
||||
{"replace", DictReplaceCmd, NULL, NULL, NULL, 0 },
|
||||
{"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 },
|
||||
{"size", DictSizeCmd, NULL, NULL, NULL, 0 },
|
||||
{"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
|
||||
{"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 },
|
||||
{"update", DictUpdateCmd, TclCompileDictUpdateCmd, NULL, NULL, 0 },
|
||||
{"values", DictValuesCmd, NULL, NULL, NULL, 0 },
|
||||
{"values", DictValuesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
|
||||
{"with", DictWithCmd, TclCompileDictWithCmd, NULL, NULL, 0 },
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
@@ -361,7 +361,7 @@ DupDictInternalRep(
|
||||
Tcl_Obj *srcPtr,
|
||||
Tcl_Obj *copyPtr)
|
||||
{
|
||||
Dict *oldDict = srcPtr->internalRep.otherValuePtr;
|
||||
Dict *oldDict = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
Dict *newDict = ckalloc(sizeof(Dict));
|
||||
ChainEntry *cPtr;
|
||||
|
||||
@@ -396,7 +396,7 @@ DupDictInternalRep(
|
||||
* Store in the object.
|
||||
*/
|
||||
|
||||
copyPtr->internalRep.otherValuePtr = newDict;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = newDict;
|
||||
copyPtr->typePtr = &tclDictType;
|
||||
}
|
||||
|
||||
@@ -422,14 +422,12 @@ static void
|
||||
FreeDictInternalRep(
|
||||
Tcl_Obj *dictPtr)
|
||||
{
|
||||
Dict *dict = dictPtr->internalRep.otherValuePtr;
|
||||
Dict *dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
dict->refcount--;
|
||||
if (dict->refcount <= 0) {
|
||||
DeleteDict(dict);
|
||||
}
|
||||
|
||||
dictPtr->internalRep.otherValuePtr = NULL; /* Belt and braces! */
|
||||
dictPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
@@ -489,7 +487,7 @@ UpdateStringOfDict(
|
||||
{
|
||||
#define LOCAL_SIZE 20
|
||||
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
|
||||
Dict *dict = dictPtr->internalRep.otherValuePtr;
|
||||
Dict *dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
ChainEntry *cPtr;
|
||||
Tcl_Obj *keyPtr, *valuePtr;
|
||||
int i, length, bytesNeeded = 0;
|
||||
@@ -715,7 +713,7 @@ SetDictFromAny(
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
objPtr->internalRep.otherValuePtr = dict;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = dict;
|
||||
objPtr->typePtr = &tclDictType;
|
||||
return TCL_OK;
|
||||
|
||||
@@ -784,7 +782,7 @@ TclTraceDictPath(
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (flags & DICT_PATH_UPDATE) {
|
||||
dict->chain = NULL;
|
||||
}
|
||||
@@ -827,7 +825,7 @@ TclTraceDictPath(
|
||||
}
|
||||
}
|
||||
|
||||
newDict = tmpObj->internalRep.otherValuePtr;
|
||||
newDict = tmpObj->internalRep.twoPtrValue.ptr1;
|
||||
if (flags & DICT_PATH_UPDATE) {
|
||||
if (Tcl_IsShared(tmpObj)) {
|
||||
TclDecrRefCount(tmpObj);
|
||||
@@ -835,7 +833,7 @@ TclTraceDictPath(
|
||||
Tcl_IncrRefCount(tmpObj);
|
||||
Tcl_SetHashValue(hPtr, tmpObj);
|
||||
dict->epoch++;
|
||||
newDict = tmpObj->internalRep.otherValuePtr;
|
||||
newDict = tmpObj->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
|
||||
newDict->chain = dictPtr;
|
||||
@@ -870,17 +868,17 @@ static void
|
||||
InvalidateDictChain(
|
||||
Tcl_Obj *dictObj)
|
||||
{
|
||||
Dict *dict = dictObj->internalRep.otherValuePtr;
|
||||
Dict *dict = dictObj->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
do {
|
||||
Tcl_InvalidateStringRep(dictObj);
|
||||
TclInvalidateStringRep(dictObj);
|
||||
dict->epoch++;
|
||||
dictObj = dict->chain;
|
||||
if (dictObj == NULL) {
|
||||
break;
|
||||
}
|
||||
dict->chain = NULL;
|
||||
dict = dictObj->internalRep.otherValuePtr;
|
||||
dict = dictObj->internalRep.twoPtrValue.ptr1;
|
||||
} while (dict != NULL);
|
||||
}
|
||||
|
||||
@@ -927,9 +925,9 @@ Tcl_DictObjPut(
|
||||
}
|
||||
|
||||
if (dictPtr->bytes != NULL) {
|
||||
Tcl_InvalidateStringRep(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
hPtr = CreateChainEntry(dict, keyPtr, &isNew);
|
||||
Tcl_IncrRefCount(valuePtr);
|
||||
if (!isNew) {
|
||||
@@ -980,7 +978,7 @@ Tcl_DictObjGet(
|
||||
}
|
||||
}
|
||||
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
hPtr = Tcl_FindHashEntry(&dict->table, keyPtr);
|
||||
if (hPtr == NULL) {
|
||||
*valuePtrPtr = NULL;
|
||||
@@ -1029,9 +1027,9 @@ Tcl_DictObjRemove(
|
||||
}
|
||||
|
||||
if (dictPtr->bytes != NULL) {
|
||||
Tcl_InvalidateStringRep(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (DeleteChainEntry(dict, keyPtr)) {
|
||||
dict->epoch++;
|
||||
}
|
||||
@@ -1071,7 +1069,7 @@ Tcl_DictObjSize(
|
||||
}
|
||||
}
|
||||
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
*sizePtr = dict->table.numEntries;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1126,7 +1124,7 @@ Tcl_DictObjFirst(
|
||||
}
|
||||
}
|
||||
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
cPtr = dict->entryChainHead;
|
||||
if (cPtr == NULL) {
|
||||
searchPtr->epoch = -1;
|
||||
@@ -1301,7 +1299,7 @@ Tcl_DictObjPutKeyList(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew);
|
||||
Tcl_IncrRefCount(valuePtr);
|
||||
if (!isNew) {
|
||||
@@ -1357,7 +1355,7 @@ Tcl_DictObjRemoveKeyList(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
DeleteChainEntry(dict, keyv[keyc-1]);
|
||||
InvalidateDictChain(dictPtr);
|
||||
return TCL_OK;
|
||||
@@ -1397,13 +1395,13 @@ Tcl_NewDictObj(void)
|
||||
Dict *dict;
|
||||
|
||||
TclNewObj(dictPtr);
|
||||
Tcl_InvalidateStringRep(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
dict = ckalloc(sizeof(Dict));
|
||||
InitChainTable(dict);
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
dictPtr->internalRep.otherValuePtr = dict;
|
||||
dictPtr->internalRep.twoPtrValue.ptr1 = dict;
|
||||
dictPtr->typePtr = &tclDictType;
|
||||
return dictPtr;
|
||||
#endif
|
||||
@@ -1446,13 +1444,13 @@ Tcl_DbNewDictObj(
|
||||
Dict *dict;
|
||||
|
||||
TclDbNewObj(dictPtr, file, line);
|
||||
Tcl_InvalidateStringRep(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
dict = ckalloc(sizeof(Dict));
|
||||
InitChainTable(dict);
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
dictPtr->internalRep.otherValuePtr = dict;
|
||||
dictPtr->internalRep.twoPtrValue.ptr1 = dict;
|
||||
dictPtr->typePtr = &tclDictType;
|
||||
return dictPtr;
|
||||
#else /* !TCL_MEM_DEBUG */
|
||||
@@ -2064,7 +2062,7 @@ DictInfoCmd(
|
||||
return result;
|
||||
}
|
||||
}
|
||||
dict = dictPtr->internalRep.otherValuePtr;
|
||||
dict = dictPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
statsStr = Tcl_HashStats(&dict->table);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(statsStr, -1));
|
||||
@@ -2179,7 +2177,7 @@ DictIncrCmd(
|
||||
}
|
||||
}
|
||||
if (code == TCL_OK) {
|
||||
Tcl_InvalidateStringRep(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
valuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL,
|
||||
dictPtr, TCL_LEAVE_ERR_MSG);
|
||||
if (valuePtr == NULL) {
|
||||
@@ -2268,7 +2266,7 @@ DictLappendCmd(
|
||||
if (allocatedValue) {
|
||||
Tcl_DictObjPut(interp, dictPtr, objv[2], valuePtr);
|
||||
} else if (dictPtr->bytes != NULL) {
|
||||
Tcl_InvalidateStringRep(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
|
||||
resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
|
||||
|
||||
@@ -270,7 +270,7 @@ static int Iso88591ToUtfProc(ClientData clientData,
|
||||
int *dstCharsPtr);
|
||||
|
||||
/*
|
||||
* A Tcl_ObjType for holding a cached Tcl_Encoding in the otherValuePtr field
|
||||
* A Tcl_ObjType for holding a cached Tcl_Encoding in the twoPtrValue.ptr1 field
|
||||
* of the intrep. This should help the lifetime of encodings be more useful.
|
||||
* See concerns raised in [Bug 1077262].
|
||||
*/
|
||||
@@ -313,7 +313,7 @@ Tcl_GetEncodingFromObj(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.otherValuePtr = encoding;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = encoding;
|
||||
objPtr->typePtr = &encodingType;
|
||||
}
|
||||
*encodingPtr = Tcl_GetEncoding(NULL, name);
|
||||
@@ -334,7 +334,7 @@ static void
|
||||
FreeEncodingIntRep(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
Tcl_FreeEncoding(objPtr->internalRep.otherValuePtr);
|
||||
Tcl_FreeEncoding(objPtr->internalRep.twoPtrValue.ptr1);
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ DupEncodingIntRep(
|
||||
Tcl_Obj *srcPtr,
|
||||
Tcl_Obj *dupPtr)
|
||||
{
|
||||
dupPtr->internalRep.otherValuePtr = Tcl_GetEncoding(NULL, srcPtr->bytes);
|
||||
dupPtr->internalRep.twoPtrValue.ptr1 = Tcl_GetEncoding(NULL, srcPtr->bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+602
-68
@@ -4,7 +4,7 @@
|
||||
* Contains support for ensembles (see TIP#112), which provide simple
|
||||
* mechanism for creating composite commands on top of namespaces.
|
||||
*
|
||||
* Copyright (c) 2005-2010 Donal K. Fellows.
|
||||
* Copyright (c) 2005-2013 Donal K. Fellows.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -35,6 +35,15 @@ static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr,
|
||||
static void FreeEnsembleCmdRep(Tcl_Obj *objPtr);
|
||||
static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
|
||||
static void StringOfEnsembleCmdRep(Tcl_Obj *objPtr);
|
||||
static int CompileToCompiledCommand(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, int depth, Command *cmdPtr,
|
||||
CompileEnv *envPtr);
|
||||
static void CompileToInvokedCommand(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Tcl_Obj *replacements,
|
||||
Command *cmdPtr, CompileEnv *envPtr);
|
||||
static int CompileBasicNArgCommand(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
CompileEnv *envPtr);
|
||||
|
||||
/*
|
||||
* The lists of subcommands and options for the [namespace ensemble] command.
|
||||
@@ -78,6 +87,17 @@ const Tcl_ObjType tclEnsembleCmdType = {
|
||||
StringOfEnsembleCmdRep, /* updateStringProc */
|
||||
NULL /* setFromAnyProc */
|
||||
};
|
||||
|
||||
/*
|
||||
* Copied from tclCompCmds.c
|
||||
*/
|
||||
|
||||
#define DefineLineInformation \
|
||||
ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr; \
|
||||
int eclIndex = mapPtr->nuloc - 1
|
||||
#define SetLineInformation(word) \
|
||||
envPtr->line = mapPtr->loc[eclIndex].line[(word)]; \
|
||||
envPtr->clNext = mapPtr->loc[eclIndex].next[(word)]
|
||||
|
||||
static inline Tcl_Obj *
|
||||
NewNsObj(
|
||||
@@ -1565,21 +1585,23 @@ TclMakeEnsemble(
|
||||
NULL);
|
||||
}
|
||||
cmdPtr->compileProc = map[i].compileProc;
|
||||
if (map[i].compileProc != NULL) {
|
||||
ensembleFlags |= ENSEMBLE_COMPILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict);
|
||||
if (ensembleFlags & ENSEMBLE_COMPILE) {
|
||||
Tcl_SetEnsembleFlags(interp, ensemble, ensembleFlags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch on compilation always for core ensembles now that we can do
|
||||
* nice bytecode things with them.
|
||||
*/
|
||||
|
||||
Tcl_SetEnsembleFlags(interp, ensemble,
|
||||
ensembleFlags | ENSEMBLE_COMPILE);
|
||||
}
|
||||
|
||||
Tcl_DStringFree(&buf);
|
||||
Tcl_DStringFree(&hiddenBuf);
|
||||
if (nameParts != NULL) {
|
||||
Tcl_Free((char *) nameParts);
|
||||
ckfree((char *) nameParts);
|
||||
}
|
||||
return ensemble;
|
||||
}
|
||||
@@ -1696,7 +1718,7 @@ NsEnsembleImplementationCmdNR(
|
||||
|
||||
if (objv[1+ensemblePtr->numParameters]->typePtr==&tclEnsembleCmdType){
|
||||
EnsembleCmdRep *ensembleCmd = objv[1+ensemblePtr->numParameters]
|
||||
->internalRep.otherValuePtr;
|
||||
->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
if (ensembleCmd->nsPtr == ensemblePtr->nsPtr &&
|
||||
ensembleCmd->epoch == ensemblePtr->epoch &&
|
||||
@@ -1892,7 +1914,7 @@ NsEnsembleImplementationCmdNR(
|
||||
* Hand off to the target command.
|
||||
*/
|
||||
|
||||
iPtr->evalFlags |= TCL_EVAL_REDIRECT;
|
||||
TclSkipTailcall(interp);
|
||||
return TclNREvalObjEx(interp, copyPtr, TCL_EVAL_INVOKE, NULL,INT_MIN);
|
||||
}
|
||||
|
||||
@@ -2100,7 +2122,7 @@ EnsembleUnknownCallback(
|
||||
*/
|
||||
|
||||
Tcl_Preserve(ensemblePtr);
|
||||
((Interp *) interp)->evalFlags |= TCL_EVAL_REDIRECT;
|
||||
TclSkipTailcall(interp);
|
||||
result = Tcl_EvalObjv(interp, paramc, paramv, 0);
|
||||
if ((result == TCL_OK) && (ensemblePtr->flags & ENSEMBLE_DEAD)) {
|
||||
if (!Tcl_InterpDeleted(interp)) {
|
||||
@@ -2174,7 +2196,7 @@ EnsembleUnknownCallback(
|
||||
}
|
||||
Tcl_AddErrorInfo(interp, "\n result of "
|
||||
"ensemble unknown subcommand handler: ");
|
||||
Tcl_AddErrorInfo(interp, TclGetString(unknownCmd));
|
||||
Tcl_AppendObjToErrorInfo(interp, unknownCmd);
|
||||
Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_RESULT",
|
||||
NULL);
|
||||
} else {
|
||||
@@ -2216,7 +2238,7 @@ MakeCachedEnsembleCommand(
|
||||
int length;
|
||||
|
||||
if (objPtr->typePtr == &tclEnsembleCmdType) {
|
||||
ensembleCmd = objPtr->internalRep.otherValuePtr;
|
||||
ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
|
||||
TclNsDecrRefCount(ensembleCmd->nsPtr);
|
||||
ckfree(ensembleCmd->fullSubcmdName);
|
||||
@@ -2228,7 +2250,7 @@ MakeCachedEnsembleCommand(
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
ensembleCmd = ckalloc(sizeof(EnsembleCmdRep));
|
||||
objPtr->internalRep.otherValuePtr = ensembleCmd;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = ensembleCmd;
|
||||
objPtr->typePtr = &tclEnsembleCmdType;
|
||||
}
|
||||
|
||||
@@ -2623,7 +2645,7 @@ static void
|
||||
FreeEnsembleCmdRep(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
|
||||
ckfree(ensembleCmd->fullSubcmdName);
|
||||
@@ -2655,12 +2677,12 @@ DupEnsembleCmdRep(
|
||||
Tcl_Obj *objPtr,
|
||||
Tcl_Obj *copyPtr)
|
||||
{
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
EnsembleCmdRep *ensembleCopy = ckalloc(sizeof(EnsembleCmdRep));
|
||||
int length = strlen(ensembleCmd->fullSubcmdName);
|
||||
|
||||
copyPtr->typePtr = &tclEnsembleCmdType;
|
||||
copyPtr->internalRep.otherValuePtr = ensembleCopy;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = ensembleCopy;
|
||||
ensembleCopy->nsPtr = ensembleCmd->nsPtr;
|
||||
ensembleCopy->epoch = ensembleCmd->epoch;
|
||||
ensembleCopy->token = ensembleCmd->token;
|
||||
@@ -2693,7 +2715,7 @@ static void
|
||||
StringOfEnsembleCmdRep(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
|
||||
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
int length = strlen(ensembleCmd->fullSubcmdName);
|
||||
|
||||
objPtr->length = length;
|
||||
@@ -2731,25 +2753,33 @@ TclCompileEnsemble(
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
Tcl_Token *tokenPtr;
|
||||
Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems;
|
||||
Tcl_Obj *replaced = Tcl_NewObj(), *replacement;
|
||||
Tcl_Command ensemble = (Tcl_Command) cmdPtr;
|
||||
Tcl_Parse synthetic;
|
||||
int len, result, flags = 0, i;
|
||||
Command *oldCmdPtr = cmdPtr, *newCmdPtr;
|
||||
int len, result, flags = 0, i, depth = 1, invokeAnyway = 0;
|
||||
int ourResult = TCL_ERROR;
|
||||
unsigned numBytes;
|
||||
const char *word;
|
||||
|
||||
if (parsePtr->numWords < 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_IncrRefCount(replaced);
|
||||
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
/*
|
||||
* This is where we return to if we are parsing multiple nested compiled
|
||||
* ensembles. [info object] is such a beast.
|
||||
*/
|
||||
|
||||
checkNextWord:
|
||||
if (parsePtr->numWords < depth + 1) {
|
||||
goto failed;
|
||||
}
|
||||
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
/*
|
||||
* Too hard.
|
||||
*/
|
||||
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
word = tokenPtr[1].start;
|
||||
@@ -2768,7 +2798,7 @@ TclCompileEnsemble(
|
||||
* to proceed.
|
||||
*/
|
||||
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2782,7 +2812,7 @@ TclCompileEnsemble(
|
||||
* Figuring out how to compile this has become too much. Bail out.
|
||||
*/
|
||||
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2805,7 +2835,7 @@ TclCompileEnsemble(
|
||||
Tcl_Obj *matchObj = NULL;
|
||||
|
||||
if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
for (i=0 ; i<len ; i++) {
|
||||
str = Tcl_GetStringFromObj(elems[i], &sclen);
|
||||
@@ -2816,8 +2846,9 @@ TclCompileEnsemble(
|
||||
|
||||
result = Tcl_DictObjGet(NULL, mapObj,elems[i], &targetCmdObj);
|
||||
if (result != TCL_OK || targetCmdObj == NULL) {
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
replacement = elems[i];
|
||||
goto doneMapLookup;
|
||||
}
|
||||
|
||||
@@ -2833,18 +2864,19 @@ TclCompileEnsemble(
|
||||
if ((flags & TCL_ENSEMBLE_PREFIX)
|
||||
&& strncmp(word, str, numBytes) == 0) {
|
||||
if (matchObj != NULL) {
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
matchObj = elems[i];
|
||||
}
|
||||
}
|
||||
if (matchObj == NULL) {
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
result = Tcl_DictObjGet(NULL, mapObj, matchObj, &targetCmdObj);
|
||||
if (result != TCL_OK || targetCmdObj == NULL) {
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
replacement = matchObj;
|
||||
} else {
|
||||
Tcl_DictSearch s;
|
||||
int done, matched;
|
||||
@@ -2856,14 +2888,15 @@ TclCompileEnsemble(
|
||||
|
||||
TclNewStringObj(subcmdObj, word, (int) numBytes);
|
||||
result = Tcl_DictObjGet(NULL, mapObj, subcmdObj, &targetCmdObj);
|
||||
TclDecrRefCount(subcmdObj);
|
||||
if (result == TCL_OK && targetCmdObj != NULL) {
|
||||
/*
|
||||
* Got it. Skip the fiddling around with prefixes.
|
||||
*/
|
||||
|
||||
replacement = subcmdObj;
|
||||
goto doneMapLookup;
|
||||
}
|
||||
TclDecrRefCount(subcmdObj);
|
||||
|
||||
/*
|
||||
* We've not literally got a valid subcommand. But maybe we have a
|
||||
@@ -2871,7 +2904,7 @@ TclCompileEnsemble(
|
||||
*/
|
||||
|
||||
if (!(flags & TCL_ENSEMBLE_PREFIX)) {
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2881,6 +2914,7 @@ TclCompileEnsemble(
|
||||
|
||||
Tcl_DictObjFirst(NULL, mapObj, &s, &subcmdObj, &tmpObj, &done);
|
||||
matched = 0;
|
||||
replacement = NULL; /* Silence, fool compiler! */
|
||||
while (!done) {
|
||||
if (strncmp(TclGetString(subcmdObj), word, numBytes) == 0) {
|
||||
if (matched++) {
|
||||
@@ -2891,6 +2925,7 @@ TclCompileEnsemble(
|
||||
|
||||
break;
|
||||
}
|
||||
replacement = subcmdObj;
|
||||
targetCmdObj = tmpObj;
|
||||
}
|
||||
Tcl_DictObjNext(&s, &subcmdObj, &tmpObj, &done);
|
||||
@@ -2903,7 +2938,8 @@ TclCompileEnsemble(
|
||||
*/
|
||||
|
||||
if (matched != 1) {
|
||||
return TCL_ERROR;
|
||||
invokeAnyway = 1;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2917,75 +2953,157 @@ TclCompileEnsemble(
|
||||
*/
|
||||
|
||||
doneMapLookup:
|
||||
Tcl_ListObjAppendElement(NULL, replaced, replacement);
|
||||
if (Tcl_ListObjGetElements(NULL, targetCmdObj, &len, &elems) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (len > 1 && Tcl_IsSafe(interp)) {
|
||||
return TCL_ERROR;
|
||||
goto failed;
|
||||
} else if (len != 1) {
|
||||
/*
|
||||
* Note that at this point we know we can't issue any special
|
||||
* instruction sequence as the mapping isn't one that we support at
|
||||
* the compiled level.
|
||||
*/
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
targetCmdObj = elems[0];
|
||||
|
||||
oldCmdPtr = cmdPtr;
|
||||
Tcl_IncrRefCount(targetCmdObj);
|
||||
cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj);
|
||||
newCmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj);
|
||||
TclDecrRefCount(targetCmdObj);
|
||||
if (cmdPtr == NULL || cmdPtr->compileProc == NULL
|
||||
|| cmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION
|
||||
|| cmdPtr->flags * CMD_HAS_EXEC_TRACES
|
||||
if (newCmdPtr == NULL || Tcl_IsSafe(interp)
|
||||
|| newCmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION
|
||||
|| newCmdPtr->flags & CMD_HAS_EXEC_TRACES
|
||||
|| ((Interp *)interp)->flags & DONT_COMPILE_CMDS_INLINE) {
|
||||
/*
|
||||
* Maps to an undefined command or a command without a compiler.
|
||||
* Cannot compile.
|
||||
*/
|
||||
|
||||
return TCL_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
cmdPtr = newCmdPtr;
|
||||
depth++;
|
||||
|
||||
/*
|
||||
* See whether we have a nested ensemble. If we do, we can go round the
|
||||
* mulberry bush again, consuming the next word.
|
||||
*/
|
||||
|
||||
if (cmdPtr->compileProc == TclCompileEnsemble) {
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
ensemble = (Tcl_Command) cmdPtr;
|
||||
goto checkNextWord;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we've done the mapping process, can now actually try to compile.
|
||||
* We do this by handing off to the subcommand's actual compiler. But to
|
||||
* do that, we have to perform some trickery to rewrite the arguments.
|
||||
* If there is a subcommand compiler and that successfully produces code,
|
||||
* we'll use that. Otherwise, we fall back to generating opcodes to do the
|
||||
* invoke at runtime.
|
||||
*/
|
||||
|
||||
TclParseInit(interp, NULL, 0, &synthetic);
|
||||
synthetic.numWords = parsePtr->numWords - 2 + len;
|
||||
TclGrowParseTokenArray(&synthetic, 2*len);
|
||||
synthetic.numTokens = 2*len;
|
||||
invokeAnyway = 1;
|
||||
if (CompileToCompiledCommand(interp, parsePtr, depth, cmdPtr,
|
||||
envPtr) == TCL_OK) {
|
||||
ourResult = TCL_OK;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have the space to work in, install something rewritten. Note
|
||||
* that we are here praying for all our might that none of these words are
|
||||
* a script; the error detection code will crash if that happens and there
|
||||
* is nothing we can do to avoid it!
|
||||
* Failed to do a full compile for some reason. Try to do a direct invoke
|
||||
* instead of going through the ensemble lookup process again.
|
||||
*/
|
||||
|
||||
for (i=0 ; i<len ; i++) {
|
||||
int sclen;
|
||||
const char *str = Tcl_GetStringFromObj(elems[i], &sclen);
|
||||
failed:
|
||||
if (depth < 250) {
|
||||
if (depth > 1) {
|
||||
if (!invokeAnyway) {
|
||||
cmdPtr = oldCmdPtr;
|
||||
depth--;
|
||||
}
|
||||
(void) Tcl_ListObjReplace(NULL, replaced, depth, 2, 0, NULL);
|
||||
}
|
||||
CompileToInvokedCommand(interp, parsePtr, replaced, cmdPtr, envPtr);
|
||||
ourResult = TCL_OK;
|
||||
}
|
||||
|
||||
synthetic.tokenPtr[2*i].type = TCL_TOKEN_SIMPLE_WORD;
|
||||
synthetic.tokenPtr[2*i].start = str;
|
||||
synthetic.tokenPtr[2*i].size = sclen;
|
||||
synthetic.tokenPtr[2*i].numComponents = 1;
|
||||
/*
|
||||
* Release the memory we allocated. If we've got here, we've either done
|
||||
* something useful or we're in a case that we can't compile at all and
|
||||
* we're just giving up.
|
||||
*/
|
||||
|
||||
synthetic.tokenPtr[2*i+1].type = TCL_TOKEN_TEXT;
|
||||
synthetic.tokenPtr[2*i+1].start = str;
|
||||
synthetic.tokenPtr[2*i+1].size = sclen;
|
||||
synthetic.tokenPtr[2*i+1].numComponents = 0;
|
||||
cleanup:
|
||||
Tcl_DecrRefCount(replaced);
|
||||
return ourResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* How to compile a subcommand using its own command compiler. To do that, we
|
||||
* have to perform some trickery to rewrite the arguments, as compilers *must*
|
||||
* have parse tokens that refer to addresses in the original script.
|
||||
*/
|
||||
|
||||
static int
|
||||
CompileToCompiledCommand(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr,
|
||||
int depth,
|
||||
Command *cmdPtr,
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
Tcl_Parse synthetic;
|
||||
Tcl_Token *tokenPtr;
|
||||
int result, i;
|
||||
int savedNumCmds = envPtr->numCommands;
|
||||
int savedStackDepth = envPtr->currStackDepth;
|
||||
unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart;
|
||||
|
||||
if (cmdPtr->compileProc == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclParseInit(interp, NULL, 0, &synthetic);
|
||||
synthetic.numWords = parsePtr->numWords - depth + 1;
|
||||
TclGrowParseTokenArray(&synthetic, 2);
|
||||
synthetic.numTokens = 2;
|
||||
|
||||
/*
|
||||
* Now we have the space to work in, install something rewritten. The
|
||||
* first word will "officially" be the bytes of the structured ensemble
|
||||
* name. That's technically wrong, but nobody will care; we just need
|
||||
* *something* here...
|
||||
*/
|
||||
|
||||
synthetic.tokenPtr[0].type = TCL_TOKEN_SIMPLE_WORD;
|
||||
synthetic.tokenPtr[0].start = parsePtr->tokenPtr[0].start;
|
||||
synthetic.tokenPtr[0].numComponents = 1;
|
||||
synthetic.tokenPtr[1].type = TCL_TOKEN_TEXT;
|
||||
synthetic.tokenPtr[1].start = parsePtr->tokenPtr[0].start;
|
||||
synthetic.tokenPtr[1].numComponents = 0;
|
||||
for (i=0,tokenPtr=parsePtr->tokenPtr ; i<depth ; i++) {
|
||||
int sclen = (tokenPtr->start - synthetic.tokenPtr[0].start)
|
||||
+ tokenPtr->size;
|
||||
|
||||
synthetic.tokenPtr[0].size = sclen;
|
||||
synthetic.tokenPtr[1].size = sclen;
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy over the real argument tokens.
|
||||
*/
|
||||
|
||||
for (i=len; i<synthetic.numWords; i++) {
|
||||
for (i=1; i<synthetic.numWords; i++) {
|
||||
int toCopy;
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
toCopy = tokenPtr->numComponents + 1;
|
||||
TclGrowParseTokenArray(&synthetic, toCopy);
|
||||
memcpy(synthetic.tokenPtr + synthetic.numTokens, tokenPtr,
|
||||
sizeof(Tcl_Token) * toCopy);
|
||||
synthetic.numTokens += toCopy;
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2994,6 +3112,17 @@ TclCompileEnsemble(
|
||||
|
||||
result = cmdPtr->compileProc(interp, &synthetic, cmdPtr, envPtr);
|
||||
|
||||
/*
|
||||
* If our target fails to compile, revert the number of commands and the
|
||||
* pointer to the place to issue the next instruction. [Bug 3600328]
|
||||
*/
|
||||
|
||||
if (result != TCL_OK) {
|
||||
envPtr->numCommands = savedNumCmds;
|
||||
envPtr->currStackDepth = savedStackDepth;
|
||||
envPtr->codeNext = envPtr->codeStart + savedCodeNext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up if necessary.
|
||||
*/
|
||||
@@ -3001,6 +3130,411 @@ TclCompileEnsemble(
|
||||
Tcl_FreeParse(&synthetic);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* How to compile a subcommand to a _replacing_ invoke of its implementation
|
||||
* command.
|
||||
*/
|
||||
|
||||
static void
|
||||
CompileToInvokedCommand(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr,
|
||||
Tcl_Obj *replacements,
|
||||
Command *cmdPtr,
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
Tcl_Token *tokPtr;
|
||||
Tcl_Obj *objPtr, **words;
|
||||
char *bytes;
|
||||
int length, i, numWords, cmdLit;
|
||||
DefineLineInformation;
|
||||
|
||||
/*
|
||||
* Push the words of the command. Take care; the command words may be
|
||||
* scripts that have backslashes in them, and [info frame 0] can see the
|
||||
* difference. Hence the call to TclContinuationsEnterDerived...
|
||||
*/
|
||||
|
||||
Tcl_ListObjGetElements(NULL, replacements, &numWords, &words);
|
||||
for (i=0,tokPtr=parsePtr->tokenPtr ; i<parsePtr->numWords ; i++) {
|
||||
if (i > 0 && i < numWords+1) {
|
||||
bytes = Tcl_GetStringFromObj(words[i-1], &length);
|
||||
PushLiteral(envPtr, bytes, length);
|
||||
} else if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) {
|
||||
int literal = TclRegisterNewLiteral(envPtr,
|
||||
tokPtr[1].start, tokPtr[1].size);
|
||||
|
||||
if (envPtr->clNext) {
|
||||
TclContinuationsEnterDerived(
|
||||
TclFetchLiteral(envPtr, literal),
|
||||
tokPtr[1].start - envPtr->source,
|
||||
mapPtr->loc[eclIndex].next[i]);
|
||||
}
|
||||
TclEmitPush(literal, envPtr);
|
||||
} else {
|
||||
if (envPtr->clNext) {
|
||||
SetLineInformation(i);
|
||||
}
|
||||
CompileTokens(envPtr, tokPtr, interp);
|
||||
}
|
||||
tokPtr = TokenAfter(tokPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Push the name of the command we're actually dispatching to as part of
|
||||
* the implementation.
|
||||
*/
|
||||
|
||||
objPtr = Tcl_NewObj();
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
cmdLit = TclRegisterNewCmdLiteral(envPtr, bytes, length);
|
||||
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);
|
||||
TclEmitPush(cmdLit, envPtr);
|
||||
TclDecrRefCount(objPtr);
|
||||
|
||||
/*
|
||||
* Do the replacing dispatch.
|
||||
*/
|
||||
|
||||
TclEmitInstInt4(INST_INVOKE_REPLACE, parsePtr->numWords, envPtr);
|
||||
TclEmitInt1(numWords+1, envPtr);
|
||||
TclAdjustStackDepth(-1, envPtr); /* Correction to stack depth calcs. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers that do issuing of instructions for commands that "don't have
|
||||
* compilers" (well, they do; these). They all work by just generating base
|
||||
* code to invoke the command; they're intended for ensemble subcommands so
|
||||
* that the costs of INST_INVOKE_REPLACE can be avoided where we can work out
|
||||
* that they're not needed.
|
||||
*
|
||||
* Note that these are NOT suitable for commands where there's an argument
|
||||
* that is a script, as an [info level] or [info frame] in the inner context
|
||||
* can see the difference.
|
||||
*/
|
||||
|
||||
static int
|
||||
CompileBasicNArgCommand(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
Tcl_Token *tokenPtr;
|
||||
Tcl_Obj *objPtr;
|
||||
char *bytes;
|
||||
int length, i, literal;
|
||||
DefineLineInformation;
|
||||
|
||||
/*
|
||||
* Push the name of the command we're actually dispatching to as part of
|
||||
* the implementation.
|
||||
*/
|
||||
|
||||
objPtr = Tcl_NewObj();
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
literal = TclRegisterNewCmdLiteral(envPtr, bytes, length);
|
||||
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, literal), cmdPtr);
|
||||
TclEmitPush(literal, envPtr);
|
||||
TclDecrRefCount(objPtr);
|
||||
|
||||
/*
|
||||
* Push the words of the command.
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
for (i=1 ; i<parsePtr->numWords ; i++) {
|
||||
if (envPtr->clNext) {
|
||||
SetLineInformation(i);
|
||||
}
|
||||
if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
|
||||
PushLiteral(envPtr, tokenPtr[1].start, tokenPtr[1].size);
|
||||
} else {
|
||||
CompileTokens(envPtr, tokenPtr, interp);
|
||||
}
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the standard dispatch.
|
||||
*/
|
||||
|
||||
if (i <= 255) {
|
||||
TclEmitInstInt1(INST_INVOKE_STK1, i, envPtr);
|
||||
} else {
|
||||
TclEmitInstInt4(INST_INVOKE_STK4, i, envPtr);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic0ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 1) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic1ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic2ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 3) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic3ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 4) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic0Or1ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 1 && parsePtr->numWords != 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic1Or2ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 2 && parsePtr->numWords != 3) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic2Or3ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 3 && parsePtr->numWords != 4) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic0To2ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords < 1 || parsePtr->numWords > 3) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasic1To3ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords < 2 || parsePtr->numWords > 4) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasicMin0ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords < 1) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasicMin1ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords < 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileBasicMin2ArgCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
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. */
|
||||
{
|
||||
/*
|
||||
* Verify that the number of arguments is correct; that's the only case
|
||||
* that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
|
||||
* which is the only code that sees the shenanigans of ensemble dispatch.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords < 3) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
+2
-2
@@ -1402,7 +1402,7 @@ Tcl_VwaitObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
nameString = Tcl_GetString(objv[1]);
|
||||
if (Tcl_TraceVar(interp, nameString,
|
||||
if (Tcl_TraceVar2(interp, nameString, NULL,
|
||||
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||||
VwaitVarProc, &done) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
@@ -1420,7 +1420,7 @@ Tcl_VwaitObjCmd(
|
||||
break;
|
||||
}
|
||||
}
|
||||
Tcl_UntraceVar(interp, nameString,
|
||||
Tcl_UntraceVar2(interp, nameString, NULL,
|
||||
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||||
VwaitVarProc, &done);
|
||||
|
||||
|
||||
+202
-137
@@ -251,13 +251,27 @@ VarHashCreateVar(
|
||||
* otherwise, push objResultPtr. If (result < 0), objResultPtr already
|
||||
* has the correct reference count.
|
||||
*
|
||||
* We use the new compile-time assertions to cheack that nCleanup is constant
|
||||
* We use the new compile-time assertions to check that nCleanup is constant
|
||||
* and within range.
|
||||
*/
|
||||
|
||||
#define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \
|
||||
/* Verify the stack depth, only when no expansion is in progress */
|
||||
|
||||
#if TCL_COMPILE_DEBUG
|
||||
#define CHECK_STACK() \
|
||||
do { \
|
||||
ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, \
|
||||
/*checkStack*/ !(starting || auxObjList)); \
|
||||
starting = 0; \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_STACK()
|
||||
#endif
|
||||
|
||||
#define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \
|
||||
do { \
|
||||
TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2)); \
|
||||
CHECK_STACK(); \
|
||||
if (nCleanup == 0) { \
|
||||
if (resultHandling != 0) { \
|
||||
if ((resultHandling) > 0) { \
|
||||
@@ -286,7 +300,8 @@ VarHashCreateVar(
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \
|
||||
#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \
|
||||
CHECK_STACK(); \
|
||||
do { \
|
||||
pc += (pcAdjustment); \
|
||||
cleanup = (nCleanup); \
|
||||
@@ -685,7 +700,7 @@ static void PrintByteCodeInfo(ByteCode *codePtr);
|
||||
static const char * StringForResultCode(int result);
|
||||
static void ValidatePcAndStackTop(ByteCode *codePtr,
|
||||
const unsigned char *pc, int stackTop,
|
||||
int stackLowerBound, int checkStack);
|
||||
int checkStack);
|
||||
#endif /* TCL_COMPILE_DEBUG */
|
||||
static ByteCode * CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static void DeleteExecStack(ExecStack *esPtr);
|
||||
@@ -1048,6 +1063,7 @@ GrowEvaluationStack(
|
||||
return MEMSTART(markerPtr);
|
||||
}
|
||||
} else {
|
||||
#ifndef PURIFY
|
||||
Tcl_Obj **tmpMarkerPtr = esPtr->tosPtr + 1;
|
||||
int offset = OFFSET(tmpMarkerPtr);
|
||||
|
||||
@@ -1064,6 +1080,7 @@ GrowEvaluationStack(
|
||||
*esPtr->markerPtr = (Tcl_Obj *) markerPtr;
|
||||
return memStart;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1077,6 +1094,7 @@ GrowEvaluationStack(
|
||||
}
|
||||
needed = growth + moveWords + WALLOCALIGN;
|
||||
|
||||
|
||||
/*
|
||||
* Check if there is enough room in the next stack (if there is one, it
|
||||
* should be both empty and the last one!)
|
||||
@@ -1106,10 +1124,15 @@ GrowEvaluationStack(
|
||||
* including the elements to be copied over and the new marker.
|
||||
*/
|
||||
|
||||
#ifndef PURIFY
|
||||
newElems = 2*currElems;
|
||||
while (needed > newElems) {
|
||||
newElems *= 2;
|
||||
}
|
||||
#else
|
||||
newElems = needed;
|
||||
#endif
|
||||
|
||||
newBytes = sizeof(ExecStack) + (newElems-1) * sizeof(Tcl_Obj *);
|
||||
|
||||
oldPtr = esPtr;
|
||||
@@ -1212,7 +1235,7 @@ TclStackFree(
|
||||
Tcl_Obj **markerPtr, *marker;
|
||||
|
||||
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
|
||||
Tcl_Free((char *) freePtr);
|
||||
ckfree((char *) freePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1258,6 +1281,10 @@ TclStackFree(
|
||||
}
|
||||
if (esPtr->prevPtr) {
|
||||
eePtr->execStackPtr = esPtr->prevPtr;
|
||||
#ifdef PURIFY
|
||||
eePtr->execStackPtr->nextPtr = NULL;
|
||||
DeleteExecStack(esPtr);
|
||||
#endif
|
||||
} else {
|
||||
eePtr->execStackPtr = esPtr;
|
||||
}
|
||||
@@ -1272,7 +1299,7 @@ TclStackAlloc(
|
||||
int numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
|
||||
|
||||
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
|
||||
return (void *) Tcl_Alloc(numBytes);
|
||||
return (void *) ckalloc(numBytes);
|
||||
}
|
||||
|
||||
return (void *) StackAllocWords(interp, numWords);
|
||||
@@ -1291,7 +1318,7 @@ TclStackRealloc(
|
||||
int numWords;
|
||||
|
||||
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
|
||||
return (void *) Tcl_Realloc((char *) ptr, numBytes);
|
||||
return (void *) ckrealloc((char *) ptr, numBytes);
|
||||
}
|
||||
|
||||
eePtr = iPtr->execEnvPtr;
|
||||
@@ -1467,7 +1494,7 @@ CompileExprObj(
|
||||
if (objPtr->typePtr == &exprCodeType) {
|
||||
Namespace *namespacePtr = iPtr->varFramePtr->nsPtr;
|
||||
|
||||
codePtr = objPtr->internalRep.otherValuePtr;
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (((Interp *) *codePtr->interpHandle != iPtr)
|
||||
|| (codePtr->compileEpoch != iPtr->compileEpoch)
|
||||
|| (codePtr->nsPtr != namespacePtr)
|
||||
@@ -1507,7 +1534,7 @@ CompileExprObj(
|
||||
TclInitByteCodeObj(objPtr, &compEnv);
|
||||
objPtr->typePtr = &exprCodeType;
|
||||
TclFreeCompileEnv(&compEnv);
|
||||
codePtr = objPtr->internalRep.otherValuePtr;
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (iPtr->varFramePtr->localCachePtr) {
|
||||
codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
|
||||
codePtr->localCachePtr->refCount++;
|
||||
@@ -1579,10 +1606,9 @@ static void
|
||||
FreeExprCodeInternalRep(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
ByteCode *codePtr = objPtr->internalRep.otherValuePtr;
|
||||
ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
objPtr->internalRep.otherValuePtr = NULL;
|
||||
codePtr->refCount--;
|
||||
if (codePtr->refCount <= 0) {
|
||||
TclCleanupByteCode(codePtr);
|
||||
@@ -1640,7 +1666,7 @@ TclCompileObj(
|
||||
* here.
|
||||
*/
|
||||
|
||||
codePtr = objPtr->internalRep.otherValuePtr;
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (((Interp *) *codePtr->interpHandle != iPtr)
|
||||
|| (codePtr->compileEpoch != iPtr->compileEpoch)
|
||||
|| (codePtr->nsPtr != namespacePtr)
|
||||
@@ -1768,7 +1794,7 @@ TclCompileObj(
|
||||
iPtr->invokeWord = word;
|
||||
TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
|
||||
iPtr->invokeCmdFramePtr = NULL;
|
||||
codePtr = objPtr->internalRep.otherValuePtr;
|
||||
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (iPtr->varFramePtr->localCachePtr) {
|
||||
codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
|
||||
codePtr->localCachePtr->refCount++;
|
||||
@@ -2060,7 +2086,8 @@ TEBCresume(
|
||||
Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation
|
||||
* stack. */
|
||||
const unsigned char *pc; /* The current program counter. */
|
||||
|
||||
unsigned char inst; /* The currently running instruction */
|
||||
|
||||
/*
|
||||
* Transfer variables - needed only between opcodes, but not while
|
||||
* executing an instruction.
|
||||
@@ -2085,6 +2112,7 @@ TEBCresume(
|
||||
#endif
|
||||
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
int starting = 1;
|
||||
traceInstructions = (tclTraceExec == 3);
|
||||
#endif
|
||||
|
||||
@@ -2226,24 +2254,6 @@ TEBCresume(
|
||||
}
|
||||
cleanup0:
|
||||
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
/*
|
||||
* Skip the stack depth check if an expansion is in progress.
|
||||
*/
|
||||
|
||||
ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, 0,
|
||||
/*checkStack*/ auxObjList == NULL);
|
||||
if (traceInstructions) {
|
||||
fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH);
|
||||
TclPrintInstruction(codePtr, pc);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif /* TCL_COMPILE_DEBUG */
|
||||
|
||||
#ifdef TCL_COMPILE_STATS
|
||||
iPtr->stats.instructionCount[*pc]++;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for asynchronous handlers [Bug 746722]; we do the check every
|
||||
* ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1).
|
||||
@@ -2275,8 +2285,6 @@ TEBCresume(
|
||||
CACHE_STACK_INFO();
|
||||
}
|
||||
|
||||
TCL_DTRACE_INST_NEXT();
|
||||
|
||||
/*
|
||||
* These two instructions account for 26% of all instructions (according
|
||||
* to measurements on tclbench by Ben Vitale
|
||||
@@ -2286,13 +2294,53 @@ TEBCresume(
|
||||
* reduces total obj size.
|
||||
*/
|
||||
|
||||
if (*pc == INST_LOAD_SCALAR1) {
|
||||
goto instLoadScalar1;
|
||||
} else if (*pc == INST_PUSH1) {
|
||||
goto instPush1Peephole;
|
||||
}
|
||||
inst = *pc;
|
||||
|
||||
peepholeStart:
|
||||
#ifdef TCL_COMPILE_STATS
|
||||
iPtr->stats.instructionCount[*pc]++;
|
||||
#endif
|
||||
|
||||
switch (*pc) {
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
/*
|
||||
* Skip the stack depth check if an expansion is in progress.
|
||||
*/
|
||||
|
||||
CHECK_STACK();
|
||||
if (traceInstructions) {
|
||||
fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH);
|
||||
TclPrintInstruction(codePtr, pc);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif /* TCL_COMPILE_DEBUG */
|
||||
|
||||
TCL_DTRACE_INST_NEXT();
|
||||
|
||||
if (inst == INST_LOAD_SCALAR1) {
|
||||
goto instLoadScalar1;
|
||||
} else if (inst == INST_PUSH1) {
|
||||
PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
|
||||
TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), OBJ_AT_TOS);
|
||||
inst = *(pc += 2);
|
||||
goto peepholeStart;
|
||||
} else if (inst == INST_START_CMD) {
|
||||
/*
|
||||
* Peephole: do not run INST_START_CMD, just skip it
|
||||
*/
|
||||
|
||||
iPtr->cmdCount += TclGetUInt4AtPtr(pc+5);
|
||||
if (checkInterp) {
|
||||
checkInterp = 0;
|
||||
if ((codePtr->compileEpoch != iPtr->compileEpoch)
|
||||
|| (codePtr->nsEpoch != iPtr->varFramePtr->nsPtr->resolverEpoch)) {
|
||||
goto instStartCmdFailed;
|
||||
}
|
||||
}
|
||||
inst = *(pc += 9);
|
||||
goto peepholeStart;
|
||||
}
|
||||
|
||||
switch (inst) {
|
||||
case INST_SYNTAX:
|
||||
case INST_RETURN_IMM: {
|
||||
int code = TclGetInt4AtPtr(pc+1);
|
||||
@@ -2376,7 +2424,6 @@ TEBCresume(
|
||||
|
||||
case INST_TAILCALL: {
|
||||
Tcl_Obj *listPtr, *nsObjPtr;
|
||||
NRE_callback *tailcallPtr;
|
||||
|
||||
opnd = TclGetUInt1AtPtr(pc+1);
|
||||
|
||||
@@ -2410,18 +2457,12 @@ TEBCresume(
|
||||
|
||||
listPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1));
|
||||
nsObjPtr = Tcl_NewStringObj(iPtr->varFramePtr->nsPtr->fullName, -1);
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
Tcl_IncrRefCount(nsObjPtr);
|
||||
TclNRAddCallback(interp, TclNRTailcallEval, listPtr, nsObjPtr,
|
||||
NULL, NULL);
|
||||
TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
|
||||
if (iPtr->varFramePtr->tailcallPtr) {
|
||||
Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr);
|
||||
}
|
||||
iPtr->varFramePtr->tailcallPtr = listPtr;
|
||||
|
||||
/*
|
||||
* Unstitch ourselves and do a [return].
|
||||
*/
|
||||
|
||||
tailcallPtr = TOP_CB(interp);
|
||||
TOP_CB(interp) = tailcallPtr->nextPtr;
|
||||
iPtr->varFramePtr->tailcallPtr = tailcallPtr;
|
||||
result = TCL_RETURN;
|
||||
cleanup = opnd;
|
||||
goto processExceptionReturn;
|
||||
@@ -2449,23 +2490,6 @@ TEBCresume(
|
||||
(void) POP_OBJECT();
|
||||
goto abnormalReturn;
|
||||
|
||||
case INST_PUSH1:
|
||||
instPush1Peephole:
|
||||
PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
|
||||
TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), OBJ_AT_TOS);
|
||||
pc += 2;
|
||||
#if !TCL_COMPILE_DEBUG
|
||||
/*
|
||||
* Runtime peephole optimisation: check if we are pushing again.
|
||||
*/
|
||||
|
||||
if (*pc == INST_PUSH1) {
|
||||
TCL_DTRACE_INST_NEXT();
|
||||
goto instPush1Peephole;
|
||||
}
|
||||
#endif
|
||||
NEXT_INST_F(0, 0, 0);
|
||||
|
||||
case INST_PUSH4:
|
||||
objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)];
|
||||
TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), objResultPtr);
|
||||
@@ -2475,68 +2499,10 @@ TEBCresume(
|
||||
TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS);
|
||||
objPtr = POP_OBJECT();
|
||||
TclDecrRefCount(objPtr);
|
||||
|
||||
/*
|
||||
* Runtime peephole optimisation: an INST_POP is scheduled at the end
|
||||
* of most commands. If the next instruction is an INST_START_CMD,
|
||||
* fall through to it.
|
||||
*/
|
||||
|
||||
pc++;
|
||||
#if !TCL_COMPILE_DEBUG
|
||||
if (*pc == INST_START_CMD) {
|
||||
TCL_DTRACE_INST_NEXT();
|
||||
goto instStartCmdPeephole;
|
||||
}
|
||||
#endif
|
||||
NEXT_INST_F(0, 0, 0);
|
||||
|
||||
case INST_START_CMD:
|
||||
#if !TCL_COMPILE_DEBUG
|
||||
instStartCmdPeephole:
|
||||
#endif
|
||||
/*
|
||||
* Remark that if the interpreter is marked for deletion its
|
||||
* compileEpoch is modified, so that the epoch check also verifies
|
||||
* that the interp is not deleted. If no outside call has been made
|
||||
* since the last check, it is safe to omit the check.
|
||||
*/
|
||||
|
||||
iPtr->cmdCount += TclGetUInt4AtPtr(pc+5);
|
||||
if (!checkInterp) {
|
||||
goto instStartCmdOK;
|
||||
} else if (((codePtr->compileEpoch == iPtr->compileEpoch)
|
||||
&& (codePtr->nsEpoch == iPtr->varFramePtr->nsPtr->resolverEpoch))
|
||||
|| (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
|
||||
checkInterp = 0;
|
||||
instStartCmdOK:
|
||||
NEXT_INST_F(9, 0, 0);
|
||||
} else {
|
||||
const char *bytes;
|
||||
|
||||
length = 0;
|
||||
|
||||
/*
|
||||
* We used to switch to direct eval; for NRE-awareness we now
|
||||
* compile and eval the command so that this evaluation does not
|
||||
* add a new TEBC instance. [Bug 2910748]
|
||||
*/
|
||||
|
||||
if (TclInterpReady(interp) == TCL_ERROR) {
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
codePtr->flags |= TCL_BYTECODE_RECOMPILE;
|
||||
bytes = GetSrcInfoForPc(pc, codePtr, &length, NULL);
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
pc += (opnd-1);
|
||||
PUSH_OBJECT(Tcl_NewStringObj(bytes, length));
|
||||
goto instEvalStk;
|
||||
}
|
||||
NEXT_INST_F(1, 0, 0);
|
||||
|
||||
case INST_NOP:
|
||||
pc += 1;
|
||||
goto cleanup0;
|
||||
NEXT_INST_F(1, 0, 0);
|
||||
|
||||
case INST_DUP:
|
||||
objResultPtr = OBJ_AT_TOS;
|
||||
@@ -2972,6 +2938,70 @@ TEBCresume(
|
||||
Tcl_Panic("TclNRExecuteByteCode: obsolete INST_CALL_FUNC1 found");
|
||||
#endif
|
||||
|
||||
case INST_INVOKE_REPLACE:
|
||||
objc = TclGetUInt4AtPtr(pc+1);
|
||||
opnd = TclGetUInt1AtPtr(pc+5);
|
||||
objPtr = POP_OBJECT();
|
||||
objv = &OBJ_AT_DEPTH(objc-1);
|
||||
cleanup = objc;
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (tclTraceExec >= 2) {
|
||||
int i;
|
||||
|
||||
if (traceInstructions) {
|
||||
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
|
||||
TRACE(("%u => call (implementation %s) ", objc, O2S(objPtr)));
|
||||
} else {
|
||||
fprintf(stdout,
|
||||
"%d: (%u) invoking (using implementation %s) ",
|
||||
iPtr->numLevels, (unsigned)(pc - codePtr->codeStart),
|
||||
O2S(objPtr));
|
||||
}
|
||||
for (i = 0; i < objc; i++) {
|
||||
if (i < opnd) {
|
||||
fprintf(stdout, "<");
|
||||
TclPrintObject(stdout, objv[i], 15);
|
||||
fprintf(stdout, ">");
|
||||
} else {
|
||||
TclPrintObject(stdout, objv[i], 15);
|
||||
}
|
||||
fprintf(stdout, " ");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
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) {
|
||||
TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc,
|
||||
codePtr, bcFramePtr, pc - codePtr->codeStart);
|
||||
}
|
||||
iPtr->ensembleRewrite.sourceObjs = objv;
|
||||
iPtr->ensembleRewrite.numRemovedObjs = opnd;
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 1;
|
||||
DECACHE_STACK_INFO();
|
||||
pc += 6;
|
||||
TEBC_YIELD();
|
||||
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL);
|
||||
TclSkipTailcall(interp);
|
||||
return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE, NULL, INT_MIN);
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------
|
||||
* Start of INST_LOAD instructions.
|
||||
@@ -3433,8 +3463,8 @@ TEBCresume(
|
||||
varPtr = TclObjLookupVarEx(interp, objPtr, part2Ptr,
|
||||
TCL_LEAVE_ERR_MSG, "read", 1, 1, &arrayPtr);
|
||||
if (!varPtr) {
|
||||
Tcl_AddObjErrorInfo(interp,
|
||||
"\n (reading value of variable to increment)", -1);
|
||||
Tcl_AddErrorInfo(interp,
|
||||
"\n (reading value of variable to increment)");
|
||||
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
|
||||
Tcl_DecrRefCount(incrPtr);
|
||||
goto gotError;
|
||||
@@ -7022,6 +7052,42 @@ TEBCresume(
|
||||
TclStackFree(interp, TD); /* free my stack */
|
||||
|
||||
return result;
|
||||
|
||||
/*
|
||||
* INST_START_CMD failure case removed where it doesn't bother that much
|
||||
*
|
||||
* Remark that if the interpreter is marked for deletion its
|
||||
* compileEpoch is modified, so that the epoch check also verifies
|
||||
* that the interp is not deleted. If no outside call has been made
|
||||
* since the last check, it is safe to omit the check.
|
||||
|
||||
* case INST_START_CMD:
|
||||
*/
|
||||
|
||||
instStartCmdFailed:
|
||||
{
|
||||
const char *bytes;
|
||||
|
||||
checkInterp = 1;
|
||||
length = 0;
|
||||
|
||||
/*
|
||||
* We used to switch to direct eval; for NRE-awareness we now
|
||||
* compile and eval the command so that this evaluation does not
|
||||
* add a new TEBC instance. [Bug 2910748]
|
||||
*/
|
||||
|
||||
if (TclInterpReady(interp) == TCL_ERROR) {
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
codePtr->flags |= TCL_BYTECODE_RECOMPILE;
|
||||
bytes = GetSrcInfoForPc(pc, codePtr, &length, NULL);
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
pc += (opnd-1);
|
||||
PUSH_OBJECT(Tcl_NewStringObj(bytes, length));
|
||||
goto instEvalStk;
|
||||
}
|
||||
}
|
||||
|
||||
#undef codePtr
|
||||
@@ -8485,11 +8551,10 @@ ValidatePcAndStackTop(
|
||||
int stackTop, /* Current stack top. Must be between
|
||||
* stackLowerBound and stackUpperBound
|
||||
* (inclusive). */
|
||||
int stackLowerBound, /* Smallest legal value for stackTop. */
|
||||
int checkStack) /* 0 if the stack depth check should be
|
||||
* skipped. */
|
||||
{
|
||||
int stackUpperBound = stackLowerBound + codePtr->maxStackDepth;
|
||||
int stackUpperBound = codePtr->maxStackDepth;
|
||||
/* Greatest legal value for stackTop. */
|
||||
unsigned relativePc = (unsigned) (pc - codePtr->codeStart);
|
||||
unsigned long codeStart = (unsigned long) codePtr->codeStart;
|
||||
@@ -8507,13 +8572,13 @@ ValidatePcAndStackTop(
|
||||
(unsigned) opCode, relativePc);
|
||||
Tcl_Panic("TclNRExecuteByteCode execution failure: bad opcode");
|
||||
}
|
||||
if (checkStack &&
|
||||
((stackTop < stackLowerBound) || (stackTop > stackUpperBound))) {
|
||||
if (checkStack &&
|
||||
((stackTop < 0) || (stackTop > stackUpperBound))) {
|
||||
int numChars;
|
||||
const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars, NULL);
|
||||
|
||||
fprintf(stderr, "\nBad stack top %d at pc %u in TclNRExecuteByteCode (min %i, max %i)",
|
||||
stackTop, relativePc, stackLowerBound, stackUpperBound);
|
||||
fprintf(stderr, "\nBad stack top %d at pc %u in TclNRExecuteByteCode (min 0, max %i)",
|
||||
stackTop, relativePc, stackUpperBound);
|
||||
if (cmd != NULL) {
|
||||
Tcl_Obj *message;
|
||||
|
||||
|
||||
+7
-10
@@ -734,17 +734,14 @@ CopyRenameOneFile(
|
||||
*/
|
||||
|
||||
errfile = target;
|
||||
|
||||
/*
|
||||
* We now need to reset the result, because the above call, if it
|
||||
* failed, may have put an error message in place. (Ideally we
|
||||
* would prefer not to pass an interpreter in above, but the
|
||||
* channel IO code used by TclCrossFilesystemCopy currently
|
||||
* requires one).
|
||||
*/
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
/*
|
||||
* We now need to reset the result, because the above call,
|
||||
* may have left set it. (Ideally we would prefer not to pass
|
||||
* an interpreter in above, but the channel IO code used by
|
||||
* TclCrossFilesystemCopy currently requires one)
|
||||
*/
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
if ((copyFlag == 0) && (result == TCL_OK)) {
|
||||
if (S_ISDIR(sourceStatBuf.st_mode)) {
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ Tcl_GetBoolean(
|
||||
obj.length = strlen(src);
|
||||
obj.typePtr = NULL;
|
||||
|
||||
code = Tcl_ConvertToType(interp, &obj, &tclBooleanType);
|
||||
code = TclSetBooleanFromAny(interp, &obj);
|
||||
if (obj.refCount > 1) {
|
||||
Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
|
||||
}
|
||||
|
||||
+119
-3
@@ -15,6 +15,108 @@
|
||||
#include "tclIO.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* For each channel handler registered in a call to Tcl_CreateChannelHandler,
|
||||
* there is one record of the following type. All of records for a specific
|
||||
* channel are chained together in a singly linked list which is stored in
|
||||
* the channel structure.
|
||||
*/
|
||||
|
||||
typedef struct ChannelHandler {
|
||||
Channel *chanPtr; /* The channel structure for this channel. */
|
||||
int mask; /* Mask of desired events. */
|
||||
Tcl_ChannelProc *proc; /* Procedure to call in the type of
|
||||
* Tcl_CreateChannelHandler. */
|
||||
ClientData clientData; /* Argument to pass to procedure. */
|
||||
struct ChannelHandler *nextPtr;
|
||||
/* Next one in list of registered handlers. */
|
||||
} ChannelHandler;
|
||||
|
||||
/*
|
||||
* This structure keeps track of the current ChannelHandler being invoked in
|
||||
* the current invocation of ChannelHandlerEventProc. There is a potential
|
||||
* problem if a ChannelHandler is deleted while it is the current one, since
|
||||
* ChannelHandlerEventProc needs to look at the nextPtr field. To handle this
|
||||
* problem, structures of the type below indicate the next handler to be
|
||||
* processed for any (recursively nested) dispatches in progress. The
|
||||
* nextHandlerPtr field is updated if the handler being pointed to is deleted.
|
||||
* The nextPtr field is used to chain together all recursive invocations, so
|
||||
* that Tcl_DeleteChannelHandler can find all the recursively nested
|
||||
* invocations of ChannelHandlerEventProc and compare the handler being
|
||||
* deleted against the NEXT handler to be invoked in that invocation; when it
|
||||
* finds such a situation, Tcl_DeleteChannelHandler updates the nextHandlerPtr
|
||||
* field of the structure to the next handler.
|
||||
*/
|
||||
|
||||
typedef struct NextChannelHandler {
|
||||
ChannelHandler *nextHandlerPtr; /* The next handler to be invoked in
|
||||
* this invocation. */
|
||||
struct NextChannelHandler *nestedHandlerPtr;
|
||||
/* Next nested invocation of
|
||||
* ChannelHandlerEventProc. */
|
||||
} NextChannelHandler;
|
||||
|
||||
/*
|
||||
* The following structure describes the event that is added to the Tcl
|
||||
* event queue by the channel handler check procedure.
|
||||
*/
|
||||
|
||||
typedef struct ChannelHandlerEvent {
|
||||
Tcl_Event header; /* Standard header for all events. */
|
||||
Channel *chanPtr; /* The channel that is ready. */
|
||||
int readyMask; /* Events that have occurred. */
|
||||
} ChannelHandlerEvent;
|
||||
|
||||
/*
|
||||
* The following structure is used by Tcl_GetsObj() to encapsulates the
|
||||
* state for a "gets" operation.
|
||||
*/
|
||||
|
||||
typedef struct GetsState {
|
||||
Tcl_Obj *objPtr; /* The object to which UTF-8 characters
|
||||
* will be appended. */
|
||||
char **dstPtr; /* Pointer into objPtr's string rep where
|
||||
* next character should be stored. */
|
||||
Tcl_Encoding encoding; /* The encoding to use to convert raw bytes
|
||||
* to UTF-8. */
|
||||
ChannelBuffer *bufPtr; /* The current buffer of raw bytes being
|
||||
* emptied. */
|
||||
Tcl_EncodingState state; /* The encoding state just before the last
|
||||
* external to UTF-8 conversion in
|
||||
* FilterInputBytes(). */
|
||||
int rawRead; /* The number of bytes removed from bufPtr
|
||||
* in the last call to FilterInputBytes(). */
|
||||
int bytesWrote; /* The number of bytes of UTF-8 data
|
||||
* appended to objPtr during the last call to
|
||||
* FilterInputBytes(). */
|
||||
int charsWrote; /* The corresponding number of UTF-8
|
||||
* characters appended to objPtr during the
|
||||
* last call to FilterInputBytes(). */
|
||||
int totalChars; /* The total number of UTF-8 characters
|
||||
* appended to objPtr so far, just before the
|
||||
* last call to FilterInputBytes(). */
|
||||
} GetsState;
|
||||
|
||||
/*
|
||||
* The following structure encapsulates the state for a background channel
|
||||
* copy. Note that the data buffer for the copy will be appended to this
|
||||
* structure.
|
||||
*/
|
||||
|
||||
typedef struct CopyState {
|
||||
struct Channel *readPtr; /* Pointer to input channel. */
|
||||
struct Channel *writePtr; /* Pointer to output channel. */
|
||||
int readFlags; /* Original read channel flags. */
|
||||
int writeFlags; /* Original write channel flags. */
|
||||
Tcl_WideInt toRead; /* Number of bytes to copy, or -1. */
|
||||
Tcl_WideInt total; /* Total bytes transferred (written). */
|
||||
Tcl_Interp *interp; /* Interp that started the copy. */
|
||||
Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */
|
||||
int bufSize; /* Size of appended buffer. */
|
||||
char buffer[1]; /* Copy buffer, this must be the last
|
||||
* field. */
|
||||
} CopyState;
|
||||
|
||||
/*
|
||||
* All static variables used in this file are collected into a single instance
|
||||
* of the following structure. For multi-threaded implementations, there is
|
||||
@@ -43,6 +145,18 @@ typedef struct ThreadSpecificData {
|
||||
|
||||
static Tcl_ThreadDataKey dataKey;
|
||||
|
||||
/*
|
||||
* Structure to record a close callback. One such record exists for
|
||||
* each close callback registered for a channel.
|
||||
*/
|
||||
|
||||
typedef struct CloseCallback {
|
||||
Tcl_CloseProc *proc; /* The procedure to call. */
|
||||
ClientData clientData; /* Arbitrary one-word data to pass
|
||||
* to the callback. */
|
||||
struct CloseCallback *nextPtr; /* For chaining close callbacks. */
|
||||
} CloseCallback;
|
||||
|
||||
/*
|
||||
* Static functions in this file:
|
||||
*/
|
||||
@@ -221,9 +335,9 @@ static const Tcl_ObjType tclChannelType = {
|
||||
};
|
||||
|
||||
#define GET_CHANNELSTATE(objPtr) \
|
||||
((ChannelState *) (objPtr)->internalRep.otherValuePtr)
|
||||
((ChannelState *) (objPtr)->internalRep.twoPtrValue.ptr1)
|
||||
#define SET_CHANNELSTATE(objPtr, storePtr) \
|
||||
((objPtr)->internalRep.otherValuePtr = (void *) (storePtr))
|
||||
((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (storePtr))
|
||||
#define GET_CHANNELINTERP(objPtr) \
|
||||
((Interp *) (objPtr)->internalRep.twoPtrValue.ptr2)
|
||||
#define SET_CHANNELINTERP(objPtr, storePtr) \
|
||||
@@ -695,6 +809,8 @@ Tcl_DeleteCloseHandler(
|
||||
if ((cbPtr->proc == proc) && (cbPtr->clientData == clientData)) {
|
||||
if (cbPrevPtr == NULL) {
|
||||
statePtr->closeCbPtr = cbPtr->nextPtr;
|
||||
} else {
|
||||
cbPrevPtr->nextPtr = cbPtr->nextPtr;
|
||||
}
|
||||
ckfree(cbPtr);
|
||||
break;
|
||||
@@ -2472,7 +2588,7 @@ FlushChannel(
|
||||
* it's a tty channel (dup'ed underneath)
|
||||
*/
|
||||
|
||||
if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
|
||||
if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED) && !TclInExit()) {
|
||||
SetFlag(statePtr, BG_FLUSH_SCHEDULED);
|
||||
UpdateInterest(chanPtr);
|
||||
}
|
||||
|
||||
+6
-119
@@ -29,26 +29,6 @@
|
||||
#error one of EWOULDBLOCK or EAGAIN must be defined
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following structure encapsulates the state for a background channel
|
||||
* copy. Note that the data buffer for the copy will be appended to this
|
||||
* structure.
|
||||
*/
|
||||
|
||||
typedef struct CopyState {
|
||||
struct Channel *readPtr; /* Pointer to input channel. */
|
||||
struct Channel *writePtr; /* Pointer to output channel. */
|
||||
int readFlags; /* Original read channel flags. */
|
||||
int writeFlags; /* Original write channel flags. */
|
||||
Tcl_WideInt toRead; /* Number of bytes to copy, or -1. */
|
||||
Tcl_WideInt total; /* Total bytes transferred (written). */
|
||||
Tcl_Interp *interp; /* Interp that started the copy. */
|
||||
Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */
|
||||
int bufSize; /* Size of appended buffer. */
|
||||
char buffer[1]; /* Copy buffer, this must be the last
|
||||
* field. */
|
||||
} CopyState;
|
||||
|
||||
/*
|
||||
* struct ChannelBuffer:
|
||||
*
|
||||
@@ -85,19 +65,6 @@ typedef struct ChannelBuffer {
|
||||
|
||||
#define CHANNELBUFFER_DEFAULT_SIZE (1024 * 4)
|
||||
|
||||
/*
|
||||
* Structure to record a close callback. One such record exists for each close
|
||||
* callback registered for a channel.
|
||||
*/
|
||||
|
||||
typedef struct CloseCallback {
|
||||
Tcl_CloseProc *proc; /* The procedure to call. */
|
||||
ClientData clientData; /* Arbitrary one-word data to pass to the
|
||||
* callback. */
|
||||
struct CloseCallback *nextPtr;
|
||||
/* For chaining close callbacks. */
|
||||
} CloseCallback;
|
||||
|
||||
/*
|
||||
* The following structure describes the information saved from a call to
|
||||
* "fileevent". This is used later when the event being waited for to invoke
|
||||
@@ -195,7 +162,8 @@ typedef struct ChannelState {
|
||||
* value is the POSIX error code. */
|
||||
int refCount; /* How many interpreters hold references to
|
||||
* this IO channel? */
|
||||
CloseCallback *closeCbPtr; /* Callbacks registered to be called when the
|
||||
struct CloseCallback *closeCbPtr;
|
||||
/* Callbacks registered to be called when the
|
||||
* channel is closed. */
|
||||
char *outputStage; /* Temporary staging buffer used when
|
||||
* translating EOL before converting from
|
||||
@@ -217,8 +185,10 @@ typedef struct ChannelState {
|
||||
* handlers ("fileevent") on this channel. */
|
||||
int bufSize; /* What size buffers to allocate? */
|
||||
Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */
|
||||
CopyState *csPtrR; /* State of background copy for which channel is input, or NULL. */
|
||||
CopyState *csPtrW; /* State of background copy for which channel is output, or NULL. */
|
||||
struct CopyState *csPtrR; /* State of background copy for which channel
|
||||
* is input, or NULL. */
|
||||
struct CopyState *csPtrW; /* State of background copy for which channel
|
||||
* is output, or NULL. */
|
||||
Channel *topChanPtr; /* Refers to topmost channel in a stack. Never
|
||||
* NULL. */
|
||||
Channel *bottomChanPtr; /* Refers to bottommost channel in a stack.
|
||||
@@ -341,89 +311,6 @@ typedef struct ChannelState {
|
||||
* No further Tcl-level write IO on
|
||||
* the channel is allowed. */
|
||||
|
||||
/*
|
||||
* For each channel handler registered in a call to Tcl_CreateChannelHandler,
|
||||
* there is one record of the following type. All of records for a specific
|
||||
* channel are chained together in a singly linked list which is stored in the
|
||||
* channel structure.
|
||||
*/
|
||||
|
||||
typedef struct ChannelHandler {
|
||||
Channel *chanPtr; /* The channel structure for this channel. */
|
||||
int mask; /* Mask of desired events. */
|
||||
Tcl_ChannelProc *proc; /* Procedure to call in the type of
|
||||
* Tcl_CreateChannelHandler. */
|
||||
ClientData clientData; /* Argument to pass to procedure. */
|
||||
struct ChannelHandler *nextPtr;
|
||||
/* Next one in list of registered handlers. */
|
||||
} ChannelHandler;
|
||||
|
||||
/*
|
||||
* This structure keeps track of the current ChannelHandler being invoked in
|
||||
* the current invocation of ChannelHandlerEventProc. There is a potential
|
||||
* problem if a ChannelHandler is deleted while it is the current one, since
|
||||
* ChannelHandlerEventProc needs to look at the nextPtr field. To handle this
|
||||
* problem, structures of the type below indicate the next handler to be
|
||||
* processed for any (recursively nested) dispatches in progress. The
|
||||
* nextHandlerPtr field is updated if the handler being pointed to is deleted.
|
||||
* The nextPtr field is used to chain together all recursive invocations, so
|
||||
* that Tcl_DeleteChannelHandler can find all the recursively nested
|
||||
* invocations of ChannelHandlerEventProc and compare the handler being
|
||||
* deleted against the NEXT handler to be invoked in that invocation; when it
|
||||
* finds such a situation, Tcl_DeleteChannelHandler updates the nextHandlerPtr
|
||||
* field of the structure to the next handler.
|
||||
*/
|
||||
|
||||
typedef struct NextChannelHandler {
|
||||
ChannelHandler *nextHandlerPtr;
|
||||
/* The next handler to be invoked in this
|
||||
* invocation. */
|
||||
struct NextChannelHandler *nestedHandlerPtr;
|
||||
/* Next nested invocation of
|
||||
* ChannelHandlerEventProc. */
|
||||
} NextChannelHandler;
|
||||
|
||||
/*
|
||||
* The following structure describes the event that is added to the Tcl event
|
||||
* queue by the channel handler check procedure.
|
||||
*/
|
||||
|
||||
typedef struct ChannelHandlerEvent {
|
||||
Tcl_Event header; /* Standard header for all events. */
|
||||
Channel *chanPtr; /* The channel that is ready. */
|
||||
int readyMask; /* Events that have occurred. */
|
||||
} ChannelHandlerEvent;
|
||||
|
||||
/*
|
||||
* The following structure is used by Tcl_GetsObj() to encapsulates the state
|
||||
* for a "gets" operation.
|
||||
*/
|
||||
|
||||
typedef struct GetsState {
|
||||
Tcl_Obj *objPtr; /* The object to which UTF-8 characters will
|
||||
* be appended. */
|
||||
char **dstPtr; /* Pointer into objPtr's string rep where next
|
||||
* character should be stored. */
|
||||
Tcl_Encoding encoding; /* The encoding to use to convert raw bytes to
|
||||
* UTF-8. */
|
||||
ChannelBuffer *bufPtr; /* The current buffer of raw bytes being
|
||||
* emptied. */
|
||||
Tcl_EncodingState state; /* The encoding state just before the last
|
||||
* external to UTF-8 conversion in
|
||||
* FilterInputBytes(). */
|
||||
int rawRead; /* The number of bytes removed from bufPtr in
|
||||
* the last call to FilterInputBytes(). */
|
||||
int bytesWrote; /* The number of bytes of UTF-8 data appended
|
||||
* to objPtr during the last call to
|
||||
* FilterInputBytes(). */
|
||||
int charsWrote; /* The corresponding number of UTF-8
|
||||
* characters appended to objPtr during the
|
||||
* last call to FilterInputBytes(). */
|
||||
int totalChars; /* The total number of UTF-8 characters
|
||||
* appended to objPtr so far, just before the
|
||||
* last call to FilterInputBytes(). */
|
||||
} GetsState;
|
||||
|
||||
/*
|
||||
* The length of time to wait between synthetic timer events. Must be zero or
|
||||
* bad things tend to happen.
|
||||
|
||||
+19
-19
@@ -1952,25 +1952,25 @@ TclInitChanCmd(
|
||||
* function at the moment.
|
||||
*/
|
||||
static const EnsembleImplMap initMap[] = {
|
||||
{"blocked", Tcl_FblockedObjCmd, NULL, NULL, NULL, 0},
|
||||
{"close", Tcl_CloseObjCmd, NULL, NULL, NULL, 0},
|
||||
{"copy", Tcl_FcopyObjCmd, NULL, NULL, NULL, 0},
|
||||
{"create", TclChanCreateObjCmd, NULL, NULL, NULL, 0}, /* TIP #219 */
|
||||
{"eof", Tcl_EofObjCmd, NULL, NULL, NULL, 0},
|
||||
{"event", Tcl_FileEventObjCmd, NULL, NULL, NULL, 0},
|
||||
{"flush", Tcl_FlushObjCmd, NULL, NULL, NULL, 0},
|
||||
{"gets", Tcl_GetsObjCmd, NULL, NULL, NULL, 0},
|
||||
{"names", TclChannelNamesCmd, NULL, NULL, NULL, 0},
|
||||
{"pending", ChanPendingObjCmd, NULL, NULL, NULL, 0}, /* TIP #287 */
|
||||
{"pop", TclChanPopObjCmd, NULL, NULL, NULL, 0}, /* TIP #230 */
|
||||
{"postevent", TclChanPostEventObjCmd, NULL, NULL, NULL, 0}, /* TIP #219 */
|
||||
{"push", TclChanPushObjCmd, NULL, NULL, NULL, 0}, /* TIP #230 */
|
||||
{"puts", Tcl_PutsObjCmd, NULL, NULL, NULL, 0},
|
||||
{"read", Tcl_ReadObjCmd, NULL, NULL, NULL, 0},
|
||||
{"seek", Tcl_SeekObjCmd, NULL, NULL, NULL, 0},
|
||||
{"pipe", ChanPipeObjCmd, NULL, NULL, NULL, 0}, /* TIP #304 */
|
||||
{"tell", Tcl_TellObjCmd, NULL, NULL, NULL, 0},
|
||||
{"truncate", ChanTruncateObjCmd, NULL, NULL, NULL, 0}, /* TIP #208 */
|
||||
{"blocked", Tcl_FblockedObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"close", Tcl_CloseObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"copy", Tcl_FcopyObjCmd, NULL, NULL, NULL, 0},
|
||||
{"create", TclChanCreateObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */
|
||||
{"eof", Tcl_EofObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"event", Tcl_FileEventObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0},
|
||||
{"flush", Tcl_FlushObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"gets", Tcl_GetsObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"names", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"pending", ChanPendingObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #287 */
|
||||
{"pipe", ChanPipeObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, /* TIP #304 */
|
||||
{"pop", TclChanPopObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, /* TIP #230 */
|
||||
{"postevent", TclChanPostEventObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */
|
||||
{"push", TclChanPushObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #230 */
|
||||
{"puts", Tcl_PutsObjCmd, NULL, NULL, NULL, 0},
|
||||
{"read", Tcl_ReadObjCmd, NULL, NULL, NULL, 0},
|
||||
{"seek", Tcl_SeekObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0},
|
||||
{"tell", Tcl_TellObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"truncate", ChanTruncateObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, /* TIP #208 */
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
static const char *const extras[] = {
|
||||
|
||||
@@ -2942,7 +2942,7 @@ ResultClear(
|
||||
return;
|
||||
}
|
||||
|
||||
Tcl_Free((char *) rPtr->buf);
|
||||
ckfree((char *) rPtr->buf);
|
||||
rPtr->buf = NULL;
|
||||
rPtr->allocated = 0;
|
||||
}
|
||||
@@ -2977,10 +2977,10 @@ ResultAdd(
|
||||
|
||||
if (rPtr->allocated == 0) {
|
||||
rPtr->allocated = toWrite + RB_INCREMENT;
|
||||
rPtr->buf = UCHARP(Tcl_Alloc(rPtr->allocated));
|
||||
rPtr->buf = UCHARP(ckalloc(rPtr->allocated));
|
||||
} else {
|
||||
rPtr->allocated += toWrite + RB_INCREMENT;
|
||||
rPtr->buf = UCHARP(Tcl_Realloc((char *) rPtr->buf,
|
||||
rPtr->buf = UCHARP(ckrealloc((char *) rPtr->buf,
|
||||
rPtr->allocated));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_SYS_STAT_H) && !defined _WIN32
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#include "tclInt.h"
|
||||
#ifdef __WIN32__
|
||||
# include "tclWinInt.h"
|
||||
|
||||
+26
-25
@@ -53,7 +53,7 @@ static const Tcl_ObjType indexType = {
|
||||
|
||||
/*
|
||||
* The definition of the internal representation of the "index" object; The
|
||||
* internalRep.otherValuePtr field of an object of "index" type will be a
|
||||
* internalRep.twoPtrValue.ptr1 field of an object of "index" type will be a
|
||||
* pointer to one of these structures.
|
||||
*
|
||||
* Keep this structure declaration in sync with tclTestObj.c
|
||||
@@ -69,12 +69,12 @@ typedef struct {
|
||||
* The following macros greatly simplify moving through a table...
|
||||
*/
|
||||
|
||||
#define STRING_AT(table, offset, index) \
|
||||
(*((const char *const *)(((char *)(table)) + ((offset) * (index)))))
|
||||
#define STRING_AT(table, offset) \
|
||||
(*((const char *const *)(((char *)(table)) + (offset))))
|
||||
#define NEXT_ENTRY(table, offset) \
|
||||
(&(STRING_AT(table, offset, 1)))
|
||||
(&(STRING_AT(table, offset)))
|
||||
#define EXPAND_OF(indexRep) \
|
||||
STRING_AT((indexRep)->tablePtr, (indexRep)->offset, (indexRep)->index)
|
||||
STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -101,6 +101,7 @@ typedef struct {
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_GetIndexFromObj
|
||||
int
|
||||
Tcl_GetIndexFromObj(
|
||||
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
|
||||
@@ -121,7 +122,7 @@ Tcl_GetIndexFromObj(
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &indexType) {
|
||||
IndexRep *indexRep = objPtr->internalRep.otherValuePtr;
|
||||
IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
/*
|
||||
* Here's hoping we don't get hit by unfortunate packing constraints
|
||||
@@ -238,7 +239,7 @@ GetIndexFromObjList(
|
||||
* a proper match, then TCL_ERROR is returned and an error message is
|
||||
* left in interp's result (unless interp is NULL). The msg argument is
|
||||
* used in the error message; for example, if msg has the value "option"
|
||||
* then the error message will say something flag 'bad option "foo": must
|
||||
* then the error message will say something like 'bad option "foo": must
|
||||
* be ...'
|
||||
*
|
||||
* Side effects:
|
||||
@@ -270,12 +271,16 @@ Tcl_GetIndexFromObjStruct(
|
||||
Tcl_Obj *resultPtr;
|
||||
IndexRep *indexRep;
|
||||
|
||||
/* Protect against invalid values, like -1 or 0. */
|
||||
if (offset < (int)sizeof(char *)) {
|
||||
offset = (int)sizeof(char *);
|
||||
}
|
||||
/*
|
||||
* See if there is a valid cached result from a previous lookup.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &indexType) {
|
||||
indexRep = objPtr->internalRep.otherValuePtr;
|
||||
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
|
||||
*indexPtr = indexRep->index;
|
||||
return TCL_OK;
|
||||
@@ -302,10 +307,6 @@ Tcl_GetIndexFromObjStruct(
|
||||
entryPtr = NEXT_ENTRY(entryPtr, offset), idx++) {
|
||||
for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) {
|
||||
if (*p1 == '\0') {
|
||||
if (p1 == key) {
|
||||
/* empty keys never match */
|
||||
continue;
|
||||
}
|
||||
index = idx;
|
||||
goto done;
|
||||
}
|
||||
@@ -340,11 +341,11 @@ Tcl_GetIndexFromObjStruct(
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &indexType) {
|
||||
indexRep = objPtr->internalRep.otherValuePtr;
|
||||
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
indexRep = ckalloc(sizeof(IndexRep));
|
||||
objPtr->internalRep.otherValuePtr = indexRep;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = indexRep;
|
||||
objPtr->typePtr = &indexType;
|
||||
}
|
||||
indexRep->tablePtr = (void *) tablePtr;
|
||||
@@ -447,7 +448,7 @@ static void
|
||||
UpdateStringOfIndex(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
IndexRep *indexRep = objPtr->internalRep.otherValuePtr;
|
||||
IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
register char *buf;
|
||||
register unsigned len;
|
||||
register const char *indexStr = EXPAND_OF(indexRep);
|
||||
@@ -482,11 +483,11 @@ DupIndex(
|
||||
Tcl_Obj *srcPtr,
|
||||
Tcl_Obj *dupPtr)
|
||||
{
|
||||
IndexRep *srcIndexRep = srcPtr->internalRep.otherValuePtr;
|
||||
IndexRep *srcIndexRep = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
IndexRep *dupIndexRep = ckalloc(sizeof(IndexRep));
|
||||
|
||||
memcpy(dupIndexRep, srcIndexRep, sizeof(IndexRep));
|
||||
dupPtr->internalRep.otherValuePtr = dupIndexRep;
|
||||
dupPtr->internalRep.twoPtrValue.ptr1 = dupIndexRep;
|
||||
dupPtr->typePtr = &indexType;
|
||||
}
|
||||
|
||||
@@ -511,7 +512,7 @@ static void
|
||||
FreeIndex(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
ckfree(objPtr->internalRep.otherValuePtr);
|
||||
ckfree(objPtr->internalRep.twoPtrValue.ptr1);
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
@@ -537,9 +538,9 @@ TclInitPrefixCmd(
|
||||
Tcl_Interp *interp) /* Current interpreter. */
|
||||
{
|
||||
static const EnsembleImplMap prefixImplMap[] = {
|
||||
{"all", PrefixAllObjCmd, NULL, NULL, NULL, 0},
|
||||
{"longest", PrefixLongestObjCmd, NULL, NULL, NULL, 0},
|
||||
{"match", PrefixMatchObjCmd, NULL, NULL, NULL, 0},
|
||||
{"all", PrefixAllObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"longest", PrefixLongestObjCmd,TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"match", PrefixMatchObjCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
Tcl_Command prefixCmd;
|
||||
@@ -952,13 +953,13 @@ Tcl_WrongNumArgs(
|
||||
|
||||
if (origObjv[i]->typePtr == &indexType) {
|
||||
register IndexRep *indexRep =
|
||||
origObjv[i]->internalRep.otherValuePtr;
|
||||
origObjv[i]->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
elementStr = EXPAND_OF(indexRep);
|
||||
elemLen = strlen(elementStr);
|
||||
} else if (origObjv[i]->typePtr == &tclEnsembleCmdType) {
|
||||
register EnsembleCmdRep *ecrPtr =
|
||||
origObjv[i]->internalRep.otherValuePtr;
|
||||
origObjv[i]->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
elementStr = ecrPtr->fullSubcmdName;
|
||||
elemLen = strlen(elementStr);
|
||||
@@ -1007,12 +1008,12 @@ Tcl_WrongNumArgs(
|
||||
*/
|
||||
|
||||
if (objv[i]->typePtr == &indexType) {
|
||||
register IndexRep *indexRep = objv[i]->internalRep.otherValuePtr;
|
||||
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.otherValuePtr;
|
||||
objv[i]->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
Tcl_AppendStringsToObj(objPtr, ecrPtr->fullSubcmdName, NULL);
|
||||
} else {
|
||||
|
||||
+35
-36
@@ -626,14 +626,14 @@ declare 156 {
|
||||
declare 157 {
|
||||
Var *TclVarTraceExists(Tcl_Interp *interp, const char *varName)
|
||||
}
|
||||
# REMOVED - use public Tcl_SetStartupScript()
|
||||
#declare 158 {
|
||||
# void TclSetStartupScriptFileName(const char *filename)
|
||||
#}
|
||||
# REMOVED - use public Tcl_GetStartupScript()
|
||||
#declare 159 {
|
||||
# const char *TclGetStartupScriptFileName(void)
|
||||
#}
|
||||
# REMOVED (except from stub table) - use public Tcl_SetStartupScript()
|
||||
declare 158 {
|
||||
void TclSetStartupScriptFileName(const char *filename)
|
||||
}
|
||||
# REMOVED (except from stub table) - use public Tcl_GetStartupScript()
|
||||
declare 159 {
|
||||
const char *TclGetStartupScriptFileName(void)
|
||||
}
|
||||
#declare 160 {
|
||||
# int TclpMatchFilesTypes(Tcl_Interp *interp, char *separators,
|
||||
# Tcl_DString *dirPtr, char *pattern, char *tail,
|
||||
@@ -678,14 +678,14 @@ declare 166 {
|
||||
}
|
||||
|
||||
# VFS-aware versions of Tcl*StartupScriptFileName (158 and 159 above)
|
||||
# REMOVED - use public Tcl_SetStartupScript()
|
||||
#declare 167 {
|
||||
# void TclSetStartupScriptPath(Tcl_Obj *pathPtr)
|
||||
#}
|
||||
# REMOVED - use public Tcl_GetStartupScript()
|
||||
#declare 168 {
|
||||
# Tcl_Obj *TclGetStartupScriptPath(void)
|
||||
#}
|
||||
# REMOVED (except from stub table) - use public Tcl_SetStartupScript()
|
||||
declare 167 {
|
||||
void TclSetStartupScriptPath(Tcl_Obj *pathPtr)
|
||||
}
|
||||
# REMOVED (except from stub table) - use public Tcl_GetStartupScript()
|
||||
declare 168 {
|
||||
Tcl_Obj *TclGetStartupScriptPath(void)
|
||||
}
|
||||
# variant of Tcl_UtfNCmp that takes n as bytes, not chars
|
||||
declare 169 {
|
||||
int TclpUtfNcmp2(const char *s1, const char *s2, unsigned long n)
|
||||
@@ -731,13 +731,13 @@ declare 177 {
|
||||
void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2,
|
||||
const char *operation, const char *reason)
|
||||
}
|
||||
# TIP 338 made these public - now declared in tcl.h
|
||||
#declare 178 {
|
||||
# void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName)
|
||||
#}
|
||||
#declare 179 {
|
||||
# Tcl_Obj *Tcl_GetStartupScript(const char **encodingNamePtr)
|
||||
#}
|
||||
# TIP 338 made these public - now declared in tcl.h too
|
||||
declare 178 {
|
||||
void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName)
|
||||
}
|
||||
declare 179 {
|
||||
Tcl_Obj *Tcl_GetStartupScript(const char **encodingNamePtr)
|
||||
}
|
||||
|
||||
# REMOVED
|
||||
# Allocate lists without copying arrays
|
||||
@@ -941,9 +941,9 @@ declare 235 {
|
||||
|
||||
|
||||
# TIP 337 made this one public
|
||||
#declare 236 {
|
||||
# void TclBackgroundException(Tcl_Interp *interp, int code)
|
||||
#}
|
||||
declare 236 {
|
||||
void TclBackgroundException(Tcl_Interp *interp, int code)
|
||||
}
|
||||
|
||||
# TIP #285: Script cancellation support.
|
||||
declare 237 {
|
||||
@@ -1148,9 +1148,6 @@ declare 27 win {
|
||||
declare 28 win {
|
||||
void TclWinResetInterfaces(void)
|
||||
}
|
||||
declare 29 win {
|
||||
int TclWinCPUID(unsigned int index, unsigned int *regs)
|
||||
}
|
||||
|
||||
################################
|
||||
# Unix specific functions
|
||||
@@ -1219,12 +1216,6 @@ declare 14 unix {
|
||||
const Tcl_StatBuf *statBufPtr, int dontCopyAtts)
|
||||
}
|
||||
|
||||
# Added in 8.6; core of TclpOpenTemporaryFile
|
||||
declare 20 unix {
|
||||
int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj,
|
||||
Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj)
|
||||
}
|
||||
|
||||
################################
|
||||
# Mac OS X specific functions
|
||||
|
||||
@@ -1248,9 +1239,17 @@ declare 18 macosx {
|
||||
declare 19 macosx {
|
||||
void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode)
|
||||
}
|
||||
declare 29 unix {
|
||||
|
||||
declare 29 {win unix} {
|
||||
int TclWinCPUID(unsigned int index, unsigned int *regs)
|
||||
}
|
||||
# Added in 8.6; core of TclpOpenTemporaryFile
|
||||
declare 30 {win unix} {
|
||||
int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj,
|
||||
Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj)
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Local Variables:
|
||||
# mode: tcl
|
||||
|
||||
+51
-104
@@ -396,7 +396,7 @@ struct NamespacePathEntry {
|
||||
|
||||
/*
|
||||
* The data cached in an ensemble subcommand's Tcl_Obj rep (reference in
|
||||
* otherValuePtr field). This structure is not shared between Tcl_Objs
|
||||
* twoPtrValue.ptr1 field). This structure is not shared between Tcl_Objs
|
||||
* referring to the same subcommand, even where one is a duplicate of another.
|
||||
*/
|
||||
|
||||
@@ -588,30 +588,6 @@ typedef struct ActiveVarTrace {
|
||||
* free'd memory. */
|
||||
} ActiveVarTrace;
|
||||
|
||||
/*
|
||||
* The following structure describes an enumerative search in progress on an
|
||||
* array variable; this are invoked with options to the "array" command.
|
||||
*/
|
||||
|
||||
typedef struct ArraySearch {
|
||||
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_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. */
|
||||
} ArraySearch;
|
||||
|
||||
/*
|
||||
* The structure below defines a variable, which associates a string name with
|
||||
* a Tcl_Obj value. These structures are kept in procedure call frames (for
|
||||
@@ -1154,7 +1130,7 @@ typedef struct CallFrame {
|
||||
* meaning of the value is, which we do not
|
||||
* specify. */
|
||||
LocalCache *localCachePtr;
|
||||
struct NRE_callback *tailcallPtr;
|
||||
Tcl_Obj *tailcallPtr;
|
||||
/* NULL if no tailcall is scheduled */
|
||||
} CallFrame;
|
||||
|
||||
@@ -2201,17 +2177,6 @@ typedef struct Interp {
|
||||
#define TclUnsetCancelFlags(iPtr) \
|
||||
(iPtr)->flags &= (~(CANCELED | TCL_CANCEL_UNWIND))
|
||||
|
||||
/*
|
||||
* General list of interpreters. Doubly linked for easier removal of items
|
||||
* deep in the list.
|
||||
*/
|
||||
|
||||
typedef struct InterpList {
|
||||
Interp *interpPtr;
|
||||
struct InterpList *prevPtr;
|
||||
struct InterpList *nextPtr;
|
||||
} InterpList;
|
||||
|
||||
/*
|
||||
* Macros for splicing into and out of doubly linked lists. They assume
|
||||
* existence of struct items 'prevPtr' and 'nextPtr'.
|
||||
@@ -2250,7 +2215,6 @@ typedef struct InterpList {
|
||||
#define TCL_ALLOW_EXCEPTIONS 4
|
||||
#define TCL_EVAL_FILE 2
|
||||
#define TCL_EVAL_CTX 8
|
||||
#define TCL_EVAL_REDIRECT 16
|
||||
|
||||
/*
|
||||
* Flag bits for Interp structures:
|
||||
@@ -2317,35 +2281,6 @@ typedef struct InterpList {
|
||||
|
||||
#define MAX_NESTING_DEPTH 1000
|
||||
|
||||
/*
|
||||
* TIP#143 limit handler internal representation.
|
||||
*/
|
||||
|
||||
struct LimitHandler {
|
||||
int flags; /* The state of this particular handler. */
|
||||
Tcl_LimitHandlerProc *handlerProc;
|
||||
/* The handler callback. */
|
||||
ClientData clientData; /* Opaque argument to the handler callback. */
|
||||
Tcl_LimitHandlerDeleteProc *deleteProc;
|
||||
/* How to delete the clientData. */
|
||||
LimitHandler *prevPtr; /* Previous item in linked list of
|
||||
* handlers. */
|
||||
LimitHandler *nextPtr; /* Next item in linked list of handlers. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Values for the LimitHandler flags field.
|
||||
* LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
|
||||
* processed; handlers are never to be entered reentrantly.
|
||||
* LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This
|
||||
* should not normally be observed because when a handler is
|
||||
* deleted it is also spliced out of the list of handlers, but
|
||||
* even so we will be careful.
|
||||
*/
|
||||
|
||||
#define LIMIT_HANDLER_ACTIVE 0x01
|
||||
#define LIMIT_HANDLER_DELETED 0x02
|
||||
|
||||
/*
|
||||
* The macro below is used to modify a "char" value (e.g. by casting it to an
|
||||
* unsigned character) so that it can be used safely with macros such as
|
||||
@@ -2805,8 +2740,12 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd;
|
||||
|
||||
MODULE_SCOPE void TclSpliceTailcall(Tcl_Interp *interp,
|
||||
struct NRE_callback *tailcallPtr);
|
||||
MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp, Tcl_Obj *tailcallPtr);
|
||||
MODULE_SCOPE void TclPushTailcallPoint(Tcl_Interp *interp);
|
||||
|
||||
/* These two can be considered for the public api */
|
||||
MODULE_SCOPE void TclMarkTailcall(Tcl_Interp *interp);
|
||||
MODULE_SCOPE void TclSkipTailcall(Tcl_Interp *interp);
|
||||
|
||||
/*
|
||||
* This structure holds the data for the various iteration callbacks used to
|
||||
@@ -2881,7 +2820,6 @@ MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr,
|
||||
const unsigned char *bytes, int len);
|
||||
MODULE_SCOPE int TclNREvalCmd(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int flags);
|
||||
MODULE_SCOPE void TclPushTailcallPoint(Tcl_Interp *interp);
|
||||
MODULE_SCOPE void TclAdvanceContinuations(int *line, int **next,
|
||||
int loc);
|
||||
MODULE_SCOPE void TclAdvanceLines(int *line, const char *start,
|
||||
@@ -3132,6 +3070,7 @@ MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp,
|
||||
Tcl_Obj *cmdPrefix);
|
||||
MODULE_SCOPE void TclSetBignumIntRep(Tcl_Obj *objPtr,
|
||||
mp_int *bignumValue);
|
||||
MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
Command *cmdPtr);
|
||||
MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
|
||||
@@ -3716,6 +3655,42 @@ MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileYieldCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic0ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic1ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic2ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic3ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic0Or1ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic1Or2ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic2Or3ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic0To2ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic1To3ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasicMin0ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasicMin1ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasicMin2ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
|
||||
MODULE_SCOPE int TclInvertOpCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
@@ -4008,12 +3983,13 @@ typedef const char *TclDTraceStr;
|
||||
*/
|
||||
|
||||
# define TclAllocObjStorageEx(interp, objPtr) \
|
||||
(objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj))
|
||||
(objPtr) = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj))
|
||||
|
||||
# define TclFreeObjStorageEx(interp, objPtr) \
|
||||
ckfree((char *) (objPtr))
|
||||
|
||||
#undef USE_THREAD_ALLOC
|
||||
#undef USE_TCLALLOC
|
||||
#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
|
||||
/*
|
||||
@@ -4049,7 +4025,7 @@ MODULE_SCOPE void TclpFreeAllocCache(void *);
|
||||
(objPtr) = TclThreadAllocObj(); \
|
||||
} else { \
|
||||
(objPtr) = cachePtr->firstObjPtr; \
|
||||
cachePtr->firstObjPtr = (objPtr)->internalRep.otherValuePtr; \
|
||||
cachePtr->firstObjPtr = (objPtr)->internalRep.twoPtrValue.ptr1; \
|
||||
--cachePtr->numObjects; \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -4062,7 +4038,7 @@ MODULE_SCOPE void TclpFreeAllocCache(void *);
|
||||
(cachePtr->numObjects >= ALLOC_NOBJHIGH))) { \
|
||||
TclThreadFreeObj(objPtr); \
|
||||
} else { \
|
||||
(objPtr)->internalRep.otherValuePtr = cachePtr->firstObjPtr; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr; \
|
||||
cachePtr->firstObjPtr = objPtr; \
|
||||
++cachePtr->numObjects; \
|
||||
} \
|
||||
@@ -4090,14 +4066,14 @@ MODULE_SCOPE Tcl_Mutex tclObjMutex;
|
||||
} \
|
||||
(objPtr) = tclFreeObjList; \
|
||||
tclFreeObjList = (Tcl_Obj *) \
|
||||
tclFreeObjList->internalRep.otherValuePtr; \
|
||||
tclFreeObjList->internalRep.twoPtrValue.ptr1; \
|
||||
Tcl_MutexUnlock(&tclObjMutex); \
|
||||
} while (0)
|
||||
|
||||
# define TclFreeObjStorageEx(interp, objPtr) \
|
||||
do { \
|
||||
Tcl_MutexLock(&tclObjMutex); \
|
||||
(objPtr)->internalRep.otherValuePtr = (void *) tclFreeObjList; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = (void *) tclFreeObjList; \
|
||||
tclFreeObjList = (objPtr); \
|
||||
Tcl_MutexUnlock(&tclObjMutex); \
|
||||
} while (0)
|
||||
@@ -4771,35 +4747,6 @@ typedef struct NRE_callback {
|
||||
TOP_CB(interp) = callbackPtr; \
|
||||
} while (0)
|
||||
|
||||
#define TclNRDeferCallback(interp,postProcPtr,data0,data1,data2,data3) \
|
||||
do { \
|
||||
NRE_callback *callbackPtr; \
|
||||
TCLNR_ALLOC((interp), (callbackPtr)); \
|
||||
callbackPtr->procPtr = (postProcPtr); \
|
||||
callbackPtr->data[0] = (ClientData)(data0); \
|
||||
callbackPtr->data[1] = (ClientData)(data1); \
|
||||
callbackPtr->data[2] = (ClientData)(data2); \
|
||||
callbackPtr->data[3] = (ClientData)(data3); \
|
||||
callbackPtr->nextPtr = ((Interp *)interp)->deferredCallbacks; \
|
||||
((Interp *)interp)->deferredCallbacks = callbackPtr; \
|
||||
} while (0)
|
||||
|
||||
#define TclNRSpliceCallbacks(interp, topPtr) \
|
||||
do { \
|
||||
NRE_callback *bottomPtr = topPtr; \
|
||||
while (bottomPtr->nextPtr) { \
|
||||
bottomPtr = bottomPtr->nextPtr; \
|
||||
} \
|
||||
bottomPtr->nextPtr = TOP_CB(interp); \
|
||||
TOP_CB(interp) = topPtr; \
|
||||
} while (0)
|
||||
|
||||
#define TclNRSpliceDeferred(interp) \
|
||||
if (((Interp *)interp)->deferredCallbacks) { \
|
||||
TclNRSpliceCallbacks(interp, ((Interp *)interp)->deferredCallbacks); \
|
||||
((Interp *)interp)->deferredCallbacks = NULL; \
|
||||
}
|
||||
|
||||
#if NRE_USE_SMALL_ALLOC
|
||||
#define TCLNR_ALLOC(interp, ptr) \
|
||||
TclSmallAllocEx(interp, sizeof(NRE_callback), (ptr))
|
||||
|
||||
+98
-28
@@ -29,19 +29,20 @@
|
||||
#endif
|
||||
|
||||
/* [Bug #803489] Tcl_FindNamespace problem in the Stubs table */
|
||||
#undef Tcl_AppendExportList
|
||||
#undef Tcl_CreateNamespace
|
||||
#undef Tcl_DeleteNamespace
|
||||
#undef Tcl_AppendExportList
|
||||
#undef Tcl_Export
|
||||
#undef Tcl_FindCommand
|
||||
#undef Tcl_FindNamespace
|
||||
#undef Tcl_FindNamespaceVar
|
||||
#undef Tcl_Import
|
||||
#undef Tcl_ForgetImport
|
||||
#undef Tcl_GetCommandFromObj
|
||||
#undef Tcl_GetCommandFullName
|
||||
#undef Tcl_GetCurrentNamespace
|
||||
#undef Tcl_GetGlobalNamespace
|
||||
#undef Tcl_Import
|
||||
#undef Tcl_FindNamespace
|
||||
#undef Tcl_FindCommand
|
||||
#undef Tcl_GetCommandFromObj
|
||||
#undef Tcl_GetCommandFullName
|
||||
#undef Tcl_SetStartupScript
|
||||
#undef Tcl_GetStartupScript
|
||||
|
||||
/*
|
||||
* WARNING: This file is automatically generated by the tools/genStubs.tcl
|
||||
@@ -395,8 +396,10 @@ EXTERN void TclRegError(Tcl_Interp *interp, const char *msg,
|
||||
/* 157 */
|
||||
EXTERN Var * TclVarTraceExists(Tcl_Interp *interp,
|
||||
const char *varName);
|
||||
/* Slot 158 is reserved */
|
||||
/* Slot 159 is reserved */
|
||||
/* 158 */
|
||||
EXTERN void TclSetStartupScriptFileName(const char *filename);
|
||||
/* 159 */
|
||||
EXTERN const char * TclGetStartupScriptFileName(void);
|
||||
/* Slot 160 is reserved */
|
||||
/* 161 */
|
||||
EXTERN int TclChannelTransform(Tcl_Interp *interp,
|
||||
@@ -414,8 +417,10 @@ EXTERN void TclpSetInitialEncodings(void);
|
||||
EXTERN int TclListObjSetElement(Tcl_Interp *interp,
|
||||
Tcl_Obj *listPtr, int index,
|
||||
Tcl_Obj *valuePtr);
|
||||
/* Slot 167 is reserved */
|
||||
/* Slot 168 is reserved */
|
||||
/* 167 */
|
||||
EXTERN void TclSetStartupScriptPath(Tcl_Obj *pathPtr);
|
||||
/* 168 */
|
||||
EXTERN Tcl_Obj * TclGetStartupScriptPath(void);
|
||||
/* 169 */
|
||||
EXTERN int TclpUtfNcmp2(const char *s1, const char *s2,
|
||||
unsigned long n);
|
||||
@@ -447,8 +452,11 @@ EXTERN void TclCleanupVar(Var *varPtr, Var *arrayPtr);
|
||||
EXTERN void TclVarErrMsg(Tcl_Interp *interp, const char *part1,
|
||||
const char *part2, const char *operation,
|
||||
const char *reason);
|
||||
/* Slot 178 is reserved */
|
||||
/* Slot 179 is reserved */
|
||||
/* 178 */
|
||||
EXTERN void Tcl_SetStartupScript(Tcl_Obj *pathPtr,
|
||||
const char *encodingName);
|
||||
/* 179 */
|
||||
EXTERN Tcl_Obj * Tcl_GetStartupScript(const char **encodingNamePtr);
|
||||
/* Slot 180 is reserved */
|
||||
/* Slot 181 is reserved */
|
||||
/* 182 */
|
||||
@@ -557,7 +565,8 @@ EXTERN Var * TclVarHashCreateVar(TclVarHashTable *tablePtr,
|
||||
/* 235 */
|
||||
EXTERN void TclInitVarHashTable(TclVarHashTable *tablePtr,
|
||||
Namespace *nsPtr);
|
||||
/* Slot 236 is reserved */
|
||||
/* 236 */
|
||||
EXTERN void TclBackgroundException(Tcl_Interp *interp, int code);
|
||||
/* 237 */
|
||||
EXTERN int TclResetCancellation(Tcl_Interp *interp, int force);
|
||||
/* 238 */
|
||||
@@ -764,8 +773,8 @@ typedef struct TclIntStubs {
|
||||
void (*reserved155)(void);
|
||||
void (*tclRegError) (Tcl_Interp *interp, const char *msg, int status); /* 156 */
|
||||
Var * (*tclVarTraceExists) (Tcl_Interp *interp, const char *varName); /* 157 */
|
||||
void (*reserved158)(void);
|
||||
void (*reserved159)(void);
|
||||
void (*tclSetStartupScriptFileName) (const char *filename); /* 158 */
|
||||
const char * (*tclGetStartupScriptFileName) (void); /* 159 */
|
||||
void (*reserved160)(void);
|
||||
int (*tclChannelTransform) (Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 161 */
|
||||
void (*tclChannelEventScriptInvoker) (ClientData clientData, int flags); /* 162 */
|
||||
@@ -773,8 +782,8 @@ typedef struct TclIntStubs {
|
||||
void (*tclExpandCodeArray) (void *envPtr); /* 164 */
|
||||
void (*tclpSetInitialEncodings) (void); /* 165 */
|
||||
int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 166 */
|
||||
void (*reserved167)(void);
|
||||
void (*reserved168)(void);
|
||||
void (*tclSetStartupScriptPath) (Tcl_Obj *pathPtr); /* 167 */
|
||||
Tcl_Obj * (*tclGetStartupScriptPath) (void); /* 168 */
|
||||
int (*tclpUtfNcmp2) (const char *s1, const char *s2, unsigned long n); /* 169 */
|
||||
int (*tclCheckInterpTraces) (Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 170 */
|
||||
int (*tclCheckExecutionTraces) (Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 171 */
|
||||
@@ -784,8 +793,8 @@ typedef struct TclIntStubs {
|
||||
int (*tclCallVarTraces) (Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, int leaveErrMsg); /* 175 */
|
||||
void (*tclCleanupVar) (Var *varPtr, Var *arrayPtr); /* 176 */
|
||||
void (*tclVarErrMsg) (Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); /* 177 */
|
||||
void (*reserved178)(void);
|
||||
void (*reserved179)(void);
|
||||
void (*tcl_SetStartupScript) (Tcl_Obj *pathPtr, const char *encodingName); /* 178 */
|
||||
Tcl_Obj * (*tcl_GetStartupScript) (const char **encodingNamePtr); /* 179 */
|
||||
void (*reserved180)(void);
|
||||
void (*reserved181)(void);
|
||||
struct tm * (*tclpLocaltime) (const time_t *clock); /* 182 */
|
||||
@@ -842,7 +851,7 @@ typedef struct TclIntStubs {
|
||||
void (*tclGetSrcInfoForPc) (CmdFrame *contextPtr); /* 233 */
|
||||
Var * (*tclVarHashCreateVar) (TclVarHashTable *tablePtr, const char *key, int *newPtr); /* 234 */
|
||||
void (*tclInitVarHashTable) (TclVarHashTable *tablePtr, Namespace *nsPtr); /* 235 */
|
||||
void (*reserved236)(void);
|
||||
void (*tclBackgroundException) (Tcl_Interp *interp, int code); /* 236 */
|
||||
int (*tclResetCancellation) (Tcl_Interp *interp, int force); /* 237 */
|
||||
int (*tclNRInterpProc) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 238 */
|
||||
int (*tclNRInterpProcCore) (Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip, ProcErrorProc *errorProc); /* 239 */
|
||||
@@ -1130,8 +1139,10 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
(tclIntStubsPtr->tclRegError) /* 156 */
|
||||
#define TclVarTraceExists \
|
||||
(tclIntStubsPtr->tclVarTraceExists) /* 157 */
|
||||
/* Slot 158 is reserved */
|
||||
/* Slot 159 is reserved */
|
||||
#define TclSetStartupScriptFileName \
|
||||
(tclIntStubsPtr->tclSetStartupScriptFileName) /* 158 */
|
||||
#define TclGetStartupScriptFileName \
|
||||
(tclIntStubsPtr->tclGetStartupScriptFileName) /* 159 */
|
||||
/* Slot 160 is reserved */
|
||||
#define TclChannelTransform \
|
||||
(tclIntStubsPtr->tclChannelTransform) /* 161 */
|
||||
@@ -1145,8 +1156,10 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
(tclIntStubsPtr->tclpSetInitialEncodings) /* 165 */
|
||||
#define TclListObjSetElement \
|
||||
(tclIntStubsPtr->tclListObjSetElement) /* 166 */
|
||||
/* Slot 167 is reserved */
|
||||
/* Slot 168 is reserved */
|
||||
#define TclSetStartupScriptPath \
|
||||
(tclIntStubsPtr->tclSetStartupScriptPath) /* 167 */
|
||||
#define TclGetStartupScriptPath \
|
||||
(tclIntStubsPtr->tclGetStartupScriptPath) /* 168 */
|
||||
#define TclpUtfNcmp2 \
|
||||
(tclIntStubsPtr->tclpUtfNcmp2) /* 169 */
|
||||
#define TclCheckInterpTraces \
|
||||
@@ -1164,8 +1177,10 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
(tclIntStubsPtr->tclCleanupVar) /* 176 */
|
||||
#define TclVarErrMsg \
|
||||
(tclIntStubsPtr->tclVarErrMsg) /* 177 */
|
||||
/* Slot 178 is reserved */
|
||||
/* Slot 179 is reserved */
|
||||
#define Tcl_SetStartupScript \
|
||||
(tclIntStubsPtr->tcl_SetStartupScript) /* 178 */
|
||||
#define Tcl_GetStartupScript \
|
||||
(tclIntStubsPtr->tcl_GetStartupScript) /* 179 */
|
||||
/* Slot 180 is reserved */
|
||||
/* Slot 181 is reserved */
|
||||
#define TclpLocaltime \
|
||||
@@ -1252,7 +1267,8 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
(tclIntStubsPtr->tclVarHashCreateVar) /* 234 */
|
||||
#define TclInitVarHashTable \
|
||||
(tclIntStubsPtr->tclInitVarHashTable) /* 235 */
|
||||
/* Slot 236 is reserved */
|
||||
#define TclBackgroundException \
|
||||
(tclIntStubsPtr->tclBackgroundException) /* 236 */
|
||||
#define TclResetCancellation \
|
||||
(tclIntStubsPtr->tclResetCancellation) /* 237 */
|
||||
#define TclNRInterpProc \
|
||||
@@ -1289,4 +1305,58 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#define TCL_STORAGE_CLASS DLLIMPORT
|
||||
|
||||
#undef TclGetStartupScriptFileName
|
||||
#undef TclSetStartupScriptFileName
|
||||
#undef TclGetStartupScriptPath
|
||||
#undef TclSetStartupScriptPath
|
||||
#undef TclBackgroundException
|
||||
|
||||
#if defined(USE_TCL_STUBS) && defined(TCL_NO_DEPRECATED)
|
||||
# undef Tcl_SetStartupScript
|
||||
# define Tcl_SetStartupScript \
|
||||
(tclStubsPtr->tcl_SetStartupScript) /* 622 */
|
||||
# undef Tcl_GetStartupScript
|
||||
# define Tcl_GetStartupScript \
|
||||
(tclStubsPtr->tcl_GetStartupScript) /* 623 */
|
||||
# undef Tcl_CreateNamespace
|
||||
# define Tcl_CreateNamespace \
|
||||
(tclStubsPtr->tcl_CreateNamespace) /* 506 */
|
||||
# undef Tcl_DeleteNamespace
|
||||
# define Tcl_DeleteNamespace \
|
||||
(tclStubsPtr->tcl_DeleteNamespace) /* 507 */
|
||||
# undef Tcl_AppendExportList
|
||||
# define Tcl_AppendExportList \
|
||||
(tclStubsPtr->tcl_AppendExportList) /* 508 */
|
||||
# undef Tcl_Export
|
||||
# define Tcl_Export \
|
||||
(tclStubsPtr->tcl_Export) /* 509 */
|
||||
# undef Tcl_Import
|
||||
# define Tcl_Import \
|
||||
(tclStubsPtr->tcl_Import) /* 510 */
|
||||
# undef Tcl_ForgetImport
|
||||
# define Tcl_ForgetImport \
|
||||
(tclStubsPtr->tcl_ForgetImport) /* 511 */
|
||||
# undef Tcl_GetCurrentNamespace
|
||||
# define Tcl_GetCurrentNamespace \
|
||||
(tclStubsPtr->tcl_GetCurrentNamespace) /* 512 */
|
||||
# undef Tcl_GetGlobalNamespace
|
||||
# define Tcl_GetGlobalNamespace \
|
||||
(tclStubsPtr->tcl_GetGlobalNamespace) /* 513 */
|
||||
# undef Tcl_FindNamespace
|
||||
# define Tcl_FindNamespace \
|
||||
(tclStubsPtr->tcl_FindNamespace) /* 514 */
|
||||
# undef Tcl_FindCommand
|
||||
# define Tcl_FindCommand \
|
||||
(tclStubsPtr->tcl_FindCommand) /* 515 */
|
||||
# undef Tcl_GetCommandFromObj
|
||||
# define Tcl_GetCommandFromObj \
|
||||
(tclStubsPtr->tcl_GetCommandFromObj) /* 516 */
|
||||
# undef Tcl_GetCommandFullName
|
||||
# define Tcl_GetCommandFullName \
|
||||
(tclStubsPtr->tcl_GetCommandFullName) /* 517 */
|
||||
#endif
|
||||
|
||||
#undef TclCopyChannelOld
|
||||
#undef TclSockMinimumBuffersOld
|
||||
|
||||
#endif /* _TCLINTDECLS */
|
||||
|
||||
+27
-14
@@ -84,10 +84,7 @@ EXTERN int TclUnixCopyFile(const char *src, const char *dst,
|
||||
/* Slot 17 is reserved */
|
||||
/* Slot 18 is reserved */
|
||||
/* Slot 19 is reserved */
|
||||
/* 20 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
Tcl_Obj *resultingNameObj);
|
||||
/* Slot 20 is reserved */
|
||||
/* Slot 21 is reserved */
|
||||
/* Slot 22 is reserved */
|
||||
/* Slot 23 is reserved */
|
||||
@@ -98,6 +95,10 @@ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
/* Slot 28 is reserved */
|
||||
/* 29 */
|
||||
EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs);
|
||||
/* 30 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
Tcl_Obj *resultingNameObj);
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
/* 0 */
|
||||
@@ -169,6 +170,10 @@ EXTERN void TclWinFlushDirtyChannels(void);
|
||||
EXTERN void TclWinResetInterfaces(void);
|
||||
/* 29 */
|
||||
EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs);
|
||||
/* 30 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
Tcl_Obj *resultingNameObj);
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
/* 0 */
|
||||
@@ -228,10 +233,7 @@ EXTERN int TclMacOSXMatchType(Tcl_Interp *interp,
|
||||
/* 19 */
|
||||
EXTERN void TclMacOSXNotifierAddRunLoopMode(
|
||||
const void *runLoopMode);
|
||||
/* 20 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
Tcl_Obj *resultingNameObj);
|
||||
/* Slot 20 is reserved */
|
||||
/* Slot 21 is reserved */
|
||||
/* Slot 22 is reserved */
|
||||
/* Slot 23 is reserved */
|
||||
@@ -242,6 +244,10 @@ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
/* Slot 28 is reserved */
|
||||
/* 29 */
|
||||
EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs);
|
||||
/* 30 */
|
||||
EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
Tcl_Obj *resultingNameObj);
|
||||
#endif /* MACOSX */
|
||||
|
||||
typedef struct TclIntPlatStubs {
|
||||
@@ -269,7 +275,7 @@ typedef struct TclIntPlatStubs {
|
||||
void (*reserved17)(void);
|
||||
void (*reserved18)(void);
|
||||
void (*reserved19)(void);
|
||||
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 20 */
|
||||
void (*reserved20)(void);
|
||||
void (*reserved21)(void);
|
||||
void (*reserved22)(void);
|
||||
void (*reserved23)(void);
|
||||
@@ -279,6 +285,7 @@ typedef struct TclIntPlatStubs {
|
||||
void (*reserved27)(void);
|
||||
void (*reserved28)(void);
|
||||
int (*tclWinCPUID) (unsigned int index, unsigned 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 */
|
||||
void (*tclWinConvertError) (DWORD errCode); /* 0 */
|
||||
@@ -311,6 +318,7 @@ typedef struct TclIntPlatStubs {
|
||||
void (*tclWinFlushDirtyChannels) (void); /* 27 */
|
||||
void (*tclWinResetInterfaces) (void); /* 28 */
|
||||
int (*tclWinCPUID) (unsigned int index, unsigned 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 */
|
||||
void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */
|
||||
@@ -333,7 +341,7 @@ typedef struct TclIntPlatStubs {
|
||||
int (*tclMacOSXCopyFileAttributes) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr); /* 17 */
|
||||
int (*tclMacOSXMatchType) (Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 18 */
|
||||
void (*tclMacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 19 */
|
||||
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 20 */
|
||||
void (*reserved20)(void);
|
||||
void (*reserved21)(void);
|
||||
void (*reserved22)(void);
|
||||
void (*reserved23)(void);
|
||||
@@ -343,6 +351,7 @@ typedef struct TclIntPlatStubs {
|
||||
void (*reserved27)(void);
|
||||
void (*reserved28)(void);
|
||||
int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */
|
||||
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
|
||||
#endif /* MACOSX */
|
||||
} TclIntPlatStubs;
|
||||
|
||||
@@ -395,8 +404,7 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
/* Slot 17 is reserved */
|
||||
/* Slot 18 is reserved */
|
||||
/* Slot 19 is reserved */
|
||||
#define TclUnixOpenTemporaryFile \
|
||||
(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 20 */
|
||||
/* Slot 20 is reserved */
|
||||
/* Slot 21 is reserved */
|
||||
/* Slot 22 is reserved */
|
||||
/* Slot 23 is reserved */
|
||||
@@ -407,6 +415,8 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
/* Slot 28 is reserved */
|
||||
#define TclWinCPUID \
|
||||
(tclIntPlatStubsPtr->tclWinCPUID) /* 29 */
|
||||
#define TclUnixOpenTemporaryFile \
|
||||
(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#define TclWinConvertError \
|
||||
@@ -467,6 +477,8 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
(tclIntPlatStubsPtr->tclWinResetInterfaces) /* 28 */
|
||||
#define TclWinCPUID \
|
||||
(tclIntPlatStubsPtr->tclWinCPUID) /* 29 */
|
||||
#define TclUnixOpenTemporaryFile \
|
||||
(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
#define TclGetAndDetachPids \
|
||||
@@ -508,8 +520,7 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
(tclIntPlatStubsPtr->tclMacOSXMatchType) /* 18 */
|
||||
#define TclMacOSXNotifierAddRunLoopMode \
|
||||
(tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */
|
||||
#define TclUnixOpenTemporaryFile \
|
||||
(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 20 */
|
||||
/* Slot 20 is reserved */
|
||||
/* Slot 21 is reserved */
|
||||
/* Slot 22 is reserved */
|
||||
/* Slot 23 is reserved */
|
||||
@@ -520,6 +531,8 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
/* Slot 28 is reserved */
|
||||
#define TclWinCPUID \
|
||||
(tclIntPlatStubsPtr->tclWinCPUID) /* 29 */
|
||||
#define TclUnixOpenTemporaryFile \
|
||||
(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */
|
||||
#endif /* MACOSX */
|
||||
|
||||
#endif /* defined(USE_TCL_STUBS) */
|
||||
|
||||
+33
-2
@@ -178,6 +178,37 @@ typedef struct ScriptLimitCallbackKey {
|
||||
long type; /* The type of callback that this is. */
|
||||
} ScriptLimitCallbackKey;
|
||||
|
||||
/*
|
||||
* TIP#143 limit handler internal representation.
|
||||
*/
|
||||
|
||||
struct LimitHandler {
|
||||
int flags; /* The state of this particular handler. */
|
||||
Tcl_LimitHandlerProc *handlerProc;
|
||||
/* The handler callback. */
|
||||
ClientData clientData; /* Opaque argument to the handler callback. */
|
||||
Tcl_LimitHandlerDeleteProc *deleteProc;
|
||||
/* How to delete the clientData. */
|
||||
LimitHandler *prevPtr; /* Previous item in linked list of
|
||||
* handlers. */
|
||||
LimitHandler *nextPtr; /* Next item in linked list of handlers. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Values for the LimitHandler flags field.
|
||||
* LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
|
||||
* processed; handlers are never to be entered reentrantly.
|
||||
* LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This
|
||||
* should not normally be observed because when a handler is
|
||||
* deleted it is also spliced out of the list of handlers, but
|
||||
* even so we will be careful.
|
||||
*/
|
||||
|
||||
#define LIMIT_HANDLER_ACTIVE 0x01
|
||||
#define LIMIT_HANDLER_DELETED 0x02
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes for local static functions:
|
||||
*/
|
||||
@@ -1798,9 +1829,9 @@ AliasNRCmd(
|
||||
*/
|
||||
|
||||
if (isRootEnsemble) {
|
||||
TclNRDeferCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
|
||||
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
iPtr->evalFlags |= TCL_EVAL_REDIRECT;
|
||||
TclSkipTailcall(interp);
|
||||
return Tcl_NREvalObj(interp, listPtr, flags);
|
||||
}
|
||||
|
||||
|
||||
+11
-10
@@ -112,8 +112,8 @@ Tcl_LinkVar(
|
||||
Link *linkPtr;
|
||||
int code;
|
||||
|
||||
linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
|
||||
LinkTraceProc, (ClientData) NULL);
|
||||
linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
|
||||
TCL_GLOBAL_ONLY, LinkTraceProc, (ClientData) NULL);
|
||||
if (linkPtr != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"variable '%s' is already linked", varName));
|
||||
@@ -138,8 +138,9 @@ Tcl_LinkVar(
|
||||
ckfree(linkPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
code = Tcl_TraceVar(interp, varName, TCL_GLOBAL_ONLY|TCL_TRACE_READS
|
||||
|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc, linkPtr);
|
||||
code = Tcl_TraceVar2(interp, varName, NULL,
|
||||
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||||
LinkTraceProc, linkPtr);
|
||||
if (code != TCL_OK) {
|
||||
Tcl_DecrRefCount(linkPtr->varName);
|
||||
ckfree(linkPtr);
|
||||
@@ -170,13 +171,13 @@ Tcl_UnlinkVar(
|
||||
Tcl_Interp *interp, /* Interpreter containing variable to unlink */
|
||||
const char *varName) /* Global variable in interp to unlink. */
|
||||
{
|
||||
Link *linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName,
|
||||
Link *linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
|
||||
TCL_GLOBAL_ONLY, LinkTraceProc, NULL);
|
||||
|
||||
if (linkPtr == NULL) {
|
||||
return;
|
||||
}
|
||||
Tcl_UntraceVar(interp, varName,
|
||||
Tcl_UntraceVar2(interp, varName, NULL,
|
||||
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||||
LinkTraceProc, linkPtr);
|
||||
Tcl_DecrRefCount(linkPtr->varName);
|
||||
@@ -207,7 +208,7 @@ Tcl_UpdateLinkedVar(
|
||||
Tcl_Interp *interp, /* Interpreter containing variable. */
|
||||
const char *varName) /* Name of global variable that is linked. */
|
||||
{
|
||||
Link *linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName,
|
||||
Link *linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
|
||||
TCL_GLOBAL_ONLY, LinkTraceProc, NULL);
|
||||
int savedFlag;
|
||||
|
||||
@@ -221,8 +222,8 @@ Tcl_UpdateLinkedVar(
|
||||
/*
|
||||
* Callback may have unlinked the variable. [Bug 1740631]
|
||||
*/
|
||||
linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
|
||||
LinkTraceProc, NULL);
|
||||
linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
|
||||
TCL_GLOBAL_ONLY, LinkTraceProc, NULL);
|
||||
if (linkPtr != NULL) {
|
||||
linkPtr->flags = (linkPtr->flags & ~LINK_BEING_UPDATED) | savedFlag;
|
||||
}
|
||||
@@ -278,7 +279,7 @@ LinkTraceProc(
|
||||
} else if (flags & TCL_TRACE_DESTROYED) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
Tcl_TraceVar(interp, Tcl_GetString(linkPtr->varName),
|
||||
Tcl_TraceVar2(interp, Tcl_GetString(linkPtr->varName), NULL,
|
||||
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
|
||||
|TCL_TRACE_UNSETS, LinkTraceProc, linkPtr);
|
||||
}
|
||||
|
||||
+20
-13
@@ -237,7 +237,7 @@ Tcl_NewListObj(
|
||||
* Now create the object.
|
||||
*/
|
||||
|
||||
Tcl_InvalidateStringRep(listPtr);
|
||||
TclInvalidateStringRep(listPtr);
|
||||
ListSetIntRep(listPtr, listRepPtr);
|
||||
return listPtr;
|
||||
}
|
||||
@@ -302,7 +302,7 @@ Tcl_DbNewListObj(
|
||||
* Now create the object.
|
||||
*/
|
||||
|
||||
Tcl_InvalidateStringRep(listPtr);
|
||||
TclInvalidateStringRep(listPtr);
|
||||
ListSetIntRep(listPtr, listRepPtr);
|
||||
|
||||
return listPtr;
|
||||
@@ -362,7 +362,7 @@ Tcl_SetListObj(
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
Tcl_InvalidateStringRep(objPtr);
|
||||
TclInvalidateStringRep(objPtr);
|
||||
|
||||
/*
|
||||
* Set the object's type to "list" and initialize the internal rep.
|
||||
@@ -697,7 +697,7 @@ Tcl_ListObjAppendElement(
|
||||
* representation has changed.
|
||||
*/
|
||||
|
||||
Tcl_InvalidateStringRep(listPtr);
|
||||
TclInvalidateStringRep(listPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -909,6 +909,10 @@ Tcl_ListObjReplace(
|
||||
isShared = (listRepPtr->refCount > 1);
|
||||
numRequired = numElems - count + objc;
|
||||
|
||||
for (i = 0; i < objc; i++) {
|
||||
Tcl_IncrRefCount(objv[i]);
|
||||
}
|
||||
|
||||
if ((numRequired <= listRepPtr->maxElemCount) && !isShared) {
|
||||
int shift;
|
||||
|
||||
@@ -963,6 +967,14 @@ Tcl_ListObjReplace(
|
||||
if (listRepPtr == NULL) {
|
||||
listRepPtr = AttemptNewList(interp, numRequired, NULL);
|
||||
if (listRepPtr == NULL) {
|
||||
for (i = 0; i < objc; i++) {
|
||||
/* See bug 3598580 */
|
||||
#if TCL_MAJOR_VERSION > 8
|
||||
Tcl_DecrRefCount(objv[i]);
|
||||
#else
|
||||
objv[i]->refCount--;
|
||||
#endif
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -1027,14 +1039,11 @@ Tcl_ListObjReplace(
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert the new elements into elemPtrs before "first". We don't do a
|
||||
* memcpy here because we must increment the reference counts for the
|
||||
* added elements, so we must explicitly loop anyway.
|
||||
* Insert the new elements into elemPtrs before "first".
|
||||
*/
|
||||
|
||||
for (i=0,j=first ; i<objc ; i++,j++) {
|
||||
elemPtrs[j] = objv[i];
|
||||
Tcl_IncrRefCount(objv[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1048,7 +1057,7 @@ Tcl_ListObjReplace(
|
||||
* reflects the list's internal representation.
|
||||
*/
|
||||
|
||||
Tcl_InvalidateStringRep(listPtr);
|
||||
TclInvalidateStringRep(listPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -1514,7 +1523,7 @@ TclLsetFlat(
|
||||
* containing lists.
|
||||
*/
|
||||
|
||||
Tcl_InvalidateStringRep(objPtr);
|
||||
TclInvalidateStringRep(objPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1550,7 +1559,7 @@ TclLsetFlat(
|
||||
} else {
|
||||
TclListObjSetElement(NULL, subListPtr, index, valuePtr);
|
||||
}
|
||||
Tcl_InvalidateStringRep(subListPtr);
|
||||
TclInvalidateStringRep(subListPtr);
|
||||
Tcl_IncrRefCount(retValuePtr);
|
||||
return retValuePtr;
|
||||
}
|
||||
@@ -1727,8 +1736,6 @@ FreeListInternalRep(
|
||||
ckfree(listRepPtr);
|
||||
}
|
||||
|
||||
listPtr->internalRep.twoPtrValue.ptr1 = NULL;
|
||||
listPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
listPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
|
||||
+52
-8
@@ -32,6 +32,10 @@ static int AddLocalLiteralEntry(CompileEnv *envPtr,
|
||||
Tcl_Obj *objPtr, int localHash);
|
||||
static void ExpandLocalLiteralArray(CompileEnv *envPtr);
|
||||
static unsigned HashString(const char *string, int length);
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
static LiteralEntry * LookupLiteralEntry(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
#endif
|
||||
static void RebuildLiteralTable(LiteralTable *tablePtr);
|
||||
|
||||
/*
|
||||
@@ -239,7 +243,7 @@ TclCreateLiteral(
|
||||
}
|
||||
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
if (TclLookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
|
||||
if (LookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
|
||||
Tcl_Panic("%s: literal \"%.*s\" found globally but shouldn't be",
|
||||
"TclRegisterLiteral", (length>60? 60 : length), bytes);
|
||||
}
|
||||
@@ -298,6 +302,33 @@ TclCreateLiteral(
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclFetchLiteral --
|
||||
*
|
||||
* Fetch from a CompileEnv the literal value identified by an index
|
||||
* value, as returned by a prior call to TclRegisterLiteral().
|
||||
*
|
||||
* Results:
|
||||
* The literal value, or NULL if the index is out of range.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclFetchLiteral(
|
||||
CompileEnv *envPtr, /* Points to the CompileEnv from which to
|
||||
* fetch the registered literal value. */
|
||||
unsigned int index) /* Index of the desired literal, as returned
|
||||
* by prior call to TclRegisterLiteral() */
|
||||
{
|
||||
if (index >= (unsigned int) envPtr->literalArrayNext) {
|
||||
return NULL;
|
||||
}
|
||||
return envPtr->literalArrayPtr[index].objPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -414,10 +445,11 @@ TclRegisterLiteral(
|
||||
return objIndex;
|
||||
}
|
||||
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclLookupLiteralEntry --
|
||||
* LookupLiteralEntry --
|
||||
*
|
||||
* Finds the LiteralEntry that corresponds to a literal Tcl object
|
||||
* holding a literal.
|
||||
@@ -431,8 +463,8 @@ TclRegisterLiteral(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
LiteralEntry *
|
||||
TclLookupLiteralEntry(
|
||||
static LiteralEntry *
|
||||
LookupLiteralEntry(
|
||||
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
|
||||
* hold a literal. */
|
||||
register Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
|
||||
@@ -456,6 +488,7 @@ TclLookupLiteralEntry(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -750,11 +783,16 @@ TclReleaseLiteral(
|
||||
* TclRegisterLiteral. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
LiteralTable *globalTablePtr = &iPtr->literalTable;
|
||||
LiteralTable *globalTablePtr;
|
||||
register LiteralEntry *entryPtr, *prevPtr;
|
||||
const char *bytes;
|
||||
int length, index;
|
||||
|
||||
if (iPtr == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
globalTablePtr = &iPtr->literalTable;
|
||||
bytes = TclGetStringFromObj(objPtr, &length);
|
||||
index = (HashString(bytes, length) & globalTablePtr->mask);
|
||||
|
||||
@@ -798,6 +836,7 @@ TclReleaseLiteral(
|
||||
* Remove the reference corresponding to the local literal table entry.
|
||||
*/
|
||||
|
||||
done:
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
|
||||
@@ -971,8 +1010,13 @@ TclInvalidateCmdLiteral(
|
||||
Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, (char *) name,
|
||||
strlen(name), -1, NULL, nsPtr, 0, NULL);
|
||||
|
||||
if (literalObjPtr != NULL && literalObjPtr->typePtr == &tclCmdNameType) {
|
||||
TclFreeIntRep(literalObjPtr);
|
||||
if (literalObjPtr != NULL) {
|
||||
if (literalObjPtr->typePtr == &tclCmdNameType) {
|
||||
TclFreeIntRep(literalObjPtr);
|
||||
}
|
||||
/* Balance the refcount effects of TclCreateLiteral() above */
|
||||
Tcl_IncrRefCount(literalObjPtr);
|
||||
TclReleaseLiteral(interp, literalObjPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1090,7 +1134,7 @@ TclVerifyLocalLiteralTable(
|
||||
"TclVerifyLocalLiteralTable",
|
||||
(length>60? 60 : length), bytes, localPtr->refCount);
|
||||
}
|
||||
if (TclLookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
|
||||
if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
|
||||
localPtr->objPtr) == NULL) {
|
||||
bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
|
||||
Tcl_Panic("%s: local literal \"%.*s\" is not global",
|
||||
|
||||
@@ -81,6 +81,39 @@ TclGuessPackageName(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are fallbacks if we somehow determine that the platform can
|
||||
* do loading from memory but the user wishes to disable it. They just report
|
||||
* (gracefully) that they fail.
|
||||
*/
|
||||
|
||||
#ifdef TCL_LOAD_FROM_MEMORY
|
||||
|
||||
MODULE_SCOPE void *
|
||||
TclpLoadMemoryGetBuffer(
|
||||
Tcl_Interp *interp, /* Dummy: unused by this implementation */
|
||||
int size) /* Dummy: unused by this implementation */
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MODULE_SCOPE int
|
||||
TclpLoadMemory(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
void *buffer, /* Dummy: unused by this implementation */
|
||||
int size, /* Dummy: unused by this implementation */
|
||||
int codeSize, /* Dummy: unused by this implementation */
|
||||
Tcl_LoadHandle *loadHandle, /* Dummy: unused by this implementation */
|
||||
Tcl_FSUnloadFileProc **unloadProcPtr)
|
||||
/* Dummy: unused by this implementation */
|
||||
{
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("dynamic loading from memory "
|
||||
"is not available on this system", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
#endif /* TCL_LOAD_FROM_MEMORY */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+37
-61
@@ -160,23 +160,23 @@ static const Tcl_ObjType nsNameType = {
|
||||
*/
|
||||
|
||||
static const EnsembleImplMap defaultNamespaceMap[] = {
|
||||
{"children", NamespaceChildrenCmd, NULL, NULL, NULL, 0},
|
||||
{"children", NamespaceChildrenCmd, TclCompileBasic0To2ArgCmd, NULL, NULL, 0},
|
||||
{"code", NamespaceCodeCmd, TclCompileNamespaceCodeCmd, NULL, NULL, 0},
|
||||
{"current", NamespaceCurrentCmd, TclCompileNamespaceCurrentCmd, NULL, NULL, 0},
|
||||
{"delete", NamespaceDeleteCmd, NULL, NULL, NULL, 0},
|
||||
{"delete", NamespaceDeleteCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"ensemble", TclNamespaceEnsembleCmd, NULL, NULL, NULL, 0},
|
||||
{"eval", NamespaceEvalCmd, NULL, NRNamespaceEvalCmd, NULL, 0},
|
||||
{"exists", NamespaceExistsCmd, NULL, NULL, NULL, 0},
|
||||
{"export", NamespaceExportCmd, NULL, NULL, NULL, 0},
|
||||
{"forget", NamespaceForgetCmd, NULL, NULL, NULL, 0},
|
||||
{"import", NamespaceImportCmd, NULL, NULL, NULL, 0},
|
||||
{"exists", NamespaceExistsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"export", NamespaceExportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"forget", NamespaceForgetCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"import", NamespaceImportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"inscope", NamespaceInscopeCmd, NULL, NRNamespaceInscopeCmd, NULL, 0},
|
||||
{"origin", NamespaceOriginCmd, NULL, NULL, NULL, 0},
|
||||
{"parent", NamespaceParentCmd, NULL, NULL, NULL, 0},
|
||||
{"path", NamespacePathCmd, NULL, NULL, NULL, 0},
|
||||
{"origin", NamespaceOriginCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"parent", NamespaceParentCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"path", NamespacePathCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"qualifiers", NamespaceQualifiersCmd, TclCompileNamespaceQualifiersCmd, NULL, NULL, 0},
|
||||
{"tail", NamespaceTailCmd, TclCompileNamespaceTailCmd, NULL, NULL, 0},
|
||||
{"unknown", NamespaceUnknownCmd, NULL, NULL, NULL, 0},
|
||||
{"unknown", NamespaceUnknownCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"upvar", NamespaceUpvarCmd, TclCompileNamespaceUpvarCmd, NULL, NULL, 0},
|
||||
{"which", NamespaceWhichCmd, TclCompileNamespaceWhichCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
@@ -423,7 +423,7 @@ Tcl_PopCallFrame(
|
||||
framePtr->nsPtr = NULL;
|
||||
|
||||
if (framePtr->tailcallPtr) {
|
||||
TclSpliceTailcall(interp, framePtr->tailcallPtr);
|
||||
TclSetTailcall(interp, framePtr->tailcallPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,9 +505,9 @@ EstablishErrorCodeTraces(
|
||||
const char *name2,
|
||||
int flags)
|
||||
{
|
||||
Tcl_TraceVar(interp, "errorCode", TCL_GLOBAL_ONLY | TCL_TRACE_READS,
|
||||
Tcl_TraceVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS,
|
||||
ErrorCodeRead, NULL);
|
||||
Tcl_TraceVar(interp, "errorCode", TCL_GLOBAL_ONLY | TCL_TRACE_UNSETS,
|
||||
Tcl_TraceVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_UNSETS,
|
||||
EstablishErrorCodeTraces, NULL);
|
||||
return NULL;
|
||||
}
|
||||
@@ -579,9 +579,9 @@ EstablishErrorInfoTraces(
|
||||
const char *name2,
|
||||
int flags)
|
||||
{
|
||||
Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_READS,
|
||||
Tcl_TraceVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS,
|
||||
ErrorInfoRead, NULL);
|
||||
Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_UNSETS,
|
||||
Tcl_TraceVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_UNSETS,
|
||||
EstablishErrorInfoTraces, NULL);
|
||||
return NULL;
|
||||
}
|
||||
@@ -697,8 +697,7 @@ Tcl_CreateNamespace(
|
||||
* Find the parent for the new namespace.
|
||||
*/
|
||||
|
||||
TclGetNamespaceForQualName(interp, name, NULL,
|
||||
/*flags*/ (TCL_CREATE_NS_IF_UNKNOWN | TCL_LEAVE_ERR_MSG),
|
||||
TclGetNamespaceForQualName(interp, name, NULL, TCL_CREATE_NS_IF_UNKNOWN,
|
||||
&parentPtr, &dummy1Ptr, &dummy2Ptr, &simpleName);
|
||||
|
||||
/*
|
||||
@@ -1330,8 +1329,7 @@ Tcl_Export(
|
||||
* Check that the pattern doesn't have namespace qualifiers.
|
||||
*/
|
||||
|
||||
TclGetNamespaceForQualName(interp, pattern, nsPtr,
|
||||
/*flags*/ (TCL_LEAVE_ERR_MSG | TCL_NAMESPACE_ONLY),
|
||||
TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY,
|
||||
&exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
|
||||
|
||||
if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) {
|
||||
@@ -1545,8 +1543,7 @@ Tcl_Import(
|
||||
Tcl_SetErrorCode(interp, "TCL", "IMPORT", "EMPTY", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
TclGetNamespaceForQualName(interp, pattern, nsPtr,
|
||||
/*flags*/ (TCL_LEAVE_ERR_MSG | TCL_NAMESPACE_ONLY),
|
||||
TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY,
|
||||
&importNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
|
||||
|
||||
if (importNsPtr == NULL) {
|
||||
@@ -1791,8 +1788,7 @@ Tcl_ForgetImport(
|
||||
* simple pattern.
|
||||
*/
|
||||
|
||||
TclGetNamespaceForQualName(interp, pattern, nsPtr,
|
||||
/*flags*/ (TCL_LEAVE_ERR_MSG | TCL_NAMESPACE_ONLY),
|
||||
TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY,
|
||||
&sourceNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
|
||||
|
||||
if (sourceNsPtr == NULL) {
|
||||
@@ -1945,7 +1941,7 @@ InvokeImportedNRCmd(
|
||||
ImportedCmdData *dataPtr = clientData;
|
||||
Command *realCmdPtr = dataPtr->realCmdPtr;
|
||||
|
||||
((Interp *) interp)->evalFlags |= TCL_EVAL_REDIRECT;
|
||||
TclSkipTailcall(interp);
|
||||
return Tcl_NRCmdSwap(interp, (Tcl_Command) realCmdPtr, objc, objv, 0);
|
||||
}
|
||||
|
||||
@@ -3435,53 +3431,35 @@ NamespaceExportCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
|
||||
const char *pattern, *string;
|
||||
int resetListFirst = 0;
|
||||
int firstArg, patternCt, i, result;
|
||||
int firstArg, i;
|
||||
|
||||
if (objc < 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-clear? ?pattern pattern...?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the optional "-clear" argument.
|
||||
*/
|
||||
|
||||
firstArg = 1;
|
||||
if (firstArg < objc) {
|
||||
string = TclGetString(objv[firstArg]);
|
||||
if (strcmp(string, "-clear") == 0) {
|
||||
resetListFirst = 1;
|
||||
firstArg++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If no pattern arguments are given, and "-clear" isn't specified, return
|
||||
* the namespace's current export pattern list.
|
||||
*/
|
||||
|
||||
patternCt = objc - firstArg;
|
||||
if (patternCt == 0) {
|
||||
if (firstArg > 1) {
|
||||
return TCL_OK;
|
||||
} else {
|
||||
/*
|
||||
* Create list with export patterns.
|
||||
*/
|
||||
if (objc == 1) {
|
||||
Tcl_Obj *listPtr = Tcl_NewObj();
|
||||
|
||||
Tcl_Obj *listPtr = Tcl_NewListObj(0, NULL);
|
||||
(void) Tcl_AppendExportList(interp, NULL, listPtr);
|
||||
Tcl_SetObjResult(interp, listPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
result = Tcl_AppendExportList(interp, (Tcl_Namespace *) currNsPtr,
|
||||
listPtr);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
Tcl_SetObjResult(interp, listPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
/*
|
||||
* Process the optional "-clear" argument.
|
||||
*/
|
||||
|
||||
firstArg = 1;
|
||||
if (strcmp("-clear", Tcl_GetString(objv[firstArg])) == 0) {
|
||||
Tcl_Export(interp, NULL, "::", 1);
|
||||
Tcl_ResetResult(interp);
|
||||
firstArg++;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3489,9 +3467,7 @@ NamespaceExportCmd(
|
||||
*/
|
||||
|
||||
for (i = firstArg; i < objc; i++) {
|
||||
pattern = TclGetString(objv[i]);
|
||||
result = Tcl_Export(interp, (Tcl_Namespace *) currNsPtr, pattern,
|
||||
((i == firstArg)? resetListFirst : 0));
|
||||
int result = Tcl_Export(interp, NULL, Tcl_GetString(objv[i]), 0);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -843,7 +843,7 @@ ObjectRenamedTrace(
|
||||
result = Tcl_NRCallObjProc(interp, TclOOInvokeContext,
|
||||
contextPtr, 0, NULL);
|
||||
if (result != TCL_OK) {
|
||||
Tcl_BackgroundError(interp);
|
||||
Tcl_BackgroundException(interp, result);
|
||||
}
|
||||
Tcl_RestoreInterpState(interp, state);
|
||||
TclOODeleteContext(contextPtr);
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ extern const char *TclOOInitializeStubs(
|
||||
* win/tclooConfig.sh
|
||||
*/
|
||||
|
||||
#define TCLOO_VERSION "0.7"
|
||||
#define TCLOO_VERSION "1.0"
|
||||
#define TCLOO_PATCHLEVEL TCLOO_VERSION
|
||||
|
||||
/*
|
||||
|
||||
+27
-28
@@ -687,52 +687,51 @@ TclOO_Object_VarName(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const *objv) /* The actual arguments. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Var *varPtr, *aryVar;
|
||||
Tcl_Obj *varNamePtr;
|
||||
Tcl_Obj *varNamePtr, *argPtr;
|
||||
const char *arg;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
"varName");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
argPtr = objv[objc-1];
|
||||
arg = Tcl_GetString(argPtr);
|
||||
|
||||
/*
|
||||
* Switch to the object's namespace for the duration of this call. Like
|
||||
* this, the variable is looked up in the namespace of the object, and not
|
||||
* in the namespace of the caller. Otherwise this would only work if the
|
||||
* caller was a method of the object itself, which might not be true if
|
||||
* the method was exported. This is a bit of a hack, but the simplest way
|
||||
* to do this (pushing a stack frame would be horribly expensive by
|
||||
* comparison, and is only done when we'd otherwise interfere with the
|
||||
* global namespace).
|
||||
* Convert the variable name to fully-qualified form if it wasn't already.
|
||||
* This has to be done prior to lookup because we can run into problems
|
||||
* with resolvers otherwise. [Bug 3603695]
|
||||
*
|
||||
* We still need to do the lookup; the variable could be linked to another
|
||||
* variable and we want the target's name.
|
||||
*/
|
||||
|
||||
if (iPtr->varFramePtr == NULL) {
|
||||
Tcl_CallFrame *dummyFrame;
|
||||
|
||||
TclPushStackFrame(interp, &dummyFrame,
|
||||
Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context)),0);
|
||||
varPtr = TclObjLookupVar(interp, objv[objc-1], NULL,
|
||||
TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to",1,1,&aryVar);
|
||||
TclPopStackFrame(interp);
|
||||
if (arg[0] == ':' && arg[1] == ':') {
|
||||
varNamePtr = argPtr;
|
||||
} else {
|
||||
Namespace *savedNsPtr;
|
||||
|
||||
savedNsPtr = iPtr->varFramePtr->nsPtr;
|
||||
iPtr->varFramePtr->nsPtr = (Namespace *)
|
||||
Tcl_Namespace *namespacePtr =
|
||||
Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context));
|
||||
varPtr = TclObjLookupVar(interp, objv[objc-1], NULL,
|
||||
TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to",1,1,&aryVar);
|
||||
iPtr->varFramePtr->nsPtr = savedNsPtr;
|
||||
}
|
||||
|
||||
varNamePtr = Tcl_NewStringObj(namespacePtr->fullName, -1);
|
||||
Tcl_AppendToObj(varNamePtr, "::", 2);
|
||||
Tcl_AppendObjToObj(varNamePtr, argPtr);
|
||||
}
|
||||
Tcl_IncrRefCount(varNamePtr);
|
||||
varPtr = TclObjLookupVar(interp, varNamePtr, NULL,
|
||||
TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1, &aryVar);
|
||||
Tcl_DecrRefCount(varNamePtr);
|
||||
if (varPtr == NULL) {
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE",
|
||||
TclGetString(objv[objc-1]), NULL);
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we've pinned down what variable we're really talking about
|
||||
* (including traversing variable links), convert back to a name.
|
||||
*/
|
||||
|
||||
varNamePtr = Tcl_NewObj();
|
||||
if (aryVar != NULL) {
|
||||
Tcl_HashEntry *hPtr;
|
||||
|
||||
+5
-6
@@ -178,7 +178,7 @@ StashCallChain(
|
||||
callPtr->refCount++;
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &methodNameType;
|
||||
objPtr->internalRep.otherValuePtr = callPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = callPtr;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -205,10 +205,10 @@ DupMethodNameRep(
|
||||
Tcl_Obj *srcPtr,
|
||||
Tcl_Obj *dstPtr)
|
||||
{
|
||||
register CallChain *callPtr = srcPtr->internalRep.otherValuePtr;
|
||||
register CallChain *callPtr = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
dstPtr->typePtr = &methodNameType;
|
||||
dstPtr->internalRep.otherValuePtr = callPtr;
|
||||
dstPtr->internalRep.twoPtrValue.ptr1 = callPtr;
|
||||
callPtr->refCount++;
|
||||
}
|
||||
|
||||
@@ -216,10 +216,9 @@ static void
|
||||
FreeMethodNameRep(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
register CallChain *callPtr = objPtr->internalRep.otherValuePtr;
|
||||
register CallChain *callPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
TclOODeleteChain(callPtr);
|
||||
objPtr->internalRep.otherValuePtr = NULL;
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
@@ -952,7 +951,7 @@ TclOOGetCallContext(
|
||||
const int reuseMask = ((flags & PUBLIC_METHOD) ? ~0 : ~PUBLIC_METHOD);
|
||||
|
||||
if (cacheInThisObj->typePtr == &methodNameType) {
|
||||
callPtr = cacheInThisObj->internalRep.otherValuePtr;
|
||||
callPtr = cacheInThisObj->internalRep.twoPtrValue.ptr1;
|
||||
if (IsStillValid(callPtr, oPtr, flags, reuseMask)) {
|
||||
callPtr->refCount++;
|
||||
goto returnContext;
|
||||
|
||||
+29
-41
@@ -48,18 +48,18 @@ static Tcl_ObjCmdProc InfoClassVariablesCmd;
|
||||
*/
|
||||
|
||||
static const EnsembleImplMap infoObjectCmds[] = {
|
||||
{"call", InfoObjectCallCmd, NULL, NULL, NULL, 0},
|
||||
{"call", InfoObjectCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"class", InfoObjectClassCmd, TclCompileInfoObjectClassCmd, NULL, NULL, 0},
|
||||
{"definition", InfoObjectDefnCmd, NULL, NULL, NULL, 0},
|
||||
{"filters", InfoObjectFiltersCmd, NULL, NULL, NULL, 0},
|
||||
{"forward", InfoObjectForwardCmd, NULL, NULL, NULL, 0},
|
||||
{"definition", InfoObjectDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"filters", InfoObjectFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"forward", InfoObjectForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"isa", InfoObjectIsACmd, TclCompileInfoObjectIsACmd, NULL, NULL, 0},
|
||||
{"methods", InfoObjectMethodsCmd, NULL, NULL, NULL, 0},
|
||||
{"methodtype", InfoObjectMethodTypeCmd, NULL, NULL, NULL, 0},
|
||||
{"mixins", InfoObjectMixinsCmd, NULL, NULL, NULL, 0},
|
||||
{"methods", InfoObjectMethodsCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"methodtype", InfoObjectMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"mixins", InfoObjectMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"namespace", InfoObjectNsCmd, TclCompileInfoObjectNamespaceCmd, NULL, NULL, 0},
|
||||
{"variables", InfoObjectVariablesCmd, NULL, NULL, NULL, 0},
|
||||
{"vars", InfoObjectVarsCmd, NULL, NULL, NULL, 0},
|
||||
{"variables", InfoObjectVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"vars", InfoObjectVarsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
@@ -68,19 +68,19 @@ static const EnsembleImplMap infoObjectCmds[] = {
|
||||
*/
|
||||
|
||||
static const EnsembleImplMap infoClassCmds[] = {
|
||||
{"call", InfoClassCallCmd, NULL, NULL, NULL, 0},
|
||||
{"constructor", InfoClassConstrCmd, NULL, NULL, NULL, 0},
|
||||
{"definition", InfoClassDefnCmd, NULL, NULL, NULL, 0},
|
||||
{"destructor", InfoClassDestrCmd, NULL, NULL, NULL, 0},
|
||||
{"filters", InfoClassFiltersCmd, NULL, NULL, NULL, 0},
|
||||
{"forward", InfoClassForwardCmd, NULL, NULL, NULL, 0},
|
||||
{"instances", InfoClassInstancesCmd, NULL, NULL, NULL, 0},
|
||||
{"methods", InfoClassMethodsCmd, NULL, NULL, NULL, 0},
|
||||
{"methodtype", InfoClassMethodTypeCmd, NULL, NULL, NULL, 0},
|
||||
{"mixins", InfoClassMixinsCmd, NULL, NULL, NULL, 0},
|
||||
{"subclasses", InfoClassSubsCmd, NULL, NULL, NULL, 0},
|
||||
{"superclasses", InfoClassSupersCmd, NULL, NULL, NULL, 0},
|
||||
{"variables", InfoClassVariablesCmd, NULL, NULL, NULL, 0},
|
||||
{"call", InfoClassCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"constructor", InfoClassConstrCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"definition", InfoClassDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"destructor", InfoClassDestrCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"filters", InfoClassFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"forward", InfoClassForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"instances", InfoClassInstancesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"methods", InfoClassMethodsCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"methodtype", InfoClassMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"mixins", InfoClassMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"subclasses", InfoClassSubsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"superclasses", InfoClassSupersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"variables", InfoClassVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
@@ -100,6 +100,7 @@ TclOOInitInfo(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
Tcl_Command infoCmd;
|
||||
Tcl_Obj *mapDict;
|
||||
|
||||
/*
|
||||
* Build the ensembles used to implement [info object] and [info class].
|
||||
@@ -113,25 +114,12 @@ TclOOInitInfo(
|
||||
*/
|
||||
|
||||
infoCmd = Tcl_FindCommand(interp, "info", NULL, TCL_GLOBAL_ONLY);
|
||||
if (infoCmd != NULL && Tcl_IsEnsemble(infoCmd)) {
|
||||
Tcl_Obj *mapDict, *objectObj, *classObj;
|
||||
|
||||
Tcl_GetEnsembleMappingDict(NULL, infoCmd, &mapDict);
|
||||
if (mapDict != NULL) {
|
||||
objectObj = Tcl_NewStringObj("object", -1);
|
||||
classObj = Tcl_NewStringObj("class", -1);
|
||||
|
||||
Tcl_IncrRefCount(objectObj);
|
||||
Tcl_IncrRefCount(classObj);
|
||||
Tcl_DictObjPut(NULL, mapDict, objectObj,
|
||||
Tcl_NewStringObj("::oo::InfoObject", -1));
|
||||
Tcl_DictObjPut(NULL, mapDict, classObj,
|
||||
Tcl_NewStringObj("::oo::InfoClass", -1));
|
||||
Tcl_DecrRefCount(objectObj);
|
||||
Tcl_DecrRefCount(classObj);
|
||||
Tcl_SetEnsembleMappingDict(interp, infoCmd, mapDict);
|
||||
}
|
||||
}
|
||||
Tcl_GetEnsembleMappingDict(NULL, infoCmd, &mapDict);
|
||||
Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("object", -1),
|
||||
Tcl_NewStringObj("::oo::InfoObject", -1));
|
||||
Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("class", -1),
|
||||
Tcl_NewStringObj("::oo::InfoClass", -1));
|
||||
Tcl_SetEnsembleMappingDict(interp, infoCmd, mapDict);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -860,7 +860,7 @@ PushMethodCallFrame(
|
||||
|
||||
if (pmPtr->procPtr->bodyPtr->typePtr == &tclByteCodeType) {
|
||||
ByteCode *codePtr =
|
||||
pmPtr->procPtr->bodyPtr->internalRep.otherValuePtr;
|
||||
pmPtr->procPtr->bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
codePtr->nsPtr = nsPtr;
|
||||
}
|
||||
|
||||
+31
-47
@@ -2,19 +2,6 @@
|
||||
* ORIGINAL SOURCE: tk/generic/tkStubLib.c, version 1.9 2004/03/17
|
||||
*/
|
||||
|
||||
/*
|
||||
* We need to ensure that we use the tcl stub macros so that this file
|
||||
* contains no references to any of the tcl stub functions.
|
||||
*/
|
||||
|
||||
#undef USE_TCL_STUBS
|
||||
#define USE_TCL_STUBS
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define USE_TCLOO_STUBS 1
|
||||
#include "tclOOInt.h"
|
||||
|
||||
MODULE_SCOPE const TclOOStubs *tclOOStubsPtr;
|
||||
@@ -35,51 +22,48 @@ const TclOOIntStubs *tclOOIntStubsPtr = NULL;
|
||||
* to indicate that an error occurred.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets the stub table pointer.
|
||||
* Sets the stub table pointers.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE const char *
|
||||
TclOOInitializeStubs(
|
||||
Tcl_Interp *interp, const char *version)
|
||||
Tcl_Interp *interp,
|
||||
const char *version)
|
||||
{
|
||||
int exact = 0;
|
||||
const char *packageName = "TclOO";
|
||||
const char *errMsg = NULL;
|
||||
ClientData clientData = NULL;
|
||||
const char *actualVersion =
|
||||
Tcl_PkgRequireEx(interp, packageName,version, exact, &clientData);
|
||||
TclOOStubs *stubsPtr = NULL;
|
||||
const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
|
||||
packageName, version, exact, &stubsPtr);
|
||||
|
||||
if (clientData == NULL) {
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"error loading %s package; package not present or incomplete",
|
||||
packageName));
|
||||
return NULL;
|
||||
} else {
|
||||
const TclOOStubs * const stubsPtr = clientData;
|
||||
const TclOOIntStubs * const intStubsPtr = stubsPtr->hooks ?
|
||||
stubsPtr->hooks->tclOOIntStubs : NULL;
|
||||
|
||||
if (!actualVersion) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!stubsPtr || !intStubsPtr) {
|
||||
errMsg = "missing stub table pointer";
|
||||
goto error;
|
||||
}
|
||||
|
||||
tclOOStubsPtr = stubsPtr;
|
||||
tclOOIntStubsPtr = intStubsPtr;
|
||||
return actualVersion;
|
||||
|
||||
error:
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf("Error loading %s package"
|
||||
" (requested version '%s', loaded version '%s'): %s",
|
||||
packageName, version, actualVersion, errMsg));
|
||||
if (actualVersion == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (stubsPtr == NULL) {
|
||||
errMsg = "missing stub table pointer";
|
||||
} else {
|
||||
tclOOStubsPtr = stubsPtr;
|
||||
if (stubsPtr->hooks) {
|
||||
tclOOIntStubsPtr = stubsPtr->hooks->tclOOIntStubs;
|
||||
} else {
|
||||
tclOOIntStubsPtr = NULL;
|
||||
}
|
||||
return actualVersion;
|
||||
}
|
||||
tclStubsPtr->tcl_ResetResult(interp);
|
||||
tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName,
|
||||
" (requested version ", version, ", actual version ",
|
||||
actualVersion, "): ", errMsg, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
||||
|
||||
+32
-13
@@ -208,7 +208,6 @@ static Tcl_ThreadDataKey pendingObjDataKey;
|
||||
*/
|
||||
|
||||
static int ParseBoolean(Tcl_Obj *objPtr);
|
||||
static int SetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static void UpdateStringOfDouble(Tcl_Obj *objPtr);
|
||||
@@ -250,14 +249,14 @@ static const Tcl_ObjType oldBooleanType = {
|
||||
NULL, /* freeIntRepProc */
|
||||
NULL, /* dupIntRepProc */
|
||||
NULL, /* updateStringProc */
|
||||
SetBooleanFromAny /* setFromAnyProc */
|
||||
TclSetBooleanFromAny /* setFromAnyProc */
|
||||
};
|
||||
const Tcl_ObjType tclBooleanType = {
|
||||
"booleanString", /* name */
|
||||
NULL, /* freeIntRepProc */
|
||||
NULL, /* dupIntRepProc */
|
||||
NULL, /* updateStringProc */
|
||||
SetBooleanFromAny /* setFromAnyProc */
|
||||
TclSetBooleanFromAny /* setFromAnyProc */
|
||||
};
|
||||
const Tcl_ObjType tclDoubleType = {
|
||||
"double", /* name */
|
||||
@@ -1006,7 +1005,12 @@ Tcl_ConvertToType(
|
||||
*/
|
||||
|
||||
if (typePtr->setFromAnyProc == NULL) {
|
||||
Tcl_Panic("may not convert object to type %s", typePtr->name);
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"can't convert value to type %s", typePtr->name));
|
||||
Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return typePtr->setFromAnyProc(interp, objPtr);
|
||||
@@ -1255,7 +1259,7 @@ Tcl_DbNewObj(
|
||||
* Side effects:
|
||||
* tclFreeObjList, the head of the list of free Tcl_Objs, is set to the
|
||||
* first of a number of free Tcl_Obj's linked together by their
|
||||
* internalRep.otherValuePtrs.
|
||||
* internalRep.twoPtrValue.ptr1's.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1284,7 +1288,7 @@ TclAllocateFreeObjects(void)
|
||||
prevPtr = NULL;
|
||||
objPtr = (Tcl_Obj *) basePtr;
|
||||
for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) {
|
||||
objPtr->internalRep.otherValuePtr = prevPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = prevPtr;
|
||||
prevPtr = objPtr;
|
||||
objPtr++;
|
||||
}
|
||||
@@ -1329,9 +1333,21 @@ TclFreeObj(
|
||||
|
||||
ObjInitDeletionContext(context);
|
||||
|
||||
/*
|
||||
* Check for a double free of the same value. This is slightly tricky
|
||||
* because it is customary to free a Tcl_Obj when its refcount falls
|
||||
* either from 1 to 0, or from 0 to -1. Falling from -1 to -2, though,
|
||||
* and so on, is always a sign of a botch in the caller.
|
||||
*/
|
||||
if (objPtr->refCount < -1) {
|
||||
Tcl_Panic("Reference count for %p was negative", objPtr);
|
||||
}
|
||||
/*
|
||||
* Now, in case we just approved drop from 1 to 0 as acceptable, make
|
||||
* sure we do not accept a second free when falling from 0 to -1.
|
||||
* Skip that possibility so any double free will trigger the panic.
|
||||
*/
|
||||
objPtr->refCount = -1;
|
||||
|
||||
/*
|
||||
* Invalidate the string rep first so we can use the bytes value for our
|
||||
@@ -1729,8 +1745,8 @@ Tcl_InvalidateStringRep(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
#undef Tcl_NewBooleanObj
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
Tcl_Obj *
|
||||
Tcl_NewBooleanObj(
|
||||
@@ -1778,6 +1794,7 @@ Tcl_NewBooleanObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_DbNewBooleanObj
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
Tcl_Obj *
|
||||
@@ -1830,6 +1847,7 @@ Tcl_DbNewBooleanObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_SetBooleanObj
|
||||
void
|
||||
Tcl_SetBooleanObj(
|
||||
register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
|
||||
@@ -1911,7 +1929,7 @@ Tcl_GetBooleanFromObj(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* SetBooleanFromAny --
|
||||
* TclSetBooleanFromAny --
|
||||
*
|
||||
* Attempt to generate a boolean internal form for the Tcl object
|
||||
* "objPtr".
|
||||
@@ -1928,8 +1946,8 @@ Tcl_GetBooleanFromObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
SetBooleanFromAny(
|
||||
int
|
||||
TclSetBooleanFromAny(
|
||||
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
|
||||
register Tcl_Obj *objPtr) /* The object to convert. */
|
||||
{
|
||||
@@ -2389,8 +2407,8 @@ UpdateStringOfDouble(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
#undef Tcl_NewIntObj
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
Tcl_Obj *
|
||||
Tcl_NewIntObj(
|
||||
@@ -2430,6 +2448,7 @@ Tcl_NewIntObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_SetIntObj
|
||||
void
|
||||
Tcl_SetIntObj(
|
||||
register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
|
||||
@@ -4171,7 +4190,7 @@ Tcl_GetCommandFromObj(
|
||||
* had is invalid one way or another.
|
||||
*/
|
||||
|
||||
if (tclCmdNameType.setFromAnyProc(interp, objPtr) != TCL_OK) {
|
||||
if (SetCmdNameFromAny(interp, objPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
@@ -4390,7 +4409,7 @@ SetCmdNameFromAny(
|
||||
|
||||
if (cmdPtr) {
|
||||
cmdPtr->refCount++;
|
||||
resPtr = objPtr->internalRep.otherValuePtr;
|
||||
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if ((objPtr->typePtr == &tclCmdNameType)
|
||||
&& resPtr && (resPtr->refCount == 1)) {
|
||||
/*
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@
|
||||
* TYPE_BRACE - Character is a curly brace (either left or right).
|
||||
*/
|
||||
|
||||
const char charTypeTable[] = {
|
||||
const char tclCharTypeTable[] = {
|
||||
/*
|
||||
* Negative character values, from -128 to -1:
|
||||
*/
|
||||
|
||||
+2
-2
@@ -12,6 +12,6 @@
|
||||
#define TYPE_CLOSE_BRACK 0x20
|
||||
#define TYPE_BRACE 0x40
|
||||
|
||||
#define CHAR_TYPE(c) (charTypeTable+128)[(int)(c)]
|
||||
#define CHAR_TYPE(c) (tclCharTypeTable+128)[(int)(c)]
|
||||
|
||||
MODULE_SCOPE const char charTypeTable[];
|
||||
MODULE_SCOPE const char tclCharTypeTable[];
|
||||
|
||||
@@ -109,9 +109,9 @@ typedef struct FsPath {
|
||||
* fields.
|
||||
*/
|
||||
|
||||
#define PATHOBJ(pathPtr) ((FsPath *) (pathPtr)->internalRep.otherValuePtr)
|
||||
#define PATHOBJ(pathPtr) ((FsPath *) (pathPtr)->internalRep.twoPtrValue.ptr1)
|
||||
#define SETPATHOBJ(pathPtr,fsPathPtr) \
|
||||
((pathPtr)->internalRep.otherValuePtr = (void *) (fsPathPtr))
|
||||
((pathPtr)->internalRep.twoPtrValue.ptr1 = (void *) (fsPathPtr))
|
||||
#define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags)
|
||||
|
||||
/*
|
||||
@@ -1156,7 +1156,7 @@ Tcl_FSConvertToPathType(
|
||||
FreeFsPathInternalRep(pathPtr);
|
||||
}
|
||||
|
||||
return Tcl_ConvertToType(interp, pathPtr, &tclFsPathType);
|
||||
return SetFsPathFromAny(interp, pathPtr);
|
||||
|
||||
/*
|
||||
* We used to have more complex code here:
|
||||
@@ -1873,7 +1873,7 @@ Tcl_FSGetNormalizedPath(
|
||||
UpdateStringOfFsPath(pathPtr);
|
||||
}
|
||||
FreeFsPathInternalRep(pathPtr);
|
||||
if (Tcl_ConvertToType(interp, pathPtr, &tclFsPathType) != TCL_OK) {
|
||||
if (SetFsPathFromAny(interp, pathPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
fsPathPtr = PATHOBJ(pathPtr);
|
||||
|
||||
+9
-2
@@ -106,6 +106,7 @@ static const char * PkgRequireCore(Tcl_Interp *interp, const char *name,
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_PkgProvide
|
||||
int
|
||||
Tcl_PkgProvide(
|
||||
Tcl_Interp *interp, /* Interpreter in which package is now
|
||||
@@ -188,6 +189,7 @@ Tcl_PkgProvideEx(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_PkgRequire
|
||||
const char *
|
||||
Tcl_PkgRequire(
|
||||
Tcl_Interp *interp, /* Interpreter in which package is now
|
||||
@@ -356,6 +358,10 @@ PkgRequireCore(
|
||||
char *script, *pkgVersionI;
|
||||
Tcl_DString command;
|
||||
|
||||
if (TCL_OK != CheckAllRequirements(interp, reqc, reqv)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* It can take up to three passes to find the package: one pass to run the
|
||||
* "package unknown" script, one to run the "package ifneeded" script for
|
||||
@@ -666,6 +672,7 @@ PkgRequireCore(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_PkgPresent
|
||||
const char *
|
||||
Tcl_PkgPresent(
|
||||
Tcl_Interp *interp, /* Interpreter in which package is now
|
||||
@@ -942,7 +949,7 @@ Tcl_PackageObjCmd(
|
||||
version = TclGetString(objv[3]);
|
||||
}
|
||||
}
|
||||
Tcl_PkgPresent(interp, name, version, exact);
|
||||
Tcl_PkgPresentEx(interp, name, version, exact, NULL);
|
||||
return TCL_ERROR;
|
||||
break;
|
||||
}
|
||||
@@ -967,7 +974,7 @@ Tcl_PackageObjCmd(
|
||||
if (CheckVersionAndConvert(interp, argv3, NULL, NULL) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return Tcl_PkgProvide(interp, argv2, argv3);
|
||||
return Tcl_PkgProvideEx(interp, argv2, argv3, NULL);
|
||||
case PKG_REQUIRE:
|
||||
require:
|
||||
if (objc < 3) {
|
||||
|
||||
+2
-3
@@ -19,11 +19,10 @@
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
# include "tclWinPort.h"
|
||||
#endif
|
||||
#include "tcl.h"
|
||||
#if !defined(_WIN32)
|
||||
#else
|
||||
# include "tclUnixPort.h"
|
||||
#endif
|
||||
#include "tcl.h"
|
||||
|
||||
#if !defined(LLONG_MIN)
|
||||
# ifdef TCL_WIDE_INT_IS_LONG
|
||||
|
||||
+19
-30
@@ -421,7 +421,7 @@ TclCreateProc(
|
||||
* will be holding a reference to it.
|
||||
*/
|
||||
|
||||
procPtr = bodyPtr->internalRep.otherValuePtr;
|
||||
procPtr = bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
procPtr->iPtr = iPtr;
|
||||
procPtr->refCount++;
|
||||
precompiled = 1;
|
||||
@@ -1197,7 +1197,7 @@ TclInitCompiledLocals(
|
||||
if (bodyPtr->typePtr != &tclByteCodeType) {
|
||||
Tcl_Panic("body object for proc attached to frame is not a byte code type");
|
||||
}
|
||||
codePtr = bodyPtr->internalRep.otherValuePtr;
|
||||
codePtr = bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
if (framePtr->numCompiledLocals) {
|
||||
if (!codePtr->localCachePtr) {
|
||||
@@ -1347,17 +1347,9 @@ TclFreeLocalCache(
|
||||
for (i = 0; i < localCachePtr->numVars; i++, namePtrPtr++) {
|
||||
register Tcl_Obj *objPtr = *namePtrPtr;
|
||||
|
||||
/*
|
||||
* Note that this can be called with interp==NULL, on interp deletion.
|
||||
* In that case, the literal table and objects go away on their own.
|
||||
*/
|
||||
|
||||
if (objPtr) {
|
||||
if (interp) {
|
||||
TclReleaseLiteral(interp, objPtr);
|
||||
} else {
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
/* TclReleaseLiteral calls Tcl_DecrRefCount for us */
|
||||
TclReleaseLiteral(interp, objPtr);
|
||||
}
|
||||
}
|
||||
ckfree(localCachePtr);
|
||||
@@ -1368,7 +1360,7 @@ InitLocalCache(
|
||||
Proc *procPtr)
|
||||
{
|
||||
Interp *iPtr = procPtr->iPtr;
|
||||
ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
|
||||
ByteCode *codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
int localCt = procPtr->numCompiledLocals;
|
||||
int numArgs = procPtr->numArgs, i = 0;
|
||||
|
||||
@@ -1445,7 +1437,7 @@ InitArgsAndLocals(
|
||||
{
|
||||
CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
|
||||
register Proc *procPtr = framePtr->procPtr;
|
||||
ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
|
||||
ByteCode *codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
register Var *varPtr, *defPtr;
|
||||
int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax;
|
||||
Tcl_Obj *const *argObjs;
|
||||
@@ -1632,7 +1624,7 @@ PushProcCallFrame(
|
||||
* commands and/or resolver changes are considered).
|
||||
*/
|
||||
|
||||
codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
|
||||
codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (((Interp *) *codePtr->interpHandle != iPtr)
|
||||
|| (codePtr->compileEpoch != iPtr->compileEpoch)
|
||||
|| (codePtr->nsPtr != nsPtr)
|
||||
@@ -1833,7 +1825,7 @@ TclNRInterpProcCore(
|
||||
*/
|
||||
|
||||
procPtr->refCount++;
|
||||
codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
|
||||
codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc,
|
||||
NULL, NULL);
|
||||
@@ -1975,7 +1967,7 @@ TclProcCompileProc(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_CallFrame *framePtr;
|
||||
ByteCode *codePtr = bodyPtr->internalRep.otherValuePtr;
|
||||
ByteCode *codePtr = bodyPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
/*
|
||||
* If necessary, compile the procedure's body. The compiler will allocate
|
||||
@@ -2095,7 +2087,7 @@ TclProcCompileProc(
|
||||
|
||||
iPtr->invokeWord = 0;
|
||||
iPtr->invokeCmdFramePtr = (hePtr ? Tcl_GetHashValue(hePtr) : NULL);
|
||||
tclByteCodeType.setFromAnyProc(interp, bodyPtr);
|
||||
TclSetByteCodeFromAny(interp, bodyPtr, NULL, NULL);
|
||||
iPtr->invokeCmdFramePtr = NULL;
|
||||
TclPopStackFrame(interp);
|
||||
} else if (codePtr->nsEpoch != nsPtr->resolverEpoch) {
|
||||
@@ -2365,7 +2357,7 @@ TclNewProcBodyObj(
|
||||
TclNewObj(objPtr);
|
||||
if (objPtr) {
|
||||
objPtr->typePtr = &tclProcBodyType;
|
||||
objPtr->internalRep.otherValuePtr = procPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = procPtr;
|
||||
|
||||
procPtr->refCount++;
|
||||
}
|
||||
@@ -2395,10 +2387,10 @@ ProcBodyDup(
|
||||
Tcl_Obj *srcPtr, /* Object to copy. */
|
||||
Tcl_Obj *dupPtr) /* Target object for the duplication. */
|
||||
{
|
||||
Proc *procPtr = srcPtr->internalRep.otherValuePtr;
|
||||
Proc *procPtr = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
dupPtr->typePtr = &tclProcBodyType;
|
||||
dupPtr->internalRep.otherValuePtr = procPtr;
|
||||
dupPtr->internalRep.twoPtrValue.ptr1 = procPtr;
|
||||
procPtr->refCount++;
|
||||
}
|
||||
|
||||
@@ -2425,10 +2417,9 @@ static void
|
||||
ProcBodyFree(
|
||||
Tcl_Obj *objPtr) /* The object to clean up. */
|
||||
{
|
||||
Proc *procPtr = objPtr->internalRep.otherValuePtr;
|
||||
Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
procPtr->refCount--;
|
||||
if (procPtr->refCount <= 0) {
|
||||
if (procPtr->refCount-- < 2) {
|
||||
TclProcCleanupProc(procPtr);
|
||||
}
|
||||
}
|
||||
@@ -2721,7 +2712,6 @@ TclNRApplyObjCmd(
|
||||
else {
|
||||
/*
|
||||
* Joe English's suggestion to allow cmdNames to function as lambdas.
|
||||
* Also requires making tclCmdNameType non-static in tclObj.c
|
||||
*/
|
||||
|
||||
Tcl_Obj *elemPtr;
|
||||
@@ -2961,10 +2951,9 @@ Tcl_DisassembleObjCmd(
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "script");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objv[2]->typePtr != &tclByteCodeType) {
|
||||
if (TclSetByteCodeFromAny(interp, objv[2], NULL, NULL) != TCL_OK){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if ((objv[2]->typePtr != &tclByteCodeType)
|
||||
&& (TclSetByteCodeFromAny(interp, objv[2], NULL, NULL) != TCL_OK)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
codeObjPtr = objv[2];
|
||||
break;
|
||||
@@ -3061,7 +3050,7 @@ Tcl_DisassembleObjCmd(
|
||||
* Do the actual disassembly.
|
||||
*/
|
||||
|
||||
if (((ByteCode *) codeObjPtr->internalRep.otherValuePtr)->flags
|
||||
if (((ByteCode *) codeObjPtr->internalRep.twoPtrValue.ptr1)->flags
|
||||
& TCL_BYTECODE_PRECOMPILED) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"may not disassemble prebuilt bytecode", -1));
|
||||
|
||||
+5
-5
@@ -578,7 +578,7 @@ Tcl_GetRegExpFromObj(
|
||||
* TclRegexp* when the type is tclRegexpType.
|
||||
*/
|
||||
|
||||
regexpPtr = objPtr->internalRep.otherValuePtr;
|
||||
regexpPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
if ((objPtr->typePtr != &tclRegexpType) || (regexpPtr->flags != flags)) {
|
||||
pattern = TclGetStringFromObj(objPtr, &length);
|
||||
@@ -601,7 +601,7 @@ Tcl_GetRegExpFromObj(
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.otherValuePtr = regexpPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = regexpPtr;
|
||||
objPtr->typePtr = &tclRegexpType;
|
||||
}
|
||||
return (Tcl_RegExp) regexpPtr;
|
||||
@@ -749,7 +749,7 @@ static void
|
||||
FreeRegexpInternalRep(
|
||||
Tcl_Obj *objPtr) /* Regexp object with internal rep to free. */
|
||||
{
|
||||
TclRegexp *regexpRepPtr = objPtr->internalRep.otherValuePtr;
|
||||
TclRegexp *regexpRepPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
/*
|
||||
* If this is the last reference to the regexp, free it.
|
||||
@@ -783,10 +783,10 @@ DupRegexpInternalRep(
|
||||
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
|
||||
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
|
||||
{
|
||||
TclRegexp *regexpPtr = srcPtr->internalRep.otherValuePtr;
|
||||
TclRegexp *regexpPtr = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
regexpPtr->refCount++;
|
||||
copyPtr->internalRep.otherValuePtr = srcPtr->internalRep.otherValuePtr;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
copyPtr->typePtr = &tclRegexpType;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -230,6 +230,7 @@ Tcl_DiscardInterpState(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_SaveResult
|
||||
void
|
||||
Tcl_SaveResult(
|
||||
Tcl_Interp *interp, /* Interpreter to save. */
|
||||
@@ -304,6 +305,7 @@ Tcl_SaveResult(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_RestoreResult
|
||||
void
|
||||
Tcl_RestoreResult(
|
||||
Tcl_Interp *interp, /* Interpreter being restored. */
|
||||
@@ -372,6 +374,7 @@ Tcl_RestoreResult(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_DiscardResult
|
||||
void
|
||||
Tcl_DiscardResult(
|
||||
Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */
|
||||
@@ -1587,7 +1590,7 @@ Tcl_GetReturnOptions(
|
||||
}
|
||||
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AddObjErrorInfo(interp, "", -1);
|
||||
Tcl_AddErrorInfo(interp, "");
|
||||
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack);
|
||||
}
|
||||
if (iPtr->errorCode) {
|
||||
|
||||
@@ -140,9 +140,9 @@ typedef struct String {
|
||||
#define stringAttemptRealloc(ptr, numChars) \
|
||||
(String *) attemptckrealloc((ptr), (unsigned) STRING_SIZE(numChars) )
|
||||
#define GET_STRING(objPtr) \
|
||||
((String *) (objPtr)->internalRep.otherValuePtr)
|
||||
((String *) (objPtr)->internalRep.twoPtrValue.ptr1)
|
||||
#define SET_STRING(objPtr, stringPtr) \
|
||||
((objPtr)->internalRep.otherValuePtr = (void *) (stringPtr))
|
||||
((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (stringPtr))
|
||||
|
||||
/*
|
||||
* TCL STRING GROWTH ALGORITHM
|
||||
|
||||
+40
-9
@@ -41,6 +41,8 @@
|
||||
#undef Tcl_FindExecutable
|
||||
#undef TclpGetPid
|
||||
#undef TclSockMinimumBuffers
|
||||
#define TclBackgroundException Tcl_BackgroundException
|
||||
#undef Tcl_SetIntObj
|
||||
|
||||
/* See bug 510001: TclSockMinimumBuffers needs plat imp */
|
||||
#ifdef _WIN64
|
||||
@@ -53,6 +55,31 @@ static int TclSockMinimumBuffersOld(int sock, int size)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TclSetStartupScriptPath setStartupScriptPath
|
||||
static void TclSetStartupScriptPath(Tcl_Obj *path)
|
||||
{
|
||||
Tcl_SetStartupScript(path, NULL);
|
||||
}
|
||||
#define TclGetStartupScriptPath getStartupScriptPath
|
||||
static Tcl_Obj *TclGetStartupScriptPath(void)
|
||||
{
|
||||
return Tcl_GetStartupScript(NULL);
|
||||
}
|
||||
#define TclSetStartupScriptFileName setStartupScriptFileName
|
||||
static void TclSetStartupScriptFileName(
|
||||
const char *fileName)
|
||||
{
|
||||
Tcl_SetStartupScript(Tcl_NewStringObj(fileName,-1), NULL);
|
||||
}
|
||||
#define TclGetStartupScriptFileName getStartupScriptFileName
|
||||
static const char *TclGetStartupScriptFileName(void)
|
||||
{
|
||||
Tcl_Obj *path = Tcl_GetStartupScript(NULL);
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return Tcl_GetStringFromObj(path, NULL);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#undef TclWinNToHS
|
||||
@@ -65,6 +92,7 @@ static unsigned short TclWinNToHS(unsigned short ns) {
|
||||
#ifdef __WIN32__
|
||||
# define TclUnixWaitForFile 0
|
||||
# define TclUnixCopyFile 0
|
||||
# define TclUnixOpenTemporaryFile 0
|
||||
# define TclpReaddir 0
|
||||
# define TclpIsAtty 0
|
||||
#elif defined(__CYGWIN__)
|
||||
@@ -346,8 +374,8 @@ static const TclIntStubs tclIntStubs = {
|
||||
0, /* 155 */
|
||||
TclRegError, /* 156 */
|
||||
TclVarTraceExists, /* 157 */
|
||||
0, /* 158 */
|
||||
0, /* 159 */
|
||||
TclSetStartupScriptFileName, /* 158 */
|
||||
TclGetStartupScriptFileName, /* 159 */
|
||||
0, /* 160 */
|
||||
TclChannelTransform, /* 161 */
|
||||
TclChannelEventScriptInvoker, /* 162 */
|
||||
@@ -355,8 +383,8 @@ static const TclIntStubs tclIntStubs = {
|
||||
TclExpandCodeArray, /* 164 */
|
||||
TclpSetInitialEncodings, /* 165 */
|
||||
TclListObjSetElement, /* 166 */
|
||||
0, /* 167 */
|
||||
0, /* 168 */
|
||||
TclSetStartupScriptPath, /* 167 */
|
||||
TclGetStartupScriptPath, /* 168 */
|
||||
TclpUtfNcmp2, /* 169 */
|
||||
TclCheckInterpTraces, /* 170 */
|
||||
TclCheckExecutionTraces, /* 171 */
|
||||
@@ -366,8 +394,8 @@ static const TclIntStubs tclIntStubs = {
|
||||
TclCallVarTraces, /* 175 */
|
||||
TclCleanupVar, /* 176 */
|
||||
TclVarErrMsg, /* 177 */
|
||||
0, /* 178 */
|
||||
0, /* 179 */
|
||||
Tcl_SetStartupScript, /* 178 */
|
||||
Tcl_GetStartupScript, /* 179 */
|
||||
0, /* 180 */
|
||||
0, /* 181 */
|
||||
TclpLocaltime, /* 182 */
|
||||
@@ -424,7 +452,7 @@ static const TclIntStubs tclIntStubs = {
|
||||
TclGetSrcInfoForPc, /* 233 */
|
||||
TclVarHashCreateVar, /* 234 */
|
||||
TclInitVarHashTable, /* 235 */
|
||||
0, /* 236 */
|
||||
TclBackgroundException, /* 236 */
|
||||
TclResetCancellation, /* 237 */
|
||||
TclNRInterpProc, /* 238 */
|
||||
TclNRInterpProcCore, /* 239 */
|
||||
@@ -465,7 +493,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
0, /* 17 */
|
||||
0, /* 18 */
|
||||
0, /* 19 */
|
||||
TclUnixOpenTemporaryFile, /* 20 */
|
||||
0, /* 20 */
|
||||
0, /* 21 */
|
||||
0, /* 22 */
|
||||
0, /* 23 */
|
||||
@@ -475,6 +503,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
0, /* 27 */
|
||||
0, /* 28 */
|
||||
TclWinCPUID, /* 29 */
|
||||
TclUnixOpenTemporaryFile, /* 30 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
TclWinConvertError, /* 0 */
|
||||
@@ -507,6 +536,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
TclWinFlushDirtyChannels, /* 27 */
|
||||
TclWinResetInterfaces, /* 28 */
|
||||
TclWinCPUID, /* 29 */
|
||||
TclUnixOpenTemporaryFile, /* 30 */
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
TclGetAndDetachPids, /* 0 */
|
||||
@@ -529,7 +559,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
TclMacOSXCopyFileAttributes, /* 17 */
|
||||
TclMacOSXMatchType, /* 18 */
|
||||
TclMacOSXNotifierAddRunLoopMode, /* 19 */
|
||||
TclUnixOpenTemporaryFile, /* 20 */
|
||||
0, /* 20 */
|
||||
0, /* 21 */
|
||||
0, /* 22 */
|
||||
0, /* 23 */
|
||||
@@ -539,6 +569,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
0, /* 27 */
|
||||
0, /* 28 */
|
||||
TclWinCPUID, /* 29 */
|
||||
TclUnixOpenTemporaryFile, /* 30 */
|
||||
#endif /* MACOSX */
|
||||
};
|
||||
|
||||
|
||||
+12
-34
@@ -11,15 +11,6 @@
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We need to ensure that we use the stub macros so that this file contains no
|
||||
* references to any of the stub functions. This will make it possible to
|
||||
* build an extension that references Tcl_InitStubs but doesn't end up
|
||||
* including the rest of the stub functions.
|
||||
*/
|
||||
|
||||
#define USE_TCL_STUBS
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
MODULE_SCOPE const TclStubs *tclStubsPtr;
|
||||
@@ -32,24 +23,8 @@ const TclPlatStubs *tclPlatStubsPtr = NULL;
|
||||
const TclIntStubs *tclIntStubsPtr = NULL;
|
||||
const TclIntPlatStubs *tclIntPlatStubsPtr = NULL;
|
||||
|
||||
static const TclStubs *
|
||||
HasStubSupport(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) {
|
||||
return iPtr->stubTable;
|
||||
}
|
||||
|
||||
iPtr->result =
|
||||
(char *)"This interpreter does not support stubs-enabled extensions.";
|
||||
iPtr->freeProc = TCL_STATIC;
|
||||
return 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)
|
||||
@@ -74,15 +49,17 @@ static int isDigit(const int c)
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_InitStubs
|
||||
MODULE_SCOPE const char *
|
||||
Tcl_InitStubs(
|
||||
Tcl_Interp *interp,
|
||||
const char *version,
|
||||
int exact)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
const char *actualVersion = NULL;
|
||||
ClientData pkgData = NULL;
|
||||
const TclStubs *stubsPtr = iPtr->stubTable;
|
||||
|
||||
/*
|
||||
* We can't optimize this check by caching tclStubsPtr because that
|
||||
@@ -90,12 +67,13 @@ Tcl_InitStubs(
|
||||
* times. [Bug 615304]
|
||||
*/
|
||||
|
||||
tclStubsPtr = HasStubSupport(interp);
|
||||
if (!tclStubsPtr) {
|
||||
if (!stubsPtr || (stubsPtr->magic != TCL_STUB_MAGIC)) {
|
||||
iPtr->result = "interpreter uses an incompatible stubs mechanism";
|
||||
iPtr->freeProc = TCL_STATIC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData);
|
||||
actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData);
|
||||
if (actualVersion == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -113,19 +91,19 @@ Tcl_InitStubs(
|
||||
while (*p && (*p == *q)) {
|
||||
p++; q++;
|
||||
}
|
||||
if (*p) {
|
||||
if (*p || isDigit(*q)) {
|
||||
/* Construct error message */
|
||||
Tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
|
||||
stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
|
||||
actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
|
||||
if (actualVersion == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
tclStubsPtr = (TclStubs *) pkgData;
|
||||
tclStubsPtr = (TclStubs *)pkgData;
|
||||
|
||||
if (tclStubsPtr->hooks) {
|
||||
tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs;
|
||||
|
||||
+20
-4
@@ -327,10 +327,12 @@ static int TestreturnObjCmd(ClientData dummy,
|
||||
Tcl_Obj *const objv[]);
|
||||
static void TestregexpXflags(const char *string,
|
||||
int length, int *cflagsPtr, int *eflagsPtr);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
static int TestsaveresultCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static void TestsaveresultFree(char *blockPtr);
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
static int TestsetassocdataCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int argc, const char **argv);
|
||||
static int TestsetCmd(ClientData dummy,
|
||||
@@ -523,7 +525,9 @@ int
|
||||
Tcltest_Init(
|
||||
Tcl_Interp *interp) /* Interpreter for application. */
|
||||
{
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
Tcl_ValueType t3ArgTypes[2];
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
Tcl_Obj *listPtr;
|
||||
Tcl_Obj **objv;
|
||||
@@ -642,8 +646,10 @@ Tcltest_Init(
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
|
||||
NULL, NULL);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd,
|
||||
NULL, NULL);
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
|
||||
@@ -665,8 +671,10 @@ Tcltest_Init(
|
||||
Tcl_CreateCommand(interp, "testtranslatefilename",
|
||||
TesttranslatefilenameCmd, NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
Tcl_CreateMathFunc(interp, "T1", 0, NULL, TestMathFunc, (ClientData) 123);
|
||||
Tcl_CreateMathFunc(interp, "T2", 0, NULL, TestMathFunc, (ClientData) 345);
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, NULL,
|
||||
NULL);
|
||||
Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
|
||||
@@ -677,10 +685,12 @@ Tcltest_Init(
|
||||
Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd,
|
||||
(ClientData) 0, NULL);
|
||||
#endif
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
t3ArgTypes[0] = TCL_EITHER;
|
||||
t3ArgTypes[1] = TCL_EITHER;
|
||||
Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2,
|
||||
NULL);
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
Tcl_CreateObjCommand(interp, "testnrelevels", TestNRELevels,
|
||||
NULL, NULL);
|
||||
@@ -5003,6 +5013,7 @@ Testset2Cmd(
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -5136,6 +5147,7 @@ TestsaveresultFree(
|
||||
{
|
||||
freeCount++;
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -6170,7 +6182,7 @@ TestReport(
|
||||
* API, but there you go. We should convert it to objects.
|
||||
*/
|
||||
|
||||
Tcl_SavedResult savedResult;
|
||||
Tcl_Obj *savedResult;
|
||||
Tcl_DString ds;
|
||||
|
||||
Tcl_DStringInit(&ds);
|
||||
@@ -6184,11 +6196,15 @@ TestReport(
|
||||
Tcl_DStringAppendElement(&ds, Tcl_GetString(arg2));
|
||||
}
|
||||
Tcl_DStringEndSublist(&ds);
|
||||
Tcl_SaveResult(interp, &savedResult);
|
||||
savedResult = Tcl_GetObjResult(interp);
|
||||
Tcl_IncrRefCount(savedResult);
|
||||
Tcl_SetObjResult(interp, Tcl_NewObj());
|
||||
Tcl_Eval(interp, Tcl_DStringValue(&ds));
|
||||
Tcl_DStringFree(&ds);
|
||||
Tcl_RestoreResult(interp, &savedResult);
|
||||
}
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetObjResult(interp, savedResult);
|
||||
Tcl_DecrRefCount(savedResult);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
+15
-4
@@ -555,7 +555,7 @@ TestindexobjCmd(
|
||||
}
|
||||
|
||||
Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index);
|
||||
indexRep = objv[1]->internalRep.otherValuePtr;
|
||||
indexRep = objv[1]->internalRep.twoPtrValue.ptr1;
|
||||
indexRep->index = index2;
|
||||
result = Tcl_GetIndexFromObj(NULL, objv[1],
|
||||
tablePtr, "token", 0, &index);
|
||||
@@ -592,7 +592,7 @@ TestindexobjCmd(
|
||||
|
||||
if (objv[3]->typePtr != NULL
|
||||
&& !strcmp("index", objv[3]->typePtr->name)) {
|
||||
indexRep = objv[3]->internalRep.otherValuePtr;
|
||||
indexRep = objv[3]->internalRep.twoPtrValue.ptr1;
|
||||
if (indexRep->tablePtr == (void *) argv) {
|
||||
TclFreeIntRep(objv[3]);
|
||||
}
|
||||
@@ -963,6 +963,17 @@ TestobjCmd(
|
||||
}
|
||||
SetVarToObj(varPtr, destIndex, varPtr[varIndex]);
|
||||
Tcl_SetObjResult(interp, varPtr[destIndex]);
|
||||
} else if (strcmp(subCmd, "bug3598580") == 0) {
|
||||
Tcl_Obj *listObjPtr, *elemObjPtr;
|
||||
if (objc != 2) {
|
||||
goto wrongNumArgs;
|
||||
}
|
||||
elemObjPtr = Tcl_NewIntObj(123);
|
||||
listObjPtr = Tcl_NewListObj(1, &elemObjPtr);
|
||||
/* Replace the single list element through itself, nonsense but legal. */
|
||||
Tcl_ListObjReplace(interp, listObjPtr, 0, 1, 1, &elemObjPtr);
|
||||
Tcl_SetObjResult(interp, listObjPtr);
|
||||
return TCL_OK;
|
||||
} else if (strcmp(subCmd, "convert") == 0) {
|
||||
const char *typeName;
|
||||
|
||||
@@ -1239,7 +1250,7 @@ TeststringobjCmd(
|
||||
if (varPtr[varIndex] != NULL) {
|
||||
Tcl_ConvertToType(NULL, varPtr[varIndex],
|
||||
Tcl_GetObjType("string"));
|
||||
strPtr = varPtr[varIndex]->internalRep.otherValuePtr;
|
||||
strPtr = varPtr[varIndex]->internalRep.twoPtrValue.ptr1;
|
||||
length = (int) strPtr->allocated;
|
||||
} else {
|
||||
length = -1;
|
||||
@@ -1293,7 +1304,7 @@ TeststringobjCmd(
|
||||
if (varPtr[varIndex] != NULL) {
|
||||
Tcl_ConvertToType(NULL, varPtr[varIndex],
|
||||
Tcl_GetObjType("string"));
|
||||
strPtr = varPtr[varIndex]->internalRep.otherValuePtr;
|
||||
strPtr = varPtr[varIndex]->internalRep.twoPtrValue.ptr1;
|
||||
length = strPtr->maxChars;
|
||||
} else {
|
||||
length = -1;
|
||||
|
||||
@@ -573,7 +573,7 @@ TclThreadAllocObj(void)
|
||||
}
|
||||
while (--numMove >= 0) {
|
||||
objPtr = &newObjsPtr[numMove];
|
||||
objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr;
|
||||
cachePtr->firstObjPtr = objPtr;
|
||||
}
|
||||
}
|
||||
@@ -584,7 +584,7 @@ TclThreadAllocObj(void)
|
||||
*/
|
||||
|
||||
objPtr = cachePtr->firstObjPtr;
|
||||
cachePtr->firstObjPtr = objPtr->internalRep.otherValuePtr;
|
||||
cachePtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
cachePtr->numObjects--;
|
||||
return objPtr;
|
||||
}
|
||||
@@ -621,7 +621,7 @@ TclThreadFreeObj(
|
||||
* Get this thread's list and push on the free Tcl_Obj.
|
||||
*/
|
||||
|
||||
objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr;
|
||||
cachePtr->firstObjPtr = objPtr;
|
||||
cachePtr->numObjects++;
|
||||
|
||||
@@ -722,16 +722,16 @@ MoveObjs(
|
||||
*/
|
||||
|
||||
while (--numMove) {
|
||||
objPtr = objPtr->internalRep.otherValuePtr;
|
||||
objPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr;
|
||||
fromPtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
/*
|
||||
* Move all objects as a block - they are already linked to each other, we
|
||||
* just have to update the first and last.
|
||||
*/
|
||||
|
||||
objPtr->internalRep.otherValuePtr = toPtr->firstObjPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = toPtr->firstObjPtr;
|
||||
toPtr->firstObjPtr = fromFirstObjPtr;
|
||||
}
|
||||
|
||||
|
||||
@@ -513,7 +513,6 @@ ThreadCreate(
|
||||
TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) {
|
||||
Tcl_MutexUnlock(&threadMutex);
|
||||
Tcl_AppendResult(interp, "can't create a new thread", NULL);
|
||||
ckfree(ctrl.script);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -927,10 +926,11 @@ ThreadSend(
|
||||
ckfree(resultPtr->errorInfo);
|
||||
}
|
||||
}
|
||||
Tcl_SetResult(interp, resultPtr->result, TCL_DYNAMIC);
|
||||
Tcl_AppendResult(interp, resultPtr->result, NULL);
|
||||
Tcl_ConditionFinalize(&resultPtr->done);
|
||||
code = resultPtr->code;
|
||||
|
||||
ckfree(resultPtr->result);
|
||||
ckfree(resultPtr);
|
||||
|
||||
return code;
|
||||
|
||||
@@ -111,7 +111,7 @@ extern void *
|
||||
TclBNAlloc(
|
||||
size_t x)
|
||||
{
|
||||
return (void *) Tcl_Alloc((unsigned int) x);
|
||||
return (void *) ckalloc((unsigned int) x);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -135,7 +135,7 @@ TclBNRealloc(
|
||||
void *p,
|
||||
size_t s)
|
||||
{
|
||||
return (void *) Tcl_Realloc((char *) p, (unsigned int) s);
|
||||
return (void *) ckrealloc((char *) p, (unsigned int) s);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -161,7 +161,7 @@ extern void
|
||||
TclBNFree(
|
||||
void *p)
|
||||
{
|
||||
Tcl_Free((char *) p);
|
||||
ckree((char *) p);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+11
-21
@@ -11,15 +11,6 @@
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We need to ensure that we use the stub macros so that this file contains no
|
||||
* references to any of the stub functions. This will make it possible to
|
||||
* build an extension that references Tcl_InitStubs but doesn't end up
|
||||
* including the rest of the stub functions.
|
||||
*/
|
||||
|
||||
#define USE_TCL_STUBS
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
MODULE_SCOPE const TclTomMathStubs *tclTomMathStubsPtr;
|
||||
@@ -55,31 +46,30 @@ TclTomMathInitializeStubs(
|
||||
int exact = 0;
|
||||
const char *packageName = "tcl::tommath";
|
||||
const char *errMsg = NULL;
|
||||
ClientData pkgClientData = NULL;
|
||||
const char *actualVersion =
|
||||
Tcl_PkgRequireEx(interp, packageName, version, exact, &pkgClientData);
|
||||
const TclTomMathStubs *stubsPtr = pkgClientData;
|
||||
TclTomMathStubs *stubsPtr = NULL;
|
||||
const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
|
||||
packageName, version, exact, &stubsPtr);
|
||||
|
||||
if (actualVersion == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (pkgClientData == NULL) {
|
||||
if (stubsPtr == NULL) {
|
||||
errMsg = "missing stub table pointer";
|
||||
} else if ((stubsPtr->tclBN_epoch)() != epoch) {
|
||||
} else if(stubsPtr->tclBN_epoch() != epoch) {
|
||||
errMsg = "epoch number mismatch";
|
||||
} else if ((stubsPtr->tclBN_revision)() != revision) {
|
||||
} else if(stubsPtr->tclBN_revision() != revision) {
|
||||
errMsg = "requires a later revision";
|
||||
} else {
|
||||
tclTomMathStubsPtr = stubsPtr;
|
||||
return actualVersion;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"error loading %s (requested version %s, actual version %s): %s",
|
||||
packageName, version, actualVersion, errMsg));
|
||||
tclStubsPtr->tcl_ResetResult(interp);
|
||||
tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName,
|
||||
" (requested version ", version, ", actual version ",
|
||||
actualVersion, "): ", errMsg, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+11
-4
@@ -155,8 +155,8 @@ typedef struct StringTraceData {
|
||||
|
||||
#define FOREACH_VAR_TRACE(interp, name, clientData) \
|
||||
(clientData) = NULL; \
|
||||
while (((clientData) = Tcl_VarTraceInfo((interp), (name), 0, \
|
||||
TraceVarProc, (clientData))) != NULL)
|
||||
while (((clientData) = Tcl_VarTraceInfo2((interp), (name), NULL, \
|
||||
0, TraceVarProc, (clientData))) != NULL)
|
||||
|
||||
#define FOREACH_COMMAND_TRACE(interp, name, clientData) \
|
||||
(clientData) = NULL; \
|
||||
@@ -1322,7 +1322,7 @@ TraceCommandProc(
|
||||
Tcl_DStringLength(&cmd), 0);
|
||||
if (code != TCL_OK) {
|
||||
/* We ignore errors in these traced commands */
|
||||
/*** QUESTION: Use Tcl_BackgroundError(interp); instead? ***/
|
||||
/*** QUESTION: Use Tcl_BackgroundException(interp, code); instead? ***/
|
||||
}
|
||||
Tcl_DStringFree(&cmd);
|
||||
}
|
||||
@@ -1485,7 +1485,11 @@ TclCheckExecutionTraces(
|
||||
}
|
||||
iPtr->activeCmdTracePtr = active.nextPtr;
|
||||
if (state) {
|
||||
Tcl_RestoreInterpState(interp, state);
|
||||
if (traceCode == TCL_OK) {
|
||||
(void) Tcl_RestoreInterpState(interp, state);
|
||||
} else {
|
||||
Tcl_DiscardInterpState(state);
|
||||
}
|
||||
}
|
||||
|
||||
return traceCode;
|
||||
@@ -2811,6 +2815,7 @@ DisposeTraceResult(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_UntraceVar
|
||||
void
|
||||
Tcl_UntraceVar(
|
||||
Tcl_Interp *interp, /* Interpreter containing variable. */
|
||||
@@ -2979,6 +2984,7 @@ Tcl_UntraceVar2(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_VarTraceInfo
|
||||
ClientData
|
||||
Tcl_VarTraceInfo(
|
||||
Tcl_Interp *interp, /* Interpreter containing variable. */
|
||||
@@ -3087,6 +3093,7 @@ Tcl_VarTraceInfo2(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_TraceVar
|
||||
int
|
||||
Tcl_TraceVar(
|
||||
Tcl_Interp *interp, /* Interpreter in which variable is to be
|
||||
|
||||
+3
-2
@@ -1516,8 +1516,9 @@ Tcl_UniCharIsSpace(
|
||||
|
||||
if (((Tcl_UniChar) ch) < ((Tcl_UniChar) 0x80)) {
|
||||
return isspace(UCHAR(ch)); /* INTL: ISO space */
|
||||
} else if ((Tcl_UniChar) ch == 0x0085 || (Tcl_UniChar) ch == 0x200b
|
||||
|| (Tcl_UniChar) ch == 0x2060 || (Tcl_UniChar) ch == 0xfeff) {
|
||||
} else if ((Tcl_UniChar) ch == 0x0085 || (Tcl_UniChar) ch == 0x180e
|
||||
|| (Tcl_UniChar) ch == 0x200b || (Tcl_UniChar) ch == 0x2060
|
||||
|| (Tcl_UniChar) ch == 0xfeff) {
|
||||
return 1;
|
||||
} else {
|
||||
return ((SPACE_BITS >> GetCategory(ch)) & 1);
|
||||
|
||||
+12
-10
@@ -167,7 +167,7 @@ const Tcl_ObjType tclEndOffsetType = {
|
||||
* separating whitespace, or a string terminator. It is just another
|
||||
* character in a list element.
|
||||
*
|
||||
* The interpretaton of a formatted substring as a list element follows rules
|
||||
* The interpretation of a formatted substring as a list element follows rules
|
||||
* similar to the parsing of the words of a command in a Tcl script. Backslash
|
||||
* substitution plays a key role, and is defined exactly as it is in command
|
||||
* parsing. The same routine, TclParseBackslash() is used in both command
|
||||
@@ -179,7 +179,7 @@ const Tcl_ObjType tclEndOffsetType = {
|
||||
* Backslash substitution replaces an "escape sequence" of one or more
|
||||
* characters starting with
|
||||
* \u005c \ BACKSLASH
|
||||
* with a single character. The one character escape sequent case happens only
|
||||
* with a single character. The one character escape sequence case happens only
|
||||
* when BACKSLASH is the last character in the string. In all other cases, the
|
||||
* escape sequence is at least two characters long.
|
||||
*
|
||||
@@ -2927,14 +2927,16 @@ TclDStringToObj(
|
||||
{
|
||||
Tcl_Obj *result;
|
||||
|
||||
if (dsPtr->length == 0) {
|
||||
TclNewObj(result);
|
||||
} else if (dsPtr->string == dsPtr->staticSpace) {
|
||||
/*
|
||||
* Static buffer, so must copy.
|
||||
*/
|
||||
|
||||
TclNewStringObj(result, dsPtr->string, dsPtr->length);
|
||||
if (dsPtr->string == dsPtr->staticSpace) {
|
||||
if (dsPtr->length == 0) {
|
||||
TclNewObj(result);
|
||||
} else {
|
||||
/*
|
||||
* Static buffer, so must copy.
|
||||
*/
|
||||
|
||||
TclNewStringObj(result, dsPtr->string, dsPtr->length);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Dynamic buffer, so transfer ownership and reset.
|
||||
|
||||
+123
-95
@@ -47,6 +47,13 @@ static inline void CleanupVar(Var *varPtr, Var *arrayPtr);
|
||||
#define VarHashGetValue(hPtr) \
|
||||
((Var *) ((char *)hPtr - TclOffset(VarInHash, entry)))
|
||||
|
||||
/*
|
||||
* NOTE: VarHashCreateVar increments the recount of its key argument.
|
||||
* All callers that will call Tcl_DecrRefCount on that argument must
|
||||
* call Tcl_IncrRefCount on it before passing it in. This requirement
|
||||
* can bubble up to callers of callers .... etc.
|
||||
*/
|
||||
|
||||
static inline Var *
|
||||
VarHashCreateVar(
|
||||
TclVarHashTable *tablePtr,
|
||||
@@ -136,6 +143,30 @@ static const char *isArrayElement =
|
||||
|
||||
#define HasLocalVars(framePtr) ((framePtr)->isProcCallFrame & FRAME_IS_PROC)
|
||||
|
||||
/*
|
||||
* The following structure describes an enumerative search in progress on an
|
||||
* array variable; this are invoked with options to the "array" command.
|
||||
*/
|
||||
|
||||
typedef struct ArraySearch {
|
||||
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_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. */
|
||||
} ArraySearch;
|
||||
|
||||
/*
|
||||
* Forward references to functions defined later in this file:
|
||||
*/
|
||||
@@ -383,11 +414,12 @@ TclLookupVar(
|
||||
* address of array variable. Otherwise this
|
||||
* is set to NULL. */
|
||||
{
|
||||
Tcl_Obj *part1Ptr;
|
||||
Var *varPtr;
|
||||
Tcl_Obj *part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
|
||||
part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
if (createPart1) {
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
}
|
||||
|
||||
varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, msg,
|
||||
createPart1, createPart2, arrayPtrPtr);
|
||||
@@ -432,6 +464,8 @@ TclLookupVar(
|
||||
* are 1. The object part1Ptr is converted to one of localVarNameType,
|
||||
* tclNsVarNameType or tclParsedVarNameType and caches as much of the
|
||||
* lookup as it can.
|
||||
* When createPart1 is 1, callers must IncrRefCount part1Ptr if they
|
||||
* plan to DecrRefCount it.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -460,14 +494,14 @@ TclObjLookupVar(
|
||||
* address of array variable. Otherwise this
|
||||
* is set to NULL. */
|
||||
{
|
||||
Tcl_Obj *part2Ptr;
|
||||
Tcl_Obj *part2Ptr = NULL;
|
||||
Var *resPtr;
|
||||
|
||||
if (part2) {
|
||||
part2Ptr = Tcl_NewStringObj(part2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
} else {
|
||||
part2Ptr = NULL;
|
||||
if (createPart2) {
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
}
|
||||
}
|
||||
|
||||
resPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr,
|
||||
@@ -480,6 +514,12 @@ TclObjLookupVar(
|
||||
return resPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* When createPart1 is 1, callers must IncrRefCount part1Ptr if they
|
||||
* plan to DecrRefCount it.
|
||||
* When createPart2 is 1, callers must IncrRefCount part2Ptr if they
|
||||
* plan to DecrRefCount it.
|
||||
*/
|
||||
Var *
|
||||
TclObjLookupVarEx(
|
||||
Tcl_Interp *interp, /* Interpreter to use for lookup. */
|
||||
@@ -620,7 +660,9 @@ TclObjLookupVarEx(
|
||||
part2 = newPart2 = part1Ptr->internalRep.twoPtrValue.ptr2;
|
||||
if (newPart2) {
|
||||
part2Ptr = Tcl_NewStringObj(newPart2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
if (createPart2) {
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
}
|
||||
}
|
||||
part1Ptr = part1Ptr->internalRep.twoPtrValue.ptr1;
|
||||
typePtr = part1Ptr->typePtr;
|
||||
@@ -666,7 +708,9 @@ TclObjLookupVarEx(
|
||||
*(newPart2+len2) = '\0';
|
||||
part2 = newPart2;
|
||||
part2Ptr = Tcl_NewStringObj(newPart2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
if (createPart2) {
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the internal rep of the original part1Ptr, now renamed
|
||||
@@ -847,6 +891,7 @@ TclObjLookupVarEx(
|
||||
*
|
||||
* Side effects:
|
||||
* A new hashtable entry may be created if create is 1.
|
||||
* Callers must Incr varNamePtr if they plan to Decr it if create is 1.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1075,6 +1120,8 @@ TclLookupSimpleVar(
|
||||
* The variable at arrayPtr may be converted to be an array if
|
||||
* createPart1 is 1. A new hashtable entry may be created if createPart2
|
||||
* is 1.
|
||||
* When createElem is 1, callers must incr elNamePtr if they plan
|
||||
* to decr it.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1200,6 +1247,7 @@ TclLookupArrayElement(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_GetVar
|
||||
const char *
|
||||
Tcl_GetVar(
|
||||
Tcl_Interp *interp, /* Command interpreter in which varName is to
|
||||
@@ -1209,11 +1257,9 @@ Tcl_GetVar(
|
||||
* TCL_NAMESPACE_ONLY or TCL_LEAVE_ERR_MSG
|
||||
* bits. */
|
||||
{
|
||||
Tcl_Obj *varNamePtr, *resultPtr;
|
||||
Tcl_Obj *varNamePtr = Tcl_NewStringObj(varName, -1);
|
||||
Tcl_Obj *resultPtr = Tcl_ObjGetVar2(interp, varNamePtr, NULL, flags);
|
||||
|
||||
varNamePtr = Tcl_NewStringObj(varName, -1);
|
||||
Tcl_IncrRefCount(varNamePtr);
|
||||
resultPtr = Tcl_ObjGetVar2(interp, varNamePtr, NULL, flags);
|
||||
TclDecrRefCount(varNamePtr);
|
||||
|
||||
if (resultPtr == NULL) {
|
||||
@@ -1257,15 +1303,12 @@ Tcl_GetVar2(
|
||||
* TCL_NAMESPACE_ONLY and TCL_LEAVE_ERR_MSG *
|
||||
* bits. */
|
||||
{
|
||||
Tcl_Obj *resultPtr, *part1Ptr, *part2Ptr;
|
||||
Tcl_Obj *resultPtr;
|
||||
Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
|
||||
part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
if (part2) {
|
||||
part2Ptr = Tcl_NewStringObj(part2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
} else {
|
||||
part2Ptr = NULL;
|
||||
}
|
||||
|
||||
resultPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags);
|
||||
@@ -1314,15 +1357,11 @@ Tcl_GetVar2Ex(
|
||||
int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and
|
||||
* TCL_LEAVE_ERR_MSG bits. */
|
||||
{
|
||||
Tcl_Obj *part1Ptr, *part2Ptr, *resPtr;
|
||||
Tcl_Obj *resPtr, *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
|
||||
part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
if (part2) {
|
||||
part2Ptr = Tcl_NewStringObj(part2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
} else {
|
||||
part2Ptr = NULL;
|
||||
}
|
||||
|
||||
resPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags);
|
||||
@@ -1355,6 +1394,8 @@ Tcl_GetVar2Ex(
|
||||
* the returned reference; if you want to keep a reference to the object
|
||||
* you must increment its ref count yourself.
|
||||
*
|
||||
* Callers must incr part2Ptr if they plan to decr it.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -1549,6 +1590,7 @@ Tcl_SetObjCmd(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_SetVar
|
||||
const char *
|
||||
Tcl_SetVar(
|
||||
Tcl_Interp *interp, /* Command interpreter in which varName is to
|
||||
@@ -1560,17 +1602,13 @@ Tcl_SetVar(
|
||||
* TCL_APPEND_VALUE, TCL_LIST_ELEMENT,
|
||||
* TCL_LEAVE_ERR_MSG. */
|
||||
{
|
||||
Tcl_Obj *valuePtr, *varNamePtr, *varValuePtr;
|
||||
Tcl_Obj *varValuePtr, *varNamePtr = Tcl_NewStringObj(varName, -1);
|
||||
|
||||
varNamePtr = Tcl_NewStringObj(varName, -1);
|
||||
Tcl_IncrRefCount(varNamePtr);
|
||||
valuePtr = Tcl_NewStringObj(newValue, -1);
|
||||
Tcl_IncrRefCount(valuePtr);
|
||||
|
||||
varValuePtr = Tcl_ObjSetVar2(interp, varNamePtr, NULL, valuePtr, flags);
|
||||
|
||||
varValuePtr = Tcl_ObjSetVar2(interp, varNamePtr, NULL,
|
||||
Tcl_NewStringObj(newValue, -1), flags);
|
||||
Tcl_DecrRefCount(varNamePtr);
|
||||
Tcl_DecrRefCount(valuePtr);
|
||||
|
||||
if (varValuePtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1618,27 +1656,9 @@ Tcl_SetVar2(
|
||||
* TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or
|
||||
* TCL_LEAVE_ERR_MSG. */
|
||||
{
|
||||
Tcl_Obj *valuePtr, *part1Ptr, *part2Ptr;
|
||||
Tcl_Obj *varValuePtr;
|
||||
Tcl_Obj *varValuePtr = Tcl_SetVar2Ex(interp, part1, part2,
|
||||
Tcl_NewStringObj(newValue, -1), flags);
|
||||
|
||||
part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
if (part2 != NULL) {
|
||||
part2Ptr = Tcl_NewStringObj(part2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
} else {
|
||||
part2Ptr = NULL;
|
||||
}
|
||||
valuePtr = Tcl_NewStringObj(newValue, -1);
|
||||
Tcl_IncrRefCount(valuePtr);
|
||||
|
||||
varValuePtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, valuePtr, flags);
|
||||
|
||||
Tcl_DecrRefCount(part1Ptr);
|
||||
if (part2Ptr != NULL) {
|
||||
Tcl_DecrRefCount(part2Ptr);
|
||||
}
|
||||
Tcl_DecrRefCount(valuePtr);
|
||||
if (varValuePtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1697,15 +1717,12 @@ Tcl_SetVar2Ex(
|
||||
* TCL_APPEND_VALUE, TCL_LIST_ELEMENT or
|
||||
* TCL_LEAVE_ERR_MSG. */
|
||||
{
|
||||
Tcl_Obj *part1Ptr, *part2Ptr, *resPtr;
|
||||
Tcl_Obj *resPtr, *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
|
||||
part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
if (part2) {
|
||||
part2Ptr = Tcl_NewStringObj(part2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
} else {
|
||||
part2Ptr = NULL;
|
||||
}
|
||||
|
||||
resPtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags);
|
||||
@@ -1738,6 +1755,8 @@ Tcl_SetVar2Ex(
|
||||
* Side effects:
|
||||
* The value of the given variable is set. If either the array or the
|
||||
* entry didn't exist then a new variable is created.
|
||||
* Callers must Incr part1Ptr if they plan to Decr it.
|
||||
* Callers must Incr part2Ptr if they plan to Decr it.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2027,6 +2046,8 @@ TclPtrSetVar(
|
||||
* variable is created. The ref count for the returned object is _not_
|
||||
* incremented to reflect the returned reference; if you want to keep a
|
||||
* reference to the object you must increment its ref count yourself.
|
||||
* Callers must Incr part1Ptr if they plan to Decr it.
|
||||
* Callers must Incr part2Ptr if they plan to Decr it.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2052,8 +2073,8 @@ TclIncrObjVar2(
|
||||
varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read",
|
||||
1, 1, &arrayPtr);
|
||||
if (varPtr == NULL) {
|
||||
Tcl_AddObjErrorInfo(interp,
|
||||
"\n (reading value of variable to increment)", -1);
|
||||
Tcl_AddErrorInfo(interp,
|
||||
"\n (reading value of variable to increment)");
|
||||
return NULL;
|
||||
}
|
||||
return TclPtrIncrObjVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
@@ -2109,8 +2130,7 @@ TclPtrIncrObjVar(
|
||||
* variable, or -1. Only used when part1Ptr is
|
||||
* NULL. */
|
||||
{
|
||||
register Tcl_Obj *varValuePtr, *newValuePtr = NULL;
|
||||
int duplicated, code;
|
||||
register Tcl_Obj *varValuePtr;
|
||||
|
||||
if (TclIsVarInHash(varPtr)) {
|
||||
VarHashRefCount(varPtr)++;
|
||||
@@ -2124,19 +2144,33 @@ TclPtrIncrObjVar(
|
||||
varValuePtr = Tcl_NewIntObj(0);
|
||||
}
|
||||
if (Tcl_IsShared(varValuePtr)) {
|
||||
duplicated = 1;
|
||||
/* Copy on write */
|
||||
varValuePtr = Tcl_DuplicateObj(varValuePtr);
|
||||
|
||||
if (TCL_OK == TclIncrObj(interp, varValuePtr, incrPtr)) {
|
||||
return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
varValuePtr, flags, index);
|
||||
} else {
|
||||
Tcl_DecrRefCount(varValuePtr);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
duplicated = 0;
|
||||
/* Unshared - can Incr in place */
|
||||
if (TCL_OK == TclIncrObj(interp, varValuePtr, incrPtr)) {
|
||||
|
||||
/*
|
||||
* This seems dumb to write the incremeted value into the var
|
||||
* after we just adjusted the value in place, but the spec for
|
||||
* [incr] requires that write traces fire, and making this call
|
||||
* is the way to make that happen.
|
||||
*/
|
||||
|
||||
return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
varValuePtr, flags, index);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
code = TclIncrObj(interp, varValuePtr, incrPtr);
|
||||
if (code == TCL_OK) {
|
||||
newValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr,
|
||||
part2Ptr, varValuePtr, flags, index);
|
||||
} else if (duplicated) {
|
||||
Tcl_DecrRefCount(varValuePtr);
|
||||
}
|
||||
return newValuePtr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2159,6 +2193,7 @@ TclPtrIncrObjVar(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_UnsetVar
|
||||
int
|
||||
Tcl_UnsetVar(
|
||||
Tcl_Interp *interp, /* Command interpreter in which varName is to
|
||||
@@ -2219,13 +2254,10 @@ Tcl_UnsetVar2(
|
||||
* TCL_LEAVE_ERR_MSG. */
|
||||
{
|
||||
int result;
|
||||
Tcl_Obj *part1Ptr, *part2Ptr = NULL;
|
||||
Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
|
||||
part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
if (part2) {
|
||||
part2Ptr = Tcl_NewStringObj(part2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2841,6 +2873,7 @@ Tcl_LappendObjCmd(
|
||||
*
|
||||
* Side effects:
|
||||
* A variable will be created if one does not already exist.
|
||||
* Callers must Incr arrayNameObj if they pland to Decr it.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -4222,16 +4255,16 @@ TclInitArrayCmd(
|
||||
Tcl_Interp *interp) /* Current interpreter. */
|
||||
{
|
||||
static const EnsembleImplMap arrayImplMap[] = {
|
||||
{"anymore", ArrayAnyMoreCmd, NULL, NULL, NULL, 0},
|
||||
{"donesearch", ArrayDoneSearchCmd, NULL, NULL, NULL, 0},
|
||||
{"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0},
|
||||
{"get", ArrayGetCmd, NULL, NULL, NULL, 0},
|
||||
{"names", ArrayNamesCmd, NULL, NULL, NULL, 0},
|
||||
{"nextelement", ArrayNextElementCmd, NULL, NULL, NULL, 0},
|
||||
{"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
|
||||
{"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"set", ArraySetCmd, TclCompileArraySetCmd, NULL, NULL, 0},
|
||||
{"size", ArraySizeCmd, NULL, NULL, NULL, 0},
|
||||
{"startsearch", ArrayStartSearchCmd, NULL, NULL, NULL, 0},
|
||||
{"statistics", ArrayStatsCmd, NULL, NULL, NULL, 0},
|
||||
{"size", ArraySizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"startsearch", ArrayStartSearchCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"statistics", ArrayStatsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"unset", ArrayUnsetCmd, TclCompileArrayUnsetCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
@@ -4255,6 +4288,8 @@ TclInitArrayCmd(
|
||||
* The variable given by myName is linked to the variable in framePtr
|
||||
* given by otherP1 and otherP2, so that references to myName are
|
||||
* redirected to the other variable like a symbolic link.
|
||||
* Callers must Incr myNamePtr if they plan to Decr it.
|
||||
* Callers must Incr otherP1Ptr if they plan to Decr it.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -4363,14 +4398,12 @@ TclPtrMakeUpvar(
|
||||
int index) /* If the variable to be linked is an indexed
|
||||
* scalar, this is its index. Otherwise, -1 */
|
||||
{
|
||||
Tcl_Obj *myNamePtr;
|
||||
Tcl_Obj *myNamePtr = NULL;
|
||||
int result;
|
||||
|
||||
if (myName) {
|
||||
myNamePtr = Tcl_NewStringObj(myName, -1);
|
||||
Tcl_IncrRefCount(myNamePtr);
|
||||
} else {
|
||||
myNamePtr = NULL;
|
||||
}
|
||||
result = TclPtrObjMakeUpvar(interp, otherPtr, myNamePtr, myFlags, index);
|
||||
if (myNamePtr) {
|
||||
@@ -4379,6 +4412,8 @@ TclPtrMakeUpvar(
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Callers must Incr myNamePtr if they plan to Decr it. */
|
||||
|
||||
int
|
||||
TclPtrObjMakeUpvar(
|
||||
Tcl_Interp *interp, /* Interpreter containing variables. Used for
|
||||
@@ -4518,6 +4553,7 @@ TclPtrObjMakeUpvar(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_UpVar
|
||||
int
|
||||
Tcl_UpVar(
|
||||
Tcl_Interp *interp, /* Command interpreter in which varName is to
|
||||
@@ -5111,7 +5147,8 @@ ParseSearchId(
|
||||
* Parse the id.
|
||||
*/
|
||||
|
||||
if (Tcl_ConvertToType(interp, handleObj, &tclArraySearchType) != TCL_OK) {
|
||||
if ((handleObj->typePtr != &tclArraySearchType)
|
||||
&& (SetArraySearchObj(interp, handleObj) != TCL_OK)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -5242,8 +5279,6 @@ TclDeleteNamespaceVars(
|
||||
for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL;
|
||||
varPtr = VarHashFirstVar(tablePtr, &search)) {
|
||||
Tcl_Obj *objPtr = Tcl_NewObj();
|
||||
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
VarHashRefCount(varPtr)++; /* Make sure we get to remove from
|
||||
* hash. */
|
||||
Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr);
|
||||
@@ -5507,15 +5542,10 @@ TclVarErrMsg(
|
||||
* e.g. "read", "set", or "unset". */
|
||||
const char *reason) /* String describing why operation failed. */
|
||||
{
|
||||
Tcl_Obj *part1Ptr = NULL, *part2Ptr = NULL;
|
||||
Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
|
||||
part1Ptr = Tcl_NewStringObj(part1, -1);
|
||||
Tcl_IncrRefCount(part1Ptr);
|
||||
if (part2) {
|
||||
part2Ptr = Tcl_NewStringObj(part2, -1);
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
} else {
|
||||
part2 = NULL;
|
||||
}
|
||||
|
||||
TclObjVarErrMsg(interp, part1Ptr, part2Ptr, operation, reason, -1);
|
||||
@@ -5788,7 +5818,6 @@ Tcl_FindNamespaceVar(
|
||||
Tcl_Obj *namePtr = Tcl_NewStringObj(name, -1);
|
||||
Tcl_Var var;
|
||||
|
||||
Tcl_IncrRefCount(namePtr);
|
||||
var = ObjFindNamespaceVar(interp, namePtr, contextNsPtr, flags);
|
||||
Tcl_DecrRefCount(namePtr);
|
||||
return var;
|
||||
@@ -5883,7 +5912,6 @@ ObjFindNamespaceVar(
|
||||
varPtr = NULL;
|
||||
if (simpleName != name) {
|
||||
simpleNamePtr = Tcl_NewStringObj(simpleName, -1);
|
||||
Tcl_IncrRefCount(simpleNamePtr);
|
||||
} else {
|
||||
simpleNamePtr = namePtr;
|
||||
}
|
||||
|
||||
+45
-48
@@ -507,7 +507,7 @@ GenerateHeader(
|
||||
* ExtractHeader --
|
||||
*
|
||||
* Take the values out of a gzip header and store them in a dictionary.
|
||||
* SetValue is a helper function.
|
||||
* SetValue is a helper macro.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -518,18 +518,8 @@ GenerateHeader(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline void
|
||||
SetValue(
|
||||
Tcl_Obj *dictObj,
|
||||
const char *key,
|
||||
Tcl_Obj *value)
|
||||
{
|
||||
Tcl_Obj *keyObj = Tcl_NewStringObj(key, -1);
|
||||
|
||||
Tcl_IncrRefCount(keyObj);
|
||||
Tcl_DictObjPut(NULL, dictObj, keyObj, value);
|
||||
TclDecrRefCount(keyObj);
|
||||
}
|
||||
#define SetValue(dictObj, key, value) \
|
||||
Tcl_DictObjPut(NULL, (dictObj), Tcl_NewStringObj((key), -1), (value))
|
||||
|
||||
static void
|
||||
ExtractHeader(
|
||||
@@ -2119,9 +2109,6 @@ ZlibCmd(
|
||||
}
|
||||
if (headerVarObj != NULL && Tcl_ObjSetVar2(interp, headerVarObj, NULL,
|
||||
headerDictObj, TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
if (headerDictObj) {
|
||||
TclDecrRefCount(headerDictObj);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -2177,29 +2164,36 @@ ZlibStreamSubcmd(
|
||||
FMT_INFLATE
|
||||
};
|
||||
int i, format, mode = 0, option, level;
|
||||
enum objIndices {
|
||||
OPT_COMPRESSION_DICTIONARY = 0,
|
||||
OPT_GZIP_HEADER = 1,
|
||||
OPT_COMPRESSION_LEVEL = 2,
|
||||
OPT_END = -1
|
||||
};
|
||||
Tcl_Obj *obj[3] = { NULL, NULL, NULL };
|
||||
#define compDictObj obj[OPT_COMPRESSION_DICTIONARY]
|
||||
#define gzipHeaderObj obj[OPT_GZIP_HEADER]
|
||||
#define levelObj obj[OPT_COMPRESSION_LEVEL]
|
||||
typedef struct {
|
||||
const char *name;
|
||||
Tcl_Obj **valueVar;
|
||||
enum objIndices offset;
|
||||
} OptDescriptor;
|
||||
Tcl_Obj *compDictObj = NULL;
|
||||
Tcl_Obj *gzipHeaderObj = NULL;
|
||||
Tcl_Obj *levelObj = NULL;
|
||||
const OptDescriptor compressionOpts[] = {
|
||||
{ "-dictionary", &compDictObj },
|
||||
{ "-level", &levelObj },
|
||||
{ NULL, NULL }
|
||||
static const OptDescriptor compressionOpts[] = {
|
||||
{ "-dictionary", OPT_COMPRESSION_DICTIONARY },
|
||||
{ "-level", OPT_COMPRESSION_LEVEL },
|
||||
{ NULL, OPT_END }
|
||||
};
|
||||
const OptDescriptor gzipOpts[] = {
|
||||
{ "-header", &gzipHeaderObj },
|
||||
{ "-level", &levelObj },
|
||||
{ NULL, NULL }
|
||||
static const OptDescriptor gzipOpts[] = {
|
||||
{ "-header", OPT_GZIP_HEADER },
|
||||
{ "-level", OPT_COMPRESSION_LEVEL },
|
||||
{ NULL, OPT_END }
|
||||
};
|
||||
const OptDescriptor expansionOpts[] = {
|
||||
{ "-dictionary", &compDictObj },
|
||||
{ NULL, NULL }
|
||||
static const OptDescriptor expansionOpts[] = {
|
||||
{ "-dictionary", OPT_COMPRESSION_DICTIONARY },
|
||||
{ NULL, OPT_END }
|
||||
};
|
||||
const OptDescriptor gunzipOpts[] = {
|
||||
{ NULL, NULL }
|
||||
static const OptDescriptor gunzipOpts[] = {
|
||||
{ NULL, OPT_END }
|
||||
};
|
||||
const OptDescriptor *desc = NULL;
|
||||
Tcl_ZlibStream zh;
|
||||
@@ -2262,13 +2256,7 @@ ZlibStreamSubcmd(
|
||||
sizeof(OptDescriptor), "option", 0, &option) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*desc[option].valueVar = objv[i+1];
|
||||
|
||||
/*
|
||||
* Drop the cache on the option name; table address not constant.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objv[i]);
|
||||
obj[desc[option].offset] = objv[i+1];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2300,6 +2288,9 @@ ZlibStreamSubcmd(
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_ZlibStreamGetCommandName(zh));
|
||||
return TCL_OK;
|
||||
#undef compDictObj
|
||||
#undef gzipHeaderObj
|
||||
#undef levelObj
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3120,7 +3111,7 @@ ZlibTransformOutput(
|
||||
e = deflate(&cd->outStream, Z_NO_FLUSH);
|
||||
produced = cd->outAllocated - cd->outStream.avail_out;
|
||||
|
||||
if (e == Z_OK && cd->outStream.avail_out > 0) {
|
||||
if (e == Z_OK && produced > 0) {
|
||||
if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) < 0) {
|
||||
*errorCodePtr = Tcl_GetErrno();
|
||||
return -1;
|
||||
@@ -3874,7 +3865,7 @@ TclZlibInit(
|
||||
cfg[0].key = "zlibVersion";
|
||||
cfg[0].value = zlibVersion();
|
||||
cfg[1].key = NULL;
|
||||
Tcl_RegisterConfig(interp, "zlib", cfg, "ascii");
|
||||
Tcl_RegisterConfig(interp, "zlib", cfg, "iso8859-1");
|
||||
|
||||
/*
|
||||
* Formally provide the package as a Tcl built-in.
|
||||
@@ -3900,8 +3891,10 @@ Tcl_ZlibStreamInit(
|
||||
Tcl_Obj *dictObj,
|
||||
Tcl_ZlibStream *zshandle)
|
||||
{
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -3966,8 +3959,10 @@ Tcl_ZlibDeflate(
|
||||
int level,
|
||||
Tcl_Obj *gzipHeaderDictObj)
|
||||
{
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -3979,8 +3974,10 @@ Tcl_ZlibInflate(
|
||||
int bufferSize,
|
||||
Tcl_Obj *gzipHeaderDictObj)
|
||||
{
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+21
-13
@@ -20,8 +20,9 @@
|
||||
# None.
|
||||
|
||||
proc auto_reset {} {
|
||||
if {[array exists ::auto_index]} {
|
||||
foreach cmdName [array names ::auto_index] {
|
||||
global auto_execs auto_index auto_path
|
||||
if {[array exists auto_index]} {
|
||||
foreach cmdName [array names auto_index] {
|
||||
set fqcn [namespace which $cmdName]
|
||||
if {$fqcn eq ""} {
|
||||
continue
|
||||
@@ -29,11 +30,11 @@ proc auto_reset {} {
|
||||
rename $fqcn {}
|
||||
}
|
||||
}
|
||||
unset -nocomplain ::auto_execs ::auto_index ::tcl::auto_oldpath
|
||||
if {[catch {llength $::auto_path}]} {
|
||||
set ::auto_path [list [info library]]
|
||||
} elseif {[info library] ni $::auto_path} {
|
||||
lappend ::auto_path [info library]
|
||||
unset -nocomplain auto_execs auto_index ::tcl::auto_oldpath
|
||||
if {[catch {llength $auto_path}]} {
|
||||
set auto_path [list [info library]]
|
||||
} elseif {[info library] ni $auto_path} {
|
||||
lappend auto_path [info library]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +54,7 @@ proc auto_reset {} {
|
||||
|
||||
proc tcl_findLibrary {basename version patch initScript enVarName varName} {
|
||||
upvar #0 $varName the_library
|
||||
global env
|
||||
global auto_path env tcl_platform
|
||||
|
||||
set dirs {}
|
||||
set errors {}
|
||||
@@ -83,12 +84,10 @@ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
|
||||
# 3. Relative to auto_path directories. This checks relative to the
|
||||
# Tcl library as well as allowing loading of libraries added to the
|
||||
# auto_path that is not relative to the core library or binary paths.
|
||||
foreach d $::auto_path {
|
||||
foreach d $auto_path {
|
||||
lappend dirs [file join $d $basename$version]
|
||||
if {
|
||||
$::tcl_platform(platform) eq "unix"
|
||||
&& $::tcl_platform(os) eq "Darwin"
|
||||
} then {
|
||||
if {$tcl_platform(platform) eq "unix"
|
||||
&& $tcl_platform(os) eq "Darwin"} {
|
||||
# 4. On MacOSX, check the Resources/Scripts subdir too
|
||||
lappend dirs [file join $d $basename$version Resources Scripts]
|
||||
}
|
||||
@@ -606,6 +605,15 @@ auto_mkindex_parser::command namespace {op args} {
|
||||
}
|
||||
catch {$parser eval "_%@namespace import $args"}
|
||||
}
|
||||
ensemble {
|
||||
variable parser
|
||||
variable contextStack
|
||||
if {[lindex $args 0] eq "create"} {
|
||||
set name ::[join [lreverse $contextStack] ::]
|
||||
# create artifical proc to force an entry in the tclIndex
|
||||
$parser eval [list ::proc $name {} {}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+49
-38
@@ -11,7 +11,7 @@
|
||||
package require Tcl 8.6
|
||||
# Keep this in sync with pkgIndex.tcl and with the install directories in
|
||||
# Makefiles
|
||||
package provide http 2.8.5
|
||||
package provide http 2.8.7
|
||||
|
||||
namespace eval http {
|
||||
# Allow resourcing to not clobber existing data
|
||||
@@ -394,13 +394,16 @@ proc http::geturl {url args} {
|
||||
# First, before the colon, is the protocol scheme (e.g. http)
|
||||
# Second, for HTTP-like protocols, is the authority
|
||||
# The authority is preceded by // and lasts up to (but not including)
|
||||
# the following / and it identifies up to four parts, of which only one,
|
||||
# the host, is required (if an authority is present at all). All other
|
||||
# parts of the authority (user name, password, port number) are optional.
|
||||
# the following / or ? and it identifies up to four parts, of which
|
||||
# only one, the host, is required (if an authority is present at all).
|
||||
# All other parts of the authority (user name, password, port number)
|
||||
# are optional.
|
||||
# Third is the resource name, which is split into two parts at a ?
|
||||
# The first part (from the single "/" up to "?") is the path, and the
|
||||
# second part (from that "?" up to "#") is the query. *HOWEVER*, we do
|
||||
# not need to separate them; we send the whole lot to the server.
|
||||
# Both, path and query are allowed to be missing, including their
|
||||
# delimiting character.
|
||||
# Fourth is the fragment identifier, which is everything after the first
|
||||
# "#" in the URL. The fragment identifier MUST NOT be sent to the server
|
||||
# and indeed, we don't bother to validate it (it could be an error to
|
||||
@@ -437,7 +440,7 @@ proc http::geturl {url args} {
|
||||
)
|
||||
(?: : (\d+) )? # <port part of authority>
|
||||
)?
|
||||
( / [^\#]*)? # <path> (including query)
|
||||
( [/\?] [^\#]*)? # <path> (including query)
|
||||
(?: \# (.*) )? # <fragment>
|
||||
$
|
||||
}
|
||||
@@ -481,6 +484,12 @@ proc http::geturl {url args} {
|
||||
}
|
||||
}
|
||||
if {$srvurl ne ""} {
|
||||
# RFC 3986 allows empty paths (not even a /), but servers
|
||||
# return 400 if the path in the HTTP request doesn't start
|
||||
# with / , so add it here if needed.
|
||||
if {[string index $srvurl 0] ne "/"} {
|
||||
set srvurl /$srvurl
|
||||
}
|
||||
# Check for validity according to RFC 3986, Appendix A
|
||||
set validityRE {(?xi)
|
||||
^
|
||||
@@ -537,11 +546,10 @@ proc http::geturl {url args} {
|
||||
# If a timeout is specified we set up the after event and arrange for an
|
||||
# asynchronous socket connection.
|
||||
|
||||
set sockopts [list]
|
||||
set sockopts [list -async]
|
||||
if {$state(-timeout) > 0} {
|
||||
set state(after) [after $state(-timeout) \
|
||||
[list http::reset $token timeout]]
|
||||
lappend sockopts -async
|
||||
}
|
||||
|
||||
# If we are using the proxy, we must pass in the full URL that includes
|
||||
@@ -597,10 +605,15 @@ proc http::geturl {url args} {
|
||||
set socketmap($state(socketinfo)) $sock
|
||||
}
|
||||
|
||||
# Wait for the connection to complete.
|
||||
if {![info exists phost]} {
|
||||
set phost ""
|
||||
}
|
||||
fileevent $sock writable [list http::Connect $token $proto $phost $srvurl]
|
||||
|
||||
if {$state(-timeout) > 0} {
|
||||
fileevent $sock writable [list http::Connect $token]
|
||||
# Wait for the connection to complete.
|
||||
if {![info exists state(-command)]} {
|
||||
# geturl does EVERYTHING asynchronously, so if the user
|
||||
# calls it synchronously, we just do a wait here.
|
||||
http::wait $token
|
||||
|
||||
if {![info exists state]} {
|
||||
@@ -616,13 +629,29 @@ proc http::geturl {url args} {
|
||||
set err [lindex $state(error) 0]
|
||||
cleanup $token
|
||||
return -code error $err
|
||||
} elseif {$state(status) ne "connect"} {
|
||||
# Likely to be connection timeout
|
||||
return $token
|
||||
}
|
||||
set state(status) ""
|
||||
}
|
||||
|
||||
return $token
|
||||
}
|
||||
|
||||
|
||||
proc http::Connected { token proto phost srvurl} {
|
||||
variable http
|
||||
variable urlTypes
|
||||
|
||||
variable $token
|
||||
upvar 0 $token state
|
||||
|
||||
# Set back the variables needed here
|
||||
set sock $state(sock)
|
||||
set isQueryChannel [info exists state(-querychannel)]
|
||||
set isQuery [info exists state(-query)]
|
||||
set host [lindex [split $state(socketinfo) :] 0]
|
||||
set port [lindex [split $state(socketinfo) :] 1]
|
||||
|
||||
set defport [lindex $urlTypes($proto) 0]
|
||||
|
||||
# Send data in cr-lf format, but accept any line terminators
|
||||
|
||||
fconfigure $sock -translation {auto crlf} -buffersize $state(-blocksize)
|
||||
@@ -753,35 +782,17 @@ proc http::geturl {url args} {
|
||||
fileevent $sock readable [list http::Event $sock $token]
|
||||
}
|
||||
|
||||
if {![info exists state(-command)]} {
|
||||
# geturl does EVERYTHING asynchronously, so if the user calls it
|
||||
# synchronously, we just do a wait here.
|
||||
|
||||
wait $token
|
||||
if {$state(status) eq "error"} {
|
||||
# Something went wrong, so throw the exception, and the
|
||||
# enclosing catch will do cleanup.
|
||||
return -code error [lindex $state(error) 0]
|
||||
}
|
||||
}
|
||||
} err]} {
|
||||
# The socket probably was never connected, or the connection dropped
|
||||
# later.
|
||||
|
||||
# Clean up after events and such, but DON'T call the command callback
|
||||
# (if available) because we're going to throw an exception from here
|
||||
# instead.
|
||||
|
||||
# if state(status) is error, it means someone's already called Finish
|
||||
# to do the above-described clean up.
|
||||
if {$state(status) ne "error"} {
|
||||
Finish $token $err 1
|
||||
Finish $token $err
|
||||
}
|
||||
cleanup $token
|
||||
return -code error $err
|
||||
}
|
||||
|
||||
return $token
|
||||
}
|
||||
|
||||
# Data access functions:
|
||||
@@ -865,7 +876,7 @@ proc http::cleanup {token} {
|
||||
# Sets the status of the connection, which unblocks
|
||||
# the waiting geturl call
|
||||
|
||||
proc http::Connect {token} {
|
||||
proc http::Connect {token proto phost srvurl} {
|
||||
variable $token
|
||||
upvar 0 $token state
|
||||
set err "due to unexpected EOF"
|
||||
@@ -873,10 +884,10 @@ proc http::Connect {token} {
|
||||
[eof $state(sock)] ||
|
||||
[set err [fconfigure $state(sock) -error]] ne ""
|
||||
} {
|
||||
Finish $token "connect failed $err" 1
|
||||
Finish $token "connect failed $err"
|
||||
} else {
|
||||
set state(status) connect
|
||||
fileevent $state(sock) writable {}
|
||||
::http::Connected $token $proto $phost $srvurl
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -981,7 +992,7 @@ proc http::Event {sock token} {
|
||||
} elseif {$n == 0} {
|
||||
# We have now read all headers
|
||||
# We ignore HTTP/1.1 100 Continue returns. RFC2616 sec 8.2.3
|
||||
if {$state(http) == "" || [lindex $state(http) 1] == 100} {
|
||||
if {$state(http) == "" || ([regexp {^\S+\s(\d+)} $state(http) {} x] && $x == 100)} {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1379,7 +1390,7 @@ proc http::mapReply {string} {
|
||||
}
|
||||
set converted [string map $formMap $string]
|
||||
if {[string match "*\[\u0100-\uffff\]*" $converted]} {
|
||||
regexp {[\u0100-\uffff]} $converted badChar
|
||||
regexp "\[\u0100-\uffff\]" $converted badChar
|
||||
# Return this error message for maximum compatability... :^/
|
||||
return -code error \
|
||||
"can't read \"formMap($badChar)\": no such element in array"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user