Compare commits
792
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7248e185c4 | ||
|
|
439d6c8c82 | ||
|
|
8427c0c455 | ||
|
|
88f46ca664 | ||
|
|
d5eccf9907 | ||
|
|
64287131fc | ||
|
|
d6f93ff450 | ||
|
|
961684edff | ||
|
|
6b52ee1bdf | ||
|
|
22de896416 | ||
|
|
fddae29c41 | ||
|
|
a27c0164cf | ||
|
|
648ab28529 | ||
|
|
a251837534 | ||
|
|
f924c7b244 | ||
|
|
82895be625 | ||
|
|
ee7950cf32 | ||
|
|
de01419022 | ||
|
|
d45e087497 | ||
|
|
69ab106ada | ||
|
|
4c575021c7 | ||
|
|
3a9e04c001 | ||
|
|
880c78393c | ||
|
|
e6b77e0b06 | ||
|
|
7effd2e72c | ||
|
|
385adbd9bd | ||
|
|
96b15ff9f6 | ||
|
|
4dab6d3efb | ||
|
|
fc0255af91 | ||
|
|
d9d4467ee7 | ||
|
|
4443c3177b | ||
|
|
f4d4331782 | ||
|
|
b3960702d2 | ||
|
|
2ac9cdcd73 | ||
|
|
6cc00def7f | ||
|
|
568aff25e3 | ||
|
|
435c078290 | ||
|
|
93dd0ea623 | ||
|
|
5406225cc1 | ||
|
|
0fad3893a7 | ||
|
|
49201a46ad | ||
|
|
71018d9954 | ||
|
|
188c4a20f4 | ||
|
|
2439cb752a | ||
|
|
feb0337f75 | ||
|
|
08c1b1b2c6 | ||
|
|
bd73d3bc98 | ||
|
|
30d34a3e70 | ||
|
|
9ac7d18c6d | ||
|
|
fa8c01a36d | ||
|
|
d0e53f4558 | ||
|
|
2c5e56832a | ||
|
|
5f54d6e35c | ||
|
|
14e507ab0f | ||
|
|
69726197d8 | ||
|
|
d3daca383d | ||
|
|
652558eef5 | ||
|
|
434e26477d | ||
|
|
e2f0af2714 | ||
|
|
a20eb8bc6a | ||
|
|
bf2c7d3f0a | ||
|
|
4dce301da4 | ||
|
|
9f4d273655 | ||
|
|
7de3da420f | ||
|
|
986775b761 | ||
|
|
b5dd9ceaab | ||
|
|
b3722a8c03 | ||
|
|
af55dc01d8 | ||
|
|
029911a413 | ||
|
|
4478afff2a | ||
|
|
5860f82135 | ||
|
|
ac8205c8ee | ||
|
|
a4b27124be | ||
|
|
5c6745ec03 | ||
|
|
3b26998f18 | ||
|
|
2ecb2c5da4 | ||
|
|
d284f9118b | ||
|
|
b33dac7519 | ||
|
|
42725da7ba | ||
|
|
f3cd1bab12 | ||
|
|
a95bde4890 | ||
|
|
71a5f30a95 | ||
|
|
535d9351df | ||
|
|
2109289587 | ||
|
|
e31b21beff | ||
|
|
d50475d2e7 | ||
|
|
7f743eb32b | ||
|
|
0321a464b9 | ||
|
|
232912fd60 | ||
|
|
940919e356 | ||
|
|
a9af7dc696 | ||
|
|
0a6c6bf801 | ||
|
|
14b58a3e20 | ||
|
|
102d340fa6 | ||
|
|
05ad3060a8 | ||
|
|
538ca551b7 | ||
|
|
7e4c95c24e | ||
|
|
10b1362daa | ||
|
|
0a21b6eed5 | ||
|
|
61e2cc66b9 | ||
|
|
8bced55797 | ||
|
|
cd0fea5763 | ||
|
|
1154dfa4f0 | ||
|
|
a93fc66525 | ||
|
|
a83fb66df9 | ||
|
|
ff93032670 | ||
|
|
63e9714b2e | ||
|
|
cca1a031f7 | ||
|
|
800194c7f4 | ||
|
|
eb58711740 | ||
|
|
dace399671 | ||
|
|
65b29252af | ||
|
|
6a89806ee6 | ||
|
|
165eea24c0 | ||
|
|
1e47aa3a2e | ||
|
|
03c0cbaafd | ||
|
|
03dd129a16 | ||
|
|
7093dc16ae | ||
|
|
4864c57e4d | ||
|
|
4ee7135c5a | ||
|
|
905f8b73d7 | ||
|
|
17a2efee72 | ||
|
|
f80e08da71 | ||
|
|
10f3bcbb8d | ||
|
|
c7706471ad | ||
|
|
c418b4db02 | ||
|
|
562da42399 | ||
|
|
88928b4fff | ||
|
|
e125854648 | ||
|
|
dde7348f86 | ||
|
|
2d4422bbba | ||
|
|
01f1143ddf | ||
|
|
0aad2eded0 | ||
|
|
fa96d47dfc | ||
|
|
0dcd38a24d | ||
|
|
9582b7a005 | ||
|
|
4a3783d6df | ||
|
|
88f4b5757c | ||
|
|
97e33af67f | ||
|
|
a43258ca27 | ||
|
|
b166c166e7 | ||
|
|
f963e96259 | ||
|
|
aa6bf4e80b | ||
|
|
fef64f5de5 | ||
|
|
ac81afab4f | ||
|
|
111470b8a2 | ||
|
|
67c8c51001 | ||
|
|
4b52c0611f | ||
|
|
8796676d52 | ||
|
|
3095406395 | ||
|
|
8133abce26 | ||
|
|
66ce9bc185 | ||
|
|
db1368a130 | ||
|
|
5f00348134 | ||
|
|
8061873d98 | ||
|
|
0548037236 | ||
|
|
6048f838e3 | ||
|
|
2fd7fd7369 | ||
|
|
2e55b5dd3a | ||
|
|
b522ab7c2a | ||
|
|
234032f005 | ||
|
|
5c18029325 | ||
|
|
2d7d8d6fd1 | ||
|
|
4b6e6f5c2c | ||
|
|
b099f09ec9 | ||
|
|
f2fa51ec73 | ||
|
|
d282dddcfd | ||
|
|
e24b8208b0 | ||
|
|
0056593b61 | ||
|
|
71e90a29ad | ||
|
|
20a3d4112f | ||
|
|
4ba51a6b66 | ||
|
|
bb662c4f7a | ||
|
|
e82486aa49 | ||
|
|
9ef1e66fba | ||
|
|
d702f1dcba | ||
|
|
c31f8caa4d | ||
|
|
5178c9fe83 | ||
|
|
a0b91a68d7 | ||
|
|
4f6b05865f | ||
|
|
0e0db3eebb | ||
|
|
609c82da5e | ||
|
|
e1d9fc8bc1 | ||
|
|
eb1fba12e2 | ||
|
|
3912efe30f | ||
|
|
fadad8447c | ||
|
|
3858e79861 | ||
|
|
4893e98712 | ||
|
|
70efeebc57 | ||
|
|
3cf7de3328 | ||
|
|
8b2e59a8c8 | ||
|
|
1ae6a7c4d3 | ||
|
|
7c308a99f7 | ||
|
|
902548b5ec | ||
|
|
0a57b1e0c7 | ||
|
|
4d20eb490b | ||
|
|
b6b37b7c74 | ||
|
|
0da7d37ae9 | ||
|
|
23a39ad85f | ||
|
|
fb7805683f | ||
|
|
3fe5d2c50d | ||
|
|
a37a480bf5 | ||
|
|
7ccad65c74 | ||
|
|
b099048f89 | ||
|
|
cc1ea405b7 | ||
|
|
25b0e9b76d | ||
|
|
5c1c118b8a | ||
|
|
e1b559b602 | ||
|
|
8f511d22c9 | ||
|
|
691d6c5fc0 | ||
|
|
1be1ad4d27 | ||
|
|
d6ef48a710 | ||
|
|
3a52401ad2 | ||
|
|
bd24ad87ac | ||
|
|
559b1b2e28 | ||
|
|
985deea75b | ||
|
|
4da420a519 | ||
|
|
19128173ab | ||
|
|
875011d6f2 | ||
|
|
da34f9f408 | ||
|
|
97bb071f95 | ||
|
|
b2d6d22bf0 | ||
|
|
09d76814f4 | ||
|
|
b66fac0f73 | ||
|
|
fd550b5cb8 | ||
|
|
88c4d1b817 | ||
|
|
cb86661230 | ||
|
|
4fa79a7023 | ||
|
|
039786589f | ||
|
|
09489c384b | ||
|
|
d7c57a0c14 | ||
|
|
0e4baeaa35 | ||
|
|
a7943f6350 | ||
|
|
650bb69c7b | ||
|
|
60f0a67594 | ||
|
|
a025151f2d | ||
|
|
5c3426d524 | ||
|
|
cb3067db94 | ||
|
|
899a818f23 | ||
|
|
e7e759c639 | ||
|
|
970eb178b2 | ||
|
|
135e331c3a | ||
|
|
9ff2ef9fe1 | ||
|
|
6f2c08cfba | ||
|
|
de58f61c2a | ||
|
|
8fb869a726 | ||
|
|
635ba5bd14 | ||
|
|
e499be71f0 | ||
|
|
9feb99ecb1 | ||
|
|
06740b2fe5 | ||
|
|
78cb74134b | ||
|
|
c1432f0462 | ||
|
|
db32da8682 | ||
|
|
a8a1f62999 | ||
|
|
5af2155539 | ||
|
|
c9498e0b05 | ||
|
|
7fe677cf6b | ||
|
|
71581e9afa | ||
|
|
4882c7bc07 | ||
|
|
dde6018798 | ||
|
|
21d149f5e9 | ||
|
|
dc7f50b812 | ||
|
|
6fb310bb09 | ||
|
|
45f4c1b34e | ||
|
|
4562b6d22c | ||
|
|
0dee7bed88 | ||
|
|
f4a5ba54ac | ||
|
|
b1ac90a4a8 | ||
|
|
1528383bf1 | ||
|
|
e6d42cbc43 | ||
|
|
f9d43f296c | ||
|
|
c3ceb84d68 | ||
|
|
23015fefad | ||
|
|
b9b2db3c5f | ||
|
|
0b12aaa081 | ||
|
|
01ff23f34d | ||
|
|
8727b0b49a | ||
|
|
6e5503565e | ||
|
|
51f172a42a | ||
|
|
0f6435157f | ||
|
|
f6bf9def7e | ||
|
|
b01a4e6bd3 | ||
|
|
1a3d7da175 | ||
|
|
b4169bc203 | ||
|
|
1d58e7eba2 | ||
|
|
4e8007f55d | ||
|
|
40bc3d16a3 | ||
|
|
e4f4cb135c | ||
|
|
0cb9c0b3f8 | ||
|
|
66c3ad95b6 | ||
|
|
4073788a7e | ||
|
|
ed50905900 | ||
|
|
2a51e8e640 | ||
|
|
cb357cc4bf | ||
|
|
99cd5e5444 | ||
|
|
8f6b586b58 | ||
|
|
934c9819c7 | ||
|
|
e634d18c48 | ||
|
|
7ec3df7ddd | ||
|
|
cb435cd742 | ||
|
|
8678f0ba6a | ||
|
|
269d6061c3 | ||
|
|
cb6415b2d5 | ||
|
|
34630d5ca1 | ||
|
|
b50a64424f | ||
|
|
72ab4731bf | ||
|
|
93c204b162 | ||
|
|
ee4c12f1b4 | ||
|
|
5142b5748e | ||
|
|
5d75a1e629 | ||
|
|
662d103e7d | ||
|
|
0d4d978c52 | ||
|
|
5721de48ca | ||
|
|
bb3e4af18d | ||
|
|
e41cc9b99b | ||
|
|
ce70b3ebe4 | ||
|
|
dc55749c58 | ||
|
|
af368b9049 | ||
|
|
b824cdafec | ||
|
|
6c2dedfaa4 | ||
|
|
9e7c74bb55 | ||
|
|
55777cb64d | ||
|
|
89b3243fd8 | ||
|
|
9cd8ebbfe8 | ||
|
|
ad4985397d | ||
|
|
ecd951296b | ||
|
|
bc62e73bb8 | ||
|
|
d5ba2b9a38 | ||
|
|
c708a47b25 | ||
|
|
daa1e38bab | ||
|
|
2426c3bd63 | ||
|
|
d84809538f | ||
|
|
d832d24006 | ||
|
|
ea836428c1 | ||
|
|
afdd41dd6a | ||
|
|
8b9e2d4583 | ||
|
|
e6fdf643b3 | ||
|
|
b90ddeb75c | ||
|
|
b264aa7c57 | ||
|
|
264e9e9793 | ||
|
|
2e36c3e97b | ||
|
|
e57c57e122 | ||
|
|
3b5e99739b | ||
|
|
f1d8f0a503 | ||
|
|
7b258bd47c | ||
|
|
7b458b0a03 | ||
|
|
17437636cb | ||
|
|
3c192328ca | ||
|
|
5193d058c2 | ||
|
|
214cce5517 | ||
|
|
dcb9cf19bb | ||
|
|
86070b6f26 | ||
|
|
122a3f6a2d | ||
|
|
69768ac78c | ||
|
|
487afeafb4 | ||
|
|
a46ef482b3 | ||
|
|
a570556b6e | ||
|
|
cc4e06ba60 | ||
|
|
9631a6e074 | ||
|
|
24a53e6920 | ||
|
|
1b050f07c1 | ||
|
|
209a4cd4ff | ||
|
|
0ae1b02c78 | ||
|
|
7ad8f9bfd7 | ||
|
|
2d48fa2684 | ||
|
|
c8a2ab1879 | ||
|
|
b20c1053ab | ||
|
|
6c81bff536 | ||
|
|
e8b57cc705 | ||
|
|
636cda54f0 | ||
|
|
8a631b4d12 | ||
|
|
ea30a47ef4 | ||
|
|
f981dcbe94 | ||
|
|
8e85d70b91 | ||
|
|
0d3b650a17 | ||
|
|
8db5a8ae20 | ||
|
|
1b671ec0dd | ||
|
|
66cd404c19 | ||
|
|
aa73ee6e56 | ||
|
|
16c428e8b9 | ||
|
|
624802c0f3 | ||
|
|
4b07d6b1e2 | ||
|
|
480e15a41c | ||
|
|
beb9469222 | ||
|
|
f1a3e189ec | ||
|
|
44b80fc8ad | ||
|
|
68c9014a4a | ||
|
|
84be74fba6 | ||
|
|
baec983c04 | ||
|
|
fea176b546 | ||
|
|
7b90822271 | ||
|
|
19591e2473 | ||
|
|
c39440fea5 | ||
|
|
875729efc9 | ||
|
|
2aabb685b6 | ||
|
|
1b654bc947 | ||
|
|
dc52697066 | ||
|
|
5aff1b51d1 | ||
|
|
b55915dc2d | ||
|
|
ec6493f2b8 | ||
|
|
74867b094c | ||
|
|
5c21ccca7b | ||
|
|
dab38fe514 | ||
|
|
28aca7303b | ||
|
|
43cbca4fbf | ||
|
|
01cd0a0e45 | ||
|
|
d5fb294747 | ||
|
|
c283aca1bc | ||
|
|
f07a0838c2 | ||
|
|
94b7fc5ca7 | ||
|
|
99d97ce43f | ||
|
|
7278dc8cbc | ||
|
|
3de98b6fb6 | ||
|
|
b38f2f3429 | ||
|
|
cea3281fa1 | ||
|
|
b537b155ed | ||
|
|
ccdaf5990b | ||
|
|
bd808f7dcc | ||
|
|
5e3100e225 | ||
|
|
e88b3c601b | ||
|
|
38808ad999 | ||
|
|
a01dee70ea | ||
|
|
11ab70fd89 | ||
|
|
1dfad0a9d3 | ||
|
|
d24753dbf1 | ||
|
|
1958ac85c0 | ||
|
|
6ad83f332d | ||
|
|
995249252e | ||
|
|
c7a571a771 | ||
|
|
0cf8975e2a | ||
|
|
a367c2d812 | ||
|
|
7b34cb4a15 | ||
|
|
c6afdfc531 | ||
|
|
6cc142428e | ||
|
|
24f8828f4d | ||
|
|
a7346777c6 | ||
|
|
082bbbea10 | ||
|
|
f748950db6 | ||
|
|
304456608e | ||
|
|
3ab0bb6501 | ||
|
|
b4b10b99d7 | ||
|
|
ce74537dd7 | ||
|
|
da8d758711 | ||
|
|
e7cf3a048c | ||
|
|
401ff4964c | ||
|
|
76f4308926 | ||
|
|
abc2391b16 | ||
|
|
077a6cbece | ||
|
|
6cdf0568cf | ||
|
|
4bdb2c7b6e | ||
|
|
791b296b8e | ||
|
|
7d0bbc47d7 | ||
|
|
f6627105c2 | ||
|
|
be130b0337 | ||
|
|
40c5514475 | ||
|
|
62d918cae7 | ||
|
|
8ebcf55a9f | ||
|
|
cd3de32c6b | ||
|
|
255658907d | ||
|
|
36db921e01 | ||
|
|
e569e9e9ab | ||
|
|
c34088c42a | ||
|
|
1b6a0ff3b0 | ||
|
|
31181a01b6 | ||
|
|
08f8cf1a9e | ||
|
|
2ea0874f3f | ||
|
|
2d357d6e45 | ||
|
|
502fec899c | ||
|
|
1d7632f6e0 | ||
|
|
9ca9c5016b | ||
|
|
ee9184e1a9 | ||
|
|
c4db257e2e | ||
|
|
7c6afac7e6 | ||
|
|
f1d660fcb3 | ||
|
|
98d42037a5 | ||
|
|
326bfdff35 | ||
|
|
de6f149f5f | ||
|
|
48c4185146 | ||
|
|
0eb53a0627 | ||
|
|
370566c1e6 | ||
|
|
dfa4a65a52 | ||
|
|
24d8781502 | ||
|
|
e2ce695c5d | ||
|
|
3170aa3764 | ||
|
|
114535264c | ||
|
|
35dc38b268 | ||
|
|
d4406723ec | ||
|
|
b9f37656c8 | ||
|
|
d554c361d3 | ||
|
|
e0792c933b | ||
|
|
b4f22927e5 | ||
|
|
1978e5ad54 | ||
|
|
08fa057f64 | ||
|
|
a9d4c8d1cd | ||
|
|
d0020e0e23 | ||
|
|
5cced2c4ac | ||
|
|
a331adea33 | ||
|
|
ba9e9a59a9 | ||
|
|
6e5baa7e71 | ||
|
|
327160f25e | ||
|
|
69a513d135 | ||
|
|
56ec7b2901 | ||
|
|
d99e33e348 | ||
|
|
f145c7fbd2 | ||
|
|
9534c91a41 | ||
|
|
810f50427c | ||
|
|
97d5fe7c2b | ||
|
|
3f43b4f84e | ||
|
|
923be72f83 | ||
|
|
700440e0f3 | ||
|
|
7d59bf0f64 | ||
|
|
3f8091f15a | ||
|
|
8e0716b082 | ||
|
|
1eb17e0903 | ||
|
|
14c5e416e3 | ||
|
|
2e70d1dbe5 | ||
|
|
d8ceb92fcc | ||
|
|
ddd949b958 | ||
|
|
780e40c538 | ||
|
|
c939f74973 | ||
|
|
6e2188ef57 | ||
|
|
ebff9819e9 | ||
|
|
c4d746554b | ||
|
|
dfa5717634 | ||
|
|
14e9c92103 | ||
|
|
5f4f0bf1e6 | ||
|
|
deb0e4ee28 | ||
|
|
59040bcaaa | ||
|
|
a6a2d6ced9 | ||
|
|
5303e4fc8c | ||
|
|
010caf4f10 | ||
|
|
beea64e0dc | ||
|
|
5c2cca7db2 | ||
|
|
5637219381 | ||
|
|
58b76f95b2 | ||
|
|
7a6af69ba8 | ||
|
|
6b4720e854 | ||
|
|
72c2ffce20 | ||
|
|
352041bd83 | ||
|
|
7778d0116c | ||
|
|
3ea2a44644 | ||
|
|
0ce06d0a65 | ||
|
|
efc03cf36f | ||
|
|
9087f55082 | ||
|
|
c4618712a0 | ||
|
|
5d722018ba | ||
|
|
17c37ca31c | ||
|
|
0f9b3af702 | ||
|
|
122acc8cfc | ||
|
|
f4148ccf2d | ||
|
|
852b5011b5 | ||
|
|
9aadfdb56c | ||
|
|
2162d59e4e | ||
|
|
da37aa322d | ||
|
|
b335e24a13 | ||
|
|
9a0c9856d3 | ||
|
|
86256cad5d | ||
|
|
c0d43e104e | ||
|
|
bb617aa011 | ||
|
|
f3b1fa4a60 | ||
|
|
71b8db3a9a | ||
|
|
aef01f5394 | ||
|
|
cb54d306f9 | ||
|
|
70debab1ce | ||
|
|
71edf928c8 | ||
|
|
251a65dfe2 | ||
|
|
b2a81a3d7e | ||
|
|
c1ee663c10 | ||
|
|
32b0659781 | ||
|
|
261e788b4b | ||
|
|
d7d393915e | ||
|
|
d64b72d8fd | ||
|
|
5e124df2db | ||
|
|
54cca63d30 | ||
|
|
a360d1ff46 | ||
|
|
f0f7d04113 | ||
|
|
af3de31400 | ||
|
|
8195694d54 | ||
|
|
e13b7bf325 | ||
|
|
a1e0baea6b | ||
|
|
16999286b6 | ||
|
|
673fb318a9 | ||
|
|
7a29841637 | ||
|
|
372a2a96af | ||
|
|
bbb91873be | ||
|
|
912328358c | ||
|
|
293ec0d7c9 | ||
|
|
f0c7d69b86 | ||
|
|
a2080b3378 | ||
|
|
1b611e1bee | ||
|
|
a3059ecfb2 | ||
|
|
ca60852f72 | ||
|
|
95655e1884 | ||
|
|
40a88a72aa | ||
|
|
6e0db94a9d | ||
|
|
2607730ae3 | ||
|
|
3c66bcb735 | ||
|
|
1dc49da1cb | ||
|
|
bd0d093bad | ||
|
|
770dd633db | ||
|
|
944bea7be8 | ||
|
|
9ea5c1a2b0 | ||
|
|
0ac7bff9c6 | ||
|
|
9ded4a5c19 | ||
|
|
c6d1381fb4 | ||
|
|
e45ea65375 | ||
|
|
e115aca98d | ||
|
|
300e6fafe8 | ||
|
|
0e0fc46b35 | ||
|
|
5f9fe4c7b3 | ||
|
|
e174970572 | ||
|
|
6a0ca4e14c | ||
|
|
379052de37 | ||
|
|
5c7bff1cc5 | ||
|
|
338cdcc115 | ||
|
|
e4abfe81b8 | ||
|
|
b15dc02b2a | ||
|
|
bd0892c974 | ||
|
|
9247bf55f4 | ||
|
|
94d3df3717 | ||
|
|
fd8f8e85b0 | ||
|
|
dd341f2f32 | ||
|
|
7520900f79 | ||
|
|
550e49b9df | ||
|
|
de090950d0 | ||
|
|
ff74101e1b | ||
|
|
196f398e9f | ||
|
|
2ab4e97376 | ||
|
|
edf5dfe3e9 | ||
|
|
7d6d88eb1c | ||
|
|
ca052cf9ed | ||
|
|
0e8128247f | ||
|
|
2210bdaf09 | ||
|
|
f2bca09409 | ||
|
|
71820613ac | ||
|
|
07b458931d | ||
|
|
460ff921b5 | ||
|
|
455497137d | ||
|
|
c3e0794dac | ||
|
|
9c7449fb49 | ||
|
|
9a6ca5c470 | ||
|
|
df7ef174ae | ||
|
|
47f3be4dd5 | ||
|
|
c07a381b03 | ||
|
|
349112862e | ||
|
|
57d6a76259 | ||
|
|
adb1650aa3 | ||
|
|
bc01294a88 | ||
|
|
218a91458a | ||
|
|
8565b15660 | ||
|
|
a034b5b04e | ||
|
|
9b753ab59f | ||
|
|
d8892d524c | ||
|
|
a0ecb0cc3c | ||
|
|
9e8816331f | ||
|
|
8d9737dce6 | ||
|
|
aff1f2501e | ||
|
|
1f531e65e3 | ||
|
|
a8485dc6d6 | ||
|
|
165eb1f3e7 | ||
|
|
c489ce3000 | ||
|
|
39223e515f | ||
|
|
ea6c1b6230 | ||
|
|
7ece2cabd3 | ||
|
|
5a7a1ab379 | ||
|
|
5bdca475f1 | ||
|
|
ab8975174d | ||
|
|
c7d153cbbb | ||
|
|
075a14cd43 | ||
|
|
3fcdad6278 | ||
|
|
dc785821c0 | ||
|
|
0ec38e800a | ||
|
|
4ddbdc2f1b | ||
|
|
60aa83fdd4 | ||
|
|
4078b3aa79 | ||
|
|
47dd25a0aa | ||
|
|
bb33ee662c | ||
|
|
dd843d4484 | ||
|
|
51df805a81 | ||
|
|
a65023af76 | ||
|
|
6e4e90b77a | ||
|
|
ef3d4161e5 | ||
|
|
c6a7fdc9d4 | ||
|
|
e33638fe9d | ||
|
|
23dca0cd0d | ||
|
|
c815194539 | ||
|
|
3929f9e90e | ||
|
|
e507bdc0e4 | ||
|
|
eb94916257 | ||
|
|
19d1fdff7c | ||
|
|
ac3567a097 | ||
|
|
93069ee44f | ||
|
|
e9fe9e755c | ||
|
|
2146c122aa | ||
|
|
67681ec324 | ||
|
|
febd18f728 | ||
|
|
745e9ef82f | ||
|
|
4fa72e4d11 | ||
|
|
a905678adc | ||
|
|
88670a2902 | ||
|
|
fa450103b8 | ||
|
|
96b3e6bc09 | ||
|
|
8e247cc6a3 | ||
|
|
6625300b0d | ||
|
|
7e6ae2d3b4 | ||
|
|
1bd82c3ea9 | ||
|
|
81f7db2d51 | ||
|
|
1fd30794f5 | ||
|
|
03d79b534e | ||
|
|
baee7785fd | ||
|
|
693f52fa84 | ||
|
|
369748c404 | ||
|
|
3bb36458a1 | ||
|
|
fb90452743 | ||
|
|
d3734ecb52 | ||
|
|
03eff5665c | ||
|
|
7393667c57 | ||
|
|
a6bfdceed2 | ||
|
|
6bdfb292f2 | ||
|
|
cd11dabef8 | ||
|
|
18b33c63ad | ||
|
|
ee58b4b226 | ||
|
|
a54a0757a8 | ||
|
|
5ea2ee0bfb | ||
|
|
ce3e961fed | ||
|
|
443637dcd2 | ||
|
|
cf0978ad98 | ||
|
|
8058b22442 | ||
|
|
0a074deaa3 | ||
|
|
74bb80deb6 | ||
|
|
0f506c60ed | ||
|
|
a6be688d45 | ||
|
|
d5e9e1ba68 | ||
|
|
4c439372a6 | ||
|
|
07df807261 | ||
|
|
eba3a79748 | ||
|
|
eddf277649 | ||
|
|
7e01424293 | ||
|
|
9a2719509c | ||
|
|
4366d35d49 | ||
|
|
6b33a12391 | ||
|
|
f2e4744fc4 | ||
|
|
2367b2f504 | ||
|
|
9d702a3135 | ||
|
|
3fcc1a8bb2 | ||
|
|
56c39ebf06 | ||
|
|
93c9217da1 | ||
|
|
03a7150261 | ||
|
|
74dd7b71b7 | ||
|
|
2cf3949e32 | ||
|
|
54b083e10a | ||
|
|
b1b52b0143 | ||
|
|
82d26bceb4 | ||
|
|
0841fa9252 | ||
|
|
7a7d102788 | ||
|
|
90f7b103f2 | ||
|
|
2c5e45746f | ||
|
|
b3f2fec373 | ||
|
|
4472e53a91 | ||
|
|
40ca720fc0 | ||
|
|
31ca9f0983 | ||
|
|
aaf74cba98 | ||
|
|
2b0fe4a3ef | ||
|
|
d46e9784ab | ||
|
|
66da10b424 | ||
|
|
ab6d0556fe | ||
|
|
6beacbba8a | ||
|
|
ad696be16d | ||
|
|
8e89253fad | ||
|
|
8b2d288738 | ||
|
|
020cd464d7 | ||
|
|
f3965a147d | ||
|
|
93c27b3700 | ||
|
|
be8b424ef4 | ||
|
|
aeecd32b9b | ||
|
|
0706496a46 | ||
|
|
afdadec486 | ||
|
|
c6322dc7d5 | ||
|
|
eab48b4a77 | ||
|
|
9e753e6ef6 | ||
|
|
0f6cd492bf | ||
|
|
02e0539f3c | ||
|
|
c80c627dd0 | ||
|
|
c21651adee | ||
|
|
6d80c9d7b2 | ||
|
|
b2b4b1a7d6 | ||
|
|
1ad46af73b | ||
|
|
6b8af07217 | ||
|
|
7826ad63b8 | ||
|
|
2fcdb49939 | ||
|
|
50891f3a2d | ||
|
|
6dd788dfc6 |
@@ -0,0 +1,7 @@
|
||||
puts exe:\t[info nameofexecutable]
|
||||
puts ver:\t[info patchlevel]
|
||||
catch {
|
||||
puts build:\t[tcl::build-info]
|
||||
}
|
||||
puts lib:\t[info library]
|
||||
puts plat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]
|
||||
@@ -5,32 +5,54 @@ on:
|
||||
- "main"
|
||||
- "core-9-0-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
- "core-*"
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
plan:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
gcc: ${{ steps.matrix.outputs.gcc }}
|
||||
steps:
|
||||
- name: Select build matrix based on branch name
|
||||
id: matrix
|
||||
run: |
|
||||
(
|
||||
echo gcc=$(jq -nc '{config: (if env.IsMatched == "true" then env.FULL else env.PARTIAL end) | fromjson }' )
|
||||
) | tee -a $GITHUB_OUTPUT
|
||||
env:
|
||||
IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }}
|
||||
# DO NOT CHANGE THESE MATRIX SPECS; IT AFFECTS OUR COST CONTROLS
|
||||
FULL: >
|
||||
[
|
||||
"",
|
||||
"CFLAGS=-DTCL_NO_DEPRECATED=1",
|
||||
"--disable-shared",
|
||||
"--disable-zipfs",
|
||||
"--enable-symbols",
|
||||
"--enable-symbols=mem",
|
||||
"--enable-symbols=all",
|
||||
"CFLAGS=-ftrapv",
|
||||
"CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit"
|
||||
]
|
||||
PARTIAL: >
|
||||
[
|
||||
"",
|
||||
"--enable-symbols=all",
|
||||
"CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit"
|
||||
]
|
||||
gcc:
|
||||
needs: plan
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- ""
|
||||
- "CFLAGS=-DTCL_NO_DEPRECATED=1"
|
||||
- "--disable-shared"
|
||||
- "--disable-zipfs"
|
||||
- "--enable-symbols"
|
||||
- "--enable-symbols=mem"
|
||||
- "--enable-symbols=all"
|
||||
- "CFLAGS=-ftrapv"
|
||||
# Duplicated below
|
||||
- "CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit"
|
||||
matrix: ${{ fromJson(needs.plan.outputs.gcc) }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: unix
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
timeout-minutes: 5
|
||||
- name: Install 32-bit dependencies if needed
|
||||
# Duplicated from above
|
||||
@@ -60,7 +82,7 @@ jobs:
|
||||
- name: Info
|
||||
run: |
|
||||
ulimit -a || echo 'get limit failed'
|
||||
echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
|
||||
make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed'
|
||||
- name: Run Tests
|
||||
run: |
|
||||
make test
|
||||
@@ -72,10 +94,12 @@ jobs:
|
||||
make install
|
||||
timeout-minutes: 5
|
||||
- name: Create Distribution Package
|
||||
if: ${{ matrix.config == '' }}
|
||||
run: |
|
||||
make dist
|
||||
timeout-minutes: 5
|
||||
- name: Convert Documentation to HTML
|
||||
if: ${{ matrix.config == '' }}
|
||||
run: |
|
||||
make html-tcl
|
||||
timeout-minutes: 5
|
||||
|
||||
@@ -5,10 +5,38 @@ on:
|
||||
- "main"
|
||||
- "core-9-0-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
- "core-*"
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
plan:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
clang: ${{ steps.matrix.outputs.clang }}
|
||||
steps:
|
||||
- name: Select build matrix based on branch name
|
||||
id: matrix
|
||||
run: |
|
||||
(
|
||||
echo clang=$(jq -nc '{config: (if env.IsMatched == "true" then env.FULL else env.PARTIAL end) | fromjson }' )
|
||||
) | tee -a $GITHUB_OUTPUT
|
||||
env:
|
||||
IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }}
|
||||
# DO NOT CHANGE THIS MATRIX SPEC; IT AFFECTS OUR COST CONTROLS
|
||||
FULL: >
|
||||
[
|
||||
"",
|
||||
"--disable-shared",
|
||||
"--disable-zipfs",
|
||||
"--enable-symbols",
|
||||
"--enable-symbols=mem",
|
||||
"--enable-symbols=all"
|
||||
]
|
||||
PARTIAL: >
|
||||
[
|
||||
"",
|
||||
"--enable-symbols=all"
|
||||
]
|
||||
xcode:
|
||||
runs-on: macos-15
|
||||
defaults:
|
||||
@@ -17,7 +45,7 @@ jobs:
|
||||
working-directory: macosx
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
timeout-minutes: 5
|
||||
- name: Prepare
|
||||
run: |
|
||||
@@ -36,22 +64,16 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
clang:
|
||||
runs-on: macos-15
|
||||
needs: plan
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- ""
|
||||
- "--disable-shared"
|
||||
- "--disable-zipfs"
|
||||
- "--enable-symbols"
|
||||
- "--enable-symbols=mem"
|
||||
- "--enable-symbols=all"
|
||||
matrix: ${{ fromJson(needs.plan.outputs.clang) }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: unix
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
timeout-minutes: 5
|
||||
- name: Prepare
|
||||
run: |
|
||||
@@ -74,7 +96,7 @@ jobs:
|
||||
- name: Info
|
||||
run: |
|
||||
ulimit -a || echo 'get limit failed'
|
||||
echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
|
||||
make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed'
|
||||
- name: Run Tests
|
||||
run: |
|
||||
make test
|
||||
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
- "main"
|
||||
- "core-9-0-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
- "core-*"
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Prepare
|
||||
run: |
|
||||
touch generic/tclStubInit.c generic/tclOOStubInit.c
|
||||
@@ -61,9 +61,9 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Checkout create-dmg
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: create-dmg/create-dmg
|
||||
ref: v1.0.8
|
||||
@@ -139,7 +139,7 @@ jobs:
|
||||
msystem: UCRT64
|
||||
install: git mingw-w64-ucrt-x86_64-toolchain make zip
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Prepare
|
||||
run: |
|
||||
touch generic/tclStubInit.c generic/tclOOStubInit.c
|
||||
@@ -194,7 +194,7 @@ jobs:
|
||||
run: |
|
||||
mkdir data
|
||||
- name: Get Linux build
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: data
|
||||
# Can't download by artifact ID; stupid missing feature!
|
||||
@@ -205,7 +205,7 @@ jobs:
|
||||
working-directory: data
|
||||
- name: Transfer built files
|
||||
# https://github.com/marketplace/actions/rsync-deployments-action
|
||||
uses: burnett01/rsync-deployments@7.0.2
|
||||
uses: burnett01/rsync-deployments@7.1.0
|
||||
id: rsync
|
||||
if: false # Disabled... for now
|
||||
with:
|
||||
|
||||
@@ -5,31 +5,69 @@ on:
|
||||
- "main"
|
||||
- "core-9-0-branch"
|
||||
tags:
|
||||
- "core-**"
|
||||
- "core-*"
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
ERROR_ON_FAILURES: 1
|
||||
jobs:
|
||||
plan:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
msvc: ${{ steps.matrix.outputs.msvc }}
|
||||
gcc: ${{ steps.matrix.outputs.gcc }}
|
||||
steps:
|
||||
- name: Select build matrix based on branch name
|
||||
id: matrix
|
||||
run: |
|
||||
(
|
||||
echo msvc=$(jq -nc '{config: (if env.IsMatched == "true" then env.MSVC_FULL else env.MSVC_PARTIAL end) | fromjson }' )
|
||||
echo gcc=$(jq -nc '{config: (if env.IsMatched == "true" then env.GCC_FULL else env.GCC_PARTIAL end) | fromjson }' )
|
||||
) | tee -a $GITHUB_OUTPUT
|
||||
env:
|
||||
IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }}
|
||||
# DO NOT CHANGE THESE MATRIX SPECS; IT AFFECTS OUR COST CONTROLS
|
||||
MSVC_FULL: >
|
||||
[
|
||||
"",
|
||||
"CHECKS=nodep",
|
||||
"OPTS=static",
|
||||
"OPTS=noembed",
|
||||
"OPTS=symbols",
|
||||
"OPTS=symbols STATS=compdbg,memdbg"
|
||||
]
|
||||
MSVC_PARTIAL: >
|
||||
[
|
||||
"",
|
||||
"OPTS=symbols STATS=compdbg,memdbg"
|
||||
]
|
||||
GCC_FULL: >
|
||||
[
|
||||
"",
|
||||
"CFLAGS=-DTCL_NO_DEPRECATED=1",
|
||||
"--disable-shared",
|
||||
"--disable-zipfs",
|
||||
"--enable-symbols",
|
||||
"--enable-symbols=mem",
|
||||
"--enable-symbols=all"
|
||||
]
|
||||
GCC_PARTIAL: >
|
||||
[
|
||||
"",
|
||||
"--disable-shared",
|
||||
"--enable-symbols=all"
|
||||
]
|
||||
msvc:
|
||||
runs-on: windows-2025
|
||||
needs: plan
|
||||
defaults:
|
||||
run:
|
||||
shell: powershell
|
||||
working-directory: win
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- ""
|
||||
- "CHECKS=nodep"
|
||||
- "OPTS=static"
|
||||
- "OPTS=noembed"
|
||||
- "OPTS=symbols"
|
||||
- "OPTS=symbols STATS=compdbg,memdbg"
|
||||
matrix: ${{ fromJson(needs.plan.outputs.msvc) }}
|
||||
# Using powershell means we need to explicitly stop on failure
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
timeout-minutes: 5
|
||||
- name: Init MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
@@ -55,23 +93,17 @@ jobs:
|
||||
throw "nmake exit code: $lastexitcode"
|
||||
}
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
ERROR_ON_FAILURES: 1
|
||||
gcc:
|
||||
runs-on: windows-2025
|
||||
needs: plan
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
working-directory: win
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- ""
|
||||
- "CFLAGS=-DTCL_NO_DEPRECATED=1"
|
||||
- "--disable-shared"
|
||||
- "--disable-zipfs"
|
||||
- "--enable-symbols"
|
||||
- "--enable-symbols=mem"
|
||||
- "--enable-symbols=all"
|
||||
# Using powershell means we need to explicitly stop on failure
|
||||
matrix: ${{ fromJson(needs.plan.outputs.gcc) }}
|
||||
steps:
|
||||
- name: Install MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
@@ -80,7 +112,7 @@ jobs:
|
||||
install: git mingw-w64-x86_64-toolchain make
|
||||
timeout-minutes: 10
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
timeout-minutes: 5
|
||||
- name: Prepare
|
||||
run: |
|
||||
@@ -102,10 +134,12 @@ jobs:
|
||||
- name: Info
|
||||
run: |
|
||||
ulimit -a || echo 'get limit failed'
|
||||
echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
|
||||
make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed'
|
||||
- name: Run Tests
|
||||
run: make test
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
ERROR_ON_FAILURES: 1
|
||||
|
||||
# If you add builds with Wine, be sure to define the environment variable
|
||||
# CI_USING_WINE when running them so that broken tests know not to run.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>tcl9</name>
|
||||
<name>tcl9.1</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# README: Tcl
|
||||
|
||||
This is the **Tcl 9.1a0** source distribution.
|
||||
This is the **Tcl 9.1a1** source distribution.
|
||||
|
||||
You can get any source release of Tcl from [our distribution
|
||||
site](https://sourceforge.net/projects/tcl/files/Tcl/).
|
||||
@@ -31,7 +31,7 @@ site](https://sourceforge.net/projects/tcl/files/Tcl/).
|
||||
Tcl provides a powerful platform for creating integration applications that
|
||||
tie together diverse applications, protocols, devices, and frameworks.
|
||||
When paired with the Tk toolkit, Tcl provides the fastest and most powerful
|
||||
way to create GUI applications that run on PCs, Unix, and Mac OS X.
|
||||
way to create GUI applications that run on PCs, Unix, and macOS.
|
||||
Tcl can also be used for a variety of web-related tasks and for creating
|
||||
powerful command languages for applications.
|
||||
|
||||
|
||||
+19
-1
@@ -4,12 +4,30 @@ changes to the Tcl source code at
|
||||
|
||||
> [Tcl Source Code](https://core.tcl-lang.org/tcl/timeline)
|
||||
|
||||
Release Tcl 9.1a0 arises from the check-in with tag `core-9-1-a0`.
|
||||
Release Tcl 9.1a1 arises from the check-in with tag `core-9-1-a1`.
|
||||
|
||||
Highlighted differences between Tcl 9.1 and Tcl 9.0 are summarized below,
|
||||
with focus on changes important to programmers using the Tcl library and
|
||||
writing Tcl scripts.
|
||||
|
||||
# New commands and options
|
||||
|
||||
- [New options -backslashes, -commands and -variables for subst command](https://core.tcl-lang.org/tips/doc/trunk/tip/712.md)
|
||||
- [New command unicode for Unicode normalization](https://core.tcl-lang.org/tips/doc/trunk/tip/726.md)
|
||||
|
||||
# New public C API
|
||||
|
||||
- [Tcl\_IsEmpty checks if the string representation of a value would be the empty string](https://core.tcl-lang.org/tips/doc/trunk/tip/711.md)
|
||||
- [Tcl\_GetEncodingNameForUser returns name of encoding from user settings](https://core.tcl-lang.org/tips/doc/trunk/tip/716.md)
|
||||
- [Tcl\_AttemptCreateHashEntry - version of Tcl\_CreateHashEntry that returns NULL instead of panic'ing on memory allocation errors](https://core.tcl-lang.org/tips/doc/trunk/tip/717.md)
|
||||
- [Tcl\_ListObjRange, Tcl\_ListObjRepeat, Tcl\_TclListObjReverse - C API for new list operations](https://core.tcl-lang.org/tips/doc/trunk/tip/649.md)
|
||||
- [Tcl\_UtfToNormalized, Tcl\_UtfToNormalizedDString - C API for Unicode normalization](https://core.tcl-lang.org/tips/doc/trunk/tip/726.md)
|
||||
|
||||
# Performance
|
||||
|
||||
- [Memory efficient internal representations](https://core.tcl-lang.org/tcl/wiki?name=New+abstract+list+representations)
|
||||
for list operations on large lists.
|
||||
|
||||
# Bug fixes
|
||||
- [tclEpollNotfy PlatformEventsControl panics if websocket disconnected](https://core.tcl-lang.org/tcl/tktview/010d8f38)
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ Interpreter to use for error reporting.
|
||||
Points to space where the number of bytes in the array may be written.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will return
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
|
||||
NULL for byte arrays larger than INT_MAX (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.BE
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ for an alias.
|
||||
Pointer to location to store count of additional value arguments to be
|
||||
passed to the alias. The location is in storage owned by the caller.
|
||||
If it points to a variable which type is not \fBTcl_Size\fR, a compiler
|
||||
warning will be generated. If your extensions is compiled with -DTCL_8_API,
|
||||
warning will be generated. If your extensions is compiled with \fB-DTCL_8_API\fR,
|
||||
this function will return TCL_ERROR for aliases with more than INT_MAX
|
||||
value arguments, otherwise expect it to crash
|
||||
.AP Tcl_Obj ***objvPtr out
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ Points to a variable that will have the number of key/value pairs
|
||||
contained within the dictionary placed within it.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will return
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
|
||||
NULL for dictionaries larger than INT_MAX (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.AP Tcl_DictSearch *searchPtr in/out
|
||||
|
||||
+20
-7
@@ -8,7 +8,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtfDStringEx, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternalDStringEx, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings
|
||||
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtfDStringEx, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternalDStringEx, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNameForUser, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -53,6 +53,9 @@ int
|
||||
const char *
|
||||
\fBTcl_GetEncodingNameFromEnvironment\fR(\fIbufPtr\fR)
|
||||
.sp
|
||||
const char *
|
||||
\fBTcl_GetEncodingNameForUser\fR(\fIbufPtr\fR)
|
||||
.sp
|
||||
\fBTcl_GetEncodingNames\fR(\fIinterp\fR)
|
||||
.sp
|
||||
Tcl_Encoding
|
||||
@@ -308,12 +311,22 @@ procedure increments the reference count of the new system encoding,
|
||||
decrements the reference count of the old system encoding, and returns
|
||||
\fBTCL_OK\fR.
|
||||
.PP
|
||||
\fBTcl_GetEncodingNameFromEnvironment\fR provides a means for the Tcl
|
||||
library to report the encoding name it believes to be the correct one
|
||||
to use as the system encoding, based on system calls and examination of
|
||||
the environment suitable for the platform. It accepts \fIbufPtr\fR,
|
||||
a pointer to an uninitialized or freed \fBTcl_DString\fR and writes
|
||||
the encoding name to it. The \fBTcl_DStringValue\fR is returned.
|
||||
\fBTcl_GetEncodingNameFromEnvironment\fR retrieves the encoding name to
|
||||
use as the system encoding. On non-Windows platforms, this is derived
|
||||
from the \fBnl_langinfo\fR system call if available, and environment
|
||||
variables \fBLC_ALL\fR, \fBLC_CTYPE\fR or \fBLANG\fR otherwise. On
|
||||
Windows versions Windows 10 Build 18362 and later the returned value is
|
||||
always \fButf-8\fR. On earlier Windows versions, it is derived from the
|
||||
user settings in the Windows registry. \fBTcl_GetEncodingNameForUser\fR
|
||||
retrieves the encoding name based on the user settings for the current
|
||||
user and is derived in the same manner as
|
||||
\fBTcl_GetEncodingNameFromEnvironment\fR on non-Windows platforms. On
|
||||
Windows, unlike \fBTcl_GetEncodingNameFromEnvironment\fR, it returns the
|
||||
encoding name as per the Windows registry settings irrespective of the
|
||||
Windows version. Both functions accept \fIbufPtr\fR, a pointer to an
|
||||
uninitialized or freed \fBTcl_DString\fR and write the encoding name to
|
||||
it. They return \fBTcl_DStringValue(bufPtr)\fR which points to the stored
|
||||
name.
|
||||
.PP
|
||||
\fBTcl_GetEncodingNames\fR sets the \fIinterp\fR result to a list
|
||||
consisting of the names of all the encodings that are currently defined
|
||||
|
||||
+1
-1
@@ -278,7 +278,7 @@ permissions will be set on the created file.
|
||||
Filled with the number of elements in the split path.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will return
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
|
||||
NULL for paths having more than INT_MAX elements (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.AP Tcl_Obj *basePtr in
|
||||
|
||||
+10
-1
@@ -9,7 +9,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_DeleteHashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, Tcl_HashStats \- procedures to manage hash tables
|
||||
Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_AttemptCreateHashEntry, Tcl_DeleteHashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, Tcl_HashStats \- procedures to manage hash tables
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -25,6 +25,9 @@ Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHash
|
||||
Tcl_HashEntry *
|
||||
\fBTcl_CreateHashEntry\fR(\fItablePtr, key, newPtr\fR)
|
||||
.sp
|
||||
Tcl_HashEntry *
|
||||
\fBTcl_AttemptCreateHashEntry\fR(\fItablePtr, key, newPtr\fR)
|
||||
.sp
|
||||
\fBTcl_DeleteHashEntry\fR(\fIentryPtr\fR)
|
||||
.sp
|
||||
Tcl_HashEntry *
|
||||
@@ -170,10 +173,16 @@ If an entry already existed with the given key then \fI*newPtr\fR
|
||||
is set to zero.
|
||||
If a new entry was created, then \fI*newPtr\fR is set to a non-zero
|
||||
value and the value of the new entry will be set to zero.
|
||||
\fI*newPtr\fR is allowed to be NULL.
|
||||
The return value from \fBTcl_CreateHashEntry\fR is a pointer to
|
||||
the entry, which may be used to retrieve and modify the entry's
|
||||
value or to delete the entry from the table.
|
||||
.PP
|
||||
\fBTcl_AttemptCreateHashEntry\fR does the same as
|
||||
\fBTcl_CreateHashEntry\fR, except in case of a memory
|
||||
overflow. \fBTcl_AttemptCreateHashEntry\fR returns NULL
|
||||
in that case while \fBTcl_CreateHashEntry\fR panics.
|
||||
.PP
|
||||
\fBTcl_DeleteHashEntry\fR will remove an existing entry from a
|
||||
table.
|
||||
The memory associated with the entry itself will be freed, but
|
||||
|
||||
+83
-33
@@ -4,11 +4,11 @@
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH Tcl_ListObj 3 8.0 Tcl "Tcl Library Procedures"
|
||||
.TH Tcl_ListObj 3 9.1 Tcl "Tcl Library Procedures"
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjGetElements, Tcl_ListObjLength, Tcl_ListObjIndex, Tcl_ListObjReplace \- manipulate Tcl values as lists
|
||||
Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjGetElements, Tcl_ListObjLength, Tcl_ListObjIndex, Tcl_ListObjReplace, Tcl_ListObjRange, Tcl_ListObjRepeat, Tcl_ListObjReverse \- manipulate Tcl values as lists
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -35,6 +35,15 @@ int
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ListObjReplace\fR(\fIinterp, listPtr, first, count, objc, objv\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ListObjRange\fR(\fIinterp, listPtr, first, last, objPtrPtr\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ListObjRepeat\fR(\fIinterp, count, objc, objv, objPtrPtr\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ListObjReverse\fR(\fIinterp, listPtr, objPtrPtr\fR)
|
||||
.fi
|
||||
.SH ARGUMENTS
|
||||
.AS "Tcl_Obj *const" *elemListPtr in/out
|
||||
@@ -43,9 +52,12 @@ If an error occurs while converting a value to be a list value,
|
||||
an error message is left in the interpreter's result value
|
||||
unless \fIinterp\fR is NULL.
|
||||
.AP Tcl_Obj *listPtr in/out
|
||||
Points to the list value to be manipulated.
|
||||
Points to the input list value.
|
||||
If \fIlistPtr\fR does not already point to a list value,
|
||||
an attempt will be made to convert it to one.
|
||||
Some functions may store a reference to it internally so
|
||||
care must be taken when managing its reference count.
|
||||
See the \fBREFERENCE COUNT MANAGEMENT\fR section below.
|
||||
.AP Tcl_Obj *elemListPtr in/out
|
||||
For \fBTcl_ListObjAppendList\fR, this points to a list value
|
||||
containing elements to be appended onto \fIlistPtr\fR.
|
||||
@@ -65,29 +77,22 @@ Points to location where \fBTcl_ListObjGetElements\fR
|
||||
stores the number of element values in \fIlistPtr\fR.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will return
|
||||
If your extensions is compiled with \fB\-DTCL_8_API\fR, this function will return
|
||||
NULL for lists with more than INT_MAX elements (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.AP Tcl_Obj ***objvPtr out
|
||||
A location where \fBTcl_ListObjGetElements\fR stores a pointer to an array
|
||||
of pointers to the element values of \fIlistPtr\fR.
|
||||
.AP Tcl_Size objc in
|
||||
The number of Tcl values that \fBTcl_NewListObj\fR
|
||||
will insert into a new list value,
|
||||
and \fBTcl_ListObjReplace\fR will insert into \fIlistPtr\fR.
|
||||
For \fBTcl_SetListObj\fR,
|
||||
the number of Tcl values to insert into \fIobjPtr\fR.
|
||||
The number of Tcl values in the \fIobjv\fR array.
|
||||
.AP "Tcl_Obj *const" objv[] in
|
||||
An array of pointers to values.
|
||||
\fBTcl_NewListObj\fR will insert these values into a new list value
|
||||
and \fBTcl_ListObjReplace\fR will insert them into an existing \fIlistPtr\fR.
|
||||
Each value will become a separate list element.
|
||||
An array of pointers to Tcl values.
|
||||
.AP "Tcl_Size \&| int" *lengthPtr out
|
||||
Points to location where \fBTcl_ListObjLength\fR
|
||||
stores the length of the list.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will return
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
|
||||
TCL_ERROR for lists with more than INT_MAX elements (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.AP Tcl_Size index in
|
||||
@@ -95,23 +100,22 @@ Index of the list element that \fBTcl_ListObjIndex\fR
|
||||
is to return.
|
||||
The first element has index 0.
|
||||
.AP Tcl_Obj **objPtrPtr out
|
||||
Points to place where \fBTcl_ListObjIndex\fR is to store
|
||||
a pointer to the resulting list element value.
|
||||
Points to location to store an output list or element value. No assumptions
|
||||
should be made about the reference count of the returned value.
|
||||
See the \fBREFERENCE COUNT MANAGEMENT\fR section below.
|
||||
.AP Tcl_Size first in
|
||||
Index of the starting list element that \fBTcl_ListObjReplace\fR
|
||||
is to replace.
|
||||
The list's first element has index 0.
|
||||
Index of the first element in a range of elements in a list.
|
||||
.AP Tcl_Size last in
|
||||
Index of the last element in a range of elements in a list.
|
||||
.AP Tcl_Size count in
|
||||
The number of elements that \fBTcl_ListObjReplace\fR
|
||||
is to replace.
|
||||
The number of elements to be operated on or a repetition count.
|
||||
.BE
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Tcl list values have an internal representation that supports
|
||||
the efficient indexing and appending.
|
||||
The procedures described in this man page are used to
|
||||
create, modify, index, and append to Tcl list values from C code.
|
||||
create, modify, access, and transform Tcl list values from C code.
|
||||
.PP
|
||||
\fBTcl_ListObjAppendList\fR and \fBTcl_ListObjAppendElement\fR
|
||||
both add one or more values
|
||||
@@ -209,7 +213,6 @@ change from Tcl 8 where all list elements always have a reference
|
||||
count of at least 1. (See \fBABSTRACT LIST TYPES\fR, \fBSTORAGE
|
||||
MANAGEMENT OF VALUES\fR, Tcl_BounceRefCount(3), and lseq(n) for more
|
||||
information.)
|
||||
|
||||
.PP
|
||||
\fBTcl_ListObjReplace\fR replaces zero or more elements
|
||||
of the list referenced by \fIlistPtr\fR
|
||||
@@ -268,8 +271,44 @@ with a NULL \fIobjvPtr\fR:
|
||||
result = \fBTcl_ListObjReplace\fR(interp, listPtr, first, count,
|
||||
0, NULL);
|
||||
.CE
|
||||
.PP
|
||||
\fBTcl_ListObjRange\fR stores in \fIobjPtrPtr\fR a pointer to a list value
|
||||
containing all elements in the passed input list \fIlistPtr\fR at indices
|
||||
between \fIfirst\fR and \fIlast\fR, both inclusive. An empty
|
||||
list is returned in the case of \fIfirst\fR being greater than \fIlast\fR.
|
||||
.PP
|
||||
\fBTcl_ListObjRepeat\fR stores in \fIobjPtrPtr\fR a pointer to a list value
|
||||
whose elements are the \fIobjc\fR elements passed in \fIobjv\fR, repeated
|
||||
\fIcount\fR number of times. An error is raised if \fIcount\fR is negative.
|
||||
.PP
|
||||
\fBTcl_ListObjReverse\fR stores in \fIobjPtrPtr\fR a pointer to a list value
|
||||
containing all elements of the input list \fIlistPtr\fR in reverse order.
|
||||
.PP
|
||||
For all three functions, \fBTcl_ListObjRange\fR, \fBTcl_ListObjRepeat\fR and
|
||||
\fBTcl_ListObjReverse\fR, the value passed in \fIlistPtr\fR need not be unshared.
|
||||
The pointer stored at \fIobjPtrPtr\fR is guaranteed to be different from
|
||||
\fIlistPtr\fR but no assumptions should be made about its reference count.
|
||||
In case of errors, the location addressed by \fIobjPtrPtr\fR may have been
|
||||
modified and should be treated by the caller as undefined.
|
||||
.SH "REFERENCE COUNT MANAGEMENT"
|
||||
.PP
|
||||
Care must be taken by callers when managing the reference count
|
||||
of values passed in as well as values returned from the above functions.
|
||||
.PP
|
||||
Unless specified otherwise below, the above functions may internally
|
||||
keep a reference to the value passed in \fIlistPtr\fR and increment its
|
||||
reference count. Therefore, if \fIlistPtr\fR is newly allocated and has
|
||||
a zero reference count, it should not be freed after the call with
|
||||
\fBTcl_DecrRefCount\fR. Rather, use \fBTcl_BounceRefCount\fR instead.
|
||||
Furthermore, if \fIlistPtr\fR was retrieved from the interpreter result
|
||||
(e.g. via \fBTcl_GetObjResult\fR) and that is the only reference to the
|
||||
value, it may be deleted if a function sets the interpreter result on
|
||||
error. The more general and safe method for passing values is to
|
||||
increment their reference counts with \fBTcl_IncrRefCount\fR prior to
|
||||
the call and release them with \fBTcl_DecrRefCount\fR when the call
|
||||
returns. However, this may preclude certain optimizations based on
|
||||
modifying unshared values in-place.
|
||||
.PP
|
||||
\fBTcl_NewListObj\fR always returns a zero-reference object, much like
|
||||
\fBTcl_NewObj\fR. If a non-NULL \fIobjv\fR argument is given, the reference
|
||||
counts of the first \fIobjc\fR values in that array are incremented.
|
||||
@@ -279,20 +318,31 @@ argument, but does require that the object be unshared. The reference counts
|
||||
of the first \fIobjc\fR values in the \fIobjv\fR array are incremented.
|
||||
.PP
|
||||
\fBTcl_ListObjGetElements\fR, \fBTcl_ListObjIndex\fR, and
|
||||
\fBTcl_ListObjLength\fR do not modify the reference count of their
|
||||
\fIlistPtr\fR arguments; they only read. Note however that these three
|
||||
functions may set the interpreter result; if that is the only place that is
|
||||
holding a reference to the object, it will be deleted.
|
||||
\fBTcl_ListObjLength\fR do not modify the reference count of the
|
||||
\fIlistPtr\fR argument except on error when the interpreter
|
||||
result holds a reference to it as described earlier.
|
||||
.PP
|
||||
\fBTcl_ListObjAppendList\fR, \fBTcl_ListObjAppendElement\fR, and
|
||||
\fBTcl_ListObjReplace\fR require an unshared \fIlistPtr\fR argument.
|
||||
\fBTcl_ListObjAppendList\fR only reads its \fIelemListPtr\fR argument.
|
||||
\fBTcl_ListObjAppendElement\fR increments the reference count of its
|
||||
\fIobjPtr\fR on success. \fBTcl_ListObjReplace\fR increments the reference
|
||||
count of the first \fIobjc\fR values in the \fIobjv\fR array on success. Note
|
||||
however that all these three functions may set the interpreter result on
|
||||
failure; if that is the only place that is holding a reference to the object,
|
||||
it will be deleted.
|
||||
\fIobjPtr\fR on success. \fBTcl_ListObjReplace\fR increments the
|
||||
reference count of the first \fIobjc\fR values in the \fIobjv\fR array
|
||||
on success. Note that the same caveat stated earlier applies if the
|
||||
interpreter result holds a reference to \fIlistPtr\fR.
|
||||
.PP
|
||||
The pointer to a result value returned in \fIobjPtrPtr\fR by the
|
||||
functions \fBTcl_ListObjRange\fR,
|
||||
\fBTcl_ListObjRepeat\fR and \fBTcl_ListObjReverse\fR is guaranteed
|
||||
to be different from the \fBlistPtr\fR passed in. It is therefore
|
||||
safe to manage its reference count independently from that of
|
||||
\fBlistPtr\fR. No assumptions should be made about its reference
|
||||
count and the standard reference counting idiom should be followed.
|
||||
The caller can pass it to a function such as \fBTcl_SetObjResult\fR,
|
||||
\fBTcl_ListObjAppendElement\fR etc. which take ownership of
|
||||
its reference count management or dispose of the value itself
|
||||
with either a \fBTcl_IncrRefCount\fR/\fBTcl_DecrRefCount\fR pair or
|
||||
\fBTcl_BounceRefCount\fR.
|
||||
.SH "SEE ALSO"
|
||||
Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_GetObjResult(3)
|
||||
.SH KEYWORDS
|
||||
|
||||
+5
-2
@@ -8,7 +8,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_BounceRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values
|
||||
Tcl_NewObj, Tcl_DuplicateObj, Tcl_AttemptDuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_BounceRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -19,6 +19,9 @@ Tcl_Obj *
|
||||
Tcl_Obj *
|
||||
\fBTcl_DuplicateObj\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_AttemptDuplicateObj\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
\fBTcl_IncrRefCount\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
\fBTcl_DecrRefCount\fR(\fIobjPtr\fR)
|
||||
@@ -28,7 +31,7 @@ Tcl_Obj *
|
||||
int
|
||||
\fBTcl_IsShared\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)3
|
||||
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)
|
||||
.fi
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_Obj *objPtr
|
||||
|
||||
+34
-5
@@ -128,6 +128,17 @@ When \fInumBytes\fR is greater than zero, and the returned pointer is
|
||||
representation.
|
||||
The caller may then choose whether to raise an error or panic.
|
||||
.PP
|
||||
\fBTcl_InitStringRep\fR performs the function of the existing internal macro
|
||||
\fBTclInitStringRep\fR, but is extended to return a pointer to the string rep,
|
||||
and to accept \fBNULL\fR as a value for bytes.
|
||||
When \fIbytes\fR is \fBNULL\fR and \fIobjPtr\fR has no string rep, an uninitialzed
|
||||
buffer of numBytes bytes is created for filling by the caller.
|
||||
When \fIbytes\fR is \fBNULL\fR and \fIobjPtr\fR has a string rep, the string
|
||||
rep will be truncated to a length of numBytes bytes.
|
||||
When numBytes is greater than zero, and the returned pointer is \fBNULL\fR, that
|
||||
indicates a failure to allocate memory for the string representation.
|
||||
The caller may then choose whether to raise an error or panic.
|
||||
.PP
|
||||
\fBTcl_HasStringRep\fR returns a boolean indicating whether or not a string
|
||||
rep is currently stored in \fIobjPtr\fR.
|
||||
This is used when the caller wants to act on \fIobjPtr\fR differently
|
||||
@@ -258,6 +269,9 @@ Tcl routines accepting string values as arguments.
|
||||
Storage for the byte array must be allocated in the heap by \fBTcl_Alloc\fR.
|
||||
Note that \fIupdateStringProc\fRs must allocate
|
||||
enough storage for the string's bytes and the terminating null byte.
|
||||
If the \fIupdateStringProc\fR cannot do that, it must set
|
||||
interp->bytes to be NULL (freeing the previous content), and set
|
||||
interp->length to the number of bytes it tried to allocate.
|
||||
.PP
|
||||
The \fIupdateStringProc\fR for Tcl's built-in double type, for example,
|
||||
calls Tcl_PrintDouble to write to a buffer of size TCL_DOUBLE_SPACE,
|
||||
@@ -338,8 +352,9 @@ without converting the value to a List type. This requires the custom
|
||||
type to provide functions that will perform the given operation on the
|
||||
custom data representation. Not all functions are required. In the
|
||||
absence of a particular function (set to NULL), the fallback is to
|
||||
allow the internal List operation to perform the operation, most
|
||||
likely causing the value type to be converted to a traditional list.
|
||||
allow the internal List operation to perform the operation, which
|
||||
may possibly cause the value type to be converted to a traditional
|
||||
list.
|
||||
.SS "SCALAR VALUE TYPES"
|
||||
.PP
|
||||
For a custom value type that is scalar or atomic in nature, i.e., not
|
||||
@@ -353,6 +368,17 @@ Version 2, \fBTCL_OBJTYPE_V2\fR, allows full List support when the
|
||||
functions described below are provided. This allows for script level
|
||||
use of the List commands without causing the type of the Tcl_Obj value
|
||||
to be converted to a list.
|
||||
|
||||
Unless specified otherwise, all functions specific to Version 2 should return
|
||||
\fBTCL_OK\fR on success and \fBTCL_ERROR\fR on failure.
|
||||
|
||||
In the case that a \fBTcl_Obj*\fR is also returned, the reference count of the
|
||||
returned \fBTcl_Obj\fR should not be incremented so, for example, if a new
|
||||
\fBTcl_Obj\fR value is returned it should have a reference count of zero.
|
||||
|
||||
The functions should not assume that any \fBTcl_Obj\fR passed in
|
||||
is unshared.
|
||||
|
||||
.SS "THE LENGTHPROC FIELD"
|
||||
.PP
|
||||
The \fBLengthProc\fR function correlates with the \fBTcl_ListObjLength\fR
|
||||
@@ -367,8 +393,11 @@ typedef Tcl_Size
|
||||
.SS "THE INDEXPROC FIELD"
|
||||
.PP
|
||||
The \fBIndexProc\fR function correlates with with the
|
||||
\fBTcl_ListObjIndex\fR C API. The function returns a Tcl_Obj value for
|
||||
the element at the specified index.
|
||||
\fBTcl_ListObjIndex\fR C API. The function should store a pointer to
|
||||
the element at the specified \fBindex\fR in \fB*elemObj\fR.
|
||||
Indices that are out of bounds should not be treated as errors;
|
||||
rather, the function should store a null pointer and
|
||||
return TCL_OK.
|
||||
.CS
|
||||
typedef int (\fBTcl_ObjTypeIndexProc\fR) (
|
||||
Tcl_Interp *interp,
|
||||
@@ -393,7 +422,7 @@ typedef int (\fBTcl_ObjTypeSliceProc\fR) (
|
||||
.PP
|
||||
The \fBReverseProc\fR correlates with the \fBlreverse\fR command,
|
||||
returning a List or Abstract List that has the same elements as the
|
||||
input Abstract List, with the elements in the reverse order.
|
||||
input Abstract List, but in reverse order.
|
||||
.CS
|
||||
typedef int (\fBTcl_ObjTypeReverseProc\fR) (
|
||||
Tcl_Interp *interp,
|
||||
|
||||
+22
-8
@@ -9,7 +9,7 @@
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_TruncateChannel, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
|
||||
Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_CloseEx, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_TruncateChannel, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -46,6 +46,9 @@ int
|
||||
int
|
||||
\fBTcl_Close\fR(\fIinterp, channel\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_CloseEx\fR(\fIinterp, channel, closeFlags\fR)
|
||||
.sp
|
||||
Tcl_Size
|
||||
\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR)
|
||||
.sp
|
||||
@@ -157,6 +160,10 @@ channel.
|
||||
The number of characters to read from the channel. If the channel's encoding
|
||||
is \fBbinary\fR, this is equivalent to the number of bytes to read from the
|
||||
channel.
|
||||
.AP int closeFlags in
|
||||
If \fB0\fR, the channel is closed in both directions. If \fBTCL_CLOSE_READ\fR,
|
||||
the channel is only closed for reading. If \fBTCL_CLOSE_WRITE\fR, the channel
|
||||
is only closed for writing. These flags must not be combined.
|
||||
.AP int appendFlag in
|
||||
If non-zero, data read from the channel will be appended to the value.
|
||||
Otherwise, the data will replace the existing contents of the value.
|
||||
@@ -369,7 +376,7 @@ If so, it returns 1, otherwise 0.
|
||||
.PP
|
||||
No attempt is made to check whether the given channel or the standard
|
||||
channels are initialized or otherwise valid.
|
||||
.SH TCL_CLOSE
|
||||
.SH "TCL_CLOSE AND TCL_CLOSEEX"
|
||||
.PP
|
||||
\fBTcl_Close\fR destroys the channel \fIchannel\fR, which must denote a
|
||||
currently open channel. The channel should not be registered in any
|
||||
@@ -383,16 +390,23 @@ immediately; output is flushed in the background and the channel will be
|
||||
closed once all of the buffered data has been output. In this case errors
|
||||
during flushing are not reported.
|
||||
.PP
|
||||
If the channel was closed successfully, \fBTcl_Close\fR returns \fBTCL_OK\fR.
|
||||
If an error occurs, \fBTcl_Close\fR returns \fBTCL_ERROR\fR and records a
|
||||
POSIX error code that can be retrieved with \fBTcl_GetErrno\fR.
|
||||
\fBTcl_CloseEx\fR allows for both full closing and half-closing of channels
|
||||
depending on its \fBcloseFlags\fR parameter. See the description of the
|
||||
parameter above. It is an error to attempt to close the channel for
|
||||
a direction for which it is not open. The channel is destroyed only when
|
||||
it has been closed for both reading and writing. Only socket and command
|
||||
pipe channels support half-closing.
|
||||
.PP
|
||||
If the channel was closed successfully, \fBTcl_Close\fR and \fBTcl_CloseEx\fR
|
||||
return \fBTCL_OK\fR. If an error occurs, they return \fBTCL_ERROR\fR and record
|
||||
a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR.
|
||||
If the channel is being closed synchronously and an error occurs during
|
||||
closing of the channel and \fIinterp\fR is not NULL, an error message is
|
||||
left in the interpreter's result.
|
||||
.PP
|
||||
Note that it is not safe to call \fBTcl_Close\fR on a channel that has been
|
||||
registered using \fBTcl_RegisterChannel\fR; see the documentation for
|
||||
\fBTcl_RegisterChannel\fR, above, for details. If the channel has ever
|
||||
Note that it is not safe to call the channel closing functions on a channel
|
||||
that has been registered using \fBTcl_RegisterChannel\fR; see the documentation
|
||||
for \fBTcl_RegisterChannel\fR, above, for details. If the channel has ever
|
||||
been given as the \fBchan\fR argument in a call to
|
||||
\fBTcl_RegisterChannel\fR, you should instead use
|
||||
\fBTcl_UnregisterChannel\fR, which will internally call \fBTcl_Close\fR
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ modified to hold number of arguments left in the unprocessed argument list
|
||||
stored in \fIremObjv\fR.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will return
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
|
||||
NULL for argument lists with more than INT_MAX elements (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.AP "Tcl_Obj *const" *objv in
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ Pointer to a string with proper list structure.
|
||||
Filled in with number of elements in \fIlist\fR.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will return
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
|
||||
TCL_ERROR for lists with more than INT_MAX elements (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.AP "const char" ***argvPtr out
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ File path in a form appropriate for the current platform (see the
|
||||
Filled in with number of path elements in \fIpath\fR.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, argcPtr will be filled
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, argcPtr will be filled
|
||||
with -1 for paths with more than INT_MAX elements (which should
|
||||
trigger proper error-handling), otherwise expect it to crash.
|
||||
.AP "const char" ***argvPtr out
|
||||
|
||||
+15
-2
@@ -8,7 +8,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj, Tcl_IsEmpty \- manipulate Tcl values as strings
|
||||
Tcl_NewStringObj, Tcl_AttemptNewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_AttemptSetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_AttemptGetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj, Tcl_IsEmpty \- manipulate Tcl values as strings
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -17,11 +17,17 @@ Tcl_Obj *
|
||||
\fBTcl_NewStringObj\fR(\fIbytes, length\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_AttemptNewStringObj\fR(\fIbytes, length\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_NewUnicodeObj\fR(\fIunicode, numChars\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_SetStringObj\fR(\fIobjPtr, bytes, length\fR)
|
||||
.sp
|
||||
char *
|
||||
\fBTcl_AttemptSetStringObj\fR(\fIobjPtr, bytes, length\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_SetUnicodeObj\fR(\fIobjPtr, unicode, numChars\fR)
|
||||
.sp
|
||||
@@ -43,6 +49,9 @@ int
|
||||
Tcl_Size
|
||||
\fBTcl_GetCharLength\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
Tcl_Size
|
||||
\fBTcl_AttemptGetCharLength\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_GetRange\fR(\fIobjPtr, first, last\fR)
|
||||
.sp
|
||||
@@ -127,7 +136,7 @@ The location where \fBTcl_GetStringFromObj\fR will store the length
|
||||
of a value's string representation.
|
||||
May be (Tcl_Size *)NULL when not used. If it points to a variable which
|
||||
type is not \fBTcl_Size\fR, a compiler warning will be generated.
|
||||
If your extensions is compiled with -DTCL_8_API, this function will
|
||||
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will
|
||||
panic for strings with more than INT_MAX bytes/characters, otherwise
|
||||
expect it to crash.
|
||||
.AP "const char" *string in
|
||||
@@ -224,6 +233,10 @@ negative, then the returned string ends at the end of the value.
|
||||
\fBTcl_GetCharLength\fR returns the number of characters (as opposed
|
||||
to bytes) in the string value.
|
||||
.PP
|
||||
\fBTcl_AttemptGetCharLength\fR returns the number of characters
|
||||
(as opposed to bytes) in the string value. It returns -1 if this
|
||||
cannot be determined.
|
||||
.PP
|
||||
\fBTcl_AppendToObj\fR appends the data given by \fIbytes\fR and
|
||||
\fIlength\fR to the string representation of the value specified by
|
||||
\fIobjPtr\fR. If the value has an invalid string representation,
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ Tcl_Obj *
|
||||
Number of elements in \fIargv\fR.
|
||||
.AP char *argv[] in
|
||||
Array of strings containing command-line arguments. On Windows, when
|
||||
using -DUNICODE, the parameter type changes to wchar_t *.
|
||||
using \fB\-DUNICODE\fR, the parameter type changes to wchar_t *.
|
||||
.AP char *charargv[] in
|
||||
As argv, but does not change type to wchar_t.
|
||||
.AP char *wideargv[] in
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
'\"
|
||||
'\" Copyright (c) 2025 Ashok P. Nadkarni.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH unicode n "9.1" Tcl "Tcl Built-In Commands"
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
unicode \- Unicode character transforms
|
||||
.SH SYNOPSIS
|
||||
\fBunicode \fIfunction\fR ?\fIoptions\fR? \fIstring\fR
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The command performs one of several Unicode character transformations, depending on
|
||||
\fIfunction\fR which may take the values described below.
|
||||
.\" METHOD: tonfc
|
||||
.VS "TIP726"
|
||||
.TP
|
||||
\fBunicode tonfc\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
|
||||
.VE "TIP726"
|
||||
.
|
||||
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form C\fR (NFC).
|
||||
.PP
|
||||
.\" METHOD: tonfd
|
||||
.VS "TIP726"
|
||||
.TP
|
||||
\fBunicode tonfd\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
|
||||
.VE "TIP726"
|
||||
.
|
||||
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form D\fR (NFD).
|
||||
.PP
|
||||
.\" METHOD: tonfkc
|
||||
.VS "TIP726"
|
||||
.TP
|
||||
\fBunicode tonfkc\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
|
||||
.VE "TIP726"
|
||||
.
|
||||
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form KC\fR (NFKC).
|
||||
.PP
|
||||
.\" METHOD: tonfkd
|
||||
.VS "TIP726"
|
||||
.TP
|
||||
\fBunicode tonfkd\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
|
||||
.VE "TIP726"
|
||||
.
|
||||
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form KD\fR (NFKD).
|
||||
.PP
|
||||
The normalization forms NFC, NFD, NFKC and NFKD referenced above are defined
|
||||
in \fBSection 3.11\fR of the Unicode standard
|
||||
(see https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/).
|
||||
.PP
|
||||
The \fB-profile\fR option determines the command behavior in the presence
|
||||
of conversion errors. The passed profile must be \fBstrict\fR or \fBreplace\fR.
|
||||
See the \fBPROFILES\fR section in the documentation
|
||||
of the \fBencoding\fR command for details on profiles.
|
||||
.PP
|
||||
.SH "SEE ALSO"
|
||||
Tcl_UtfToNormalized(3)
|
||||
.SH KEYWORDS
|
||||
Unicode, normalize
|
||||
.\" Local Variables:
|
||||
.\" mode: nroff
|
||||
.\" End:
|
||||
@@ -0,0 +1,82 @@
|
||||
'\"
|
||||
'\" Copyright (c) 2025 Ashok P. Nadkarni
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH Tcl_UtfToNormalized 3 "9.1" Tcl "Tcl Library Procedures"
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_UtfToNormalized, Tcl_UtfToNormalizedDString \- procedures for Unicode normalization
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
.sp
|
||||
int
|
||||
\fBTcl_UtfToNormalized\fR(\fIinterp, src, numBytes, normForm, profile, dst, dstLen, dstWrotePtr\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_UtfToNormalizedDString\fR(\fIinterp, src, numBytes, normForm, profile, dstPtr\fR)
|
||||
.fi
|
||||
.SH ARGUMENTS
|
||||
.AP Tcl_Interp *interp in
|
||||
Interpreter to use for error reporting, or NULL if no error reporting is
|
||||
desired.
|
||||
.AP "const char" *src in
|
||||
An array of bytes in Tcl's internal UTF-8 based encoding.
|
||||
.AP Tcl_Size numBytes in
|
||||
Length of \fIsrc\fR in bytes. If the length is negative,
|
||||
the length includes all bytes until the first nul byte.
|
||||
.AP char *dst out
|
||||
Buffer in which the converted result will be stored. No more than
|
||||
\fIdstLen\fR bytes will be stored in \fIdst\fR.
|
||||
.AP Tcl_Size dstLen in
|
||||
The size of the output buffer \fIdst\fR in bytes.
|
||||
.AP Tcl_Size *dstWrotePtr out
|
||||
Filled with the number of bytes in the normalized string. This number
|
||||
does not include the terminating nul character.
|
||||
May be NULL.
|
||||
.AP Tcl_UnicodeNormalizationForm normForm in
|
||||
Must be one of the \fBTcl_UnicodeNormalizationForm\fR members
|
||||
\fBTCL_NFC\fR, \fBTCL_NFD\fR, \fBTCL_NFKC\fR or \fBTCL_NFKD\fR specifying
|
||||
the Unicode normalization type.
|
||||
.AP int profile in/out
|
||||
The encoding profile as described in the \fBTcl_GetEncoding\fR documentation.
|
||||
Must be either \fBTCL_ENCODING_PROFILE_STRICT\fR
|
||||
or \fBTCL_ENCODING_PROFILE_REPLACE\fR.
|
||||
.AP Tcl_DString *dstPtr out
|
||||
Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted
|
||||
result, which is also encoded in Tcl's internal UTF-8 encoding, will be stored.
|
||||
The function initializes the storage and caller must call
|
||||
\fBTcl_DStringFree\fR on success.
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The \fBTcl_UtfToNormalized\fR and \fBTcl_UtfToNormalizedDString\fR functions
|
||||
transform the passed string into one of the standard normalization forms defined
|
||||
in the Unicode standard. The normalization form is specified via the
|
||||
\fInormForm\fR argument which must have one of the values \fBTCL_NFC\fR,
|
||||
\fBTCL_NFD\fR, \fBTCL_NFKC\fR or \fBTCL_NFKD\fR corresponding to the Unicode
|
||||
normalization forms \fBNormalization Form C\fR (NFC), \fBNormalization Form D\fR
|
||||
(NFD), \fBNormalization Form KC\fR (NFKC) and \fBNormalization Form KD\fR (NFKD)
|
||||
respectively. For details on the above normalization forms, refer to Section
|
||||
3.11 of the Unicode standard
|
||||
(https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/).
|
||||
.PP
|
||||
The \fBTcl_UtfToNormalized\fR function stores the normalized result
|
||||
in the buffer provided by the caller through the \fIdst\fR argument. The
|
||||
result is nul terminated but the nul is not included in the count of
|
||||
stored bytes returned in \fIdstWrotePtr\fR. The function returns TCL_OK
|
||||
on success, TCL_CONVERT_NOSPACE if there is insufficient room in the output
|
||||
buffer and TCL_ERROR in case of other failures. In the latter two cases,
|
||||
an error message is stored in \fIinterp\fR if it is not NULL.
|
||||
.PP
|
||||
The \fBTcl_UtfToNormalizedDString\fR function stores the normalized result
|
||||
in \fIdstPtr\fR which must eventually be freed by caller through
|
||||
\fBTcl_DStringFree\fR. The function returns TCL_OK on success and
|
||||
TCL_ERROR on failure with an error message in \fIinterp\fR if it is not NULL.
|
||||
.SH "SEE ALSO"
|
||||
unicode(n)
|
||||
.SH KEYWORDS
|
||||
utf, Unicode, normalize
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
'\"
|
||||
'\" Copyright (c) 2025 Jan Nijtmans.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH build-info n 9.0 Tcl "Tcl Built-In Commands"
|
||||
.so man.macros
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
buildinfo \- Build info
|
||||
.SH SYNOPSIS
|
||||
\fB::tcl::build-info\fR ?\fIfield\fR?
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
This command provides a way to retrieve information about how Tcl was built.
|
||||
Without any options, the command returns the Tcl patchlevel, followed
|
||||
by the '+'-sign, followed by the fossil commit-id followed by a list of
|
||||
dot-separated tags. If a \fIfield\fR is given, this command extracts that
|
||||
field as described below. Any other \fIfield\fR value not mentioned
|
||||
below will always return "0". For official Tcl releases, the \fIfield\fRs are:
|
||||
.\" METHOD: clang
|
||||
.TP
|
||||
\fB::tcl::build-info clang\fR
|
||||
.
|
||||
Returns the clang version number (as 4 digits) if Tcl is compiled with clang, 0 otherwise.
|
||||
.\" METHOD: commit
|
||||
.TP
|
||||
\fB::tcl::build-info commit\fR
|
||||
.
|
||||
Returns the fossil commit-id where Tcl was built from.
|
||||
.\" METHOD: compiledebug
|
||||
.TP
|
||||
\fB::tcl::build-info compiledebug\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with \fB\-DTCL_COMPILE_DEBUG\fR, 0 otherwise.
|
||||
.\" METHOD: compiler
|
||||
.TP
|
||||
\fB::tcl::build-info compiler\fR
|
||||
.
|
||||
Returns the compiler name (either clang, gcc, icc or msvc), followed by a dash and a (4-digit) version number.
|
||||
.\" METHOD: compilestats
|
||||
.TP
|
||||
\fB::tcl::build-info compilestats\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with \fB\-DTCL_COMPILE_STATS\fR, 0 otherwise.
|
||||
.\" METHOD: cplusplus
|
||||
.TP
|
||||
\fB::tcl::build-info cplusplus\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with a C++ compiler, 0 otherwise.
|
||||
.\" METHOD: debug
|
||||
.TP
|
||||
\fB::tcl::build-info debug\fR
|
||||
.
|
||||
Returns 1 if Tcl is not compiled with \fB\-DNDEBUG\fR, 0 otherwise.
|
||||
.\" METHOD: gcc
|
||||
.TP
|
||||
\fB::tcl::build-info gcc\fR
|
||||
.
|
||||
Returns the gcc version number (as 4 digits) if Tcl is compiled with gcc, 0 otherwise.
|
||||
.\" METHOD: icc
|
||||
.TP
|
||||
\fB::tcl::build-info icc\fR
|
||||
.
|
||||
Returns the icc version number (as 4 digits) if Tcl is compiled with icc, 0 otherwise.
|
||||
.\" METHOD: ilp32
|
||||
.TP
|
||||
\fB::tcl::build-info ilp32\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled such that integers, longs and pointers are all 32-bit, 0 otherwise.
|
||||
.\" METHOD: memdebug
|
||||
.TP
|
||||
\fB::tcl::build-info memdebug\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with \fB\-DTCL_MEM_DEBUG\fR, 0 otherwise.
|
||||
.\" METHOD: msvc
|
||||
.TP
|
||||
\fB::tcl::build-info msvc\fR
|
||||
.
|
||||
Returns the msvc version number (as 4 digits) if Tcl is compiled with msvc, 0 otherwise.
|
||||
.\" METHOD: nmake
|
||||
.TP
|
||||
\fB::tcl::build-info nmake\fR
|
||||
.
|
||||
Returns 1 if Tcl is built using nmake, 0 otherwise.
|
||||
.\" METHOD: no-deprecate
|
||||
.TP
|
||||
\fB::tcl::build-info no-deprecate\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with \fB\-DTCL_NO_DEPRECATED\fR, 0 otherwise.
|
||||
.\" METHOD: no-thread
|
||||
.TP
|
||||
\fB::tcl::build-info no-thread\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with \fB\-DTCL_THREADS=0\fR, 0 otherwise.
|
||||
.\" METHOD: no-optimize
|
||||
.TP
|
||||
\fB::tcl::build-info no-optimize\fR
|
||||
.
|
||||
Returns 1 if Tcl is not compiled with \fB\-DTCL_CFG_OPTIMIZED\fR, 0 otherwise.
|
||||
.\" METHOD: objective-c
|
||||
.TP
|
||||
\fB::tcl::build-info objective-c\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with an objective-c compiler, 0 otherwise.
|
||||
.\" METHOD: objective-cplusplus
|
||||
.TP
|
||||
\fB::tcl::build-info objective-cplusplus\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with an objective-c++ compiler, 0 otherwise.
|
||||
.\" METHOD: patchlevel
|
||||
.TP
|
||||
\fB::tcl::build-info patchlevel\fR
|
||||
.
|
||||
Returns the Tcl patchlevel, same as \fBinfo patchlevel\fR.
|
||||
.\" METHOD: profile
|
||||
.TP
|
||||
\fB::tcl::build-info profile\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with \fB\-DTCL_CFG_PROFILED\fR, 0 otherwise.
|
||||
.\" METHOD: purify
|
||||
.TP
|
||||
\fB::tcl::build-info purify\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled with \fB\-DPURIFY\fR, 0 otherwise.
|
||||
.\" METHOD: static
|
||||
.TP
|
||||
\fB::tcl::build-info static\fR
|
||||
.
|
||||
Returns 1 if Tcl is compiled as a static library, 0 otherwise.
|
||||
.\" METHOD: tommath
|
||||
.TP
|
||||
\fB::tcl::build-info tommath\fR
|
||||
.
|
||||
Returns the libtommath version number (as 4 digits) if libtommath is built into Tcl, 0 otherwise.
|
||||
.\" METHOD: version
|
||||
.TP
|
||||
\fB::tcl::build-info version\fR
|
||||
.
|
||||
Returns the Tcl version, same as \fBinfo tclversion\fR.
|
||||
.\" METHOD: zlib
|
||||
.TP
|
||||
\fB::tcl::build-info zlib\fR
|
||||
.
|
||||
Returns the zlib version number (as 4 digits) if zlib is built into Tcl, 0 otherwise.
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
These show the use of \fB::tcl::build-info\fR.
|
||||
.PP
|
||||
.CS
|
||||
\fB::tcl::build-info\fR
|
||||
\fI\(-> 9.0.2+af16c07b81655fabde8028374161ad54b84ef9956843c63f49976b4ef601b611.gcc-1204\fR
|
||||
\fB::tcl::build-info commit\fR
|
||||
\fI\(-> af16c07b81655fabde8028374161ad54b84ef9956843c63f49976b4ef601b611\fR
|
||||
\fB::tcl::build-info compiler\fR
|
||||
\fI\(-> gcc-1204\fR
|
||||
\fB::tcl::build-info gcc\fR
|
||||
\fI\(-> 1204\fR
|
||||
\fB::tcl::build-info version\fR
|
||||
\fI\(-> 9.0\fR
|
||||
\fB::tcl::build-info patchlevel\fR
|
||||
\fI\(-> 9.0.2\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
info(n)
|
||||
.SH "KEYWORDS"
|
||||
build-info
|
||||
'\" Local Variables:
|
||||
'\" mode: nroff
|
||||
'\" End:
|
||||
@@ -104,6 +104,14 @@ Returns a list of the names of encoding profiles. See \fBPROFILES\fR below.
|
||||
Set the system encoding to \fIencoding\fR. If \fIencoding\fR is
|
||||
omitted then the command returns the current system encoding. The
|
||||
system encoding is used whenever Tcl passes strings to system calls.
|
||||
.TP
|
||||
\fBencoding user\fR
|
||||
.VS TIP716
|
||||
Returns the name of encoding as per the user's preferences. On Windows
|
||||
systems, this is based on the user's code page settings in the registry.
|
||||
On other platforms, the returned value is the same as returned by
|
||||
\fBencoding system\fR.
|
||||
.VE TIP716
|
||||
.\" Do not put .VS on whole section as that messes up the bullet list alignment
|
||||
.SH PROFILES
|
||||
.PP
|
||||
|
||||
@@ -31,6 +31,12 @@ If the initial arguments to \fBexec\fR start with \fB\-\fR then
|
||||
they are treated as command-line switches and are not part
|
||||
of the pipeline specification. The following switches are
|
||||
currently supported:
|
||||
.\" OPTION: -encoding
|
||||
.TP 13
|
||||
\fB\-encoding \fIencodingName\fR
|
||||
.
|
||||
Specifies the name of the encoding to use to decode the output of the first
|
||||
subprocess. Defaults to that returned by the \fBencoding system\fR command.
|
||||
.\" OPTION: -ignorestderr
|
||||
.TP 13
|
||||
\fB\-ignorestderr\fR
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ oo::class create Ex {
|
||||
}
|
||||
|
||||
set o [Ex new]
|
||||
$o 3 5 7
|
||||
$o call 3 5 7
|
||||
\fI\(-> This is a\fR
|
||||
\fI\(-> This is b(3)\fR
|
||||
\fI\(-> This is c(5,7)\fR
|
||||
|
||||
+5
-1
@@ -19,7 +19,8 @@ lseq \- Build a numeric sequence returned as a list
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The \fBlseq\fR command creates a sequence of numeric values using the given
|
||||
The \fBlseq\fR command creates a sequence of numeric values, which may
|
||||
be either wide integers or doubles, using the given
|
||||
parameters \fIstart\fR, \fIend\fR, and \fIstep\fR. The \fIoperation\fR
|
||||
argument "\fB..\fR" or "\fBto\fR" defines the range. The "\fBcount\fR" option
|
||||
is used to define a count of the number of elements in the list. A short form
|
||||
@@ -42,6 +43,9 @@ empty list is returned. For example:
|
||||
% \fBlseq\fR 5 to 1 ;# decreasing
|
||||
\fI\(-> 5 4 3 2 1
|
||||
|
||||
% \fBlseq\fR 0 0.5 by 0.1 ;# doubles
|
||||
\fI\(-> 0.0 0.1 0.2 0.3 0.4 0.5\fR
|
||||
|
||||
% \fBlseq\fR 6 to 1 by 2 ;# decreasing, step wrong sign, empty list
|
||||
|
||||
% \fBlseq\fR 1 to 5 by 0 ;# all step sizes of 0 produce an empty list
|
||||
|
||||
+10
-7
@@ -348,8 +348,9 @@ characters in the reverse order.
|
||||
Returns a value equal to \fIstring\fR except that all upper (or title)
|
||||
case letters have been converted to lower case. If \fIfirst\fR is
|
||||
specified, it refers to the first char index in the string to start
|
||||
modifying. If \fIlast\fR is specified, it refers to the char index in
|
||||
the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
|
||||
modifying. If \fIlast\fR is not specified, only the character at position
|
||||
\fIfirst\fR is converted, otherwise \fIlast\fR refers to the char index
|
||||
in the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
|
||||
specified using the forms described in \fBSTRING INDICES\fR.
|
||||
.\" METHOD: totitle
|
||||
.TP
|
||||
@@ -360,9 +361,10 @@ in \fIstring\fR is converted to its Unicode title case variant (or
|
||||
upper case if there is no title case variant) and the rest of the
|
||||
string is converted to lower case. If \fIfirst\fR is specified, it
|
||||
refers to the first char index in the string to start modifying. If
|
||||
\fIlast\fR is specified, it refers to the char index in the string to
|
||||
stop at (inclusive). \fIfirst\fR and \fIlast\fR may be specified
|
||||
using the forms described in \fBSTRING INDICES\fR.
|
||||
\fIlast\fR is not specified, only the character at position \fIfirst\fR
|
||||
is converted, otherwise \fIlast\fR refers to the char index in
|
||||
the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
|
||||
specified using the forms described in \fBSTRING INDICES\fR.
|
||||
.\" METHOD: toupper
|
||||
.TP
|
||||
\fBstring toupper \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR?
|
||||
@@ -370,8 +372,9 @@ using the forms described in \fBSTRING INDICES\fR.
|
||||
Returns a value equal to \fIstring\fR except that all lower (or title)
|
||||
case letters have been converted to upper case. If \fIfirst\fR is
|
||||
specified, it refers to the first char index in the string to start
|
||||
modifying. If \fIlast\fR is specified, it refers to the char index in
|
||||
the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
|
||||
modifying. If \fIlast\fR is not specified, only the character at position
|
||||
\fIfirst\fR is converted, otherwise \fIlast\fR refers to the char index
|
||||
in the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
|
||||
specified using the forms described in \fBSTRING INDICES\fR.
|
||||
.\" METHOD: trim
|
||||
.TP
|
||||
|
||||
+15
@@ -13,7 +13,10 @@
|
||||
.SH NAME
|
||||
subst \- Perform backslash, command, and variable substitutions
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fBsubst \fR?\fB\-nobackslashes\fR? ?\fB\-nocommands\fR? ?\fB\-novariables\fR? \fIstring\fR
|
||||
\fBsubst \fR?\fB\-backslashes\fR? ?\fB\-commands\fR? ?\fB\-variables\fR? \fIstring\fR
|
||||
.fi
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@@ -33,6 +36,18 @@ For example, if \fB\-nocommands\fR is specified, command substitution
|
||||
is not performed: open and close brackets are treated as ordinary characters
|
||||
with no special interpretation.
|
||||
.PP
|
||||
If any of the \fB\-backslashes\fR, \fB\-commands\fR, or
|
||||
\fB\-variables\fR are specified, then only the corresponding
|
||||
substitutions are performed. This means that the following lines are
|
||||
equivalent:
|
||||
.PP
|
||||
.CS
|
||||
\fBsubst\fR -nobackslashes -nocommands $string
|
||||
\fBsubst\fR -variables $string
|
||||
.CE
|
||||
.PP
|
||||
It is not allowed to combine positive and negated options.
|
||||
.PP
|
||||
Note that the substitution of one kind can include substitution of
|
||||
other kinds. For example, even when the \fB\-novariables\fR option
|
||||
is specified, command substitution is performed without restriction.
|
||||
|
||||
@@ -330,9 +330,6 @@ general operating environment of the machine.
|
||||
.IP \fBpointerSize\fR
|
||||
This gives the size of the native-machine pointer in bytes (strictly, it
|
||||
is same as the result of evaluating \fIsizeof(void*)\fR in C.)
|
||||
.IP \fBthreaded\fR
|
||||
If this variable exists, then the interpreter
|
||||
was compiled with threads enabled.
|
||||
.IP \fBuser\fR
|
||||
This identifies the
|
||||
current user based on the login information available on the platform.
|
||||
|
||||
+66
-9
@@ -104,6 +104,9 @@ declare 20 {
|
||||
declare 21 {
|
||||
int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file, int line)
|
||||
}
|
||||
declare 22 {
|
||||
char *Tcl_DbGetStringFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr, const char *file, int line)
|
||||
}
|
||||
declare 23 {
|
||||
Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes,
|
||||
Tcl_Size numBytes, const char *file, int line)
|
||||
@@ -193,6 +196,9 @@ declare 55 {
|
||||
declare 56 {
|
||||
Tcl_Obj *Tcl_NewStringObj(const char *bytes, Tcl_Size length)
|
||||
}
|
||||
declare 57 {
|
||||
Tcl_Obj *Tcl_AttemptNewStringObj(const char *bytes, Tcl_Size length)
|
||||
}
|
||||
declare 58 {
|
||||
unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, Tcl_Size numBytes)
|
||||
}
|
||||
@@ -203,6 +209,9 @@ declare 59 {
|
||||
declare 60 {
|
||||
void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue)
|
||||
}
|
||||
declare 61 {
|
||||
Tcl_Size Tcl_AttemptGetCharLength(Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 62 {
|
||||
void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[])
|
||||
}
|
||||
@@ -1039,7 +1048,13 @@ declare 339 {
|
||||
Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 340 {
|
||||
char *Tcl_GetString(Tcl_Obj *objPtr)
|
||||
char *Tcl_AttemptGetStringFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr)
|
||||
}
|
||||
declare 341 {
|
||||
char *Tcl_AttemptSetStringObj(Tcl_Obj *objPtr, const char *bytes, Tcl_Size length)
|
||||
}
|
||||
declare 342 {
|
||||
Tcl_Obj *Tcl_AttemptDuplicateObj(Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 343 {
|
||||
void Tcl_AlertNotifier(void *clientData)
|
||||
@@ -1118,10 +1133,10 @@ declare 365 {
|
||||
char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
|
||||
}
|
||||
declare 366 {
|
||||
int Tcl_Chdir(const char *dirName)
|
||||
int Tcl_Chdir(const char *dirName)
|
||||
}
|
||||
declare 367 {
|
||||
int Tcl_Access(const char *path, int mode)
|
||||
int Tcl_Access(const char *path, int mode)
|
||||
}
|
||||
declare 368 {
|
||||
int Tcl_Stat(const char *path, struct stat *bufPtr)
|
||||
@@ -1288,6 +1303,14 @@ declare 417 {
|
||||
declare 418 {
|
||||
int Tcl_IsChannelExisting(const char *channelName)
|
||||
}
|
||||
declare 421 {
|
||||
Tcl_HashEntry *Tcl_DbCreateHashEntry(Tcl_HashTable *tablePtr,
|
||||
const void *key, int *newPtr, const char *file, int line)
|
||||
}
|
||||
declare 422 {
|
||||
Tcl_HashEntry *Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
|
||||
const void *key, int *newPtr)
|
||||
}
|
||||
declare 423 {
|
||||
void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr, int keyType,
|
||||
const Tcl_HashKeyType *typePtr)
|
||||
@@ -2081,12 +2104,12 @@ declare 626 {
|
||||
# TIP #357 (Export TclLoadFile and TclpFindSymbol) kbk
|
||||
declare 627 {
|
||||
int Tcl_LoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
|
||||
const char *const symv[], int flags, void *procPtrs,
|
||||
Tcl_LoadHandle *handlePtr)
|
||||
const char *const symv[], int flags, void *procPtrs,
|
||||
Tcl_LoadHandle *handlePtr)
|
||||
}
|
||||
declare 628 {
|
||||
void *Tcl_FindSymbol(Tcl_Interp *interp, Tcl_LoadHandle handle,
|
||||
const char *symbol)
|
||||
const char *symbol)
|
||||
}
|
||||
declare 629 {
|
||||
int Tcl_FSUnloadFile(Tcl_Interp *interp, Tcl_LoadHandle handlePtr)
|
||||
@@ -2331,7 +2354,7 @@ declare 682 {
|
||||
|
||||
# TIP 643
|
||||
declare 683 {
|
||||
Tcl_Size Tcl_GetEncodingNulLength(Tcl_Encoding encoding)
|
||||
Tcl_Size Tcl_GetEncodingNulLength(Tcl_Encoding encoding)
|
||||
}
|
||||
|
||||
# TIP #650
|
||||
@@ -2360,15 +2383,49 @@ declare 689 {
|
||||
void Tcl_SetWideUIntObj(Tcl_Obj *objPtr, Tcl_WideUInt uwideValue)
|
||||
}
|
||||
|
||||
# ----- BASELINE -- FOR -- 8.7.0 / 9.0.0 ----- #
|
||||
# ----- BASELINE -- FOR -- 9.0.0 ----- #
|
||||
|
||||
# TIP 711
|
||||
declare 690 {
|
||||
int Tcl_IsEmpty(Tcl_Obj *obj)
|
||||
}
|
||||
|
||||
# TIP 716
|
||||
declare 691 {
|
||||
const char *Tcl_GetEncodingNameForUser(Tcl_DString *bufPtr)
|
||||
}
|
||||
|
||||
# TIP 649
|
||||
declare 692 {
|
||||
int Tcl_ListObjReverse(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
Tcl_Obj **resultPtrPtr)
|
||||
}
|
||||
declare 693 {
|
||||
int Tcl_ListObjRepeat(Tcl_Interp *interp, Tcl_Size repeatCount,
|
||||
Tcl_Size objc, Tcl_Obj *const objv[], Tcl_Obj **resultPtrPtr)
|
||||
}
|
||||
declare 694 {
|
||||
int Tcl_ListObjRange(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
Tcl_Size start, Tcl_Size end, Tcl_Obj **resultPtrPtr)
|
||||
}
|
||||
|
||||
# TIP 726
|
||||
declare 695 {
|
||||
int Tcl_UtfToNormalizedDString(Tcl_Interp *interp,
|
||||
const char *bytes, Tcl_Size length,
|
||||
Tcl_UnicodeNormalizationForm normForm, int profile,
|
||||
Tcl_DString *dsPtr)
|
||||
}
|
||||
declare 696 {
|
||||
int Tcl_UtfToNormalized(Tcl_Interp *interp,
|
||||
const char *bytes, Tcl_Size length,
|
||||
Tcl_UnicodeNormalizationForm normForm, int profile,
|
||||
char *bufPtr, Tcl_Size bufLen, Tcl_Size *lengthPtr)
|
||||
}
|
||||
|
||||
# ----- BASELINE -- FOR -- 9.1.0 ----- #
|
||||
|
||||
declare 691 {
|
||||
declare 697 {
|
||||
void TclUnusedStubEntry(void)
|
||||
}
|
||||
|
||||
|
||||
+23
-7
@@ -54,10 +54,10 @@ extern "C" {
|
||||
#endif
|
||||
#define TCL_MINOR_VERSION 1
|
||||
#define TCL_RELEASE_LEVEL TCL_ALPHA_RELEASE
|
||||
#define TCL_RELEASE_SERIAL 0
|
||||
#define TCL_RELEASE_SERIAL 1
|
||||
|
||||
#define TCL_VERSION "9.1"
|
||||
#define TCL_PATCH_LEVEL "9.1a0"
|
||||
#define TCL_PATCH_LEVEL "9.1a1"
|
||||
|
||||
#if defined(RC_INVOKED)
|
||||
/*
|
||||
@@ -1020,7 +1020,7 @@ typedef struct Tcl_DString {
|
||||
* Forward declarations of Tcl_HashTable and related types.
|
||||
*/
|
||||
|
||||
#ifndef TCL_HASH_TYPE
|
||||
#if !defined(TCL_HASH_TYPE) && !defined (TCL_NO_DEPRECATED)
|
||||
# define TCL_HASH_TYPE size_t
|
||||
#endif
|
||||
|
||||
@@ -1155,7 +1155,11 @@ struct Tcl_HashTable {
|
||||
* TCL_ONE_WORD_KEYS, or an integer giving the
|
||||
* number of ints that is the size of the
|
||||
* key. */
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
Tcl_HashEntry *(*findProc) (Tcl_HashTable *tablePtr, const char *key);
|
||||
#else
|
||||
void *unUsed;
|
||||
#endif
|
||||
Tcl_HashEntry *(*createProc) (Tcl_HashTable *tablePtr, const char *key,
|
||||
int *newPtr);
|
||||
const Tcl_HashKeyType *typePtr;
|
||||
@@ -2042,6 +2046,13 @@ typedef unsigned short Tcl_UniChar;
|
||||
#else
|
||||
# error "This TCL_UTF_MAX value is not supported"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Specifiers for Unicode normalization forms.
|
||||
*/
|
||||
typedef enum {
|
||||
TCL_NFC, TCL_NFD, TCL_NFKC, TCL_NFKD
|
||||
} Tcl_UnicodeNormalizationForm;
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -2409,12 +2420,12 @@ EXTERN const char *TclZipfs_AppHook(int *argc, char ***argv);
|
||||
static inline void
|
||||
TclBounceRefCount(
|
||||
Tcl_Obj* objPtr,
|
||||
const char* fn,
|
||||
const char* file,
|
||||
int line)
|
||||
{
|
||||
if (objPtr) {
|
||||
if ((objPtr)->refCount == 0) {
|
||||
Tcl_DbDecrRefCount(objPtr, fn, line);
|
||||
Tcl_DbDecrRefCount(objPtr, file, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2510,9 +2521,14 @@ TclBounceRefCount(
|
||||
*/
|
||||
|
||||
#define Tcl_FindHashEntry(tablePtr, key) \
|
||||
(*((tablePtr)->findProc))(tablePtr, (const char *)(key))
|
||||
#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
|
||||
(*((tablePtr)->createProc))(tablePtr, (const char *)(key), (int *)-1)
|
||||
#define Tcl_AttemptCreateHashEntry(tablePtr, key, newPtr) \
|
||||
(*((tablePtr)->createProc))(tablePtr, (const char *)(key), newPtr)
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
#undef Tcl_CreateHashEntry
|
||||
#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
|
||||
Tcl_DbCreateHashEntry(tablePtr, key, newPtr, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
#endif /* RC_INVOKED */
|
||||
|
||||
|
||||
+127
-76
@@ -217,7 +217,7 @@ ArithSeriesGetInternalRep(
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute number of significant fractional digits
|
||||
* Compute number of significant fractional digits.
|
||||
*/
|
||||
static inline unsigned
|
||||
ObjPrecision(
|
||||
@@ -228,8 +228,7 @@ ObjPrecision(
|
||||
|
||||
if (TclHasInternalRep(numObj, &tclDoubleType) || (
|
||||
Tcl_GetNumberFromObj(NULL, numObj, &ptr, &type) == TCL_OK
|
||||
&& type == TCL_NUMBER_DOUBLE)
|
||||
) { /* TCL_NUMBER_DOUBLE */
|
||||
&& type == TCL_NUMBER_DOUBLE)) {
|
||||
const char *str = TclGetString(numObj);
|
||||
|
||||
if (strchr(str, 'e') == NULL && strchr(str, 'E') == NULL) {
|
||||
@@ -275,15 +274,13 @@ maxObjPrecision(
|
||||
*
|
||||
* ArithSeriesLen --
|
||||
*
|
||||
* Compute the length of the equivalent list where
|
||||
* every element is generated starting from *start*,
|
||||
* and adding *step* to generate every successive element
|
||||
* that's < *end* for positive steps, or > *end* for negative
|
||||
* steps.
|
||||
* Compute the length of the equivalent list where every element is
|
||||
* generated starting from *start*, and adding *step* to generate every
|
||||
* successive element that's < *end* for positive steps, or > *end* for
|
||||
* negative steps.
|
||||
*
|
||||
* Results:
|
||||
* The length of the list generated by the given range,
|
||||
* that may be zero.
|
||||
* The length of the list generated by the given range, that may be zero.
|
||||
* The function returns -1 if the list is of length infinite.
|
||||
*
|
||||
* Side effects:
|
||||
@@ -456,21 +453,61 @@ static Tcl_Obj *
|
||||
NewArithSeriesInt(
|
||||
Tcl_WideInt start,
|
||||
Tcl_WideInt step,
|
||||
Tcl_WideInt len)
|
||||
Tcl_WideInt length)
|
||||
{
|
||||
Tcl_WideInt length;
|
||||
Tcl_Obj *arithSeriesObj;
|
||||
Tcl_Obj *arithSeriesObj = NULL;
|
||||
ArithSeriesInt *arithSeriesRepPtr;
|
||||
|
||||
length = len>=0 ? len : -1;
|
||||
if (length < 0) {
|
||||
length = -1;
|
||||
}
|
||||
|
||||
TclNewObj(arithSeriesObj);
|
||||
|
||||
if (length <= 0) {
|
||||
/* TODO - should negative lengths be an error? */
|
||||
return arithSeriesObj;
|
||||
} else if (length > 1) {
|
||||
/* Check for numeric overflow. Not needed for single element lists */
|
||||
Tcl_WideUInt absoluteStep;
|
||||
Tcl_WideInt numIntervals = length - 1;
|
||||
/*
|
||||
* The checks below can probably be condensed but it is very easy to
|
||||
* either inadvertently use undefined C behavior or unintended type
|
||||
* promotion. Separating the cases helps me think more clearly.
|
||||
*/
|
||||
if (step >= 0) {
|
||||
absoluteStep = step;
|
||||
} else if (step == WIDE_MIN) {
|
||||
/* -step and abs(step) are both undefined behavior */
|
||||
absoluteStep = 1 + (Tcl_WideUInt)WIDE_MAX;
|
||||
} else {
|
||||
absoluteStep = -step;
|
||||
}
|
||||
/* First, step*number of intervals should not overflow */
|
||||
if ((UWIDE_MAX / absoluteStep) < (Tcl_WideUInt) numIntervals) {
|
||||
goto invalidRange;
|
||||
}
|
||||
if (step > 0) {
|
||||
/*
|
||||
* Because of check above and UWIDE_MAX=2*WIDE_MAX+1,
|
||||
* second term will not underflow a Tcl_WideInt
|
||||
*/
|
||||
if (start > (WIDE_MAX - (step * numIntervals))) {
|
||||
goto invalidRange;
|
||||
}
|
||||
} else if (step == WIDE_MIN) {
|
||||
if (numIntervals > 0 || start < 0) {
|
||||
goto invalidRange;
|
||||
}
|
||||
} else if (step < 0) {
|
||||
/*
|
||||
* Because of check above and UWIDE_MAX=2*WIDE_MAX+1 and
|
||||
* step != WIDE_MIN second term will not underflow a Tcl_WideInt.
|
||||
* DON'T use absoluteStep here because of unsigned type promotion
|
||||
*/
|
||||
if (start < (WIDE_MIN + ((-step) * numIntervals))) {
|
||||
goto invalidRange;
|
||||
}
|
||||
} else /* step == 0 */ {
|
||||
/* TODO - step == 0 && length > 1 should be error? */
|
||||
}
|
||||
}
|
||||
|
||||
arithSeriesRepPtr = (ArithSeriesInt *) Tcl_Alloc(sizeof(ArithSeriesInt));
|
||||
@@ -483,11 +520,13 @@ NewArithSeriesInt(
|
||||
arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
|
||||
arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
arithSeriesObj->typePtr = &arithSeriesType;
|
||||
if (length > 0) {
|
||||
Tcl_InvalidateStringRep(arithSeriesObj);
|
||||
}
|
||||
Tcl_InvalidateStringRep(arithSeriesObj);
|
||||
|
||||
return arithSeriesObj;
|
||||
|
||||
invalidRange:
|
||||
Tcl_BounceRefCount(arithSeriesObj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -504,6 +543,7 @@ NewArithSeriesInt(
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static Tcl_Obj *
|
||||
@@ -561,6 +601,7 @@ NewArithSeriesDbl(
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
@@ -622,6 +663,7 @@ assignNumber(
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
Tcl_Obj *
|
||||
@@ -639,6 +681,8 @@ TclNewArithSeriesObj(
|
||||
Tcl_WideInt len = -1;
|
||||
Tcl_Obj *objPtr;
|
||||
unsigned precision = (unsigned)-1; /* unknown precision */
|
||||
const char *description;
|
||||
char tmp[TCL_DOUBLE_SPACE + 2] = {0};
|
||||
|
||||
if (startObj) {
|
||||
if (assignNumber(interp, useDoubles, &start, &dstart, startObj) != TCL_OK) {
|
||||
@@ -657,15 +701,11 @@ TclNewArithSeriesObj(
|
||||
return objPtr;
|
||||
}
|
||||
}
|
||||
if (endObj) {
|
||||
if (assignNumber(interp, useDoubles, &end, &dend, endObj) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
if (endObj && assignNumber(interp, useDoubles, &end, &dend, endObj) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
if (lenObj) {
|
||||
if (Tcl_GetWideIntFromObj(interp, lenObj, &len) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
if (lenObj && Tcl_GetWideIntFromObj(interp, lenObj, &len) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (endObj) {
|
||||
@@ -682,24 +722,13 @@ TclNewArithSeriesObj(
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(dstep!=0);
|
||||
assert(dstep != 0);
|
||||
if (!lenObj) {
|
||||
if (useDoubles) {
|
||||
if (isinf(dstart) || isinf(dend)) {
|
||||
goto exceeded;
|
||||
}
|
||||
if (isnan(dstart) || isnan(dend)) {
|
||||
const char *description = "non-numeric floating-point value";
|
||||
char tmp[TCL_DOUBLE_SPACE + 2];
|
||||
|
||||
tmp[0] = '\0';
|
||||
Tcl_PrintDouble(NULL, isnan(dstart)?dstart:dend, tmp);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"cannot use %s \"%s\" to estimate length of arith-series",
|
||||
description, tmp));
|
||||
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description,
|
||||
(char *)NULL);
|
||||
return NULL;
|
||||
} else if (isnan(dstart) || isnan(dend)) {
|
||||
goto notANumber;
|
||||
}
|
||||
precision = maxObjPrecision(startObj, endObj, stepObj);
|
||||
len = ArithSeriesLenDbl(dstart, dend, dstep, precision);
|
||||
@@ -707,32 +736,23 @@ TclNewArithSeriesObj(
|
||||
len = ArithSeriesLenInt(start, end, step);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (useDoubles) {
|
||||
// Compute precision based on given command argument values
|
||||
precision = maxObjPrecision(startObj, NULL, stepObj);
|
||||
} else if (useDoubles) {
|
||||
// Compute precision based on given command argument values
|
||||
precision = maxObjPrecision(startObj, NULL, stepObj);
|
||||
|
||||
dend = dstart + (dstep * (double)(len-1));
|
||||
// Make computed end value match argument(s) precision
|
||||
dend = ArithRound(dend, precision);
|
||||
end = dend;
|
||||
} else {
|
||||
end = start + (step * (len - 1));
|
||||
dend = (double)end;
|
||||
}
|
||||
dend = dstart + (dstep * (double)(len-1));
|
||||
// Make computed end value match argument(s) precision
|
||||
dend = ArithRound(dend, precision);
|
||||
end = dend;
|
||||
}
|
||||
|
||||
/*
|
||||
* todo: check whether the boundary must be rather LIST_MAX, to be more
|
||||
* similar to plain lists, otherwise it'd generare an error or panic later
|
||||
* similar to plain lists, otherwise it'd generate an error or panic later
|
||||
* (0x0ffffffffffffffa instead of 0x7fffffffffffffff by 64bit)
|
||||
*/
|
||||
if (len > TCL_SIZE_MAX) {
|
||||
exceeded:
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"max length of a Tcl list exceeded", TCL_AUTO_LENGTH));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
|
||||
return NULL;
|
||||
goto exceeded;
|
||||
}
|
||||
|
||||
if (useDoubles) {
|
||||
@@ -740,10 +760,8 @@ TclNewArithSeriesObj(
|
||||
* so simply check the end of it and behave like [expr {Inf - Inf}] */
|
||||
double d = dstart + (double)(len - 1) * dstep;
|
||||
if (isnan(d)) {
|
||||
const char *s = "domain error: argument not in valid range";
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
|
||||
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (char *)NULL);
|
||||
return NULL;
|
||||
description = "domain error: argument not in valid range";
|
||||
goto domain;
|
||||
}
|
||||
|
||||
if (precision == (unsigned)-1) {
|
||||
@@ -755,7 +773,31 @@ TclNewArithSeriesObj(
|
||||
objPtr = NewArithSeriesInt(start, step, len);
|
||||
}
|
||||
|
||||
if (objPtr == NULL && interp) {
|
||||
description = "invalid arithmetic series parameter values";
|
||||
goto domain;
|
||||
}
|
||||
return objPtr;
|
||||
|
||||
exceeded:
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"max length of a Tcl list exceeded", TCL_AUTO_LENGTH));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
|
||||
return NULL;
|
||||
|
||||
domain:
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(description, TCL_AUTO_LENGTH));
|
||||
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, (char *)NULL);
|
||||
return NULL;
|
||||
|
||||
notANumber:
|
||||
description = "non-numeric floating-point value";
|
||||
Tcl_PrintDouble(NULL, isnan(dstart) ? dstart : dend, tmp);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"cannot use %s \"%s\" to estimate length of arith-series",
|
||||
description, tmp));
|
||||
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, (char *)NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1147,11 +1189,11 @@ UpdateStringOfArithSeries(
|
||||
{
|
||||
ArithSeries *arithSeriesRepPtr = (ArithSeries *)
|
||||
arithSeriesObjPtr->internalRep.twoPtrValue.ptr1;
|
||||
char *p;
|
||||
char *p, *srep;
|
||||
Tcl_Size i, bytlen = 0;
|
||||
|
||||
if (!arithSeriesRepPtr->len) {
|
||||
TclInitEmptyStringRep(arithSeriesObjPtr);
|
||||
if (arithSeriesRepPtr->len == 0) {
|
||||
(void)Tcl_InitStringRep(arithSeriesObjPtr, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1169,15 +1211,15 @@ UpdateStringOfArithSeries(
|
||||
char tmp[TCL_DOUBLE_SPACE + 2];
|
||||
for (i = 0; i < arithSeriesRepPtr->len; i++) {
|
||||
double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
|
||||
Tcl_Size elen;
|
||||
|
||||
tmp[0] = '\0';
|
||||
Tcl_PrintDouble(NULL,d,tmp);
|
||||
bytlen += strlen(tmp);
|
||||
if (bytlen > TCL_SIZE_MAX) {
|
||||
/* overflow, todo: check we could use some representation instead of the panic
|
||||
* to signal it is too large for string representation, because too heavy */
|
||||
Tcl_Panic("UpdateStringOfArithSeries: too large to represent");
|
||||
elen = strlen(tmp);
|
||||
if (bytlen > TCL_SIZE_MAX - elen) {
|
||||
goto repTooLarge;
|
||||
}
|
||||
bytlen += elen;
|
||||
}
|
||||
}
|
||||
bytlen += arithSeriesRepPtr->len; // Space for each separator
|
||||
@@ -1186,7 +1228,17 @@ UpdateStringOfArithSeries(
|
||||
* Pass 2: generate the string repr.
|
||||
*/
|
||||
|
||||
p = Tcl_InitStringRep(arithSeriesObjPtr, NULL, bytlen);
|
||||
p = srep = TclAttemptInitStringRep(arithSeriesObjPtr, NULL, bytlen);
|
||||
if (!p) {
|
||||
repTooLarge:
|
||||
if (arithSeriesObjPtr->bytes) {
|
||||
Tcl_Free(arithSeriesObjPtr->bytes);
|
||||
arithSeriesObjPtr->bytes = 0;
|
||||
}
|
||||
arithSeriesObjPtr->length = bytlen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!arithSeriesRepPtr->isDouble) {
|
||||
for (i = 0; i < arithSeriesRepPtr->len; i++) {
|
||||
Tcl_WideInt d = ArithSeriesIndexInt(arithSeriesRepPtr, i);
|
||||
@@ -1205,8 +1257,7 @@ UpdateStringOfArithSeries(
|
||||
*p++ = ' ';
|
||||
}
|
||||
}
|
||||
*(--p) = '\0';
|
||||
arithSeriesObjPtr->length = p - arithSeriesObjPtr->bytes;
|
||||
(void) Tcl_InitStringRep(arithSeriesObjPtr, NULL, (--p - srep));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+525
-524
File diff suppressed because it is too large
Load Diff
+63
-62
@@ -237,7 +237,6 @@ static Tcl_NRPostProc TEOV_RunLeaveTraces;
|
||||
static Tcl_NRPostProc EvalObjvCore;
|
||||
static Tcl_NRPostProc Dispatch;
|
||||
|
||||
static Tcl_NRPostProc NRPostInvoke;
|
||||
static Tcl_ObjCmdProc CoroTypeObjCmd;
|
||||
static Tcl_ObjCmdProc TclNRCoroInjectObjCmd;
|
||||
static Tcl_ObjCmdProc TclNRCoroProbeObjCmd;
|
||||
@@ -250,12 +249,10 @@ MODULE_SCOPE const TclStubs tclStubs;
|
||||
* Magical counts for the number of arguments accepted by a coroutine command
|
||||
* after particular kinds of [yield].
|
||||
*/
|
||||
|
||||
#define CORO_ACTIVATE_YIELD NULL
|
||||
#define CORO_ACTIVATE_YIELDM INT2PTR(1)
|
||||
|
||||
#define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL (-1)
|
||||
#define COROUTINE_ARGUMENTS_ARBITRARY (-2)
|
||||
enum CoroutineArgumentTypes {
|
||||
COROUTINE_ARGUMENTS_SINGLE_OPTIONAL = -1,
|
||||
COROUTINE_ARGUMENTS_ARBITRARY = -2
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure define the commands in the Tcl core.
|
||||
@@ -299,7 +296,7 @@ typedef struct {
|
||||
*/
|
||||
|
||||
static int
|
||||
procObjCmd(
|
||||
ProcObjCmd(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -310,7 +307,7 @@ procObjCmd(
|
||||
|
||||
static const CmdInfo builtInCmds[] = {
|
||||
/*
|
||||
* Commands in the generic core.
|
||||
* Commands in the generic core. All are safe.
|
||||
*/
|
||||
|
||||
{"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE},
|
||||
@@ -334,26 +331,26 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE},
|
||||
{"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE},
|
||||
{"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE},
|
||||
{"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
|
||||
{"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE},
|
||||
{"ledit", Tcl_LeditObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"ledit", Tcl_LeditObjCmd, TclCompileLeditCmd, NULL, CMD_IS_SAFE},
|
||||
{"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE},
|
||||
{"linsert", Tcl_LinsertObjCmd, TclCompileLinsertCmd, NULL, CMD_IS_SAFE},
|
||||
{"list", Tcl_ListObjCmd, TclCompileListCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
|
||||
{"llength", Tcl_LlengthObjCmd, TclCompileLlengthCmd, NULL, CMD_IS_SAFE},
|
||||
{"lmap", Tcl_LmapObjCmd, TclCompileLmapCmd, TclNRLmapCmd, CMD_IS_SAFE},
|
||||
{"lpop", Tcl_LpopObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lpop", Tcl_LpopObjCmd, TclCompileLpopCmd, NULL, CMD_IS_SAFE},
|
||||
{"lrange", Tcl_LrangeObjCmd, TclCompileLrangeCmd, NULL, CMD_IS_SAFE},
|
||||
{"lremove", Tcl_LremoveObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lrepeat", Tcl_LrepeatObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lreplace", Tcl_LreplaceObjCmd, TclCompileLreplaceCmd, NULL, CMD_IS_SAFE},
|
||||
{"lreverse", Tcl_LreverseObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lseq", Tcl_LseqObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lseq", Tcl_LseqObjCmd, TclCompileLseqCmd, NULL, CMD_IS_SAFE},
|
||||
{"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE},
|
||||
{"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE},
|
||||
{"proc", procObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"proc", ProcObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE},
|
||||
{"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE},
|
||||
{"rename", Tcl_RenameObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
@@ -363,17 +360,17 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"split", Tcl_SplitObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"subst", Tcl_SubstObjCmd, TclCompileSubstCmd, TclNRSubstObjCmd, CMD_IS_SAFE},
|
||||
{"switch", Tcl_SwitchObjCmd, TclCompileSwitchCmd, TclNRSwitchObjCmd, CMD_IS_SAFE},
|
||||
{"tailcall", NULL, TclCompileTailcallCmd, TclNRTailcallObjCmd, CMD_IS_SAFE},
|
||||
{"tailcall", NULL, TclCompileTailcallCmd, TclNRTailcallObjCmd, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
|
||||
{"throw", Tcl_ThrowObjCmd, TclCompileThrowCmd, NULL, CMD_IS_SAFE},
|
||||
{"trace", Tcl_TraceObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"try", Tcl_TryObjCmd, TclCompileTryCmd, TclNRTryObjCmd, CMD_IS_SAFE},
|
||||
{"unset", Tcl_UnsetObjCmd, TclCompileUnsetCmd, NULL, CMD_IS_SAFE},
|
||||
{"uplevel", Tcl_UplevelObjCmd, NULL, TclNRUplevelObjCmd, CMD_IS_SAFE},
|
||||
{"uplevel", Tcl_UplevelObjCmd, TclCompileUplevelCmd, TclNRUplevelObjCmd, CMD_IS_SAFE},
|
||||
{"upvar", Tcl_UpvarObjCmd, TclCompileUpvarCmd, NULL, CMD_IS_SAFE},
|
||||
{"variable", Tcl_VariableObjCmd, TclCompileVariableCmd, NULL, CMD_IS_SAFE},
|
||||
{"while", Tcl_WhileObjCmd, TclCompileWhileCmd, TclNRWhileObjCmd, CMD_IS_SAFE},
|
||||
{"yield", NULL, TclCompileYieldCmd, TclNRYieldObjCmd, CMD_IS_SAFE},
|
||||
{"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE},
|
||||
{"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
|
||||
|
||||
/*
|
||||
* Commands in the OS-interface. Note that many of these are unsafe.
|
||||
@@ -650,7 +647,7 @@ TclFinalizeEvaluation(void)
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* buildInfoObjCmd --
|
||||
* BuildInfoObjCmd --
|
||||
*
|
||||
* Implements tcl::build-info command.
|
||||
*
|
||||
@@ -664,7 +661,7 @@ TclFinalizeEvaluation(void)
|
||||
*/
|
||||
|
||||
static int
|
||||
buildInfoObjCmd2(
|
||||
BuildInfoObjCmd2(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
Tcl_Size objc, /* Number of arguments. */
|
||||
@@ -731,7 +728,8 @@ buildInfoObjCmd2(
|
||||
}
|
||||
return TCL_OK;
|
||||
case ID_COMPILER:
|
||||
for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) {
|
||||
for (p = strchr(buildData, '.'); p != NULL; p = strchr(p, '.')) {
|
||||
p++;
|
||||
/*
|
||||
* Does the word begin with one of the standard prefixes?
|
||||
*/
|
||||
@@ -752,7 +750,8 @@ buildInfoObjCmd2(
|
||||
break;
|
||||
default: /* Boolean test for other identifiers' presence */
|
||||
arg = TclGetStringFromObj(objv[1], &len);
|
||||
for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) {
|
||||
for (p = strchr(buildData, '.'); p != NULL; p = strchr(p, '.')) {
|
||||
p++;
|
||||
if (!strncmp(p, arg, len)
|
||||
&& ((p[len] == '.') || (p[len] == '-') || (p[len] == '\0'))) {
|
||||
if (p[len] == '-') {
|
||||
@@ -776,13 +775,13 @@ buildInfoObjCmd2(
|
||||
}
|
||||
|
||||
static int
|
||||
buildInfoObjCmd(
|
||||
BuildInfoObjCmd(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
return buildInfoObjCmd2(clientData, interp, objc, objv);
|
||||
return BuildInfoObjCmd2(clientData, interp, objc, objv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1163,6 +1162,7 @@ Tcl_CreateInterp(void)
|
||||
TclInitInfoCmd(interp);
|
||||
TclInitNamespaceCmd(interp);
|
||||
TclInitStringCmd(interp);
|
||||
TclInitUnicodeCmd(interp);
|
||||
TclInitPrefixCmd(interp);
|
||||
TclInitProcessCmd(interp);
|
||||
|
||||
@@ -1325,9 +1325,9 @@ Tcl_CreateInterp(void)
|
||||
Tcl_PkgProvideEx(interp, "tcl", TCL_PATCH_LEVEL, &tclStubs);
|
||||
Tcl_CmdInfo info2;
|
||||
Tcl_Command buildInfoCmd = Tcl_CreateObjCommand(interp, "::tcl::build-info",
|
||||
buildInfoObjCmd, (void *)version, NULL);
|
||||
BuildInfoObjCmd, (void *)version, NULL);
|
||||
Tcl_GetCommandInfoFromToken(buildInfoCmd, &info2);
|
||||
info2.objProc2 = buildInfoObjCmd2;
|
||||
info2.objProc2 = BuildInfoObjCmd2;
|
||||
info2.objClientData2 = (void *)version;
|
||||
Tcl_SetCommandInfoFromToken(buildInfoCmd, &info2);
|
||||
|
||||
@@ -1385,8 +1385,8 @@ TclRegisterCommandTypeName(
|
||||
int isNew;
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&commandTypeTable,
|
||||
implementationProc, &isNew);
|
||||
Tcl_SetHashValue(hPtr, (void *) nameStr);
|
||||
(void *)implementationProc, &isNew);
|
||||
Tcl_SetHashValue(hPtr, nameStr);
|
||||
} else {
|
||||
hPtr = Tcl_FindHashEntry(&commandTypeTable,
|
||||
implementationProc);
|
||||
@@ -2724,7 +2724,7 @@ typedef struct {
|
||||
} CmdWrapperInfo;
|
||||
|
||||
static int
|
||||
cmdWrapperProc(
|
||||
CmdWrapperProc(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -2738,7 +2738,7 @@ cmdWrapperProc(
|
||||
}
|
||||
|
||||
static void
|
||||
cmdWrapperDeleteProc(
|
||||
CmdWrapperDeleteProc(
|
||||
void *clientData)
|
||||
{
|
||||
CmdWrapperInfo *info = (CmdWrapperInfo *) clientData;
|
||||
@@ -2774,8 +2774,8 @@ Tcl_CreateObjCommand2(
|
||||
info->deleteData = clientData;
|
||||
|
||||
return Tcl_CreateObjCommand(interp, cmdName,
|
||||
(proc ? cmdWrapperProc : NULL),
|
||||
info, cmdWrapperDeleteProc);
|
||||
(proc ? CmdWrapperProc : NULL),
|
||||
info, CmdWrapperDeleteProc);
|
||||
}
|
||||
|
||||
Tcl_Command
|
||||
@@ -3293,7 +3293,7 @@ Tcl_SetCommandInfo(
|
||||
*/
|
||||
|
||||
static int
|
||||
invokeObj2Command(
|
||||
InvokeObj2Command(
|
||||
void *clientData, /* Points to command's Command structure. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
Tcl_Size objc, /* Number of arguments. */
|
||||
@@ -3315,7 +3315,7 @@ invokeObj2Command(
|
||||
}
|
||||
|
||||
static int
|
||||
cmdWrapper2Proc(
|
||||
CmdWrapper2Proc(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Size objc,
|
||||
@@ -3357,10 +3357,10 @@ Tcl_SetCommandInfoFromToken(
|
||||
}
|
||||
cmdPtr->objClientData = infoPtr->objClientData;
|
||||
}
|
||||
if (cmdPtr->deleteProc == cmdWrapperDeleteProc) {
|
||||
if (cmdPtr->deleteProc == CmdWrapperDeleteProc) {
|
||||
CmdWrapperInfo *info = (CmdWrapperInfo *) cmdPtr->deleteData;
|
||||
if (infoPtr->objProc2 == NULL) {
|
||||
info->proc = invokeObj2Command;
|
||||
info->proc = InvokeObj2Command;
|
||||
info->clientData = cmdPtr;
|
||||
info->nreProc = NULL;
|
||||
} else {
|
||||
@@ -3373,14 +3373,14 @@ Tcl_SetCommandInfoFromToken(
|
||||
info->deleteProc = infoPtr->deleteProc;
|
||||
info->deleteData = infoPtr->deleteData;
|
||||
} else {
|
||||
if ((infoPtr->objProc2 != NULL) && (infoPtr->objProc2 != cmdWrapper2Proc)) {
|
||||
if ((infoPtr->objProc2 != NULL) && (infoPtr->objProc2 != CmdWrapper2Proc)) {
|
||||
CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo));
|
||||
info->proc = infoPtr->objProc2;
|
||||
info->clientData = infoPtr->objClientData2;
|
||||
info->nreProc = NULL;
|
||||
info->deleteProc = infoPtr->deleteProc;
|
||||
info->deleteData = infoPtr->deleteData;
|
||||
cmdPtr->deleteProc = cmdWrapperDeleteProc;
|
||||
cmdPtr->deleteProc = CmdWrapperDeleteProc;
|
||||
cmdPtr->deleteData = info;
|
||||
} else {
|
||||
cmdPtr->deleteProc = infoPtr->deleteProc;
|
||||
@@ -3464,19 +3464,19 @@ Tcl_GetCommandInfoFromToken(
|
||||
infoPtr->objClientData = cmdPtr->objClientData;
|
||||
infoPtr->proc = cmdPtr->proc;
|
||||
infoPtr->clientData = cmdPtr->clientData;
|
||||
if (cmdPtr->deleteProc == cmdWrapperDeleteProc) {
|
||||
if (cmdPtr->deleteProc == CmdWrapperDeleteProc) {
|
||||
CmdWrapperInfo *info = (CmdWrapperInfo *)cmdPtr->deleteData;
|
||||
infoPtr->deleteProc = info->deleteProc;
|
||||
infoPtr->deleteData = info->deleteData;
|
||||
infoPtr->objProc2 = info->proc;
|
||||
infoPtr->objClientData2 = info->clientData;
|
||||
if (cmdPtr->objProc == cmdWrapperProc) {
|
||||
if (cmdPtr->objProc == CmdWrapperProc) {
|
||||
infoPtr->isNativeObjectProc = 2;
|
||||
}
|
||||
} else {
|
||||
infoPtr->deleteProc = cmdPtr->deleteProc;
|
||||
infoPtr->deleteData = cmdPtr->deleteData;
|
||||
infoPtr->objProc2 = cmdWrapper2Proc;
|
||||
infoPtr->objProc2 = CmdWrapper2Proc;
|
||||
infoPtr->objClientData2 = cmdPtr;
|
||||
}
|
||||
infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
|
||||
@@ -4619,7 +4619,8 @@ Dispatch(
|
||||
}
|
||||
if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) {
|
||||
Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
|
||||
const char *a[6]; Tcl_Size i[2];
|
||||
const char *a[6];
|
||||
Tcl_Size i[2];
|
||||
|
||||
TclDTraceInfo(info, a, i);
|
||||
TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]);
|
||||
@@ -5574,7 +5575,7 @@ TclEvalEx(
|
||||
Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
|
||||
commandLength);
|
||||
}
|
||||
posterror:
|
||||
posterror:
|
||||
iPtr->flags &= ~ERR_ALREADY_LOGGED;
|
||||
|
||||
/*
|
||||
@@ -5596,7 +5597,7 @@ TclEvalEx(
|
||||
}
|
||||
iPtr->varFramePtr = savedVarFramePtr;
|
||||
|
||||
cleanup_return:
|
||||
cleanup_return:
|
||||
/*
|
||||
* TIP #280. Release the local CmdFrame, and its contents.
|
||||
*/
|
||||
@@ -6547,7 +6548,7 @@ Tcl_ExprLongObj(
|
||||
}
|
||||
resultPtr = Tcl_NewBignumObj(&big);
|
||||
}
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
case TCL_NUMBER_INT:
|
||||
case TCL_NUMBER_BIG:
|
||||
result = TclGetLongFromObj(interp, resultPtr, ptr);
|
||||
@@ -6739,7 +6740,7 @@ TclNRInvoke(
|
||||
*/
|
||||
|
||||
iPtr->numLevels++;
|
||||
Tcl_NRAddCallback(interp, NRPostInvoke, NULL, NULL, NULL, NULL);
|
||||
Tcl_NRAddCallback(interp, TclNRPostInvoke, NULL, NULL, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Normal command resolution of objv[0] isn't going to find cmdPtr.
|
||||
@@ -6750,8 +6751,8 @@ TclNRInvoke(
|
||||
return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NORESOLVE, cmdPtr);
|
||||
}
|
||||
|
||||
static int
|
||||
NRPostInvoke(
|
||||
int
|
||||
TclNRPostInvoke(
|
||||
TCL_UNUSED(void **),
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
@@ -8063,16 +8064,16 @@ DoubleObjClass(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (type) {
|
||||
case TCL_NUMBER_NAN:
|
||||
case TCL_NUMBER_NAN:
|
||||
*fpClsPtr = FP_NAN;
|
||||
return TCL_OK;
|
||||
case TCL_NUMBER_DOUBLE:
|
||||
case TCL_NUMBER_DOUBLE:
|
||||
d = *((const double *) ptr);
|
||||
break;
|
||||
case TCL_NUMBER_INT:
|
||||
case TCL_NUMBER_INT:
|
||||
d = (double)*((const Tcl_WideInt *) ptr);
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -8459,7 +8460,7 @@ Tcl_NRCallObjProc(
|
||||
}
|
||||
|
||||
static int
|
||||
wrapperNRObjProc(
|
||||
WrapperNRObjProc(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -8493,7 +8494,7 @@ Tcl_NRCallObjProc2(
|
||||
info->clientData = clientData;
|
||||
info->proc = objProc;
|
||||
|
||||
TclNRAddCallback(interp, Dispatch, wrapperNRObjProc, info,
|
||||
TclNRAddCallback(interp, Dispatch, WrapperNRObjProc, info,
|
||||
INT2PTR(objc), objv);
|
||||
return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
|
||||
}
|
||||
@@ -8527,7 +8528,7 @@ Tcl_NRCallObjProc2(
|
||||
*/
|
||||
|
||||
static int
|
||||
cmdWrapperNreProc(
|
||||
CmdWrapperNreProc(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -8568,9 +8569,9 @@ Tcl_NRCreateCommand2(
|
||||
info->deleteProc = deleteProc;
|
||||
info->deleteData = clientData;
|
||||
return Tcl_NRCreateCommand(interp, cmdName,
|
||||
(proc ? cmdWrapperProc : NULL),
|
||||
(nreProc ? cmdWrapperNreProc : NULL),
|
||||
info, cmdWrapperDeleteProc);
|
||||
(proc ? CmdWrapperProc : NULL),
|
||||
(nreProc ? CmdWrapperNreProc : NULL),
|
||||
info, CmdWrapperDeleteProc);
|
||||
}
|
||||
|
||||
Tcl_Command
|
||||
@@ -8816,6 +8817,7 @@ TclNRTailcallObjCmd(
|
||||
|
||||
listPtr = Tcl_NewListObj(objc, objv);
|
||||
TclListObjSetElement(NULL, listPtr, 0, TclNewNamespaceObj(nsPtr));
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
|
||||
iPtr->varFramePtr->tailcallPtr = listPtr;
|
||||
}
|
||||
@@ -9607,13 +9609,13 @@ TclNRInterpCoroutine(
|
||||
break;
|
||||
default:
|
||||
if (corPtr->nargs + 1 != objc) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("wrong coro nargs; how did we get here? "
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"wrong coro nargs; how did we get here? "
|
||||
"not implemented!", TCL_INDEX_NONE));
|
||||
Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/* fallthrough */
|
||||
TCL_FALLTHROUGH();
|
||||
case COROUTINE_ARGUMENTS_ARBITRARY:
|
||||
if (objc > 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(objc - 1, objv + 1));
|
||||
@@ -9707,11 +9709,10 @@ TclNRCoroutineObjCmd(
|
||||
|
||||
for (hePtr = Tcl_FirstHashEntry(iPtr->lineLABCPtr,&hSearch);
|
||||
hePtr; hePtr = Tcl_NextHashEntry(&hSearch)) {
|
||||
int isNew;
|
||||
Tcl_HashEntry *newPtr =
|
||||
Tcl_CreateHashEntry(corPtr->lineLABCPtr,
|
||||
Tcl_GetHashKey(iPtr->lineLABCPtr, hePtr),
|
||||
&isNew);
|
||||
NULL);
|
||||
|
||||
Tcl_SetHashValue(newPtr, Tcl_GetHashValue(hePtr));
|
||||
}
|
||||
|
||||
+47
-44
@@ -384,7 +384,7 @@ Tcl_GetBytesFromObj(
|
||||
return baPtr->bytes;
|
||||
}
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED)
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
unsigned char *
|
||||
TclGetBytesFromObj(
|
||||
Tcl_Interp *interp, /* For error reporting */
|
||||
@@ -770,12 +770,9 @@ TclAppendBytesToByteArray(
|
||||
needed = byteArrayPtr->used + len;
|
||||
if (needed > byteArrayPtr->allocated) {
|
||||
Tcl_Size newCapacity;
|
||||
byteArrayPtr =
|
||||
(ByteArray *)TclReallocElemsEx(byteArrayPtr,
|
||||
needed,
|
||||
1,
|
||||
offsetof(ByteArray, bytes),
|
||||
&newCapacity);
|
||||
byteArrayPtr = (ByteArray *)
|
||||
TclReallocElemsEx(byteArrayPtr, needed, 1,
|
||||
offsetof(ByteArray, bytes), &newCapacity);
|
||||
byteArrayPtr->allocated = newCapacity;
|
||||
SET_BYTEARRAY(irPtr, byteArrayPtr);
|
||||
}
|
||||
@@ -1296,22 +1293,22 @@ BinaryFormatCmd(
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
return TCL_OK;
|
||||
|
||||
badValue:
|
||||
badValue:
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected %s string but got \"%s\" instead",
|
||||
errorString, errorValue));
|
||||
return TCL_ERROR;
|
||||
|
||||
badCount:
|
||||
badCount:
|
||||
errorString = "missing count for \"@\" field specifier";
|
||||
goto error;
|
||||
|
||||
badIndex:
|
||||
badIndex:
|
||||
errorString = "not enough arguments for all format specifiers";
|
||||
goto error;
|
||||
|
||||
badField:
|
||||
badField:
|
||||
{
|
||||
Tcl_UniChar ch = 0;
|
||||
char buf[5] = "";
|
||||
@@ -1323,7 +1320,7 @@ BinaryFormatCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
error:
|
||||
error:
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1678,21 +1675,21 @@ BinaryScanCmd(
|
||||
* Set the result to the last position of the cursor.
|
||||
*/
|
||||
|
||||
done:
|
||||
done:
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(arg - 3));
|
||||
DeleteScanNumberCache(numberCachePtr);
|
||||
|
||||
return TCL_OK;
|
||||
|
||||
badCount:
|
||||
badCount:
|
||||
errorString = "missing count for \"@\" field specifier";
|
||||
goto error;
|
||||
|
||||
badIndex:
|
||||
badIndex:
|
||||
errorString = "not enough arguments for all format specifiers";
|
||||
goto error;
|
||||
|
||||
badField:
|
||||
badField:
|
||||
{
|
||||
Tcl_UniChar ch = 0;
|
||||
char buf[5] = "";
|
||||
@@ -1704,7 +1701,7 @@ BinaryScanCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
error:
|
||||
error:
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2505,6 +2502,8 @@ BinaryDecodeHex(
|
||||
case OPT_STRICT:
|
||||
strict = 1;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2649,6 +2648,8 @@ BinaryEncode64(
|
||||
wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (wrapcharlen == 0) {
|
||||
@@ -2736,13 +2737,13 @@ BinaryEncodeUu(
|
||||
{
|
||||
Tcl_Obj *resultObj;
|
||||
unsigned char *data, *start, *cursor;
|
||||
int i, bits, index;
|
||||
int i, bits;
|
||||
unsigned int n;
|
||||
int lineLength = 61;
|
||||
const unsigned char SingleNewline[] = { UCHAR('\n') };
|
||||
const unsigned char *wrapchar = SingleNewline;
|
||||
Tcl_Size j, rawLength, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
|
||||
enum { OPT_MAXLEN, OPT_WRAPCHAR };
|
||||
enum { OPT_MAXLEN, OPT_WRAPCHAR } index;
|
||||
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
|
||||
|
||||
if (objc < 2 || objc % 2 != 0) {
|
||||
@@ -2773,35 +2774,33 @@ BinaryEncodeUu(
|
||||
case OPT_WRAPCHAR:
|
||||
wrapchar = (const unsigned char *)TclGetStringFromObj(
|
||||
objv[i + 1], &wrapcharlen);
|
||||
{
|
||||
const unsigned char *p = wrapchar;
|
||||
Tcl_Size numBytes = wrapcharlen;
|
||||
const unsigned char *p = wrapchar;
|
||||
Tcl_Size numBytes = wrapcharlen;
|
||||
|
||||
while (numBytes) {
|
||||
switch (*p) {
|
||||
case '\t':
|
||||
case '\v':
|
||||
case '\f':
|
||||
case '\r':
|
||||
p++; numBytes--;
|
||||
continue;
|
||||
case '\n':
|
||||
numBytes--;
|
||||
break;
|
||||
default:
|
||||
badwrap:
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"invalid wrapchar; will defeat decoding",
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "BINARY",
|
||||
"ENCODE", "WRAPCHAR", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
if (numBytes) {
|
||||
while (numBytes) {
|
||||
switch (*p) {
|
||||
case '\t':
|
||||
case '\v':
|
||||
case '\f':
|
||||
case '\r':
|
||||
p++;
|
||||
numBytes--;
|
||||
continue;
|
||||
case '\n':
|
||||
numBytes--;
|
||||
break;
|
||||
default:
|
||||
goto badwrap;
|
||||
}
|
||||
}
|
||||
if (numBytes) {
|
||||
badwrap:
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"invalid wrapchar; will defeat decoding", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "BINARY",
|
||||
"ENCODE", "WRAPCHAR", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2909,6 +2908,8 @@ BinaryDecodeUu(
|
||||
case OPT_STRICT:
|
||||
strict = 1;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3084,6 +3085,8 @@ BinaryDecode64(
|
||||
case OPT_STRICT:
|
||||
strict = 1;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -812,7 +812,8 @@ MemoryCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (strcmp(TclGetString(objv[1]), "active") == 0 || strcmp(TclGetString(objv[1]), "display") == 0) {
|
||||
if (strcmp(TclGetString(objv[1]), "active") == 0 ||
|
||||
strcmp(TclGetString(objv[1]), "display") == 0) {
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "file");
|
||||
return TCL_ERROR;
|
||||
@@ -1256,12 +1257,11 @@ TclAllocElemsEx(
|
||||
* non-NULL. Only modified on success */
|
||||
{
|
||||
void *ptr = TclAttemptReallocElemsEx(
|
||||
NULL, elemCount, elemSize, leadSize, capacityPtr);
|
||||
NULL, elemCount, elemSize, leadSize, capacityPtr);
|
||||
if (ptr == NULL) {
|
||||
Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER
|
||||
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
|
||||
elemCount,
|
||||
elemSize);
|
||||
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
|
||||
elemCount, elemSize);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
@@ -1362,12 +1362,11 @@ TclReallocElemsEx(
|
||||
* non-NULL. Only modified on success */
|
||||
{
|
||||
void *ptr = TclAttemptReallocElemsEx(
|
||||
oldPtr, elemCount, elemSize, leadSize, capacityPtr);
|
||||
oldPtr, elemCount, elemSize, leadSize, capacityPtr);
|
||||
if (ptr == NULL) {
|
||||
Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER
|
||||
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
|
||||
elemCount,
|
||||
elemSize);
|
||||
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
|
||||
elemCount, elemSize);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
+22
-9
@@ -129,10 +129,10 @@ static const struct ClockCommand clockCommands[] = {
|
||||
{"clicks", ClockClicksObjCmd, TclCompileClockClicksCmd, NULL},
|
||||
{"format", ClockFormatObjCmd, TclCompileBasicMin1ArgCmd, NULL},
|
||||
{"getenv", ClockGetenvObjCmd, TclCompileBasicMin1ArgCmd, NULL},
|
||||
{"microseconds", ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(1)},
|
||||
{"milliseconds", ClockMillisecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(2)},
|
||||
{"microseconds", ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(CLOCK_READ_MICROS)},
|
||||
{"milliseconds", ClockMillisecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(CLOCK_READ_MILLIS)},
|
||||
{"scan", ClockScanObjCmd, TclCompileBasicMin1ArgCmd, NULL},
|
||||
{"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, INT2PTR(3)},
|
||||
{"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, INT2PTR(CLOCK_READ_SECS)},
|
||||
{"ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd, NULL, NULL},
|
||||
{"GetDateFields", ClockGetdatefieldsObjCmd, NULL, NULL},
|
||||
{"GetJulianDayFromEraYearMonthDay",
|
||||
@@ -988,7 +988,11 @@ ClockConfigureObjCmd(
|
||||
TclSetObjRef(dataPtr->systemTimeZone, objv[i]);
|
||||
TclUnsetObjRef(dataPtr->systemSetupTZData);
|
||||
}
|
||||
dataPtr->lastTZEpoch = lastTZEpoch;
|
||||
if (dataPtr->lastTZEpoch != lastTZEpoch) {
|
||||
dataPtr->lastTZEpoch = lastTZEpoch;
|
||||
/* TZ epoch changed - invalidate base-cache */
|
||||
TclUnsetObjRef(dataPtr->lastBase.timezoneObj);
|
||||
}
|
||||
}
|
||||
if (i + 1 >= objc && dataPtr->systemTimeZone != NULL
|
||||
&& dataPtr->lastTZEpoch == lastTZEpoch) {
|
||||
@@ -1154,6 +1158,8 @@ ClockConfigureObjCmd(
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3159,6 +3165,8 @@ ClockClicksObjCmd(
|
||||
case CLICKS_MICROS:
|
||||
clicks = TclpGetMicroseconds();
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(clicks));
|
||||
@@ -3371,6 +3379,8 @@ ClockParseFmtScnArgs(
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
saw |= 1 << optionIndex;
|
||||
}
|
||||
@@ -3431,8 +3441,8 @@ ClockParseFmtScnArgs(
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad seconds \"%s\": must be now or integer",
|
||||
TclGetString(baseObj)));
|
||||
"bad seconds \"%s\": must be now or integer",
|
||||
TclGetString(baseObj)));
|
||||
i = baseIdx;
|
||||
goto badOption;
|
||||
}
|
||||
@@ -3474,7 +3484,7 @@ ClockParseFmtScnArgs(
|
||||
/* extact fields from base */
|
||||
date->seconds = baseVal;
|
||||
if (ClockGetDateFields(dataPtr, interp, date, opts->timezoneObj,
|
||||
GREGORIAN_CHANGE_DATE) != TCL_OK) {
|
||||
GREGORIAN_CHANGE_DATE) != TCL_OK) {
|
||||
/* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -3624,7 +3634,8 @@ ClockScanObjCmd(
|
||||
}
|
||||
|
||||
/* seconds are in localSeconds (relative base date), so reset time here */
|
||||
yyHour = yyMinutes = yySeconds = yySecondOfDay = 0; yyMeridian = MER24;
|
||||
yyHour = yyMinutes = yySeconds = yySecondOfDay = 0;
|
||||
yyMeridian = MER24;
|
||||
|
||||
/* If free scan */
|
||||
if (opts.formatObj == NULL) {
|
||||
@@ -4265,7 +4276,7 @@ ClockCalcRelTime(
|
||||
yyRelSeconds = 0;
|
||||
/* Convert it back */
|
||||
if (ClockGetDateFields(opts->dataPtr, opts->interp, &yydate,
|
||||
opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) {
|
||||
opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) {
|
||||
/* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -4537,6 +4548,8 @@ ClockAddObjCmd(
|
||||
case CLC_ADD_SECONDS:
|
||||
yyRelSeconds += offs;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
if (unitIndex < CLC_ADD_HOURS) { /* date units only */
|
||||
info->flags |= CLF_RELCONV;
|
||||
|
||||
+43
-30
@@ -565,7 +565,10 @@ ClockFmtScnStorageAllocProc(
|
||||
allocsize -= sizeof(hPtr->key);
|
||||
}
|
||||
|
||||
fss = (ClockFmtScnStorage *)Tcl_Alloc(allocsize);
|
||||
fss = (ClockFmtScnStorage *)Tcl_AttemptAlloc(allocsize);
|
||||
if (!fss) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize */
|
||||
memset(fss, 0, sizeof(*fss));
|
||||
@@ -841,7 +844,7 @@ FindOrCreateFmtScnStorage(
|
||||
}
|
||||
|
||||
/* get or create entry (and alocate storage) */
|
||||
hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
|
||||
hPtr = Tcl_AttemptCreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
|
||||
if (hPtr != NULL) {
|
||||
fss = FmtScn4HashEntry(hPtr);
|
||||
|
||||
@@ -1024,7 +1027,7 @@ static const char *
|
||||
FindTokenBegin(
|
||||
const char *p,
|
||||
const char *end,
|
||||
ClockScanToken *tok,
|
||||
const ClockScanToken *tok,
|
||||
int flags)
|
||||
{
|
||||
if (p < end) {
|
||||
@@ -1037,10 +1040,14 @@ FindTokenBegin(
|
||||
if (!(flags & CLF_STRICT)) {
|
||||
/* should match at least one digit or space */
|
||||
while (!isdigit(UCHAR(*p)) && !isspace(UCHAR(*p)) &&
|
||||
(p = Tcl_UtfNext(p)) < end) {}
|
||||
(p = Tcl_UtfNext(p)) < end) {
|
||||
// Empty
|
||||
}
|
||||
} else {
|
||||
/* should match at least one digit */
|
||||
while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
|
||||
while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
return p;
|
||||
|
||||
@@ -1049,19 +1056,25 @@ FindTokenBegin(
|
||||
goto findChar;
|
||||
|
||||
case CTOKT_SPACE:
|
||||
while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
|
||||
while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {
|
||||
// Empty
|
||||
}
|
||||
return p;
|
||||
|
||||
case CTOKT_CHAR:
|
||||
c = *((char *)tok->map->data);
|
||||
findChar:
|
||||
findChar:
|
||||
if (!(flags & CLF_STRICT)) {
|
||||
/* should match the char or space */
|
||||
while (*p != c && !isspace(UCHAR(*p)) &&
|
||||
(p = Tcl_UtfNext(p)) < end) {}
|
||||
(p = Tcl_UtfNext(p)) < end) {
|
||||
// Empty
|
||||
}
|
||||
} else {
|
||||
/* should match the char */
|
||||
while (*p != c && (p = Tcl_UtfNext(p)) < end) {}
|
||||
while (*p != c && (p = Tcl_UtfNext(p)) < end) {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -1089,7 +1102,7 @@ static void
|
||||
DetermineGreedySearchLen(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok,
|
||||
const ClockScanToken *tok,
|
||||
int *minLenPtr,
|
||||
int *maxLenPtr)
|
||||
{
|
||||
@@ -1141,7 +1154,7 @@ DetermineGreedySearchLen(
|
||||
/* try to get max length more precise for greedy match,
|
||||
* check the next ahead token available there */
|
||||
if (minLen < maxLen && tok->lookAhTok) {
|
||||
ClockScanToken *laTok = tok + tok->lookAhTok + 1;
|
||||
const ClockScanToken *laTok = tok + tok->lookAhTok + 1;
|
||||
|
||||
p = yyInput + maxLen;
|
||||
/* regards all possible spaces here (because they are optional) */
|
||||
@@ -1155,7 +1168,7 @@ DetermineGreedySearchLen(
|
||||
/* try to find laTok between [lookAhMin, lookAhMax] */
|
||||
while (minLen < maxLen) {
|
||||
const char *f = FindTokenBegin(p, end, laTok,
|
||||
TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
|
||||
TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
|
||||
/* if found (not below lookAhMax) */
|
||||
if (f < end) {
|
||||
break;
|
||||
@@ -1491,7 +1504,7 @@ StaticListSearch(
|
||||
|
||||
static inline const char *
|
||||
FindWordEnd(
|
||||
ClockScanToken *tok,
|
||||
const ClockScanToken *tok,
|
||||
const char *p,
|
||||
const char *end)
|
||||
{
|
||||
@@ -1516,7 +1529,7 @@ static int
|
||||
ClockScnToken_Month_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
#if 0
|
||||
/* currently unused, test purposes only */
|
||||
@@ -1566,7 +1579,7 @@ static int
|
||||
ClockScnToken_DayOfWeek_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
static int dowKeys[] = {MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_FULL, 0};
|
||||
|
||||
@@ -1640,7 +1653,7 @@ static int
|
||||
ClockScnToken_amPmInd_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
int ret, val;
|
||||
int minLen, maxLen;
|
||||
@@ -1673,7 +1686,7 @@ static int
|
||||
ClockScnToken_LocaleERA_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
ClockClientData *dataPtr = opts->dataPtr;
|
||||
|
||||
@@ -1712,7 +1725,7 @@ static int
|
||||
ClockScnToken_LocaleListMatcher_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
int ret, val;
|
||||
int minLen, maxLen;
|
||||
@@ -1743,7 +1756,7 @@ static int
|
||||
ClockScnToken_JDN_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
int minLen, maxLen;
|
||||
const char *p = yyInput, *end, *s;
|
||||
@@ -1814,7 +1827,7 @@ static int
|
||||
ClockScnToken_TimeZone_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
int minLen, maxLen;
|
||||
int len = 0;
|
||||
@@ -1906,7 +1919,7 @@ static int
|
||||
ClockScnToken_StarDate_Proc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok)
|
||||
const ClockScanToken *tok)
|
||||
{
|
||||
int minLen, maxLen;
|
||||
const char *p = yyInput, *end, *s;
|
||||
@@ -2300,8 +2313,7 @@ ClockGetOrParseScanFormat(
|
||||
tokCnt++;
|
||||
continue;
|
||||
}
|
||||
word_tok:
|
||||
{
|
||||
word_tok: {
|
||||
/* try continue with previous word token */
|
||||
ClockScanToken *wordTok = tok - 1;
|
||||
|
||||
@@ -2324,9 +2336,9 @@ ClockGetOrParseScanFormat(
|
||||
AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *);
|
||||
tokCnt++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate end distance value for each tokens */
|
||||
@@ -2373,8 +2385,8 @@ ClockScan(
|
||||
ClockFmtScnCmdArgs *opts) /* Command options */
|
||||
{
|
||||
ClockClientData *dataPtr = opts->dataPtr;
|
||||
ClockFmtScnStorage *fss;
|
||||
ClockScanToken *tok;
|
||||
const ClockFmtScnStorage *fss;
|
||||
const ClockScanToken *tok;
|
||||
const ClockScanTokenMap *map;
|
||||
const char *p, *x, *end;
|
||||
unsigned short flags = 0;
|
||||
@@ -2554,6 +2566,8 @@ ClockScan(
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
/* check end was reached */
|
||||
@@ -2602,7 +2616,7 @@ ClockScan(
|
||||
case (CLF_DAYOFYEAR | CLF_DAYOFMONTH):
|
||||
/* miss month: ddd over dd (without month) */
|
||||
flags &= ~CLF_DAYOFMONTH;
|
||||
/* fallthrough */
|
||||
TCL_FALLTHROUGH();
|
||||
case CLF_DAYOFYEAR:
|
||||
/* ddd over naked weekday */
|
||||
if (!(flags & CLF_ISO8601YEAR)) {
|
||||
@@ -3343,8 +3357,7 @@ ClockGetOrParseFmtFormat(
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
word_tok:
|
||||
{
|
||||
word_tok: {
|
||||
/* try continue with previous word token */
|
||||
ClockFormatToken *wordTok = tok - 1;
|
||||
|
||||
@@ -3363,9 +3376,9 @@ ClockGetOrParseFmtFormat(
|
||||
AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *);
|
||||
tokCnt++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* correct count of real used tokens and free mem if desired
|
||||
|
||||
+101
-65
@@ -53,6 +53,7 @@ static Tcl_ObjCmdProc EncodingDirsObjCmd;
|
||||
static Tcl_ObjCmdProc EncodingNamesObjCmd;
|
||||
static Tcl_ObjCmdProc EncodingProfilesObjCmd;
|
||||
static Tcl_ObjCmdProc EncodingSystemObjCmd;
|
||||
static Tcl_ObjCmdProc EncodingUserObjCmd;
|
||||
static inline int ForeachAssignments(Tcl_Interp *interp,
|
||||
struct ForeachState *statePtr);
|
||||
static inline void ForeachCleanup(Tcl_Interp *interp,
|
||||
@@ -394,6 +395,7 @@ TclInitEncodingCmd(
|
||||
{"names", EncodingNamesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"profiles", EncodingProfilesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"system", EncodingSystemObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
|
||||
{"user", EncodingUserObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 1},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
@@ -483,6 +485,8 @@ EncodingConvertParseOptions(
|
||||
case FAILINDEX:
|
||||
failVarObj = objv[argIndex];
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
/* Get encoding after opts so no need to free it on option error */
|
||||
@@ -547,14 +551,14 @@ EncodingConvertfromObjCmd(
|
||||
result = Tcl_ExternalToUtfDStringEx(interp, encoding, bytesPtr, length, flags,
|
||||
&ds, failVarObj ? &errorLocation : NULL);
|
||||
/* NOTE: ds must be freed beyond this point even on error */
|
||||
|
||||
switch (result) {
|
||||
case TCL_OK:
|
||||
errorLocation = TCL_INDEX_NONE;
|
||||
break;
|
||||
case TCL_ERROR:
|
||||
/* Error in parameters. Should not happen. interp will have error */
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
goto done;
|
||||
default:
|
||||
/*
|
||||
* One of the TCL_CONVERT_* errors. If we were not interested in the
|
||||
@@ -563,8 +567,8 @@ EncodingConvertfromObjCmd(
|
||||
* what could be decoded and the returned error location.
|
||||
*/
|
||||
if (failVarObj == NULL) {
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -578,8 +582,8 @@ EncodingConvertfromObjCmd(
|
||||
TclNewIndexObj(failIndex, errorLocation);
|
||||
if (Tcl_ObjSetVar2(interp, failVarObj, NULL, failIndex,
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -588,11 +592,14 @@ EncodingConvertfromObjCmd(
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_DStringToObj(&ds));
|
||||
result = TCL_OK;
|
||||
|
||||
/* We're done with the encoding */
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return TCL_OK;
|
||||
done:
|
||||
Tcl_DStringFree(&ds);
|
||||
if (encoding) {
|
||||
Tcl_FreeEncoding(encoding);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -646,8 +653,7 @@ EncodingConverttoObjCmd(
|
||||
break;
|
||||
case TCL_ERROR:
|
||||
/* Error in parameters. Should not happen. interp will have error */
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
goto done;
|
||||
default:
|
||||
/*
|
||||
* One of the TCL_CONVERT_* errors. If we were not interested in the
|
||||
@@ -656,8 +662,8 @@ EncodingConverttoObjCmd(
|
||||
* what could be decoded and the returned error location.
|
||||
*/
|
||||
if (failVarObj == NULL) {
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -671,20 +677,23 @@ EncodingConverttoObjCmd(
|
||||
TclNewIndexObj(failIndex, errorLocation);
|
||||
if (Tcl_ObjSetVar2(interp, failVarObj, NULL, failIndex,
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
Tcl_DStringFree(&ds);
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
|
||||
(unsigned char*) Tcl_DStringValue(&ds),
|
||||
Tcl_DStringLength(&ds)));
|
||||
|
||||
result = TCL_OK;
|
||||
|
||||
done:
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
/* We're done with the encoding */
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return TCL_OK;
|
||||
if (encoding) {
|
||||
Tcl_FreeEncoding(encoding);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -826,6 +835,36 @@ EncodingSystemObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* EncodingUserObjCmd --
|
||||
*
|
||||
* This command retrieves the encoding as per the user settings.
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingUserObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
int objc, /* Number of command line args */
|
||||
Tcl_Obj* const objv[]) /* Vector of command line args */
|
||||
{
|
||||
if (objc > 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DString ds;
|
||||
Tcl_GetEncodingNameForUser(&ds);
|
||||
Tcl_DStringResult(interp, &ds);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -2118,8 +2157,7 @@ PathTypeCmd(
|
||||
TclNewLiteralStringObj(typeName, "volumerelative");
|
||||
break;
|
||||
default:
|
||||
/* Should be unreachable */
|
||||
return TCL_OK;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
Tcl_SetObjResult(interp, typeName);
|
||||
return TCL_OK;
|
||||
@@ -2339,34 +2377,30 @@ StoreStatData(
|
||||
* store in varName. */
|
||||
{
|
||||
Tcl_Obj *field, *value, *result;
|
||||
unsigned short mode;
|
||||
unsigned short modeVal = (unsigned short) statPtr->st_mode;
|
||||
|
||||
if (varName == NULL) {
|
||||
TclNewObj(result);
|
||||
Tcl_IncrRefCount(result);
|
||||
#define DOBJPUT(key, objValue) \
|
||||
Tcl_DictObjPut(NULL, result, \
|
||||
Tcl_NewStringObj((key), -1), \
|
||||
(objValue));
|
||||
DOBJPUT("dev", Tcl_NewWideIntObj((long)statPtr->st_dev));
|
||||
DOBJPUT("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
|
||||
DOBJPUT("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink));
|
||||
DOBJPUT("uid", Tcl_NewWideIntObj((long)statPtr->st_uid));
|
||||
DOBJPUT("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
|
||||
DOBJPUT("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
|
||||
#define D_PUT(key, objValue) TclDictPut(NULL, result, #key, (objValue))
|
||||
D_PUT(dev, Tcl_NewWideIntObj((long)statPtr->st_dev));
|
||||
D_PUT(ino, Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
|
||||
D_PUT(nlink, Tcl_NewWideIntObj((long)statPtr->st_nlink));
|
||||
D_PUT(uid, Tcl_NewWideIntObj((long)statPtr->st_uid));
|
||||
D_PUT(gid, Tcl_NewWideIntObj((long)statPtr->st_gid));
|
||||
D_PUT(size, Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
DOBJPUT("blocks", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
|
||||
D_PUT(blocks, Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
DOBJPUT("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
|
||||
D_PUT(blksize, Tcl_NewWideIntObj((long)statPtr->st_blksize));
|
||||
#endif
|
||||
DOBJPUT("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
|
||||
DOBJPUT("mtime", Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
DOBJPUT("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
|
||||
mode = (unsigned short) statPtr->st_mode;
|
||||
DOBJPUT("mode", Tcl_NewWideIntObj(mode));
|
||||
DOBJPUT("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
|
||||
#undef DOBJPUT
|
||||
D_PUT(atime, Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
|
||||
D_PUT(mtime, Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
D_PUT(ctime, Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
|
||||
D_PUT(mode, Tcl_NewWideIntObj(modeVal));
|
||||
D_PUT(type, Tcl_NewStringObj(GetTypeFromMode(modeVal), -1));
|
||||
#undef D_PUT
|
||||
Tcl_SetObjResult(interp, result);
|
||||
Tcl_DecrRefCount(result);
|
||||
return TCL_OK;
|
||||
@@ -2379,44 +2413,45 @@ StoreStatData(
|
||||
*/
|
||||
|
||||
#define STORE_ARY(fieldName, object) \
|
||||
TclNewLiteralStringObj(field, fieldName); \
|
||||
Tcl_IncrRefCount(field); \
|
||||
value = (object); \
|
||||
if (Tcl_ObjSetVar2(interp,varName,field,value,TCL_LEAVE_ERR_MSG)==NULL) { \
|
||||
do { \
|
||||
TclNewLiteralStringObj(field, #fieldName); \
|
||||
Tcl_IncrRefCount(field); \
|
||||
value = (object); \
|
||||
if (Tcl_ObjSetVar2(interp, varName, field, value, \
|
||||
TCL_LEAVE_ERR_MSG) == NULL) { \
|
||||
TclDecrRefCount(field); \
|
||||
return TCL_ERROR; \
|
||||
} \
|
||||
TclDecrRefCount(field); \
|
||||
return TCL_ERROR; \
|
||||
} \
|
||||
TclDecrRefCount(field);
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Watch out porters; the inode is meant to be an *unsigned* value, so the
|
||||
* cast might fail when there isn't a real arithmetic 'long long' type...
|
||||
*/
|
||||
|
||||
STORE_ARY("dev", Tcl_NewWideIntObj((long)statPtr->st_dev));
|
||||
STORE_ARY("ino", Tcl_NewWideIntObj(statPtr->st_ino));
|
||||
STORE_ARY("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink));
|
||||
STORE_ARY("uid", Tcl_NewWideIntObj((long)statPtr->st_uid));
|
||||
STORE_ARY("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
|
||||
STORE_ARY("size", Tcl_NewWideIntObj(statPtr->st_size));
|
||||
STORE_ARY(dev, Tcl_NewWideIntObj((long)statPtr->st_dev));
|
||||
STORE_ARY(ino, Tcl_NewWideIntObj(statPtr->st_ino));
|
||||
STORE_ARY(nlink, Tcl_NewWideIntObj((long)statPtr->st_nlink));
|
||||
STORE_ARY(uid, Tcl_NewWideIntObj((long)statPtr->st_uid));
|
||||
STORE_ARY(gid, Tcl_NewWideIntObj((long)statPtr->st_gid));
|
||||
STORE_ARY(size, Tcl_NewWideIntObj(statPtr->st_size));
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
STORE_ARY("blocks", Tcl_NewWideIntObj(statPtr->st_blocks));
|
||||
STORE_ARY(blocks, Tcl_NewWideIntObj(statPtr->st_blocks));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
|
||||
STORE_ARY(blksize, Tcl_NewWideIntObj((long)statPtr->st_blksize));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_RDEV
|
||||
if (S_ISCHR(statPtr->st_mode) || S_ISBLK(statPtr->st_mode)) {
|
||||
STORE_ARY("rdev", Tcl_NewWideIntObj((long) statPtr->st_rdev));
|
||||
}
|
||||
#endif
|
||||
STORE_ARY("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
|
||||
STORE_ARY("mtime", Tcl_NewWideIntObj(
|
||||
Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
STORE_ARY("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
|
||||
mode = (unsigned short) statPtr->st_mode;
|
||||
STORE_ARY("mode", Tcl_NewWideIntObj(mode));
|
||||
STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
|
||||
STORE_ARY(atime, Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
|
||||
STORE_ARY(mtime, Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
|
||||
STORE_ARY(ctime, Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
|
||||
STORE_ARY(mode, Tcl_NewWideIntObj(modeVal));
|
||||
STORE_ARY(type, Tcl_NewStringObj(GetTypeFromMode(modeVal), -1));
|
||||
#undef STORE_ARY
|
||||
|
||||
return TCL_OK;
|
||||
@@ -2928,6 +2963,7 @@ ForeachLoopStep(
|
||||
"\n (\"%s\" body line %d)",
|
||||
(statePtr->resultList != NULL ? "lmap" : "foreach"),
|
||||
Tcl_GetErrorLine(interp)));
|
||||
TCL_FALLTHROUGH();
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
|
||||
+58
-212
@@ -106,7 +106,7 @@ typedef enum {
|
||||
LSEQ_DOTS, LSEQ_TO, LSEQ_COUNT, LSEQ_BY
|
||||
} SequenceOperators;
|
||||
typedef enum {
|
||||
NoneArg, NumericArg, RangeKeywordArg, ErrArg, LastArg = 8
|
||||
NoneArg, NumericArg, RangeKeywordArg, ErrArg, LastArg = 8
|
||||
} SequenceDecoded;
|
||||
|
||||
/*
|
||||
@@ -818,7 +818,7 @@ InfoCommandsCmd(
|
||||
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
|
||||
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
|
||||
(void) Tcl_CreateHashEntry(&addedCommandsTable,
|
||||
elemObjPtr, &isNew);
|
||||
elemObjPtr, NULL);
|
||||
}
|
||||
entryPtr = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
@@ -1304,7 +1304,7 @@ TclInfoFrame(
|
||||
break;
|
||||
|
||||
case TCL_LOCATION_PREBC:
|
||||
precompiled:
|
||||
precompiled:
|
||||
/*
|
||||
* Precompiled. Result contains the type as signal, nothing else.
|
||||
*/
|
||||
@@ -1607,7 +1607,7 @@ InfoLevelCmd(
|
||||
}
|
||||
for (framePtr=iPtr->varFramePtr ; framePtr!=rootFramePtr;
|
||||
framePtr=framePtr->callerVarPtr) {
|
||||
if ((int)framePtr->level == level) {
|
||||
if (framePtr->level == level) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2327,22 +2327,14 @@ Tcl_LassignObjCmd(
|
||||
}
|
||||
|
||||
if (listObjc > 0) {
|
||||
Tcl_Obj *resultObjPtr = NULL;
|
||||
Tcl_Size fromIdx = origListObjc - listObjc;
|
||||
Tcl_Size toIdx = origListObjc - 1;
|
||||
if (TclObjTypeHasProc(listPtr, sliceProc)) {
|
||||
if (TclObjTypeSlice(
|
||||
interp, listPtr, fromIdx, toIdx, &resultObjPtr) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
resultObjPtr = TclListObjRange(
|
||||
interp, listPtr, origListObjc - listObjc, origListObjc - 1);
|
||||
if (resultObjPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Obj *resultObj = NULL;
|
||||
Tcl_Size first = origListObjc - listObjc;
|
||||
Tcl_Size last = origListObjc - 1;
|
||||
int result = Tcl_ListObjRange(interp, listPtr, first, last, &resultObj);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObjPtr);
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
@@ -2748,22 +2740,12 @@ Tcl_LrangeObjCmd(
|
||||
return result;
|
||||
}
|
||||
|
||||
if (TclObjTypeHasProc(objv[1], sliceProc)) {
|
||||
Tcl_Obj *resultObj;
|
||||
int status = TclObjTypeSlice(interp, objv[1], first, last, &resultObj);
|
||||
if (status == TCL_OK) {
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
} else {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
Tcl_Obj *resultObj = TclListObjRange(interp, objv[1], first, last);
|
||||
if (resultObj == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Obj *resultObj;
|
||||
result = Tcl_ListObjRange(interp, objv[1], first, last, &resultObj);
|
||||
if (result == TCL_OK) {
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
}
|
||||
return TCL_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2936,92 +2918,24 @@ Tcl_LrepeatObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* The argument objects. */
|
||||
{
|
||||
Tcl_WideInt elementCount, i;
|
||||
Tcl_Size totalElems;
|
||||
Tcl_Obj *listPtr, **dataArray = NULL;
|
||||
|
||||
/*
|
||||
* Check arguments for legality:
|
||||
* lrepeat count ?value ...?
|
||||
*/
|
||||
Tcl_Size repeatCount;
|
||||
Tcl_Obj *resultPtr;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "count ?value ...?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (TCL_OK != TclGetWideIntFromObj(interp, objv[1], &elementCount)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (elementCount < 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad count \"%" TCL_LL_MODIFIER "d\": must be integer >= 0", elementCount));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG",
|
||||
(char *)NULL);
|
||||
|
||||
if (Tcl_GetSizeIntFromObj(interp, objv[1], &repeatCount) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip forward to the interesting arguments now we've finished parsing.
|
||||
*/
|
||||
|
||||
objc -= 2;
|
||||
objv += 2;
|
||||
|
||||
/* Final sanity check. Do not exceed limits on max list length. */
|
||||
|
||||
if (elementCount && objc > LIST_MAX/elementCount) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max length of a Tcl list (%" TCL_SIZE_MODIFIER "d elements) exceeded", LIST_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
|
||||
if (Tcl_ListObjRepeat(
|
||||
interp, repeatCount, objc - 2, objv + 2, &resultPtr) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
totalElems = objc * elementCount;
|
||||
|
||||
/*
|
||||
* Get an empty list object that is allocated large enough to hold each
|
||||
* init value elementCount times.
|
||||
*/
|
||||
|
||||
listPtr = Tcl_NewListObj(totalElems, NULL);
|
||||
if (totalElems) {
|
||||
ListRep listRep;
|
||||
ListObjGetRep(listPtr, &listRep);
|
||||
dataArray = ListRepElementsBase(&listRep);
|
||||
listRep.storePtr->numUsed = totalElems;
|
||||
if (listRep.spanPtr) {
|
||||
/* Future proofing in case Tcl_NewListObj returns a span */
|
||||
listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
|
||||
listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the elements. Note that we handle the common degenerate case of a
|
||||
* single value being repeated separately to permit the compiler as much
|
||||
* room as possible to optimize a loop that might be run a very large
|
||||
* number of times.
|
||||
*/
|
||||
|
||||
CLANG_ASSERT(dataArray || totalElems == 0 );
|
||||
if (objc == 1) {
|
||||
Tcl_Obj *tmpPtr = objv[0];
|
||||
|
||||
tmpPtr->refCount += elementCount;
|
||||
for (i=0 ; i<elementCount ; i++) {
|
||||
dataArray[i] = tmpPtr;
|
||||
}
|
||||
} else {
|
||||
Tcl_Size j, k = 0;
|
||||
|
||||
for (i=0 ; i<elementCount ; i++) {
|
||||
for (j=0 ; j<objc ; j++) {
|
||||
Tcl_IncrRefCount(objv[j]);
|
||||
dataArray[k++] = objv[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, listPtr);
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -3152,82 +3066,16 @@ Tcl_LreverseObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument values. */
|
||||
{
|
||||
Tcl_Obj **elemv;
|
||||
Tcl_Size elemc, i, j;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "list");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle AbstractList special case - do not shimmer into a list, if it
|
||||
* supports a private Reverse function, just to reverse it.
|
||||
*/
|
||||
if (TclObjTypeHasProc(objv[1], reverseProc)) {
|
||||
Tcl_Obj *resultObj;
|
||||
|
||||
if (TclObjTypeReverse(interp, objv[1], &resultObj) == TCL_OK) {
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
} /* end Abstract List */
|
||||
|
||||
if (TclListObjLength(interp, objv[1], &elemc) != TCL_OK) {
|
||||
Tcl_Obj *resultObj = NULL;
|
||||
if (Tcl_ListObjReverse(interp, objv[1], &resultObj) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the list is empty, just return it. [Bug 1876793]
|
||||
*/
|
||||
|
||||
if (!elemc) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (Tcl_IsShared(objv[1])
|
||||
|| ListObjRepIsShared(objv[1])) { /* Bug 1675044 */
|
||||
Tcl_Obj *resultObj, **dataArray;
|
||||
ListRep listRep;
|
||||
|
||||
resultObj = Tcl_NewListObj(elemc, NULL);
|
||||
|
||||
/* Modify the internal rep in-place */
|
||||
ListObjGetRep(resultObj, &listRep);
|
||||
listRep.storePtr->numUsed = elemc;
|
||||
dataArray = ListRepElementsBase(&listRep);
|
||||
if (listRep.spanPtr) {
|
||||
/* Future proofing */
|
||||
listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
|
||||
listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
|
||||
}
|
||||
|
||||
for (i=0,j=elemc-1 ; i<elemc ; i++,j--) {
|
||||
dataArray[j] = elemv[i];
|
||||
Tcl_IncrRefCount(elemv[i]);
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Not shared, so swap "in place". This relies on Tcl_LOGE above
|
||||
* returning a pointer to the live array of Tcl_Obj values.
|
||||
*/
|
||||
|
||||
for (i=0,j=elemc-1 ; i<j ; i++,j--) {
|
||||
Tcl_Obj *tmp = elemv[i];
|
||||
|
||||
elemv[i] = elemv[j];
|
||||
elemv[j] = tmp;
|
||||
}
|
||||
TclInvalidateStringRep(objv[1]);
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -3504,6 +3352,8 @@ Tcl_LsearchObjCmd(
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3924,7 +3774,7 @@ Tcl_LsearchObjCmd(
|
||||
} else if (returnSubindices && (sortInfo.indexc == 0) && (groupSize > 1)) {
|
||||
Tcl_BounceRefCount(itemPtr);
|
||||
itemPtr = listv[i + groupOffset];
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
} else if (groupSize > 1) {
|
||||
Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0,
|
||||
groupSize, &listv[i]);
|
||||
@@ -3972,8 +3822,8 @@ Tcl_LsearchObjCmd(
|
||||
}
|
||||
Tcl_SetObjResult(interp, itemPtr);
|
||||
} else {
|
||||
Tcl_Obj *elObj;
|
||||
TclNewIndexObj(elObj, index);
|
||||
Tcl_Obj *elObj;
|
||||
TclNewIndexObj(elObj, index);
|
||||
Tcl_SetObjResult(interp, elObj);
|
||||
}
|
||||
} else if (index < 0) {
|
||||
@@ -4032,11 +3882,11 @@ Tcl_LsearchObjCmd(
|
||||
|
||||
static SequenceDecoded
|
||||
SequenceIdentifyArgument(
|
||||
Tcl_Interp *interp, /* for error reporting */
|
||||
Tcl_Obj *argPtr, /* Argument to decode */
|
||||
int allowedArgs, /* Flags if keyword or numeric allowed. */
|
||||
Tcl_Obj **numValuePtr, /* Return numeric value */
|
||||
int *keywordIndexPtr) /* Return keyword enum */
|
||||
Tcl_Interp *interp, /* for error reporting */
|
||||
Tcl_Obj *argPtr, /* Argument to decode */
|
||||
int allowedArgs, /* Flags if keyword or numeric allowed. */
|
||||
Tcl_Obj **numValuePtr, /* Return numeric value */
|
||||
int *keywordIndexPtr) /* Return keyword enum */
|
||||
{
|
||||
int result = TCL_ERROR;
|
||||
SequenceOperators opmode;
|
||||
@@ -4045,7 +3895,7 @@ SequenceIdentifyArgument(
|
||||
if (allowedArgs & NumericArg) {
|
||||
/* speed-up a bit (and avoid shimmer for compiled expressions) */
|
||||
if (TclHasInternalRep(argPtr, &tclExprCodeType)) {
|
||||
goto doExpr;
|
||||
goto doExpr;
|
||||
}
|
||||
result = Tcl_GetNumberFromObj(NULL, argPtr, &internalPtr, keywordIndexPtr);
|
||||
if (result == TCL_OK) {
|
||||
@@ -4056,13 +3906,13 @@ SequenceIdentifyArgument(
|
||||
}
|
||||
if (allowedArgs & RangeKeywordArg) {
|
||||
result = Tcl_GetIndexFromObj(NULL, argPtr, seq_operations,
|
||||
"range operation", 0, &opmode);
|
||||
"range operation", 0, &opmode);
|
||||
}
|
||||
if (result == TCL_OK) {
|
||||
if (allowedArgs & LastArg) {
|
||||
/* keyword found, but no followed number */
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"missing \"%s\" value.", TclGetString(argPtr)));
|
||||
"missing \"%s\" value.", TclGetString(argPtr)));
|
||||
return ErrArg;
|
||||
}
|
||||
*keywordIndexPtr = opmode;
|
||||
@@ -4145,8 +3995,8 @@ Tcl_LseqObjCmd(
|
||||
SequenceDecoded decoded;
|
||||
int i, arg_key = 0, value_i = 0;
|
||||
/* Default constants */
|
||||
#define zero ((Interp *)interp)->execEnvPtr->constants[0];
|
||||
#define one ((Interp *)interp)->execEnvPtr->constants[1];
|
||||
#define zero ((Interp *)interp)->execEnvPtr->constants[0];
|
||||
#define one ((Interp *)interp)->execEnvPtr->constants[1];
|
||||
|
||||
/*
|
||||
* Create a decoding key by looping through the arguments and identify
|
||||
@@ -4161,19 +4011,19 @@ Tcl_LseqObjCmd(
|
||||
arg_key = (arg_key * 10);
|
||||
numValues[value_i] = NULL;
|
||||
decoded = SequenceIdentifyArgument(interp, objv[i],
|
||||
allowedArgs | (i == objc-1 ? LastArg : 0),
|
||||
&numberObj, &keyword);
|
||||
allowedArgs | (i == objc-1 ? LastArg : 0),
|
||||
&numberObj, &keyword);
|
||||
switch (decoded) {
|
||||
case NoneArg:
|
||||
case NoneArg:
|
||||
/*
|
||||
* Unrecognizable argument
|
||||
* Reproduce operation error message
|
||||
*/
|
||||
status = Tcl_GetIndexFromObj(interp, objv[i], seq_operations,
|
||||
"operation", 0, &opmode);
|
||||
"operation", 0, &opmode);
|
||||
goto done;
|
||||
|
||||
case NumericArg:
|
||||
case NumericArg:
|
||||
remNums--;
|
||||
arg_key += NumericArg;
|
||||
allowedArgs = RangeKeywordArg;
|
||||
@@ -4189,14 +4039,14 @@ Tcl_LseqObjCmd(
|
||||
value_i++;
|
||||
break;
|
||||
|
||||
case RangeKeywordArg:
|
||||
case RangeKeywordArg:
|
||||
arg_key += RangeKeywordArg;
|
||||
allowedArgs = NumericArg; /* after keyword always numeric only */
|
||||
values[value_i] = keyword; /* SequenceOperators */
|
||||
value_i++;
|
||||
break;
|
||||
|
||||
default: /* Error state */
|
||||
default: /* Error state */
|
||||
status = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
@@ -4278,10 +4128,8 @@ Tcl_LseqObjCmd(
|
||||
case LSEQ_BY:
|
||||
/* Error case */
|
||||
goto syntax;
|
||||
break;
|
||||
default:
|
||||
goto syntax;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4299,7 +4147,6 @@ Tcl_LseqObjCmd(
|
||||
case LSEQ_COUNT:
|
||||
default:
|
||||
goto syntax;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4314,7 +4161,6 @@ Tcl_LseqObjCmd(
|
||||
break;
|
||||
default:
|
||||
goto syntax;
|
||||
break;
|
||||
}
|
||||
opmode = (SequenceOperators)values[1];
|
||||
switch (opmode) {
|
||||
@@ -4329,16 +4175,14 @@ Tcl_LseqObjCmd(
|
||||
break;
|
||||
default:
|
||||
goto syntax;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* All other argument errors */
|
||||
default:
|
||||
syntax:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??");
|
||||
goto done;
|
||||
break;
|
||||
syntax:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Count needs to be integer, so try to convert if possible */
|
||||
@@ -4367,7 +4211,7 @@ Tcl_LseqObjCmd(
|
||||
* Success! Now lets create the series object.
|
||||
*/
|
||||
arithSeriesPtr = TclNewArithSeriesObj(interp,
|
||||
useDoubles, start, end, step, elementCount);
|
||||
useDoubles, start, end, step, elementCount);
|
||||
|
||||
status = TCL_ERROR;
|
||||
if (arithSeriesPtr) {
|
||||
@@ -4375,7 +4219,7 @@ Tcl_LseqObjCmd(
|
||||
Tcl_SetObjResult(interp, arithSeriesPtr);
|
||||
}
|
||||
|
||||
done:
|
||||
done:
|
||||
// Free number arguments.
|
||||
while (--value_i>=0) {
|
||||
if (numValues[value_i]) {
|
||||
@@ -4390,8 +4234,8 @@ Tcl_LseqObjCmd(
|
||||
}
|
||||
|
||||
/* Undef constants */
|
||||
#undef zero
|
||||
#undef one
|
||||
#undef zero
|
||||
#undef one
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -4452,13 +4296,13 @@ Tcl_LsetObjCmd(
|
||||
} else {
|
||||
if (TclObjTypeHasProc(listPtr, setElementProc)) {
|
||||
finalValuePtr = TclObjTypeSetElement(interp, listPtr,
|
||||
objc-3, objv+2, objv[objc-1]);
|
||||
objc-3, objv+2, objv[objc-1]);
|
||||
if (finalValuePtr) {
|
||||
Tcl_IncrRefCount(finalValuePtr);
|
||||
}
|
||||
} else {
|
||||
finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
|
||||
objv[objc-1]);
|
||||
objv[objc-1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4684,6 +4528,8 @@ Tcl_LsortObjCmd(
|
||||
group = 1;
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (nocase && (sortInfo.sortMode == SORTMODE_ASCII)) {
|
||||
|
||||
+158
-20
@@ -21,6 +21,7 @@
|
||||
#include "tclRegexp.h"
|
||||
#include "tclStringTrim.h"
|
||||
#include "tclTomMath.h"
|
||||
#include "../utf8proc/utf8proc.h"
|
||||
|
||||
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
|
||||
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
|
||||
@@ -132,7 +133,8 @@ Tcl_RegexpObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Size offset, stringLength, matchLength, cflags, eflags;
|
||||
int i, indices, match, about, all, doinline, numMatchesSaved;
|
||||
Tcl_Size i;
|
||||
int indices, match, about, all, doinline, numMatchesSaved;
|
||||
Tcl_RegExp regExpr;
|
||||
Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL;
|
||||
Tcl_RegExpInfo info;
|
||||
@@ -211,6 +213,8 @@ Tcl_RegexpObjCmd(
|
||||
case REGEXP_LAST:
|
||||
i++;
|
||||
goto endOfForLoop;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,7 +379,7 @@ Tcl_RegexpObjCmd(
|
||||
* area. (Scriptics Bug 4391/SF Bug #219232)
|
||||
*/
|
||||
|
||||
if (i <= (int)info.nsubs && info.matches[i].start >= 0) {
|
||||
if (i <= info.nsubs && info.matches[i].start >= 0) {
|
||||
start = offset + info.matches[i].start;
|
||||
end = offset + info.matches[i].end;
|
||||
|
||||
@@ -397,7 +401,7 @@ Tcl_RegexpObjCmd(
|
||||
|
||||
newPtr = Tcl_NewListObj(2, objs);
|
||||
} else {
|
||||
if ((i <= (int)info.nsubs) && (info.matches[i].end > 0)) {
|
||||
if ((i <= info.nsubs) && (info.matches[i].end > 0)) {
|
||||
newPtr = Tcl_GetRange(objPtr,
|
||||
offset + info.matches[i].start,
|
||||
offset + info.matches[i].end - 1);
|
||||
@@ -566,6 +570,8 @@ Tcl_RegsubObjCmd(
|
||||
case REGSUB_LAST:
|
||||
idx++;
|
||||
goto endOfForLoop;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1319,13 +1325,20 @@ StringFirstCmd(
|
||||
}
|
||||
|
||||
if (objc == 4) {
|
||||
Tcl_Size end = Tcl_GetCharLength(objv[2]) - 1;
|
||||
Tcl_Size end = Tcl_AttemptGetCharLength(objv[2]) - 1;
|
||||
if (end == -1) {
|
||||
return TclCannotAllocateError(interp, objv[2]);
|
||||
}
|
||||
|
||||
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &start)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, TclStringFirst(objv[1], objv[2], start));
|
||||
Tcl_Obj *objPtr = TclStringFirst(objv[1], objv[2], start);
|
||||
if (!objPtr) {
|
||||
return TclCannotAllocateError(interp, objPtr);
|
||||
}
|
||||
Tcl_SetObjResult(interp, objPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -1580,6 +1593,8 @@ StringIsCmd(
|
||||
}
|
||||
failVarObj = objv[++i];
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1877,6 +1892,8 @@ StringIsCmd(
|
||||
case STR_IS_XDIGIT:
|
||||
chcomp = UniCharIsHexDigit;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (chcomp != NULL) {
|
||||
@@ -1904,7 +1921,7 @@ StringIsCmd(
|
||||
* valid fail index (>= 0).
|
||||
*/
|
||||
|
||||
str_is_done:
|
||||
str_is_done:
|
||||
if ((result == 0) && (failVarObj != NULL)) {
|
||||
TclNewIndexObj(objPtr, failat);
|
||||
if (Tcl_ObjSetVar2(interp, failVarObj, NULL, objPtr, TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
@@ -2040,8 +2057,8 @@ StringMapCmd(
|
||||
* The charMap must be an even number of key/value items.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("char map list unbalanced", -1));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"char map list unbalanced", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "MAP",
|
||||
"UNBALANCED", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
@@ -2293,7 +2310,11 @@ StringRangeCmd(
|
||||
* 'end' refers to the last character, not one past it.
|
||||
*/
|
||||
|
||||
end = Tcl_GetCharLength(objv[1]) - 1;
|
||||
end = Tcl_AttemptGetCharLength(objv[1]);
|
||||
if (end < 0) {
|
||||
return TclCannotAllocateError(interp, objv[1]);
|
||||
}
|
||||
end--;
|
||||
|
||||
if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK ||
|
||||
TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK) {
|
||||
@@ -2469,7 +2490,11 @@ StringRevCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, TclStringReverse(objv[1], TCL_STRING_IN_PLACE));
|
||||
Tcl_Obj *objPtr = TclStringReverse(objv[1], TCL_STRING_IN_PLACE);
|
||||
if (!objPtr) {
|
||||
return TclCannotAllocateError(interp, objv[1]);
|
||||
}
|
||||
Tcl_SetObjResult(interp, objPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2681,6 +2706,10 @@ StringEqualCmd(
|
||||
|
||||
objv += objc-2;
|
||||
match = TclStringCmp(objv[0], objv[1], 1, nocase, reqlength);
|
||||
if (match == INT_MIN) {
|
||||
Tcl_AppendResult(interp, "memory allocation error", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1));
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -2726,6 +2755,10 @@ StringCmpCmd(
|
||||
|
||||
objv += objc-2;
|
||||
match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength);
|
||||
if (match == INT_MIN) {
|
||||
Tcl_AppendResult(interp, "memory allocation error", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(match));
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -3337,12 +3370,18 @@ TclSubstOptions(
|
||||
int *flagPtr)
|
||||
{
|
||||
static const char *const substOptions[] = {
|
||||
"-backslashes", "-commands", "-variables",
|
||||
"-nobackslashes", "-nocommands", "-novariables", NULL
|
||||
};
|
||||
static const int optionFlags[] = {
|
||||
TCL_SUBST_BACKSLASHES, TCL_SUBST_COMMANDS, TCL_SUBST_VARIABLES
|
||||
TCL_SUBST_BACKSLASHES, /* -backslashes */
|
||||
TCL_SUBST_COMMANDS, /* -commands */
|
||||
TCL_SUBST_VARIABLES, /* -variables */
|
||||
TCL_SUBST_BACKSLASHES << 16, /* -nobackslashes */
|
||||
TCL_SUBST_COMMANDS << 16, /* -nocommands */
|
||||
TCL_SUBST_VARIABLES << 16 /* -novariables */
|
||||
};
|
||||
int flags = TCL_SUBST_ALL;
|
||||
int flags = numOpts ? 0 : TCL_SUBST_ALL;
|
||||
|
||||
for (Tcl_Size i = 0; i < numOpts; i++) {
|
||||
int optionIndex;
|
||||
@@ -3351,7 +3390,18 @@ TclSubstOptions(
|
||||
&optionIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
flags &= ~optionFlags[optionIndex];
|
||||
flags |= optionFlags[optionIndex];
|
||||
}
|
||||
if (flags >> 16) { /* negative options specified */
|
||||
if (flags & 0xFFFF) { /* positive options specified too */
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"cannot combine positive and negative options", -1));
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/* mask default flags using negative options */
|
||||
flags = TCL_SUBST_ALL & ~(flags >> 16);
|
||||
}
|
||||
*flagPtr = flags;
|
||||
return TCL_OK;
|
||||
@@ -3378,6 +3428,7 @@ TclNRSubstObjCmd(
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"?-backslashes? ?-commands? ?-variables? "
|
||||
"?-nobackslashes? ?-nocommands? ?-novariables? string");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -4186,6 +4237,8 @@ Tcl_TimeRateObjCmd(
|
||||
break;
|
||||
case TMRT_LAST:
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4271,7 +4324,7 @@ Tcl_TimeRateObjCmd(
|
||||
maxms = -1000;
|
||||
do {
|
||||
lastMeasureOverhead = measureOverhead;
|
||||
TclNewIntObj(clobjv[i], (int) maxms);
|
||||
TclNewIntObj(clobjv[i], maxms);
|
||||
Tcl_IncrRefCount(clobjv[i]);
|
||||
result = Tcl_TimeRateObjCmd(NULL, interp, i + 1, clobjv);
|
||||
Tcl_DecrRefCount(clobjv[i]);
|
||||
@@ -4410,7 +4463,7 @@ Tcl_TimeRateObjCmd(
|
||||
*/
|
||||
threshold = 1;
|
||||
maxcnt = 0;
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
case TCL_CONTINUE:
|
||||
result = TCL_OK;
|
||||
break;
|
||||
@@ -4499,7 +4552,8 @@ Tcl_TimeRateObjCmd(
|
||||
lastIterTm = avgIterTm;
|
||||
}
|
||||
estIterTm *= lastIterTm;
|
||||
last = middle; lastCount = count;
|
||||
last = middle;
|
||||
lastCount = count;
|
||||
|
||||
/*
|
||||
* Calculate next threshold to check.
|
||||
@@ -4507,10 +4561,10 @@ Tcl_TimeRateObjCmd(
|
||||
* considering last known iteration growth factor.
|
||||
*/
|
||||
threshold = (Tcl_WideUInt)(stop - middle) * TR_SCALE;
|
||||
/*
|
||||
* Estimated count of iteration til the end of execution.
|
||||
* Thereby 2.5% longer execution time would be OK.
|
||||
*/
|
||||
/*
|
||||
* Estimated count of iteration til the end of execution.
|
||||
* Thereby 2.5% longer execution time would be OK.
|
||||
*/
|
||||
if (threshold / estIterTm < 0.975) {
|
||||
/* estimated time for next iteration is too large */
|
||||
break;
|
||||
@@ -4836,6 +4890,8 @@ TclNRTryObjCmd(
|
||||
haveHandlers = 1;
|
||||
i += 3;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (bodyShared) {
|
||||
@@ -5371,6 +5427,88 @@ TclListLines(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TclUnicodeNormalizeCmd --
|
||||
*
|
||||
* This procedure implements the "unicode tonfc|tonfd|tonfkc|tonfkd"
|
||||
* commands. See the user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Stores the normalized string in the interpreter result.
|
||||
*/
|
||||
static int
|
||||
TclUnicodeNormalizeCmd(
|
||||
void *clientData, /* TCL_{NFC,NFD,NFKC,NFKD} */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
static const char *optNames[] = {"-profile", NULL};
|
||||
enum { OPT_PROFILE } opt;
|
||||
int profile = TCL_ENCODING_PROFILE_STRICT;
|
||||
|
||||
if (objc == 4) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], optNames, "option", 0, &opt) !=
|
||||
TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
const char *s = Tcl_GetString(objv[2]);
|
||||
if (!strcmp(s, "replace")) {
|
||||
profile = TCL_ENCODING_PROFILE_REPLACE;
|
||||
} else if (!strcmp(s, "strict")) {
|
||||
profile = TCL_ENCODING_PROFILE_STRICT;
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"Invalid value \"%s\" supplied for option \"-profile\". "
|
||||
"Must be \"strict\" or \"replace\".", s));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-profile PROFILE? STRING");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_DString ds;
|
||||
if (Tcl_UtfToNormalizedDString(interp, Tcl_GetString(objv[objc - 1]),
|
||||
TCL_INDEX_NONE, (Tcl_UnicodeNormalizationForm)PTR2INT(clientData), profile,
|
||||
&ds) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_DStringResult(interp, &ds);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* TclInitUnicodeCmd --
|
||||
*
|
||||
* This procedure creates the "unicode" Tcl ensemble command. See user
|
||||
* documentation for details on implemented commands.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Stores the result in the interpreter result.
|
||||
*/
|
||||
Tcl_Command
|
||||
TclInitUnicodeCmd(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
static const EnsembleImplMap unicodeImplMap[] = {
|
||||
{"tonfc", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFC, 0},
|
||||
{"tonfd", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFD, 0},
|
||||
{"tonfkc", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFKC, 0},
|
||||
{"tonfkd", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFKD, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
return TclMakeEnsemble(interp, "unicode", unicodeImplMap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
+799
-1051
File diff suppressed because it is too large
Load Diff
+1015
-483
File diff suppressed because it is too large
Load Diff
+1960
-1271
File diff suppressed because it is too large
Load Diff
+175
-184
@@ -61,11 +61,11 @@ typedef struct {
|
||||
*/
|
||||
|
||||
enum OperandTypes {
|
||||
OT_LITERAL = -3, /* Operand is a literal in the literal list */
|
||||
OT_TOKENS = -2, /* Operand is sequence of Tcl_Tokens */
|
||||
OT_EMPTY = -1 /* "Operand" is an empty string. This is a special
|
||||
* case used only to represent the EMPTY lexeme. See
|
||||
* below. */
|
||||
OT_LITERAL = -3, /* Operand is a literal in the literal list */
|
||||
OT_TOKENS = -2, /* Operand is sequence of Tcl_Tokens */
|
||||
OT_EMPTY = -1 /* "Operand" is an empty string. This is a
|
||||
* special case used only to represent the
|
||||
* EMPTY lexeme. See below. */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -106,9 +106,9 @@ enum OperandTypes {
|
||||
*/
|
||||
|
||||
enum Marks {
|
||||
MARK_LEFT, /* Next step of traversal is to visit left subtree */
|
||||
MARK_RIGHT, /* Next step of traversal is to visit right subtree */
|
||||
MARK_PARENT /* Next step of traversal is to return to parent */
|
||||
MARK_LEFT, /* Next step of traversal is to visit left subtree */
|
||||
MARK_RIGHT, /* Next step of traversal is to visit right subtree */
|
||||
MARK_PARENT /* Next step of traversal is to return to parent */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -292,24 +292,24 @@ enum LexemeCodes {
|
||||
*/
|
||||
|
||||
enum Precedence {
|
||||
PREC_END = 1, /* END */
|
||||
PREC_START, /* START */
|
||||
PREC_CLOSE_PAREN, /* ")" */
|
||||
PREC_OPEN_PAREN, /* "(" */
|
||||
PREC_COMMA, /* "," */
|
||||
PREC_CONDITIONAL, /* "?", ":" */
|
||||
PREC_OR, /* "||" */
|
||||
PREC_AND, /* "&&" */
|
||||
PREC_BIT_OR, /* "|" */
|
||||
PREC_BIT_XOR, /* "^" */
|
||||
PREC_BIT_AND, /* "&" */
|
||||
PREC_EQUAL, /* "==", "!=", "eq", "ne", "in", "ni" */
|
||||
PREC_COMPARE, /* "<", ">", "<=", ">=" */
|
||||
PREC_SHIFT, /* "<<", ">>" */
|
||||
PREC_ADD, /* "+", "-" */
|
||||
PREC_MULT, /* "*", "/", "%" */
|
||||
PREC_EXPON, /* "**" */
|
||||
PREC_UNARY /* "+", "-", FUNCTION, "!", "~" */
|
||||
PREC_END = 1, /* END */
|
||||
PREC_START, /* START */
|
||||
PREC_CLOSE_PAREN, /* ")" */
|
||||
PREC_OPEN_PAREN, /* "(" */
|
||||
PREC_COMMA, /* "," */
|
||||
PREC_CONDITIONAL, /* "?", ":" */
|
||||
PREC_OR, /* "||" */
|
||||
PREC_AND, /* "&&" */
|
||||
PREC_BIT_OR, /* "|" */
|
||||
PREC_BIT_XOR, /* "^" */
|
||||
PREC_BIT_AND, /* "&" */
|
||||
PREC_EQUAL, /* "==", "!=", "eq", "ne", "in", "ni" */
|
||||
PREC_COMPARE, /* "<", ">", "<=", ">=" */
|
||||
PREC_SHIFT, /* "<<", ">>" */
|
||||
PREC_ADD, /* "+", "-" */
|
||||
PREC_MULT, /* "*", "/", "%" */
|
||||
PREC_EXPON, /* "**" */
|
||||
PREC_UNARY /* "+", "-", FUNCTION, "!", "~" */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -326,49 +326,49 @@ static const unsigned char prec[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
/* Binary operator lexemes */
|
||||
PREC_ADD, /* BINARY_PLUS */
|
||||
PREC_ADD, /* BINARY_MINUS */
|
||||
PREC_COMMA, /* COMMA */
|
||||
PREC_MULT, /* MULT */
|
||||
PREC_MULT, /* DIVIDE */
|
||||
PREC_MULT, /* MOD */
|
||||
PREC_COMPARE, /* LESS */
|
||||
PREC_COMPARE, /* GREATER */
|
||||
PREC_BIT_AND, /* BIT_AND */
|
||||
PREC_BIT_XOR, /* BIT_XOR */
|
||||
PREC_BIT_OR, /* BIT_OR */
|
||||
PREC_CONDITIONAL, /* QUESTION */
|
||||
PREC_CONDITIONAL, /* COLON */
|
||||
PREC_SHIFT, /* LEFT_SHIFT */
|
||||
PREC_SHIFT, /* RIGHT_SHIFT */
|
||||
PREC_COMPARE, /* LEQ */
|
||||
PREC_COMPARE, /* GEQ */
|
||||
PREC_EQUAL, /* EQUAL */
|
||||
PREC_EQUAL, /* NEQ */
|
||||
PREC_AND, /* AND */
|
||||
PREC_OR, /* OR */
|
||||
PREC_EQUAL, /* STREQ */
|
||||
PREC_EQUAL, /* STRNEQ */
|
||||
PREC_EXPON, /* EXPON */
|
||||
PREC_EQUAL, /* IN_LIST */
|
||||
PREC_EQUAL, /* NOT_IN_LIST */
|
||||
PREC_CLOSE_PAREN, /* CLOSE_PAREN */
|
||||
PREC_COMPARE, /* STR_LT */
|
||||
PREC_COMPARE, /* STR_GT */
|
||||
PREC_COMPARE, /* STR_LEQ */
|
||||
PREC_COMPARE, /* STR_GEQ */
|
||||
PREC_END, /* END */
|
||||
PREC_ADD, /* BINARY_PLUS */
|
||||
PREC_ADD, /* BINARY_MINUS */
|
||||
PREC_COMMA, /* COMMA */
|
||||
PREC_MULT, /* MULT */
|
||||
PREC_MULT, /* DIVIDE */
|
||||
PREC_MULT, /* MOD */
|
||||
PREC_COMPARE, /* LESS */
|
||||
PREC_COMPARE, /* GREATER */
|
||||
PREC_BIT_AND, /* BIT_AND */
|
||||
PREC_BIT_XOR, /* BIT_XOR */
|
||||
PREC_BIT_OR, /* BIT_OR */
|
||||
PREC_CONDITIONAL, /* QUESTION */
|
||||
PREC_CONDITIONAL, /* COLON */
|
||||
PREC_SHIFT, /* LEFT_SHIFT */
|
||||
PREC_SHIFT, /* RIGHT_SHIFT */
|
||||
PREC_COMPARE, /* LEQ */
|
||||
PREC_COMPARE, /* GEQ */
|
||||
PREC_EQUAL, /* EQUAL */
|
||||
PREC_EQUAL, /* NEQ */
|
||||
PREC_AND, /* AND */
|
||||
PREC_OR, /* OR */
|
||||
PREC_EQUAL, /* STREQ */
|
||||
PREC_EQUAL, /* STRNEQ */
|
||||
PREC_EXPON, /* EXPON */
|
||||
PREC_EQUAL, /* IN_LIST */
|
||||
PREC_EQUAL, /* NOT_IN_LIST */
|
||||
PREC_CLOSE_PAREN, /* CLOSE_PAREN */
|
||||
PREC_COMPARE, /* STR_LT */
|
||||
PREC_COMPARE, /* STR_GT */
|
||||
PREC_COMPARE, /* STR_LEQ */
|
||||
PREC_COMPARE, /* STR_GEQ */
|
||||
PREC_END, /* END */
|
||||
/* Expansion room for more binary operators */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* Unary operator lexemes */
|
||||
PREC_UNARY, /* UNARY_PLUS */
|
||||
PREC_UNARY, /* UNARY_MINUS */
|
||||
PREC_UNARY, /* FUNCTION */
|
||||
PREC_START, /* START */
|
||||
PREC_OPEN_PAREN, /* OPEN_PAREN */
|
||||
PREC_UNARY, /* NOT*/
|
||||
PREC_UNARY, /* BIT_NOT*/
|
||||
PREC_UNARY, /* UNARY_PLUS */
|
||||
PREC_UNARY, /* UNARY_MINUS */
|
||||
PREC_UNARY, /* FUNCTION */
|
||||
PREC_START, /* START */
|
||||
PREC_OPEN_PAREN, /* OPEN_PAREN */
|
||||
PREC_UNARY, /* NOT*/
|
||||
PREC_UNARY, /* BIT_NOT*/
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -383,49 +383,49 @@ static const unsigned char instruction[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
/* Binary operator lexemes */
|
||||
INST_ADD, /* BINARY_PLUS */
|
||||
INST_SUB, /* BINARY_MINUS */
|
||||
0, /* COMMA */
|
||||
INST_MULT, /* MULT */
|
||||
INST_DIV, /* DIVIDE */
|
||||
INST_MOD, /* MOD */
|
||||
INST_LT, /* LESS */
|
||||
INST_GT, /* GREATER */
|
||||
INST_BITAND, /* BIT_AND */
|
||||
INST_BITXOR, /* BIT_XOR */
|
||||
INST_BITOR, /* BIT_OR */
|
||||
0, /* QUESTION */
|
||||
0, /* COLON */
|
||||
INST_LSHIFT, /* LEFT_SHIFT */
|
||||
INST_RSHIFT, /* RIGHT_SHIFT */
|
||||
INST_LE, /* LEQ */
|
||||
INST_GE, /* GEQ */
|
||||
INST_EQ, /* EQUAL */
|
||||
INST_NEQ, /* NEQ */
|
||||
0, /* AND */
|
||||
0, /* OR */
|
||||
INST_STR_EQ, /* STREQ */
|
||||
INST_STR_NEQ, /* STRNEQ */
|
||||
INST_EXPON, /* EXPON */
|
||||
INST_LIST_IN, /* IN_LIST */
|
||||
INST_LIST_NOT_IN, /* NOT_IN_LIST */
|
||||
0, /* CLOSE_PAREN */
|
||||
INST_STR_LT, /* STR_LT */
|
||||
INST_STR_GT, /* STR_GT */
|
||||
INST_STR_LE, /* STR_LEQ */
|
||||
INST_STR_GE, /* STR_GEQ */
|
||||
0, /* END */
|
||||
INST_ADD, /* BINARY_PLUS */
|
||||
INST_SUB, /* BINARY_MINUS */
|
||||
0, /* COMMA */
|
||||
INST_MULT, /* MULT */
|
||||
INST_DIV, /* DIVIDE */
|
||||
INST_MOD, /* MOD */
|
||||
INST_LT, /* LESS */
|
||||
INST_GT, /* GREATER */
|
||||
INST_BITAND, /* BIT_AND */
|
||||
INST_BITXOR, /* BIT_XOR */
|
||||
INST_BITOR, /* BIT_OR */
|
||||
0, /* QUESTION */
|
||||
0, /* COLON */
|
||||
INST_LSHIFT, /* LEFT_SHIFT */
|
||||
INST_RSHIFT, /* RIGHT_SHIFT */
|
||||
INST_LE, /* LEQ */
|
||||
INST_GE, /* GEQ */
|
||||
INST_EQ, /* EQUAL */
|
||||
INST_NEQ, /* NEQ */
|
||||
0, /* AND */
|
||||
0, /* OR */
|
||||
INST_STR_EQ, /* STREQ */
|
||||
INST_STR_NEQ, /* STRNEQ */
|
||||
INST_EXPON, /* EXPON */
|
||||
INST_LIST_IN, /* IN_LIST */
|
||||
INST_LIST_NOT_IN, /* NOT_IN_LIST */
|
||||
0, /* CLOSE_PAREN */
|
||||
INST_STR_LT, /* STR_LT */
|
||||
INST_STR_GT, /* STR_GT */
|
||||
INST_STR_LE, /* STR_LEQ */
|
||||
INST_STR_GE, /* STR_GEQ */
|
||||
0, /* END */
|
||||
/* Expansion room for more binary operators */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* Unary operator lexemes */
|
||||
INST_UPLUS, /* UNARY_PLUS */
|
||||
INST_UMINUS, /* UNARY_MINUS */
|
||||
0, /* FUNCTION */
|
||||
0, /* START */
|
||||
0, /* OPEN_PAREN */
|
||||
INST_LNOT, /* NOT*/
|
||||
INST_BITNOT, /* BIT_NOT*/
|
||||
INST_UPLUS, /* UNARY_PLUS */
|
||||
INST_UMINUS, /* UNARY_MINUS */
|
||||
0, /* FUNCTION */
|
||||
0, /* START */
|
||||
0, /* OPEN_PAREN */
|
||||
INST_LNOT, /* NOT*/
|
||||
INST_BITNOT, /* BIT_NOT*/
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -721,7 +721,7 @@ ParseExpr(
|
||||
* is a legal literal boolean value, we accept that as well.
|
||||
*/
|
||||
|
||||
if (start[scanned+TclParseAllWhiteSpace(
|
||||
if (literal && start[scanned+TclParseAllWhiteSpace(
|
||||
start+scanned, numBytes-scanned)] == '(') {
|
||||
lexeme = FUNCTION;
|
||||
|
||||
@@ -733,7 +733,7 @@ ParseExpr(
|
||||
*/
|
||||
|
||||
Tcl_ListObjAppendElement(NULL, funcList, literal);
|
||||
} else if (Tcl_GetBooleanFromObj(NULL,literal,&b) == TCL_OK) {
|
||||
} else if (literal && Tcl_GetBooleanFromObj(NULL,literal,&b) == TCL_OK) {
|
||||
lexeme = BOOL_LIT;
|
||||
} else {
|
||||
/*
|
||||
@@ -748,7 +748,7 @@ ParseExpr(
|
||||
start + scanned2, numBytes - scanned2, &lexeme,
|
||||
NULL);
|
||||
} while (lexeme == COMMENT);
|
||||
if (lexeme == OPEN_PAREN) {
|
||||
if (literal && lexeme == OPEN_PAREN) {
|
||||
/*
|
||||
* Actually a function call, but with obscuring
|
||||
* comments. Skip to the start of the parentheses.
|
||||
@@ -762,7 +762,9 @@ ParseExpr(
|
||||
break;
|
||||
}
|
||||
|
||||
Tcl_DecrRefCount(literal);
|
||||
if (literal) {
|
||||
Tcl_DecrRefCount(literal);
|
||||
}
|
||||
msg = Tcl_ObjPrintf("invalid bareword \"%.*s%s\"",
|
||||
(int)((scanned < limit) ? scanned : limit - 3), start,
|
||||
(scanned < limit) ? "" : "...");
|
||||
@@ -785,14 +787,16 @@ ParseExpr(
|
||||
switch (start[1]) {
|
||||
case 'b':
|
||||
Tcl_AppendToObj(post,
|
||||
" (invalid binary number?)", -1);
|
||||
" (invalid binary number?)",
|
||||
TCL_AUTO_LENGTH);
|
||||
parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
|
||||
errCode = "BADNUMBER";
|
||||
subErrCode = "BINARY";
|
||||
break;
|
||||
case 'o':
|
||||
Tcl_AppendToObj(post,
|
||||
" (invalid octal number?)", -1);
|
||||
" (invalid octal number?)",
|
||||
TCL_AUTO_LENGTH);
|
||||
parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
|
||||
errCode = "BADNUMBER";
|
||||
subErrCode = "OCTAL";
|
||||
@@ -800,7 +804,8 @@ ParseExpr(
|
||||
default:
|
||||
if (isdigit(UCHAR(start[1]))) {
|
||||
Tcl_AppendToObj(post,
|
||||
" (invalid octal number?)", -1);
|
||||
" (invalid octal number?)",
|
||||
TCL_AUTO_LENGTH);
|
||||
parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
|
||||
errCode = "BADNUMBER";
|
||||
subErrCode = "OCTAL";
|
||||
@@ -1449,7 +1454,7 @@ ParseExpr(
|
||||
*/
|
||||
|
||||
if (post != NULL) {
|
||||
Tcl_AppendToObj(msg, ";\n", -1);
|
||||
Tcl_AppendToObj(msg, ";\n", TCL_AUTO_LENGTH);
|
||||
Tcl_AppendObjToObj(msg, post);
|
||||
Tcl_DecrRefCount(post);
|
||||
}
|
||||
@@ -1793,7 +1798,7 @@ ConvertTreeToTokens(
|
||||
*/
|
||||
|
||||
subExprTokenPtr->numComponents =
|
||||
((int)parsePtr->numTokens - subExprTokenIdx) - 1;
|
||||
(parsePtr->numTokens - subExprTokenIdx) - 1;
|
||||
|
||||
/*
|
||||
* Finally, as we return up the tree to our parent, pop the
|
||||
@@ -1856,10 +1861,10 @@ Tcl_ParseExpr(
|
||||
{
|
||||
int code;
|
||||
OpNode *opTree = NULL; /* Will point to the tree of operators. */
|
||||
Tcl_Obj *litList; /* List to hold the literals. */
|
||||
Tcl_Obj *funcList; /* List to hold the functon names. */
|
||||
Tcl_Parse *exprParsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse));
|
||||
/* Holds the Tcl_Tokens of substitutions. */
|
||||
Tcl_Obj *litList; /* List to hold the literals. */
|
||||
Tcl_Obj *funcList; /* List to hold the functon names. */
|
||||
Tcl_Parse *exprParsePtr = (Tcl_Parse *)TclStackAlloc(interp,
|
||||
sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions. */
|
||||
|
||||
TclNewObj(litList);
|
||||
TclNewObj(funcList);
|
||||
@@ -2082,7 +2087,10 @@ ParseLexeme(
|
||||
number:
|
||||
*lexemePtr = NUMBER;
|
||||
if (literalPtr) {
|
||||
TclInitStringRep(literal, start, end-start);
|
||||
if(!TclAttemptInitStringRep(literal, start, end-start)) {
|
||||
Tcl_DecrRefCount(literal);
|
||||
literal = NULL;
|
||||
}
|
||||
*literalPtr = literal;
|
||||
} else {
|
||||
Tcl_DecrRefCount(literal);
|
||||
@@ -2268,7 +2276,7 @@ ExecConstantExprTree(
|
||||
TclInitCompileEnv(interp, envPtr, NULL, 0, NULL, 0);
|
||||
CompileExprTree(interp, nodes, index, litObjvPtr, NULL, NULL, envPtr,
|
||||
0 /* optimize */);
|
||||
TclEmitOpcode(INST_DONE, envPtr);
|
||||
OP( DONE);
|
||||
byteCodePtr = TclInitByteCode(envPtr);
|
||||
TclFreeCompileEnv(envPtr);
|
||||
TclStackFree(interp, envPtr);
|
||||
@@ -2333,19 +2341,12 @@ CompileExprTree(
|
||||
|
||||
switch (nodePtr->lexeme) {
|
||||
case FUNCTION: {
|
||||
Tcl_DString cmdName;
|
||||
const char *p;
|
||||
Tcl_Size length;
|
||||
Tcl_Obj *cmdName;
|
||||
|
||||
Tcl_DStringInit(&cmdName);
|
||||
TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::");
|
||||
p = TclGetStringFromObj(*funcObjv, &length);
|
||||
TclNewLiteralStringObj(cmdName, "tcl::mathfunc::");
|
||||
Tcl_AppendObjToObj(cmdName, *funcObjv);
|
||||
funcObjv++;
|
||||
Tcl_DStringAppend(&cmdName, p, length);
|
||||
TclEmitPush(TclRegisterLiteral(envPtr,
|
||||
Tcl_DStringValue(&cmdName),
|
||||
Tcl_DStringLength(&cmdName), LITERAL_CMD_NAME), envPtr);
|
||||
Tcl_DStringFree(&cmdName);
|
||||
PUSH_OBJ_FLAGS(cmdName, LITERAL_CMD_NAME);
|
||||
|
||||
/*
|
||||
* Start a count of the number of words in this function
|
||||
@@ -2370,7 +2371,7 @@ CompileExprTree(
|
||||
jumpPtr = newJump;
|
||||
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
|
||||
&jumpPtr->jump);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
STKDELTA(-1);
|
||||
if (convert) {
|
||||
jumpPtr->jump.jumpType = TCL_TRUE_JUMP;
|
||||
}
|
||||
@@ -2386,13 +2387,14 @@ CompileExprTree(
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Tcl_Size pc1, pc2, target;
|
||||
Tcl_Size target;
|
||||
Tcl_BytecodeLabel pc1, pc2;
|
||||
|
||||
switch (nodePtr->lexeme) {
|
||||
case START:
|
||||
case QUESTION:
|
||||
if (convert && (nodePtr == rootPtr)) {
|
||||
TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
|
||||
OP( TRY_CVT_TO_NUMERIC);
|
||||
}
|
||||
break;
|
||||
case OPEN_PAREN:
|
||||
@@ -2405,11 +2407,7 @@ CompileExprTree(
|
||||
* command with the correct number of arguments.
|
||||
*/
|
||||
|
||||
if (numWords < 255) {
|
||||
TclEmitInvoke(envPtr, INST_INVOKE_STK1, numWords);
|
||||
} else {
|
||||
TclEmitInvoke(envPtr, INST_INVOKE_STK4, numWords);
|
||||
}
|
||||
INVOKE4( INVOKE_STK, numWords);
|
||||
|
||||
/*
|
||||
* Restore any saved numWords value.
|
||||
@@ -2431,15 +2429,13 @@ CompileExprTree(
|
||||
jumpPtr->jump.jumpType = TCL_UNCONDITIONAL_JUMP;
|
||||
convert = 1;
|
||||
}
|
||||
target = jumpPtr->jump.codeOffset + 2;
|
||||
if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) {
|
||||
target += 3;
|
||||
}
|
||||
target = jumpPtr->jump.codeOffset + 5;
|
||||
TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump);
|
||||
freePtr = jumpPtr;
|
||||
jumpPtr = jumpPtr->next;
|
||||
TclStackFree(interp, freePtr);
|
||||
TclFixupForwardJump(envPtr, &jumpPtr->jump,
|
||||
target - jumpPtr->jump.codeOffset, 127);
|
||||
target - jumpPtr->jump.codeOffset);
|
||||
|
||||
freePtr = jumpPtr;
|
||||
jumpPtr = jumpPtr->next;
|
||||
@@ -2448,23 +2444,18 @@ CompileExprTree(
|
||||
case AND:
|
||||
case OR:
|
||||
CLANG_ASSERT(jumpPtr);
|
||||
pc1 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1((nodePtr->lexeme == AND) ? INST_JUMP_FALSE1
|
||||
: INST_JUMP_TRUE1, 0, envPtr);
|
||||
TclEmitPush(TclRegisterLiteral(envPtr,
|
||||
(nodePtr->lexeme == AND) ? "1" : "0", 1, 0), envPtr);
|
||||
pc2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1(INST_JUMP1, 0, envPtr);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc1,
|
||||
envPtr->codeStart + pc1 + 1);
|
||||
if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) {
|
||||
pc2 += 3;
|
||||
if (nodePtr->lexeme == AND) {
|
||||
FWDJUMP( JUMP_FALSE, pc1);
|
||||
} else {
|
||||
FWDJUMP( JUMP_TRUE, pc1);
|
||||
}
|
||||
TclEmitPush(TclRegisterLiteral(envPtr,
|
||||
(nodePtr->lexeme == AND) ? "0" : "1", 1, 0), envPtr);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc2,
|
||||
envPtr->codeStart + pc2 + 1);
|
||||
PUSH_STRING( (nodePtr->lexeme == AND) ? "1" : "0");
|
||||
FWDJUMP( JUMP, pc2);
|
||||
STKDELTA(-1);
|
||||
FWDLABEL(pc1);
|
||||
TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump);
|
||||
PUSH_STRING( (nodePtr->lexeme == AND) ? "0" : "1");
|
||||
FWDLABEL(pc2);
|
||||
convert = 0;
|
||||
freePtr = jumpPtr;
|
||||
jumpPtr = jumpPtr->next;
|
||||
@@ -2494,9 +2485,7 @@ CompileExprTree(
|
||||
Tcl_Obj *literal = *litObjv;
|
||||
|
||||
if (optimize) {
|
||||
Tcl_Size length;
|
||||
const char *bytes = TclGetStringFromObj(literal, &length);
|
||||
int idx = TclRegisterLiteral(envPtr, bytes, length, 0);
|
||||
int idx = PUSH_OBJ_FLAGS(literal, 0);
|
||||
Tcl_Obj *objPtr = TclFetchLiteral(envPtr, idx);
|
||||
|
||||
if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
|
||||
@@ -2517,7 +2506,6 @@ CompileExprTree(
|
||||
objPtr->internalRep = literal->internalRep;
|
||||
literal->typePtr = NULL;
|
||||
}
|
||||
TclEmitPush(idx, envPtr);
|
||||
} else {
|
||||
/*
|
||||
* When optimize==0, we know the expression is a one-off and
|
||||
@@ -2528,7 +2516,7 @@ CompileExprTree(
|
||||
* that preserves internalreps.
|
||||
*/
|
||||
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, literal, NULL), envPtr);
|
||||
PUSH_OBJ( literal);
|
||||
}
|
||||
(*litObjvPtr)++;
|
||||
break;
|
||||
@@ -2672,7 +2660,8 @@ TclSortingOpCmd(
|
||||
TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
|
||||
Tcl_Obj **litObjv = (Tcl_Obj **)TclStackAlloc(interp,
|
||||
2 * (objc-2) * sizeof(Tcl_Obj *));
|
||||
OpNode *nodes = (OpNode *)TclStackAlloc(interp, 2 * (objc-2) * sizeof(OpNode));
|
||||
OpNode *nodes = (OpNode *)TclStackAlloc(interp,
|
||||
2 * (objc-2) * sizeof(OpNode));
|
||||
unsigned char lexeme;
|
||||
int i, lastAnd = 1;
|
||||
Tcl_Obj *const *litObjPtrPtr = litObjv;
|
||||
@@ -2683,29 +2672,30 @@ TclSortingOpCmd(
|
||||
nodes[0].lexeme = START;
|
||||
nodes[0].mark = MARK_RIGHT;
|
||||
for (i=2; i<objc-1; i++) {
|
||||
litObjv[2*(i-1)-1] = objv[i];
|
||||
nodes[2*(i-1)-1].lexeme = lexeme;
|
||||
nodes[2*(i-1)-1].mark = MARK_LEFT;
|
||||
nodes[2*(i-1)-1].left = OT_LITERAL;
|
||||
nodes[2*(i-1)-1].right = OT_LITERAL;
|
||||
int j = 2 * (i - 1);
|
||||
litObjv[j - 1] = objv[i];
|
||||
nodes[j - 1].lexeme = lexeme;
|
||||
nodes[j - 1].mark = MARK_LEFT;
|
||||
nodes[j - 1].left = OT_LITERAL;
|
||||
nodes[j - 1].right = OT_LITERAL;
|
||||
|
||||
litObjv[2*(i-1)] = objv[i];
|
||||
nodes[2*(i-1)].lexeme = AND;
|
||||
nodes[2*(i-1)].mark = MARK_LEFT;
|
||||
nodes[2*(i-1)].left = lastAnd;
|
||||
nodes[lastAnd].p.parent = 2*(i-1);
|
||||
litObjv[j] = objv[i];
|
||||
nodes[j].lexeme = AND;
|
||||
nodes[j].mark = MARK_LEFT;
|
||||
nodes[j].left = lastAnd;
|
||||
nodes[lastAnd].p.parent = j;
|
||||
|
||||
nodes[2*(i-1)].right = 2*(i-1)+1;
|
||||
nodes[2*(i-1)+1].p.parent= 2*(i-1);
|
||||
nodes[j].right = j + 1;
|
||||
nodes[j + 1].p.parent= j;
|
||||
|
||||
lastAnd = 2*(i-1);
|
||||
lastAnd = j;
|
||||
}
|
||||
litObjv[2*(objc-2)-1] = objv[objc-1];
|
||||
litObjv[2 * (objc - 2) - 1] = objv[objc - 1];
|
||||
|
||||
nodes[2*(objc-2)-1].lexeme = lexeme;
|
||||
nodes[2*(objc-2)-1].mark = MARK_LEFT;
|
||||
nodes[2*(objc-2)-1].left = OT_LITERAL;
|
||||
nodes[2*(objc-2)-1].right = OT_LITERAL;
|
||||
nodes[2 * (objc - 2) - 1].lexeme = lexeme;
|
||||
nodes[2 * (objc - 2) - 1].mark = MARK_LEFT;
|
||||
nodes[2 * (objc - 2) - 1].left = OT_LITERAL;
|
||||
nodes[2 * (objc - 2) - 1].right = OT_LITERAL;
|
||||
|
||||
nodes[0].right = lastAnd;
|
||||
nodes[lastAnd].p.parent = 0;
|
||||
@@ -2799,7 +2789,8 @@ TclVariadicOpCmd(
|
||||
return code;
|
||||
} else {
|
||||
Tcl_Obj *const *litObjv = objv + 1;
|
||||
OpNode *nodes = (OpNode *)TclStackAlloc(interp, (objc-1) * sizeof(OpNode));
|
||||
OpNode *nodes = (OpNode *)TclStackAlloc(interp,
|
||||
(objc - 1) * sizeof(OpNode));
|
||||
int i, lastOp = OT_LITERAL;
|
||||
|
||||
nodes[0].lexeme = START;
|
||||
|
||||
+1082
-493
File diff suppressed because it is too large
Load Diff
+809
-306
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -299,8 +299,7 @@ QueryConfigObjCmd(
|
||||
return TCL_OK;
|
||||
|
||||
default:
|
||||
Tcl_Panic("QueryConfigObjCmd: Unknown subcommand to 'pkgconfig'. This can't happen");
|
||||
break;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
+1
-1
@@ -393,7 +393,7 @@ typedef struct ClockScanToken ClockScanToken;
|
||||
typedef int ClockScanTokenProc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok);
|
||||
const ClockScanToken *tok);
|
||||
|
||||
typedef enum _CLCKTOK_TYPE {
|
||||
CTOKT_INT = 1, CTOKT_WIDE, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
|
||||
|
||||
+97
-29
@@ -107,7 +107,10 @@ EXTERN void Tcl_DbIncrRefCount(Tcl_Obj *objPtr, const char *file,
|
||||
/* 21 */
|
||||
EXTERN int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file,
|
||||
int line);
|
||||
/* Slot 22 is reserved */
|
||||
/* 22 */
|
||||
EXTERN char * Tcl_DbGetStringFromObj(Tcl_Obj *objPtr,
|
||||
Tcl_Size *lengthPtr, const char *file,
|
||||
int line);
|
||||
/* 23 */
|
||||
EXTERN Tcl_Obj * Tcl_DbNewByteArrayObj(const unsigned char *bytes,
|
||||
Tcl_Size numBytes, const char *file,
|
||||
@@ -189,7 +192,9 @@ EXTERN Tcl_Obj * Tcl_NewListObj(Tcl_Size objc, Tcl_Obj *const objv[]);
|
||||
EXTERN Tcl_Obj * Tcl_NewObj(void);
|
||||
/* 56 */
|
||||
EXTERN Tcl_Obj * Tcl_NewStringObj(const char *bytes, Tcl_Size length);
|
||||
/* Slot 57 is reserved */
|
||||
/* 57 */
|
||||
EXTERN Tcl_Obj * Tcl_AttemptNewStringObj(const char *bytes,
|
||||
Tcl_Size length);
|
||||
/* 58 */
|
||||
EXTERN unsigned char * Tcl_SetByteArrayLength(Tcl_Obj *objPtr,
|
||||
Tcl_Size numBytes);
|
||||
@@ -199,7 +204,8 @@ EXTERN void Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
|
||||
Tcl_Size numBytes);
|
||||
/* 60 */
|
||||
EXTERN void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue);
|
||||
/* Slot 61 is reserved */
|
||||
/* 61 */
|
||||
EXTERN Tcl_Size Tcl_AttemptGetCharLength(Tcl_Obj *objPtr);
|
||||
/* 62 */
|
||||
EXTERN void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -895,9 +901,13 @@ EXTERN Tcl_Size Tcl_WriteChars(Tcl_Channel chan, const char *src,
|
||||
/* 339 */
|
||||
EXTERN Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr);
|
||||
/* 340 */
|
||||
EXTERN char * Tcl_GetString(Tcl_Obj *objPtr);
|
||||
/* Slot 341 is reserved */
|
||||
/* Slot 342 is reserved */
|
||||
EXTERN char * Tcl_AttemptGetStringFromObj(Tcl_Obj *objPtr,
|
||||
Tcl_Size *lengthPtr);
|
||||
/* 341 */
|
||||
EXTERN char * Tcl_AttemptSetStringObj(Tcl_Obj *objPtr,
|
||||
const char *bytes, Tcl_Size length);
|
||||
/* 342 */
|
||||
EXTERN Tcl_Obj * Tcl_AttemptDuplicateObj(Tcl_Obj *objPtr);
|
||||
/* 343 */
|
||||
EXTERN void Tcl_AlertNotifier(void *clientData);
|
||||
/* 344 */
|
||||
@@ -1094,8 +1104,13 @@ EXTERN void Tcl_ClearChannelHandlers(Tcl_Channel channel);
|
||||
EXTERN int Tcl_IsChannelExisting(const char *channelName);
|
||||
/* Slot 419 is reserved */
|
||||
/* Slot 420 is reserved */
|
||||
/* Slot 421 is reserved */
|
||||
/* Slot 422 is reserved */
|
||||
/* 421 */
|
||||
EXTERN Tcl_HashEntry * Tcl_DbCreateHashEntry(Tcl_HashTable *tablePtr,
|
||||
const void *key, int *newPtr,
|
||||
const char *file, int line);
|
||||
/* 422 */
|
||||
EXTERN Tcl_HashEntry * Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
|
||||
const void *key, int *newPtr);
|
||||
/* 423 */
|
||||
EXTERN void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr,
|
||||
int keyType, const Tcl_HashKeyType *typePtr);
|
||||
@@ -1869,6 +1884,31 @@ EXTERN void Tcl_SetWideUIntObj(Tcl_Obj *objPtr,
|
||||
/* 690 */
|
||||
EXTERN int Tcl_IsEmpty(Tcl_Obj *obj);
|
||||
/* 691 */
|
||||
EXTERN const char * Tcl_GetEncodingNameForUser(Tcl_DString *bufPtr);
|
||||
/* 692 */
|
||||
EXTERN int Tcl_ListObjReverse(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr);
|
||||
/* 693 */
|
||||
EXTERN int Tcl_ListObjRepeat(Tcl_Interp *interp,
|
||||
Tcl_Size repeatCount, Tcl_Size objc,
|
||||
Tcl_Obj *const objv[],
|
||||
Tcl_Obj **resultPtrPtr);
|
||||
/* 694 */
|
||||
EXTERN int Tcl_ListObjRange(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
Tcl_Size start, Tcl_Size end,
|
||||
Tcl_Obj **resultPtrPtr);
|
||||
/* 695 */
|
||||
EXTERN int Tcl_UtfToNormalizedDString(Tcl_Interp *interp,
|
||||
const char *bytes, Tcl_Size length,
|
||||
Tcl_UnicodeNormalizationForm normForm,
|
||||
int profile, Tcl_DString *dsPtr);
|
||||
/* 696 */
|
||||
EXTERN int Tcl_UtfToNormalized(Tcl_Interp *interp,
|
||||
const char *bytes, Tcl_Size length,
|
||||
Tcl_UnicodeNormalizationForm normForm,
|
||||
int profile, char *bufPtr, Tcl_Size bufLen,
|
||||
Tcl_Size *lengthPtr);
|
||||
/* 697 */
|
||||
EXTERN void TclUnusedStubEntry(void);
|
||||
|
||||
typedef struct {
|
||||
@@ -1903,7 +1943,7 @@ typedef struct TclStubs {
|
||||
void (*tcl_DbDecrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 19 */
|
||||
void (*tcl_DbIncrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 20 */
|
||||
int (*tcl_DbIsShared) (Tcl_Obj *objPtr, const char *file, int line); /* 21 */
|
||||
void (*reserved22)(void);
|
||||
char * (*tcl_DbGetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr, const char *file, int line); /* 22 */
|
||||
Tcl_Obj * (*tcl_DbNewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes, const char *file, int line); /* 23 */
|
||||
Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, const char *file, int line); /* 24 */
|
||||
Tcl_Obj * (*tcl_DbNewListObj) (Tcl_Size objc, Tcl_Obj *const *objv, const char *file, int line); /* 25 */
|
||||
@@ -1938,11 +1978,11 @@ typedef struct TclStubs {
|
||||
void (*reserved54)(void);
|
||||
Tcl_Obj * (*tcl_NewObj) (void); /* 55 */
|
||||
Tcl_Obj * (*tcl_NewStringObj) (const char *bytes, Tcl_Size length); /* 56 */
|
||||
void (*reserved57)(void);
|
||||
Tcl_Obj * (*tcl_AttemptNewStringObj) (const char *bytes, Tcl_Size length); /* 57 */
|
||||
unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, Tcl_Size numBytes); /* 58 */
|
||||
void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, const unsigned char *bytes, Tcl_Size numBytes); /* 59 */
|
||||
void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */
|
||||
void (*reserved61)(void);
|
||||
Tcl_Size (*tcl_AttemptGetCharLength) (Tcl_Obj *objPtr); /* 61 */
|
||||
void (*tcl_SetListObj) (Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 62 */
|
||||
void (*reserved63)(void);
|
||||
void (*tcl_SetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 64 */
|
||||
@@ -2221,9 +2261,9 @@ typedef struct TclStubs {
|
||||
Tcl_Size (*tcl_UtfToUpper) (char *src); /* 337 */
|
||||
Tcl_Size (*tcl_WriteChars) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 338 */
|
||||
Tcl_Size (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */
|
||||
char * (*tcl_GetString) (Tcl_Obj *objPtr); /* 340 */
|
||||
void (*reserved341)(void);
|
||||
void (*reserved342)(void);
|
||||
char * (*tcl_AttemptGetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 340 */
|
||||
char * (*tcl_AttemptSetStringObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length); /* 341 */
|
||||
Tcl_Obj * (*tcl_AttemptDuplicateObj) (Tcl_Obj *objPtr); /* 342 */
|
||||
void (*tcl_AlertNotifier) (void *clientData); /* 343 */
|
||||
void (*tcl_ServiceModeHook) (int mode); /* 344 */
|
||||
int (*tcl_UniCharIsAlnum) (int ch); /* 345 */
|
||||
@@ -2302,8 +2342,8 @@ typedef struct TclStubs {
|
||||
int (*tcl_IsChannelExisting) (const char *channelName); /* 418 */
|
||||
void (*reserved419)(void);
|
||||
void (*reserved420)(void);
|
||||
void (*reserved421)(void);
|
||||
void (*reserved422)(void);
|
||||
Tcl_HashEntry * (*tcl_DbCreateHashEntry) (Tcl_HashTable *tablePtr, const void *key, int *newPtr, const char *file, int line); /* 421 */
|
||||
Tcl_HashEntry * (*tcl_CreateHashEntry) (Tcl_HashTable *tablePtr, const void *key, int *newPtr); /* 422 */
|
||||
void (*tcl_InitCustomHashTable) (Tcl_HashTable *tablePtr, int keyType, const Tcl_HashKeyType *typePtr); /* 423 */
|
||||
void (*tcl_InitObjHashTable) (Tcl_HashTable *tablePtr); /* 424 */
|
||||
void * (*tcl_CommandTraceInfo) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *procPtr, void *prevClientData); /* 425 */
|
||||
@@ -2572,7 +2612,13 @@ typedef struct TclStubs {
|
||||
Tcl_Obj * (*tcl_NewWideUIntObj) (Tcl_WideUInt wideValue); /* 688 */
|
||||
void (*tcl_SetWideUIntObj) (Tcl_Obj *objPtr, Tcl_WideUInt uwideValue); /* 689 */
|
||||
int (*tcl_IsEmpty) (Tcl_Obj *obj); /* 690 */
|
||||
void (*tclUnusedStubEntry) (void); /* 691 */
|
||||
const char * (*tcl_GetEncodingNameForUser) (Tcl_DString *bufPtr); /* 691 */
|
||||
int (*tcl_ListObjReverse) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr); /* 692 */
|
||||
int (*tcl_ListObjRepeat) (Tcl_Interp *interp, Tcl_Size repeatCount, Tcl_Size objc, Tcl_Obj *const objv[], Tcl_Obj **resultPtrPtr); /* 693 */
|
||||
int (*tcl_ListObjRange) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size start, Tcl_Size end, Tcl_Obj **resultPtrPtr); /* 694 */
|
||||
int (*tcl_UtfToNormalizedDString) (Tcl_Interp *interp, const char *bytes, Tcl_Size length, Tcl_UnicodeNormalizationForm normForm, int profile, Tcl_DString *dsPtr); /* 695 */
|
||||
int (*tcl_UtfToNormalized) (Tcl_Interp *interp, const char *bytes, Tcl_Size length, Tcl_UnicodeNormalizationForm normForm, int profile, char *bufPtr, Tcl_Size bufLen, Tcl_Size *lengthPtr); /* 696 */
|
||||
void (*tclUnusedStubEntry) (void); /* 697 */
|
||||
} TclStubs;
|
||||
|
||||
extern const TclStubs *tclStubsPtr;
|
||||
@@ -2631,7 +2677,8 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_DbIncrRefCount) /* 20 */
|
||||
#define Tcl_DbIsShared \
|
||||
(tclStubsPtr->tcl_DbIsShared) /* 21 */
|
||||
/* Slot 22 is reserved */
|
||||
#define Tcl_DbGetStringFromObj \
|
||||
(tclStubsPtr->tcl_DbGetStringFromObj) /* 22 */
|
||||
#define Tcl_DbNewByteArrayObj \
|
||||
(tclStubsPtr->tcl_DbNewByteArrayObj) /* 23 */
|
||||
#define Tcl_DbNewDoubleObj \
|
||||
@@ -2692,14 +2739,16 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_NewObj) /* 55 */
|
||||
#define Tcl_NewStringObj \
|
||||
(tclStubsPtr->tcl_NewStringObj) /* 56 */
|
||||
/* Slot 57 is reserved */
|
||||
#define Tcl_AttemptNewStringObj \
|
||||
(tclStubsPtr->tcl_AttemptNewStringObj) /* 57 */
|
||||
#define Tcl_SetByteArrayLength \
|
||||
(tclStubsPtr->tcl_SetByteArrayLength) /* 58 */
|
||||
#define Tcl_SetByteArrayObj \
|
||||
(tclStubsPtr->tcl_SetByteArrayObj) /* 59 */
|
||||
#define Tcl_SetDoubleObj \
|
||||
(tclStubsPtr->tcl_SetDoubleObj) /* 60 */
|
||||
/* Slot 61 is reserved */
|
||||
#define Tcl_AttemptGetCharLength \
|
||||
(tclStubsPtr->tcl_AttemptGetCharLength) /* 61 */
|
||||
#define Tcl_SetListObj \
|
||||
(tclStubsPtr->tcl_SetListObj) /* 62 */
|
||||
/* Slot 63 is reserved */
|
||||
@@ -3215,10 +3264,12 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_WriteChars) /* 338 */
|
||||
#define Tcl_WriteObj \
|
||||
(tclStubsPtr->tcl_WriteObj) /* 339 */
|
||||
#define Tcl_GetString \
|
||||
(tclStubsPtr->tcl_GetString) /* 340 */
|
||||
/* Slot 341 is reserved */
|
||||
/* Slot 342 is reserved */
|
||||
#define Tcl_AttemptGetStringFromObj \
|
||||
(tclStubsPtr->tcl_AttemptGetStringFromObj) /* 340 */
|
||||
#define Tcl_AttemptSetStringObj \
|
||||
(tclStubsPtr->tcl_AttemptSetStringObj) /* 341 */
|
||||
#define Tcl_AttemptDuplicateObj \
|
||||
(tclStubsPtr->tcl_AttemptDuplicateObj) /* 342 */
|
||||
#define Tcl_AlertNotifier \
|
||||
(tclStubsPtr->tcl_AlertNotifier) /* 343 */
|
||||
#define Tcl_ServiceModeHook \
|
||||
@@ -3368,8 +3419,10 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_IsChannelExisting) /* 418 */
|
||||
/* Slot 419 is reserved */
|
||||
/* Slot 420 is reserved */
|
||||
/* Slot 421 is reserved */
|
||||
/* Slot 422 is reserved */
|
||||
#define Tcl_DbCreateHashEntry \
|
||||
(tclStubsPtr->tcl_DbCreateHashEntry) /* 421 */
|
||||
#define Tcl_CreateHashEntry \
|
||||
(tclStubsPtr->tcl_CreateHashEntry) /* 422 */
|
||||
#define Tcl_InitCustomHashTable \
|
||||
(tclStubsPtr->tcl_InitCustomHashTable) /* 423 */
|
||||
#define Tcl_InitObjHashTable \
|
||||
@@ -3903,8 +3956,20 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_SetWideUIntObj) /* 689 */
|
||||
#define Tcl_IsEmpty \
|
||||
(tclStubsPtr->tcl_IsEmpty) /* 690 */
|
||||
#define Tcl_GetEncodingNameForUser \
|
||||
(tclStubsPtr->tcl_GetEncodingNameForUser) /* 691 */
|
||||
#define Tcl_ListObjReverse \
|
||||
(tclStubsPtr->tcl_ListObjReverse) /* 692 */
|
||||
#define Tcl_ListObjRepeat \
|
||||
(tclStubsPtr->tcl_ListObjRepeat) /* 693 */
|
||||
#define Tcl_ListObjRange \
|
||||
(tclStubsPtr->tcl_ListObjRange) /* 694 */
|
||||
#define Tcl_UtfToNormalizedDString \
|
||||
(tclStubsPtr->tcl_UtfToNormalizedDString) /* 695 */
|
||||
#define Tcl_UtfToNormalized \
|
||||
(tclStubsPtr->tcl_UtfToNormalized) /* 696 */
|
||||
#define TclUnusedStubEntry \
|
||||
(tclStubsPtr->tclUnusedStubEntry) /* 691 */
|
||||
(tclStubsPtr->tclUnusedStubEntry) /* 697 */
|
||||
|
||||
#endif /* defined(USE_TCL_STUBS) */
|
||||
|
||||
@@ -4003,10 +4068,10 @@ extern const TclStubs *tclStubsPtr;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#undef Tcl_GetString
|
||||
#undef Tcl_GetUnicode
|
||||
#define Tcl_GetString(objPtr) \
|
||||
Tcl_GetStringFromObj(objPtr, (Tcl_Size *)NULL)
|
||||
#define Tcl_AttemptGetString(objPtr) \
|
||||
Tcl_AttemptGetStringFromObj(objPtr, (Tcl_Size *)NULL)
|
||||
#define Tcl_GetUnicode(objPtr) \
|
||||
Tcl_GetUnicodeFromObj(objPtr, (Tcl_Size *)NULL)
|
||||
#undef Tcl_GetIndexFromObjStruct
|
||||
@@ -4060,6 +4125,9 @@ extern const TclStubs *tclStubsPtr;
|
||||
# undef Tcl_AttemptRealloc
|
||||
# define Tcl_AttemptRealloc(x,y) \
|
||||
(Tcl_AttemptDbCkrealloc((x), (y), __FILE__, __LINE__))
|
||||
# undef Tcl_GetStringFromObj
|
||||
# define Tcl_GetStringFromObj(x,y) \
|
||||
(Tcl_DbGetStringFromObj((x), (y), __FILE__, __LINE__))
|
||||
#endif /* !TCL_MEM_DEBUG */
|
||||
|
||||
#define Tcl_NewLongObj(value) Tcl_NewWideIntObj((long)(value))
|
||||
|
||||
+42
-22
@@ -82,8 +82,8 @@ static const EnsembleImplMap implementationMap[] = {
|
||||
{"lappend", DictLappendCmd, TclCompileDictLappendCmd, NULL, NULL, 0 },
|
||||
{"map", NULL, TclCompileDictMapCmd, DictMapNRCmd, NULL, 0 },
|
||||
{"merge", DictMergeCmd, TclCompileDictMergeCmd, NULL, NULL, 0 },
|
||||
{"remove", DictRemoveCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 },
|
||||
{"replace", DictReplaceCmd, NULL, NULL, NULL, 0 },
|
||||
{"remove", DictRemoveCmd, TclCompileDictRemoveCmd, NULL, NULL, 0 },
|
||||
{"replace", DictReplaceCmd, TclCompileDictReplaceCmd, NULL, NULL, 0 },
|
||||
{"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 },
|
||||
{"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
|
||||
{"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 },
|
||||
@@ -520,7 +520,17 @@ UpdateStringOfDict(
|
||||
if (numElems <= LOCAL_SIZE) {
|
||||
flagPtr = localFlags;
|
||||
} else {
|
||||
flagPtr = (char *)Tcl_Alloc(numElems);
|
||||
flagPtr = (char *)Tcl_AttemptAlloc(numElems);
|
||||
if (!flagPtr) {
|
||||
dictPtr->length = numElems - 1;
|
||||
allocError:
|
||||
/* Allocation error. Just give up. */
|
||||
if (dictPtr->bytes) {
|
||||
Tcl_Free(dictPtr->bytes);
|
||||
dictPtr->bytes = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
|
||||
/*
|
||||
@@ -530,11 +540,19 @@ UpdateStringOfDict(
|
||||
|
||||
flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
|
||||
keyPtr = (Tcl_Obj *)Tcl_GetHashKey(&dict->table, &cPtr->entry);
|
||||
elem = TclGetStringFromObj(keyPtr, &length);
|
||||
elem = TclAttemptGetStringFromObj(keyPtr, &length);
|
||||
if (!elem) {
|
||||
dictPtr->length = keyPtr->length;
|
||||
goto allocError;
|
||||
}
|
||||
bytesNeeded += TclScanElement(elem, length, flagPtr+i);
|
||||
flagPtr[i+1] = TCL_DONT_QUOTE_HASH;
|
||||
valuePtr = (Tcl_Obj *)Tcl_GetHashValue(&cPtr->entry);
|
||||
elem = TclGetStringFromObj(valuePtr, &length);
|
||||
elem = TclAttemptGetStringFromObj(valuePtr, &length);
|
||||
if (!elem) {
|
||||
dictPtr->length = valuePtr->length;
|
||||
goto allocError;
|
||||
}
|
||||
bytesNeeded += TclScanElement(elem, length, flagPtr+i+1);
|
||||
}
|
||||
bytesNeeded += numElems;
|
||||
@@ -544,7 +562,10 @@ UpdateStringOfDict(
|
||||
*/
|
||||
|
||||
dst = Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1);
|
||||
TclOOM(dst, bytesNeeded);
|
||||
if (!dst) {
|
||||
dictPtr->length = bytesNeeded;
|
||||
goto allocError;
|
||||
}
|
||||
for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
|
||||
if (i) {
|
||||
flagPtr[i] |= TCL_DONT_QUOTE_HASH;
|
||||
@@ -1472,7 +1493,7 @@ Tcl_DbNewDictObj(
|
||||
|
||||
TclDbNewObj(dictPtr, file, line);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
dict = (Dict *)Tcl_Alloc(sizeof(Dict));
|
||||
dict = (Dict *)Tcl_DbCkalloc(sizeof(Dict), file, line);
|
||||
InitChainTable(dict);
|
||||
dict->epoch = 1;
|
||||
dict->chain = NULL;
|
||||
@@ -3231,7 +3252,7 @@ DictFilterCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], filters, "filterType",
|
||||
0, &index) != TCL_OK) {
|
||||
0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -3424,7 +3445,7 @@ DictFilterCmd(
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_DictObjDone(&search);
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
case TCL_CONTINUE:
|
||||
result = TCL_OK;
|
||||
break;
|
||||
@@ -3432,6 +3453,7 @@ DictFilterCmd(
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (\"dict filter\" script line %d)",
|
||||
Tcl_GetErrorLine(interp)));
|
||||
TCL_FALLTHROUGH();
|
||||
default:
|
||||
goto abnormalResult;
|
||||
}
|
||||
@@ -3457,20 +3479,18 @@ DictFilterCmd(
|
||||
TclDecrRefCount(resultObj);
|
||||
}
|
||||
return result;
|
||||
|
||||
abnormalResult:
|
||||
Tcl_DictObjDone(&search);
|
||||
TclDecrRefCount(keyObj);
|
||||
TclDecrRefCount(valueObj);
|
||||
TclDecrRefCount(keyVarObj);
|
||||
TclDecrRefCount(valueVarObj);
|
||||
TclDecrRefCount(scriptObj);
|
||||
TclDecrRefCount(resultObj);
|
||||
return result;
|
||||
}
|
||||
Tcl_Panic("unexpected fallthrough");
|
||||
/* Control never reaches this point. */
|
||||
return TCL_ERROR;
|
||||
TCL_UNREACHABLE();
|
||||
|
||||
abnormalResult:
|
||||
Tcl_DictObjDone(&search);
|
||||
TclDecrRefCount(keyObj);
|
||||
TclDecrRefCount(valueObj);
|
||||
TclDecrRefCount(keyVarObj);
|
||||
TclDecrRefCount(valueVarObj);
|
||||
TclDecrRefCount(scriptObj);
|
||||
TclDecrRefCount(resultObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+159
-120
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#define ALLOW_DEPRECATED_OPCODES
|
||||
#include "tclCompile.h"
|
||||
#include "tclOOInt.h"
|
||||
#include <assert.h>
|
||||
@@ -132,7 +133,7 @@ void
|
||||
TclDebugPrintByteCodeObj(
|
||||
Tcl_Obj *objPtr) /* The bytecode object to disassemble. */
|
||||
{
|
||||
if (tclTraceCompile >= 2) {
|
||||
if (tclTraceCompile >= TCL_TRACE_BYTECODE_COMPILE_DETAIL) {
|
||||
Tcl_Obj *bufPtr = DisassembleByteCodeObj(objPtr);
|
||||
|
||||
fprintf(stdout, "\n%s", TclGetString(bufPtr));
|
||||
@@ -280,8 +281,11 @@ DisassembleByteCodeObj(
|
||||
*/
|
||||
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"ByteCode %p, refCt %" TCL_SIZE_MODIFIER "d, epoch %" TCL_SIZE_MODIFIER "d, interp %p (epoch %" TCL_SIZE_MODIFIER "d)\n",
|
||||
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr, iPtr->compileEpoch);
|
||||
"ByteCode %p, refCt %" TCL_SIZE_MODIFIER "d, "
|
||||
"epoch %" TCL_SIZE_MODIFIER "d, interp %p "
|
||||
"(epoch %" TCL_SIZE_MODIFIER "d)\n",
|
||||
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
|
||||
iPtr->compileEpoch);
|
||||
Tcl_AppendToObj(bufferObj, " Source ", -1);
|
||||
PrintSourceToObj(bufferObj, codePtr->source,
|
||||
TclMin(codePtr->numSrcBytes, 55));
|
||||
@@ -291,7 +295,10 @@ DisassembleByteCodeObj(
|
||||
TclGetString(fileObj), line);
|
||||
}
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"\n Cmds %d, src %" TCL_SIZE_MODIFIER "d, inst %" TCL_SIZE_MODIFIER "d, litObjs %" TCL_SIZE_MODIFIER "d, aux %" TCL_SIZE_MODIFIER "d, stkDepth %" TCL_SIZE_MODIFIER "d, code/src %.2f\n",
|
||||
"\n Cmds %d, src %" TCL_SIZE_MODIFIER "d, "
|
||||
"inst %" TCL_SIZE_MODIFIER "d, litObjs %" TCL_SIZE_MODIFIER "d, "
|
||||
"aux %" TCL_SIZE_MODIFIER "d, stkDepth %" TCL_SIZE_MODIFIER "d, "
|
||||
"code/src %.2f\n",
|
||||
numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes,
|
||||
codePtr->numLitObjects, codePtr->numAuxDataItems,
|
||||
codePtr->maxStackDepth,
|
||||
@@ -303,8 +310,10 @@ DisassembleByteCodeObj(
|
||||
|
||||
#ifdef TCL_COMPILE_STATS
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+inst %" TCL_SIZE_MODIFIER "d+litObj %"
|
||||
TCL_Z_MODIFIER "u+exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+cmdMap %" TCL_SIZE_MODIFIER "d\n",
|
||||
" Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+"
|
||||
"inst %" TCL_SIZE_MODIFIER "d+litObj %" TCL_Z_MODIFIER "u+"
|
||||
"exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+"
|
||||
"cmdMap %" TCL_SIZE_MODIFIER "d\n",
|
||||
codePtr->structureSize,
|
||||
offsetof(ByteCode, localCachePtr),
|
||||
codePtr->numCodeBytes,
|
||||
@@ -325,7 +334,9 @@ DisassembleByteCodeObj(
|
||||
Tcl_Size numCompiledLocals = procPtr->numCompiledLocals;
|
||||
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" Proc %p, refCt %" TCL_SIZE_MODIFIER "d, args %" TCL_SIZE_MODIFIER "d, compiled locals %" TCL_SIZE_MODIFIER "d\n",
|
||||
" Proc %p, refCt %" TCL_SIZE_MODIFIER "d, "
|
||||
"args %" TCL_SIZE_MODIFIER "d, "
|
||||
"compiled locals %" TCL_SIZE_MODIFIER "d\n",
|
||||
procPtr, procPtr->refCount, procPtr->numArgs,
|
||||
numCompiledLocals);
|
||||
if (numCompiledLocals > 0) {
|
||||
@@ -356,24 +367,31 @@ DisassembleByteCodeObj(
|
||||
*/
|
||||
|
||||
if ((int)codePtr->numExceptRanges > 0) {
|
||||
Tcl_AppendPrintfToObj(bufferObj, " Exception ranges %" TCL_SIZE_MODIFIER "d, depth %" TCL_SIZE_MODIFIER "d:\n",
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" Exception ranges %" TCL_SIZE_MODIFIER "d, "
|
||||
"depth %" TCL_SIZE_MODIFIER "d:\n",
|
||||
codePtr->numExceptRanges, codePtr->maxExceptDepth);
|
||||
for (i = 0; i < (int)codePtr->numExceptRanges; i++) {
|
||||
ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];
|
||||
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" %" TCL_SIZE_MODIFIER "d: level %" TCL_SIZE_MODIFIER "d, %s, pc %" TCL_SIZE_MODIFIER "d-%" TCL_SIZE_MODIFIER "d, ",
|
||||
" %" TCL_SIZE_MODIFIER "d: "
|
||||
"level %" TCL_SIZE_MODIFIER "d, %s, "
|
||||
"pc %" TCL_SIZE_MODIFIER "d-%" TCL_SIZE_MODIFIER "d, ",
|
||||
i, rangePtr->nestingLevel,
|
||||
(rangePtr->type==LOOP_EXCEPTION_RANGE ? "loop" : "catch"),
|
||||
rangePtr->codeOffset,
|
||||
(rangePtr->codeOffset + rangePtr->numCodeBytes - 1));
|
||||
switch (rangePtr->type) {
|
||||
case LOOP_EXCEPTION_RANGE:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "continue %" TCL_SIZE_MODIFIER "d, break %" TCL_SIZE_MODIFIER "d\n",
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"continue %" TCL_SIZE_MODIFIER "d, "
|
||||
"break %" TCL_SIZE_MODIFIER "d\n",
|
||||
rangePtr->continueOffset, rangePtr->breakOffset);
|
||||
break;
|
||||
case CATCH_EXCEPTION_RANGE:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "catch %" TCL_SIZE_MODIFIER "d\n",
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"catch %" TCL_SIZE_MODIFIER "d\n",
|
||||
rangePtr->catchOffset);
|
||||
break;
|
||||
default:
|
||||
@@ -447,7 +465,8 @@ DisassembleByteCodeObj(
|
||||
srcLengthNext++;
|
||||
}
|
||||
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%s%4" TCL_SIZE_MODIFIER "d: pc %d-%d, src %d-%d",
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"%s%4" TCL_SIZE_MODIFIER "d: pc %d-%d, src %d-%d",
|
||||
((i % 2)? " " : "\n "),
|
||||
(i+1), codeOffset, (codeOffset + codeLen - 1),
|
||||
srcOffset, (srcOffset + srcLen - 1));
|
||||
@@ -559,56 +578,69 @@ FormatInstruction(
|
||||
for (i = 0; i < instDesc->numOperands; i++) {
|
||||
switch (instDesc->opTypes[i]) {
|
||||
case OPERAND_INT1:
|
||||
opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
|
||||
opnd = TclGetInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
|
||||
break;
|
||||
case OPERAND_INT4:
|
||||
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
|
||||
opnd = TclGetInt4AtPtr(pc+numBytes);
|
||||
numBytes += 4;
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
|
||||
break;
|
||||
case OPERAND_UINT1:
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
|
||||
break;
|
||||
case OPERAND_UINT4:
|
||||
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
|
||||
opnd = TclGetUInt4AtPtr(pc+numBytes);
|
||||
numBytes += 4;
|
||||
if (opCode == INST_START_CMD) {
|
||||
snprintf(suffixBuffer+strlen(suffixBuffer), sizeof(suffixBuffer) - strlen(suffixBuffer),
|
||||
snprintf(suffixBuffer+strlen(suffixBuffer),
|
||||
sizeof(suffixBuffer) - strlen(suffixBuffer),
|
||||
", %u cmds start here", opnd);
|
||||
}
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
|
||||
break;
|
||||
case OPERAND_OFFSET1:
|
||||
opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
|
||||
opnd = TclGetInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd);
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
|
||||
break;
|
||||
case OPERAND_OFFSET4:
|
||||
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
|
||||
opnd = TclGetInt4AtPtr(pc+numBytes);
|
||||
numBytes += 4;
|
||||
if (opCode == INST_START_CMD) {
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer), "next cmd at pc %u", pcOffset+opnd);
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer),
|
||||
"next cmd at pc %u", pcOffset+opnd);
|
||||
} else {
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd);
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer),
|
||||
"pc %u", pcOffset+opnd);
|
||||
}
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
|
||||
break;
|
||||
case OPERAND_LIT1:
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
suffixObj = codePtr->objArrayPtr[opnd];
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
|
||||
break;
|
||||
case OPERAND_LIT4:
|
||||
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
|
||||
opnd = TclGetUInt4AtPtr(pc+numBytes);
|
||||
numBytes += 4;
|
||||
suffixObj = codePtr->objArrayPtr[opnd];
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
|
||||
break;
|
||||
case OPERAND_AUX4:
|
||||
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
|
||||
opnd = TclGetUInt4AtPtr(pc+numBytes);
|
||||
numBytes += 4;
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
|
||||
auxPtr = &codePtr->auxDataArrayPtr[opnd];
|
||||
break;
|
||||
case OPERAND_IDX4:
|
||||
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
|
||||
opnd = TclGetInt4AtPtr(pc+numBytes);
|
||||
numBytes += 4;
|
||||
if (opnd >= -1) {
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%d ", opnd);
|
||||
} else if (opnd == -2) {
|
||||
@@ -627,14 +659,16 @@ FormatInstruction(
|
||||
printLVTindex:
|
||||
if (localPtr != NULL) {
|
||||
if (opnd >= localCt) {
|
||||
Tcl_Panic("FormatInstruction: bad local var index %u (%" TCL_SIZE_MODIFIER "d locals)",
|
||||
Tcl_Panic("FormatInstruction: bad local var index %u "
|
||||
"(%" TCL_SIZE_MODIFIER "d locals)",
|
||||
opnd, localCt);
|
||||
}
|
||||
for (j = 0; j < opnd; j++) {
|
||||
localPtr = localPtr->nextPtr;
|
||||
}
|
||||
if (TclIsVarTemporary(localPtr)) {
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer), "temp var %u", opnd);
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer),
|
||||
"temp var %u", opnd);
|
||||
} else {
|
||||
snprintf(suffixBuffer, sizeof(suffixBuffer), "var ");
|
||||
suffixSrc = localPtr->name;
|
||||
@@ -643,10 +677,57 @@ FormatInstruction(
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", opnd);
|
||||
break;
|
||||
case OPERAND_SCLS1:
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%s ",
|
||||
tclStringClassTable[opnd].name);
|
||||
break;
|
||||
case OPERAND_UNSF1:
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
Tcl_AppendPrintfToObj(bufferObj, "silent=%s ", opnd?"no":"yes");
|
||||
break;
|
||||
case OPERAND_CLK1:
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
switch (opnd) {
|
||||
case CLOCK_READ_CLICKS:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "clicks " );
|
||||
break;
|
||||
case CLOCK_READ_MICROS:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "micros " );
|
||||
break;
|
||||
case CLOCK_READ_MILLIS:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "millis " );
|
||||
break;
|
||||
case CLOCK_READ_SECS:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "secs " );
|
||||
break;
|
||||
default:
|
||||
Tcl_Panic("unknown clock type");
|
||||
}
|
||||
break;
|
||||
case OPERAND_LRPL1:
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes);
|
||||
numBytes++;
|
||||
switch (opnd) {
|
||||
case 0:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "0 ");
|
||||
break;
|
||||
case TCL_LREPLACE_END_IS_LAST:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "endLast ");
|
||||
break;
|
||||
case TCL_LREPLACE_SINGLE_INDEX:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "singleIdx ");
|
||||
break;
|
||||
case TCL_LREPLACE_END_IS_LAST | TCL_LREPLACE_NEED_IN_RANGE:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "endLast,indexTest ");
|
||||
break;
|
||||
default:
|
||||
Tcl_AppendPrintfToObj(bufferObj, "endLast,singleIdx ");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OPERAND_NONE:
|
||||
default:
|
||||
break;
|
||||
@@ -746,13 +827,15 @@ TclGetInnerContext(
|
||||
objc = 2;
|
||||
break;
|
||||
|
||||
case INST_INVOKE_STK4:
|
||||
objc = TclGetUInt4AtPtr(pc+1);
|
||||
case INST_INVOKE_STK:
|
||||
objc = TclGetUInt4AtPtr(pc + 1);
|
||||
break;
|
||||
|
||||
#ifndef REMOVE_DEPRECATED_OPCODES
|
||||
case INST_INVOKE_STK1:
|
||||
objc = TclGetUInt1AtPtr(pc+1);
|
||||
objc = TclGetUInt1AtPtr(pc + 1);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
result = iPtr->innerContext;
|
||||
@@ -1026,6 +1109,9 @@ DisassembleByteCodeAsDicts(
|
||||
val = TclGetInt1AtPtr(opnd);
|
||||
opnd += 1;
|
||||
goto formatNumber;
|
||||
case OPERAND_UNSF1: // TODO: decode
|
||||
case OPERAND_CLK1: // TODO: decode
|
||||
case OPERAND_LRPL1: // TODO: decode
|
||||
case OPERAND_UINT1:
|
||||
val = TclGetUInt1AtPtr(opnd);
|
||||
opnd += 1;
|
||||
@@ -1148,14 +1234,19 @@ DisassembleByteCodeAsDicts(
|
||||
switch (rangePtr->type) {
|
||||
case LOOP_EXCEPTION_RANGE:
|
||||
Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf(
|
||||
"type %s level %" TCL_SIZE_MODIFIER "d from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d break %" TCL_SIZE_MODIFIER "d continue %" TCL_SIZE_MODIFIER "d",
|
||||
"type %s level %" TCL_SIZE_MODIFIER "d "
|
||||
"from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d "
|
||||
"break %" TCL_SIZE_MODIFIER "d "
|
||||
"continue %" TCL_SIZE_MODIFIER "d",
|
||||
"loop", rangePtr->nestingLevel, rangePtr->codeOffset,
|
||||
rangePtr->codeOffset + rangePtr->numCodeBytes - 1,
|
||||
rangePtr->breakOffset, rangePtr->continueOffset));
|
||||
break;
|
||||
case CATCH_EXCEPTION_RANGE:
|
||||
Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf(
|
||||
"type %s level %" TCL_SIZE_MODIFIER "d from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d catch %" TCL_SIZE_MODIFIER "d",
|
||||
"type %s level %" TCL_SIZE_MODIFIER "d "
|
||||
"from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d "
|
||||
"catch %" TCL_SIZE_MODIFIER "d",
|
||||
"catch", rangePtr->nestingLevel, rangePtr->codeOffset,
|
||||
rangePtr->codeOffset + rangePtr->numCodeBytes - 1,
|
||||
rangePtr->catchOffset));
|
||||
@@ -1279,9 +1370,12 @@ Tcl_DisassembleObjCmd(
|
||||
Tcl_Obj *codeObjPtr = NULL;
|
||||
Proc *procPtr = NULL;
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_Obj *ooWhat = NULL;
|
||||
Object *oPtr;
|
||||
Class *classPtr;
|
||||
ByteCode *codePtr;
|
||||
Method *methodPtr;
|
||||
const char *bodyType;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "type ...");
|
||||
@@ -1379,23 +1473,17 @@ Tcl_DisassembleObjCmd(
|
||||
* Look up the body of a constructor.
|
||||
*/
|
||||
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr->classPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" is not a class", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
|
||||
TclGetString(objv[2]), (char *)NULL);
|
||||
ooWhat = objv[2];
|
||||
classPtr = TclOOGetClassFromObj(interp, ooWhat);
|
||||
if (classPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
methodPtr = oPtr->classPtr->constructorPtr;
|
||||
methodPtr = classPtr->constructorPtr;
|
||||
if (methodPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" has no defined constructor",
|
||||
TclGetString(objv[2])));
|
||||
TclGetString(ooWhat)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
|
||||
"CONSRUCTOR", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
@@ -1409,30 +1497,9 @@ Tcl_DisassembleObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile if necessary.
|
||||
*/
|
||||
|
||||
if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) {
|
||||
Command cmd;
|
||||
|
||||
/*
|
||||
* Yes, this is ugly, but we need to pass the namespace in to the
|
||||
* compiler in two places.
|
||||
*/
|
||||
|
||||
cmd.nsPtr = (Namespace *) oPtr->namespacePtr;
|
||||
procPtr->cmdPtr = &cmd;
|
||||
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
|
||||
(Namespace *) oPtr->namespacePtr, "body of constructor",
|
||||
TclGetString(objv[2]));
|
||||
procPtr->cmdPtr = NULL;
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
codeObjPtr = procPtr->bodyPtr;
|
||||
break;
|
||||
oPtr = classPtr->thisPtr;
|
||||
bodyType = "body of constructor";
|
||||
goto compileMethodIfNeeded;
|
||||
|
||||
case DISAS_CLASS_DESTRUCTOR:
|
||||
if (objc != 3) {
|
||||
@@ -1444,23 +1511,17 @@ Tcl_DisassembleObjCmd(
|
||||
* Look up the body of a destructor.
|
||||
*/
|
||||
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr->classPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" is not a class", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
|
||||
TclGetString(objv[2]), (char *)NULL);
|
||||
ooWhat = objv[2];
|
||||
classPtr = TclOOGetClassFromObj(interp, ooWhat);
|
||||
if (classPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
methodPtr = oPtr->classPtr->destructorPtr;
|
||||
methodPtr = classPtr->destructorPtr;
|
||||
if (methodPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" has no defined destructor",
|
||||
TclGetString(objv[2])));
|
||||
TclGetString(ooWhat)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
|
||||
"DESRUCTOR", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
@@ -1474,30 +1535,9 @@ Tcl_DisassembleObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile if necessary.
|
||||
*/
|
||||
|
||||
if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) {
|
||||
Command cmd;
|
||||
|
||||
/*
|
||||
* Yes, this is ugly, but we need to pass the namespace in to the
|
||||
* compiler in two places.
|
||||
*/
|
||||
|
||||
cmd.nsPtr = (Namespace *) oPtr->namespacePtr;
|
||||
procPtr->cmdPtr = &cmd;
|
||||
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
|
||||
(Namespace *) oPtr->namespacePtr, "body of destructor",
|
||||
TclGetString(objv[2]));
|
||||
procPtr->cmdPtr = NULL;
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
codeObjPtr = procPtr->bodyPtr;
|
||||
break;
|
||||
oPtr = classPtr->thisPtr;
|
||||
bodyType = "body of destructor";
|
||||
goto compileMethodIfNeeded;
|
||||
|
||||
case DISAS_CLASS_METHOD:
|
||||
if (objc != 4) {
|
||||
@@ -1509,19 +1549,13 @@ Tcl_DisassembleObjCmd(
|
||||
* Look up the body of a class method.
|
||||
*/
|
||||
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
|
||||
if (oPtr == NULL) {
|
||||
ooWhat = objv[3];
|
||||
classPtr = TclOOGetClassFromObj(interp, objv[2]);
|
||||
if (classPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (oPtr->classPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" is not a class", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
|
||||
TclGetString(objv[2]), (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
|
||||
objv[3]);
|
||||
oPtr = classPtr->thisPtr;
|
||||
hPtr = Tcl_FindHashEntry(&classPtr->classMethods, ooWhat);
|
||||
goto methodBody;
|
||||
case DISAS_OBJECT_METHOD:
|
||||
if (objc != 4) {
|
||||
@@ -1533,14 +1567,16 @@ Tcl_DisassembleObjCmd(
|
||||
* Look up the body of an instance method.
|
||||
*/
|
||||
|
||||
ooWhat = objv[3];
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
ooWhat = objv[3];
|
||||
if (oPtr->methodsPtr == NULL) {
|
||||
goto unknownMethod;
|
||||
}
|
||||
hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[3]);
|
||||
hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, ooWhat);
|
||||
|
||||
/*
|
||||
* Compile (if necessary) and disassemble a method body.
|
||||
@@ -1550,9 +1586,9 @@ Tcl_DisassembleObjCmd(
|
||||
if (hPtr == NULL) {
|
||||
unknownMethod:
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"unknown method \"%s\"", TclGetString(objv[3])));
|
||||
"unknown method \"%s\"", TclGetString(ooWhat)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
|
||||
TclGetString(objv[3]), (char *)NULL);
|
||||
TclGetString(ooWhat), (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
procPtr = TclOOGetProcFromMethod((Method *)Tcl_GetHashValue(hPtr));
|
||||
@@ -1563,6 +1599,9 @@ Tcl_DisassembleObjCmd(
|
||||
"METHODTYPE", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
bodyType = "body of method";
|
||||
|
||||
compileMethodIfNeeded:
|
||||
if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) {
|
||||
Command cmd;
|
||||
|
||||
@@ -1574,8 +1613,8 @@ Tcl_DisassembleObjCmd(
|
||||
cmd.nsPtr = (Namespace *) oPtr->namespacePtr;
|
||||
procPtr->cmdPtr = &cmd;
|
||||
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
|
||||
(Namespace *) oPtr->namespacePtr, "body of method",
|
||||
TclGetString(objv[3]));
|
||||
(Namespace *) oPtr->namespacePtr, bodyType,
|
||||
TclGetString(ooWhat));
|
||||
procPtr->cmdPtr = NULL;
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
@@ -1584,7 +1623,7 @@ Tcl_DisassembleObjCmd(
|
||||
codeObjPtr = procPtr->bodyPtr;
|
||||
break;
|
||||
default:
|
||||
CLANG_ASSERT(0);
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+304
-70
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include <assert.h>
|
||||
#include "../utf8proc/utf8proc.h" /* Relative path to ignore system include */
|
||||
|
||||
typedef size_t (LengthProc)(const char *src);
|
||||
|
||||
@@ -881,7 +882,7 @@ Tcl_GetEncodingNames(
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_Obj *map, *name, *result;
|
||||
Tcl_DictSearch mapSearch;
|
||||
int dummy, done = 0;
|
||||
int done = 0;
|
||||
|
||||
TclNewObj(result);
|
||||
Tcl_InitObjHashTable(&table);
|
||||
@@ -896,7 +897,7 @@ Tcl_GetEncodingNames(
|
||||
Encoding *encodingPtr = (Encoding *)Tcl_GetHashValue(hPtr);
|
||||
|
||||
Tcl_CreateHashEntry(&table,
|
||||
Tcl_NewStringObj(encodingPtr->name, TCL_INDEX_NONE), &dummy);
|
||||
Tcl_NewStringObj(encodingPtr->name, TCL_INDEX_NONE), NULL);
|
||||
}
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
|
||||
@@ -909,7 +910,7 @@ Tcl_GetEncodingNames(
|
||||
|
||||
Tcl_DictObjFirst(NULL, map, &mapSearch, &name, NULL, &done);
|
||||
for (; !done; Tcl_DictObjNext(&mapSearch, &name, NULL, &done)) {
|
||||
Tcl_CreateHashEntry(&table, name, &dummy);
|
||||
Tcl_CreateHashEntry(&table, name, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -969,9 +970,11 @@ Tcl_GetEncodingNulLength(
|
||||
* unless interp was NULL.
|
||||
*
|
||||
* Side effects:
|
||||
* The reference count of the new system encoding is incremented. The
|
||||
* reference count of the old system encoding is decremented and it may
|
||||
* be freed. All VFS cached information is invalidated.
|
||||
* If the passed encoding is the same as the current system
|
||||
* encoding, the call is effectively a no-op. Otherwise, the reference
|
||||
* count of the new system encoding is incremented. The reference count
|
||||
* of the old system encoding is decremented and it may be freed. All
|
||||
* VFS cached information is invalidated.
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -983,25 +986,34 @@ Tcl_SetSystemEncoding(
|
||||
* to reset to default encoding. */
|
||||
{
|
||||
Tcl_Encoding encoding;
|
||||
Encoding *encodingPtr;
|
||||
|
||||
if (!name || !*name) {
|
||||
Tcl_MutexLock(&encodingMutex);
|
||||
Tcl_MutexLock(&encodingMutex);
|
||||
if (name == NULL || name[0] == '\0') {
|
||||
if (defaultEncoding == systemEncoding) {
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
return TCL_OK;
|
||||
}
|
||||
encoding = defaultEncoding;
|
||||
encodingPtr = (Encoding *) encoding;
|
||||
encodingPtr->refCount++;
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
((Encoding *)encoding)->refCount += 1;
|
||||
} else {
|
||||
encoding = Tcl_GetEncoding(interp, name);
|
||||
if (encoding == NULL) {
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (encoding == systemEncoding) {
|
||||
FreeEncoding(encoding);
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_MutexLock(&encodingMutex);
|
||||
assert(encoding != systemEncoding);
|
||||
FreeEncoding(systemEncoding);
|
||||
systemEncoding = encoding;
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
|
||||
/* Checks above ensure this is only called when system encoding changes */
|
||||
Tcl_FSMountsChanged(NULL);
|
||||
|
||||
return TCL_OK;
|
||||
@@ -1228,7 +1240,7 @@ Tcl_ExternalToUtfDStringEx(
|
||||
* and loop. Otherwise, return the result we got.
|
||||
*/
|
||||
if ((result != TCL_CONVERT_NOSPACE) &&
|
||||
!(result == TCL_CONVERT_MULTIBYTE && (flags & TCL_ENCODING_END))) {
|
||||
(result != TCL_CONVERT_MULTIBYTE || (flags & TCL_ENCODING_END))) {
|
||||
Tcl_Size nBytesProcessed = (src - srcStart);
|
||||
|
||||
Tcl_DStringSetLength(dstPtr, soFar);
|
||||
@@ -1544,7 +1556,7 @@ Tcl_UtfToExternalDStringEx(
|
||||
* and loop. Otherwise, return the result we got.
|
||||
*/
|
||||
if ((result != TCL_CONVERT_NOSPACE) &&
|
||||
!(result == TCL_CONVERT_MULTIBYTE && (flags & TCL_ENCODING_END))) {
|
||||
(result != TCL_CONVERT_MULTIBYTE || (flags & TCL_ENCODING_END))) {
|
||||
Tcl_Size nBytesProcessed = (src - srcStart);
|
||||
Tcl_Size i = soFar + encodingPtr->nullSize - 1;
|
||||
/* Loop as DStringSetLength only stores one nul byte at a time */
|
||||
@@ -1953,22 +1965,22 @@ LoadTableEncoding(
|
||||
*/
|
||||
|
||||
static const char staticHex[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 ... 15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 ... 31 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 ... 47 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 48 ... 63 */
|
||||
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 ... 79 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 ... 95 */
|
||||
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 ... 111 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 112 ... 127 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 ... 143 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 ... 159 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 160 ... 175 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176 ... 191 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 ... 207 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208 ... 223 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 ... 239 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 240 ... 255 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 ... 15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 ... 31 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 ... 47 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 48 ... 63 */
|
||||
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 ... 79 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 ... 95 */
|
||||
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 ... 111 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 112 ... 127 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 ... 143 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 ... 159 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 160 ... 175 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176 ... 191 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 ... 207 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208 ... 223 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 ... 239 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 240 ... 255 */
|
||||
};
|
||||
|
||||
Tcl_DStringInit(&lineString);
|
||||
@@ -2481,19 +2493,19 @@ UtfToUtfProc(
|
||||
* by a low surrogate. NOT to be called for strict profile since
|
||||
* that should raise an error.
|
||||
*/
|
||||
#define OUTPUT_ISOLATEDSURROGATE \
|
||||
do { \
|
||||
Tcl_UniChar high; \
|
||||
if (PROFILE_REPLACE(profile)) { \
|
||||
high = UNICODE_REPLACE_CHAR; \
|
||||
} else { \
|
||||
high = (Tcl_UniChar)(ptrdiff_t) *statePtr; \
|
||||
} \
|
||||
assert(!(flags & ENCODING_UTF)); /* Must be CESU-8 */ \
|
||||
assert(HIGH_SURROGATE(high)); \
|
||||
assert(!PROFILE_STRICT(profile)); \
|
||||
dst += Tcl_UniCharToUtf(high, dst); \
|
||||
*statePtr = 0; /* Reset state */ \
|
||||
#define OUTPUT_ISOLATEDSURROGATE() \
|
||||
do { \
|
||||
Tcl_UniChar high; \
|
||||
if (PROFILE_REPLACE(profile)) { \
|
||||
high = UNICODE_REPLACE_CHAR; \
|
||||
} else { \
|
||||
high = (Tcl_UniChar)(ptrdiff_t) *statePtr; \
|
||||
} \
|
||||
assert(!(flags & ENCODING_UTF)); /* Must be CESU-8 */ \
|
||||
assert(HIGH_SURROGATE(high)); \
|
||||
assert(!PROFILE_STRICT(profile)); \
|
||||
dst += Tcl_UniCharToUtf(high, dst); \
|
||||
*statePtr = 0; /* Reset state */ \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
@@ -2501,20 +2513,19 @@ UtfToUtfProc(
|
||||
* an error if profile is strict, or output an appropriate
|
||||
* character for replace and tcl8 profiles and continue.
|
||||
*/
|
||||
#define CHECK_ISOLATEDSURROGATE \
|
||||
if (*statePtr) { \
|
||||
if (PROFILE_STRICT(profile)) { \
|
||||
result = TCL_CONVERT_SYNTAX; \
|
||||
break; \
|
||||
} \
|
||||
OUTPUT_ISOLATEDSURROGATE; \
|
||||
continue; /* Rerun loop so length checks etc. repeated */ \
|
||||
} else \
|
||||
#define CHECK_ISOLATEDSURROGATE() \
|
||||
if (*statePtr) { \
|
||||
if (PROFILE_STRICT(profile)) { \
|
||||
result = TCL_CONVERT_SYNTAX; \
|
||||
break; \
|
||||
} \
|
||||
OUTPUT_ISOLATEDSURROGATE(); \
|
||||
continue; /* Rerun loop so length checks etc. repeated */ \
|
||||
} else \
|
||||
(void) 0
|
||||
|
||||
profile = ENCODING_PROFILE_GET(flags);
|
||||
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
|
||||
|
||||
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
|
||||
/*
|
||||
* If there is more string to follow, this will ensure that the
|
||||
@@ -2529,19 +2540,18 @@ UtfToUtfProc(
|
||||
break;
|
||||
}
|
||||
if (UCHAR(*src) < 0x80 && !((UCHAR(*src) == 0) && (flags & ENCODING_INPUT))) {
|
||||
|
||||
CHECK_ISOLATEDSURROGATE;
|
||||
CHECK_ISOLATEDSURROGATE();
|
||||
/*
|
||||
* Copy 7bit characters, but skip null-bytes when we are in input
|
||||
* mode, so that they get converted to \xC0\x80.
|
||||
*/
|
||||
*dst++ = *src++;
|
||||
} else if ((UCHAR(*src) == 0xC0) && (src + 1 < srcEnd) &&
|
||||
(UCHAR(src[1]) == 0x80) &&
|
||||
(!(flags & ENCODING_INPUT) || !PROFILE_TCL8(profile))) {
|
||||
(UCHAR(src[1]) == 0x80) &&
|
||||
(!(flags & ENCODING_INPUT) || !PROFILE_TCL8(profile))) {
|
||||
/* Special sequence \xC0\x80 */
|
||||
|
||||
CHECK_ISOLATEDSURROGATE;
|
||||
CHECK_ISOLATEDSURROGATE();
|
||||
if (!PROFILE_TCL8(profile) && (flags & ENCODING_INPUT)) {
|
||||
if (PROFILE_REPLACE(profile)) {
|
||||
dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
|
||||
@@ -2567,7 +2577,7 @@ UtfToUtfProc(
|
||||
* because the UTF-8 sequence is truncated.
|
||||
*/
|
||||
|
||||
CHECK_ISOLATEDSURROGATE;
|
||||
CHECK_ISOLATEDSURROGATE();
|
||||
|
||||
if (flags & ENCODING_INPUT) {
|
||||
/* Incomplete bytes for modified UTF-8 target */
|
||||
@@ -2584,7 +2594,8 @@ UtfToUtfProc(
|
||||
} else {
|
||||
/* TCL_ENCODING_PROFILE_TCL8 */
|
||||
char chbuf[2];
|
||||
chbuf[0] = UCHAR(*src++); chbuf[1] = 0;
|
||||
chbuf[0] = UCHAR(*src++);
|
||||
chbuf[1] = 0;
|
||||
TclUtfToUniChar(chbuf, &ch);
|
||||
}
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
@@ -2610,8 +2621,8 @@ UtfToUtfProc(
|
||||
src += len;
|
||||
if (!(flags & ENCODING_UTF) && !(flags & ENCODING_INPUT)
|
||||
&& (ch > 0x7FF)) {
|
||||
assert(savedSurrogate == 0); /* Since this flag combo
|
||||
will never set *statePtr */
|
||||
assert(savedSurrogate == 0); /* Since this flag combo
|
||||
* will never set *statePtr */
|
||||
if (ch > 0xFFFF) {
|
||||
/* CESU-8 6-byte sequence for chars > U+FFFF */
|
||||
ch -= 0x10000;
|
||||
@@ -2629,7 +2640,7 @@ UtfToUtfProc(
|
||||
/* UTF-8, not CESU-8, so surrogates should not appear */
|
||||
if (PROFILE_STRICT(profile)) {
|
||||
result = (flags & ENCODING_INPUT)
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
src = saveSrc;
|
||||
break;
|
||||
} else if (PROFILE_REPLACE(profile)) {
|
||||
@@ -2647,7 +2658,7 @@ UtfToUtfProc(
|
||||
/* Isolated low surrogate */
|
||||
if (PROFILE_STRICT(profile)) {
|
||||
result = (flags & ENCODING_INPUT)
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
src = saveSrc;
|
||||
break;
|
||||
} else if (PROFILE_REPLACE(profile)) {
|
||||
@@ -2664,7 +2675,7 @@ UtfToUtfProc(
|
||||
assert(HIGH_SURROGATE(savedSurrogate));
|
||||
if (PROFILE_STRICT(profile)) {
|
||||
result = (flags & ENCODING_INPUT)
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
src = saveSrc;
|
||||
break;
|
||||
} else if (PROFILE_REPLACE(profile)) {
|
||||
@@ -2682,7 +2693,7 @@ UtfToUtfProc(
|
||||
}
|
||||
} else {
|
||||
/* Normal character */
|
||||
CHECK_ISOLATEDSURROGATE;
|
||||
CHECK_ISOLATEDSURROGATE();
|
||||
}
|
||||
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
@@ -2698,7 +2709,7 @@ UtfToUtfProc(
|
||||
/* No more data coming */
|
||||
if (PROFILE_STRICT(profile)) {
|
||||
result = (flags & ENCODING_INPUT)
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
|
||||
} else {
|
||||
if (PROFILE_REPLACE(profile)) {
|
||||
ch = UNICODE_REPLACE_CHAR;
|
||||
@@ -3510,7 +3521,8 @@ TableToUtfProc(
|
||||
ch = UNICODE_REPLACE_CHAR;
|
||||
} else {
|
||||
char chbuf[2];
|
||||
chbuf[0] = byte; chbuf[1] = 0;
|
||||
chbuf[0] = byte;
|
||||
chbuf[1] = 0;
|
||||
TclUtfToUniChar(chbuf, &ch);
|
||||
}
|
||||
}
|
||||
@@ -4067,6 +4079,30 @@ EscapeToUtfProc(
|
||||
numChars++;
|
||||
}
|
||||
|
||||
if ((flags & TCL_ENCODING_END) && (result == TCL_CONVERT_MULTIBYTE)) {
|
||||
/* We have a code fragment left-over at the end */
|
||||
if (dst > dstEnd) {
|
||||
result = TCL_CONVERT_NOSPACE;
|
||||
} else {
|
||||
/* destination is not full, so we really are at the end now */
|
||||
if (PROFILE_STRICT(flags)) {
|
||||
result = TCL_CONVERT_SYNTAX;
|
||||
} else {
|
||||
/*
|
||||
* PROFILE_REPLACE or PROFILE_TCL8. The latter is treated
|
||||
* similar to former because Tcl8 was broken in this regard
|
||||
* as it just ignored the byte and truncated which is really
|
||||
* a no-no as per Unicode recommendations.
|
||||
*/
|
||||
result = TCL_OK;
|
||||
dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
|
||||
numChars++;
|
||||
/* TCL_CONVERT_MULTIBYTE means all source consumed */
|
||||
src = srcEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*statePtr = (Tcl_EncodingState) INT2PTR(state);
|
||||
*srcReadPtr = src - srcStart;
|
||||
*dstWrotePtr = dst - dstStart;
|
||||
@@ -4612,7 +4648,205 @@ TclGetEncodingProfiles(
|
||||
}
|
||||
Tcl_SetObjResult(interp, objPtr);
|
||||
}
|
||||
|
||||
|
||||
static utf8proc_ssize_t
|
||||
TclUtfNormalize(
|
||||
Tcl_Interp *interp, /* Error messages. May be NULL */
|
||||
const char *bytes, /* Operand encoded in Tcl internal UTF8 */
|
||||
Tcl_Size numBytes, /* Length bytes[], or -1 if NUL terminated */
|
||||
Tcl_Encoding encoding, /* Encoding - must be UTF-8. Caller passed for reuse */
|
||||
Tcl_UnicodeNormalizationForm normForm, /* TCL_{NFC,NFD,NFKC,NFKC} */
|
||||
int profile, /* TCL_ENCODING_PROFILE_{STRICT,REPLACE} */
|
||||
utf8proc_uint8_t **bufPtrPtr) /* On success, output length excluding nul */
|
||||
{
|
||||
if (profile != TCL_ENCODING_PROFILE_REPLACE &&
|
||||
profile != TCL_ENCODING_PROFILE_STRICT) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Invalid value %d passed for encoding profile.",
|
||||
profile));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
utf8proc_option_t options = UTF8PROC_STABLE;
|
||||
switch (normForm) {
|
||||
case TCL_NFC:
|
||||
options |= UTF8PROC_COMPOSE;
|
||||
break;
|
||||
case TCL_NFD:
|
||||
options |= UTF8PROC_DECOMPOSE;
|
||||
break;
|
||||
case TCL_NFKC:
|
||||
options |= UTF8PROC_COMPOSE | UTF8PROC_COMPAT;
|
||||
break;
|
||||
case TCL_NFKD:
|
||||
options |= UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT;
|
||||
break;
|
||||
default:
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Invalid value %d passed for normalization form.",
|
||||
normForm));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (numBytes < 0) {
|
||||
numBytes = -1;
|
||||
}
|
||||
int result;
|
||||
Tcl_DString dsExt;
|
||||
result = Tcl_UtfToExternalDStringEx(interp, encoding, bytes, numBytes,
|
||||
profile, &dsExt, NULL);
|
||||
/* !!! dsExt needs to be freed even in case of error returns */
|
||||
|
||||
utf8proc_ssize_t normLength = -1;
|
||||
if (result == TCL_OK) {
|
||||
normLength =
|
||||
utf8proc_map_custom((utf8proc_uint8_t *)Tcl_DStringValue(&dsExt),
|
||||
Tcl_DStringLength(&dsExt), bufPtrPtr, options, NULL, NULL);
|
||||
|
||||
if (normLength < 0) {
|
||||
if (interp) {
|
||||
const char *errorMsg = utf8proc_errmsg(normLength);
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj(
|
||||
errorMsg ? errorMsg : "Unicode normalization failed.",
|
||||
-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_DStringFree(&dsExt);
|
||||
return normLength;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tcl_UtfToNormalizedDString --
|
||||
*
|
||||
* Converts the passed string to a Unicode normalization form storing
|
||||
* it in dsPtr.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl error code.
|
||||
*
|
||||
* Side effects:
|
||||
* The output string is stored in dsPtr, which is initialized.
|
||||
*/
|
||||
int
|
||||
Tcl_UtfToNormalizedDString(
|
||||
Tcl_Interp *interp, /* Used for error messages. May be NULL */
|
||||
const char *bytes, /* Operand encoded in Tcl internal UTF8 */
|
||||
Tcl_Size numBytes, /* Length of bytes[], or -1 if NUL terminated */
|
||||
Tcl_UnicodeNormalizationForm normForm, /* TCL_{NFC,NFD,NFKC,NFKC} */
|
||||
int profile, /* TCL_ENCODING_PROFILE_{STRICT,REPLACE} */
|
||||
Tcl_DString *dsPtr) /* Converted output string in Tcl internal
|
||||
* UTF8 encoding. Init'ed by function */
|
||||
{
|
||||
Tcl_DStringInit(dsPtr);
|
||||
Tcl_Encoding encoding = Tcl_GetEncoding(interp, "utf-8");
|
||||
if (encoding == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
utf8proc_uint8_t *normUtf8;
|
||||
utf8proc_ssize_t normLength;
|
||||
|
||||
normLength = TclUtfNormalize(interp, bytes, numBytes, encoding, normForm,
|
||||
profile, &normUtf8);
|
||||
if (normLength >= 0) {
|
||||
assert(normUtf8);
|
||||
/* Convert standard UTF8 to internal UTF8 */
|
||||
int result = Tcl_ExternalToUtfDStringEx(interp, encoding,
|
||||
(const char *)normUtf8, normLength, profile, dsPtr, NULL);
|
||||
if (result != TCL_OK) {
|
||||
normLength = -1;
|
||||
}
|
||||
free(normUtf8); /* NOT Tcl_Free! */
|
||||
}
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return normLength >= 0 ? TCL_OK : TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tcl_UtfToNormalized --
|
||||
*
|
||||
* Converts the passed string to a Unicode normalization form storing
|
||||
* it in the caller provided buffer.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl error code.
|
||||
*
|
||||
* Side effects:
|
||||
* The output string is stored in bufPtr.
|
||||
*/
|
||||
int
|
||||
Tcl_UtfToNormalized(
|
||||
Tcl_Interp *interp, /* Used for error messages. May be NULL */
|
||||
const char *bytes, /* Operand encoded in Tcl internal UTF8 */
|
||||
Tcl_Size numBytes, /* Length of bytes[], or -1 if NUL terminated */
|
||||
Tcl_UnicodeNormalizationForm normForm, /* TCL_{NFC,NFD,NFKC,NFKC} */
|
||||
int profile, /* TCL_ENCODING_PROFILE_{STRICT,REPLACE} */
|
||||
char *bufPtr, /* Pointer to output buffer. Must not be NULL. */
|
||||
Tcl_Size bufLen, /* Size of bufPtr storage. */
|
||||
Tcl_Size *lengthPtr) /* Length of the output string in bytes excluding
|
||||
* the trailing NUL byte. May be NULL */
|
||||
{
|
||||
Tcl_Encoding encoding = Tcl_GetEncoding(interp, "utf-8");
|
||||
if (encoding == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
utf8proc_uint8_t *normUtf8;
|
||||
utf8proc_ssize_t normLength;
|
||||
normLength = TclUtfNormalize(interp, bytes, numBytes, encoding, normForm,
|
||||
profile, &normUtf8);
|
||||
Tcl_FreeEncoding(encoding);
|
||||
if (normLength < 0) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
assert(normUtf8);
|
||||
|
||||
/* Convert standard UTF8 to internal UTF8 */
|
||||
int result;
|
||||
utf8proc_uint8_t *from = normUtf8;
|
||||
utf8proc_uint8_t *fromEnd = from + normLength;
|
||||
char *to = bufPtr;
|
||||
char *toEnd = to + bufLen - 1; /* -1 for trailing NUL */
|
||||
while (from < fromEnd && to < toEnd) {
|
||||
/*
|
||||
* The only difference between UTF-8 and internal UTF-8 is that
|
||||
* internal UTF-8 does not allow NUL bytes in the middle of the string.
|
||||
*/
|
||||
if (*from) {
|
||||
*to++ = *from++;
|
||||
} else {
|
||||
*to++ = 0xC0; /* NUL byte in internal UTF-8 is encoded as C080 */
|
||||
if (to == toEnd) {
|
||||
break;
|
||||
}
|
||||
*to++ = 0x80;
|
||||
from++;
|
||||
}
|
||||
}
|
||||
if (from < fromEnd) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("Output buffer too small.", -1));
|
||||
result = TCL_CONVERT_NOSPACE;
|
||||
} else {
|
||||
assert(to <= toEnd);
|
||||
*to = '\0'; /* NUL terminate the output */
|
||||
if (lengthPtr) {
|
||||
*lengthPtr = to-bufPtr;
|
||||
}
|
||||
result = TCL_OK;
|
||||
}
|
||||
|
||||
free(normUtf8); /* NOT Tcl_Free! */
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+19
-33
@@ -230,9 +230,8 @@ TclNamespaceEnsembleCmd(
|
||||
}
|
||||
|
||||
default:
|
||||
Tcl_Panic("unexpected ensemble command");
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -387,6 +386,8 @@ InitEnsembleFromOptions(
|
||||
}
|
||||
unknownObj = (len > 0 ? objv[1] : NULL);
|
||||
continue;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,6 +486,8 @@ ReadOneEnsembleOption(
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -715,6 +718,8 @@ SetEnsembleConfigOptions(
|
||||
}
|
||||
unknownObj = (len > 0 ? objv[1] : NULL);
|
||||
continue;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2744,7 +2749,7 @@ BuildEnsembleConfig(
|
||||
while (!done) {
|
||||
const char *name = TclGetString(keyObj);
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, NULL);
|
||||
Tcl_SetHashValue(hPtr, valueObj);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
|
||||
@@ -3255,18 +3260,7 @@ TclCompileEnsemble(
|
||||
* Throw out any line information generated by the failed compile attempt.
|
||||
*/
|
||||
|
||||
while (mapPtr->nuloc > eclIndex + 1) {
|
||||
mapPtr->nuloc--;
|
||||
Tcl_Free(mapPtr->loc[mapPtr->nuloc].line);
|
||||
mapPtr->loc[mapPtr->nuloc].line = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the index of next command. Toss out any from failed nested
|
||||
* partial compiles.
|
||||
*/
|
||||
|
||||
envPtr->numCommands = mapPtr->nuloc;
|
||||
ClearFailedCompile(envPtr);
|
||||
|
||||
/*
|
||||
* Failed to do a full compile for some reason. Try to do a direct invoke
|
||||
@@ -3326,7 +3320,7 @@ TclAttemptCompileProc(
|
||||
Tcl_Size i;
|
||||
Tcl_Token *saveTokenPtr = parsePtr->tokenPtr;
|
||||
Tcl_Size savedStackDepth = envPtr->currStackDepth;
|
||||
Tcl_Size savedCodeNext = envPtr->codeNext - envPtr->codeStart;
|
||||
Tcl_Size savedCodeNext = CurrentOffset(envPtr);
|
||||
Tcl_Size savedAuxDataArrayNext = envPtr->auxDataArrayNext;
|
||||
Tcl_Size savedExceptArrayNext = envPtr->exceptArrayNext;
|
||||
#ifdef TCL_COMPILE_DEBUG
|
||||
@@ -3354,8 +3348,8 @@ TclAttemptCompileProc(
|
||||
* index values.
|
||||
*/
|
||||
|
||||
mapPtr->loc[eclIndex].line += (depth - 1);
|
||||
mapPtr->loc[eclIndex].next += (depth - 1);
|
||||
ExtCmdLocation.line += (depth - 1);
|
||||
ExtCmdLocation.next += (depth - 1);
|
||||
|
||||
/*
|
||||
* Hand off compilation to the subcommand compiler. At last!
|
||||
@@ -3367,8 +3361,8 @@ TclAttemptCompileProc(
|
||||
* Undo the shift.
|
||||
*/
|
||||
|
||||
mapPtr->loc[eclIndex].line -= (depth - 1);
|
||||
mapPtr->loc[eclIndex].next -= (depth - 1);
|
||||
ExtCmdLocation.line -= (depth - 1);
|
||||
ExtCmdLocation.next -= (depth - 1);
|
||||
|
||||
parsePtr->numWords += (depth - 1);
|
||||
parsePtr->tokenPtr = saveTokenPtr;
|
||||
@@ -3458,9 +3452,8 @@ CompileToInvokedCommand(
|
||||
DefineLineInformation;
|
||||
Tcl_Token *tokPtr;
|
||||
Tcl_Obj *objPtr, **words;
|
||||
const char *bytes;
|
||||
int cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
|
||||
Tcl_Size i, numWords, length;
|
||||
Tcl_Size i, numWords;
|
||||
|
||||
/*
|
||||
* Push the words of the command. Take care; the command words may be
|
||||
@@ -3472,15 +3465,13 @@ CompileToInvokedCommand(
|
||||
for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;
|
||||
i++, tokPtr = TokenAfter(tokPtr)) {
|
||||
if (i > 0 && i <= numWords) {
|
||||
bytes = TclGetStringFromObj(words[i - 1], &length);
|
||||
PushLiteral(envPtr, bytes, length);
|
||||
PUSH_OBJ( words[i - 1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
SetLineInformation(i);
|
||||
if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) {
|
||||
int literal = TclRegisterLiteral(envPtr,
|
||||
tokPtr[1].start, tokPtr[1].size, 0);
|
||||
int literal = PUSH_SIMPLE_TOKEN(tokPtr);
|
||||
|
||||
if (envPtr->clNext) {
|
||||
TclContinuationsEnterDerived(
|
||||
@@ -3488,7 +3479,6 @@ CompileToInvokedCommand(
|
||||
tokPtr[1].start - envPtr->source,
|
||||
envPtr->clNext);
|
||||
}
|
||||
TclEmitPush(literal, envPtr);
|
||||
} else {
|
||||
CompileTokens(envPtr, tokPtr, interp);
|
||||
}
|
||||
@@ -3501,21 +3491,17 @@ CompileToInvokedCommand(
|
||||
|
||||
TclNewObj(objPtr);
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
|
||||
bytes = TclGetStringFromObj(objPtr, &length);
|
||||
if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
|
||||
extraLiteralFlags |= LITERAL_UNSHARED;
|
||||
}
|
||||
cmdLit = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags);
|
||||
cmdLit = PUSH_OBJ_FLAGS(objPtr, extraLiteralFlags);
|
||||
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);
|
||||
TclEmitPush(cmdLit, envPtr);
|
||||
TclDecrRefCount(objPtr);
|
||||
|
||||
/*
|
||||
* Do the replacing dispatch.
|
||||
*/
|
||||
|
||||
TclEmitInvoke(envPtr, INST_INVOKE_REPLACE, parsePtr->numWords,
|
||||
numWords + 1);
|
||||
INVOKE41( INVOKE_REPLACE, parsePtr->numWords, numWords+1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+16
-7
@@ -35,6 +35,13 @@ typedef struct BgError {
|
||||
* list. */
|
||||
} BgError;
|
||||
|
||||
/*
|
||||
* The assoc data key used in this file. The data associated with it is a
|
||||
* reference to an ErrAssocData structure, and will be deallocated with
|
||||
* BgErrorDeleteProc at the appropriate time.
|
||||
*/
|
||||
#define ASSOC_KEY "tclBgError"
|
||||
|
||||
/*
|
||||
* One of the structures below is associated with the "tclBgError" assoc data
|
||||
* for each interpreter. It keeps track of the head and tail of the list of
|
||||
@@ -182,7 +189,7 @@ Tcl_BackgroundException(
|
||||
errPtr->nextPtr = NULL;
|
||||
|
||||
(void) TclGetBgErrorHandler(interp);
|
||||
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
|
||||
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
if (assocPtr->firstBgPtr == NULL) {
|
||||
assocPtr->firstBgPtr = errPtr;
|
||||
Tcl_DoWhenIdle(HandleBgErrors, assocPtr);
|
||||
@@ -522,7 +529,7 @@ TclSetBgErrorHandler(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *cmdPrefix)
|
||||
{
|
||||
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
|
||||
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
|
||||
if (cmdPrefix == NULL) {
|
||||
Tcl_Panic("TclSetBgErrorHandler: NULL cmdPrefix argument");
|
||||
@@ -537,7 +544,7 @@ TclSetBgErrorHandler(
|
||||
assocPtr->cmdPrefix = NULL;
|
||||
assocPtr->firstBgPtr = NULL;
|
||||
assocPtr->lastBgPtr = NULL;
|
||||
Tcl_SetAssocData(interp, "tclBgError", BgErrorDeleteProc, assocPtr);
|
||||
Tcl_SetAssocData(interp, ASSOC_KEY, BgErrorDeleteProc, assocPtr);
|
||||
}
|
||||
if (assocPtr->cmdPrefix) {
|
||||
Tcl_DecrRefCount(assocPtr->cmdPrefix);
|
||||
@@ -567,14 +574,14 @@ Tcl_Obj *
|
||||
TclGetBgErrorHandler(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
|
||||
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
|
||||
if (assocPtr == NULL) {
|
||||
Tcl_Obj *bgerrorObj;
|
||||
|
||||
TclNewLiteralStringObj(bgerrorObj, "::tcl::Bgerror");
|
||||
TclSetBgErrorHandler(interp, bgerrorObj);
|
||||
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
|
||||
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
}
|
||||
return assocPtr->cmdPrefix;
|
||||
}
|
||||
@@ -1650,6 +1657,8 @@ Tcl_VwaitObjCmd(
|
||||
vwaitItems[numItems].sourceObj = objv[i];
|
||||
numItems++;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1725,7 +1734,7 @@ Tcl_VwaitObjCmd(
|
||||
|
||||
foundEvent = 1;
|
||||
while (!timedOut && foundEvent &&
|
||||
((!any && (done < numItems)) || (any && !done))) {
|
||||
((!any && (done < numItems)) || (any && !done))) {
|
||||
foundEvent = Tcl_DoOneEvent(mask);
|
||||
if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
|
||||
break;
|
||||
@@ -1967,7 +1976,7 @@ Tcl_UpdateObjCmd(
|
||||
flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT;
|
||||
break;
|
||||
default:
|
||||
Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions");
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
|
||||
|
||||
+1861
-1268
File diff suppressed because it is too large
Load Diff
+37
-43
@@ -26,6 +26,34 @@ static int FileCopyRename(Tcl_Interp *interp,
|
||||
static int FileForceOption(Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const objv[], int *forcePtr);
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* CheckFilenameEncodable
|
||||
*
|
||||
* This checks if a filename can be encoded on the target platform,
|
||||
* disallowing things like naked surrogates, etc.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* May update the interpreter result with an error message on failure.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
static inline int
|
||||
CheckFilenameEncodable(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *fileName)
|
||||
{
|
||||
Tcl_DString ds;
|
||||
int code = Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING,
|
||||
TclGetString(fileName), TCL_INDEX_NONE, 0, &ds, NULL);
|
||||
Tcl_DStringFree(&ds);
|
||||
return code == TCL_OK ? TCL_OK : TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
@@ -113,7 +141,6 @@ FileCopyRename(
|
||||
int i, result, force;
|
||||
Tcl_StatBuf statBuf;
|
||||
Tcl_Obj *target;
|
||||
Tcl_DString ds;
|
||||
|
||||
i = FileForceOption(interp, objc - 1, objv + 1, &force);
|
||||
if (i < 0) {
|
||||
@@ -135,12 +162,9 @@ FileCopyRename(
|
||||
if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(target),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, target) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
result = TCL_OK;
|
||||
|
||||
@@ -232,7 +256,6 @@ TclFileMakeDirsCmd(
|
||||
Tcl_Obj *split = NULL;
|
||||
Tcl_Obj *target = NULL;
|
||||
Tcl_StatBuf statBuf;
|
||||
Tcl_DString ds;
|
||||
|
||||
result = TCL_OK;
|
||||
for (i = 1; i < objc; i++) {
|
||||
@@ -240,13 +263,10 @@ TclFileMakeDirsCmd(
|
||||
result = TCL_ERROR;
|
||||
break;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[i]),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, objv[i]) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
break;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
split = Tcl_FSSplitPath(objv[i], &pobjc);
|
||||
Tcl_IncrRefCount(split);
|
||||
@@ -362,7 +382,6 @@ TclFileDeleteCmd(
|
||||
int i, force, result;
|
||||
Tcl_Obj *errfile;
|
||||
Tcl_Obj *errorBuffer = NULL;
|
||||
Tcl_DString ds;
|
||||
|
||||
i = FileForceOption(interp, objc - 1, objv + 1, &force);
|
||||
if (i < 0) {
|
||||
@@ -380,13 +399,10 @@ TclFileDeleteCmd(
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[i]),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, objv[i]) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
/*
|
||||
* Call lstat() to get info so can delete symbolic link itself.
|
||||
@@ -506,26 +522,19 @@ CopyRenameOneFile(
|
||||
Tcl_Obj *actualSource=NULL; /* If source is a link, then this is the real
|
||||
* file/directory. */
|
||||
Tcl_StatBuf sourceStatBuf, targetStatBuf;
|
||||
Tcl_DString ds;
|
||||
|
||||
if (Tcl_FSConvertToPathType(interp, source) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(source),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, source) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(target),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, target) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
errfile = NULL;
|
||||
errorBuffer = NULL;
|
||||
@@ -985,7 +994,6 @@ TclFileAttrsCmd(
|
||||
Tcl_Obj *objStrings = NULL;
|
||||
Tcl_Size numObjStrings = TCL_INDEX_NONE;
|
||||
Tcl_Obj *filePtr;
|
||||
Tcl_DString ds;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "name ?-option value ...?");
|
||||
@@ -996,12 +1004,9 @@ TclFileAttrsCmd(
|
||||
if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(filePtr),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, filePtr) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
objc -= 2;
|
||||
objv += 2;
|
||||
@@ -1204,7 +1209,6 @@ TclFileLinkCmd(
|
||||
{
|
||||
Tcl_Obj *contents;
|
||||
int index;
|
||||
Tcl_DString ds;
|
||||
|
||||
if (objc < 2 || objc > 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-linktype? linkname ?target?");
|
||||
@@ -1247,12 +1251,9 @@ TclFileLinkCmd(
|
||||
if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[index]),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, objv[index]) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
/*
|
||||
* Create link from source to target.
|
||||
@@ -1310,12 +1311,9 @@ TclFileLinkCmd(
|
||||
if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[index]),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, objv[index]) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
/*
|
||||
* Read link
|
||||
@@ -1367,7 +1365,6 @@ TclFileReadLinkCmd(
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Tcl_Obj *contents;
|
||||
Tcl_DString ds;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "name");
|
||||
@@ -1377,12 +1374,9 @@ TclFileReadLinkCmd(
|
||||
if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[1]),
|
||||
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (CheckFilenameEncodable(interp, objv[1]) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
contents = Tcl_FSLink(objv[1], NULL, 0);
|
||||
|
||||
|
||||
@@ -1233,6 +1233,8 @@ Tcl_GlobObjCmd(
|
||||
case GLOB_LAST: /* -- */
|
||||
i++;
|
||||
goto endOfForLoop;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+75
-45
@@ -13,6 +13,12 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
/*
|
||||
* Prevent macros from clashing with function definitions.
|
||||
*/
|
||||
|
||||
#undef Tcl_CreateHashEntry
|
||||
|
||||
/*
|
||||
* When there are this many entries per bucket, on average, rebuild the hash
|
||||
* table to make it larger.
|
||||
@@ -49,12 +55,13 @@ static Tcl_HashEntry * AllocStringEntry(Tcl_HashTable *tablePtr,
|
||||
* Function prototypes for static functions in this file:
|
||||
*/
|
||||
|
||||
static Tcl_HashEntry * BogusFind(Tcl_HashTable *tablePtr, const char *key);
|
||||
static Tcl_HashEntry * BogusCreate(Tcl_HashTable *tablePtr, const char *key,
|
||||
int *newPtr);
|
||||
static Tcl_HashEntry * CreateHashEntry(Tcl_HashTable *tablePtr, const char *key,
|
||||
int *newPtr);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
static Tcl_HashEntry * FindHashEntry(Tcl_HashTable *tablePtr, const char *key);
|
||||
#endif
|
||||
static void RebuildTable(Tcl_HashTable *tablePtr);
|
||||
|
||||
const Tcl_HashKeyType tclArrayHashKeyType = {
|
||||
@@ -164,7 +171,9 @@ Tcl_InitCustomHashTable(
|
||||
tablePtr->downShift = 28;
|
||||
tablePtr->mask = 3;
|
||||
tablePtr->keyType = keyType;
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
tablePtr->findProc = FindHashEntry;
|
||||
#endif
|
||||
tablePtr->createProc = CreateHashEntry;
|
||||
|
||||
if (typePtr == NULL) {
|
||||
@@ -203,18 +212,20 @@ Tcl_InitCustomHashTable(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
static Tcl_HashEntry *
|
||||
FindHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
const char *key) /* Key to use to find matching entry. */
|
||||
{
|
||||
return CreateHashEntry(tablePtr, key, NULL);
|
||||
return tablePtr->createProc(tablePtr, key, TCL_HASH_FIND);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* CreateHashEntry --
|
||||
* Tcl_CreateHashEntry --
|
||||
*
|
||||
* Given a hash table with string keys, and a string key, find the entry
|
||||
* with a matching key. If there is no matching entry, then create a new
|
||||
@@ -232,6 +243,38 @@ FindHashEntry(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_HashEntry *
|
||||
Tcl_CreateHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
const void *key, /* Key to use to find or create matching
|
||||
* entry. */
|
||||
int *newPtr) /* Store info here telling whether a new entry
|
||||
* was created. */
|
||||
{
|
||||
Tcl_HashEntry *entry = (*((tablePtr)->createProc))(tablePtr, (const char *)key, newPtr);
|
||||
if (!entry) {
|
||||
Tcl_Panic("%s: Memory overflow", "Tcl_CreateHashEntry");
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
Tcl_HashEntry *
|
||||
Tcl_DbCreateHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
const void *key, /* Key to use to find or create matching
|
||||
* entry. */
|
||||
int *newPtr, /* Store info here telling whether a new entry
|
||||
* was created. */
|
||||
const char *file,
|
||||
int line)
|
||||
{
|
||||
Tcl_HashEntry *entry = (*((tablePtr)->createProc))(tablePtr, (const char *)key, newPtr);
|
||||
if (!entry) {
|
||||
Tcl_Panic("%s: Memory overflow in file %s:%d", "Tcl_CreateHashEntry", file, line);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
static Tcl_HashEntry *
|
||||
CreateHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
@@ -282,7 +325,7 @@ CreateHashEntry(
|
||||
/* if keys pointers or values are equal */
|
||||
if ((key == hPtr->key.oneWordValue)
|
||||
|| compareKeysProc((void *) key, hPtr)) {
|
||||
if (newPtr) {
|
||||
if (newPtr && (newPtr != TCL_HASH_FIND)) {
|
||||
*newPtr = 0;
|
||||
}
|
||||
return hPtr;
|
||||
@@ -297,7 +340,7 @@ CreateHashEntry(
|
||||
/* if needle pointer equals content pointer or values equal */
|
||||
if ((key == hPtr->key.string)
|
||||
|| compareKeysProc((void *) key, hPtr)) {
|
||||
if (newPtr) {
|
||||
if (newPtr && (newPtr != TCL_HASH_FIND)) {
|
||||
*newPtr = 0;
|
||||
}
|
||||
return hPtr;
|
||||
@@ -311,7 +354,7 @@ CreateHashEntry(
|
||||
continue;
|
||||
}
|
||||
if (key == hPtr->key.oneWordValue) {
|
||||
if (newPtr) {
|
||||
if (newPtr && (newPtr != TCL_HASH_FIND)) {
|
||||
*newPtr = 0;
|
||||
}
|
||||
return hPtr;
|
||||
@@ -319,7 +362,8 @@ CreateHashEntry(
|
||||
}
|
||||
}
|
||||
|
||||
if (!newPtr) {
|
||||
if (newPtr == TCL_HASH_FIND) {
|
||||
/* This is the findProc functionality, so we are done. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -327,11 +371,16 @@ CreateHashEntry(
|
||||
* Entry not found. Add a new one to the bucket.
|
||||
*/
|
||||
|
||||
*newPtr = 1;
|
||||
if (newPtr) {
|
||||
*newPtr = 1;
|
||||
}
|
||||
if (typePtr->allocEntryProc) {
|
||||
hPtr = typePtr->allocEntryProc(tablePtr, (void *) key);
|
||||
} else {
|
||||
hPtr = (Tcl_HashEntry *)Tcl_Alloc(sizeof(Tcl_HashEntry));
|
||||
hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(sizeof(Tcl_HashEntry));
|
||||
if (!hPtr) {
|
||||
return NULL;
|
||||
}
|
||||
hPtr->key.oneWordValue = (char *) key;
|
||||
Tcl_SetHashValue(hPtr, NULL);
|
||||
}
|
||||
@@ -495,7 +544,9 @@ Tcl_DeleteHashTable(
|
||||
* re-initialization.
|
||||
*/
|
||||
|
||||
tablePtr->findProc = BogusFind;
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
tablePtr->findProc = FindHashEntry;
|
||||
#endif
|
||||
tablePtr->createProc = BogusCreate;
|
||||
}
|
||||
|
||||
@@ -675,10 +726,12 @@ AllocArrayEntry(
|
||||
if (size < sizeof(Tcl_HashEntry)) {
|
||||
size = sizeof(Tcl_HashEntry);
|
||||
}
|
||||
hPtr = (Tcl_HashEntry *)Tcl_Alloc(size);
|
||||
hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(size);
|
||||
|
||||
memcpy(hPtr->key.string, keyPtr, count);
|
||||
Tcl_SetHashValue(hPtr, NULL);
|
||||
if (hPtr) {
|
||||
memcpy(hPtr->key.string, keyPtr, count);
|
||||
Tcl_SetHashValue(hPtr, NULL);
|
||||
}
|
||||
|
||||
return hPtr;
|
||||
}
|
||||
@@ -773,10 +826,12 @@ AllocStringEntry(
|
||||
if (size < sizeof(hPtr->key)) {
|
||||
allocsize = sizeof(hPtr->key);
|
||||
}
|
||||
hPtr = (Tcl_HashEntry *)Tcl_Alloc(offsetof(Tcl_HashEntry, key) + allocsize);
|
||||
memset(hPtr, 0, offsetof(Tcl_HashEntry, key) + allocsize);
|
||||
memcpy(hPtr->key.string, string, size);
|
||||
Tcl_SetHashValue(hPtr, NULL);
|
||||
hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(offsetof(Tcl_HashEntry, key) + allocsize);
|
||||
if (hPtr) {
|
||||
memset(hPtr, 0, offsetof(Tcl_HashEntry, key) + allocsize);
|
||||
memcpy(hPtr->key.string, string, size);
|
||||
Tcl_SetHashValue(hPtr, NULL);
|
||||
}
|
||||
return hPtr;
|
||||
}
|
||||
|
||||
@@ -871,32 +926,6 @@ TclHashStringKey(
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* BogusFind --
|
||||
*
|
||||
* This function is invoked when Tcl_FindHashEntry is called on a
|
||||
* table that has been deleted.
|
||||
*
|
||||
* Results:
|
||||
* If Tcl_Panic returns (which it shouldn't) this function returns NULL.
|
||||
*
|
||||
* Side effects:
|
||||
* Generates a panic.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static Tcl_HashEntry *
|
||||
BogusFind(
|
||||
TCL_UNUSED(Tcl_HashTable *),
|
||||
TCL_UNUSED(const char *))
|
||||
{
|
||||
Tcl_Panic("called %s on deleted table", "Tcl_FindHashEntry");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -918,9 +947,10 @@ static Tcl_HashEntry *
|
||||
BogusCreate(
|
||||
TCL_UNUSED(Tcl_HashTable *),
|
||||
TCL_UNUSED(const char *),
|
||||
TCL_UNUSED(int *))
|
||||
int *isNew)
|
||||
{
|
||||
Tcl_Panic("called %s on deleted table", "Tcl_CreateHashEntry");
|
||||
Tcl_Panic("called %s on deleted table",
|
||||
(isNew != TCL_HASH_FIND)? "Tcl_CreateHashEntry" : "Tcl_FindHashEntry");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+32
-20
@@ -137,6 +137,12 @@ typedef struct {
|
||||
|
||||
static Tcl_ThreadDataKey dataKey;
|
||||
|
||||
/*
|
||||
* Key for looking up the channel table (a Tcl_HashTable indexed by channel
|
||||
* name) in the interpreter's associated data table.
|
||||
*/
|
||||
#define ASSOC_KEY "tclIO"
|
||||
|
||||
/*
|
||||
* Structure to record a close callback. One such record exists for
|
||||
* each close callback registered for a channel.
|
||||
@@ -360,8 +366,8 @@ static const Tcl_ObjType chanObjType = {
|
||||
} while (0)
|
||||
|
||||
#define BUSY_STATE(st, fl) \
|
||||
((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
|
||||
(((st)->csPtrW) && ((fl) & TCL_WRITABLE)))
|
||||
((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
|
||||
(((st)->csPtrW) && ((fl) & TCL_WRITABLE)))
|
||||
|
||||
#define MAX_CHANNEL_BUFFER_SIZE (1024*1024)
|
||||
|
||||
@@ -738,8 +744,10 @@ Tcl_SetStdChannel(
|
||||
tsdPtr->stderrInitialized = init;
|
||||
tsdPtr->stderrChannel = channel;
|
||||
if (channel) {
|
||||
ENCODING_PROFILE_SET(((Channel *)channel)->state->inputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
|
||||
ENCODING_PROFILE_SET(((Channel *)channel)->state->outputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
|
||||
ENCODING_PROFILE_SET(((Channel *)channel)->state->inputEncodingFlags,
|
||||
TCL_ENCODING_PROFILE_REPLACE);
|
||||
ENCODING_PROFILE_SET(((Channel *)channel)->state->outputEncodingFlags,
|
||||
TCL_ENCODING_PROFILE_REPLACE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -811,8 +819,10 @@ Tcl_GetStdChannel(
|
||||
tsdPtr->stderrInitialized = -1;
|
||||
tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
|
||||
if (tsdPtr->stderrChannel != NULL) {
|
||||
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->inputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
|
||||
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->outputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
|
||||
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->inputEncodingFlags,
|
||||
TCL_ENCODING_PROFILE_REPLACE);
|
||||
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->outputEncodingFlags,
|
||||
TCL_ENCODING_PROFILE_REPLACE);
|
||||
tsdPtr->stderrInitialized = 1;
|
||||
Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
|
||||
}
|
||||
@@ -932,11 +942,11 @@ GetChannelTable(
|
||||
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
|
||||
Tcl_Channel stdinChan, stdoutChan, stderrChan;
|
||||
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclIO", NULL);
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
if (hTblPtr == NULL) {
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
|
||||
Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS);
|
||||
Tcl_SetAssocData(interp, "tclIO",
|
||||
Tcl_SetAssocData(interp, ASSOC_KEY,
|
||||
(Tcl_InterpDeleteProc *) DeleteChannelTable, hTblPtr);
|
||||
|
||||
/*
|
||||
@@ -1372,7 +1382,7 @@ DetachChannel(
|
||||
statePtr = chanPtr->state;
|
||||
|
||||
if (interp != NULL) {
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclIO", NULL);
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
if (hTblPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1617,10 +1627,12 @@ Tcl_CreateChannel(
|
||||
Tcl_Panic("channel type %s must define close2Proc", typePtr->typeName);
|
||||
}
|
||||
if ((TCL_READABLE & mask) && (NULL == typePtr->inputProc)) {
|
||||
Tcl_Panic("channel type %s must define inputProc when used for reader channel", typePtr->typeName);
|
||||
Tcl_Panic("channel type %s must define inputProc when used for reader channel",
|
||||
typePtr->typeName);
|
||||
}
|
||||
if ((TCL_WRITABLE & mask) && (NULL == typePtr->outputProc)) {
|
||||
Tcl_Panic("channel type %s must define outputProc when used for writer channel", typePtr->typeName);
|
||||
Tcl_Panic("channel type %s must define outputProc when used for writer channel",
|
||||
typePtr->typeName);
|
||||
}
|
||||
if (NULL == typePtr->watchProc) {
|
||||
Tcl_Panic("channel type %s must define watchProc", typePtr->typeName);
|
||||
@@ -2438,9 +2450,9 @@ Tcl_GetChannelHandle(
|
||||
|
||||
int
|
||||
Tcl_RemoveChannelMode(
|
||||
Tcl_Interp *interp, /* The interp for an error message. Allowed to be NULL. */
|
||||
Tcl_Channel chan, /* The channel which is modified. */
|
||||
int mode) /* The access mode to drop from the channel */
|
||||
Tcl_Interp *interp, /* The interp for an error message. Allowed to be NULL. */
|
||||
Tcl_Channel chan, /* The channel which is modified. */
|
||||
int mode) /* The access mode to drop from the channel */
|
||||
{
|
||||
const char* emsg;
|
||||
ChannelState *statePtr = ((Channel *) chan)->state;
|
||||
@@ -2458,7 +2470,7 @@ Tcl_RemoveChannelMode(
|
||||
ResetFlag(statePtr, mode);
|
||||
return TCL_OK;
|
||||
|
||||
error:
|
||||
error:
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"Tcl_RemoveChannelMode error: %s. Channel: \"%s\"",
|
||||
@@ -9423,7 +9435,8 @@ TclCopyChannel(
|
||||
* completed.
|
||||
*/
|
||||
|
||||
csPtr = (CopyState *)Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize);
|
||||
csPtr = (CopyState *)
|
||||
Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize);
|
||||
csPtr->bufSize = !moveBytes * inStatePtr->bufSize;
|
||||
csPtr->readPtr = inPtr;
|
||||
csPtr->writePtr = outPtr;
|
||||
@@ -9802,7 +9815,7 @@ CopyData(
|
||||
|
||||
if (moveBytes) {
|
||||
size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb,
|
||||
!GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
|
||||
!GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
|
||||
} else {
|
||||
size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb,
|
||||
!GotFlag(inStatePtr, CHANNEL_NONBLOCKING)
|
||||
@@ -10165,8 +10178,7 @@ DoRead(
|
||||
}
|
||||
|
||||
if (!bufPtr) {
|
||||
readErr:
|
||||
|
||||
readErr:
|
||||
UpdateInterest(chanPtr);
|
||||
TclChannelRelease((Tcl_Channel)chanPtr);
|
||||
return -1;
|
||||
@@ -10702,7 +10714,7 @@ Tcl_IsChannelRegistered(
|
||||
chanPtr = ((Channel *) chan)->state->bottomChanPtr;
|
||||
statePtr = chanPtr->state;
|
||||
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclIO", NULL);
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
if (hTblPtr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+62
-18
@@ -34,6 +34,13 @@ typedef struct {
|
||||
|
||||
static Tcl_ThreadDataKey dataKey;
|
||||
|
||||
/*
|
||||
* Key for looking up the table of registered TCP accept callbacks, a hash
|
||||
* table indexed by AcceptCallback references, used as a set (values are
|
||||
* meaningless).
|
||||
*/
|
||||
#define ASSOC_KEY "tclTCPAcceptCallbacks"
|
||||
|
||||
/*
|
||||
* Static functions for this file:
|
||||
*/
|
||||
@@ -135,7 +142,7 @@ Tcl_PutsObjCmd(
|
||||
string = objv[3];
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
TCL_FALLTHROUGH();
|
||||
default: /* [puts] or
|
||||
* [puts some bad number of arguments...] */
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channel? string");
|
||||
@@ -910,11 +917,12 @@ Tcl_ExecObjCmd(
|
||||
int argc, background, i, index, keepNewline, result, skip, ignoreStderr;
|
||||
Tcl_Size length;
|
||||
static const char *const options[] = {
|
||||
"-ignorestderr", "-keepnewline", "--", NULL
|
||||
"-ignorestderr", "-keepnewline", "-encoding", "--", NULL
|
||||
};
|
||||
enum execOptionsEnum {
|
||||
EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_LAST
|
||||
EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_ENCODING, EXEC_LAST
|
||||
};
|
||||
Tcl_Obj *encodingObj = NULL;
|
||||
|
||||
/*
|
||||
* Check for any leading option arguments.
|
||||
@@ -931,14 +939,34 @@ Tcl_ExecObjCmd(
|
||||
TCL_EXACT, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (index == EXEC_KEEPNEWLINE) {
|
||||
keepNewline = 1;
|
||||
} else if (index == EXEC_IGNORESTDERR) {
|
||||
ignoreStderr = 1;
|
||||
} else {
|
||||
if (index == EXEC_LAST) {
|
||||
skip++;
|
||||
break;
|
||||
}
|
||||
switch (index) {
|
||||
case EXEC_KEEPNEWLINE:
|
||||
keepNewline = 1;
|
||||
break;
|
||||
case EXEC_IGNORESTDERR:
|
||||
ignoreStderr = 1;
|
||||
break;
|
||||
case EXEC_ENCODING:
|
||||
if (++skip >= objc) {
|
||||
Tcl_SetResult(interp, "No value given for option -encoding.",
|
||||
TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
} else {
|
||||
Tcl_Encoding encoding;
|
||||
encodingObj = objv[skip];
|
||||
/* Verify validity - bug [da5e1bc7bc] */
|
||||
if (Tcl_GetEncodingFromObj(interp, encodingObj, &encoding)
|
||||
!= TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_FreeEncoding(encoding);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (objc <= skip) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? arg ?arg ...?");
|
||||
@@ -986,11 +1014,6 @@ Tcl_ExecObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* Bug [0f1ddc0df7] - encoding errors - use replace profile */
|
||||
if (Tcl_SetChannelOption(NULL, chan, "-profile", "replace") != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (background) {
|
||||
/*
|
||||
* Store the list of PIDs from the pipeline in interp's result and
|
||||
@@ -1004,6 +1027,18 @@ Tcl_ExecObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* Bug [0f1ddc0df7] - encoding errors - use replace profile */
|
||||
if (Tcl_SetChannelOption(interp, chan, "-profile", "replace") != TCL_OK) {
|
||||
goto errorWithOpenChannel;
|
||||
}
|
||||
|
||||
/* TIP 716 */
|
||||
if (encodingObj &&
|
||||
Tcl_SetChannelOption(interp, chan, "-encoding",
|
||||
Tcl_GetString(encodingObj)) != TCL_OK) {
|
||||
goto errorWithOpenChannel;
|
||||
}
|
||||
|
||||
TclNewObj(resultPtr);
|
||||
if (Tcl_GetChannelHandle(chan, TCL_READABLE, NULL) == TCL_OK) {
|
||||
if (Tcl_ReadChars(chan, resultPtr, -1, 0) == TCL_IO_FAILURE) {
|
||||
@@ -1020,7 +1055,7 @@ Tcl_ExecObjCmd(
|
||||
Tcl_PosixError(interp)));
|
||||
Tcl_DecrRefCount(resultPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
goto errorWithOpenChannel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1047,6 +1082,11 @@ Tcl_ExecObjCmd(
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
|
||||
return result;
|
||||
|
||||
errorWithOpenChannel:
|
||||
/* Interpreter should already contain error. Pass NULL to not overwrite */
|
||||
(void)Tcl_CloseEx(NULL, chan, 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1291,12 +1331,12 @@ RegisterTcpServerInterpCleanup(
|
||||
Tcl_HashEntry *hPtr; /* Entry for this record. */
|
||||
int isNew; /* Is the entry new? */
|
||||
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
|
||||
if (hTblPtr == NULL) {
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
|
||||
Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS);
|
||||
Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks",
|
||||
Tcl_SetAssocData(interp, ASSOC_KEY,
|
||||
TcpAcceptCallbacksDeleteProc, hTblPtr);
|
||||
}
|
||||
|
||||
@@ -1337,7 +1377,7 @@ UnregisterTcpServerInterpCleanupProc(
|
||||
Tcl_HashTable *hTblPtr;
|
||||
Tcl_HashEntry *hPtr;
|
||||
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
|
||||
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
if (hTblPtr == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -1605,7 +1645,7 @@ Tcl_SocketObjCmd(
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions");
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (server) {
|
||||
@@ -1810,6 +1850,8 @@ Tcl_FcopyObjCmd(
|
||||
case FcopyCommand:
|
||||
cmdPtr = objv[i+1];
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1876,6 +1918,8 @@ ChanPendingObjCmd(
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_OutputBuffered(chan)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+2
-2
@@ -267,8 +267,8 @@ TclChannelTransform(
|
||||
}
|
||||
|
||||
if (TCL_OK != TclListObjLength(interp, cmdObjPtr, &objc)) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("-command value is not a list", -1));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"-command value is not a list", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+19
-16
@@ -461,8 +461,9 @@ static const char *msg_seek_beforestart = "{Tried to seek before origin}";
|
||||
#if TCL_THREADS
|
||||
static const char *msg_send_originlost = "{Channel thread lost}";
|
||||
#endif /* TCL_THREADS */
|
||||
static const char *msg_send_dstlost = "{Owner lost}";
|
||||
static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}";
|
||||
static const char *msg_send_dstlost = "{Owner lost}";
|
||||
static const char *msg_dstlost =
|
||||
"-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}";
|
||||
|
||||
/*
|
||||
* Main methods to plug into the 'chan' ensemble'. ==================
|
||||
@@ -722,7 +723,7 @@ TclChanCreateObjCmd(
|
||||
#if TCL_THREADS
|
||||
rcmPtr = GetThreadReflectedChannelMap();
|
||||
hPtr = Tcl_CreateHashEntry(&rcmPtr->map, chanPtr->state->channelName,
|
||||
&isNew);
|
||||
NULL);
|
||||
Tcl_SetHashValue(hPtr, chan);
|
||||
#endif
|
||||
|
||||
@@ -913,8 +914,8 @@ TclChanPostEventObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (events == 0) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("bad event list: is empty", -1));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"bad event list: is empty", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1350,14 +1351,14 @@ ReflectInput(
|
||||
memcpy(buf, bytev, bytec);
|
||||
}
|
||||
|
||||
stop:
|
||||
stop:
|
||||
Tcl_DecrRefCount(toReadObj);
|
||||
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
|
||||
Tcl_Release(rcPtr);
|
||||
return bytec;
|
||||
invalid:
|
||||
invalid:
|
||||
*errorCodePtr = EINVAL;
|
||||
error:
|
||||
error:
|
||||
bytec = -1;
|
||||
goto stop;
|
||||
}
|
||||
@@ -1478,15 +1479,15 @@ ReflectOutput(
|
||||
}
|
||||
|
||||
*errorCodePtr = EOK;
|
||||
stop:
|
||||
stop:
|
||||
Tcl_DecrRefCount(bufObj);
|
||||
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
|
||||
Tcl_Release(rcPtr->interp);
|
||||
Tcl_Release(rcPtr);
|
||||
return written;
|
||||
invalid:
|
||||
invalid:
|
||||
*errorCodePtr = EINVAL;
|
||||
error:
|
||||
error:
|
||||
written = -1;
|
||||
goto stop;
|
||||
}
|
||||
@@ -1571,13 +1572,13 @@ ReflectSeekWide(
|
||||
}
|
||||
|
||||
*errorCodePtr = EOK;
|
||||
stop:
|
||||
stop:
|
||||
Tcl_DecrRefCount(offObj);
|
||||
Tcl_DecrRefCount(baseObj);
|
||||
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
|
||||
Tcl_Release(rcPtr);
|
||||
return newLoc;
|
||||
invalid:
|
||||
invalid:
|
||||
*errorCodePtr = EINVAL;
|
||||
newLoc = -1;
|
||||
goto stop;
|
||||
@@ -1971,16 +1972,16 @@ ReflectGetOption(
|
||||
goto ok;
|
||||
}
|
||||
|
||||
ok:
|
||||
ok:
|
||||
result = TCL_OK;
|
||||
stop:
|
||||
stop:
|
||||
if (optionObj) {
|
||||
Tcl_DecrRefCount(optionObj);
|
||||
}
|
||||
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
|
||||
Tcl_Release(rcPtr);
|
||||
return result;
|
||||
error:
|
||||
error:
|
||||
result = TCL_ERROR;
|
||||
goto stop;
|
||||
}
|
||||
@@ -2108,6 +2109,8 @@ EncodeEventMask(
|
||||
case EVENT_WRITE:
|
||||
events |= TCL_WRITABLE;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
listc --;
|
||||
}
|
||||
|
||||
@@ -695,7 +695,7 @@ TclChanPushObjCmd(
|
||||
Tcl_SetHashValue(hPtr, rtPtr);
|
||||
#if TCL_THREADS
|
||||
rtmPtr = GetThreadReflectedTransformMap();
|
||||
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), &isNew);
|
||||
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), NULL);
|
||||
Tcl_SetHashValue(hPtr, rtPtr);
|
||||
#endif /* TCL_THREADS */
|
||||
|
||||
@@ -1211,7 +1211,7 @@ ReflectInput(
|
||||
Tcl_SetByteArrayLength(bufObj, 0);
|
||||
} /* while toRead > 0 */
|
||||
|
||||
stop:
|
||||
stop:
|
||||
if (gotBytes == 0) {
|
||||
rtPtr->eofPending = 0;
|
||||
}
|
||||
@@ -1219,7 +1219,7 @@ ReflectInput(
|
||||
Tcl_Release(rtPtr);
|
||||
return gotBytes;
|
||||
|
||||
error:
|
||||
error:
|
||||
gotBytes = -1;
|
||||
goto stop;
|
||||
}
|
||||
|
||||
@@ -336,6 +336,25 @@ Tcl_OpenTcpServer(
|
||||
-1, acceptProc, callbackData);
|
||||
}
|
||||
|
||||
#ifdef TCL_SOCK_PRINTF_DEBUGGING
|
||||
/* printf debugging */
|
||||
void
|
||||
printaddrinfo(
|
||||
struct addrinfo *addrlist,
|
||||
char *prefix)
|
||||
{
|
||||
char host[NI_MAXHOST], port[NI_MAXSERV];
|
||||
struct addrinfo *ai;
|
||||
|
||||
for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
|
||||
getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
host, sizeof(host), port, sizeof(port),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV);
|
||||
fprintf(stderr,"%s: %s:%s\n", prefix, host, port);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+15
-15
@@ -255,8 +255,7 @@ Tcl_Stat(
|
||||
Tcl_WideInt tmp1, tmp2, tmp3 = 0;
|
||||
|
||||
# define OUT_OF_RANGE(x) \
|
||||
(((Tcl_WideInt)(x)) < LONG_MIN || \
|
||||
((Tcl_WideInt)(x)) > LONG_MAX)
|
||||
(((Tcl_WideInt)(x)) < LONG_MIN || ((Tcl_WideInt)(x)) > LONG_MAX)
|
||||
# define OUT_OF_URANGE(x) \
|
||||
(((Tcl_WideUInt)(x)) > ((Tcl_WideUInt)ULONG_MAX))
|
||||
|
||||
@@ -2783,7 +2782,7 @@ Tcl_FSGetCwd(
|
||||
norm = TclFSNormalizeAbsolutePath(interp, retVal);
|
||||
|
||||
if (norm == NULL) {
|
||||
/*
|
||||
/*
|
||||
* 'norm' shouldn't ever be NULL, but we are careful.
|
||||
*/
|
||||
|
||||
@@ -2794,7 +2793,7 @@ Tcl_FSGetCwd(
|
||||
} else if (norm == tsdPtr->cwdPathPtr) {
|
||||
goto cdEqual;
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* Determine whether the filesystem's answer is the same as the
|
||||
* cached local value. Since both 'norm' and 'tsdPtr->cwdPathPtr'
|
||||
* are normalized pathnames, do something more efficient than
|
||||
@@ -2900,7 +2899,7 @@ Tcl_FSChdir(
|
||||
|
||||
retVal = 0;
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* 'Tcl_SetErrno()' has already been called.
|
||||
*/
|
||||
}
|
||||
@@ -2910,9 +2909,8 @@ Tcl_FSChdir(
|
||||
}
|
||||
|
||||
if (retVal == 0) {
|
||||
|
||||
/* Assume that the cwd was actually changed to the normalized value
|
||||
* just calculated, and cache that information. */
|
||||
/* Assume that the cwd was actually changed to the normalized value
|
||||
* just calculated, and cache that information. */
|
||||
|
||||
/*
|
||||
* If the filesystem epoch changed recently, the normalized pathname or
|
||||
@@ -2929,6 +2927,7 @@ Tcl_FSChdir(
|
||||
Tcl_SetErrno(ENOENT);
|
||||
return -1;
|
||||
}
|
||||
if (normDirName != pathPtr) { Tcl_IncrRefCount(normDirName); }
|
||||
|
||||
if (fsPtr == &tclNativeFilesystem) {
|
||||
void *cd;
|
||||
@@ -2980,6 +2979,7 @@ Tcl_FSChdir(
|
||||
*/
|
||||
Tcl_FSMountsChanged(NULL);
|
||||
}
|
||||
if (normDirName != pathPtr) { Tcl_DecrRefCount(normDirName); }
|
||||
} else {
|
||||
/*
|
||||
* The current directory is now changed or an error occurred and an
|
||||
@@ -3094,7 +3094,7 @@ Tcl_FSLoadFile(
|
||||
#endif
|
||||
|
||||
static int
|
||||
skipUnlink(
|
||||
SkipUnlink(
|
||||
Tcl_Obj *shlibFile)
|
||||
{
|
||||
/*
|
||||
@@ -3284,9 +3284,9 @@ Tcl_LoadFile(
|
||||
* load further.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Try to delete the file we probably created and then exit.
|
||||
*/
|
||||
/*
|
||||
* Try to delete the file we probably created and then exit.
|
||||
*/
|
||||
|
||||
Tcl_FSDeleteFile(copyToPtr);
|
||||
Tcl_DecrRefCount(copyToPtr);
|
||||
@@ -3307,14 +3307,14 @@ Tcl_LoadFile(
|
||||
/*
|
||||
* It might be necessary on some systems to set the appropriate permissions
|
||||
* on the file. On Unix we could loop over the file attributes and set any
|
||||
* that are called "-permissions" to 0700, but just do it directly instead:
|
||||
* that are called "-permissions" to 0o700, but just do it directly instead:
|
||||
*/
|
||||
|
||||
{
|
||||
Tcl_Size index;
|
||||
Tcl_Obj *perm;
|
||||
|
||||
TclNewLiteralStringObj(perm, "0700");
|
||||
TclNewLiteralStringObj(perm, "0o700");
|
||||
Tcl_IncrRefCount(perm);
|
||||
if (TclFSFileAttrIndex(copyToPtr, "-permissions", &index) == TCL_OK) {
|
||||
Tcl_FSFileAttrsSet(NULL, index, copyToPtr, perm);
|
||||
@@ -3345,7 +3345,7 @@ Tcl_LoadFile(
|
||||
* and it avoids leaving the copy laying around after exit.
|
||||
*/
|
||||
|
||||
if (!skipUnlink(copyToPtr) &&
|
||||
if (!SkipUnlink(copyToPtr) &&
|
||||
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
|
||||
Tcl_DecrRefCount(copyToPtr);
|
||||
|
||||
|
||||
+85
-116
@@ -45,9 +45,9 @@ typedef enum {
|
||||
} UConverterCallbackReasonx;
|
||||
|
||||
typedef enum UNormalizationCheckResultx {
|
||||
UNORM_NO,
|
||||
UNORM_YES,
|
||||
UNORM_MAYBE
|
||||
UNORM_NO,
|
||||
UNORM_YES,
|
||||
UNORM_MAYBE
|
||||
} UNormalizationCheckResultx;
|
||||
|
||||
typedef struct UEnumeration UEnumeration;
|
||||
@@ -59,50 +59,31 @@ typedef struct UConverter UConverter;
|
||||
typedef struct UConverterFromUnicodeArgs UConverterFromUnicodeArgs;
|
||||
typedef struct UConverterToUnicodeArgs UConverterToUnicodeArgs;
|
||||
typedef void (*UConverterFromUCallback)(const void *context,
|
||||
UConverterFromUnicodeArgs *args,
|
||||
const UCharx *codeUnits,
|
||||
int32_t length, UChar32x codePoint,
|
||||
UConverterCallbackReasonx reason,
|
||||
UErrorCodex *pErrorCode);
|
||||
UConverterFromUnicodeArgs *args, const UCharx *codeUnits,
|
||||
int32_t length, UChar32x codePoint, UConverterCallbackReasonx reason,
|
||||
UErrorCodex *pErrorCode);
|
||||
typedef void (*UConverterToUCallback)(const void *context,
|
||||
UConverterToUnicodeArgs *args,
|
||||
const char *codeUnits,
|
||||
int32_t length,
|
||||
UConverterCallbackReasonx reason,
|
||||
UErrorCodex *pErrorCode);
|
||||
UConverterToUnicodeArgs *args, const char *codeUnits,
|
||||
int32_t length, UConverterCallbackReasonx reason,
|
||||
UErrorCodex *pErrorCode);
|
||||
/*
|
||||
* Prototypes for ICU functions sorted by category.
|
||||
*/
|
||||
typedef void (*fn_u_cleanup)(void);
|
||||
typedef const char *(*fn_u_errorName)(UErrorCodex);
|
||||
typedef UCharx *(*fn_u_strFromUTF32)(UCharx *dest,
|
||||
int32_t destCapacity,
|
||||
int32_t *pDestLength,
|
||||
const UChar32x *src,
|
||||
int32_t srcLength,
|
||||
UErrorCodex *pErrorCode);
|
||||
typedef UCharx *(*fn_u_strFromUTF32WithSub)(UCharx *dest,
|
||||
int32_t destCapacity,
|
||||
int32_t *pDestLength,
|
||||
const UChar32x *src,
|
||||
int32_t srcLength,
|
||||
UChar32x subchar,
|
||||
int32_t *pNumSubstitutions,
|
||||
UErrorCodex *pErrorCode);
|
||||
typedef UChar32x *(*fn_u_strToUTF32)(UChar32x *dest,
|
||||
int32_t destCapacity,
|
||||
int32_t *pDestLength,
|
||||
const UCharx *src,
|
||||
int32_t srcLength,
|
||||
UErrorCodex *pErrorCode);
|
||||
typedef UCharx *(*fn_u_strFromUTF32)(UCharx *dest, int32_t destCapacity,
|
||||
int32_t *pDestLength, const UChar32x *src, int32_t srcLength,
|
||||
UErrorCodex *pErrorCode);
|
||||
typedef UCharx *(*fn_u_strFromUTF32WithSub)(UCharx *dest, int32_t destCapacity,
|
||||
int32_t *pDestLength, const UChar32x *src, int32_t srcLength,
|
||||
UChar32x subchar, int32_t *pNumSubstitutions, UErrorCodex *pErrorCode);
|
||||
typedef UChar32x *(*fn_u_strToUTF32)(UChar32x *dest, int32_t destCapacity,
|
||||
int32_t *pDestLength, const UCharx *src, int32_t srcLength,
|
||||
UErrorCodex *pErrorCode);
|
||||
typedef UChar32x *(*fn_u_strToUTF32WithSub)(UChar32x *dest,
|
||||
int32_t destCapacity,
|
||||
int32_t *pDestLength,
|
||||
const UCharx *src,
|
||||
int32_t srcLength,
|
||||
UChar32x subchar,
|
||||
int32_t *pNumSubstitutions,
|
||||
UErrorCodex *pErrorCode);
|
||||
int32_t destCapacity, int32_t *pDestLength, const UCharx *src,
|
||||
int32_t srcLength, UChar32x subchar, int32_t *pNumSubstitutions,
|
||||
UErrorCodex *pErrorCode);
|
||||
|
||||
typedef void (*fn_ucnv_close)(UConverter *);
|
||||
typedef uint16_t (*fn_ucnv_countAliases)(const char *, UErrorCodex *);
|
||||
@@ -113,19 +94,15 @@ typedef const char *(*fn_ucnv_getAlias)(const char *, uint16_t, UErrorCodex *);
|
||||
typedef const char *(*fn_ucnv_getAvailableName)(int32_t);
|
||||
typedef UConverter *(*fn_ucnv_open)(const char *converterName, UErrorCodex *);
|
||||
typedef void (*fn_ucnv_setFromUCallBack)(UConverter *,
|
||||
UConverterFromUCallback newAction,
|
||||
const void *newContext,
|
||||
UConverterFromUCallback *oldAction,
|
||||
const void **oldContext,
|
||||
UErrorCodex *err);
|
||||
UConverterFromUCallback newAction, const void *newContext,
|
||||
UConverterFromUCallback *oldAction, const void **oldContext,
|
||||
UErrorCodex *err);
|
||||
typedef void (*fn_ucnv_setToUCallBack)(UConverter *,
|
||||
UConverterToUCallback newAction,
|
||||
const void *newContext,
|
||||
UConverterToUCallback *oldAction,
|
||||
const void **oldContext,
|
||||
UErrorCodex *err);
|
||||
UConverterToUCallback newAction, const void *newContext,
|
||||
UConverterToUCallback *oldAction, const void **oldContext,
|
||||
UErrorCodex *err);
|
||||
typedef int32_t (*fn_ucnv_toUChars)(UConverter *, UCharx *dest,
|
||||
int32_t destCapacity, const char *src, int32_t srcLen, UErrorCodex *);
|
||||
int32_t destCapacity, const char *src, int32_t srcLen, UErrorCodex *);
|
||||
typedef UConverterFromUCallback fn_UCNV_FROM_U_CALLBACK_STOP;
|
||||
typedef UConverterToUCallback fn_UCNV_TO_U_CALLBACK_STOP;
|
||||
|
||||
@@ -161,12 +138,8 @@ typedef UNormalizer2 *(*fn_unorm2_getNFCInstance)(UErrorCodex *);
|
||||
typedef UNormalizer2 *(*fn_unorm2_getNFDInstance)(UErrorCodex *);
|
||||
typedef UNormalizer2 *(*fn_unorm2_getNFKCInstance)(UErrorCodex *);
|
||||
typedef UNormalizer2 *(*fn_unorm2_getNFKDInstance)(UErrorCodex *);
|
||||
typedef int32_t (*fn_unorm2_normalize)(const UNormalizer2 *,
|
||||
const UCharx *,
|
||||
int32_t,
|
||||
UCharx *,
|
||||
int32_t,
|
||||
UErrorCodex *);
|
||||
typedef int32_t (*fn_unorm2_normalize)(const UNormalizer2 *, const UCharx *,
|
||||
int32_t, UCharx *, int32_t, UErrorCodex *);
|
||||
|
||||
#define FIELD(name) fn_ ## name _ ## name
|
||||
|
||||
@@ -354,8 +327,8 @@ DetectEncoding(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (len > INT_MAX) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
UErrorCodex status = U_ZERO_ERRORZ;
|
||||
@@ -499,14 +472,9 @@ IcuObjToUCharDString(
|
||||
char *s;
|
||||
Tcl_Size len;
|
||||
s = Tcl_GetStringFromObj(objPtr, &len);
|
||||
result = Tcl_UtfToExternalDStringEx(interp,
|
||||
encoding,
|
||||
s,
|
||||
len,
|
||||
strict ? TCL_ENCODING_PROFILE_STRICT
|
||||
: TCL_ENCODING_PROFILE_REPLACE,
|
||||
dsPtr,
|
||||
NULL);
|
||||
result = Tcl_UtfToExternalDStringEx(interp, encoding, s, len,
|
||||
strict ? TCL_ENCODING_PROFILE_STRICT : TCL_ENCODING_PROFILE_REPLACE,
|
||||
dsPtr, NULL);
|
||||
if (result != TCL_OK) {
|
||||
Tcl_DStringFree(dsPtr); /* Must be done on error */
|
||||
/* TCL_CONVER_* errors -> TCL_ERROR */
|
||||
@@ -554,14 +522,9 @@ IcuObjFromUCharDString(
|
||||
Tcl_Size len = Tcl_DStringLength(dsPtr);
|
||||
Tcl_DString dsOut;
|
||||
int result;
|
||||
result = Tcl_ExternalToUtfDStringEx(interp,
|
||||
encoding,
|
||||
s,
|
||||
len,
|
||||
strict ? TCL_ENCODING_PROFILE_STRICT
|
||||
: TCL_ENCODING_PROFILE_REPLACE,
|
||||
&dsOut,
|
||||
NULL);
|
||||
result = Tcl_ExternalToUtfDStringEx(interp, encoding, s, len,
|
||||
strict ? TCL_ENCODING_PROFILE_STRICT : TCL_ENCODING_PROFILE_REPLACE,
|
||||
&dsOut, NULL);
|
||||
|
||||
if (result == TCL_OK) {
|
||||
objPtr = Tcl_DStringToObj(&dsOut); /* Clears dsPtr! */
|
||||
@@ -776,8 +739,8 @@ IcuConverttoDString(
|
||||
Tcl_Size utf16len = Tcl_DStringLength(dsInPtr) / sizeof(UCharx);
|
||||
Tcl_Size dstLen, dstCapacity;
|
||||
if (utf16len > INT_MAX) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -785,7 +748,7 @@ IcuConverttoDString(
|
||||
Tcl_DStringInit(dsOutPtr);
|
||||
Tcl_DStringSetLength(dsOutPtr, dstCapacity);
|
||||
dstLen = ucnv_fromUChars(ucnvPtr, Tcl_DStringValue(dsOutPtr), (int)dstCapacity,
|
||||
utf16, (int)utf16len, &status);
|
||||
utf16, (int)utf16len, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
switch (status) {
|
||||
case U_STRING_NOT_TERMINATED_WARNING:
|
||||
@@ -794,11 +757,11 @@ IcuConverttoDString(
|
||||
Tcl_DStringSetLength(dsOutPtr, (int)dstLen);
|
||||
status = U_ZERO_ERRORZ; /* Reset before call */
|
||||
dstLen = ucnv_fromUChars(ucnvPtr, Tcl_DStringValue(dsOutPtr), (int)dstLen,
|
||||
utf16, (int)utf16len, &status);
|
||||
utf16, (int)utf16len, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
default:
|
||||
Tcl_DStringFree(dsOutPtr);
|
||||
ucnv_close(ucnvPtr);
|
||||
@@ -840,8 +803,8 @@ IcuBytesToUCharDString(
|
||||
}
|
||||
|
||||
if (nbytes > INT_MAX) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -864,7 +827,7 @@ IcuBytesToUCharDString(
|
||||
Tcl_DStringInit(dsOutPtr);
|
||||
Tcl_DStringSetLength(dsOutPtr, dstCapacity);
|
||||
dstLen = ucnv_toUChars(ucnvPtr, (UCharx *)Tcl_DStringValue(dsOutPtr), dstCapacity,
|
||||
(const char *)bytes, (int)nbytes, &status);
|
||||
(const char *)bytes, (int)nbytes, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
switch (status) {
|
||||
case U_STRING_NOT_TERMINATED_WARNING:
|
||||
@@ -874,11 +837,11 @@ IcuBytesToUCharDString(
|
||||
Tcl_DStringSetLength(dsOutPtr, dstCapacity);
|
||||
status = U_ZERO_ERRORZ; /* Reset before call */
|
||||
dstLen = ucnv_toUChars(ucnvPtr, (UCharx *)Tcl_DStringValue(dsOutPtr), dstCapacity,
|
||||
(const char *)bytes, (int)nbytes, &status);
|
||||
(const char *)bytes, (int)nbytes, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
default:
|
||||
Tcl_DStringFree(dsOutPtr);
|
||||
ucnv_close(ucnvPtr);
|
||||
@@ -949,8 +912,8 @@ IcuNormalizeUCharDString(
|
||||
utf16 = (UCharx *) Tcl_DStringValue(dsInPtr);
|
||||
utf16len = Tcl_DStringLength(dsInPtr) / sizeof(UCharx);
|
||||
if (utf16len > INT_MAX) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringInit(dsOutPtr);
|
||||
@@ -974,7 +937,7 @@ IcuNormalizeUCharDString(
|
||||
if (U_SUCCESS(status)) {
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
default:
|
||||
Tcl_DStringFree(dsOutPtr);
|
||||
return IcuError(interp, "String normalization failed", status);
|
||||
@@ -1014,9 +977,9 @@ static int IcuParseConvertOptions(
|
||||
}
|
||||
++i;
|
||||
if (i == objc) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Missing value for option %s.",
|
||||
Tcl_GetString(objv[i - 1])));
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"Missing value for option %s.",
|
||||
Tcl_GetString(objv[i - 1])));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
const char *s = Tcl_GetString(objv[i]);
|
||||
@@ -1025,18 +988,20 @@ static int IcuParseConvertOptions(
|
||||
if (!strcmp(s, "replace")) {
|
||||
strict = 0;
|
||||
} else if (strcmp(s, "strict")) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Invalid value \"%s\" supplied for option"
|
||||
" \"-profile\". Must be \"strict\" or \"replace\".",
|
||||
s));
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"Invalid value \"%s\" supplied for option"
|
||||
" \"-profile\". Must be \"strict\" or \"replace\".",
|
||||
s));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
case OPT_FAILINDEX:
|
||||
/* TBD */
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("Option -failindex not implemented.", TCL_INDEX_NONE));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"Option -failindex not implemented.", TCL_INDEX_NONE));
|
||||
return TCL_ERROR;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
*strictPtr = strict;
|
||||
@@ -1182,9 +1147,9 @@ IcuNormalizeObjCmd(
|
||||
}
|
||||
++i;
|
||||
if (i == (objc-1)) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Missing value for option %s.",
|
||||
Tcl_GetString(objv[i - 1])));
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"Missing value for option %s.",
|
||||
Tcl_GetString(objv[i - 1])));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
const char *s = Tcl_GetString(objv[i]);
|
||||
@@ -1193,18 +1158,21 @@ IcuNormalizeObjCmd(
|
||||
if (!strcmp(s, "replace")) {
|
||||
strict = 0;
|
||||
} else if (strcmp(s, "strict")) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("Invalid value \"%s\" supplied for option \"-profile\". Must be "
|
||||
"\"strict\" or \"replace\".",
|
||||
s));
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"Invalid value \"%s\" supplied for option \"-profile\". "
|
||||
"Must be \"strict\" or \"replace\".",
|
||||
s));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE:
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], normalizationForms, "normalization mode", 0, &mode) != TCL_OK) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], normalizationForms,
|
||||
"normalization mode", 0, &mode) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1359,7 +1327,8 @@ TclIcuInit(
|
||||
/* Going back down to ICU version 60 */
|
||||
while ((icu_fns.libs[0] == NULL) && (icuversion[1] >= '6')) {
|
||||
if (--icuversion[2] < '0') {
|
||||
icuversion[1]--; icuversion[2] = '9';
|
||||
icuversion[1]--;
|
||||
icuversion[2] = '9';
|
||||
}
|
||||
#if defined(__CYGWIN__)
|
||||
i = 2;
|
||||
@@ -1438,10 +1407,10 @@ TclIcuInit(
|
||||
|
||||
/* Symbol may have version (Linux), or not (Windows, FreeBSD) */
|
||||
|
||||
#define ICUUC_SYM(name) \
|
||||
do { \
|
||||
icu_fns._##name = \
|
||||
(fn_##name)IcuFindSymbol(icu_fns.libs[0], #name, icuversion); \
|
||||
#define ICUUC_SYM(name) \
|
||||
do { \
|
||||
icu_fns._##name = (fn_##name) \
|
||||
IcuFindSymbol(icu_fns.libs[0], #name, icuversion); \
|
||||
} while (0)
|
||||
|
||||
if (icu_fns.libs[0] != NULL) {
|
||||
@@ -1485,10 +1454,10 @@ TclIcuInit(
|
||||
#undef ICUUC_SYM
|
||||
}
|
||||
|
||||
#define ICUIN_SYM(name) \
|
||||
do { \
|
||||
icu_fns._##name = \
|
||||
(fn_##name)IcuFindSymbol(icu_fns.libs[1], #name, icuversion); \
|
||||
#define ICUIN_SYM(name) \
|
||||
do { \
|
||||
icu_fns._##name = (fn_##name) \
|
||||
IcuFindSymbol(icu_fns.libs[1], #name, icuversion); \
|
||||
} while (0)
|
||||
|
||||
if (icu_fns.libs[1] != NULL) {
|
||||
@@ -1514,9 +1483,9 @@ TclIcuInit(
|
||||
/* Ref count number of commands */
|
||||
icu_fns.nopen += 3;
|
||||
Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::convertto",
|
||||
IcuConverttoObjCmd, 0, TclIcuCleanup);
|
||||
IcuConverttoObjCmd, 0, TclIcuCleanup);
|
||||
Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::convertfrom",
|
||||
IcuConvertfromObjCmd, 0, TclIcuCleanup);
|
||||
IcuConvertfromObjCmd, 0, TclIcuCleanup);
|
||||
Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::detect",
|
||||
IcuDetectObjCmd, 0, TclIcuCleanup);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,9 @@ typedef struct {
|
||||
#define NEXT_ENTRY(table, offset) \
|
||||
(&(STRING_AT(table, offset)))
|
||||
#define EXPAND_OF(indexRep) \
|
||||
(((indexRep)->index != TCL_INDEX_NONE) ? STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) : "")
|
||||
(((indexRep)->index != TCL_INDEX_NONE) ? \
|
||||
STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) : \
|
||||
"")
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -363,7 +365,8 @@ Tcl_GetIndexFromObjStruct(
|
||||
}
|
||||
/* #define again, needed below */
|
||||
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
|
||||
((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
|
||||
((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), \
|
||||
(msg), (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -386,10 +389,12 @@ static void
|
||||
UpdateStringOfIndex(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
IndexRep *indexRep = (IndexRep *)TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1;
|
||||
IndexRep *indexRep = (IndexRep *)
|
||||
TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1;
|
||||
const char *indexStr = EXPAND_OF(indexRep);
|
||||
size_t len = strlen(indexStr);
|
||||
|
||||
Tcl_InitStringRep(objPtr, indexStr, strlen(indexStr));
|
||||
TclOOM(Tcl_InitStringRep(objPtr, indexStr, len), len+1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -555,7 +555,7 @@ declare 239 {
|
||||
}
|
||||
declare 240 {
|
||||
int TclNRRunCallbacks(Tcl_Interp *interp, int result,
|
||||
struct NRE_callback *rootPtr)
|
||||
struct NRE_callback *rootPtr)
|
||||
}
|
||||
declare 241 {
|
||||
int TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags,
|
||||
@@ -563,7 +563,7 @@ declare 241 {
|
||||
}
|
||||
declare 242 {
|
||||
int TclNREvalObjv(Tcl_Interp *interp, Tcl_Size objc,
|
||||
Tcl_Obj *const objv[], int flags, Command *cmdPtr)
|
||||
Tcl_Obj *const objv[], int flags, Command *cmdPtr)
|
||||
}
|
||||
|
||||
# Tcl_Obj leak detection support.
|
||||
@@ -593,7 +593,7 @@ declare 248 {
|
||||
|
||||
declare 249 {
|
||||
char *TclDoubleDigits(double dv, int ndigits, int flags,
|
||||
int *decpt, int *signum, char **endPtr)
|
||||
int *decpt, int *signum, char **endPtr)
|
||||
}
|
||||
# TIP #285: Script cancellation support.
|
||||
declare 250 {
|
||||
@@ -635,6 +635,9 @@ declare 257 {
|
||||
void TclStaticLibrary(Tcl_Interp *interp, const char *prefix,
|
||||
Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc)
|
||||
}
|
||||
declare 258 {
|
||||
int TclMSB(unsigned long long n)
|
||||
}
|
||||
|
||||
declare 261 {
|
||||
void TclUnusedStubEntry(void)
|
||||
|
||||
+135
-38
@@ -141,6 +141,32 @@
|
||||
# define Tcl_ConditionFinalize(condPtr)
|
||||
#endif
|
||||
|
||||
// A way to mark a code path as unreachable.
|
||||
#ifndef TCL_UNREACHABLE
|
||||
#if defined(__STDC__) && __STDC__ >= 202311L
|
||||
#include <stddef.h>
|
||||
#define TCL_UNREACHABLE() unreachable()
|
||||
#elif defined(__GNUC__)
|
||||
#define TCL_UNREACHABLE() __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
#include <stdbool.h>
|
||||
#define TCL_UNREACHABLE() __assume(false)
|
||||
#else
|
||||
#define TCL_UNREACHABLE() ((void) 0)
|
||||
#endif
|
||||
#endif // TCL_UNREACHABLE
|
||||
|
||||
#ifndef TCL_FALLTHROUGH
|
||||
#if defined(__STDC__) && __STDC__ >= 202311L
|
||||
#define TCL_FALLTHROUGH() [[fallthrough]]
|
||||
#elif defined(__GNUC__)
|
||||
#define TCL_FALLTHROUGH() __attribute__((fallthrough))
|
||||
#else
|
||||
// Nothing documented as an alternative to the standard [[fallthrough]].
|
||||
#define TCL_FALLTHROUGH() ((void) 0)
|
||||
#endif
|
||||
#endif // TCL_FALLTHROUGH
|
||||
|
||||
/*
|
||||
* The following procedures allow namespaces to be customized to support
|
||||
* special name resolution rules for commands/variables.
|
||||
@@ -718,6 +744,8 @@ typedef struct VarInHash {
|
||||
#define VAR_ARRAY 0x1
|
||||
#define VAR_LINK 0x2
|
||||
#define VAR_CONSTANT 0x10000
|
||||
#define VAR_TYPE \
|
||||
(VAR_ARRAY | VAR_LINK | VAR_CONSTANT)
|
||||
|
||||
/* Type of storage (0 is compiled local) */
|
||||
#define VAR_IN_HASHTABLE 0x4
|
||||
@@ -745,6 +773,8 @@ typedef struct VarInHash {
|
||||
#define VAR_IS_ARGS 0x400
|
||||
#define VAR_RESOLVED 0x8000
|
||||
|
||||
#define TCL_HASH_FIND ((int *)-1)
|
||||
|
||||
/*
|
||||
* Macros to ensure that various flag bits are set properly for variables.
|
||||
* The ANSI C "prototypes" for these macros are:
|
||||
@@ -887,7 +917,7 @@ typedef struct VarInHash {
|
||||
|
||||
#define TclIsVarTricky(varPtr,trickyFlags) \
|
||||
( ((varPtr)->flags & (VAR_ARRAY|VAR_LINK|trickyFlags)) \
|
||||
|| (TclIsVarInHash(varPtr) \
|
||||
|| (TclIsVarInHash(varPtr) \
|
||||
&& (TclVarParentArray(varPtr) != NULL) \
|
||||
&& (TclVarParentArray(varPtr)->flags & (trickyFlags))))
|
||||
|
||||
@@ -1631,6 +1661,10 @@ typedef struct ExecEnv {
|
||||
#define COR_IS_SUSPENDED(corPtr) \
|
||||
((corPtr)->stackLevel == NULL)
|
||||
|
||||
// The different types of yielded coroutine we have.
|
||||
#define CORO_ACTIVATE_YIELD NULL // 0 or 1 argument expected
|
||||
#define CORO_ACTIVATE_YIELDM INT2PTR(1) // Arbitrary arguments expected
|
||||
|
||||
/*
|
||||
* The definitions for the LiteralTable and LiteralEntry structures. Each
|
||||
* interpreter contains a LiteralTable. It is used to reduce the storage
|
||||
@@ -1830,35 +1864,39 @@ typedef struct Command {
|
||||
|
||||
/*
|
||||
* Flag bits for commands.
|
||||
*
|
||||
* CMD_DYING - If 1 the command is in the process of
|
||||
* being deleted (its deleteProc is currently
|
||||
* executing). Other attempts to delete the
|
||||
* command should be ignored.
|
||||
* CMD_TRACE_ACTIVE - If 1 the trace processing is currently
|
||||
* underway for a rename/delete change. See the
|
||||
* two flags below for which is currently being
|
||||
* processed.
|
||||
* CMD_HAS_EXEC_TRACES - If 1 means that this command has at least one
|
||||
* execution trace (as opposed to simple
|
||||
* delete/rename traces) in its tracePtr list.
|
||||
* CMD_COMPILES_EXPANDED - If 1 this command has a compiler that
|
||||
* can handle expansion (provided it is not the
|
||||
* first word).
|
||||
* TCL_TRACE_RENAME - A rename trace is in progress. Further
|
||||
* recursive renames will not be traced.
|
||||
* TCL_TRACE_DELETE - A delete trace is in progress. Further
|
||||
* recursive deletes will not be traced.
|
||||
* (these last two flags are defined in tcl.h)
|
||||
*/
|
||||
|
||||
#define CMD_DYING 0x01
|
||||
#define CMD_TRACE_ACTIVE 0x02
|
||||
#define CMD_HAS_EXEC_TRACES 0x04
|
||||
#define CMD_COMPILES_EXPANDED 0x08
|
||||
#define CMD_REDEF_IN_PROGRESS 0x10
|
||||
#define CMD_VIA_RESOLVER 0x20
|
||||
#define CMD_DEAD 0x40
|
||||
enum CommandFlags {
|
||||
CMD_DYING = 0x01, /* The command is in the process of being
|
||||
* deleted (its deleteProc is currently
|
||||
* executing). Other attempts to delete the
|
||||
* command should be ignored.*/
|
||||
CMD_TRACE_ACTIVE = 0x02, /* The trace processing is currently underway
|
||||
* for a rename/delete change. See the flags
|
||||
* CMD_TRACE_RENAMING, CMD_TRACE_DELETING for
|
||||
* which is currently being processed. */
|
||||
CMD_HAS_EXEC_TRACES = 0x04, /* This command has at least one execution
|
||||
* trace (as opposed to simple delete/rename
|
||||
* traces) in its tracePtr list. */
|
||||
CMD_COMPILES_EXPANDED = 0x08,
|
||||
/* This command has a compiler that can handle
|
||||
* expansion (provided it is not the first
|
||||
* word). */
|
||||
CMD_REDEF_IN_PROGRESS = 0x10,
|
||||
/* Command is currently being redefined. It
|
||||
* should not be deleted, though its ClientData
|
||||
* may be purged. */
|
||||
CMD_VIA_RESOLVER = 0x20, /* Command was located by resolver. Its literal
|
||||
* should be marked unshared by the compiler. */
|
||||
CMD_DEAD = 0x40, /* Command is at an advanced stage of being
|
||||
* deleted, and is no longer in any hash tables
|
||||
* but stale references may exist elsewhere. */
|
||||
CMD_TRACE_RENAMING = TCL_TRACE_RENAME,
|
||||
/* A rename trace is in progress. Further
|
||||
* recursive renames will not be traced. */
|
||||
CMD_TRACE_DELETING = TCL_TRACE_DELETE
|
||||
/* A delete trace is in progress. Further
|
||||
* recursive deletes will not be traced. */
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -2545,10 +2583,11 @@ typedef struct ListStore {
|
||||
Tcl_Obj *slots[TCLFLEXARRAY];
|
||||
/* Variable size array. Grown as needed */
|
||||
} ListStore;
|
||||
|
||||
#define LISTSTORE_CANONICAL 0x1 /* All Tcl_Obj's referencing this
|
||||
enum ListStoreFlags {
|
||||
LISTSTORE_CANONICAL = 1 /* All Tcl_Obj's referencing this
|
||||
* store have their string representation
|
||||
* derived from the list representation */
|
||||
};
|
||||
|
||||
/* Max number of elements that can be contained in a list */
|
||||
#define LIST_MAX \
|
||||
@@ -3152,6 +3191,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRSubstObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRSwitchObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRTryObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRUplevelObjCmd;
|
||||
MODULE_SCOPE Tcl_NRPostProc TclUplevelCallback;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRWhileObjCmd;
|
||||
|
||||
MODULE_SCOPE Tcl_NRPostProc TclNRForIterCallback;
|
||||
@@ -3163,6 +3203,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRInvoke;
|
||||
MODULE_SCOPE Tcl_NRPostProc TclNRPostInvoke;
|
||||
MODULE_SCOPE Tcl_NRPostProc TclNRReleaseValues;
|
||||
|
||||
MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp,
|
||||
@@ -3222,6 +3263,17 @@ struct Tcl_LoadHandle_ {
|
||||
#define TCL_DD_CONVERSION_TYPE_MASK 0x3
|
||||
/* Mask to isolate the conversion type */
|
||||
|
||||
/*
|
||||
* Clock operations, communicated from command definitions to the bytecode
|
||||
* compiler.
|
||||
*/
|
||||
enum ClockOps {
|
||||
CLOCK_READ_CLICKS = 0, /* Read the click counter. */
|
||||
CLOCK_READ_MICROS = 1, /* Time in microseconds. */
|
||||
CLOCK_READ_MILLIS = 2, /* Time in milliseconds. */
|
||||
CLOCK_READ_SECS = 3 /* Time in seconds. */
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Procedures shared among Tcl modules but not used by the outside world:
|
||||
@@ -3232,6 +3284,10 @@ MODULE_SCOPE void TclAdvanceContinuations(int *line, Tcl_Size **next,
|
||||
Tcl_Size loc);
|
||||
MODULE_SCOPE void TclAdvanceLines(int *line, const char *start,
|
||||
const char *end);
|
||||
MODULE_SCOPE int TclAliasCreate(Tcl_Interp *interp,
|
||||
Tcl_Interp *childInterp, Tcl_Interp *parentInterp,
|
||||
Tcl_Obj *namePtr, Tcl_Obj *targetPtr, Tcl_Size objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr,
|
||||
const unsigned char *bytes, Tcl_Size len);
|
||||
MODULE_SCOPE void TclAppendUtfToUtf(Tcl_Obj *objPtr,
|
||||
@@ -3278,6 +3334,13 @@ MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr,
|
||||
Tcl_Obj *originObjPtr);
|
||||
MODULE_SCOPE Tcl_Size TclConvertElement(const char *src, Tcl_Size length,
|
||||
char *dst, int flags);
|
||||
MODULE_SCOPE int TclCopyNamespaceProcedures(Tcl_Interp *interp,
|
||||
Namespace *srcNsPtr, Namespace *tgtNsPtr);
|
||||
MODULE_SCOPE int TclCopyNamespaceVariables(Tcl_Interp *interp,
|
||||
Namespace *originNs, Namespace *targetNs);
|
||||
MODULE_SCOPE int TclCreateConstantInNS(Tcl_Interp *interp,
|
||||
Namespace *nsPtr, Tcl_Obj *nameObj,
|
||||
Tcl_Obj *valueObj);
|
||||
MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp,
|
||||
const char *cmdName, Tcl_Namespace *nsPtr,
|
||||
Tcl_ObjCmdProc *proc, void *clientData,
|
||||
@@ -3647,6 +3710,8 @@ MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclZipfs_Init(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int TclIsZipfsPath(const char *path);
|
||||
MODULE_SCOPE void TclZipfsFinalize(void);
|
||||
MODULE_SCOPE Tcl_Obj * TclGetObjNameOfShlib(void);
|
||||
MODULE_SCOPE void TclSetObjNameOfShlib(Tcl_Obj *namePtr, Tcl_Encoding);
|
||||
|
||||
/*
|
||||
* Many parsing tasks need a common definition of whitespace.
|
||||
@@ -3656,7 +3721,7 @@ MODULE_SCOPE void TclZipfsFinalize(void);
|
||||
|
||||
MODULE_SCOPE int TclIsSpaceProc(int byte);
|
||||
#define TclIsSpaceProcM(byte) \
|
||||
(((byte) > 0x20) ? 0 : TclIsSpaceProc(byte))
|
||||
(((unsigned)(byte) > 0x20) ? 0 : TclIsSpaceProc(byte))
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -3764,6 +3829,7 @@ MODULE_SCOPE Tcl_ObjCmdProc Tcl_SplitObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SocketObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SourceObjCmd;
|
||||
MODULE_SCOPE Tcl_Command TclInitStringCmd(Tcl_Interp *interp);
|
||||
MODULE_SCOPE Tcl_Command TclInitUnicodeCmd(Tcl_Interp *interp);
|
||||
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SubstObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SwitchObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc Tcl_TellObjCmd;
|
||||
@@ -3808,6 +3874,8 @@ MODULE_SCOPE CompileProc TclCompileDictIncrCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictLappendCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictMapCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictMergeCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictRemoveCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictReplaceCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictSetCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictUnsetCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileDictUpdateCmd;
|
||||
@@ -3825,18 +3893,22 @@ MODULE_SCOPE CompileProc TclCompileInfoCoroutineCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileInfoExistsCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileInfoLevelCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileInfoObjectClassCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileInfoObjectCreationIdCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileInfoObjectIsACmd;
|
||||
MODULE_SCOPE CompileProc TclCompileInfoObjectNamespaceCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileIncrCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLappendCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLassignCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLeditCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLindexCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLinsertCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileListCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLlengthCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLmapCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLpopCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLrangeCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLreplaceCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLseqCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileLsetCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileNamespaceCodeCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileNamespaceCurrentCmd;
|
||||
@@ -3878,6 +3950,7 @@ MODULE_SCOPE CompileProc TclCompileTailcallCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileThrowCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileTryCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileUnsetCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileUplevelCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileUpvarCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileVariableCmd;
|
||||
MODULE_SCOPE CompileProc TclCompileWhileCmd;
|
||||
@@ -3963,9 +4036,10 @@ MODULE_SCOPE Tcl_Obj * TclStringReplace(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
MODULE_SCOPE Tcl_Obj * TclStringReverse(Tcl_Obj *objPtr, int flags);
|
||||
|
||||
/* Flag values for the [string] ensemble functions. */
|
||||
|
||||
#define TCL_STRING_MATCH_NOCASE TCL_MATCH_NOCASE /* (1<<0) in tcl.h */
|
||||
#define TCL_STRING_IN_PLACE (1<<1)
|
||||
enum StringOpFlags {
|
||||
TCL_STRING_MATCH_NOCASE = TCL_MATCH_NOCASE, /* (1<<0) in tcl.h */
|
||||
TCL_STRING_IN_PLACE = (1<<1) /* Do in-place surgery on Tcl_Obj */
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions defined in generic/tclVar.c and currently exported only for use
|
||||
@@ -4093,7 +4167,8 @@ MODULE_SCOPE Tcl_Size TclIndexDecode(int encoded, Tcl_Size endValue);
|
||||
*/
|
||||
MODULE_SCOPE int TclCommandWordLimitError(Tcl_Interp *interp,
|
||||
Tcl_Size count);
|
||||
|
||||
MODULE_SCOPE int TclListLimitExceededError(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int TclCannotAllocateError(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
|
||||
/* Constants used in index value encoding routines. */
|
||||
#define TCL_INDEX_END ((Tcl_Size)-2)
|
||||
@@ -4368,7 +4443,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
*
|
||||
* MODULE_SCOPE void TclInitEmptyStringRep(Tcl_Obj *objPtr);
|
||||
* MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
|
||||
* MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
|
||||
* MODULE_SCOPE const char *TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
|
||||
*
|
||||
*----------------------------------------------------------------
|
||||
*/
|
||||
@@ -4393,7 +4468,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
(objPtr)->bytes = (char *)Tcl_AttemptAlloc((len) + 1U), \
|
||||
(objPtr)->length = ((objPtr)->bytes) ? \
|
||||
(memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)), \
|
||||
(objPtr)->bytes[len] = '\0', (len)) : (-1) \
|
||||
(objPtr)->bytes[len] = '\0', (Tcl_Size)(len)) : (-1) \
|
||||
)), (objPtr)->bytes)
|
||||
|
||||
/*
|
||||
@@ -4416,6 +4491,14 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes) \
|
||||
: (Tcl_GetStringFromObj)((objPtr), (lenPtr)))
|
||||
|
||||
#define TclAttemptGetString(objPtr) \
|
||||
((objPtr)->bytes? (objPtr)->bytes : Tcl_AttemptGetString(objPtr))
|
||||
|
||||
#define TclAttemptGetStringFromObj(objPtr, lenPtr) \
|
||||
((objPtr)->bytes \
|
||||
? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes) \
|
||||
: (Tcl_AttemptGetStringFromObj)((objPtr), (lenPtr)))
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Macro used by the Tcl core to clean out an object's internal
|
||||
@@ -4787,6 +4870,16 @@ MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init;
|
||||
TCL_DTRACE_OBJ_CREATE(objPtr); \
|
||||
} while (0)
|
||||
|
||||
#define TclAttemptNewStringObj(objPtr, s, len) \
|
||||
do { \
|
||||
TclIncrObjsAllocated(); \
|
||||
TclAllocObjStorage(objPtr); \
|
||||
(objPtr)->refCount = 0; \
|
||||
TclAttemptInitStringRep((objPtr), (s), (len)); \
|
||||
(objPtr)->typePtr = NULL; \
|
||||
TCL_DTRACE_OBJ_CREATE(objPtr); \
|
||||
} while (0)
|
||||
|
||||
#else /* TCL_MEM_DEBUG */
|
||||
#define TclNewIntObj(objPtr, w) \
|
||||
(objPtr) = Tcl_NewWideIntObj(w)
|
||||
@@ -4814,6 +4907,10 @@ MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init;
|
||||
|
||||
#define TclNewStringObj(objPtr, s, len) \
|
||||
(objPtr) = Tcl_NewStringObj((s), (len))
|
||||
|
||||
#define TclAttemptNewStringObj(objPtr, s, len) \
|
||||
(objPtr) = Tcl_AttemptNewStringObj((s), (len))
|
||||
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
|
||||
/*
|
||||
|
||||
@@ -569,7 +569,8 @@ EXTERN void TclStaticLibrary(Tcl_Interp *interp,
|
||||
const char *prefix,
|
||||
Tcl_LibraryInitProc *initProc,
|
||||
Tcl_LibraryInitProc *safeInitProc);
|
||||
/* Slot 258 is reserved */
|
||||
/* 258 */
|
||||
EXTERN int TclMSB(unsigned long long n);
|
||||
/* Slot 259 is reserved */
|
||||
/* Slot 260 is reserved */
|
||||
/* 261 */
|
||||
@@ -837,7 +838,7 @@ typedef struct TclIntStubs {
|
||||
int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */
|
||||
int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 256 */
|
||||
void (*tclStaticLibrary) (Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); /* 257 */
|
||||
void (*reserved258)(void);
|
||||
int (*tclMSB) (unsigned long long n); /* 258 */
|
||||
void (*reserved259)(void);
|
||||
void (*reserved260)(void);
|
||||
void (*tclUnusedStubEntry) (void); /* 261 */
|
||||
@@ -1252,7 +1253,8 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
(tclIntStubsPtr->tclPtrUnsetVar) /* 256 */
|
||||
#define TclStaticLibrary \
|
||||
(tclIntStubsPtr->tclStaticLibrary) /* 257 */
|
||||
/* Slot 258 is reserved */
|
||||
#define TclMSB \
|
||||
(tclIntStubsPtr->tclMSB) /* 258 */
|
||||
/* Slot 259 is reserved */
|
||||
/* Slot 260 is reserved */
|
||||
#define TclUnusedStubEntry \
|
||||
|
||||
@@ -232,7 +232,7 @@ MODULE_SCOPE int TclMacOSXMatchType(Tcl_Interp *interp,
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# if !defined(TCL_NO_DEPRECATED)
|
||||
# ifndef TCL_NO_DEPRECATED
|
||||
# define TclWinConvertError Tcl_WinConvertError
|
||||
# define TclWinConvertWSAError Tcl_WinConvertError
|
||||
# define TclWinNToHS ntohs
|
||||
|
||||
+27
-19
@@ -221,10 +221,6 @@ enum LimitHandlerFlags {
|
||||
* Prototypes for local static functions:
|
||||
*/
|
||||
|
||||
static int AliasCreate(Tcl_Interp *interp,
|
||||
Tcl_Interp *childInterp, Tcl_Interp *parentInterp,
|
||||
Tcl_Obj *namePtr, Tcl_Obj *targetPtr, Tcl_Size objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int AliasDelete(Tcl_Interp *interp,
|
||||
Tcl_Interp *childInterp, Tcl_Obj *namePtr);
|
||||
static int AliasDescribe(Tcl_Interp *interp,
|
||||
@@ -701,7 +697,7 @@ NRInterpCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return AliasCreate(interp, childInterp, parentInterp, objv[3],
|
||||
return TclAliasCreate(interp, childInterp, parentInterp, objv[3],
|
||||
objv[5], objc - 6, objv + 6);
|
||||
}
|
||||
|
||||
@@ -756,6 +752,8 @@ NRInterpCmd(
|
||||
case OPT_LAST:
|
||||
i++;
|
||||
goto endOfForLoop;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1022,8 +1020,7 @@ NRInterpCmd(
|
||||
case LIMIT_TYPE_TIME:
|
||||
return ChildTimeLimitCmd(interp, childInterp, 4, objc, objv);
|
||||
default:
|
||||
Tcl_Panic("unreachable");
|
||||
return TCL_ERROR;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
case OPT_MARKTRUSTED:
|
||||
@@ -1147,8 +1144,7 @@ NRInterpCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
default:
|
||||
Tcl_Panic("unreachable");
|
||||
return TCL_ERROR;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1232,7 +1228,7 @@ Tcl_CreateAlias(
|
||||
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
|
||||
Tcl_IncrRefCount(targetObjPtr);
|
||||
|
||||
result = AliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
|
||||
result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
|
||||
targetObjPtr, argc, objv);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
@@ -1279,7 +1275,7 @@ Tcl_CreateAliasObj(
|
||||
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
|
||||
Tcl_IncrRefCount(targetObjPtr);
|
||||
|
||||
result = AliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
|
||||
result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
|
||||
targetObjPtr, objc, objv);
|
||||
|
||||
Tcl_DecrRefCount(childObjPtr);
|
||||
@@ -1452,7 +1448,7 @@ TclPreventAliasLoop(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* AliasCreate --
|
||||
* TclAliasCreate --
|
||||
*
|
||||
* Helper function to do the work to actually create an alias.
|
||||
*
|
||||
@@ -1466,8 +1462,8 @@ TclPreventAliasLoop(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
AliasCreate(
|
||||
int
|
||||
TclAliasCreate(
|
||||
Tcl_Interp *interp, /* Interp for error reporting. */
|
||||
Tcl_Interp *childInterp, /* Interp where alias cmd will live or from
|
||||
* which alias will be deleted. */
|
||||
@@ -2468,7 +2464,7 @@ ChildCreate(
|
||||
|
||||
TclNewLiteralStringObj(clockObj, "clock");
|
||||
Tcl_IncrRefCount(clockObj);
|
||||
status = AliasCreate(interp, childInterp, parentInterp, clockObj,
|
||||
status = TclAliasCreate(interp, childInterp, parentInterp, clockObj,
|
||||
clockObj, 0, NULL);
|
||||
Tcl_DecrRefCount(clockObj);
|
||||
if (status != TCL_OK) {
|
||||
@@ -2558,7 +2554,7 @@ NRChildCmd(
|
||||
return AliasDelete(interp, childInterp, objv[2]);
|
||||
}
|
||||
} else {
|
||||
return AliasCreate(interp, childInterp, interp, objv[2],
|
||||
return TclAliasCreate(interp, childInterp, interp, objv[2],
|
||||
objv[3], objc - 4, objv + 4);
|
||||
}
|
||||
}
|
||||
@@ -2677,9 +2673,10 @@ NRChildCmd(
|
||||
return ChildCommandLimitCmd(interp, childInterp, 3, objc,objv);
|
||||
case LIMIT_TYPE_TIME:
|
||||
return ChildTimeLimitCmd(interp, childInterp, 3, objc, objv);
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPT_MARKTRUSTED:
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, NULL);
|
||||
@@ -2692,6 +2689,8 @@ NRChildCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return ChildRecursionLimit(interp, childInterp, objc - 2, objv + 2);
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
return TCL_ERROR;
|
||||
@@ -4529,6 +4528,8 @@ ChildCommandLimitCmd(
|
||||
Tcl_NewWideIntObj(Tcl_LimitGetCommands(childInterp)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_OK;
|
||||
} else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
|
||||
@@ -4537,7 +4538,8 @@ ChildCommandLimitCmd(
|
||||
} else {
|
||||
Tcl_Size i, scriptLen = 0, limitLen = 0;
|
||||
Tcl_Obj *scriptObj = NULL, *granObj = NULL, *limitObj = NULL;
|
||||
int gran = 0, limit = 0;
|
||||
int gran = 0;
|
||||
Tcl_Size limit = 0;
|
||||
|
||||
for (i=consumedObjc ; i<objc ; i+=2) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
|
||||
@@ -4568,7 +4570,7 @@ ChildCommandLimitCmd(
|
||||
if (limitLen == 0) {
|
||||
break;
|
||||
}
|
||||
if (TclGetIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
|
||||
if (Tcl_GetSizeIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (limit < 0) {
|
||||
@@ -4579,6 +4581,8 @@ ChildCommandLimitCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (scriptObj != NULL) {
|
||||
@@ -4729,6 +4733,8 @@ ChildTimeLimitCmd(
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(limitMoment.sec));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_OK;
|
||||
} else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
|
||||
@@ -4802,6 +4808,8 @@ ChildTimeLimitCmd(
|
||||
}
|
||||
limitMoment.sec = (long long) tmp;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (milliObj != NULL || secObj != NULL) {
|
||||
|
||||
+1
-1
@@ -1316,7 +1316,7 @@ ObjValue(
|
||||
Tcl_Obj *uwObj;
|
||||
TclNewUIntObj(uwObj, linkPtr->lastValue.uw);
|
||||
return uwObj;
|
||||
}
|
||||
}
|
||||
|
||||
case TCL_LINK_STRING:
|
||||
p = LinkedVar(char *);
|
||||
|
||||
+101
-69
@@ -39,32 +39,31 @@
|
||||
|
||||
#ifdef ENABLE_LIST_ASSERTS
|
||||
|
||||
#define LIST_ASSERT(cond_) assert(cond_)
|
||||
#define LIST_ASSERT(cond_) \
|
||||
assert(cond_)
|
||||
/*
|
||||
* LIST_INDEX_ASSERT is to catch errors with negative indices and counts
|
||||
* being passed AFTER validation. On Tcl9 length types are unsigned hence
|
||||
* the checks against LIST_MAX. On Tcl8 length types are signed hence the
|
||||
* also checks against 0.
|
||||
*/
|
||||
#define LIST_INDEX_ASSERT(idxarg_) \
|
||||
do { \
|
||||
Tcl_Size idx_ = (idxarg_); /* To guard against ++ etc. */ \
|
||||
LIST_ASSERT(idx_ >= 0 && idx_ < LIST_MAX); \
|
||||
#define LIST_INDEX_ASSERT(idxarg_) \
|
||||
do { \
|
||||
Tcl_Size idx_ = (idxarg_); /* To guard against ++ etc. */ \
|
||||
LIST_ASSERT(idx_ >= 0 && idx_ < LIST_MAX); \
|
||||
} while (0)
|
||||
/* Ditto for counts except upper limit is different */
|
||||
#define LIST_COUNT_ASSERT(countarg_) \
|
||||
do { \
|
||||
Tcl_Size count_ = (countarg_); /* To guard against ++ etc. */ \
|
||||
LIST_ASSERT(count_ >= 0 && count_ <= LIST_MAX); \
|
||||
#define LIST_COUNT_ASSERT(countarg_) \
|
||||
do { \
|
||||
Tcl_Size count_ = (countarg_); /* To guard against ++ etc. */ \
|
||||
LIST_ASSERT(count_ >= 0 && count_ <= LIST_MAX); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define LIST_ASSERT(cond_) ((void) 0)
|
||||
#define LIST_INDEX_ASSERT(idx_) ((void) 0)
|
||||
#define LIST_COUNT_ASSERT(count_) ((void) 0)
|
||||
|
||||
#endif
|
||||
#else // !ENABLE_LIST_ASSERTS
|
||||
#define LIST_ASSERT(cond_) ((void) 0)
|
||||
#define LIST_INDEX_ASSERT(idx_) ((void) 0)
|
||||
#define LIST_COUNT_ASSERT(count_) ((void) 0)
|
||||
#endif // ENABLE_LIST_ASSERTS
|
||||
|
||||
/* Checks for when caller should have already converted to internal list type */
|
||||
#define LIST_ASSERT_TYPE(listObj_) \
|
||||
@@ -105,13 +104,15 @@
|
||||
* - Finally if LISTREP_SPACE_ONLY_BACK is present, ALL extra space is at
|
||||
* the back.
|
||||
*/
|
||||
#define LISTREP_PANIC_ON_FAIL 0x00000001
|
||||
#define LISTREP_SPACE_FAVOR_FRONT 0x00000002
|
||||
#define LISTREP_SPACE_FAVOR_BACK 0x00000004
|
||||
#define LISTREP_SPACE_ONLY_BACK 0x00000008
|
||||
enum ListRepresentationFlags {
|
||||
LISTREP_PANIC_ON_FAIL = 1,
|
||||
LISTREP_SPACE_FAVOR_FRONT = 2,
|
||||
LISTREP_SPACE_FAVOR_BACK = 4,
|
||||
LISTREP_SPACE_ONLY_BACK = 8
|
||||
};
|
||||
#define LISTREP_SPACE_FAVOR_NONE \
|
||||
(LISTREP_SPACE_FAVOR_FRONT | LISTREP_SPACE_FAVOR_BACK)
|
||||
#define LISTREP_SPACE_FLAGS \
|
||||
#define LISTREP_SPACE_FLAGS \
|
||||
(LISTREP_SPACE_FAVOR_FRONT | LISTREP_SPACE_FAVOR_BACK \
|
||||
| LISTREP_SPACE_ONLY_BACK)
|
||||
|
||||
@@ -119,7 +120,6 @@
|
||||
* Prototypes for non-inline static functions defined later in this file:
|
||||
*/
|
||||
static int MemoryAllocationError(Tcl_Interp *, size_t size);
|
||||
static int ListLimitExceededError(Tcl_Interp *);
|
||||
static ListStore *ListStoreNew(Tcl_Size objc, Tcl_Obj *const objv[], int flags);
|
||||
static int ListRepInit(Tcl_Size objc, Tcl_Obj *const objv[], int flags, ListRep *);
|
||||
static int ListRepInitAttempt(Tcl_Interp *,
|
||||
@@ -199,26 +199,26 @@ const Tcl_ObjType tclListType = {
|
||||
* passed ListRep) and frees it first. Additionally invalidates the string
|
||||
* representation. Generally used when modifying a Tcl_Obj value.
|
||||
*/
|
||||
#define ListObjStompRep(objPtr_, repPtr_) \
|
||||
do { \
|
||||
(objPtr_)->internalRep.twoPtrValue.ptr1 = (repPtr_)->storePtr; \
|
||||
(objPtr_)->internalRep.twoPtrValue.ptr2 = (repPtr_)->spanPtr; \
|
||||
(objPtr_)->typePtr = &tclListType; \
|
||||
#define ListObjStompRep(objPtr_, repPtr_) \
|
||||
do { \
|
||||
(objPtr_)->internalRep.twoPtrValue.ptr1 = (repPtr_)->storePtr; \
|
||||
(objPtr_)->internalRep.twoPtrValue.ptr2 = (repPtr_)->spanPtr; \
|
||||
(objPtr_)->typePtr = &tclListType; \
|
||||
} while (0)
|
||||
|
||||
#define ListObjOverwriteRep(objPtr_, repPtr_) \
|
||||
do { \
|
||||
ListRepIncrRefs(repPtr_); \
|
||||
ListObjStompRep(objPtr_, repPtr_); \
|
||||
do { \
|
||||
ListRepIncrRefs(repPtr_); \
|
||||
ListObjStompRep(objPtr_, repPtr_); \
|
||||
} while (0)
|
||||
|
||||
#define ListObjReplaceRepAndInvalidate(objPtr_, repPtr_) \
|
||||
do { \
|
||||
/* Note order important, don't use ListObjOverwriteRep! */ \
|
||||
ListRepIncrRefs(repPtr_); \
|
||||
TclFreeInternalRep(objPtr_); \
|
||||
TclInvalidateStringRep(objPtr_); \
|
||||
ListObjStompRep(objPtr_, repPtr_); \
|
||||
#define ListObjReplaceRepAndInvalidate(objPtr_, repPtr_) \
|
||||
do { \
|
||||
/* Note order important, don't use ListObjOverwriteRep! */ \
|
||||
ListRepIncrRefs(repPtr_); \
|
||||
TclFreeInternalRep(objPtr_); \
|
||||
TclInvalidateStringRep(objPtr_); \
|
||||
ListObjStompRep(objPtr_, repPtr_); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
@@ -481,7 +481,7 @@ MemoryAllocationError(
|
||||
/*
|
||||
*------------------------------------------------------------------------
|
||||
*
|
||||
* ListLimitExceeded --
|
||||
* TclListLimitExceededError --
|
||||
*
|
||||
* Generates an error for exceeding maximum list size.
|
||||
*
|
||||
@@ -493,13 +493,19 @@ MemoryAllocationError(
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
ListLimitExceededError(
|
||||
int
|
||||
TclListLimitExceededError(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
/*
|
||||
* As an aside, note there is no parameter passed for the bad length
|
||||
* because the cverflow is computationally detected and does not fit
|
||||
* in Tcl_Size.
|
||||
*/
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"max length of a Tcl list exceeded", -1));
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_ObjPrintf("max length (%" TCL_SIZE_MODIFIER
|
||||
"d) of a Tcl list exceeded", (Tcl_Size)LIST_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
@@ -640,12 +646,12 @@ ListRepValidate(
|
||||
|
||||
(void)storePtr; /* To stop gcc from whining about unused vars */
|
||||
|
||||
#define INVARIANT(cond_) \
|
||||
do { \
|
||||
if (!(cond_)) { \
|
||||
condition = #cond_; \
|
||||
goto failure; \
|
||||
} \
|
||||
#define INVARIANT(cond_) \
|
||||
do { \
|
||||
if (!(cond_)) { \
|
||||
condition = #cond_; \
|
||||
goto failure; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Separate each condition so line number gives exact reason for failure */
|
||||
@@ -671,14 +677,11 @@ ListRepValidate(
|
||||
INVARIANT(ListRepStart(repPtr) <= (storePtr->firstUsed + storePtr->numUsed - ListRepLength(repPtr)));
|
||||
|
||||
#undef INVARIANT
|
||||
|
||||
return;
|
||||
|
||||
failure:
|
||||
failure:
|
||||
Tcl_Panic("List internal failure in %s line %d. Condition: %s",
|
||||
file,
|
||||
lineNum,
|
||||
condition);
|
||||
file, lineNum, condition);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -705,7 +708,7 @@ TclListObjValidate(
|
||||
ListRep listRep;
|
||||
if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
|
||||
Tcl_Panic("Object passed to TclListObjValidate cannot be converted to "
|
||||
"a list object.");
|
||||
"a list object.");
|
||||
}
|
||||
ListRepValidate(&listRep, __FILE__, __LINE__);
|
||||
}
|
||||
@@ -942,7 +945,7 @@ ListRepInitAttempt(
|
||||
|
||||
if (result != TCL_OK && interp != NULL) {
|
||||
if (objc > LIST_MAX) {
|
||||
ListLimitExceededError(interp);
|
||||
TclListLimitExceededError(interp);
|
||||
} else {
|
||||
MemoryAllocationError(interp, LIST_SIZE(objc));
|
||||
}
|
||||
@@ -1197,6 +1200,7 @@ Tcl_DbNewListObj(
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
#if 0
|
||||
Tcl_Obj *
|
||||
TclNewListObj2(
|
||||
Tcl_Size objc1, /* Count of objects referenced by objv1. */
|
||||
@@ -1230,6 +1234,7 @@ TclNewListObj2(
|
||||
storePtr->numUsed = objc;
|
||||
return listObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -1457,7 +1462,7 @@ ListRepRange(
|
||||
if (rangeStart == 0 && rangeEnd == (numSrcElems-1)) {
|
||||
/* Option 0 - entire list. This may be used to canonicalize */
|
||||
/* T:listrep-1.10.1,2.8.1 */
|
||||
*rangeRepPtr = *srcRepPtr; /* Not ref counts not incremented */
|
||||
*rangeRepPtr = *srcRepPtr; /* Note ref counts not incremented */
|
||||
} else if (rangeStart == 0 && (!preserveSrcRep)
|
||||
&& (!ListRepIsShared(srcRepPtr) && srcRepPtr->spanPtr == NULL)) {
|
||||
/* Option 1 - Special case unshared, exclude end elements, no span */
|
||||
@@ -1754,8 +1759,8 @@ Tcl_ListObjAppendList(
|
||||
*
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclListObjAppendElements (
|
||||
int
|
||||
TclListObjAppendElements(
|
||||
Tcl_Interp *interp, /* Used to report errors if not NULL. */
|
||||
Tcl_Obj *toObj, /* List object to append */
|
||||
Tcl_Size elemCount, /* Number of elements in elemObjs[] */
|
||||
@@ -1792,7 +1797,7 @@ Tcl_ListObjAppendList(
|
||||
|
||||
ListRepElements(&listRep, toLen, toObjv);
|
||||
if (elemCount > LIST_MAX || toLen > (LIST_MAX - elemCount)) {
|
||||
return ListLimitExceededError(interp);
|
||||
return TclListLimitExceededError(interp);
|
||||
}
|
||||
|
||||
finalLen = toLen + elemCount;
|
||||
@@ -2133,12 +2138,12 @@ Tcl_ListObjReplace(
|
||||
if (numToDelete < 0) {
|
||||
numToDelete = 0;
|
||||
} else if (first > LIST_MAX - numToDelete /* Handle integer overflow */
|
||||
|| origListLen < first + numToDelete) {
|
||||
|| origListLen < first + numToDelete) {
|
||||
numToDelete = origListLen - first;
|
||||
}
|
||||
|
||||
if (numToInsert > LIST_MAX - (origListLen - numToDelete)) {
|
||||
return ListLimitExceededError(interp);
|
||||
return TclListLimitExceededError(interp);
|
||||
}
|
||||
|
||||
if ((first+numToDelete) >= origListLen) {
|
||||
@@ -2664,14 +2669,14 @@ TclLindexFlat(
|
||||
Tcl_Size i;
|
||||
|
||||
/* Handle AbstractList as special case */
|
||||
if (TclObjTypeHasProc(listObj,indexProc)) {
|
||||
if (indexCount == 1 && TclObjTypeHasProc(listObj,indexProc)) {
|
||||
Tcl_Size listLen = TclObjTypeLength(listObj);
|
||||
Tcl_Size index;
|
||||
Tcl_Obj *elemObj = listObj; /* for lindex without indices return list */
|
||||
for (i=0 ; i<indexCount && listObj ; i++) {
|
||||
if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
|
||||
&index) == TCL_OK) {
|
||||
// TODO: ???
|
||||
&index) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
if (i==0) {
|
||||
if (TclObjTypeIndex(interp, listObj, index, &elemObj) != TCL_OK) {
|
||||
@@ -2684,6 +2689,13 @@ TclLindexFlat(
|
||||
elemObj = e2Obj;
|
||||
}
|
||||
}
|
||||
if (elemObj == NULL) {
|
||||
/*
|
||||
* TclObjTypeIndex returns TCL_OK with NULL in elemObj if
|
||||
* index was out of bounds.
|
||||
*/
|
||||
TclNewObj(elemObj);
|
||||
}
|
||||
Tcl_IncrRefCount(elemObj);
|
||||
return elemObj;
|
||||
}
|
||||
@@ -2720,6 +2732,7 @@ TclLindexFlat(
|
||||
Tcl_IncrRefCount(listObj);
|
||||
} else {
|
||||
Tcl_Obj *itemObj;
|
||||
/* TODO - this will cause shimmering of inner abstract lists! */
|
||||
/*
|
||||
* Must set the internal rep again because it may have been
|
||||
* changed by TclGetIntForIndexM. See test lindex-8.4.
|
||||
@@ -3531,14 +3544,29 @@ UpdateStringOfList(
|
||||
flagPtr = localFlags;
|
||||
} else {
|
||||
/* We know numElems <= LIST_MAX, so this is safe. */
|
||||
flagPtr = (char *)Tcl_Alloc(numElems);
|
||||
flagPtr = (char *)Tcl_AttemptAlloc(numElems);
|
||||
if (!flagPtr) {
|
||||
listObj->length = numElems - 1;
|
||||
allocError:
|
||||
/* Allocation error. Just give up. */
|
||||
if (listObj->bytes) {
|
||||
Tcl_Free(listObj->bytes);
|
||||
listObj->bytes = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < numElems; i++) {
|
||||
flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0);
|
||||
elem = TclGetStringFromObj(elemPtrs[i], &length);
|
||||
elem = TclAttemptGetStringFromObj(elemPtrs[i], &length);
|
||||
if (!elem) {
|
||||
listObj->length = elemPtrs[i]->length;
|
||||
goto allocError;
|
||||
}
|
||||
bytesNeeded += TclScanElement(elem, length, flagPtr+i);
|
||||
if (bytesNeeded > SIZE_MAX - numElems) {
|
||||
Tcl_Panic("max size for a Tcl value (%" TCL_Z_MODIFIER "u bytes) exceeded", SIZE_MAX);
|
||||
listObj->length = bytesNeeded;
|
||||
goto allocError;
|
||||
}
|
||||
}
|
||||
bytesNeeded += numElems - 1;
|
||||
@@ -3553,7 +3581,11 @@ UpdateStringOfList(
|
||||
if (i) {
|
||||
flagPtr[i] |= TCL_DONT_QUOTE_HASH;
|
||||
}
|
||||
elem = TclGetStringFromObj(elemPtrs[i], &length);
|
||||
elem = TclAttemptGetStringFromObj(elemPtrs[i], &length);
|
||||
if (!elem) {
|
||||
listObj->length = elemPtrs[i]->length;
|
||||
goto allocError;
|
||||
}
|
||||
dst += TclConvertElement(elem, length, dst, flagPtr[i]);
|
||||
*dst++ = ' ';
|
||||
}
|
||||
@@ -3619,7 +3651,7 @@ TclListTestObj(
|
||||
ListObjReplaceRepAndInvalidate(listObj, &listRep);
|
||||
return listObj;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+51
-8
@@ -250,8 +250,9 @@ TclCreateLiteral(
|
||||
if ((flags & LITERAL_ON_HEAP)) {
|
||||
objPtr->bytes = (char *) bytes;
|
||||
objPtr->length = length;
|
||||
} else {
|
||||
TclInitStringRep(objPtr, bytes, length);
|
||||
} else if (!TclAttemptInitStringRep(objPtr, bytes, length)) {
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Should the new literal be shared globally? */
|
||||
@@ -506,7 +507,7 @@ static LiteralEntry *
|
||||
LookupLiteralEntry(
|
||||
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
|
||||
* hold a literal. */
|
||||
Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
|
||||
Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
|
||||
* that was previously created by a call to
|
||||
* TclRegisterLiteral. */
|
||||
{
|
||||
@@ -552,7 +553,7 @@ void
|
||||
TclHideLiteral(
|
||||
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
|
||||
* hold a literal. */
|
||||
CompileEnv *envPtr,/* Points to CompileEnv whose literal array
|
||||
CompileEnv *envPtr, /* Points to CompileEnv whose literal array
|
||||
* contains the entry being hidden. */
|
||||
int index) /* The index of the entry in the literal
|
||||
* array. */
|
||||
@@ -616,7 +617,7 @@ TclHideLiteral(
|
||||
|
||||
int
|
||||
TclAddLiteralObj(
|
||||
CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
|
||||
CompileEnv *envPtr, /* Points to CompileEnv in whose literal array
|
||||
* the object is to be inserted. */
|
||||
Tcl_Obj *objPtr, /* The object to insert into the array. */
|
||||
LiteralEntry **litPtrPtr) /* The location where the pointer to the new
|
||||
@@ -649,6 +650,48 @@ TclAddLiteralObj(
|
||||
return (int)objIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclRegisterLiteralObj --
|
||||
*
|
||||
* Find, or if necessary create, an object in a CompileEnv literal array
|
||||
* that has a string representation matching the argument object.
|
||||
*
|
||||
* Results:
|
||||
* The index in the CompileEnv's literal array that references a shared
|
||||
* literal matching the string. The object is created if necessary.
|
||||
*
|
||||
* Side effects:
|
||||
* To maximize sharing, we look up the string in the interpreter's global
|
||||
* literal table. If not found, we create a new shared literal in the
|
||||
* global table. We then add a reference to the shared literal in the
|
||||
* CompileEnv's literal array.
|
||||
*
|
||||
* The reference count of the argument object is bounced, so that the
|
||||
* normal case where the object is zero ref count (as it is really acting
|
||||
* as a local worker buffer) doesn't need explicit refcount handling by
|
||||
* the caller.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclRegisterLiteralObj(
|
||||
CompileEnv *envPtr, /* Points to CompileEnv in whose literal array
|
||||
* the object is to be inserted. */
|
||||
Tcl_Obj *objPtr, /* The object to insert into the array. */
|
||||
int flags) /* If LITERAL_CMD_NAME then the literal should
|
||||
* not be shared across namespaces.
|
||||
* LITERAL_ON_HEAP is unsupported/ignored. */
|
||||
{
|
||||
Tcl_Size length;
|
||||
const char *bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
int num = TclRegisterLiteral(envPtr, bytes, length,
|
||||
flags & ~LITERAL_ON_HEAP);
|
||||
Tcl_BounceRefCount(objPtr);
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -669,7 +712,7 @@ TclAddLiteralObj(
|
||||
|
||||
static size_t
|
||||
AddLocalLiteralEntry(
|
||||
CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
|
||||
CompileEnv *envPtr, /* Points to CompileEnv in whose literal array
|
||||
* the object is to be inserted. */
|
||||
Tcl_Obj *objPtr, /* The literal to add to the CompileEnv. */
|
||||
size_t localHash) /* Hash value for the literal's string. */
|
||||
@@ -748,7 +791,7 @@ AddLocalLiteralEntry(
|
||||
|
||||
static void
|
||||
ExpandLocalLiteralArray(
|
||||
CompileEnv *envPtr)/* Points to the CompileEnv whose object array
|
||||
CompileEnv *envPtr) /* Points to the CompileEnv whose object array
|
||||
* must be enlarged. */
|
||||
{
|
||||
/*
|
||||
@@ -830,7 +873,7 @@ void
|
||||
TclReleaseLiteral(
|
||||
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
|
||||
* hold a literal. */
|
||||
Tcl_Obj *objPtr) /* Points to a literal object that was
|
||||
Tcl_Obj *objPtr) /* Points to a literal object that was
|
||||
* previously created by a call to
|
||||
* TclRegisterLiteral. */
|
||||
{
|
||||
|
||||
+20
-11
@@ -85,6 +85,12 @@ typedef struct InterpLibrary {
|
||||
* for end of list. */
|
||||
} InterpLibrary;
|
||||
|
||||
/*
|
||||
* Associated data key used to look up the linked list of libraries registered
|
||||
* in the interpreter.
|
||||
*/
|
||||
#define ASSOC_KEY "tclLoad"
|
||||
|
||||
/*
|
||||
* Prototypes for functions that are private to this file:
|
||||
*/
|
||||
@@ -157,13 +163,14 @@ Tcl_LoadObjCmd(
|
||||
&index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
++objv; --objc;
|
||||
++objv;
|
||||
--objc;
|
||||
if (LOAD_GLOBAL == index) {
|
||||
flags |= TCL_LOAD_GLOBAL;
|
||||
} else if (LOAD_LAZY == index) {
|
||||
flags |= TCL_LOAD_LAZY;
|
||||
} else {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((objc < 2) || (objc > 4)) {
|
||||
@@ -278,7 +285,7 @@ Tcl_LoadObjCmd(
|
||||
*/
|
||||
|
||||
if (libraryPtr != NULL) {
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
|
||||
for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
|
||||
if (ipPtr->libraryPtr == libraryPtr) {
|
||||
code = TCL_OK;
|
||||
@@ -514,11 +521,11 @@ Tcl_LoadObjCmd(
|
||||
* static libraries at the head of the linked list!
|
||||
*/
|
||||
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
|
||||
ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary));
|
||||
ipPtr->libraryPtr = libraryPtr;
|
||||
ipPtr->nextPtr = ipFirstPtr;
|
||||
Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipPtr);
|
||||
Tcl_SetAssocData(target, ASSOC_KEY, LoadCleanupProc, ipPtr);
|
||||
|
||||
done:
|
||||
Tcl_DStringFree(&pfx);
|
||||
@@ -599,6 +606,8 @@ Tcl_UnloadObjCmd(
|
||||
case UNLOAD_LAST: /* -- */
|
||||
i++;
|
||||
goto endOfForLoop;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
endOfForLoop:
|
||||
@@ -719,7 +728,7 @@ Tcl_UnloadObjCmd(
|
||||
|
||||
code = TCL_ERROR;
|
||||
if (libraryPtr != NULL) {
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
|
||||
for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
|
||||
if (ipPtr->libraryPtr == libraryPtr) {
|
||||
code = TCL_OK;
|
||||
@@ -861,7 +870,7 @@ UnloadLibrary(
|
||||
*/
|
||||
|
||||
if (!interpExiting) {
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
|
||||
if (ipFirstPtr) {
|
||||
ipPtr = ipFirstPtr;
|
||||
if (ipPtr->libraryPtr == libraryPtr) {
|
||||
@@ -878,7 +887,7 @@ UnloadLibrary(
|
||||
}
|
||||
}
|
||||
Tcl_Free(ipPtr);
|
||||
Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr);
|
||||
Tcl_SetAssocData(target, ASSOC_KEY, LoadCleanupProc, ipFirstPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1055,7 +1064,7 @@ Tcl_StaticLibrary(
|
||||
* it's already loaded.
|
||||
*/
|
||||
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL);
|
||||
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
|
||||
if (ipPtr->libraryPtr == libraryPtr) {
|
||||
return;
|
||||
@@ -1070,7 +1079,7 @@ Tcl_StaticLibrary(
|
||||
ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary));
|
||||
ipPtr->libraryPtr = libraryPtr;
|
||||
ipPtr->nextPtr = ipFirstPtr;
|
||||
Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr);
|
||||
Tcl_SetAssocData(interp, ASSOC_KEY, LoadCleanupProc, ipPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1130,7 +1139,7 @@ TclGetLoadedLibraries(
|
||||
if (target == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
|
||||
ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
|
||||
|
||||
/*
|
||||
* Return information about all of the available libraries.
|
||||
|
||||
+37
-11
@@ -533,13 +533,26 @@ Tcl_MainEx(
|
||||
} else if (is.tty) {
|
||||
resultPtr = Tcl_GetObjResult(interp);
|
||||
Tcl_IncrRefCount(resultPtr);
|
||||
(void)Tcl_GetStringFromObj(resultPtr, &length);
|
||||
chan = Tcl_GetStdChannel(TCL_STDOUT);
|
||||
if ((length > 0) && chan) {
|
||||
if (Tcl_WriteObj(chan, resultPtr) < 0) {
|
||||
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
|
||||
(void)Tcl_AttemptGetStringFromObj(resultPtr, &length);
|
||||
if (!resultPtr->bytes) {
|
||||
chan = Tcl_GetStdChannel(TCL_STDERR);
|
||||
if (chan) {
|
||||
char buf[24];
|
||||
snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "d", resultPtr->length + 1);
|
||||
Tcl_WriteChars(chan, "cannot allocate ", -1);
|
||||
Tcl_WriteChars(chan, buf, -1);
|
||||
Tcl_WriteChars(chan, " bytes for type \'", -1);
|
||||
Tcl_WriteChars(chan, resultPtr->typePtr->name , -1);
|
||||
Tcl_WriteChars(chan, "\'\n", -1);
|
||||
}
|
||||
} else {
|
||||
chan = Tcl_GetStdChannel(TCL_STDOUT);
|
||||
if ((length > 0) && chan) {
|
||||
if (Tcl_WriteObj(chan, resultPtr) < 0) {
|
||||
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
|
||||
}
|
||||
Tcl_WriteChars(chan, "\n", 1);
|
||||
}
|
||||
Tcl_WriteChars(chan, "\n", 1);
|
||||
}
|
||||
Tcl_DecrRefCount(resultPtr);
|
||||
}
|
||||
@@ -813,12 +826,25 @@ StdinProc(
|
||||
chan = Tcl_GetStdChannel(TCL_STDOUT);
|
||||
|
||||
Tcl_IncrRefCount(resultPtr);
|
||||
(void)Tcl_GetStringFromObj(resultPtr, &length);
|
||||
if ((length > 0) && (chan != NULL)) {
|
||||
if (Tcl_WriteObj(chan, resultPtr) < 0) {
|
||||
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
|
||||
(void)Tcl_AttemptGetStringFromObj(resultPtr, &length);
|
||||
if (!resultPtr->bytes) {
|
||||
chan = Tcl_GetStdChannel(TCL_STDERR);
|
||||
if (chan) {
|
||||
char buf[24];
|
||||
snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "d", resultPtr->length + 1);
|
||||
Tcl_WriteChars(chan, "cannot allocate ", -1);
|
||||
Tcl_WriteChars(chan, buf, -1);
|
||||
Tcl_WriteChars(chan, " bytes for type \'", -1);
|
||||
Tcl_WriteChars(chan, resultPtr->typePtr->name , -1);
|
||||
Tcl_WriteChars(chan, "\'\n", -1);
|
||||
}
|
||||
} else {
|
||||
if ((length > 0) && (chan != NULL)) {
|
||||
if (Tcl_WriteObj(chan, resultPtr) < 0) {
|
||||
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
|
||||
}
|
||||
Tcl_WriteChars(chan, "\n", 1);
|
||||
}
|
||||
Tcl_WriteChars(chan, "\n", 1);
|
||||
}
|
||||
Tcl_DecrRefCount(resultPtr);
|
||||
}
|
||||
|
||||
+7
-8
@@ -201,16 +201,15 @@ CreateChildEntry(
|
||||
Namespace *nsPtr, /* Parent namespace. */
|
||||
const char *name) /* Simple name to look for. */
|
||||
{
|
||||
int newEntry;
|
||||
#ifndef BREAK_NAMESPACE_COMPAT
|
||||
return Tcl_CreateHashEntry(&nsPtr->childTable, name, &newEntry);
|
||||
return Tcl_CreateHashEntry(&nsPtr->childTable, name, NULL);
|
||||
#else
|
||||
if (nsPtr->childTablePtr == NULL) {
|
||||
nsPtr->childTablePtr = (Tcl_HashTable *)
|
||||
Tcl_Alloc(sizeof(Tcl_HashTable));
|
||||
Tcl_InitHashTable(nsPtr->childTablePtr, TCL_STRING_KEYS);
|
||||
}
|
||||
return Tcl_CreateHashEntry(nsPtr->childTablePtr, name, &newEntry);
|
||||
return Tcl_CreateHashEntry(nsPtr->childTablePtr, name, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3265,7 +3264,7 @@ NamespaceCodeCmd(
|
||||
* Take care to only check for scoping in precisely the style that
|
||||
* [::namespace code] generates it. Anything more forgiving can have
|
||||
* the effect of failing in namespaces that contain their own custom
|
||||
" "namespace" command. [Bug 3202171].
|
||||
* "namespace" command. [Bug 3202171].
|
||||
*/
|
||||
|
||||
arg = TclGetStringFromObj(objv[1], &length);
|
||||
@@ -4745,7 +4744,7 @@ NamespaceWhichCmd(
|
||||
static const char *const opts[] = {
|
||||
"-command", "-variable", NULL
|
||||
};
|
||||
int lookupType = 0;
|
||||
enum { OPT_COMMAND, OPT_VARIABLE } lookupType = OPT_COMMAND;
|
||||
Tcl_Obj *resultPtr;
|
||||
|
||||
if (objc < 2 || objc > 3) {
|
||||
@@ -4770,7 +4769,7 @@ NamespaceWhichCmd(
|
||||
|
||||
TclNewObj(resultPtr);
|
||||
switch (lookupType) {
|
||||
case 0: { /* -command */
|
||||
case OPT_COMMAND: {
|
||||
Tcl_Command cmd = Tcl_GetCommandFromObj(interp, objv[objc-1]);
|
||||
|
||||
if (cmd != NULL) {
|
||||
@@ -4778,7 +4777,7 @@ NamespaceWhichCmd(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: { /* -variable */
|
||||
case OPT_VARIABLE: {
|
||||
Tcl_Var var = Tcl_FindNamespaceVar(interp,
|
||||
TclGetString(objv[objc-1]), NULL, /*flags*/ 0);
|
||||
|
||||
@@ -4909,7 +4908,7 @@ SetNsNameFromAny(
|
||||
|
||||
name = TclGetString(objPtr);
|
||||
TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS,
|
||||
&nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
|
||||
&nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
|
||||
|
||||
if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) {
|
||||
return TCL_ERROR;
|
||||
|
||||
+1
-1
@@ -390,7 +390,7 @@ Tcl_DeleteEventSource(
|
||||
void
|
||||
Tcl_QueueEvent(
|
||||
Tcl_Event *evPtr, /* Event to add to queue. The storage space
|
||||
* must have been allocated the caller with
|
||||
* must have been allocated by the caller with
|
||||
* malloc (Tcl_Alloc), and it becomes the
|
||||
* property of the event queue. It will be
|
||||
* freed after the event has been handled. */
|
||||
|
||||
+350
-115
@@ -16,37 +16,67 @@
|
||||
#include "tclInt.h"
|
||||
#include "tclOOInt.h"
|
||||
|
||||
/*
|
||||
* Commands in oo and oo::Helpers.
|
||||
*/
|
||||
|
||||
static const struct StdCommands {
|
||||
const char *name;
|
||||
Tcl_ObjCmdProc *objProc;
|
||||
Tcl_ObjCmdProc *nreProc;
|
||||
CompileProc *compileProc;
|
||||
int flags;
|
||||
} ooCmds[] = {
|
||||
{"define", TclOODefineObjCmd, NULL, NULL, 0},
|
||||
{"objdefine", TclOOObjDefObjCmd, NULL, NULL, 0},
|
||||
{"copy", TclOOCopyObjectCmd, NULL, NULL, 0},
|
||||
{"DelegateName", TclOODelegateNameObjCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, 0}
|
||||
}, helpCmds[] = {
|
||||
{"callback", TclOOCallbackObjCmd, NULL, NULL, 0},
|
||||
{"mymethod", TclOOCallbackObjCmd, NULL, NULL, 0},
|
||||
{"classvariable", TclOOClassVariableObjCmd, NULL, NULL, 0},
|
||||
{"link", TclOOLinkObjCmd, NULL, NULL, 0},
|
||||
{"next", NULL, TclOONextObjCmd, TclCompileObjectNextCmd, CMD_COMPILES_EXPANDED},
|
||||
{"nextto", NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd, CMD_COMPILES_EXPANDED},
|
||||
{"self", TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd, 0},
|
||||
{NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Commands in oo::define and oo::objdefine.
|
||||
*/
|
||||
|
||||
static const struct {
|
||||
static const struct DefineCommands {
|
||||
const char *name;
|
||||
Tcl_ObjCmdProc *objProc;
|
||||
int flag;
|
||||
} defineCmds[] = {
|
||||
{"constructor", TclOODefineConstructorObjCmd, 0},
|
||||
{"classmethod", TclOODefineClassMethodObjCmd, 0},
|
||||
{"constructor", TclOODefineConstructorObjCmd, 0},
|
||||
{"definitionnamespace", TclOODefineDefnNsObjCmd, 0},
|
||||
{"deletemethod", TclOODefineDeleteMethodObjCmd, 0},
|
||||
{"destructor", TclOODefineDestructorObjCmd, 0},
|
||||
{"export", TclOODefineExportObjCmd, 0},
|
||||
{"forward", TclOODefineForwardObjCmd, 0},
|
||||
{"method", TclOODefineMethodObjCmd, 0},
|
||||
{"private", TclOODefinePrivateObjCmd, 0},
|
||||
{"renamemethod", TclOODefineRenameMethodObjCmd, 0},
|
||||
{"self", TclOODefineSelfObjCmd, 0},
|
||||
{"unexport", TclOODefineUnexportObjCmd, 0},
|
||||
{"deletemethod", TclOODefineDeleteMethodObjCmd, 0},
|
||||
{"destructor", TclOODefineDestructorObjCmd, 0},
|
||||
{"export", TclOODefineExportObjCmd, 0},
|
||||
{"forward", TclOODefineForwardObjCmd, 0},
|
||||
{"initialise", TclOODefineInitialiseObjCmd, 0},
|
||||
{"initialize", TclOODefineInitialiseObjCmd, 0},
|
||||
{"method", TclOODefineMethodObjCmd, 0},
|
||||
{"private", TclOODefinePrivateObjCmd, 0},
|
||||
{"renamemethod", TclOODefineRenameMethodObjCmd, 0},
|
||||
{"self", TclOODefineSelfObjCmd, 0},
|
||||
{"unexport", TclOODefineUnexportObjCmd, 0},
|
||||
{NULL, NULL, 0}
|
||||
}, objdefCmds[] = {
|
||||
{"class", TclOODefineClassObjCmd, 1},
|
||||
{"deletemethod", TclOODefineDeleteMethodObjCmd, 1},
|
||||
{"export", TclOODefineExportObjCmd, 1},
|
||||
{"forward", TclOODefineForwardObjCmd, 1},
|
||||
{"method", TclOODefineMethodObjCmd, 1},
|
||||
{"private", TclOODefinePrivateObjCmd, 1},
|
||||
{"renamemethod", TclOODefineRenameMethodObjCmd, 1},
|
||||
{"self", TclOODefineObjSelfObjCmd, 0},
|
||||
{"unexport", TclOODefineUnexportObjCmd, 1},
|
||||
{"class", TclOODefineClassObjCmd, 1},
|
||||
{"deletemethod", TclOODefineDeleteMethodObjCmd, 1},
|
||||
{"export", TclOODefineExportObjCmd, 1},
|
||||
{"forward", TclOODefineForwardObjCmd, 1},
|
||||
{"method", TclOODefineMethodObjCmd, 1},
|
||||
{"private", TclOODefinePrivateObjCmd, 1},
|
||||
{"renamemethod", TclOODefineRenameMethodObjCmd, 1},
|
||||
{"self", TclOODefineObjSelfObjCmd, 0},
|
||||
{"unexport", TclOODefineUnexportObjCmd, 1},
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
|
||||
@@ -67,7 +97,7 @@ static int CloneClassMethod(Tcl_Interp *interp, Class *clsPtr,
|
||||
Method **newMPtrPtr);
|
||||
static int CloneObjectMethod(Tcl_Interp *interp, Object *oPtr,
|
||||
Method *mPtr, Tcl_Obj *namePtr);
|
||||
static void DeletedHelpersNamespace(void *clientData);
|
||||
static Tcl_NamespaceDeleteProc DeletedHelpersNamespace;
|
||||
static Tcl_NRPostProc FinalizeAlloc;
|
||||
static Tcl_NRPostProc FinalizeNext;
|
||||
static Tcl_NRPostProc FinalizeObjectCall;
|
||||
@@ -76,23 +106,20 @@ static void InitClassSystemRoots(Tcl_Interp *interp,
|
||||
Foundation *fPtr);
|
||||
static int InitFoundation(Tcl_Interp *interp);
|
||||
static Tcl_InterpDeleteProc KillFoundation;
|
||||
static void MyDeleted(void *clientData);
|
||||
static void ObjectNamespaceDeleted(void *clientData);
|
||||
static void MakeAdditionalClasses(Foundation *fPtr,
|
||||
Tcl_Namespace *defineNs,
|
||||
Tcl_Namespace *objDefineNs);
|
||||
static Tcl_CmdDeleteProc MyDeleted;
|
||||
static Tcl_NamespaceDeleteProc ObjectNamespaceDeleted;
|
||||
static Tcl_CommandTraceProc ObjectRenamedTrace;
|
||||
static inline void RemoveClass(Class **list, size_t num, size_t idx);
|
||||
static inline void RemoveObject(Object **list, size_t num, size_t idx);
|
||||
static inline void SquelchCachedName(Object *oPtr);
|
||||
|
||||
static int PublicNRObjectCmd(void *clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
static int PrivateNRObjectCmd(void *clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
static int MyClassNRObjCmd(void *clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
static void MyClassDeleted(void *clientData);
|
||||
static Tcl_ObjCmdProc PublicNRObjectCmd;
|
||||
static Tcl_ObjCmdProc PrivateNRObjectCmd;
|
||||
static Tcl_ObjCmdProc MyClassNRObjCmd;
|
||||
static Tcl_CmdDeleteProc MyClassDeleted;
|
||||
|
||||
/*
|
||||
* Methods in the oo::object and oo::class classes. First, we define a helper
|
||||
@@ -107,6 +134,7 @@ static void MyClassDeleted(void *clientData);
|
||||
{TCL_OO_METHOD_VERSION_CURRENT,"core method: "#name,proc,NULL,NULL}}
|
||||
|
||||
static const DeclaredClassMethod objMethods[] = {
|
||||
DCM("<cloned>", 0, TclOO_Object_Cloned),
|
||||
DCM("destroy", 1, TclOO_Object_Destroy),
|
||||
DCM("eval", 0, TclOO_Object_Eval),
|
||||
DCM("unknown", 0, TclOO_Object_Unknown),
|
||||
@@ -114,6 +142,7 @@ static const DeclaredClassMethod objMethods[] = {
|
||||
DCM("varname", 0, TclOO_Object_VarName),
|
||||
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
|
||||
}, clsMethods[] = {
|
||||
DCM("<cloned>", 0, TclOO_Class_Cloned),
|
||||
DCM("create", 1, TclOO_Class_Create),
|
||||
DCM("new", 1, TclOO_Class_New),
|
||||
DCM("createWithNamespace", 0, TclOO_Class_CreateNs),
|
||||
@@ -121,6 +150,13 @@ static const DeclaredClassMethod objMethods[] = {
|
||||
}, cfgMethods[] = {
|
||||
DCM("configure", 1, TclOO_Configurable_Configure),
|
||||
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
|
||||
}, singletonMethods[] = {
|
||||
DCM("new", 1, TclOO_Singleton_New),
|
||||
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
|
||||
}, singletonInstanceMethods[] = {
|
||||
DCM("<cloned>", 0, TclOO_SingletonInstance_Cloned),
|
||||
DCM("destroy", 1, TclOO_SingletonInstance_Destroy),
|
||||
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -134,25 +170,25 @@ static const Tcl_MethodType classConstructor = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Scripted parts of TclOO. First, the main script (cannot be outside this
|
||||
* file).
|
||||
* And the oo::configurable constructor...
|
||||
*/
|
||||
|
||||
static const Tcl_MethodType configurableConstructor = {
|
||||
TCL_OO_METHOD_VERSION_CURRENT,
|
||||
"oo::configurable constructor",
|
||||
TclOO_Configurable_Constructor, NULL, NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* The scripted part of TclOO: (legacy) package registration. There's no C API
|
||||
* at all for doing this, not even internally to Tcl.
|
||||
*/
|
||||
|
||||
static const char initScript[] =
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
"package ifneeded TclOO " TCLOO_PATCHLEVEL " {# Already present, OK?};"
|
||||
#endif
|
||||
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};"
|
||||
"namespace eval ::oo { variable version " TCLOO_VERSION " };"
|
||||
"namespace eval ::oo { variable patchlevel " TCLOO_PATCHLEVEL " };";
|
||||
/* "tcl_findLibrary tcloo $oo::version $oo::version" */
|
||||
/* " tcloo.tcl OO_LIBRARY oo::library;"; */
|
||||
|
||||
/*
|
||||
* The scripted part of the definitions of TclOO.
|
||||
*/
|
||||
|
||||
#include "tclOOScript.h"
|
||||
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};";
|
||||
|
||||
/*
|
||||
* The actual definition of the variable holding the TclOO stub table.
|
||||
@@ -181,6 +217,7 @@ MODULE_SCOPE const TclOOStubs tclOOStubs;
|
||||
#define IsRootClass(ocPtr) ((ocPtr)->flags & ROOT_CLASS)
|
||||
#define IsRoot(ocPtr) ((ocPtr)->flags & (ROOT_OBJECT|ROOT_CLASS))
|
||||
|
||||
/* Wrapper for removing an item from a "flexible" item list. */
|
||||
#define RemoveItem(type, lst, i) \
|
||||
do { \
|
||||
Remove ## type ((lst).list, (lst).num, i); \
|
||||
@@ -304,7 +341,8 @@ CreateCmdInNS(
|
||||
const char *name,
|
||||
Tcl_ObjCmdProc *cmdProc,
|
||||
Tcl_ObjCmdProc *nreProc,
|
||||
CompileProc *compileProc)
|
||||
CompileProc *compileProc,
|
||||
int flags)
|
||||
{
|
||||
Command *cmdPtr;
|
||||
|
||||
@@ -315,6 +353,33 @@ CreateCmdInNS(
|
||||
namespacePtr, cmdProc, NULL, NULL);
|
||||
cmdPtr->nreProc = nreProc;
|
||||
cmdPtr->compileProc = compileProc;
|
||||
cmdPtr->flags |= flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* CreateConstantInNSStr --
|
||||
*
|
||||
* Wrapper around TclCreateConstantInNS to make using it with string
|
||||
* constants easier.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static inline void
|
||||
CreateConstantInNSStr(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Namespace *namespacePtr,// The namespace to contain the constant.
|
||||
const char *nameStr, // The unqualified name of the constant.
|
||||
const char *valueStr) // The value to put in the constant.
|
||||
{
|
||||
Tcl_Obj *nameObj = Tcl_NewStringObj(nameStr, TCL_AUTO_LENGTH);
|
||||
Tcl_IncrRefCount(nameObj);
|
||||
Tcl_Obj *valueObj = Tcl_NewStringObj(valueStr, TCL_AUTO_LENGTH);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
TclCreateConstantInNS(interp, (Namespace *) namespacePtr, nameObj, valueObj);
|
||||
Tcl_DecrRefCount(nameObj);
|
||||
Tcl_DecrRefCount(valueObj);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -366,14 +431,20 @@ InitFoundation(
|
||||
TclNewLiteralStringObj(fPtr->clonedName, "<cloned>");
|
||||
TclNewLiteralStringObj(fPtr->defineName, "::oo::define");
|
||||
TclNewLiteralStringObj(fPtr->myName, "my");
|
||||
TclNewLiteralStringObj(fPtr->mcdName, "::oo::MixinClassDelegates");
|
||||
TclNewLiteralStringObj(fPtr->slotGetName, "Get");
|
||||
TclNewLiteralStringObj(fPtr->slotSetName, "Set");
|
||||
TclNewLiteralStringObj(fPtr->slotResolveName, "Resolve");
|
||||
TclNewLiteralStringObj(fPtr->slotDefOpName, "--default-operation");
|
||||
Tcl_IncrRefCount(fPtr->unknownMethodNameObj);
|
||||
Tcl_IncrRefCount(fPtr->constructorName);
|
||||
Tcl_IncrRefCount(fPtr->destructorName);
|
||||
Tcl_IncrRefCount(fPtr->clonedName);
|
||||
Tcl_IncrRefCount(fPtr->defineName);
|
||||
Tcl_IncrRefCount(fPtr->myName);
|
||||
Tcl_IncrRefCount(fPtr->mcdName);
|
||||
Tcl_IncrRefCount(fPtr->slotGetName);
|
||||
Tcl_IncrRefCount(fPtr->slotSetName);
|
||||
Tcl_IncrRefCount(fPtr->slotResolveName);
|
||||
Tcl_IncrRefCount(fPtr->slotDefOpName);
|
||||
|
||||
TclCreateObjCommandInNs(interp, "UnknownDefinition", fPtr->ooNs,
|
||||
TclOOUnknownDefinition, NULL, NULL);
|
||||
@@ -418,7 +489,7 @@ InitFoundation(
|
||||
|
||||
TclNewLiteralStringObj(namePtr, "new");
|
||||
TclNewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr,
|
||||
namePtr /* keeps ref */, 0 /* private */, NULL, NULL);
|
||||
namePtr /*keeps ref*/, 0 /*private*/, NULL, NULL);
|
||||
Tcl_BounceRefCount(namePtr);
|
||||
fPtr->classCls->constructorPtr = (Method *) TclNewMethod(
|
||||
(Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);
|
||||
@@ -428,16 +499,16 @@ InitFoundation(
|
||||
* ensemble.
|
||||
*/
|
||||
|
||||
CreateCmdInNS(interp, fPtr->helpersNs, "next",
|
||||
NULL, TclOONextObjCmd, TclCompileObjectNextCmd);
|
||||
CreateCmdInNS(interp, fPtr->helpersNs, "nextto",
|
||||
NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd);
|
||||
CreateCmdInNS(interp, fPtr->helpersNs, "self",
|
||||
TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd);
|
||||
|
||||
CreateCmdInNS(interp, fPtr->ooNs, "define", TclOODefineObjCmd, NULL, NULL);
|
||||
CreateCmdInNS(interp, fPtr->ooNs, "objdefine", TclOOObjDefObjCmd, NULL, NULL);
|
||||
CreateCmdInNS(interp, fPtr->ooNs, "copy", TclOOCopyObjectCmd, NULL, NULL);
|
||||
for (i = 0 ; helpCmds[i].name ; i++) {
|
||||
CreateCmdInNS(interp, fPtr->helpersNs, helpCmds[i].name,
|
||||
helpCmds[i].objProc, helpCmds[i].nreProc,
|
||||
helpCmds[i].compileProc, helpCmds[i].flags);
|
||||
}
|
||||
for (i = 0 ; ooCmds[i].name ; i++) {
|
||||
CreateCmdInNS(interp, fPtr->ooNs, ooCmds[i].name,
|
||||
ooCmds[i].objProc, ooCmds[i].nreProc,
|
||||
ooCmds[i].compileProc, ooCmds[i].flags);
|
||||
}
|
||||
|
||||
TclOOInitInfo(interp);
|
||||
|
||||
@@ -449,33 +520,13 @@ InitFoundation(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the configurable class and install its standard defined method.
|
||||
*/
|
||||
MakeAdditionalClasses(fPtr, define, objdef);
|
||||
|
||||
Tcl_Object cfgCls = Tcl_NewObjectInstance(interp,
|
||||
(Tcl_Class) fPtr->classCls, "::oo::configuresupport::configurable",
|
||||
NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
TclOODefineBasicMethods(((Object *) cfgCls)->classPtr, cfgMethods);
|
||||
|
||||
/*
|
||||
* Don't have handles to these namespaces, so use Tcl_CreateObjCommand.
|
||||
*/
|
||||
|
||||
Tcl_CreateObjCommand(interp,
|
||||
"::oo::configuresupport::configurableobject::property",
|
||||
TclOODefinePropertyCmd, (void *) 1, NULL);
|
||||
Tcl_CreateObjCommand(interp,
|
||||
"::oo::configuresupport::configurableclass::property",
|
||||
TclOODefinePropertyCmd, (void *) 0, NULL);
|
||||
|
||||
/*
|
||||
* Evaluate the remaining definitions, which are a compiled-in Tcl script.
|
||||
*/
|
||||
|
||||
return Tcl_EvalEx(interp, tclOOSetupScript, TCL_INDEX_NONE, 0);
|
||||
CreateConstantInNSStr(interp, fPtr->ooNs, "version", TCLOO_VERSION);
|
||||
CreateConstantInNSStr(interp, fPtr->ooNs, "patchlevel", TCLOO_PATCHLEVEL);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -567,6 +618,154 @@ InitClassSystemRoots(
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* MarkAsMetaclass --
|
||||
*
|
||||
* Make a simple class into a metaclass by making it into a subclass of
|
||||
* oo::class. Assumes that the previous class it had can be ignored.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static inline void
|
||||
MarkAsMetaclass(
|
||||
Foundation *fPtr,
|
||||
Class *classPtr)
|
||||
{
|
||||
Class **supers = (Class **) Tcl_Alloc(sizeof(Class *));
|
||||
supers[0] = fPtr->classCls;
|
||||
AddRef(supers[0]->thisPtr);
|
||||
TclOOSetSuperclasses(classPtr, 1, supers);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* MakeAdditionalClasses --
|
||||
*
|
||||
* Make the extra classes in TclOO that aren't core to how it functions.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
MakeAdditionalClasses(
|
||||
Foundation *fPtr,
|
||||
Tcl_Namespace *defineNs,
|
||||
Tcl_Namespace *objDefineNs)
|
||||
{
|
||||
Tcl_Interp *interp = fPtr->interp;
|
||||
|
||||
/*
|
||||
* Make the singleton class, the SingletonInstance class, and install their
|
||||
* standard defined methods.
|
||||
*/
|
||||
|
||||
// A metaclass that is used to make classes that only permit one instance
|
||||
// of them to exist. See singleton(n).
|
||||
Object *singletonObj = (Object *) Tcl_NewObjectInstance(interp,
|
||||
(Tcl_Class) fPtr->classCls, "::oo::singleton",
|
||||
NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
Class *singletonCls = singletonObj->classPtr;
|
||||
TclOODefineBasicMethods(singletonCls, singletonMethods);
|
||||
// Set the superclass to oo::class
|
||||
MarkAsMetaclass(fPtr, singletonCls);
|
||||
// Unexport methods
|
||||
TclOOUnexportMethods(singletonCls, "create", "createWithNamespace", NULL);
|
||||
|
||||
// A mixin used to make an object so it won't be destroyed or cloned (or
|
||||
// at least not easily).
|
||||
Object *singletonInst = (Object *) Tcl_NewObjectInstance(interp,
|
||||
(Tcl_Class) fPtr->classCls, "::oo::SingletonInstance",
|
||||
NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
TclOODefineBasicMethods(singletonInst->classPtr, singletonInstanceMethods);
|
||||
|
||||
/*
|
||||
* Make the abstract class.
|
||||
*/
|
||||
|
||||
// A metaclass that is used to make classes that can't be directly
|
||||
// instantiated. See abstract(n).
|
||||
Object *abstractCls = (Object *) Tcl_NewObjectInstance(interp,
|
||||
(Tcl_Class) fPtr->classCls, "::oo::abstract",
|
||||
NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
// Set the superclass to oo::class
|
||||
MarkAsMetaclass(fPtr, abstractCls->classPtr);
|
||||
// Unexport methods
|
||||
TclOOUnexportMethods(abstractCls->classPtr,
|
||||
"create", "createWithNamespace", "new", NULL);
|
||||
|
||||
/*
|
||||
* Make the configurable class and install its standard defined method.
|
||||
*/
|
||||
|
||||
// The class that contains the implementation of the actual
|
||||
// 'configure' method (mixed into actually configurable classes).
|
||||
// The 'configure' method is in tclOOBasic.c.
|
||||
Object *cfgSupObj = (Object *) Tcl_NewObjectInstance(interp,
|
||||
(Tcl_Class) fPtr->classCls, "::oo::configuresupport::configurable",
|
||||
NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
Class *cfgSupCls = cfgSupObj->classPtr;
|
||||
TclOODefineBasicMethods(cfgSupCls, cfgMethods);
|
||||
|
||||
// Namespaces used as implementation vectors for oo::define and
|
||||
// oo::objdefine when the class/instance is configurable.
|
||||
// Note that these also contain commands implemented in C,
|
||||
// especially the [property] definition command.
|
||||
|
||||
Tcl_Namespace *cfgObjNs = Tcl_CreateNamespace(interp,
|
||||
"::oo::configuresupport::configurableobject", NULL, NULL);
|
||||
TclCreateObjCommandInNs(interp, "property", cfgObjNs,
|
||||
TclOODefinePropertyCmd, INT2PTR(1) /*useInstance*/, NULL);
|
||||
TclCreateObjCommandInNs(interp, "properties", cfgObjNs,
|
||||
TclOODefinePropertyCmd, INT2PTR(1) /*useInstance*/, NULL);
|
||||
Tcl_Export(interp, cfgObjNs, "property", /*reset*/1);
|
||||
TclSetNsPath((Namespace *) cfgObjNs, 1, &objDefineNs);
|
||||
|
||||
Tcl_Namespace *cfgClsNs = Tcl_CreateNamespace(interp,
|
||||
"::oo::configuresupport::configurableclass", NULL, NULL);
|
||||
TclCreateObjCommandInNs(interp, "property", cfgClsNs,
|
||||
TclOODefinePropertyCmd, INT2PTR(0) /*useInstance*/, NULL);
|
||||
TclCreateObjCommandInNs(interp, "properties", cfgClsNs,
|
||||
TclOODefinePropertyCmd, INT2PTR(0) /*useInstance*/, NULL);
|
||||
Tcl_Export(interp, cfgClsNs, "property", /*reset*/1);
|
||||
TclSetNsPath((Namespace *) cfgClsNs, 1, &defineNs);
|
||||
|
||||
// A metaclass that is used to make classes that can be configured in
|
||||
// their creation phase (and later too). All the metaclass itself does is
|
||||
// arrange for the class created to have a 'configure' method and for
|
||||
// oo::define and oo::objdefine (on the class and its instances) to have
|
||||
// a property definition for setting things up for 'configure'.
|
||||
Object *configurableObj = (Object *) Tcl_NewObjectInstance(interp,
|
||||
(Tcl_Class) fPtr->classCls, "::oo::configurable",
|
||||
NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
Class *configurableCls = configurableObj->classPtr;
|
||||
MarkAsMetaclass(fPtr, configurableCls);
|
||||
Tcl_ClassSetConstructor(interp, (Tcl_Class) configurableCls, TclNewMethod(
|
||||
(Tcl_Class) configurableCls, NULL, 0, &configurableConstructor, NULL));
|
||||
|
||||
Tcl_Obj *nsName = Tcl_NewStringObj("::oo::configuresupport::configurableclass",
|
||||
TCL_AUTO_LENGTH);
|
||||
Tcl_IncrRefCount(nsName);
|
||||
if (cfgSupCls->clsDefinitionNs != NULL) {
|
||||
Tcl_DecrRefCount(cfgSupCls->clsDefinitionNs);
|
||||
}
|
||||
cfgSupCls->clsDefinitionNs = nsName;
|
||||
Tcl_IncrRefCount(nsName);
|
||||
if (configurableCls->clsDefinitionNs != NULL) {
|
||||
Tcl_DecrRefCount(configurableCls->clsDefinitionNs);
|
||||
}
|
||||
configurableCls->clsDefinitionNs = nsName;
|
||||
|
||||
nsName = Tcl_NewStringObj("::oo::configuresupport::configurableobject",
|
||||
TCL_AUTO_LENGTH);
|
||||
Tcl_IncrRefCount(nsName);
|
||||
if (cfgSupCls->objDefinitionNs != NULL) {
|
||||
Tcl_DecrRefCount(cfgSupCls->objDefinitionNs);
|
||||
}
|
||||
cfgSupCls->objDefinitionNs = nsName;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -612,7 +811,10 @@ KillFoundation(
|
||||
TclDecrRefCount(fPtr->clonedName);
|
||||
TclDecrRefCount(fPtr->defineName);
|
||||
TclDecrRefCount(fPtr->myName);
|
||||
TclDecrRefCount(fPtr->mcdName);
|
||||
TclDecrRefCount(fPtr->slotGetName);
|
||||
TclDecrRefCount(fPtr->slotSetName);
|
||||
TclDecrRefCount(fPtr->slotResolveName);
|
||||
TclDecrRefCount(fPtr->slotDefOpName);
|
||||
TclOODecrRefCount(fPtr->objectCls->thisPtr);
|
||||
TclOODecrRefCount(fPtr->classCls->thisPtr);
|
||||
|
||||
@@ -796,6 +998,7 @@ AllocObject(
|
||||
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
|
||||
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
|
||||
MyClassDeleted);
|
||||
oPtr->linkedCmdsList = NULL;
|
||||
return oPtr;
|
||||
}
|
||||
|
||||
@@ -840,6 +1043,17 @@ MyDeleted(
|
||||
{
|
||||
Object *oPtr = (Object *) clientData;
|
||||
|
||||
if (oPtr->linkedCmdsList) {
|
||||
Tcl_Size linkc, i;
|
||||
Tcl_Obj **linkv;
|
||||
TclListObjGetElements(NULL, oPtr->linkedCmdsList, &linkc, &linkv);
|
||||
for (i=0 ; i<linkc ; i++) {
|
||||
Tcl_Obj *link = linkv[i];
|
||||
(void) Tcl_DeleteCommand(oPtr->fPtr->interp, TclGetString(link));
|
||||
}
|
||||
Tcl_DecrRefCount(oPtr->linkedCmdsList);
|
||||
oPtr->linkedCmdsList = NULL;
|
||||
}
|
||||
oPtr->myCommand = NULL;
|
||||
}
|
||||
|
||||
@@ -1240,7 +1454,7 @@ ObjectNamespaceDeleted(
|
||||
* freed memory.
|
||||
*/
|
||||
|
||||
if (((Command *) oPtr->command)->flags && CMD_DYING) {
|
||||
if (((Command *) oPtr->command)->flags & CMD_DYING) {
|
||||
/*
|
||||
* Something has already started the command deletion process. We can
|
||||
* go ahead and clean up the namespace,
|
||||
@@ -1387,7 +1601,6 @@ TclOODecrRefCount(
|
||||
Object *oPtr)
|
||||
{
|
||||
if (oPtr->refCount-- <= 1) {
|
||||
|
||||
if (oPtr->classPtr != NULL) {
|
||||
Tcl_Free(oPtr->classPtr);
|
||||
}
|
||||
@@ -1865,6 +2078,16 @@ TclNRNewObjectInstance(
|
||||
return TclOOInvokeContext(contextPtr, interp, objc, objv);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclNewObjectInstanceCommon --
|
||||
*
|
||||
* Common code for handling object allocation. Does the basic object
|
||||
* structure and class structure allocation.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
Object *
|
||||
TclNewObjectInstanceCommon(
|
||||
Tcl_Interp *interp,
|
||||
@@ -1930,6 +2153,17 @@ TclNewObjectInstanceCommon(
|
||||
return oPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* FinalizeAlloc --
|
||||
*
|
||||
* Final stage of NR-aware object allocation, running after the
|
||||
* constructor has been called to decide whether the construction
|
||||
* succeeded or failed.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
FinalizeAlloc(
|
||||
void *data[],
|
||||
@@ -2885,7 +3119,6 @@ Tcl_ObjectContextInvokeNext(
|
||||
CallContext *contextPtr = (CallContext *) context;
|
||||
size_t savedIndex = contextPtr->index;
|
||||
size_t savedSkip = contextPtr->skip;
|
||||
int result;
|
||||
|
||||
if (contextPtr->index + 1 >= contextPtr->callPtr->numChain) {
|
||||
/*
|
||||
@@ -2895,22 +3128,11 @@ Tcl_ObjectContextInvokeNext(
|
||||
* unexpectedly.
|
||||
*/
|
||||
|
||||
const char *methodType;
|
||||
|
||||
if (Tcl_InterpDeleted(interp)) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
|
||||
methodType = "constructor";
|
||||
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
|
||||
methodType = "destructor";
|
||||
} else {
|
||||
methodType = "method";
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"no next %s implementation", methodType));
|
||||
"no next %s implementation", TclOOContextTypeName(contextPtr)));
|
||||
OO_ERROR(interp, NOTHING_NEXT);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2932,8 +3154,8 @@ Tcl_ObjectContextInvokeNext(
|
||||
* Invoke the (advanced) method call context in the caller context.
|
||||
*/
|
||||
|
||||
result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, objc,
|
||||
objv);
|
||||
int result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr,
|
||||
objc, objv);
|
||||
|
||||
/*
|
||||
* Restore the call chain context index as we've finished the inner invoke
|
||||
@@ -2964,22 +3186,11 @@ TclNRObjectContextInvokeNext(
|
||||
* unexpectedly.
|
||||
*/
|
||||
|
||||
const char *methodType;
|
||||
|
||||
if (Tcl_InterpDeleted(interp)) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
|
||||
methodType = "constructor";
|
||||
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
|
||||
methodType = "destructor";
|
||||
} else {
|
||||
methodType = "method";
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"no next %s implementation", methodType));
|
||||
"no next %s implementation", TclOOContextTypeName(contextPtr)));
|
||||
OO_ERROR(interp, NOTHING_NEXT);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -3141,6 +3352,30 @@ Tcl_GetObjectName(
|
||||
return TclOOObjectName(interp, (Object *) object);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOObjectMyName --
|
||||
*
|
||||
* Utility function that returns the name of the object's [my], or NULL
|
||||
* if it has been deleted (or otherwise doesn't exist).
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
Tcl_Obj *
|
||||
TclOOObjectMyName(
|
||||
Tcl_Interp *interp,
|
||||
Object *oPtr)
|
||||
{
|
||||
if (!oPtr->myCommand) {
|
||||
return NULL;
|
||||
}
|
||||
Tcl_Obj *namePtr;
|
||||
TclNewObj(namePtr);
|
||||
Tcl_GetCommandFullName(interp, oPtr->myCommand, namePtr);
|
||||
return namePtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+2
-1
@@ -20,12 +20,13 @@
|
||||
*
|
||||
* tests/oo.test
|
||||
* tests/ooNext2.test
|
||||
* tests/ooUtil.test
|
||||
* unix/tclooConfig.sh
|
||||
* win/tclooConfig.sh
|
||||
*/
|
||||
|
||||
#define TCLOO_VERSION "1.3"
|
||||
#define TCLOO_PATCHLEVEL TCLOO_VERSION ".0"
|
||||
#define TCLOO_PATCHLEVEL TCLOO_VERSION ".1"
|
||||
|
||||
#include "tcl.h"
|
||||
|
||||
|
||||
+700
-68
@@ -19,10 +19,12 @@
|
||||
|
||||
static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp);
|
||||
static Tcl_NRPostProc AfterNRDestructor;
|
||||
static Tcl_NRPostProc DecrRefsPostClassConstructor;
|
||||
static Tcl_NRPostProc PostClassConstructor;
|
||||
static Tcl_NRPostProc FinalizeConstruction;
|
||||
static Tcl_NRPostProc FinalizeEval;
|
||||
static Tcl_NRPostProc NextRestoreFrame;
|
||||
static Tcl_NRPostProc MarkAsSingleton;
|
||||
static Tcl_NRPostProc UpdateClassDelegatesAfterClone;
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -65,6 +67,119 @@ FinalizeConstruction(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* MixinClassDelegates --
|
||||
*
|
||||
* Internal utility for setting up the class delegate.
|
||||
* Runs after the class has called [oo::define] on its argument.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Look up the delegate for a class.
|
||||
static inline Class *
|
||||
GetClassDelegate(
|
||||
Tcl_Interp *interp,
|
||||
Class *clsPtr)
|
||||
{
|
||||
Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
|
||||
clsPtr->thisPtr->namespacePtr->fullName);
|
||||
Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
|
||||
Tcl_DecrRefCount(delegateName);
|
||||
return delegatePtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Patches in the appropriate class delegates' superclasses.
|
||||
* Sonewhat messy because the list of superclasses isn't modified frequently.
|
||||
*/
|
||||
static inline void
|
||||
SetDelegateSuperclasses(
|
||||
Tcl_Interp *interp,
|
||||
Class *clsPtr,
|
||||
Class *delegatePtr)
|
||||
{
|
||||
// Build new list of superclasses
|
||||
int i, j = delegatePtr->superclasses.num, k;
|
||||
Class *superPtr, **supers = (Class **) Tcl_Alloc(sizeof(Class *) *
|
||||
(delegatePtr->superclasses.num + clsPtr->superclasses.num));
|
||||
if (delegatePtr->superclasses.num) {
|
||||
memcpy(supers, delegatePtr->superclasses.list,
|
||||
sizeof(Class *) * delegatePtr->superclasses.num);
|
||||
}
|
||||
FOREACH(superPtr, clsPtr->superclasses) {
|
||||
Class *superDelegatePtr = GetClassDelegate(interp, superPtr);
|
||||
if (!superDelegatePtr) {
|
||||
continue;
|
||||
}
|
||||
for (k=0 ; k<=j ; k++) {
|
||||
if (k == j) {
|
||||
supers[j++] = superDelegatePtr;
|
||||
TclOOAddToSubclasses(delegatePtr, superDelegatePtr);
|
||||
AddRef(superDelegatePtr->thisPtr);
|
||||
break;
|
||||
} else if (supers[k] == superDelegatePtr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Install new list of superclasses;
|
||||
if (delegatePtr->superclasses.num) {
|
||||
Tcl_Free(delegatePtr->superclasses.list);
|
||||
}
|
||||
delegatePtr->superclasses.list = supers;
|
||||
delegatePtr->superclasses.num = j;
|
||||
|
||||
// Definitely don't need to bump any epoch here
|
||||
}
|
||||
|
||||
/*
|
||||
* Mixes the delegate into its controlling class.
|
||||
*/
|
||||
static inline void
|
||||
InstallDelegateAsMixin(
|
||||
Tcl_Interp *interp,
|
||||
Class *clsPtr,
|
||||
Class *delegatePtr)
|
||||
{
|
||||
if (clsPtr->thisPtr->mixins.num == 0) {
|
||||
TclOOObjectSetMixins(clsPtr->thisPtr, 1, &delegatePtr);
|
||||
return;
|
||||
}
|
||||
Class **mixins = (Class **) TclStackAlloc(interp,
|
||||
sizeof(Class *) * (clsPtr->thisPtr->mixins.num + 1));
|
||||
for (int i = 0; i < clsPtr->thisPtr->mixins.num; i++) {
|
||||
mixins[i] = clsPtr->thisPtr->mixins.list[i];
|
||||
if (mixins[i] == delegatePtr) {
|
||||
TclStackFree(interp, (void *) mixins);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mixins[clsPtr->thisPtr->mixins.num] = delegatePtr;
|
||||
TclOOObjectSetMixins(clsPtr->thisPtr, clsPtr->thisPtr->mixins.num + 1, mixins);
|
||||
TclStackFree(interp, mixins);
|
||||
}
|
||||
|
||||
// Patches in the appropriate class delegates.
|
||||
static void
|
||||
MixinClassDelegates(
|
||||
Tcl_Interp *interp,
|
||||
Object *oPtr,
|
||||
Tcl_Obj *delegateName)
|
||||
{
|
||||
Class *clsPtr = oPtr->classPtr;
|
||||
if (clsPtr) {
|
||||
Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
|
||||
if (delegatePtr) {
|
||||
SetDelegateSuperclasses(interp, clsPtr, delegatePtr);
|
||||
InstallDelegateAsMixin(interp, clsPtr, delegatePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -84,7 +199,6 @@ TclOO_Class_Constructor(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
|
||||
Tcl_Obj **invoke, *nameObj;
|
||||
|
||||
size_t skip = Tcl_ObjectContextSkippedArgs(context);
|
||||
if ((size_t) objc > skip + 1) {
|
||||
@@ -101,25 +215,28 @@ TclOO_Class_Constructor(
|
||||
* argument to [oo::define]. [Bug 680503]
|
||||
*/
|
||||
|
||||
nameObj = Tcl_ObjPrintf("%s:: oo ::delegate",
|
||||
Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
|
||||
oPtr->namespacePtr->fullName);
|
||||
Tcl_IncrRefCount(delegateName);
|
||||
Tcl_NewObjectInstance(interp, (Tcl_Class) oPtr->fPtr->classCls,
|
||||
TclGetString(nameObj), NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
Tcl_BounceRefCount(nameObj);
|
||||
TclGetString(delegateName), NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
|
||||
/*
|
||||
* If there's nothing else to do, we're done.
|
||||
*/
|
||||
|
||||
if ((size_t) objc == skip) {
|
||||
return TCL_OK;
|
||||
Tcl_InterpState saved = Tcl_SaveInterpState(interp, TCL_OK);
|
||||
MixinClassDelegates(interp, oPtr, delegateName);
|
||||
Tcl_DecrRefCount(delegateName);
|
||||
return Tcl_RestoreInterpState(interp, saved);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegate to [oo::define] to do the work.
|
||||
*/
|
||||
|
||||
invoke = (Tcl_Obj **) TclStackAlloc(interp, 3 * sizeof(Tcl_Obj *));
|
||||
Tcl_Obj **invoke = (Tcl_Obj **) TclStackAlloc(interp, 3 * sizeof(Tcl_Obj *));
|
||||
invoke[0] = oPtr->fPtr->defineName;
|
||||
invoke[1] = TclOOObjectName(interp, oPtr);
|
||||
invoke[2] = objv[objc - 1];
|
||||
@@ -132,8 +249,8 @@ TclOO_Class_Constructor(
|
||||
Tcl_IncrRefCount(invoke[0]);
|
||||
Tcl_IncrRefCount(invoke[1]);
|
||||
Tcl_IncrRefCount(invoke[2]);
|
||||
TclNRAddCallback(interp, DecrRefsPostClassConstructor,
|
||||
invoke, oPtr, NULL, NULL);
|
||||
TclNRAddCallback(interp, PostClassConstructor,
|
||||
invoke, oPtr, delegateName, NULL);
|
||||
|
||||
/*
|
||||
* Tricky point: do not want the extra reported level in the Tcl stack
|
||||
@@ -143,33 +260,28 @@ TclOO_Class_Constructor(
|
||||
return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called *after* [oo::define] inside the constructor of a class.
|
||||
* Cleans up some temporary storage and sets up the delegate.
|
||||
*/
|
||||
static int
|
||||
DecrRefsPostClassConstructor(
|
||||
PostClassConstructor(
|
||||
void *data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
Tcl_Obj **invoke = (Tcl_Obj **) data[0];
|
||||
Object *oPtr = (Object *) data[1];
|
||||
Tcl_InterpState saved;
|
||||
int code;
|
||||
Tcl_Obj *delegateName = (Tcl_Obj *) data[2];
|
||||
|
||||
TclDecrRefCount(invoke[0]);
|
||||
TclDecrRefCount(invoke[1]);
|
||||
TclDecrRefCount(invoke[2]);
|
||||
invoke[0] = oPtr->fPtr->mcdName;
|
||||
invoke[1] = TclOOObjectName(interp, oPtr);
|
||||
Tcl_IncrRefCount(invoke[0]);
|
||||
Tcl_IncrRefCount(invoke[1]);
|
||||
saved = Tcl_SaveInterpState(interp, result);
|
||||
code = Tcl_EvalObjv(interp, 2, invoke, 0);
|
||||
TclDecrRefCount(invoke[0]);
|
||||
TclDecrRefCount(invoke[1]);
|
||||
TclStackFree(interp, invoke);
|
||||
if (code != TCL_OK) {
|
||||
Tcl_DiscardInterpState(saved);
|
||||
return code;
|
||||
}
|
||||
|
||||
Tcl_InterpState saved = Tcl_SaveInterpState(interp, result);
|
||||
MixinClassDelegates(interp, oPtr, delegateName);
|
||||
Tcl_DecrRefCount(delegateName);
|
||||
return Tcl_RestoreInterpState(interp, saved);
|
||||
}
|
||||
|
||||
@@ -355,6 +467,176 @@ TclOO_Class_New(
|
||||
AddConstructionFinalizer(interp));
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOO_Class_Cloned --
|
||||
*
|
||||
* Handler for cloning classes, which fixes up the delegates. This allows
|
||||
* the clone's class methods to evolve independently of the origin's
|
||||
* class methods; this is how TclOO works by default.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclOO_Class_Cloned(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Interpreter in which to create the object;
|
||||
* also used for error reporting. */
|
||||
Tcl_ObjectContext context, /* The object/call context. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const *objv) /* The actual arguments. */
|
||||
{
|
||||
Tcl_Object targetObject = Tcl_ObjectContextObject(context);
|
||||
Tcl_Size skip = Tcl_ObjectContextSkippedArgs(context);
|
||||
if (skip >= objc) {
|
||||
Tcl_WrongNumArgs(interp, skip, objv, "originObject");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Object originObject = Tcl_GetObjectFromObj(interp, objv[skip]);
|
||||
if (!originObject) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
// Add references so things won't vanish until after
|
||||
// UpdateClassDelegatesAfterClone is finished with them.
|
||||
AddRef((Object *) originObject);
|
||||
AddRef((Object *) targetObject);
|
||||
TclNRAddCallback(interp, UpdateClassDelegatesAfterClone,
|
||||
originObject, targetObject, NULL, NULL);
|
||||
return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
|
||||
}
|
||||
|
||||
// Rebuilds the class inheritance delegation class.
|
||||
static int
|
||||
UpdateClassDelegatesAfterClone(
|
||||
void *data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
Object *originPtr = (Object *) data[0];
|
||||
Object *targetPtr = (Object *) data[1];
|
||||
if (result == TCL_OK && originPtr->classPtr && targetPtr->classPtr) {
|
||||
// Get the originating delegate to be cloned.
|
||||
|
||||
Tcl_Obj *originName = Tcl_ObjPrintf("%s:: oo ::delegate",
|
||||
originPtr->namespacePtr->fullName);
|
||||
Object *originDelegate = (Object *) Tcl_GetObjectFromObj(interp,
|
||||
originName);
|
||||
Tcl_BounceRefCount(originName);
|
||||
// Delegates never have their own delegates, so silently make sure we
|
||||
// don't try to make a clone of them.
|
||||
if (!(originDelegate && originDelegate->classPtr)) {
|
||||
goto noOriginDelegate;
|
||||
}
|
||||
|
||||
// Create the cloned target delegate.
|
||||
|
||||
Tcl_Obj *targetName = Tcl_ObjPrintf("%s:: oo ::delegate",
|
||||
targetPtr->namespacePtr->fullName);
|
||||
Object *targetDelegate = (Object *) Tcl_CopyObjectInstance(interp,
|
||||
(Tcl_Object) originDelegate, Tcl_GetString(targetName), NULL);
|
||||
Tcl_BounceRefCount(targetName);
|
||||
if (targetDelegate == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto noOriginDelegate;
|
||||
}
|
||||
|
||||
// Point the cloned target class at the cloned target delegate.
|
||||
// This is like TclOOObjectSetMixins() but more efficient in this
|
||||
// case as there's definitely no relevant call chains to invalidate
|
||||
// and we're doing a one-for-one replacement.
|
||||
|
||||
Tcl_Size i;
|
||||
Class *mixin;
|
||||
FOREACH(mixin, targetPtr->mixins) {
|
||||
if (mixin == originDelegate->classPtr) {
|
||||
TclOORemoveFromInstances(targetPtr, originDelegate->classPtr);
|
||||
TclOODecrRefCount(originDelegate);
|
||||
targetPtr->mixins.list[i] = targetDelegate->classPtr;
|
||||
TclOOAddToInstances(targetPtr, targetDelegate->classPtr);
|
||||
AddRef(targetDelegate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
noOriginDelegate:
|
||||
TclOODecrRefCount(originPtr);
|
||||
TclOODecrRefCount(targetPtr);
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOO_Configurable_Constructor --
|
||||
*
|
||||
* Implementation for oo::configurable constructor.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclOO_Configurable_Constructor(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
|
||||
Tcl_Size skip = Tcl_ObjectContextSkippedArgs(context);
|
||||
if (objc != skip && objc != skip + 1) {
|
||||
Tcl_WrongNumArgs(interp, skip, objv, "?definitionScript?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Obj *cfgSupportName = Tcl_NewStringObj(
|
||||
"::oo::configuresupport::configurable", TCL_AUTO_LENGTH);
|
||||
Class *mixin = TclOOGetClassFromObj(interp, cfgSupportName);
|
||||
Tcl_BounceRefCount(cfgSupportName);
|
||||
if (!mixin) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
TclOOClassSetMixins(interp, oPtr->classPtr, 1, &mixin);
|
||||
return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOO_Object_Cloned --
|
||||
*
|
||||
* Handler for cloning objects that clones basic bits (only!) of the
|
||||
* object's namespace. Non-procedures, traces, sub-namespaces, etc. need
|
||||
* more complex (and class-specific) handling.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclOO_Object_Cloned(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, // Interpreter for error reporting.
|
||||
Tcl_ObjectContext context, // The object/call context.
|
||||
int objc, // Number of arguments.
|
||||
Tcl_Obj *const *objv) // The actual arguments.
|
||||
{
|
||||
int skip = Tcl_ObjectContextSkippedArgs(context);
|
||||
if (objc != skip + 1) {
|
||||
Tcl_WrongNumArgs(interp, skip, objv, "originObject");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Object *targetObject = (Object *) Tcl_ObjectContextObject(context);
|
||||
Object *originObject = (Object *) Tcl_GetObjectFromObj(interp, objv[skip]);
|
||||
if (!originObject) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Namespace *originNs = (Namespace *) originObject->namespacePtr;
|
||||
Namespace *targetNs = (Namespace *) targetObject->namespacePtr;
|
||||
if (TclCopyNamespaceProcedures(interp, originNs, targetNs) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TclCopyNamespaceVariables(interp, originNs, targetNs);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -401,6 +683,9 @@ TclOO_Object_Destroy(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* Post-NRE-callback for TclOO_Object_Destroy. Deletes the object command if
|
||||
* it's still there, which triggers destruction of the namespace and attached
|
||||
* structures. */
|
||||
static int
|
||||
AfterNRDestructor(
|
||||
void *data[],
|
||||
@@ -488,6 +773,7 @@ TclOO_Object_Eval(
|
||||
return TclNREvalObjEx(interp, scriptPtr, 0, invoker, skip);
|
||||
}
|
||||
|
||||
/* Post-NRE-callback for TclOO_Object_Eval. Cleans up. */
|
||||
static int
|
||||
FinalizeEval(
|
||||
void *data[],
|
||||
@@ -901,6 +1187,98 @@ TclOO_Object_VarName(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOLinkObjCmd --
|
||||
*
|
||||
* Implementation of the [link] command, that makes a command that
|
||||
* invokes a method on the current object. The name of the command and
|
||||
* the name of the method match by default. Note that this command is
|
||||
* only ever to be used inside the body of a procedure-like method,
|
||||
* and is typically intended for constructors.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclOOLinkObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
// Set up common bits.
|
||||
CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
|
||||
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%s may only be called from inside a method",
|
||||
TclGetString(objv[0])));
|
||||
OO_ERROR(interp, CONTEXT_REQUIRED);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
CallContext *context = (CallContext *) framePtr->clientData;
|
||||
Object *oPtr = context->oPtr;
|
||||
if (!oPtr->myCommand) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"cannot link to non-existent callback handle"));
|
||||
OO_ERROR(interp, MY_GONE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Obj *myCmd = Tcl_NewObj();
|
||||
Tcl_GetCommandFullName(interp, oPtr->myCommand, myCmd);
|
||||
if (!oPtr->linkedCmdsList) {
|
||||
oPtr->linkedCmdsList = Tcl_NewListObj(0, NULL);
|
||||
Tcl_IncrRefCount(oPtr->linkedCmdsList);
|
||||
}
|
||||
|
||||
// For each argument
|
||||
for (int i=1; i<objc; i++) {
|
||||
Tcl_Size linkc;
|
||||
Tcl_Obj **linkv, *src, *dst;
|
||||
|
||||
// Parse as list of (one or) two items: source and destination names
|
||||
if (TclListObjGetElements(interp, objv[i], &linkc, &linkv) != TCL_OK) {
|
||||
Tcl_BounceRefCount(myCmd);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (linkc) {
|
||||
case 1:
|
||||
// Degenerate case
|
||||
src = dst = linkv[0];
|
||||
break;
|
||||
case 2:
|
||||
src = linkv[0];
|
||||
dst = linkv[1];
|
||||
break;
|
||||
default:
|
||||
Tcl_BounceRefCount(myCmd);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad link description; must only have one or two elements"));
|
||||
OO_ERROR(interp, CMDLINK_FORMAT);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// Qualify the source if necessary
|
||||
const char *srcStr = TclGetString(src);
|
||||
if (srcStr[0] != ':' || srcStr[1] != ':') {
|
||||
src = Tcl_ObjPrintf("%s::%s",
|
||||
context->oPtr->namespacePtr->fullName, srcStr);
|
||||
}
|
||||
|
||||
// Make the alias command
|
||||
if (TclAliasCreate(interp, interp, interp, src, myCmd, 1, &dst) != TCL_OK) {
|
||||
Tcl_BounceRefCount(myCmd);
|
||||
Tcl_BounceRefCount(src);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// Remember the alias for cleanup if necessary
|
||||
Tcl_ListObjAppendElement(NULL, oPtr->linkedCmdsList, src);
|
||||
}
|
||||
Tcl_BounceRefCount(myCmd);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -958,11 +1336,6 @@ TclOONextToObjCmd(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
CallFrame *framePtr = iPtr->varFramePtr;
|
||||
Class *classPtr;
|
||||
CallContext *contextPtr;
|
||||
Tcl_Size i;
|
||||
Tcl_Object object;
|
||||
const char *methodType;
|
||||
|
||||
/*
|
||||
* Start with sanity checks on the calling context to make sure that we
|
||||
@@ -977,7 +1350,7 @@ TclOONextToObjCmd(
|
||||
OO_ERROR(interp, CONTEXT_REQUIRED);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
contextPtr = (CallContext *) framePtr->clientData;
|
||||
CallContext *contextPtr = (CallContext *) framePtr->clientData;
|
||||
|
||||
/*
|
||||
* Sanity check the arguments; we need the first one to refer to a class.
|
||||
@@ -987,15 +1360,8 @@ TclOONextToObjCmd(
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "class ?arg...?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
object = Tcl_GetObjectFromObj(interp, objv[1]);
|
||||
if (object == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
classPtr = ((Object *) object)->classPtr;
|
||||
Class *classPtr = TclOOGetClassFromObj(interp, objv[1]);
|
||||
if (classPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"\"%s\" is not a class", TclGetString(objv[1])));
|
||||
OO_ERROR(interp, CLASS_REQUIRED);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1005,6 +1371,7 @@ TclOONextToObjCmd(
|
||||
* allow jumping backwards!
|
||||
*/
|
||||
|
||||
Tcl_Size i;
|
||||
for (i=contextPtr->index+1 ; i<contextPtr->callPtr->numChain ; i++) {
|
||||
MInvoke *miPtr = &contextPtr->callPtr->chain[i];
|
||||
|
||||
@@ -1028,14 +1395,7 @@ TclOONextToObjCmd(
|
||||
* is on the chain but unreachable, or not on the chain at all.
|
||||
*/
|
||||
|
||||
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
|
||||
methodType = "constructor";
|
||||
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
|
||||
methodType = "destructor";
|
||||
} else {
|
||||
methodType = "method";
|
||||
}
|
||||
|
||||
const char *methodType = TclOOContextTypeName(contextPtr);
|
||||
for (i=contextPtr->index ; i != TCL_INDEX_NONE ; i--) {
|
||||
MInvoke *miPtr = &contextPtr->callPtr->chain[i];
|
||||
|
||||
@@ -1054,6 +1414,7 @@ TclOONextToObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* Post-NRE-callback for [next] and [nextto]. */
|
||||
static int
|
||||
NextRestoreFrame(
|
||||
void *data[],
|
||||
@@ -1207,13 +1568,7 @@ TclOOSelfObjCmd(
|
||||
} else if (mPtr->declaringObjectPtr != NULL) {
|
||||
declarerPtr = mPtr->declaringObjectPtr;
|
||||
} else {
|
||||
/*
|
||||
* This should be unreachable code.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"method without declarer!", TCL_AUTO_LENGTH));
|
||||
return TCL_ERROR;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
result[0] = TclOOObjectName(interp, declarerPtr);
|
||||
@@ -1239,13 +1594,7 @@ TclOOSelfObjCmd(
|
||||
} else if (mPtr->declaringObjectPtr != NULL) {
|
||||
declarerPtr = mPtr->declaringObjectPtr;
|
||||
} else {
|
||||
/*
|
||||
* This should be unreachable code.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"method without declarer!", TCL_AUTO_LENGTH));
|
||||
return TCL_ERROR;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
result[0] = TclOOObjectName(interp, declarerPtr);
|
||||
@@ -1284,13 +1633,7 @@ TclOOSelfObjCmd(
|
||||
} else if (mPtr->declaringObjectPtr != NULL) {
|
||||
declarerPtr = mPtr->declaringObjectPtr;
|
||||
} else {
|
||||
/*
|
||||
* This should be unreachable code.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"method without declarer!", TCL_AUTO_LENGTH));
|
||||
return TCL_ERROR;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
result[0] = TclOOObjectName(interp, declarerPtr);
|
||||
result[1] = mPtr->namePtr;
|
||||
@@ -1302,8 +1645,9 @@ TclOOSelfObjCmd(
|
||||
TclNewIndexObj(result[1], contextPtr->index);
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));
|
||||
return TCL_OK;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1389,6 +1733,294 @@ TclOOCopyObjectCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOCallbackObjCmd --
|
||||
*
|
||||
* Implementation of the [callback] command, which constructs callbacks
|
||||
* into the current object.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclOOCallbackObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
CallFrame *framePtr = iPtr->varFramePtr;
|
||||
|
||||
/*
|
||||
* Start with sanity checks on the calling context to make sure that we
|
||||
* are invoked from a suitable method context. If so, we can safely
|
||||
* retrieve the handle to the object call context.
|
||||
*/
|
||||
|
||||
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%s may only be called from inside a method",
|
||||
TclGetString(objv[0])));
|
||||
OO_ERROR(interp, CONTEXT_REQUIRED);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
CallContext *contextPtr = (CallContext *) framePtr->clientData;
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "method ...");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// Get the [my] real name.
|
||||
Tcl_Obj *namePtr = TclOOObjectMyName(interp, contextPtr->oPtr);
|
||||
if (!namePtr) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"no possible safe callback without my", TCL_AUTO_LENGTH));
|
||||
OO_ERROR(interp, NO_MY);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// No check that the method exists; could be dynamically added.
|
||||
|
||||
Tcl_Obj *listPtr = Tcl_NewListObj(1, &namePtr);
|
||||
(void) TclListObjAppendElements(NULL, listPtr, objc-1, objv+1);
|
||||
Tcl_SetObjResult(interp, listPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOClassVariableObjCmd --
|
||||
*
|
||||
* Implementation of the [classvariable] command, which links to
|
||||
* variables in the class of the current object.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclOOClassVariableObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
CallFrame *framePtr = iPtr->varFramePtr;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "name ...");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start with sanity checks on the calling context to make sure that we
|
||||
* are invoked from a suitable method context. If so, we can safely
|
||||
* retrieve the handle to the object call context.
|
||||
*/
|
||||
|
||||
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%s may only be called from inside a method",
|
||||
TclGetString(objv[0])));
|
||||
OO_ERROR(interp, CONTEXT_REQUIRED);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// Get a reference to the class's namespace
|
||||
CallContext *contextPtr = (CallContext *) framePtr->clientData;
|
||||
Class *clsPtr = CurrentlyInvoked(contextPtr).mPtr->declaringClassPtr;
|
||||
if (clsPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"method not defined by a class", TCL_AUTO_LENGTH));
|
||||
OO_ERROR(interp, UNMATCHED_CONTEXT);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Namespace *clsNsPtr = clsPtr->thisPtr->namespacePtr;
|
||||
|
||||
// Check the list of variable names
|
||||
for (int i = 1; i < objc; i++) {
|
||||
const char *varName = TclGetString(objv[i]);
|
||||
if (Tcl_StringMatch(varName, "*(*)")) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad variable name \"%s\": can't create a %s",
|
||||
varName, "scalar variable that looks like an array element"));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_StringMatch(varName, "*::*")) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad variable name \"%s\": can't create a %s",
|
||||
varName, "local variable with a namespace separator in it"));
|
||||
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Lastly, link the caller's local variables to the class's variables
|
||||
Tcl_Namespace *ourNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
|
||||
for (int i = 1; i < objc; i++) {
|
||||
// Locate the other variable.
|
||||
iPtr->varFramePtr->nsPtr = (Namespace *) clsNsPtr;
|
||||
Var *arrayPtr, *otherPtr = TclObjLookupVarEx(interp, objv[i], NULL,
|
||||
(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
|
||||
"access", /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr);
|
||||
iPtr->varFramePtr->nsPtr = (Namespace *) ourNsPtr;
|
||||
if (otherPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// Create the new variable and link it to otherPtr.
|
||||
if (TclPtrObjMakeUpvarIdx(interp, otherPtr, objv[i], 0,
|
||||
TCL_INDEX_NONE) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODelegateNameObjCmd --
|
||||
*
|
||||
* Implementation of the [oo::DelegateName] command, which is a utility
|
||||
* that gets the name of the class delegate for a class. It's trivial,
|
||||
* but makes working with them much easier as delegate names are
|
||||
* intentionally hard to create by accident.
|
||||
*
|
||||
* Not part of TclOO public API. No public documentation.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclOODelegateNameObjCmd(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "class");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Class *clsPtr = TclOOGetClassFromObj(interp, objv[1]);
|
||||
if (clsPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s:: oo ::delegate",
|
||||
clsPtr->thisPtr->namespacePtr->fullName));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOO_Singleton_New, MarkAsSingleton --
|
||||
*
|
||||
* Implementation for oo::singleton->new method.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclOO_Singleton_New(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Interpreter in which to create the object;
|
||||
* also used for error reporting. */
|
||||
Tcl_ObjectContext context, /* The object/call context. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const *objv) /* The actual arguments. */
|
||||
{
|
||||
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
|
||||
Class *clsPtr = oPtr->classPtr;
|
||||
|
||||
if (clsPtr->instances.num) {
|
||||
Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->instances.list[0]));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
TclNRAddCallback(interp, MarkAsSingleton, clsPtr, NULL, NULL, NULL);
|
||||
return TclNRNewObjectInstance(interp, (Tcl_Class) clsPtr,
|
||||
NULL, NULL, objc, objv, Tcl_ObjectContextSkippedArgs(context),
|
||||
AddConstructionFinalizer(interp));
|
||||
}
|
||||
|
||||
/* Once the singleton object is made, this mixes in a class to disable easy
|
||||
* deleting of the instance. */
|
||||
static int
|
||||
MarkAsSingleton(
|
||||
void *data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
Class *clsPtr = (Class *) data[0];
|
||||
if (result == TCL_OK && clsPtr->instances.num) {
|
||||
// Prepend oo::SingletonInstance to the list of mixins
|
||||
Tcl_Obj *singletonInstanceName = Tcl_NewStringObj(
|
||||
"::oo::SingletonInstance", TCL_AUTO_LENGTH);
|
||||
Class *singInst = TclOOGetClassFromObj(interp, singletonInstanceName);
|
||||
Tcl_BounceRefCount(singletonInstanceName);
|
||||
if (!singInst) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Object *oPtr = clsPtr->instances.list[0];
|
||||
Tcl_Size mixinc = oPtr->mixins.num;
|
||||
Class **mixins = (Class **)TclStackAlloc(interp,
|
||||
sizeof(Class *) * (mixinc + 1));
|
||||
if (mixinc > 0) {
|
||||
memcpy(mixins + 1, oPtr->mixins.list, mixinc * sizeof(Class *));
|
||||
}
|
||||
mixins[0] = singInst;
|
||||
TclOOObjectSetMixins(oPtr, mixinc + 1, mixins);
|
||||
TclStackFree(interp, mixins);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOO_SingletonInstance_Destroy, TclOO_SingletonInstance_Cloned --
|
||||
*
|
||||
* Implementation for oo::SingletonInstance->destroy method and its
|
||||
* cloning callback method.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclOO_SingletonInstance_Destroy(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Interpreter for error reporting. */
|
||||
TCL_UNUSED(Tcl_ObjectContext),
|
||||
TCL_UNUSED(int),
|
||||
TCL_UNUSED(Tcl_Obj *const *))
|
||||
{
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"may not destroy a singleton object"));
|
||||
OO_ERROR(interp, SINGLETON);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
TclOO_SingletonInstance_Cloned(
|
||||
TCL_UNUSED(void *),
|
||||
Tcl_Interp *interp, /* Interpreter in which to create the object;
|
||||
* also used for error reporting. */
|
||||
TCL_UNUSED(Tcl_ObjectContext),
|
||||
TCL_UNUSED(int),
|
||||
TCL_UNUSED(Tcl_Obj *const *))
|
||||
{
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"may not clone a singleton object"));
|
||||
OO_ERROR(interp, SINGLETON);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+29
-7
@@ -427,6 +427,29 @@ FinalizeMethodRefs(
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOContextTypeName --
|
||||
*
|
||||
* Get the name of the (high-level) type of method that a context is
|
||||
* processing. Used for error message generation.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
const char *
|
||||
TclOOContextTypeName(
|
||||
CallContext *contextPtr)
|
||||
{
|
||||
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
|
||||
return "constructor";
|
||||
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
|
||||
return "destructor";
|
||||
} else {
|
||||
return "method";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -776,9 +799,7 @@ AddPrivateMethodNames(
|
||||
|
||||
FOREACH_HASH(namePtr, mPtr, methodsTablePtr) {
|
||||
if (IS_PRIVATE(mPtr)) {
|
||||
int isNew;
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(namesPtr, namePtr, &isNew);
|
||||
hPtr = Tcl_CreateHashEntry(namesPtr, namePtr, NULL);
|
||||
Tcl_SetHashValue(hPtr, INT2PTR(IN_LIST));
|
||||
}
|
||||
}
|
||||
@@ -1554,14 +1575,13 @@ TclOOGetStereotypeCallChain(
|
||||
}
|
||||
} else {
|
||||
if (hPtr == NULL) {
|
||||
int isNew;
|
||||
if (clsPtr->classChainCache == NULL) {
|
||||
clsPtr->classChainCache = (Tcl_HashTable *)
|
||||
Tcl_Alloc(sizeof(Tcl_HashTable));
|
||||
Tcl_InitObjHashTable(clsPtr->classChainCache);
|
||||
}
|
||||
hPtr = Tcl_CreateHashEntry(clsPtr->classChainCache,
|
||||
methodNameObj, &isNew);
|
||||
methodNameObj, NULL);
|
||||
}
|
||||
callPtr->refCount++;
|
||||
Tcl_SetHashValue(hPtr, callPtr);
|
||||
@@ -1647,6 +1667,7 @@ AddClassFiltersToCallContext(
|
||||
AddClassFiltersToCallContext(oPtr, superPtr, cbPtr, doneFilters,
|
||||
flags);
|
||||
}
|
||||
TCL_FALLTHROUGH();
|
||||
case 0:
|
||||
return;
|
||||
}
|
||||
@@ -1734,7 +1755,7 @@ AddPrivatesFromClassChainToCallContext(
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
case 0:
|
||||
return 0;
|
||||
}
|
||||
@@ -1829,7 +1850,7 @@ AddSimpleClassChainToCallContext(
|
||||
privateDanger |= AddSimpleClassChainToCallContext(superPtr,
|
||||
methodNameObj, cbPtr, doneFilters, flags, filterDecl);
|
||||
}
|
||||
/* FALLTHRU */
|
||||
TCL_FALLTHROUGH();
|
||||
case 0:
|
||||
return privateDanger;
|
||||
}
|
||||
@@ -2067,6 +2088,7 @@ AddSimpleClassDefineNamespaces(
|
||||
FOREACH(superPtr, classPtr->superclasses) {
|
||||
AddSimpleClassDefineNamespaces(superPtr, definePtr, flags);
|
||||
}
|
||||
TCL_FALLTHROUGH();
|
||||
case 0:
|
||||
return;
|
||||
}
|
||||
|
||||
+932
-129
File diff suppressed because it is too large
Load Diff
+40
-55
@@ -51,7 +51,7 @@ static Tcl_ObjCmdProc InfoClassVariablesCmd;
|
||||
static const EnsembleImplMap infoObjectCmds[] = {
|
||||
{"call", InfoObjectCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"class", InfoObjectClassCmd, TclCompileInfoObjectClassCmd, NULL, NULL, 0},
|
||||
{"creationid", InfoObjectIdCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"creationid", InfoObjectIdCmd, TclCompileInfoObjectCreationIdCmd, NULL, NULL, 0},
|
||||
{"definition", InfoObjectDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"filters", InfoObjectFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"forward", InfoObjectForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
@@ -88,22 +88,39 @@ static const EnsembleImplMap infoClassCmds[] = {
|
||||
{"variables", InfoClassVariablesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* LocalVarName --
|
||||
* DescribeMethodArgs --
|
||||
*
|
||||
* Get the name of a local variable (especially a method argument) as a
|
||||
* Tcl value.
|
||||
* Generate the descriptor for the arguments to a method (including a
|
||||
* constructor, usually).
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static inline Tcl_Obj *
|
||||
LocalVarName(
|
||||
CompiledLocal *localPtr)
|
||||
DescribeMethodArgs(
|
||||
Proc *procPtr)
|
||||
{
|
||||
return Tcl_NewStringObj(localPtr->name, TCL_AUTO_LENGTH);
|
||||
Tcl_Obj *argObjList;
|
||||
CompiledLocal *localPtr;
|
||||
|
||||
TclNewObj(argObjList);
|
||||
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
|
||||
localPtr=localPtr->nextPtr) {
|
||||
if (TclIsVarArgument(localPtr)) {
|
||||
Tcl_Obj *argObj;
|
||||
|
||||
TclNewObj(argObj);
|
||||
Tcl_ListObjAppendElement(NULL, argObj, Tcl_NewStringObj(
|
||||
localPtr->name, localPtr->nameLength));
|
||||
if (localPtr->defValuePtr != NULL) {
|
||||
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, argObjList, argObj);
|
||||
}
|
||||
}
|
||||
return argObjList;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -252,7 +269,6 @@ InfoObjectDefnCmd(
|
||||
Object *oPtr;
|
||||
Tcl_HashEntry *hPtr;
|
||||
Proc *procPtr;
|
||||
CompiledLocal *localPtr;
|
||||
Tcl_Obj *resultObjs[2];
|
||||
|
||||
if (objc != 3) {
|
||||
@@ -281,20 +297,7 @@ InfoObjectDefnCmd(
|
||||
* We now have the method to describe the definition of.
|
||||
*/
|
||||
|
||||
TclNewObj(resultObjs[0]);
|
||||
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
|
||||
localPtr=localPtr->nextPtr) {
|
||||
if (TclIsVarArgument(localPtr)) {
|
||||
Tcl_Obj *argObj;
|
||||
|
||||
TclNewObj(argObj);
|
||||
Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
|
||||
if (localPtr->defValuePtr != NULL) {
|
||||
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
|
||||
}
|
||||
}
|
||||
resultObjs[0] = DescribeMethodArgs(procPtr);
|
||||
resultObjs[1] = TclOOGetMethodBody((Method *) Tcl_GetHashValue(hPtr));
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
|
||||
return TCL_OK;
|
||||
@@ -485,6 +488,8 @@ InfoObjectIsACmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -538,6 +543,8 @@ InfoObjectIsACmd(
|
||||
result = TclOOIsReachable(o2Ptr->classPtr, oPtr->selfCls);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
|
||||
return TCL_OK;
|
||||
@@ -628,6 +635,8 @@ InfoObjectMethodsCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -995,7 +1004,6 @@ InfoClassConstrCmd(
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Proc *procPtr;
|
||||
CompiledLocal *localPtr;
|
||||
Tcl_Obj *resultObjs[2];
|
||||
Class *clsPtr;
|
||||
|
||||
@@ -1019,20 +1027,7 @@ InfoClassConstrCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclNewObj(resultObjs[0]);
|
||||
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
|
||||
localPtr=localPtr->nextPtr) {
|
||||
if (TclIsVarArgument(localPtr)) {
|
||||
Tcl_Obj *argObj;
|
||||
|
||||
TclNewObj(argObj);
|
||||
Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
|
||||
if (localPtr->defValuePtr != NULL) {
|
||||
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
|
||||
}
|
||||
}
|
||||
resultObjs[0] = DescribeMethodArgs(procPtr);
|
||||
resultObjs[1] = TclOOGetMethodBody(clsPtr->constructorPtr);
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
|
||||
return TCL_OK;
|
||||
@@ -1057,7 +1052,6 @@ InfoClassDefnCmd(
|
||||
{
|
||||
Tcl_HashEntry *hPtr;
|
||||
Proc *procPtr;
|
||||
CompiledLocal *localPtr;
|
||||
Tcl_Obj *resultObjs[2];
|
||||
Class *clsPtr;
|
||||
|
||||
@@ -1087,20 +1081,7 @@ InfoClassDefnCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclNewObj(resultObjs[0]);
|
||||
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
|
||||
localPtr=localPtr->nextPtr) {
|
||||
if (TclIsVarArgument(localPtr)) {
|
||||
Tcl_Obj *argObj;
|
||||
|
||||
TclNewObj(argObj);
|
||||
Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
|
||||
if (localPtr->defValuePtr != NULL) {
|
||||
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
|
||||
}
|
||||
}
|
||||
resultObjs[0] = DescribeMethodArgs(procPtr);
|
||||
resultObjs[1] = TclOOGetMethodBody((Method *) Tcl_GetHashValue(hPtr));
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
|
||||
return TCL_OK;
|
||||
@@ -1145,9 +1126,9 @@ InfoClassDefnNsCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (kind) {
|
||||
if (kind) { // -instance
|
||||
nsNamePtr = clsPtr->objDefinitionNs;
|
||||
} else {
|
||||
} else { // -class
|
||||
nsNamePtr = clsPtr->clsDefinitionNs;
|
||||
}
|
||||
if (nsNamePtr) {
|
||||
@@ -1412,6 +1393,8 @@ InfoClassMethodsCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1427,6 +1410,8 @@ InfoClassMethodsCmd(
|
||||
case SCOPE_UNEXPORTED:
|
||||
flag = 0;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-3
@@ -255,6 +255,7 @@ struct Object {
|
||||
PropertyStorage properties; /* Information relating to the lists of
|
||||
* properties that this object *claims* to
|
||||
* support. */
|
||||
Tcl_Obj *linkedCmdsList; /* List of names of linked commands. */
|
||||
};
|
||||
|
||||
enum ObjectFlags {
|
||||
@@ -405,8 +406,10 @@ struct Foundation {
|
||||
* "<cloned>" pseudo-constructor. */
|
||||
Tcl_Obj *defineName; /* Fully qualified name of oo::define. */
|
||||
Tcl_Obj *myName; /* The "my" shared object. */
|
||||
Tcl_Obj *mcdName; /* The shared object for calling the helper to
|
||||
* mix in class delegates. */
|
||||
Tcl_Obj *slotGetName; /* The "Get" name used by slots. */
|
||||
Tcl_Obj *slotSetName; /* The "Set" name used by slots. */
|
||||
Tcl_Obj *slotResolveName; /* The "Resolve" name used by slots. */
|
||||
Tcl_Obj *slotDefOpName; /* The "--default-operation" name used by slots. */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -498,12 +501,14 @@ struct DeclaredClassMethod {
|
||||
MODULE_SCOPE int TclOOInit(Tcl_Interp *interp);
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOOObjDefObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineClassMethodObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineConstructorObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDefnNsObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDeleteMethodObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDestructorObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineExportObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineForwardObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineInitialiseObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineMethodObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineRenameMethodObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineUnexportObjCmd;
|
||||
@@ -513,7 +518,11 @@ MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjSelfObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePrivateObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePropertyCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOOUnknownDefinition;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOOCallbackObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOOClassVariableObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOOCopyObjectCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOODelegateNameObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOOLinkObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOONextObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOONextToObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclOOSelfObjCmd;
|
||||
@@ -524,16 +533,22 @@ MODULE_SCOPE Tcl_ObjCmdProc TclOOInfoClassPropCmd;
|
||||
* Method implementations (in tclOOBasic.c).
|
||||
*/
|
||||
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Cloned;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Constructor;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Create;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_CreateNs;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_New;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Cloned;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Destroy;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Eval;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_LinkVar;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Unknown;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_VarName;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Configure;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Constructor;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_Singleton_New;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_SingletonInstance_Cloned;
|
||||
MODULE_SCOPE Tcl_MethodCallProc TclOO_SingletonInstance_Destroy;
|
||||
|
||||
/*
|
||||
* Private definitions, some of which perhaps ought to be exposed properly or
|
||||
@@ -567,6 +582,7 @@ MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp,
|
||||
const char *nsNameStr);
|
||||
MODULE_SCOPE int TclOODecrRefCount(Object *oPtr);
|
||||
MODULE_SCOPE int TclOOObjectDestroyed(Object *oPtr);
|
||||
MODULE_SCOPE const char *TclOOContextTypeName(CallContext *contextPtr);
|
||||
MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr);
|
||||
MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr);
|
||||
MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr);
|
||||
@@ -574,6 +590,7 @@ MODULE_SCOPE void TclOODeleteContext(CallContext *contextPtr);
|
||||
MODULE_SCOPE void TclOODeleteDescendants(Tcl_Interp *interp,
|
||||
Object *oPtr);
|
||||
MODULE_SCOPE void TclOODelMethodRef(Method *method);
|
||||
MODULE_SCOPE int TclOOExportMethods(Class *clsPtr, ...);
|
||||
MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr,
|
||||
Tcl_Obj *methodNameObj, int flags,
|
||||
Object *contextObjPtr, Class *contextClsPtr,
|
||||
@@ -608,6 +625,7 @@ MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp,
|
||||
MODULE_SCOPE void TclOODefineBasicMethods(Class *clsPtr,
|
||||
const DeclaredClassMethod *dcm);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOObjectMyName(Tcl_Interp *interp, Object *oPtr);
|
||||
MODULE_SCOPE void TclOOReleaseClassContents(Tcl_Interp *interp,
|
||||
Object *oPtr);
|
||||
MODULE_SCOPE int TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
|
||||
@@ -618,11 +636,14 @@ MODULE_SCOPE int TclOORemoveFromSubclasses(Class *subPtr,
|
||||
Class *superPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclOORenderCallChain(Tcl_Interp *interp,
|
||||
CallChain *callPtr);
|
||||
MODULE_SCOPE void TclOOSetSuperclasses(Class *clsPtr, Tcl_Size superc,
|
||||
Class **superclasses);
|
||||
MODULE_SCOPE void TclOOStashContext(Tcl_Obj *objPtr,
|
||||
CallContext *contextPtr);
|
||||
MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
|
||||
MODULE_SCOPE int TclOOUnexportMethods(Class *clsPtr, ...);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOGetAllObjectProperties(Object *oPtr,
|
||||
int writable);
|
||||
MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOGetPropertyList(PropertyList *propList);
|
||||
MODULE_SCOPE void TclOOReleasePropertyStorage(PropertyStorage *propsPtr);
|
||||
MODULE_SCOPE void TclOOInstallReadableProperties(PropertyStorage *props,
|
||||
|
||||
+22
-14
@@ -99,7 +99,16 @@ static const Tcl_MethodType fwdMethodType = {
|
||||
((Tcl_HashTable *) (&((Namespace *) (contextNs))->varTable))
|
||||
#define TclVarHashGetValue(hPtr) \
|
||||
((Tcl_Var) ((char *)hPtr - offsetof(VarInHash, entry)))
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* AllocProcedureMethodRecord --
|
||||
*
|
||||
* Allocate and initialise the record for procedure-like methods.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static inline ProcedureMethod *
|
||||
AllocProcedureMethodRecord(
|
||||
int flags)
|
||||
@@ -555,7 +564,6 @@ InitCmdFrame(
|
||||
|
||||
if (context.line && context.nline > 1
|
||||
&& (context.line[context.nline - 1] >= 0)) {
|
||||
int isNew;
|
||||
CmdFrame *cfPtr = (CmdFrame *) Tcl_Alloc(sizeof(CmdFrame));
|
||||
Tcl_HashEntry *hPtr;
|
||||
|
||||
@@ -574,7 +582,7 @@ InitCmdFrame(
|
||||
cfPtr->len = 0;
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
|
||||
procPtr, &isNew);
|
||||
procPtr, NULL);
|
||||
Tcl_SetHashValue(hPtr, cfPtr);
|
||||
}
|
||||
|
||||
@@ -586,7 +594,8 @@ InitCmdFrame(
|
||||
Tcl_DecrRefCount(context.data.eval.path);
|
||||
context.data.eval.path = NULL;
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -774,14 +783,14 @@ TclOOMakeProcMethod2(
|
||||
|
||||
InitCmdFrame(iPtr, procPtr);
|
||||
|
||||
return TclNewMethod(
|
||||
(Tcl_Class) clsPtr, nameObj, flags, (const Tcl_MethodType *)typePtr, clientData);
|
||||
return TclNewMethod((Tcl_Class) clsPtr, nameObj, flags,
|
||||
(const Tcl_MethodType *)typePtr, clientData);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* InvokeProcedureMethod, PushMethodCallFrame --
|
||||
* InvokeProcedureMethod, FinalizePMCall, PushMethodCallFrame --
|
||||
*
|
||||
* How to invoke a procedure-like method.
|
||||
*
|
||||
@@ -790,7 +799,7 @@ TclOOMakeProcMethod2(
|
||||
|
||||
static int
|
||||
InvokeProcedureMethod(
|
||||
void *clientData, /* Pointer to some per-method context. */
|
||||
void *clientData, /* Pointer to the per-method record. */
|
||||
Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context, /* The method calling context. */
|
||||
int objc, /* Number of arguments. */
|
||||
@@ -894,9 +903,9 @@ InvokeProcedureMethod(
|
||||
|
||||
static int
|
||||
FinalizePMCall(
|
||||
void *data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
void *data[], /* Data from InvokeProcedureMethod. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int result) /* Result of the body of the method. */
|
||||
{
|
||||
ProcedureMethod *pmPtr = (ProcedureMethod *) data[0];
|
||||
Tcl_ObjectContext context = (Tcl_ObjectContext) data[1];
|
||||
@@ -1548,7 +1557,7 @@ TclOONewForwardMethod(
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* InvokeForwardMethod --
|
||||
* InvokeForwardMethod, FinalizeForwardCall --
|
||||
*
|
||||
* How to invoke a forwarded method. Works by doing some ensemble-like
|
||||
* command rearranging and then invokes some other Tcl command.
|
||||
@@ -1580,7 +1589,7 @@ InvokeForwardMethod(
|
||||
TclListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs);
|
||||
argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
|
||||
numPrefixes, prefixObjs, &len);
|
||||
Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
|
||||
TclNRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
|
||||
/*
|
||||
* NOTE: The combination of direct set of iPtr->lookupNsPtr and the use
|
||||
* of the TCL_EVAL_NOERR flag results in an evaluation configuration
|
||||
@@ -1708,7 +1717,6 @@ TclOOGetFwdFromMethod(
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static Tcl_Obj **
|
||||
InitEnsembleRewrite(
|
||||
Tcl_Interp *interp, /* Place to log the rewrite info. */
|
||||
|
||||
+14
-8
@@ -211,10 +211,10 @@ GetPropertyName(
|
||||
* We use a recursive call to look this up.
|
||||
*/
|
||||
|
||||
Tcl_InterpState foo = Tcl_SaveInterpState(interp, result);
|
||||
Tcl_InterpState state = Tcl_SaveInterpState(interp, result);
|
||||
Tcl_Obj *otherName = GetPropertyName(interp, oPtr,
|
||||
flags ^ (GPN_WRITABLE | GPN_FALLING_BACK), namePtr, NULL);
|
||||
result = Tcl_RestoreInterpState(interp, foo);
|
||||
result = Tcl_RestoreInterpState(interp, state);
|
||||
if (otherName != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"property \"%s\" is %s only",
|
||||
@@ -542,18 +542,18 @@ FindClassProps(
|
||||
* property set. */
|
||||
Tcl_HashTable *accumulator) /* Where to gather the names. */
|
||||
{
|
||||
int i, dummy;
|
||||
int i;
|
||||
Tcl_Obj *propName;
|
||||
Class *mixin, *sup;
|
||||
|
||||
tailRecurse:
|
||||
if (writable) {
|
||||
FOREACH(propName, clsPtr->properties.writable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
|
||||
}
|
||||
} else {
|
||||
FOREACH(propName, clsPtr->properties.readable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
|
||||
}
|
||||
}
|
||||
if (clsPtr->thisPtr->flags & ROOT_OBJECT) {
|
||||
@@ -593,17 +593,17 @@ FindObjectProps(
|
||||
* property set. */
|
||||
Tcl_HashTable *accumulator) /* Where to gather the names. */
|
||||
{
|
||||
int i, dummy;
|
||||
int i;
|
||||
Tcl_Obj *propName;
|
||||
Class *mixin;
|
||||
|
||||
if (writable) {
|
||||
FOREACH(propName, oPtr->properties.writable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
|
||||
}
|
||||
} else {
|
||||
FOREACH(propName, oPtr->properties.readable) {
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
|
||||
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
|
||||
}
|
||||
}
|
||||
FOREACH(mixin, oPtr->mixins) {
|
||||
@@ -1099,6 +1099,8 @@ TclOODefinePropertyCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1221,6 +1223,8 @@ TclOOInfoClassPropCmd(
|
||||
case PROP_WRITABLE:
|
||||
writable = 1;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1279,6 +1283,8 @@ TclOOInfoObjectPropCmd(
|
||||
case PROP_WRITABLE:
|
||||
writable = 1;
|
||||
break;
|
||||
default:
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
/*
|
||||
* tclOOScript.h --
|
||||
*
|
||||
* This file contains support scripts for TclOO. They are defined here so
|
||||
* that the code can be definitely run even in safe interpreters; TclOO's
|
||||
* core setup is safe.
|
||||
*
|
||||
* Copyright (c) 2012-2018 Donal K. Fellows
|
||||
* Copyright (c) 2013 Andreas Kupries
|
||||
* Copyright (c) 2017 Gerald Lester
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifndef TCL_OO_SCRIPT_H
|
||||
#define TCL_OO_SCRIPT_H
|
||||
|
||||
/*
|
||||
* The scripted part of the definitions of TclOO.
|
||||
*
|
||||
* Compiled from tools/tclOOScript.tcl by tools/makeHeader.tcl, which
|
||||
* contains the commented version of everything; *this* file is automatically
|
||||
* generated.
|
||||
*/
|
||||
|
||||
static const char *tclOOSetupScript =
|
||||
/* !BEGIN!: Do not edit below this line. */
|
||||
"::namespace eval ::oo {\n"
|
||||
"\t::namespace path {}\n"
|
||||
"\tnamespace eval Helpers {\n"
|
||||
"\t\tnamespace path {}\n"
|
||||
"\t\tproc callback {method args} {\n"
|
||||
"\t\t\tlist [uplevel 1 {::namespace which my}] $method {*}$args\n"
|
||||
"\t\t}\n"
|
||||
"\t\tnamespace export callback\n"
|
||||
"\t\tnamespace eval tmp {namespace import ::oo::Helpers::callback}\n"
|
||||
"\t\tnamespace export -clear\n"
|
||||
"\t\trename tmp::callback mymethod\n"
|
||||
"\t\tnamespace delete tmp\n"
|
||||
"\t\tproc classvariable {name args} {\n"
|
||||
"\t\t\tset ns [info object namespace [uplevel 1 {self class}]]\n"
|
||||
"\t\t\tforeach v [list $name {*}$args] {\n"
|
||||
"\t\t\t\tif {[string match *(*) $v]} {\n"
|
||||
"\t\t\t\t\tset reason \"can\'t create a scalar variable that looks like an array element\"\n"
|
||||
"\t\t\t\t\treturn -code error -errorcode {TCL UPVAR LOCAL_ELEMENT} \\\n"
|
||||
"\t\t\t\t\t\t[format {bad variable name \"%s\": %s} $v $reason]\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tif {[string match *::* $v]} {\n"
|
||||
"\t\t\t\t\tset reason \"can\'t create a local variable with a namespace separator in it\"\n"
|
||||
"\t\t\t\t\treturn -code error -errorcode {TCL UPVAR INVERTED} \\\n"
|
||||
"\t\t\t\t\t\t[format {bad variable name \"%s\": %s} $v $reason]\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tlappend vs $v $v\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\ttailcall namespace upvar $ns {*}$vs\n"
|
||||
"\t\t}\n"
|
||||
"\t\tproc link {args} {\n"
|
||||
"\t\t\tset ns [uplevel 1 {::namespace current}]\n"
|
||||
"\t\t\tforeach link $args {\n"
|
||||
"\t\t\t\tif {[llength $link] == 2} {\n"
|
||||
"\t\t\t\t\tlassign $link src dst\n"
|
||||
"\t\t\t\t} elseif {[llength $link] == 1} {\n"
|
||||
"\t\t\t\t\tlassign $link src\n"
|
||||
"\t\t\t\t\tset dst $src\n"
|
||||
"\t\t\t\t} else {\n"
|
||||
"\t\t\t\t\treturn -code error -errorcode {TCL OO CMDLINK_FORMAT} \\\n"
|
||||
"\t\t\t\t\t\t\"bad link description; must only have one or two elements\"\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tif {![string match ::* $src]} {\n"
|
||||
"\t\t\t\t\tset src [string cat $ns :: $src]\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t\tinterp alias {} $src {} ${ns}::my $dst\n"
|
||||
"\t\t\t\ttrace add command ${ns}::my delete [list \\\n"
|
||||
"\t\t\t\t\t::oo::UnlinkLinkedCommand $src]\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\treturn\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tproc UnlinkLinkedCommand {cmd args} {\n"
|
||||
"\t\tif {[namespace which $cmd] ne {}} {\n"
|
||||
"\t\t\trename $cmd {}\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tproc DelegateName {class} {\n"
|
||||
"\t\tstring cat [info object namespace $class] {:: oo ::delegate}\n"
|
||||
"\t}\n"
|
||||
"\tproc MixinClassDelegates {class} {\n"
|
||||
"\t\tif {![info object isa class $class]} {\n"
|
||||
"\t\t\treturn\n"
|
||||
"\t\t}\n"
|
||||
"\t\tset delegate [DelegateName $class]\n"
|
||||
"\t\tif {![info object isa class $delegate]} {\n"
|
||||
"\t\t\treturn\n"
|
||||
"\t\t}\n"
|
||||
"\t\tforeach c [info class superclass $class] {\n"
|
||||
"\t\t\tset d [DelegateName $c]\n"
|
||||
"\t\t\tif {![info object isa class $d]} {\n"
|
||||
"\t\t\t\tcontinue\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\tdefine $delegate ::oo::define::superclass -appendifnew $d\n"
|
||||
"\t\t}\n"
|
||||
"\t\tobjdefine $class ::oo::objdefine::mixin -appendifnew $delegate\n"
|
||||
"\t}\n"
|
||||
"\tproc UpdateClassDelegatesAfterClone {originObject targetObject} {\n"
|
||||
"\t\tset originDelegate [DelegateName $originObject]\n"
|
||||
"\t\tset targetDelegate [DelegateName $targetObject]\n"
|
||||
"\t\tif {\n"
|
||||
"\t\t\t[info object isa class $originDelegate]\n"
|
||||
"\t\t\t&& ![info object isa class $targetDelegate]\n"
|
||||
"\t\t} then {\n"
|
||||
"\t\t\tcopy $originDelegate $targetDelegate\n"
|
||||
"\t\t\tobjdefine $targetObject ::oo::objdefine::mixin -set \\\n"
|
||||
"\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n"
|
||||
"\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n"
|
||||
"\t\t\t\t}]\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tproc define::classmethod {name args} {\n"
|
||||
"\t\t::set argc [::llength [::info level 0]]\n"
|
||||
"\t\t::if {$argc == 3} {\n"
|
||||
"\t\t\t::return -code error -errorcode {TCL WRONGARGS} [::format \\\n"
|
||||
"\t\t\t\t{wrong # args: should be \"%s name \?args body\?\"} \\\n"
|
||||
"\t\t\t\t[::lindex [::info level 0] 0]]\n"
|
||||
"\t\t}\n"
|
||||
"\t\t::set cls [::uplevel 1 self]\n"
|
||||
"\t\t::if {$argc == 4} {\n"
|
||||
"\t\t\t::oo::define [::oo::DelegateName $cls] method $name {*}$args\n"
|
||||
"\t\t}\n"
|
||||
"\t\t::tailcall forward $name myclass $name\n"
|
||||
"\t}\n"
|
||||
"\tproc define::initialise {body} {\n"
|
||||
"\t\t::set clsns [::info object namespace [::uplevel 1 self]]\n"
|
||||
"\t\t::tailcall apply [::list {} $body $clsns]\n"
|
||||
"\t}\n"
|
||||
"\tnamespace eval define {\n"
|
||||
"\t\t::namespace export initialise\n"
|
||||
"\t\t::namespace eval tmp {::namespace import ::oo::define::initialise}\n"
|
||||
"\t\t::namespace export -clear\n"
|
||||
"\t\t::rename tmp::initialise initialize\n"
|
||||
"\t\t::namespace delete tmp\n"
|
||||
"\t}\n"
|
||||
"\tdefine Slot {\n"
|
||||
"\t\tmethod Get -unexport {} {\n"
|
||||
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod Set -unexport list {\n"
|
||||
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod Resolve -unexport list {\n"
|
||||
"\t\t\treturn $list\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -set -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\ttailcall my Set $args\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -append -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
"\t\t\ttailcall my Set [list {*}$current {*}$args]\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -appendifnew -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
"\t\t\tforeach a $args {\n"
|
||||
"\t\t\t\tset a [uplevel 1 [list $my Resolve $a]]\n"
|
||||
"\t\t\t\tif {$a ni $current} {\n"
|
||||
"\t\t\t\t\tlappend current $a\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\ttailcall my Set $current\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -clear -export {} {tailcall my Set {}}\n"
|
||||
"\t\tmethod -prepend -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
"\t\t\ttailcall my Set [list {*}$args {*}$current]\n"
|
||||
"\t\t}\n"
|
||||
"\t\tmethod -remove -export args {\n"
|
||||
"\t\t\tset my [namespace which my]\n"
|
||||
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
|
||||
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
|
||||
"\t\t\ttailcall my Set [lmap val $current {\n"
|
||||
"\t\t\t\tif {$val in $args} continue else {set val}\n"
|
||||
"\t\t\t}]\n"
|
||||
"\t\t}\n"
|
||||
"\t\tforward --default-operation my -append\n"
|
||||
"\t\tmethod unknown -unexport {args} {\n"
|
||||
"\t\t\tset def --default-operation\n"
|
||||
"\t\t\tif {[llength $args] == 0} {\n"
|
||||
"\t\t\t\ttailcall my $def\n"
|
||||
"\t\t\t} elseif {![string match -* [lindex $args 0]]} {\n"
|
||||
"\t\t\t\ttailcall my $def {*}$args\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\tnext {*}$args\n"
|
||||
"\t\t}\n"
|
||||
"\t\tunexport destroy\n"
|
||||
"\t}\n"
|
||||
"\tobjdefine define::superclass forward --default-operation my -set\n"
|
||||
"\tobjdefine define::mixin forward --default-operation my -set\n"
|
||||
"\tobjdefine objdefine::mixin forward --default-operation my -set\n"
|
||||
"\tdefine object method <cloned> -unexport {originObject} {\n"
|
||||
"\t\tforeach p [info procs [info object namespace $originObject]::*] {\n"
|
||||
"\t\t\tset args [info args $p]\n"
|
||||
"\t\t\tset idx -1\n"
|
||||
"\t\t\tforeach a $args {\n"
|
||||
"\t\t\t\tif {[info default $p $a d]} {\n"
|
||||
"\t\t\t\t\tlset args [incr idx] [list $a $d]\n"
|
||||
"\t\t\t\t} else {\n"
|
||||
"\t\t\t\t\tlset args [incr idx] [list $a]\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\tset b [info body $p]\n"
|
||||
"\t\t\tset p [namespace tail $p]\n"
|
||||
"\t\t\tproc $p $args $b\n"
|
||||
"\t\t}\n"
|
||||
"\t\tforeach v [info vars [info object namespace $originObject]::*] {\n"
|
||||
"\t\t\tupvar 0 $v vOrigin\n"
|
||||
"\t\t\tnamespace upvar [namespace current] [namespace tail $v] vNew\n"
|
||||
"\t\t\tif {[info exists vOrigin]} {\n"
|
||||
"\t\t\t\tif {[array exists vOrigin]} {\n"
|
||||
"\t\t\t\t\tarray set vNew [array get vOrigin]\n"
|
||||
"\t\t\t\t} else {\n"
|
||||
"\t\t\t\t\tset vNew $vOrigin\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tdefine class method <cloned> -unexport {originObject} {\n"
|
||||
"\t\tnext $originObject\n"
|
||||
"\t\t::oo::UpdateClassDelegatesAfterClone $originObject [self]\n"
|
||||
"\t}\n"
|
||||
"\tclass create singleton {\n"
|
||||
"\t\tsuperclass class\n"
|
||||
"\t\tvariable object\n"
|
||||
"\t\tunexport create createWithNamespace\n"
|
||||
"\t\tmethod new args {\n"
|
||||
"\t\t\tif {![info exists object] || ![info object isa object $object]} {\n"
|
||||
"\t\t\t\tset object [next {*}$args]\n"
|
||||
"\t\t\t\t::oo::objdefine $object {\n"
|
||||
"\t\t\t\t\tmethod destroy {} {\n"
|
||||
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
|
||||
"\t\t\t\t\t\t\t\"may not destroy a singleton object\"\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t\tmethod <cloned> -unexport {originObject} {\n"
|
||||
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
|
||||
"\t\t\t\t\t\t\t\"may not clone a singleton object\"\n"
|
||||
"\t\t\t\t\t}\n"
|
||||
"\t\t\t\t}\n"
|
||||
"\t\t\t}\n"
|
||||
"\t\t\treturn $object\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tclass create abstract {\n"
|
||||
"\t\tsuperclass class\n"
|
||||
"\t\tunexport create createWithNamespace new\n"
|
||||
"\t}\n"
|
||||
"\tnamespace eval configuresupport {\n"
|
||||
"\t\t::namespace eval configurableclass {\n"
|
||||
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
|
||||
"\t\t\t::namespace path ::oo::define\n"
|
||||
"\t\t\t::namespace export property\n"
|
||||
"\t\t}\n"
|
||||
"\t\t::namespace eval configurableobject {\n"
|
||||
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
|
||||
"\t\t\t::namespace path ::oo::objdefine\n"
|
||||
"\t\t\t::namespace export property\n"
|
||||
"\t\t}\n"
|
||||
"\t\t::oo::define configurable {\n"
|
||||
"\t\t\tdefinitionnamespace -instance configurableobject\n"
|
||||
"\t\t\tdefinitionnamespace -class configurableclass\n"
|
||||
"\t\t}\n"
|
||||
"\t}\n"
|
||||
"\tclass create configurable {\n"
|
||||
"\t\tsuperclass class\n"
|
||||
"\t\tconstructor {{definitionScript \"\"}} {\n"
|
||||
"\t\t\tnext {mixin ::oo::configuresupport::configurable}\n"
|
||||
"\t\t\tnext $definitionScript\n"
|
||||
"\t\t}\n"
|
||||
"\t\tdefinitionnamespace -class configuresupport::configurableclass\n"
|
||||
"\t}\n"
|
||||
"}\n"
|
||||
/* !END!: Do not edit above this line. */
|
||||
;
|
||||
|
||||
#endif /* TCL_OO_SCRIPT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
||||
+159
-93
@@ -145,13 +145,13 @@ typedef struct PendingObjData {
|
||||
#define ObjDeletionUnlock(contextPtr) ((contextPtr)->deletionCount--)
|
||||
#define ObjDeletePending(contextPtr) ((contextPtr)->deletionCount > 0)
|
||||
#define ObjOnStack(contextPtr) ((contextPtr)->deletionStack != NULL)
|
||||
#define PushObjToDelete(contextPtr,objPtr) \
|
||||
#define PushObjToDelete(contextPtr, objPtr) \
|
||||
/* The string rep is already invalidated so we can use the bytes value \
|
||||
* for our pointer chain: push onto the head of the stack. */ \
|
||||
(objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
|
||||
* for our pointer chain: push onto the head of the stack. */ \
|
||||
(objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
|
||||
(contextPtr)->deletionStack = (objPtr)
|
||||
#define PopObjToDelete(contextPtr,objPtrVar) \
|
||||
(objPtrVar) = (contextPtr)->deletionStack; \
|
||||
#define PopObjToDelete(contextPtr, objPtrVar) \
|
||||
(objPtrVar) = (contextPtr)->deletionStack; \
|
||||
(contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes
|
||||
|
||||
/*
|
||||
@@ -168,8 +168,8 @@ static __thread PendingObjData pendingObjData;
|
||||
#else
|
||||
static Tcl_ThreadDataKey pendingObjDataKey;
|
||||
#define ObjInitDeletionContext(contextPtr) \
|
||||
PendingObjData *const contextPtr = \
|
||||
(PendingObjData *)Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
|
||||
PendingObjData *const contextPtr = (PendingObjData *) \
|
||||
Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -177,15 +177,15 @@ static Tcl_ThreadDataKey pendingObjDataKey;
|
||||
*/
|
||||
|
||||
#define PACK_BIGNUM(bignum, objPtr) \
|
||||
if ((bignum).used > 0x7FFF) { \
|
||||
mp_int *temp = (mp_int *)Tcl_Alloc(sizeof(mp_int)); \
|
||||
*temp = bignum; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
|
||||
if ((bignum).used > 0x7FFF) { \
|
||||
mp_int *temp = (mp_int *)Tcl_Alloc(sizeof(mp_int)); \
|
||||
*temp = bignum; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
|
||||
} else if (((bignum).alloc <= 0x7FFF) || (mp_shrink(&(bignum))) == MP_OKAY) { \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = (bignum).dp; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = (bignum).dp; \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(((bignum).sign << 30) \
|
||||
| ((bignum).alloc << 15) | ((bignum).used)); \
|
||||
| ((bignum).alloc << 15) | ((bignum).used)); \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -548,7 +548,8 @@ TclContinuationsEnter(
|
||||
ThreadSpecificData *tsdPtr = TclGetContLineTable();
|
||||
Tcl_HashEntry *hPtr =
|
||||
Tcl_CreateHashEntry(tsdPtr->lineCLPtr, objPtr, &newEntry);
|
||||
ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1U) *sizeof(Tcl_Size));
|
||||
ContLineLoc *clLocPtr = (ContLineLoc *)
|
||||
Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1U) *sizeof(Tcl_Size));
|
||||
|
||||
if (!newEntry) {
|
||||
/*
|
||||
@@ -810,11 +811,9 @@ Tcl_RegisterObjType(
|
||||
* be statically allocated (must live
|
||||
* forever). */
|
||||
{
|
||||
int isNew;
|
||||
|
||||
Tcl_MutexLock(&tableMutex);
|
||||
Tcl_SetHashValue(
|
||||
Tcl_CreateHashEntry(&typeTable, typePtr->name, &isNew), typePtr);
|
||||
Tcl_CreateHashEntry(&typeTable, typePtr->name, NULL), typePtr);
|
||||
Tcl_MutexUnlock(&tableMutex);
|
||||
}
|
||||
|
||||
@@ -1556,6 +1555,25 @@ TclObjBeingDeleted(
|
||||
} \
|
||||
}
|
||||
|
||||
#define AttemptSetDuplicateObj(dupPtr, objPtr) \
|
||||
{ \
|
||||
const Tcl_ObjType *typePtr = (objPtr)->typePtr; \
|
||||
const char *bytes = (objPtr)->bytes; \
|
||||
if (bytes) { \
|
||||
(void)TclAttemptInitStringRep((dupPtr), bytes, (objPtr)->length); \
|
||||
} else { \
|
||||
(dupPtr)->bytes = NULL; \
|
||||
} \
|
||||
if (typePtr) { \
|
||||
if (typePtr->dupIntRepProc) { \
|
||||
typePtr->dupIntRepProc((objPtr), (dupPtr)); \
|
||||
} else { \
|
||||
(dupPtr)->internalRep = (objPtr)->internalRep; \
|
||||
(dupPtr)->typePtr = typePtr; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
Tcl_Obj *
|
||||
Tcl_DuplicateObj(
|
||||
Tcl_Obj *objPtr) /* The object to duplicate. */
|
||||
@@ -1567,6 +1585,21 @@ Tcl_DuplicateObj(
|
||||
return dupPtr;
|
||||
}
|
||||
|
||||
Tcl_Obj *
|
||||
Tcl_AttemptDuplicateObj(
|
||||
Tcl_Obj *objPtr) /* The object to duplicate. */
|
||||
{
|
||||
Tcl_Obj *dupPtr;
|
||||
|
||||
TclNewObj(dupPtr);
|
||||
AttemptSetDuplicateObj(dupPtr, objPtr);
|
||||
if (!dupPtr->bytes) {
|
||||
Tcl_DecrRefCount(dupPtr);
|
||||
dupPtr = NULL;
|
||||
}
|
||||
return dupPtr;
|
||||
}
|
||||
|
||||
void
|
||||
TclSetDuplicateObj(
|
||||
Tcl_Obj *dupPtr,
|
||||
@@ -1580,61 +1613,6 @@ TclSetDuplicateObj(
|
||||
SetDuplicateObj(dupPtr, objPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_GetString --
|
||||
*
|
||||
* Returns the string representation byte array pointer for an object.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to the string representation of objPtr. The byte
|
||||
* array referenced by the returned pointer must not be modified by the
|
||||
* caller. Furthermore, the caller must copy the bytes if they need to
|
||||
* retain them since the object's string rep can change as a result of
|
||||
* other operations.
|
||||
*
|
||||
* Side effects:
|
||||
* May call the object's updateStringProc to update the string
|
||||
* representation from the internal representation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_GetString
|
||||
char *
|
||||
Tcl_GetString(
|
||||
Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
|
||||
* be returned. */
|
||||
{
|
||||
if (objPtr->bytes == NULL) {
|
||||
/*
|
||||
* Note we do not check for objPtr->typePtr == NULL. An invariant
|
||||
* of a properly maintained Tcl_Obj is that at least one of
|
||||
* objPtr->bytes and objPtr->typePtr must not be NULL. If broken
|
||||
* extensions fail to maintain that invariant, we can crash here.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr->updateStringProc == NULL) {
|
||||
/*
|
||||
* Those Tcl_ObjTypes which choose not to define an
|
||||
* updateStringProc must be written in such a way that
|
||||
* (objPtr->bytes) never becomes NULL.
|
||||
*/
|
||||
Tcl_Panic("UpdateStringProc should not be invoked for type %s",
|
||||
objPtr->typePtr->name);
|
||||
}
|
||||
objPtr->typePtr->updateStringProc(objPtr);
|
||||
if (objPtr->bytes == NULL || objPtr->length == TCL_INDEX_NONE
|
||||
|| objPtr->bytes[objPtr->length] != '\0') {
|
||||
Tcl_Panic("UpdateStringProc for type '%s' "
|
||||
"failed to create a valid string rep",
|
||||
objPtr->typePtr->name);
|
||||
}
|
||||
}
|
||||
return objPtr->bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1658,7 +1636,7 @@ Tcl_GetString(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED)
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef TclGetStringFromObj
|
||||
char *
|
||||
TclGetStringFromObj(
|
||||
@@ -1702,7 +1680,7 @@ TclGetStringFromObj(
|
||||
}
|
||||
return objPtr->bytes;
|
||||
}
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
#undef Tcl_GetStringFromObj
|
||||
char *
|
||||
@@ -1731,10 +1709,11 @@ Tcl_GetStringFromObj(
|
||||
objPtr->typePtr->name);
|
||||
}
|
||||
objPtr->typePtr->updateStringProc(objPtr);
|
||||
if (objPtr->bytes == NULL
|
||||
|| objPtr->bytes[objPtr->length] != '\0') {
|
||||
Tcl_Panic("UpdateStringProc for type '%s' "
|
||||
"failed to create a valid string rep",
|
||||
if (objPtr->bytes == NULL) {
|
||||
Tcl_Panic("cannot allocate %" TCL_SIZE_MODIFIER "d bytes for type '%s' ",
|
||||
objPtr->length + 1, objPtr->typePtr->name);
|
||||
} else if (objPtr->bytes[objPtr->length] != '\0') {
|
||||
Tcl_Panic("cannot create a valid string rep for type '%s'",
|
||||
objPtr->typePtr->name);
|
||||
}
|
||||
}
|
||||
@@ -1743,6 +1722,86 @@ Tcl_GetStringFromObj(
|
||||
}
|
||||
return objPtr->bytes;
|
||||
}
|
||||
|
||||
char *
|
||||
Tcl_DbGetStringFromObj(
|
||||
Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
|
||||
* be returned. */
|
||||
Tcl_Size *lengthPtr, /* If non-NULL, the location where the string
|
||||
* rep's byte array length should * be stored.
|
||||
* If NULL, no length is stored. */
|
||||
const char *file,
|
||||
int line)
|
||||
{
|
||||
if (objPtr->bytes == NULL) {
|
||||
/*
|
||||
* Note we do not check for objPtr->typePtr == NULL. An invariant
|
||||
* of a properly maintained Tcl_Obj is that at least one of
|
||||
* objPtr->bytes and objPtr->typePtr must not be NULL. If broken
|
||||
* extensions fail to maintain that invariant, we can crash here.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr->updateStringProc == NULL) {
|
||||
/*
|
||||
* Those Tcl_ObjTypes which choose not to define an
|
||||
* updateStringProc must be written in such a way that
|
||||
* (objPtr->bytes) never becomes NULL.
|
||||
*/
|
||||
Tcl_Panic("cannot invoke UpdateStringProc for type %s. %s:%d",
|
||||
objPtr->typePtr->name, file, line);
|
||||
}
|
||||
objPtr->typePtr->updateStringProc(objPtr);
|
||||
if (objPtr->bytes == NULL) {
|
||||
Tcl_Panic("cannot allocate %" TCL_SIZE_MODIFIER "d bytes for type '%s'. %s:%d",
|
||||
objPtr->length + 1, objPtr->typePtr->name, file, line);
|
||||
} else if (objPtr->bytes[objPtr->length] != '\0') {
|
||||
Tcl_Panic("cannot create a valid string rep for type '%s'. %s:%d",
|
||||
objPtr->typePtr->name, file, line);
|
||||
}
|
||||
}
|
||||
if (lengthPtr != NULL) {
|
||||
*lengthPtr = objPtr->length;
|
||||
}
|
||||
return objPtr->bytes;
|
||||
}
|
||||
|
||||
char *
|
||||
Tcl_AttemptGetStringFromObj(
|
||||
Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
|
||||
* be returned. */
|
||||
Tcl_Size *lengthPtr) /* If non-NULL, the location where the string
|
||||
* rep's byte array length should * be stored.
|
||||
* If NULL, no length is stored. */
|
||||
{
|
||||
if (objPtr->bytes == NULL) {
|
||||
/*
|
||||
* Note we do not check for objPtr->typePtr == NULL. An invariant
|
||||
* of a properly maintained Tcl_Obj is that at least one of
|
||||
* objPtr->bytes and objPtr->typePtr must not be NULL. If broken
|
||||
* extensions fail to maintain that invariant, we can crash here.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr->updateStringProc == NULL) {
|
||||
/*
|
||||
* Those Tcl_ObjTypes which choose not to define an
|
||||
* updateStringProc must be written in such a way that
|
||||
* (objPtr->bytes) never becomes NULL.
|
||||
*/
|
||||
Tcl_Panic("cannot invoke UpdateStringProc for type %s",
|
||||
objPtr->typePtr->name);
|
||||
}
|
||||
objPtr->typePtr->updateStringProc(objPtr);
|
||||
if (objPtr->bytes != NULL
|
||||
&& objPtr->bytes[objPtr->length] != '\0') {
|
||||
Tcl_Panic("cannot create a valid string rep for type '%s'",
|
||||
objPtr->typePtr->name);
|
||||
}
|
||||
}
|
||||
if (lengthPtr != NULL) {
|
||||
*lengthPtr = objPtr->bytes ? objPtr->length : -1;
|
||||
}
|
||||
return objPtr->bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2015,13 +2074,15 @@ Tcl_GetBoolFromObj(
|
||||
if (interp) {
|
||||
TclNewObj(objPtr);
|
||||
TclParseNumber(interp, objPtr, (flags & TCL_NULL_OK)
|
||||
? "boolean value or \"\"" : "boolean value", NULL, TCL_INDEX_NONE, NULL, 0);
|
||||
? "boolean value or \"\"" : "boolean value", NULL,
|
||||
TCL_INDEX_NONE, NULL, 0);
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
do {
|
||||
if (TclHasInternalRep(objPtr, &tclIntType) || TclHasInternalRep(objPtr, &tclBooleanType)) {
|
||||
if (TclHasInternalRep(objPtr, &tclIntType)
|
||||
|| TclHasInternalRep(objPtr, &tclBooleanType)) {
|
||||
result = (objPtr->internalRep.wideValue != 0);
|
||||
goto boolEnd;
|
||||
}
|
||||
@@ -2068,7 +2129,8 @@ Tcl_GetBoolFromObj(
|
||||
if (length > 0) {
|
||||
listRep:
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf("expected boolean value%s but got a list",
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected boolean value%s but got a list",
|
||||
(flags & TCL_NULL_OK) ? " or \"\"" : ""));
|
||||
}
|
||||
return TCL_ERROR;
|
||||
@@ -2091,7 +2153,8 @@ Tcl_GetBooleanFromObj(
|
||||
Tcl_Obj *objPtr, /* The object from which to get boolean. */
|
||||
int *intPtr) /* Place to store resulting boolean. */
|
||||
{
|
||||
return Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof(int), (char *)(void *)intPtr);
|
||||
return Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof(int),
|
||||
(char *)(void *)intPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2470,8 +2533,9 @@ Tcl_GetDoubleFromObj(
|
||||
if (length > 0) {
|
||||
listRep:
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("expected floating-point number but got a list", TCL_INDEX_NONE));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"expected floating-point number but got a list",
|
||||
TCL_INDEX_NONE));
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -4186,11 +4250,13 @@ AllocObjEntry(
|
||||
void *keyPtr) /* Key to store in the hash table entry. */
|
||||
{
|
||||
Tcl_Obj *objPtr = (Tcl_Obj *)keyPtr;
|
||||
Tcl_HashEntry *hPtr = (Tcl_HashEntry *)Tcl_Alloc(sizeof(Tcl_HashEntry));
|
||||
Tcl_HashEntry *hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(sizeof(Tcl_HashEntry));
|
||||
|
||||
hPtr->key.objPtr = objPtr;
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
hPtr->clientData = NULL;
|
||||
if (hPtr) {
|
||||
hPtr->key.objPtr = objPtr;
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
hPtr->clientData = NULL;
|
||||
}
|
||||
|
||||
return hPtr;
|
||||
}
|
||||
@@ -4226,10 +4292,10 @@ TclCompareObjKeys(
|
||||
* If the object pointers are the same then they match.
|
||||
* OPT: this comparison was moved to the caller
|
||||
|
||||
if (objPtr1 == objPtr2) {
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
if (objPtr1 == objPtr2) {
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
|
||||
|
||||
+108
-20
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#define ALLOW_DEPRECATED_OPCODES
|
||||
#include "tclCompile.h"
|
||||
#include <assert.h>
|
||||
|
||||
@@ -79,38 +80,48 @@ LocateTargetAddresses(
|
||||
currentInstPtr < envPtr->codeNext ;
|
||||
currentInstPtr += AddrLength(currentInstPtr)) {
|
||||
switch (*currentInstPtr) {
|
||||
#ifndef REMOVE_DEPRECATED_OPCODES
|
||||
case INST_JUMP1:
|
||||
case INST_JUMP_TRUE1:
|
||||
case INST_JUMP_FALSE1:
|
||||
targetInstPtr = currentInstPtr+TclGetInt1AtPtr(currentInstPtr+1);
|
||||
goto storeTarget;
|
||||
case INST_JUMP4:
|
||||
case INST_JUMP_TRUE4:
|
||||
case INST_JUMP_FALSE4:
|
||||
#endif
|
||||
case INST_JUMP:
|
||||
case INST_JUMP_TRUE:
|
||||
case INST_JUMP_FALSE:
|
||||
case INST_START_CMD:
|
||||
targetInstPtr = currentInstPtr+TclGetInt4AtPtr(currentInstPtr+1);
|
||||
goto storeTarget;
|
||||
case INST_BEGIN_CATCH4:
|
||||
case INST_BEGIN_CATCH:
|
||||
targetInstPtr = envPtr->codeStart + envPtr->exceptArrayPtr[
|
||||
TclGetUInt4AtPtr(currentInstPtr+1)].codeOffset;
|
||||
storeTarget:
|
||||
DefineTargetAddress(tablePtr, targetInstPtr);
|
||||
break;
|
||||
case INST_JUMP_TABLE_NUM:
|
||||
hPtr = Tcl_FirstHashEntry(
|
||||
&JUMPTABLENUMINFO(envPtr, currentInstPtr+1)->hashTable,
|
||||
&hSearch);
|
||||
goto storeJumpTableTargets;
|
||||
case INST_JUMP_TABLE:
|
||||
hPtr = Tcl_FirstHashEntry(
|
||||
&JUMPTABLEINFO(envPtr, currentInstPtr+1)->hashTable,
|
||||
&hSearch);
|
||||
storeJumpTableTargets:
|
||||
for (; hPtr ; hPtr = Tcl_NextHashEntry(&hSearch)) {
|
||||
targetInstPtr = currentInstPtr +
|
||||
PTR2INT(Tcl_GetHashValue(hPtr));
|
||||
DefineTargetAddress(tablePtr, targetInstPtr);
|
||||
}
|
||||
break;
|
||||
#ifndef REMOVE_DEPRECATED_OPCODES
|
||||
case INST_RETURN_CODE_BRANCH:
|
||||
for (i=TCL_ERROR ; i<TCL_CONTINUE+1 ; i++) {
|
||||
DefineTargetAddress(tablePtr, currentInstPtr + 2*i - 1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +251,7 @@ ConvertZeroEffectToNOP(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INST_PUSH4:
|
||||
case INST_PUSH:
|
||||
if (nextInst == INST_POP) {
|
||||
blank = size + 1;
|
||||
} else if (nextInst == INST_STR_CONCAT1
|
||||
@@ -258,6 +269,7 @@ ConvertZeroEffectToNOP(
|
||||
|
||||
case INST_LNOT:
|
||||
switch (nextInst) {
|
||||
#ifndef REMOVE_DEPRECATED_OPCODES
|
||||
case INST_JUMP_TRUE1:
|
||||
blank = size;
|
||||
currentInstPtr[size] = INST_JUMP_FALSE1;
|
||||
@@ -266,25 +278,30 @@ ConvertZeroEffectToNOP(
|
||||
blank = size;
|
||||
currentInstPtr[size] = INST_JUMP_TRUE1;
|
||||
break;
|
||||
case INST_JUMP_TRUE4:
|
||||
#endif
|
||||
case INST_JUMP_TRUE:
|
||||
blank = size;
|
||||
currentInstPtr[size] = INST_JUMP_FALSE4;
|
||||
currentInstPtr[size] = INST_JUMP_FALSE;
|
||||
break;
|
||||
case INST_JUMP_FALSE4:
|
||||
case INST_JUMP_FALSE:
|
||||
blank = size;
|
||||
currentInstPtr[size] = INST_JUMP_TRUE4;
|
||||
currentInstPtr[size] = INST_JUMP_TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case INST_TRY_CVT_TO_NUMERIC:
|
||||
switch (nextInst) {
|
||||
#ifndef REMOVE_DEPRECATED_OPCODES
|
||||
case INST_JUMP_TRUE1:
|
||||
case INST_JUMP_TRUE4:
|
||||
case INST_JUMP_FALSE1:
|
||||
case INST_JUMP_FALSE4:
|
||||
#endif
|
||||
case INST_JUMP_TRUE:
|
||||
case INST_JUMP_FALSE:
|
||||
case INST_INCR_SCALAR1:
|
||||
case INST_INCR_SCALAR:
|
||||
case INST_INCR_ARRAY1:
|
||||
case INST_INCR_ARRAY:
|
||||
case INST_INCR_ARRAY_STK:
|
||||
case INST_INCR_SCALAR_STK:
|
||||
case INST_INCR_STK:
|
||||
@@ -351,6 +368,7 @@ AdvanceJumps(
|
||||
int offset, delta, isNew;
|
||||
|
||||
switch (*currentInstPtr) {
|
||||
#ifndef REMOVE_DEPRECATED_OPCODES
|
||||
case INST_JUMP1:
|
||||
case INST_JUMP_TRUE1:
|
||||
case INST_JUMP_FALSE1:
|
||||
@@ -373,7 +391,7 @@ AdvanceJumps(
|
||||
case INST_JUMP1:
|
||||
delta = TclGetInt1AtPtr(currentInstPtr + offset + 1);
|
||||
continue;
|
||||
case INST_JUMP4:
|
||||
case INST_JUMP:
|
||||
delta = TclGetInt4AtPtr(currentInstPtr + offset + 1);
|
||||
continue;
|
||||
}
|
||||
@@ -382,12 +400,13 @@ AdvanceJumps(
|
||||
Tcl_DeleteHashTable(&jumps);
|
||||
TclStoreInt1AtPtr(offset, currentInstPtr + 1);
|
||||
continue;
|
||||
#endif
|
||||
|
||||
case INST_JUMP4:
|
||||
case INST_JUMP_TRUE4:
|
||||
case INST_JUMP_FALSE4:
|
||||
case INST_JUMP:
|
||||
case INST_JUMP_TRUE:
|
||||
case INST_JUMP_FALSE:
|
||||
Tcl_InitHashTable(&jumps, TCL_ONE_WORD_KEYS);
|
||||
Tcl_CreateHashEntry(&jumps, INT2PTR(0), &isNew);
|
||||
Tcl_CreateHashEntry(&jumps, INT2PTR(0), NULL);
|
||||
for (offset = TclGetInt4AtPtr(currentInstPtr + 1); offset!=0 ;) {
|
||||
Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew);
|
||||
if (!isNew) {
|
||||
@@ -398,10 +417,12 @@ AdvanceJumps(
|
||||
case INST_NOP:
|
||||
offset += InstLength(INST_NOP);
|
||||
continue;
|
||||
#ifndef REMOVE_DEPRECATED_OPCODES
|
||||
case INST_JUMP1:
|
||||
offset += TclGetInt1AtPtr(currentInstPtr + offset + 1);
|
||||
continue;
|
||||
case INST_JUMP4:
|
||||
#endif
|
||||
case INST_JUMP:
|
||||
offset += TclGetInt4AtPtr(currentInstPtr + offset + 1);
|
||||
continue;
|
||||
}
|
||||
@@ -414,6 +435,71 @@ AdvanceJumps(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* BetterEqualityTesting --
|
||||
*
|
||||
* Convert PUSH("");OP(STR_EQ); into OP(IS_EMPTY); and some NOPs.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
BetterEqualityTesting(
|
||||
CompileEnv *envPtr)
|
||||
{
|
||||
unsigned char *currentInstPtr, *emptyPushInstPtr = NULL;
|
||||
Tcl_HashTable targets;
|
||||
|
||||
LocateTargetAddresses(envPtr, &targets);
|
||||
for (currentInstPtr = envPtr->codeStart ;
|
||||
currentInstPtr < envPtr->codeNext-1 ;
|
||||
currentInstPtr += AddrLength(currentInstPtr)) {
|
||||
if (emptyPushInstPtr && IsTargetAddress(&targets, currentInstPtr)) {
|
||||
emptyPushInstPtr = NULL;
|
||||
}
|
||||
switch (*currentInstPtr) {
|
||||
case INST_PUSH: {
|
||||
Tcl_Size idx = TclGetUInt4AtPtr(currentInstPtr + 1);
|
||||
Tcl_Obj *literal = TclFetchLiteral(envPtr, idx);
|
||||
if (literal->bytes && literal->length == 0) {
|
||||
emptyPushInstPtr = currentInstPtr;
|
||||
} else {
|
||||
emptyPushInstPtr = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case INST_EQ:
|
||||
case INST_STR_EQ:
|
||||
if (emptyPushInstPtr != NULL) {
|
||||
while (emptyPushInstPtr < currentInstPtr) {
|
||||
*emptyPushInstPtr++ = INST_NOP;
|
||||
}
|
||||
*currentInstPtr = INST_IS_EMPTY;
|
||||
}
|
||||
emptyPushInstPtr = NULL;
|
||||
break;
|
||||
case INST_NEQ:
|
||||
case INST_STR_NEQ:
|
||||
if (emptyPushInstPtr != NULL) {
|
||||
while (emptyPushInstPtr < currentInstPtr) {
|
||||
*emptyPushInstPtr++ = INST_NOP;
|
||||
}
|
||||
currentInstPtr[-1] = INST_IS_EMPTY;
|
||||
currentInstPtr[0] = INST_LNOT;
|
||||
}
|
||||
emptyPushInstPtr = NULL;
|
||||
break;
|
||||
case INST_NOP:
|
||||
break;
|
||||
default:
|
||||
emptyPushInstPtr = NULL;
|
||||
}
|
||||
}
|
||||
Tcl_DeleteHashTable(&targets);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -428,9 +514,11 @@ void
|
||||
TclOptimizeBytecode(
|
||||
void *envPtr)
|
||||
{
|
||||
ConvertZeroEffectToNOP((CompileEnv *)envPtr);
|
||||
AdvanceJumps((CompileEnv *)envPtr);
|
||||
TrimUnreachable((CompileEnv *)envPtr);
|
||||
CompileEnv *realEnvPtr = (CompileEnv *) envPtr;
|
||||
ConvertZeroEffectToNOP(realEnvPtr);
|
||||
BetterEqualityTesting(realEnvPtr);
|
||||
AdvanceJumps(realEnvPtr);
|
||||
TrimUnreachable(realEnvPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+10
-4
@@ -1381,7 +1381,8 @@ Tcl_ParseVarName(
|
||||
*/
|
||||
|
||||
if (*src == '{') {
|
||||
char ch; int braceCount = 0;
|
||||
char ch;
|
||||
int braceCount = 0;
|
||||
src++;
|
||||
numBytes--;
|
||||
tokenPtr->type = TCL_TOKEN_TEXT;
|
||||
@@ -1391,13 +1392,18 @@ Tcl_ParseVarName(
|
||||
ch = *src;
|
||||
while (numBytes && (braceCount>0 || ch != '}')) {
|
||||
switch (ch) {
|
||||
case '{': braceCount++; break;
|
||||
case '}': braceCount--; break;
|
||||
case '{':
|
||||
braceCount++;
|
||||
break;
|
||||
case '}':
|
||||
braceCount--;
|
||||
break;
|
||||
case '\\':
|
||||
/* if 2 or more left, consume 2, else consume
|
||||
* just the \ and let it run into the end */
|
||||
if (numBytes > 1) {
|
||||
src++; numBytes--;
|
||||
src++;
|
||||
numBytes--;
|
||||
}
|
||||
}
|
||||
numBytes--;
|
||||
|
||||
+10
-12
@@ -89,14 +89,15 @@ typedef struct {
|
||||
* fields.
|
||||
*/
|
||||
|
||||
#define PATHOBJ(pathPtr) ((FsPath *) (TclFetchInternalRep((pathPtr), &fsPathType)->twoPtrValue.ptr1))
|
||||
#define PATHOBJ(pathPtr) \
|
||||
((FsPath *) (TclFetchInternalRep((pathPtr), &fsPathType)->twoPtrValue.ptr1))
|
||||
#define SETPATHOBJ(pathPtr,fsPathPtr) \
|
||||
do { \
|
||||
Tcl_ObjInternalRep ir; \
|
||||
ir.twoPtrValue.ptr1 = (void *) (fsPathPtr); \
|
||||
ir.twoPtrValue.ptr2 = NULL; \
|
||||
Tcl_StoreInternalRep((pathPtr), &fsPathType, &ir); \
|
||||
} while (0)
|
||||
do { \
|
||||
Tcl_ObjInternalRep ir; \
|
||||
ir.twoPtrValue.ptr1 = (void *) (fsPathPtr); \
|
||||
ir.twoPtrValue.ptr2 = NULL; \
|
||||
Tcl_StoreInternalRep((pathPtr), &fsPathType, &ir); \
|
||||
} while (0)
|
||||
#define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags)
|
||||
|
||||
/*
|
||||
@@ -679,10 +680,7 @@ TclPathPart(
|
||||
}
|
||||
}
|
||||
default:
|
||||
/* We should never get here */
|
||||
Tcl_Panic("Bad portion to TclPathPart");
|
||||
/* For less clever compilers */
|
||||
return NULL;
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
} else if (fsPathPtr->cwdPtr != NULL) {
|
||||
/* Relative path */
|
||||
@@ -2606,7 +2604,7 @@ Tcl_FSTildeExpand(
|
||||
|
||||
/* path[split] is / for ~user/... or \0 for ~user */
|
||||
result = MakeTildeRelativePath(interp, user,
|
||||
path[split] ? &path[split + 1] : NULL, dsPtr);
|
||||
path[split] ? &path[split + 1] : NULL, dsPtr);
|
||||
Tcl_DStringFree(&dsUser);
|
||||
}
|
||||
if (result != TCL_OK) {
|
||||
|
||||
+19
-20
@@ -50,6 +50,9 @@ typedef struct PkgFiles {
|
||||
* package. */
|
||||
} PkgFiles;
|
||||
|
||||
/* Associated data key used to look up the PkgFiles for an interpreter. */
|
||||
#define ASSOC_KEY "tclPkgFiles"
|
||||
|
||||
/*
|
||||
* For each package that is known in any way to an interpreter, there is one
|
||||
* record of the following type. These records are stored in the
|
||||
@@ -101,7 +104,8 @@ static int PkgRequireCoreFinal(void *data[], Tcl_Interp *interp, int result);
|
||||
static int PkgRequireCoreCleanup(void *data[], Tcl_Interp *interp, int result);
|
||||
static int PkgRequireCoreStep1(void *data[], Tcl_Interp *interp, int result);
|
||||
static int PkgRequireCoreStep2(void *data[], Tcl_Interp *interp, int result);
|
||||
static int TclNRPkgRequireProc(void *clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]);
|
||||
static int TclNRPkgRequireProc(void *clientData, Tcl_Interp *interp,
|
||||
int reqc, Tcl_Obj *const reqv[]);
|
||||
static int SelectPackage(void *data[], Tcl_Interp *interp, int result);
|
||||
static int SelectPackageFinal(void *data[], Tcl_Interp *interp, int result);
|
||||
static int TclNRPackageObjCmdCleanup(void *data[], Tcl_Interp *interp, int result);
|
||||
@@ -258,13 +262,13 @@ TclInitPkgFiles(
|
||||
* If assocdata "tclPkgFiles" doesn't exist yet, create it.
|
||||
*/
|
||||
|
||||
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
|
||||
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
|
||||
if (!pkgFiles) {
|
||||
pkgFiles = (PkgFiles *)Tcl_Alloc(sizeof(PkgFiles));
|
||||
pkgFiles->names = NULL;
|
||||
Tcl_InitHashTable(&pkgFiles->table, TCL_STRING_KEYS);
|
||||
Tcl_SetAssocData(interp, "tclPkgFiles", PkgFilesCleanupProc, pkgFiles);
|
||||
Tcl_SetAssocData(interp, ASSOC_KEY, PkgFilesCleanupProc, pkgFiles);
|
||||
}
|
||||
return pkgFiles;
|
||||
}
|
||||
@@ -274,8 +278,7 @@ TclPkgFileSeen(
|
||||
Tcl_Interp *interp,
|
||||
const char *fileName)
|
||||
{
|
||||
PkgFiles *pkgFiles = (PkgFiles *)
|
||||
Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
|
||||
PkgFiles *pkgFiles = (PkgFiles *) Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
|
||||
if (pkgFiles && pkgFiles->names) {
|
||||
const char *name = pkgFiles->names->name;
|
||||
@@ -857,7 +860,7 @@ SelectPackageFinal(
|
||||
* Pop the "ifneeded" package name from "tclPkgFiles" assocdata
|
||||
*/
|
||||
|
||||
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
|
||||
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
PkgName *pkgName = pkgFiles->names;
|
||||
pkgFiles->names = pkgName->nextPtr;
|
||||
Tcl_Free(pkgName);
|
||||
@@ -1098,13 +1101,12 @@ TclNRPackageObjCmd(
|
||||
}
|
||||
switch (optionIndex) {
|
||||
case PKG_FILES: {
|
||||
PkgFiles *pkgFiles;
|
||||
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "package");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pkgFiles = (PkgFiles *) Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
|
||||
PkgFiles *pkgFiles = (PkgFiles *)
|
||||
Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
if (pkgFiles) {
|
||||
Tcl_HashEntry *entry = Tcl_FindHashEntry(&pkgFiles->table,
|
||||
TclGetString(objv[2]));
|
||||
@@ -1116,12 +1118,11 @@ TclNRPackageObjCmd(
|
||||
break;
|
||||
}
|
||||
case PKG_FORGET: {
|
||||
const char *keyString;
|
||||
PkgFiles *pkgFiles = (PkgFiles *)
|
||||
Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
|
||||
Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
|
||||
|
||||
for (i = 2; i < objc; i++) {
|
||||
keyString = TclGetString(objv[i]);
|
||||
const char *keyString = TclGetString(objv[i]);
|
||||
if (pkgFiles) {
|
||||
hPtr = Tcl_FindHashEntry(&pkgFiles->table, keyString);
|
||||
if (hPtr) {
|
||||
@@ -1157,8 +1158,7 @@ TclNRPackageObjCmd(
|
||||
}
|
||||
case PKG_IFNEEDED: {
|
||||
Tcl_Size length;
|
||||
int res;
|
||||
char *argv3i, *avi;
|
||||
char *argv3i;
|
||||
|
||||
if ((objc != 4) && (objc != 5)) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?");
|
||||
@@ -1183,13 +1183,14 @@ TclNRPackageObjCmd(
|
||||
|
||||
for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
|
||||
prevPtr = availPtr, availPtr = availPtr->nextPtr) {
|
||||
char *avi;
|
||||
if (CheckVersionAndConvert(interp, availPtr->version, &avi,
|
||||
NULL) != TCL_OK) {
|
||||
Tcl_Free(argv3i);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
res = CompareVersions(avi, argv3i, NULL);
|
||||
int res = CompareVersions(avi, argv3i, NULL);
|
||||
Tcl_Free(avi);
|
||||
|
||||
if (res == 0) {
|
||||
@@ -1394,9 +1395,7 @@ TclNRPackageObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
break;
|
||||
case PKG_UNKNOWN: {
|
||||
Tcl_Size length;
|
||||
|
||||
case PKG_UNKNOWN:
|
||||
if (objc == 2) {
|
||||
if (iPtr->packageUnknown != NULL) {
|
||||
Tcl_SetObjResult(interp,
|
||||
@@ -1406,6 +1405,7 @@ TclNRPackageObjCmd(
|
||||
if (iPtr->packageUnknown != NULL) {
|
||||
Tcl_Free(iPtr->packageUnknown);
|
||||
}
|
||||
Tcl_Size length;
|
||||
argv2 = TclGetStringFromObj(objv[2], &length);
|
||||
if (argv2[0] == 0) {
|
||||
iPtr->packageUnknown = NULL;
|
||||
@@ -1417,7 +1417,6 @@ TclNRPackageObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PKG_PREFER: {
|
||||
static const char *const pkgPreferOptions[] = {
|
||||
"latest", "stable", NULL
|
||||
@@ -1528,7 +1527,7 @@ TclNRPackageObjCmd(
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
|
||||
TCL_UNREACHABLE();
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user