Compare commits
579
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba9cf35aa3 | ||
|
|
db41a49d9c | ||
|
|
df06afadcf | ||
|
|
aa199edba6 | ||
|
|
c5e979695a | ||
|
|
5d355c0fd9 | ||
|
|
e6e44fb3b8 | ||
|
|
6fcbcd9f12 | ||
|
|
4751bcf256 | ||
|
|
99ab923ed5 | ||
|
|
72c721f3e7 | ||
|
|
6d4320b5fb | ||
|
|
73de582148 | ||
|
|
d0bce3e99f | ||
|
|
1bf60bab3c | ||
|
|
43f670e530 | ||
|
|
77ab9f868a | ||
|
|
6e7c474da7 | ||
|
|
2d87ed6d29 | ||
|
|
3cda2dc805 | ||
|
|
0a3e263036 | ||
|
|
864d754a8a | ||
|
|
b16ec6f23b | ||
|
|
17e2ed6919 | ||
|
|
15bfd5756e | ||
|
|
0d0b8e03ed | ||
|
|
fd2d896c8f | ||
|
|
f597744c5f | ||
|
|
261fbdac7e | ||
|
|
ec5288cc2e | ||
|
|
90f38b1023 | ||
|
|
64eaafad72 | ||
|
|
62079a5c69 | ||
|
|
41ed3e0e2b | ||
|
|
9ac074bd09 | ||
|
|
bbae63cfa9 | ||
|
|
a275b8a5ea | ||
|
|
962427e8cd | ||
|
|
debafda1e7 | ||
|
|
1af314024c | ||
|
|
23178bb208 | ||
|
|
2ae2445072 | ||
|
|
8bd4a8cf2c | ||
|
|
5ff641a603 | ||
|
|
71618ce230 | ||
|
|
f35817ce5a | ||
|
|
3af272b07a | ||
|
|
67a242e003 | ||
|
|
4ba8623115 | ||
|
|
410bda416e | ||
|
|
861217dbe3 | ||
|
|
a28f176470 | ||
|
|
45f5143205 | ||
|
|
de9c1aff4a | ||
|
|
e7a5b8aaa5 | ||
|
|
cd39f34fa5 | ||
|
|
e7be4a19a0 | ||
|
|
a0374a6e61 | ||
|
|
3f3c89a947 | ||
|
|
6b5d0e5d8d | ||
|
|
d9dbcf5afb | ||
|
|
4dc5255a8e | ||
|
|
e7a86d967c | ||
|
|
6fce39545c | ||
|
|
87fd09e44a | ||
|
|
cd4e0ec5de | ||
|
|
954522812e | ||
|
|
db9b0eccf3 | ||
|
|
06c3fd0c5b | ||
|
|
c13e34da37 | ||
|
|
a9d546dfbc | ||
|
|
6798b2404f | ||
|
|
5fd318bc35 | ||
|
|
88812125b1 | ||
|
|
947fb98db5 | ||
|
|
ed53b715ac | ||
|
|
b8b87e5280 | ||
|
|
0c5bd7480e | ||
|
|
64038c5656 | ||
|
|
101ac8bca7 | ||
|
|
30e7e05895 | ||
|
|
b4d6691add | ||
|
|
ce6aa3ea08 | ||
|
|
3492c92f3d | ||
|
|
d7f41b448c | ||
|
|
405b9175e6 | ||
|
|
2c44354d13 | ||
|
|
612199cbe9 | ||
|
|
f337281f75 | ||
|
|
7fe003f8d2 | ||
|
|
f003df5624 | ||
|
|
9fb9471807 | ||
|
|
0254080ca0 | ||
|
|
8c2cbf3211 | ||
|
|
c68d043691 | ||
|
|
720c8de452 | ||
|
|
596e89b17d | ||
|
|
847a048c18 | ||
|
|
da8fbb89c4 | ||
|
|
0d33258649 | ||
|
|
f406561f40 | ||
|
|
465d28aa75 | ||
|
|
6c0170972f | ||
|
|
4d47b7f97f | ||
|
|
0e5d21e88f | ||
|
|
0c568099ee | ||
|
|
5753c7a42b | ||
|
|
914d6e1546 | ||
|
|
683dada217 | ||
|
|
2cd8bf554e | ||
|
|
e9c0312caf | ||
|
|
9a809e614a | ||
|
|
0bceead396 | ||
|
|
6faf2feff2 | ||
|
|
9090aca429 | ||
|
|
fe83175465 | ||
|
|
468041eef8 | ||
|
|
85233a4693 | ||
|
|
4ad7747c62 | ||
|
|
812174d578 | ||
|
|
471d356605 | ||
|
|
455b61dce3 | ||
|
|
2d54b68224 | ||
|
|
cce4368ace | ||
|
|
7a1cc7e3b3 | ||
|
|
0b90c0b92e | ||
|
|
dda81853f3 | ||
|
|
0af226b20a | ||
|
|
919808c6a5 | ||
|
|
beff988e79 | ||
|
|
e8f10bd44e | ||
|
|
fa3a1e4638 | ||
|
|
74c5043b5a | ||
|
|
dafcde1702 | ||
|
|
e16817b409 | ||
|
|
03a4436237 | ||
|
|
e52e074e4f | ||
|
|
0b5a1c79b7 | ||
|
|
0c44c5003d | ||
|
|
2b9b50b436 | ||
|
|
80fc86a116 | ||
|
|
1da12398f2 | ||
|
|
4322dab97e | ||
|
|
3243dfedd1 | ||
|
|
fa5058cbca | ||
|
|
e62743b6ee | ||
|
|
ade95255b9 | ||
|
|
0b96f3fb32 | ||
|
|
3971514c1b | ||
|
|
e6dd74e90e | ||
|
|
cf4de002dc | ||
|
|
c64afc94f1 | ||
|
|
55898c44b9 | ||
|
|
b9b319fad2 | ||
|
|
5d5bd4cd55 | ||
|
|
1e854210b7 | ||
|
|
7d25e385a2 | ||
|
|
c329006b1a | ||
|
|
40e9ab2e65 | ||
|
|
dc74da2f56 | ||
|
|
c6eb0cc51d | ||
|
|
a7c17bc224 | ||
|
|
2606a3a7db | ||
|
|
ea6e8c9dcd | ||
|
|
01a9d5c7cc | ||
|
|
4a6163c6a6 | ||
|
|
396c1a637c | ||
|
|
1553090bc3 | ||
|
|
f4babdb0ac | ||
|
|
4c79bcbe64 | ||
|
|
568724e468 | ||
|
|
ad022e6d3b | ||
|
|
5765c1e392 | ||
|
|
0031252bf1 | ||
|
|
4d73b33b87 | ||
|
|
e2877119cd | ||
|
|
451c384456 | ||
|
|
4f65558ad0 | ||
|
|
ffae8c82da | ||
|
|
4cff9271ac | ||
|
|
3f2c5cd5aa | ||
|
|
185cdc39c6 | ||
|
|
365ee5bb13 | ||
|
|
f674720166 | ||
|
|
a37e29cf85 | ||
|
|
fde3c52d29 | ||
|
|
99ca63a80a | ||
|
|
25fcbf685d | ||
|
|
2567185fd2 | ||
|
|
ca5e7c5b63 | ||
|
|
836fa11775 | ||
|
|
3be49723fc | ||
|
|
da7f77f96f | ||
|
|
98887219c2 | ||
|
|
93310b9171 | ||
|
|
b618278c9f | ||
|
|
73eb8eb8d1 | ||
|
|
adf9cf5543 | ||
|
|
77821adfe8 | ||
|
|
4f918b61b0 | ||
|
|
1a98844412 | ||
|
|
876f2d5b63 | ||
|
|
fa7659336c | ||
|
|
175fe8c23f | ||
|
|
a0c6bf8d92 | ||
|
|
2eba1ce11e | ||
|
|
6cd01fd0f8 | ||
|
|
46e8af13b6 | ||
|
|
b0fce7a700 | ||
|
|
d20d1e603b | ||
|
|
19c0142741 | ||
|
|
189d0a83d2 | ||
|
|
aa4c401952 | ||
|
|
f08ea44564 | ||
|
|
83df36ac41 | ||
|
|
eb9e2858c1 | ||
|
|
68214211b7 | ||
|
|
92aca935b3 | ||
|
|
e403ff8f45 | ||
|
|
8a7371192a | ||
|
|
0abda82b1e | ||
|
|
92c0d0a011 | ||
|
|
fb10dc69ee | ||
|
|
03a71b0706 | ||
|
|
a4953f93f4 | ||
|
|
1c35ed873a | ||
|
|
69868ee129 | ||
|
|
ac67b57981 | ||
|
|
7ea11c7f98 | ||
|
|
e755aba59f | ||
|
|
5fea88381c | ||
|
|
7c60d44ce6 | ||
|
|
e89d1e331e | ||
|
|
9a892a33b7 | ||
|
|
8e6fe27ecc | ||
|
|
e841295386 | ||
|
|
87c12599bf | ||
|
|
eaacc9bb56 | ||
|
|
ecaec63f48 | ||
|
|
f0b9b9fbb6 | ||
|
|
e1ffd3f005 | ||
|
|
2cfe8bb561 | ||
|
|
e9f2695255 | ||
|
|
1fda13591a | ||
|
|
244885a03e | ||
|
|
45e646472d | ||
|
|
3b5858bcd2 | ||
|
|
48d6a20861 | ||
|
|
498f069f0e | ||
|
|
48456596ff | ||
|
|
6d9902632c | ||
|
|
fafc11d6e0 | ||
|
|
4a5058fc1b | ||
|
|
7e4261e22c | ||
|
|
eb1212a3c1 | ||
|
|
063db11523 | ||
|
|
26b5bf3eca | ||
|
|
6c799d891d | ||
|
|
32f3dce79d | ||
|
|
fc03549d34 | ||
|
|
54590627ee | ||
|
|
daa36e9a1b | ||
|
|
b0898beca6 | ||
|
|
a922e9fd15 | ||
|
|
6631e46bd3 | ||
|
|
4a038240c4 | ||
|
|
ad43c617e3 | ||
|
|
a27cc004d2 | ||
|
|
301f6bcb83 | ||
|
|
9a7ce78e96 | ||
|
|
ca634be831 | ||
|
|
b0e6ac7da9 | ||
|
|
9a9b619c9f | ||
|
|
0b3bf9e30d | ||
|
|
82cd662f00 | ||
|
|
cae732bd8d | ||
|
|
f2f7b85f88 | ||
|
|
444ba0a874 | ||
|
|
71df313773 | ||
|
|
189c6453b4 | ||
|
|
5a190dd003 | ||
|
|
5bcb4bc9a0 | ||
|
|
28361a2bfe | ||
|
|
c1f84789ba | ||
|
|
5e11793221 | ||
|
|
dc40e6f797 | ||
|
|
b6f5c15189 | ||
|
|
1725b74695 | ||
|
|
e10cd2e0a5 | ||
|
|
34c238c152 | ||
|
|
07c71d17a2 | ||
|
|
f4cc39572c | ||
|
|
051a7ec3ae | ||
|
|
ee66488c36 | ||
|
|
f64bba0499 | ||
|
|
dbe18af9ea | ||
|
|
9acbab2c0e | ||
|
|
52dc6e55e5 | ||
|
|
0fb81cb5dd | ||
|
|
03e581e857 | ||
|
|
e0360a8c34 | ||
|
|
aecff8b1e7 | ||
|
|
67f6f5cdb1 | ||
|
|
603e23c2a9 | ||
|
|
4fb66d5d55 | ||
|
|
3f03f8189e | ||
|
|
c576cbec93 | ||
|
|
50bb6253da | ||
|
|
556dc3036e | ||
|
|
3ddcb1cfb5 | ||
|
|
191ea171cb | ||
|
|
48549d55b0 | ||
|
|
137a89f1e2 | ||
|
|
8c866ee6be | ||
|
|
0239e7e77f | ||
|
|
dddf400b7e | ||
|
|
c220b0dcfa | ||
|
|
2555e0d7e6 | ||
|
|
dfeacc8edb | ||
|
|
9ef7f0a940 | ||
|
|
5cddfdcda6 | ||
|
|
54ae4feac8 | ||
|
|
a2c5ea2c08 | ||
|
|
a3daf1a6d1 | ||
|
|
6c313a5846 | ||
|
|
bbaba520ab | ||
|
|
a0a62d119d | ||
|
|
7573551ccb | ||
|
|
5d11ad1e8a | ||
|
|
cd525c7bb1 | ||
|
|
4644a04ee3 | ||
|
|
0af956fe7e | ||
|
|
9ba4b4f901 | ||
|
|
cf3348e41c | ||
|
|
7b04f399b0 | ||
|
|
3aab0c568b | ||
|
|
21877b851c | ||
|
|
d7ed325913 | ||
|
|
07aa7381a9 | ||
|
|
bb1c5fe833 | ||
|
|
a69614b432 | ||
|
|
3f1dfde45f | ||
|
|
c15cc5c510 | ||
|
|
99e890b52c | ||
|
|
72f0f0b346 | ||
|
|
f3af86c67e | ||
|
|
3eef9fcea1 | ||
|
|
906cf353b2 | ||
|
|
8a44c35e8c | ||
|
|
3e34d38b2d | ||
|
|
92f8ce13df | ||
|
|
f0d821a83c | ||
|
|
b8fbe8c1d3 | ||
|
|
1a237e67df | ||
|
|
db726dc570 | ||
|
|
4bbfdee3db | ||
|
|
88233497ab | ||
|
|
e68b491806 | ||
|
|
14c8dabffe | ||
|
|
ca83d59e10 | ||
|
|
119652bd95 | ||
|
|
011dd7b0f6 | ||
|
|
52b098ca11 | ||
|
|
82877a8aa3 | ||
|
|
335305de9c | ||
|
|
42236b435f | ||
|
|
a27501598a | ||
|
|
ac3259b669 | ||
|
|
5560b9198b | ||
|
|
51319d2cae | ||
|
|
4eed307023 | ||
|
|
0dd94666f5 | ||
|
|
c4d4363abd | ||
|
|
0197a30845 | ||
|
|
ca86fd3219 | ||
|
|
1ed5a135ed | ||
|
|
f6a35fe784 | ||
|
|
b7e5592df1 | ||
|
|
944a3d95ff | ||
|
|
29dda71bad | ||
|
|
0faadee83c | ||
|
|
a037934e21 | ||
|
|
56e7df256a | ||
|
|
429acda3ee | ||
|
|
cf4d5a8cfe | ||
|
|
ed20823380 | ||
|
|
e82d7fb753 | ||
|
|
3b989eefe0 | ||
|
|
a982dd11fa | ||
|
|
2c1224dce7 | ||
|
|
c7530621ad | ||
|
|
a7ba08158b | ||
|
|
42764c99be | ||
|
|
2ad54a6f6e | ||
|
|
f941597e43 | ||
|
|
c1e89d73fd | ||
|
|
47b333303e | ||
|
|
27e8f4db3d | ||
|
|
9b30058284 | ||
|
|
6fff25ecbc | ||
|
|
cf516b0eb8 | ||
|
|
8c4d8a4f14 | ||
|
|
d52223f024 | ||
|
|
88451d16ba | ||
|
|
3691ae66b6 | ||
|
|
203cbf2ea0 | ||
|
|
b6c2770a30 | ||
|
|
1a0c2e24eb | ||
|
|
735d38cd7c | ||
|
|
9e2ed8b729 | ||
|
|
adc216698f | ||
|
|
1cbd95eeee | ||
|
|
db930a501f | ||
|
|
2f2459e120 | ||
|
|
8fd76cb873 | ||
|
|
c8fbbd8f3e | ||
|
|
b0a9f6c55b | ||
|
|
b8b341fea6 | ||
|
|
9a322ef016 | ||
|
|
312263821f | ||
|
|
9e80ee005e | ||
|
|
3aa68b1a0b | ||
|
|
ca470c3d4e | ||
|
|
6642181b9d | ||
|
|
a67fec7324 | ||
|
|
aad24c7ffc | ||
|
|
fe508fa3b5 | ||
|
|
2318b70929 | ||
|
|
fcc5b3486f | ||
|
|
c324bb3eff | ||
|
|
ff1c348970 | ||
|
|
16976013d1 | ||
|
|
ef7ea2c390 | ||
|
|
172896b15a | ||
|
|
fe8915122a | ||
|
|
5470f13299 | ||
|
|
c0effc5b46 | ||
|
|
7db056b75a | ||
|
|
6f23316c4a | ||
|
|
fa7141288f | ||
|
|
63a9fcf2e7 | ||
|
|
b6f90aaf1f | ||
|
|
4ef03a8950 | ||
|
|
ef82c5073a | ||
|
|
237b4d22a2 | ||
|
|
823edbf0ab | ||
|
|
a72fed191e | ||
|
|
5015dd8a1f | ||
|
|
5abbd5b2da | ||
|
|
0c646bc3d1 | ||
|
|
f4e4349cad | ||
|
|
9845cc7c9c | ||
|
|
fdc29e53d3 | ||
|
|
a0f84e1b73 | ||
|
|
21379b0cf5 | ||
|
|
65895760ea | ||
|
|
20730e0afb | ||
|
|
c0295836a8 | ||
|
|
8c50df7bbf | ||
|
|
ec0fc7f816 | ||
|
|
f5c6b07246 | ||
|
|
35256f809e | ||
|
|
01201582b7 | ||
|
|
24b65fbe41 | ||
|
|
457587f033 | ||
|
|
78cf383197 | ||
|
|
71c784c8bc | ||
|
|
e4269a7140 | ||
|
|
3734937878 | ||
|
|
07c1c221cb | ||
|
|
246e599142 | ||
|
|
f1aa04858d | ||
|
|
301208c889 | ||
|
|
b5e3779cf2 | ||
|
|
56e2bd0be4 | ||
|
|
34cb030c7b | ||
|
|
a91099b33b | ||
|
|
ad9a3b8b45 | ||
|
|
c7e43807bf | ||
|
|
d8e7cf09b1 | ||
|
|
4f406d752d | ||
|
|
6d85564696 | ||
|
|
071f38c482 | ||
|
|
b81c66b4c7 | ||
|
|
0e5d15e072 | ||
|
|
78a20a11b2 | ||
|
|
54431f3360 | ||
|
|
943b46881e | ||
|
|
757012c289 | ||
|
|
15f27ca8f2 | ||
|
|
0a8718312d | ||
|
|
68b53cfb25 | ||
|
|
935e991786 | ||
|
|
43c89a019c | ||
|
|
57aa77515a | ||
|
|
8dd2373a08 | ||
|
|
03470df2ff | ||
|
|
5aaef06572 | ||
|
|
0b8e964f45 | ||
|
|
c86a23de04 | ||
|
|
ca0b2a012e | ||
|
|
4401a58b2a | ||
|
|
ccabb2af0c | ||
|
|
875f1b248d | ||
|
|
b1c5e807ca | ||
|
|
cf30ba443c | ||
|
|
8c62a9c228 | ||
|
|
b5273bc1fa | ||
|
|
3bde30215b | ||
|
|
46db6e4a00 | ||
|
|
cddb5b612f | ||
|
|
d56986e037 | ||
|
|
e9b2f70238 | ||
|
|
de59a00a30 | ||
|
|
7eea851880 | ||
|
|
0515becf7a | ||
|
|
6b2a58ffcd | ||
|
|
30cebba4d6 | ||
|
|
afc0ba5cdc | ||
|
|
cf3f133df1 | ||
|
|
eb03584c16 | ||
|
|
f0aac87b35 | ||
|
|
cdba31b9d5 | ||
|
|
bb504b06b4 | ||
|
|
55717aeaea | ||
|
|
8615597984 | ||
|
|
a333bbaa12 | ||
|
|
2bc847ac57 | ||
|
|
9283692888 | ||
|
|
017b8b10b6 | ||
|
|
4ddfe70ae2 | ||
|
|
53dc25e532 | ||
|
|
542b57cf21 | ||
|
|
e36fd891e4 | ||
|
|
954b241f34 | ||
|
|
3f56494834 | ||
|
|
6a811b97b9 | ||
|
|
1900da6d24 | ||
|
|
8f38d12eee | ||
|
|
3f5f45f002 | ||
|
|
e6528cb48d | ||
|
|
041184928d | ||
|
|
b108063f75 | ||
|
|
9ce336b3d1 | ||
|
|
b5da760544 | ||
|
|
7e520e2089 | ||
|
|
07af7d5337 | ||
|
|
696a9ba3f9 | ||
|
|
9db6776dbe | ||
|
|
1c6a242b2e | ||
|
|
a58db736cf | ||
|
|
449ea43718 | ||
|
|
260c2634b9 | ||
|
|
6d0db57c02 | ||
|
|
11593d64b8 | ||
|
|
e4a0b9dbfd | ||
|
|
bb770e33f8 | ||
|
|
d048128004 | ||
|
|
eecece2afe | ||
|
|
74c7068a25 | ||
|
|
59360240b3 | ||
|
|
91ba235b3c | ||
|
|
d13fe1e431 | ||
|
|
f361c1805c | ||
|
|
52b8ad45d1 | ||
|
|
9b6c85d82e | ||
|
|
88b8fc30a2 | ||
|
|
1a0463ea04 | ||
|
|
cab91124b4 | ||
|
|
8d9ea7c132 | ||
|
|
c5558280d7 | ||
|
|
3913f5f7ae | ||
|
|
e8c69aa654 | ||
|
|
b2b37d97cf | ||
|
|
4796adf5cb | ||
|
|
2c02c2ae5d | ||
|
|
ef824b7395 | ||
|
|
2930daf68c | ||
|
|
0481e3ca74 |
@@ -12,6 +12,8 @@ win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/rules-ext.vc
|
||||
win/targets.vc
|
||||
win/tcl.dsp
|
||||
win/tcl.dsw
|
||||
win/tcl.hpj.in
|
||||
@@ -12,6 +12,8 @@ win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/rules-ext.vc
|
||||
win/targets.vc
|
||||
win/tcl.dsp
|
||||
win/tcl.dsw
|
||||
win/tcl.hpj.in
|
||||
@@ -44,5 +44,6 @@ unix/pkgs/*
|
||||
win/Debug*
|
||||
win/Release*
|
||||
win/pkgs/*
|
||||
win/coffbase.txt
|
||||
win/tcl.hpj
|
||||
win/nmhlp-out.txt
|
||||
|
||||
@@ -8234,7 +8234,7 @@ Dropped support for OS X versions less than 10.4 (Tiger) (fellows)
|
||||
|
||||
2013-05-16 (platform support) mingw-4.0 (nijtmans)
|
||||
|
||||
2013-05-19 (platform support) FreeBSD updates (gahr)
|
||||
2013-05-19 (platform support) FreeBSD updates (cerutti)
|
||||
|
||||
2013-05-20 (bug fix)[3613567] access error temp file creation (keene)
|
||||
|
||||
@@ -8657,7 +8657,7 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich)
|
||||
|
||||
2016-05-21 (bug)[f7d4e] [namespace delete] performance (fellows)
|
||||
|
||||
2016-06-02 (TIP 447) execution time verbosity option (gahr)
|
||||
2016-06-02 (TIP 447) execution time verbosity option (cerutti)
|
||||
=> tcltest 2.4.0
|
||||
|
||||
2016-06-16 (bug)[16828b] crash due to [vwait] trace undo fail (dah,porter)
|
||||
@@ -8796,6 +8796,45 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich)
|
||||
|
||||
--- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2017-08-10 [array names -regexp] supports backrefs (goth)
|
||||
|
||||
2017-08-10 Fix gcc build failures due to #pragma placement (cassoff,fellows)
|
||||
|
||||
2017-08-29 (bug)[b50fb2] exec redir append stdout and stderr to file (coulter)
|
||||
|
||||
2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann)
|
||||
=> http 2.8.12
|
||||
|
||||
2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter)
|
||||
|
||||
2017-10-19 (bug)[1a5655] [info * methods] includes mixins (fellows)
|
||||
|
||||
2017-10-23 tzdata updated to Olson's tzdata2017c (jima)
|
||||
|
||||
2017-10-24 (bug)[fc1409] segfault in method cloning, oo-15.15 (coulter,fellows)
|
||||
|
||||
2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS (werner)
|
||||
|
||||
2017-11-08 (bug)[3298012] Stop crash when hash tables overflow 32 bits (porter)
|
||||
|
||||
2017-11-14 (bug)[5d6de6] Close failing case of [package prefer stable] (kupries)
|
||||
|
||||
2017-11-17 (bug)[fab924] Fix misleading [load] message on Windows (oehlmann)
|
||||
|
||||
2017-12-05 (bug)[4f6a1e] Crash when ensemble map and list are same (sebres)
|
||||
|
||||
2017-12-06 (bug)[ce3a21] file normalize failure when tail is empty (porter)
|
||||
|
||||
2017-12-08 (new)[TIP 477] nmake build system reform (nadkarni)
|
||||
|
||||
2017-12-19 (bug)[586e71] EvalObjv exception handling at level #0 (sebres,porter)
|
||||
|
||||
--- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
Changes to 8.7a1 include all changes to the 8.6 line through 8.6.7,
|
||||
plus the following, which focuses on the high-level feature changes
|
||||
in this changeset (new minor version) rather than bug fixes:
|
||||
|
||||
2016-03-17 (bug)[0b8c38] socket accept callbacks always in global ns (porter)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
@@ -8836,8 +8875,12 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich)
|
||||
2017-06-23 (TIP 472) Support 0d as prefix of decimal numbers (iyer,griffin)
|
||||
|
||||
2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann)
|
||||
=> http 2.8.12
|
||||
|
||||
2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter)
|
||||
|
||||
--- Released 8.7a1, September 8, 2017 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2018-03-12 (TIP 490) add oo support for msgcat => msgcat 1.7.0 (oehlmann)
|
||||
|
||||
2018-03-12 (TIP 499) custom locale preference list (oehlmann)
|
||||
=> msgcat 1.7.0
|
||||
|
||||
@@ -260,10 +260,6 @@ Windows-only convenience
|
||||
functions for converting between UTF-8 and Windows strings
|
||||
based on the TCHAR type which is by convention
|
||||
a Unicode character on Windows NT.
|
||||
These functions are essentially wrappers around
|
||||
\fBTcl_UtfToExternalDString\fR and
|
||||
\fBTcl_ExternalToUtfDString\fR that convert to and from the
|
||||
Unicode encoding.
|
||||
.PP
|
||||
\fBTcl_GetEncodingName\fR is roughly the inverse of \fBTcl_GetEncoding\fR.
|
||||
Given an \fIencoding\fR, the return value is the \fIname\fR argument that
|
||||
|
||||
+4
-4
@@ -176,10 +176,10 @@ it is faster to execute the script directly.
|
||||
.TP 23
|
||||
\fBTCL_EVAL_GLOBAL\fR
|
||||
.
|
||||
If this flag is set, the script is processed at global level. This
|
||||
means that it is evaluated in the global namespace and its variable
|
||||
context consists of global variables only (it ignores any Tcl
|
||||
procedures that are active).
|
||||
If this flag is set, the script is evaluated in the global namespace instead of
|
||||
the current namespace and its variable context consists of global variables
|
||||
only (it ignores any Tcl procedures that are active).
|
||||
.\" TODO: document TCL_EVAL_INVOKE and TCL_EVAL_NOERR.
|
||||
|
||||
.SH "MISCELLANEOUS DETAILS"
|
||||
.PP
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ are provided by the C language standard. The \fBTcl_WideInt\fR type is a
|
||||
typedef defined to be whatever signed integral type covers at least the
|
||||
64-bit integer range (-9223372036854775808 to 9223372036854775807). Depending
|
||||
on the platform and the C compiler, the actual type might be
|
||||
\fBlong int\fR, \fBlong long int\fR, \fB__int64\fR, or something else.
|
||||
\fBlong long int\fR, \fB__int64\fR, or something else.
|
||||
The \fBmp_int\fR type is a multiple-precision integer type defined
|
||||
by the LibTomMath multiple-precision integer library.
|
||||
.PP
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ the command. The \fIfreeProc\fR field will be initialized to zero,
|
||||
and \fIinterp->result\fR will point to an empty string. Commands that
|
||||
do not return any value can simply leave the fields alone.
|
||||
Furthermore, the empty string pointed to by \fIresult\fR is actually
|
||||
part of an array of \fBTCL_RESULT_SIZE\fR characters (approximately 200).
|
||||
part of an array of approximately 200 characters.
|
||||
If a command wishes to return a short string, it can simply copy
|
||||
it to the area pointed to by \fIinterp->result\fR. Or, it can use
|
||||
the sprintf procedure to generate a short result string at the location
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2008 by Kevin B. Kenny.
|
||||
.\" Copyright (c) 2018 by Nathan Coulter.
|
||||
.\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -38,43 +39,39 @@ void
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_CmdDeleteProc *interp in
|
||||
.AP Tcl_Interp *interp in
|
||||
Interpreter in which to create or evaluate a command.
|
||||
The relevant Interpreter.
|
||||
.AP char *cmdName in
|
||||
Name of a new command to create.
|
||||
Name of the command to create.
|
||||
.AP Tcl_ObjCmdProc *proc in
|
||||
Implementation of a command that will be called whenever \fIcmdName\fR
|
||||
is invoked as a command in the unoptimized way.
|
||||
Called in order to evaluate a command. Is often just a small wrapper that uses
|
||||
\fBTcl_NRCallObjProc\fR to call \fInreProc\fR using a new trampoline. Behaves
|
||||
in the same way as the \fIproc\fR argument to \fBTcl_CreateObjCommand\fR(3)
|
||||
(\fIq.v.\fR).
|
||||
.AP Tcl_ObjCmdProc *nreProc in
|
||||
Implementation of a command that will be called whenever \fIcmdName\fR
|
||||
is invoked and requested to conserve the C stack.
|
||||
Called instead of \fIproc\fR when a trampoline is already in use.
|
||||
.AP ClientData clientData in
|
||||
Arbitrary one-word value that will be passed to \fIproc\fR, \fInreProc\fR,
|
||||
\fIdeleteProc\fR and \fIobjProc\fR.
|
||||
Arbitrary one-word value passed to \fIproc\fR, \fInreProc\fR, \fIdeleteProc\fR
|
||||
and \fIobjProc\fR.
|
||||
.AP Tcl_CmdDeleteProc *deleteProc in/out
|
||||
Procedure to call before \fIcmdName\fR is deleted from the interpreter.
|
||||
This procedure allows for command-specific cleanup. If \fIdeleteProc\fR
|
||||
is \fBNULL\fR, then no procedure is called before the command is deleted.
|
||||
Called before \fIcmdName\fR is deleted from the interpreter, allowing for
|
||||
command-specific cleanup. May be NULL.
|
||||
.AP int objc in
|
||||
Count of parameters provided to the implementation of a command.
|
||||
Number of items in \fIobjv\fR.
|
||||
.AP Tcl_Obj **objv in
|
||||
Pointer to an array of Tcl values. Each value holds the value of a
|
||||
single word in the command to execute.
|
||||
Words in the command.
|
||||
.AP Tcl_Obj *objPtr in
|
||||
Pointer to a Tcl_Obj whose value is a script or expression to execute.
|
||||
A script or expression to evaluate.
|
||||
.AP int flags in
|
||||
ORed combination of flag bits that specify additional options.
|
||||
\fBTCL_EVAL_GLOBAL\fR is the only flag that is currently supported.
|
||||
.\" TODO: This is a lie. But kbk didn't grasp TCL_EVAL_INVOKE and
|
||||
.\" TCL_EVAL_NOERR well enough to document them.
|
||||
As described for \fITcl_EvalObjv\fR.
|
||||
.PP
|
||||
.AP Tcl_Command cmd in
|
||||
Token for a command that is to be used instead of the currently
|
||||
executing command.
|
||||
Token to use instead of one derived from the first word of \fIobjv\fR in order
|
||||
to evaluate a command.
|
||||
.AP Tcl_Obj *resultPtr out
|
||||
Pointer to an unshared Tcl_Obj where the result of expression
|
||||
evaluation is written.
|
||||
Pointer to an unshared Tcl_Obj where the result of the evaluation is stored if
|
||||
the return code is TCL_OK.
|
||||
.AP Tcl_NRPostProc *postProcPtr in
|
||||
Pointer to a function that will be invoked when the command currently
|
||||
executing in the interpreter designated by \fIinterp\fR completes.
|
||||
A function to push.
|
||||
.AP ClientData data0 in
|
||||
.AP ClientData data1 in
|
||||
.AP ClientData data2 in
|
||||
@@ -84,98 +81,51 @@ to the function designated by \fIpostProcPtr\fR when it is invoked.
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
This series of C functions provides an interface whereby commands that
|
||||
are implemented in C can be evaluated, and invoke Tcl commands scripts
|
||||
and scripts, without consuming space on the C stack. The non-recursive
|
||||
evaluation is done by installing a \fItrampoline\fR, a small piece of
|
||||
code that invokes a command or script, and then executes a series of
|
||||
callbacks when the command or script returns.
|
||||
These functions provide an interface to the function stack that an interpreter
|
||||
iterates through to evaluate commands. The routine behind a command is
|
||||
implemented by an initial function and any additional functions that the
|
||||
routine pushes onto the stack as it progresses. The interpreter itself pushes
|
||||
functions onto the stack to react to the end of a routine and to exercise other
|
||||
forms of control such as switching between in-progress stacks and the
|
||||
evaluation of other scripts at additional levels without adding frames to the C
|
||||
stack. To execute a routine, the initial function for the routine is called
|
||||
and then a small bit of code called a \fItrampoline\fR iteratively takes
|
||||
functions off the stack and calls them, using the value of the last call as the
|
||||
value of the routine.
|
||||
.PP
|
||||
The \fBTcl_NRCreateCommand\fR function creates a Tcl command in the
|
||||
interpreter designated by \fIinterp\fR that is prepared to handle
|
||||
nonrecursive evaluation with a trampoline. The \fIcmdName\fR argument
|
||||
gives the name of the new command. If \fIcmdName\fR contains any
|
||||
namespace qualifiers, then the new command is added to the specified
|
||||
namespace; otherwise, it is added to the global namespace. \fIproc\fR
|
||||
gives the procedure that will be called when the interpreter wishes to
|
||||
evaluate the command in an unoptimized manner, and \fInreProc\fR is
|
||||
the procedure that will be called when the interpreter wishes to
|
||||
evaluate the command using a trampoline. \fIdeleteProc\fR is a
|
||||
function that will be called before the command is deleted from the
|
||||
interpreter. When any of the three functions is invoked, it is passed
|
||||
the \fIclientData\fR parameter.
|
||||
\fBTcl_NRCallObjProc\fR calls \fInreProc\fR using a new trampoline.
|
||||
.PP
|
||||
\fBTcl_NRCreateCommand\fR deletes any existing command
|
||||
\fIname\fR already associated with the interpreter
|
||||
(however see below for an exception where the existing command
|
||||
is not deleted).
|
||||
It returns a token that may be used to refer
|
||||
to the command in subsequent calls to \fBTcl_GetCommandName\fR.
|
||||
If \fBTcl_NRCreateCommand\fR is called for an interpreter that is in
|
||||
the process of being deleted, then it does not create a new command,
|
||||
does not delete any existing command of the same name, and returns NULL.
|
||||
\fBTcl_NRCreateCommand\fR, an alternative to \fBTcl_CreateObjCommand\fR,
|
||||
resolves \fIcmdName\fR, which may contain namespace qualifiers, relative to the
|
||||
current namespace, creates a command by that name, and returns a token for the
|
||||
command which may be used in subsequent calls to \fBTcl_GetCommandName\fR.
|
||||
Except for a few cases noted below any existing command by the same name is
|
||||
first deleted. If \fIinterp\fR is in the process of being deleted
|
||||
\fBTcl_NRCreateCommand\fR does not create any command, does not delete any
|
||||
command, and returns NULL.
|
||||
.PP
|
||||
The \fIproc\fR and \fInreProc\fR function are expected to conform to
|
||||
all the rules set forth for the \fIproc\fR argument to
|
||||
\fBTcl_CreateObjCommand\fR(3) (\fIq.v.\fR).
|
||||
\fBTcl_NREvalObj\fR pushes a function that is like \fBTcl_EvalObjEx\fR but
|
||||
consumes no space on the C stack.
|
||||
.PP
|
||||
When a command that is written to cope with evaluation via trampoline
|
||||
is invoked without a trampoline on the stack, it will usually respond
|
||||
to the invocation by creating a trampoline and calling the
|
||||
trampoline-enabled implementation of the same command. This call is done by
|
||||
means of \fBTcl_NRCallObjProc\fR. In the call to
|
||||
\fBTcl_NRCallObjProc\fR, the \fIinterp\fR, \fIclientData\fR,
|
||||
\fIobjc\fR and \fIobjv\fR parameters should be the same ones that were
|
||||
passed to \fIproc\fR. The \fInreProc\fR parameter should designate the
|
||||
trampoline-enabled implementation of the command.
|
||||
\fBTcl_NREvalObjv\fR pushes a function that is like \fBTcl_EvalObjv\fR but
|
||||
consumes no space on the C stack.
|
||||
.PP
|
||||
\fBTcl_NREvalObj\fR arranges for the script contained in \fIobjPtr\fR
|
||||
to be evaluated in the interpreter designated by \fIinterp\fR after
|
||||
the current command (which must be trampoline-enabled) returns. It is
|
||||
the method by which a command may invoke a script without consuming
|
||||
space on the C stack. Similarly, \fBTcl_NREvalObjv\fR arranges to
|
||||
invoke a single Tcl command whose words have already been separated
|
||||
and substituted. The \fIobjc\fR and \fIobjv\fR parameters give the
|
||||
words of the command to be evaluated when execution reaches the
|
||||
trampoline.
|
||||
\fBTcl_NRCmdSwap\fR is like \fBTcl_NREvalObjv\fR, but uses \fIcmd\fR, a token
|
||||
previously returned by \fBTcl_CreateObjCommand\fR or
|
||||
\fBTcl_GetCommandFromObj\fR, instead of resolving the first word of \fIobjv\fR.
|
||||
. The name of this command must be the same as \fIobjv[0]\fR.
|
||||
.PP
|
||||
\fBTcl_NRCmdSwap\fR allows for trampoline evaluation of a command whose
|
||||
resolution is already known. The \fIcmd\fR parameter gives a
|
||||
\fBTcl_Command\fR token (returned from \fBTcl_CreateObjCommand\fR or
|
||||
\fBTcl_GetCommandFromObj\fR) identifying the command to be invoked in
|
||||
the trampoline; this command must match the word in \fIobjv[0]\fR.
|
||||
The remaining arguments are as for \fBTcl_NREvalObjv\fR.
|
||||
\fBTcl_NRExprObj\fR pushes a function that evaluates \fIobjPtr\fR as an
|
||||
expression in the same manner as \fBTcl_ExprObj\fR but without consuming space
|
||||
on the C stack.
|
||||
.PP
|
||||
\fBTcl_NREvalObj\fR, \fBTcl_NREvalObjv\fR and \fBTcl_NRCmdSwap\fR
|
||||
all accept a \fIflags\fR parameter, which is an OR-ed-together set of
|
||||
bits to control evaluation. At the present time, the only supported flag
|
||||
available to callers is \fBTCL_EVAL_GLOBAL\fR.
|
||||
.\" TODO: Again, this is a lie. Do we want to explain TCL_EVAL_INVOKE
|
||||
.\" and TCL_EVAL_NOERR?
|
||||
If the \fBTCL_EVAL_GLOBAL\fR flag is set, the script or command is
|
||||
evaluated in the global namespace. If it is not set, it is evaluated
|
||||
in the current namespace.
|
||||
All of the functions return \fBTCL_OK\fR if the evaluation of the script,
|
||||
command, or expression has been scheduled successfully. Otherwise (for example
|
||||
if the command name cannot be resolved), they return \fBTCL_ERROR\fR and store
|
||||
a message as the interpreter's result.
|
||||
.PP
|
||||
\fBTcl_NRExprObj\fR arranges for the expression contained in \fIobjPtr\fR
|
||||
to be evaluated in the interpreter designated by \fIinterp\fR after
|
||||
the current command (which must be trampoline-enabled) returns. It is
|
||||
the method by which a command may evaluate a Tcl expression without consuming
|
||||
space on the C stack. The argument \fIresultPtr\fR is a pointer to an
|
||||
unshared Tcl_Obj where the result of expression evaluation is to be written.
|
||||
If expression evaluation returns any code other than TCL_OK, the
|
||||
\fIresultPtr\fR value is left untouched.
|
||||
.PP
|
||||
All of the routines return \fBTCL_OK\fR if command or expression invocation
|
||||
has been scheduled successfully. If for any reason the scheduling cannot
|
||||
be completed (for example, if the interpreter is unable to find
|
||||
the requested command), they return \fBTCL_ERROR\fR with an
|
||||
appropriate message left in the interpreter's result.
|
||||
.PP
|
||||
\fBTcl_NRAddCallback\fR arranges to have a C function called when the
|
||||
current trampoline-enabled command in the Tcl interpreter designated
|
||||
by \fIinterp\fR returns. The \fIpostProcPtr\fR argument is a pointer
|
||||
to the callback function, which must have arguments and return value
|
||||
consistent with the \fBTcl_NRPostProc\fR data type:
|
||||
\fBTcl_NRAddCallback\fR pushes \fIpostProcPtr\fR. The signature for
|
||||
\fBTcl_NRPostProc\fR is:
|
||||
.PP
|
||||
.CS
|
||||
typedef int
|
||||
@@ -185,25 +135,13 @@ typedef int
|
||||
int \fIresult\fR);
|
||||
.CE
|
||||
.PP
|
||||
When the trampoline invokes the callback function, the \fIdata\fR
|
||||
parameter will point to an array containing the four one-word
|
||||
quantities that were passed to \fBTcl_NRAddCallback\fR in the
|
||||
\fIdata0\fR through \fIdata3\fR parameters. The Tcl interpreter will
|
||||
be designated by the \fIinterp\fR parameter, and the \fIresult\fR
|
||||
parameter will contain the result (\fBTCL_OK\fR, \fBTCL_ERROR\fR,
|
||||
\fBTCL_RETURN\fR, \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR) that was
|
||||
returned by the command evaluation. The callback function is expected,
|
||||
in turn, either to return a \fIresult\fR to control further evaluation.
|
||||
.PP
|
||||
Multiple \fBTcl_NRAddCallback\fR invocations may request multiple
|
||||
callbacks, which may be to the same or different callback
|
||||
functions. If multiple callbacks are requested, they are executed in
|
||||
last-in, first-out order, that is, the most recently requested
|
||||
callback is executed first.
|
||||
\fIdata\fR is a pointer to an array containing \fIdata0\fR through \fIdata3\fR.
|
||||
\fIresult\fR is the value returned by the previous function implementing part
|
||||
the routine.
|
||||
.SH EXAMPLE
|
||||
.PP
|
||||
The usual pattern for Tcl commands that invoke other Tcl commands
|
||||
is something like:
|
||||
The following command uses \fBTcl_EvalObjEx\fR, which consumes space on the C
|
||||
stack, to evalute a script:
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
@@ -228,28 +166,17 @@ int
|
||||
\fITheCmdOldObjProc\fR, clientData, TheCmdDeleteProc);
|
||||
.CE
|
||||
.PP
|
||||
To enable a command like this one for trampoline-based evaluation,
|
||||
it must be split into three pieces:
|
||||
.IP \(bu
|
||||
A non-trampoline implementation, \fITheCmdNewObjProc\fR,
|
||||
which will simply create a trampoline
|
||||
and invoke the trampoline-based implementation.
|
||||
.IP \(bu
|
||||
A trampoline-enabled implementation, \fITheCmdNRObjProc\fR. This
|
||||
function will perform the initialization, request that the trampoline
|
||||
call the postprocessing routine after command evaluation, and finally,
|
||||
request that the trampoline call the inner command.
|
||||
.IP \(bu
|
||||
A postprocessing routine, \fITheCmdPostProc\fR. This function will
|
||||
perform the postprocessing formerly done after the return from the
|
||||
inner command in \fITheCmdObjProc\fR.
|
||||
.PP
|
||||
The non-trampoline implementation is simple and stylized, containing
|
||||
a single statement:
|
||||
To avoid consuming space on the C stack, \fITheCmdOldObjProc\fR is renamed to
|
||||
\fITheCmdNRObjProc\fR and the postprocessing step is split into a separate
|
||||
function, \fITheCmdPostProc\fR, which is pushed onto the function stack.
|
||||
\fITcl_EvalObjEx\fR is replaced with \fITcl_NREvalObj\fR, which uses a
|
||||
trampoline instead of consuming space on the C stack. A new version of
|
||||
\fITheCmdOldObjProc\fR is just a a wrapper that uses \fBTcl_NRCallObjProc\fR to
|
||||
call \fITheCmdNRObjProc\fR:
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
\fITheCmdNewObjProc\fR(
|
||||
\fITheCmdOldObjProc\fR(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -260,9 +187,6 @@ int
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
The trampoline-enabled implementation requests postprocessing,
|
||||
and returns to the trampoline requesting command evaluation.
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
\fITheCmdNRObjProc\fR
|
||||
@@ -284,9 +208,6 @@ int
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
The postprocessing procedure does whatever the original command did
|
||||
upon return from the inner evaluation.
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
\fITheCmdNRPostProc\fR(
|
||||
@@ -303,26 +224,13 @@ int
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
If \fItheCommand\fR is a command that results in multiple commands or
|
||||
scripts being evaluated, its postprocessing routine may schedule
|
||||
additional postprocessing and then request another command evaluation
|
||||
by means of \fBTcl_NREvalObj\fR or one of the other evaluation
|
||||
routines. Looping and sequencing constructs may be implemented in this way.
|
||||
Any function comprising a routine can push other functions, making it possible
|
||||
implement looping and sequencing constructs using the function stack.
|
||||
.PP
|
||||
Finally, to install a trampoline-enabled command in the interpreter,
|
||||
\fBTcl_NRCreateCommand\fR is used in place of
|
||||
\fBTcl_CreateObjCommand\fR. It accepts two command procedures instead
|
||||
of one. The first is for use when no trampoline is yet on the stack,
|
||||
and the second is for use when there is already a trampoline in place.
|
||||
.PP
|
||||
.CS
|
||||
\fBTcl_NRCreateCommand\fR(interp, "theCommand",
|
||||
\fITheCmdNewObjProc\fR, \fITheCmdNRObjProc\fR, clientData,
|
||||
TheCmdDeleteProc);
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
Tcl_CreateCommand(3), Tcl_CreateObjCommand(3), Tcl_EvalObjEx(3), Tcl_GetCommandFromObj(3), Tcl_ExprObj(3)
|
||||
.SH KEYWORDS
|
||||
stackless, nonrecursive, execute, command, global, value, result, script
|
||||
.SH COPYRIGHT
|
||||
Copyright (c) 2008 by Kevin B. Kenny
|
||||
Copyright (c) 2008 by Kevin B. Kenny.
|
||||
Copyright (c) 2018 by Nathan Coulter.
|
||||
|
||||
+12
-1
@@ -7,7 +7,7 @@
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc \- report fatal error and abort
|
||||
Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc, Tcl_ConsolePanic \- report fatal error and abort
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -21,6 +21,9 @@ void
|
||||
void
|
||||
\fBTcl_SetPanicProc\fR(\fIpanicProc\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_ConsolePanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
|
||||
.sp
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_PanicProc *panicProc
|
||||
.AP "const char*" format in
|
||||
@@ -54,6 +57,14 @@ message is sent to the debugger in stead. If the windows executable
|
||||
does not have a stderr channel (e.g. \fBwish.exe\fR), then a
|
||||
system dialog box is used to display the panic message.
|
||||
.PP
|
||||
If your application doesn't use \fBTcl_Main\fR or \fBTk_Main\fR
|
||||
and you want to implicitly use the stderr channel of your
|
||||
application's C runtime (in stead of the stderr channel of the
|
||||
C runtime used by Tcl), you can call \fBTcl_SetPanicProc\fR
|
||||
with \fBTcl_ConsolePanic\fR as its argument. On platforms which
|
||||
only have one C runtime (almost all platforms except Windows)
|
||||
\fBTcl_ConsolePanic\fR is equivalent to NULL.
|
||||
.PP
|
||||
\fBTcl_SetPanicProc\fR may be used to modify the behavior of
|
||||
\fBTcl_Panic\fR. The \fIpanicProc\fR argument should match the
|
||||
type \fBTcl_PanicProc\fR:
|
||||
|
||||
+23
-10
@@ -83,14 +83,15 @@ Specifies that the number should be padded on the left with
|
||||
zeroes instead of spaces.
|
||||
.TP 10
|
||||
\fB#\fR
|
||||
Requests an alternate output form. For \fBo\fR and \fBO\fR
|
||||
conversions it guarantees that the first digit is always \fB0\fR.
|
||||
For \fBx\fR or \fBX\fR conversions, \fB0x\fR or \fB0X\fR (respectively)
|
||||
Requests an alternate output form. For \fBo\fR conversions,
|
||||
\fB0o\fR will be added to the beginning of the result unless
|
||||
it is zero. For \fBx\fR or \fBX\fR conversions, \fB0x\fR
|
||||
will be added to the beginning of the result unless it is zero.
|
||||
For \fBb\fR conversions, \fB0b\fR
|
||||
will be added to the beginning of the result unless it is zero.
|
||||
For \fBd\fR conversions, \fB0d\fR will be added to the beginning
|
||||
of the result unless it is zero.
|
||||
For \fBd\fR conversions, \fB0d\fR there is no effect unless
|
||||
the \fB0\fR specifier is used as well: In that case, \fB0d\fR
|
||||
will be added to the beginning.
|
||||
For all floating-point conversions (\fBe\fR, \fBE\fR, \fBf\fR,
|
||||
\fBg\fR, and \fBG\fR) it guarantees that the result always
|
||||
has a decimal point.
|
||||
@@ -132,7 +133,7 @@ it must be a numeric string.
|
||||
.SS "OPTIONAL SIZE MODIFIER"
|
||||
.PP
|
||||
The fifth part of a conversion specifier is a size modifier,
|
||||
which must be \fBll\fR, \fBh\fR, or \fBl\fR.
|
||||
which must be \fBll\fR, \fBh\fR, \fBl\fR, or \fBL\fR.
|
||||
If it is \fBll\fR it specifies that an integer value is taken
|
||||
without truncation for conversion to a formatted substring.
|
||||
If it is \fBh\fR it specifies that an integer value is
|
||||
@@ -140,7 +141,9 @@ truncated to a 16-bit range before converting. This option is rarely useful.
|
||||
If it is \fBl\fR it specifies that the integer value is
|
||||
truncated to the same range as that produced by the \fBwide()\fR
|
||||
function of the \fBexpr\fR command (at least a 64-bit range).
|
||||
If neither \fBh\fR nor \fBl\fR are present, the integer value is
|
||||
If it is \fBL\fR it specifies that an integer or double value is taken
|
||||
without truncation for conversion to a formatted substring.
|
||||
If neither \fBh\fR nor \fBl\fR nor \fBL\fR are present, the integer value is
|
||||
truncated to the same range as that produced by the \fBint()\fR
|
||||
function of the \fBexpr\fR command (at least a 32-bit range, but
|
||||
determined by the value of the \fBwordSize\fR element of the
|
||||
@@ -171,7 +174,7 @@ for \fBx\fR and
|
||||
for \fBX\fR).
|
||||
.TP 10
|
||||
\fBb\fR
|
||||
Convert integer to binary string, using digits 0 and 1.
|
||||
Convert integer to unsigned binary string, using digits 0 and 1.
|
||||
.TP 10
|
||||
\fBc\fR
|
||||
Convert integer to the Unicode character it represents.
|
||||
@@ -200,8 +203,19 @@ precision, then convert number as for \fB%e\fR or
|
||||
Otherwise convert as for \fB%f\fR.
|
||||
Trailing zeroes and a trailing decimal point are omitted.
|
||||
.TP 10
|
||||
\fBa\fR or \fBA\fR
|
||||
Convert double to hexadecimal notation in the form
|
||||
\fI0x1.yyy\fBp\(+-\fIzz\fR, where the number of \fIy\fR's is
|
||||
determined by the precision (default: 13).
|
||||
If the \fBA\fR form is used then the hex characters
|
||||
are printed in uppercase.
|
||||
.TP 10
|
||||
\fB%\fR
|
||||
No conversion: just insert \fB%\fR.
|
||||
.TP 10
|
||||
\fBp\fR
|
||||
Shorthand form for \fB0x%zx\fR, so it outputs the integer in
|
||||
hexadecimal form with \fB0x\fR prefix.
|
||||
.SH "DIFFERENCES FROM ANSI SPRINTF"
|
||||
.PP
|
||||
The behavior of the format command is the same as the
|
||||
@@ -210,13 +224,12 @@ differences:
|
||||
.IP [1]
|
||||
Tcl guarantees that it will be working with UNICODE characters.
|
||||
.IP [2]
|
||||
\fB%p\fR and \fB%n\fR specifiers are not supported.
|
||||
\fB%n\fR specifier is not supported.
|
||||
.IP [3]
|
||||
For \fB%c\fR conversions the argument must be an integer value,
|
||||
which will then be converted to the corresponding character value.
|
||||
.IP [4]
|
||||
The size modifiers are ignored when formatting floating-point values.
|
||||
The \fBll\fR modifier has no \fBsprintf\fR counterpart.
|
||||
The \fBb\fR specifier has no \fBsprintf\fR counterpart.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
|
||||
@@ -148,6 +148,19 @@ or \fB\-not\fR.
|
||||
These options are used to search lists of lists. They may be used
|
||||
with any other options.
|
||||
.TP
|
||||
\fB\-stride\0\fIstrideLength\fR
|
||||
.
|
||||
If this option is specified, the list is treated as consisting of
|
||||
groups of \fIstrideLength\fR elements and the groups are searched by
|
||||
either their first element or, if the \fB\-index\fR option is used,
|
||||
by the element within each group given by the first index passed to
|
||||
\fB\-index\fR (which is then ignored by \fB\-index\fR). The resulting
|
||||
index always points to the first element in a group.
|
||||
.PP
|
||||
The list length must be an integer multiple of \fIstrideLength\fR, which
|
||||
in turn must be at least 1. A \fIstrideLength\fR of 1 is the default and
|
||||
indicates no grouping.
|
||||
.TP
|
||||
\fB\-index\fR\0\fIindexList\fR
|
||||
.
|
||||
This option is designed for use when searching within nested lists.
|
||||
@@ -208,6 +221,13 @@ It is also possible to search inside elements:
|
||||
\fBlsearch\fR -index 1 -all -inline {{a abc} {b bcd} {c cde}} *bc*
|
||||
\fI\(-> {a abc} {b bcd}\fR
|
||||
.CE
|
||||
.PP
|
||||
The same thing for a flattened list:
|
||||
.PP
|
||||
.CS
|
||||
\fBlsearch\fR -stride 2 -index 1 -all -inline {a abc b bcd c cde} *bc*
|
||||
\fI\(-> {a abc b bcd}\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
foreach(n), list(n), lappend(n), lindex(n), linsert(n), llength(n),
|
||||
lset(n), lsort(n), lrange(n), lreplace(n),
|
||||
|
||||
+178
-27
@@ -11,9 +11,9 @@
|
||||
.SH NAME
|
||||
msgcat \- Tcl message catalog
|
||||
.SH SYNOPSIS
|
||||
\fBpackage require Tcl 8.5\fR
|
||||
\fBpackage require Tcl 8.7\fR
|
||||
.sp
|
||||
\fBpackage require msgcat 1.6\fR
|
||||
\fBpackage require msgcat 1.7\fR
|
||||
.sp
|
||||
\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
|
||||
.sp
|
||||
@@ -23,9 +23,15 @@ msgcat \- Tcl message catalog
|
||||
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? \fIsrc-string\fR
|
||||
.VE "TIP 412"
|
||||
.sp
|
||||
.VS "TIP 490"
|
||||
\fB::msgcat::mcpackagenamespaceget\fR
|
||||
.VE "TIP 490"
|
||||
.sp
|
||||
\fB::msgcat::mclocale \fR?\fInewLocale\fR?
|
||||
.sp
|
||||
\fB::msgcat::mcpreferences\fR
|
||||
.VS "TIP 499"
|
||||
\fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ...
|
||||
.VE "TIP 499"
|
||||
.sp
|
||||
.VS "TIP 412"
|
||||
\fB::msgcat::mcloadedlocales subcommand\fR ?\fIlocale\fR?
|
||||
@@ -50,6 +56,10 @@ msgcat \- Tcl message catalog
|
||||
.sp
|
||||
\fB::msgcat::mcforgetpackage\fR
|
||||
.VE "TIP 412"
|
||||
.sp
|
||||
.VS "TIP 499"
|
||||
\fB::msgcat::mcutil subcommand\fR ?\fIlocale\fR?
|
||||
.VS "TIP 499"
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@@ -71,6 +81,11 @@ In \fBmsgcat\fR, there is a global locale initialized by the system locale of th
|
||||
Each package may decide to use the global locale or to use a package specific locale.
|
||||
.PP
|
||||
The global locale may be changed on demand, for example by a user initiated language change or within a multi user application like a web server.
|
||||
.PP
|
||||
.VS tip490
|
||||
Object oriented programming is supported by the use of a package namespace.
|
||||
.VE tip490
|
||||
.PP
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
|
||||
@@ -95,6 +110,17 @@ use the result. If an application is written for a single language in
|
||||
this fashion, then it is easy to add support for additional languages
|
||||
later simply by defining new message catalog entries.
|
||||
.RE
|
||||
.VS "TIP 490"
|
||||
.TP
|
||||
\fB::msgcat::mcn \fInamespace\fR \fIsrc-string\fR ?\fIarg arg ...\fR?
|
||||
.
|
||||
Like \fB::msgcat::mc\fR, but with the message namespace specified as first argument.
|
||||
.PP
|
||||
.RS
|
||||
\fBmcn\fR may be used for cases where the package namespace is not the namespace of the caller.
|
||||
An example is shown within the description of the command \fB::msgcat::mcpackagenamespaceget\fR below.
|
||||
.RE
|
||||
.PP
|
||||
.TP
|
||||
\fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR?
|
||||
.
|
||||
@@ -103,28 +129,68 @@ of the longest translated string. This is useful when designing
|
||||
localized GUIs, which may require that all buttons, for example, be a
|
||||
fixed width (which will be the width of the widest button).
|
||||
.TP
|
||||
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? \fIsrc-string\fR
|
||||
.
|
||||
.VS "TIP 412"
|
||||
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? ?\fB-namespace\fR \fInamespace\fR? \fIsrc-string\fR
|
||||
.
|
||||
Return true, if there is a translation for the given \fIsrc-string\fR.
|
||||
.PP
|
||||
.RS
|
||||
The search may be limited by the option \fB\-exactnamespace\fR to only check the current namespace and not any parent namespaces.
|
||||
.PP
|
||||
It may also be limited by the option \fB\-exactlocale\fR to only check the first prefered locale (e.g. first element returned by \fB::msgcat::mcpreferences\fR if global locale is used).
|
||||
.RE
|
||||
.PP
|
||||
.VE "TIP 412"
|
||||
.VS "TIP 490"
|
||||
An explicit package namespace may be specified by the option \fB-namespace\fR.
|
||||
The namespace of the caller is used if not explicitly specified.
|
||||
.RE
|
||||
.PP
|
||||
.VE "TIP 490"
|
||||
.VS "TIP 490"
|
||||
.TP
|
||||
\fB::msgcat::mcpackagenamespaceget\fR
|
||||
.
|
||||
Return the package namespace of the caller.
|
||||
This command handles all cases described in section \fBOBJECT ORIENTED PROGRAMMING\fR.
|
||||
.PP
|
||||
.RS
|
||||
Example usage is a tooltip package, which saves the caller package namespace to update the translation each time the tooltip is shown:
|
||||
.CS
|
||||
proc ::tooltip::tooltip {widget message} {
|
||||
...
|
||||
set messagenamespace [uplevel 1 {::msgcat::mcpackagenamespaceget}]
|
||||
...
|
||||
bind $widget [list ::tooltip::show $widget $messagenamespace $message]
|
||||
}
|
||||
|
||||
proc ::tooltip::show {widget messagenamespace message} {
|
||||
...
|
||||
set message [::msgcat::mcn $messagenamespace $message]
|
||||
...
|
||||
}
|
||||
.CE
|
||||
.RE
|
||||
.PP
|
||||
.VE "TIP 490"
|
||||
.TP
|
||||
\fB::msgcat::mclocale \fR?\fInewLocale\fR?
|
||||
.
|
||||
This function sets the locale to \fInewLocale\fR. If \fInewLocale\fR
|
||||
is omitted, the current locale is returned, otherwise the current locale
|
||||
is set to \fInewLocale\fR. msgcat stores and compares the locale in a
|
||||
If \fInewLocale\fR is omitted, the current locale is returned, otherwise the current locale
|
||||
is set to \fInewLocale\fR.
|
||||
.PP
|
||||
.RS
|
||||
If the new locale is set to \fInewLocale\fR, the corresponding preferences are calculated and set.
|
||||
For example, if the current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR returns \fB{en_us_funky en_us en {}}\fR.
|
||||
.PP
|
||||
The same result may be acheved by \fB::msgcat::mcpreferences\fR {*}[\fB::msgcat::mcutil getpreferences\fR \fInewLocale\fR].
|
||||
.PP
|
||||
The current locale is always the first element of the list returned by \fBmcpreferences\fR.
|
||||
.PP
|
||||
msgcat stores and compares the locale in a
|
||||
case-insensitive manner, and returns locales in lowercase.
|
||||
The initial locale is determined by the locale specified in
|
||||
the user's environment. See \fBLOCALE SPECIFICATION\fR
|
||||
below for a description of the locale string format.
|
||||
.RS
|
||||
.PP
|
||||
.VS "TIP 412"
|
||||
If the locale is set, the preference list of locales is evaluated.
|
||||
@@ -132,16 +198,26 @@ Locales in this list are loaded now, if not jet loaded.
|
||||
.VE "TIP 412"
|
||||
.RE
|
||||
.TP
|
||||
\fB::msgcat::mcpreferences\fR
|
||||
\fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ...
|
||||
.
|
||||
Returns an ordered list of the locales preferred by
|
||||
the user, based on the user's language specification.
|
||||
The list is ordered from most specific to least
|
||||
preference. The list is derived from the current
|
||||
locale set in msgcat by \fB::msgcat::mclocale\fR, and
|
||||
cannot be set independently. For example, if the
|
||||
current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR
|
||||
returns \fB{en_us_funky en_us en {}}\fR.
|
||||
Without arguments, returns an ordered list of the locales preferred by
|
||||
the user.
|
||||
The list is ordered from most specific to least preference.
|
||||
.PP
|
||||
.VS "TIP 499"
|
||||
.RS
|
||||
A set of locale preferences may be given to set the list of locale preferences.
|
||||
The current locale is also set, which is the first element of the locale preferences list.
|
||||
.PP
|
||||
Locale preferences are loaded now, if not jet loaded.
|
||||
.PP
|
||||
As an example, the user may prefer French or English text. This may be configured by:
|
||||
.CS
|
||||
::msgcat::mcpreferences fr en {}
|
||||
.CE
|
||||
.RE
|
||||
.PP
|
||||
.VS "TIP 499"
|
||||
.TP
|
||||
\fB::msgcat:mcloadedlocales subcommand\fR ?\fIlocale\fR?
|
||||
.
|
||||
@@ -232,6 +308,22 @@ Note that this routine is only called if the concerned package did not set a pac
|
||||
The calling package clears all its state within the \fBmsgcat\fR package including all settings and translations.
|
||||
.VE "TIP 412"
|
||||
.PP
|
||||
.VS "TIP 499"
|
||||
.TP
|
||||
\fB::msgcat::mcutil getpreferences\fR \fIlocale\fR
|
||||
.
|
||||
Return the preferences list of the given locale as described in section \fBLOCALE SPECIFICATION\fR.
|
||||
An example is the composition of a preference list for the bilingual region "Biel/Bienne" as a concatenation of swiss german and swiss french:
|
||||
.CS
|
||||
% concat [lrange [msgcat::mcutil getpreferences fr_CH] 0 end-1] [msgcat::mcutil getpreferences de_CH]
|
||||
fr_ch fr de_ch de {}
|
||||
.CE
|
||||
.TP
|
||||
\fB::msgcat::mcutil getsystemlocale\fR
|
||||
.
|
||||
The system locale is returned as described by the section \fBLOCALE SPECIFICATION\fR.
|
||||
.VE "TIP 499"
|
||||
.PP
|
||||
.SH "LOCALE SPECIFICATION"
|
||||
.PP
|
||||
The locale is specified to \fBmsgcat\fR by a locale string
|
||||
@@ -437,7 +529,7 @@ formatting substitution is done directly.
|
||||
# human-oriented versions by \fBmsgcat::mcset\fR
|
||||
.CE
|
||||
.VS "TIP 412"
|
||||
.SH Package private locale
|
||||
.SH "PACKAGE PRIVATE LOCALE"
|
||||
.PP
|
||||
A package using \fBmsgcat\fR may choose to use its own package private
|
||||
locale and its own set of loaded locales, independent to the global
|
||||
@@ -461,10 +553,22 @@ This command may cause the load of locales.
|
||||
.
|
||||
Return the package private locale or the global locale, if no package private locale is set.
|
||||
.TP
|
||||
\fB::msgcat::mcpackagelocale preferences\fR
|
||||
\fB::msgcat::mcpackagelocale preferences\fR ?\fIlocale preference\fR? ...
|
||||
.
|
||||
Return the package private preferences or the global preferences,
|
||||
With no parameters, return the package private preferences or the global preferences,
|
||||
if no package private locale is set.
|
||||
The package locale state (set or not) is not changed (in contrast to the command \fB::msgcat::mcpackagelocale set\fR).
|
||||
.PP
|
||||
.RS
|
||||
.VS "TIP 499"
|
||||
If a set of locale preferences is given, it is set as package locale preference list.
|
||||
The package locale is set to the first element of the preference list.
|
||||
A package locale is activated, if it was not set so far.
|
||||
.PP
|
||||
Locale preferences are loaded now for the package, if not jet loaded.
|
||||
.VE "TIP 499"
|
||||
.RE
|
||||
.PP
|
||||
.TP
|
||||
\fB::msgcat::mcpackagelocale loaded\fR
|
||||
.
|
||||
@@ -488,7 +592,7 @@ Returns true, if the given locale is loaded for the package.
|
||||
.
|
||||
Clear any loaded locales of the package not present in the package preferences.
|
||||
.PP
|
||||
.SH Changing package options
|
||||
.SH "CHANGING PACKAGE OPTIONS"
|
||||
.PP
|
||||
Each package using msgcat has a set of options within \fBmsgcat\fR.
|
||||
The package options are described in the next sectionPackage options.
|
||||
@@ -563,7 +667,7 @@ A generic unknown handler is used if set to the empty string. This consists in r
|
||||
See section \fBcallback invocation\fR below.
|
||||
The appended arguments are identical to \fB::msgcat::mcunknown\fR.
|
||||
.RE
|
||||
.SS Callback invocation
|
||||
.SH "Callback invocation"
|
||||
A package may decide to register one or multiple callbacks, as described above.
|
||||
.PP
|
||||
Callbacks are invoked, if:
|
||||
@@ -577,7 +681,54 @@ Callbacks are invoked, if:
|
||||
If a called routine fails with an error, the \fBbgerror\fR routine for the interpreter is invoked after command completion.
|
||||
Only exception is the callback \fBunknowncmd\fR, where an error causes the invoking \fBmc\fR-command to fail with that error.
|
||||
.PP
|
||||
.SS Examples
|
||||
.VS tip490
|
||||
.SH "OBJECT ORIENTED PROGRAMMING"
|
||||
\fBmsgcat\fR supports packages implemented by object oriented programming.
|
||||
Objects and classes should be defined within a package namespace.
|
||||
.PP
|
||||
There are 3 supported cases where package namespace sensitive commands of msgcat (\fBmc\fR, \fBmcexists\fR, \fBmcpackagelocale\fR, \fBmcforgetpackage\fR, \fBmcpackagenamespaceget\fR, \fBmcpackageconfig\fR, \fBmcset\fR and \fBmcmset\fR) may be called:
|
||||
.PP
|
||||
.TP
|
||||
\fB1) In class definition script\fR
|
||||
.
|
||||
\fBmsgcat\fR command is called within a class definition script.
|
||||
.CS
|
||||
namespace eval ::N2 {
|
||||
mcload $dir/msgs
|
||||
oo::class create C1 {puts [mc Hi!]}
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
.TP
|
||||
\fB2) method defined in a class\fR
|
||||
.
|
||||
\fBmsgcat\fR command is called from a method in an object and the method is defined in a class.
|
||||
.CS
|
||||
namespace eval ::N3Class {
|
||||
mcload $dir/msgs
|
||||
oo::class create C1
|
||||
oo::define C1 method m1 {
|
||||
puts [mc Hi!]
|
||||
}
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
.TP
|
||||
\fB3) method defined in a classless object\fR
|
||||
.
|
||||
\fBmsgcat\fR command is called from a method of a classless object.
|
||||
.CS
|
||||
namespace eval ::N4 {
|
||||
mcload $dir/msgs
|
||||
oo::object create O1
|
||||
oo::objdefine O1 method m1 {} {
|
||||
puts [mc Hi!]
|
||||
}
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
.VE tip490
|
||||
.SH EXAMPLES
|
||||
Packages which display a GUI may update their widgets when the global locale changes.
|
||||
To register to a callback, use:
|
||||
.CS
|
||||
@@ -643,9 +794,9 @@ proc ::tcl::clock::LocalizeFormat { locale format } {
|
||||
.PP
|
||||
The message catalog code was developed by Mark Harrison.
|
||||
.SH "SEE ALSO"
|
||||
format(n), scan(n), namespace(n), package(n)
|
||||
format(n), scan(n), namespace(n), package(n), oo::class(n), oo::object
|
||||
.SH KEYWORDS
|
||||
internationalization, i18n, localization, l10n, message, text, translation
|
||||
internationalization, i18n, localization, l10n, message, text, translation, class, object
|
||||
.\" Local Variables:
|
||||
.\" mode: nroff
|
||||
.\" End:
|
||||
|
||||
+48
-48
@@ -32,7 +32,7 @@ declare 0 {
|
||||
const char *version, const void *clientData)
|
||||
}
|
||||
declare 1 {
|
||||
CONST84_RETURN char *Tcl_PkgRequireEx(Tcl_Interp *interp,
|
||||
const char *Tcl_PkgRequireEx(Tcl_Interp *interp,
|
||||
const char *name, const char *version, int exact,
|
||||
void *clientDataPtr)
|
||||
}
|
||||
@@ -154,7 +154,7 @@ declare 35 {
|
||||
}
|
||||
declare 36 {
|
||||
int Tcl_GetIndexFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
CONST84 char *const *tablePtr, const char *msg, int flags, int *indexPtr)
|
||||
const char *const *tablePtr, const char *msg, int flags, int *indexPtr)
|
||||
}
|
||||
declare 37 {
|
||||
int Tcl_GetInt(Tcl_Interp *interp, const char *src, int *intPtr)
|
||||
@@ -285,7 +285,7 @@ declare 75 {
|
||||
declare 76 {
|
||||
void Tcl_BackgroundError(Tcl_Interp *interp)
|
||||
}
|
||||
declare 77 {
|
||||
declare 77 {deprecated {Use Tcl_UtfBackslash}} {
|
||||
char Tcl_Backslash(const char *src, int *readPtr)
|
||||
}
|
||||
declare 78 {
|
||||
@@ -306,7 +306,7 @@ declare 82 {
|
||||
int Tcl_CommandComplete(const char *cmd)
|
||||
}
|
||||
declare 83 {
|
||||
char *Tcl_Concat(int argc, CONST84 char *const *argv)
|
||||
char *Tcl_Concat(int argc, const char *const *argv)
|
||||
}
|
||||
declare 84 {
|
||||
int Tcl_ConvertElement(const char *src, char *dst, int flags)
|
||||
@@ -318,7 +318,7 @@ declare 85 {
|
||||
declare 86 {
|
||||
int Tcl_CreateAlias(Tcl_Interp *slave, const char *slaveCmd,
|
||||
Tcl_Interp *target, const char *targetCmd, int argc,
|
||||
CONST84 char *const *argv)
|
||||
const char *const *argv)
|
||||
}
|
||||
declare 87 {
|
||||
int Tcl_CreateAliasObj(Tcl_Interp *slave, const char *slaveCmd,
|
||||
@@ -352,7 +352,7 @@ declare 93 {
|
||||
declare 94 {
|
||||
Tcl_Interp *Tcl_CreateInterp(void)
|
||||
}
|
||||
declare 95 {
|
||||
declare 95 {deprecated {}} {
|
||||
void Tcl_CreateMathFunc(Tcl_Interp *interp, const char *name,
|
||||
int numArgs, Tcl_ValueType *argTypes,
|
||||
Tcl_MathProc *proc, ClientData clientData)
|
||||
@@ -461,10 +461,10 @@ declare 126 {
|
||||
int Tcl_Eof(Tcl_Channel chan)
|
||||
}
|
||||
declare 127 {
|
||||
CONST84_RETURN char *Tcl_ErrnoId(void)
|
||||
const char *Tcl_ErrnoId(void)
|
||||
}
|
||||
declare 128 {
|
||||
CONST84_RETURN char *Tcl_ErrnoMsg(int err)
|
||||
const char *Tcl_ErrnoMsg(int err)
|
||||
}
|
||||
declare 129 {
|
||||
int Tcl_Eval(Tcl_Interp *interp, const char *script)
|
||||
@@ -528,12 +528,12 @@ declare 147 {
|
||||
}
|
||||
declare 148 {
|
||||
int Tcl_GetAlias(Tcl_Interp *interp, const char *slaveCmd,
|
||||
Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr,
|
||||
int *argcPtr, CONST84 char ***argvPtr)
|
||||
Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
|
||||
int *argcPtr, const char ***argvPtr)
|
||||
}
|
||||
declare 149 {
|
||||
int Tcl_GetAliasObj(Tcl_Interp *interp, const char *slaveCmd,
|
||||
Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr,
|
||||
Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
|
||||
int *objcPtr, Tcl_Obj ***objv)
|
||||
}
|
||||
declare 150 {
|
||||
@@ -558,7 +558,7 @@ declare 155 {
|
||||
int Tcl_GetChannelMode(Tcl_Channel chan)
|
||||
}
|
||||
declare 156 {
|
||||
CONST84_RETURN char *Tcl_GetChannelName(Tcl_Channel chan)
|
||||
const char *Tcl_GetChannelName(Tcl_Channel chan)
|
||||
}
|
||||
declare 157 {
|
||||
int Tcl_GetChannelOption(Tcl_Interp *interp, Tcl_Channel chan,
|
||||
@@ -572,14 +572,14 @@ declare 159 {
|
||||
Tcl_CmdInfo *infoPtr)
|
||||
}
|
||||
declare 160 {
|
||||
CONST84_RETURN char *Tcl_GetCommandName(Tcl_Interp *interp,
|
||||
const char *Tcl_GetCommandName(Tcl_Interp *interp,
|
||||
Tcl_Command command)
|
||||
}
|
||||
declare 161 {
|
||||
int Tcl_GetErrno(void)
|
||||
}
|
||||
declare 162 {
|
||||
CONST84_RETURN char *Tcl_GetHostName(void)
|
||||
const char *Tcl_GetHostName(void)
|
||||
}
|
||||
declare 163 {
|
||||
int Tcl_GetInterpPath(Tcl_Interp *askInterp, Tcl_Interp *slaveInterp)
|
||||
@@ -622,14 +622,14 @@ declare 173 {
|
||||
Tcl_Channel Tcl_GetStdChannel(int type)
|
||||
}
|
||||
declare 174 {
|
||||
CONST84_RETURN char *Tcl_GetStringResult(Tcl_Interp *interp)
|
||||
const char *Tcl_GetStringResult(Tcl_Interp *interp)
|
||||
}
|
||||
declare 175 {
|
||||
CONST84_RETURN char *Tcl_GetVar(Tcl_Interp *interp, const char *varName,
|
||||
const char *Tcl_GetVar(Tcl_Interp *interp, const char *varName,
|
||||
int flags)
|
||||
}
|
||||
declare 176 {
|
||||
CONST84_RETURN char *Tcl_GetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *Tcl_GetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *part2, int flags)
|
||||
}
|
||||
declare 177 {
|
||||
@@ -662,7 +662,7 @@ declare 185 {
|
||||
}
|
||||
# Obsolete, use Tcl_FSJoinPath
|
||||
declare 186 {
|
||||
char *Tcl_JoinPath(int argc, CONST84 char *const *argv,
|
||||
char *Tcl_JoinPath(int argc, const char *const *argv,
|
||||
Tcl_DString *resultPtr)
|
||||
}
|
||||
declare 187 {
|
||||
@@ -685,7 +685,7 @@ declare 191 {
|
||||
Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket)
|
||||
}
|
||||
declare 192 {
|
||||
char *Tcl_Merge(int argc, CONST84 char *const *argv)
|
||||
char *Tcl_Merge(int argc, const char *const *argv)
|
||||
}
|
||||
declare 193 {
|
||||
Tcl_HashEntry *Tcl_NextHashEntry(Tcl_HashSearch *searchPtr)
|
||||
@@ -703,7 +703,7 @@ declare 196 {
|
||||
}
|
||||
declare 197 {
|
||||
Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc,
|
||||
CONST84 char **argv, int flags)
|
||||
const char **argv, int flags)
|
||||
}
|
||||
# This is obsolete, use Tcl_FSOpenFileChannel
|
||||
declare 198 {
|
||||
@@ -729,7 +729,7 @@ declare 203 {
|
||||
int Tcl_PutEnv(const char *assignment)
|
||||
}
|
||||
declare 204 {
|
||||
CONST84_RETURN char *Tcl_PosixError(Tcl_Interp *interp)
|
||||
const char *Tcl_PosixError(Tcl_Interp *interp)
|
||||
}
|
||||
declare 205 {
|
||||
void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position)
|
||||
@@ -765,7 +765,7 @@ declare 214 {
|
||||
}
|
||||
declare 215 {
|
||||
void Tcl_RegExpRange(Tcl_RegExp regexp, int index,
|
||||
CONST84 char **startPtr, CONST84 char **endPtr)
|
||||
const char **startPtr, const char **endPtr)
|
||||
}
|
||||
declare 216 {
|
||||
void Tcl_Release(ClientData clientData)
|
||||
@@ -835,29 +835,29 @@ declare 236 {
|
||||
void Tcl_SetStdChannel(Tcl_Channel channel, int type)
|
||||
}
|
||||
declare 237 {
|
||||
CONST84_RETURN char *Tcl_SetVar(Tcl_Interp *interp, const char *varName,
|
||||
const char *Tcl_SetVar(Tcl_Interp *interp, const char *varName,
|
||||
const char *newValue, int flags)
|
||||
}
|
||||
declare 238 {
|
||||
CONST84_RETURN char *Tcl_SetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *Tcl_SetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *part2, const char *newValue, int flags)
|
||||
}
|
||||
declare 239 {
|
||||
CONST84_RETURN char *Tcl_SignalId(int sig)
|
||||
const char *Tcl_SignalId(int sig)
|
||||
}
|
||||
declare 240 {
|
||||
CONST84_RETURN char *Tcl_SignalMsg(int sig)
|
||||
const char *Tcl_SignalMsg(int sig)
|
||||
}
|
||||
declare 241 {
|
||||
void Tcl_SourceRCFile(Tcl_Interp *interp)
|
||||
}
|
||||
declare 242 {
|
||||
int Tcl_SplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
|
||||
CONST84 char ***argvPtr)
|
||||
const char ***argvPtr)
|
||||
}
|
||||
# Obsolete, use Tcl_FSSplitPath
|
||||
declare 243 {
|
||||
void Tcl_SplitPath(const char *path, int *argcPtr, CONST84 char ***argvPtr)
|
||||
void Tcl_SplitPath(const char *path, int *argcPtr, const char ***argvPtr)
|
||||
}
|
||||
declare 244 {
|
||||
void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName,
|
||||
@@ -952,15 +952,15 @@ declare 269 {
|
||||
char *Tcl_HashStats(Tcl_HashTable *tablePtr)
|
||||
}
|
||||
declare 270 {
|
||||
CONST84_RETURN char *Tcl_ParseVar(Tcl_Interp *interp, const char *start,
|
||||
CONST84 char **termPtr)
|
||||
const char *Tcl_ParseVar(Tcl_Interp *interp, const char *start,
|
||||
const char **termPtr)
|
||||
}
|
||||
declare 271 {
|
||||
CONST84_RETURN char *Tcl_PkgPresent(Tcl_Interp *interp, const char *name,
|
||||
const char *Tcl_PkgPresent(Tcl_Interp *interp, const char *name,
|
||||
const char *version, int exact)
|
||||
}
|
||||
declare 272 {
|
||||
CONST84_RETURN char *Tcl_PkgPresentEx(Tcl_Interp *interp,
|
||||
const char *Tcl_PkgPresentEx(Tcl_Interp *interp,
|
||||
const char *name, const char *version, int exact,
|
||||
void *clientDataPtr)
|
||||
}
|
||||
@@ -970,7 +970,7 @@ declare 273 {
|
||||
}
|
||||
# TIP #268: The internally used new Require function is in slot 573.
|
||||
declare 274 {
|
||||
CONST84_RETURN char *Tcl_PkgRequire(Tcl_Interp *interp, const char *name,
|
||||
const char *Tcl_PkgRequire(Tcl_Interp *interp, const char *name,
|
||||
const char *version, int exact)
|
||||
}
|
||||
declare 275 {deprecated {see TIP #422}} {
|
||||
@@ -1084,7 +1084,7 @@ declare 301 {
|
||||
Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, const char *name)
|
||||
}
|
||||
declare 302 {
|
||||
CONST84_RETURN char *Tcl_GetEncodingName(Tcl_Encoding encoding)
|
||||
const char *Tcl_GetEncodingName(Tcl_Encoding encoding)
|
||||
}
|
||||
declare 303 {
|
||||
void Tcl_GetEncodingNames(Tcl_Interp *interp)
|
||||
@@ -1160,7 +1160,7 @@ declare 324 {
|
||||
int Tcl_UniCharToUtf(int ch, char *buf)
|
||||
}
|
||||
declare 325 {
|
||||
CONST84_RETURN char *Tcl_UtfAtIndex(const char *src, int index)
|
||||
const char *Tcl_UtfAtIndex(const char *src, int index)
|
||||
}
|
||||
declare 326 {
|
||||
int Tcl_UtfCharComplete(const char *src, int length)
|
||||
@@ -1169,16 +1169,16 @@ declare 327 {
|
||||
int Tcl_UtfBackslash(const char *src, int *readPtr, char *dst)
|
||||
}
|
||||
declare 328 {
|
||||
CONST84_RETURN char *Tcl_UtfFindFirst(const char *src, int ch)
|
||||
const char *Tcl_UtfFindFirst(const char *src, int ch)
|
||||
}
|
||||
declare 329 {
|
||||
CONST84_RETURN char *Tcl_UtfFindLast(const char *src, int ch)
|
||||
const char *Tcl_UtfFindLast(const char *src, int ch)
|
||||
}
|
||||
declare 330 {
|
||||
CONST84_RETURN char *Tcl_UtfNext(const char *src)
|
||||
const char *Tcl_UtfNext(const char *src)
|
||||
}
|
||||
declare 331 {
|
||||
CONST84_RETURN char *Tcl_UtfPrev(const char *src, const char *start)
|
||||
const char *Tcl_UtfPrev(const char *src, const char *start)
|
||||
}
|
||||
declare 332 {
|
||||
int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding,
|
||||
@@ -1211,10 +1211,10 @@ declare 339 {
|
||||
declare 340 {
|
||||
char *Tcl_GetString(Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 341 {
|
||||
CONST84_RETURN char *Tcl_GetDefaultEncodingDir(void)
|
||||
declare 341 {deprecated {Use Tcl_GetEncodingSearchPath}} {
|
||||
const char *Tcl_GetDefaultEncodingDir(void)
|
||||
}
|
||||
declare 342 {
|
||||
declare 342 {deprecated {Use Tcl_SetEncodingSearchPath}} {
|
||||
void Tcl_SetDefaultEncodingDir(const char *path)
|
||||
}
|
||||
declare 343 {
|
||||
@@ -1263,7 +1263,7 @@ declare 356 {
|
||||
Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj,
|
||||
int flags)
|
||||
}
|
||||
declare 357 {
|
||||
declare 357 {deprecated {Use Tcl_EvalTokensStandard}} {
|
||||
Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
|
||||
int count)
|
||||
}
|
||||
@@ -1276,7 +1276,7 @@ declare 359 {
|
||||
}
|
||||
declare 360 {
|
||||
int Tcl_ParseBraces(Tcl_Interp *interp, const char *start, int numBytes,
|
||||
Tcl_Parse *parsePtr, int append, CONST84 char **termPtr)
|
||||
Tcl_Parse *parsePtr, int append, const char **termPtr)
|
||||
}
|
||||
declare 361 {
|
||||
int Tcl_ParseCommand(Tcl_Interp *interp, const char *start, int numBytes,
|
||||
@@ -1289,7 +1289,7 @@ declare 362 {
|
||||
declare 363 {
|
||||
int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start,
|
||||
int numBytes, Tcl_Parse *parsePtr, int append,
|
||||
CONST84 char **termPtr)
|
||||
const char **termPtr)
|
||||
}
|
||||
declare 364 {
|
||||
int Tcl_ParseVarName(Tcl_Interp *interp, const char *start, int numBytes,
|
||||
@@ -1405,7 +1405,7 @@ declare 397 {
|
||||
int Tcl_ChannelBuffered(Tcl_Channel chan)
|
||||
}
|
||||
declare 398 {
|
||||
CONST84_RETURN char *Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr)
|
||||
const char *Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr)
|
||||
}
|
||||
declare 399 {
|
||||
Tcl_ChannelTypeVersion Tcl_ChannelVersion(
|
||||
@@ -1545,12 +1545,12 @@ declare 434 {
|
||||
}
|
||||
|
||||
# TIP#15 (math function introspection) dkf
|
||||
declare 435 {
|
||||
declare 435 {deprecated {}} {
|
||||
int Tcl_GetMathFuncInfo(Tcl_Interp *interp, const char *name,
|
||||
int *numArgsPtr, Tcl_ValueType **argTypesPtr,
|
||||
Tcl_MathProc **procPtr, ClientData *clientDataPtr)
|
||||
}
|
||||
declare 436 {
|
||||
declare 436 {deprecated {}} {
|
||||
Tcl_Obj *Tcl_ListMathFuncs(Tcl_Interp *interp, const char *pattern)
|
||||
}
|
||||
|
||||
|
||||
+54
-99
@@ -137,7 +137,7 @@ extern "C" {
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
# define TCL_VARARGS(type, name) (type name, ...)
|
||||
# define TCL_VARARGS_DEF(type, name) (type name, ...)
|
||||
# define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
|
||||
@@ -254,10 +254,9 @@ extern "C" {
|
||||
* New code should use prototypes.
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
# undef _ANSI_ARGS_
|
||||
# define _ANSI_ARGS_(x) x
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Definitions that allow this header file to be used either with or without
|
||||
@@ -267,34 +266,16 @@ extern "C" {
|
||||
#ifndef INLINE
|
||||
# define INLINE
|
||||
#endif
|
||||
|
||||
#ifdef NO_CONST
|
||||
# ifndef const
|
||||
# define const
|
||||
# endif
|
||||
#endif
|
||||
#ifndef CONST
|
||||
# define CONST const
|
||||
#endif
|
||||
#define CONST84 const
|
||||
#define CONST84_RETURN const
|
||||
|
||||
#ifdef USE_NON_CONST
|
||||
# ifdef USE_COMPAT_CONST
|
||||
# error define at most one of USE_NON_CONST and USE_COMPAT_CONST
|
||||
# endif
|
||||
# define CONST84
|
||||
# define CONST84_RETURN
|
||||
#else
|
||||
# ifdef USE_COMPAT_CONST
|
||||
# define CONST84
|
||||
# define CONST84_RETURN const
|
||||
# else
|
||||
# define CONST84 const
|
||||
# define CONST84_RETURN const
|
||||
# endif
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
#ifndef CONST86
|
||||
# define CONST86 CONST84
|
||||
# define CONST86 const
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -318,6 +299,7 @@ extern "C" {
|
||||
* VOID. This block is skipped under Cygwin and Mingw.
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
#if defined(_WIN32) && !defined(HAVE_WINNT_IGNORE_VOID)
|
||||
#ifndef VOID
|
||||
#define VOID void
|
||||
@@ -333,23 +315,16 @@ typedef long LONG;
|
||||
*/
|
||||
|
||||
#ifndef __VXWORKS__
|
||||
# ifndef NO_VOID
|
||||
# define VOID void
|
||||
# else
|
||||
# define VOID char
|
||||
# endif
|
||||
# define VOID void
|
||||
#endif
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 */
|
||||
|
||||
/*
|
||||
* Miscellaneous declarations.
|
||||
*/
|
||||
|
||||
#ifndef _CLIENTDATA
|
||||
# ifndef NO_VOID
|
||||
typedef void *ClientData;
|
||||
# else
|
||||
typedef int *ClientData;
|
||||
# endif
|
||||
typedef void *ClientData;
|
||||
# define _CLIENTDATA
|
||||
#endif
|
||||
|
||||
@@ -396,44 +371,40 @@ typedef long LONG;
|
||||
# if defined(_WIN32)
|
||||
# define TCL_WIDE_INT_TYPE __int64
|
||||
# define TCL_LL_MODIFIER "I64"
|
||||
# if defined(_WIN64)
|
||||
# define TCL_Z_MODIFIER "I"
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
# define TCL_Z_MODIFIER "z"
|
||||
# else /* ! _WIN32 && ! __GNUC__ */
|
||||
/*
|
||||
* Don't know what platform it is and configure hasn't discovered what is
|
||||
* going on for us. Try to guess...
|
||||
*/
|
||||
# include <limits.h>
|
||||
# if (INT_MAX < LONG_MAX)
|
||||
# if defined(LLONG_MAX) && (LLONG_MAX == LONG_MAX)
|
||||
# define TCL_WIDE_INT_IS_LONG 1
|
||||
# else
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# endif
|
||||
# endif /* _WIN32 */
|
||||
#endif /* !TCL_WIDE_INT_TYPE & !TCL_WIDE_INT_IS_LONG */
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
# undef TCL_WIDE_INT_TYPE
|
||||
# define TCL_WIDE_INT_TYPE long
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#ifndef TCL_WIDE_INT_TYPE
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
#endif /* !TCL_WIDE_INT_TYPE */
|
||||
|
||||
typedef TCL_WIDE_INT_TYPE Tcl_WideInt;
|
||||
typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "l"
|
||||
# endif /* !TCL_LL_MODIFIER */
|
||||
#else /* TCL_WIDE_INT_IS_LONG */
|
||||
/*
|
||||
* The next short section of defines are only done when not running on Windows
|
||||
* or some other strange platform.
|
||||
*/
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
# endif /* !TCL_LL_MODIFIER */
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
#endif /* !TCL_LL_MODIFIER */
|
||||
#ifndef TCL_Z_MODIFIER
|
||||
# if defined(__GNUC__) && !defined(_WIN32)
|
||||
# define TCL_Z_MODIFIER "z"
|
||||
# else
|
||||
# define TCL_Z_MODIFIER ""
|
||||
# endif
|
||||
#endif /* !TCL_Z_MODIFIER */
|
||||
#define Tcl_WideAsLong(val) ((long)((Tcl_WideInt)(val)))
|
||||
#define Tcl_LongAsWide(val) ((Tcl_WideInt)((long)(val)))
|
||||
#define Tcl_WideAsDouble(val) ((double)((Tcl_WideInt)(val)))
|
||||
@@ -493,35 +464,13 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
*/
|
||||
|
||||
typedef struct Tcl_Interp
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
{
|
||||
/* TIP #330: Strongly discourage extensions from using the string
|
||||
* result. */
|
||||
#ifdef USE_INTERP_RESULT
|
||||
char *result TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult");
|
||||
/* If the last command returned a string
|
||||
* result, this points to it. */
|
||||
void (*freeProc) (char *blockPtr)
|
||||
TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult");
|
||||
/* Zero means the string result is statically
|
||||
* allocated. TCL_DYNAMIC means it was
|
||||
* allocated with ckalloc and should be freed
|
||||
* with ckfree. Other values give the address
|
||||
* of function to invoke to free the result.
|
||||
* Tcl_Eval must free it before executing next
|
||||
* command. */
|
||||
#else
|
||||
char *resultDontUse; /* Don't use in extensions! */
|
||||
void (*freeProcDontUse) (char *); /* Don't use in extensions! */
|
||||
#endif
|
||||
#ifdef USE_INTERP_ERRORLINE
|
||||
int errorLine TCL_DEPRECATED_API("use Tcl_GetErrorLine/Tcl_SetErrorLine");
|
||||
/* When TCL_ERROR is returned, this gives the
|
||||
* line number within the command where the
|
||||
* error occurred (1 if first line). */
|
||||
#else
|
||||
int errorLineDontUse; /* Don't use in extensions! */
|
||||
#endif
|
||||
}
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
Tcl_Interp;
|
||||
@@ -673,7 +622,9 @@ typedef struct stat *Tcl_OldStat_;
|
||||
#define TCL_BREAK 3
|
||||
#define TCL_CONTINUE 4
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
#define TCL_RESULT_SIZE 200
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -689,6 +640,7 @@ typedef struct stat *Tcl_OldStat_;
|
||||
* Argument descriptors for math function callbacks in expressions:
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
typedef enum {
|
||||
TCL_INT, TCL_DOUBLE, TCL_EITHER, TCL_WIDE_INT
|
||||
} Tcl_ValueType;
|
||||
@@ -700,6 +652,10 @@ typedef struct Tcl_Value {
|
||||
double doubleValue; /* Double-precision floating value. */
|
||||
Tcl_WideInt wideValue; /* Wide (min. 64-bit) integer value. */
|
||||
} Tcl_Value;
|
||||
#else
|
||||
#define Tcl_ValueType void /* Just enough to prevent compilation error in Tcl */
|
||||
#define Tcl_Value void /* Just enough to prevent compilation error in Tcl */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Forward declaration of Tcl_Obj to prevent an error when the forward
|
||||
@@ -720,10 +676,10 @@ typedef void (Tcl_ChannelProc) (ClientData clientData, int mask);
|
||||
typedef void (Tcl_CloseProc) (ClientData data);
|
||||
typedef void (Tcl_CmdDeleteProc) (ClientData clientData);
|
||||
typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, const char *argv[]);
|
||||
typedef void (Tcl_CmdTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
int level, char *command, Tcl_CmdProc *proc,
|
||||
ClientData cmdClientData, int argc, CONST84 char *argv[]);
|
||||
ClientData cmdClientData, int argc, const char *argv[]);
|
||||
typedef int (Tcl_CmdObjTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
int level, const char *command, Tcl_Command commandInfo, int objc,
|
||||
struct Tcl_Obj *const *objv);
|
||||
@@ -760,7 +716,7 @@ typedef void (Tcl_TimerProc) (ClientData clientData);
|
||||
typedef int (Tcl_SetFromAnyProc) (Tcl_Interp *interp, struct Tcl_Obj *objPtr);
|
||||
typedef void (Tcl_UpdateStringProc) (struct Tcl_Obj *objPtr);
|
||||
typedef char * (Tcl_VarTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
CONST84 char *part1, CONST84 char *part2, int flags);
|
||||
const char *part1, const char *part2, int flags);
|
||||
typedef void (Tcl_CommandTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
const char *oldName, const char *newName, int flags);
|
||||
typedef void (Tcl_CreateFileHandlerProc) (int fd, int mask, Tcl_FileProc *proc,
|
||||
@@ -871,7 +827,7 @@ typedef struct Tcl_SavedResult {
|
||||
char *appendResult;
|
||||
int appendAvl;
|
||||
int appendUsed;
|
||||
char resultSpace[TCL_RESULT_SIZE+1];
|
||||
char resultSpace[200+1];
|
||||
} Tcl_SavedResult;
|
||||
|
||||
/*
|
||||
@@ -997,7 +953,7 @@ typedef struct Tcl_DString {
|
||||
|
||||
#define Tcl_DStringLength(dsPtr) ((dsPtr)->length)
|
||||
#define Tcl_DStringValue(dsPtr) ((dsPtr)->string)
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
# define Tcl_DStringTrunc Tcl_DStringSetLength
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
@@ -1125,7 +1081,7 @@ typedef struct Tcl_DString {
|
||||
* give the flag)
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
# define TCL_PARSE_PART1 0x400
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
@@ -1478,14 +1434,14 @@ typedef int (Tcl_DriverClose2Proc) (ClientData instanceData,
|
||||
typedef int (Tcl_DriverInputProc) (ClientData instanceData, char *buf,
|
||||
int toRead, int *errorCodePtr);
|
||||
typedef int (Tcl_DriverOutputProc) (ClientData instanceData,
|
||||
CONST84 char *buf, int toWrite, int *errorCodePtr);
|
||||
const char *buf, int toWrite, int *errorCodePtr);
|
||||
typedef int (Tcl_DriverSeekProc) (ClientData instanceData, long offset,
|
||||
int mode, int *errorCodePtr);
|
||||
typedef int (Tcl_DriverSetOptionProc) (ClientData instanceData,
|
||||
Tcl_Interp *interp, const char *optionName,
|
||||
const char *value);
|
||||
typedef int (Tcl_DriverGetOptionProc) (ClientData instanceData,
|
||||
Tcl_Interp *interp, CONST84 char *optionName,
|
||||
Tcl_Interp *interp, const char *optionName,
|
||||
Tcl_DString *dsPtr);
|
||||
typedef void (Tcl_DriverWatchProc) (ClientData instanceData, int mask);
|
||||
typedef int (Tcl_DriverGetHandleProc) (ClientData instanceData,
|
||||
@@ -1978,7 +1934,7 @@ typedef struct Tcl_Token {
|
||||
* TCL_TOKEN_OPERATOR - The token describes one expression operator.
|
||||
* An operator might be the name of a math
|
||||
* function such as "abs". A TCL_TOKEN_OPERATOR
|
||||
* token is always preceeded by one
|
||||
* token is always preceded by one
|
||||
* TCL_TOKEN_SUB_EXPR token for the operator's
|
||||
* subexpression, and is followed by zero or more
|
||||
* TCL_TOKEN_SUB_EXPR tokens for the operator's
|
||||
@@ -2407,6 +2363,11 @@ const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version,
|
||||
int exact, int magic);
|
||||
const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
|
||||
const char *version, int epoch, int revision);
|
||||
#if defined(_WIN32)
|
||||
TCL_NORETURN void Tcl_ConsolePanic(const char *format, ...);
|
||||
#else
|
||||
# define Tcl_ConsolePanic ((Tcl_PanicProc *)0)
|
||||
#endif
|
||||
|
||||
#ifdef USE_TCL_STUBS
|
||||
#if TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
|
||||
@@ -2438,7 +2399,7 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
|
||||
*/
|
||||
|
||||
#define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \
|
||||
((Tcl_CreateInterp)()))
|
||||
((Tcl_SetPanicProc(Tcl_ConsolePanic), Tcl_CreateInterp)()))
|
||||
EXTERN void Tcl_MainEx(int argc, char **argv,
|
||||
Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
|
||||
EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp,
|
||||
@@ -2557,15 +2518,9 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
# undef Tcl_NewDoubleObj
|
||||
# define Tcl_NewDoubleObj(val) \
|
||||
Tcl_DbNewDoubleObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewIntObj
|
||||
# define Tcl_NewIntObj(val) \
|
||||
Tcl_DbNewLongObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewListObj
|
||||
# define Tcl_NewListObj(objc, objv) \
|
||||
Tcl_DbNewListObj(objc, objv, __FILE__, __LINE__)
|
||||
# undef Tcl_NewLongObj
|
||||
# define Tcl_NewLongObj(val) \
|
||||
Tcl_DbNewLongObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewObj
|
||||
# define Tcl_NewObj() \
|
||||
Tcl_DbNewObj(__FILE__, __LINE__)
|
||||
@@ -2628,10 +2583,10 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
* Deprecated Tcl functions:
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
/*
|
||||
* These function have been renamed. The old names are deprecated, but we
|
||||
* define these macros for backwards compatibilty.
|
||||
* define these macros for backwards compatibility.
|
||||
*/
|
||||
|
||||
# define Tcl_Ckalloc Tcl_Alloc
|
||||
|
||||
+5
-5
@@ -661,14 +661,14 @@ mstats(
|
||||
|
||||
fprintf(stderr, "\nused:\t");
|
||||
for (i = 0; i < NBUCKETS; i++) {
|
||||
fprintf(stderr, " %" TCL_LL_MODIFIER "d", (Tcl_WideInt)numMallocs[i]);
|
||||
fprintf(stderr, " %" TCL_Z_MODIFIER "u", numMallocs[i]);
|
||||
totalUsed += numMallocs[i] * (1 << (i + 3));
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\tTotal small in use: %" TCL_LL_MODIFIER "d, total free: %" TCL_LL_MODIFIER "d\n",
|
||||
(Tcl_WideInt)totalUsed, (Tcl_WideInt)totalFree);
|
||||
fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %" TCL_LL_MODIFIER "d\n",
|
||||
MAXMALLOC, (Tcl_WideInt)numMallocs[NBUCKETS]);
|
||||
fprintf(stderr, "\n\tTotal small in use: %" TCL_Z_MODIFIER "u, total free: %" TCL_Z_MODIFIER "u\n",
|
||||
totalUsed, totalFree);
|
||||
fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %" TCL_Z_MODIFIER "u\n",
|
||||
MAXMALLOC, numMallocs[NBUCKETS]);
|
||||
|
||||
Tcl_MutexUnlock(allocMutexPtr);
|
||||
}
|
||||
|
||||
+13
-12
@@ -2246,23 +2246,24 @@ GetListIndexOperand(
|
||||
Tcl_Token* tokenPtr = *tokenPtrPtr;
|
||||
/* INOUT: Pointer to the next token in the
|
||||
* source code */
|
||||
Tcl_Obj* intObj; /* Integer from the source code */
|
||||
int status; /* Tcl status return */
|
||||
Tcl_Obj *value;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Extract the next token as a string.
|
||||
*/
|
||||
|
||||
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &intObj) != TCL_OK) {
|
||||
/* General operand validity check */
|
||||
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &value) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Convert to an integer, advance to the next token and return. */
|
||||
/*
|
||||
* Convert to an integer, advance to the next token and return.
|
||||
* NOTE: Indexing a list with an index before it yields the
|
||||
* same result as indexing after it, and might be more easily portable
|
||||
* when list size limits grow.
|
||||
*/
|
||||
status = TclIndexEncode(interp, value,
|
||||
TCL_INDEX_BEFORE,TCL_INDEX_BEFORE, result);
|
||||
|
||||
status = TclGetIntForIndex(interp, intObj, -2, result);
|
||||
Tcl_DecrRefCount(intObj);
|
||||
Tcl_DecrRefCount(value);
|
||||
*tokenPtrPtr = TokenAfter(tokenPtr);
|
||||
return status;
|
||||
}
|
||||
@@ -4266,7 +4267,7 @@ AddBasicBlockRangeToErrorInfo(
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
Tcl_AddErrorInfo(interp, " and ");
|
||||
if (bbPtr->successor1 != NULL) {
|
||||
TclSetLongObj(lineNo, bbPtr->successor1->startLine);
|
||||
TclSetIntObj(lineNo, bbPtr->successor1->startLine);
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
} else {
|
||||
Tcl_AddErrorInfo(interp, "end of assembly code");
|
||||
|
||||
+42
-40
@@ -132,8 +132,10 @@ static Tcl_NRPostProc NRCoroutineCallerCallback;
|
||||
static Tcl_NRPostProc NRCoroutineExitCallback;
|
||||
static Tcl_NRPostProc NRCommand;
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED)
|
||||
static Tcl_ObjCmdProc OldMathFuncProc;
|
||||
static void OldMathFuncDeleteProc(ClientData clientData);
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
static void ProcessUnexpectedResult(Tcl_Interp *interp,
|
||||
int returnCode);
|
||||
static int RewindCoroutine(CoroutineData *corPtr, int result);
|
||||
@@ -205,7 +207,7 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE},
|
||||
{"apply", Tcl_ApplyObjCmd, NULL, TclNRApplyObjCmd, CMD_IS_SAFE},
|
||||
{"break", Tcl_BreakObjCmd, TclCompileBreakCmd, NULL, CMD_IS_SAFE},
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
{"case", Tcl_CaseObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
#endif
|
||||
{"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, TclNRCatchObjCmd, CMD_IS_SAFE},
|
||||
@@ -236,7 +238,7 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE},
|
||||
{"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"package", Tcl_PackageObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE},
|
||||
{"proc", Tcl_ProcObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE},
|
||||
{"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE},
|
||||
@@ -817,6 +819,7 @@ Tcl_CreateInterp(void)
|
||||
TclInitNamespaceCmd(interp);
|
||||
TclInitStringCmd(interp);
|
||||
TclInitPrefixCmd(interp);
|
||||
TclInitProcessCmd(interp);
|
||||
|
||||
/*
|
||||
* Register "clock" subcommands. These *do* go through
|
||||
@@ -954,9 +957,11 @@ Tcl_CreateInterp(void)
|
||||
|
||||
Tcl_SetVar2(interp, "tcl_patchLevel", NULL, TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "tcl_version", NULL, TCL_VERSION, TCL_GLOBAL_ONLY);
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
Tcl_TraceVar2(interp, "tcl_precision", NULL,
|
||||
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||||
TclPrecTraceProc, NULL);
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
TclpSetVariables(interp);
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
@@ -2624,10 +2629,6 @@ TclRenameCommand(
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
cmdNsPtr = cmdPtr->nsPtr;
|
||||
oldFullName = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(oldFullName);
|
||||
Tcl_GetCommandFullName(interp, cmd, oldFullName);
|
||||
|
||||
/*
|
||||
* If the new command name is NULL or empty, delete the command. Do this
|
||||
@@ -2636,10 +2637,14 @@ TclRenameCommand(
|
||||
|
||||
if ((newName == NULL) || (*newName == '\0')) {
|
||||
Tcl_DeleteCommandFromToken(interp, cmd);
|
||||
result = TCL_OK;
|
||||
goto done;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
cmdNsPtr = cmdPtr->nsPtr;
|
||||
oldFullName = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(oldFullName);
|
||||
Tcl_GetCommandFullName(interp, cmd, oldFullName);
|
||||
|
||||
/*
|
||||
* Make sure that the destination command does not already exist. The
|
||||
* rename operation is like creating a command, so we should automatically
|
||||
@@ -3151,6 +3156,8 @@ Tcl_DeleteCommandFromToken(
|
||||
* traces.
|
||||
*/
|
||||
|
||||
cmdPtr->nsPtr->refCount++;
|
||||
|
||||
if (cmdPtr->tracePtr != NULL) {
|
||||
CommandTrace *tracePtr;
|
||||
CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);
|
||||
@@ -3178,6 +3185,7 @@ Tcl_DeleteCommandFromToken(
|
||||
*/
|
||||
|
||||
TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
|
||||
TclNsDecrRefCount(cmdPtr->nsPtr);
|
||||
|
||||
/*
|
||||
* If the command being deleted has a compile function, increment the
|
||||
@@ -3515,6 +3523,7 @@ TclCleanupCommand(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED)
|
||||
void
|
||||
Tcl_CreateMathFunc(
|
||||
Tcl_Interp *interp, /* Interpreter in which function is to be
|
||||
@@ -3565,7 +3574,7 @@ Tcl_CreateMathFunc(
|
||||
|
||||
static int
|
||||
OldMathFuncProc(
|
||||
ClientData clientData, /* Ponter to OldMathFuncData describing the
|
||||
ClientData clientData, /* Pointer to OldMathFuncData describing the
|
||||
* function being called */
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
int objc, /* Actual parameter count */
|
||||
@@ -3678,7 +3687,7 @@ OldMathFuncProc(
|
||||
*/
|
||||
|
||||
if (funcResult.type == TCL_INT) {
|
||||
TclNewLongObj(valuePtr, funcResult.intValue);
|
||||
TclNewIntObj(valuePtr, funcResult.intValue);
|
||||
} else if (funcResult.type == TCL_WIDE_INT) {
|
||||
valuePtr = Tcl_NewWideIntObj(funcResult.wideValue);
|
||||
} else {
|
||||
@@ -3846,6 +3855,7 @@ Tcl_ListMathFuncs(
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -4453,7 +4463,9 @@ TclNRRunCallbacks(
|
||||
/* All callbacks down to rootPtr not inclusive
|
||||
* are to be run. */
|
||||
{
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
NRE_callback *callbackPtr;
|
||||
Tcl_NRPostProc *procPtr;
|
||||
|
||||
@@ -4467,9 +4479,13 @@ TclNRRunCallbacks(
|
||||
* are for NR function calls, and those are Tcl_Obj based.
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
if (*(iPtr->result) != 0) {
|
||||
(void) Tcl_GetObjResult(interp);
|
||||
}
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
|
||||
/* This is the trampoline. */
|
||||
|
||||
while (TOP_CB(interp) != rootPtr) {
|
||||
callbackPtr = TOP_CB(interp);
|
||||
@@ -4604,7 +4620,7 @@ TEOV_Exception(
|
||||
if (result == TCL_RETURN) {
|
||||
result = TclUpdateReturnInfo(iPtr);
|
||||
}
|
||||
if ((result != TCL_ERROR) && !allowExceptions) {
|
||||
if ((result != TCL_OK) && (result != TCL_ERROR) && !allowExceptions) {
|
||||
ProcessUnexpectedResult(interp, result);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
@@ -4785,7 +4801,7 @@ TEOV_RunEnterTraces(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Command *cmdPtr = *cmdPtrPtr;
|
||||
size_t newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
|
||||
unsigned int newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
|
||||
int length, traceCode = TCL_OK;
|
||||
const char *command = TclGetStringFromObj(commandPtr, &length);
|
||||
|
||||
@@ -4928,6 +4944,7 @@ Tcl_EvalTokensStandard(
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -4975,6 +4992,7 @@ Tcl_EvalTokens(
|
||||
Tcl_ResetResult(interp);
|
||||
return resPtr;
|
||||
}
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -6493,7 +6511,6 @@ Tcl_ExprLongObj(
|
||||
resultPtr = Tcl_NewBignumObj(&big);
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
case TCL_NUMBER_LONG:
|
||||
case TCL_NUMBER_WIDE:
|
||||
case TCL_NUMBER_BIG:
|
||||
result = TclGetLongFromObj(interp, resultPtr, ptr);
|
||||
@@ -6861,7 +6878,8 @@ Tcl_AddObjErrorInfo(
|
||||
|
||||
iPtr->flags |= ERR_LEGACY_COPY;
|
||||
if (iPtr->errorInfo == NULL) {
|
||||
if (iPtr->result[0] != 0) {
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
if (*(iPtr->result) != 0) {
|
||||
/*
|
||||
* The interp's string result is set, apparently by some extension
|
||||
* making a deprecated direct write to it. That extension may
|
||||
@@ -6871,9 +6889,9 @@ Tcl_AddObjErrorInfo(
|
||||
*/
|
||||
|
||||
iPtr->errorInfo = Tcl_NewStringObj(iPtr->result, -1);
|
||||
} else {
|
||||
} else
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
iPtr->errorInfo = iPtr->objResultPtr;
|
||||
}
|
||||
Tcl_IncrRefCount(iPtr->errorInfo);
|
||||
if (!iPtr->errorCode) {
|
||||
Tcl_SetErrorCode(interp, "NONE", NULL);
|
||||
@@ -7469,12 +7487,12 @@ ExprAbsFunc(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (type == TCL_NUMBER_LONG) {
|
||||
long l = *((const long *) ptr);
|
||||
if (type == TCL_NUMBER_WIDE) {
|
||||
Tcl_WideInt l = *((const Tcl_WideInt *) ptr);
|
||||
|
||||
if (l > (long)0) {
|
||||
if (l > (Tcl_WideInt)0) {
|
||||
goto unChanged;
|
||||
} else if (l == (long)0) {
|
||||
} else if (l == (Tcl_WideInt)0) {
|
||||
const char *string = objv[1]->bytes;
|
||||
if (string) {
|
||||
while (*string != '0') {
|
||||
@@ -7486,11 +7504,11 @@ ExprAbsFunc(
|
||||
}
|
||||
}
|
||||
goto unChanged;
|
||||
} else if (l == LONG_MIN) {
|
||||
TclInitBignumFromLong(&big, l);
|
||||
} else if (l == LLONG_MIN) {
|
||||
TclInitBignumFromWideInt(&big, l);
|
||||
goto tooLarge;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewLongObj(-l));
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -7514,24 +7532,8 @@ ExprAbsFunc(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (type == TCL_NUMBER_WIDE) {
|
||||
Tcl_WideInt w = *((const Tcl_WideInt *) ptr);
|
||||
|
||||
if (w >= (Tcl_WideInt)0) {
|
||||
goto unChanged;
|
||||
}
|
||||
if (w == LLONG_MIN) {
|
||||
TclInitBignumFromWideInt(&big, w);
|
||||
goto tooLarge;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (type == TCL_NUMBER_BIG) {
|
||||
if (mp_cmp_d((const mp_int *) ptr, 0) == MP_LT) {
|
||||
if (mp_isneg((const mp_int *) ptr)) {
|
||||
Tcl_GetBignumFromObj(NULL, objv[1], &big);
|
||||
tooLarge:
|
||||
mp_neg(&big, &big);
|
||||
|
||||
+14
-14
@@ -187,15 +187,15 @@ TclDumpMemoryInfo(
|
||||
"total mallocs %10u\n"
|
||||
"total frees %10u\n"
|
||||
"current packets allocated %10u\n"
|
||||
"current bytes allocated %10" TCL_LL_MODIFIER "u\n"
|
||||
"current bytes allocated %10" TCL_Z_MODIFIER "u\n"
|
||||
"maximum packets allocated %10u\n"
|
||||
"maximum bytes allocated %10" TCL_LL_MODIFIER "u\n",
|
||||
"maximum bytes allocated %10" TCL_Z_MODIFIER "u\n",
|
||||
total_mallocs,
|
||||
total_frees,
|
||||
current_malloc_packets,
|
||||
(Tcl_WideInt)current_bytes_malloced,
|
||||
current_bytes_malloced,
|
||||
maximum_malloc_packets,
|
||||
(Tcl_WideInt)maximum_bytes_malloced);
|
||||
maximum_bytes_malloced);
|
||||
if (flags == 0) {
|
||||
fprintf((FILE *)clientData, "%s", buf);
|
||||
} else {
|
||||
@@ -254,7 +254,7 @@ ValidateMemory(
|
||||
fprintf(stderr, "low guard failed at %p, %s %d\n",
|
||||
memHeaderP->body, file, line);
|
||||
fflush(stderr); /* In case name pointer is bad. */
|
||||
fprintf(stderr, "%" TCL_LL_MODIFIER "d bytes allocated at (%s %d)\n", (Tcl_WideInt) memHeaderP->length,
|
||||
fprintf(stderr, "%" TCL_Z_MODIFIER "u bytes allocated at (%s %d)\n", memHeaderP->length,
|
||||
memHeaderP->file, memHeaderP->line);
|
||||
Tcl_Panic("Memory validation failure");
|
||||
}
|
||||
@@ -276,8 +276,8 @@ ValidateMemory(
|
||||
fprintf(stderr, "high guard failed at %p, %s %d\n",
|
||||
memHeaderP->body, file, line);
|
||||
fflush(stderr); /* In case name pointer is bad. */
|
||||
fprintf(stderr, "%" TCL_LL_MODIFIER "d bytes allocated at (%s %d)\n",
|
||||
(Tcl_WideInt)memHeaderP->length, memHeaderP->file,
|
||||
fprintf(stderr, "%" TCL_Z_MODIFIER "u bytes allocated at (%s %d)\n",
|
||||
memHeaderP->length, memHeaderP->file,
|
||||
memHeaderP->line);
|
||||
Tcl_Panic("Memory validation failure");
|
||||
}
|
||||
@@ -359,9 +359,9 @@ Tcl_DumpActiveMemory(
|
||||
Tcl_MutexLock(ckallocMutexPtr);
|
||||
for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
|
||||
address = &memScanP->body[0];
|
||||
fprintf(fileP, "%p - %p %" TCL_LL_MODIFIER "d @ %s %d %s",
|
||||
fprintf(fileP, "%p - %p %" TCL_Z_MODIFIER "u @ %s %d %s",
|
||||
address, address + memScanP->length - 1,
|
||||
(Tcl_WideInt)memScanP->length, memScanP->file, memScanP->line,
|
||||
memScanP->length, memScanP->file, memScanP->line,
|
||||
(memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
|
||||
(void) fputc('\n', fileP);
|
||||
}
|
||||
@@ -611,8 +611,8 @@ Tcl_DbCkfree(
|
||||
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
|
||||
|
||||
if (alloc_tracing) {
|
||||
fprintf(stderr, "ckfree %p %" TCL_LL_MODIFIER "d %s %d\n",
|
||||
memp->body, (Tcl_WideInt) memp->length, file, line);
|
||||
fprintf(stderr, "ckfree %p %" TCL_Z_MODIFIER "u %s %d\n",
|
||||
memp->body, memp->length, file, line);
|
||||
}
|
||||
|
||||
if (validate_memory) {
|
||||
@@ -859,12 +859,12 @@ MemoryCmd(
|
||||
}
|
||||
if (strcmp(argv[1],"info") == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_LL_MODIFIER"d\n%-25s %10u\n%-25s %10" TCL_LL_MODIFIER "d\n",
|
||||
"%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER"u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER "u\n",
|
||||
"total mallocs", total_mallocs, "total frees", total_frees,
|
||||
"current packets allocated", current_malloc_packets,
|
||||
"current bytes allocated", (Tcl_WideInt)current_bytes_malloced,
|
||||
"current bytes allocated", current_bytes_malloced,
|
||||
"maximum packets allocated", maximum_malloc_packets,
|
||||
"maximum bytes allocated", (Tcl_WideInt)maximum_bytes_malloced));
|
||||
"maximum bytes allocated", maximum_bytes_malloced));
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1], "init") == 0) {
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ Tcl_BreakObjCmd(
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
/* ARGSUSED */
|
||||
int
|
||||
Tcl_CaseObjCmd(
|
||||
|
||||
+185
-90
@@ -64,8 +64,9 @@ typedef struct SortInfo {
|
||||
* SORTMODE_COMMAND. Pre-initialized to hold
|
||||
* base of command. */
|
||||
int *indexv; /* If the -index option was specified, this
|
||||
* holds the indexes contained in the list
|
||||
* supplied as an argument to that option.
|
||||
* holds an encoding of the indexes contained
|
||||
* in the list supplied as an argument to
|
||||
* that option.
|
||||
* NULL if no indexes supplied, and points to
|
||||
* singleIndex field when only one
|
||||
* supplied. */
|
||||
@@ -92,14 +93,6 @@ typedef struct SortInfo {
|
||||
#define SORTMODE_DICTIONARY 4
|
||||
#define SORTMODE_ASCII_NC 8
|
||||
|
||||
/*
|
||||
* Magic values for the index field of the SortInfo structure. Note that the
|
||||
* index "end-1" will be translated to SORTIDX_END-1, etc.
|
||||
*/
|
||||
|
||||
#define SORTIDX_NONE -1 /* Not indexed; use whole value. */
|
||||
#define SORTIDX_END -2 /* Indexed from end. */
|
||||
|
||||
/*
|
||||
* Forward declarations for procedures defined in this file:
|
||||
*/
|
||||
@@ -2160,7 +2153,7 @@ Tcl_JoinObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* The argument objects. */
|
||||
{
|
||||
int listLen;
|
||||
int length, listLen;
|
||||
Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs;
|
||||
|
||||
if ((objc < 2) || (objc > 3)) {
|
||||
@@ -2191,9 +2184,9 @@ Tcl_JoinObjCmd(
|
||||
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
|
||||
Tcl_IncrRefCount(joinObjPtr);
|
||||
|
||||
if (Tcl_GetCharLength(joinObjPtr) == 0) {
|
||||
TclStringCatObjv(interp, /* inPlace */ 0, listLen, elemPtrs,
|
||||
&resObjPtr);
|
||||
(void) Tcl_GetStringFromObj(joinObjPtr, &length);
|
||||
if (length == 0) {
|
||||
resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
|
||||
} else {
|
||||
int i;
|
||||
|
||||
@@ -2787,7 +2780,7 @@ Tcl_LreplaceObjCmd(
|
||||
* (to allow for replacing the last elem).
|
||||
*/
|
||||
|
||||
if ((first > listLen) && (listLen > 0)) {
|
||||
if ((first >= listLen) && (listLen > 0)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %s", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPLACE", "BADIDX",
|
||||
@@ -2938,8 +2931,9 @@ Tcl_LsearchObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument values. */
|
||||
{
|
||||
const char *bytes, *patternBytes;
|
||||
int i, match, index, result, listc, length, elemLen, bisect;
|
||||
int dataType, isIncreasing, lower, upper, offset;
|
||||
int i, match, index, result=TCL_OK, listc, length, elemLen, bisect;
|
||||
int allocatedIndexVector = 0;
|
||||
int dataType, isIncreasing, lower, upper, start, groupSize, groupOffset;
|
||||
Tcl_WideInt patWide, objWide;
|
||||
int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
|
||||
double patDouble, objDouble;
|
||||
@@ -2951,7 +2945,7 @@ Tcl_LsearchObjCmd(
|
||||
"-all", "-ascii", "-bisect", "-decreasing", "-dictionary",
|
||||
"-exact", "-glob", "-increasing", "-index",
|
||||
"-inline", "-integer", "-nocase", "-not",
|
||||
"-real", "-regexp", "-sorted", "-start",
|
||||
"-real", "-regexp", "-sorted", "-start", "-stride",
|
||||
"-subindices", NULL
|
||||
};
|
||||
enum options {
|
||||
@@ -2959,7 +2953,7 @@ Tcl_LsearchObjCmd(
|
||||
LSEARCH_DICTIONARY, LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING,
|
||||
LSEARCH_INDEX, LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOCASE,
|
||||
LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED,
|
||||
LSEARCH_START, LSEARCH_SUBINDICES
|
||||
LSEARCH_START, LSEARCH_STRIDE, LSEARCH_SUBINDICES
|
||||
};
|
||||
enum datatypes {
|
||||
ASCII, DICTIONARY, INTEGER, REAL
|
||||
@@ -2979,7 +2973,9 @@ Tcl_LsearchObjCmd(
|
||||
bisect = 0;
|
||||
listPtr = NULL;
|
||||
startPtr = NULL;
|
||||
offset = 0;
|
||||
groupSize = 1;
|
||||
groupOffset = 0;
|
||||
start = 0;
|
||||
noCase = 0;
|
||||
sortInfo.compareCmdPtr = NULL;
|
||||
sortInfo.isIncreasing = 1;
|
||||
@@ -2997,9 +2993,6 @@ Tcl_LsearchObjCmd(
|
||||
for (i = 1; i < objc-2; i++) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index)
|
||||
!= TCL_OK) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
@@ -3064,6 +3057,7 @@ Tcl_LsearchObjCmd(
|
||||
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
startPtr = NULL;
|
||||
}
|
||||
if (i > objc-4) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
@@ -3084,25 +3078,47 @@ Tcl_LsearchObjCmd(
|
||||
startPtr = Tcl_DuplicateObj(objv[i]);
|
||||
} else {
|
||||
startPtr = objv[i];
|
||||
Tcl_IncrRefCount(startPtr);
|
||||
}
|
||||
Tcl_IncrRefCount(startPtr);
|
||||
break;
|
||||
case LSEARCH_STRIDE: /* -stride */
|
||||
if (i > objc-4) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"\"-stride\" option must be "
|
||||
"followed by stride length", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (Tcl_GetIntFromObj(interp, objv[i+1], &groupSize) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (groupSize < 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"stride length must be at least 1", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT",
|
||||
"BADSTRIDE", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
case LSEARCH_INDEX: { /* -index */
|
||||
Tcl_Obj **indices;
|
||||
int j;
|
||||
|
||||
if (sortInfo.indexc > 1) {
|
||||
if (allocatedIndexVector) {
|
||||
TclStackFree(interp, sortInfo.indexv);
|
||||
allocatedIndexVector = 0;
|
||||
}
|
||||
if (i > objc-4) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"\"-index\" option must be followed by list index",
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3114,10 +3130,8 @@ Tcl_LsearchObjCmd(
|
||||
i++;
|
||||
if (TclListObjGetElements(interp, objv[i],
|
||||
&sortInfo.indexc, &indices) != TCL_OK) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
switch (sortInfo.indexc) {
|
||||
case 0:
|
||||
@@ -3129,6 +3143,8 @@ Tcl_LsearchObjCmd(
|
||||
default:
|
||||
sortInfo.indexv =
|
||||
TclStackAlloc(interp, sizeof(int) * sortInfo.indexc);
|
||||
allocatedIndexVector = 1; /* Cannot use indexc field, as it
|
||||
* might be decreased by 1 later. */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3138,13 +3154,26 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
if (TclGetIntForIndexM(interp, indices[j], SORTIDX_END,
|
||||
&sortInfo.indexv[j]) != TCL_OK) {
|
||||
int encoded = 0;
|
||||
if (TclIndexEncode(interp, indices[j], TCL_INDEX_BEFORE,
|
||||
TCL_INDEX_AFTER, &encoded) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if ((encoded == TCL_INDEX_BEFORE)
|
||||
|| (encoded == TCL_INDEX_AFTER)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"index \"%s\" cannot select an element "
|
||||
"from any list", Tcl_GetString(indices[j])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
|
||||
"OUTOFRANGE", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (-index option item number %d)", j));
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
sortInfo.indexv[j] = encoded;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3156,14 +3185,12 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
if (returnSubindices && sortInfo.indexc==0) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"-subindices cannot be used without -index option", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
|
||||
"BAD_OPTION_MIX", NULL);
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (bisect && (allMatches || negatedMatch)) {
|
||||
@@ -3171,7 +3198,8 @@ Tcl_LsearchObjCmd(
|
||||
"-bisect is not compatible with -all or -not", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
|
||||
"BAD_OPTION_MIX", NULL);
|
||||
return TCL_ERROR;
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (mode == REGEXP) {
|
||||
@@ -3197,9 +3225,6 @@ Tcl_LsearchObjCmd(
|
||||
}
|
||||
|
||||
if (regexp == NULL) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
@@ -3212,24 +3237,64 @@ Tcl_LsearchObjCmd(
|
||||
|
||||
result = TclListObjGetElements(interp, objv[objc - 2], &listc, &listv);
|
||||
if (result != TCL_OK) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for sanity when grouping elements of the overall list together
|
||||
* because of the -stride option. [TIP #351]
|
||||
*/
|
||||
|
||||
if (groupSize > 1) {
|
||||
if (listc % groupSize) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"list size must be a multiple of the stride length",
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH", "BADSTRIDE",
|
||||
NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (sortInfo.indexc > 0) {
|
||||
/*
|
||||
* Use the first value in the list supplied to -index as the
|
||||
* offset of the element within each group by which to sort.
|
||||
*/
|
||||
|
||||
groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1);
|
||||
if (groupOffset < 0 || groupOffset >= groupSize) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"when used with \"-stride\", the leading \"-index\""
|
||||
" value must be within the group", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
|
||||
"BADINDEX", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (sortInfo.indexc == 1) {
|
||||
sortInfo.indexc = 0;
|
||||
sortInfo.indexv = NULL;
|
||||
} else {
|
||||
sortInfo.indexc--;
|
||||
|
||||
for (i = 0; i < sortInfo.indexc; i++) {
|
||||
sortInfo.indexv[i] = sortInfo.indexv[i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the user-specified start offset.
|
||||
*/
|
||||
|
||||
if (startPtr) {
|
||||
result = TclGetIntForIndexM(interp, startPtr, listc-1, &offset);
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
result = TclGetIntForIndexM(interp, startPtr, listc-1, &start);
|
||||
if (result != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3237,16 +3302,21 @@ Tcl_LsearchObjCmd(
|
||||
* "did not match anything at all" result straight away. [Bug 1374778]
|
||||
*/
|
||||
|
||||
if (offset > listc-1) {
|
||||
if (sortInfo.indexc > 1) {
|
||||
TclStackFree(interp, sortInfo.indexv);
|
||||
}
|
||||
if (start > listc-1) {
|
||||
if (allMatches || inlineReturn) {
|
||||
Tcl_ResetResult(interp);
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
}
|
||||
return TCL_OK;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* If start points within a group, it points to the start of the group.
|
||||
*/
|
||||
|
||||
if (groupSize > 1) {
|
||||
start -= (start % groupSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3305,18 +3375,23 @@ Tcl_LsearchObjCmd(
|
||||
* sense in doing this when the match sense is inverted.
|
||||
*/
|
||||
|
||||
lower = offset - 1;
|
||||
/*
|
||||
* With -stride, lower, upper and i are kept as multiples of groupSize.
|
||||
*/
|
||||
|
||||
lower = start - groupSize;
|
||||
upper = listc;
|
||||
while (lower + 1 != upper && sortInfo.resultCode == TCL_OK) {
|
||||
while (lower + groupSize != upper && sortInfo.resultCode == TCL_OK) {
|
||||
i = (lower + upper)/2;
|
||||
i -= i % groupSize;
|
||||
if (sortInfo.indexc != 0) {
|
||||
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
|
||||
itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
|
||||
if (sortInfo.resultCode != TCL_OK) {
|
||||
result = sortInfo.resultCode;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
itemPtr = listv[i];
|
||||
itemPtr = listv[i+groupOffset];
|
||||
}
|
||||
switch ((enum datatypes) dataType) {
|
||||
case ASCII:
|
||||
@@ -3405,10 +3480,10 @@ Tcl_LsearchObjCmd(
|
||||
if (allMatches) {
|
||||
listPtr = Tcl_NewListObj(0, NULL);
|
||||
}
|
||||
for (i = offset; i < listc; i++) {
|
||||
for (i = start; i < listc; i += groupSize) {
|
||||
match = 0;
|
||||
if (sortInfo.indexc != 0) {
|
||||
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
|
||||
itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
|
||||
if (sortInfo.resultCode != TCL_OK) {
|
||||
if (listPtr != NULL) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
@@ -3417,7 +3492,7 @@ Tcl_LsearchObjCmd(
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
itemPtr = listv[i];
|
||||
itemPtr = listv[i+groupOffset];
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
@@ -3507,18 +3582,23 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
if (returnSubindices && (sortInfo.indexc != 0)) {
|
||||
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
|
||||
itemPtr = SelectObjFromSublist(listv[i+groupOffset],
|
||||
&sortInfo);
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
} else if (groupSize > 1) {
|
||||
Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0,
|
||||
groupSize, &listv[i]);
|
||||
} else {
|
||||
itemPtr = listv[i];
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
} else if (returnSubindices) {
|
||||
int j;
|
||||
|
||||
itemPtr = Tcl_NewIntObj(i);
|
||||
itemPtr = Tcl_NewIntObj(i+groupOffset);
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
Tcl_ListObjAppendElement(interp, itemPtr,
|
||||
Tcl_NewIntObj(sortInfo.indexv[j]));
|
||||
Tcl_ListObjAppendElement(interp, itemPtr, Tcl_NewIntObj(
|
||||
TclIndexDecode(sortInfo.indexv[j], listc)));
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
} else {
|
||||
@@ -3537,10 +3617,10 @@ Tcl_LsearchObjCmd(
|
||||
if (returnSubindices) {
|
||||
int j;
|
||||
|
||||
itemPtr = Tcl_NewIntObj(index);
|
||||
itemPtr = Tcl_NewIntObj(index+groupOffset);
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
Tcl_ListObjAppendElement(interp, itemPtr,
|
||||
Tcl_NewIntObj(sortInfo.indexv[j]));
|
||||
Tcl_ListObjAppendElement(interp, itemPtr, Tcl_NewIntObj(
|
||||
TclIndexDecode(sortInfo.indexv[j], listc)));
|
||||
}
|
||||
Tcl_SetObjResult(interp, itemPtr);
|
||||
} else {
|
||||
@@ -3554,7 +3634,14 @@ Tcl_LsearchObjCmd(
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewObj());
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, listv[index]);
|
||||
if (returnSubindices) {
|
||||
Tcl_SetObjResult(interp, SelectObjFromSublist(listv[i+groupOffset],
|
||||
&sortInfo));
|
||||
} else if (groupSize > 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(groupSize, &listv[index]));
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, listv[index]);
|
||||
}
|
||||
}
|
||||
result = TCL_OK;
|
||||
|
||||
@@ -3563,7 +3650,10 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
done:
|
||||
if (sortInfo.indexc > 1) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
if (allocatedIndexVector) {
|
||||
TclStackFree(interp, sortInfo.indexv);
|
||||
}
|
||||
return result;
|
||||
@@ -3757,7 +3847,7 @@ Tcl_LsortObjCmd(
|
||||
sortInfo.isIncreasing = 1;
|
||||
break;
|
||||
case LSORT_INDEX: {
|
||||
int indexc, dummy;
|
||||
int indexc;
|
||||
Tcl_Obj **indexv;
|
||||
|
||||
if (i == objc-2) {
|
||||
@@ -3783,8 +3873,20 @@ Tcl_LsortObjCmd(
|
||||
*/
|
||||
|
||||
for (j=0 ; j<indexc ; j++) {
|
||||
if (TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
|
||||
&dummy) != TCL_OK) {
|
||||
int encoded = 0;
|
||||
int result = TclIndexEncode(interp, indexv[j],
|
||||
TCL_INDEX_BEFORE, TCL_INDEX_AFTER, &encoded);
|
||||
|
||||
if ((result == TCL_OK) && ((encoded == TCL_INDEX_BEFORE)
|
||||
|| (encoded == TCL_INDEX_AFTER))) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"index \"%s\" cannot select an element "
|
||||
"from any list", Tcl_GetString(indexv[j])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
|
||||
"OUTOFRANGE", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (-index option item number %d)", j));
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
@@ -3864,8 +3966,8 @@ Tcl_LsortObjCmd(
|
||||
* might be decreased by 1 later. */
|
||||
}
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
|
||||
&sortInfo.indexv[j]);
|
||||
/* Prescreened values, no errors or out of range possible */
|
||||
TclIndexEncode(NULL, indexv[j], 0, 0, &sortInfo.indexv[j]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3936,10 +4038,7 @@ Tcl_LsortObjCmd(
|
||||
* offset of the element within each group by which to sort.
|
||||
*/
|
||||
|
||||
groupOffset = sortInfo.indexv[0];
|
||||
if (groupOffset <= SORTIDX_END) {
|
||||
groupOffset = (groupOffset - SORTIDX_END) + groupSize - 1;
|
||||
}
|
||||
groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1);
|
||||
if (groupOffset < 0 || groupOffset >= groupSize) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"when used with \"-stride\", the leading \"-index\""
|
||||
@@ -3958,6 +4057,9 @@ Tcl_LsortObjCmd(
|
||||
/*
|
||||
* Do not shrink the actual memory block used; that doesn't
|
||||
* work with TclStackAlloc-allocated memory. [Bug 2918962]
|
||||
*
|
||||
* TODO: Consider a pointer increment to replace this
|
||||
* array shift.
|
||||
*/
|
||||
|
||||
for (i = 0; i < sortInfo.indexc; i++) {
|
||||
@@ -4526,15 +4628,8 @@ SelectObjFromSublist(
|
||||
infoPtr->resultCode = TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
index = infoPtr->indexv[i];
|
||||
|
||||
/*
|
||||
* Adjust for end-based indexing.
|
||||
*/
|
||||
|
||||
if (index < SORTIDX_NONE) {
|
||||
index += listLen + 1;
|
||||
}
|
||||
index = TclIndexDecode(infoPtr->indexv[i], listLen - 1);
|
||||
|
||||
if (Tcl_ListObjIndex(infoPtr->interp, objPtr, index,
|
||||
¤tObj) != TCL_OK) {
|
||||
|
||||
+43
-67
@@ -1335,16 +1335,8 @@ StringFirstCmd(
|
||||
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &start)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
if (start >= size) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFind(objv[1],
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFirst(objv[1],
|
||||
objv[2], start)));
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1388,14 +1380,6 @@ StringLastCmd(
|
||||
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &last)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (last < 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
return TCL_OK;
|
||||
}
|
||||
if (last >= size) {
|
||||
last = size - 1;
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringLast(objv[1],
|
||||
objv[2], last)));
|
||||
@@ -1588,11 +1572,11 @@ StringIsCmd(
|
||||
string1 = TclGetStringFromObj(objPtr, &length1);
|
||||
result = length1 == 0;
|
||||
}
|
||||
} else if (((index == STR_IS_TRUE) &&
|
||||
objPtr->internalRep.longValue == 0)
|
||||
|| ((index == STR_IS_FALSE) &&
|
||||
objPtr->internalRep.longValue != 0)) {
|
||||
result = 0;
|
||||
} else if (index != STR_IS_BOOL) {
|
||||
TclGetBooleanFromObj(NULL, objPtr, &i);
|
||||
if ((index == STR_IS_TRUE) ^ i) {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STR_IS_CONTROL:
|
||||
@@ -1605,9 +1589,6 @@ StringIsCmd(
|
||||
/* TODO */
|
||||
if ((objPtr->typePtr == &tclDoubleType) ||
|
||||
(objPtr->typePtr == &tclIntType) ||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
(objPtr->typePtr == &tclWideIntType) ||
|
||||
#endif
|
||||
(objPtr->typePtr == &tclBignumType)) {
|
||||
break;
|
||||
}
|
||||
@@ -1642,9 +1623,6 @@ StringIsCmd(
|
||||
goto failedIntParse;
|
||||
case STR_IS_ENTIER:
|
||||
if ((objPtr->typePtr == &tclIntType) ||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
(objPtr->typePtr == &tclWideIntType) ||
|
||||
#endif
|
||||
(objPtr->typePtr == &tclBignumType)) {
|
||||
break;
|
||||
}
|
||||
@@ -2294,11 +2272,12 @@ StringReptCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (TCL_OK != TclStringRepeat(interp, objv[1], count, &resultPtr)) {
|
||||
return TCL_ERROR;
|
||||
resultPtr = TclStringRepeat(interp, objv[1], count, TCL_STRING_IN_PLACE);
|
||||
if (resultPtr) {
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
return TCL_OK;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2326,42 +2305,50 @@ StringRplcCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar *ustring;
|
||||
int first, last, length;
|
||||
int first, last, length, end;
|
||||
|
||||
if (objc < 4 || objc > 5) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
|
||||
length--;
|
||||
length = Tcl_GetCharLength(objv[1]);
|
||||
end = length - 1;
|
||||
|
||||
if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK ||
|
||||
TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK){
|
||||
if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK ||
|
||||
TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if ((last < first) || (last < 0) || (first > length)) {
|
||||
/*
|
||||
* The following test screens out most empty substrings as
|
||||
* candidates for replacement. When they are detected, no
|
||||
* replacement is done, and the result is the original string,
|
||||
*/
|
||||
if ((last < 0) || /* Range ends before start of string */
|
||||
(first > end) || /* Range begins after end of string */
|
||||
(last < first)) { /* Range begins after it starts */
|
||||
|
||||
/*
|
||||
* BUT!!! when (end < 0) -- an empty original string -- we can
|
||||
* have (first <= end < 0 <= last) and an empty string is permitted
|
||||
* to be replaced.
|
||||
*/
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
} else {
|
||||
Tcl_Obj *resultPtr;
|
||||
|
||||
ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
|
||||
length--;
|
||||
|
||||
if (first < 0) {
|
||||
first = 0;
|
||||
}
|
||||
if (last > end) {
|
||||
last = end;
|
||||
}
|
||||
|
||||
resultPtr = TclStringReplace(interp, objv[1], first,
|
||||
last + 1 - first, (objc == 5) ? objv[4] : NULL,
|
||||
TCL_STRING_IN_PLACE);
|
||||
|
||||
resultPtr = Tcl_NewUnicodeObj(ustring, first);
|
||||
if (objc == 5) {
|
||||
Tcl_AppendObjToObj(resultPtr, objv[4]);
|
||||
}
|
||||
if (last < length) {
|
||||
Tcl_AppendUnicodeToObj(resultPtr, ustring + last + 1,
|
||||
length - last);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -2397,7 +2384,7 @@ StringRevCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, TclStringObjReverse(objv[1]));
|
||||
Tcl_SetObjResult(interp, TclStringReverse(objv[1], TCL_STRING_IN_PLACE));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2846,7 +2833,6 @@ StringCatCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int code;
|
||||
Tcl_Obj *objResultPtr;
|
||||
|
||||
if (objc < 2) {
|
||||
@@ -2856,23 +2842,15 @@ StringCatCmd(
|
||||
*/
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objc == 2) {
|
||||
/*
|
||||
* Other trivial case, single arg, just return it.
|
||||
*/
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
code = TclStringCatObjv(interp, /* inPlace */ 1, objc-1, objv+1,
|
||||
&objResultPtr);
|
||||
objResultPtr = TclStringCat(interp, objc-1, objv+1, TCL_STRING_IN_PLACE);
|
||||
|
||||
if (code == TCL_OK) {
|
||||
if (objResultPtr) {
|
||||
Tcl_SetObjResult(interp, objResultPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
return code;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2893,7 +2871,6 @@ StringCatCmd(
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
StringBytesCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
@@ -3241,8 +3218,7 @@ StringTrimCmd(
|
||||
}
|
||||
string1 = TclGetStringFromObj(objv[1], &length1);
|
||||
|
||||
triml = TclTrimLeft(string1, length1, string2, length2);
|
||||
trimr = TclTrimRight(string1 + triml, length1 - triml, string2, length2);
|
||||
triml = TclTrim(string1, length1, string2, length2, &trimr);
|
||||
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj(string1 + triml, length1 - triml - trimr));
|
||||
@@ -4310,7 +4286,7 @@ TclNRTryObjCmd(
|
||||
}
|
||||
|
||||
info[0] = objv[i]; /* type */
|
||||
TclNewLongObj(info[1], code); /* returnCode */
|
||||
TclNewIntObj(info[1], code); /* returnCode */
|
||||
if (info[2] == NULL) { /* errorCodePrefix */
|
||||
TclNewObj(info[2]);
|
||||
}
|
||||
|
||||
+195
-270
@@ -28,56 +28,39 @@ static void CompileReturnInternal(CompileEnv *envPtr,
|
||||
static int IndexTailVarIfKnown(Tcl_Interp *interp,
|
||||
Tcl_Token *varTokenPtr, CompileEnv *envPtr);
|
||||
|
||||
#define INDEX_END (-2)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GetIndexFromToken --
|
||||
* TclGetIndexFromToken --
|
||||
*
|
||||
* Parse a token and get the encoded version of the index (as understood
|
||||
* by TEBC), assuming it is at all knowable at compile time. Only handles
|
||||
* indices that are integers or 'end' or 'end-integer'.
|
||||
* Parse a token to determine if an index value is known at
|
||||
* compile time.
|
||||
*
|
||||
* Returns:
|
||||
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets *index to the index value if successful.
|
||||
* When TCL_OK is returned, the encoded index value is written
|
||||
* to *index.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline int
|
||||
GetIndexFromToken(
|
||||
int
|
||||
TclGetIndexFromToken(
|
||||
Tcl_Token *tokenPtr,
|
||||
int *index)
|
||||
int before,
|
||||
int after,
|
||||
int *indexPtr)
|
||||
{
|
||||
Tcl_Obj *tmpObj = Tcl_NewObj();
|
||||
int result, idx;
|
||||
int result = TCL_ERROR;
|
||||
|
||||
if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
result = TclGetIntFromObj(NULL, tmpObj, &idx);
|
||||
if (result == TCL_OK) {
|
||||
if (idx < 0) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx);
|
||||
if (result == TCL_OK && idx > INDEX_END) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if (TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
|
||||
result = TclIndexEncode(NULL, tmpObj, before, after, indexPtr);
|
||||
}
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
|
||||
if (result == TCL_OK) {
|
||||
*index = idx;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -144,7 +127,7 @@ TclCompileGlobalCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: Consider what value can pass throug the
|
||||
/* TODO: Consider what value can pass through the
|
||||
* IndexTailVarIfKnown() screen. Full CompileWord()
|
||||
* likely does not apply here. Push known value instead. */
|
||||
CompileWord(envPtr, varTokenPtr, interp, i);
|
||||
@@ -1053,7 +1036,7 @@ TclCompileLassignCmd(
|
||||
*/
|
||||
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1104,14 +1087,14 @@ TclCompileLindexCmd(
|
||||
}
|
||||
|
||||
idxTokenPtr = TokenAfter(valTokenPtr);
|
||||
if (GetIndexFromToken(idxTokenPtr, &idx) == TCL_OK) {
|
||||
if (TclGetIndexFromToken(idxTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_BEFORE,
|
||||
&idx) == TCL_OK) {
|
||||
/*
|
||||
* All checks have been completed, and we have exactly one of these
|
||||
* constructs:
|
||||
* lindex <arbitraryValue> <posInt>
|
||||
* lindex <arbitraryValue> end-<posInt>
|
||||
* This is best compiled as a push of the arbitrary value followed by
|
||||
* an "immediate lindex" which is the most efficient variety.
|
||||
* The idxTokenPtr parsed as a valid index value and was
|
||||
* encoded as expected by INST_LIST_INDEX_IMM.
|
||||
*
|
||||
* NOTE: that we rely on indexing before a list producing the
|
||||
* same result as indexing after a list.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valTokenPtr, interp, 1);
|
||||
@@ -1258,7 +1241,7 @@ TclCompileListCmd(
|
||||
|
||||
if (concat && numWords == 2) {
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1332,21 +1315,25 @@ TclCompileLrangeCmd(
|
||||
}
|
||||
listTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
|
||||
&idx1) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* Parse the indices. Will only compile if both are constants and not an
|
||||
* _integer_ less than zero (since we reserve negative indices here for
|
||||
* end-relative indexing) or an end-based index greater than 'end' itself.
|
||||
* Token was an index value, and we treat all "first" indices
|
||||
* before the list same as the start of the list.
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
|
||||
&idx2) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* Token was an index value, and we treat all "last" indices
|
||||
* after the list same as the end of the list.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Issue instructions. It's not safe to skip doing the LIST_RANGE, as
|
||||
@@ -1396,21 +1383,30 @@ TclCompileLinsertCmd(
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx) != TCL_OK) {
|
||||
|
||||
/*
|
||||
* NOTE: This command treats all inserts at indices before the list
|
||||
* the same as inserts at the start of the list, and all inserts
|
||||
* after the list the same as inserts at the end of the list. We
|
||||
* make that transformation here so we can use the optimized bytecode
|
||||
* as much as possible.
|
||||
*/
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_END,
|
||||
&idx) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are four main cases. If there are no values to insert, this is
|
||||
* just a confirm-listiness check. If the index is '0', this is a prepend.
|
||||
* If the index is 'end' (== INDEX_END), this is an append. Otherwise,
|
||||
* If the index is 'end' (== TCL_INDEX_END), this is an append. Otherwise,
|
||||
* this is a splice (== split, insert values as list, concat-3).
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, listTokenPtr, interp, 1);
|
||||
if (parsePtr->numWords == 3) {
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -1420,13 +1416,25 @@ TclCompileLinsertCmd(
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST, i-3, envPtr);
|
||||
|
||||
if (idx == 0 /*start*/) {
|
||||
if (idx == TCL_INDEX_START) {
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
} else if (idx == INDEX_END /*end*/) {
|
||||
} else if (idx == TCL_INDEX_END) {
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
} else {
|
||||
if (idx < 0) {
|
||||
/*
|
||||
* Here we handle two ranges for idx. First when idx > 0, we
|
||||
* want the first half of the split to end at index idx-1 and
|
||||
* the second half to start at index idx.
|
||||
* Second when idx < TCL_INDEX_END, indicating "end-N" indexing,
|
||||
* we want the first half of the split to end at index end-N and
|
||||
* the second half to start at index end-N+1. We accomplish this
|
||||
* with a pre-adjustment of the end-N value.
|
||||
* The root of this is that the commands [lrange] and [linsert]
|
||||
* differ in their interpretation of the "end" index.
|
||||
*/
|
||||
|
||||
if (idx < TCL_INDEX_END) {
|
||||
idx++;
|
||||
}
|
||||
TclEmitInstInt4( INST_OVER, 1, envPtr);
|
||||
@@ -1434,7 +1442,7 @@ TclCompileLinsertCmd(
|
||||
TclEmitInt4( idx-1, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 3, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
}
|
||||
@@ -1464,250 +1472,167 @@ TclCompileLreplaceCmd(
|
||||
{
|
||||
Tcl_Token *tokenPtr, *listTokenPtr;
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
Tcl_Obj *tmpObj;
|
||||
int idx1, idx2, i, offset, offset2;
|
||||
int emptyPrefix=1, suffixStart = 0;
|
||||
|
||||
if (parsePtr->numWords < 4) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
listTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
|
||||
/*
|
||||
* Parse the indices. Will only compile if both are constants and not an
|
||||
* _integer_ less than zero (since we reserve negative indices here for
|
||||
* end-relative indexing) or an end-based index greater than 'end' itself.
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
|
||||
&idx1) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
|
||||
&idx2) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* idx1, idx2 are now in canonical form:
|
||||
* idx1, idx2 are the conventional encoded forms of the tokens parsed
|
||||
* as all forms of index values. Values of idx1 that come before the
|
||||
* list are treated the same as if they were the start of the list.
|
||||
* Values of idx2 that come after the list are treated the same as if
|
||||
* they were the end of the list.
|
||||
*/
|
||||
|
||||
if (idx1 == TCL_INDEX_AFTER) {
|
||||
/*
|
||||
* [lreplace] treats idx1 value end+1 differently from end+2, etc.
|
||||
* The operand encoding cannot distinguish them, so we must bail
|
||||
* out to direct evaluation.
|
||||
*/
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* General structure of the [lreplace] result is
|
||||
* prefix replacement suffix
|
||||
* In a few cases we can predict various parts will be empty and
|
||||
* take advantage.
|
||||
*
|
||||
* - integer: [0,len+1]
|
||||
* - end index: INDEX_END
|
||||
* - -ive offset: INDEX_END-[len-1,0]
|
||||
* - +ive offset: INDEX_END+1
|
||||
* The proper suffix begins with the greater of indices idx1 or
|
||||
* idx2 + 1. If we cannot tell at compile time which is greater,
|
||||
* we must defer to direct evaluation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compilation fails when one index is end-based but the other isn't.
|
||||
* Fixing this will require more bytecodes, but this is a workaround for
|
||||
* now. [Bug 47ac84309b]
|
||||
*/
|
||||
|
||||
if ((idx1 <= INDEX_END) != (idx2 <= INDEX_END)) {
|
||||
if (idx2 == TCL_INDEX_BEFORE) {
|
||||
suffixStart = idx1;
|
||||
} else if (idx2 == TCL_INDEX_END) {
|
||||
suffixStart = TCL_INDEX_AFTER;
|
||||
} else if (((idx2 < TCL_INDEX_END) && (idx1 <= TCL_INDEX_END))
|
||||
|| ((idx2 >= TCL_INDEX_START) && (idx1 >= TCL_INDEX_START))) {
|
||||
suffixStart = (idx1 > idx2 + 1) ? idx1 : idx2 + 1;
|
||||
} else {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (idx2 != INDEX_END && idx2 >= 0 && idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Work out what this [lreplace] is actually doing.
|
||||
*/
|
||||
|
||||
tmpObj = NULL;
|
||||
/* All paths start with computing/pushing the original value. */
|
||||
CompileWord(envPtr, listTokenPtr, interp, 1);
|
||||
if (parsePtr->numWords == 4) {
|
||||
if (idx1 == 0) {
|
||||
if (idx2 == INDEX_END) {
|
||||
goto dropAll;
|
||||
}
|
||||
idx1 = idx2 + 1;
|
||||
idx2 = INDEX_END;
|
||||
goto dropEnd;
|
||||
} else if (idx2 == INDEX_END) {
|
||||
idx2 = idx1 - 1;
|
||||
idx1 = 0;
|
||||
goto dropEnd;
|
||||
} else {
|
||||
if (idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
}
|
||||
if (idx1 > 0) {
|
||||
tmpObj = Tcl_NewIntObj(idx1);
|
||||
Tcl_IncrRefCount(tmpObj);
|
||||
}
|
||||
goto dropRange;
|
||||
}
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
for (i=4 ; i<parsePtr->numWords ; i++) {
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
/*
|
||||
* Push all the replacement values next so any errors raised in
|
||||
* creating them get raised first.
|
||||
*/
|
||||
if (parsePtr->numWords > 4) {
|
||||
/* Push the replacement arguments */
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
for (i=4 ; i<parsePtr->numWords ; i++) {
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
|
||||
/* Make a list of them... */
|
||||
TclEmitInstInt4( INST_LIST, i - 4, envPtr);
|
||||
|
||||
emptyPrefix = 0;
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST, i - 4, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
if (idx1 == 0) {
|
||||
if (idx2 == INDEX_END) {
|
||||
goto replaceAll;
|
||||
|
||||
/*
|
||||
* [lreplace] raises an error when idx1 points after the list, but
|
||||
* only when the list is not empty. This is maximum stupidity.
|
||||
*
|
||||
* TODO: TIP this nonsense away!
|
||||
*/
|
||||
if (idx1 >= TCL_INDEX_START) {
|
||||
if (emptyPrefix) {
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
} else {
|
||||
TclEmitInstInt4( INST_OVER, 1, envPtr);
|
||||
}
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
|
||||
|
||||
/* List is not empty */
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_NewIntObj(idx1),
|
||||
NULL), envPtr);
|
||||
TclEmitOpcode( INST_GT, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
|
||||
/* Idx1 >= list length ===> raise an error */
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %d", idx1), NULL), envPtr);
|
||||
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
|
||||
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
|
||||
envPtr->codeStart + offset + 1);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
|
||||
envPtr->codeStart + offset2 + 1);
|
||||
}
|
||||
|
||||
if ((idx1 == suffixStart) && (parsePtr->numWords == 4)) {
|
||||
/*
|
||||
* This is a "no-op". Example: [lreplace {a b c} 2 0]
|
||||
* We still do a list operation to get list-verification
|
||||
* and canonicalization side effects.
|
||||
*/
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (idx1 != TCL_INDEX_START) {
|
||||
/* Prefix may not be empty; generate bytecode to push it */
|
||||
if (emptyPrefix) {
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
} else {
|
||||
TclEmitInstInt4( INST_OVER, 1, envPtr);
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( idx1 - 1, envPtr);
|
||||
if (!emptyPrefix) {
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
}
|
||||
emptyPrefix = 0;
|
||||
}
|
||||
|
||||
if (!emptyPrefix) {
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
}
|
||||
|
||||
if (suffixStart == TCL_INDEX_AFTER) {
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
if (emptyPrefix) {
|
||||
PushStringLiteral(envPtr, "");
|
||||
}
|
||||
idx1 = idx2 + 1;
|
||||
idx2 = INDEX_END;
|
||||
goto replaceHead;
|
||||
} else if (idx2 == INDEX_END) {
|
||||
idx2 = idx1 - 1;
|
||||
idx1 = 0;
|
||||
goto replaceTail;
|
||||
} else {
|
||||
if (idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
/* Suffix may not be empty; generate bytecode to push it */
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, suffixStart, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
if (!emptyPrefix) {
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
}
|
||||
if (idx1 > 0) {
|
||||
tmpObj = Tcl_NewIntObj(idx1);
|
||||
Tcl_IncrRefCount(tmpObj);
|
||||
}
|
||||
goto replaceRange;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue instructions to perform the operations relating to configurations
|
||||
* that just drop. The only argument pushed on the stack is the list to
|
||||
* operate on.
|
||||
*/
|
||||
|
||||
dropAll: /* This just ensures the arg is a list. */
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
PushStringLiteral(envPtr, "");
|
||||
goto done;
|
||||
|
||||
dropEnd:
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
|
||||
TclEmitInt4( idx2, envPtr);
|
||||
goto done;
|
||||
|
||||
dropRange:
|
||||
if (tmpObj != NULL) {
|
||||
/*
|
||||
* Emit bytecode to check the list length.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
|
||||
TclEmitOpcode( INST_GE, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
|
||||
/*
|
||||
* Emit an error if we've been given an empty list.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %d", idx1), NULL), envPtr);
|
||||
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
|
||||
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
|
||||
envPtr->codeStart + offset + 1);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
|
||||
envPtr->codeStart + offset2 + 1);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
}
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( idx1 - 1, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Issue instructions to perform the operations relating to configurations
|
||||
* that do real replacement. All arguments are pushed and assembled into a
|
||||
* pair: the list of values to replace with, and the list to do the
|
||||
* surgery on.
|
||||
*/
|
||||
|
||||
replaceAll:
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
goto done;
|
||||
|
||||
replaceHead:
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
|
||||
TclEmitInt4( idx2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
replaceTail:
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
|
||||
TclEmitInt4( idx2, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
replaceRange:
|
||||
if (tmpObj != NULL) {
|
||||
/*
|
||||
* Emit bytecode to check the list length.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
|
||||
/*
|
||||
* Check the list length vs idx1.
|
||||
*/
|
||||
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
|
||||
TclEmitOpcode( INST_GE, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
|
||||
/*
|
||||
* Emit an error if we've been given an empty list.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %d", idx1), NULL), envPtr);
|
||||
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
|
||||
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
|
||||
envPtr->codeStart + offset + 1);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
|
||||
envPtr->codeStart + offset2 + 1);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
}
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( idx1 - 1, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 3, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Clean up the allocated memory.
|
||||
*/
|
||||
|
||||
done:
|
||||
if (tmpObj != NULL) {
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2933,7 +2858,7 @@ TclCompileVariableCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: Consider what value can pass throug the
|
||||
/* TODO: Consider what value can pass through the
|
||||
* IndexTailVarIfKnown() screen. Full CompileWord()
|
||||
* likely does not apply here. Push known value instead. */
|
||||
CompileWord(envPtr, varTokenPtr, interp, i);
|
||||
|
||||
+183
-137
@@ -107,58 +107,6 @@ const AuxDataType tclJumptableInfoType = {
|
||||
#define INVOKE(name) \
|
||||
TclEmitInvoke(envPtr,INST_##name)
|
||||
|
||||
#define INDEX_END (-2)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GetIndexFromToken --
|
||||
*
|
||||
* Parse a token and get the encoded version of the index (as understood
|
||||
* by TEBC), assuming it is at all knowable at compile time. Only handles
|
||||
* indices that are integers or 'end' or 'end-integer'.
|
||||
*
|
||||
* Returns:
|
||||
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets *index to the index value if successful.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline int
|
||||
GetIndexFromToken(
|
||||
Tcl_Token *tokenPtr,
|
||||
int *index)
|
||||
{
|
||||
Tcl_Obj *tmpObj = Tcl_NewObj();
|
||||
int result, idx;
|
||||
|
||||
if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
result = TclGetIntFromObj(NULL, tmpObj, &idx);
|
||||
if (result == TCL_OK) {
|
||||
if (idx < 0) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx);
|
||||
if (result == TCL_OK && idx > INDEX_END) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
|
||||
if (result == TCL_OK) {
|
||||
*index = idx;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -982,22 +930,48 @@ TclCompileStringRangeCmd(
|
||||
fromTokenPtr = TokenAfter(stringTokenPtr);
|
||||
toTokenPtr = TokenAfter(fromTokenPtr);
|
||||
|
||||
/* Every path must push the string argument */
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 1);
|
||||
|
||||
/*
|
||||
* Parse the two indices.
|
||||
*/
|
||||
|
||||
if (GetIndexFromToken(fromTokenPtr, &idx1) != TCL_OK) {
|
||||
if (TclGetIndexFromToken(fromTokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
|
||||
&idx1) != TCL_OK) {
|
||||
goto nonConstantIndices;
|
||||
}
|
||||
if (GetIndexFromToken(toTokenPtr, &idx2) != TCL_OK) {
|
||||
/*
|
||||
* Token parsed as an index expression. We treat all indices before
|
||||
* the string the same as the start of the string.
|
||||
*/
|
||||
|
||||
if (idx1 == TCL_INDEX_AFTER) {
|
||||
/* [string range $s end+1 $last] must be empty string */
|
||||
OP( POP);
|
||||
PUSH( "");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (TclGetIndexFromToken(toTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
|
||||
&idx2) != TCL_OK) {
|
||||
goto nonConstantIndices;
|
||||
}
|
||||
/*
|
||||
* Token parsed as an index expression. We treat all indices after
|
||||
* the string the same as the end of the string.
|
||||
*/
|
||||
if (idx2 == TCL_INDEX_BEFORE) {
|
||||
/* [string range $s $first -1] must be empty string */
|
||||
OP( POP);
|
||||
PUSH( "");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push the operand onto the stack and then the substring operation.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 1);
|
||||
OP44( STR_RANGE_IMM, idx1, idx2);
|
||||
return TCL_OK;
|
||||
|
||||
@@ -1006,7 +980,6 @@ TclCompileStringRangeCmd(
|
||||
*/
|
||||
|
||||
nonConstantIndices:
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 1);
|
||||
CompileWord(envPtr, fromTokenPtr, interp, 2);
|
||||
CompileWord(envPtr, toTokenPtr, interp, 3);
|
||||
OP( STR_RANGE);
|
||||
@@ -1022,124 +995,197 @@ TclCompileStringReplaceCmd(
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds the resulting instructions. */
|
||||
{
|
||||
Tcl_Token *tokenPtr, *valueTokenPtr, *replacementTokenPtr = NULL;
|
||||
Tcl_Token *tokenPtr, *valueTokenPtr;
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
int idx1, idx2;
|
||||
int first, last;
|
||||
|
||||
if (parsePtr->numWords < 4 || parsePtr->numWords > 5) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* Bytecode to compute/push string argument being replaced */
|
||||
valueTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
if (parsePtr->numWords == 5) {
|
||||
tokenPtr = TokenAfter(valueTokenPtr);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
replacementTokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
|
||||
/*
|
||||
* Parse the indices. Will only compile special cases if both are
|
||||
* constants and not an _integer_ less than zero (since we reserve
|
||||
* negative indices here for end-relative indexing) or an end-based index
|
||||
* greater than 'end' itself.
|
||||
* Check for first index known and useful at compile time.
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(valueTokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
|
||||
goto genericReplace;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_AFTER,
|
||||
&first) != TCL_OK) {
|
||||
goto genericReplace;
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle these replacements specially: first character (where
|
||||
* idx1=idx2=0) and last character (where idx1=idx2=INDEX_END). Anything
|
||||
* else and the semantics get rather screwy.
|
||||
* Check for last index known and useful at compile time.
|
||||
*/
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_AFTER,
|
||||
&last) != TCL_OK) {
|
||||
goto genericReplace;
|
||||
}
|
||||
|
||||
/*
|
||||
* [string replace] is an odd bird. For many arguments it is
|
||||
* a conventional substring replacer. However it also goes out
|
||||
* of its way to become a no-op for many cases where it would be
|
||||
* replacing an empty substring. Precisely, it is a no-op when
|
||||
*
|
||||
* (last < first) OR
|
||||
* (last < 0) OR
|
||||
* (end < first)
|
||||
*
|
||||
* For some compile-time values we can detect these cases, and
|
||||
* compile direct to bytecode implementing the no-op.
|
||||
*/
|
||||
|
||||
if (idx1 == 0 && idx2 == 0) {
|
||||
int notEq, end;
|
||||
if ((last == TCL_INDEX_BEFORE) /* Know (last < 0) */
|
||||
|| (first == TCL_INDEX_AFTER) /* Know (first > end) */
|
||||
|
||||
/*
|
||||
* Just working with the first character.
|
||||
* Tricky to determine when runtime (last < first) can be
|
||||
* certainly known based on the encoded values. Consider the
|
||||
* cases...
|
||||
*
|
||||
* (first <= TCL_INDEX_END) &&
|
||||
* (last == TCL_INDEX_AFTER) => cannot tell REJECT
|
||||
* (last <= TCL_INDEX END) && (last < first) => ACCEPT
|
||||
* else => cannot tell REJECT
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
if (replacementTokenPtr == NULL) {
|
||||
/* Drop first */
|
||||
OP44( STR_RANGE_IMM, 1, INDEX_END);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Replace first */
|
||||
CompileWord(envPtr, replacementTokenPtr, interp, 4);
|
||||
OP4( OVER, 1);
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
JUMP1( JUMP_FALSE, notEq);
|
||||
OP( POP);
|
||||
JUMP1( JUMP, end);
|
||||
FIXJUMP1(notEq);
|
||||
TclAdjustStackDepth(1, envPtr);
|
||||
OP4( REVERSE, 2);
|
||||
OP44( STR_RANGE_IMM, 1, INDEX_END);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
FIXJUMP1(end);
|
||||
return TCL_OK;
|
||||
|
||||
} else if (idx1 == INDEX_END && idx2 == INDEX_END) {
|
||||
int notEq, end;
|
||||
|
||||
|| ((first <= TCL_INDEX_END) && (last <= TCL_INDEX_END)
|
||||
&& (last < first)) /* Know (last < first) */
|
||||
/*
|
||||
* Just working with the last character.
|
||||
* (first == TCL_INDEX_BEFORE) &&
|
||||
* (last == TCL_INDEX_AFTER) => (first < last) REJECT
|
||||
* (last <= TCL_INDEX_END) => cannot tell REJECT
|
||||
* else => (first < last) REJECT
|
||||
*
|
||||
* else [[first >= TCL_INDEX_START]] &&
|
||||
* (last == TCL_INDEX_AFTER) => cannot tell REJECT
|
||||
* (last <= TCL_INDEX_END) => cannot tell REJECT
|
||||
* else [[last >= TCL_INDEX START]] && (last < first) => ACCEPT
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
if (replacementTokenPtr == NULL) {
|
||||
/* Drop last */
|
||||
OP44( STR_RANGE_IMM, 0, INDEX_END-1);
|
||||
return TCL_OK;
|
||||
|| ((first >= TCL_INDEX_START) && (last >= TCL_INDEX_START)
|
||||
&& (last < first))) { /* Know (last < first) */
|
||||
if (parsePtr->numWords == 5) {
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
OP( POP); /* Pop newString */
|
||||
}
|
||||
/* Replace last */
|
||||
CompileWord(envPtr, replacementTokenPtr, interp, 4);
|
||||
OP4( OVER, 1);
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
JUMP1( JUMP_FALSE, notEq);
|
||||
OP( POP);
|
||||
JUMP1( JUMP, end);
|
||||
FIXJUMP1(notEq);
|
||||
TclAdjustStackDepth(1, envPtr);
|
||||
OP4( REVERSE, 2);
|
||||
OP44( STR_RANGE_IMM, 0, INDEX_END-1);
|
||||
OP4( REVERSE, 2);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
FIXJUMP1(end);
|
||||
/* Original string argument now on TOS as result */
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (parsePtr->numWords == 5) {
|
||||
/*
|
||||
* When we have a string replacement, we have to take care about
|
||||
* not replacing empty substrings that [string replace] promises
|
||||
* not to replace
|
||||
*
|
||||
* The remaining index values might be suitable for conventional
|
||||
* string replacement, but only if they cannot possibly meet the
|
||||
* conditions described above at runtime. If there's a chance they
|
||||
* might, we would have to emit bytecode to check and at that point
|
||||
* we're paying more in bytecode execution time than would make
|
||||
* things worthwhile. Trouble is we are very limited in
|
||||
* how much we can detect that at compile time. After decoding,
|
||||
* we need, first:
|
||||
*
|
||||
* (first <= end)
|
||||
*
|
||||
* The encoded indices (first <= TCL_INDEX END) and
|
||||
* (first == TCL_INDEX_BEFORE) always meets this condition, but
|
||||
* any other encoded first index has some list for which it fails.
|
||||
*
|
||||
* We also need, second:
|
||||
*
|
||||
* (last >= 0)
|
||||
*
|
||||
* The encoded indices (last >= TCL_INDEX_START) and
|
||||
* (last == TCL_INDEX_AFTER) always meet this condition but any
|
||||
* other encoded last index has some list for which it fails.
|
||||
*
|
||||
* Finally we need, third:
|
||||
*
|
||||
* (first <= last)
|
||||
*
|
||||
* Considered in combination with the constraints we already have,
|
||||
* we see that we can proceed when (first == TCL_INDEX_BEFORE)
|
||||
* or (last == TCL_INDEX_AFTER). These also permit simplification
|
||||
* of the prefix|replace|suffix construction. The other constraints,
|
||||
* though, interfere with getting a guarantee that first <= last.
|
||||
*/
|
||||
|
||||
if ((first == TCL_INDEX_BEFORE) && (last >= TCL_INDEX_START)) {
|
||||
/* empty prefix */
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
OP4( REVERSE, 2);
|
||||
if (last == TCL_INDEX_AFTER) {
|
||||
OP( POP); /* Pop original */
|
||||
} else {
|
||||
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if ((last == TCL_INDEX_AFTER) && (first <= TCL_INDEX_END)) {
|
||||
OP44( STR_RANGE_IMM, 0, first-1);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* FLOW THROUGH TO genericReplace */
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Need to process indices at runtime. This could be because the
|
||||
* indices are not constants, or because we need to resolve them to
|
||||
* absolute indices to work out if a replacement is going to happen.
|
||||
* In any case, to runtime it is.
|
||||
/*
|
||||
* When we have no replacement string to worry about, we may
|
||||
* have more luck, because the forbidden empty string replacements
|
||||
* are harmless when they are replaced by another empty string.
|
||||
*/
|
||||
|
||||
if ((first == TCL_INDEX_BEFORE) || (first == TCL_INDEX_START)) {
|
||||
/* empty prefix - build suffix only */
|
||||
|
||||
if ((last == TCL_INDEX_END) || (last == TCL_INDEX_AFTER)) {
|
||||
/* empty suffix too => empty result */
|
||||
OP( POP); /* Pop original */
|
||||
PUSH ( "");
|
||||
return TCL_OK;
|
||||
}
|
||||
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
|
||||
return TCL_OK;
|
||||
} else {
|
||||
if ((last == TCL_INDEX_END) || (last == TCL_INDEX_AFTER)) {
|
||||
/* empty suffix - build prefix only */
|
||||
OP44( STR_RANGE_IMM, 0, first-1);
|
||||
return TCL_OK;
|
||||
}
|
||||
OP( DUP);
|
||||
OP44( STR_RANGE_IMM, 0, first-1);
|
||||
OP4( REVERSE, 2);
|
||||
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
genericReplace:
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
tokenPtr = TokenAfter(valueTokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 2);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 3);
|
||||
if (replacementTokenPtr != NULL) {
|
||||
CompileWord(envPtr, replacementTokenPtr, interp, 4);
|
||||
if (parsePtr->numWords == 5) {
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
} else {
|
||||
PUSH( "");
|
||||
}
|
||||
OP( STR_REPLACE);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -425,11 +425,11 @@ typedef struct ByteCode {
|
||||
* compiled. If the code is executed if a
|
||||
* different namespace, it must be
|
||||
* recompiled. */
|
||||
size_t nsEpoch; /* Value of nsPtr->resolverEpoch when this
|
||||
unsigned int nsEpoch; /* Value of nsPtr->resolverEpoch when this
|
||||
* ByteCode was compiled. Used to invalidate
|
||||
* code when new namespace resolution rules
|
||||
* are put into effect. */
|
||||
int refCount; /* Reference count: set 1 when created plus 1
|
||||
unsigned int refCount; /* Reference count: set 1 when created plus 1
|
||||
* for each execution of the code currently
|
||||
* active. This structure can be freed when
|
||||
* refCount becomes zero. */
|
||||
@@ -1120,6 +1120,8 @@ MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr,
|
||||
int distThreshold);
|
||||
MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr);
|
||||
MODULE_SCOPE int TclGetIndexFromToken(Tcl_Token *tokenPtr,
|
||||
int before, int after, int *indexPtr);
|
||||
MODULE_SCOPE ByteCode * TclInitByteCode(CompileEnv *envPtr);
|
||||
MODULE_SCOPE ByteCode * TclInitByteCodeObj(Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr, CompileEnv *envPtr);
|
||||
|
||||
+117
-112
@@ -53,7 +53,7 @@ EXTERN int Tcl_PkgProvideEx(Tcl_Interp *interp,
|
||||
const char *name, const char *version,
|
||||
const void *clientData);
|
||||
/* 1 */
|
||||
EXTERN CONST84_RETURN char * Tcl_PkgRequireEx(Tcl_Interp *interp,
|
||||
EXTERN const char * Tcl_PkgRequireEx(Tcl_Interp *interp,
|
||||
const char *name, const char *version,
|
||||
int exact, void *clientDataPtr);
|
||||
/* 2 */
|
||||
@@ -159,8 +159,7 @@ EXTERN int Tcl_GetDoubleFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, double *doublePtr);
|
||||
/* 36 */
|
||||
EXTERN int Tcl_GetIndexFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr,
|
||||
CONST84 char *const *tablePtr,
|
||||
Tcl_Obj *objPtr, const char *const *tablePtr,
|
||||
const char *msg, int flags, int *indexPtr);
|
||||
/* 37 */
|
||||
EXTERN int Tcl_GetInt(Tcl_Interp *interp, const char *src,
|
||||
@@ -263,7 +262,8 @@ EXTERN int Tcl_AsyncReady(void);
|
||||
/* 76 */
|
||||
EXTERN void Tcl_BackgroundError(Tcl_Interp *interp);
|
||||
/* 77 */
|
||||
EXTERN char Tcl_Backslash(const char *src, int *readPtr);
|
||||
TCL_DEPRECATED("Use Tcl_UtfBackslash")
|
||||
char Tcl_Backslash(const char *src, int *readPtr);
|
||||
/* 78 */
|
||||
EXTERN int Tcl_BadChannelOption(Tcl_Interp *interp,
|
||||
const char *optionName,
|
||||
@@ -280,7 +280,7 @@ EXTERN int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan);
|
||||
/* 82 */
|
||||
EXTERN int Tcl_CommandComplete(const char *cmd);
|
||||
/* 83 */
|
||||
EXTERN char * Tcl_Concat(int argc, CONST84 char *const *argv);
|
||||
EXTERN char * Tcl_Concat(int argc, const char *const *argv);
|
||||
/* 84 */
|
||||
EXTERN int Tcl_ConvertElement(const char *src, char *dst,
|
||||
int flags);
|
||||
@@ -291,7 +291,7 @@ EXTERN int Tcl_ConvertCountedElement(const char *src,
|
||||
EXTERN int Tcl_CreateAlias(Tcl_Interp *slave,
|
||||
const char *slaveCmd, Tcl_Interp *target,
|
||||
const char *targetCmd, int argc,
|
||||
CONST84 char *const *argv);
|
||||
const char *const *argv);
|
||||
/* 87 */
|
||||
EXTERN int Tcl_CreateAliasObj(Tcl_Interp *slave,
|
||||
const char *slaveCmd, Tcl_Interp *target,
|
||||
@@ -322,7 +322,8 @@ EXTERN void Tcl_CreateExitHandler(Tcl_ExitProc *proc,
|
||||
/* 94 */
|
||||
EXTERN Tcl_Interp * Tcl_CreateInterp(void);
|
||||
/* 95 */
|
||||
EXTERN void Tcl_CreateMathFunc(Tcl_Interp *interp,
|
||||
TCL_DEPRECATED("")
|
||||
void Tcl_CreateMathFunc(Tcl_Interp *interp,
|
||||
const char *name, int numArgs,
|
||||
Tcl_ValueType *argTypes, Tcl_MathProc *proc,
|
||||
ClientData clientData);
|
||||
@@ -412,9 +413,9 @@ EXTERN void Tcl_DStringStartSublist(Tcl_DString *dsPtr);
|
||||
/* 126 */
|
||||
EXTERN int Tcl_Eof(Tcl_Channel chan);
|
||||
/* 127 */
|
||||
EXTERN CONST84_RETURN char * Tcl_ErrnoId(void);
|
||||
EXTERN const char * Tcl_ErrnoId(void);
|
||||
/* 128 */
|
||||
EXTERN CONST84_RETURN char * Tcl_ErrnoMsg(int err);
|
||||
EXTERN const char * Tcl_ErrnoMsg(int err);
|
||||
/* 129 */
|
||||
EXTERN int Tcl_Eval(Tcl_Interp *interp, const char *script);
|
||||
/* 130 */
|
||||
@@ -469,13 +470,13 @@ EXTERN void Tcl_FreeResult(Tcl_Interp *interp);
|
||||
EXTERN int Tcl_GetAlias(Tcl_Interp *interp,
|
||||
const char *slaveCmd,
|
||||
Tcl_Interp **targetInterpPtr,
|
||||
CONST84 char **targetCmdPtr, int *argcPtr,
|
||||
CONST84 char ***argvPtr);
|
||||
const char **targetCmdPtr, int *argcPtr,
|
||||
const char ***argvPtr);
|
||||
/* 149 */
|
||||
EXTERN int Tcl_GetAliasObj(Tcl_Interp *interp,
|
||||
const char *slaveCmd,
|
||||
Tcl_Interp **targetInterpPtr,
|
||||
CONST84 char **targetCmdPtr, int *objcPtr,
|
||||
const char **targetCmdPtr, int *objcPtr,
|
||||
Tcl_Obj ***objv);
|
||||
/* 150 */
|
||||
EXTERN ClientData Tcl_GetAssocData(Tcl_Interp *interp,
|
||||
@@ -494,7 +495,7 @@ EXTERN ClientData Tcl_GetChannelInstanceData(Tcl_Channel chan);
|
||||
/* 155 */
|
||||
EXTERN int Tcl_GetChannelMode(Tcl_Channel chan);
|
||||
/* 156 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetChannelName(Tcl_Channel chan);
|
||||
EXTERN const char * Tcl_GetChannelName(Tcl_Channel chan);
|
||||
/* 157 */
|
||||
EXTERN int Tcl_GetChannelOption(Tcl_Interp *interp,
|
||||
Tcl_Channel chan, const char *optionName,
|
||||
@@ -505,12 +506,12 @@ EXTERN CONST86 Tcl_ChannelType * Tcl_GetChannelType(Tcl_Channel chan);
|
||||
EXTERN int Tcl_GetCommandInfo(Tcl_Interp *interp,
|
||||
const char *cmdName, Tcl_CmdInfo *infoPtr);
|
||||
/* 160 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetCommandName(Tcl_Interp *interp,
|
||||
EXTERN const char * Tcl_GetCommandName(Tcl_Interp *interp,
|
||||
Tcl_Command command);
|
||||
/* 161 */
|
||||
EXTERN int Tcl_GetErrno(void);
|
||||
/* 162 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetHostName(void);
|
||||
EXTERN const char * Tcl_GetHostName(void);
|
||||
/* 163 */
|
||||
EXTERN int Tcl_GetInterpPath(Tcl_Interp *askInterp,
|
||||
Tcl_Interp *slaveInterp);
|
||||
@@ -546,14 +547,13 @@ EXTERN Tcl_Interp * Tcl_GetSlave(Tcl_Interp *interp,
|
||||
/* 173 */
|
||||
EXTERN Tcl_Channel Tcl_GetStdChannel(int type);
|
||||
/* 174 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetStringResult(Tcl_Interp *interp);
|
||||
EXTERN const char * Tcl_GetStringResult(Tcl_Interp *interp);
|
||||
/* 175 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetVar(Tcl_Interp *interp,
|
||||
const char *varName, int flags);
|
||||
/* 176 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetVar2(Tcl_Interp *interp,
|
||||
const char *part1, const char *part2,
|
||||
EXTERN const char * Tcl_GetVar(Tcl_Interp *interp, const char *varName,
|
||||
int flags);
|
||||
/* 176 */
|
||||
EXTERN const char * Tcl_GetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *part2, int flags);
|
||||
/* 177 */
|
||||
EXTERN int Tcl_GlobalEval(Tcl_Interp *interp,
|
||||
const char *command);
|
||||
@@ -578,7 +578,7 @@ EXTERN int Tcl_InterpDeleted(Tcl_Interp *interp);
|
||||
/* 185 */
|
||||
EXTERN int Tcl_IsSafe(Tcl_Interp *interp);
|
||||
/* 186 */
|
||||
EXTERN char * Tcl_JoinPath(int argc, CONST84 char *const *argv,
|
||||
EXTERN char * Tcl_JoinPath(int argc, const char *const *argv,
|
||||
Tcl_DString *resultPtr);
|
||||
/* 187 */
|
||||
EXTERN int Tcl_LinkVar(Tcl_Interp *interp, const char *varName,
|
||||
@@ -591,7 +591,7 @@ EXTERN int Tcl_MakeSafe(Tcl_Interp *interp);
|
||||
/* 191 */
|
||||
EXTERN Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket);
|
||||
/* 192 */
|
||||
EXTERN char * Tcl_Merge(int argc, CONST84 char *const *argv);
|
||||
EXTERN char * Tcl_Merge(int argc, const char *const *argv);
|
||||
/* 193 */
|
||||
EXTERN Tcl_HashEntry * Tcl_NextHashEntry(Tcl_HashSearch *searchPtr);
|
||||
/* 194 */
|
||||
@@ -605,7 +605,7 @@ EXTERN Tcl_Obj * Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
int flags);
|
||||
/* 197 */
|
||||
EXTERN Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc,
|
||||
CONST84 char **argv, int flags);
|
||||
const char **argv, int flags);
|
||||
/* 198 */
|
||||
EXTERN Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp,
|
||||
const char *fileName, const char *modeString,
|
||||
@@ -627,7 +627,7 @@ EXTERN void Tcl_PrintDouble(Tcl_Interp *interp, double value,
|
||||
/* 203 */
|
||||
EXTERN int Tcl_PutEnv(const char *assignment);
|
||||
/* 204 */
|
||||
EXTERN CONST84_RETURN char * Tcl_PosixError(Tcl_Interp *interp);
|
||||
EXTERN const char * Tcl_PosixError(Tcl_Interp *interp);
|
||||
/* 205 */
|
||||
EXTERN void Tcl_QueueEvent(Tcl_Event *evPtr,
|
||||
Tcl_QueuePosition position);
|
||||
@@ -657,8 +657,7 @@ EXTERN int Tcl_RegExpMatch(Tcl_Interp *interp, const char *text,
|
||||
const char *pattern);
|
||||
/* 215 */
|
||||
EXTERN void Tcl_RegExpRange(Tcl_RegExp regexp, int index,
|
||||
CONST84 char **startPtr,
|
||||
CONST84 char **endPtr);
|
||||
const char **startPtr, const char **endPtr);
|
||||
/* 216 */
|
||||
EXTERN void Tcl_Release(ClientData clientData);
|
||||
/* 217 */
|
||||
@@ -714,26 +713,25 @@ EXTERN void Tcl_SetObjResult(Tcl_Interp *interp,
|
||||
/* 236 */
|
||||
EXTERN void Tcl_SetStdChannel(Tcl_Channel channel, int type);
|
||||
/* 237 */
|
||||
EXTERN CONST84_RETURN char * Tcl_SetVar(Tcl_Interp *interp,
|
||||
const char *varName, const char *newValue,
|
||||
int flags);
|
||||
/* 238 */
|
||||
EXTERN CONST84_RETURN char * Tcl_SetVar2(Tcl_Interp *interp,
|
||||
const char *part1, const char *part2,
|
||||
EXTERN const char * Tcl_SetVar(Tcl_Interp *interp, const char *varName,
|
||||
const char *newValue, int flags);
|
||||
/* 238 */
|
||||
EXTERN const char * Tcl_SetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *part2, const char *newValue,
|
||||
int flags);
|
||||
/* 239 */
|
||||
EXTERN CONST84_RETURN char * Tcl_SignalId(int sig);
|
||||
EXTERN const char * Tcl_SignalId(int sig);
|
||||
/* 240 */
|
||||
EXTERN CONST84_RETURN char * Tcl_SignalMsg(int sig);
|
||||
EXTERN const char * Tcl_SignalMsg(int sig);
|
||||
/* 241 */
|
||||
EXTERN void Tcl_SourceRCFile(Tcl_Interp *interp);
|
||||
/* 242 */
|
||||
EXTERN int Tcl_SplitList(Tcl_Interp *interp,
|
||||
const char *listStr, int *argcPtr,
|
||||
CONST84 char ***argvPtr);
|
||||
const char ***argvPtr);
|
||||
/* 243 */
|
||||
EXTERN void Tcl_SplitPath(const char *path, int *argcPtr,
|
||||
CONST84 char ***argvPtr);
|
||||
const char ***argvPtr);
|
||||
/* 244 */
|
||||
EXTERN void Tcl_StaticPackage(Tcl_Interp *interp,
|
||||
const char *pkgName,
|
||||
@@ -824,23 +822,21 @@ void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr,
|
||||
/* 269 */
|
||||
EXTERN char * Tcl_HashStats(Tcl_HashTable *tablePtr);
|
||||
/* 270 */
|
||||
EXTERN CONST84_RETURN char * Tcl_ParseVar(Tcl_Interp *interp,
|
||||
const char *start, CONST84 char **termPtr);
|
||||
EXTERN const char * Tcl_ParseVar(Tcl_Interp *interp, const char *start,
|
||||
const char **termPtr);
|
||||
/* 271 */
|
||||
EXTERN CONST84_RETURN char * Tcl_PkgPresent(Tcl_Interp *interp,
|
||||
const char *name, const char *version,
|
||||
int exact);
|
||||
EXTERN const char * Tcl_PkgPresent(Tcl_Interp *interp, const char *name,
|
||||
const char *version, int exact);
|
||||
/* 272 */
|
||||
EXTERN CONST84_RETURN char * Tcl_PkgPresentEx(Tcl_Interp *interp,
|
||||
EXTERN const char * Tcl_PkgPresentEx(Tcl_Interp *interp,
|
||||
const char *name, const char *version,
|
||||
int exact, void *clientDataPtr);
|
||||
/* 273 */
|
||||
EXTERN int Tcl_PkgProvide(Tcl_Interp *interp, const char *name,
|
||||
const char *version);
|
||||
/* 274 */
|
||||
EXTERN CONST84_RETURN char * Tcl_PkgRequire(Tcl_Interp *interp,
|
||||
const char *name, const char *version,
|
||||
int exact);
|
||||
EXTERN const char * Tcl_PkgRequire(Tcl_Interp *interp, const char *name,
|
||||
const char *version, int exact);
|
||||
/* 275 */
|
||||
TCL_DEPRECATED("see TIP #422")
|
||||
void Tcl_SetErrorCodeVA(Tcl_Interp *interp,
|
||||
@@ -917,7 +913,7 @@ EXTERN Tcl_ThreadId Tcl_GetCurrentThread(void);
|
||||
/* 301 */
|
||||
EXTERN Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, const char *name);
|
||||
/* 302 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetEncodingName(Tcl_Encoding encoding);
|
||||
EXTERN const char * Tcl_GetEncodingName(Tcl_Encoding encoding);
|
||||
/* 303 */
|
||||
EXTERN void Tcl_GetEncodingNames(Tcl_Interp *interp);
|
||||
/* 304 */
|
||||
@@ -976,20 +972,20 @@ EXTERN Tcl_UniChar Tcl_UniCharToUpper(int ch);
|
||||
/* 324 */
|
||||
EXTERN int Tcl_UniCharToUtf(int ch, char *buf);
|
||||
/* 325 */
|
||||
EXTERN CONST84_RETURN char * Tcl_UtfAtIndex(const char *src, int index);
|
||||
EXTERN const char * Tcl_UtfAtIndex(const char *src, int index);
|
||||
/* 326 */
|
||||
EXTERN int Tcl_UtfCharComplete(const char *src, int length);
|
||||
/* 327 */
|
||||
EXTERN int Tcl_UtfBackslash(const char *src, int *readPtr,
|
||||
char *dst);
|
||||
/* 328 */
|
||||
EXTERN CONST84_RETURN char * Tcl_UtfFindFirst(const char *src, int ch);
|
||||
EXTERN const char * Tcl_UtfFindFirst(const char *src, int ch);
|
||||
/* 329 */
|
||||
EXTERN CONST84_RETURN char * Tcl_UtfFindLast(const char *src, int ch);
|
||||
EXTERN const char * Tcl_UtfFindLast(const char *src, int ch);
|
||||
/* 330 */
|
||||
EXTERN CONST84_RETURN char * Tcl_UtfNext(const char *src);
|
||||
EXTERN const char * Tcl_UtfNext(const char *src);
|
||||
/* 331 */
|
||||
EXTERN CONST84_RETURN char * Tcl_UtfPrev(const char *src, const char *start);
|
||||
EXTERN const char * Tcl_UtfPrev(const char *src, const char *start);
|
||||
/* 332 */
|
||||
EXTERN int Tcl_UtfToExternal(Tcl_Interp *interp,
|
||||
Tcl_Encoding encoding, const char *src,
|
||||
@@ -1017,9 +1013,11 @@ EXTERN int Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr);
|
||||
/* 340 */
|
||||
EXTERN char * Tcl_GetString(Tcl_Obj *objPtr);
|
||||
/* 341 */
|
||||
EXTERN CONST84_RETURN char * Tcl_GetDefaultEncodingDir(void);
|
||||
TCL_DEPRECATED("Use Tcl_GetEncodingSearchPath")
|
||||
const char * Tcl_GetDefaultEncodingDir(void);
|
||||
/* 342 */
|
||||
EXTERN void Tcl_SetDefaultEncodingDir(const char *path);
|
||||
TCL_DEPRECATED("Use Tcl_SetEncodingSearchPath")
|
||||
void Tcl_SetDefaultEncodingDir(const char *path);
|
||||
/* 343 */
|
||||
EXTERN void Tcl_AlertNotifier(ClientData clientData);
|
||||
/* 344 */
|
||||
@@ -1054,7 +1052,8 @@ EXTERN Tcl_UniChar * Tcl_UtfToUniCharDString(const char *src, int length,
|
||||
EXTERN Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *patObj, int flags);
|
||||
/* 357 */
|
||||
EXTERN Tcl_Obj * Tcl_EvalTokens(Tcl_Interp *interp,
|
||||
TCL_DEPRECATED("Use Tcl_EvalTokensStandard")
|
||||
Tcl_Obj * Tcl_EvalTokens(Tcl_Interp *interp,
|
||||
Tcl_Token *tokenPtr, int count);
|
||||
/* 358 */
|
||||
EXTERN void Tcl_FreeParse(Tcl_Parse *parsePtr);
|
||||
@@ -1066,7 +1065,7 @@ EXTERN void Tcl_LogCommandInfo(Tcl_Interp *interp,
|
||||
EXTERN int Tcl_ParseBraces(Tcl_Interp *interp,
|
||||
const char *start, int numBytes,
|
||||
Tcl_Parse *parsePtr, int append,
|
||||
CONST84 char **termPtr);
|
||||
const char **termPtr);
|
||||
/* 361 */
|
||||
EXTERN int Tcl_ParseCommand(Tcl_Interp *interp,
|
||||
const char *start, int numBytes, int nested,
|
||||
@@ -1078,7 +1077,7 @@ EXTERN int Tcl_ParseExpr(Tcl_Interp *interp, const char *start,
|
||||
EXTERN int Tcl_ParseQuotedString(Tcl_Interp *interp,
|
||||
const char *start, int numBytes,
|
||||
Tcl_Parse *parsePtr, int append,
|
||||
CONST84 char **termPtr);
|
||||
const char **termPtr);
|
||||
/* 364 */
|
||||
EXTERN int Tcl_ParseVarName(Tcl_Interp *interp,
|
||||
const char *start, int numBytes,
|
||||
@@ -1168,8 +1167,7 @@ EXTERN Tcl_Channel Tcl_GetTopChannel(Tcl_Channel chan);
|
||||
/* 397 */
|
||||
EXTERN int Tcl_ChannelBuffered(Tcl_Channel chan);
|
||||
/* 398 */
|
||||
EXTERN CONST84_RETURN char * Tcl_ChannelName(
|
||||
const Tcl_ChannelType *chanTypePtr);
|
||||
EXTERN const char * Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr);
|
||||
/* 399 */
|
||||
EXTERN Tcl_ChannelTypeVersion Tcl_ChannelVersion(
|
||||
const Tcl_ChannelType *chanTypePtr);
|
||||
@@ -1275,13 +1273,15 @@ EXTERN Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel);
|
||||
EXTERN Tcl_UniChar * Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr,
|
||||
int *lengthPtr);
|
||||
/* 435 */
|
||||
EXTERN int Tcl_GetMathFuncInfo(Tcl_Interp *interp,
|
||||
TCL_DEPRECATED("")
|
||||
int Tcl_GetMathFuncInfo(Tcl_Interp *interp,
|
||||
const char *name, int *numArgsPtr,
|
||||
Tcl_ValueType **argTypesPtr,
|
||||
Tcl_MathProc **procPtr,
|
||||
ClientData *clientDataPtr);
|
||||
/* 436 */
|
||||
EXTERN Tcl_Obj * Tcl_ListMathFuncs(Tcl_Interp *interp,
|
||||
TCL_DEPRECATED("")
|
||||
Tcl_Obj * Tcl_ListMathFuncs(Tcl_Interp *interp,
|
||||
const char *pattern);
|
||||
/* 437 */
|
||||
EXTERN Tcl_Obj * Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
@@ -1850,7 +1850,7 @@ typedef struct TclStubs {
|
||||
const TclStubHooks *hooks;
|
||||
|
||||
int (*tcl_PkgProvideEx) (Tcl_Interp *interp, const char *name, const char *version, const void *clientData); /* 0 */
|
||||
CONST84_RETURN char * (*tcl_PkgRequireEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 1 */
|
||||
const char * (*tcl_PkgRequireEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 1 */
|
||||
TCL_NORETURN1 void (*tcl_Panic) (const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 2 */
|
||||
char * (*tcl_Alloc) (unsigned int size); /* 3 */
|
||||
void (*tcl_Free) (char *ptr); /* 4 */
|
||||
@@ -1901,7 +1901,7 @@ typedef struct TclStubs {
|
||||
unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */
|
||||
int (*tcl_GetDouble) (Tcl_Interp *interp, const char *src, double *doublePtr); /* 34 */
|
||||
int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */
|
||||
int (*tcl_GetIndexFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, CONST84 char *const *tablePtr, const char *msg, int flags, int *indexPtr); /* 36 */
|
||||
int (*tcl_GetIndexFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, const char *const *tablePtr, const char *msg, int flags, int *indexPtr); /* 36 */
|
||||
int (*tcl_GetInt) (Tcl_Interp *interp, const char *src, int *intPtr); /* 37 */
|
||||
int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */
|
||||
int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */
|
||||
@@ -1942,16 +1942,16 @@ typedef struct TclStubs {
|
||||
void (*tcl_AsyncMark) (Tcl_AsyncHandler async); /* 74 */
|
||||
int (*tcl_AsyncReady) (void); /* 75 */
|
||||
void (*tcl_BackgroundError) (Tcl_Interp *interp); /* 76 */
|
||||
char (*tcl_Backslash) (const char *src, int *readPtr); /* 77 */
|
||||
TCL_DEPRECATED_API("Use Tcl_UtfBackslash") char (*tcl_Backslash) (const char *src, int *readPtr); /* 77 */
|
||||
int (*tcl_BadChannelOption) (Tcl_Interp *interp, const char *optionName, const char *optionList); /* 78 */
|
||||
void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 79 */
|
||||
void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, ClientData clientData); /* 80 */
|
||||
int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */
|
||||
int (*tcl_CommandComplete) (const char *cmd); /* 82 */
|
||||
char * (*tcl_Concat) (int argc, CONST84 char *const *argv); /* 83 */
|
||||
char * (*tcl_Concat) (int argc, const char *const *argv); /* 83 */
|
||||
int (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */
|
||||
int (*tcl_ConvertCountedElement) (const char *src, int length, char *dst, int flags); /* 85 */
|
||||
int (*tcl_CreateAlias) (Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int argc, CONST84 char *const *argv); /* 86 */
|
||||
int (*tcl_CreateAlias) (Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int argc, const char *const *argv); /* 86 */
|
||||
int (*tcl_CreateAliasObj) (Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int objc, Tcl_Obj *const objv[]); /* 87 */
|
||||
Tcl_Channel (*tcl_CreateChannel) (const Tcl_ChannelType *typePtr, const char *chanName, ClientData instanceData, int mask); /* 88 */
|
||||
void (*tcl_CreateChannelHandler) (Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, ClientData clientData); /* 89 */
|
||||
@@ -1960,7 +1960,7 @@ typedef struct TclStubs {
|
||||
void (*tcl_CreateEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 92 */
|
||||
void (*tcl_CreateExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 93 */
|
||||
Tcl_Interp * (*tcl_CreateInterp) (void); /* 94 */
|
||||
void (*tcl_CreateMathFunc) (Tcl_Interp *interp, const char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData); /* 95 */
|
||||
TCL_DEPRECATED_API("") void (*tcl_CreateMathFunc) (Tcl_Interp *interp, const char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData); /* 95 */
|
||||
Tcl_Command (*tcl_CreateObjCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 96 */
|
||||
Tcl_Interp * (*tcl_CreateSlave) (Tcl_Interp *interp, const char *slaveName, int isSafe); /* 97 */
|
||||
Tcl_TimerToken (*tcl_CreateTimerHandler) (int milliseconds, Tcl_TimerProc *proc, ClientData clientData); /* 98 */
|
||||
@@ -1992,8 +1992,8 @@ typedef struct TclStubs {
|
||||
void (*tcl_DStringSetLength) (Tcl_DString *dsPtr, int length); /* 124 */
|
||||
void (*tcl_DStringStartSublist) (Tcl_DString *dsPtr); /* 125 */
|
||||
int (*tcl_Eof) (Tcl_Channel chan); /* 126 */
|
||||
CONST84_RETURN char * (*tcl_ErrnoId) (void); /* 127 */
|
||||
CONST84_RETURN char * (*tcl_ErrnoMsg) (int err); /* 128 */
|
||||
const char * (*tcl_ErrnoId) (void); /* 127 */
|
||||
const char * (*tcl_ErrnoMsg) (int err); /* 128 */
|
||||
int (*tcl_Eval) (Tcl_Interp *interp, const char *script); /* 129 */
|
||||
int (*tcl_EvalFile) (Tcl_Interp *interp, const char *fileName); /* 130 */
|
||||
int (*tcl_EvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 131 */
|
||||
@@ -2013,21 +2013,21 @@ typedef struct TclStubs {
|
||||
Tcl_HashEntry * (*tcl_FirstHashEntry) (Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 145 */
|
||||
int (*tcl_Flush) (Tcl_Channel chan); /* 146 */
|
||||
void (*tcl_FreeResult) (Tcl_Interp *interp); /* 147 */
|
||||
int (*tcl_GetAlias) (Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *argcPtr, CONST84 char ***argvPtr); /* 148 */
|
||||
int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv); /* 149 */
|
||||
int (*tcl_GetAlias) (Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *argcPtr, const char ***argvPtr); /* 148 */
|
||||
int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv); /* 149 */
|
||||
ClientData (*tcl_GetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc **procPtr); /* 150 */
|
||||
Tcl_Channel (*tcl_GetChannel) (Tcl_Interp *interp, const char *chanName, int *modePtr); /* 151 */
|
||||
int (*tcl_GetChannelBufferSize) (Tcl_Channel chan); /* 152 */
|
||||
int (*tcl_GetChannelHandle) (Tcl_Channel chan, int direction, ClientData *handlePtr); /* 153 */
|
||||
ClientData (*tcl_GetChannelInstanceData) (Tcl_Channel chan); /* 154 */
|
||||
int (*tcl_GetChannelMode) (Tcl_Channel chan); /* 155 */
|
||||
CONST84_RETURN char * (*tcl_GetChannelName) (Tcl_Channel chan); /* 156 */
|
||||
const char * (*tcl_GetChannelName) (Tcl_Channel chan); /* 156 */
|
||||
int (*tcl_GetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, Tcl_DString *dsPtr); /* 157 */
|
||||
CONST86 Tcl_ChannelType * (*tcl_GetChannelType) (Tcl_Channel chan); /* 158 */
|
||||
int (*tcl_GetCommandInfo) (Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr); /* 159 */
|
||||
CONST84_RETURN char * (*tcl_GetCommandName) (Tcl_Interp *interp, Tcl_Command command); /* 160 */
|
||||
const char * (*tcl_GetCommandName) (Tcl_Interp *interp, Tcl_Command command); /* 160 */
|
||||
int (*tcl_GetErrno) (void); /* 161 */
|
||||
CONST84_RETURN char * (*tcl_GetHostName) (void); /* 162 */
|
||||
const char * (*tcl_GetHostName) (void); /* 162 */
|
||||
int (*tcl_GetInterpPath) (Tcl_Interp *askInterp, Tcl_Interp *slaveInterp); /* 163 */
|
||||
Tcl_Interp * (*tcl_GetMaster) (Tcl_Interp *interp); /* 164 */
|
||||
const char * (*tcl_GetNameOfExecutable) (void); /* 165 */
|
||||
@@ -2047,9 +2047,9 @@ typedef struct TclStubs {
|
||||
int (*tcl_GetServiceMode) (void); /* 171 */
|
||||
Tcl_Interp * (*tcl_GetSlave) (Tcl_Interp *interp, const char *slaveName); /* 172 */
|
||||
Tcl_Channel (*tcl_GetStdChannel) (int type); /* 173 */
|
||||
CONST84_RETURN char * (*tcl_GetStringResult) (Tcl_Interp *interp); /* 174 */
|
||||
CONST84_RETURN char * (*tcl_GetVar) (Tcl_Interp *interp, const char *varName, int flags); /* 175 */
|
||||
CONST84_RETURN char * (*tcl_GetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 176 */
|
||||
const char * (*tcl_GetStringResult) (Tcl_Interp *interp); /* 174 */
|
||||
const char * (*tcl_GetVar) (Tcl_Interp *interp, const char *varName, int flags); /* 175 */
|
||||
const char * (*tcl_GetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 176 */
|
||||
int (*tcl_GlobalEval) (Tcl_Interp *interp, const char *command); /* 177 */
|
||||
int (*tcl_GlobalEvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 178 */
|
||||
int (*tcl_HideCommand) (Tcl_Interp *interp, const char *cmdName, const char *hiddenCmdToken); /* 179 */
|
||||
@@ -2059,25 +2059,25 @@ typedef struct TclStubs {
|
||||
int (*tcl_InputBuffered) (Tcl_Channel chan); /* 183 */
|
||||
int (*tcl_InterpDeleted) (Tcl_Interp *interp); /* 184 */
|
||||
int (*tcl_IsSafe) (Tcl_Interp *interp); /* 185 */
|
||||
char * (*tcl_JoinPath) (int argc, CONST84 char *const *argv, Tcl_DString *resultPtr); /* 186 */
|
||||
char * (*tcl_JoinPath) (int argc, const char *const *argv, Tcl_DString *resultPtr); /* 186 */
|
||||
int (*tcl_LinkVar) (Tcl_Interp *interp, const char *varName, char *addr, int type); /* 187 */
|
||||
void (*reserved188)(void);
|
||||
Tcl_Channel (*tcl_MakeFileChannel) (ClientData handle, int mode); /* 189 */
|
||||
int (*tcl_MakeSafe) (Tcl_Interp *interp); /* 190 */
|
||||
Tcl_Channel (*tcl_MakeTcpClientChannel) (ClientData tcpSocket); /* 191 */
|
||||
char * (*tcl_Merge) (int argc, CONST84 char *const *argv); /* 192 */
|
||||
char * (*tcl_Merge) (int argc, const char *const *argv); /* 192 */
|
||||
Tcl_HashEntry * (*tcl_NextHashEntry) (Tcl_HashSearch *searchPtr); /* 193 */
|
||||
void (*tcl_NotifyChannel) (Tcl_Channel channel, int mask); /* 194 */
|
||||
Tcl_Obj * (*tcl_ObjGetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 195 */
|
||||
Tcl_Obj * (*tcl_ObjSetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 196 */
|
||||
Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, CONST84 char **argv, int flags); /* 197 */
|
||||
Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, const char **argv, int flags); /* 197 */
|
||||
Tcl_Channel (*tcl_OpenFileChannel) (Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* 198 */
|
||||
Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int async); /* 199 */
|
||||
Tcl_Channel (*tcl_OpenTcpServer) (Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 200 */
|
||||
void (*tcl_Preserve) (ClientData data); /* 201 */
|
||||
void (*tcl_PrintDouble) (Tcl_Interp *interp, double value, char *dst); /* 202 */
|
||||
int (*tcl_PutEnv) (const char *assignment); /* 203 */
|
||||
CONST84_RETURN char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */
|
||||
const char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */
|
||||
void (*tcl_QueueEvent) (Tcl_Event *evPtr, Tcl_QueuePosition position); /* 205 */
|
||||
int (*tcl_Read) (Tcl_Channel chan, char *bufPtr, int toRead); /* 206 */
|
||||
void (*tcl_ReapDetachedProcs) (void); /* 207 */
|
||||
@@ -2088,7 +2088,7 @@ typedef struct TclStubs {
|
||||
Tcl_RegExp (*tcl_RegExpCompile) (Tcl_Interp *interp, const char *pattern); /* 212 */
|
||||
int (*tcl_RegExpExec) (Tcl_Interp *interp, Tcl_RegExp regexp, const char *text, const char *start); /* 213 */
|
||||
int (*tcl_RegExpMatch) (Tcl_Interp *interp, const char *text, const char *pattern); /* 214 */
|
||||
void (*tcl_RegExpRange) (Tcl_RegExp regexp, int index, CONST84 char **startPtr, CONST84 char **endPtr); /* 215 */
|
||||
void (*tcl_RegExpRange) (Tcl_RegExp regexp, int index, const char **startPtr, const char **endPtr); /* 215 */
|
||||
void (*tcl_Release) (ClientData clientData); /* 216 */
|
||||
void (*tcl_ResetResult) (Tcl_Interp *interp); /* 217 */
|
||||
int (*tcl_ScanElement) (const char *src, int *flagPtr); /* 218 */
|
||||
@@ -2110,13 +2110,13 @@ typedef struct TclStubs {
|
||||
void (*tcl_SetObjErrorCode) (Tcl_Interp *interp, Tcl_Obj *errorObjPtr); /* 234 */
|
||||
void (*tcl_SetObjResult) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr); /* 235 */
|
||||
void (*tcl_SetStdChannel) (Tcl_Channel channel, int type); /* 236 */
|
||||
CONST84_RETURN char * (*tcl_SetVar) (Tcl_Interp *interp, const char *varName, const char *newValue, int flags); /* 237 */
|
||||
CONST84_RETURN char * (*tcl_SetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, const char *newValue, int flags); /* 238 */
|
||||
CONST84_RETURN char * (*tcl_SignalId) (int sig); /* 239 */
|
||||
CONST84_RETURN char * (*tcl_SignalMsg) (int sig); /* 240 */
|
||||
const char * (*tcl_SetVar) (Tcl_Interp *interp, const char *varName, const char *newValue, int flags); /* 237 */
|
||||
const char * (*tcl_SetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, const char *newValue, int flags); /* 238 */
|
||||
const char * (*tcl_SignalId) (int sig); /* 239 */
|
||||
const char * (*tcl_SignalMsg) (int sig); /* 240 */
|
||||
void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */
|
||||
int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, CONST84 char ***argvPtr); /* 242 */
|
||||
void (*tcl_SplitPath) (const char *path, int *argcPtr, CONST84 char ***argvPtr); /* 243 */
|
||||
int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, const char ***argvPtr); /* 242 */
|
||||
void (*tcl_SplitPath) (const char *path, int *argcPtr, const char ***argvPtr); /* 243 */
|
||||
void (*tcl_StaticPackage) (Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 244 */
|
||||
int (*tcl_StringMatch) (const char *str, const char *pattern); /* 245 */
|
||||
TCL_DEPRECATED_API("") int (*tcl_TellOld) (Tcl_Channel chan); /* 246 */
|
||||
@@ -2143,11 +2143,11 @@ typedef struct TclStubs {
|
||||
TCL_DEPRECATED_API("see TIP #422") void (*tcl_AppendResultVA) (Tcl_Interp *interp, va_list argList); /* 267 */
|
||||
TCL_DEPRECATED_API("see TIP #422") void (*tcl_AppendStringsToObjVA) (Tcl_Obj *objPtr, va_list argList); /* 268 */
|
||||
char * (*tcl_HashStats) (Tcl_HashTable *tablePtr); /* 269 */
|
||||
CONST84_RETURN char * (*tcl_ParseVar) (Tcl_Interp *interp, const char *start, CONST84 char **termPtr); /* 270 */
|
||||
CONST84_RETURN char * (*tcl_PkgPresent) (Tcl_Interp *interp, const char *name, const char *version, int exact); /* 271 */
|
||||
CONST84_RETURN char * (*tcl_PkgPresentEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 272 */
|
||||
const char * (*tcl_ParseVar) (Tcl_Interp *interp, const char *start, const char **termPtr); /* 270 */
|
||||
const char * (*tcl_PkgPresent) (Tcl_Interp *interp, const char *name, const char *version, int exact); /* 271 */
|
||||
const char * (*tcl_PkgPresentEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 272 */
|
||||
int (*tcl_PkgProvide) (Tcl_Interp *interp, const char *name, const char *version); /* 273 */
|
||||
CONST84_RETURN char * (*tcl_PkgRequire) (Tcl_Interp *interp, const char *name, const char *version, int exact); /* 274 */
|
||||
const char * (*tcl_PkgRequire) (Tcl_Interp *interp, const char *name, const char *version, int exact); /* 274 */
|
||||
TCL_DEPRECATED_API("see TIP #422") void (*tcl_SetErrorCodeVA) (Tcl_Interp *interp, va_list argList); /* 275 */
|
||||
TCL_DEPRECATED_API("see TIP #422") int (*tcl_VarEvalVA) (Tcl_Interp *interp, va_list argList); /* 276 */
|
||||
Tcl_Pid (*tcl_WaitPid) (Tcl_Pid pid, int *statPtr, int options); /* 277 */
|
||||
@@ -2175,7 +2175,7 @@ typedef struct TclStubs {
|
||||
void (*tcl_FreeEncoding) (Tcl_Encoding encoding); /* 299 */
|
||||
Tcl_ThreadId (*tcl_GetCurrentThread) (void); /* 300 */
|
||||
Tcl_Encoding (*tcl_GetEncoding) (Tcl_Interp *interp, const char *name); /* 301 */
|
||||
CONST84_RETURN char * (*tcl_GetEncodingName) (Tcl_Encoding encoding); /* 302 */
|
||||
const char * (*tcl_GetEncodingName) (Tcl_Encoding encoding); /* 302 */
|
||||
void (*tcl_GetEncodingNames) (Tcl_Interp *interp); /* 303 */
|
||||
int (*tcl_GetIndexFromObjStruct) (Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, int offset, const char *msg, int flags, int *indexPtr); /* 304 */
|
||||
void * (*tcl_GetThreadData) (Tcl_ThreadDataKey *keyPtr, int size); /* 305 */
|
||||
@@ -2198,13 +2198,13 @@ typedef struct TclStubs {
|
||||
Tcl_UniChar (*tcl_UniCharToTitle) (int ch); /* 322 */
|
||||
Tcl_UniChar (*tcl_UniCharToUpper) (int ch); /* 323 */
|
||||
int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */
|
||||
CONST84_RETURN char * (*tcl_UtfAtIndex) (const char *src, int index); /* 325 */
|
||||
const char * (*tcl_UtfAtIndex) (const char *src, int index); /* 325 */
|
||||
int (*tcl_UtfCharComplete) (const char *src, int length); /* 326 */
|
||||
int (*tcl_UtfBackslash) (const char *src, int *readPtr, char *dst); /* 327 */
|
||||
CONST84_RETURN char * (*tcl_UtfFindFirst) (const char *src, int ch); /* 328 */
|
||||
CONST84_RETURN char * (*tcl_UtfFindLast) (const char *src, int ch); /* 329 */
|
||||
CONST84_RETURN char * (*tcl_UtfNext) (const char *src); /* 330 */
|
||||
CONST84_RETURN char * (*tcl_UtfPrev) (const char *src, const char *start); /* 331 */
|
||||
const char * (*tcl_UtfFindFirst) (const char *src, int ch); /* 328 */
|
||||
const char * (*tcl_UtfFindLast) (const char *src, int ch); /* 329 */
|
||||
const char * (*tcl_UtfNext) (const char *src); /* 330 */
|
||||
const char * (*tcl_UtfPrev) (const char *src, const char *start); /* 331 */
|
||||
int (*tcl_UtfToExternal) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 332 */
|
||||
char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 333 */
|
||||
int (*tcl_UtfToLower) (char *src); /* 334 */
|
||||
@@ -2214,8 +2214,8 @@ typedef struct TclStubs {
|
||||
int (*tcl_WriteChars) (Tcl_Channel chan, const char *src, int srcLen); /* 338 */
|
||||
int (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */
|
||||
char * (*tcl_GetString) (Tcl_Obj *objPtr); /* 340 */
|
||||
CONST84_RETURN char * (*tcl_GetDefaultEncodingDir) (void); /* 341 */
|
||||
void (*tcl_SetDefaultEncodingDir) (const char *path); /* 342 */
|
||||
TCL_DEPRECATED_API("Use Tcl_GetEncodingSearchPath") const char * (*tcl_GetDefaultEncodingDir) (void); /* 341 */
|
||||
TCL_DEPRECATED_API("Use Tcl_SetEncodingSearchPath") void (*tcl_SetDefaultEncodingDir) (const char *path); /* 342 */
|
||||
void (*tcl_AlertNotifier) (ClientData clientData); /* 343 */
|
||||
void (*tcl_ServiceModeHook) (int mode); /* 344 */
|
||||
int (*tcl_UniCharIsAlnum) (int ch); /* 345 */
|
||||
@@ -2230,13 +2230,13 @@ typedef struct TclStubs {
|
||||
char * (*tcl_UniCharToUtfDString) (const Tcl_UniChar *uniStr, int uniLength, Tcl_DString *dsPtr); /* 354 */
|
||||
Tcl_UniChar * (*tcl_UtfToUniCharDString) (const char *src, int length, Tcl_DString *dsPtr); /* 355 */
|
||||
Tcl_RegExp (*tcl_GetRegExpFromObj) (Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* 356 */
|
||||
Tcl_Obj * (*tcl_EvalTokens) (Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 357 */
|
||||
TCL_DEPRECATED_API("Use Tcl_EvalTokensStandard") Tcl_Obj * (*tcl_EvalTokens) (Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 357 */
|
||||
void (*tcl_FreeParse) (Tcl_Parse *parsePtr); /* 358 */
|
||||
void (*tcl_LogCommandInfo) (Tcl_Interp *interp, const char *script, const char *command, int length); /* 359 */
|
||||
int (*tcl_ParseBraces) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 360 */
|
||||
int (*tcl_ParseBraces) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 360 */
|
||||
int (*tcl_ParseCommand) (Tcl_Interp *interp, const char *start, int numBytes, int nested, Tcl_Parse *parsePtr); /* 361 */
|
||||
int (*tcl_ParseExpr) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr); /* 362 */
|
||||
int (*tcl_ParseQuotedString) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 363 */
|
||||
int (*tcl_ParseQuotedString) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 363 */
|
||||
int (*tcl_ParseVarName) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append); /* 364 */
|
||||
char * (*tcl_GetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 365 */
|
||||
int (*tcl_Chdir) (const char *dirName); /* 366 */
|
||||
@@ -2271,7 +2271,7 @@ typedef struct TclStubs {
|
||||
int (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, int srcLen); /* 395 */
|
||||
Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */
|
||||
int (*tcl_ChannelBuffered) (Tcl_Channel chan); /* 397 */
|
||||
CONST84_RETURN char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */
|
||||
const char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */
|
||||
Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (const Tcl_ChannelType *chanTypePtr); /* 399 */
|
||||
Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (const Tcl_ChannelType *chanTypePtr); /* 400 */
|
||||
Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) (const Tcl_ChannelType *chanTypePtr); /* 401 */
|
||||
@@ -2308,8 +2308,8 @@ typedef struct TclStubs {
|
||||
int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, int length); /* 432 */
|
||||
Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */
|
||||
Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 434 */
|
||||
int (*tcl_GetMathFuncInfo) (Tcl_Interp *interp, const char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr); /* 435 */
|
||||
Tcl_Obj * (*tcl_ListMathFuncs) (Tcl_Interp *interp, const char *pattern); /* 436 */
|
||||
TCL_DEPRECATED_API("") int (*tcl_GetMathFuncInfo) (Tcl_Interp *interp, const char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr); /* 435 */
|
||||
TCL_DEPRECATED_API("") Tcl_Obj * (*tcl_ListMathFuncs) (Tcl_Interp *interp, const char *pattern); /* 436 */
|
||||
Tcl_Obj * (*tcl_SubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 437 */
|
||||
int (*tcl_DetachChannel) (Tcl_Interp *interp, Tcl_Channel channel); /* 438 */
|
||||
int (*tcl_IsStandardChannel) (Tcl_Channel channel); /* 439 */
|
||||
@@ -3934,20 +3934,14 @@ extern const TclStubs *tclStubsPtr;
|
||||
* possible. Tcl 9 must find a better solution, but that cannot be done
|
||||
* without introducing a binary incompatibility.
|
||||
*/
|
||||
# undef Tcl_DbNewLongObj
|
||||
# undef Tcl_GetLongFromObj
|
||||
# undef Tcl_NewLongObj
|
||||
# undef Tcl_SetLongObj
|
||||
# undef Tcl_ExprLong
|
||||
# undef Tcl_ExprLongObj
|
||||
# undef Tcl_UniCharNcmp
|
||||
# undef Tcl_UtfNcmp
|
||||
# undef Tcl_UtfNcasecmp
|
||||
# undef Tcl_UniCharNcasecmp
|
||||
# define Tcl_DbNewLongObj ((Tcl_Obj*(*)(long,const char*,int))Tcl_DbNewWideIntObj)
|
||||
# define Tcl_GetLongFromObj ((int(*)(Tcl_Interp*,Tcl_Obj*,long*))Tcl_GetWideIntFromObj)
|
||||
# define Tcl_NewLongObj ((Tcl_Obj*(*)(long))Tcl_NewWideIntObj)
|
||||
# define Tcl_SetLongObj ((void(*)(Tcl_Obj*,long))Tcl_SetWideIntObj)
|
||||
# define Tcl_ExprLong TclExprLong
|
||||
static inline int TclExprLong(Tcl_Interp *interp, const char *string, long *ptr){
|
||||
int intValue;
|
||||
@@ -3973,6 +3967,17 @@ extern const TclStubs *tclStubsPtr;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#undef Tcl_NewLongObj
|
||||
#define Tcl_NewLongObj(value) Tcl_NewWideIntObj((long)(value))
|
||||
#undef Tcl_NewIntObj
|
||||
#define Tcl_NewIntObj(value) Tcl_NewWideIntObj((int)(value))
|
||||
#undef Tcl_DbNewLongObj
|
||||
#define Tcl_DbNewLongObj(value, file, line) Tcl_DbNewWideIntObj((long)(value), file, line)
|
||||
#undef Tcl_SetIntObj
|
||||
#define Tcl_SetIntObj(objPtr, value) Tcl_SetWideIntObj(objPtr, (int)(value))
|
||||
#undef Tcl_SetLongObj
|
||||
#define Tcl_SetLongObj(objPtr, value) Tcl_SetWideIntObj(objPtr, (long)(value))
|
||||
|
||||
/*
|
||||
* Deprecated Tcl procedures:
|
||||
*/
|
||||
|
||||
@@ -2309,9 +2309,12 @@ DictAppendCmd(
|
||||
|
||||
if (objc == 4) {
|
||||
appendObjPtr = objv[3];
|
||||
} else if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1,
|
||||
objc-3, objv+3, &appendObjPtr)) {
|
||||
return TCL_ERROR;
|
||||
} else {
|
||||
appendObjPtr = TclStringCat(interp, objc-3, objv+3,
|
||||
TCL_STRING_IN_PLACE);
|
||||
if (appendObjPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ DisassembleByteCodeObj(
|
||||
Tcl_Obj *bufferObj, *fileObj;
|
||||
|
||||
TclNewObj(bufferObj);
|
||||
if (codePtr->refCount <= 0) {
|
||||
if (!codePtr->refCount) {
|
||||
return bufferObj; /* Already freed. */
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ DisassembleByteCodeObj(
|
||||
int numCompiledLocals = procPtr->numCompiledLocals;
|
||||
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" Proc %p, refCt %d, args %d, compiled locals %d\n",
|
||||
" Proc %p, refCt %u, args %d, compiled locals %d\n",
|
||||
procPtr, procPtr->refCount, procPtr->numArgs,
|
||||
numCompiledLocals);
|
||||
if (numCompiledLocals > 0) {
|
||||
@@ -797,7 +797,7 @@ TclNewInstNameObj(
|
||||
Tcl_Obj *objPtr = Tcl_NewObj();
|
||||
|
||||
objPtr->typePtr = &tclInstNameType;
|
||||
objPtr->internalRep.longValue = (long) inst;
|
||||
objPtr->internalRep.wideValue = (long) inst;
|
||||
objPtr->bytes = NULL;
|
||||
|
||||
return objPtr;
|
||||
@@ -817,17 +817,17 @@ static void
|
||||
UpdateStringOfInstName(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
int inst = objPtr->internalRep.longValue;
|
||||
char *s, buf[20];
|
||||
int len;
|
||||
size_t len, inst = (size_t)objPtr->internalRep.wideValue;
|
||||
char *s, buf[TCL_INTEGER_SPACE + 5];
|
||||
|
||||
if ((inst < 0) || (inst > LAST_INST_OPCODE)) {
|
||||
sprintf(buf, "inst_%d", inst);
|
||||
if (inst > LAST_INST_OPCODE) {
|
||||
sprintf(buf, "inst_%" TCL_Z_MODIFIER "d", inst);
|
||||
s = buf;
|
||||
} else {
|
||||
s = (char *) tclInstructionTable[objPtr->internalRep.longValue].name;
|
||||
s = (char *) tclInstructionTable[inst].name;
|
||||
}
|
||||
len = strlen(s);
|
||||
/* assert (len < UINT_MAX) */
|
||||
objPtr->bytes = ckalloc(len + 1);
|
||||
memcpy(objPtr->bytes, s, len + 1);
|
||||
objPtr->length = len;
|
||||
|
||||
@@ -693,6 +693,7 @@ TclFinalizeEncodingSubsystem(void)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
const char *
|
||||
Tcl_GetDefaultEncodingDir(void)
|
||||
{
|
||||
@@ -736,6 +737,7 @@ Tcl_SetDefaultEncodingDir(
|
||||
Tcl_ListObjReplace(NULL, searchPath, 0, 0, 1, &directory);
|
||||
Tcl_SetEncodingSearchPath(searchPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
@@ -3609,7 +3611,7 @@ unilen(
|
||||
static void
|
||||
InitializeEncodingSearchPath(
|
||||
char **valuePtr,
|
||||
size_t *lengthPtr,
|
||||
unsigned int *lengthPtr,
|
||||
Tcl_Encoding *encodingPtr)
|
||||
{
|
||||
const char *bytes;
|
||||
|
||||
+105
-103
@@ -92,7 +92,7 @@ static const Tcl_ObjType ensembleCmdType = {
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
size_t epoch; /* Used to confirm when the data in this
|
||||
unsigned int epoch; /* Used to confirm when the data in this
|
||||
* really structure matches up with the
|
||||
* ensemble. */
|
||||
Command *token; /* Reference to the command for which this
|
||||
@@ -2431,14 +2431,32 @@ MakeCachedEnsembleCommand(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
ClearTable(
|
||||
EnsembleConfig *ensemblePtr)
|
||||
{
|
||||
Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
|
||||
|
||||
if (hash->numEntries != 0) {
|
||||
Tcl_HashSearch search;
|
||||
Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(hash, &search);
|
||||
|
||||
while (hPtr != NULL) {
|
||||
Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
|
||||
Tcl_DecrRefCount(prefixObj);
|
||||
hPtr = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
ckfree((char *) ensemblePtr->subcommandArrayPtr);
|
||||
}
|
||||
Tcl_DeleteHashTable(hash);
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteEnsembleConfig(
|
||||
ClientData clientData)
|
||||
{
|
||||
EnsembleConfig *ensemblePtr = clientData;
|
||||
Namespace *nsPtr = ensemblePtr->nsPtr;
|
||||
Tcl_HashSearch search;
|
||||
Tcl_HashEntry *hEnt;
|
||||
|
||||
/*
|
||||
* Unlink from the ensemble chain if it has not been marked as having been
|
||||
@@ -2472,17 +2490,7 @@ DeleteEnsembleConfig(
|
||||
* Kill the pointer-containing fields.
|
||||
*/
|
||||
|
||||
if (ensemblePtr->subcommandTable.numEntries != 0) {
|
||||
ckfree(ensemblePtr->subcommandArrayPtr);
|
||||
}
|
||||
hEnt = Tcl_FirstHashEntry(&ensemblePtr->subcommandTable, &search);
|
||||
while (hEnt != NULL) {
|
||||
Tcl_Obj *prefixObj = Tcl_GetHashValue(hEnt);
|
||||
|
||||
Tcl_DecrRefCount(prefixObj);
|
||||
hEnt = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
Tcl_DeleteHashTable(&ensemblePtr->subcommandTable);
|
||||
ClearTable(ensemblePtr);
|
||||
if (ensemblePtr->subcmdList != NULL) {
|
||||
Tcl_DecrRefCount(ensemblePtr->subcmdList);
|
||||
}
|
||||
@@ -2538,107 +2546,101 @@ BuildEnsembleConfig(
|
||||
int i, j, isNew;
|
||||
Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_Obj *subcmdDictCopy = NULL ;
|
||||
Tcl_Obj *mapDict = ensemblePtr->subcommandDict;
|
||||
Tcl_Obj *subList = ensemblePtr->subcmdList;
|
||||
|
||||
if (hash->numEntries != 0) {
|
||||
/*
|
||||
* Remove pre-existing table.
|
||||
*/
|
||||
ClearTable(ensemblePtr);
|
||||
Tcl_InitHashTable(hash, TCL_STRING_KEYS);
|
||||
|
||||
ckfree(ensemblePtr->subcommandArrayPtr);
|
||||
hPtr = Tcl_FirstHashEntry(hash, &search);
|
||||
while (hPtr != NULL) {
|
||||
Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
|
||||
if (subList) {
|
||||
int subc;
|
||||
Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj;
|
||||
char *name;
|
||||
|
||||
Tcl_DecrRefCount(prefixObj);
|
||||
hPtr = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
Tcl_DeleteHashTable(hash);
|
||||
Tcl_InitHashTable(hash, TCL_STRING_KEYS);
|
||||
}
|
||||
/*
|
||||
* There is a list of exactly what subcommands go in the table.
|
||||
* Must determine the target for each.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See if we've got an export list. If so, we will only export exactly
|
||||
* those commands, which may be either implemented by the prefix in the
|
||||
* subcommandDict or mapped directly onto the namespace's commands.
|
||||
*/
|
||||
Tcl_ListObjGetElements(NULL, subList, &subc, &subv);
|
||||
if (subList == mapDict) {
|
||||
/*
|
||||
* Strange case where explicit list of subcommands is same value
|
||||
* as the dict mapping to targets.
|
||||
*/
|
||||
|
||||
if (ensemblePtr->subcmdList != NULL) {
|
||||
Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj;
|
||||
int subcmdc;
|
||||
for (i = 0; i < subc; i += 2) {
|
||||
name = TclGetString(subv[i]);
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
if (!isNew) {
|
||||
cmdObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
|
||||
Tcl_DecrRefCount(cmdObj);
|
||||
}
|
||||
Tcl_SetHashValue(hPtr, subv[i+1]);
|
||||
Tcl_IncrRefCount(subv[i+1]);
|
||||
|
||||
TclListObjGetElements(NULL, ensemblePtr->subcmdList, &subcmdc,
|
||||
&subcmdv);
|
||||
for (i=0 ; i<subcmdc ; i++) {
|
||||
const char *name = TclGetString(subcmdv[i]);
|
||||
name = TclGetString(subv[i+1]);
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
if (isNew) {
|
||||
cmdObj = Tcl_NewStringObj(name, -1);
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
Tcl_IncrRefCount(cmdPrefixObj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Usual case where we can freely act on the list and dict. */
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
for (i = 0; i < subc; i++) {
|
||||
name = TclGetString(subv[i]);
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
if (!isNew) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip non-unique cases.
|
||||
*/
|
||||
/* Lookup target in the dictionary */
|
||||
if (mapDict) {
|
||||
Tcl_DictObjGet(NULL, mapDict, subv[i], &target);
|
||||
if (target) {
|
||||
Tcl_SetHashValue(hPtr, target);
|
||||
Tcl_IncrRefCount(target);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isNew) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* target was not in the dictionary so map onto the namespace.
|
||||
* Note in this case that we do not guarantee that the
|
||||
* command is actually there; that is the programmer's
|
||||
* responsibility (or [::unknown] of course).
|
||||
*/
|
||||
cmdObj = Tcl_NewStringObj(name, -1);
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
Tcl_IncrRefCount(cmdPrefixObj);
|
||||
}
|
||||
}
|
||||
} else if (mapDict) {
|
||||
/*
|
||||
* No subcmd list, but we do have a mapping dictionary so we should
|
||||
* use the keys of that. Convert the dictionary's contents into the
|
||||
* form required for the ensemble's internal hashtable.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Look in our dictionary (if present) for the command.
|
||||
*/
|
||||
Tcl_DictSearch dictSearch;
|
||||
Tcl_Obj *keyObj, *valueObj;
|
||||
int done;
|
||||
|
||||
if (ensemblePtr->subcommandDict != NULL) {
|
||||
if (subcmdDictCopy == NULL) {
|
||||
if (ensemblePtr->subcmdList == ensemblePtr->subcommandDict) {
|
||||
subcmdDictCopy = Tcl_DuplicateObj(ensemblePtr->subcommandDict);
|
||||
} else {
|
||||
subcmdDictCopy = ensemblePtr->subcommandDict;
|
||||
}
|
||||
Tcl_IncrRefCount(subcmdDictCopy);
|
||||
}
|
||||
Tcl_DictObjGet(NULL, subcmdDictCopy, subcmdv[i],
|
||||
&target);
|
||||
if (target != NULL) {
|
||||
Tcl_SetHashValue(hPtr, target);
|
||||
Tcl_IncrRefCount(target);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
|
||||
&keyObj, &valueObj, &done);
|
||||
while (!done) {
|
||||
char *name = TclGetString(keyObj);
|
||||
|
||||
/*
|
||||
* Not there, so map onto the namespace. Note in this case that we
|
||||
* do not guarantee that the command is actually there; that is
|
||||
* the programmer's responsibility (or [::unknown] of course).
|
||||
*/
|
||||
|
||||
cmdObj = Tcl_NewStringObj(name, -1);
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
Tcl_IncrRefCount(cmdPrefixObj);
|
||||
}
|
||||
if (subcmdDictCopy != NULL) {
|
||||
Tcl_DecrRefCount(subcmdDictCopy);
|
||||
}
|
||||
} else if (ensemblePtr->subcommandDict != NULL) {
|
||||
/*
|
||||
* No subcmd list, but we do have a mapping dictionary so we should
|
||||
* use the keys of that. Convert the dictionary's contents into the
|
||||
* form required for the ensemble's internal hashtable.
|
||||
*/
|
||||
|
||||
Tcl_DictSearch dictSearch;
|
||||
Tcl_Obj *keyObj, *valueObj;
|
||||
int done;
|
||||
|
||||
Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
|
||||
&keyObj, &valueObj, &done);
|
||||
while (!done) {
|
||||
const char *name = TclGetString(keyObj);
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
Tcl_SetHashValue(hPtr, valueObj);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
|
||||
}
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
Tcl_SetHashValue(hPtr, valueObj);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Discover what commands are actually exported by the namespace.
|
||||
|
||||
@@ -1057,7 +1057,6 @@ TclInitSubsystems(void)
|
||||
* mutexes. */
|
||||
TclInitIOSubsystem(); /* Inits a tsd key (noop). */
|
||||
TclInitEncodingSubsystem(); /* Process wide encoding init. */
|
||||
TclpSetInterfaces();
|
||||
TclInitNamespaceSubsystem();/* Register ns obj type (mutexed). */
|
||||
subsystemsInitialized = 1;
|
||||
}
|
||||
|
||||
+311
-707
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -142,7 +142,7 @@ Tcl_GetBoolean(
|
||||
Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
|
||||
}
|
||||
if (code == TCL_OK) {
|
||||
*boolPtr = obj.internalRep.longValue;
|
||||
TclGetBooleanFromObj(NULL, &obj, boolPtr);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
+13
-9
@@ -721,17 +721,18 @@ Tcl_SetStdChannel(
|
||||
{
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
int init = channel ? 1 : -1;
|
||||
switch (type) {
|
||||
case TCL_STDIN:
|
||||
tsdPtr->stdinInitialized = 1;
|
||||
tsdPtr->stdinInitialized = init;
|
||||
tsdPtr->stdinChannel = channel;
|
||||
break;
|
||||
case TCL_STDOUT:
|
||||
tsdPtr->stdoutInitialized = 1;
|
||||
tsdPtr->stdoutInitialized = init;
|
||||
tsdPtr->stdoutChannel = channel;
|
||||
break;
|
||||
case TCL_STDERR:
|
||||
tsdPtr->stderrInitialized = 1;
|
||||
tsdPtr->stderrInitialized = init;
|
||||
tsdPtr->stderrChannel = channel;
|
||||
break;
|
||||
}
|
||||
@@ -768,8 +769,8 @@ Tcl_GetStdChannel(
|
||||
switch (type) {
|
||||
case TCL_STDIN:
|
||||
if (!tsdPtr->stdinInitialized) {
|
||||
tsdPtr->stdinInitialized = -1;
|
||||
tsdPtr->stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN);
|
||||
tsdPtr->stdinInitialized = 1;
|
||||
|
||||
/*
|
||||
* Artificially bump the refcount to ensure that the channel is
|
||||
@@ -781,6 +782,7 @@ Tcl_GetStdChannel(
|
||||
*/
|
||||
|
||||
if (tsdPtr->stdinChannel != NULL) {
|
||||
tsdPtr->stdinInitialized = 1;
|
||||
Tcl_RegisterChannel(NULL, tsdPtr->stdinChannel);
|
||||
}
|
||||
}
|
||||
@@ -788,9 +790,10 @@ Tcl_GetStdChannel(
|
||||
break;
|
||||
case TCL_STDOUT:
|
||||
if (!tsdPtr->stdoutInitialized) {
|
||||
tsdPtr->stdoutInitialized = -1;
|
||||
tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT);
|
||||
tsdPtr->stdoutInitialized = 1;
|
||||
if (tsdPtr->stdoutChannel != NULL) {
|
||||
tsdPtr->stdoutInitialized = 1;
|
||||
Tcl_RegisterChannel(NULL, tsdPtr->stdoutChannel);
|
||||
}
|
||||
}
|
||||
@@ -798,9 +801,10 @@ Tcl_GetStdChannel(
|
||||
break;
|
||||
case TCL_STDERR:
|
||||
if (!tsdPtr->stderrInitialized) {
|
||||
tsdPtr->stderrInitialized = -1;
|
||||
tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
|
||||
tsdPtr->stderrInitialized = 1;
|
||||
if (tsdPtr->stderrChannel != NULL) {
|
||||
tsdPtr->stderrInitialized = 1;
|
||||
Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
|
||||
}
|
||||
}
|
||||
@@ -1068,7 +1072,7 @@ CheckForStdChannelsBeingClosed(
|
||||
ChannelState *statePtr = ((Channel *) chan)->state;
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
if (tsdPtr->stdinInitialized
|
||||
if (tsdPtr->stdinInitialized == 1
|
||||
&& tsdPtr->stdinChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stdinChannel)->state) {
|
||||
if (statePtr->refCount < 2) {
|
||||
@@ -1076,7 +1080,7 @@ CheckForStdChannelsBeingClosed(
|
||||
tsdPtr->stdinChannel = NULL;
|
||||
return;
|
||||
}
|
||||
} else if (tsdPtr->stdoutInitialized
|
||||
} else if (tsdPtr->stdoutInitialized == 1
|
||||
&& tsdPtr->stdoutChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) {
|
||||
if (statePtr->refCount < 2) {
|
||||
@@ -1084,7 +1088,7 @@ CheckForStdChannelsBeingClosed(
|
||||
tsdPtr->stdoutChannel = NULL;
|
||||
return;
|
||||
}
|
||||
} else if (tsdPtr->stderrInitialized
|
||||
} else if (tsdPtr->stderrInitialized == 1
|
||||
&& tsdPtr->stderrChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stderrChannel)->state) {
|
||||
if (statePtr->refCount < 2) {
|
||||
|
||||
+3
-3
@@ -137,7 +137,7 @@ Tcl_PutsObjCmd(
|
||||
chanObjPtr = objv[2];
|
||||
string = objv[3];
|
||||
break;
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
} else if (strcmp(TclGetString(objv[3]), "nonewline") == 0) {
|
||||
/*
|
||||
* The code below provides backwards compatibility with an old
|
||||
@@ -439,7 +439,7 @@ Tcl_ReadObjCmd(
|
||||
if (i < objc) {
|
||||
if ((TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK)
|
||||
|| (toRead < 0)) {
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
/*
|
||||
* The code below provides backwards compatibility with an old
|
||||
* form of the command that is no longer recommended or
|
||||
@@ -454,7 +454,7 @@ Tcl_ReadObjCmd(
|
||||
TclGetString(objv[i])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
|
||||
return TCL_ERROR;
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
}
|
||||
newline = 1;
|
||||
#endif
|
||||
|
||||
@@ -830,15 +830,6 @@ TclResetFilesystem(void)
|
||||
if (++theFilesystemEpoch == 0) {
|
||||
++theFilesystemEpoch;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Cleans up the win32 API filesystem proc lookup table. This must happen
|
||||
* very late in finalization so that deleting of copied dlls can occur.
|
||||
*/
|
||||
|
||||
TclWinResetInterfaces();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -114,7 +114,7 @@ declare 23 {
|
||||
}
|
||||
# Replaced with macro (see tclInt.h) in Tcl 8.5.0, restored in 8.5.10
|
||||
declare 24 {
|
||||
int TclFormatInt(char *buffer, long n)
|
||||
int TclFormatInt(char *buffer, Tcl_WideInt n)
|
||||
}
|
||||
declare 25 {
|
||||
void TclFreePackageInfo(Interp *iPtr)
|
||||
@@ -187,7 +187,7 @@ declare 42 {
|
||||
}
|
||||
# Removed in 8.5a2:
|
||||
#declare 43 {
|
||||
# int TclGlobalInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv,
|
||||
# int TclGlobalInvoke(Tcl_Interp *interp, int argc, const char **argv,
|
||||
# int flags)
|
||||
#}
|
||||
declare 44 {
|
||||
@@ -222,12 +222,12 @@ declare 51 {
|
||||
}
|
||||
# Removed in 8.5a2:
|
||||
#declare 52 {
|
||||
# int TclInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv,
|
||||
# int TclInvoke(Tcl_Interp *interp, int argc, const char **argv,
|
||||
# int flags)
|
||||
#}
|
||||
declare 53 {
|
||||
int TclInvokeObjectCommand(ClientData clientData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char **argv)
|
||||
int argc, const char **argv)
|
||||
}
|
||||
declare 54 {
|
||||
int TclInvokeStringCommand(ClientData clientData, Tcl_Interp *interp,
|
||||
@@ -355,7 +355,7 @@ declare 81 {
|
||||
# declare 87 {
|
||||
# void TclPlatformInit(Tcl_Interp *interp)
|
||||
# }
|
||||
declare 88 {
|
||||
declare 88 {deprecated {}} {
|
||||
char *TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp,
|
||||
const char *name1, const char *name2, int flags)
|
||||
}
|
||||
@@ -548,7 +548,7 @@ declare 133 {deprecated {}} {
|
||||
# int TclpChdir(const char *dirName)
|
||||
#}
|
||||
declare 138 {
|
||||
CONST84_RETURN char *TclGetEnv(const char *name, Tcl_DString *valuePtr)
|
||||
const char *TclGetEnv(const char *name, Tcl_DString *valuePtr)
|
||||
}
|
||||
#declare 139 {
|
||||
# int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1,
|
||||
@@ -560,7 +560,7 @@ declare 138 {
|
||||
#}
|
||||
# This is used by TclX, but should otherwise be considered private
|
||||
declare 141 {
|
||||
CONST84_RETURN char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
|
||||
const char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
|
||||
}
|
||||
declare 142 {
|
||||
int TclSetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
|
||||
+139
-104
@@ -160,13 +160,13 @@ typedef struct Tcl_ResolvedVarInfo {
|
||||
} Tcl_ResolvedVarInfo;
|
||||
|
||||
typedef int (Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp,
|
||||
CONST84 char *name, int length, Tcl_Namespace *context,
|
||||
const char *name, int length, Tcl_Namespace *context,
|
||||
Tcl_ResolvedVarInfo **rPtr);
|
||||
|
||||
typedef int (Tcl_ResolveVarProc)(Tcl_Interp *interp, CONST84 char *name,
|
||||
typedef int (Tcl_ResolveVarProc)(Tcl_Interp *interp, const char *name,
|
||||
Tcl_Namespace *context, int flags, Tcl_Var *rPtr);
|
||||
|
||||
typedef int (Tcl_ResolveCmdProc)(Tcl_Interp *interp, CONST84 char *name,
|
||||
typedef int (Tcl_ResolveCmdProc)(Tcl_Interp *interp, const char *name,
|
||||
Tcl_Namespace *context, int flags, Tcl_Command *rPtr);
|
||||
|
||||
typedef struct Tcl_ResolverInfo {
|
||||
@@ -265,7 +265,7 @@ typedef struct Namespace {
|
||||
* strings; values have type (Namespace *). If
|
||||
* NULL, there are no children. */
|
||||
#endif
|
||||
size_t nsId; /* Unique id for the namespace. */
|
||||
unsigned long nsId; /* Unique id for the namespace. */
|
||||
Tcl_Interp *interp; /* The interpreter containing this
|
||||
* namespace. */
|
||||
int flags; /* OR-ed combination of the namespace status
|
||||
@@ -274,7 +274,7 @@ typedef struct Namespace {
|
||||
* frames for this namespace that are on the
|
||||
* Tcl call stack. The namespace won't be
|
||||
* freed until activationCount becomes zero. */
|
||||
int refCount; /* Count of references by namespaceName
|
||||
unsigned int refCount; /* Count of references by namespaceName
|
||||
* objects. The namespace can't be freed until
|
||||
* refCount becomes zero. */
|
||||
Tcl_HashTable cmdTable; /* Contains all the commands currently
|
||||
@@ -299,12 +299,12 @@ typedef struct Namespace {
|
||||
* registered using "namespace export". */
|
||||
int maxExportPatterns; /* Mumber of export patterns for which space
|
||||
* is currently allocated. */
|
||||
size_t cmdRefEpoch; /* Incremented if a newly added command
|
||||
unsigned int cmdRefEpoch; /* Incremented if a newly added command
|
||||
* shadows a command for which this namespace
|
||||
* has already cached a Command* pointer; this
|
||||
* causes all its cached Command* pointers to
|
||||
* be invalidated. */
|
||||
size_t resolverEpoch; /* Incremented whenever (a) the name
|
||||
unsigned int resolverEpoch; /* Incremented whenever (a) the name
|
||||
* resolution rules change for this namespace
|
||||
* or (b) a newly added command shadows a
|
||||
* command that is compiled to bytecodes. This
|
||||
@@ -331,7 +331,7 @@ typedef struct Namespace {
|
||||
* LookupCompiledLocal to resolve variable
|
||||
* references within the namespace at compile
|
||||
* time. */
|
||||
size_t exportLookupEpoch; /* Incremented whenever a command is added to
|
||||
unsigned int exportLookupEpoch; /* Incremented whenever a command is added to
|
||||
* a namespace, removed from a namespace or
|
||||
* the exports of a namespace are changed.
|
||||
* Allows TIP#112-driven command lists to be
|
||||
@@ -426,13 +426,13 @@ struct NamespacePathEntry {
|
||||
*/
|
||||
|
||||
typedef struct EnsembleConfig {
|
||||
Namespace *nsPtr; /* The namspace backing this ensemble up. */
|
||||
Namespace *nsPtr; /* The namespace backing this ensemble up. */
|
||||
Tcl_Command token; /* The token for the command that provides
|
||||
* ensemble support for the namespace, or NULL
|
||||
* if the command has been deleted (or never
|
||||
* existed; the global namespace never has an
|
||||
* ensemble command.) */
|
||||
size_t epoch; /* The epoch at which this ensemble's table of
|
||||
unsigned int epoch; /* The epoch at which this ensemble's table of
|
||||
* exported commands is valid. */
|
||||
char **subcommandArrayPtr; /* Array of ensemble subcommand names. At all
|
||||
* consistent points, this will have the same
|
||||
@@ -545,7 +545,7 @@ typedef struct CommandTrace {
|
||||
struct CommandTrace *nextPtr;
|
||||
/* Next in list of traces associated with a
|
||||
* particular command. */
|
||||
int refCount; /* Used to ensure this structure is not
|
||||
size_t refCount; /* Used to ensure this structure is not
|
||||
* deleted too early. Keeps track of how many
|
||||
* pieces of code have a pointer to this
|
||||
* structure. */
|
||||
@@ -618,7 +618,7 @@ typedef struct Var {
|
||||
|
||||
typedef struct VarInHash {
|
||||
Var var;
|
||||
int refCount; /* Counts number of active uses of this
|
||||
unsigned int refCount; /* Counts number of active uses of this
|
||||
* variable: 1 for the entry in the hash
|
||||
* table, 1 for each additional variable whose
|
||||
* linkPtr points here, 1 for each nested
|
||||
@@ -950,7 +950,7 @@ typedef struct CompiledLocal {
|
||||
typedef struct Proc {
|
||||
struct Interp *iPtr; /* Interpreter for which this command is
|
||||
* defined. */
|
||||
int refCount; /* Reference count: 1 if still present in
|
||||
unsigned int refCount; /* Reference count: 1 if still present in
|
||||
* command table plus 1 for each call to the
|
||||
* procedure that is currently active. This
|
||||
* structure can be freed when refCount
|
||||
@@ -1067,7 +1067,7 @@ typedef struct AssocData {
|
||||
*/
|
||||
|
||||
typedef struct LocalCache {
|
||||
int refCount;
|
||||
unsigned int refCount;
|
||||
int numVars;
|
||||
Tcl_Obj *varName0;
|
||||
} LocalCache;
|
||||
@@ -1229,7 +1229,7 @@ typedef struct CmdFrame {
|
||||
typedef struct CFWord {
|
||||
CmdFrame *framePtr; /* CmdFrame to access. */
|
||||
int word; /* Index of the word in the command. */
|
||||
int refCount; /* Number of times the word is on the
|
||||
unsigned int refCount; /* Number of times the word is on the
|
||||
* stack. */
|
||||
} CFWord;
|
||||
|
||||
@@ -1492,11 +1492,11 @@ typedef struct LiteralEntry {
|
||||
* NULL if end of chain. */
|
||||
Tcl_Obj *objPtr; /* Points to Tcl object that holds the
|
||||
* literal's bytes and length. */
|
||||
int refCount; /* If in an interpreter's global literal
|
||||
size_t refCount; /* If in an interpreter's global literal
|
||||
* table, the number of ByteCode structures
|
||||
* that share the literal object; the literal
|
||||
* entry can be freed when refCount drops to
|
||||
* 0. If in a local literal table, -1. */
|
||||
* 0. If in a local literal table, (size_t)-1. */
|
||||
Namespace *nsPtr; /* Namespace in which this literal is used. We
|
||||
* try to avoid sharing literal non-FQ command
|
||||
* names among different namespaces to reduce
|
||||
@@ -1516,7 +1516,7 @@ typedef struct LiteralTable {
|
||||
* table. */
|
||||
int rebuildSize; /* Enlarge table when numEntries gets to be
|
||||
* this large. */
|
||||
int mask; /* Mask value used in hashing function. */
|
||||
unsigned int mask; /* Mask value used in hashing function. */
|
||||
} LiteralTable;
|
||||
|
||||
/*
|
||||
@@ -1634,12 +1634,12 @@ typedef struct Command {
|
||||
* recreated). */
|
||||
Namespace *nsPtr; /* Points to the namespace containing this
|
||||
* command. */
|
||||
int refCount; /* 1 if in command hashtable plus 1 for each
|
||||
unsigned int refCount; /* 1 if in command hashtable plus 1 for each
|
||||
* reference from a CmdName Tcl object
|
||||
* representing a command's name in a ByteCode
|
||||
* instruction sequence. This structure can be
|
||||
* freed when refCount becomes zero. */
|
||||
size_t cmdEpoch; /* Incremented to invalidate any references
|
||||
unsigned int cmdEpoch; /* Incremented to invalidate any references
|
||||
* that point to this command when it is
|
||||
* renamed, deleted, hidden, or exposed. */
|
||||
CompileProc *compileProc; /* Procedure called to compile command. NULL
|
||||
@@ -1826,7 +1826,7 @@ typedef struct Interp {
|
||||
* unused space in interp was repurposed for
|
||||
* pluggable bytecode optimizers. The core
|
||||
* contains one optimizer, which can be
|
||||
* selectively overriden by extensions. */
|
||||
* selectively overridden by extensions. */
|
||||
} extra;
|
||||
|
||||
/*
|
||||
@@ -1862,7 +1862,7 @@ typedef struct Interp {
|
||||
* See Tcl_AppendResult code for details.
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
char *appendResult; /* Storage space for results generated by
|
||||
* Tcl_AppendResult. Ckalloc-ed. NULL means
|
||||
* not yet allocated. */
|
||||
@@ -1936,11 +1936,13 @@ typedef struct Interp {
|
||||
* string. Returned by Tcl_ObjSetVar2 when
|
||||
* variable traces change a variable in a
|
||||
* gross way. */
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
char resultSpace[TCL_RESULT_SIZE+1];
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
# if !defined(TCL_NO_DEPRECATED)
|
||||
char resultSpace[TCL_DSTRING_STATIC_SIZE+1];
|
||||
/* Static space holding small results. */
|
||||
#else
|
||||
char resultSpaceDontUse[TCL_RESULT_SIZE+1];
|
||||
# else
|
||||
char resultSpaceDontUse[TCL_DSTRING_STATIC_SIZE+1];
|
||||
# endif
|
||||
#endif
|
||||
Tcl_Obj *objResultPtr; /* If the last command returned an object
|
||||
* result, this points to it. Should not be
|
||||
@@ -2251,7 +2253,7 @@ typedef struct Interp {
|
||||
* use the rand() or srand() functions.
|
||||
* SAFE_INTERP: Non zero means that the current interp is a safe
|
||||
* interp (i.e. it has only the safe commands installed,
|
||||
* less priviledge than a regular interp).
|
||||
* less privilege than a regular interp).
|
||||
* INTERP_DEBUG_FRAME: Used for switching on various extra interpreter
|
||||
* debug/info mechanisms (e.g. info frame eval/uplevel
|
||||
* tracing) which are performance intensive.
|
||||
@@ -2384,7 +2386,7 @@ typedef enum TclEolTranslation {
|
||||
*/
|
||||
|
||||
typedef struct List {
|
||||
int refCount;
|
||||
unsigned int refCount;
|
||||
int maxElemCount; /* Total number of element array slots. */
|
||||
int elemCount; /* Current number of list elements. */
|
||||
int canonicalFlag; /* Set if the string representation was
|
||||
@@ -2392,7 +2394,7 @@ typedef struct List {
|
||||
* be ignored if there is no string rep at
|
||||
* all.*/
|
||||
Tcl_Obj *elements; /* First list element; the struct is grown to
|
||||
* accomodate all elements. */
|
||||
* accommodate all elements. */
|
||||
} List;
|
||||
|
||||
#define LIST_MAX \
|
||||
@@ -2445,40 +2447,46 @@ typedef struct List {
|
||||
#define TCL_EACH_COLLECT 1 /* Collect iteration result like [lmap] */
|
||||
|
||||
/*
|
||||
* Macros providing a faster path to integers: Tcl_GetLongFromObj,
|
||||
* Tcl_GetIntFromObj and TclGetIntForIndex.
|
||||
* Macros providing a faster path to booleans and integers:
|
||||
* Tcl_GetBooleanFromObj, Tcl_GetLongFromObj, Tcl_GetIntFromObj
|
||||
* and TclGetIntForIndex.
|
||||
*
|
||||
* WARNING: these macros eval their args more than once.
|
||||
*/
|
||||
|
||||
#define TclGetBooleanFromObj(interp, objPtr, boolPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType) \
|
||||
? (*(boolPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK) \
|
||||
: ((objPtr)->typePtr == &tclBooleanType) \
|
||||
? (*(boolPtr) = ((objPtr)->internalRep.longValue!=0), TCL_OK) \
|
||||
: Tcl_GetBooleanFromObj((interp), (objPtr), (boolPtr)))
|
||||
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
#define TclGetLongFromObj(interp, objPtr, longPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType) \
|
||||
? ((*(longPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
|
||||
? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \
|
||||
: Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
|
||||
|
||||
#if (LONG_MAX == INT_MAX)
|
||||
#define TclGetIntFromObj(interp, objPtr, intPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType) \
|
||||
? ((*(intPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
|
||||
: Tcl_GetIntFromObj((interp), (objPtr), (intPtr)))
|
||||
#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType) \
|
||||
? ((*(idxPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
|
||||
: TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))
|
||||
#else
|
||||
#define TclGetLongFromObj(interp, objPtr, longPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType \
|
||||
&& (objPtr)->internalRep.wideValue >= -(Tcl_WideInt)(ULONG_MAX) \
|
||||
&& (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(ULONG_MAX)) \
|
||||
? ((*(longPtr) = (long)(objPtr)->internalRep.wideValue), TCL_OK) \
|
||||
: Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
|
||||
#endif
|
||||
|
||||
#define TclGetIntFromObj(interp, objPtr, intPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType \
|
||||
&& (objPtr)->internalRep.longValue >= -(Tcl_WideInt)(UINT_MAX) \
|
||||
&& (objPtr)->internalRep.longValue <= (Tcl_WideInt)(UINT_MAX)) \
|
||||
? ((*(intPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
|
||||
&& (objPtr)->internalRep.wideValue >= -(Tcl_WideInt)(UINT_MAX) \
|
||||
&& (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(UINT_MAX)) \
|
||||
? ((*(intPtr) = (int)(objPtr)->internalRep.wideValue), TCL_OK) \
|
||||
: Tcl_GetIntFromObj((interp), (objPtr), (intPtr)))
|
||||
#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType \
|
||||
&& (objPtr)->internalRep.longValue >= INT_MIN \
|
||||
&& (objPtr)->internalRep.longValue <= INT_MAX) \
|
||||
? ((*(idxPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
|
||||
&& (objPtr)->internalRep.wideValue >= INT_MIN \
|
||||
&& (objPtr)->internalRep.wideValue <= INT_MAX) \
|
||||
? ((*(idxPtr) = (int)(objPtr)->internalRep.wideValue), TCL_OK) \
|
||||
: TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro used to save a function call for common uses of
|
||||
@@ -2488,21 +2496,11 @@ typedef struct List {
|
||||
* Tcl_WideInt *wideIntPtr);
|
||||
*/
|
||||
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType) \
|
||||
? (*(wideIntPtr) = (Tcl_WideInt) \
|
||||
((objPtr)->internalRep.longValue), TCL_OK) : \
|
||||
((objPtr)->internalRep.wideValue), TCL_OK) : \
|
||||
Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
|
||||
#else /* !TCL_WIDE_INT_IS_LONG */
|
||||
#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
|
||||
(((objPtr)->typePtr == &tclWideIntType) \
|
||||
? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \
|
||||
((objPtr)->typePtr == &tclIntType) \
|
||||
? (*(wideIntPtr) = (Tcl_WideInt) \
|
||||
((objPtr)->internalRep.longValue), TCL_OK) : \
|
||||
Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
/*
|
||||
* Flag values for TclTraceDictPath().
|
||||
@@ -2514,13 +2512,13 @@ typedef struct List {
|
||||
* tip of the path, so duplication of shared objects should be done along the
|
||||
* way.
|
||||
*
|
||||
* DICT_PATH_EXISTS indicates that we are performing an existance test and a
|
||||
* DICT_PATH_EXISTS indicates that we are performing an existence test and a
|
||||
* lookup failure should therefore not be an error. If (and only if) this flag
|
||||
* is set, TclTraceDictPath() will return the special value
|
||||
* DICT_PATH_NON_EXISTENT if the path is not traceable.
|
||||
*
|
||||
* DICT_PATH_CREATE (which also requires the DICT_PATH_UPDATE bit to be set)
|
||||
* indicates that we are to create non-existant dictionaries on the path.
|
||||
* indicates that we are to create non-existent dictionaries on the path.
|
||||
*/
|
||||
|
||||
#define DICT_PATH_READ 0
|
||||
@@ -2626,7 +2624,7 @@ typedef Tcl_ObjCmdProc *TclObjCmdProcType;
|
||||
*----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, size_t *lengthPtr,
|
||||
typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, unsigned int *lengthPtr,
|
||||
Tcl_Encoding *encodingPtr);
|
||||
|
||||
/*
|
||||
@@ -2638,9 +2636,9 @@ typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, size_t *lengthPtr,
|
||||
*/
|
||||
|
||||
typedef struct ProcessGlobalValue {
|
||||
size_t epoch; /* Epoch counter to detect changes in the
|
||||
unsigned int epoch; /* Epoch counter to detect changes in the
|
||||
* master value. */
|
||||
size_t numBytes; /* Length of the master string. */
|
||||
unsigned int numBytes; /* Length of the master string. */
|
||||
char *value; /* The master string value. */
|
||||
Tcl_Encoding encoding; /* system encoding when master string was
|
||||
* initialized. */
|
||||
@@ -2728,9 +2726,6 @@ MODULE_SCOPE const Tcl_ObjType tclDictType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclProcBodyType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclStringType;
|
||||
MODULE_SCOPE const Tcl_ObjType tclEnsembleCmdType;
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
MODULE_SCOPE const Tcl_ObjType tclWideIntType;
|
||||
#endif
|
||||
MODULE_SCOPE const Tcl_ObjType tclRegexpType;
|
||||
MODULE_SCOPE Tcl_ObjType tclCmdNameType;
|
||||
|
||||
@@ -2780,6 +2775,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRForObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRForeachCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRIfObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRLmapCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRPackageObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRSourceObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRSubstObjCmd;
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclNRSwitchObjCmd;
|
||||
@@ -2960,10 +2956,8 @@ MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr,
|
||||
MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr);
|
||||
MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp,
|
||||
Tcl_Obj *const *objv, int objc, int *objcPtr);
|
||||
Tcl_Namespace * TclEnsureNamespace(
|
||||
Tcl_Interp *interp,
|
||||
MODULE_SCOPE Tcl_Namespace * TclEnsureNamespace(Tcl_Interp *interp,
|
||||
Tcl_Namespace *namespacePtr);
|
||||
|
||||
MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
|
||||
MODULE_SCOPE void TclFinalizeAsync(void);
|
||||
MODULE_SCOPE void TclFinalizeDoubleConversion(void);
|
||||
@@ -3125,7 +3119,7 @@ MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr,
|
||||
int stackSize, int flags);
|
||||
MODULE_SCOPE int TclpFindVariable(const char *name, int *lengthPtr);
|
||||
MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr,
|
||||
size_t *lengthPtr, Tcl_Encoding *encodingPtr);
|
||||
unsigned int *lengthPtr, Tcl_Encoding *encodingPtr);
|
||||
MODULE_SCOPE void TclpInitLock(void);
|
||||
MODULE_SCOPE void TclpInitPlatform(void);
|
||||
MODULE_SCOPE void TclpInitUnlock(void);
|
||||
@@ -3159,7 +3153,6 @@ MODULE_SCOPE Tcl_Obj * TclPathPart(Tcl_Interp *interp, Tcl_Obj *pathPtr,
|
||||
Tcl_PathPart portion);
|
||||
MODULE_SCOPE char * TclpReadlink(const char *fileName,
|
||||
Tcl_DString *linkPtr);
|
||||
MODULE_SCOPE void TclpSetInterfaces(void);
|
||||
MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp);
|
||||
MODULE_SCOPE void * TclThreadStorageKeyGet(Tcl_ThreadDataKey *keyPtr);
|
||||
MODULE_SCOPE void TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr,
|
||||
@@ -3190,20 +3183,10 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp,
|
||||
Tcl_Obj *bad, Tcl_Obj *fix);
|
||||
MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
|
||||
int numBytes);
|
||||
MODULE_SCOPE int TclStringCatObjv(Tcl_Interp *interp, int inPlace,
|
||||
int objc, Tcl_Obj *const objv[],
|
||||
Tcl_Obj **objPtrPtr);
|
||||
MODULE_SCOPE int TclStringFind(Tcl_Obj *needle, Tcl_Obj *haystack,
|
||||
int start);
|
||||
MODULE_SCOPE int TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack,
|
||||
int last);
|
||||
MODULE_SCOPE int TclStringMatch(const char *str, int strLen,
|
||||
const char *pattern, int ptnLen, int flags);
|
||||
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
|
||||
Tcl_Obj *patternObj, int flags);
|
||||
MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE int TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int count, Tcl_Obj **objPtrPtr);
|
||||
MODULE_SCOPE void TclSubstCompile(Tcl_Interp *interp, const char *bytes,
|
||||
int numBytes, int flags, int line,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3215,6 +3198,8 @@ MODULE_SCOPE void TclSubstParse(Tcl_Interp *interp, const char *bytes,
|
||||
MODULE_SCOPE int TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
|
||||
int count, int *tokensLeftPtr, int line,
|
||||
int *clNextOuter, const char *outerScript);
|
||||
MODULE_SCOPE int TclTrim(const char *bytes, int numBytes,
|
||||
const char *trim, int numTrim, int *trimRight);
|
||||
MODULE_SCOPE int TclTrimLeft(const char *bytes, int numBytes,
|
||||
const char *trim, int numTrim);
|
||||
MODULE_SCOPE int TclTrimRight(const char *bytes, int numBytes,
|
||||
@@ -3269,7 +3254,7 @@ MODULE_SCOPE Tcl_Command TclInitBinaryCmd(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int Tcl_BreakObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
MODULE_SCOPE int Tcl_CaseObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -4008,6 +3993,29 @@ MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
|
||||
/*
|
||||
* Routines that provide the [string] ensemble functionality. Possible
|
||||
* candidates for public interface.
|
||||
*/
|
||||
|
||||
MODULE_SCOPE Tcl_Obj * TclStringCat(Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[], int flags);
|
||||
MODULE_SCOPE int TclStringFirst(Tcl_Obj *needle, Tcl_Obj *haystack,
|
||||
int start);
|
||||
MODULE_SCOPE int TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack,
|
||||
int last);
|
||||
MODULE_SCOPE Tcl_Obj * TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int count, int flags);
|
||||
MODULE_SCOPE Tcl_Obj * TclStringReplace(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int first, int count, Tcl_Obj *insertPtr,
|
||||
int flags);
|
||||
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)
|
||||
|
||||
/*
|
||||
* Functions defined in generic/tclVar.c and currently exported only for use
|
||||
* by the bytecode compiler and engine. Some of these could later be placed in
|
||||
@@ -4063,6 +4071,45 @@ MODULE_SCOPE TCL_HASH_TYPE TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
|
||||
MODULE_SCOPE int TclFullFinalizationRequested(void);
|
||||
|
||||
/*
|
||||
* TIP #462.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following enum values give the status of a spawned process.
|
||||
*/
|
||||
|
||||
typedef enum TclProcessWaitStatus {
|
||||
TCL_PROCESS_ERROR = -1, /* Error waiting for process to exit */
|
||||
TCL_PROCESS_UNCHANGED = 0, /* No change since the last call. */
|
||||
TCL_PROCESS_EXITED = 1, /* Process has exited. */
|
||||
TCL_PROCESS_SIGNALED = 2, /* Child killed because of a signal. */
|
||||
TCL_PROCESS_STOPPED = 3, /* Child suspended because of a signal. */
|
||||
TCL_PROCESS_UNKNOWN_STATUS = 4
|
||||
/* Child wait status didn't make sense. */
|
||||
} TclProcessWaitStatus;
|
||||
|
||||
MODULE_SCOPE Tcl_Command TclInitProcessCmd(Tcl_Interp *interp);
|
||||
MODULE_SCOPE void TclProcessCreated(Tcl_Pid pid);
|
||||
MODULE_SCOPE TclProcessWaitStatus TclProcessWait(Tcl_Pid pid, int options,
|
||||
int *codePtr, Tcl_Obj **msgObjPtr,
|
||||
Tcl_Obj **errorObjPtr);
|
||||
|
||||
/*
|
||||
* Utility routines for encoding index values as integers. Used by both
|
||||
* some of the command compilers and by [lsort] and [lsearch].
|
||||
*/
|
||||
|
||||
MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int before, int after, int *indexPtr);
|
||||
MODULE_SCOPE int TclIndexDecode(int encoded, int endValue);
|
||||
|
||||
/* Constants used in index value encoding routines. */
|
||||
#define TCL_INDEX_END (-2)
|
||||
#define TCL_INDEX_BEFORE (-1)
|
||||
#define TCL_INDEX_START (0)
|
||||
#define TCL_INDEX_AFTER (INT_MAX)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Macros used by the Tcl core to create and release Tcl objects.
|
||||
@@ -4572,30 +4619,19 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
* core. They should only be called on unshared objects. The ANSI C
|
||||
* "prototypes" for these macros are:
|
||||
*
|
||||
* MODULE_SCOPE void TclSetLongObj(Tcl_Obj *objPtr, long longValue);
|
||||
* MODULE_SCOPE void TclSetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclSetIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d);
|
||||
*----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define TclSetLongObj(objPtr, i) \
|
||||
#define TclSetIntObj(objPtr, i) \
|
||||
do { \
|
||||
TclInvalidateStringRep(objPtr); \
|
||||
TclFreeIntRep(objPtr); \
|
||||
(objPtr)->internalRep.longValue = (long)(i); \
|
||||
(objPtr)->internalRep.wideValue = (Tcl_WideInt)(i); \
|
||||
(objPtr)->typePtr = &tclIntType; \
|
||||
} while (0)
|
||||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
#define TclSetWideIntObj(objPtr, w) \
|
||||
do { \
|
||||
TclInvalidateStringRep(objPtr); \
|
||||
TclFreeIntRep(objPtr); \
|
||||
(objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \
|
||||
(objPtr)->typePtr = &tclWideIntType; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define TclSetDoubleObj(objPtr, d) \
|
||||
do { \
|
||||
TclInvalidateStringRep(objPtr); \
|
||||
@@ -4610,8 +4646,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
* types, avoiding the corresponding function calls in time critical parts of
|
||||
* the core. The ANSI C "prototypes" for these macros are:
|
||||
*
|
||||
* MODULE_SCOPE void TclNewLongObj(Tcl_Obj *objPtr, long l);
|
||||
* MODULE_SCOPE void TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclNewIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d);
|
||||
* MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, int len);
|
||||
* MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, const char *sLiteral);
|
||||
@@ -4620,13 +4655,13 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
*/
|
||||
|
||||
#ifndef TCL_MEM_DEBUG
|
||||
#define TclNewLongObj(objPtr, i) \
|
||||
#define TclNewIntObj(objPtr, i) \
|
||||
do { \
|
||||
TclIncrObjsAllocated(); \
|
||||
TclAllocObjStorage(objPtr); \
|
||||
(objPtr)->refCount = 0; \
|
||||
(objPtr)->bytes = NULL; \
|
||||
(objPtr)->internalRep.longValue = (long)(i); \
|
||||
(objPtr)->internalRep.wideValue = (Tcl_WideInt)(i); \
|
||||
(objPtr)->typePtr = &tclIntType; \
|
||||
TCL_DTRACE_OBJ_CREATE(objPtr); \
|
||||
} while (0)
|
||||
@@ -4653,8 +4688,8 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
} while (0)
|
||||
|
||||
#else /* TCL_MEM_DEBUG */
|
||||
#define TclNewLongObj(objPtr, l) \
|
||||
(objPtr) = Tcl_NewLongObj(l)
|
||||
#define TclNewIntObj(objPtr, w) \
|
||||
(objPtr) = Tcl_NewWideIntObj(w)
|
||||
|
||||
#define TclNewDoubleObj(objPtr, d) \
|
||||
(objPtr) = Tcl_NewDoubleObj(d)
|
||||
|
||||
+27
-63
@@ -28,6 +28,22 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9)
|
||||
/* Those macro's are especially for Itcl 3.4 compatibility */
|
||||
# define tclCreateNamespace tcl_CreateNamespace
|
||||
# define tclDeleteNamespace tcl_DeleteNamespace
|
||||
# define tclAppendExportList tcl_AppendExportList
|
||||
# define tclExport tcl_Export
|
||||
# define tclImport tcl_Import
|
||||
# define tclForgetImport tcl_ForgetImport
|
||||
# define tclGetCurrentNamespace_ tcl_GetCurrentNamespace
|
||||
# define tclGetGlobalNamespace_ tcl_GetGlobalNamespace
|
||||
# define tclFindNamespace tcl_FindNamespace
|
||||
# define tclFindCommand tcl_FindCommand
|
||||
# define tclGetCommandFromObj tcl_GetCommandFromObj
|
||||
# define tclGetCommandFullName tcl_GetCommandFullName
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
|
||||
/*
|
||||
* WARNING: This file is automatically generated by the tools/genStubs.tcl
|
||||
* script. Any modifications to the function declarations below should be made
|
||||
@@ -98,7 +114,7 @@ EXTERN int TclFindElement(Tcl_Interp *interp,
|
||||
/* 23 */
|
||||
EXTERN Proc * TclFindProc(Interp *iPtr, const char *procName);
|
||||
/* 24 */
|
||||
EXTERN int TclFormatInt(char *buffer, long n);
|
||||
EXTERN int TclFormatInt(char *buffer, Tcl_WideInt n);
|
||||
/* 25 */
|
||||
EXTERN void TclFreePackageInfo(Interp *iPtr);
|
||||
/* Slot 26 is reserved */
|
||||
@@ -158,7 +174,7 @@ EXTERN int TclInterpInit(Tcl_Interp *interp);
|
||||
/* 53 */
|
||||
EXTERN int TclInvokeObjectCommand(ClientData clientData,
|
||||
Tcl_Interp *interp, int argc,
|
||||
CONST84 char **argv);
|
||||
const char **argv);
|
||||
/* 54 */
|
||||
EXTERN int TclInvokeStringCommand(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
@@ -217,7 +233,8 @@ EXTERN char * TclpRealloc(char *ptr, unsigned int size);
|
||||
/* Slot 86 is reserved */
|
||||
/* Slot 87 is reserved */
|
||||
/* 88 */
|
||||
EXTERN char * TclPrecTraceProc(ClientData clientData,
|
||||
TCL_DEPRECATED("")
|
||||
char * TclPrecTraceProc(ClientData clientData,
|
||||
Tcl_Interp *interp, const char *name1,
|
||||
const char *name2, int flags);
|
||||
/* 89 */
|
||||
@@ -344,13 +361,11 @@ struct tm * TclpGetDate(const time_t *time, int useGMT);
|
||||
/* Slot 136 is reserved */
|
||||
/* Slot 137 is reserved */
|
||||
/* 138 */
|
||||
EXTERN CONST84_RETURN char * TclGetEnv(const char *name,
|
||||
Tcl_DString *valuePtr);
|
||||
EXTERN const char * TclGetEnv(const char *name, Tcl_DString *valuePtr);
|
||||
/* Slot 139 is reserved */
|
||||
/* Slot 140 is reserved */
|
||||
/* 141 */
|
||||
EXTERN CONST84_RETURN char * TclpGetCwd(Tcl_Interp *interp,
|
||||
Tcl_DString *cwdPtr);
|
||||
EXTERN const char * TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr);
|
||||
/* 142 */
|
||||
EXTERN int TclSetByteCodeFromAny(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, CompileHookProc *hookProc,
|
||||
@@ -663,7 +678,7 @@ typedef struct TclIntStubs {
|
||||
void (*reserved21)(void);
|
||||
int (*tclFindElement) (Tcl_Interp *interp, const char *listStr, int listLength, const char **elementPtr, const char **nextPtr, int *sizePtr, int *bracePtr); /* 22 */
|
||||
Proc * (*tclFindProc) (Interp *iPtr, const char *procName); /* 23 */
|
||||
int (*tclFormatInt) (char *buffer, long n); /* 24 */
|
||||
int (*tclFormatInt) (char *buffer, Tcl_WideInt n); /* 24 */
|
||||
void (*tclFreePackageInfo) (Interp *iPtr); /* 25 */
|
||||
void (*reserved26)(void);
|
||||
void (*reserved27)(void);
|
||||
@@ -692,7 +707,7 @@ typedef struct TclIntStubs {
|
||||
void (*tclInitCompiledLocals) (Tcl_Interp *interp, CallFrame *framePtr, Namespace *nsPtr); /* 50 */
|
||||
int (*tclInterpInit) (Tcl_Interp *interp); /* 51 */
|
||||
void (*reserved52)(void);
|
||||
int (*tclInvokeObjectCommand) (ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char **argv); /* 53 */
|
||||
int (*tclInvokeObjectCommand) (ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); /* 53 */
|
||||
int (*tclInvokeStringCommand) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 54 */
|
||||
Proc * (*tclIsProc) (Command *cmdPtr); /* 55 */
|
||||
void (*reserved56)(void);
|
||||
@@ -727,7 +742,7 @@ typedef struct TclIntStubs {
|
||||
void (*reserved85)(void);
|
||||
void (*reserved86)(void);
|
||||
void (*reserved87)(void);
|
||||
char * (*tclPrecTraceProc) (ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); /* 88 */
|
||||
TCL_DEPRECATED_API("") char * (*tclPrecTraceProc) (ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); /* 88 */
|
||||
int (*tclPreventAliasLoop) (Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd); /* 89 */
|
||||
void (*reserved90)(void);
|
||||
void (*tclProcCleanupProc) (Proc *procPtr); /* 91 */
|
||||
@@ -777,10 +792,10 @@ typedef struct TclIntStubs {
|
||||
void (*reserved135)(void);
|
||||
void (*reserved136)(void);
|
||||
void (*reserved137)(void);
|
||||
CONST84_RETURN char * (*tclGetEnv) (const char *name, Tcl_DString *valuePtr); /* 138 */
|
||||
const char * (*tclGetEnv) (const char *name, Tcl_DString *valuePtr); /* 138 */
|
||||
void (*reserved139)(void);
|
||||
void (*reserved140)(void);
|
||||
CONST84_RETURN char * (*tclpGetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 141 */
|
||||
const char * (*tclpGetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 141 */
|
||||
int (*tclSetByteCodeFromAny) (Tcl_Interp *interp, Tcl_Obj *objPtr, CompileHookProc *hookProc, ClientData clientData); /* 142 */
|
||||
int (*tclAddLiteralObj) (struct CompileEnv *envPtr, Tcl_Obj *objPtr, LiteralEntry **litPtrPtr); /* 143 */
|
||||
void (*tclHideLiteral) (Tcl_Interp *interp, struct CompileEnv *envPtr, int index); /* 144 */
|
||||
@@ -1367,57 +1382,6 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
# undef TclGetCommandFullName
|
||||
# undef TclCopyChannelOld
|
||||
# undef TclSockMinimumBuffersOld
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED)
|
||||
# undef Tcl_CreateNamespace
|
||||
# define Tcl_CreateNamespace \
|
||||
(tclIntStubsPtr->tclCreateNamespace) /* 113 */
|
||||
# define tcl_CreateNamespace tclCreateNamespace
|
||||
# undef Tcl_DeleteNamespace
|
||||
# define Tcl_DeleteNamespace \
|
||||
(tclIntStubsPtr->tclDeleteNamespace) /* 114 */
|
||||
# define tcl_DeleteNamespace tclDeleteNamespace
|
||||
# undef Tcl_AppendExportList
|
||||
# define Tcl_AppendExportList \
|
||||
(tclIntStubsPtr->tclAppendExportList) /* 112 */
|
||||
# define tcl_AppendExportList tclAppendExportList
|
||||
# undef Tcl_Export
|
||||
# define Tcl_Export \
|
||||
(tclIntStubsPtr->tclExport) /* 115 */
|
||||
# define tcl_Export tclExport
|
||||
# undef Tcl_Import
|
||||
# define Tcl_Import \
|
||||
(tclIntStubsPtr->tclImport) /* 127 */
|
||||
# define tcl_Import tclImport
|
||||
# undef Tcl_ForgetImport
|
||||
# define Tcl_ForgetImport \
|
||||
(tclIntStubsPtr->tclForgetImport) /* 121 */
|
||||
# define tcl_ForgetImport tclForgetImport
|
||||
# undef Tcl_GetCurrentNamespace
|
||||
# define Tcl_GetCurrentNamespace \
|
||||
(tclIntStubsPtr->tclGetCurrentNamespace_) /* 124 */
|
||||
# define tcl_GetCurrentNamespace tclGetCurrentNamespace_
|
||||
# undef Tcl_GetGlobalNamespace
|
||||
# define Tcl_GetGlobalNamespace \
|
||||
(tclIntStubsPtr->tclGetGlobalNamespace_) /* 125 */
|
||||
# define tcl_GetGlobalNamespace tclGetGlobalNamespace_
|
||||
# undef Tcl_FindNamespace
|
||||
# define Tcl_FindNamespace \
|
||||
(tclIntStubsPtr->tclFindNamespace) /* 117 */
|
||||
# define tcl_FindNamespace tclFindNamespace
|
||||
# undef Tcl_FindCommand
|
||||
# define Tcl_FindCommand \
|
||||
(tclIntStubsPtr->tclFindCommand) /* 116 */
|
||||
# define tcl_FindCommand tclFindCommand
|
||||
# undef Tcl_GetCommandFromObj
|
||||
# define Tcl_GetCommandFromObj \
|
||||
(tclIntStubsPtr->tclGetCommandFromObj) /* 122 */
|
||||
# define tcl_GetCommandFromObj tclGetCommandFromObj
|
||||
# undef Tcl_GetCommandFullName
|
||||
# define Tcl_GetCommandFullName \
|
||||
(tclIntStubsPtr->tclGetCommandFullName) /* 123 */
|
||||
# define tcl_GetCommandFullName tclGetCommandFullName
|
||||
#endif /* !defined(TCL_NO_DEPRECATED) */
|
||||
#endif
|
||||
|
||||
#endif /* _TCLINTDECLS */
|
||||
|
||||
@@ -555,12 +555,18 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
# undef TclWinGetServByName
|
||||
# undef TclWinGetSockOpt
|
||||
# undef TclWinSetSockOpt
|
||||
# define TclWinNToHS ntohs
|
||||
# define TclWinGetServByName getservbyname
|
||||
# define TclWinGetSockOpt getsockopt
|
||||
# define TclWinSetSockOpt setsockopt
|
||||
# undef TclWinGetPlatformId
|
||||
# define TclWinGetPlatformId() (2) /* VER_PLATFORM_WIN32_NT */
|
||||
# undef TclWinResetInterfaces
|
||||
# undef TclWinSetInterfaces
|
||||
# if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
# define TclWinNToHS ntohs
|
||||
# define TclWinGetServByName getservbyname
|
||||
# define TclWinGetSockOpt getsockopt
|
||||
# define TclWinSetSockOpt setsockopt
|
||||
# define TclWinGetPlatformId() (2) /* VER_PLATFORM_WIN32_NT */
|
||||
# define TclWinResetInterfaces() /* nop */
|
||||
# define TclWinSetInterfaces(dummy) /* nop */
|
||||
# endif /* TCL_NO_DEPRECATED */
|
||||
#else
|
||||
# undef TclpGetPid
|
||||
# define TclpGetPid(pid) ((unsigned long) (pid))
|
||||
|
||||
+4
-10
@@ -1165,17 +1165,11 @@ TclLindexList(
|
||||
return TclLindexFlat(interp, listPtr, 1, &argPtr);
|
||||
}
|
||||
|
||||
if (indexListCopy->typePtr == &tclListType) {
|
||||
List *listRepPtr = ListRepPtr(indexListCopy);
|
||||
{
|
||||
int indexCount = -1; /* Size of the array of list indices. */
|
||||
Tcl_Obj **indices = NULL; /* Array of list indices. */
|
||||
|
||||
listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount,
|
||||
&listRepPtr->elements);
|
||||
} else {
|
||||
int indexCount = -1; /* Size of the array of list indices. */
|
||||
Tcl_Obj **indices = NULL;
|
||||
/* Array of list indices. */
|
||||
|
||||
Tcl_ListObjGetElements(NULL, indexListCopy, &indexCount, &indices);
|
||||
TclListObjGetElements(NULL, indexListCopy, &indexCount, &indices);
|
||||
listPtr = TclLindexFlat(interp, listPtr, indexCount, indices);
|
||||
}
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
|
||||
+12
-11
@@ -186,7 +186,7 @@ TclCreateLiteral(
|
||||
{
|
||||
LiteralTable *globalTablePtr = &iPtr->literalTable;
|
||||
LiteralEntry *globalPtr;
|
||||
int globalHash;
|
||||
unsigned int globalHash;
|
||||
Tcl_Obj *objPtr;
|
||||
|
||||
/*
|
||||
@@ -393,7 +393,8 @@ TclRegisterLiteral(
|
||||
LiteralEntry *globalPtr, *localPtr;
|
||||
Tcl_Obj *objPtr;
|
||||
unsigned hash;
|
||||
int localHash, objIndex, new;
|
||||
unsigned int localHash;
|
||||
int objIndex, new;
|
||||
Namespace *nsPtr;
|
||||
|
||||
if (length < 0) {
|
||||
@@ -537,7 +538,8 @@ TclHideLiteral(
|
||||
{
|
||||
LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
|
||||
LiteralTable *localTablePtr = &envPtr->localLitTable;
|
||||
int localHash, length;
|
||||
unsigned int localHash;
|
||||
int length;
|
||||
const char *bytes;
|
||||
Tcl_Obj *newObjPtr;
|
||||
|
||||
@@ -556,7 +558,7 @@ TclHideLiteral(
|
||||
lPtr->objPtr = newObjPtr;
|
||||
|
||||
bytes = TclGetStringFromObj(newObjPtr, &length);
|
||||
localHash = (HashString(bytes, length) & localTablePtr->mask);
|
||||
localHash = HashString(bytes, length) & localTablePtr->mask;
|
||||
nextPtrPtr = &localTablePtr->buckets[localHash];
|
||||
|
||||
for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) {
|
||||
@@ -612,7 +614,7 @@ TclAddLiteralObj(
|
||||
lPtr = &envPtr->literalArrayPtr[objIndex];
|
||||
lPtr->objPtr = objPtr;
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
lPtr->refCount = -1; /* i.e., unused */
|
||||
lPtr->refCount = (size_t)-1; /* i.e., unused */
|
||||
lPtr->nextPtr = NULL;
|
||||
|
||||
if (litPtrPtr) {
|
||||
@@ -809,7 +811,8 @@ TclReleaseLiteral(
|
||||
LiteralTable *globalTablePtr;
|
||||
register LiteralEntry *entryPtr, *prevPtr;
|
||||
const char *bytes;
|
||||
int length, index;
|
||||
int length;
|
||||
unsigned int index;
|
||||
|
||||
if (iPtr == NULL) {
|
||||
goto done;
|
||||
@@ -828,15 +831,13 @@ TclReleaseLiteral(
|
||||
for (prevPtr=NULL, entryPtr=globalTablePtr->buckets[index];
|
||||
entryPtr!=NULL ; prevPtr=entryPtr, entryPtr=entryPtr->nextPtr) {
|
||||
if (entryPtr->objPtr == objPtr) {
|
||||
entryPtr->refCount--;
|
||||
|
||||
/*
|
||||
* If the literal is no longer being used by any ByteCode, delete
|
||||
* the entry then remove the reference corresponding to the global
|
||||
* literal table entry (decrement the ref count of the object).
|
||||
*/
|
||||
|
||||
if (entryPtr->refCount == 0) {
|
||||
if (entryPtr->refCount-- <= 1) {
|
||||
if (prevPtr == NULL) {
|
||||
globalTablePtr->buckets[index] = entryPtr->nextPtr;
|
||||
} else {
|
||||
@@ -954,8 +955,8 @@ RebuildLiteralTable(
|
||||
register LiteralEntry *entryPtr;
|
||||
LiteralEntry **bucketPtr;
|
||||
const char *bytes;
|
||||
unsigned int oldSize;
|
||||
int count, index, length;
|
||||
unsigned int oldSize, index;
|
||||
int count, length;
|
||||
|
||||
oldSize = tablePtr->numBuckets;
|
||||
oldBuckets = tablePtr->buckets;
|
||||
|
||||
@@ -470,6 +470,19 @@ Tcl_LoadObjCmd(
|
||||
*/
|
||||
|
||||
if (code != TCL_OK) {
|
||||
#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8
|
||||
Interp *iPtr = (Interp *) target;
|
||||
if (iPtr->result && *(iPtr->result) && !iPtr->freeProc) {
|
||||
/*
|
||||
* A call to Tcl_InitStubs() determined the caller extension and
|
||||
* this interp are incompatible in their stubs mechanisms, and
|
||||
* recorded the error in the oldest legacy place we have to do so.
|
||||
*/
|
||||
Tcl_SetObjResult(target, Tcl_NewStringObj(iPtr->result, -1));
|
||||
iPtr->result = &tclEmptyString;
|
||||
iPtr->freeProc = NULL;
|
||||
}
|
||||
#endif /* defined(TCL_NO_DEPRECATED) */
|
||||
Tcl_TransferResult(target, code, interp);
|
||||
goto done;
|
||||
}
|
||||
|
||||
+9
-12
@@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
size_t numNsCreated; /* Count of the number of namespaces created
|
||||
unsigned long numNsCreated; /* Count of the number of namespaces created
|
||||
* within the thread. This value is used as a
|
||||
* unique id for each namespace. Cannot be
|
||||
* per-interp because the nsId is used to
|
||||
@@ -402,7 +402,7 @@ Tcl_PopCallFrame(
|
||||
}
|
||||
if (framePtr->numCompiledLocals > 0) {
|
||||
TclDeleteCompiledLocalVars(iPtr, framePtr);
|
||||
if (--framePtr->localCachePtr->refCount == 0) {
|
||||
if (framePtr->localCachePtr->refCount-- <= 1) {
|
||||
TclFreeLocalCache(interp, framePtr->localCachePtr);
|
||||
}
|
||||
framePtr->localCachePtr = NULL;
|
||||
@@ -915,6 +915,11 @@ Tcl_DeleteNamespace(
|
||||
Tcl_HashSearch search;
|
||||
Command *cmdPtr;
|
||||
|
||||
/*
|
||||
* Ensure that this namespace doesn't get deallocated in the meantime.
|
||||
*/
|
||||
nsPtr->refCount++;
|
||||
|
||||
/*
|
||||
* Give anyone interested - notably TclOO - a chance to use this namespace
|
||||
* normally despite the fact that the namespace is going to go. Allows the
|
||||
@@ -1047,16 +1052,7 @@ Tcl_DeleteNamespace(
|
||||
#endif
|
||||
Tcl_DeleteHashTable(&nsPtr->cmdTable);
|
||||
|
||||
/*
|
||||
* If the reference count is 0, then discard the namespace.
|
||||
* Otherwise, mark it as "dead" so that it can't be used.
|
||||
*/
|
||||
|
||||
if (nsPtr->refCount == 0) {
|
||||
NamespaceFree(nsPtr);
|
||||
} else {
|
||||
nsPtr->flags |= NS_DEAD;
|
||||
}
|
||||
nsPtr ->flags |= NS_DEAD;
|
||||
} else {
|
||||
/*
|
||||
* Restore the ::errorInfo and ::errorCode traces.
|
||||
@@ -1073,6 +1069,7 @@ Tcl_DeleteNamespace(
|
||||
nsPtr->flags &= ~(NS_DYING|NS_KILLED);
|
||||
}
|
||||
}
|
||||
TclNsDecrRefCount(nsPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+422
-401
File diff suppressed because it is too large
Load Diff
@@ -1206,22 +1206,10 @@ TclOOCopyObjectCmd(
|
||||
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, NULL, NULL);
|
||||
} else {
|
||||
const char *name, *namespaceName;
|
||||
Tcl_DString buffer;
|
||||
|
||||
name = TclGetString(objv[2]);
|
||||
Tcl_DStringInit(&buffer);
|
||||
if (name[0] == '\0') {
|
||||
name = NULL;
|
||||
} else if (name[0]!=':' || name[1]!=':') {
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
if (iPtr->varFramePtr != NULL) {
|
||||
Tcl_DStringAppend(&buffer,
|
||||
iPtr->varFramePtr->nsPtr->fullName, -1);
|
||||
}
|
||||
TclDStringAppendLiteral(&buffer, "::");
|
||||
Tcl_DStringAppend(&buffer, name, -1);
|
||||
name = Tcl_DStringValue(&buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1243,7 +1231,6 @@ TclOOCopyObjectCmd(
|
||||
}
|
||||
|
||||
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, name, namespaceName);
|
||||
Tcl_DStringFree(&buffer);
|
||||
}
|
||||
|
||||
if (o2Ptr == NULL) {
|
||||
|
||||
+12
-1
@@ -110,7 +110,12 @@ TclOODeleteContext(
|
||||
TclOODeleteChain(contextPtr->callPtr);
|
||||
if (oPtr != NULL) {
|
||||
TclStackFree(oPtr->fPtr->interp, contextPtr);
|
||||
DelRef(oPtr);
|
||||
|
||||
/*
|
||||
* Corresponding AddRef() in TclOO.c/TclOOObjectCmdCore
|
||||
*/
|
||||
|
||||
TclOODecrRefCount(oPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,6 +905,7 @@ InitCallChain(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* IsStillValid --
|
||||
*
|
||||
* Calculates whether the given call chain can be used for executing a
|
||||
* method for the given object. The condition on a chain from a cached
|
||||
* location being reusable is:
|
||||
@@ -1171,6 +1177,11 @@ TclOOGetCallContext(
|
||||
returnContext:
|
||||
contextPtr = TclStackAlloc(oPtr->fPtr->interp, sizeof(CallContext));
|
||||
contextPtr->oPtr = oPtr;
|
||||
|
||||
/*
|
||||
* Corresponding TclOODecrRefCount() in TclOODeleteContext
|
||||
*/
|
||||
|
||||
AddRef(oPtr);
|
||||
contextPtr->callPtr = callPtr;
|
||||
contextPtr->skip = 2;
|
||||
|
||||
+72
-27
@@ -123,6 +123,7 @@ static const struct DeclaredSlot slots[] = {
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* BumpGlobalEpoch --
|
||||
*
|
||||
* Utility that ensures that call chains that are invalid will get thrown
|
||||
* away at an appropriate time. Note that exactly which epoch gets
|
||||
* advanced will depend on exactly what the class is tangled up in; in
|
||||
@@ -167,6 +168,7 @@ BumpGlobalEpoch(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* RecomputeClassCacheFlag --
|
||||
*
|
||||
* Determine whether the object is prototypical of its class, and hence
|
||||
* able to use the class's method chain cache.
|
||||
*
|
||||
@@ -189,6 +191,7 @@ RecomputeClassCacheFlag(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOObjectSetFilters --
|
||||
*
|
||||
* Install a list of filter method names into an object.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -247,6 +250,7 @@ TclOOObjectSetFilters(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOClassSetFilters --
|
||||
*
|
||||
* Install a list of filter method names into a class.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -309,6 +313,7 @@ TclOOClassSetFilters(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOObjectSetMixins --
|
||||
*
|
||||
* Install a list of mixin classes into an object.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -326,9 +331,8 @@ TclOOObjectSetMixins(
|
||||
if (numMixins == 0) {
|
||||
if (oPtr->mixins.num != 0) {
|
||||
FOREACH(mixinPtr, oPtr->mixins) {
|
||||
if (mixinPtr) {
|
||||
TclOORemoveFromInstances(oPtr, mixinPtr);
|
||||
}
|
||||
TclOORemoveFromInstances(oPtr, mixinPtr);
|
||||
TclOODecrRefCount(mixinPtr->thisPtr);
|
||||
}
|
||||
ckfree(oPtr->mixins.list);
|
||||
oPtr->mixins.num = 0;
|
||||
@@ -340,6 +344,7 @@ TclOOObjectSetMixins(
|
||||
if (mixinPtr && mixinPtr != oPtr->selfCls) {
|
||||
TclOORemoveFromInstances(oPtr, mixinPtr);
|
||||
}
|
||||
TclOODecrRefCount(mixinPtr->thisPtr);
|
||||
}
|
||||
oPtr->mixins.list = ckrealloc(oPtr->mixins.list,
|
||||
sizeof(Class *) * numMixins);
|
||||
@@ -352,6 +357,8 @@ TclOOObjectSetMixins(
|
||||
FOREACH(mixinPtr, oPtr->mixins) {
|
||||
if (mixinPtr != oPtr->selfCls) {
|
||||
TclOOAddToInstances(oPtr, mixinPtr);
|
||||
/* For the new copy created by memcpy */
|
||||
AddRef(mixinPtr->thisPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,6 +369,7 @@ TclOOObjectSetMixins(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOClassSetMixins --
|
||||
*
|
||||
* Install a list of mixin classes into a class.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -381,6 +389,7 @@ TclOOClassSetMixins(
|
||||
if (classPtr->mixins.num != 0) {
|
||||
FOREACH(mixinPtr, classPtr->mixins) {
|
||||
TclOORemoveFromMixinSubs(classPtr, mixinPtr);
|
||||
TclOODecrRefCount(mixinPtr->thisPtr);
|
||||
}
|
||||
ckfree(classPtr->mixins.list);
|
||||
classPtr->mixins.num = 0;
|
||||
@@ -389,6 +398,7 @@ TclOOClassSetMixins(
|
||||
if (classPtr->mixins.num != 0) {
|
||||
FOREACH(mixinPtr, classPtr->mixins) {
|
||||
TclOORemoveFromMixinSubs(classPtr, mixinPtr);
|
||||
TclOODecrRefCount(mixinPtr->thisPtr);
|
||||
}
|
||||
classPtr->mixins.list = ckrealloc(classPtr->mixins.list,
|
||||
sizeof(Class *) * numMixins);
|
||||
@@ -399,6 +409,8 @@ TclOOClassSetMixins(
|
||||
memcpy(classPtr->mixins.list, mixins, sizeof(Class *) * numMixins);
|
||||
FOREACH(mixinPtr, classPtr->mixins) {
|
||||
TclOOAddToMixinSubs(classPtr, mixinPtr);
|
||||
/* For the new copy created by memcpy */
|
||||
AddRef(mixinPtr->thisPtr);
|
||||
}
|
||||
}
|
||||
BumpGlobalEpoch(interp, classPtr);
|
||||
@@ -408,6 +420,7 @@ TclOOClassSetMixins(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* RenameDeleteMethod --
|
||||
*
|
||||
* Core of the code to rename and delete methods.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -497,6 +510,7 @@ RenameDeleteMethod(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOUnknownDefinition --
|
||||
*
|
||||
* Handles what happens when an unknown command is encountered during the
|
||||
* processing of a definition script. Works by finding a command in the
|
||||
* operating definition namespace that the requested command is a unique
|
||||
@@ -575,6 +589,7 @@ TclOOUnknownDefinition(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* FindCommand --
|
||||
*
|
||||
* Specialized version of Tcl_FindCommand that handles command prefixes
|
||||
* and disallows namespace magic.
|
||||
*
|
||||
@@ -635,6 +650,7 @@ FindCommand(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* InitDefineContext --
|
||||
*
|
||||
* Does the magic incantations necessary to push the special stack frame
|
||||
* used when processing object definitions. It is up to the caller to
|
||||
* dispose of the frame (with TclPopStackFrame) when finished.
|
||||
@@ -660,7 +676,9 @@ InitDefineContext(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* framePtrPtr is needed to satisfy GCC 3.3's strict aliasing rules */
|
||||
/*
|
||||
* framePtrPtr is needed to satisfy GCC 3.3's strict aliasing rules.
|
||||
*/
|
||||
|
||||
(void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
|
||||
namespacePtr, FRAME_IS_OO_DEFINE);
|
||||
@@ -675,6 +693,7 @@ InitDefineContext(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOGetDefineCmdContext --
|
||||
*
|
||||
* Extracts the magic token from the current stack frame, or returns NULL
|
||||
* (and leaves an error message) otherwise.
|
||||
*
|
||||
@@ -711,6 +730,7 @@ TclOOGetDefineCmdContext(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* GetClassInOuterContext --
|
||||
*
|
||||
* Wrapper round Tcl_GetObjectFromObj to perform the lookup in the
|
||||
* context that called oo::define (or equivalent). Note that this may
|
||||
* have to go up multiple levels to get the level that we started doing
|
||||
@@ -753,6 +773,7 @@ GetClassInOuterContext(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* GenerateErrorInfo --
|
||||
*
|
||||
* Factored out code to generate part of the error trace messages.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -791,6 +812,7 @@ GenerateErrorInfo(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* MagicDefinitionInvoke --
|
||||
*
|
||||
* Part of the implementation of the "oo::define" and "oo::objdefine"
|
||||
* commands that is used to implement the more-than-one-argument case,
|
||||
* applying ensemble-like tricks with dispatch so that error messages are
|
||||
@@ -854,6 +876,7 @@ MagicDefinitionInvoke(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineObjCmd --
|
||||
*
|
||||
* Implementation of the "oo::define" command. Works by effectively doing
|
||||
* the same as 'namespace eval', but with extra magic applied so that the
|
||||
* object to be modified is known to the commands in the target
|
||||
@@ -914,7 +937,7 @@ TclOODefineObjCmd(
|
||||
} else {
|
||||
result = MagicDefinitionInvoke(interp, fPtr->defineNs, 2, objc, objv);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
TclOODecrRefCount(oPtr);
|
||||
|
||||
/*
|
||||
* Restore the previous "current" namespace.
|
||||
@@ -928,6 +951,7 @@ TclOODefineObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOOObjDefObjCmd --
|
||||
*
|
||||
* Implementation of the "oo::objdefine" command. Works by effectively
|
||||
* doing the same as 'namespace eval', but with extra magic applied so
|
||||
* that the object to be modified is known to the commands in the target
|
||||
@@ -981,7 +1005,7 @@ TclOOObjDefObjCmd(
|
||||
} else {
|
||||
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 2, objc, objv);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
TclOODecrRefCount(oPtr);
|
||||
|
||||
/*
|
||||
* Restore the previous "current" namespace.
|
||||
@@ -995,6 +1019,7 @@ TclOOObjDefObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineSelfObjCmd --
|
||||
*
|
||||
* Implementation of the "self" subcommand of the "oo::define" command.
|
||||
* Works by effectively doing the same as 'namespace eval', but with
|
||||
* extra magic applied so that the object to be modified is known to the
|
||||
@@ -1048,7 +1073,7 @@ TclOODefineSelfObjCmd(
|
||||
} else {
|
||||
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 1, objc, objv);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
TclOODecrRefCount(oPtr);
|
||||
|
||||
/*
|
||||
* Restore the previous "current" namespace.
|
||||
@@ -1062,6 +1087,7 @@ TclOODefineSelfObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineObjSelfObjCmd --
|
||||
*
|
||||
* Implementation of the "self" subcommand of the "oo::objdefine"
|
||||
* command.
|
||||
*
|
||||
@@ -1095,6 +1121,7 @@ TclOODefineObjSelfObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineClassObjCmd --
|
||||
*
|
||||
* Implementation of the "class" subcommand of the "oo::objdefine"
|
||||
* command.
|
||||
*
|
||||
@@ -1110,7 +1137,6 @@ TclOODefineClassObjCmd(
|
||||
{
|
||||
Object *oPtr;
|
||||
Class *clsPtr;
|
||||
Foundation *fPtr = TclOOGetFoundation(interp);
|
||||
|
||||
/*
|
||||
* Parse the context to get the object to operate on.
|
||||
@@ -1147,20 +1173,6 @@ TclOODefineClassObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply semantic checks. In particular, classes and non-classes are not
|
||||
* interchangable (too complicated to do the conversion!) so we must
|
||||
* produce an error if any attempt is made to swap from one to the other.
|
||||
*/
|
||||
|
||||
if ((oPtr->classPtr==NULL) == TclOOIsReachable(fPtr->classCls, clsPtr)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"may not change a %sclass object into a %sclass object",
|
||||
(oPtr->classPtr==NULL ? "non-" : ""),
|
||||
(oPtr->classPtr==NULL ? "" : "non-")));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "TRANSMUTATION", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the object's class.
|
||||
@@ -1168,11 +1180,11 @@ TclOODefineClassObjCmd(
|
||||
|
||||
if (oPtr->selfCls != clsPtr) {
|
||||
TclOORemoveFromInstances(oPtr, oPtr->selfCls);
|
||||
TclOODecrRefCount(oPtr->selfCls->thisPtr);
|
||||
oPtr->selfCls = clsPtr;
|
||||
AddRef(oPtr->selfCls->thisPtr);
|
||||
TclOOAddToInstances(oPtr, oPtr->selfCls);
|
||||
if (!(clsPtr->thisPtr->flags & OBJECT_DELETED)) {
|
||||
oPtr->flags &= ~CLASS_GONE;
|
||||
}
|
||||
|
||||
if (oPtr->classPtr != NULL) {
|
||||
BumpGlobalEpoch(interp, oPtr->classPtr);
|
||||
} else {
|
||||
@@ -1186,6 +1198,7 @@ TclOODefineClassObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineConstructorObjCmd --
|
||||
*
|
||||
* Implementation of the "constructor" subcommand of the "oo::define"
|
||||
* command.
|
||||
*
|
||||
@@ -1254,6 +1267,7 @@ TclOODefineConstructorObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineDeleteMethodObjCmd --
|
||||
*
|
||||
* Implementation of the "deletemethod" subcommand of the "oo::define"
|
||||
* and "oo::objdefine" commands.
|
||||
*
|
||||
@@ -1310,6 +1324,7 @@ TclOODefineDeleteMethodObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineDestructorObjCmd --
|
||||
*
|
||||
* Implementation of the "destructor" subcommand of the "oo::define"
|
||||
* command.
|
||||
*
|
||||
@@ -1374,6 +1389,7 @@ TclOODefineDestructorObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineExportObjCmd --
|
||||
*
|
||||
* Implementation of the "export" subcommand of the "oo::define" and
|
||||
* "oo::objdefine" commands.
|
||||
*
|
||||
@@ -1468,6 +1484,7 @@ TclOODefineExportObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineForwardObjCmd --
|
||||
*
|
||||
* Implementation of the "forward" subcommand of the "oo::define" and
|
||||
* "oo::objdefine" commands.
|
||||
*
|
||||
@@ -1528,6 +1545,7 @@ TclOODefineForwardObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineMethodObjCmd --
|
||||
*
|
||||
* Implementation of the "method" subcommand of the "oo::define" and
|
||||
* "oo::objdefine" commands.
|
||||
*
|
||||
@@ -1585,6 +1603,7 @@ TclOODefineMethodObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineMixinObjCmd --
|
||||
*
|
||||
* Implementation of the "mixin" subcommand of the "oo::define" and
|
||||
* "oo::objdefine" commands.
|
||||
*
|
||||
@@ -1648,6 +1667,7 @@ TclOODefineMixinObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineRenameMethodObjCmd --
|
||||
*
|
||||
* Implementation of the "renamemethod" subcommand of the "oo::define"
|
||||
* and "oo::objdefine" commands.
|
||||
*
|
||||
@@ -1704,6 +1724,7 @@ TclOODefineRenameMethodObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineUnexportObjCmd --
|
||||
*
|
||||
* Implementation of the "unexport" subcommand of the "oo::define" and
|
||||
* "oo::objdefine" commands.
|
||||
*
|
||||
@@ -1798,6 +1819,7 @@ TclOODefineUnexportObjCmd(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_ClassSetConstructor, Tcl_ClassSetDestructor --
|
||||
*
|
||||
* How to install a constructor or destructor into a class; API to call
|
||||
* from C.
|
||||
*
|
||||
@@ -1852,6 +1874,7 @@ Tcl_ClassSetDestructor(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineSlots --
|
||||
*
|
||||
* Create the "::oo::Slot" class and its standard instances. Class
|
||||
* definition is empty at the stage (added by scripting).
|
||||
*
|
||||
@@ -1895,6 +1918,7 @@ TclOODefineSlots(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ClassFilterGet, ClassFilterSet --
|
||||
*
|
||||
* Implementation of the "filter" slot accessors of the "oo::define"
|
||||
* command.
|
||||
*
|
||||
@@ -1974,6 +1998,7 @@ ClassFilterSet(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ClassMixinGet, ClassMixinSet --
|
||||
*
|
||||
* Implementation of the "mixin" slot accessors of the "oo::define"
|
||||
* command.
|
||||
*
|
||||
@@ -2055,6 +2080,7 @@ ClassMixinSet(
|
||||
mixins[i] = GetClassInOuterContext(interp, mixinv[i],
|
||||
"may only mix in classes");
|
||||
if (mixins[i] == NULL) {
|
||||
i--;
|
||||
goto freeAndError;
|
||||
}
|
||||
if (TclOOIsReachable(oPtr->classPtr, mixins[i])) {
|
||||
@@ -2078,6 +2104,7 @@ ClassMixinSet(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ClassSuperGet, ClassSuperSet --
|
||||
*
|
||||
* Implementation of the "superclass" slot accessors of the "oo::define"
|
||||
* command.
|
||||
*
|
||||
@@ -2172,16 +2199,19 @@ ClassSuperSet(
|
||||
|
||||
if (superc == 0) {
|
||||
superclasses = ckrealloc(superclasses, sizeof(Class *));
|
||||
superclasses[0] = oPtr->fPtr->objectCls;
|
||||
superc = 1;
|
||||
if (TclOOIsReachable(oPtr->fPtr->classCls, oPtr->classPtr)) {
|
||||
superclasses[0] = oPtr->fPtr->classCls;
|
||||
} else {
|
||||
superclasses[0] = oPtr->fPtr->objectCls;
|
||||
}
|
||||
superc = 1;
|
||||
AddRef(superclasses[0]->thisPtr);
|
||||
} else {
|
||||
for (i=0 ; i<superc ; i++) {
|
||||
superclasses[i] = GetClassInOuterContext(interp, superv[i],
|
||||
"only a class can be a superclass");
|
||||
if (superclasses[i] == NULL) {
|
||||
i--;
|
||||
goto failedAfterAlloc;
|
||||
}
|
||||
for (j=0 ; j<i ; j++) {
|
||||
@@ -2198,9 +2228,19 @@ ClassSuperSet(
|
||||
"attempt to form circular dependency graph", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
|
||||
failedAfterAlloc:
|
||||
for (; i > 0; i--) {
|
||||
TclOODecrRefCount(superclasses[i]->thisPtr);
|
||||
}
|
||||
ckfree(superclasses);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponding TclOODecrRefCount() is near the end of this
|
||||
* function.
|
||||
*/
|
||||
|
||||
AddRef(superclasses[i]->thisPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2214,6 +2254,7 @@ ClassSuperSet(
|
||||
if (oPtr->classPtr->superclasses.num != 0) {
|
||||
FOREACH(superPtr, oPtr->classPtr->superclasses) {
|
||||
TclOORemoveFromSubclasses(oPtr->classPtr, superPtr);
|
||||
TclOODecrRefCount(superPtr->thisPtr);
|
||||
}
|
||||
ckfree(oPtr->classPtr->superclasses.list);
|
||||
}
|
||||
@@ -2231,6 +2272,7 @@ ClassSuperSet(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ClassVarsGet, ClassVarsSet --
|
||||
*
|
||||
* Implementation of the "variable" slot accessors of the "oo::define"
|
||||
* command.
|
||||
*
|
||||
@@ -2373,6 +2415,7 @@ ClassVarsSet(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ObjectFilterGet, ObjectFilterSet --
|
||||
*
|
||||
* Implementation of the "filter" slot accessors of the "oo::objdefine"
|
||||
* command.
|
||||
*
|
||||
@@ -2440,6 +2483,7 @@ ObjFilterSet(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ObjectMixinGet, ObjectMixinSet --
|
||||
*
|
||||
* Implementation of the "mixin" slot accessors of the "oo::objdefine"
|
||||
* command.
|
||||
*
|
||||
@@ -2525,6 +2569,7 @@ ObjMixinSet(
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ObjectVarsGet, ObjectVarsSet --
|
||||
*
|
||||
* Implementation of the "variable" slot accessors of the "oo::objdefine"
|
||||
* command.
|
||||
*
|
||||
|
||||
+18
-28
@@ -193,9 +193,10 @@ typedef struct Object {
|
||||
* destroyed. */
|
||||
#define DESTRUCTOR_CALLED 2 /* Flag to say that the destructor has been
|
||||
* called. */
|
||||
#define CLASS_GONE 4 /* Indicates that the class of this object has
|
||||
* been deleted, and so the object should not
|
||||
* attempt to remove itself from its class. */
|
||||
#define CLASS_GONE 4 /* Obsolete. Indicates that the class of this
|
||||
* object has been deleted, and so the object
|
||||
* should not attempt to remove itself from its
|
||||
* class. */
|
||||
#define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of
|
||||
* the class hierarchy and should be treated
|
||||
* specially during teardown. */
|
||||
@@ -222,10 +223,6 @@ typedef struct Object {
|
||||
typedef struct Class {
|
||||
Object *thisPtr; /* Reference to the object associated with
|
||||
* this class. */
|
||||
int refCount; /* Number of strong references to this class.
|
||||
* Weak references are not counted; the
|
||||
* purpose of this is to avoid Tcl_Preserve as
|
||||
* that is quite slow. */
|
||||
int flags; /* Assorted flags. */
|
||||
LIST_STATIC(struct Class *) superclasses;
|
||||
/* List of superclasses, used for generation
|
||||
@@ -499,6 +496,7 @@ MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp,
|
||||
Class *classPtr,
|
||||
const char *nameStr,
|
||||
const char *nsNameStr);
|
||||
MODULE_SCOPE int TclOODecrRefCount(Object *oPtr);
|
||||
MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr);
|
||||
MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr);
|
||||
MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr);
|
||||
@@ -528,10 +526,10 @@ MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp,
|
||||
MODULE_SCOPE void TclOONewBasicMethod(Tcl_Interp *interp, Class *clsPtr,
|
||||
const DeclaredClassMethod *dcm);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr);
|
||||
MODULE_SCOPE void TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
|
||||
MODULE_SCOPE void TclOORemoveFromMixinSubs(Class *subPtr,
|
||||
MODULE_SCOPE int TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
|
||||
MODULE_SCOPE int TclOORemoveFromMixinSubs(Class *subPtr,
|
||||
Class *mixinPtr);
|
||||
MODULE_SCOPE void TclOORemoveFromSubclasses(Class *subPtr,
|
||||
MODULE_SCOPE int TclOORemoveFromSubclasses(Class *subPtr,
|
||||
Class *superPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclOORenderCallChain(Tcl_Interp *interp,
|
||||
CallChain *callPtr);
|
||||
@@ -545,19 +543,22 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
|
||||
|
||||
#include "tclOOIntDecls.h"
|
||||
|
||||
/*
|
||||
* Alternatives to Tcl_Preserve/Tcl_EventuallyFree/Tcl_Release.
|
||||
*/
|
||||
|
||||
#define AddRef(ptr) ((ptr)->refCount++)
|
||||
|
||||
/*
|
||||
* A convenience macro for iterating through the lists used in the internal
|
||||
* memory management of objects. This is a bit gnarly because we want to do
|
||||
* the assignment of the picked-out value only when the body test succeeds,
|
||||
* but we cannot rely on the assigned value being useful, forcing us to do
|
||||
* some nasty stuff with the comma operator. The compiler's optimizer should
|
||||
* be able to sort it all out!
|
||||
*
|
||||
* memory management of objects.
|
||||
* REQUIRES DECLARATION: int i;
|
||||
*/
|
||||
|
||||
#define FOREACH(var,ary) \
|
||||
for(i=0 ; (i<(ary).num?((var=(ary).list[i]),1):0) ; i++)
|
||||
for(i=0 ; i<(ary).num; i++) if ((ary).list[i] == NULL) { \
|
||||
continue; \
|
||||
} else if (var = (ary).list[i], 1)
|
||||
|
||||
/*
|
||||
* Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS
|
||||
@@ -592,17 +593,6 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Alternatives to Tcl_Preserve/Tcl_EventuallyFree/Tcl_Release.
|
||||
*/
|
||||
|
||||
#define AddRef(ptr) ((ptr)->refCount++)
|
||||
#define DelRef(ptr) do { \
|
||||
if ((ptr)->refCount-- <= 1) { \
|
||||
ckfree(ptr); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* TCL_OO_INTERNAL_H */
|
||||
|
||||
/*
|
||||
|
||||
+75
-192
@@ -210,9 +210,8 @@ static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
static void UpdateStringOfDouble(Tcl_Obj *objPtr);
|
||||
static void UpdateStringOfInt(Tcl_Obj *objPtr);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
static void UpdateStringOfWideInt(Tcl_Obj *objPtr);
|
||||
static int SetWideIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG)
|
||||
static void UpdateStringOfOldInt(Tcl_Obj *objPtr);
|
||||
#endif
|
||||
static void FreeBignum(Tcl_Obj *objPtr);
|
||||
static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
|
||||
@@ -242,6 +241,7 @@ static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
* implementations.
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
static const Tcl_ObjType oldBooleanType = {
|
||||
"boolean", /* name */
|
||||
NULL, /* freeIntRepProc */
|
||||
@@ -249,6 +249,7 @@ static const Tcl_ObjType oldBooleanType = {
|
||||
NULL, /* updateStringProc */
|
||||
TclSetBooleanFromAny /* setFromAnyProc */
|
||||
};
|
||||
#endif
|
||||
const Tcl_ObjType tclBooleanType = {
|
||||
"booleanString", /* name */
|
||||
NULL, /* freeIntRepProc */
|
||||
@@ -264,19 +265,23 @@ const Tcl_ObjType tclDoubleType = {
|
||||
SetDoubleFromAny /* setFromAnyProc */
|
||||
};
|
||||
const Tcl_ObjType tclIntType = {
|
||||
#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 || defined(TCL_WIDE_INT_IS_LONG)
|
||||
"int", /* name */
|
||||
#else
|
||||
"wideInt", /* name, keeping maximum compatibility with Tcl 8.6 on 32-bit platforms*/
|
||||
#endif
|
||||
NULL, /* freeIntRepProc */
|
||||
NULL, /* dupIntRepProc */
|
||||
UpdateStringOfInt, /* updateStringProc */
|
||||
SetIntFromAny /* setFromAnyProc */
|
||||
};
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
const Tcl_ObjType tclWideIntType = {
|
||||
"wideInt", /* name */
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG)
|
||||
static const Tcl_ObjType oldIntType = {
|
||||
"int", /* name */
|
||||
NULL, /* freeIntRepProc */
|
||||
NULL, /* dupIntRepProc */
|
||||
UpdateStringOfWideInt, /* updateStringProc */
|
||||
SetWideIntFromAny /* setFromAnyProc */
|
||||
UpdateStringOfOldInt, /* updateStringProc */
|
||||
SetIntFromAny /* setFromAnyProc */
|
||||
};
|
||||
#endif
|
||||
const Tcl_ObjType tclBignumType = {
|
||||
@@ -344,17 +349,17 @@ typedef struct ResolvedCmdName {
|
||||
* reference (not the namespace that contains
|
||||
* the referenced command). NULL if the name
|
||||
* is fully qualified.*/
|
||||
size_t refNsId; /* refNsPtr's unique namespace id. Used to
|
||||
unsigned long refNsId; /* refNsPtr's unique namespace id. Used to
|
||||
* verify that refNsPtr is still valid (e.g.,
|
||||
* it's possible that the cmd's containing
|
||||
* namespace was deleted and a new one created
|
||||
* at the same address). */
|
||||
size_t refNsCmdEpoch; /* Value of the referencing namespace's
|
||||
unsigned int refNsCmdEpoch; /* Value of the referencing namespace's
|
||||
* cmdRefEpoch when the pointer was cached.
|
||||
* Before using the cached pointer, we check
|
||||
* if the namespace's epoch was incremented;
|
||||
* if so, this cached pointer is invalid. */
|
||||
size_t cmdEpoch; /* Value of the command's cmdEpoch when this
|
||||
unsigned int cmdEpoch; /* Value of the command's cmdEpoch when this
|
||||
* pointer was cached. Before using the cached
|
||||
* pointer, we check if the cmd's epoch was
|
||||
* incremented; if so, the cmd was renamed,
|
||||
@@ -395,8 +400,6 @@ TclInitObjSubsystem(void)
|
||||
|
||||
Tcl_RegisterObjType(&tclByteArrayType);
|
||||
Tcl_RegisterObjType(&tclDoubleType);
|
||||
Tcl_RegisterObjType(&tclEndOffsetType);
|
||||
Tcl_RegisterObjType(&tclIntType);
|
||||
Tcl_RegisterObjType(&tclStringType);
|
||||
Tcl_RegisterObjType(&tclListType);
|
||||
Tcl_RegisterObjType(&tclDictType);
|
||||
@@ -406,9 +409,12 @@ TclInitObjSubsystem(void)
|
||||
Tcl_RegisterObjType(&tclProcBodyType);
|
||||
|
||||
/* For backward compatibility only ... */
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
Tcl_RegisterObjType(&tclIntType);
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG)
|
||||
Tcl_RegisterObjType(&oldIntType);
|
||||
#endif
|
||||
Tcl_RegisterObjType(&oldBooleanType);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
Tcl_RegisterObjType(&tclWideIntType);
|
||||
#endif
|
||||
|
||||
#ifdef TCL_COMPILE_STATS
|
||||
@@ -1762,7 +1768,7 @@ Tcl_NewBooleanObj(
|
||||
{
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclNewLongObj(objPtr, boolValue!=0);
|
||||
TclNewIntObj(objPtr, boolValue!=0);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
@@ -1810,7 +1816,7 @@ Tcl_DbNewBooleanObj(
|
||||
TclDbNewObj(objPtr, file, line);
|
||||
objPtr->bytes = NULL;
|
||||
|
||||
objPtr->internalRep.longValue = (boolValue != 0);
|
||||
objPtr->internalRep.wideValue = (boolValue != 0);
|
||||
objPtr->typePtr = &tclIntType;
|
||||
return objPtr;
|
||||
}
|
||||
@@ -1857,7 +1863,7 @@ Tcl_SetBooleanObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj");
|
||||
}
|
||||
|
||||
TclSetLongObj(objPtr, boolValue!=0);
|
||||
TclSetIntObj(objPtr, boolValue!=0);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
@@ -1888,11 +1894,11 @@ Tcl_GetBooleanFromObj(
|
||||
{
|
||||
do {
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
*boolPtr = (objPtr->internalRep.longValue != 0);
|
||||
*boolPtr = (objPtr->internalRep.wideValue != 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclBooleanType) {
|
||||
*boolPtr = (int) objPtr->internalRep.longValue;
|
||||
*boolPtr = objPtr->internalRep.longValue != 0;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclDoubleType) {
|
||||
@@ -1916,12 +1922,6 @@ Tcl_GetBooleanFromObj(
|
||||
*boolPtr = 1;
|
||||
return TCL_OK;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
*boolPtr = (objPtr->internalRep.wideValue != 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
} while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK ==
|
||||
TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0)));
|
||||
return TCL_ERROR;
|
||||
@@ -1942,7 +1942,12 @@ Tcl_GetBooleanFromObj(
|
||||
*
|
||||
* Side effects:
|
||||
* If no error occurs, an integer 1 or 0 is stored as "objPtr"s internal
|
||||
* representation and the type of "objPtr" is set to boolean.
|
||||
* representation and the type of "objPtr" is set to boolean or int/wideInt.
|
||||
*
|
||||
* Warning: If the returned type is "wideInt" (32-bit platforms) and your
|
||||
* platform is bigendian, you cannot use internalRep.longValue to distinguish
|
||||
* between false and true. On Windows and most other platforms this still will
|
||||
* work fine, but basically it is non-portable.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1960,8 +1965,7 @@ TclSetBooleanFromAny(
|
||||
|
||||
if (objPtr->bytes == NULL) {
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
switch (objPtr->internalRep.longValue) {
|
||||
case 0L: case 1L:
|
||||
if ((Tcl_WideUInt)objPtr->internalRep.wideValue < 2) {
|
||||
return TCL_OK;
|
||||
}
|
||||
goto badBoolean;
|
||||
@@ -1971,12 +1975,6 @@ TclSetBooleanFromAny(
|
||||
goto badBoolean;
|
||||
}
|
||||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
goto badBoolean;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (objPtr->typePtr == &tclDoubleType) {
|
||||
goto badBoolean;
|
||||
}
|
||||
@@ -2113,7 +2111,7 @@ ParseBoolean(
|
||||
|
||||
numericBoolean:
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.longValue = newBool;
|
||||
objPtr->internalRep.wideValue = newBool;
|
||||
objPtr->typePtr = &tclIntType;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -2294,7 +2292,7 @@ Tcl_GetDoubleFromObj(
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
*dblPtr = objPtr->internalRep.longValue;
|
||||
*dblPtr = (double) objPtr->internalRep.wideValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclBignumType) {
|
||||
@@ -2304,12 +2302,6 @@ Tcl_GetDoubleFromObj(
|
||||
*dblPtr = TclBignumToDouble(&big);
|
||||
return TCL_OK;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
*dblPtr = (double) objPtr->internalRep.wideValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
} while (SetDoubleFromAny(interp, objPtr) == TCL_OK);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2427,7 +2419,7 @@ Tcl_NewIntObj(
|
||||
{
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclNewLongObj(objPtr, intValue);
|
||||
TclNewIntObj(objPtr, intValue);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* if TCL_MEM_DEBUG */
|
||||
@@ -2460,7 +2452,7 @@ Tcl_SetIntObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetIntObj");
|
||||
}
|
||||
|
||||
TclSetLongObj(objPtr, intValue);
|
||||
TclSetIntObj(objPtr, intValue);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2538,9 +2530,8 @@ SetIntFromAny(
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
Tcl_Obj *objPtr) /* Pointer to the object to convert */
|
||||
{
|
||||
long l;
|
||||
|
||||
return TclGetLongFromObj(interp, objPtr, &l);
|
||||
Tcl_WideInt w;
|
||||
return Tcl_GetWideIntFromObj(interp, objPtr, &w);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2569,12 +2560,28 @@ UpdateStringOfInt(
|
||||
char buffer[TCL_INTEGER_SPACE];
|
||||
register int len;
|
||||
|
||||
len = TclFormatInt(buffer, objPtr->internalRep.wideValue);
|
||||
|
||||
objPtr->bytes = ckalloc(len + 1);
|
||||
memcpy(objPtr->bytes, buffer, (unsigned) len + 1);
|
||||
objPtr->length = len;
|
||||
}
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG)
|
||||
static void
|
||||
UpdateStringOfOldInt(
|
||||
register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
|
||||
{
|
||||
char buffer[TCL_INTEGER_SPACE];
|
||||
register int len;
|
||||
|
||||
len = TclFormatInt(buffer, objPtr->internalRep.longValue);
|
||||
|
||||
objPtr->bytes = ckalloc(len + 1);
|
||||
memcpy(objPtr->bytes, buffer, (unsigned) len + 1);
|
||||
objPtr->length = len;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2606,8 +2613,8 @@ UpdateStringOfInt(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
#undef Tcl_NewLongObj
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
Tcl_Obj *
|
||||
Tcl_NewLongObj(
|
||||
@@ -2626,7 +2633,7 @@ Tcl_NewLongObj(
|
||||
{
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclNewLongObj(objPtr, longValue);
|
||||
TclNewIntObj(objPtr, longValue);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* if TCL_MEM_DEBUG */
|
||||
@@ -2663,6 +2670,7 @@ Tcl_NewLongObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_DbNewLongObj
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
Tcl_Obj *
|
||||
@@ -2679,7 +2687,7 @@ Tcl_DbNewLongObj(
|
||||
TclDbNewObj(objPtr, file, line);
|
||||
objPtr->bytes = NULL;
|
||||
|
||||
objPtr->internalRep.longValue = longValue;
|
||||
objPtr->internalRep.wideValue = longValue;
|
||||
objPtr->typePtr = &tclIntType;
|
||||
return objPtr;
|
||||
}
|
||||
@@ -2717,6 +2725,7 @@ Tcl_DbNewLongObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_SetLongObj
|
||||
void
|
||||
Tcl_SetLongObj(
|
||||
register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
|
||||
@@ -2727,7 +2736,7 @@ Tcl_SetLongObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetLongObj");
|
||||
}
|
||||
|
||||
TclSetLongObj(objPtr, longValue);
|
||||
TclSetIntObj(objPtr, longValue);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2758,12 +2767,13 @@ Tcl_GetLongFromObj(
|
||||
register long *longPtr) /* Place to store resulting long. */
|
||||
{
|
||||
do {
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
*longPtr = objPtr->internalRep.longValue;
|
||||
*longPtr = objPtr->internalRep.wideValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
#else
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
/*
|
||||
* We return any integer in the range -ULONG_MAX to ULONG_MAX
|
||||
* converted to a long, ignoring overflow. The rule preserves
|
||||
@@ -2836,49 +2846,6 @@ Tcl_GetLongFromObj(
|
||||
TCL_PARSE_INTEGER_ONLY)==TCL_OK);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* UpdateStringOfWideInt --
|
||||
*
|
||||
* Update the string representation for a wide integer object. Note: this
|
||||
* function does not free an existing old string rep so storage will be
|
||||
* lost if this has not already been done.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The object's string is set to a valid string that results from the
|
||||
* wideInt-to-string conversion.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
UpdateStringOfWideInt(
|
||||
register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
|
||||
{
|
||||
char buffer[TCL_INTEGER_SPACE+2];
|
||||
register unsigned len;
|
||||
register Tcl_WideInt wideVal = objPtr->internalRep.wideValue;
|
||||
|
||||
/*
|
||||
* Note that sprintf will generate a compiler warning under Mingw claiming
|
||||
* %I64 is an unknown format specifier. Just ignore this warning. We can't
|
||||
* use %L as the format specifier since that gets printed as a 32 bit
|
||||
* value.
|
||||
*/
|
||||
|
||||
sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal);
|
||||
len = strlen(buffer);
|
||||
objPtr->bytes = ckalloc(len + 1);
|
||||
memcpy(objPtr->bytes, buffer, len + 1);
|
||||
objPtr->length = len;
|
||||
}
|
||||
#endif /* !TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2928,7 +2895,7 @@ Tcl_NewWideIntObj(
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclNewObj(objPtr);
|
||||
Tcl_SetWideIntObj(objPtr, wideValue);
|
||||
TclSetIntObj(objPtr, wideValue);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* if TCL_MEM_DEBUG */
|
||||
@@ -2980,7 +2947,7 @@ Tcl_DbNewWideIntObj(
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclDbNewObj(objPtr, file, line);
|
||||
Tcl_SetWideIntObj(objPtr, wideValue);
|
||||
TclSetIntObj(objPtr, wideValue);
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
@@ -3029,19 +2996,7 @@ Tcl_SetWideIntObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetWideIntObj");
|
||||
}
|
||||
|
||||
if ((wideValue >= (Tcl_WideInt) LONG_MIN)
|
||||
&& (wideValue <= (Tcl_WideInt) LONG_MAX)) {
|
||||
TclSetLongObj(objPtr, (long) wideValue);
|
||||
} else {
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
TclSetWideIntObj(objPtr, wideValue);
|
||||
#else
|
||||
mp_int big;
|
||||
|
||||
TclInitBignumFromWideInt(&big, wideValue);
|
||||
Tcl_SetBignumObj(objPtr, &big);
|
||||
#endif
|
||||
}
|
||||
TclSetIntObj(objPtr, wideValue);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3073,14 +3028,8 @@ Tcl_GetWideIntFromObj(
|
||||
/* Place to store resulting long. */
|
||||
{
|
||||
do {
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
*wideIntPtr = objPtr->internalRep.wideValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
*wideIntPtr = (Tcl_WideInt) objPtr->internalRep.longValue;
|
||||
*wideIntPtr = objPtr->internalRep.wideValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclDoubleType) {
|
||||
@@ -3133,33 +3082,6 @@ Tcl_GetWideIntFromObj(
|
||||
TCL_PARSE_INTEGER_ONLY)==TCL_OK);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* SetWideIntFromAny --
|
||||
*
|
||||
* Attempts to force the internal representation for a Tcl object to
|
||||
* tclWideIntType, specifically.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a standard object Tcl result. If an error occurs
|
||||
* during conversion, an error message is left in the interpreter's
|
||||
* result unless "interp" is NULL.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
SetWideIntFromAny(
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
Tcl_Obj *objPtr) /* Pointer to the object to convert */
|
||||
{
|
||||
Tcl_WideInt w;
|
||||
return Tcl_GetWideIntFromObj(interp, objPtr, &w);
|
||||
}
|
||||
#endif /* !TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -3402,16 +3324,10 @@ GetBignumFromObj(
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
TclInitBignumFromLong(bignumValue, objPtr->internalRep.longValue);
|
||||
return TCL_OK;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
TclInitBignumFromWideInt(bignumValue,
|
||||
objPtr->internalRep.wideValue);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
if (objPtr->typePtr == &tclDoubleType) {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
@@ -3521,36 +3437,11 @@ Tcl_SetBignumObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj");
|
||||
}
|
||||
if ((size_t) bignumValue->used
|
||||
<= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) {
|
||||
unsigned long value = 0, numBytes = sizeof(long);
|
||||
long scratch;
|
||||
unsigned char *bytes = (unsigned char *) &scratch;
|
||||
|
||||
if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
|
||||
goto tooLargeForLong;
|
||||
}
|
||||
while (numBytes-- > 0) {
|
||||
value = (value << CHAR_BIT) | *bytes++;
|
||||
}
|
||||
if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) {
|
||||
goto tooLargeForLong;
|
||||
}
|
||||
if (bignumValue->sign) {
|
||||
TclSetLongObj(objPtr, -(long)value);
|
||||
} else {
|
||||
TclSetLongObj(objPtr, (long)value);
|
||||
}
|
||||
mp_clear(bignumValue);
|
||||
return;
|
||||
}
|
||||
tooLargeForLong:
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if ((size_t) bignumValue->used
|
||||
<= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) {
|
||||
<= (CHAR_BIT * sizeof(Tcl_WideUInt) + DIGIT_BIT - 1) / DIGIT_BIT) {
|
||||
Tcl_WideUInt value = 0;
|
||||
unsigned long numBytes = sizeof(Tcl_WideInt);
|
||||
Tcl_WideInt scratch;
|
||||
unsigned char *bytes = (unsigned char *)&scratch;
|
||||
unsigned long numBytes = sizeof(Tcl_WideUInt);
|
||||
Tcl_WideUInt scratch;
|
||||
unsigned char *bytes = (unsigned char *) &scratch;
|
||||
|
||||
if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
|
||||
goto tooLargeForWide;
|
||||
@@ -3562,15 +3453,14 @@ Tcl_SetBignumObj(
|
||||
goto tooLargeForWide;
|
||||
}
|
||||
if (bignumValue->sign) {
|
||||
TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
|
||||
TclSetIntObj(objPtr, -(Tcl_WideInt)value);
|
||||
} else {
|
||||
TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
|
||||
TclSetIntObj(objPtr, (Tcl_WideInt)value);
|
||||
}
|
||||
mp_clear(bignumValue);
|
||||
return;
|
||||
}
|
||||
tooLargeForWide:
|
||||
#endif
|
||||
TclInvalidateStringRep(objPtr);
|
||||
TclFreeIntRep(objPtr);
|
||||
TclSetBignumIntRep(objPtr, bignumValue);
|
||||
@@ -3652,17 +3542,10 @@ TclGetNumberFromObj(
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
*typePtr = TCL_NUMBER_LONG;
|
||||
*clientDataPtr = &objPtr->internalRep.longValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
*typePtr = TCL_NUMBER_WIDE;
|
||||
*clientDataPtr = &objPtr->internalRep.wideValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
if (objPtr->typePtr == &tclBignumType) {
|
||||
static Tcl_ThreadDataKey bignumKey;
|
||||
mp_int *bigPtr = Tcl_GetThreadData(&bignumKey,
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
* procedure.
|
||||
*/
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
#if defined(__CYGWIN__) || (defined(_WIN32) && (defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8))
|
||||
static TCL_NORETURN Tcl_PanicProc *panicProc = tclWinDebugPanic;
|
||||
#else
|
||||
static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL;
|
||||
|
||||
@@ -1809,7 +1809,6 @@ Tcl_FSGetNormalizedPath(
|
||||
*/
|
||||
|
||||
(void) TclGetStringFromObj(dir, &cwdLen);
|
||||
cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
|
||||
|
||||
/* Normalize the combined string. */
|
||||
|
||||
@@ -1831,12 +1830,12 @@ Tcl_FSGetNormalizedPath(
|
||||
* normalized head, we can more efficiently normalize the combined
|
||||
* path by passing over only the unnormalized tail portion. When
|
||||
* this is sufficient, prior developers claim this should be much
|
||||
* faster. We use 'cwdLen-1' so that we are already pointing at
|
||||
* faster. We use 'cwdLen' so that we are already pointing at
|
||||
* the dir-separator that we know about. The normalization code
|
||||
* will actually start off directly after that separator.
|
||||
*/
|
||||
|
||||
TclFSNormalizeToUniquePath(interp, copy, cwdLen-1);
|
||||
TclFSNormalizeToUniquePath(interp, copy, cwdLen);
|
||||
}
|
||||
|
||||
/* Now we need to construct the new path object. */
|
||||
|
||||
+21
-57
@@ -221,13 +221,13 @@ Tcl_ReapDetachedProcs(void)
|
||||
{
|
||||
register Detached *detPtr;
|
||||
Detached *nextPtr, *prevPtr;
|
||||
int status;
|
||||
Tcl_Pid pid;
|
||||
int status, code;
|
||||
|
||||
Tcl_MutexLock(&pipeMutex);
|
||||
for (detPtr = detList, prevPtr = NULL; detPtr != NULL; ) {
|
||||
pid = Tcl_WaitPid(detPtr->pid, &status, WNOHANG);
|
||||
if ((pid == 0) || ((pid == (Tcl_Pid) -1) && (errno != ECHILD))) {
|
||||
status = TclProcessWait(detPtr->pid, WNOHANG, &code, NULL, NULL);
|
||||
if (status == TCL_PROCESS_UNCHANGED || (status == TCL_PROCESS_ERROR
|
||||
&& code != ECHILD)) {
|
||||
prevPtr = detPtr;
|
||||
detPtr = detPtr->nextPtr;
|
||||
continue;
|
||||
@@ -277,38 +277,21 @@ TclCleanupChildren(
|
||||
{
|
||||
int result = TCL_OK;
|
||||
int i, abnormalExit, anyErrorInfo;
|
||||
Tcl_Pid pid;
|
||||
int waitStatus;
|
||||
const char *msg;
|
||||
unsigned long resolvedPid;
|
||||
TclProcessWaitStatus waitStatus;
|
||||
int code;
|
||||
Tcl_Obj *msg, *error;
|
||||
|
||||
abnormalExit = 0;
|
||||
for (i = 0; i < numPids; i++) {
|
||||
/*
|
||||
* We need to get the resolved pid before we wait on it as the windows
|
||||
* implementation of Tcl_WaitPid deletes the information such that any
|
||||
* following calls to TclpGetPid fail.
|
||||
*/
|
||||
|
||||
resolvedPid = TclpGetPid(pidPtr[i]);
|
||||
pid = Tcl_WaitPid(pidPtr[i], &waitStatus, 0);
|
||||
if (pid == (Tcl_Pid) -1) {
|
||||
waitStatus = TclProcessWait(pidPtr[i], 0, &code, &msg, &error);
|
||||
if (waitStatus == TCL_PROCESS_ERROR) {
|
||||
result = TCL_ERROR;
|
||||
if (interp != NULL) {
|
||||
msg = Tcl_PosixError(interp);
|
||||
if (errno == ECHILD) {
|
||||
/*
|
||||
* This changeup in message suggested by Mark Diekhans to
|
||||
* remind people that ECHILD errors can occur on some
|
||||
* systems if SIGCHLD isn't in its default state.
|
||||
*/
|
||||
|
||||
msg =
|
||||
"child process lost (is SIGCHLD ignored or trapped?)";
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"error waiting for process to exit: %s", msg));
|
||||
Tcl_SetObjErrorCode(interp, error);
|
||||
Tcl_SetObjResult(interp, msg);
|
||||
}
|
||||
Tcl_DecrRefCount(error);
|
||||
Tcl_DecrRefCount(msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -319,39 +302,19 @@ TclCleanupChildren(
|
||||
* removed).
|
||||
*/
|
||||
|
||||
if (!WIFEXITED(waitStatus) || (WEXITSTATUS(waitStatus) != 0)) {
|
||||
char msg1[TCL_INTEGER_SPACE], msg2[TCL_INTEGER_SPACE];
|
||||
|
||||
if (waitStatus != TCL_PROCESS_EXITED || code != 0) {
|
||||
result = TCL_ERROR;
|
||||
sprintf(msg1, "%lu", resolvedPid);
|
||||
if (WIFEXITED(waitStatus)) {
|
||||
if (waitStatus == TCL_PROCESS_EXITED) {
|
||||
if (interp != NULL) {
|
||||
sprintf(msg2, "%u", WEXITSTATUS(waitStatus));
|
||||
Tcl_SetErrorCode(interp, "CHILDSTATUS", msg1, msg2, NULL);
|
||||
Tcl_SetObjErrorCode(interp, error);
|
||||
}
|
||||
abnormalExit = 1;
|
||||
} else if (interp != NULL) {
|
||||
const char *p;
|
||||
|
||||
if (WIFSIGNALED(waitStatus)) {
|
||||
p = Tcl_SignalMsg(WTERMSIG(waitStatus));
|
||||
Tcl_SetErrorCode(interp, "CHILDKILLED", msg1,
|
||||
Tcl_SignalId(WTERMSIG(waitStatus)), p, NULL);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"child killed: %s\n", p));
|
||||
} else if (WIFSTOPPED(waitStatus)) {
|
||||
p = Tcl_SignalMsg(WSTOPSIG(waitStatus));
|
||||
Tcl_SetErrorCode(interp, "CHILDSUSP", msg1,
|
||||
Tcl_SignalId(WSTOPSIG(waitStatus)), p, NULL);
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"child suspended: %s\n", p));
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"child wait status didn't make sense\n", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC",
|
||||
"ODDWAITRESULT", msg1, NULL);
|
||||
}
|
||||
Tcl_SetObjErrorCode(interp, error);
|
||||
Tcl_SetObjResult(interp, msg);
|
||||
}
|
||||
Tcl_DecrRefCount(error);
|
||||
Tcl_DecrRefCount(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -936,6 +899,7 @@ TclCreatePipeline(
|
||||
|
||||
pidPtr[numPids] = pid;
|
||||
numPids++;
|
||||
TclProcessCreated(pid);
|
||||
|
||||
/*
|
||||
* Close off our copies of file descriptors that were set up for this
|
||||
|
||||
+463
-332
@@ -65,6 +65,18 @@ typedef struct Package {
|
||||
const void *clientData; /* Client data. */
|
||||
} Package;
|
||||
|
||||
typedef struct Require {
|
||||
void * clientDataPtr;
|
||||
const char *name;
|
||||
Package *pkgPtr;
|
||||
char *versionToProvide;
|
||||
} Require;
|
||||
|
||||
typedef struct RequireProcArgs {
|
||||
const char *name;
|
||||
void *clientDataPtr;
|
||||
} RequireProcArgs;
|
||||
|
||||
/*
|
||||
* Prototypes for functions defined in this file:
|
||||
*/
|
||||
@@ -85,9 +97,15 @@ static void AddRequirementsToResult(Tcl_Interp *interp, int reqc,
|
||||
static void AddRequirementsToDString(Tcl_DString *dstring,
|
||||
int reqc, Tcl_Obj *const reqv[]);
|
||||
static Package * FindPackage(Tcl_Interp *interp, const char *name);
|
||||
static const char * PkgRequireCore(Tcl_Interp *interp, const char *name,
|
||||
int reqc, Tcl_Obj *const reqv[],
|
||||
void *clientDataPtr);
|
||||
static int PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static int PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static int PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static int PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static int PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static int TclNRPkgRequireProc(ClientData clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]);
|
||||
static int SelectPackage(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static int SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result);
|
||||
static int TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result);
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
@@ -365,7 +383,10 @@ Tcl_PkgRequireEx(
|
||||
*/
|
||||
|
||||
if (version == NULL) {
|
||||
result = PkgRequireCore(interp, name, 0, NULL, clientDataPtr);
|
||||
if (Tcl_PkgRequireProc(interp, name, 0, NULL, clientDataPtr) == TCL_OK) {
|
||||
result = Tcl_GetStringResult(interp);
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
} else {
|
||||
if (exact && TCL_OK
|
||||
!= CheckVersionAndConvert(interp, version, NULL, NULL)) {
|
||||
@@ -376,10 +397,12 @@ Tcl_PkgRequireEx(
|
||||
Tcl_AppendStringsToObj(ov, "-", version, NULL);
|
||||
}
|
||||
Tcl_IncrRefCount(ov);
|
||||
result = PkgRequireCore(interp, name, 1, &ov, clientDataPtr);
|
||||
if (Tcl_PkgRequireProc(interp, name, 1, &ov, clientDataPtr) == TCL_OK) {
|
||||
result = Tcl_GetStringResult(interp);
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
TclDecrRefCount(ov);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -394,343 +417,130 @@ Tcl_PkgRequireProc(
|
||||
* available. */
|
||||
void *clientDataPtr)
|
||||
{
|
||||
const char *result =
|
||||
PkgRequireCore(interp, name, reqc, reqv, clientDataPtr);
|
||||
RequireProcArgs args;
|
||||
args.name = name;
|
||||
args.clientDataPtr = clientDataPtr;
|
||||
return Tcl_NRCallObjProc(interp, TclNRPkgRequireProc, (void *)&args, reqc, reqv);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1));
|
||||
static int
|
||||
TclNRPkgRequireProc(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int reqc,
|
||||
Tcl_Obj *const reqv[]) {
|
||||
RequireProcArgs *args = clientData;
|
||||
Tcl_NRAddCallback(interp, PkgRequireCore, (void *)args->name, INT2PTR(reqc), (void *)reqv, args->clientDataPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static const char *
|
||||
PkgRequireCore(
|
||||
Tcl_Interp *interp, /* Interpreter in which package is now
|
||||
* available. */
|
||||
const char *name, /* Name of desired package. */
|
||||
int reqc, /* Requirements constraining the desired
|
||||
* version. */
|
||||
Tcl_Obj *const reqv[], /* 0 means to use the latest version
|
||||
* available. */
|
||||
void *clientDataPtr)
|
||||
static int
|
||||
PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Package *pkgPtr;
|
||||
PkgAvail *availPtr, *bestPtr, *bestStablePtr;
|
||||
char *availVersion, *bestVersion, *bestStableVersion;
|
||||
/* Internal rep. of versions */
|
||||
int availStable, code, satisfies, pass;
|
||||
char *script, *pkgVersionI;
|
||||
Tcl_DString command;
|
||||
|
||||
if (TCL_OK != CheckAllRequirements(interp, reqc, reqv)) {
|
||||
return NULL;
|
||||
const char *name = data[0];
|
||||
int reqc = PTR2INT(data[1]);
|
||||
Tcl_Obj *const *reqv = data[2];
|
||||
int code = CheckAllRequirements(interp, reqc, reqv);
|
||||
Require *reqPtr;
|
||||
if (code != TCL_OK) {
|
||||
return code;
|
||||
}
|
||||
reqPtr = ckalloc(sizeof(Require));
|
||||
Tcl_NRAddCallback(interp, PkgRequireCoreCleanup, reqPtr, NULL, NULL, NULL);
|
||||
reqPtr->clientDataPtr = data[3];
|
||||
reqPtr->name = name;
|
||||
reqPtr->pkgPtr = FindPackage(interp, name);
|
||||
if (reqPtr->pkgPtr->version == NULL) {
|
||||
Tcl_NRAddCallback(interp, SelectPackage, reqPtr, INT2PTR(reqc), (void *)reqv, PkgRequireCoreStep1);
|
||||
} else {
|
||||
Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* It can take up to three passes to find the package: one pass to run the
|
||||
* "package unknown" script, one to run the "package ifneeded" script for
|
||||
* a specific version, and a final pass to lookup the package loaded by
|
||||
* the "package ifneeded" script.
|
||||
*/
|
||||
|
||||
for (pass=1 ;; pass++) {
|
||||
pkgPtr = FindPackage(interp, name);
|
||||
if (pkgPtr->version != NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether we're already attempting to load some version of this
|
||||
* package (circular dependency detection).
|
||||
*/
|
||||
|
||||
if (pkgPtr->clientData != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"circular package dependency:"
|
||||
" attempt to provide %s %s requires %s",
|
||||
name, (char *) pkgPtr->clientData, name));
|
||||
AddRequirementsToResult(interp, reqc, reqv);
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The package isn't yet present. Search the list of available
|
||||
* versions and invoke the script for the best available version. We
|
||||
* are actually locating the best, and the best stable version. One of
|
||||
* them is then chosen based on the selection mode.
|
||||
*/
|
||||
|
||||
bestPtr = NULL;
|
||||
bestStablePtr = NULL;
|
||||
bestVersion = NULL;
|
||||
bestStableVersion = NULL;
|
||||
|
||||
for (availPtr = pkgPtr->availPtr; availPtr != NULL;
|
||||
availPtr = availPtr->nextPtr) {
|
||||
if (CheckVersionAndConvert(interp, availPtr->version,
|
||||
&availVersion, &availStable) != TCL_OK) {
|
||||
/*
|
||||
* The provided version number has invalid syntax. This
|
||||
* should not happen. This should have been caught by the
|
||||
* 'package ifneeded' registering the package.
|
||||
*/
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check satisfaction of requirements before considering the current version further. */
|
||||
if (reqc > 0) {
|
||||
satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv);
|
||||
if (!satisfies) {
|
||||
ckfree(availVersion);
|
||||
availVersion = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestPtr != NULL) {
|
||||
int res = CompareVersions(availVersion, bestVersion, NULL);
|
||||
|
||||
/*
|
||||
* Note: Used internal reps in the comparison!
|
||||
*/
|
||||
|
||||
if (res > 0) {
|
||||
/*
|
||||
* The version of the package sought is better than the
|
||||
* currently selected version.
|
||||
*/
|
||||
goto newbest;
|
||||
}
|
||||
} else {
|
||||
newbest:
|
||||
/* We have found a version which is better than our max. */
|
||||
|
||||
bestPtr = availPtr;
|
||||
CheckVersionAndConvert(interp, bestPtr->version, &bestVersion, NULL);
|
||||
}
|
||||
|
||||
if (!availStable) {
|
||||
ckfree(availVersion);
|
||||
availVersion = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bestStablePtr != NULL) {
|
||||
int res = CompareVersions(availVersion, bestStableVersion, NULL);
|
||||
|
||||
/*
|
||||
* Note: Used internal reps in the comparison!
|
||||
*/
|
||||
|
||||
if (res > 0) {
|
||||
/*
|
||||
* This stable version of the package sought is better
|
||||
* than the currently selected stable version.
|
||||
*/
|
||||
goto newstable;
|
||||
}
|
||||
} else {
|
||||
newstable:
|
||||
/* We have found a stable version which is better than our max stable. */
|
||||
bestStablePtr = availPtr;
|
||||
CheckVersionAndConvert(interp, bestStablePtr->version, &bestStableVersion, NULL);
|
||||
}
|
||||
|
||||
ckfree(availVersion);
|
||||
availVersion = NULL;
|
||||
} /* end for */
|
||||
|
||||
/*
|
||||
* Clean up memorized internal reps, if any.
|
||||
*/
|
||||
|
||||
if (bestVersion != NULL) {
|
||||
ckfree(bestVersion);
|
||||
bestVersion = NULL;
|
||||
}
|
||||
|
||||
if (bestStableVersion != NULL) {
|
||||
ckfree(bestStableVersion);
|
||||
bestStableVersion = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now choose a version among the two best. For 'latest' we simply
|
||||
* take (actually keep) the best. For 'stable' we take the best
|
||||
* stable, if there is any, or the best if there is nothing stable.
|
||||
*/
|
||||
|
||||
if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
|
||||
&& (bestStablePtr != NULL)) {
|
||||
bestPtr = bestStablePtr;
|
||||
}
|
||||
|
||||
if (bestPtr != NULL) {
|
||||
static int
|
||||
PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result) {
|
||||
Tcl_DString command;
|
||||
char *script;
|
||||
Require *reqPtr = data[0];
|
||||
int reqc = PTR2INT(data[1]);
|
||||
Tcl_Obj **const reqv = data[2];
|
||||
const char *name = reqPtr->name /* Name of desired package. */;
|
||||
if (reqPtr->pkgPtr->version == NULL) {
|
||||
/*
|
||||
* We found an ifneeded script for the package. Be careful while
|
||||
* executing it: this could cause reentrancy, so (a) protect the
|
||||
* script itself from deletion and (b) don't assume that bestPtr
|
||||
* will still exist when the script completes.
|
||||
* The package is not in the database. If there is a "package unknown"
|
||||
* command, invoke it.
|
||||
*/
|
||||
|
||||
char *versionToProvide = bestPtr->version;
|
||||
PkgFiles *pkgFiles;
|
||||
PkgName *pkgName;
|
||||
script = bestPtr->script;
|
||||
script = ((Interp *) interp)->packageUnknown;
|
||||
if (script == NULL) {
|
||||
Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
|
||||
} else {
|
||||
Tcl_DStringInit(&command);
|
||||
Tcl_DStringAppend(&command, script, -1);
|
||||
Tcl_DStringAppendElement(&command, name);
|
||||
AddRequirementsToDString(&command, reqc, reqv);
|
||||
|
||||
pkgPtr->clientData = versionToProvide;
|
||||
Tcl_Preserve(versionToProvide);
|
||||
Tcl_Preserve(script);
|
||||
pkgFiles = TclInitPkgFiles(interp);
|
||||
/* Push "ifneeded" package name in "tclPkgFiles" assocdata. */
|
||||
pkgName = ckalloc(sizeof(PkgName) + strlen(name));
|
||||
pkgName->nextPtr = pkgFiles->names;
|
||||
strcpy(pkgName->name, name);
|
||||
pkgFiles->names = pkgName;
|
||||
if (bestPtr->pkgIndex) {
|
||||
TclPkgFileSeen(interp, bestPtr->pkgIndex);
|
||||
Tcl_NRAddCallback(interp, PkgRequireCoreStep2, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
|
||||
Tcl_NREvalObj(interp,
|
||||
Tcl_NewStringObj(Tcl_DStringValue(&command), Tcl_DStringLength(&command)),
|
||||
TCL_EVAL_GLOBAL
|
||||
);
|
||||
Tcl_DStringFree(&command);
|
||||
}
|
||||
code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);
|
||||
/* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/
|
||||
pkgFiles->names = pkgName->nextPtr;
|
||||
ckfree(pkgName);
|
||||
Tcl_Release(script);
|
||||
|
||||
pkgPtr = FindPackage(interp, name);
|
||||
if (code == TCL_OK) {
|
||||
Tcl_ResetResult(interp);
|
||||
if (pkgPtr->version == NULL) {
|
||||
code = TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"attempt to provide package %s %s failed:"
|
||||
" no version of package %s provided",
|
||||
name, versionToProvide, name));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED",
|
||||
NULL);
|
||||
} else {
|
||||
char *pvi, *vi;
|
||||
|
||||
if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi,
|
||||
NULL) != TCL_OK) {
|
||||
code = TCL_ERROR;
|
||||
} else if (CheckVersionAndConvert(interp,
|
||||
versionToProvide, &vi, NULL) != TCL_OK) {
|
||||
ckfree(pvi);
|
||||
code = TCL_ERROR;
|
||||
} else {
|
||||
int res = CompareVersions(pvi, vi, NULL);
|
||||
|
||||
ckfree(pvi);
|
||||
ckfree(vi);
|
||||
if (res != 0) {
|
||||
code = TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"attempt to provide package %s %s failed:"
|
||||
" package %s %s provided instead",
|
||||
name, versionToProvide,
|
||||
name, pkgPtr->version));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE",
|
||||
"WRONGPROVIDE", NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (code != TCL_ERROR) {
|
||||
Tcl_Obj *codePtr = Tcl_NewIntObj(code);
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"attempt to provide package %s %s failed:"
|
||||
" bad return code: %s",
|
||||
name, versionToProvide, TclGetString(codePtr)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
|
||||
TclDecrRefCount(codePtr);
|
||||
code = TCL_ERROR;
|
||||
}
|
||||
|
||||
if (code == TCL_ERROR) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (\"package ifneeded %s %s\" script)",
|
||||
name, versionToProvide));
|
||||
}
|
||||
Tcl_Release(versionToProvide);
|
||||
|
||||
if (code != TCL_OK) {
|
||||
/*
|
||||
* Take a non-TCL_OK code from the script as an indication the
|
||||
* package wasn't loaded properly, so the package system
|
||||
* should not remember an improper load.
|
||||
*
|
||||
* This is consistent with our returning NULL. If we're not
|
||||
* willing to tell our caller we got a particular version, we
|
||||
* shouldn't store that version for telling future callers
|
||||
* either.
|
||||
*/
|
||||
|
||||
if (pkgPtr->version != NULL) {
|
||||
ckfree(pkgPtr->version);
|
||||
pkgPtr->version = NULL;
|
||||
}
|
||||
pkgPtr->clientData = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The package is not in the database. If there is a "package unknown"
|
||||
* command, invoke it (but only on the first pass; after that, we
|
||||
* should not get here in the first place).
|
||||
*/
|
||||
|
||||
if (pass > 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
script = ((Interp *) interp)->packageUnknown;
|
||||
if (script != NULL) {
|
||||
Tcl_DStringInit(&command);
|
||||
Tcl_DStringAppend(&command, script, -1);
|
||||
Tcl_DStringAppendElement(&command, name);
|
||||
AddRequirementsToDString(&command, reqc, reqv);
|
||||
|
||||
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
|
||||
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
|
||||
Tcl_DStringFree(&command);
|
||||
|
||||
if ((code != TCL_OK) && (code != TCL_ERROR)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad return code: %d", code));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
|
||||
code = TCL_ERROR;
|
||||
}
|
||||
if (code == TCL_ERROR) {
|
||||
Tcl_AddErrorInfo(interp,
|
||||
"\n (\"package unknown\" script)");
|
||||
return NULL;
|
||||
}
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
return TCL_OK;
|
||||
} else {
|
||||
Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (pkgPtr->version == NULL) {
|
||||
static int
|
||||
PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result) {
|
||||
Require *reqPtr = data[0];
|
||||
int reqc = PTR2INT(data[1]);
|
||||
Tcl_Obj **const reqv = data[2];
|
||||
const char *name = reqPtr->name /* Name of desired package. */;
|
||||
if ((result != TCL_OK) && (result != TCL_ERROR)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad return code: %d", result));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AddErrorInfo(interp,
|
||||
"\n (\"package unknown\" script)");
|
||||
return result;
|
||||
}
|
||||
Tcl_ResetResult(interp);
|
||||
/* pkgPtr may now be invalid, so refresh it. */
|
||||
reqPtr->pkgPtr = FindPackage(interp, name);
|
||||
Tcl_NRAddCallback(interp, SelectPackage, reqPtr, INT2PTR(reqc), (void *)reqv, PkgRequireCoreFinal);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result) {
|
||||
Require *reqPtr = data[0];
|
||||
int reqc = PTR2INT(data[1]), satisfies;
|
||||
Tcl_Obj **const reqv = data[2];
|
||||
char *pkgVersionI;
|
||||
void *clientDataPtr = reqPtr->clientDataPtr;
|
||||
const char *name = reqPtr->name /* Name of desired package. */;
|
||||
if (reqPtr->pkgPtr->version == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"can't find package %s", name));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL);
|
||||
AddRequirementsToResult(interp, reqc, reqv);
|
||||
return NULL;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we know that the package is present. Make sure that the
|
||||
* provided version meets the current requirements.
|
||||
* Ensure that the provided version meets the current requirements.
|
||||
*/
|
||||
|
||||
if (reqc != 0) {
|
||||
CheckVersionAndConvert(interp, pkgPtr->version, &pkgVersionI, NULL);
|
||||
CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pkgVersionI, NULL);
|
||||
satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv);
|
||||
|
||||
ckfree(pkgVersionI);
|
||||
@@ -738,20 +548,301 @@ PkgRequireCore(
|
||||
if (!satisfies) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"version conflict for package \"%s\": have %s, need",
|
||||
name, pkgPtr->version));
|
||||
name, reqPtr->pkgPtr->version));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT",
|
||||
NULL);
|
||||
AddRequirementsToResult(interp, reqc, reqv);
|
||||
return NULL;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (clientDataPtr) {
|
||||
const void **ptr = (const void **) clientDataPtr;
|
||||
|
||||
*ptr = pkgPtr->clientData;
|
||||
*ptr = reqPtr->pkgPtr->clientData;
|
||||
}
|
||||
return pkgPtr->version;
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(reqPtr->pkgPtr->version, -1));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result) {
|
||||
ckfree(data[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
SelectPackage(ClientData data[], Tcl_Interp *interp, int result) {
|
||||
PkgAvail *availPtr, *bestPtr, *bestStablePtr;
|
||||
char *availVersion, *bestVersion, *bestStableVersion;
|
||||
/* Internal rep. of versions */
|
||||
int availStable, satisfies;
|
||||
Require *reqPtr = data[0];
|
||||
int reqc = PTR2INT(data[1]);
|
||||
Tcl_Obj **const reqv = data[2];
|
||||
const char *name = reqPtr->name;
|
||||
Package *pkgPtr = reqPtr->pkgPtr;
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
/*
|
||||
* Check whether we're already attempting to load some version of this
|
||||
* package (circular dependency detection).
|
||||
*/
|
||||
|
||||
if (pkgPtr->clientData != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"circular package dependency:"
|
||||
" attempt to provide %s %s requires %s",
|
||||
name, (char *) pkgPtr->clientData, name));
|
||||
AddRequirementsToResult(interp, reqc, reqv);
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* The package isn't yet present. Search the list of available
|
||||
* versions and invoke the script for the best available version. We
|
||||
* are actually locating the best, and the best stable version. One of
|
||||
* them is then chosen based on the selection mode.
|
||||
*/
|
||||
|
||||
bestPtr = NULL;
|
||||
bestStablePtr = NULL;
|
||||
bestVersion = NULL;
|
||||
bestStableVersion = NULL;
|
||||
|
||||
for (availPtr = pkgPtr->availPtr; availPtr != NULL;
|
||||
availPtr = availPtr->nextPtr) {
|
||||
if (CheckVersionAndConvert(interp, availPtr->version,
|
||||
&availVersion, &availStable) != TCL_OK) {
|
||||
/*
|
||||
* The provided version number has invalid syntax. This
|
||||
* should not happen. This should have been caught by the
|
||||
* 'package ifneeded' registering the package.
|
||||
*/
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check satisfaction of requirements before considering the current version further. */
|
||||
if (reqc > 0) {
|
||||
satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv);
|
||||
if (!satisfies) {
|
||||
ckfree(availVersion);
|
||||
availVersion = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestPtr != NULL) {
|
||||
int res = CompareVersions(availVersion, bestVersion, NULL);
|
||||
|
||||
/*
|
||||
* Note: Used internal reps in the comparison!
|
||||
*/
|
||||
|
||||
if (res > 0) {
|
||||
/*
|
||||
* The version of the package sought is better than the
|
||||
* currently selected version.
|
||||
*/
|
||||
ckfree(bestVersion);
|
||||
bestVersion = NULL;
|
||||
goto newbest;
|
||||
}
|
||||
} else {
|
||||
newbest:
|
||||
/* We have found a version which is better than our max. */
|
||||
|
||||
bestPtr = availPtr;
|
||||
CheckVersionAndConvert(interp, bestPtr->version, &bestVersion, NULL);
|
||||
}
|
||||
|
||||
if (!availStable) {
|
||||
ckfree(availVersion);
|
||||
availVersion = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bestStablePtr != NULL) {
|
||||
int res = CompareVersions(availVersion, bestStableVersion, NULL);
|
||||
|
||||
/*
|
||||
* Note: Used internal reps in the comparison!
|
||||
*/
|
||||
|
||||
if (res > 0) {
|
||||
/*
|
||||
* This stable version of the package sought is better
|
||||
* than the currently selected stable version.
|
||||
*/
|
||||
ckfree(bestStableVersion);
|
||||
bestStableVersion = NULL;
|
||||
goto newstable;
|
||||
}
|
||||
} else {
|
||||
newstable:
|
||||
/* We have found a stable version which is better than our max stable. */
|
||||
bestStablePtr = availPtr;
|
||||
CheckVersionAndConvert(interp, bestStablePtr->version, &bestStableVersion, NULL);
|
||||
}
|
||||
|
||||
ckfree(availVersion);
|
||||
availVersion = NULL;
|
||||
} /* end for */
|
||||
|
||||
/*
|
||||
* Clean up memorized internal reps, if any.
|
||||
*/
|
||||
|
||||
if (bestVersion != NULL) {
|
||||
ckfree(bestVersion);
|
||||
bestVersion = NULL;
|
||||
}
|
||||
|
||||
if (bestStableVersion != NULL) {
|
||||
ckfree(bestStableVersion);
|
||||
bestStableVersion = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now choose a version among the two best. For 'latest' we simply
|
||||
* take (actually keep) the best. For 'stable' we take the best
|
||||
* stable, if there is any, or the best if there is nothing stable.
|
||||
*/
|
||||
|
||||
if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
|
||||
&& (bestStablePtr != NULL)) {
|
||||
bestPtr = bestStablePtr;
|
||||
}
|
||||
|
||||
if (bestPtr == NULL) {
|
||||
Tcl_NRAddCallback(interp, data[3], reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
|
||||
} else {
|
||||
/*
|
||||
* We found an ifneeded script for the package. Be careful while
|
||||
* executing it: this could cause reentrancy, so (a) protect the
|
||||
* script itself from deletion and (b) don't assume that bestPtr
|
||||
* will still exist when the script completes.
|
||||
*/
|
||||
|
||||
char *versionToProvide = bestPtr->version;
|
||||
PkgFiles *pkgFiles;
|
||||
PkgName *pkgName;
|
||||
|
||||
Tcl_Preserve(versionToProvide);
|
||||
pkgPtr->clientData = versionToProvide;
|
||||
|
||||
pkgFiles = TclInitPkgFiles(interp);
|
||||
/* Push "ifneeded" package name in "tclPkgFiles" assocdata. */
|
||||
pkgName = ckalloc(sizeof(PkgName) + strlen(name));
|
||||
pkgName->nextPtr = pkgFiles->names;
|
||||
strcpy(pkgName->name, name);
|
||||
pkgFiles->names = pkgName;
|
||||
if (bestPtr->pkgIndex) {
|
||||
TclPkgFileSeen(interp, bestPtr->pkgIndex);
|
||||
}
|
||||
reqPtr->versionToProvide = versionToProvide;
|
||||
Tcl_NRAddCallback(interp, SelectPackageFinal, reqPtr, INT2PTR(reqc), (void *)reqv, data[3]);
|
||||
Tcl_NREvalObj(interp, Tcl_NewStringObj(bestPtr->script, -1), TCL_EVAL_GLOBAL);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result) {
|
||||
Require *reqPtr = data[0];
|
||||
int reqc = PTR2INT(data[1]);
|
||||
Tcl_Obj **const reqv = data[2];
|
||||
const char *name = reqPtr->name;
|
||||
char *versionToProvide = reqPtr->versionToProvide;
|
||||
|
||||
/* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/
|
||||
PkgFiles *pkgFiles = Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
|
||||
PkgName *pkgName = pkgFiles->names;
|
||||
pkgFiles->names = pkgName->nextPtr;
|
||||
ckfree(pkgName);
|
||||
|
||||
reqPtr->pkgPtr = FindPackage(interp, name);
|
||||
if (result == TCL_OK) {
|
||||
Tcl_ResetResult(interp);
|
||||
if (reqPtr->pkgPtr->version == NULL) {
|
||||
result = TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"attempt to provide package %s %s failed:"
|
||||
" no version of package %s provided",
|
||||
name, versionToProvide, name));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED",
|
||||
NULL);
|
||||
} else {
|
||||
char *pvi, *vi;
|
||||
|
||||
if (CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pvi,
|
||||
NULL) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
} else if (CheckVersionAndConvert(interp,
|
||||
versionToProvide, &vi, NULL) != TCL_OK) {
|
||||
ckfree(pvi);
|
||||
result = TCL_ERROR;
|
||||
} else {
|
||||
int res = CompareVersions(pvi, vi, NULL);
|
||||
|
||||
ckfree(pvi);
|
||||
ckfree(vi);
|
||||
if (res != 0) {
|
||||
result = TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"attempt to provide package %s %s failed:"
|
||||
" package %s %s provided instead",
|
||||
name, versionToProvide,
|
||||
name, reqPtr->pkgPtr->version));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE",
|
||||
"WRONGPROVIDE", NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (result != TCL_ERROR) {
|
||||
Tcl_Obj *codePtr = Tcl_NewIntObj(result);
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"attempt to provide package %s %s failed:"
|
||||
" bad return code: %s",
|
||||
name, versionToProvide, TclGetString(codePtr)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
|
||||
TclDecrRefCount(codePtr);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (\"package ifneeded %s %s\" script)",
|
||||
name, versionToProvide));
|
||||
}
|
||||
Tcl_Release(versionToProvide);
|
||||
|
||||
if (result != TCL_OK) {
|
||||
/*
|
||||
* Take a non-TCL_OK code from the script as an indication the
|
||||
* package wasn't loaded properly, so the package system
|
||||
* should not remember an improper load.
|
||||
*
|
||||
* This is consistent with our returning NULL. If we're not
|
||||
* willing to tell our caller we got a particular version, we
|
||||
* shouldn't store that version for telling future callers
|
||||
* either.
|
||||
*/
|
||||
|
||||
if (reqPtr->pkgPtr->version != NULL) {
|
||||
ckfree(reqPtr->pkgPtr->version);
|
||||
reqPtr->pkgPtr->version = NULL;
|
||||
}
|
||||
reqPtr->pkgPtr->clientData = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
Tcl_NRAddCallback(interp, data[3], reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -857,10 +948,19 @@ Tcl_PkgPresentEx(
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Tcl_PackageObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
return Tcl_NRCallObjProc(interp, TclNRPackageObjCmd, NULL, objc, objv);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
Tcl_PackageObjCmd(
|
||||
TclNRPackageObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
@@ -877,7 +977,7 @@ Tcl_PackageObjCmd(
|
||||
PKG_VERSIONS, PKG_VSATISFIES
|
||||
};
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
int optionIndex, exact, i, satisfies;
|
||||
int optionIndex, exact, i, newobjc, satisfies;
|
||||
PkgAvail *availPtr, *prevPtr;
|
||||
Package *pkgPtr;
|
||||
Tcl_HashEntry *hPtr;
|
||||
@@ -886,6 +986,7 @@ Tcl_PackageObjCmd(
|
||||
const char *version;
|
||||
const char *argv2, *argv3, *argv4;
|
||||
char *iva = NULL, *ivb = NULL;
|
||||
Tcl_Obj *objvListPtr, **newObjvPtr;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
|
||||
@@ -944,6 +1045,7 @@ Tcl_PackageObjCmd(
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
availPtr->pkgIndex = NULL;
|
||||
}
|
||||
ckfree(availPtr);
|
||||
}
|
||||
@@ -997,6 +1099,7 @@ Tcl_PackageObjCmd(
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
availPtr->pkgIndex = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1008,7 +1111,7 @@ Tcl_PackageObjCmd(
|
||||
}
|
||||
if (availPtr == NULL) {
|
||||
availPtr = ckalloc(sizeof(PkgAvail));
|
||||
availPtr->pkgIndex = 0;
|
||||
availPtr->pkgIndex = NULL;
|
||||
DupBlock(availPtr->version, argv3, (unsigned) length + 1);
|
||||
|
||||
if (prevPtr == NULL) {
|
||||
@@ -1129,7 +1232,6 @@ Tcl_PackageObjCmd(
|
||||
argv2 = TclGetString(objv[2]);
|
||||
if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
|
||||
Tcl_Obj *ov;
|
||||
int res;
|
||||
|
||||
if (objc != 5) {
|
||||
goto requireSyntax;
|
||||
@@ -1149,17 +1251,38 @@ Tcl_PackageObjCmd(
|
||||
Tcl_AppendStringsToObj(ov, "-", version, NULL);
|
||||
version = NULL;
|
||||
argv3 = TclGetString(objv[3]);
|
||||
Tcl_IncrRefCount(objv[3]);
|
||||
|
||||
Tcl_IncrRefCount(ov);
|
||||
res = Tcl_PkgRequireProc(interp, argv3, 1, &ov, NULL);
|
||||
TclDecrRefCount(ov);
|
||||
return res;
|
||||
objvListPtr = Tcl_NewListObj(0, NULL);
|
||||
Tcl_IncrRefCount(objvListPtr);
|
||||
Tcl_ListObjAppendElement(interp, objvListPtr, ov);
|
||||
Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
|
||||
|
||||
Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[3], objvListPtr, NULL, NULL);
|
||||
Tcl_NRAddCallback(interp, PkgRequireCore, (void *)argv3, INT2PTR(newobjc), newObjvPtr, NULL);
|
||||
return TCL_OK;
|
||||
} else {
|
||||
int i, newobjc = objc-3;
|
||||
Tcl_Obj *const *newobjv = objv + 3;
|
||||
if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objvListPtr = Tcl_NewListObj(0, NULL);
|
||||
Tcl_IncrRefCount(objvListPtr);
|
||||
Tcl_IncrRefCount(objv[2]);
|
||||
for (i = 0; i < newobjc; i++) {
|
||||
|
||||
return Tcl_PkgRequireProc(interp, argv2, objc-3, objv+3, NULL);
|
||||
/*
|
||||
* Tcl_Obj structures may have come from another interpreter,
|
||||
* so duplicate them.
|
||||
*/
|
||||
|
||||
Tcl_ListObjAppendElement(interp, objvListPtr, Tcl_DuplicateObj(newobjv[i]));
|
||||
}
|
||||
Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
|
||||
Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[2], objvListPtr, NULL, NULL);
|
||||
Tcl_NRAddCallback(interp, PkgRequireCore, (void *)argv2, INT2PTR(newobjc), newObjvPtr, NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
break;
|
||||
case PKG_UNKNOWN: {
|
||||
@@ -1299,6 +1422,13 @@ Tcl_PackageObjCmd(
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result) {
|
||||
TclDecrRefCount((Tcl_Obj *)data[0]);
|
||||
TclDecrRefCount((Tcl_Obj *)data[1]);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -1380,6 +1510,7 @@ TclFreePackageInfo(
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
availPtr->pkgIndex = NULL;
|
||||
}
|
||||
ckfree(availPtr);
|
||||
}
|
||||
|
||||
+3
-3
@@ -790,7 +790,7 @@ TclObjGetFrame(
|
||||
level = curLevel - level;
|
||||
result = 1;
|
||||
} else if (objPtr->typePtr == &levelReferenceType) {
|
||||
level = (int) objPtr->internalRep.longValue;
|
||||
level = (int) objPtr->internalRep.wideValue;
|
||||
result = 1;
|
||||
} else {
|
||||
name = TclGetString(objPtr);
|
||||
@@ -798,7 +798,7 @@ TclObjGetFrame(
|
||||
if (TCL_OK == Tcl_GetInt(NULL, name+1, &level) && level >= 0) {
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &levelReferenceType;
|
||||
objPtr->internalRep.longValue = level;
|
||||
objPtr->internalRep.wideValue = level;
|
||||
result = 1;
|
||||
} else {
|
||||
result = -1;
|
||||
@@ -2380,7 +2380,7 @@ FreeLambdaInternalRep(
|
||||
Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
Tcl_Obj *nsObjPtr = objPtr->internalRep.twoPtrValue.ptr2;
|
||||
|
||||
if (procPtr->refCount-- == 1) {
|
||||
if (procPtr->refCount-- <= 1) {
|
||||
TclProcCleanupProc(procPtr);
|
||||
}
|
||||
TclDecrRefCount(nsObjPtr);
|
||||
|
||||
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
* tclProcess.c --
|
||||
*
|
||||
* This file implements the "tcl::process" ensemble for subprocess
|
||||
* management as defined by TIP #462.
|
||||
*
|
||||
* Copyright (c) 2017 Frederic Bonnet.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
/*
|
||||
* Autopurge flag. Process-global because of the way Tcl manages child
|
||||
* processes (see tclPipe.c).
|
||||
*/
|
||||
|
||||
static int autopurge = 1; /* Autopurge flag. */
|
||||
|
||||
/*
|
||||
* Hash tables that keeps track of all child process statuses. Keys are the
|
||||
* child process ids and resolved pids, values are (ProcessInfo *).
|
||||
*/
|
||||
|
||||
typedef struct ProcessInfo {
|
||||
Tcl_Pid pid; /* Process id. */
|
||||
int resolvedPid; /* Resolved process id. */
|
||||
int purge; /* Purge eventualy. */
|
||||
TclProcessWaitStatus status;/* Process status. */
|
||||
int code; /* Error code, exit status or signal
|
||||
number. */
|
||||
Tcl_Obj *msg; /* Error message. */
|
||||
Tcl_Obj *error; /* Error code. */
|
||||
} ProcessInfo;
|
||||
static Tcl_HashTable infoTablePerPid;
|
||||
static Tcl_HashTable infoTablePerResolvedPid;
|
||||
static int infoTablesInitialized = 0; /* 0 means not yet initialized. */
|
||||
TCL_DECLARE_MUTEX(infoTablesMutex)
|
||||
|
||||
/*
|
||||
* Prototypes for functions defined later in this file:
|
||||
*/
|
||||
|
||||
static void InitProcessInfo(ProcessInfo *info, Tcl_Pid pid,
|
||||
int resolvedPid);
|
||||
static void FreeProcessInfo(ProcessInfo *info);
|
||||
static int RefreshProcessInfo(ProcessInfo *info, int options);
|
||||
static TclProcessWaitStatus WaitProcessStatus(Tcl_Pid pid, int resolvedPid,
|
||||
int options, int *codePtr, Tcl_Obj **msgPtr,
|
||||
Tcl_Obj **errorObjPtr);
|
||||
static Tcl_Obj * BuildProcessStatusObj(ProcessInfo *info);
|
||||
static int ProcessListObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int ProcessStatusObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int ProcessPurgeObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int ProcessAutopurgeObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* InitProcessInfo --
|
||||
*
|
||||
* Initializes the ProcessInfo structure.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Memory written.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
InitProcessInfo(
|
||||
ProcessInfo *info, /* Structure to initialize. */
|
||||
Tcl_Pid pid, /* Process id. */
|
||||
int resolvedPid) /* Resolved process id. */
|
||||
{
|
||||
info->pid = pid;
|
||||
info->resolvedPid = resolvedPid;
|
||||
info->purge = 0;
|
||||
info->status = TCL_PROCESS_UNCHANGED;
|
||||
info->code = 0;
|
||||
info->msg = NULL;
|
||||
info->error = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* FreeProcessInfo --
|
||||
*
|
||||
* Free the ProcessInfo structure.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Memory deallocated, Tcl_Obj refcount decreased.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
FreeProcessInfo(
|
||||
ProcessInfo *info) /* Structure to free. */
|
||||
{
|
||||
/*
|
||||
* Free stored Tcl_Objs.
|
||||
*/
|
||||
|
||||
if (info->msg) {
|
||||
Tcl_DecrRefCount(info->msg);
|
||||
}
|
||||
if (info->error) {
|
||||
Tcl_DecrRefCount(info->error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free allocated structure.
|
||||
*/
|
||||
|
||||
ckfree(info);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* RefreshProcessInfo --
|
||||
*
|
||||
* Refresh process info.
|
||||
*
|
||||
* Results:
|
||||
* Nonzero if state changed, else zero.
|
||||
*
|
||||
* Side effects:
|
||||
* May call WaitProcessStatus, which can block if WNOHANG option is set.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
RefreshProcessInfo(
|
||||
ProcessInfo *info, /* Structure to refresh. */
|
||||
int options /* Options passed to WaitProcessStatus. */
|
||||
)
|
||||
{
|
||||
if (info->status == TCL_PROCESS_UNCHANGED) {
|
||||
/*
|
||||
* Refresh & store status.
|
||||
*/
|
||||
|
||||
info->status = WaitProcessStatus(info->pid, info->resolvedPid,
|
||||
options, &info->code, &info->msg, &info->error);
|
||||
if (info->msg) Tcl_IncrRefCount(info->msg);
|
||||
if (info->error) Tcl_IncrRefCount(info->error);
|
||||
return (info->status != TCL_PROCESS_UNCHANGED);
|
||||
} else {
|
||||
/*
|
||||
* No change.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* WaitProcessStatus --
|
||||
*
|
||||
* Wait for process status to change.
|
||||
*
|
||||
* Results:
|
||||
* TclProcessWaitStatus enum value.
|
||||
*
|
||||
* Side effects:
|
||||
* May call WaitProcessStatus, which can block if WNOHANG option is set.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
TclProcessWaitStatus
|
||||
WaitProcessStatus(
|
||||
Tcl_Pid pid, /* Process id. */
|
||||
int resolvedPid, /* Resolved process id. */
|
||||
int options, /* Options passed to Tcl_WaitPid. */
|
||||
int *codePtr, /* If non-NULL, will receive either:
|
||||
* - 0 for normal exit.
|
||||
* - errno in case of error.
|
||||
* - non-zero exit code for abormal exit.
|
||||
* - signal number if killed or suspended.
|
||||
* - Tcl_WaitPid status in all other cases.
|
||||
*/
|
||||
Tcl_Obj **msgObjPtr, /* If non-NULL, will receive error message. */
|
||||
Tcl_Obj **errorObjPtr) /* If non-NULL, will receive error code. */
|
||||
{
|
||||
int waitStatus;
|
||||
Tcl_Obj *errorStrings[5];
|
||||
const char *msg;
|
||||
|
||||
pid = Tcl_WaitPid(pid, &waitStatus, options);
|
||||
if (pid == 0) {
|
||||
/*
|
||||
* No change.
|
||||
*/
|
||||
|
||||
return TCL_PROCESS_UNCHANGED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get process status.
|
||||
*/
|
||||
|
||||
if (pid == (Tcl_Pid) -1) {
|
||||
/*
|
||||
* POSIX errName msg
|
||||
*/
|
||||
|
||||
msg = Tcl_ErrnoMsg(errno);
|
||||
if (errno == ECHILD) {
|
||||
/*
|
||||
* This changeup in message suggested by Mark Diekhans to
|
||||
* remind people that ECHILD errors can occur on some
|
||||
* systems if SIGCHLD isn't in its default state.
|
||||
*/
|
||||
|
||||
msg = "child process lost (is SIGCHLD ignored or trapped?)";
|
||||
}
|
||||
if (codePtr) *codePtr = errno;
|
||||
if (msgObjPtr) *msgObjPtr = Tcl_ObjPrintf(
|
||||
"error waiting for process to exit: %s", msg);
|
||||
if (errorObjPtr) {
|
||||
errorStrings[0] = Tcl_NewStringObj("POSIX", -1);
|
||||
errorStrings[1] = Tcl_NewStringObj(Tcl_ErrnoId(), -1);
|
||||
errorStrings[2] = Tcl_NewStringObj(msg, -1);
|
||||
*errorObjPtr = Tcl_NewListObj(3, errorStrings);
|
||||
}
|
||||
return TCL_PROCESS_ERROR;
|
||||
} else if (WIFEXITED(waitStatus)) {
|
||||
if (codePtr) *codePtr = WEXITSTATUS(waitStatus);
|
||||
if (!WEXITSTATUS(waitStatus)) {
|
||||
/*
|
||||
* Normal exit.
|
||||
*/
|
||||
|
||||
if (msgObjPtr) *msgObjPtr = NULL;
|
||||
if (errorObjPtr) *errorObjPtr = NULL;
|
||||
} else {
|
||||
/*
|
||||
* CHILDSTATUS pid code
|
||||
*
|
||||
* Child exited with a non-zero exit status.
|
||||
*/
|
||||
|
||||
if (msgObjPtr) *msgObjPtr = Tcl_NewStringObj(
|
||||
"child process exited abnormally", -1);
|
||||
if (errorObjPtr) {
|
||||
errorStrings[0] = Tcl_NewStringObj("CHILDSTATUS", -1);
|
||||
errorStrings[1] = Tcl_NewIntObj(resolvedPid);
|
||||
errorStrings[2] = Tcl_NewIntObj(WEXITSTATUS(waitStatus));
|
||||
*errorObjPtr = Tcl_NewListObj(3, errorStrings);
|
||||
}
|
||||
}
|
||||
return TCL_PROCESS_EXITED;
|
||||
} else if (WIFSIGNALED(waitStatus)) {
|
||||
/*
|
||||
* CHILDKILLED pid sigName msg
|
||||
*
|
||||
* Child killed because of a signal.
|
||||
*/
|
||||
|
||||
msg = Tcl_SignalMsg(WTERMSIG(waitStatus));
|
||||
if (codePtr) *codePtr = WTERMSIG(waitStatus);
|
||||
if (msgObjPtr) *msgObjPtr = Tcl_ObjPrintf(
|
||||
"child killed: %s", msg);
|
||||
if (errorObjPtr) {
|
||||
errorStrings[0] = Tcl_NewStringObj("CHILDKILLED", -1);
|
||||
errorStrings[1] = Tcl_NewIntObj(resolvedPid);
|
||||
errorStrings[2] = Tcl_NewStringObj(Tcl_SignalId(WTERMSIG(waitStatus)), -1);
|
||||
errorStrings[3] = Tcl_NewStringObj(msg, -1);
|
||||
*errorObjPtr = Tcl_NewListObj(4, errorStrings);
|
||||
}
|
||||
return TCL_PROCESS_SIGNALED;
|
||||
} else if (WIFSTOPPED(waitStatus)) {
|
||||
/*
|
||||
* CHILDSUSP pid sigName msg
|
||||
*
|
||||
* Child suspended because of a signal.
|
||||
*/
|
||||
|
||||
msg = Tcl_SignalMsg(WSTOPSIG(waitStatus));
|
||||
if (codePtr) *codePtr = WSTOPSIG(waitStatus);
|
||||
if (msgObjPtr) *msgObjPtr = Tcl_ObjPrintf(
|
||||
"child suspended: %s", msg);
|
||||
if (errorObjPtr) {
|
||||
errorStrings[0] = Tcl_NewStringObj("CHILDSUSP", -1);
|
||||
errorStrings[1] = Tcl_NewIntObj(resolvedPid);
|
||||
errorStrings[2] = Tcl_NewStringObj(Tcl_SignalId(WSTOPSIG(waitStatus)), -1);
|
||||
errorStrings[3] = Tcl_NewStringObj(msg, -1);
|
||||
*errorObjPtr = Tcl_NewListObj(4, errorStrings);
|
||||
}
|
||||
return TCL_PROCESS_STOPPED;
|
||||
} else {
|
||||
/*
|
||||
* TCL OPERATION EXEC ODDWAITRESULT
|
||||
*
|
||||
* Child wait status didn't make sense.
|
||||
*/
|
||||
|
||||
if (codePtr) *codePtr = waitStatus;
|
||||
if (msgObjPtr) *msgObjPtr = Tcl_NewStringObj(
|
||||
"child wait status didn't make sense\n", -1);
|
||||
if (errorObjPtr) {
|
||||
errorStrings[0] = Tcl_NewStringObj("TCL", -1);
|
||||
errorStrings[1] = Tcl_NewStringObj("OPERATION", -1);
|
||||
errorStrings[2] = Tcl_NewStringObj("EXEC", -1);
|
||||
errorStrings[3] = Tcl_NewStringObj("ODDWAITRESULT", -1);
|
||||
errorStrings[4] = Tcl_NewIntObj(resolvedPid);
|
||||
*errorObjPtr = Tcl_NewListObj(5, errorStrings);
|
||||
}
|
||||
return TCL_PROCESS_UNKNOWN_STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* BuildProcessStatusObj --
|
||||
*
|
||||
* Build a list object with process status. The first element is always
|
||||
* a standard Tcl return value, which can be either TCL_OK or TCL_ERROR.
|
||||
* In the latter case, the second element is the error message and the
|
||||
* third element is a Tcl error code (see tclvars).
|
||||
*
|
||||
* Results:
|
||||
* A list object.
|
||||
*
|
||||
* Side effects:
|
||||
* Tcl_Objs are created.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
BuildProcessStatusObj(
|
||||
ProcessInfo *info)
|
||||
{
|
||||
Tcl_Obj *resultObjs[3];
|
||||
|
||||
if (info->status == TCL_PROCESS_UNCHANGED) {
|
||||
/*
|
||||
* Process still running, return empty obj.
|
||||
*/
|
||||
|
||||
return Tcl_NewObj();
|
||||
}
|
||||
if (info->status == TCL_PROCESS_EXITED && info->code == 0) {
|
||||
/*
|
||||
* Normal exit, return TCL_OK.
|
||||
*/
|
||||
|
||||
return Tcl_NewIntObj(TCL_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Abnormal exit, return {TCL_ERROR msg error}
|
||||
*/
|
||||
|
||||
resultObjs[0] = Tcl_NewIntObj(TCL_ERROR);
|
||||
resultObjs[1] = info->msg;
|
||||
resultObjs[2] = info->error;
|
||||
return Tcl_NewListObj(3, resultObjs);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* ProcessListObjCmd --
|
||||
*
|
||||
* This function implements the 'tcl::process list' Tcl command.
|
||||
* Refer to the user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Access to the internal structures is protected by infoTablesMutex.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ProcessListObjCmd(
|
||||
ClientData clientData, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Obj *list;
|
||||
Tcl_HashEntry *entry;
|
||||
Tcl_HashSearch search;
|
||||
ProcessInfo *info;
|
||||
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the list of all chid process ids.
|
||||
*/
|
||||
|
||||
list = Tcl_NewListObj(0, NULL);
|
||||
Tcl_MutexLock(&infoTablesMutex);
|
||||
for (entry = Tcl_FirstHashEntry(&infoTablePerResolvedPid, &search);
|
||||
entry != NULL; entry = Tcl_NextHashEntry(&search)) {
|
||||
info = (ProcessInfo *) Tcl_GetHashValue(entry);
|
||||
Tcl_ListObjAppendElement(interp, list,
|
||||
Tcl_NewIntObj(info->resolvedPid));
|
||||
}
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
Tcl_SetObjResult(interp, list);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* ProcessStatusObjCmd --
|
||||
*
|
||||
* This function implements the 'tcl::process status' Tcl command.
|
||||
* Refer to the user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Access to the internal structures is protected by infoTablesMutex.
|
||||
* Calls RefreshProcessInfo, which can block if -wait switch is given.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ProcessStatusObjCmd(
|
||||
ClientData clientData, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Obj *dict;
|
||||
int index, options = WNOHANG;
|
||||
Tcl_HashEntry *entry;
|
||||
Tcl_HashSearch search;
|
||||
ProcessInfo *info;
|
||||
int numPids;
|
||||
Tcl_Obj **pidObjs;
|
||||
int result;
|
||||
int i;
|
||||
int pid;
|
||||
Tcl_Obj *const *savedobjv = objv;
|
||||
static const char *const switches[] = {
|
||||
"-wait", "--", NULL
|
||||
};
|
||||
enum switches {
|
||||
STATUS_WAIT, STATUS_LAST
|
||||
};
|
||||
|
||||
while (objc > 1) {
|
||||
if (TclGetString(objv[1])[0] != '-') {
|
||||
break;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], switches, "switches", 0,
|
||||
&index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
++objv; --objc;
|
||||
if (STATUS_WAIT == (enum switches) index) {
|
||||
options = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (objc != 1 && objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, savedobjv, "?switches? ?pids?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (objc == 1) {
|
||||
/*
|
||||
* Return a dict with all child process statuses.
|
||||
*/
|
||||
|
||||
dict = Tcl_NewDictObj();
|
||||
Tcl_MutexLock(&infoTablesMutex);
|
||||
for (entry = Tcl_FirstHashEntry(&infoTablePerResolvedPid, &search);
|
||||
entry != NULL; entry = Tcl_NextHashEntry(&search)) {
|
||||
info = (ProcessInfo *) Tcl_GetHashValue(entry);
|
||||
RefreshProcessInfo(info, options);
|
||||
|
||||
if (info->purge && autopurge) {
|
||||
/*
|
||||
* Purge entry.
|
||||
*/
|
||||
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
entry = Tcl_FindHashEntry(&infoTablePerPid, info->pid);
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
FreeProcessInfo(info);
|
||||
} else {
|
||||
/*
|
||||
* Add to result.
|
||||
*/
|
||||
|
||||
Tcl_DictObjPut(interp, dict, Tcl_NewIntObj(info->resolvedPid),
|
||||
BuildProcessStatusObj(info));
|
||||
}
|
||||
}
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
} else {
|
||||
/*
|
||||
* Only return statuses of provided processes.
|
||||
*/
|
||||
|
||||
result = Tcl_ListObjGetElements(interp, objv[1], &numPids, &pidObjs);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
dict = Tcl_NewDictObj();
|
||||
Tcl_MutexLock(&infoTablesMutex);
|
||||
for (i = 0; i < numPids; i++) {
|
||||
result = Tcl_GetIntFromObj(interp, pidObjs[i], (int *) &pid);
|
||||
if (result != TCL_OK) {
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
Tcl_DecrRefCount(dict);
|
||||
return result;
|
||||
}
|
||||
|
||||
entry = Tcl_FindHashEntry(&infoTablePerResolvedPid, INT2PTR(pid));
|
||||
if (!entry) {
|
||||
/*
|
||||
* Skip unknown process.
|
||||
*/
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
info = (ProcessInfo *) Tcl_GetHashValue(entry);
|
||||
RefreshProcessInfo(info, options);
|
||||
|
||||
if (info->purge && autopurge) {
|
||||
/*
|
||||
* Purge entry.
|
||||
*/
|
||||
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
entry = Tcl_FindHashEntry(&infoTablePerPid, info->pid);
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
FreeProcessInfo(info);
|
||||
} else {
|
||||
/*
|
||||
* Add to result.
|
||||
*/
|
||||
|
||||
Tcl_DictObjPut(interp, dict, Tcl_NewIntObj(info->resolvedPid),
|
||||
BuildProcessStatusObj(info));
|
||||
}
|
||||
}
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
}
|
||||
Tcl_SetObjResult(interp, dict);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* ProcessPurgeObjCmd --
|
||||
*
|
||||
* This function implements the 'tcl::process purge' Tcl command.
|
||||
* Refer to the user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Frees all ProcessInfo structures with their purge flag set.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ProcessPurgeObjCmd(
|
||||
ClientData clientData, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_HashEntry *entry;
|
||||
Tcl_HashSearch search;
|
||||
ProcessInfo *info;
|
||||
int numPids;
|
||||
Tcl_Obj **pidObjs;
|
||||
int result;
|
||||
int i;
|
||||
int pid;
|
||||
|
||||
if (objc != 1 && objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?pids?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* First reap detached procs so that their purge flag is up-to-date.
|
||||
*/
|
||||
|
||||
Tcl_ReapDetachedProcs();
|
||||
|
||||
if (objc == 1) {
|
||||
/*
|
||||
* Purge all terminated processes.
|
||||
*/
|
||||
|
||||
Tcl_MutexLock(&infoTablesMutex);
|
||||
for (entry = Tcl_FirstHashEntry(&infoTablePerResolvedPid, &search);
|
||||
entry != NULL; entry = Tcl_NextHashEntry(&search)) {
|
||||
info = (ProcessInfo *) Tcl_GetHashValue(entry);
|
||||
if (info->purge) {
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
entry = Tcl_FindHashEntry(&infoTablePerPid, info->pid);
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
FreeProcessInfo(info);
|
||||
}
|
||||
}
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
} else {
|
||||
/*
|
||||
* Purge only provided processes.
|
||||
*/
|
||||
|
||||
result = Tcl_ListObjGetElements(interp, objv[1], &numPids, &pidObjs);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
Tcl_MutexLock(&infoTablesMutex);
|
||||
for (i = 0; i < numPids; i++) {
|
||||
result = Tcl_GetIntFromObj(interp, pidObjs[i], (int *) &pid);
|
||||
if (result != TCL_OK) {
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
entry = Tcl_FindHashEntry(&infoTablePerResolvedPid, INT2PTR(pid));
|
||||
if (!entry) {
|
||||
/*
|
||||
* Skip unknown process.
|
||||
*/
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
info = (ProcessInfo *) Tcl_GetHashValue(entry);
|
||||
if (info->purge) {
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
entry = Tcl_FindHashEntry(&infoTablePerPid, info->pid);
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
FreeProcessInfo(info);
|
||||
}
|
||||
}
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* ProcessAutopurgeObjCmd --
|
||||
*
|
||||
* This function implements the 'tcl::process autopurge' Tcl command.
|
||||
* Refer to the user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Alters detached process handling by Tcl_ReapDetachedProcs().
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ProcessAutopurgeObjCmd(
|
||||
ClientData clientData, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
if (objc != 1 && objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?flag?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (objc == 2) {
|
||||
/*
|
||||
* Set given value.
|
||||
*/
|
||||
|
||||
int flag;
|
||||
int result = Tcl_GetBooleanFromObj(interp, objv[1], &flag);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
autopurge = !!flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return current value.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(autopurge));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclInitProcessCmd --
|
||||
*
|
||||
* This procedure creates the "tcl::process" Tcl command. See the user
|
||||
* documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Command
|
||||
TclInitProcessCmd(
|
||||
Tcl_Interp *interp) /* Current interpreter. */
|
||||
{
|
||||
static const EnsembleImplMap processImplMap[] = {
|
||||
{"list", ProcessListObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 1},
|
||||
{"status", ProcessStatusObjCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 1},
|
||||
{"purge", ProcessPurgeObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
|
||||
{"autopurge", ProcessAutopurgeObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
Tcl_Command processCmd;
|
||||
|
||||
if (infoTablesInitialized == 0) {
|
||||
Tcl_MutexLock(&infoTablesMutex);
|
||||
if (infoTablesInitialized == 0) {
|
||||
Tcl_InitHashTable(&infoTablePerPid, TCL_ONE_WORD_KEYS);
|
||||
Tcl_InitHashTable(&infoTablePerResolvedPid, TCL_ONE_WORD_KEYS);
|
||||
infoTablesInitialized = 1;
|
||||
}
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
}
|
||||
|
||||
processCmd = TclMakeEnsemble(interp, "::tcl::process", processImplMap);
|
||||
Tcl_Export(interp, Tcl_FindNamespace(interp, "::tcl", NULL, 0),
|
||||
"process", 0);
|
||||
return processCmd;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclProcessCreated --
|
||||
*
|
||||
* Called when a child process has been created by Tcl.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Internal structures are updated with a new ProcessInfo.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TclProcessCreated(
|
||||
Tcl_Pid pid) /* Process id. */
|
||||
{
|
||||
int resolvedPid;
|
||||
Tcl_HashEntry *entry, *entry2;
|
||||
int isNew;
|
||||
ProcessInfo *info;
|
||||
|
||||
/*
|
||||
* Get resolved pid first.
|
||||
*/
|
||||
|
||||
resolvedPid = TclpGetPid(pid);
|
||||
|
||||
Tcl_MutexLock(&infoTablesMutex);
|
||||
|
||||
/*
|
||||
* Create entry in pid table.
|
||||
*/
|
||||
|
||||
entry = Tcl_CreateHashEntry(&infoTablePerPid, pid, &isNew);
|
||||
if (!isNew) {
|
||||
/*
|
||||
* Pid was reused, free old info and reuse structure.
|
||||
*/
|
||||
|
||||
info = (ProcessInfo *) Tcl_GetHashValue(entry);
|
||||
entry2 = Tcl_FindHashEntry(&infoTablePerResolvedPid,
|
||||
INT2PTR(resolvedPid));
|
||||
if (entry2) Tcl_DeleteHashEntry(entry2);
|
||||
FreeProcessInfo(info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialize info structure.
|
||||
*/
|
||||
|
||||
info = (ProcessInfo *) ckalloc(sizeof(ProcessInfo));
|
||||
InitProcessInfo(info, pid, resolvedPid);
|
||||
|
||||
/*
|
||||
* Add entry to tables.
|
||||
*/
|
||||
|
||||
Tcl_SetHashValue(entry, info);
|
||||
entry = Tcl_CreateHashEntry(&infoTablePerResolvedPid, INT2PTR(resolvedPid),
|
||||
&isNew);
|
||||
Tcl_SetHashValue(entry, info);
|
||||
|
||||
Tcl_MutexUnlock(&infoTablesMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclProcessWait --
|
||||
*
|
||||
* Wait for process status to change.
|
||||
*
|
||||
* Results:
|
||||
* TclProcessWaitStatus enum value.
|
||||
*
|
||||
* Side effects:
|
||||
* Completed process info structures are purged immediately (autopurge on)
|
||||
* or eventually (autopurge off).
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
TclProcessWaitStatus
|
||||
TclProcessWait(
|
||||
Tcl_Pid pid, /* Process id. */
|
||||
int options, /* Options passed to WaitProcessStatus. */
|
||||
int *codePtr, /* If non-NULL, will receive either:
|
||||
* - 0 for normal exit.
|
||||
* - errno in case of error.
|
||||
* - non-zero exit code for abormal exit.
|
||||
* - signal number if killed or suspended.
|
||||
* - Tcl_WaitPid status in all other cases.
|
||||
*/
|
||||
Tcl_Obj **msgObjPtr, /* If non-NULL, will receive error message. */
|
||||
Tcl_Obj **errorObjPtr) /* If non-NULL, will receive error code. */
|
||||
{
|
||||
Tcl_HashEntry *entry;
|
||||
ProcessInfo *info;
|
||||
TclProcessWaitStatus result;
|
||||
|
||||
/*
|
||||
* First search for pid in table.
|
||||
*/
|
||||
|
||||
entry = Tcl_FindHashEntry(&infoTablePerPid, pid);
|
||||
if (!entry) {
|
||||
/*
|
||||
* Unknown process, just call WaitProcessStatus and return.
|
||||
*/
|
||||
|
||||
result = WaitProcessStatus(pid, TclpGetPid(pid), options, codePtr,
|
||||
msgObjPtr, errorObjPtr);
|
||||
if (msgObjPtr && *msgObjPtr) Tcl_IncrRefCount(*msgObjPtr);
|
||||
if (errorObjPtr && *errorObjPtr) Tcl_IncrRefCount(*errorObjPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
info = (ProcessInfo *) Tcl_GetHashValue(entry);
|
||||
if (info->purge) {
|
||||
/*
|
||||
* Process has completed but TclProcessWait has already been called,
|
||||
* so report no change.
|
||||
*/
|
||||
|
||||
return TCL_PROCESS_UNCHANGED;
|
||||
}
|
||||
|
||||
RefreshProcessInfo(info, options);
|
||||
if (info->status == TCL_PROCESS_UNCHANGED) {
|
||||
/*
|
||||
* No change, stop there.
|
||||
*/
|
||||
|
||||
return TCL_PROCESS_UNCHANGED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set return values.
|
||||
*/
|
||||
|
||||
result = info->status;
|
||||
if (codePtr) *codePtr = info->code;
|
||||
if (msgObjPtr) *msgObjPtr = info->msg;
|
||||
if (errorObjPtr) *errorObjPtr = info->error;
|
||||
if (msgObjPtr && *msgObjPtr) Tcl_IncrRefCount(*msgObjPtr);
|
||||
if (errorObjPtr && *errorObjPtr) Tcl_IncrRefCount(*errorObjPtr);
|
||||
|
||||
if (autopurge) {
|
||||
/*
|
||||
* Purge now.
|
||||
*/
|
||||
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
entry = Tcl_FindHashEntry(&infoTablePerResolvedPid,
|
||||
INT2PTR(info->resolvedPid));
|
||||
Tcl_DeleteHashEntry(entry);
|
||||
FreeProcessInfo(info);
|
||||
} else {
|
||||
/*
|
||||
* Eventually purge. Subsequent calls will return
|
||||
* TCL_PROCESS_UNCHANGED.
|
||||
*/
|
||||
|
||||
info->purge = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -651,23 +651,6 @@ Tcl_AppendResultVA(
|
||||
}
|
||||
Tcl_AppendStringsToObjVA(objPtr, argList);
|
||||
Tcl_SetObjResult(interp, objPtr);
|
||||
|
||||
/*
|
||||
* Strictly we should call Tcl_GetStringResult(interp) here to make sure
|
||||
* that interp->result is correct according to the old contract, but that
|
||||
* makes the performance of much code (e.g. in Tk) absolutely awful. So we
|
||||
* leave it out; code that really wants interp->result can just insert the
|
||||
* calls to Tcl_GetStringResult() itself. [Patch 1041072 discussion]
|
||||
*/
|
||||
|
||||
#ifdef USE_INTERP_RESULT
|
||||
/*
|
||||
* Ensure that the interp->result is legal so old Tcl 7.* code still
|
||||
* works. There's still embarrasingly much of it about...
|
||||
*/
|
||||
|
||||
(void) Tcl_GetStringResult(interp);
|
||||
#endif /* USE_INTERP_RESULT */
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+17
-12
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tommath.h"
|
||||
|
||||
/*
|
||||
* Flag values used by Tcl_ScanObjCmd.
|
||||
@@ -415,14 +416,7 @@ ValidateFormat(
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'b':
|
||||
break;
|
||||
case 'u':
|
||||
if (flags & SCAN_BIG) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"unsigned bignum scans are invalid", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADUNSIGNED",NULL);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
* Bracket terms need special checking
|
||||
@@ -932,9 +926,9 @@ Tcl_ScanObjCmd(
|
||||
}
|
||||
if (flags & SCAN_LONGER) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, objPtr, &wideValue) != TCL_OK) {
|
||||
wideValue = ~(Tcl_WideUInt)0 >> 1; /* WIDE_MAX */
|
||||
wideValue = LLONG_MAX;
|
||||
if (TclGetString(objPtr)[0] == '-') {
|
||||
wideValue++; /* WIDE_MAX + 1 = WIDE_MIN */
|
||||
wideValue = LLONG_MIN;
|
||||
}
|
||||
}
|
||||
if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) {
|
||||
@@ -942,9 +936,20 @@ Tcl_ScanObjCmd(
|
||||
(Tcl_WideUInt)wideValue);
|
||||
Tcl_SetStringObj(objPtr, buf, -1);
|
||||
} else {
|
||||
Tcl_SetWideIntObj(objPtr, wideValue);
|
||||
TclSetIntObj(objPtr, wideValue);
|
||||
}
|
||||
} else if (!(flags & SCAN_BIG)) {
|
||||
} else if (flags & SCAN_BIG) {
|
||||
if (flags & SCAN_UNSIGNED) {
|
||||
mp_int big;
|
||||
if ((Tcl_GetBignumFromObj(interp, objPtr, &big) != TCL_OK)
|
||||
|| mp_isneg(&big)) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"unsigned bignum scans are invalid", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADUNSIGNED",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) {
|
||||
if (TclGetString(objPtr)[0] == '-') {
|
||||
value = LONG_MIN;
|
||||
@@ -956,7 +961,7 @@ Tcl_ScanObjCmd(
|
||||
sprintf(buf, "%lu", value); /* INTL: ISO digit */
|
||||
Tcl_SetStringObj(objPtr, buf, -1);
|
||||
} else {
|
||||
Tcl_SetLongObj(objPtr, value);
|
||||
TclSetIntObj(objPtr, value);
|
||||
}
|
||||
}
|
||||
objs[objIndex++] = objPtr;
|
||||
|
||||
+12
-40
@@ -1268,32 +1268,18 @@ TclParseNumber(
|
||||
}
|
||||
}
|
||||
if (!octalSignificandOverflow) {
|
||||
if (octalSignificandWide >
|
||||
(Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (octalSignificandWide <= (MOST_BITS + signum)) {
|
||||
objPtr->typePtr = &tclWideIntType;
|
||||
if (signum) {
|
||||
objPtr->internalRep.wideValue =
|
||||
- (Tcl_WideInt) octalSignificandWide;
|
||||
} else {
|
||||
objPtr->internalRep.wideValue =
|
||||
(Tcl_WideInt) octalSignificandWide;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (octalSignificandWide > (MOST_BITS + signum)) {
|
||||
TclInitBignumFromWideUInt(&octalSignificandBig,
|
||||
octalSignificandWide);
|
||||
octalSignificandOverflow = 1;
|
||||
} else {
|
||||
objPtr->typePtr = &tclIntType;
|
||||
if (signum) {
|
||||
objPtr->internalRep.longValue =
|
||||
- (long) octalSignificandWide;
|
||||
objPtr->internalRep.wideValue =
|
||||
- (Tcl_WideInt) octalSignificandWide;
|
||||
} else {
|
||||
objPtr->internalRep.longValue =
|
||||
(long) octalSignificandWide;
|
||||
objPtr->internalRep.wideValue =
|
||||
(Tcl_WideInt) octalSignificandWide;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1315,32 +1301,18 @@ TclParseNumber(
|
||||
}
|
||||
returnInteger:
|
||||
if (!significandOverflow) {
|
||||
if (significandWide >
|
||||
(Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (significandWide <= MOST_BITS+signum) {
|
||||
objPtr->typePtr = &tclWideIntType;
|
||||
if (signum) {
|
||||
objPtr->internalRep.wideValue =
|
||||
- (Tcl_WideInt) significandWide;
|
||||
} else {
|
||||
objPtr->internalRep.wideValue =
|
||||
(Tcl_WideInt) significandWide;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (significandWide > MOST_BITS+signum) {
|
||||
TclInitBignumFromWideUInt(&significandBig,
|
||||
significandWide);
|
||||
significandOverflow = 1;
|
||||
} else {
|
||||
objPtr->typePtr = &tclIntType;
|
||||
if (signum) {
|
||||
objPtr->internalRep.longValue =
|
||||
- (long) significandWide;
|
||||
objPtr->internalRep.wideValue =
|
||||
- (Tcl_WideInt) significandWide;
|
||||
} else {
|
||||
objPtr->internalRep.longValue =
|
||||
(long) significandWide;
|
||||
objPtr->internalRep.wideValue =
|
||||
(Tcl_WideInt) significandWide;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4725,7 +4697,7 @@ TclCeil(
|
||||
mp_int b;
|
||||
|
||||
mp_init(&b);
|
||||
if (mp_cmp_d(a, 0) == MP_LT) {
|
||||
if (mp_isneg(a)) {
|
||||
mp_neg(a, &b);
|
||||
r = -TclFloor(&b);
|
||||
} else {
|
||||
@@ -4782,7 +4754,7 @@ TclFloor(
|
||||
mp_int b;
|
||||
|
||||
mp_init(&b);
|
||||
if (mp_cmp_d(a, 0) == MP_LT) {
|
||||
if (mp_isneg(a)) {
|
||||
mp_neg(a, &b);
|
||||
r = -TclCeil(&b);
|
||||
} else {
|
||||
|
||||
+326
-180
@@ -38,6 +38,7 @@
|
||||
#include "tommath.h"
|
||||
#include "tclStringRep.h"
|
||||
|
||||
#include "assert.h"
|
||||
/*
|
||||
* Prototypes for functions defined later in this file:
|
||||
*/
|
||||
@@ -140,8 +141,8 @@ GrowStringBuffer(
|
||||
objPtr->bytes = NULL;
|
||||
}
|
||||
if (flag == 0 || stringPtr->allocated > 0) {
|
||||
attempt = 2 * needed;
|
||||
if (attempt >= 0) {
|
||||
if (needed <= INT_MAX / 2) {
|
||||
attempt = 2 * needed;
|
||||
ptr = attemptckrealloc(objPtr->bytes, attempt + 1);
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
@@ -190,8 +191,8 @@ GrowUnicodeBuffer(
|
||||
* Subsequent appends - apply the growth algorithm.
|
||||
*/
|
||||
|
||||
attempt = 2 * needed;
|
||||
if (attempt >= 0 && attempt <= STRING_MAXCHARS) {
|
||||
if (needed <= STRING_MAXCHARS / 2) {
|
||||
attempt = 2 * needed;
|
||||
ptr = stringAttemptRealloc(stringPtr, attempt);
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
@@ -418,9 +419,14 @@ Tcl_GetCharLength(
|
||||
}
|
||||
|
||||
/*
|
||||
* Optimize the case where we're really dealing with a bytearray object
|
||||
* without string representation; we don't need to convert to a string to
|
||||
* perform the get-length operation.
|
||||
* Optimize the case where we're really dealing with a bytearray object;
|
||||
* we don't need to convert to a string to perform the get-length operation.
|
||||
*
|
||||
* Starting in Tcl 8.7, we check for a "pure" bytearray, because the
|
||||
* machinery behind that test is using a proper bytearray ObjType. We
|
||||
* could also compute length of an improper bytearray without shimmering
|
||||
* but there's no value in that. We *want* to shimmer an improper bytearray
|
||||
* because improper bytearrays have worthless internal reps.
|
||||
*/
|
||||
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
@@ -476,8 +482,7 @@ Tcl_GetUniChar(
|
||||
|
||||
/*
|
||||
* Optimize the case where we're really dealing with a bytearray object
|
||||
* without string representation; we don't need to convert to a string to
|
||||
* perform the indexing operation.
|
||||
* we don't need to convert to a string to perform the indexing operation.
|
||||
*/
|
||||
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
@@ -517,7 +522,7 @@ Tcl_GetUniChar(
|
||||
*
|
||||
* Get the Unicode form of the String object. If the object is not
|
||||
* already a String object, it will be converted to one. If the String
|
||||
* object does not have a Unicode rep, then one is create from the UTF
|
||||
* object does not have a Unicode rep, then one is created from the UTF
|
||||
* string format.
|
||||
*
|
||||
* Results:
|
||||
@@ -610,8 +615,7 @@ Tcl_GetRange(
|
||||
|
||||
/*
|
||||
* Optimize the case where we're really dealing with a bytearray object
|
||||
* without string representation; we don't need to convert to a string to
|
||||
* perform the substring operation.
|
||||
* we don't need to convert to a string to perform the substring operation.
|
||||
*/
|
||||
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
@@ -651,6 +655,17 @@ Tcl_GetRange(
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
}
|
||||
|
||||
#if TCL_UTF_MAX == 4
|
||||
/* See: bug [11ae2be95dac9417] */
|
||||
if ((first>0) && ((stringPtr->unicode[first]&0xFC00) == 0xDC00)
|
||||
&& ((stringPtr->unicode[first-1]&0xFC00) == 0xD800)) {
|
||||
++first;
|
||||
}
|
||||
if ((last+1<stringPtr->numChars) && ((stringPtr->unicode[last+1]&0xFC00) == 0xDC00)
|
||||
&& ((stringPtr->unicode[last]&0xFC00) == 0xD800)) {
|
||||
++last;
|
||||
}
|
||||
#endif
|
||||
return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1);
|
||||
}
|
||||
|
||||
@@ -1208,9 +1223,9 @@ Tcl_AppendObjToObj(
|
||||
|
||||
/*
|
||||
* Handle append of one bytearray object to another as a special case.
|
||||
* Note that we only do this when the objects don't have string reps; if
|
||||
* it did, then appending the byte arrays together could well lose
|
||||
* information; this is a special-case optimization only.
|
||||
* Note that we only do this when the objects are pure so that the
|
||||
* bytearray faithfully represent the true value; Otherwise
|
||||
* appending the byte arrays together could lose information;
|
||||
*/
|
||||
|
||||
if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
|
||||
@@ -1880,20 +1895,10 @@ Tcl_AppendFormatToObj(
|
||||
format += step;
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
} else if ((ch == 't') || (ch == 'z')) {
|
||||
} else if ((ch == 't') || (ch == 'z') || (ch == 'q') || (ch == 'j') || (ch == 'L')) {
|
||||
format += step;
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (sizeof(size_t) > sizeof(int)) {
|
||||
useWide = 1;
|
||||
}
|
||||
#endif
|
||||
} else if ((ch == 'q') ||(ch == 'j')) {
|
||||
format += step;
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
useWide = 1;
|
||||
#endif
|
||||
useBig = 1;
|
||||
}
|
||||
|
||||
format += step;
|
||||
@@ -1939,11 +1944,6 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
|
||||
case 'u':
|
||||
if (useBig) {
|
||||
msg = "unsigned bignum format is invalid";
|
||||
errCode = "BADUNSIGNED";
|
||||
goto errorMsg;
|
||||
}
|
||||
case 'd':
|
||||
case 'o':
|
||||
case 'p':
|
||||
@@ -1963,13 +1963,25 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
#endif
|
||||
if (useBig) {
|
||||
int cmpResult;
|
||||
if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) {
|
||||
goto error;
|
||||
}
|
||||
isNegative = (mp_cmp_d(&big, 0) == MP_LT);
|
||||
cmpResult = mp_cmp_d(&big, 0);
|
||||
isNegative = (cmpResult == MP_LT);
|
||||
if (cmpResult == MP_EQ) gotHash = 0;
|
||||
if (ch == 'u') {
|
||||
if (isNegative) {
|
||||
msg = "unsigned bignum format is invalid";
|
||||
errCode = "BADUNSIGNED";
|
||||
goto errorMsg;
|
||||
} else {
|
||||
ch = 'd';
|
||||
}
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
} else if (useWide) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
|
||||
if (TclGetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
|
||||
Tcl_Obj *objPtr;
|
||||
|
||||
if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
|
||||
@@ -1978,13 +1990,14 @@ Tcl_AppendFormatToObj(
|
||||
mp_mod_2d(&big, (int) CHAR_BIT*sizeof(Tcl_WideInt), &big);
|
||||
objPtr = Tcl_NewBignumObj(&big);
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
Tcl_GetWideIntFromObj(NULL, objPtr, &w);
|
||||
TclGetWideIntFromObj(NULL, objPtr, &w);
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
isNegative = (w < (Tcl_WideInt) 0);
|
||||
if (w == (Tcl_WideInt) 0) gotHash = 0;
|
||||
#endif
|
||||
} else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
|
||||
if (TclGetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
|
||||
Tcl_Obj *objPtr;
|
||||
|
||||
if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
|
||||
@@ -2001,14 +2014,18 @@ Tcl_AppendFormatToObj(
|
||||
if (useShort) {
|
||||
s = (short) l;
|
||||
isNegative = (s < (short) 0);
|
||||
if (s == (short) 0) gotHash = 0;
|
||||
} else {
|
||||
isNegative = (l < (long) 0);
|
||||
if (l == (long) 0) gotHash = 0;
|
||||
}
|
||||
} else if (useShort) {
|
||||
s = (short) l;
|
||||
isNegative = (s < (short) 0);
|
||||
if (s == (short) 0) gotHash = 0;
|
||||
} else {
|
||||
isNegative = (l < (long) 0);
|
||||
if (l == (long) 0) gotHash = 0;
|
||||
}
|
||||
|
||||
segment = Tcl_NewObj();
|
||||
@@ -2025,16 +2042,12 @@ Tcl_AppendFormatToObj(
|
||||
if (gotHash || (ch == 'p')) {
|
||||
switch (ch) {
|
||||
case 'o':
|
||||
Tcl_AppendToObj(segment, "0", 1);
|
||||
segmentLimit -= 1;
|
||||
precision--;
|
||||
break;
|
||||
case 'X':
|
||||
Tcl_AppendToObj(segment, "0X", 2);
|
||||
Tcl_AppendToObj(segment, "0o", 2);
|
||||
segmentLimit -= 2;
|
||||
break;
|
||||
case 'p':
|
||||
case 'x':
|
||||
case 'X':
|
||||
Tcl_AppendToObj(segment, "0x", 2);
|
||||
segmentLimit -= 2;
|
||||
break;
|
||||
@@ -2042,10 +2055,14 @@ Tcl_AppendFormatToObj(
|
||||
Tcl_AppendToObj(segment, "0b", 2);
|
||||
segmentLimit -= 2;
|
||||
break;
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
case 'd':
|
||||
Tcl_AppendToObj(segment, "0d", 2);
|
||||
segmentLimit -= 2;
|
||||
if (gotZero) {
|
||||
Tcl_AppendToObj(segment, "0d", 2);
|
||||
segmentLimit -= 2;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2183,7 +2200,7 @@ Tcl_AppendFormatToObj(
|
||||
* Need to be sure zero becomes "0", not "".
|
||||
*/
|
||||
|
||||
if ((numDigits == 0) && !((ch == 'o') && gotHash)) {
|
||||
if (numDigits == 0) {
|
||||
numDigits = 1;
|
||||
}
|
||||
pure = Tcl_NewObj();
|
||||
@@ -2250,6 +2267,8 @@ Tcl_AppendFormatToObj(
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
@@ -2318,6 +2337,12 @@ Tcl_AppendFormatToObj(
|
||||
errCode = "OVERFLOW";
|
||||
goto errorMsg;
|
||||
}
|
||||
if (ch == 'A') {
|
||||
char *p = TclGetString(segment) + 1;
|
||||
*p = 'x';
|
||||
p = strchr(p, 'P');
|
||||
if (p) *p = 'p';
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -2523,15 +2548,26 @@ AppendPrintfToObjVA(
|
||||
Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj(
|
||||
va_arg(argList, Tcl_WideInt)));
|
||||
break;
|
||||
case 3:
|
||||
Tcl_ListObjAppendElement(NULL, list, Tcl_NewBignumObj(
|
||||
va_arg(argList, mp_int *)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'G':
|
||||
if (size > 0) {
|
||||
Tcl_ListObjAppendElement(NULL, list, Tcl_NewDoubleObj(
|
||||
va_arg(argList, double)));
|
||||
(double)va_arg(argList, long double)));
|
||||
} else {
|
||||
Tcl_ListObjAppendElement(NULL, list, Tcl_NewDoubleObj(
|
||||
va_arg(argList, double)));
|
||||
}
|
||||
seekingConversion = 0;
|
||||
break;
|
||||
case '*':
|
||||
@@ -2551,7 +2587,6 @@ AppendPrintfToObjVA(
|
||||
gotPrecision = 1;
|
||||
p++;
|
||||
break;
|
||||
/* TODO: support for bignum arguments */
|
||||
case 'l':
|
||||
++size;
|
||||
p++;
|
||||
@@ -2579,6 +2614,10 @@ AppendPrintfToObjVA(
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
case 'L':
|
||||
size = 3;
|
||||
p++;
|
||||
break;
|
||||
case 'h':
|
||||
size = -1;
|
||||
default:
|
||||
@@ -2692,23 +2731,24 @@ TclGetStringStorage(
|
||||
* Performs the [string repeat] function.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
* A (Tcl_Obj *) pointing to the result value, or NULL in case of an
|
||||
* error.
|
||||
*
|
||||
* Side effects:
|
||||
* Writes to *objPtrPtr the address of Tcl_Obj that is concatenation
|
||||
* of count copies of the value in objPtr.
|
||||
* On error, when interp is not NULL, error information is left in it.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
Tcl_Obj *
|
||||
TclStringRepeat(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr,
|
||||
int count,
|
||||
Tcl_Obj **objPtrPtr)
|
||||
int flags)
|
||||
{
|
||||
Tcl_Obj *objResultPtr;
|
||||
int inPlace = flags & TCL_STRING_IN_PLACE;
|
||||
int length = 0, unichar = 0, done = 1;
|
||||
int binary = TclIsPureByteArray(objPtr);
|
||||
|
||||
@@ -2743,8 +2783,7 @@ TclStringRepeat(
|
||||
|
||||
if (length == 0) {
|
||||
/* Any repeats of empty is empty. */
|
||||
*objPtrPtr = objPtr;
|
||||
return TCL_OK;
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
if (count > INT_MAX/length) {
|
||||
@@ -2753,13 +2792,13 @@ TclStringRepeat(
|
||||
"max size for a Tcl value (%d bytes) exceeded", INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (binary) {
|
||||
/* Efficiently produce a pure byte array result */
|
||||
objResultPtr = Tcl_IsShared(objPtr) ? Tcl_DuplicateObj(objPtr)
|
||||
: objPtr;
|
||||
objResultPtr = (!inPlace || Tcl_IsShared(objPtr)) ?
|
||||
Tcl_DuplicateObj(objPtr) : objPtr;
|
||||
|
||||
Tcl_SetByteArrayLength(objResultPtr, count*length); /* PANIC? */
|
||||
Tcl_SetByteArrayLength(objResultPtr, length);
|
||||
@@ -2772,7 +2811,7 @@ TclStringRepeat(
|
||||
(count - done) * length);
|
||||
} else if (unichar) {
|
||||
/* Efficiently produce a pure Tcl_UniChar array result */
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
if (!inPlace || Tcl_IsShared(objPtr)) {
|
||||
objResultPtr = Tcl_NewUnicodeObj(Tcl_GetUnicode(objPtr), length);
|
||||
} else {
|
||||
TclInvalidateStringRep(objPtr);
|
||||
@@ -2783,11 +2822,11 @@ TclStringRepeat(
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"string size overflow: unable to alloc %"
|
||||
TCL_LL_MODIFIER "d bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(count*length)));
|
||||
TCL_Z_MODIFIER "u bytes",
|
||||
STRING_SIZE(count*length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
Tcl_SetObjLength(objResultPtr, length);
|
||||
while (count - done > done) {
|
||||
@@ -2798,7 +2837,7 @@ TclStringRepeat(
|
||||
(count - done) * length);
|
||||
} else {
|
||||
/* Efficiently concatenate string reps */
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
if (!inPlace || Tcl_IsShared(objPtr)) {
|
||||
objResultPtr = Tcl_NewStringObj(Tcl_GetString(objPtr), length);
|
||||
} else {
|
||||
TclFreeIntRep(objPtr);
|
||||
@@ -2811,7 +2850,7 @@ TclStringRepeat(
|
||||
count*length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
Tcl_SetObjLength(objResultPtr, length);
|
||||
while (count - done > done) {
|
||||
@@ -2821,47 +2860,45 @@ TclStringRepeat(
|
||||
Tcl_AppendToObj(objResultPtr, Tcl_GetString(objResultPtr),
|
||||
(count - done) * length);
|
||||
}
|
||||
*objPtrPtr = objResultPtr;
|
||||
return TCL_OK;
|
||||
return objResultPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringCatObjv --
|
||||
* TclStringCat --
|
||||
*
|
||||
* Performs the [string cat] function.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
* A (Tcl_Obj *) pointing to the result value, or NULL in case of an
|
||||
* error.
|
||||
*
|
||||
* Side effects:
|
||||
* Writes to *objPtrPtr the address of Tcl_Obj that is concatenation
|
||||
* of all objc values in objv.
|
||||
* On error, when interp is not NULL, error information is left in it.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclStringCatObjv(
|
||||
Tcl_Obj *
|
||||
TclStringCat(
|
||||
Tcl_Interp *interp,
|
||||
int inPlace,
|
||||
int objc,
|
||||
Tcl_Obj * const objv[],
|
||||
Tcl_Obj **objPtrPtr)
|
||||
int flags)
|
||||
{
|
||||
Tcl_Obj *objResultPtr, * const *ov;
|
||||
int oc, length = 0, binary = 1;
|
||||
int allowUniChar = 1, requestUniChar = 0;
|
||||
int first = objc - 1; /* Index of first value possibly not empty */
|
||||
int last = 0; /* Index of last value possibly not empty */
|
||||
int inPlace = flags & TCL_STRING_IN_PLACE;
|
||||
|
||||
/* assert ( objc >= 0 ) */
|
||||
|
||||
if (objc <= 1) {
|
||||
/* Only one or no objects; return first or empty */
|
||||
*objPtrPtr = objc ? objv[0] : Tcl_NewObj();
|
||||
return TCL_OK;
|
||||
return objc ? objv[0] : Tcl_NewObj();
|
||||
}
|
||||
|
||||
/* assert ( objc >= 2 ) */
|
||||
@@ -2877,7 +2914,9 @@ TclStringCatObjv(
|
||||
do {
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
if (objPtr->bytes) {
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
allowUniChar = 0;
|
||||
} else if (objPtr->bytes) {
|
||||
/* Value has a string rep. */
|
||||
if (objPtr->length) {
|
||||
/*
|
||||
@@ -2892,17 +2931,13 @@ TclStringCatObjv(
|
||||
}
|
||||
} else {
|
||||
/* assert (objPtr->typePtr != NULL) -- stork! */
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
allowUniChar = 0;
|
||||
binary = 0;
|
||||
if (objPtr->typePtr == &tclStringType) {
|
||||
/* Have a pure Unicode value; ask to preserve it */
|
||||
requestUniChar = 1;
|
||||
} else {
|
||||
binary = 0;
|
||||
if (objPtr->typePtr == &tclStringType) {
|
||||
/* Have a pure Unicode value; ask to preserve it */
|
||||
requestUniChar = 1;
|
||||
} else {
|
||||
/* Have another type; prevent shimmer */
|
||||
allowUniChar = 0;
|
||||
}
|
||||
/* Have another type; prevent shimmer */
|
||||
allowUniChar = 0;
|
||||
}
|
||||
}
|
||||
} while (--oc && (binary || allowUniChar));
|
||||
@@ -3038,8 +3073,7 @@ TclStringCatObjv(
|
||||
if (last <= first /*|| length == 0 */) {
|
||||
/* Only one non-empty value or zero length; return first */
|
||||
/* NOTE: (length == 0) implies (last <= first) */
|
||||
*objPtrPtr = objv[first];
|
||||
return TCL_OK;
|
||||
return objv[first];
|
||||
}
|
||||
|
||||
objv += first; objc = (last - first + 1);
|
||||
@@ -3089,11 +3123,11 @@ TclStringCatObjv(
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %"
|
||||
TCL_LL_MODIFIER "d bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(length)));
|
||||
TCL_Z_MODIFIER "u bytes",
|
||||
STRING_SIZE(length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
dst = Tcl_GetUnicode(objResultPtr) + start;
|
||||
} else {
|
||||
@@ -3106,11 +3140,11 @@ TclStringCatObjv(
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %"
|
||||
TCL_LL_MODIFIER "d bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(length)));
|
||||
TCL_Z_MODIFIER "u bytes",
|
||||
STRING_SIZE(length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
dst = Tcl_GetUnicode(objResultPtr);
|
||||
}
|
||||
@@ -3141,7 +3175,7 @@ TclStringCatObjv(
|
||||
length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
dst = Tcl_GetString(objResultPtr) + start;
|
||||
|
||||
@@ -3157,7 +3191,7 @@ TclStringCatObjv(
|
||||
length));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
dst = Tcl_GetString(objResultPtr);
|
||||
}
|
||||
@@ -3172,8 +3206,7 @@ TclStringCatObjv(
|
||||
}
|
||||
}
|
||||
}
|
||||
*objPtrPtr = objResultPtr;
|
||||
return TCL_OK;
|
||||
return objResultPtr;
|
||||
|
||||
overflow:
|
||||
if (interp) {
|
||||
@@ -3181,13 +3214,13 @@ TclStringCatObjv(
|
||||
"max size for a Tcl value (%d bytes) exceeded", INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringFind --
|
||||
* TclStringFirst --
|
||||
*
|
||||
* Implements the [string first] operation.
|
||||
*
|
||||
@@ -3203,20 +3236,20 @@ TclStringCatObjv(
|
||||
*/
|
||||
|
||||
int
|
||||
TclStringFind(
|
||||
TclStringFirst(
|
||||
Tcl_Obj *needle,
|
||||
Tcl_Obj *haystack,
|
||||
int start)
|
||||
{
|
||||
int lh, ln = Tcl_GetCharLength(needle);
|
||||
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
if (ln == 0) {
|
||||
/*
|
||||
* We don't find empty substrings. Bizarre!
|
||||
*
|
||||
* TODO: When we one day make this a true substring
|
||||
* finder, change this to "return 0"
|
||||
*/
|
||||
/* We don't find empty substrings. Bizarre!
|
||||
* Whenever this routine is turned into a proper substring
|
||||
* finder, change to `return start` after limits imposed. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -3224,51 +3257,46 @@ TclStringFind(
|
||||
unsigned char *end, *try, *bh;
|
||||
unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln);
|
||||
|
||||
/* Find bytes in bytes */
|
||||
bh = Tcl_GetByteArrayFromObj(haystack, &lh);
|
||||
end = bh + lh;
|
||||
|
||||
try = bh + start;
|
||||
while (try + ln <= end) {
|
||||
try = memchr(try, bn[0], end - try);
|
||||
|
||||
/*
|
||||
* Look for the leading byte of the needle in the haystack
|
||||
* starting at try and stopping when there's not enough room
|
||||
* for the needle left.
|
||||
*/
|
||||
try = memchr(try, bn[0], (end + 1 - ln) - try);
|
||||
if (try == NULL) {
|
||||
/* Leading byte not found -> needle cannot be found. */
|
||||
return -1;
|
||||
}
|
||||
/* Leading byte found, check rest of needle. */
|
||||
if (0 == memcmp(try+1, bn+1, ln-1)) {
|
||||
/* Checks! Return the successful index. */
|
||||
return (try - bh);
|
||||
}
|
||||
/* Rest of needle match failed; Iterate to continue search. */
|
||||
try++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we have two strings of single-byte characters. If we have, we
|
||||
* can use strstr() to do the search. Note that we can sometimes have
|
||||
* multibyte characters when the string could be minimally represented
|
||||
* using single byte characters; we can't assume that a mismatch here
|
||||
* means no match.
|
||||
* TODO: It might be nice to support some cases where it is not
|
||||
* necessary to shimmer to &tclStringType to compute the result,
|
||||
* and instead operate just on the objPtr->bytes values directly.
|
||||
* However, we also do not want the answer to change based on the
|
||||
* code pathway, or if it does we want that to be for some values
|
||||
* we explicitly decline to support. Getting there will involve
|
||||
* locking down in practice more firmly just what encodings produce
|
||||
* what supported results for the objPtr->bytes values. For now,
|
||||
* do only the well-defined Tcl_UniChar array search.
|
||||
*/
|
||||
|
||||
lh = Tcl_GetCharLength(haystack);
|
||||
if (haystack->bytes && (lh == haystack->length) && needle->bytes
|
||||
&& (ln == needle->length)) {
|
||||
/*
|
||||
* Both haystack and needle are all single-byte chars.
|
||||
*/
|
||||
|
||||
char *found = strstr(haystack->bytes + start, needle->bytes);
|
||||
|
||||
if (found) {
|
||||
return (found - haystack->bytes);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Do the search on the unicode representation for simplicity.
|
||||
*/
|
||||
|
||||
{
|
||||
Tcl_UniChar *try, *end, *uh;
|
||||
Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln);
|
||||
|
||||
@@ -3316,24 +3344,24 @@ TclStringLast(
|
||||
* We don't find empty substrings. Bizarre!
|
||||
*
|
||||
* TODO: When we one day make this a true substring
|
||||
* finder, change this to "return 0"
|
||||
* finder, change this to "return last", after limitation.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ln > last + 1) {
|
||||
lh = Tcl_GetCharLength(haystack);
|
||||
if (last >= lh) {
|
||||
last = lh - 1;
|
||||
}
|
||||
|
||||
if (last < ln - 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) {
|
||||
unsigned char *try, *bh;
|
||||
unsigned char *try, *bh = Tcl_GetByteArrayFromObj(haystack, &lh);
|
||||
unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln);
|
||||
|
||||
bh = Tcl_GetByteArrayFromObj(haystack, &lh);
|
||||
|
||||
if (last + 1 > lh) {
|
||||
last = lh - 1;
|
||||
}
|
||||
try = bh + last + 1 - ln;
|
||||
while (try >= bh) {
|
||||
if ((*try == bn[0])
|
||||
@@ -3345,38 +3373,10 @@ TclStringLast(
|
||||
return -1;
|
||||
}
|
||||
|
||||
lh = Tcl_GetCharLength(haystack);
|
||||
if (last + 1 > lh) {
|
||||
last = lh - 1;
|
||||
}
|
||||
if (haystack->bytes && (lh == haystack->length)) {
|
||||
/* haystack is all single-byte chars */
|
||||
|
||||
if (needle->bytes && (ln == needle->length)) {
|
||||
/* needle is also all single-byte chars */
|
||||
|
||||
char *try = haystack->bytes + last + 1 - ln;
|
||||
while (try >= haystack->bytes) {
|
||||
if ((*try == needle->bytes[0])
|
||||
&& (0 == memcmp(try+1, needle->bytes + 1, ln - 1))) {
|
||||
return (try - haystack->bytes);
|
||||
}
|
||||
try--;
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
/*
|
||||
* Cannot find substring with a multi-byte char inside
|
||||
* a string with no multi-byte chars.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
Tcl_UniChar *try, *uh;
|
||||
{
|
||||
Tcl_UniChar *try, *uh = Tcl_GetUnicodeFromObj(haystack, &lh);
|
||||
Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln);
|
||||
|
||||
uh = Tcl_GetUnicodeFromObj(haystack, &lh);
|
||||
|
||||
try = uh + last + 1 - ln;
|
||||
while (try >= uh) {
|
||||
if ((*try == un[0])
|
||||
@@ -3392,14 +3392,14 @@ TclStringLast(
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringObjReverse --
|
||||
* TclStringReverse --
|
||||
*
|
||||
* Implements the [string reverse] operation.
|
||||
*
|
||||
* Results:
|
||||
* An unshared Tcl value which is the [string reverse] of the argument
|
||||
* supplied. When sharing rules permit, the returned value might be the
|
||||
* argument with modifications done in place.
|
||||
* A Tcl value which is the [string reverse] of the argument supplied.
|
||||
* When sharing rules permit and the caller requests, the returned value
|
||||
* might be the argument with modifications done in place.
|
||||
*
|
||||
* Side effects:
|
||||
* May allocate a new Tcl_Obj.
|
||||
@@ -3430,17 +3430,19 @@ ReverseBytes(
|
||||
}
|
||||
|
||||
Tcl_Obj *
|
||||
TclStringObjReverse(
|
||||
Tcl_Obj *objPtr)
|
||||
TclStringReverse(
|
||||
Tcl_Obj *objPtr,
|
||||
int flags)
|
||||
{
|
||||
String *stringPtr;
|
||||
Tcl_UniChar ch = 0;
|
||||
int inPlace = flags & TCL_STRING_IN_PLACE;
|
||||
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
int numBytes;
|
||||
unsigned char *from = Tcl_GetByteArrayFromObj(objPtr, &numBytes);
|
||||
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
if (!inPlace || Tcl_IsShared(objPtr)) {
|
||||
objPtr = Tcl_NewByteArrayObj(NULL, numBytes);
|
||||
}
|
||||
ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, NULL), from, numBytes);
|
||||
@@ -3454,7 +3456,7 @@ TclStringObjReverse(
|
||||
Tcl_UniChar *from = Tcl_GetUnicode(objPtr);
|
||||
Tcl_UniChar *src = from + stringPtr->numChars;
|
||||
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
if (!inPlace || Tcl_IsShared(objPtr)) {
|
||||
Tcl_UniChar *to;
|
||||
|
||||
/*
|
||||
@@ -3483,7 +3485,7 @@ TclStringObjReverse(
|
||||
int numBytes = objPtr->length;
|
||||
char *to, *from = objPtr->bytes;
|
||||
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
if (!inPlace || Tcl_IsShared(objPtr)) {
|
||||
objPtr = Tcl_NewObj();
|
||||
Tcl_SetObjLength(objPtr, numBytes);
|
||||
}
|
||||
@@ -3527,6 +3529,150 @@ TclStringObjReverse(
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringReplace --
|
||||
*
|
||||
* Implements the inner engine of the [string replace] command.
|
||||
*
|
||||
* The result is a concatenation of a prefix from objPtr, characters
|
||||
* 0 through first-1, the insertPtr string value, and a suffix from
|
||||
* objPtr, characters from first + count to the end. The effect is
|
||||
* as if the inner substring of characters first through first+count-1
|
||||
* are removed and replaced with insertPtr.
|
||||
* If insertPtr is NULL, it is treated as an empty string.
|
||||
* When passed the flag TCL_STRING_IN_PLACE, this routine will try
|
||||
* to do the work within objPtr, so long as no sharing forbids it.
|
||||
* Without that request, or as needed, a new Tcl value will be allocated
|
||||
* to be the result.
|
||||
*
|
||||
* Results:
|
||||
* A Tcl value that is the result of the substring replacement.
|
||||
* May return NULL in case of an error. When NULL is returned and
|
||||
* interp is non-NULL, error information is left in interp
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
TclStringReplace(
|
||||
Tcl_Interp *interp, /* For error reporting, may be NULL */
|
||||
Tcl_Obj *objPtr, /* String to act upon */
|
||||
int first, /* First index to replace */
|
||||
int count, /* How many chars to replace */
|
||||
Tcl_Obj *insertPtr, /* Replacement string, may be NULL */
|
||||
int flags) /* TCL_STRING_IN_PLACE => attempt in-place */
|
||||
{
|
||||
int inPlace = flags & TCL_STRING_IN_PLACE;
|
||||
Tcl_Obj *result;
|
||||
|
||||
/* Caller is expected to pass sensible arguments */
|
||||
assert ( count >= 0 ) ;
|
||||
assert ( first >= 0 ) ;
|
||||
|
||||
/* Replace nothing with nothing */
|
||||
if ((insertPtr == NULL) && (count == 0)) {
|
||||
if (inPlace) {
|
||||
return objPtr;
|
||||
} else {
|
||||
return Tcl_DuplicateObj(objPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller very likely had to call Tcl_GetCharLength() or similar
|
||||
* to be able to process index values. This means it is like that
|
||||
* objPtr is either a proper "bytearray" or a "string" or else it has
|
||||
* a known and short string rep.
|
||||
*/
|
||||
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
int numBytes;
|
||||
unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &numBytes);
|
||||
|
||||
if (insertPtr == NULL) {
|
||||
/* Replace something with nothing. */
|
||||
|
||||
assert ( first <= numBytes ) ;
|
||||
assert ( count <= numBytes ) ;
|
||||
assert ( first + count <= numBytes ) ;
|
||||
|
||||
result = Tcl_NewByteArrayObj(NULL, numBytes - count);/* PANIC? */
|
||||
TclAppendBytesToByteArray(result, bytes, first);
|
||||
TclAppendBytesToByteArray(result, bytes + first + count,
|
||||
numBytes - count - first);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Replace everything */
|
||||
if ((first == 0) && (count == numBytes)) {
|
||||
return insertPtr;
|
||||
}
|
||||
|
||||
if (TclIsPureByteArray(insertPtr)) {
|
||||
int newBytes;
|
||||
unsigned char *iBytes
|
||||
= Tcl_GetByteArrayFromObj(insertPtr, &newBytes);
|
||||
|
||||
if (count == newBytes && inPlace && !Tcl_IsShared(objPtr)) {
|
||||
/*
|
||||
* Removal count and replacement count are equal.
|
||||
* Other conditions permit. Do in-place splice.
|
||||
*/
|
||||
|
||||
memcpy(bytes + first, iBytes, count);
|
||||
Tcl_InvalidateStringRep(objPtr);
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
if (newBytes > INT_MAX - (numBytes - count)) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max size for a Tcl value (%d bytes) exceeded",
|
||||
INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
result = Tcl_NewByteArrayObj(NULL, numBytes - count + newBytes);
|
||||
/* PANIC? */
|
||||
TclAppendBytesToByteArray(result, bytes, first);
|
||||
TclAppendBytesToByteArray(result, iBytes, newBytes);
|
||||
TclAppendBytesToByteArray(result, bytes + first + count,
|
||||
numBytes - count - first);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Flow through to try other approaches below */
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Figure out how not to generate a Tcl_UniChar array rep
|
||||
* when it can be determined objPtr->bytes points to a string of
|
||||
* all single-byte characters so we can index it directly.
|
||||
*/
|
||||
|
||||
/* The traditional implementation... */
|
||||
{
|
||||
int numChars;
|
||||
Tcl_UniChar *ustring = Tcl_GetUnicodeFromObj(objPtr, &numChars);
|
||||
|
||||
/* TODO: Is there an in-place option worth pursuing here? */
|
||||
|
||||
result = Tcl_NewUnicodeObj(ustring, first);
|
||||
if (insertPtr) {
|
||||
Tcl_AppendObjToObj(result, insertPtr);
|
||||
}
|
||||
if (first + count < numChars) {
|
||||
Tcl_AppendUnicodeToObj(result, ustring + first + count,
|
||||
numChars - first - count);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+61
-32
@@ -31,6 +31,7 @@
|
||||
#undef Tcl_NewIntObj
|
||||
#undef Tcl_NewListObj
|
||||
#undef Tcl_NewLongObj
|
||||
#undef Tcl_DbNewLongObj
|
||||
#undef Tcl_NewObj
|
||||
#undef Tcl_NewStringObj
|
||||
#undef Tcl_DumpActiveMemory
|
||||
@@ -42,6 +43,7 @@
|
||||
#undef TclpGetPid
|
||||
#undef TclSockMinimumBuffers
|
||||
#undef Tcl_SetIntObj
|
||||
#undef Tcl_SetLongObj
|
||||
#undef TclpInetNtoa
|
||||
#undef TclWinGetServByName
|
||||
#undef TclWinGetSockOpt
|
||||
@@ -49,7 +51,7 @@
|
||||
#undef TclWinNToHS
|
||||
|
||||
/* See bug 510001: TclSockMinimumBuffers needs plat imp */
|
||||
#if defined(_WIN64) || defined(TCL_NO_DEPRECATED)
|
||||
#if defined(_WIN64) || defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8
|
||||
# define TclSockMinimumBuffersOld 0
|
||||
#else
|
||||
#define TclSockMinimumBuffersOld sockMinimumBuffersOld
|
||||
@@ -59,20 +61,31 @@ static int TclSockMinimumBuffersOld(int sock, int size)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TCL_NO_DEPRECATED)
|
||||
#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8
|
||||
# define TclSetStartupScriptPath 0
|
||||
# define TclGetStartupScriptPath 0
|
||||
# define TclSetStartupScriptFileName 0
|
||||
# define TclGetStartupScriptFileName 0
|
||||
# define TclPrecTraceProc 0
|
||||
# define TclpInetNtoa 0
|
||||
# define TclWinGetServByName 0
|
||||
# define TclWinGetSockOpt 0
|
||||
# define TclWinSetSockOpt 0
|
||||
# define TclWinNToHS 0
|
||||
# define TclWinGetPlatformId 0
|
||||
# define TclWinResetInterfaces 0
|
||||
# define TclWinSetInterfaces 0
|
||||
# define TclWinGetPlatformId 0
|
||||
# define TclBNInitBignumFromWideUInt 0
|
||||
# define TclBNInitBignumFromWideInt 0
|
||||
# define TclBNInitBignumFromLong 0
|
||||
# define Tcl_Backslash 0
|
||||
# define Tcl_GetDefaultEncodingDir 0
|
||||
# define Tcl_SetDefaultEncodingDir 0
|
||||
# define Tcl_EvalTokens 0
|
||||
# define Tcl_CreateMathFunc 0
|
||||
# define Tcl_GetMathFuncInfo 0
|
||||
# define Tcl_ListMathFuncs 0
|
||||
#else
|
||||
#define TclSetStartupScriptPath setStartupScriptPath
|
||||
static void TclSetStartupScriptPath(Tcl_Obj *path)
|
||||
@@ -99,25 +112,28 @@ static const char *TclGetStartupScriptFileName(void)
|
||||
}
|
||||
return Tcl_GetString(path);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#undef TclWinNToHS
|
||||
#undef TclWinGetPlatformId
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef TclWinResetInterfaces
|
||||
#undef TclWinSetInterfaces
|
||||
static void
|
||||
doNothing(void)
|
||||
{
|
||||
/* dummy implementation, no need to do anything */
|
||||
}
|
||||
#define TclWinNToHS winNToHS
|
||||
static unsigned short TclWinNToHS(unsigned short ns) {
|
||||
return ntohs(ns);
|
||||
}
|
||||
#define TclWinGetPlatformId winGetPlatformId
|
||||
static int
|
||||
TclWinGetPlatformId()
|
||||
TclWinGetPlatformId(void)
|
||||
{
|
||||
return 2; /* VER_PLATFORM_WIN32_NT */;
|
||||
}
|
||||
#else
|
||||
#define TclWinNToHS 0
|
||||
#define TclWinGetPlatformId 0
|
||||
#endif
|
||||
#define TclWinResetInterfaces doNothing
|
||||
#define TclWinSetInterfaces (void (*) (int)) doNothing
|
||||
#endif
|
||||
# define TclBNInitBignumFromWideUInt TclInitBignumFromWideUInt
|
||||
# define TclBNInitBignumFromWideInt TclInitBignumFromWideInt
|
||||
@@ -132,12 +148,15 @@ TclWinGetPlatformId()
|
||||
# define TclpIsAtty 0
|
||||
#elif defined(__CYGWIN__)
|
||||
# define TclpIsAtty TclPlatIsAtty
|
||||
# define TclWinSetInterfaces (void (*) (int)) doNothing
|
||||
#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8
|
||||
static void
|
||||
doNothing(void)
|
||||
{
|
||||
/* dummy implementation, no need to do anything */
|
||||
}
|
||||
#endif
|
||||
# define TclWinAddProcess (void (*) (void *, unsigned int)) doNothing
|
||||
# define TclWinFlushDirtyChannels doNothing
|
||||
# define TclWinResetInterfaces doNothing
|
||||
|
||||
static Tcl_Encoding winTCharEncoding;
|
||||
|
||||
static int
|
||||
TclpIsAtty(int fd)
|
||||
@@ -149,11 +168,11 @@ void *TclWinGetTclInstance()
|
||||
{
|
||||
void *hInstance = NULL;
|
||||
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(const char *)&winTCharEncoding, &hInstance);
|
||||
(const char *)&TclpIsAtty, &hInstance);
|
||||
return hInstance;
|
||||
}
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
#define TclWinSetSockOpt winSetSockOpt
|
||||
static int
|
||||
TclWinSetSockOpt(SOCKET s, int level, int optname,
|
||||
@@ -198,23 +217,23 @@ TclpGetPid(Tcl_Pid pid)
|
||||
return (int) (size_t) pid;
|
||||
}
|
||||
|
||||
static void
|
||||
doNothing(void)
|
||||
{
|
||||
/* dummy implementation, no need to do anything */
|
||||
}
|
||||
|
||||
char *
|
||||
Tcl_WinUtfToTChar(
|
||||
const char *string,
|
||||
int len,
|
||||
Tcl_DString *dsPtr)
|
||||
{
|
||||
if (!winTCharEncoding) {
|
||||
winTCharEncoding = Tcl_GetEncoding(0, "unicode");
|
||||
}
|
||||
return Tcl_UtfToExternalDString(winTCharEncoding,
|
||||
string, len, dsPtr);
|
||||
WCHAR *wp;
|
||||
int size = MultiByteToWideChar(CP_UTF8, 0, string, len, 0, 0);
|
||||
|
||||
Tcl_DStringInit(dsPtr);
|
||||
Tcl_DStringSetLength(dsPtr, 2*size+2);
|
||||
wp = (WCHAR *)Tcl_DStringValue(dsPtr);
|
||||
MultiByteToWideChar(CP_UTF8, 0, string, len, wp, size+1);
|
||||
if (len == -1) --size; /* account for 0-byte at string end */
|
||||
Tcl_DStringSetLength(dsPtr, 2*size);
|
||||
wp[size] = 0;
|
||||
return (char *)wp;
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -223,11 +242,21 @@ Tcl_WinTCharToUtf(
|
||||
int len,
|
||||
Tcl_DString *dsPtr)
|
||||
{
|
||||
if (!winTCharEncoding) {
|
||||
winTCharEncoding = Tcl_GetEncoding(0, "unicode");
|
||||
char *p;
|
||||
int size;
|
||||
|
||||
if (len > 0) {
|
||||
len /= 2;
|
||||
}
|
||||
return Tcl_ExternalToUtfDString(winTCharEncoding,
|
||||
string, len, dsPtr);
|
||||
size = WideCharToMultiByte(CP_UTF8, 0, string, len, 0, 0, NULL, NULL);
|
||||
Tcl_DStringInit(dsPtr);
|
||||
Tcl_DStringSetLength(dsPtr, size+1);
|
||||
p = (char *)Tcl_DStringValue(dsPtr);
|
||||
WideCharToMultiByte(CP_UTF8, 0, string, len, p, size, NULL, NULL);
|
||||
if (len == -1) --size; /* account for 0-byte at string end */
|
||||
Tcl_DStringSetLength(dsPtr, size);
|
||||
p[size] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
#if defined(TCL_WIDE_INT_IS_LONG)
|
||||
@@ -248,7 +277,7 @@ static Tcl_Obj *dbNewLongObj(
|
||||
TclDbNewObj(objPtr, file, line);
|
||||
objPtr->bytes = NULL;
|
||||
|
||||
objPtr->internalRep.longValue = (long) intValue;
|
||||
objPtr->internalRep.wideValue = (long) intValue;
|
||||
objPtr->typePtr = &tclIntType;
|
||||
return objPtr;
|
||||
#else
|
||||
@@ -315,7 +344,7 @@ static int formatInt(char *buffer, int n){
|
||||
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
#if defined(TCL_NO_DEPRECATED)
|
||||
# define Tcl_SeekOld 0
|
||||
# define Tcl_TellOld 0
|
||||
# undef Tcl_SetBooleanObj
|
||||
|
||||
+3
-166
@@ -305,14 +305,6 @@ static int TestlinkCmd(ClientData dummy,
|
||||
static int TestlocaleCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
static int TestMathFunc(ClientData clientData,
|
||||
Tcl_Interp *interp, Tcl_Value *args,
|
||||
Tcl_Value *resultPtr);
|
||||
static int TestMathFunc2(ClientData clientData,
|
||||
Tcl_Interp *interp, Tcl_Value *args,
|
||||
Tcl_Value *resultPtr);
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
static int TestmainthreadCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int argc, const char **argv);
|
||||
static int TestsetmainloopCmd(ClientData dummy,
|
||||
@@ -555,10 +547,6 @@ int
|
||||
Tcltest_Init(
|
||||
Tcl_Interp *interp) /* Interpreter for application. */
|
||||
{
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
Tcl_ValueType t3ArgTypes[2];
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
Tcl_Obj *listPtr;
|
||||
Tcl_Obj **objv;
|
||||
int objc, index;
|
||||
@@ -711,10 +699,6 @@ Tcltest_Init(
|
||||
Tcl_CreateCommand(interp, "testtranslatefilename",
|
||||
TesttranslatefilenameCmd, NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
Tcl_CreateMathFunc(interp, "T1", 0, NULL, TestMathFunc, (ClientData) 123);
|
||||
Tcl_CreateMathFunc(interp, "T2", 0, NULL, TestMathFunc, (ClientData) 345);
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, NULL,
|
||||
NULL);
|
||||
Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
|
||||
@@ -725,13 +709,6 @@ Tcltest_Init(
|
||||
Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd,
|
||||
(ClientData) 0, NULL);
|
||||
#endif
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
t3ArgTypes[0] = TCL_EITHER;
|
||||
t3ArgTypes[1] = TCL_EITHER;
|
||||
Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2,
|
||||
NULL);
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
Tcl_CreateObjCommand(interp, "testnreunwind", TestNREUnwind,
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testnrelevels", TestNRELevels,
|
||||
@@ -3354,146 +3331,6 @@ TestlocaleCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TestMathFunc --
|
||||
*
|
||||
* This is a user-defined math procedure to test out math procedures
|
||||
* with no arguments.
|
||||
*
|
||||
* Results:
|
||||
* A normal Tcl completion code.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
static int
|
||||
TestMathFunc(
|
||||
ClientData clientData, /* Integer value to return. */
|
||||
Tcl_Interp *interp, /* Not used. */
|
||||
Tcl_Value *args, /* Not used. */
|
||||
Tcl_Value *resultPtr) /* Where to store result. */
|
||||
{
|
||||
resultPtr->type = TCL_INT;
|
||||
resultPtr->intValue = PTR2INT(clientData);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TestMathFunc2 --
|
||||
*
|
||||
* This is a user-defined math procedure to test out math procedures
|
||||
* that do have arguments, in this case 2.
|
||||
*
|
||||
* Results:
|
||||
* A normal Tcl completion code.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
TestMathFunc2(
|
||||
ClientData clientData, /* Integer value to return. */
|
||||
Tcl_Interp *interp, /* Used to report errors. */
|
||||
Tcl_Value *args, /* Points to an array of two Tcl_Value structs
|
||||
* for the two arguments. */
|
||||
Tcl_Value *resultPtr) /* Where to store the result. */
|
||||
{
|
||||
int result = TCL_OK;
|
||||
|
||||
/*
|
||||
* Return the maximum of the two arguments with the correct type.
|
||||
*/
|
||||
|
||||
if (args[0].type == TCL_INT) {
|
||||
int i0 = args[0].intValue;
|
||||
|
||||
if (args[1].type == TCL_INT) {
|
||||
int i1 = args[1].intValue;
|
||||
|
||||
resultPtr->type = TCL_INT;
|
||||
resultPtr->intValue = ((i0 > i1)? i0 : i1);
|
||||
} else if (args[1].type == TCL_DOUBLE) {
|
||||
double d0 = i0;
|
||||
double d1 = args[1].doubleValue;
|
||||
|
||||
resultPtr->type = TCL_DOUBLE;
|
||||
resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
|
||||
} else if (args[1].type == TCL_WIDE_INT) {
|
||||
Tcl_WideInt w0 = Tcl_LongAsWide(i0);
|
||||
Tcl_WideInt w1 = args[1].wideValue;
|
||||
|
||||
resultPtr->type = TCL_WIDE_INT;
|
||||
resultPtr->wideValue = ((w0 > w1)? w0 : w1);
|
||||
} else {
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 2", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else if (args[0].type == TCL_DOUBLE) {
|
||||
double d0 = args[0].doubleValue;
|
||||
|
||||
if (args[1].type == TCL_INT) {
|
||||
double d1 = args[1].intValue;
|
||||
|
||||
resultPtr->type = TCL_DOUBLE;
|
||||
resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
|
||||
} else if (args[1].type == TCL_DOUBLE) {
|
||||
double d1 = args[1].doubleValue;
|
||||
|
||||
resultPtr->type = TCL_DOUBLE;
|
||||
resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
|
||||
} else if (args[1].type == TCL_WIDE_INT) {
|
||||
double d1 = Tcl_WideAsDouble(args[1].wideValue);
|
||||
|
||||
resultPtr->type = TCL_DOUBLE;
|
||||
resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
|
||||
} else {
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 2", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else if (args[0].type == TCL_WIDE_INT) {
|
||||
Tcl_WideInt w0 = args[0].wideValue;
|
||||
|
||||
if (args[1].type == TCL_INT) {
|
||||
Tcl_WideInt w1 = Tcl_LongAsWide(args[1].intValue);
|
||||
|
||||
resultPtr->type = TCL_WIDE_INT;
|
||||
resultPtr->wideValue = ((w0 > w1)? w0 : w1);
|
||||
} else if (args[1].type == TCL_DOUBLE) {
|
||||
double d0 = Tcl_WideAsDouble(w0);
|
||||
double d1 = args[1].doubleValue;
|
||||
|
||||
resultPtr->type = TCL_DOUBLE;
|
||||
resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
|
||||
} else if (args[1].type == TCL_WIDE_INT) {
|
||||
Tcl_WideInt w1 = args[1].wideValue;
|
||||
|
||||
resultPtr->type = TCL_WIDE_INT;
|
||||
resultPtr->wideValue = ((w0 > w1)? w0 : w1);
|
||||
} else {
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 2", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 1", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -5370,7 +5207,7 @@ TestmainthreadCmd(
|
||||
const char **argv) /* Argument strings. */
|
||||
{
|
||||
if (argc == 1) {
|
||||
Tcl_Obj *idObj = Tcl_NewLongObj((long)(size_t)Tcl_GetCurrentThread());
|
||||
Tcl_Obj *idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread());
|
||||
|
||||
Tcl_SetObjResult(interp, idObj);
|
||||
return TCL_OK;
|
||||
@@ -5767,8 +5604,8 @@ TestChannelCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclFormatInt(buf, (size_t) Tcl_GetChannelThread(chan));
|
||||
Tcl_AppendResult(interp, buf, NULL);
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
|
||||
(Tcl_WideInt) (size_t) Tcl_GetChannelThread(chan)));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1088,6 +1088,9 @@ TestobjCmd(
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
|
||||
} else {
|
||||
typeName = objv[2]->typePtr->name;
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (!strcmp(typeName, "wideInt")) typeName = "int";
|
||||
#endif
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1));
|
||||
}
|
||||
} else if (strcmp(subCmd, "refcount") == 0) {
|
||||
@@ -1115,6 +1118,11 @@ TestobjCmd(
|
||||
}
|
||||
if (varPtr[varIndex]->typePtr == NULL) { /* a string! */
|
||||
Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
} else if (!strcmp(varPtr[varIndex]->typePtr->name, "wideInt")) {
|
||||
Tcl_AppendToObj(Tcl_GetObjResult(interp),
|
||||
"int", -1);
|
||||
#endif
|
||||
} else {
|
||||
Tcl_AppendToObj(Tcl_GetObjResult(interp),
|
||||
varPtr[varIndex]->typePtr->name, -1);
|
||||
|
||||
@@ -248,7 +248,7 @@ ThreadObjCmd(
|
||||
|
||||
switch ((enum options)option) {
|
||||
case THREAD_CANCEL: {
|
||||
long id;
|
||||
Tcl_WideInt id;
|
||||
const char *result;
|
||||
int flags, arg;
|
||||
|
||||
@@ -264,7 +264,7 @@ ThreadObjCmd(
|
||||
arg++;
|
||||
}
|
||||
}
|
||||
if (Tcl_GetLongFromObj(interp, objv[arg], &id) != TCL_OK) {
|
||||
if (Tcl_GetWideIntFromObj(interp, objv[arg], &id) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
arg++;
|
||||
|
||||
+11
-24
@@ -819,9 +819,6 @@ Tcl_AfterObjCmd(
|
||||
*/
|
||||
|
||||
if (objv[1]->typePtr == &tclIntType
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
|| objv[1]->typePtr == &tclWideIntType
|
||||
#endif
|
||||
|| objv[1]->typePtr == &tclBignumType
|
||||
|| (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0,
|
||||
&index) != TCL_OK)) {
|
||||
@@ -1045,37 +1042,27 @@ AfterDelay(
|
||||
if (iPtr->limit.timeEvent == NULL
|
||||
|| TCL_TIME_BEFORE(endTime, iPtr->limit.time)) {
|
||||
diff = TCL_TIME_DIFF_MS_CEILING(endTime, now);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (diff > LONG_MAX) {
|
||||
diff = LONG_MAX;
|
||||
}
|
||||
#endif
|
||||
if (diff > TCL_TIME_MAXIMUM_SLICE) {
|
||||
diff = TCL_TIME_MAXIMUM_SLICE;
|
||||
}
|
||||
if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) {
|
||||
diff = 1;
|
||||
}
|
||||
if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) {
|
||||
diff = 1;
|
||||
}
|
||||
if (diff > 0) {
|
||||
Tcl_Sleep((long) diff);
|
||||
if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
|
||||
break;
|
||||
}
|
||||
Tcl_Sleep((int) diff);
|
||||
if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
diff = TCL_TIME_DIFF_MS(iPtr->limit.time, now);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (diff > LONG_MAX) {
|
||||
diff = LONG_MAX;
|
||||
}
|
||||
#endif
|
||||
if (diff > TCL_TIME_MAXIMUM_SLICE) {
|
||||
diff = TCL_TIME_MAXIMUM_SLICE;
|
||||
}
|
||||
if (diff > 0) {
|
||||
Tcl_Sleep((long) diff);
|
||||
Tcl_Sleep((int) diff);
|
||||
}
|
||||
if (Tcl_AsyncReady()) {
|
||||
if (Tcl_AsyncInvoke(interp, TCL_OK) != TCL_OK) {
|
||||
@@ -1089,7 +1076,7 @@ AfterDelay(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_GetTime(&now);
|
||||
Tcl_GetTime(&now);
|
||||
} while (TCL_TIME_BEFORE(now, endTime));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+24
-24
@@ -26,9 +26,14 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */
|
||||
#if defined(_MSC_VER) || defined(__LLP64__)
|
||||
# define MP_32BIT
|
||||
#endif
|
||||
|
||||
/* detect 64-bit mode if possible */
|
||||
#if defined(NEVER) /* 128-bit ints fail in too many places */
|
||||
# if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT))
|
||||
#if defined(NEVER)
|
||||
# if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT) || defined(_MSC_VER))
|
||||
# define MP_64BIT
|
||||
# endif
|
||||
#endif
|
||||
@@ -73,12 +78,7 @@ typedef uint32_t mp_word;
|
||||
typedef uint64_t mp_digit;
|
||||
#define MP_DIGIT_DECLARED
|
||||
#endif
|
||||
# if defined(_WIN32)
|
||||
#ifndef MP_WORD_DECLARED
|
||||
typedef unsigned __int128 mp_word;
|
||||
#define MP_WORD_DECLARED
|
||||
#endif
|
||||
# elif defined(__GNUC__)
|
||||
# if defined(__GNUC__)
|
||||
typedef unsigned long mp_word __attribute__((mode(TI)));
|
||||
# else
|
||||
/* it seems you have a problem
|
||||
@@ -124,7 +124,7 @@ typedef mp_digit mp_min_u32;
|
||||
/* use arc4random on platforms that support it */
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
# define MP_GEN_RANDOM() arc4random()
|
||||
# define MP_GEN_RANDOM_MAX 0xffffffff
|
||||
# define MP_GEN_RANDOM_MAX 0xffffffffu
|
||||
#endif
|
||||
|
||||
/* use rand() as fall-back if there's no better rand function */
|
||||
@@ -181,7 +181,7 @@ MODULE_SCOPE int KARATSUBA_MUL_CUTOFF,
|
||||
#endif
|
||||
|
||||
/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
|
||||
#define MP_WARRAY (1 << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) + 1))
|
||||
#define MP_WARRAY (1u << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) + 1))
|
||||
|
||||
/* the infamous mp_int structure */
|
||||
#ifndef MP_INT_DECLARED
|
||||
@@ -271,9 +271,9 @@ int mp_set_int(mp_int *a, unsigned long b);
|
||||
int mp_set_long(mp_int *a, unsigned long b);
|
||||
*/
|
||||
|
||||
/* set a platform dependent unsigned long long value */
|
||||
/* set a platform dependent Tcl_WideUInt value */
|
||||
/*
|
||||
int mp_set_long_long(mp_int *a, unsigned long long b);
|
||||
int mp_set_long_long(mp_int *a, Tcl_WideUInt b);
|
||||
*/
|
||||
|
||||
/* get a 32-bit value */
|
||||
@@ -286,9 +286,9 @@ unsigned long mp_get_int(const mp_int *a);
|
||||
unsigned long mp_get_long(const mp_int *a);
|
||||
*/
|
||||
|
||||
/* get a platform dependent unsigned long long value */
|
||||
/* get a platform dependent Tcl_WideUInt value */
|
||||
/*
|
||||
unsigned long long mp_get_long_long(const mp_int *a);
|
||||
Tcl_WideUInt mp_get_long_long(const mp_int *a);
|
||||
*/
|
||||
|
||||
/* initialize and set a digit */
|
||||
@@ -553,7 +553,7 @@ int mp_sqrt(const mp_int *arg, mp_int *ret);
|
||||
|
||||
/* special sqrt (mod prime) */
|
||||
/*
|
||||
int mp_sqrtmod_prime(const mp_int *arg, const mp_int *prime, mp_int *ret);
|
||||
int mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret);
|
||||
*/
|
||||
|
||||
/* is number a square? */
|
||||
@@ -573,16 +573,16 @@ int mp_reduce_setup(mp_int *a, const mp_int *b);
|
||||
|
||||
/* Barrett Reduction, computes a (mod b) with a precomputed value c
|
||||
*
|
||||
* Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
|
||||
* compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
|
||||
* Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely
|
||||
* compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code].
|
||||
*/
|
||||
/*
|
||||
int mp_reduce(mp_int *a, const mp_int *b, const mp_int *c);
|
||||
int mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu);
|
||||
*/
|
||||
|
||||
/* setups the montgomery reduction */
|
||||
/*
|
||||
int mp_montgomery_setup(const mp_int *a, mp_digit *mp);
|
||||
int mp_montgomery_setup(const mp_int *n, mp_digit *rho);
|
||||
*/
|
||||
|
||||
/* computes a = B**n mod b without division or multiplication useful for
|
||||
@@ -594,7 +594,7 @@ int mp_montgomery_calc_normalization(mp_int *a, const mp_int *b);
|
||||
|
||||
/* computes x/R == x (mod N) via Montgomery Reduction */
|
||||
/*
|
||||
int mp_montgomery_reduce(mp_int *a, const mp_int *m, mp_digit mp);
|
||||
int mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho);
|
||||
*/
|
||||
|
||||
/* returns 1 if a is a valid DR modulus */
|
||||
@@ -607,9 +607,9 @@ int mp_dr_is_modulus(const mp_int *a);
|
||||
void mp_dr_setup(const mp_int *a, mp_digit *d);
|
||||
*/
|
||||
|
||||
/* reduces a modulo b using the Diminished Radix method */
|
||||
/* reduces a modulo n using the Diminished Radix method */
|
||||
/*
|
||||
int mp_dr_reduce(mp_int *a, const mp_int *b, mp_digit mp);
|
||||
int mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k);
|
||||
*/
|
||||
|
||||
/* returns true if a can be reduced with mp_reduce_2k */
|
||||
@@ -642,9 +642,9 @@ int mp_reduce_2k_setup_l(const mp_int *a, mp_int *d);
|
||||
int mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d);
|
||||
*/
|
||||
|
||||
/* d = a**b (mod c) */
|
||||
/* Y = G**X (mod P) */
|
||||
/*
|
||||
int mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d);
|
||||
int mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y);
|
||||
*/
|
||||
|
||||
/* ---> Primes <--- */
|
||||
|
||||
+14
-10
@@ -68,11 +68,7 @@ static const unsigned char totalBytes[256] = {
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
#if TCL_UTF_MAX > 3
|
||||
4,4,4,4,4,4,4,4,
|
||||
#else
|
||||
1,1,1,1,1,1,1,1,
|
||||
#endif
|
||||
1,1,1,1,1,1,1,1
|
||||
};
|
||||
|
||||
@@ -328,13 +324,22 @@ Tcl_UtfToUniChar(
|
||||
* represents itself.
|
||||
*/
|
||||
}
|
||||
#if TCL_UTF_MAX > 3
|
||||
else if (byte < 0xF8) {
|
||||
if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) {
|
||||
/*
|
||||
* Four-byte-character lead byte followed by three trail bytes.
|
||||
*/
|
||||
#if TCL_UTF_MAX == 4
|
||||
#if TCL_UTF_MAX == 3
|
||||
byte = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)
|
||||
| ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)) - 0x10000;
|
||||
if (byte & 0x100000) {
|
||||
/* out of range, < 0x10000 or > 0x10ffff */
|
||||
} else {
|
||||
/* produce replacement character, and advance source pointer */
|
||||
*chPtr = (Tcl_UniChar) 0xFFFD;
|
||||
return 4;
|
||||
}
|
||||
#elif TCL_UTF_MAX == 4
|
||||
Tcl_UniChar surrogate;
|
||||
|
||||
byte = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)
|
||||
@@ -365,7 +370,6 @@ Tcl_UtfToUniChar(
|
||||
* represents itself.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
*chPtr = (Tcl_UniChar) byte;
|
||||
return 1;
|
||||
@@ -499,13 +503,13 @@ Tcl_NumUtfChars(
|
||||
}
|
||||
if (i < 0) i = INT_MAX; /* Bug [2738427] */
|
||||
} else {
|
||||
register const char *endPtr = src + length - TCL_UTF_MAX;
|
||||
register const char *endPtr = src + length - 4;
|
||||
|
||||
while (src < endPtr) {
|
||||
src += TclUtfToUniChar(src, &ch);
|
||||
i++;
|
||||
}
|
||||
endPtr += TCL_UTF_MAX;
|
||||
endPtr += 4;
|
||||
while ((src < endPtr) && Tcl_UtfCharComplete(src, endPtr - src)) {
|
||||
src += TclUtfToUniChar(src, &ch);
|
||||
i++;
|
||||
@@ -677,7 +681,7 @@ Tcl_UtfPrev(
|
||||
int i, byte;
|
||||
|
||||
look = --src;
|
||||
for (i = 0; i < TCL_UTF_MAX; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (look < start) {
|
||||
if (src < start) {
|
||||
src = start;
|
||||
|
||||
+376
-120
@@ -107,10 +107,11 @@ static Tcl_ThreadDataKey precisionKey;
|
||||
static void ClearHash(Tcl_HashTable *tablePtr);
|
||||
static void FreeProcessGlobalValue(ClientData clientData);
|
||||
static void FreeThreadHash(ClientData clientData);
|
||||
static int GetEndOffsetFromObj(Tcl_Obj *objPtr, int endValue,
|
||||
int *indexPtr);
|
||||
static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr);
|
||||
static int SetEndOffsetFromAny(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
static void UpdateStringOfEndOffset(Tcl_Obj *objPtr);
|
||||
static int FindElement(Tcl_Interp *interp, const char *string,
|
||||
int stringLength, const char *typeStr,
|
||||
const char *typeCode, const char **elementPtr,
|
||||
@@ -119,15 +120,18 @@ static int FindElement(Tcl_Interp *interp, const char *string,
|
||||
/*
|
||||
* The following is the Tcl object type definition for an object that
|
||||
* represents a list index in the form, "end-offset". It is used as a
|
||||
* performance optimization in TclGetIntForIndex. The internal rep is an
|
||||
* integer, so no memory management is required for it.
|
||||
* performance optimization in TclGetIntForIndex. The internal rep is
|
||||
* stored directly in the wideValue, so no memory management is required
|
||||
* for it. This is a caching intrep, keeping the result of a parse
|
||||
* around. This type is only created from a pre-existing string, so an
|
||||
* updateStringProc will never be called and need not exist.
|
||||
*/
|
||||
|
||||
const Tcl_ObjType tclEndOffsetType = {
|
||||
static const Tcl_ObjType endOffsetType = {
|
||||
"end-offset", /* name */
|
||||
NULL, /* freeIntRepProc */
|
||||
NULL, /* dupIntRepProc */
|
||||
UpdateStringOfEndOffset, /* updateStringProc */
|
||||
NULL, /* updateStringProc */
|
||||
SetEndOffsetFromAny
|
||||
};
|
||||
|
||||
@@ -1604,6 +1608,7 @@ Tcl_Merge(
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1637,15 +1642,51 @@ Tcl_Backslash(
|
||||
TclUtfToUniChar(buf, &ch);
|
||||
return (char) ch;
|
||||
}
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclTrimRight --
|
||||
* UtfWellFormedEnd --
|
||||
* Checks the end of utf string is malformed, if yes - wraps bytes
|
||||
* to the given buffer (as well-formed NTS string). The buffer
|
||||
* argument should be initialized by the caller and ready to use.
|
||||
*
|
||||
* Takes two counted strings in the Tcl encoding which must both be null
|
||||
* terminated. Conceptually trims from the right side of the first string
|
||||
* all characters found in the second string.
|
||||
* Results:
|
||||
* The bytes with well-formed end of the string.
|
||||
*
|
||||
* Side effects:
|
||||
* Buffer (DString) may be allocated, so must be released.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline const char*
|
||||
UtfWellFormedEnd(
|
||||
Tcl_DString *buffer, /* Buffer used to hold well-formed string. */
|
||||
const char *bytes, /* Pointer to the beginning of the string. */
|
||||
int length) /* Length of the string. */
|
||||
{
|
||||
const char *l = bytes + length;
|
||||
const char *p = Tcl_UtfPrev(l, bytes);
|
||||
|
||||
if (Tcl_UtfCharComplete(p, l - p)) {
|
||||
return bytes;
|
||||
}
|
||||
/*
|
||||
* Malformed utf-8 end, be sure we've NTS to safe compare of end-character,
|
||||
* avoid segfault by access violation out of range.
|
||||
*/
|
||||
Tcl_DStringAppend(buffer, bytes, length);
|
||||
return Tcl_DStringValue(buffer);
|
||||
}
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclTrimRight --
|
||||
* Takes two counted strings in the Tcl encoding. Conceptually
|
||||
* finds the sub string (offset) to trim from the right side of the
|
||||
* first string all characters found in the second string.
|
||||
*
|
||||
* Results:
|
||||
* The number of bytes to be removed from the end of the string.
|
||||
@@ -1656,8 +1697,8 @@ Tcl_Backslash(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclTrimRight(
|
||||
static inline int
|
||||
TrimRight(
|
||||
const char *bytes, /* String to be trimmed... */
|
||||
int numBytes, /* ...and its length in bytes */
|
||||
const char *trim, /* String of trim characters... */
|
||||
@@ -1667,18 +1708,6 @@ TclTrimRight(
|
||||
int pInc;
|
||||
Tcl_UniChar ch1 = 0, ch2 = 0;
|
||||
|
||||
if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) {
|
||||
Tcl_Panic("TclTrimRight works only on null-terminated strings");
|
||||
}
|
||||
|
||||
/*
|
||||
* Empty strings -> nothing to do.
|
||||
*/
|
||||
|
||||
if ((numBytes == 0) || (numTrim == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Outer loop: iterate over string to be trimmed.
|
||||
*/
|
||||
@@ -1717,15 +1746,46 @@ TclTrimRight(
|
||||
|
||||
return numBytes - (p - bytes);
|
||||
}
|
||||
|
||||
int
|
||||
TclTrimRight(
|
||||
const char *bytes, /* String to be trimmed... */
|
||||
int numBytes, /* ...and its length in bytes */
|
||||
const char *trim, /* String of trim characters... */
|
||||
int numTrim) /* ...and its length in bytes */
|
||||
{
|
||||
int res;
|
||||
Tcl_DString bytesBuf, trimBuf;
|
||||
|
||||
/* Empty strings -> nothing to do */
|
||||
if ((numBytes == 0) || (numTrim == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Tcl_DStringInit(&bytesBuf);
|
||||
Tcl_DStringInit(&trimBuf);
|
||||
bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
|
||||
trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);
|
||||
|
||||
res = TrimRight(bytes, numBytes, trim, numTrim);
|
||||
if (res > numBytes) {
|
||||
res = numBytes;
|
||||
}
|
||||
|
||||
Tcl_DStringFree(&bytesBuf);
|
||||
Tcl_DStringFree(&trimBuf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclTrimLeft --
|
||||
*
|
||||
* Takes two counted strings in the Tcl encoding which must both be null
|
||||
* terminated. Conceptually trims from the left side of the first string
|
||||
* all characters found in the second string.
|
||||
* Takes two counted strings in the Tcl encoding. Conceptually
|
||||
* finds the sub string (offset) to trim from the left side of the
|
||||
* first string all characters found in the second string.
|
||||
*
|
||||
* Results:
|
||||
* The number of bytes to be removed from the start of the string.
|
||||
@@ -1736,8 +1796,8 @@ TclTrimRight(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclTrimLeft(
|
||||
static inline int
|
||||
TrimLeft(
|
||||
const char *bytes, /* String to be trimmed... */
|
||||
int numBytes, /* ...and its length in bytes */
|
||||
const char *trim, /* String of trim characters... */
|
||||
@@ -1746,18 +1806,6 @@ TclTrimLeft(
|
||||
const char *p = bytes;
|
||||
Tcl_UniChar ch1 = 0, ch2 = 0;
|
||||
|
||||
if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) {
|
||||
Tcl_Panic("TclTrimLeft works only on null-terminated strings");
|
||||
}
|
||||
|
||||
/*
|
||||
* Empty strings -> nothing to do.
|
||||
*/
|
||||
|
||||
if ((numBytes == 0) || (numTrim == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Outer loop: iterate over string to be trimmed.
|
||||
*/
|
||||
@@ -1792,10 +1840,99 @@ TclTrimLeft(
|
||||
|
||||
p += pInc;
|
||||
numBytes -= pInc;
|
||||
} while (numBytes);
|
||||
} while (numBytes > 0);
|
||||
|
||||
return p - bytes;
|
||||
}
|
||||
|
||||
int
|
||||
TclTrimLeft(
|
||||
const char *bytes, /* String to be trimmed... */
|
||||
int numBytes, /* ...and its length in bytes */
|
||||
const char *trim, /* String of trim characters... */
|
||||
int numTrim) /* ...and its length in bytes */
|
||||
{
|
||||
int res;
|
||||
Tcl_DString bytesBuf, trimBuf;
|
||||
|
||||
/* Empty strings -> nothing to do */
|
||||
if ((numBytes == 0) || (numTrim == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Tcl_DStringInit(&bytesBuf);
|
||||
Tcl_DStringInit(&trimBuf);
|
||||
bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
|
||||
trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);
|
||||
|
||||
res = TrimLeft(bytes, numBytes, trim, numTrim);
|
||||
if (res > numBytes) {
|
||||
res = numBytes;
|
||||
}
|
||||
|
||||
Tcl_DStringFree(&bytesBuf);
|
||||
Tcl_DStringFree(&trimBuf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclTrim --
|
||||
* Finds the sub string (offset) to trim from both sides of the
|
||||
* first string all characters found in the second string.
|
||||
*
|
||||
* Results:
|
||||
* The number of bytes to be removed from the start of the string
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclTrim(
|
||||
const char *bytes, /* String to be trimmed... */
|
||||
int numBytes, /* ...and its length in bytes */
|
||||
const char *trim, /* String of trim characters... */
|
||||
int numTrim, /* ...and its length in bytes */
|
||||
int *trimRight) /* Offset from the end of the string. */
|
||||
{
|
||||
int trimLeft;
|
||||
Tcl_DString bytesBuf, trimBuf;
|
||||
|
||||
*trimRight = 0;
|
||||
/* Empty strings -> nothing to do */
|
||||
if ((numBytes == 0) || (numTrim == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Tcl_DStringInit(&bytesBuf);
|
||||
Tcl_DStringInit(&trimBuf);
|
||||
bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
|
||||
trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);
|
||||
|
||||
trimLeft = TrimLeft(bytes, numBytes, trim, numTrim);
|
||||
if (trimLeft > numBytes) {
|
||||
trimLeft = numBytes;
|
||||
}
|
||||
numBytes -= trimLeft;
|
||||
/* have to trim yet (first char was already verified within TrimLeft) */
|
||||
if (numBytes > 1) {
|
||||
bytes += trimLeft;
|
||||
*trimRight = TrimRight(bytes, numBytes, trim, numTrim);
|
||||
if (*trimRight > numBytes) {
|
||||
*trimRight = numBytes;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_DStringFree(&bytesBuf);
|
||||
Tcl_DStringFree(&trimBuf);
|
||||
|
||||
return trimLeft;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -1863,30 +2000,20 @@ Tcl_Concat(
|
||||
result = ckalloc((unsigned) (bytesNeeded + argc));
|
||||
|
||||
for (p = result, i = 0; i < argc; i++) {
|
||||
int trim, elemLength;
|
||||
int triml, trimr, elemLength;
|
||||
const char *element;
|
||||
|
||||
element = argv[i];
|
||||
elemLength = strlen(argv[i]);
|
||||
|
||||
/*
|
||||
* Trim away the leading whitespace.
|
||||
*/
|
||||
/* Trim away the leading/trailing whitespace. */
|
||||
triml = TclTrim(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE, &trimr);
|
||||
element += triml;
|
||||
elemLength -= triml + trimr;
|
||||
|
||||
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
element += trim;
|
||||
elemLength -= trim;
|
||||
|
||||
/*
|
||||
* Trim away the trailing whitespace. Do not permit trimming to expose
|
||||
* a final backslash character.
|
||||
*/
|
||||
|
||||
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
trim -= trim && (element[elemLength - trim - 1] == '\\');
|
||||
elemLength -= trim;
|
||||
/* Do not permit trimming to expose a final backslash character. */
|
||||
elemLength += trimr && (element[elemLength - 1] == '\\');
|
||||
|
||||
/*
|
||||
* If we're left with empty element after trimming, do nothing.
|
||||
@@ -2006,28 +2133,18 @@ Tcl_ConcatObj(
|
||||
Tcl_SetObjLength(resPtr, 0);
|
||||
|
||||
for (i = 0; i < objc; i++) {
|
||||
int trim;
|
||||
int triml, trimr;
|
||||
|
||||
element = TclGetStringFromObj(objv[i], &elemLength);
|
||||
|
||||
/*
|
||||
* Trim away the leading whitespace.
|
||||
*/
|
||||
/* Trim away the leading/trailing whitespace. */
|
||||
triml = TclTrim(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE, &trimr);
|
||||
element += triml;
|
||||
elemLength -= triml + trimr;
|
||||
|
||||
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
element += trim;
|
||||
elemLength -= trim;
|
||||
|
||||
/*
|
||||
* Trim away the trailing whitespace. Do not permit trimming to expose
|
||||
* a final backslash character.
|
||||
*/
|
||||
|
||||
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
trim -= trim && (element[elemLength - trim - 1] == '\\');
|
||||
elemLength -= trim;
|
||||
/* Do not permit trimming to expose a final backslash character. */
|
||||
elemLength += trimr && (element[elemLength - 1] == '\\');
|
||||
|
||||
/*
|
||||
* If we're left with empty element after trimming, do nothing.
|
||||
@@ -2528,7 +2645,8 @@ TclStringMatchObj(
|
||||
udata = Tcl_GetUnicodeFromObj(strObj, &length);
|
||||
uptn = Tcl_GetUnicodeFromObj(ptnObj, &plen);
|
||||
match = TclUniCharMatch(udata, length, uptn, plen, flags);
|
||||
} else if (TclIsPureByteArray(strObj) && !flags) {
|
||||
} else if (TclIsPureByteArray(strObj) && TclIsPureByteArray(ptnObj)
|
||||
&& !flags) {
|
||||
unsigned char *data, *ptn;
|
||||
|
||||
data = Tcl_GetByteArrayFromObj(strObj, &length);
|
||||
@@ -3298,6 +3416,7 @@ Tcl_PrintDouble(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
|
||||
/* ARGSUSED */
|
||||
char *
|
||||
TclPrecTraceProc(
|
||||
@@ -3355,6 +3474,7 @@ TclPrecTraceProc(
|
||||
*precisionPtr = prec;
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !TCL_NO_DEPRECATED)*/
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -3472,9 +3592,9 @@ int
|
||||
TclFormatInt(
|
||||
char *buffer, /* Points to the storage into which the
|
||||
* formatted characters are written. */
|
||||
long n) /* The integer to format. */
|
||||
Tcl_WideInt n) /* The integer to format. */
|
||||
{
|
||||
long intVal;
|
||||
Tcl_WideInt intVal;
|
||||
int i;
|
||||
int numFormatted, j;
|
||||
const char *digits = "0123456789";
|
||||
@@ -3497,7 +3617,7 @@ TclFormatInt(
|
||||
|
||||
intVal = -n; /* [Bug 3390638] Workaround for*/
|
||||
if (n == -n || intVal == n) { /* broken compiler optimizers. */
|
||||
return sprintf(buffer, "%ld", n);
|
||||
return sprintf(buffer, "%" TCL_LL_MODIFIER "d", n);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3575,13 +3695,7 @@ TclGetIntForIndex(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (SetEndOffsetFromAny(NULL, objPtr) == TCL_OK) {
|
||||
/*
|
||||
* If the object is already an offset from the end of the list, or can
|
||||
* be converted to one, use it.
|
||||
*/
|
||||
|
||||
*indexPtr = endValue + objPtr->internalRep.longValue;
|
||||
if (GetEndOffsetFromObj(objPtr, endValue, indexPtr) == TCL_OK) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -3648,40 +3762,38 @@ TclGetIntForIndex(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* UpdateStringOfEndOffset --
|
||||
* GetEndOffsetFromObj --
|
||||
*
|
||||
* Update the string rep of a Tcl object holding an "end-offset"
|
||||
* expression.
|
||||
* Look for a string of the form "end[+-]offset" and convert it to an
|
||||
* internal representation holding the offset.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* Tcl return code.
|
||||
*
|
||||
* Side effects:
|
||||
* Stores a valid string in the object's string rep.
|
||||
*
|
||||
* This function does NOT free any earlier string rep. If it is called on an
|
||||
* object that already has a valid string rep, it will leak memory.
|
||||
* May store a Tcl_ObjType.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
UpdateStringOfEndOffset(
|
||||
register Tcl_Obj *objPtr)
|
||||
static int
|
||||
GetEndOffsetFromObj(
|
||||
Tcl_Obj *objPtr, /* Pointer to the object to parse */
|
||||
int endValue, /* The value to be stored at "indexPtr" if
|
||||
* "objPtr" holds "end". */
|
||||
int *indexPtr) /* Location filled in with an integer
|
||||
* representing an index. */
|
||||
{
|
||||
char buffer[TCL_INTEGER_SPACE + 5];
|
||||
register int len = 3;
|
||||
|
||||
memcpy(buffer, "end", 4);
|
||||
if (objPtr->internalRep.longValue != 0) {
|
||||
buffer[len++] = '-';
|
||||
len += TclFormatInt(buffer+len, -(objPtr->internalRep.longValue));
|
||||
if (SetEndOffsetFromAny(NULL, objPtr) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objPtr->bytes = ckalloc((unsigned) len+1);
|
||||
memcpy(objPtr->bytes, buffer, (unsigned) len+1);
|
||||
objPtr->length = len;
|
||||
|
||||
/* TODO: Handle overflow cases sensibly */
|
||||
*indexPtr = endValue + (int)objPtr->internalRep.wideValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -3705,7 +3817,7 @@ SetEndOffsetFromAny(
|
||||
Tcl_Interp *interp, /* Tcl interpreter or NULL */
|
||||
Tcl_Obj *objPtr) /* Pointer to the object to parse */
|
||||
{
|
||||
int offset; /* Offset in the "end-offset" expression */
|
||||
Tcl_WideInt offset; /* Offset in the "end-offset" expression */
|
||||
register const char *bytes; /* String rep of the object */
|
||||
int length; /* Length of the object's string rep */
|
||||
|
||||
@@ -3713,7 +3825,7 @@ SetEndOffsetFromAny(
|
||||
* If it's already the right type, we're fine.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &tclEndOffsetType) {
|
||||
if (objPtr->typePtr == &endOffsetType) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -3741,16 +3853,23 @@ SetEndOffsetFromAny(
|
||||
} else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) {
|
||||
/*
|
||||
* This is our limited string expression evaluator. Pass everything
|
||||
* after "end-" to Tcl_GetInt, then reverse for offset.
|
||||
* after "end-" to TclParseNumber.
|
||||
*/
|
||||
|
||||
if (TclIsSpaceProc(bytes[4])) {
|
||||
goto badIndexFormat;
|
||||
}
|
||||
if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) {
|
||||
if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL,
|
||||
TCL_PARSE_INTEGER_ONLY) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objPtr->typePtr != &tclIntType) {
|
||||
goto badIndexFormat;
|
||||
}
|
||||
offset = objPtr->internalRep.wideValue;
|
||||
if (bytes[3] == '-') {
|
||||
|
||||
/* TODO: Review overflow concerns here! */
|
||||
offset = -offset;
|
||||
}
|
||||
} else {
|
||||
@@ -3773,12 +3892,149 @@ SetEndOffsetFromAny(
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.longValue = offset;
|
||||
objPtr->typePtr = &tclEndOffsetType;
|
||||
objPtr->internalRep.wideValue = offset;
|
||||
objPtr->typePtr = &endOffsetType;
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclIndexEncode --
|
||||
*
|
||||
* Parse objPtr to determine if it is an index value. Two cases
|
||||
* are possible. The value objPtr might be parsed as an absolute
|
||||
* index value in the C signed int range. Note that this includes
|
||||
* index values that are integers as presented and it includes index
|
||||
* arithmetic expressions. The absolute index values that can be
|
||||
* directly meaningful as an index into either a list or a string are
|
||||
* those integer values >= TCL_INDEX_START (0)
|
||||
* and < TCL_INDEX_AFTER (INT_MAX).
|
||||
* The largest string supported in Tcl 8 has bytelength INT_MAX.
|
||||
* This means the largest supported character length is also INT_MAX,
|
||||
* and the index of the last character in a string of length INT_MAX
|
||||
* is INT_MAX-1.
|
||||
*
|
||||
* Any absolute index value parsed outside that range is encoded
|
||||
* using the before and after values passed in by the
|
||||
* caller as the encoding to use for indices that are either
|
||||
* less than or greater than the usable index range. TCL_INDEX_AFTER
|
||||
* is available as a good choice for most callers to use for
|
||||
* after. Likewise, the value TCL_INDEX_BEFORE is good for
|
||||
* most callers to use for before. Other values are possible
|
||||
* when the caller knows it is helpful in producing its own behavior
|
||||
* for indices before and after the indexed item.
|
||||
*
|
||||
* A token can also be parsed as an end-relative index expression.
|
||||
* All end-relative expressions that indicate an index larger
|
||||
* than end (end+2, end--5) point beyond the end of the indexed
|
||||
* collection, and can be encoded as after. The end-relative
|
||||
* expressions that indicate an index less than or equal to end
|
||||
* are encoded relative to the value TCL_INDEX_END (-2). The
|
||||
* index "end" is encoded as -2, down to the index "end-0x7ffffffe"
|
||||
* which is encoded as INT_MIN. Since the largest index into a
|
||||
* string possible in Tcl 8 is 0x7ffffffe, the interpretation of
|
||||
* "end-0x7ffffffe" for that largest string would be 0. Thus,
|
||||
* if the tokens "end-0x7fffffff" or "end+-0x80000000" are parsed,
|
||||
* they can be encoded with the before value.
|
||||
*
|
||||
* These details will require re-examination whenever string and
|
||||
* list length limits are increased, but that will likely also
|
||||
* mean a revised routine capable of returning Tcl_WideInt values.
|
||||
*
|
||||
* Returns:
|
||||
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
|
||||
*
|
||||
* Side effects:
|
||||
* When TCL_OK is returned, the encoded index value is written
|
||||
* to *indexPtr.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclIndexEncode(
|
||||
Tcl_Interp *interp, /* For error reporting, may be NULL */
|
||||
Tcl_Obj *objPtr, /* Index value to parse */
|
||||
int before, /* Value to return for index before beginning */
|
||||
int after, /* Value to return for index after end */
|
||||
int *indexPtr) /* Where to write the encoded answer, not NULL */
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (TCL_OK == TclGetIntFromObj(NULL, objPtr, &idx)) {
|
||||
/* We parsed a value in the range INT_MIN...INT_MAX */
|
||||
integerEncode:
|
||||
if (idx < TCL_INDEX_START) {
|
||||
/* All negative absolute indices are "before the beginning" */
|
||||
idx = before;
|
||||
} else if (idx == INT_MAX) {
|
||||
/* This index value is always "after the end" */
|
||||
idx = after;
|
||||
}
|
||||
/* usual case, the absolute index value encodes itself */
|
||||
} else if (TCL_OK == GetEndOffsetFromObj(objPtr, 0, &idx)) {
|
||||
/*
|
||||
* We parsed an end+offset index value.
|
||||
* idx holds the offset value in the range INT_MIN...INT_MAX.
|
||||
*/
|
||||
if (idx > 0) {
|
||||
/*
|
||||
* All end+postive or end-negative expressions
|
||||
* always indicate "after the end".
|
||||
*/
|
||||
idx = after;
|
||||
} else if (idx < INT_MIN - TCL_INDEX_END) {
|
||||
/* These indices always indicate "before the beginning */
|
||||
idx = before;
|
||||
} else {
|
||||
/* Encoded end-positive (or end+negative) are offset */
|
||||
idx += TCL_INDEX_END;
|
||||
}
|
||||
|
||||
/* TODO: Consider flag to suppress repeated end-offset parse. */
|
||||
} else if (TCL_OK == TclGetIntForIndexM(interp, objPtr, 0, &idx)) {
|
||||
/*
|
||||
* Only reach this case when the index value is a
|
||||
* constant index arithmetic expression, and idx
|
||||
* holds the result. Treat it the same as if it were
|
||||
* parsed as an absolute integer value.
|
||||
*/
|
||||
goto integerEncode;
|
||||
} else {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*indexPtr = idx;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclIndexDecode --
|
||||
*
|
||||
* Decodes a value previously encoded by TclIndexEncode. The argument
|
||||
* endValue indicates what value of "end" should be used in the
|
||||
* decoding.
|
||||
*
|
||||
* Results:
|
||||
* The decoded index value.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclIndexDecode(
|
||||
int encoded, /* Value to decode */
|
||||
int endValue) /* Meaning of "end" to use, > TCL_INDEX_END */
|
||||
{
|
||||
if (encoded <= TCL_INDEX_END) {
|
||||
return (encoded - TCL_INDEX_END) + endValue;
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -4010,7 +4266,7 @@ TclSetProcessGlobalValue(
|
||||
Tcl_IncrRefCount(newValue);
|
||||
cacheMap = GetThreadHash(&pgvPtr->key);
|
||||
ClearHash(cacheMap);
|
||||
hPtr = Tcl_CreateHashEntry(cacheMap, (void *)(pgvPtr->epoch), &dummy);
|
||||
hPtr = Tcl_CreateHashEntry(cacheMap, (void *)(size_t)(pgvPtr->epoch), &dummy);
|
||||
Tcl_SetHashValue(hPtr, newValue);
|
||||
Tcl_MutexUnlock(&pgvPtr->mutex);
|
||||
}
|
||||
@@ -4036,7 +4292,7 @@ TclGetProcessGlobalValue(
|
||||
Tcl_Obj *value = NULL;
|
||||
Tcl_HashTable *cacheMap;
|
||||
Tcl_HashEntry *hPtr;
|
||||
size_t epoch = pgvPtr->epoch;
|
||||
unsigned int epoch = pgvPtr->epoch;
|
||||
|
||||
if (pgvPtr->encoding) {
|
||||
Tcl_Encoding current = Tcl_GetEncoding(NULL, NULL);
|
||||
@@ -4070,7 +4326,7 @@ TclGetProcessGlobalValue(
|
||||
}
|
||||
}
|
||||
cacheMap = GetThreadHash(&pgvPtr->key);
|
||||
hPtr = Tcl_FindHashEntry(cacheMap, (void *) (epoch));
|
||||
hPtr = Tcl_FindHashEntry(cacheMap, (void *)(size_t)epoch);
|
||||
if (NULL == hPtr) {
|
||||
int dummy;
|
||||
|
||||
@@ -4103,7 +4359,7 @@ TclGetProcessGlobalValue(
|
||||
|
||||
value = Tcl_NewStringObj(pgvPtr->value, pgvPtr->numBytes);
|
||||
hPtr = Tcl_CreateHashEntry(cacheMap,
|
||||
(void *)(pgvPtr->epoch), &dummy);
|
||||
(void *)(size_t)(pgvPtr->epoch), &dummy);
|
||||
Tcl_MutexUnlock(&pgvPtr->mutex);
|
||||
Tcl_SetHashValue(hPtr, value);
|
||||
Tcl_IncrRefCount(value);
|
||||
|
||||
+2
-2
@@ -280,7 +280,7 @@ CleanupVar(
|
||||
{
|
||||
if (TclIsVarUndefined(varPtr) && TclIsVarInHash(varPtr)
|
||||
&& !TclIsVarTraced(varPtr)
|
||||
&& (VarHashRefCount(varPtr) == !TclIsVarDeadHash(varPtr))) {
|
||||
&& (VarHashRefCount(varPtr) == (unsigned)!TclIsVarDeadHash(varPtr))) {
|
||||
if (VarHashRefCount(varPtr) == 0) {
|
||||
ckfree(varPtr);
|
||||
} else {
|
||||
@@ -289,7 +289,7 @@ CleanupVar(
|
||||
}
|
||||
if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) &&
|
||||
TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) &&
|
||||
(VarHashRefCount(arrayPtr) == !TclIsVarDeadHash(arrayPtr))) {
|
||||
(VarHashRefCount(arrayPtr) == (unsigned)!TclIsVarDeadHash(arrayPtr))) {
|
||||
if (VarHashRefCount(arrayPtr) == 0) {
|
||||
ckfree(arrayPtr);
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -373,7 +373,7 @@ ConvertErrorToList(
|
||||
|
||||
default:
|
||||
TclNewLiteralStringObj(objv[2], "UNKNOWN");
|
||||
TclNewLongObj(objv[3], code);
|
||||
TclNewIntObj(objv[3], code);
|
||||
return Tcl_NewListObj(4, objv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,377 +0,0 @@
|
||||
# http.tcl
|
||||
# Client-side HTTP for GET, POST, and HEAD commands.
|
||||
# These routines can be used in untrusted code that uses the Safesock
|
||||
# security policy.
|
||||
# These procedures use a callback interface to avoid using vwait,
|
||||
# which is not defined in the safe base.
|
||||
#
|
||||
# See the http.n man page for documentation
|
||||
|
||||
package provide http 1.0
|
||||
|
||||
array set http {
|
||||
-accept */*
|
||||
-proxyhost {}
|
||||
-proxyport {}
|
||||
-useragent {Tcl http client package 1.0}
|
||||
-proxyfilter httpProxyRequired
|
||||
}
|
||||
proc http_config {args} {
|
||||
global http
|
||||
set options [lsort [array names http -*]]
|
||||
set usage [join $options ", "]
|
||||
if {[llength $args] == 0} {
|
||||
set result {}
|
||||
foreach name $options {
|
||||
lappend result $name $http($name)
|
||||
}
|
||||
return $result
|
||||
}
|
||||
regsub -all -- - $options {} options
|
||||
set pat ^-([join $options |])$
|
||||
if {[llength $args] == 1} {
|
||||
set flag [lindex $args 0]
|
||||
if {[regexp -- $pat $flag]} {
|
||||
return $http($flag)
|
||||
} else {
|
||||
return -code error "Unknown option $flag, must be: $usage"
|
||||
}
|
||||
} else {
|
||||
foreach {flag value} $args {
|
||||
if {[regexp -- $pat $flag]} {
|
||||
set http($flag) $value
|
||||
} else {
|
||||
return -code error "Unknown option $flag, must be: $usage"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc httpFinish { token {errormsg ""} } {
|
||||
upvar #0 $token state
|
||||
global errorInfo errorCode
|
||||
if {[string length $errormsg] != 0} {
|
||||
set state(error) [list $errormsg $errorInfo $errorCode]
|
||||
set state(status) error
|
||||
}
|
||||
catch {close $state(sock)}
|
||||
catch {after cancel $state(after)}
|
||||
if {[info exists state(-command)]} {
|
||||
if {[catch {eval $state(-command) {$token}} err]} {
|
||||
if {[string length $errormsg] == 0} {
|
||||
set state(error) [list $err $errorInfo $errorCode]
|
||||
set state(status) error
|
||||
}
|
||||
}
|
||||
unset state(-command)
|
||||
}
|
||||
}
|
||||
proc http_reset { token {why reset} } {
|
||||
upvar #0 $token state
|
||||
set state(status) $why
|
||||
catch {fileevent $state(sock) readable {}}
|
||||
httpFinish $token
|
||||
if {[info exists state(error)]} {
|
||||
set errorlist $state(error)
|
||||
unset state(error)
|
||||
eval error $errorlist
|
||||
}
|
||||
}
|
||||
proc http_get { url args } {
|
||||
global http
|
||||
if {![info exists http(uid)]} {
|
||||
set http(uid) 0
|
||||
}
|
||||
set token http#[incr http(uid)]
|
||||
upvar #0 $token state
|
||||
http_reset $token
|
||||
array set state {
|
||||
-blocksize 8192
|
||||
-validate 0
|
||||
-headers {}
|
||||
-timeout 0
|
||||
state header
|
||||
meta {}
|
||||
currentsize 0
|
||||
totalsize 0
|
||||
type text/html
|
||||
body {}
|
||||
status ""
|
||||
}
|
||||
set options {-blocksize -channel -command -handler -headers \
|
||||
-progress -query -validate -timeout}
|
||||
set usage [join $options ", "]
|
||||
regsub -all -- - $options {} options
|
||||
set pat ^-([join $options |])$
|
||||
foreach {flag value} $args {
|
||||
if {[regexp $pat $flag]} {
|
||||
# Validate numbers
|
||||
if {[info exists state($flag)] && \
|
||||
[regexp {^[0-9]+$} $state($flag)] && \
|
||||
![regexp {^[0-9]+$} $value]} {
|
||||
return -code error "Bad value for $flag ($value), must be integer"
|
||||
}
|
||||
set state($flag) $value
|
||||
} else {
|
||||
return -code error "Unknown option $flag, can be: $usage"
|
||||
}
|
||||
}
|
||||
if {! [regexp -nocase {^(http://)?([^/:]+)(:([0-9]+))?(/.*)?$} $url \
|
||||
x proto host y port srvurl]} {
|
||||
error "Unsupported URL: $url"
|
||||
}
|
||||
if {[string length $port] == 0} {
|
||||
set port 80
|
||||
}
|
||||
if {[string length $srvurl] == 0} {
|
||||
set srvurl /
|
||||
}
|
||||
if {[string length $proto] == 0} {
|
||||
set url http://$url
|
||||
}
|
||||
set state(url) $url
|
||||
if {![catch {$http(-proxyfilter) $host} proxy]} {
|
||||
set phost [lindex $proxy 0]
|
||||
set pport [lindex $proxy 1]
|
||||
}
|
||||
if {$state(-timeout) > 0} {
|
||||
set state(after) [after $state(-timeout) [list http_reset $token timeout]]
|
||||
}
|
||||
if {[info exists phost] && [string length $phost]} {
|
||||
set srvurl $url
|
||||
set s [socket $phost $pport]
|
||||
} else {
|
||||
set s [socket $host $port]
|
||||
}
|
||||
set state(sock) $s
|
||||
|
||||
# Send data in cr-lf format, but accept any line terminators
|
||||
|
||||
fconfigure $s -translation {auto crlf} -buffersize $state(-blocksize)
|
||||
|
||||
# The following is disallowed in safe interpreters, but the socket
|
||||
# is already in non-blocking mode in that case.
|
||||
|
||||
catch {fconfigure $s -blocking off}
|
||||
set len 0
|
||||
set how GET
|
||||
if {[info exists state(-query)]} {
|
||||
set len [string length $state(-query)]
|
||||
if {$len > 0} {
|
||||
set how POST
|
||||
}
|
||||
} elseif {$state(-validate)} {
|
||||
set how HEAD
|
||||
}
|
||||
puts $s "$how $srvurl HTTP/1.0"
|
||||
puts $s "Accept: $http(-accept)"
|
||||
puts $s "Host: $host"
|
||||
puts $s "User-Agent: $http(-useragent)"
|
||||
foreach {key value} $state(-headers) {
|
||||
regsub -all \[\n\r\] $value {} value
|
||||
set key [string trim $key]
|
||||
if {[string length $key]} {
|
||||
puts $s "$key: $value"
|
||||
}
|
||||
}
|
||||
if {$len > 0} {
|
||||
puts $s "Content-Length: $len"
|
||||
puts $s "Content-Type: application/x-www-form-urlencoded"
|
||||
puts $s ""
|
||||
fconfigure $s -translation {auto binary}
|
||||
puts -nonewline $s $state(-query)
|
||||
} else {
|
||||
puts $s ""
|
||||
}
|
||||
flush $s
|
||||
fileevent $s readable [list httpEvent $token]
|
||||
if {! [info exists state(-command)]} {
|
||||
http_wait $token
|
||||
}
|
||||
return $token
|
||||
}
|
||||
proc http_data {token} {
|
||||
upvar #0 $token state
|
||||
return $state(body)
|
||||
}
|
||||
proc http_status {token} {
|
||||
upvar #0 $token state
|
||||
return $state(status)
|
||||
}
|
||||
proc http_code {token} {
|
||||
upvar #0 $token state
|
||||
return $state(http)
|
||||
}
|
||||
proc http_size {token} {
|
||||
upvar #0 $token state
|
||||
return $state(currentsize)
|
||||
}
|
||||
|
||||
proc httpEvent {token} {
|
||||
upvar #0 $token state
|
||||
set s $state(sock)
|
||||
|
||||
if {[eof $s]} {
|
||||
httpEof $token
|
||||
return
|
||||
}
|
||||
if {$state(state) == "header"} {
|
||||
set n [gets $s line]
|
||||
if {$n == 0} {
|
||||
set state(state) body
|
||||
if {![regexp -nocase ^text $state(type)]} {
|
||||
# Turn off conversions for non-text data
|
||||
fconfigure $s -translation binary
|
||||
if {[info exists state(-channel)]} {
|
||||
fconfigure $state(-channel) -translation binary
|
||||
}
|
||||
}
|
||||
if {[info exists state(-channel)] &&
|
||||
![info exists state(-handler)]} {
|
||||
# Initiate a sequence of background fcopies
|
||||
fileevent $s readable {}
|
||||
httpCopyStart $s $token
|
||||
}
|
||||
} elseif {$n > 0} {
|
||||
if {[regexp -nocase {^content-type:(.+)$} $line x type]} {
|
||||
set state(type) [string trim $type]
|
||||
}
|
||||
if {[regexp -nocase {^content-length:(.+)$} $line x length]} {
|
||||
set state(totalsize) [string trim $length]
|
||||
}
|
||||
if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} {
|
||||
lappend state(meta) $key $value
|
||||
} elseif {[regexp ^HTTP $line]} {
|
||||
set state(http) $line
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if {[catch {
|
||||
if {[info exists state(-handler)]} {
|
||||
set n [eval $state(-handler) {$s $token}]
|
||||
} else {
|
||||
set block [read $s $state(-blocksize)]
|
||||
set n [string length $block]
|
||||
if {$n >= 0} {
|
||||
append state(body) $block
|
||||
}
|
||||
}
|
||||
if {$n >= 0} {
|
||||
incr state(currentsize) $n
|
||||
}
|
||||
} err]} {
|
||||
httpFinish $token $err
|
||||
} else {
|
||||
if {[info exists state(-progress)]} {
|
||||
eval $state(-progress) {$token $state(totalsize) $state(currentsize)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
proc httpCopyStart {s token} {
|
||||
upvar #0 $token state
|
||||
if {[catch {
|
||||
fcopy $s $state(-channel) -size $state(-blocksize) -command \
|
||||
[list httpCopyDone $token]
|
||||
} err]} {
|
||||
httpFinish $token $err
|
||||
}
|
||||
}
|
||||
proc httpCopyDone {token count {error {}}} {
|
||||
upvar #0 $token state
|
||||
set s $state(sock)
|
||||
incr state(currentsize) $count
|
||||
if {[info exists state(-progress)]} {
|
||||
eval $state(-progress) {$token $state(totalsize) $state(currentsize)}
|
||||
}
|
||||
if {([string length $error] != 0)} {
|
||||
httpFinish $token $error
|
||||
} elseif {[eof $s]} {
|
||||
httpEof $token
|
||||
} else {
|
||||
httpCopyStart $s $token
|
||||
}
|
||||
}
|
||||
proc httpEof {token} {
|
||||
upvar #0 $token state
|
||||
if {$state(state) == "header"} {
|
||||
# Premature eof
|
||||
set state(status) eof
|
||||
} else {
|
||||
set state(status) ok
|
||||
}
|
||||
set state(state) eof
|
||||
httpFinish $token
|
||||
}
|
||||
proc http_wait {token} {
|
||||
upvar #0 $token state
|
||||
if {![info exists state(status)] || [string length $state(status)] == 0} {
|
||||
vwait $token\(status)
|
||||
}
|
||||
if {[info exists state(error)]} {
|
||||
set errorlist $state(error)
|
||||
unset state(error)
|
||||
eval error $errorlist
|
||||
}
|
||||
return $state(status)
|
||||
}
|
||||
|
||||
# Call http_formatQuery with an even number of arguments, where the first is
|
||||
# a name, the second is a value, the third is another name, and so on.
|
||||
|
||||
proc http_formatQuery {args} {
|
||||
set result ""
|
||||
set sep ""
|
||||
foreach i $args {
|
||||
append result $sep [httpMapReply $i]
|
||||
if {$sep != "="} {
|
||||
set sep =
|
||||
} else {
|
||||
set sep &
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
# do x-www-urlencoded character mapping
|
||||
# The spec says: "non-alphanumeric characters are replaced by '%HH'"
|
||||
# 1 leave alphanumerics characters alone
|
||||
# 2 Convert every other character to an array lookup
|
||||
# 3 Escape constructs that are "special" to the tcl parser
|
||||
# 4 "subst" the result, doing all the array substitutions
|
||||
|
||||
proc httpMapReply {string} {
|
||||
global httpFormMap
|
||||
set alphanumeric a-zA-Z0-9
|
||||
if {![info exists httpFormMap]} {
|
||||
|
||||
for {set i 1} {$i <= 256} {incr i} {
|
||||
set c [format %c $i]
|
||||
if {![string match \[$alphanumeric\] $c]} {
|
||||
set httpFormMap($c) %[format %.2x $i]
|
||||
}
|
||||
}
|
||||
# These are handled specially
|
||||
array set httpFormMap {
|
||||
" " + \n %0d%0a
|
||||
}
|
||||
}
|
||||
regsub -all \[^$alphanumeric\] $string {$httpFormMap(&)} string
|
||||
regsub -all \n $string {\\n} string
|
||||
regsub -all \t $string {\\t} string
|
||||
regsub -all {[][{})\\]\)} $string {\\&} string
|
||||
return [subst $string]
|
||||
}
|
||||
|
||||
# Default proxy filter.
|
||||
proc httpProxyRequired {host} {
|
||||
global http
|
||||
if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} {
|
||||
if {![info exists http(-proxyport)] || ![string length $http(-proxyport)]} {
|
||||
set http(-proxyport) 8080
|
||||
}
|
||||
return [list $http(-proxyhost) $http(-proxyport)]
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# Tcl package index file, version 1.0
|
||||
# This file is generated by the "pkg_mkIndex" command
|
||||
# and sourced either when an application starts up or
|
||||
# by a "package unknown" script. It invokes the
|
||||
# "package ifneeded" command to set up package-related
|
||||
# information so that packages will be loaded automatically
|
||||
# in response to "package require" commands. When this
|
||||
# script is sourced, the variable $dir must contain the
|
||||
# full path name of this file's directory.
|
||||
|
||||
package ifneeded http 1.0 [list tclPkgSetup $dir http 1.0 {{http.tcl source {httpCopyDone httpCopyStart httpEof httpEvent httpFinish httpMapReply httpProxyRequired http_code http_config http_data http_formatQuery http_get http_reset http_size http_status http_wait}}}]
|
||||
+2
-6
@@ -619,8 +619,7 @@ proc auto_execok name {
|
||||
set auto_execs($name) ""
|
||||
|
||||
set shellBuiltins [list assoc cls copy date del dir echo erase ftype \
|
||||
md mkdir mklink move rd ren rename rmdir start \
|
||||
time type ver vol]
|
||||
md mkdir mklink move rd ren rename rmdir start time type ver vol]
|
||||
if {[info exists env(PATHEXT)]} {
|
||||
# Add an initial ; to have the {} extension check first.
|
||||
set execExtensions [split ";$env(PATHEXT)" ";"]
|
||||
@@ -654,10 +653,7 @@ proc auto_execok name {
|
||||
set windir $env(WINDIR)
|
||||
}
|
||||
if {[info exists windir]} {
|
||||
if {$tcl_platform(os) eq "Windows NT"} {
|
||||
append path "$windir/system32;"
|
||||
}
|
||||
append path "$windir/system;$windir;"
|
||||
append path "$windir/system32;$windir/system;$windir;"
|
||||
}
|
||||
|
||||
foreach var {PATH Path path} {
|
||||
|
||||
+215
-85
@@ -4,22 +4,24 @@
|
||||
# message catalog facility for Tcl programs. It should be
|
||||
# loaded with the command "package require msgcat".
|
||||
#
|
||||
# Copyright (c) 2010-2015 by Harald Oehlmann.
|
||||
# Copyright (c) 2010-2018 by Harald Oehlmann.
|
||||
# Copyright (c) 1998-2000 by Ajuba Solutions.
|
||||
# Copyright (c) 1998 by Mark Harrison.
|
||||
#
|
||||
# See the file "license.terms" for information on usage and redistribution
|
||||
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
|
||||
package require Tcl 8.5-
|
||||
# We use oo::define::self, which is new in Tcl 8.7
|
||||
package require Tcl 8.7-
|
||||
# When the version number changes, be sure to update the pkgIndex.tcl file,
|
||||
# and the installation directory in the Makefiles.
|
||||
package provide msgcat 1.6.1
|
||||
package provide msgcat 1.7.0
|
||||
|
||||
namespace eval msgcat {
|
||||
namespace export mc mcexists mcload mclocale mcmax mcmset mcpreferences mcset\
|
||||
namespace export mc mcn mcexists mcload mclocale mcmax\
|
||||
mcmset mcpreferences mcset\
|
||||
mcunknown mcflset mcflmset mcloadedlocales mcforgetpackage\
|
||||
mcpackageconfig mcpackagelocale
|
||||
mcpackagenamespaceget mcpackageconfig mcpackagelocale mcutil
|
||||
|
||||
# Records the list of locales to search
|
||||
variable Loclist {}
|
||||
@@ -41,7 +43,13 @@ namespace eval msgcat {
|
||||
# namespace should be themselves dict values and the value is
|
||||
# the translated string.
|
||||
variable Msgs [dict create]
|
||||
}
|
||||
|
||||
# create ensemble namespace for mcutil command
|
||||
namespace eval msgcat::mcutil {
|
||||
namespace export getsystemlocale getpreferences
|
||||
namespace ensemble create -prefix 0
|
||||
|
||||
# Map of language codes used in Windows registry to those of ISO-639
|
||||
if {[info sharedlibextension] eq ".dll"} {
|
||||
variable WinRegToISO639 [dict create {*}{
|
||||
@@ -192,10 +200,30 @@ namespace eval msgcat {
|
||||
# Returns the translated string. Propagates errors thrown by the
|
||||
# format command.
|
||||
|
||||
proc msgcat::mc {src args} {
|
||||
# this may be replaced by:
|
||||
# return [mcget -namespace [uplevel 1 [list ::namespace current]] --\
|
||||
# $src {*}$args]
|
||||
proc msgcat::mc {args} {
|
||||
tailcall mcn [PackageNamespaceGet] {*}$args
|
||||
}
|
||||
|
||||
# msgcat::mcn --
|
||||
#
|
||||
# Find the translation for the given string based on the current
|
||||
# locale setting. Check the passed namespace first, then look in each
|
||||
# parent namespace until the source is found. If additional args are
|
||||
# specified, use the format command to work them into the traslated
|
||||
# string.
|
||||
# If no catalog item is found, mcunknown is called in the caller frame
|
||||
# and its result is returned.
|
||||
#
|
||||
# Arguments:
|
||||
# ns Package namespace of the translation
|
||||
# src The string to translate.
|
||||
# args Args to pass to the format command
|
||||
#
|
||||
# Results:
|
||||
# Returns the translated string. Propagates errors thrown by the
|
||||
# format command.
|
||||
|
||||
proc msgcat::mcn {ns src args} {
|
||||
|
||||
# Check for the src in each namespace starting from the local and
|
||||
# ending in the global.
|
||||
@@ -203,7 +231,6 @@ proc msgcat::mc {src args} {
|
||||
variable Msgs
|
||||
variable Loclist
|
||||
|
||||
set ns [uplevel 1 [list ::namespace current]]
|
||||
set loclist [PackagePreferences $ns]
|
||||
|
||||
set nscur $ns
|
||||
@@ -219,7 +246,7 @@ proc msgcat::mc {src args} {
|
||||
# call package local or default unknown command
|
||||
set args [linsert $args 0 [lindex $loclist 0] $src]
|
||||
switch -exact -- [Invoke unknowncmd $args $ns result 1] {
|
||||
0 { return [uplevel 1 [linsert $args 0 [namespace origin mcunknown]]] }
|
||||
0 { tailcall mcunknown {*}$args }
|
||||
1 { return [DefaultUnknown {*}$args] }
|
||||
default { return $result }
|
||||
}
|
||||
@@ -245,23 +272,31 @@ proc msgcat::mcexists {args} {
|
||||
variable Loclist
|
||||
variable PackageConfig
|
||||
|
||||
set ns [uplevel 1 [list ::namespace current]]
|
||||
set loclist [PackagePreferences $ns]
|
||||
|
||||
while {[llength $args] != 1} {
|
||||
set args [lassign $args option]
|
||||
switch -glob -- $option {
|
||||
-exactnamespace { set exactnamespace 1 }
|
||||
-exactlocale { set loclist [lrange $loclist 0 0] }
|
||||
-exactnamespace - -exactlocale { set $option 1 }
|
||||
-namespace {
|
||||
if {[llength $args] < 2} {
|
||||
return -code error\
|
||||
"Argument missing for switch \"-namespace\""
|
||||
}
|
||||
set args [lassign $args ns]
|
||||
}
|
||||
-* { return -code error "unknown option \"$option\"" }
|
||||
default {
|
||||
return -code error "wrong # args: should be\
|
||||
\"[lindex [info level 0] 0] ?-exactnamespace?\
|
||||
?-exactlocale? src\""
|
||||
?-exactlocale? ?-namespace ns? src\""
|
||||
}
|
||||
}
|
||||
}
|
||||
set src [lindex $args 0]
|
||||
|
||||
if {![info exists ns]} { set ns [PackageNamespaceGet] }
|
||||
|
||||
set loclist [PackagePreferences $ns]
|
||||
if {[info exists -exactlocale]} { set loclist [lrange $loclist 0 0] }
|
||||
|
||||
while {$ns ne ""} {
|
||||
foreach loc $loclist {
|
||||
@@ -269,7 +304,7 @@ proc msgcat::mcexists {args} {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if {[info exists exactnamespace]} {return 0}
|
||||
if {[info exists -exactnamespace]} {return 0}
|
||||
set ns [namespace parent $ns]
|
||||
}
|
||||
return 0
|
||||
@@ -303,32 +338,27 @@ proc msgcat::mclocale {args} {
|
||||
return -code error "invalid newLocale value \"$newLocale\":\
|
||||
could be path to unsafe code."
|
||||
}
|
||||
if {[lindex $Loclist 0] ne $newLocale} {
|
||||
set Loclist [GetPreferences $newLocale]
|
||||
|
||||
# locale not loaded jet
|
||||
LoadAll $Loclist
|
||||
# Invoke callback
|
||||
Invoke changecmd $Loclist
|
||||
}
|
||||
mcpreferences {*}[mcutil getpreferences $newLocale]
|
||||
}
|
||||
return [lindex $Loclist 0]
|
||||
}
|
||||
|
||||
# msgcat::GetPreferences --
|
||||
# msgcat::mcutil::getpreferences --
|
||||
#
|
||||
# Get list of locales from a locale.
|
||||
# The first element is always the lowercase locale.
|
||||
# Other elements have one component separated by "_" less.
|
||||
# Multiple "_" are seen as one separator: de__ch_spec de__ch de {}
|
||||
#
|
||||
# This method is part of the ensemble mcutil
|
||||
#
|
||||
# Arguments:
|
||||
# Locale.
|
||||
#
|
||||
# Results:
|
||||
# Locale list
|
||||
|
||||
proc msgcat::GetPreferences {locale} {
|
||||
proc msgcat::mcutil::getpreferences {locale} {
|
||||
set locale [string tolower $locale]
|
||||
set loclist [list $locale]
|
||||
while {-1 !=[set pos [string last "_" $locale]]} {
|
||||
@@ -349,16 +379,51 @@ proc msgcat::GetPreferences {locale} {
|
||||
# most preferred to least preferred.
|
||||
#
|
||||
# Arguments:
|
||||
# None.
|
||||
# New location list
|
||||
#
|
||||
# Results:
|
||||
# Returns an ordered list of the locales preferred by the user.
|
||||
|
||||
proc msgcat::mcpreferences {} {
|
||||
proc msgcat::mcpreferences {args} {
|
||||
variable Loclist
|
||||
|
||||
if {[llength $args] > 0} {
|
||||
# args is the new loclist
|
||||
if {![ListEqualString $args $Loclist]} {
|
||||
set Loclist $args
|
||||
|
||||
# locale not loaded jet
|
||||
LoadAll $Loclist
|
||||
# Invoke callback
|
||||
Invoke changecmd $Loclist
|
||||
}
|
||||
}
|
||||
return $Loclist
|
||||
}
|
||||
|
||||
# msgcat::ListStringEqual --
|
||||
#
|
||||
# Compare two strings for equal string contents
|
||||
#
|
||||
# Arguments:
|
||||
# list1 first list
|
||||
# list2 second list
|
||||
#
|
||||
# Results:
|
||||
# 1 if lists of strings are identical, 0 otherwise
|
||||
|
||||
proc msgcat::ListEqualString {list1 list2} {
|
||||
if {[llength $list1] != [llength $list2]} {
|
||||
return 0
|
||||
}
|
||||
foreach item1 $list1 item2 $list2 {
|
||||
if {$item1 ne $item2} {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
# msgcat::mcloadedlocales --
|
||||
#
|
||||
# Get or change the list of currently loaded default locales
|
||||
@@ -442,7 +507,7 @@ proc msgcat::mcloadedlocales {subcommand} {
|
||||
# Results:
|
||||
# Empty string, if not stated differently for the subcommand
|
||||
|
||||
proc msgcat::mcpackagelocale {subcommand {locale ""}} {
|
||||
proc msgcat::mcpackagelocale {subcommand args} {
|
||||
# todo: implement using an ensemble
|
||||
variable Loclist
|
||||
variable LoadedLocales
|
||||
@@ -450,27 +515,39 @@ proc msgcat::mcpackagelocale {subcommand {locale ""}} {
|
||||
variable PackageConfig
|
||||
# Check option
|
||||
# check if required item is exactly provided
|
||||
if {[llength [info level 0]] == 2} {
|
||||
# locale not given
|
||||
unset locale
|
||||
} else {
|
||||
# locale given
|
||||
if {$subcommand in
|
||||
{"get" "isset" "unset" "preferences" "loaded" "clear"} } {
|
||||
return -code error "wrong # args: should be\
|
||||
\"[lrange [info level 0] 0 1]\""
|
||||
}
|
||||
set locale [string tolower $locale]
|
||||
if { [llength $args] > 0
|
||||
&& $subcommand in {"get" "isset" "unset" "loaded" "clear"} } {
|
||||
return -code error "wrong # args: should be\
|
||||
\"[lrange [info level 0] 0 1]\""
|
||||
}
|
||||
set ns [uplevel 1 {::namespace current}]
|
||||
set ns [PackageNamespaceGet]
|
||||
|
||||
switch -exact -- $subcommand {
|
||||
get { return [lindex [PackagePreferences $ns] 0] }
|
||||
preferences { return [PackagePreferences $ns] }
|
||||
loaded { return [PackageLocales $ns] }
|
||||
present { return [expr {$locale in [PackageLocales $ns]} ]}
|
||||
present {
|
||||
if {[llength $args] != 1} {
|
||||
return -code error "wrong # args: should be\
|
||||
\"[lrange [info level 0] 0 1] locale\""
|
||||
}
|
||||
return [expr {[string tolower [lindex $args 0]]
|
||||
in [PackageLocales $ns]} ]
|
||||
}
|
||||
isset { return [dict exists $PackageConfig loclist $ns] }
|
||||
set { # set a package locale or add a package locale
|
||||
set - preferences {
|
||||
# set a package locale or add a package locale
|
||||
set fSet [expr {$subcommand eq "set"}]
|
||||
|
||||
# Check parameter
|
||||
if {$fSet && 1 < [llength $args] } {
|
||||
return -code error "wrong # args: should be\
|
||||
\"[lrange [info level 0] 0 1] ?locale?\""
|
||||
}
|
||||
|
||||
# > Return preferences if no parameter
|
||||
if {!$fSet && 0 == [llength $args] } {
|
||||
return [PackagePreferences $ns]
|
||||
}
|
||||
|
||||
# Copy the default locale if no package locale set so far
|
||||
if {![dict exists $PackageConfig loclist $ns]} {
|
||||
@@ -478,25 +555,43 @@ proc msgcat::mcpackagelocale {subcommand {locale ""}} {
|
||||
dict set PackageConfig loadedlocales $ns $LoadedLocales
|
||||
}
|
||||
|
||||
# Check if changed
|
||||
set loclist [dict get $PackageConfig loclist $ns]
|
||||
if {! [info exists locale] || $locale eq [lindex $loclist 0] } {
|
||||
return [lindex $loclist 0]
|
||||
# No argument for set: return current package locale
|
||||
# The difference to no argument and subcommand "preferences" is,
|
||||
# that "preferences" does not set the package locale property.
|
||||
# This case is processed above, so no check for fSet here
|
||||
if { 0 == [llength $args] } {
|
||||
return [lindex [dict get $PackageConfig loclist $ns] 0]
|
||||
}
|
||||
|
||||
# Get new loclist
|
||||
if {$fSet} {
|
||||
set loclist [mcutil getpreferences [lindex $args 0]]
|
||||
} else {
|
||||
set loclist $args
|
||||
}
|
||||
|
||||
# Check if not changed to return imediately
|
||||
if { [ListEqualString $loclist\
|
||||
[dict get $PackageConfig loclist $ns]] } {
|
||||
if {$fSet} {
|
||||
return [lindex $loclist 0]
|
||||
}
|
||||
return $loclist
|
||||
}
|
||||
|
||||
# Change loclist
|
||||
set loclist [GetPreferences $locale]
|
||||
set locale [lindex $loclist 0]
|
||||
dict set PackageConfig loclist $ns $loclist
|
||||
|
||||
# load eventual missing locales
|
||||
set loadedLocales [dict get $PackageConfig loadedlocales $ns]
|
||||
if {$locale in $loadedLocales} { return $locale }
|
||||
set loadLocales [ListComplement $loadedLocales $loclist]
|
||||
dict set PackageConfig loadedlocales $ns\
|
||||
[concat $loadedLocales $loadLocales]
|
||||
Load $ns $loadLocales
|
||||
return $locale
|
||||
if {$fSet} {
|
||||
return [lindex $loclist 0]
|
||||
}
|
||||
return $loclist
|
||||
}
|
||||
clear { # Remove all locales not contained in Loclist
|
||||
if {![dict exists $PackageConfig loclist $ns]} {
|
||||
@@ -551,7 +646,7 @@ proc msgcat::mcforgetpackage {} {
|
||||
# todo: this may be implemented using an ensemble
|
||||
variable PackageConfig
|
||||
variable Msgs
|
||||
set ns [uplevel 1 {::namespace current}]
|
||||
set ns [PackageNamespaceGet]
|
||||
# Remove MC items
|
||||
dict unset Msgs $ns
|
||||
# Remove config items
|
||||
@@ -561,6 +656,15 @@ proc msgcat::mcforgetpackage {} {
|
||||
return
|
||||
}
|
||||
|
||||
# msgcat::mcgetmynamespace --
|
||||
#
|
||||
# Return the package namespace of the caller
|
||||
# This consideres to be called from a class or object.
|
||||
|
||||
proc msgcat::mcpackagenamespaceget {} {
|
||||
return [PackageNamespaceGet]
|
||||
}
|
||||
|
||||
# msgcat::mcpackageconfig --
|
||||
#
|
||||
# Get or modify the per caller namespace (e.g. packages) config options.
|
||||
@@ -616,7 +720,7 @@ proc msgcat::mcforgetpackage {} {
|
||||
proc msgcat::mcpackageconfig {subcommand option {value ""}} {
|
||||
variable PackageConfig
|
||||
# get namespace
|
||||
set ns [uplevel 1 {::namespace current}]
|
||||
set ns [PackageNamespaceGet]
|
||||
|
||||
if {$option ni {"mcfolder" "loadcmd" "changecmd" "unknowncmd"}} {
|
||||
return -code error "bad option \"$option\": must be mcfolder, loadcmd,\
|
||||
@@ -756,8 +860,7 @@ proc msgcat::ListComplement {list1 list2 {inlistname ""}} {
|
||||
# Returns the number of message catalogs that were loaded.
|
||||
|
||||
proc msgcat::mcload {langdir} {
|
||||
return [uplevel 1 [list\
|
||||
[namespace origin mcpackageconfig] set mcfolder $langdir]]
|
||||
tailcall mcpackageconfig set mcfolder $langdir
|
||||
}
|
||||
|
||||
# msgcat::LoadAll --
|
||||
@@ -923,7 +1026,7 @@ proc msgcat::mcset {locale src {dest ""}} {
|
||||
set dest $src
|
||||
}
|
||||
|
||||
set ns [uplevel 1 [list ::namespace current]]
|
||||
set ns [PackageNamespaceGet]
|
||||
|
||||
set locale [string tolower $locale]
|
||||
|
||||
@@ -951,7 +1054,7 @@ proc msgcat::mcflset {src {dest ""}} {
|
||||
return -code error "must only be used inside a message catalog loaded\
|
||||
with ::msgcat::mcload"
|
||||
}
|
||||
return [uplevel 1 [list [namespace origin mcset] $FileLocale $src $dest]]
|
||||
tailcall mcset $FileLocale $src $dest
|
||||
}
|
||||
|
||||
# msgcat::mcmset --
|
||||
@@ -975,7 +1078,7 @@ proc msgcat::mcmset {locale pairs} {
|
||||
}
|
||||
|
||||
set locale [string tolower $locale]
|
||||
set ns [uplevel 1 [list ::namespace current]]
|
||||
set ns [PackageNamespaceGet]
|
||||
|
||||
foreach {src dest} $pairs {
|
||||
dict set Msgs $ns $locale $src $dest
|
||||
@@ -1002,7 +1105,7 @@ proc msgcat::mcflmset {pairs} {
|
||||
return -code error "must only be used inside a message catalog loaded\
|
||||
with ::msgcat::mcload"
|
||||
}
|
||||
return [uplevel 1 [list [namespace origin mcmset] $FileLocale $pairs]]
|
||||
tailcal mcmset $FileLocale $pairs
|
||||
}
|
||||
|
||||
# msgcat::mcunknown --
|
||||
@@ -1024,7 +1127,7 @@ proc msgcat::mcflmset {pairs} {
|
||||
# Returns the translated value.
|
||||
|
||||
proc msgcat::mcunknown {args} {
|
||||
return [uplevel 1 [list [namespace origin DefaultUnknown] {*}$args]]
|
||||
tailcall DefaultUnknown {*}$args
|
||||
}
|
||||
|
||||
# msgcat::DefaultUnknown --
|
||||
@@ -1067,8 +1170,9 @@ proc msgcat::DefaultUnknown {locale src args} {
|
||||
|
||||
proc msgcat::mcmax {args} {
|
||||
set max 0
|
||||
set ns [PackageNamespaceGet]
|
||||
foreach string $args {
|
||||
set translated [uplevel 1 [list [namespace origin mc] $string]]
|
||||
set translated [uplevel 1 [list [namespace origin mcn] $ns $string]]
|
||||
set len [string length $translated]
|
||||
if {$len>$max} {
|
||||
set max $len
|
||||
@@ -1079,7 +1183,7 @@ proc msgcat::mcmax {args} {
|
||||
|
||||
# Convert the locale values stored in environment variables to a form
|
||||
# suitable for passing to [mclocale]
|
||||
proc msgcat::ConvertLocale {value} {
|
||||
proc msgcat::mcutil::ConvertLocale {value} {
|
||||
# Assume $value is of form: $language[_$territory][.$codeset][@modifier]
|
||||
# Convert to form: $language[_$territory][_$modifier]
|
||||
#
|
||||
@@ -1106,8 +1210,40 @@ proc msgcat::ConvertLocale {value} {
|
||||
return $ret
|
||||
}
|
||||
|
||||
# helper function to find package namespace of stack-frame -2
|
||||
# There are 4 possibilities:
|
||||
# - called from a proc
|
||||
# - called within a class definition script
|
||||
# - called from an class defined oo object
|
||||
# - called from a classless oo object
|
||||
proc ::msgcat::PackageNamespaceGet {} {
|
||||
uplevel 2 {
|
||||
# Check self namespace to determine environment
|
||||
switch -exact -- [namespace which self] {
|
||||
{::oo::define::self} {
|
||||
# We are within a class definition
|
||||
return [namespace qualifiers [self]]
|
||||
}
|
||||
{::oo::Helpers::self} {
|
||||
# We are within an object
|
||||
set Class [info object class [self]]
|
||||
# Check for classless defined object
|
||||
if {$Class eq {::oo::object}} {
|
||||
return [namespace qualifiers [self]]
|
||||
}
|
||||
# Class defined object
|
||||
return [namespace qualifiers $Class]
|
||||
}
|
||||
default {
|
||||
# Not in object environment
|
||||
return [namespace current]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Initialize the default locale
|
||||
proc msgcat::Init {} {
|
||||
proc msgcat::mcutil::getsystemlocale {} {
|
||||
global env
|
||||
|
||||
#
|
||||
@@ -1115,10 +1251,8 @@ proc msgcat::Init {} {
|
||||
#
|
||||
foreach varName {LC_ALL LC_MESSAGES LANG} {
|
||||
if {[info exists env($varName)] && ("" ne $env($varName))} {
|
||||
if {![catch {
|
||||
mclocale [ConvertLocale $env($varName)]
|
||||
}]} {
|
||||
return
|
||||
if {![catch { ConvertLocale $env($varName) } locale]} {
|
||||
return $locale
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1126,10 +1260,8 @@ proc msgcat::Init {} {
|
||||
# On Darwin, fallback to current CFLocale identifier if available.
|
||||
#
|
||||
if {[info exists ::tcl::mac::locale] && $::tcl::mac::locale ne ""} {
|
||||
if {![catch {
|
||||
mclocale [ConvertLocale $::tcl::mac::locale]
|
||||
}]} {
|
||||
return
|
||||
if {![catch { ConvertLocale $::tcl::mac::locale } locale]} {
|
||||
return $locale
|
||||
}
|
||||
}
|
||||
#
|
||||
@@ -1138,8 +1270,7 @@ proc msgcat::Init {} {
|
||||
#
|
||||
if {([info sharedlibextension] ne ".dll")
|
||||
|| [catch {package require registry}]} {
|
||||
mclocale C
|
||||
return
|
||||
return C
|
||||
}
|
||||
#
|
||||
# On Windows or Cygwin, try to set locale depending on registry
|
||||
@@ -1170,8 +1301,8 @@ proc msgcat::Init {} {
|
||||
if {[dict exists $modifierDict $script]} {
|
||||
append locale @ [dict get $modifierDict $script]
|
||||
}
|
||||
if {![catch {mclocale [ConvertLocale $locale]}]} {
|
||||
return
|
||||
if {![catch {ConvertLocale $locale} locale]} {
|
||||
return $locale
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1180,8 +1311,7 @@ proc msgcat::Init {} {
|
||||
if {[catch {
|
||||
set locale [registry get $key "locale"]
|
||||
}]} {
|
||||
mclocale C
|
||||
return
|
||||
return C
|
||||
}
|
||||
#
|
||||
# Keep trying to match against smaller and smaller suffixes
|
||||
@@ -1196,15 +1326,15 @@ proc msgcat::Init {} {
|
||||
set locale [string tolower $locale]
|
||||
while {[string length $locale]} {
|
||||
if {![catch {
|
||||
mclocale [ConvertLocale [dict get $WinRegToISO639 $locale]]
|
||||
}]} {
|
||||
return
|
||||
ConvertLocale [dict get $WinRegToISO639 $locale]
|
||||
} localeOut]} {
|
||||
return $localeOut
|
||||
}
|
||||
set locale [string range $locale 1 end]
|
||||
}
|
||||
#
|
||||
# No translation known. Fall back on "C" locale
|
||||
#
|
||||
mclocale C
|
||||
return C
|
||||
}
|
||||
msgcat::Init
|
||||
msgcat::mclocale [msgcat::mcutil getsystemlocale]
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
|
||||
package ifneeded msgcat 1.6.1 [list source [file join $dir msgcat.tcl]]
|
||||
if {![package vsatisfies [package provide Tcl] 8.7-]} {return}
|
||||
package ifneeded msgcat 1.7.0 [list source [file join $dir msgcat.tcl]]
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# created by tools/tclZIC.tcl - do not edit
|
||||
if {![info exists TZData(Africa/Abidjan)]} {
|
||||
LoadTimeZoneFile Africa/Abidjan
|
||||
|
||||
set TZData(:Africa/Sao_Tome) {
|
||||
{-9223372036854775808 1616 0 LMT}
|
||||
{-2713912016 -2205 0 LMT}
|
||||
{-1830381795 0 0 GMT}
|
||||
{1514768400 3600 0 WAT}
|
||||
}
|
||||
set TZData(:Africa/Sao_Tome) $TZData(:Africa/Abidjan)
|
||||
|
||||
@@ -91,167 +91,167 @@ set TZData(:America/Campo_Grande) {
|
||||
{1487473200 -14400 0 -04}
|
||||
{1508040000 -10800 1 -03}
|
||||
{1518922800 -14400 0 -04}
|
||||
{1540094400 -10800 1 -03}
|
||||
{1541304000 -10800 1 -03}
|
||||
{1550372400 -14400 0 -04}
|
||||
{1571544000 -10800 1 -03}
|
||||
{1572753600 -10800 1 -03}
|
||||
{1581822000 -14400 0 -04}
|
||||
{1602993600 -10800 1 -03}
|
||||
{1604203200 -10800 1 -03}
|
||||
{1613876400 -14400 0 -04}
|
||||
{1634443200 -10800 1 -03}
|
||||
{1636257600 -10800 1 -03}
|
||||
{1645326000 -14400 0 -04}
|
||||
{1665892800 -10800 1 -03}
|
||||
{1667707200 -10800 1 -03}
|
||||
{1677380400 -14400 0 -04}
|
||||
{1697342400 -10800 1 -03}
|
||||
{1699156800 -10800 1 -03}
|
||||
{1708225200 -14400 0 -04}
|
||||
{1729396800 -10800 1 -03}
|
||||
{1730606400 -10800 1 -03}
|
||||
{1739674800 -14400 0 -04}
|
||||
{1760846400 -10800 1 -03}
|
||||
{1762056000 -10800 1 -03}
|
||||
{1771729200 -14400 0 -04}
|
||||
{1792296000 -10800 1 -03}
|
||||
{1793505600 -10800 1 -03}
|
||||
{1803178800 -14400 0 -04}
|
||||
{1823745600 -10800 1 -03}
|
||||
{1825560000 -10800 1 -03}
|
||||
{1834628400 -14400 0 -04}
|
||||
{1855195200 -10800 1 -03}
|
||||
{1857009600 -10800 1 -03}
|
||||
{1866078000 -14400 0 -04}
|
||||
{1887249600 -10800 1 -03}
|
||||
{1888459200 -10800 1 -03}
|
||||
{1897527600 -14400 0 -04}
|
||||
{1918699200 -10800 1 -03}
|
||||
{1919908800 -10800 1 -03}
|
||||
{1928977200 -14400 0 -04}
|
||||
{1950148800 -10800 1 -03}
|
||||
{1951358400 -10800 1 -03}
|
||||
{1960426800 -14400 0 -04}
|
||||
{1981598400 -10800 1 -03}
|
||||
{1983412800 -10800 1 -03}
|
||||
{1992481200 -14400 0 -04}
|
||||
{2013048000 -10800 1 -03}
|
||||
{2014862400 -10800 1 -03}
|
||||
{2024535600 -14400 0 -04}
|
||||
{2044497600 -10800 1 -03}
|
||||
{2046312000 -10800 1 -03}
|
||||
{2055380400 -14400 0 -04}
|
||||
{2076552000 -10800 1 -03}
|
||||
{2077761600 -10800 1 -03}
|
||||
{2086830000 -14400 0 -04}
|
||||
{2108001600 -10800 1 -03}
|
||||
{2109211200 -10800 1 -03}
|
||||
{2118884400 -14400 0 -04}
|
||||
{2139451200 -10800 1 -03}
|
||||
{2140660800 -10800 1 -03}
|
||||
{2150334000 -14400 0 -04}
|
||||
{2170900800 -10800 1 -03}
|
||||
{2172715200 -10800 1 -03}
|
||||
{2181783600 -14400 0 -04}
|
||||
{2202350400 -10800 1 -03}
|
||||
{2204164800 -10800 1 -03}
|
||||
{2213233200 -14400 0 -04}
|
||||
{2234404800 -10800 1 -03}
|
||||
{2235614400 -10800 1 -03}
|
||||
{2244682800 -14400 0 -04}
|
||||
{2265854400 -10800 1 -03}
|
||||
{2267064000 -10800 1 -03}
|
||||
{2276132400 -14400 0 -04}
|
||||
{2297304000 -10800 1 -03}
|
||||
{2298513600 -10800 1 -03}
|
||||
{2307582000 -14400 0 -04}
|
||||
{2328753600 -10800 1 -03}
|
||||
{2329963200 -10800 1 -03}
|
||||
{2339636400 -14400 0 -04}
|
||||
{2360203200 -10800 1 -03}
|
||||
{2362017600 -10800 1 -03}
|
||||
{2371086000 -14400 0 -04}
|
||||
{2391652800 -10800 1 -03}
|
||||
{2393467200 -10800 1 -03}
|
||||
{2402535600 -14400 0 -04}
|
||||
{2423707200 -10800 1 -03}
|
||||
{2424916800 -10800 1 -03}
|
||||
{2433985200 -14400 0 -04}
|
||||
{2455156800 -10800 1 -03}
|
||||
{2456366400 -10800 1 -03}
|
||||
{2465434800 -14400 0 -04}
|
||||
{2486606400 -10800 1 -03}
|
||||
{2487816000 -10800 1 -03}
|
||||
{2497489200 -14400 0 -04}
|
||||
{2518056000 -10800 1 -03}
|
||||
{2519870400 -10800 1 -03}
|
||||
{2528938800 -14400 0 -04}
|
||||
{2549505600 -10800 1 -03}
|
||||
{2551320000 -10800 1 -03}
|
||||
{2560388400 -14400 0 -04}
|
||||
{2580955200 -10800 1 -03}
|
||||
{2582769600 -10800 1 -03}
|
||||
{2591838000 -14400 0 -04}
|
||||
{2613009600 -10800 1 -03}
|
||||
{2614219200 -10800 1 -03}
|
||||
{2623287600 -14400 0 -04}
|
||||
{2644459200 -10800 1 -03}
|
||||
{2645668800 -10800 1 -03}
|
||||
{2654737200 -14400 0 -04}
|
||||
{2675908800 -10800 1 -03}
|
||||
{2677118400 -10800 1 -03}
|
||||
{2686791600 -14400 0 -04}
|
||||
{2707358400 -10800 1 -03}
|
||||
{2709172800 -10800 1 -03}
|
||||
{2718241200 -14400 0 -04}
|
||||
{2738808000 -10800 1 -03}
|
||||
{2740622400 -10800 1 -03}
|
||||
{2749690800 -14400 0 -04}
|
||||
{2770862400 -10800 1 -03}
|
||||
{2772072000 -10800 1 -03}
|
||||
{2781140400 -14400 0 -04}
|
||||
{2802312000 -10800 1 -03}
|
||||
{2803521600 -10800 1 -03}
|
||||
{2812590000 -14400 0 -04}
|
||||
{2833761600 -10800 1 -03}
|
||||
{2834971200 -10800 1 -03}
|
||||
{2844039600 -14400 0 -04}
|
||||
{2865211200 -10800 1 -03}
|
||||
{2867025600 -10800 1 -03}
|
||||
{2876094000 -14400 0 -04}
|
||||
{2896660800 -10800 1 -03}
|
||||
{2898475200 -10800 1 -03}
|
||||
{2907543600 -14400 0 -04}
|
||||
{2928110400 -10800 1 -03}
|
||||
{2929924800 -10800 1 -03}
|
||||
{2938993200 -14400 0 -04}
|
||||
{2960164800 -10800 1 -03}
|
||||
{2961374400 -10800 1 -03}
|
||||
{2970442800 -14400 0 -04}
|
||||
{2991614400 -10800 1 -03}
|
||||
{2992824000 -10800 1 -03}
|
||||
{3001892400 -14400 0 -04}
|
||||
{3023064000 -10800 1 -03}
|
||||
{3024273600 -10800 1 -03}
|
||||
{3033946800 -14400 0 -04}
|
||||
{3054513600 -10800 1 -03}
|
||||
{3056328000 -10800 1 -03}
|
||||
{3065396400 -14400 0 -04}
|
||||
{3085963200 -10800 1 -03}
|
||||
{3087777600 -10800 1 -03}
|
||||
{3096846000 -14400 0 -04}
|
||||
{3118017600 -10800 1 -03}
|
||||
{3119227200 -10800 1 -03}
|
||||
{3128295600 -14400 0 -04}
|
||||
{3149467200 -10800 1 -03}
|
||||
{3150676800 -10800 1 -03}
|
||||
{3159745200 -14400 0 -04}
|
||||
{3180916800 -10800 1 -03}
|
||||
{3182126400 -10800 1 -03}
|
||||
{3191194800 -14400 0 -04}
|
||||
{3212366400 -10800 1 -03}
|
||||
{3213576000 -10800 1 -03}
|
||||
{3223249200 -14400 0 -04}
|
||||
{3243816000 -10800 1 -03}
|
||||
{3245630400 -10800 1 -03}
|
||||
{3254698800 -14400 0 -04}
|
||||
{3275265600 -10800 1 -03}
|
||||
{3277080000 -10800 1 -03}
|
||||
{3286148400 -14400 0 -04}
|
||||
{3307320000 -10800 1 -03}
|
||||
{3308529600 -10800 1 -03}
|
||||
{3317598000 -14400 0 -04}
|
||||
{3338769600 -10800 1 -03}
|
||||
{3339979200 -10800 1 -03}
|
||||
{3349047600 -14400 0 -04}
|
||||
{3370219200 -10800 1 -03}
|
||||
{3371428800 -10800 1 -03}
|
||||
{3381102000 -14400 0 -04}
|
||||
{3401668800 -10800 1 -03}
|
||||
{3403483200 -10800 1 -03}
|
||||
{3412551600 -14400 0 -04}
|
||||
{3433118400 -10800 1 -03}
|
||||
{3434932800 -10800 1 -03}
|
||||
{3444001200 -14400 0 -04}
|
||||
{3464568000 -10800 1 -03}
|
||||
{3466382400 -10800 1 -03}
|
||||
{3475450800 -14400 0 -04}
|
||||
{3496622400 -10800 1 -03}
|
||||
{3497832000 -10800 1 -03}
|
||||
{3506900400 -14400 0 -04}
|
||||
{3528072000 -10800 1 -03}
|
||||
{3529281600 -10800 1 -03}
|
||||
{3538350000 -14400 0 -04}
|
||||
{3559521600 -10800 1 -03}
|
||||
{3560731200 -10800 1 -03}
|
||||
{3570404400 -14400 0 -04}
|
||||
{3590971200 -10800 1 -03}
|
||||
{3592785600 -10800 1 -03}
|
||||
{3601854000 -14400 0 -04}
|
||||
{3622420800 -10800 1 -03}
|
||||
{3624235200 -10800 1 -03}
|
||||
{3633303600 -14400 0 -04}
|
||||
{3654475200 -10800 1 -03}
|
||||
{3655684800 -10800 1 -03}
|
||||
{3664753200 -14400 0 -04}
|
||||
{3685924800 -10800 1 -03}
|
||||
{3687134400 -10800 1 -03}
|
||||
{3696202800 -14400 0 -04}
|
||||
{3717374400 -10800 1 -03}
|
||||
{3718584000 -10800 1 -03}
|
||||
{3727652400 -14400 0 -04}
|
||||
{3748824000 -10800 1 -03}
|
||||
{3750638400 -10800 1 -03}
|
||||
{3759706800 -14400 0 -04}
|
||||
{3780273600 -10800 1 -03}
|
||||
{3782088000 -10800 1 -03}
|
||||
{3791156400 -14400 0 -04}
|
||||
{3811723200 -10800 1 -03}
|
||||
{3813537600 -10800 1 -03}
|
||||
{3822606000 -14400 0 -04}
|
||||
{3843777600 -10800 1 -03}
|
||||
{3844987200 -10800 1 -03}
|
||||
{3854055600 -14400 0 -04}
|
||||
{3875227200 -10800 1 -03}
|
||||
{3876436800 -10800 1 -03}
|
||||
{3885505200 -14400 0 -04}
|
||||
{3906676800 -10800 1 -03}
|
||||
{3907886400 -10800 1 -03}
|
||||
{3917559600 -14400 0 -04}
|
||||
{3938126400 -10800 1 -03}
|
||||
{3939940800 -10800 1 -03}
|
||||
{3949009200 -14400 0 -04}
|
||||
{3969576000 -10800 1 -03}
|
||||
{3971390400 -10800 1 -03}
|
||||
{3980458800 -14400 0 -04}
|
||||
{4001630400 -10800 1 -03}
|
||||
{4002840000 -10800 1 -03}
|
||||
{4011908400 -14400 0 -04}
|
||||
{4033080000 -10800 1 -03}
|
||||
{4034289600 -10800 1 -03}
|
||||
{4043358000 -14400 0 -04}
|
||||
{4064529600 -10800 1 -03}
|
||||
{4065739200 -10800 1 -03}
|
||||
{4074807600 -14400 0 -04}
|
||||
{4095979200 -10800 1 -03}
|
||||
{4097188800 -10800 1 -03}
|
||||
}
|
||||
|
||||
@@ -91,167 +91,167 @@ set TZData(:America/Cuiaba) {
|
||||
{1487473200 -14400 0 -04}
|
||||
{1508040000 -10800 1 -03}
|
||||
{1518922800 -14400 0 -04}
|
||||
{1540094400 -10800 1 -03}
|
||||
{1541304000 -10800 1 -03}
|
||||
{1550372400 -14400 0 -04}
|
||||
{1571544000 -10800 1 -03}
|
||||
{1572753600 -10800 1 -03}
|
||||
{1581822000 -14400 0 -04}
|
||||
{1602993600 -10800 1 -03}
|
||||
{1604203200 -10800 1 -03}
|
||||
{1613876400 -14400 0 -04}
|
||||
{1634443200 -10800 1 -03}
|
||||
{1636257600 -10800 1 -03}
|
||||
{1645326000 -14400 0 -04}
|
||||
{1665892800 -10800 1 -03}
|
||||
{1667707200 -10800 1 -03}
|
||||
{1677380400 -14400 0 -04}
|
||||
{1697342400 -10800 1 -03}
|
||||
{1699156800 -10800 1 -03}
|
||||
{1708225200 -14400 0 -04}
|
||||
{1729396800 -10800 1 -03}
|
||||
{1730606400 -10800 1 -03}
|
||||
{1739674800 -14400 0 -04}
|
||||
{1760846400 -10800 1 -03}
|
||||
{1762056000 -10800 1 -03}
|
||||
{1771729200 -14400 0 -04}
|
||||
{1792296000 -10800 1 -03}
|
||||
{1793505600 -10800 1 -03}
|
||||
{1803178800 -14400 0 -04}
|
||||
{1823745600 -10800 1 -03}
|
||||
{1825560000 -10800 1 -03}
|
||||
{1834628400 -14400 0 -04}
|
||||
{1855195200 -10800 1 -03}
|
||||
{1857009600 -10800 1 -03}
|
||||
{1866078000 -14400 0 -04}
|
||||
{1887249600 -10800 1 -03}
|
||||
{1888459200 -10800 1 -03}
|
||||
{1897527600 -14400 0 -04}
|
||||
{1918699200 -10800 1 -03}
|
||||
{1919908800 -10800 1 -03}
|
||||
{1928977200 -14400 0 -04}
|
||||
{1950148800 -10800 1 -03}
|
||||
{1951358400 -10800 1 -03}
|
||||
{1960426800 -14400 0 -04}
|
||||
{1981598400 -10800 1 -03}
|
||||
{1983412800 -10800 1 -03}
|
||||
{1992481200 -14400 0 -04}
|
||||
{2013048000 -10800 1 -03}
|
||||
{2014862400 -10800 1 -03}
|
||||
{2024535600 -14400 0 -04}
|
||||
{2044497600 -10800 1 -03}
|
||||
{2046312000 -10800 1 -03}
|
||||
{2055380400 -14400 0 -04}
|
||||
{2076552000 -10800 1 -03}
|
||||
{2077761600 -10800 1 -03}
|
||||
{2086830000 -14400 0 -04}
|
||||
{2108001600 -10800 1 -03}
|
||||
{2109211200 -10800 1 -03}
|
||||
{2118884400 -14400 0 -04}
|
||||
{2139451200 -10800 1 -03}
|
||||
{2140660800 -10800 1 -03}
|
||||
{2150334000 -14400 0 -04}
|
||||
{2170900800 -10800 1 -03}
|
||||
{2172715200 -10800 1 -03}
|
||||
{2181783600 -14400 0 -04}
|
||||
{2202350400 -10800 1 -03}
|
||||
{2204164800 -10800 1 -03}
|
||||
{2213233200 -14400 0 -04}
|
||||
{2234404800 -10800 1 -03}
|
||||
{2235614400 -10800 1 -03}
|
||||
{2244682800 -14400 0 -04}
|
||||
{2265854400 -10800 1 -03}
|
||||
{2267064000 -10800 1 -03}
|
||||
{2276132400 -14400 0 -04}
|
||||
{2297304000 -10800 1 -03}
|
||||
{2298513600 -10800 1 -03}
|
||||
{2307582000 -14400 0 -04}
|
||||
{2328753600 -10800 1 -03}
|
||||
{2329963200 -10800 1 -03}
|
||||
{2339636400 -14400 0 -04}
|
||||
{2360203200 -10800 1 -03}
|
||||
{2362017600 -10800 1 -03}
|
||||
{2371086000 -14400 0 -04}
|
||||
{2391652800 -10800 1 -03}
|
||||
{2393467200 -10800 1 -03}
|
||||
{2402535600 -14400 0 -04}
|
||||
{2423707200 -10800 1 -03}
|
||||
{2424916800 -10800 1 -03}
|
||||
{2433985200 -14400 0 -04}
|
||||
{2455156800 -10800 1 -03}
|
||||
{2456366400 -10800 1 -03}
|
||||
{2465434800 -14400 0 -04}
|
||||
{2486606400 -10800 1 -03}
|
||||
{2487816000 -10800 1 -03}
|
||||
{2497489200 -14400 0 -04}
|
||||
{2518056000 -10800 1 -03}
|
||||
{2519870400 -10800 1 -03}
|
||||
{2528938800 -14400 0 -04}
|
||||
{2549505600 -10800 1 -03}
|
||||
{2551320000 -10800 1 -03}
|
||||
{2560388400 -14400 0 -04}
|
||||
{2580955200 -10800 1 -03}
|
||||
{2582769600 -10800 1 -03}
|
||||
{2591838000 -14400 0 -04}
|
||||
{2613009600 -10800 1 -03}
|
||||
{2614219200 -10800 1 -03}
|
||||
{2623287600 -14400 0 -04}
|
||||
{2644459200 -10800 1 -03}
|
||||
{2645668800 -10800 1 -03}
|
||||
{2654737200 -14400 0 -04}
|
||||
{2675908800 -10800 1 -03}
|
||||
{2677118400 -10800 1 -03}
|
||||
{2686791600 -14400 0 -04}
|
||||
{2707358400 -10800 1 -03}
|
||||
{2709172800 -10800 1 -03}
|
||||
{2718241200 -14400 0 -04}
|
||||
{2738808000 -10800 1 -03}
|
||||
{2740622400 -10800 1 -03}
|
||||
{2749690800 -14400 0 -04}
|
||||
{2770862400 -10800 1 -03}
|
||||
{2772072000 -10800 1 -03}
|
||||
{2781140400 -14400 0 -04}
|
||||
{2802312000 -10800 1 -03}
|
||||
{2803521600 -10800 1 -03}
|
||||
{2812590000 -14400 0 -04}
|
||||
{2833761600 -10800 1 -03}
|
||||
{2834971200 -10800 1 -03}
|
||||
{2844039600 -14400 0 -04}
|
||||
{2865211200 -10800 1 -03}
|
||||
{2867025600 -10800 1 -03}
|
||||
{2876094000 -14400 0 -04}
|
||||
{2896660800 -10800 1 -03}
|
||||
{2898475200 -10800 1 -03}
|
||||
{2907543600 -14400 0 -04}
|
||||
{2928110400 -10800 1 -03}
|
||||
{2929924800 -10800 1 -03}
|
||||
{2938993200 -14400 0 -04}
|
||||
{2960164800 -10800 1 -03}
|
||||
{2961374400 -10800 1 -03}
|
||||
{2970442800 -14400 0 -04}
|
||||
{2991614400 -10800 1 -03}
|
||||
{2992824000 -10800 1 -03}
|
||||
{3001892400 -14400 0 -04}
|
||||
{3023064000 -10800 1 -03}
|
||||
{3024273600 -10800 1 -03}
|
||||
{3033946800 -14400 0 -04}
|
||||
{3054513600 -10800 1 -03}
|
||||
{3056328000 -10800 1 -03}
|
||||
{3065396400 -14400 0 -04}
|
||||
{3085963200 -10800 1 -03}
|
||||
{3087777600 -10800 1 -03}
|
||||
{3096846000 -14400 0 -04}
|
||||
{3118017600 -10800 1 -03}
|
||||
{3119227200 -10800 1 -03}
|
||||
{3128295600 -14400 0 -04}
|
||||
{3149467200 -10800 1 -03}
|
||||
{3150676800 -10800 1 -03}
|
||||
{3159745200 -14400 0 -04}
|
||||
{3180916800 -10800 1 -03}
|
||||
{3182126400 -10800 1 -03}
|
||||
{3191194800 -14400 0 -04}
|
||||
{3212366400 -10800 1 -03}
|
||||
{3213576000 -10800 1 -03}
|
||||
{3223249200 -14400 0 -04}
|
||||
{3243816000 -10800 1 -03}
|
||||
{3245630400 -10800 1 -03}
|
||||
{3254698800 -14400 0 -04}
|
||||
{3275265600 -10800 1 -03}
|
||||
{3277080000 -10800 1 -03}
|
||||
{3286148400 -14400 0 -04}
|
||||
{3307320000 -10800 1 -03}
|
||||
{3308529600 -10800 1 -03}
|
||||
{3317598000 -14400 0 -04}
|
||||
{3338769600 -10800 1 -03}
|
||||
{3339979200 -10800 1 -03}
|
||||
{3349047600 -14400 0 -04}
|
||||
{3370219200 -10800 1 -03}
|
||||
{3371428800 -10800 1 -03}
|
||||
{3381102000 -14400 0 -04}
|
||||
{3401668800 -10800 1 -03}
|
||||
{3403483200 -10800 1 -03}
|
||||
{3412551600 -14400 0 -04}
|
||||
{3433118400 -10800 1 -03}
|
||||
{3434932800 -10800 1 -03}
|
||||
{3444001200 -14400 0 -04}
|
||||
{3464568000 -10800 1 -03}
|
||||
{3466382400 -10800 1 -03}
|
||||
{3475450800 -14400 0 -04}
|
||||
{3496622400 -10800 1 -03}
|
||||
{3497832000 -10800 1 -03}
|
||||
{3506900400 -14400 0 -04}
|
||||
{3528072000 -10800 1 -03}
|
||||
{3529281600 -10800 1 -03}
|
||||
{3538350000 -14400 0 -04}
|
||||
{3559521600 -10800 1 -03}
|
||||
{3560731200 -10800 1 -03}
|
||||
{3570404400 -14400 0 -04}
|
||||
{3590971200 -10800 1 -03}
|
||||
{3592785600 -10800 1 -03}
|
||||
{3601854000 -14400 0 -04}
|
||||
{3622420800 -10800 1 -03}
|
||||
{3624235200 -10800 1 -03}
|
||||
{3633303600 -14400 0 -04}
|
||||
{3654475200 -10800 1 -03}
|
||||
{3655684800 -10800 1 -03}
|
||||
{3664753200 -14400 0 -04}
|
||||
{3685924800 -10800 1 -03}
|
||||
{3687134400 -10800 1 -03}
|
||||
{3696202800 -14400 0 -04}
|
||||
{3717374400 -10800 1 -03}
|
||||
{3718584000 -10800 1 -03}
|
||||
{3727652400 -14400 0 -04}
|
||||
{3748824000 -10800 1 -03}
|
||||
{3750638400 -10800 1 -03}
|
||||
{3759706800 -14400 0 -04}
|
||||
{3780273600 -10800 1 -03}
|
||||
{3782088000 -10800 1 -03}
|
||||
{3791156400 -14400 0 -04}
|
||||
{3811723200 -10800 1 -03}
|
||||
{3813537600 -10800 1 -03}
|
||||
{3822606000 -14400 0 -04}
|
||||
{3843777600 -10800 1 -03}
|
||||
{3844987200 -10800 1 -03}
|
||||
{3854055600 -14400 0 -04}
|
||||
{3875227200 -10800 1 -03}
|
||||
{3876436800 -10800 1 -03}
|
||||
{3885505200 -14400 0 -04}
|
||||
{3906676800 -10800 1 -03}
|
||||
{3907886400 -10800 1 -03}
|
||||
{3917559600 -14400 0 -04}
|
||||
{3938126400 -10800 1 -03}
|
||||
{3939940800 -10800 1 -03}
|
||||
{3949009200 -14400 0 -04}
|
||||
{3969576000 -10800 1 -03}
|
||||
{3971390400 -10800 1 -03}
|
||||
{3980458800 -14400 0 -04}
|
||||
{4001630400 -10800 1 -03}
|
||||
{4002840000 -10800 1 -03}
|
||||
{4011908400 -14400 0 -04}
|
||||
{4033080000 -10800 1 -03}
|
||||
{4034289600 -10800 1 -03}
|
||||
{4043358000 -14400 0 -04}
|
||||
{4064529600 -10800 1 -03}
|
||||
{4065739200 -10800 1 -03}
|
||||
{4074807600 -14400 0 -04}
|
||||
{4095979200 -10800 1 -03}
|
||||
{4097188800 -10800 1 -03}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
set TZData(:America/La_Paz) {
|
||||
{-9223372036854775808 -16356 0 LMT}
|
||||
{-2524505244 -16356 0 CMT}
|
||||
{-1205954844 -12756 1 BOST}
|
||||
{-1205954844 -12756 1 BST}
|
||||
{-1192307244 -14400 0 -04}
|
||||
}
|
||||
|
||||
@@ -92,167 +92,167 @@ set TZData(:America/Sao_Paulo) {
|
||||
{1487469600 -10800 0 -03}
|
||||
{1508036400 -7200 1 -02}
|
||||
{1518919200 -10800 0 -03}
|
||||
{1540090800 -7200 1 -02}
|
||||
{1541300400 -7200 1 -02}
|
||||
{1550368800 -10800 0 -03}
|
||||
{1571540400 -7200 1 -02}
|
||||
{1572750000 -7200 1 -02}
|
||||
{1581818400 -10800 0 -03}
|
||||
{1602990000 -7200 1 -02}
|
||||
{1604199600 -7200 1 -02}
|
||||
{1613872800 -10800 0 -03}
|
||||
{1634439600 -7200 1 -02}
|
||||
{1636254000 -7200 1 -02}
|
||||
{1645322400 -10800 0 -03}
|
||||
{1665889200 -7200 1 -02}
|
||||
{1667703600 -7200 1 -02}
|
||||
{1677376800 -10800 0 -03}
|
||||
{1697338800 -7200 1 -02}
|
||||
{1699153200 -7200 1 -02}
|
||||
{1708221600 -10800 0 -03}
|
||||
{1729393200 -7200 1 -02}
|
||||
{1730602800 -7200 1 -02}
|
||||
{1739671200 -10800 0 -03}
|
||||
{1760842800 -7200 1 -02}
|
||||
{1762052400 -7200 1 -02}
|
||||
{1771725600 -10800 0 -03}
|
||||
{1792292400 -7200 1 -02}
|
||||
{1793502000 -7200 1 -02}
|
||||
{1803175200 -10800 0 -03}
|
||||
{1823742000 -7200 1 -02}
|
||||
{1825556400 -7200 1 -02}
|
||||
{1834624800 -10800 0 -03}
|
||||
{1855191600 -7200 1 -02}
|
||||
{1857006000 -7200 1 -02}
|
||||
{1866074400 -10800 0 -03}
|
||||
{1887246000 -7200 1 -02}
|
||||
{1888455600 -7200 1 -02}
|
||||
{1897524000 -10800 0 -03}
|
||||
{1918695600 -7200 1 -02}
|
||||
{1919905200 -7200 1 -02}
|
||||
{1928973600 -10800 0 -03}
|
||||
{1950145200 -7200 1 -02}
|
||||
{1951354800 -7200 1 -02}
|
||||
{1960423200 -10800 0 -03}
|
||||
{1981594800 -7200 1 -02}
|
||||
{1983409200 -7200 1 -02}
|
||||
{1992477600 -10800 0 -03}
|
||||
{2013044400 -7200 1 -02}
|
||||
{2014858800 -7200 1 -02}
|
||||
{2024532000 -10800 0 -03}
|
||||
{2044494000 -7200 1 -02}
|
||||
{2046308400 -7200 1 -02}
|
||||
{2055376800 -10800 0 -03}
|
||||
{2076548400 -7200 1 -02}
|
||||
{2077758000 -7200 1 -02}
|
||||
{2086826400 -10800 0 -03}
|
||||
{2107998000 -7200 1 -02}
|
||||
{2109207600 -7200 1 -02}
|
||||
{2118880800 -10800 0 -03}
|
||||
{2139447600 -7200 1 -02}
|
||||
{2140657200 -7200 1 -02}
|
||||
{2150330400 -10800 0 -03}
|
||||
{2170897200 -7200 1 -02}
|
||||
{2172711600 -7200 1 -02}
|
||||
{2181780000 -10800 0 -03}
|
||||
{2202346800 -7200 1 -02}
|
||||
{2204161200 -7200 1 -02}
|
||||
{2213229600 -10800 0 -03}
|
||||
{2234401200 -7200 1 -02}
|
||||
{2235610800 -7200 1 -02}
|
||||
{2244679200 -10800 0 -03}
|
||||
{2265850800 -7200 1 -02}
|
||||
{2267060400 -7200 1 -02}
|
||||
{2276128800 -10800 0 -03}
|
||||
{2297300400 -7200 1 -02}
|
||||
{2298510000 -7200 1 -02}
|
||||
{2307578400 -10800 0 -03}
|
||||
{2328750000 -7200 1 -02}
|
||||
{2329959600 -7200 1 -02}
|
||||
{2339632800 -10800 0 -03}
|
||||
{2360199600 -7200 1 -02}
|
||||
{2362014000 -7200 1 -02}
|
||||
{2371082400 -10800 0 -03}
|
||||
{2391649200 -7200 1 -02}
|
||||
{2393463600 -7200 1 -02}
|
||||
{2402532000 -10800 0 -03}
|
||||
{2423703600 -7200 1 -02}
|
||||
{2424913200 -7200 1 -02}
|
||||
{2433981600 -10800 0 -03}
|
||||
{2455153200 -7200 1 -02}
|
||||
{2456362800 -7200 1 -02}
|
||||
{2465431200 -10800 0 -03}
|
||||
{2486602800 -7200 1 -02}
|
||||
{2487812400 -7200 1 -02}
|
||||
{2497485600 -10800 0 -03}
|
||||
{2518052400 -7200 1 -02}
|
||||
{2519866800 -7200 1 -02}
|
||||
{2528935200 -10800 0 -03}
|
||||
{2549502000 -7200 1 -02}
|
||||
{2551316400 -7200 1 -02}
|
||||
{2560384800 -10800 0 -03}
|
||||
{2580951600 -7200 1 -02}
|
||||
{2582766000 -7200 1 -02}
|
||||
{2591834400 -10800 0 -03}
|
||||
{2613006000 -7200 1 -02}
|
||||
{2614215600 -7200 1 -02}
|
||||
{2623284000 -10800 0 -03}
|
||||
{2644455600 -7200 1 -02}
|
||||
{2645665200 -7200 1 -02}
|
||||
{2654733600 -10800 0 -03}
|
||||
{2675905200 -7200 1 -02}
|
||||
{2677114800 -7200 1 -02}
|
||||
{2686788000 -10800 0 -03}
|
||||
{2707354800 -7200 1 -02}
|
||||
{2709169200 -7200 1 -02}
|
||||
{2718237600 -10800 0 -03}
|
||||
{2738804400 -7200 1 -02}
|
||||
{2740618800 -7200 1 -02}
|
||||
{2749687200 -10800 0 -03}
|
||||
{2770858800 -7200 1 -02}
|
||||
{2772068400 -7200 1 -02}
|
||||
{2781136800 -10800 0 -03}
|
||||
{2802308400 -7200 1 -02}
|
||||
{2803518000 -7200 1 -02}
|
||||
{2812586400 -10800 0 -03}
|
||||
{2833758000 -7200 1 -02}
|
||||
{2834967600 -7200 1 -02}
|
||||
{2844036000 -10800 0 -03}
|
||||
{2865207600 -7200 1 -02}
|
||||
{2867022000 -7200 1 -02}
|
||||
{2876090400 -10800 0 -03}
|
||||
{2896657200 -7200 1 -02}
|
||||
{2898471600 -7200 1 -02}
|
||||
{2907540000 -10800 0 -03}
|
||||
{2928106800 -7200 1 -02}
|
||||
{2929921200 -7200 1 -02}
|
||||
{2938989600 -10800 0 -03}
|
||||
{2960161200 -7200 1 -02}
|
||||
{2961370800 -7200 1 -02}
|
||||
{2970439200 -10800 0 -03}
|
||||
{2991610800 -7200 1 -02}
|
||||
{2992820400 -7200 1 -02}
|
||||
{3001888800 -10800 0 -03}
|
||||
{3023060400 -7200 1 -02}
|
||||
{3024270000 -7200 1 -02}
|
||||
{3033943200 -10800 0 -03}
|
||||
{3054510000 -7200 1 -02}
|
||||
{3056324400 -7200 1 -02}
|
||||
{3065392800 -10800 0 -03}
|
||||
{3085959600 -7200 1 -02}
|
||||
{3087774000 -7200 1 -02}
|
||||
{3096842400 -10800 0 -03}
|
||||
{3118014000 -7200 1 -02}
|
||||
{3119223600 -7200 1 -02}
|
||||
{3128292000 -10800 0 -03}
|
||||
{3149463600 -7200 1 -02}
|
||||
{3150673200 -7200 1 -02}
|
||||
{3159741600 -10800 0 -03}
|
||||
{3180913200 -7200 1 -02}
|
||||
{3182122800 -7200 1 -02}
|
||||
{3191191200 -10800 0 -03}
|
||||
{3212362800 -7200 1 -02}
|
||||
{3213572400 -7200 1 -02}
|
||||
{3223245600 -10800 0 -03}
|
||||
{3243812400 -7200 1 -02}
|
||||
{3245626800 -7200 1 -02}
|
||||
{3254695200 -10800 0 -03}
|
||||
{3275262000 -7200 1 -02}
|
||||
{3277076400 -7200 1 -02}
|
||||
{3286144800 -10800 0 -03}
|
||||
{3307316400 -7200 1 -02}
|
||||
{3308526000 -7200 1 -02}
|
||||
{3317594400 -10800 0 -03}
|
||||
{3338766000 -7200 1 -02}
|
||||
{3339975600 -7200 1 -02}
|
||||
{3349044000 -10800 0 -03}
|
||||
{3370215600 -7200 1 -02}
|
||||
{3371425200 -7200 1 -02}
|
||||
{3381098400 -10800 0 -03}
|
||||
{3401665200 -7200 1 -02}
|
||||
{3403479600 -7200 1 -02}
|
||||
{3412548000 -10800 0 -03}
|
||||
{3433114800 -7200 1 -02}
|
||||
{3434929200 -7200 1 -02}
|
||||
{3443997600 -10800 0 -03}
|
||||
{3464564400 -7200 1 -02}
|
||||
{3466378800 -7200 1 -02}
|
||||
{3475447200 -10800 0 -03}
|
||||
{3496618800 -7200 1 -02}
|
||||
{3497828400 -7200 1 -02}
|
||||
{3506896800 -10800 0 -03}
|
||||
{3528068400 -7200 1 -02}
|
||||
{3529278000 -7200 1 -02}
|
||||
{3538346400 -10800 0 -03}
|
||||
{3559518000 -7200 1 -02}
|
||||
{3560727600 -7200 1 -02}
|
||||
{3570400800 -10800 0 -03}
|
||||
{3590967600 -7200 1 -02}
|
||||
{3592782000 -7200 1 -02}
|
||||
{3601850400 -10800 0 -03}
|
||||
{3622417200 -7200 1 -02}
|
||||
{3624231600 -7200 1 -02}
|
||||
{3633300000 -10800 0 -03}
|
||||
{3654471600 -7200 1 -02}
|
||||
{3655681200 -7200 1 -02}
|
||||
{3664749600 -10800 0 -03}
|
||||
{3685921200 -7200 1 -02}
|
||||
{3687130800 -7200 1 -02}
|
||||
{3696199200 -10800 0 -03}
|
||||
{3717370800 -7200 1 -02}
|
||||
{3718580400 -7200 1 -02}
|
||||
{3727648800 -10800 0 -03}
|
||||
{3748820400 -7200 1 -02}
|
||||
{3750634800 -7200 1 -02}
|
||||
{3759703200 -10800 0 -03}
|
||||
{3780270000 -7200 1 -02}
|
||||
{3782084400 -7200 1 -02}
|
||||
{3791152800 -10800 0 -03}
|
||||
{3811719600 -7200 1 -02}
|
||||
{3813534000 -7200 1 -02}
|
||||
{3822602400 -10800 0 -03}
|
||||
{3843774000 -7200 1 -02}
|
||||
{3844983600 -7200 1 -02}
|
||||
{3854052000 -10800 0 -03}
|
||||
{3875223600 -7200 1 -02}
|
||||
{3876433200 -7200 1 -02}
|
||||
{3885501600 -10800 0 -03}
|
||||
{3906673200 -7200 1 -02}
|
||||
{3907882800 -7200 1 -02}
|
||||
{3917556000 -10800 0 -03}
|
||||
{3938122800 -7200 1 -02}
|
||||
{3939937200 -7200 1 -02}
|
||||
{3949005600 -10800 0 -03}
|
||||
{3969572400 -7200 1 -02}
|
||||
{3971386800 -7200 1 -02}
|
||||
{3980455200 -10800 0 -03}
|
||||
{4001626800 -7200 1 -02}
|
||||
{4002836400 -7200 1 -02}
|
||||
{4011904800 -10800 0 -03}
|
||||
{4033076400 -7200 1 -02}
|
||||
{4034286000 -7200 1 -02}
|
||||
{4043354400 -10800 0 -03}
|
||||
{4064526000 -7200 1 -02}
|
||||
{4065735600 -7200 1 -02}
|
||||
{4074804000 -10800 0 -03}
|
||||
{4095975600 -7200 1 -02}
|
||||
{4097185200 -7200 1 -02}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
set TZData(:Asia/Tokyo) {
|
||||
{-9223372036854775808 33539 0 LMT}
|
||||
{-2587712400 32400 0 JST}
|
||||
{-683794800 36000 1 JDT}
|
||||
{-672393600 32400 0 JST}
|
||||
{-654764400 36000 1 JDT}
|
||||
{-640944000 32400 0 JST}
|
||||
{-620290800 36000 1 JDT}
|
||||
{-609494400 32400 0 JST}
|
||||
{-588841200 36000 1 JDT}
|
||||
{-578044800 32400 0 JST}
|
||||
{-683802000 36000 1 JDT}
|
||||
{-672314400 32400 0 JST}
|
||||
{-654771600 36000 1 JDT}
|
||||
{-640864800 32400 0 JST}
|
||||
{-620298000 36000 1 JDT}
|
||||
{-609415200 32400 0 JST}
|
||||
{-588848400 36000 1 JDT}
|
||||
{-577965600 32400 0 JST}
|
||||
}
|
||||
|
||||
+11
-3
@@ -1,8 +1,14 @@
|
||||
[](https://travis-ci.org/libtom/libtommath)
|
||||
# libtommath
|
||||
|
||||
[](https://travis-ci.org/libtom/libtommath)
|
||||
This is the git repository for [LibTomMath](http://www.libtom.net/LibTomMath/), a free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C.
|
||||
|
||||
This is the git repository for [LibTomMath](http://www.libtom.org/), a free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C.
|
||||
## Build Status
|
||||
|
||||
master - [](https://travis-ci.org/libtom/libtommath)
|
||||
|
||||
develop - [](https://travis-ci.org/libtom/libtommath)
|
||||
|
||||
## Summary
|
||||
|
||||
The `develop` branch contains the in-development version. Stable releases are tagged.
|
||||
|
||||
@@ -10,6 +16,8 @@ Documentation is built from the LaTeX file `bn.tex`. There is also limited docum
|
||||
|
||||
The project can be build by using `make`. Along with the usual `make`, `make clean` and `make install`, there are several other build targets, see the makefile for details. There are also makefiles for certain specific platforms.
|
||||
|
||||
## Testing
|
||||
|
||||
Tests are located in `demo/` and can be built in two flavors.
|
||||
* `make test` creates a test binary that is intended to be run against `mtest`. `mtest` can be built with `make mtest` and test execution is done like `./mtest/mtest | ./test`. `mtest` is creating test vectors using an alternative MPI library and `test` is consuming these vectors to verify correct behavior of ltm
|
||||
* `make test_standalone` creates a stand-alone test binary that executes several test routines.
|
||||
|
||||
@@ -27,10 +27,10 @@ static const struct {
|
||||
/* return a char * string for a given code */
|
||||
const char *mp_error_to_string(int code)
|
||||
{
|
||||
int x;
|
||||
size_t x;
|
||||
|
||||
/* scan the lookup table for the given message */
|
||||
for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
|
||||
for (x = 0; x < (sizeof(msgs) / sizeof(msgs[0])); x++) {
|
||||
if (msgs[x].code == code) {
|
||||
return msgs[x].msg;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,12 @@ int fast_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* if one of x,y is zero return an error! */
|
||||
if ((mp_iszero(&x) == MP_YES) || (mp_iszero(&y) == MP_YES)) {
|
||||
res = MP_VAL;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
|
||||
if ((res = mp_copy(&x, &u)) != MP_OKAY) {
|
||||
goto LBL_ERR;
|
||||
@@ -53,7 +59,7 @@ int fast_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
if ((res = mp_copy(&y, &v)) != MP_OKAY) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
mp_set(&D, 1);
|
||||
mp_set(&D, 1uL);
|
||||
|
||||
top:
|
||||
/* 4. while u is even do */
|
||||
@@ -122,7 +128,7 @@ top:
|
||||
/* now a = C, b = D, gcd == g*v */
|
||||
|
||||
/* if v != 1 then there is no inverse */
|
||||
if (mp_cmp_d(&v, 1) != MP_EQ) {
|
||||
if (mp_cmp_d(&v, 1uL) != MP_EQ) {
|
||||
res = MP_VAL;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ int fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho)
|
||||
int ix, res, olduse;
|
||||
mp_word W[MP_WARRAY];
|
||||
|
||||
if (x->used > (int)MP_WARRAY) {
|
||||
return MP_VAL;
|
||||
}
|
||||
|
||||
/* get old used count */
|
||||
olduse = x->used;
|
||||
|
||||
@@ -73,7 +77,7 @@ int fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho)
|
||||
* that W[ix-1] have the carry cleared (see after the inner loop)
|
||||
*/
|
||||
mp_digit mu;
|
||||
mu = (mp_digit)(((W[ix] & MP_MASK) * rho) & MP_MASK);
|
||||
mu = ((W[ix] & MP_MASK) * rho) & MP_MASK;
|
||||
|
||||
/* a = a + mu * m * b**i
|
||||
*
|
||||
@@ -102,12 +106,12 @@ int fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho)
|
||||
|
||||
/* inner loop */
|
||||
for (iy = 0; iy < n->used; iy++) {
|
||||
*_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
|
||||
*_W++ += (mp_word)mu * (mp_word)*tmpn++;
|
||||
}
|
||||
}
|
||||
|
||||
/* now fix carry for next digit, W[ix+1] */
|
||||
W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
|
||||
W[ix + 1] += W[ix] >> (mp_word)DIGIT_BIT;
|
||||
}
|
||||
|
||||
/* now we have to propagate the carries and
|
||||
@@ -127,7 +131,7 @@ int fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho)
|
||||
_W = W + ++ix;
|
||||
|
||||
for (; ix <= ((n->used * 2) + 1); ix++) {
|
||||
*_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
|
||||
*_W++ += *_W1++ >> (mp_word)DIGIT_BIT;
|
||||
}
|
||||
|
||||
/* copy out, A = A/b**n
|
||||
@@ -144,7 +148,7 @@ int fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho)
|
||||
_W = W + n->used;
|
||||
|
||||
for (ix = 0; ix < (n->used + 1); ix++) {
|
||||
*tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
|
||||
*tmpx++ = *_W++ & (mp_word)MP_MASK;
|
||||
}
|
||||
|
||||
/* zero oldused digits, if the input a was larger than
|
||||
|
||||
@@ -69,15 +69,15 @@ int fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
|
||||
|
||||
/* execute loop */
|
||||
for (iz = 0; iz < iy; ++iz) {
|
||||
_W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
|
||||
_W += (mp_word)*tmpx++ * (mp_word)*tmpy--;
|
||||
|
||||
}
|
||||
|
||||
/* store term */
|
||||
W[ix] = ((mp_digit)_W) & MP_MASK;
|
||||
W[ix] = (mp_digit)_W & MP_MASK;
|
||||
|
||||
/* make next carry */
|
||||
_W = _W >> ((mp_word)DIGIT_BIT);
|
||||
_W = _W >> (mp_word)DIGIT_BIT;
|
||||
}
|
||||
|
||||
/* setup dest */
|
||||
@@ -87,7 +87,7 @@ int fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
|
||||
{
|
||||
mp_digit *tmpc;
|
||||
tmpc = c->dp;
|
||||
for (ix = 0; ix < (pa + 1); ix++) {
|
||||
for (ix = 0; ix < pa; ix++) {
|
||||
/* now extract the previous digit [below the carry] */
|
||||
*tmpc++ = W[ix];
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@ int fast_s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int dig
|
||||
|
||||
/* execute loop */
|
||||
for (iz = 0; iz < iy; iz++) {
|
||||
_W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
|
||||
_W += (mp_word)*tmpx++ * (mp_word)*tmpy--;
|
||||
}
|
||||
|
||||
/* store term */
|
||||
W[ix] = ((mp_digit)_W) & MP_MASK;
|
||||
W[ix] = (mp_digit)_W & MP_MASK;
|
||||
|
||||
/* make next carry */
|
||||
_W = _W >> ((mp_word)DIGIT_BIT);
|
||||
_W = _W >> (mp_word)DIGIT_BIT;
|
||||
}
|
||||
|
||||
/* setup dest */
|
||||
|
||||
@@ -70,22 +70,22 @@ int fast_s_mp_sqr(const mp_int *a, mp_int *b)
|
||||
|
||||
/* execute loop */
|
||||
for (iz = 0; iz < iy; iz++) {
|
||||
_W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
|
||||
_W += (mp_word)*tmpx++ * (mp_word)*tmpy--;
|
||||
}
|
||||
|
||||
/* double the inner product and add carry */
|
||||
_W = _W + _W + W1;
|
||||
|
||||
/* even columns have the square term in them */
|
||||
if ((ix&1) == 0) {
|
||||
_W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
|
||||
if (((unsigned)ix & 1u) == 0u) {
|
||||
_W += (mp_word)a->dp[ix>>1] * (mp_word)a->dp[ix>>1];
|
||||
}
|
||||
|
||||
/* store it */
|
||||
W[ix] = (mp_digit)(_W & MP_MASK);
|
||||
W[ix] = _W & MP_MASK;
|
||||
|
||||
/* make next carry */
|
||||
W1 = _W >> ((mp_word)DIGIT_BIT);
|
||||
W1 = _W >> (mp_word)DIGIT_BIT;
|
||||
}
|
||||
|
||||
/* setup dest */
|
||||
|
||||
@@ -36,7 +36,7 @@ int mp_2expt(mp_int *a, int b)
|
||||
a->used = (b / DIGIT_BIT) + 1;
|
||||
|
||||
/* put the single bit in its place */
|
||||
a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
|
||||
a->dp[b / DIGIT_BIT] = (mp_digit)1 << (mp_digit)(b % DIGIT_BIT);
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ void mp_clamp(mp_int *a)
|
||||
/* decrease used while the most significant digit is
|
||||
* zero.
|
||||
*/
|
||||
while ((a->used > 0) && (a->dp[a->used - 1] == 0)) {
|
||||
while ((a->used > 0) && (a->dp[a->used - 1] == 0u)) {
|
||||
--(a->used);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*
|
||||
* Tom St Denis, tstdenis82@gmail.com, http://libtom.org
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void mp_clear_multi(mp_int *mp, ...)
|
||||
|
||||
@@ -31,17 +31,17 @@ int mp_cnt_lsb(const mp_int *a)
|
||||
}
|
||||
|
||||
/* scan lower digits until non-zero */
|
||||
for (x = 0; (x < a->used) && (a->dp[x] == 0); x++) {}
|
||||
for (x = 0; (x < a->used) && (a->dp[x] == 0u); x++) {}
|
||||
q = a->dp[x];
|
||||
x *= DIGIT_BIT;
|
||||
|
||||
/* now scan this digit until a 1 is found */
|
||||
if ((q & 1) == 0) {
|
||||
if ((q & 1u) == 0u) {
|
||||
do {
|
||||
qq = q & 15;
|
||||
qq = q & 15u;
|
||||
x += lnz[qq];
|
||||
q >>= 4;
|
||||
} while (qq == 0);
|
||||
} while (qq == 0u);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ int mp_count_bits(const mp_int *a)
|
||||
|
||||
/* take the last digit and count the bits in it */
|
||||
q = a->dp[a->used - 1];
|
||||
while (q > ((mp_digit) 0)) {
|
||||
while (q > (mp_digit)0) {
|
||||
++r;
|
||||
q >>= ((mp_digit) 1);
|
||||
q >>= (mp_digit)1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
+15
-15
@@ -47,7 +47,7 @@ int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
|
||||
}
|
||||
|
||||
|
||||
mp_set(&tq, 1);
|
||||
mp_set(&tq, 1uL);
|
||||
n = mp_count_bits(a) - mp_count_bits(b);
|
||||
if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
|
||||
((res = mp_abs(b, &tb)) != MP_OKAY) ||
|
||||
@@ -150,8 +150,8 @@ int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
|
||||
|
||||
/* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
|
||||
norm = mp_count_bits(&y) % DIGIT_BIT;
|
||||
if (norm < (int)(DIGIT_BIT-1)) {
|
||||
norm = (DIGIT_BIT-1) - norm;
|
||||
if (norm < (DIGIT_BIT - 1)) {
|
||||
norm = (DIGIT_BIT - 1) - norm;
|
||||
if ((res = mp_mul_2d(&x, norm, &x)) != MP_OKAY) {
|
||||
goto LBL_Y;
|
||||
}
|
||||
@@ -190,16 +190,16 @@ int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
|
||||
/* step 3.1 if xi == yt then set q{i-t-1} to b-1,
|
||||
* otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
|
||||
if (x.dp[i] == y.dp[t]) {
|
||||
q.dp[(i - t) - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
|
||||
q.dp[(i - t) - 1] = ((mp_digit)1 << (mp_digit)DIGIT_BIT) - (mp_digit)1;
|
||||
} else {
|
||||
mp_word tmp;
|
||||
tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
|
||||
tmp |= ((mp_word) x.dp[i - 1]);
|
||||
tmp /= ((mp_word) y.dp[t]);
|
||||
if (tmp > (mp_word) MP_MASK) {
|
||||
tmp = (mp_word)x.dp[i] << (mp_word)DIGIT_BIT;
|
||||
tmp |= (mp_word)x.dp[i - 1];
|
||||
tmp /= (mp_word)y.dp[t];
|
||||
if (tmp > (mp_word)MP_MASK) {
|
||||
tmp = MP_MASK;
|
||||
}
|
||||
q.dp[(i - t) - 1] = (mp_digit)(tmp & (mp_word)(MP_MASK));
|
||||
q.dp[(i - t) - 1] = (mp_digit)(tmp & (mp_word)MP_MASK);
|
||||
}
|
||||
|
||||
/* while (q{i-t-1} * (yt * b + y{t-1})) >
|
||||
@@ -207,13 +207,13 @@ int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
|
||||
|
||||
do q{i-t-1} -= 1;
|
||||
*/
|
||||
q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1) & MP_MASK;
|
||||
q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1uL) & (mp_digit)MP_MASK;
|
||||
do {
|
||||
q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1) & MP_MASK;
|
||||
q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & (mp_digit)MP_MASK;
|
||||
|
||||
/* find left hand */
|
||||
mp_zero(&t1);
|
||||
t1.dp[0] = ((t - 1) < 0) ? 0 : y.dp[t - 1];
|
||||
t1.dp[0] = ((t - 1) < 0) ? 0u : y.dp[t - 1];
|
||||
t1.dp[1] = y.dp[t];
|
||||
t1.used = 2;
|
||||
if ((res = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) {
|
||||
@@ -221,8 +221,8 @@ int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
|
||||
}
|
||||
|
||||
/* find right hand */
|
||||
t2.dp[0] = ((i - 2) < 0) ? 0 : x.dp[i - 2];
|
||||
t2.dp[1] = ((i - 1) < 0) ? 0 : x.dp[i - 1];
|
||||
t2.dp[0] = ((i - 2) < 0) ? 0u : x.dp[i - 2];
|
||||
t2.dp[1] = ((i - 1) < 0) ? 0u : x.dp[i - 1];
|
||||
t2.dp[2] = x.dp[i];
|
||||
t2.used = 3;
|
||||
} while (mp_cmp_mag(&t1, &t2) == MP_GT);
|
||||
@@ -252,7 +252,7 @@ int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
|
||||
goto LBL_Y;
|
||||
}
|
||||
|
||||
q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1UL) & MP_MASK;
|
||||
q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & MP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ int mp_div_2(const mp_int *a, mp_int *b)
|
||||
r = 0;
|
||||
for (x = b->used - 1; x >= 0; x--) {
|
||||
/* get the carry for the next iteration */
|
||||
rr = *tmpa & 1;
|
||||
rr = *tmpa & 1u;
|
||||
|
||||
/* shift the current digit, add in carry and store */
|
||||
*tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
|
||||
|
||||
@@ -44,20 +44,20 @@ int mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d)
|
||||
}
|
||||
|
||||
/* shift by as many digits in the bit count */
|
||||
if (b >= (int)DIGIT_BIT) {
|
||||
if (b >= DIGIT_BIT) {
|
||||
mp_rshd(c, b / DIGIT_BIT);
|
||||
}
|
||||
|
||||
/* shift any bit count < DIGIT_BIT */
|
||||
D = (mp_digit)(b % DIGIT_BIT);
|
||||
if (D != 0) {
|
||||
if (D != 0u) {
|
||||
mp_digit *tmpc, mask, shift;
|
||||
|
||||
/* mask */
|
||||
mask = (((mp_digit)1) << D) - 1;
|
||||
mask = ((mp_digit)1 << D) - 1uL;
|
||||
|
||||
/* shift for lsb */
|
||||
shift = DIGIT_BIT - D;
|
||||
shift = (mp_digit)DIGIT_BIT - D;
|
||||
|
||||
/* alias */
|
||||
tmpc = c->dp + (c->used - 1);
|
||||
|
||||
@@ -24,7 +24,7 @@ int mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
|
||||
int res, ix;
|
||||
|
||||
/* b = 2**DIGIT_BIT / 3 */
|
||||
b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
|
||||
b = ((mp_word)1 << (mp_word)DIGIT_BIT) / (mp_word)3;
|
||||
|
||||
if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
|
||||
return res;
|
||||
@@ -34,11 +34,11 @@ int mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
|
||||
q.sign = a->sign;
|
||||
w = 0;
|
||||
for (ix = a->used - 1; ix >= 0; ix--) {
|
||||
w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
|
||||
w = (w << (mp_word)DIGIT_BIT) | (mp_word)a->dp[ix];
|
||||
|
||||
if (w >= 3) {
|
||||
if (w >= 3u) {
|
||||
/* multiply w by [1/3] */
|
||||
t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
|
||||
t = (w * (mp_word)b) >> (mp_word)DIGIT_BIT;
|
||||
|
||||
/* now subtract 3 * [w/3] from w, to get the remainder */
|
||||
w -= t+t+t;
|
||||
@@ -46,9 +46,9 @@ int mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
|
||||
/* fixup the remainder as required since
|
||||
* the optimization is not exact.
|
||||
*/
|
||||
while (w >= 3) {
|
||||
t += 1;
|
||||
w -= 3;
|
||||
while (w >= 3u) {
|
||||
t += 1u;
|
||||
w -= 3u;
|
||||
}
|
||||
} else {
|
||||
t = 0;
|
||||
|
||||
@@ -24,12 +24,12 @@ int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
|
||||
int res, ix;
|
||||
|
||||
/* cannot divide by zero */
|
||||
if (b == 0) {
|
||||
if (b == 0u) {
|
||||
return MP_VAL;
|
||||
}
|
||||
|
||||
/* quick outs */
|
||||
if ((b == 1) || (mp_iszero(a) == MP_YES)) {
|
||||
if ((b == 1u) || (mp_iszero(a) == MP_YES)) {
|
||||
if (d != NULL) {
|
||||
*d = 0;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
|
||||
}
|
||||
}
|
||||
if (d != NULL) {
|
||||
*d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
|
||||
*d = a->dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL);
|
||||
}
|
||||
if (c != NULL) {
|
||||
return mp_div_2d(a, ix, c, NULL);
|
||||
@@ -57,7 +57,7 @@ int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
|
||||
|
||||
#ifdef BN_MP_DIV_3_C
|
||||
/* three? */
|
||||
if (b == 3) {
|
||||
if (b == 3u) {
|
||||
return mp_div_3(a, c, d);
|
||||
}
|
||||
#endif
|
||||
@@ -71,15 +71,15 @@ int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
|
||||
q.sign = a->sign;
|
||||
w = 0;
|
||||
for (ix = a->used - 1; ix >= 0; ix--) {
|
||||
w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
|
||||
w = (w << (mp_word)DIGIT_BIT) | (mp_word)a->dp[ix];
|
||||
|
||||
if (w >= b) {
|
||||
t = (mp_digit)(w / b);
|
||||
w -= ((mp_word)t) * ((mp_word)b);
|
||||
w -= (mp_word)t * (mp_word)b;
|
||||
} else {
|
||||
t = 0;
|
||||
}
|
||||
q.dp[ix] = (mp_digit)t;
|
||||
q.dp[ix] = t;
|
||||
}
|
||||
|
||||
if (d != NULL) {
|
||||
|
||||
@@ -61,7 +61,7 @@ top:
|
||||
|
||||
/* compute (x mod B**m) + k * [x/B**m] inline and inplace */
|
||||
for (i = 0; i < m; i++) {
|
||||
r = (((mp_word)*tmpx2++) * (mp_word)k) + *tmpx1 + mu;
|
||||
r = ((mp_word)*tmpx2++ * (mp_word)k) + *tmpx1 + mu;
|
||||
*tmpx1++ = (mp_digit)(r & MP_MASK);
|
||||
mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ void mp_dr_setup(const mp_int *a, mp_digit *d)
|
||||
/* the casts are required if DIGIT_BIT is one less than
|
||||
* the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
|
||||
*/
|
||||
*d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - ((mp_word)a->dp[0]));
|
||||
*d = (mp_digit)(((mp_word)1 << (mp_word)DIGIT_BIT) - (mp_word)a->dp[0]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user