Compare commits
609
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f62be3a217 | ||
|
|
e7582d10c6 | ||
|
|
5064777d16 | ||
|
|
5b74714749 | ||
|
|
15a7950c9e | ||
|
|
c925a86988 | ||
|
|
75ecb090c6 | ||
|
|
b8e5e2909e | ||
|
|
fd6a064ee7 | ||
|
|
6881a1a274 | ||
|
|
b0fe49c36d | ||
|
|
a52f0db3e4 | ||
|
|
4bf8f43b3a | ||
|
|
d45863129f | ||
|
|
1b28405773 | ||
|
|
65703d1f87 | ||
|
|
f75f76c9d4 | ||
|
|
f5ea63343e | ||
|
|
a708ae2da2 | ||
|
|
d4e73bcab5 | ||
|
|
8f339500a2 | ||
|
|
bf01a303da | ||
|
|
99d940211c | ||
|
|
7b8b406719 | ||
|
|
db3273f346 | ||
|
|
c659b044b1 | ||
|
|
3e55dbb18c | ||
|
|
b2446d8d41 | ||
|
|
e86e8a501d | ||
|
|
d03a4dcc88 | ||
|
|
4ce5b276eb | ||
|
|
877e9d6b11 | ||
|
|
413fe66650 | ||
|
|
ca70072a99 | ||
|
|
d9f2bf1d17 | ||
|
|
c2846c0f5c | ||
|
|
a15279ffd1 | ||
|
|
b74f59a5b4 | ||
|
|
e08c86934d | ||
|
|
a3dfc55957 | ||
|
|
e3f7bc2783 | ||
|
|
564b991088 | ||
|
|
0ff317501d | ||
|
|
f42f0060be | ||
|
|
3ec5b35deb | ||
|
|
7afc6b1c17 | ||
|
|
ce58cdff9f | ||
|
|
999252be01 | ||
|
|
4b9e6d92be | ||
|
|
e28f1eece4 | ||
|
|
6c1107a3e6 | ||
|
|
4ce83fdb43 | ||
|
|
ce32fdecb2 | ||
|
|
105a61c09b | ||
|
|
25b97a7df9 | ||
|
|
432e75210f | ||
|
|
595e613479 | ||
|
|
c0e413055e | ||
|
|
11719ccf59 | ||
|
|
7c7a396fc5 | ||
|
|
7aafa756ac | ||
|
|
6d8b0c705f | ||
|
|
faaf0a0fe6 | ||
|
|
07bcf919d6 | ||
|
|
f70c0ac860 | ||
|
|
97d25d7902 | ||
|
|
c3d5808cdd | ||
|
|
187a67149b | ||
|
|
2d65cb7514 | ||
|
|
92a05930af | ||
|
|
1ef0babc38 | ||
|
|
92265d56a3 | ||
|
|
4264a4f6ab | ||
|
|
a95a7dd265 | ||
|
|
f385fd1b73 | ||
|
|
2e9194366a | ||
|
|
ce72664606 | ||
|
|
5210283d10 | ||
|
|
0eb18d8f91 | ||
|
|
29be40bf89 | ||
|
|
e6336bb806 | ||
|
|
a04094e9a5 | ||
|
|
922d8a71a5 | ||
|
|
13d9910fd6 | ||
|
|
277f101d7f | ||
|
|
a50a381b04 | ||
|
|
e513ec3916 | ||
|
|
89fcfadbbf | ||
|
|
89ce4defb5 | ||
|
|
ad9bc7297d | ||
|
|
0079285837 | ||
|
|
8ccd8d10ef | ||
|
|
aedd652645 | ||
|
|
4056a4dc4b | ||
|
|
ffaeeeddaa | ||
|
|
c2982f8f62 | ||
|
|
587206a660 | ||
|
|
545f5e64be | ||
|
|
385b618c74 | ||
|
|
3a07a6d26f | ||
|
|
df9ea61fbf | ||
|
|
5f7ca471e4 | ||
|
|
ac8ddf5d4a | ||
|
|
664774bec4 | ||
|
|
3cf11a1ce9 | ||
|
|
6da97c627b | ||
|
|
735ca3d3a8 | ||
|
|
72396a1929 | ||
|
|
816674cdb7 | ||
|
|
6bcfd54d3a | ||
|
|
bb331bf1d8 | ||
|
|
b095f046e6 | ||
|
|
cee94b0658 | ||
|
|
f94f5914a8 | ||
|
|
9dd9b629b3 | ||
|
|
440dbbf620 | ||
|
|
b1243f2603 | ||
|
|
f553fe3b01 | ||
|
|
457f43e25b | ||
|
|
578eeb06bc | ||
|
|
515f0f32c0 | ||
|
|
bcb9c34521 | ||
|
|
af0816e0ca | ||
|
|
ac0fdb5bf8 | ||
|
|
2ee7180448 | ||
|
|
5541cc57f7 | ||
|
|
692ea37c40 | ||
|
|
58dd15c51d | ||
|
|
d0996f3402 | ||
|
|
39356c4079 | ||
|
|
a646f081bc | ||
|
|
89f6884455 | ||
|
|
45cf14ed03 | ||
|
|
5314bbe0ef | ||
|
|
5b2c81a0f3 | ||
|
|
f242dd36bd | ||
|
|
fb2aa596ab | ||
|
|
5621809b18 | ||
|
|
7a8a4b15c4 | ||
|
|
f4615ea166 | ||
|
|
2bd7095b87 | ||
|
|
400f9d27f5 | ||
|
|
5d68b7ef56 | ||
|
|
ba387de8cd | ||
|
|
70d12096d5 | ||
|
|
3dedad17ed | ||
|
|
a9c238476a | ||
|
|
cfafc391f2 | ||
|
|
0fbade1cf8 | ||
|
|
dd54301fb6 | ||
|
|
6352a07912 | ||
|
|
440f85800c | ||
|
|
2a11adb848 | ||
|
|
77f95f38bf | ||
|
|
2710235273 | ||
|
|
042e99227a | ||
|
|
64c9b509b0 | ||
|
|
d39c33303f | ||
|
|
6454bee19b | ||
|
|
45175dd264 | ||
|
|
9983a05a80 | ||
|
|
20b4459b9d | ||
|
|
c488b70a47 | ||
|
|
952acc3754 | ||
|
|
73f548527a | ||
|
|
3923106cf7 | ||
|
|
17711009b6 | ||
|
|
b3bda726c1 | ||
|
|
e1b4ae0798 | ||
|
|
aca86a46ff | ||
|
|
94754be1d7 | ||
|
|
9ddb31d522 | ||
|
|
6123ba004c | ||
|
|
56ea73145f | ||
|
|
bc4db4d40e | ||
|
|
0f0ca3d932 | ||
|
|
2cdd3134ab | ||
|
|
107760e1da | ||
|
|
d453cdacec | ||
|
|
e8d9fe8ebe | ||
|
|
6168d91b0e | ||
|
|
ad34457a54 | ||
|
|
2712a556fb | ||
|
|
8da19c6dbd | ||
|
|
3f2eb64de8 | ||
|
|
4b81f6ff43 | ||
|
|
cc72d116bd | ||
|
|
94b635d569 | ||
|
|
de1c1f0f47 | ||
|
|
a4f7145579 | ||
|
|
bbcbd64e3b | ||
|
|
36d9205d97 | ||
|
|
7673d614a9 | ||
|
|
c348386388 | ||
|
|
878c874975 | ||
|
|
b796f3dee7 | ||
|
|
dd96539335 | ||
|
|
23ab25afdc | ||
|
|
192d5ccf32 | ||
|
|
9ce3a23afe | ||
|
|
c2e241f3cd | ||
|
|
9562ecd7fa | ||
|
|
16f3f234e8 | ||
|
|
fbfe81cc7b | ||
|
|
73a3dfdeea | ||
|
|
4cf238f3c3 | ||
|
|
e80e320d34 | ||
|
|
1b667ef114 | ||
|
|
0aa0da515c | ||
|
|
5667bb5f8e | ||
|
|
f8bc248cc3 | ||
|
|
b0146fbd50 | ||
|
|
615771f0b6 | ||
|
|
8d78b23f96 | ||
|
|
fab7d970af | ||
|
|
617e92d7b4 | ||
|
|
7edce7686e | ||
|
|
3d8a0152af | ||
|
|
cb68061d12 | ||
|
|
5c4bb0f4e9 | ||
|
|
f165025992 | ||
|
|
8129d3e1c3 | ||
|
|
3cdd3064b5 | ||
|
|
708ca98ace | ||
|
|
f5f03750c8 | ||
|
|
901f58f13b | ||
|
|
c688e0737c | ||
|
|
21dfa74b03 | ||
|
|
3f0e8d6265 | ||
|
|
ee5e6d9bfc | ||
|
|
aaca962ffe | ||
|
|
fcd399d49a | ||
|
|
ca9d6593d1 | ||
|
|
4a9ae53836 | ||
|
|
60c071ed62 | ||
|
|
bbb13bf577 | ||
|
|
c05da96a35 | ||
|
|
73b3bf53ad | ||
|
|
777941e35b | ||
|
|
e06e0c8625 | ||
|
|
ece8767c5c | ||
|
|
b63d3d703e | ||
|
|
a59ccae461 | ||
|
|
18315c5b5c | ||
|
|
c922cc78a8 | ||
|
|
9220ca224b | ||
|
|
2da0c8192d | ||
|
|
3be2fece8c | ||
|
|
e5726b4339 | ||
|
|
919fc57599 | ||
|
|
5badb6535f | ||
|
|
cf0cf6ad90 | ||
|
|
b86c884286 | ||
|
|
f3ea991996 | ||
|
|
8a90be9a10 | ||
|
|
14949f27a3 | ||
|
|
c571887777 | ||
|
|
f100bae746 | ||
|
|
4db003c2bf | ||
|
|
62e71e311e | ||
|
|
df664778c8 | ||
|
|
82ddcc716b | ||
|
|
2f9e40fef1 | ||
|
|
34189452da | ||
|
|
8b5d3394c2 | ||
|
|
2a5ae4319f | ||
|
|
246869993a | ||
|
|
dea5aab977 | ||
|
|
8bdc794177 | ||
|
|
993aa1b338 | ||
|
|
c3077bd013 | ||
|
|
02d6d68a68 | ||
|
|
c6484de085 | ||
|
|
dcc8bd9aa8 | ||
|
|
5d20272000 | ||
|
|
0adb50f88b | ||
|
|
a6c79230c3 | ||
|
|
0ec19f6b11 | ||
|
|
d6de0fb46b | ||
|
|
6b33bdad03 | ||
|
|
5171d6b4ef | ||
|
|
39a388f035 | ||
|
|
ea1ae51d2d | ||
|
|
95d531e781 | ||
|
|
1ea7d20306 | ||
|
|
0cdf2fd457 | ||
|
|
5202a013d2 | ||
|
|
f9abf9b060 | ||
|
|
2eaa3d3c8d | ||
|
|
19b2d40089 | ||
|
|
ba8e7c4211 | ||
|
|
3fe213e031 | ||
|
|
d9b0bec7d6 | ||
|
|
a021af135e | ||
|
|
ee3d72e1e1 | ||
|
|
2752a9f58b | ||
|
|
a73818d8b6 | ||
|
|
0d218fca03 | ||
|
|
2130fd8582 | ||
|
|
f32ecd5894 | ||
|
|
1ed15145a6 | ||
|
|
46f75926ff | ||
|
|
f9d42ebf8c | ||
|
|
ca65694482 | ||
|
|
69865e4f83 | ||
|
|
71a9a4406a | ||
|
|
0177abb172 | ||
|
|
dd53d408e3 | ||
|
|
ce501f14c5 | ||
|
|
b96146d014 | ||
|
|
6f18f8d375 | ||
|
|
63cf0366bd | ||
|
|
fd7ea3420f | ||
|
|
52e520be10 | ||
|
|
af718696fb | ||
|
|
2c5a00c966 | ||
|
|
3d65f9905d | ||
|
|
709366bdfe | ||
|
|
910200b637 | ||
|
|
be831d7ecb | ||
|
|
44c544160a | ||
|
|
262df0197b | ||
|
|
ed853e1ffb | ||
|
|
799554b1c5 | ||
|
|
5d0864fb41 | ||
|
|
90ffbb4170 | ||
|
|
77822d9462 | ||
|
|
adfd841d9d | ||
|
|
237c46512c | ||
|
|
64f999ee89 | ||
|
|
198407b5ba | ||
|
|
ab5586a7a3 | ||
|
|
79426acd55 | ||
|
|
14f579844d | ||
|
|
83495af5ce | ||
|
|
dc9c72819c | ||
|
|
1200929a72 | ||
|
|
10ab52081d | ||
|
|
fecff1bcf0 | ||
|
|
513d77788d | ||
|
|
2f5a766c71 | ||
|
|
0b9703a36f | ||
|
|
2bf6ae09b3 | ||
|
|
879750b278 | ||
|
|
e3a9350e58 | ||
|
|
78a7a5b561 | ||
|
|
04086099d0 | ||
|
|
757450b24f | ||
|
|
fbbc93906e | ||
|
|
85dbf412fd | ||
|
|
1f25f80d5b | ||
|
|
99143db529 | ||
|
|
7fde7fcf7b | ||
|
|
2f99ece694 | ||
|
|
251dc3a322 | ||
|
|
c1b1e9af62 | ||
|
|
bcbbf6dacf | ||
|
|
cdccb19d1c | ||
|
|
93a924d020 | ||
|
|
6f7ac0e29c | ||
|
|
a3fdca376e | ||
|
|
bfdfb7479d | ||
|
|
56739b8036 | ||
|
|
2c5d1036db | ||
|
|
15b0a7813d | ||
|
|
490e5ace3a | ||
|
|
d2595ccfea | ||
|
|
6be0cf66e0 | ||
|
|
5b059dfd6b | ||
|
|
1a3c0d9be9 | ||
|
|
ea1a2f3fbf | ||
|
|
5ba18ec98d | ||
|
|
62b2b9bf45 | ||
|
|
244e69a10a | ||
|
|
e006ff39be | ||
|
|
9faad3da69 | ||
|
|
47a749742a | ||
|
|
9d252ff7d2 | ||
|
|
9b4213bb3f | ||
|
|
0cc7fd3498 | ||
|
|
1e22d92c69 | ||
|
|
1638a98f0e | ||
|
|
85cc06f56c | ||
|
|
76054b4646 | ||
|
|
9b95c00218 | ||
|
|
b8186ff707 | ||
|
|
f5538049ef | ||
|
|
119d9ad3aa | ||
|
|
8b0910d31f | ||
|
|
cd48f2d313 | ||
|
|
26f98a5e56 | ||
|
|
bbfc7b1ea2 | ||
|
|
1e3fa455c9 | ||
|
|
d00198bd14 | ||
|
|
ff4b11441b | ||
|
|
904733362e | ||
|
|
44de3dd8da | ||
|
|
ceb75ca9ff | ||
|
|
55edd253ff | ||
|
|
2ae10f0b33 | ||
|
|
b9cc513f2f | ||
|
|
14192d21dd | ||
|
|
19719bf57f | ||
|
|
ea8cb9b7bb | ||
|
|
72ac20b7d7 | ||
|
|
7b4e946f74 | ||
|
|
f3a4ae987d | ||
|
|
85397cf893 | ||
|
|
d10ba45b4b | ||
|
|
ce7746b49e | ||
|
|
5e45fd7662 | ||
|
|
354e08673b | ||
|
|
c552943f9e | ||
|
|
810395f913 | ||
|
|
8dfdec39fd | ||
|
|
0abecbc87d | ||
|
|
efbb62b5bd | ||
|
|
24f5b98e8c | ||
|
|
dd5e309d31 | ||
|
|
0c0b1e1498 | ||
|
|
0d54bf3711 | ||
|
|
920aa8280f | ||
|
|
8a2c820213 | ||
|
|
ab08379d1c | ||
|
|
321cd769b7 | ||
|
|
802974ec84 | ||
|
|
91cb892574 | ||
|
|
4703c1399d | ||
|
|
e58e9e1fb9 | ||
|
|
d7802b428a | ||
|
|
5894e1b085 | ||
|
|
dc25a1a62b | ||
|
|
754b233873 | ||
|
|
b8d35358ad | ||
|
|
5617ad7c18 | ||
|
|
909f1a1a30 | ||
|
|
f6837a8ef4 | ||
|
|
d287c6c8b0 | ||
|
|
488735e4a2 | ||
|
|
43d597b30f | ||
|
|
a3f676461c | ||
|
|
607667f89d | ||
|
|
6212b342f6 | ||
|
|
5ddb691286 | ||
|
|
daac4e5d34 | ||
|
|
6f905e1f0f | ||
|
|
4ccedfaec4 | ||
|
|
c010901ea9 | ||
|
|
c0bedd810f | ||
|
|
57ceb807ca | ||
|
|
5d66bf5a1f | ||
|
|
d4b614d655 | ||
|
|
91d32c4556 | ||
|
|
e9e0f57d92 | ||
|
|
f090fee89b | ||
|
|
f55296bdf0 | ||
|
|
bed000d72e | ||
|
|
b2181df698 | ||
|
|
6469ae095f | ||
|
|
636e904b09 | ||
|
|
2c343f8ac1 | ||
|
|
30dc72c0aa | ||
|
|
279bfdeef3 | ||
|
|
da85dcc288 | ||
|
|
07050778e3 | ||
|
|
ac3cb936ee | ||
|
|
d183e03dc3 | ||
|
|
fa0de66105 | ||
|
|
aaa76b7a7d | ||
|
|
ad788184e3 | ||
|
|
aec683eef8 | ||
|
|
41646a2294 | ||
|
|
2a1688c8f5 | ||
|
|
6ba062e067 | ||
|
|
089381e2b1 | ||
|
|
ef3d739cdf | ||
|
|
0f7d84bbbf | ||
|
|
94253c0df4 | ||
|
|
30c48b68df | ||
|
|
7088b7efe3 | ||
|
|
13ccdabc07 | ||
|
|
203bbab7c9 | ||
|
|
93d3ea1393 | ||
|
|
874b8643e0 | ||
|
|
d18329a21e | ||
|
|
82296abf08 | ||
|
|
5772e32729 | ||
|
|
3ef7160d41 | ||
|
|
462ffc7927 | ||
|
|
a13289725c | ||
|
|
c8646e5c72 | ||
|
|
efa3ec6939 | ||
|
|
a638162ed4 | ||
|
|
c77bd091df | ||
|
|
2bb76d85aa | ||
|
|
8dde174dd4 | ||
|
|
ca98340c4c | ||
|
|
35539e2f98 | ||
|
|
8fb5bb0f20 | ||
|
|
6db42b86e6 | ||
|
|
8066c6a687 | ||
|
|
4671050f10 | ||
|
|
fca34fb8d0 | ||
|
|
0e31751aed | ||
|
|
d5c18c780a | ||
|
|
4c239ca4d9 | ||
|
|
77481ec3e1 | ||
|
|
f03990cd12 | ||
|
|
a841205be9 | ||
|
|
df7cbb28e0 | ||
|
|
01697f2acc | ||
|
|
0a1c05fbb8 | ||
|
|
8fa2e7802e | ||
|
|
c2ee1525ef | ||
|
|
ae731e3e50 | ||
|
|
bc879a58f2 | ||
|
|
d551c0972c | ||
|
|
27fd5c0793 | ||
|
|
264cc47fd4 | ||
|
|
866efbc904 | ||
|
|
941e45f907 | ||
|
|
7a654297a0 | ||
|
|
4600d7c026 | ||
|
|
c97ddc73f6 | ||
|
|
bd20b3429a | ||
|
|
d830389b53 | ||
|
|
63c8495242 | ||
|
|
9d7b1b2b03 | ||
|
|
0f7c885e8c | ||
|
|
95b63f4c39 | ||
|
|
20ec6252d1 | ||
|
|
2ba998572c | ||
|
|
c5ff074db9 | ||
|
|
717e43f1bd | ||
|
|
e130d09c74 | ||
|
|
36d60df82c | ||
|
|
e9177a25c1 | ||
|
|
02b4c1de38 | ||
|
|
feb62aa2bd | ||
|
|
6c38124bb9 | ||
|
|
caf50ef7ea | ||
|
|
c51ce8e879 | ||
|
|
94dc5e4e43 | ||
|
|
c52322d409 | ||
|
|
a4c93085d2 | ||
|
|
18dc49dd08 | ||
|
|
c5d6cc90d9 | ||
|
|
bcb2a0a181 | ||
|
|
940c0805c0 | ||
|
|
a3c42aef3e | ||
|
|
aba1f29686 | ||
|
|
898bc97bbe | ||
|
|
5ab3eafa66 | ||
|
|
1f1f1e4dfc | ||
|
|
32b5c49ef3 | ||
|
|
21878028d5 | ||
|
|
18b31092c6 | ||
|
|
736824a259 | ||
|
|
9e52bb21b7 | ||
|
|
a3433951b0 | ||
|
|
ad284758d3 | ||
|
|
6aed9a6630 | ||
|
|
704f3a5483 | ||
|
|
2de37edd0d | ||
|
|
cdb6b73776 | ||
|
|
e62f87c5f4 | ||
|
|
1bbb844926 | ||
|
|
17cb990469 | ||
|
|
cccfc272df | ||
|
|
eb4e5e0bfb | ||
|
|
fbfcab2541 | ||
|
|
85f54ced38 | ||
|
|
b53c45a530 | ||
|
|
fa6991264b | ||
|
|
e1addb8c74 | ||
|
|
3e3a6740d5 | ||
|
|
5caacf5120 | ||
|
|
ebae9d9816 | ||
|
|
4457581ea5 | ||
|
|
fe773c0a46 | ||
|
|
348f13ad57 | ||
|
|
dd60d52814 | ||
|
|
428c3163c5 | ||
|
|
410178bb88 | ||
|
|
fad7a0e23d | ||
|
|
da7cc28446 | ||
|
|
e6e391530f | ||
|
|
a0256cda63 | ||
|
|
18eed1d727 | ||
|
|
85daeb5e16 | ||
|
|
ce72e40607 | ||
|
|
f038b7fc3d | ||
|
|
30dbc0a75b | ||
|
|
57d33c5027 | ||
|
|
e1c5526cb2 | ||
|
|
290c2ef84f | ||
|
|
073618d375 | ||
|
|
5ddf03d324 | ||
|
|
ac98be85ce | ||
|
|
048fae9de6 | ||
|
|
81735df1fa | ||
|
|
9c32ab0d8b | ||
|
|
861e75f503 | ||
|
|
e891120584 | ||
|
|
2045bb3c21 | ||
|
|
a498488c59 | ||
|
|
dd43ee3dbf | ||
|
|
39ad9eb8f3 | ||
|
|
b30ba5a92b |
@@ -0,0 +1,17 @@
|
||||
compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
|
||||
compat/zlib/contrib/vstudio/readme.txt
|
||||
compat/zlib/contrib/vstudio/*/zlib.rc
|
||||
compat/zlib/win32/*.txt
|
||||
compat/zlib/win64/*.txt
|
||||
libtommath/*.dsp
|
||||
libtommath/*.sln
|
||||
libtommath/*.vcproj
|
||||
tools/tcl.hpj.in
|
||||
tools/tcl.wse.in
|
||||
win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/tcl.dsp
|
||||
win/tcl.dsw
|
||||
win/tcl.hpj.in
|
||||
@@ -3,11 +3,13 @@ compat/zlib/contrib/vstudio/readme.txt
|
||||
compat/zlib/contrib/vstudio/*/zlib.rc
|
||||
compat/zlib/win32/*.txt
|
||||
compat/zlib/win64/*.txt
|
||||
libtommath/*.dsp
|
||||
libtommath/*.sln
|
||||
libtommath/*.vcproj
|
||||
tools/tcl.hpj.in
|
||||
tools/tcl.wse.in
|
||||
win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.bc
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/tcl.dsp
|
||||
|
||||
@@ -2,7 +2,6 @@ tools/tcl.hpj.in
|
||||
tools/tcl.wse.in
|
||||
win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.bc
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/tcl.dsp
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/tclsh*
|
||||
*/tcltest*
|
||||
*/versions.vc
|
||||
*/version.vc
|
||||
html
|
||||
libtommath/bn.ilg
|
||||
libtommath/bn.ind
|
||||
@@ -40,7 +41,8 @@ unix/dltest.marker
|
||||
unix/tcl.pc
|
||||
unix/tclIndex
|
||||
unix/pkgs/*
|
||||
win/Debug_VC*
|
||||
win/Release_VC*
|
||||
win/Debug*
|
||||
win/Release*
|
||||
win/pkgs/*
|
||||
win/tcl.hpj
|
||||
win/tcl.hpj
|
||||
win/nmhlp-out.txt
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
README: Tcl
|
||||
This is the Tcl 8.7a0 source distribution.
|
||||
This is the Tcl 8.7a2 source distribution.
|
||||
http://sourceforge.net/projects/tcl/files/Tcl/
|
||||
You can get any source release of Tcl from the URL above.
|
||||
|
||||
|
||||
@@ -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 (cerutti)
|
||||
2013-05-19 (platform support) FreeBSD updates (gahr)
|
||||
|
||||
2013-05-20 (bug fix)[3613567] access error temp file creation (keene)
|
||||
|
||||
@@ -8624,3 +8624,220 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich)
|
||||
2016-02-22 (bug)[9b4702] [info exists env(missing)] kills trace (nijtmans)
|
||||
|
||||
--- Released 8.6.5, February 29, 2016 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2016-03-01 (bug)[803042] mem leak due to reference cycle (porter)
|
||||
|
||||
2016-03-08 (bug)[bbc304] reflected watch race condition (porter)
|
||||
|
||||
2016-03-17 (bug)[fadc99] compile-5.3 (rodriguez,porter)
|
||||
|
||||
2016-03-17 (enhancement)[1a25fd] compile [variable ${ns}::v] (porter)
|
||||
|
||||
2016-03-20 (bug)[1af8de] crash in compiled [string replace] (harder,fellows)
|
||||
|
||||
2016-03-21 (bug)[d30718] segv in notifier finalize (hirofumi,nijtmans)
|
||||
|
||||
2016-03-23 (enhancement)[7d0db7] parallel make (yarda,nijtmans)
|
||||
|
||||
2016-03-23 [f12535] enable test bindings customization (vogel,nijtmans)
|
||||
|
||||
2016-04-04 (bug)[47ac84] compiled [lreplace] fixes (aspect,ferrieux,fellows)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-04-08 (bug)[866368] RE \w includes 'Punctuation Connector' (nijtmans)
|
||||
|
||||
2016-04-08 (bug)[2538f3] Win crash Tcl_OpenTcpServer() (griffin)
|
||||
|
||||
2016-04-10 [07d13d] Restore TclBlend support lost in 8.6.1 (buratti)
|
||||
|
||||
2016-05-13 (bug)[3154ea] Mem corruption in assembler exceptions (tkob,kenny)
|
||||
|
||||
2016-05-13 (bug) registry package support any Unicode env (nijtmans)
|
||||
=> registry 1.3.2
|
||||
|
||||
2016-05-21 (bug)[f7d4e] [namespace delete] performance (fellows)
|
||||
|
||||
2016-06-02 (TIP 447) execution time verbosity option (gahr)
|
||||
=> tcltest 2.4.0
|
||||
|
||||
2016-06-16 (bug)[16828b] crash due to [vwait] trace undo fail (dah,porter)
|
||||
|
||||
2016-06-16 (enhancement)[4b61af] good [info frame] from more cases (beric)
|
||||
|
||||
2016-06-21 (bug)[c383eb] crash in [glob -path a] (oehlmann,porter)
|
||||
|
||||
2016-06-21 (update) Update Unicode data to 9.0 (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-06-22 (bug)[16896d] Tcl_DString tolerate append to self. (dah,porter)
|
||||
|
||||
2016-06-23 (bug)[d55322] crash in [dict update] (yorick,fellows)
|
||||
|
||||
2016-06-27 (bug)[dd260a] crash in [chan configure -dictionary] (madden,aspect)
|
||||
|
||||
2016-07-02 (bug)[f961d7] usage message with parameters with spaces (porter)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-02 (enhancement)[09fabc] Sort order of -relateddir (lanam)
|
||||
|
||||
2016-07-07 (bug)[5d7ca0] Win: [file executable] for .cmd and .ps1 (nadkarni)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-08 (bug)[a47641] [file normalize] & Windows junctions (nadkarni)
|
||||
|
||||
2016-07-09 [ae61a6] [file] handling of Win hardcoded names (CON) (nadkarni)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-09 [3613671] [file owned] (more) useful on Win (nadkarni)
|
||||
|
||||
2016-07-09 (bug)[1493a4] [namespace upvar] use of resolvers (beric,fellows)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-10 (bug)[da340d] integer division in clock math (nadkarni)
|
||||
|
||||
2016-07-20 tzdata updated to Olson's tzdata2016f (venkat)
|
||||
|
||||
--- Released 8.6.6, July 27, 2016 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2016-09-07 (bug)[c09edf] Bad caching with custom resolver (neumann,nijtmans)
|
||||
|
||||
2016-09-07 (bug)[4dbdd9] Memleak in test var-8.3 (mr_calvin,porter)
|
||||
|
||||
2016-10-03 (bug)[2bf561] Allow empty command as alias target (yorick,nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-10-04 (bug)[4d5ae7] Crash in async connects host no address (gahr,fellows)
|
||||
|
||||
2016-10-08 (bug)[838e99] treat application/xml as text (gahr,fellows)
|
||||
=> http 2.8.10
|
||||
|
||||
2016-10-11 (bug)[3cc1d9] Thread finalization crash in zippy (neumann)
|
||||
|
||||
2016-10-12 (bug)[be003d] Fix [scan 0x1 %b], [scan 0x1 %o] (porter)
|
||||
|
||||
2016-10-14 (bug)[eb6b68] Fix stringComp-14.5 (porter)
|
||||
|
||||
2016-10-30 (bug)[b26e38] Fix zlib-7.8 (fellows)
|
||||
|
||||
2016-10-30 (bug)[1ae129] Fix memleak in [history] destruction (fellows)
|
||||
|
||||
2016-11-04 (feature) Provisional Tcl 9 support in msgcat and tcltest (nijtmans)
|
||||
=> msgcat 1.6.1
|
||||
=> tcltest 2.4.1
|
||||
|
||||
2016-11-04 (bug)[824752] Crash in Tcl_ListObjReplace() (gahr,porter)
|
||||
|
||||
2016-11-11 (bug)[79614f] invalidate VFS mounts on sytem encoding change (yorick)
|
||||
|
||||
2016-11-14 OSX: End panic() as legacy support macro; system conflicts (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-11-15 (bug) TclOO fix stops crash mixing Itcl and snit (fellows)
|
||||
|
||||
2016-11-17 (update) Reconcile libtommath updates; purge unused files (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-01-09 (bug)[b87ad7] Repair drifts in timer clock (sebres)
|
||||
|
||||
2017-01-17 (update) => zlib 1.2.11 (nijtmans)
|
||||
|
||||
2017-01-31 (bug)[39f630] Revise Tcl_LinkVar to tolerate some prefixes (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-02-01 (bug)[d0f7ba] Improper NAN optimization. expr-22.1[01] (aspect)
|
||||
|
||||
2017-02-26 (bug)[25842c] zlib stream finalization (aspect)
|
||||
|
||||
2017-03-07 (deprecate) Remove unmaintained makefile.bc file (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-03-14 (enhancement) [clock] and [encoding] are now ensembles (kenny)
|
||||
|
||||
2017-03-15 (enhancement) several [clock] subcommands bytecoded (kenny)
|
||||
|
||||
2017-03-23 tzdata updated to Olson's tzdata2017b (jima)
|
||||
|
||||
2017-03-29 (bug)[900cb0] Fix OO unexport introspection (napier)
|
||||
|
||||
2017-04-12 (bug)[42202b] Nesting imbalance in coro injection (nadkarni,sebres)
|
||||
|
||||
2017-04-18 (bug)[bc4322] http package support for safe interps (nash,nijtmans)
|
||||
|
||||
2017-04-28 (bug)[f34cf8] [file join a //b] => /b (neumann,porter)
|
||||
|
||||
2017-05-01 (bug)[8bd13f] Windows threads and pipes (sebres,nijtmans)
|
||||
|
||||
2017-05-01 (bug)[f9fe90] [file join //a b] EIAS violation (aspect,porter)
|
||||
|
||||
2017-05-04 (bug) Make test filesystem-1.52 pass on Windows (nijtmans)
|
||||
|
||||
2017-05-05 (bug)[601522] [binary] field spec overflow -> segfault (porter)
|
||||
|
||||
2017-05-08 (bug)[6ca52a] http memleak handling keep-alive (aspect,nijtmans)
|
||||
=> http 2.8.11
|
||||
|
||||
2017-05-29 (bug)[a3fb33] crash in [lsort] on long lists (sebres)
|
||||
|
||||
2017-06-05 (bug)[67aa9a] Tcl_UtfToUniChar() revised handling invalid UTF-8 (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-06-08 (bug)[2738427] Tcl_NumUtfChars() corner case utf-4.9 (nijtmans)
|
||||
|
||||
2017-06-22 (update) Update Unicode data to 10.0 (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-06-22 (TIP 473) Let [oo::copy] specify target namespace (fellows)
|
||||
|
||||
2017-06-26 (bug)[46f801] Repair autoloader fragility (porter)
|
||||
|
||||
2017-07-06 (bug)[adb198] Plug memleak in TclJoinPath (sebres,porter)
|
||||
|
||||
2017-07-17 (bug)[fb2208] Repeatable tclIndex generation (wiedemann,nijtmans)
|
||||
|
||||
--- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2016-03-17 (bug)[0b8c38] socket accept callbacks always in global ns (porter)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-01 Hack accommodations for legacy Itcl 3 disabled (porter)
|
||||
|
||||
2016-07-12 Make TCL_HASH_TYPE build-time configurable (nijtmans)
|
||||
|
||||
2016-07-19 (bug)[0363f0] Partial array search ID reform (porter)
|
||||
|
||||
2016-07-19 (feature removed) Tcl_ObjType "array search" unregistered (porter)
|
||||
*** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("array search") ***
|
||||
|
||||
2016-10-04 Server socket on port 0 chooses port supporting IPv4 * IPv6 (max)
|
||||
|
||||
2016-11-25 [array named -regexp] supports backrefs (goth)
|
||||
|
||||
2017-01-04 (TIP 456) New routine Tcl_OpenTcpServerEx() (limeboy)
|
||||
|
||||
2017-01-04 (TIP 459) New subcommand [package files] (nijtmans)
|
||||
|
||||
2017-01-16 threaded allocator initialization repair (vasiljevic,nijtmans)
|
||||
|
||||
2017-01-30 Add to Win shell builtins: assoc ftype move (ashok)
|
||||
|
||||
2017-03-31 TCL_MEM_DEBUG facilities better support 64-bit memory (nijtmans)
|
||||
|
||||
2017-04-13 \u escaped content in msg files converted to true utf-8 (nijtmans)
|
||||
|
||||
2017-05-18 (TIP 458) New epoll or kqueue notifiers are default (alborboz)
|
||||
|
||||
2017-05-31 Purge build support for SunOS-4.* (stu)
|
||||
|
||||
2017-06-22 (TIP 463) New option [regsub ... -command ...] (fellows)
|
||||
|
||||
2017-06-22 (TIP 470) Tcl_GetDefineContextObject();[oo::define [self]] (fellows)
|
||||
=> TclOO 1.2.0
|
||||
|
||||
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
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
1. Compression algorithm (deflate)
|
||||
|
||||
The deflation algorithm used by gzip (also zip and zlib) is a variation of
|
||||
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
|
||||
the input data. The second occurrence of a string is replaced by a
|
||||
pointer to the previous string, in the form of a pair (distance,
|
||||
length). Distances are limited to 32K bytes, and lengths are limited
|
||||
to 258 bytes. When a string does not occur anywhere in the previous
|
||||
32K bytes, it is emitted as a sequence of literal bytes. (In this
|
||||
description, `string' must be taken as an arbitrary sequence of bytes,
|
||||
and is not restricted to printable characters.)
|
||||
|
||||
Literals or match lengths are compressed with one Huffman tree, and
|
||||
match distances are compressed with another tree. The trees are stored
|
||||
in a compact form at the start of each block. The blocks can have any
|
||||
size (except that the compressed data for one block must fit in
|
||||
available memory). A block is terminated when deflate() determines that
|
||||
it would be useful to start another block with fresh trees. (This is
|
||||
somewhat similar to the behavior of LZW-based _compress_.)
|
||||
|
||||
Duplicated strings are found using a hash table. All input strings of
|
||||
length 3 are inserted in the hash table. A hash index is computed for
|
||||
the next 3 bytes. If the hash chain for this index is not empty, all
|
||||
strings in the chain are compared with the current input string, and
|
||||
the longest match is selected.
|
||||
|
||||
The hash chains are searched starting with the most recent strings, to
|
||||
favor small distances and thus take advantage of the Huffman encoding.
|
||||
The hash chains are singly linked. There are no deletions from the
|
||||
hash chains, the algorithm simply discards matches that are too old.
|
||||
|
||||
To avoid a worst-case situation, very long hash chains are arbitrarily
|
||||
truncated at a certain length, determined by a runtime option (level
|
||||
parameter of deflateInit). So deflate() does not always find the longest
|
||||
possible match but generally finds a match which is long enough.
|
||||
|
||||
deflate() also defers the selection of matches with a lazy evaluation
|
||||
mechanism. After a match of length N has been found, deflate() searches for
|
||||
a longer match at the next input byte. If a longer match is found, the
|
||||
previous match is truncated to a length of one (thus producing a single
|
||||
literal byte) and the process of lazy evaluation begins again. Otherwise,
|
||||
the original match is kept, and the next match search is attempted only N
|
||||
steps later.
|
||||
|
||||
The lazy match evaluation is also subject to a runtime parameter. If
|
||||
the current match is long enough, deflate() reduces the search for a longer
|
||||
match, thus speeding up the whole process. If compression ratio is more
|
||||
important than speed, deflate() attempts a complete second search even if
|
||||
the first match is already long enough.
|
||||
|
||||
The lazy match evaluation is not performed for the fastest compression
|
||||
modes (level parameter 1 to 3). For these fast modes, new strings
|
||||
are inserted in the hash table only when no match was found, or
|
||||
when the match is not too long. This degrades the compression ratio
|
||||
but saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
2. Decompression algorithm (inflate)
|
||||
|
||||
2.1 Introduction
|
||||
|
||||
The key question is how to represent a Huffman code (or any prefix code) so
|
||||
that you can decode fast. The most important characteristic is that shorter
|
||||
codes are much more common than longer codes, so pay attention to decoding the
|
||||
short codes fast, and let the long codes take longer to decode.
|
||||
|
||||
inflate() sets up a first level table that covers some number of bits of
|
||||
input less than the length of longest code. It gets that many bits from the
|
||||
stream, and looks it up in the table. The table will tell if the next
|
||||
code is that many bits or less and how many, and if it is, it will tell
|
||||
the value, else it will point to the next level table for which inflate()
|
||||
grabs more bits and tries to decode a longer code.
|
||||
|
||||
How many bits to make the first lookup is a tradeoff between the time it
|
||||
takes to decode and the time it takes to build the table. If building the
|
||||
table took no time (and if you had infinite memory), then there would only
|
||||
be a first level table to cover all the way to the longest code. However,
|
||||
building the table ends up taking a lot longer for more bits since short
|
||||
codes are replicated many times in such a table. What inflate() does is
|
||||
simply to make the number of bits in the first table a variable, and then
|
||||
to set that variable for the maximum speed.
|
||||
|
||||
For inflate, which has 286 possible codes for the literal/length tree, the size
|
||||
of the first table is nine bits. Also the distance trees have 30 possible
|
||||
values, and the size of the first table is six bits. Note that for each of
|
||||
those cases, the table ended up one bit longer than the ``average'' code
|
||||
length, i.e. the code length of an approximately flat code which would be a
|
||||
little more than eight bits for 286 symbols and a little less than five bits
|
||||
for 30 symbols.
|
||||
|
||||
|
||||
2.2 More details on the inflate table lookup
|
||||
|
||||
Ok, you want to know what this cleverly obfuscated inflate tree actually
|
||||
looks like. You are correct that it's not a Huffman tree. It is simply a
|
||||
lookup table for the first, let's say, nine bits of a Huffman symbol. The
|
||||
symbol could be as short as one bit or as long as 15 bits. If a particular
|
||||
symbol is shorter than nine bits, then that symbol's translation is duplicated
|
||||
in all those entries that start with that symbol's bits. For example, if the
|
||||
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
|
||||
symbol is nine bits long, it appears in the table once.
|
||||
|
||||
If the symbol is longer than nine bits, then that entry in the table points
|
||||
to another similar table for the remaining bits. Again, there are duplicated
|
||||
entries as needed. The idea is that most of the time the symbol will be short
|
||||
and there will only be one table look up. (That's whole idea behind data
|
||||
compression in the first place.) For the less frequent long symbols, there
|
||||
will be two lookups. If you had a compression method with really long
|
||||
symbols, you could have as many levels of lookups as is efficient. For
|
||||
inflate, two is enough.
|
||||
|
||||
So a table entry either points to another table (in which case nine bits in
|
||||
the above example are gobbled), or it contains the translation for the symbol
|
||||
and the number of bits to gobble. Then you start again with the next
|
||||
ungobbled bit.
|
||||
|
||||
You may wonder: why not just have one lookup table for how ever many bits the
|
||||
longest symbol is? The reason is that if you do that, you end up spending
|
||||
more time filling in duplicate symbol entries than you do actually decoding.
|
||||
At least for deflate's output that generates new trees every several 10's of
|
||||
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
|
||||
would take too long if you're only decoding several thousand symbols. At the
|
||||
other extreme, you could make a new table for every bit in the code. In fact,
|
||||
that's essentially a Huffman tree. But then you spend too much time
|
||||
traversing the tree while decoding, even for short symbols.
|
||||
|
||||
So the number of bits for the first lookup table is a trade of the time to
|
||||
fill out the table vs. the time spent looking at the second level and above of
|
||||
the table.
|
||||
|
||||
Here is an example, scaled down:
|
||||
|
||||
The code being decoded, with 10 symbols, from 1 to 6 bits long:
|
||||
|
||||
A: 0
|
||||
B: 10
|
||||
C: 1100
|
||||
D: 11010
|
||||
E: 11011
|
||||
F: 11100
|
||||
G: 11101
|
||||
H: 11110
|
||||
I: 111110
|
||||
J: 111111
|
||||
|
||||
Let's make the first table three bits long (eight entries):
|
||||
|
||||
000: A,1
|
||||
001: A,1
|
||||
010: A,1
|
||||
011: A,1
|
||||
100: B,2
|
||||
101: B,2
|
||||
110: -> table X (gobble 3 bits)
|
||||
111: -> table Y (gobble 3 bits)
|
||||
|
||||
Each entry is what the bits decode as and how many bits that is, i.e. how
|
||||
many bits to gobble. Or the entry points to another table, with the number of
|
||||
bits to gobble implicit in the size of the table.
|
||||
|
||||
Table X is two bits long since the longest code starting with 110 is five bits
|
||||
long:
|
||||
|
||||
00: C,1
|
||||
01: C,1
|
||||
10: D,2
|
||||
11: E,2
|
||||
|
||||
Table Y is three bits long since the longest code starting with 111 is six
|
||||
bits long:
|
||||
|
||||
000: F,2
|
||||
001: F,2
|
||||
010: G,2
|
||||
011: G,2
|
||||
100: H,2
|
||||
101: H,2
|
||||
110: I,3
|
||||
111: J,3
|
||||
|
||||
So what we have here are three tables with a total of 20 entries that had to
|
||||
be constructed. That's compared to 64 entries for a single table. Or
|
||||
compared to 16 entries for a Huffman tree (six two entry tables and one four
|
||||
entry table). Assuming that the code ideally represents the probability of
|
||||
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
|
||||
to one lookup for the single table, or 1.66 lookups per symbol for the
|
||||
Huffman tree.
|
||||
|
||||
There, I think that gives you a picture of what's going on. For inflate, the
|
||||
meaning of a particular symbol is often more than just a letter. It can be a
|
||||
byte (a "literal"), or it can be either a length or a distance which
|
||||
indicates a base value and a number of bits to fetch after the code that is
|
||||
added to the base value. Or it might be the special end-of-block code. The
|
||||
data structures created in inftrees.c try to encode all that information
|
||||
compactly in the tables.
|
||||
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
References:
|
||||
|
||||
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
|
||||
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
|
||||
pp. 337-343.
|
||||
|
||||
``DEFLATE Compressed Data Format Specification'' available in
|
||||
http://tools.ietf.org/html/rfc1951
|
||||
@@ -1,619 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group P. Deutsch
|
||||
Request for Comments: 1950 Aladdin Enterprises
|
||||
Category: Informational J-L. Gailly
|
||||
Info-ZIP
|
||||
May 1996
|
||||
|
||||
|
||||
ZLIB Compressed Data Format Specification version 3.3
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. This memo
|
||||
does not specify an Internet standard of any kind. Distribution of
|
||||
this memo is unlimited.
|
||||
|
||||
IESG Note:
|
||||
|
||||
The IESG takes no position on the validity of any Intellectual
|
||||
Property Rights statements contained in this document.
|
||||
|
||||
Notices
|
||||
|
||||
Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly
|
||||
|
||||
Permission is granted to copy and distribute this document for any
|
||||
purpose and without charge, including translations into other
|
||||
languages and incorporation into compilations, provided that the
|
||||
copyright notice and this notice are preserved, and that any
|
||||
substantive changes or deletions from the original are clearly
|
||||
marked.
|
||||
|
||||
A pointer to the latest version of this and related documentation in
|
||||
HTML format can be found at the URL
|
||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines a lossless compressed data format. The
|
||||
data can be produced or consumed, even for an arbitrarily long
|
||||
sequentially presented input data stream, using only an a priori
|
||||
bounded amount of intermediate storage. The format presently uses
|
||||
the DEFLATE compression method but can be easily extended to use
|
||||
other compression methods. It can be implemented readily in a manner
|
||||
not covered by patents. This specification also defines the ADLER-32
|
||||
checksum (an extension and improvement of the Fletcher checksum),
|
||||
used for detection of data corruption, and provides an algorithm for
|
||||
computing it.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 1]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ................................................... 2
|
||||
1.1. Purpose ................................................... 2
|
||||
1.2. Intended audience ......................................... 3
|
||||
1.3. Scope ..................................................... 3
|
||||
1.4. Compliance ................................................ 3
|
||||
1.5. Definitions of terms and conventions used ................ 3
|
||||
1.6. Changes from previous versions ............................ 3
|
||||
2. Detailed specification ......................................... 3
|
||||
2.1. Overall conventions ....................................... 3
|
||||
2.2. Data format ............................................... 4
|
||||
2.3. Compliance ................................................ 7
|
||||
3. References ..................................................... 7
|
||||
4. Source code .................................................... 8
|
||||
5. Security Considerations ........................................ 8
|
||||
6. Acknowledgements ............................................... 8
|
||||
7. Authors' Addresses ............................................. 8
|
||||
8. Appendix: Rationale ............................................ 9
|
||||
9. Appendix: Sample code ..........................................10
|
||||
|
||||
1. Introduction
|
||||
|
||||
1.1. Purpose
|
||||
|
||||
The purpose of this specification is to define a lossless
|
||||
compressed data format that:
|
||||
|
||||
* Is independent of CPU type, operating system, file system,
|
||||
and character set, and hence can be used for interchange;
|
||||
|
||||
* Can be produced or consumed, even for an arbitrarily long
|
||||
sequentially presented input data stream, using only an a
|
||||
priori bounded amount of intermediate storage, and hence can
|
||||
be used in data communications or similar structures such as
|
||||
Unix filters;
|
||||
|
||||
* Can use a number of different compression methods;
|
||||
|
||||
* Can be implemented readily in a manner not covered by
|
||||
patents, and hence can be practiced freely.
|
||||
|
||||
The data format defined by this specification does not attempt to
|
||||
allow random access to compressed data.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 2]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
1.2. Intended audience
|
||||
|
||||
This specification is intended for use by implementors of software
|
||||
to compress data into zlib format and/or decompress data from zlib
|
||||
format.
|
||||
|
||||
The text of the specification assumes a basic background in
|
||||
programming at the level of bits and other primitive data
|
||||
representations.
|
||||
|
||||
1.3. Scope
|
||||
|
||||
The specification specifies a compressed data format that can be
|
||||
used for in-memory compression of a sequence of arbitrary bytes.
|
||||
|
||||
1.4. Compliance
|
||||
|
||||
Unless otherwise indicated below, a compliant decompressor must be
|
||||
able to accept and decompress any data set that conforms to all
|
||||
the specifications presented here; a compliant compressor must
|
||||
produce data sets that conform to all the specifications presented
|
||||
here.
|
||||
|
||||
1.5. Definitions of terms and conventions used
|
||||
|
||||
byte: 8 bits stored or transmitted as a unit (same as an octet).
|
||||
(For this specification, a byte is exactly 8 bits, even on
|
||||
machines which store a character on a number of bits different
|
||||
from 8.) See below, for the numbering of bits within a byte.
|
||||
|
||||
1.6. Changes from previous versions
|
||||
|
||||
Version 3.1 was the first public release of this specification.
|
||||
In version 3.2, some terminology was changed and the Adler-32
|
||||
sample code was rewritten for clarity. In version 3.3, the
|
||||
support for a preset dictionary was introduced, and the
|
||||
specification was converted to RFC style.
|
||||
|
||||
2. Detailed specification
|
||||
|
||||
2.1. Overall conventions
|
||||
|
||||
In the diagrams below, a box like this:
|
||||
|
||||
+---+
|
||||
| | <-- the vertical bars might be missing
|
||||
+---+
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 3]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
represents one byte; a box like this:
|
||||
|
||||
+==============+
|
||||
| |
|
||||
+==============+
|
||||
|
||||
represents a variable number of bytes.
|
||||
|
||||
Bytes stored within a computer do not have a "bit order", since
|
||||
they are always treated as a unit. However, a byte considered as
|
||||
an integer between 0 and 255 does have a most- and least-
|
||||
significant bit, and since we write numbers with the most-
|
||||
significant digit on the left, we also write bytes with the most-
|
||||
significant bit on the left. In the diagrams below, we number the
|
||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
||||
the bits are numbered:
|
||||
|
||||
+--------+
|
||||
|76543210|
|
||||
+--------+
|
||||
|
||||
Within a computer, a number may occupy multiple bytes. All
|
||||
multi-byte numbers in the format described here are stored with
|
||||
the MOST-significant byte first (at the lower memory address).
|
||||
For example, the decimal number 520 is stored as:
|
||||
|
||||
0 1
|
||||
+--------+--------+
|
||||
|00000010|00001000|
|
||||
+--------+--------+
|
||||
^ ^
|
||||
| |
|
||||
| + less significant byte = 8
|
||||
+ more significant byte = 2 x 256
|
||||
|
||||
2.2. Data format
|
||||
|
||||
A zlib stream has the following structure:
|
||||
|
||||
0 1
|
||||
+---+---+
|
||||
|CMF|FLG| (more-->)
|
||||
+---+---+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 4]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
(if FLG.FDICT set)
|
||||
|
||||
0 1 2 3
|
||||
+---+---+---+---+
|
||||
| DICTID | (more-->)
|
||||
+---+---+---+---+
|
||||
|
||||
+=====================+---+---+---+---+
|
||||
|...compressed data...| ADLER32 |
|
||||
+=====================+---+---+---+---+
|
||||
|
||||
Any data which may appear after ADLER32 are not part of the zlib
|
||||
stream.
|
||||
|
||||
CMF (Compression Method and flags)
|
||||
This byte is divided into a 4-bit compression method and a 4-
|
||||
bit information field depending on the compression method.
|
||||
|
||||
bits 0 to 3 CM Compression method
|
||||
bits 4 to 7 CINFO Compression info
|
||||
|
||||
CM (Compression method)
|
||||
This identifies the compression method used in the file. CM = 8
|
||||
denotes the "deflate" compression method with a window size up
|
||||
to 32K. This is the method used by gzip and PNG (see
|
||||
references [1] and [2] in Chapter 3, below, for the reference
|
||||
documents). CM = 15 is reserved. It might be used in a future
|
||||
version of this specification to indicate the presence of an
|
||||
extra field before the compressed data.
|
||||
|
||||
CINFO (Compression info)
|
||||
For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
|
||||
size, minus eight (CINFO=7 indicates a 32K window size). Values
|
||||
of CINFO above 7 are not allowed in this version of the
|
||||
specification. CINFO is not defined in this specification for
|
||||
CM not equal to 8.
|
||||
|
||||
FLG (FLaGs)
|
||||
This flag byte is divided as follows:
|
||||
|
||||
bits 0 to 4 FCHECK (check bits for CMF and FLG)
|
||||
bit 5 FDICT (preset dictionary)
|
||||
bits 6 to 7 FLEVEL (compression level)
|
||||
|
||||
The FCHECK value must be such that CMF and FLG, when viewed as
|
||||
a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
|
||||
is a multiple of 31.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 5]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
FDICT (Preset dictionary)
|
||||
If FDICT is set, a DICT dictionary identifier is present
|
||||
immediately after the FLG byte. The dictionary is a sequence of
|
||||
bytes which are initially fed to the compressor without
|
||||
producing any compressed output. DICT is the Adler-32 checksum
|
||||
of this sequence of bytes (see the definition of ADLER32
|
||||
below). The decompressor can use this identifier to determine
|
||||
which dictionary has been used by the compressor.
|
||||
|
||||
FLEVEL (Compression level)
|
||||
These flags are available for use by specific compression
|
||||
methods. The "deflate" method (CM = 8) sets these flags as
|
||||
follows:
|
||||
|
||||
0 - compressor used fastest algorithm
|
||||
1 - compressor used fast algorithm
|
||||
2 - compressor used default algorithm
|
||||
3 - compressor used maximum compression, slowest algorithm
|
||||
|
||||
The information in FLEVEL is not needed for decompression; it
|
||||
is there to indicate if recompression might be worthwhile.
|
||||
|
||||
compressed data
|
||||
For compression method 8, the compressed data is stored in the
|
||||
deflate compressed data format as described in the document
|
||||
"DEFLATE Compressed Data Format Specification" by L. Peter
|
||||
Deutsch. (See reference [3] in Chapter 3, below)
|
||||
|
||||
Other compressed data formats are not specified in this version
|
||||
of the zlib specification.
|
||||
|
||||
ADLER32 (Adler-32 checksum)
|
||||
This contains a checksum value of the uncompressed data
|
||||
(excluding any dictionary data) computed according to Adler-32
|
||||
algorithm. This algorithm is a 32-bit extension and improvement
|
||||
of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
|
||||
standard. See references [4] and [5] in Chapter 3, below)
|
||||
|
||||
Adler-32 is composed of two sums accumulated per byte: s1 is
|
||||
the sum of all bytes, s2 is the sum of all s1 values. Both sums
|
||||
are done modulo 65521. s1 is initialized to 1, s2 to zero. The
|
||||
Adler-32 checksum is stored as s2*65536 + s1 in most-
|
||||
significant-byte first (network) order.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 6]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
2.3. Compliance
|
||||
|
||||
A compliant compressor must produce streams with correct CMF, FLG
|
||||
and ADLER32, but need not support preset dictionaries. When the
|
||||
zlib data format is used as part of another standard data format,
|
||||
the compressor may use only preset dictionaries that are specified
|
||||
by this other data format. If this other format does not use the
|
||||
preset dictionary feature, the compressor must not set the FDICT
|
||||
flag.
|
||||
|
||||
A compliant decompressor must check CMF, FLG, and ADLER32, and
|
||||
provide an error indication if any of these have incorrect values.
|
||||
A compliant decompressor must give an error indication if CM is
|
||||
not one of the values defined in this specification (only the
|
||||
value 8 is permitted in this version), since another value could
|
||||
indicate the presence of new features that would cause subsequent
|
||||
data to be interpreted incorrectly. A compliant decompressor must
|
||||
give an error indication if FDICT is set and DICTID is not the
|
||||
identifier of a known preset dictionary. A decompressor may
|
||||
ignore FLEVEL and still be compliant. When the zlib data format
|
||||
is being used as a part of another standard format, a compliant
|
||||
decompressor must support all the preset dictionaries specified by
|
||||
the other format. When the other format does not use the preset
|
||||
dictionary feature, a compliant decompressor must reject any
|
||||
stream in which the FDICT flag is set.
|
||||
|
||||
3. References
|
||||
|
||||
[1] Deutsch, L.P.,"GZIP Compressed Data Format Specification",
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[2] Thomas Boutell, "PNG (Portable Network Graphics) specification",
|
||||
available in ftp://ftp.uu.net/graphics/png/documents/
|
||||
|
||||
[3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[4] Fletcher, J. G., "An Arithmetic Checksum for Serial
|
||||
Transmissions," IEEE Transactions on Communications, Vol. COM-30,
|
||||
No. 1, January 1982, pp. 247-252.
|
||||
|
||||
[5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms,"
|
||||
November, 1993, pp. 144, 145. (Available from
|
||||
gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 7]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
4. Source code
|
||||
|
||||
Source code for a C language implementation of a "zlib" compliant
|
||||
library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/.
|
||||
|
||||
5. Security Considerations
|
||||
|
||||
A decoder that fails to check the ADLER32 checksum value may be
|
||||
subject to undetected data corruption.
|
||||
|
||||
6. Acknowledgements
|
||||
|
||||
Trademarks cited in this document are the property of their
|
||||
respective owners.
|
||||
|
||||
Jean-Loup Gailly and Mark Adler designed the zlib format and wrote
|
||||
the related software described in this specification. Glenn
|
||||
Randers-Pehrson converted this document to RFC and HTML format.
|
||||
|
||||
7. Authors' Addresses
|
||||
|
||||
L. Peter Deutsch
|
||||
Aladdin Enterprises
|
||||
203 Santa Margarita Ave.
|
||||
Menlo Park, CA 94025
|
||||
|
||||
Phone: (415) 322-0103 (AM only)
|
||||
FAX: (415) 322-1734
|
||||
EMail: <ghost@aladdin.com>
|
||||
|
||||
|
||||
Jean-Loup Gailly
|
||||
|
||||
EMail: <gzip@prep.ai.mit.edu>
|
||||
|
||||
Questions about the technical content of this specification can be
|
||||
sent by email to
|
||||
|
||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
||||
Mark Adler <madler@alumni.caltech.edu>
|
||||
|
||||
Editorial comments on this specification can be sent by email to
|
||||
|
||||
L. Peter Deutsch <ghost@aladdin.com> and
|
||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 8]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
8. Appendix: Rationale
|
||||
|
||||
8.1. Preset dictionaries
|
||||
|
||||
A preset dictionary is specially useful to compress short input
|
||||
sequences. The compressor can take advantage of the dictionary
|
||||
context to encode the input in a more compact manner. The
|
||||
decompressor can be initialized with the appropriate context by
|
||||
virtually decompressing a compressed version of the dictionary
|
||||
without producing any output. However for certain compression
|
||||
algorithms such as the deflate algorithm this operation can be
|
||||
achieved without actually performing any decompression.
|
||||
|
||||
The compressor and the decompressor must use exactly the same
|
||||
dictionary. The dictionary may be fixed or may be chosen among a
|
||||
certain number of predefined dictionaries, according to the kind
|
||||
of input data. The decompressor can determine which dictionary has
|
||||
been chosen by the compressor by checking the dictionary
|
||||
identifier. This document does not specify the contents of
|
||||
predefined dictionaries, since the optimal dictionaries are
|
||||
application specific. Standard data formats using this feature of
|
||||
the zlib specification must precisely define the allowed
|
||||
dictionaries.
|
||||
|
||||
8.2. The Adler-32 algorithm
|
||||
|
||||
The Adler-32 algorithm is much faster than the CRC32 algorithm yet
|
||||
still provides an extremely low probability of undetected errors.
|
||||
|
||||
The modulo on unsigned long accumulators can be delayed for 5552
|
||||
bytes, so the modulo operation time is negligible. If the bytes
|
||||
are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
|
||||
and order sensitive, unlike the first sum, which is just a
|
||||
checksum. That 65521 is prime is important to avoid a possible
|
||||
large class of two-byte errors that leave the check unchanged.
|
||||
(The Fletcher checksum uses 255, which is not prime and which also
|
||||
makes the Fletcher check insensitive to single byte changes 0 <->
|
||||
255.)
|
||||
|
||||
The sum s1 is initialized to 1 instead of zero to make the length
|
||||
of the sequence part of s2, so that the length does not have to be
|
||||
checked separately. (Any sequence of zeroes has a Fletcher
|
||||
checksum of zero.)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 9]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
9. Appendix: Sample code
|
||||
|
||||
The following C code computes the Adler-32 checksum of a data buffer.
|
||||
It is written for clarity, not for speed. The sample code is in the
|
||||
ANSI C programming language. Non C users may find it easier to read
|
||||
with these hints:
|
||||
|
||||
& Bitwise AND operator.
|
||||
>> Bitwise right shift operator. When applied to an
|
||||
unsigned quantity, as here, right shift inserts zero bit(s)
|
||||
at the left.
|
||||
<< Bitwise left shift operator. Left shift inserts zero
|
||||
bit(s) at the right.
|
||||
++ "n++" increments the variable n.
|
||||
% modulo operator: a % b is the remainder of a divided by b.
|
||||
|
||||
#define BASE 65521 /* largest prime smaller than 65536 */
|
||||
|
||||
/*
|
||||
Update a running Adler-32 checksum with the bytes buf[0..len-1]
|
||||
and return the updated checksum. The Adler-32 checksum should be
|
||||
initialized to 1.
|
||||
|
||||
Usage example:
|
||||
|
||||
unsigned long adler = 1L;
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
adler = update_adler32(adler, buffer, length);
|
||||
}
|
||||
if (adler != original_adler) error();
|
||||
*/
|
||||
unsigned long update_adler32(unsigned long adler,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
unsigned long s1 = adler & 0xffff;
|
||||
unsigned long s2 = (adler >> 16) & 0xffff;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < len; n++) {
|
||||
s1 = (s1 + buf[n]) % BASE;
|
||||
s2 = (s2 + s1) % BASE;
|
||||
}
|
||||
return (s2 << 16) + s1;
|
||||
}
|
||||
|
||||
/* Return the adler32 of the bytes buf[0..len-1] */
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 10]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
unsigned long adler32(unsigned char *buf, int len)
|
||||
{
|
||||
return update_adler32(1L, buf, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 11]
|
||||
|
||||
@@ -1,955 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group P. Deutsch
|
||||
Request for Comments: 1951 Aladdin Enterprises
|
||||
Category: Informational May 1996
|
||||
|
||||
|
||||
DEFLATE Compressed Data Format Specification version 1.3
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. This memo
|
||||
does not specify an Internet standard of any kind. Distribution of
|
||||
this memo is unlimited.
|
||||
|
||||
IESG Note:
|
||||
|
||||
The IESG takes no position on the validity of any Intellectual
|
||||
Property Rights statements contained in this document.
|
||||
|
||||
Notices
|
||||
|
||||
Copyright (c) 1996 L. Peter Deutsch
|
||||
|
||||
Permission is granted to copy and distribute this document for any
|
||||
purpose and without charge, including translations into other
|
||||
languages and incorporation into compilations, provided that the
|
||||
copyright notice and this notice are preserved, and that any
|
||||
substantive changes or deletions from the original are clearly
|
||||
marked.
|
||||
|
||||
A pointer to the latest version of this and related documentation in
|
||||
HTML format can be found at the URL
|
||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines a lossless compressed data format that
|
||||
compresses data using a combination of the LZ77 algorithm and Huffman
|
||||
coding, with efficiency comparable to the best currently available
|
||||
general-purpose compression methods. The data can be produced or
|
||||
consumed, even for an arbitrarily long sequentially presented input
|
||||
data stream, using only an a priori bounded amount of intermediate
|
||||
storage. The format can be implemented readily in a manner not
|
||||
covered by patents.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 1]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ................................................... 2
|
||||
1.1. Purpose ................................................... 2
|
||||
1.2. Intended audience ......................................... 3
|
||||
1.3. Scope ..................................................... 3
|
||||
1.4. Compliance ................................................ 3
|
||||
1.5. Definitions of terms and conventions used ................ 3
|
||||
1.6. Changes from previous versions ............................ 4
|
||||
2. Compressed representation overview ............................. 4
|
||||
3. Detailed specification ......................................... 5
|
||||
3.1. Overall conventions ....................................... 5
|
||||
3.1.1. Packing into bytes .................................. 5
|
||||
3.2. Compressed block format ................................... 6
|
||||
3.2.1. Synopsis of prefix and Huffman coding ............... 6
|
||||
3.2.2. Use of Huffman coding in the "deflate" format ....... 7
|
||||
3.2.3. Details of block format ............................. 9
|
||||
3.2.4. Non-compressed blocks (BTYPE=00) ................... 11
|
||||
3.2.5. Compressed blocks (length and distance codes) ...... 11
|
||||
3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12
|
||||
3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13
|
||||
3.3. Compliance ............................................... 14
|
||||
4. Compression algorithm details ................................. 14
|
||||
5. References .................................................... 16
|
||||
6. Security Considerations ....................................... 16
|
||||
7. Source code ................................................... 16
|
||||
8. Acknowledgements .............................................. 16
|
||||
9. Author's Address .............................................. 17
|
||||
|
||||
1. Introduction
|
||||
|
||||
1.1. Purpose
|
||||
|
||||
The purpose of this specification is to define a lossless
|
||||
compressed data format that:
|
||||
* Is independent of CPU type, operating system, file system,
|
||||
and character set, and hence can be used for interchange;
|
||||
* Can be produced or consumed, even for an arbitrarily long
|
||||
sequentially presented input data stream, using only an a
|
||||
priori bounded amount of intermediate storage, and hence
|
||||
can be used in data communications or similar structures
|
||||
such as Unix filters;
|
||||
* Compresses data with efficiency comparable to the best
|
||||
currently available general-purpose compression methods,
|
||||
and in particular considerably better than the "compress"
|
||||
program;
|
||||
* Can be implemented readily in a manner not covered by
|
||||
patents, and hence can be practiced freely;
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 2]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
* Is compatible with the file format produced by the current
|
||||
widely used gzip utility, in that conforming decompressors
|
||||
will be able to read data produced by the existing gzip
|
||||
compressor.
|
||||
|
||||
The data format defined by this specification does not attempt to:
|
||||
|
||||
* Allow random access to compressed data;
|
||||
* Compress specialized data (e.g., raster graphics) as well
|
||||
as the best currently available specialized algorithms.
|
||||
|
||||
A simple counting argument shows that no lossless compression
|
||||
algorithm can compress every possible input data set. For the
|
||||
format defined here, the worst case expansion is 5 bytes per 32K-
|
||||
byte block, i.e., a size increase of 0.015% for large data sets.
|
||||
English text usually compresses by a factor of 2.5 to 3;
|
||||
executable files usually compress somewhat less; graphical data
|
||||
such as raster images may compress much more.
|
||||
|
||||
1.2. Intended audience
|
||||
|
||||
This specification is intended for use by implementors of software
|
||||
to compress data into "deflate" format and/or decompress data from
|
||||
"deflate" format.
|
||||
|
||||
The text of the specification assumes a basic background in
|
||||
programming at the level of bits and other primitive data
|
||||
representations. Familiarity with the technique of Huffman coding
|
||||
is helpful but not required.
|
||||
|
||||
1.3. Scope
|
||||
|
||||
The specification specifies a method for representing a sequence
|
||||
of bytes as a (usually shorter) sequence of bits, and a method for
|
||||
packing the latter bit sequence into bytes.
|
||||
|
||||
1.4. Compliance
|
||||
|
||||
Unless otherwise indicated below, a compliant decompressor must be
|
||||
able to accept and decompress any data set that conforms to all
|
||||
the specifications presented here; a compliant compressor must
|
||||
produce data sets that conform to all the specifications presented
|
||||
here.
|
||||
|
||||
1.5. Definitions of terms and conventions used
|
||||
|
||||
Byte: 8 bits stored or transmitted as a unit (same as an octet).
|
||||
For this specification, a byte is exactly 8 bits, even on machines
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 3]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
which store a character on a number of bits different from eight.
|
||||
See below, for the numbering of bits within a byte.
|
||||
|
||||
String: a sequence of arbitrary bytes.
|
||||
|
||||
1.6. Changes from previous versions
|
||||
|
||||
There have been no technical changes to the deflate format since
|
||||
version 1.1 of this specification. In version 1.2, some
|
||||
terminology was changed. Version 1.3 is a conversion of the
|
||||
specification to RFC style.
|
||||
|
||||
2. Compressed representation overview
|
||||
|
||||
A compressed data set consists of a series of blocks, corresponding
|
||||
to successive blocks of input data. The block sizes are arbitrary,
|
||||
except that non-compressible blocks are limited to 65,535 bytes.
|
||||
|
||||
Each block is compressed using a combination of the LZ77 algorithm
|
||||
and Huffman coding. The Huffman trees for each block are independent
|
||||
of those for previous or subsequent blocks; the LZ77 algorithm may
|
||||
use a reference to a duplicated string occurring in a previous block,
|
||||
up to 32K input bytes before.
|
||||
|
||||
Each block consists of two parts: a pair of Huffman code trees that
|
||||
describe the representation of the compressed data part, and a
|
||||
compressed data part. (The Huffman trees themselves are compressed
|
||||
using Huffman encoding.) The compressed data consists of a series of
|
||||
elements of two types: literal bytes (of strings that have not been
|
||||
detected as duplicated within the previous 32K input bytes), and
|
||||
pointers to duplicated strings, where a pointer is represented as a
|
||||
pair <length, backward distance>. The representation used in the
|
||||
"deflate" format limits distances to 32K bytes and lengths to 258
|
||||
bytes, but does not limit the size of a block, except for
|
||||
uncompressible blocks, which are limited as noted above.
|
||||
|
||||
Each type of value (literals, distances, and lengths) in the
|
||||
compressed data is represented using a Huffman code, using one code
|
||||
tree for literals and lengths and a separate code tree for distances.
|
||||
The code trees for each block appear in a compact form just before
|
||||
the compressed data for that block.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 4]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
3. Detailed specification
|
||||
|
||||
3.1. Overall conventions In the diagrams below, a box like this:
|
||||
|
||||
+---+
|
||||
| | <-- the vertical bars might be missing
|
||||
+---+
|
||||
|
||||
represents one byte; a box like this:
|
||||
|
||||
+==============+
|
||||
| |
|
||||
+==============+
|
||||
|
||||
represents a variable number of bytes.
|
||||
|
||||
Bytes stored within a computer do not have a "bit order", since
|
||||
they are always treated as a unit. However, a byte considered as
|
||||
an integer between 0 and 255 does have a most- and least-
|
||||
significant bit, and since we write numbers with the most-
|
||||
significant digit on the left, we also write bytes with the most-
|
||||
significant bit on the left. In the diagrams below, we number the
|
||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
||||
the bits are numbered:
|
||||
|
||||
+--------+
|
||||
|76543210|
|
||||
+--------+
|
||||
|
||||
Within a computer, a number may occupy multiple bytes. All
|
||||
multi-byte numbers in the format described here are stored with
|
||||
the least-significant byte first (at the lower memory address).
|
||||
For example, the decimal number 520 is stored as:
|
||||
|
||||
0 1
|
||||
+--------+--------+
|
||||
|00001000|00000010|
|
||||
+--------+--------+
|
||||
^ ^
|
||||
| |
|
||||
| + more significant byte = 2 x 256
|
||||
+ less significant byte = 8
|
||||
|
||||
3.1.1. Packing into bytes
|
||||
|
||||
This document does not address the issue of the order in which
|
||||
bits of a byte are transmitted on a bit-sequential medium,
|
||||
since the final data format described here is byte- rather than
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 5]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
bit-oriented. However, we describe the compressed block format
|
||||
in below, as a sequence of data elements of various bit
|
||||
lengths, not a sequence of bytes. We must therefore specify
|
||||
how to pack these data elements into bytes to form the final
|
||||
compressed byte sequence:
|
||||
|
||||
* Data elements are packed into bytes in order of
|
||||
increasing bit number within the byte, i.e., starting
|
||||
with the least-significant bit of the byte.
|
||||
* Data elements other than Huffman codes are packed
|
||||
starting with the least-significant bit of the data
|
||||
element.
|
||||
* Huffman codes are packed starting with the most-
|
||||
significant bit of the code.
|
||||
|
||||
In other words, if one were to print out the compressed data as
|
||||
a sequence of bytes, starting with the first byte at the
|
||||
*right* margin and proceeding to the *left*, with the most-
|
||||
significant bit of each byte on the left as usual, one would be
|
||||
able to parse the result from right to left, with fixed-width
|
||||
elements in the correct MSB-to-LSB order and Huffman codes in
|
||||
bit-reversed order (i.e., with the first bit of the code in the
|
||||
relative LSB position).
|
||||
|
||||
3.2. Compressed block format
|
||||
|
||||
3.2.1. Synopsis of prefix and Huffman coding
|
||||
|
||||
Prefix coding represents symbols from an a priori known
|
||||
alphabet by bit sequences (codes), one code for each symbol, in
|
||||
a manner such that different symbols may be represented by bit
|
||||
sequences of different lengths, but a parser can always parse
|
||||
an encoded string unambiguously symbol-by-symbol.
|
||||
|
||||
We define a prefix code in terms of a binary tree in which the
|
||||
two edges descending from each non-leaf node are labeled 0 and
|
||||
1 and in which the leaf nodes correspond one-for-one with (are
|
||||
labeled with) the symbols of the alphabet; then the code for a
|
||||
symbol is the sequence of 0's and 1's on the edges leading from
|
||||
the root to the leaf labeled with that symbol. For example:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 6]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
/\ Symbol Code
|
||||
0 1 ------ ----
|
||||
/ \ A 00
|
||||
/\ B B 1
|
||||
0 1 C 011
|
||||
/ \ D 010
|
||||
A /\
|
||||
0 1
|
||||
/ \
|
||||
D C
|
||||
|
||||
A parser can decode the next symbol from an encoded input
|
||||
stream by walking down the tree from the root, at each step
|
||||
choosing the edge corresponding to the next input bit.
|
||||
|
||||
Given an alphabet with known symbol frequencies, the Huffman
|
||||
algorithm allows the construction of an optimal prefix code
|
||||
(one which represents strings with those symbol frequencies
|
||||
using the fewest bits of any possible prefix codes for that
|
||||
alphabet). Such a code is called a Huffman code. (See
|
||||
reference [1] in Chapter 5, references for additional
|
||||
information on Huffman codes.)
|
||||
|
||||
Note that in the "deflate" format, the Huffman codes for the
|
||||
various alphabets must not exceed certain maximum code lengths.
|
||||
This constraint complicates the algorithm for computing code
|
||||
lengths from symbol frequencies. Again, see Chapter 5,
|
||||
references for details.
|
||||
|
||||
3.2.2. Use of Huffman coding in the "deflate" format
|
||||
|
||||
The Huffman codes used for each alphabet in the "deflate"
|
||||
format have two additional rules:
|
||||
|
||||
* All codes of a given bit length have lexicographically
|
||||
consecutive values, in the same order as the symbols
|
||||
they represent;
|
||||
|
||||
* Shorter codes lexicographically precede longer codes.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 7]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
We could recode the example above to follow this rule as
|
||||
follows, assuming that the order of the alphabet is ABCD:
|
||||
|
||||
Symbol Code
|
||||
------ ----
|
||||
A 10
|
||||
B 0
|
||||
C 110
|
||||
D 111
|
||||
|
||||
I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are
|
||||
lexicographically consecutive.
|
||||
|
||||
Given this rule, we can define the Huffman code for an alphabet
|
||||
just by giving the bit lengths of the codes for each symbol of
|
||||
the alphabet in order; this is sufficient to determine the
|
||||
actual codes. In our example, the code is completely defined
|
||||
by the sequence of bit lengths (2, 1, 3, 3). The following
|
||||
algorithm generates the codes as integers, intended to be read
|
||||
from most- to least-significant bit. The code lengths are
|
||||
initially in tree[I].Len; the codes are produced in
|
||||
tree[I].Code.
|
||||
|
||||
1) Count the number of codes for each code length. Let
|
||||
bl_count[N] be the number of codes of length N, N >= 1.
|
||||
|
||||
2) Find the numerical value of the smallest code for each
|
||||
code length:
|
||||
|
||||
code = 0;
|
||||
bl_count[0] = 0;
|
||||
for (bits = 1; bits <= MAX_BITS; bits++) {
|
||||
code = (code + bl_count[bits-1]) << 1;
|
||||
next_code[bits] = code;
|
||||
}
|
||||
|
||||
3) Assign numerical values to all codes, using consecutive
|
||||
values for all codes of the same length with the base
|
||||
values determined at step 2. Codes that are never used
|
||||
(which have a bit length of zero) must not be assigned a
|
||||
value.
|
||||
|
||||
for (n = 0; n <= max_code; n++) {
|
||||
len = tree[n].Len;
|
||||
if (len != 0) {
|
||||
tree[n].Code = next_code[len];
|
||||
next_code[len]++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 8]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
}
|
||||
|
||||
Example:
|
||||
|
||||
Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3,
|
||||
3, 2, 4, 4). After step 1, we have:
|
||||
|
||||
N bl_count[N]
|
||||
- -----------
|
||||
2 1
|
||||
3 5
|
||||
4 2
|
||||
|
||||
Step 2 computes the following next_code values:
|
||||
|
||||
N next_code[N]
|
||||
- ------------
|
||||
1 0
|
||||
2 0
|
||||
3 2
|
||||
4 14
|
||||
|
||||
Step 3 produces the following code values:
|
||||
|
||||
Symbol Length Code
|
||||
------ ------ ----
|
||||
A 3 010
|
||||
B 3 011
|
||||
C 3 100
|
||||
D 3 101
|
||||
E 3 110
|
||||
F 2 00
|
||||
G 4 1110
|
||||
H 4 1111
|
||||
|
||||
3.2.3. Details of block format
|
||||
|
||||
Each block of compressed data begins with 3 header bits
|
||||
containing the following data:
|
||||
|
||||
first bit BFINAL
|
||||
next 2 bits BTYPE
|
||||
|
||||
Note that the header bits do not necessarily begin on a byte
|
||||
boundary, since a block does not necessarily occupy an integral
|
||||
number of bytes.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 9]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
BFINAL is set if and only if this is the last block of the data
|
||||
set.
|
||||
|
||||
BTYPE specifies how the data are compressed, as follows:
|
||||
|
||||
00 - no compression
|
||||
01 - compressed with fixed Huffman codes
|
||||
10 - compressed with dynamic Huffman codes
|
||||
11 - reserved (error)
|
||||
|
||||
The only difference between the two compressed cases is how the
|
||||
Huffman codes for the literal/length and distance alphabets are
|
||||
defined.
|
||||
|
||||
In all cases, the decoding algorithm for the actual data is as
|
||||
follows:
|
||||
|
||||
do
|
||||
read block header from input stream.
|
||||
if stored with no compression
|
||||
skip any remaining bits in current partially
|
||||
processed byte
|
||||
read LEN and NLEN (see next section)
|
||||
copy LEN bytes of data to output
|
||||
otherwise
|
||||
if compressed with dynamic Huffman codes
|
||||
read representation of code trees (see
|
||||
subsection below)
|
||||
loop (until end of block code recognized)
|
||||
decode literal/length value from input stream
|
||||
if value < 256
|
||||
copy value (literal byte) to output stream
|
||||
otherwise
|
||||
if value = end of block (256)
|
||||
break from loop
|
||||
otherwise (value = 257..285)
|
||||
decode distance from input stream
|
||||
|
||||
move backwards distance bytes in the output
|
||||
stream, and copy length bytes from this
|
||||
position to the output stream.
|
||||
end loop
|
||||
while not last block
|
||||
|
||||
Note that a duplicated string reference may refer to a string
|
||||
in a previous block; i.e., the backward distance may cross one
|
||||
or more block boundaries. However a distance cannot refer past
|
||||
the beginning of the output stream. (An application using a
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 10]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
preset dictionary might discard part of the output stream; a
|
||||
distance can refer to that part of the output stream anyway)
|
||||
Note also that the referenced string may overlap the current
|
||||
position; for example, if the last 2 bytes decoded have values
|
||||
X and Y, a string reference with <length = 5, distance = 2>
|
||||
adds X,Y,X,Y,X to the output stream.
|
||||
|
||||
We now specify each compression method in turn.
|
||||
|
||||
3.2.4. Non-compressed blocks (BTYPE=00)
|
||||
|
||||
Any bits of input up to the next byte boundary are ignored.
|
||||
The rest of the block consists of the following information:
|
||||
|
||||
0 1 2 3 4...
|
||||
+---+---+---+---+================================+
|
||||
| LEN | NLEN |... LEN bytes of literal data...|
|
||||
+---+---+---+---+================================+
|
||||
|
||||
LEN is the number of data bytes in the block. NLEN is the
|
||||
one's complement of LEN.
|
||||
|
||||
3.2.5. Compressed blocks (length and distance codes)
|
||||
|
||||
As noted above, encoded data blocks in the "deflate" format
|
||||
consist of sequences of symbols drawn from three conceptually
|
||||
distinct alphabets: either literal bytes, from the alphabet of
|
||||
byte values (0..255), or <length, backward distance> pairs,
|
||||
where the length is drawn from (3..258) and the distance is
|
||||
drawn from (1..32,768). In fact, the literal and length
|
||||
alphabets are merged into a single alphabet (0..285), where
|
||||
values 0..255 represent literal bytes, the value 256 indicates
|
||||
end-of-block, and values 257..285 represent length codes
|
||||
(possibly in conjunction with extra bits following the symbol
|
||||
code) as follows:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 11]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
Extra Extra Extra
|
||||
Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
||||
---- ---- ------ ---- ---- ------- ---- ---- -------
|
||||
257 0 3 267 1 15,16 277 4 67-82
|
||||
258 0 4 268 1 17,18 278 4 83-98
|
||||
259 0 5 269 2 19-22 279 4 99-114
|
||||
260 0 6 270 2 23-26 280 4 115-130
|
||||
261 0 7 271 2 27-30 281 5 131-162
|
||||
262 0 8 272 2 31-34 282 5 163-194
|
||||
263 0 9 273 3 35-42 283 5 195-226
|
||||
264 0 10 274 3 43-50 284 5 227-257
|
||||
265 1 11,12 275 3 51-58 285 0 258
|
||||
266 1 13,14 276 3 59-66
|
||||
|
||||
The extra bits should be interpreted as a machine integer
|
||||
stored with the most-significant bit first, e.g., bits 1110
|
||||
represent the value 14.
|
||||
|
||||
Extra Extra Extra
|
||||
Code Bits Dist Code Bits Dist Code Bits Distance
|
||||
---- ---- ---- ---- ---- ------ ---- ---- --------
|
||||
0 0 1 10 4 33-48 20 9 1025-1536
|
||||
1 0 2 11 4 49-64 21 9 1537-2048
|
||||
2 0 3 12 5 65-96 22 10 2049-3072
|
||||
3 0 4 13 5 97-128 23 10 3073-4096
|
||||
4 1 5,6 14 6 129-192 24 11 4097-6144
|
||||
5 1 7,8 15 6 193-256 25 11 6145-8192
|
||||
6 2 9-12 16 7 257-384 26 12 8193-12288
|
||||
7 2 13-16 17 7 385-512 27 12 12289-16384
|
||||
8 3 17-24 18 8 513-768 28 13 16385-24576
|
||||
9 3 25-32 19 8 769-1024 29 13 24577-32768
|
||||
|
||||
3.2.6. Compression with fixed Huffman codes (BTYPE=01)
|
||||
|
||||
The Huffman codes for the two alphabets are fixed, and are not
|
||||
represented explicitly in the data. The Huffman code lengths
|
||||
for the literal/length alphabet are:
|
||||
|
||||
Lit Value Bits Codes
|
||||
--------- ---- -----
|
||||
0 - 143 8 00110000 through
|
||||
10111111
|
||||
144 - 255 9 110010000 through
|
||||
111111111
|
||||
256 - 279 7 0000000 through
|
||||
0010111
|
||||
280 - 287 8 11000000 through
|
||||
11000111
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 12]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
The code lengths are sufficient to generate the actual codes,
|
||||
as described above; we show the codes in the table for added
|
||||
clarity. Literal/length values 286-287 will never actually
|
||||
occur in the compressed data, but participate in the code
|
||||
construction.
|
||||
|
||||
Distance codes 0-31 are represented by (fixed-length) 5-bit
|
||||
codes, with possible additional bits as shown in the table
|
||||
shown in Paragraph 3.2.5, above. Note that distance codes 30-
|
||||
31 will never actually occur in the compressed data.
|
||||
|
||||
3.2.7. Compression with dynamic Huffman codes (BTYPE=10)
|
||||
|
||||
The Huffman codes for the two alphabets appear in the block
|
||||
immediately after the header bits and before the actual
|
||||
compressed data, first the literal/length code and then the
|
||||
distance code. Each code is defined by a sequence of code
|
||||
lengths, as discussed in Paragraph 3.2.2, above. For even
|
||||
greater compactness, the code length sequences themselves are
|
||||
compressed using a Huffman code. The alphabet for code lengths
|
||||
is as follows:
|
||||
|
||||
0 - 15: Represent code lengths of 0 - 15
|
||||
16: Copy the previous code length 3 - 6 times.
|
||||
The next 2 bits indicate repeat length
|
||||
(0 = 3, ... , 3 = 6)
|
||||
Example: Codes 8, 16 (+2 bits 11),
|
||||
16 (+2 bits 10) will expand to
|
||||
12 code lengths of 8 (1 + 6 + 5)
|
||||
17: Repeat a code length of 0 for 3 - 10 times.
|
||||
(3 bits of length)
|
||||
18: Repeat a code length of 0 for 11 - 138 times
|
||||
(7 bits of length)
|
||||
|
||||
A code length of 0 indicates that the corresponding symbol in
|
||||
the literal/length or distance alphabet will not occur in the
|
||||
block, and should not participate in the Huffman code
|
||||
construction algorithm given earlier. If only one distance
|
||||
code is used, it is encoded using one bit, not zero bits; in
|
||||
this case there is a single code length of one, with one unused
|
||||
code. One distance code of zero bits means that there are no
|
||||
distance codes used at all (the data is all literals).
|
||||
|
||||
We can now define the format of the block:
|
||||
|
||||
5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
|
||||
5 Bits: HDIST, # of Distance codes - 1 (1 - 32)
|
||||
4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19)
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 13]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
(HCLEN + 4) x 3 bits: code lengths for the code length
|
||||
alphabet given just above, in the order: 16, 17, 18,
|
||||
0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
|
||||
These code lengths are interpreted as 3-bit integers
|
||||
(0-7); as above, a code length of 0 means the
|
||||
corresponding symbol (literal/length or distance code
|
||||
length) is not used.
|
||||
|
||||
HLIT + 257 code lengths for the literal/length alphabet,
|
||||
encoded using the code length Huffman code
|
||||
|
||||
HDIST + 1 code lengths for the distance alphabet,
|
||||
encoded using the code length Huffman code
|
||||
|
||||
The actual compressed data of the block,
|
||||
encoded using the literal/length and distance Huffman
|
||||
codes
|
||||
|
||||
The literal/length symbol 256 (end of data),
|
||||
encoded using the literal/length Huffman code
|
||||
|
||||
The code length repeat codes can cross from HLIT + 257 to the
|
||||
HDIST + 1 code lengths. In other words, all code lengths form
|
||||
a single sequence of HLIT + HDIST + 258 values.
|
||||
|
||||
3.3. Compliance
|
||||
|
||||
A compressor may limit further the ranges of values specified in
|
||||
the previous section and still be compliant; for example, it may
|
||||
limit the range of backward pointers to some value smaller than
|
||||
32K. Similarly, a compressor may limit the size of blocks so that
|
||||
a compressible block fits in memory.
|
||||
|
||||
A compliant decompressor must accept the full range of possible
|
||||
values defined in the previous section, and must accept blocks of
|
||||
arbitrary size.
|
||||
|
||||
4. Compression algorithm details
|
||||
|
||||
While it is the intent of this document to define the "deflate"
|
||||
compressed data format without reference to any particular
|
||||
compression algorithm, the format is related to the compressed
|
||||
formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below);
|
||||
since many variations of LZ77 are patented, it is strongly
|
||||
recommended that the implementor of a compressor follow the general
|
||||
algorithm presented here, which is known not to be patented per se.
|
||||
The material in this section is not part of the definition of the
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 14]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
specification per se, and a compressor need not follow it in order to
|
||||
be compliant.
|
||||
|
||||
The compressor terminates a block when it determines that starting a
|
||||
new block with fresh trees would be useful, or when the block size
|
||||
fills up the compressor's block buffer.
|
||||
|
||||
The compressor uses a chained hash table to find duplicated strings,
|
||||
using a hash function that operates on 3-byte sequences. At any
|
||||
given point during compression, let XYZ be the next 3 input bytes to
|
||||
be examined (not necessarily all different, of course). First, the
|
||||
compressor examines the hash chain for XYZ. If the chain is empty,
|
||||
the compressor simply writes out X as a literal byte and advances one
|
||||
byte in the input. If the hash chain is not empty, indicating that
|
||||
the sequence XYZ (or, if we are unlucky, some other 3 bytes with the
|
||||
same hash function value) has occurred recently, the compressor
|
||||
compares all strings on the XYZ hash chain with the actual input data
|
||||
sequence starting at the current point, and selects the longest
|
||||
match.
|
||||
|
||||
The compressor searches the hash chains starting with the most recent
|
||||
strings, to favor small distances and thus take advantage of the
|
||||
Huffman encoding. The hash chains are singly linked. There are no
|
||||
deletions from the hash chains; the algorithm simply discards matches
|
||||
that are too old. To avoid a worst-case situation, very long hash
|
||||
chains are arbitrarily truncated at a certain length, determined by a
|
||||
run-time parameter.
|
||||
|
||||
To improve overall compression, the compressor optionally defers the
|
||||
selection of matches ("lazy matching"): after a match of length N has
|
||||
been found, the compressor searches for a longer match starting at
|
||||
the next input byte. If it finds a longer match, it truncates the
|
||||
previous match to a length of one (thus producing a single literal
|
||||
byte) and then emits the longer match. Otherwise, it emits the
|
||||
original match, and, as described above, advances N bytes before
|
||||
continuing.
|
||||
|
||||
Run-time parameters also control this "lazy match" procedure. If
|
||||
compression ratio is most important, the compressor attempts a
|
||||
complete second search regardless of the length of the first match.
|
||||
In the normal case, if the current match is "long enough", the
|
||||
compressor reduces the search for a longer match, thus speeding up
|
||||
the process. If speed is most important, the compressor inserts new
|
||||
strings in the hash table only when no match was found, or when the
|
||||
match is not "too long". This degrades the compression ratio but
|
||||
saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 15]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
5. References
|
||||
|
||||
[1] Huffman, D. A., "A Method for the Construction of Minimum
|
||||
Redundancy Codes", Proceedings of the Institute of Radio
|
||||
Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101.
|
||||
|
||||
[2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
|
||||
Compression", IEEE Transactions on Information Theory, Vol. 23,
|
||||
No. 3, pp. 337-343.
|
||||
|
||||
[3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources,
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[4] Gailly, J.-L., and Adler, M., GZIP documentation and sources,
|
||||
available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/
|
||||
|
||||
[5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix
|
||||
encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169.
|
||||
|
||||
[6] Hirschberg and Lelewer, "Efficient decoding of prefix codes,"
|
||||
Comm. ACM, 33,4, April 1990, pp. 449-459.
|
||||
|
||||
6. Security Considerations
|
||||
|
||||
Any data compression method involves the reduction of redundancy in
|
||||
the data. Consequently, any corruption of the data is likely to have
|
||||
severe effects and be difficult to correct. Uncompressed text, on
|
||||
the other hand, will probably still be readable despite the presence
|
||||
of some corrupted bytes.
|
||||
|
||||
It is recommended that systems using this data format provide some
|
||||
means of validating the integrity of the compressed data. See
|
||||
reference [3], for example.
|
||||
|
||||
7. Source code
|
||||
|
||||
Source code for a C language implementation of a "deflate" compliant
|
||||
compressor and decompressor is available within the zlib package at
|
||||
ftp://ftp.uu.net/pub/archiving/zip/zlib/.
|
||||
|
||||
8. Acknowledgements
|
||||
|
||||
Trademarks cited in this document are the property of their
|
||||
respective owners.
|
||||
|
||||
Phil Katz designed the deflate format. Jean-Loup Gailly and Mark
|
||||
Adler wrote the related software described in this specification.
|
||||
Glenn Randers-Pehrson converted this document to RFC and HTML format.
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 16]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
9. Author's Address
|
||||
|
||||
L. Peter Deutsch
|
||||
Aladdin Enterprises
|
||||
203 Santa Margarita Ave.
|
||||
Menlo Park, CA 94025
|
||||
|
||||
Phone: (415) 322-0103 (AM only)
|
||||
FAX: (415) 322-1734
|
||||
EMail: <ghost@aladdin.com>
|
||||
|
||||
Questions about the technical content of this specification can be
|
||||
sent by email to:
|
||||
|
||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
||||
Mark Adler <madler@alumni.caltech.edu>
|
||||
|
||||
Editorial comments on this specification can be sent by email to:
|
||||
|
||||
L. Peter Deutsch <ghost@aladdin.com> and
|
||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 17]
|
||||
|
||||
@@ -1,675 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group P. Deutsch
|
||||
Request for Comments: 1952 Aladdin Enterprises
|
||||
Category: Informational May 1996
|
||||
|
||||
|
||||
GZIP file format specification version 4.3
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. This memo
|
||||
does not specify an Internet standard of any kind. Distribution of
|
||||
this memo is unlimited.
|
||||
|
||||
IESG Note:
|
||||
|
||||
The IESG takes no position on the validity of any Intellectual
|
||||
Property Rights statements contained in this document.
|
||||
|
||||
Notices
|
||||
|
||||
Copyright (c) 1996 L. Peter Deutsch
|
||||
|
||||
Permission is granted to copy and distribute this document for any
|
||||
purpose and without charge, including translations into other
|
||||
languages and incorporation into compilations, provided that the
|
||||
copyright notice and this notice are preserved, and that any
|
||||
substantive changes or deletions from the original are clearly
|
||||
marked.
|
||||
|
||||
A pointer to the latest version of this and related documentation in
|
||||
HTML format can be found at the URL
|
||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines a lossless compressed data format that is
|
||||
compatible with the widely used GZIP utility. The format includes a
|
||||
cyclic redundancy check value for detecting data corruption. The
|
||||
format presently uses the DEFLATE method of compression but can be
|
||||
easily extended to use other compression methods. The format can be
|
||||
implemented readily in a manner not covered by patents.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 1]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ................................................... 2
|
||||
1.1. Purpose ................................................... 2
|
||||
1.2. Intended audience ......................................... 3
|
||||
1.3. Scope ..................................................... 3
|
||||
1.4. Compliance ................................................ 3
|
||||
1.5. Definitions of terms and conventions used ................. 3
|
||||
1.6. Changes from previous versions ............................ 3
|
||||
2. Detailed specification ......................................... 4
|
||||
2.1. Overall conventions ....................................... 4
|
||||
2.2. File format ............................................... 5
|
||||
2.3. Member format ............................................. 5
|
||||
2.3.1. Member header and trailer ........................... 6
|
||||
2.3.1.1. Extra field ................................... 8
|
||||
2.3.1.2. Compliance .................................... 9
|
||||
3. References .................................................. 9
|
||||
4. Security Considerations .................................... 10
|
||||
5. Acknowledgements ........................................... 10
|
||||
6. Author's Address ........................................... 10
|
||||
7. Appendix: Jean-Loup Gailly's gzip utility .................. 11
|
||||
8. Appendix: Sample CRC Code .................................. 11
|
||||
|
||||
1. Introduction
|
||||
|
||||
1.1. Purpose
|
||||
|
||||
The purpose of this specification is to define a lossless
|
||||
compressed data format that:
|
||||
|
||||
* Is independent of CPU type, operating system, file system,
|
||||
and character set, and hence can be used for interchange;
|
||||
* Can compress or decompress a data stream (as opposed to a
|
||||
randomly accessible file) to produce another data stream,
|
||||
using only an a priori bounded amount of intermediate
|
||||
storage, and hence can be used in data communications or
|
||||
similar structures such as Unix filters;
|
||||
* Compresses data with efficiency comparable to the best
|
||||
currently available general-purpose compression methods,
|
||||
and in particular considerably better than the "compress"
|
||||
program;
|
||||
* Can be implemented readily in a manner not covered by
|
||||
patents, and hence can be practiced freely;
|
||||
* Is compatible with the file format produced by the current
|
||||
widely used gzip utility, in that conforming decompressors
|
||||
will be able to read data produced by the existing gzip
|
||||
compressor.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 2]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
The data format defined by this specification does not attempt to:
|
||||
|
||||
* Provide random access to compressed data;
|
||||
* Compress specialized data (e.g., raster graphics) as well as
|
||||
the best currently available specialized algorithms.
|
||||
|
||||
1.2. Intended audience
|
||||
|
||||
This specification is intended for use by implementors of software
|
||||
to compress data into gzip format and/or decompress data from gzip
|
||||
format.
|
||||
|
||||
The text of the specification assumes a basic background in
|
||||
programming at the level of bits and other primitive data
|
||||
representations.
|
||||
|
||||
1.3. Scope
|
||||
|
||||
The specification specifies a compression method and a file format
|
||||
(the latter assuming only that a file can store a sequence of
|
||||
arbitrary bytes). It does not specify any particular interface to
|
||||
a file system or anything about character sets or encodings
|
||||
(except for file names and comments, which are optional).
|
||||
|
||||
1.4. Compliance
|
||||
|
||||
Unless otherwise indicated below, a compliant decompressor must be
|
||||
able to accept and decompress any file that conforms to all the
|
||||
specifications presented here; a compliant compressor must produce
|
||||
files that conform to all the specifications presented here. The
|
||||
material in the appendices is not part of the specification per se
|
||||
and is not relevant to compliance.
|
||||
|
||||
1.5. Definitions of terms and conventions used
|
||||
|
||||
byte: 8 bits stored or transmitted as a unit (same as an octet).
|
||||
(For this specification, a byte is exactly 8 bits, even on
|
||||
machines which store a character on a number of bits different
|
||||
from 8.) See below for the numbering of bits within a byte.
|
||||
|
||||
1.6. Changes from previous versions
|
||||
|
||||
There have been no technical changes to the gzip format since
|
||||
version 4.1 of this specification. In version 4.2, some
|
||||
terminology was changed, and the sample CRC code was rewritten for
|
||||
clarity and to eliminate the requirement for the caller to do pre-
|
||||
and post-conditioning. Version 4.3 is a conversion of the
|
||||
specification to RFC style.
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 3]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
2. Detailed specification
|
||||
|
||||
2.1. Overall conventions
|
||||
|
||||
In the diagrams below, a box like this:
|
||||
|
||||
+---+
|
||||
| | <-- the vertical bars might be missing
|
||||
+---+
|
||||
|
||||
represents one byte; a box like this:
|
||||
|
||||
+==============+
|
||||
| |
|
||||
+==============+
|
||||
|
||||
represents a variable number of bytes.
|
||||
|
||||
Bytes stored within a computer do not have a "bit order", since
|
||||
they are always treated as a unit. However, a byte considered as
|
||||
an integer between 0 and 255 does have a most- and least-
|
||||
significant bit, and since we write numbers with the most-
|
||||
significant digit on the left, we also write bytes with the most-
|
||||
significant bit on the left. In the diagrams below, we number the
|
||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
||||
the bits are numbered:
|
||||
|
||||
+--------+
|
||||
|76543210|
|
||||
+--------+
|
||||
|
||||
This document does not address the issue of the order in which
|
||||
bits of a byte are transmitted on a bit-sequential medium, since
|
||||
the data format described here is byte- rather than bit-oriented.
|
||||
|
||||
Within a computer, a number may occupy multiple bytes. All
|
||||
multi-byte numbers in the format described here are stored with
|
||||
the least-significant byte first (at the lower memory address).
|
||||
For example, the decimal number 520 is stored as:
|
||||
|
||||
0 1
|
||||
+--------+--------+
|
||||
|00001000|00000010|
|
||||
+--------+--------+
|
||||
^ ^
|
||||
| |
|
||||
| + more significant byte = 2 x 256
|
||||
+ less significant byte = 8
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 4]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
2.2. File format
|
||||
|
||||
A gzip file consists of a series of "members" (compressed data
|
||||
sets). The format of each member is specified in the following
|
||||
section. The members simply appear one after another in the file,
|
||||
with no additional information before, between, or after them.
|
||||
|
||||
2.3. Member format
|
||||
|
||||
Each member has the following structure:
|
||||
|
||||
+---+---+---+---+---+---+---+---+---+---+
|
||||
|ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->)
|
||||
+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
(if FLG.FEXTRA set)
|
||||
|
||||
+---+---+=================================+
|
||||
| XLEN |...XLEN bytes of "extra field"...| (more-->)
|
||||
+---+---+=================================+
|
||||
|
||||
(if FLG.FNAME set)
|
||||
|
||||
+=========================================+
|
||||
|...original file name, zero-terminated...| (more-->)
|
||||
+=========================================+
|
||||
|
||||
(if FLG.FCOMMENT set)
|
||||
|
||||
+===================================+
|
||||
|...file comment, zero-terminated...| (more-->)
|
||||
+===================================+
|
||||
|
||||
(if FLG.FHCRC set)
|
||||
|
||||
+---+---+
|
||||
| CRC16 |
|
||||
+---+---+
|
||||
|
||||
+=======================+
|
||||
|...compressed blocks...| (more-->)
|
||||
+=======================+
|
||||
|
||||
0 1 2 3 4 5 6 7
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| CRC32 | ISIZE |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 5]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
2.3.1. Member header and trailer
|
||||
|
||||
ID1 (IDentification 1)
|
||||
ID2 (IDentification 2)
|
||||
These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139
|
||||
(0x8b, \213), to identify the file as being in gzip format.
|
||||
|
||||
CM (Compression Method)
|
||||
This identifies the compression method used in the file. CM
|
||||
= 0-7 are reserved. CM = 8 denotes the "deflate"
|
||||
compression method, which is the one customarily used by
|
||||
gzip and which is documented elsewhere.
|
||||
|
||||
FLG (FLaGs)
|
||||
This flag byte is divided into individual bits as follows:
|
||||
|
||||
bit 0 FTEXT
|
||||
bit 1 FHCRC
|
||||
bit 2 FEXTRA
|
||||
bit 3 FNAME
|
||||
bit 4 FCOMMENT
|
||||
bit 5 reserved
|
||||
bit 6 reserved
|
||||
bit 7 reserved
|
||||
|
||||
If FTEXT is set, the file is probably ASCII text. This is
|
||||
an optional indication, which the compressor may set by
|
||||
checking a small amount of the input data to see whether any
|
||||
non-ASCII characters are present. In case of doubt, FTEXT
|
||||
is cleared, indicating binary data. For systems which have
|
||||
different file formats for ascii text and binary data, the
|
||||
decompressor can use FTEXT to choose the appropriate format.
|
||||
We deliberately do not specify the algorithm used to set
|
||||
this bit, since a compressor always has the option of
|
||||
leaving it cleared and a decompressor always has the option
|
||||
of ignoring it and letting some other program handle issues
|
||||
of data conversion.
|
||||
|
||||
If FHCRC is set, a CRC16 for the gzip header is present,
|
||||
immediately before the compressed data. The CRC16 consists
|
||||
of the two least significant bytes of the CRC32 for all
|
||||
bytes of the gzip header up to and not including the CRC16.
|
||||
[The FHCRC bit was never set by versions of gzip up to
|
||||
1.2.4, even though it was documented with a different
|
||||
meaning in gzip 1.2.4.]
|
||||
|
||||
If FEXTRA is set, optional extra fields are present, as
|
||||
described in a following section.
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 6]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
If FNAME is set, an original file name is present,
|
||||
terminated by a zero byte. The name must consist of ISO
|
||||
8859-1 (LATIN-1) characters; on operating systems using
|
||||
EBCDIC or any other character set for file names, the name
|
||||
must be translated to the ISO LATIN-1 character set. This
|
||||
is the original name of the file being compressed, with any
|
||||
directory components removed, and, if the file being
|
||||
compressed is on a file system with case insensitive names,
|
||||
forced to lower case. There is no original file name if the
|
||||
data was compressed from a source other than a named file;
|
||||
for example, if the source was stdin on a Unix system, there
|
||||
is no file name.
|
||||
|
||||
If FCOMMENT is set, a zero-terminated file comment is
|
||||
present. This comment is not interpreted; it is only
|
||||
intended for human consumption. The comment must consist of
|
||||
ISO 8859-1 (LATIN-1) characters. Line breaks should be
|
||||
denoted by a single line feed character (10 decimal).
|
||||
|
||||
Reserved FLG bits must be zero.
|
||||
|
||||
MTIME (Modification TIME)
|
||||
This gives the most recent modification time of the original
|
||||
file being compressed. The time is in Unix format, i.e.,
|
||||
seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this
|
||||
may cause problems for MS-DOS and other systems that use
|
||||
local rather than Universal time.) If the compressed data
|
||||
did not come from a file, MTIME is set to the time at which
|
||||
compression started. MTIME = 0 means no time stamp is
|
||||
available.
|
||||
|
||||
XFL (eXtra FLags)
|
||||
These flags are available for use by specific compression
|
||||
methods. The "deflate" method (CM = 8) sets these flags as
|
||||
follows:
|
||||
|
||||
XFL = 2 - compressor used maximum compression,
|
||||
slowest algorithm
|
||||
XFL = 4 - compressor used fastest algorithm
|
||||
|
||||
OS (Operating System)
|
||||
This identifies the type of file system on which compression
|
||||
took place. This may be useful in determining end-of-line
|
||||
convention for text files. The currently defined values are
|
||||
as follows:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 7]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
|
||||
1 - Amiga
|
||||
2 - VMS (or OpenVMS)
|
||||
3 - Unix
|
||||
4 - VM/CMS
|
||||
5 - Atari TOS
|
||||
6 - HPFS filesystem (OS/2, NT)
|
||||
7 - Macintosh
|
||||
8 - Z-System
|
||||
9 - CP/M
|
||||
10 - TOPS-20
|
||||
11 - NTFS filesystem (NT)
|
||||
12 - QDOS
|
||||
13 - Acorn RISCOS
|
||||
255 - unknown
|
||||
|
||||
XLEN (eXtra LENgth)
|
||||
If FLG.FEXTRA is set, this gives the length of the optional
|
||||
extra field. See below for details.
|
||||
|
||||
CRC32 (CRC-32)
|
||||
This contains a Cyclic Redundancy Check value of the
|
||||
uncompressed data computed according to CRC-32 algorithm
|
||||
used in the ISO 3309 standard and in section 8.1.1.6.2 of
|
||||
ITU-T recommendation V.42. (See http://www.iso.ch for
|
||||
ordering ISO documents. See gopher://info.itu.ch for an
|
||||
online version of ITU-T V.42.)
|
||||
|
||||
ISIZE (Input SIZE)
|
||||
This contains the size of the original (uncompressed) input
|
||||
data modulo 2^32.
|
||||
|
||||
2.3.1.1. Extra field
|
||||
|
||||
If the FLG.FEXTRA bit is set, an "extra field" is present in
|
||||
the header, with total length XLEN bytes. It consists of a
|
||||
series of subfields, each of the form:
|
||||
|
||||
+---+---+---+---+==================================+
|
||||
|SI1|SI2| LEN |... LEN bytes of subfield data ...|
|
||||
+---+---+---+---+==================================+
|
||||
|
||||
SI1 and SI2 provide a subfield ID, typically two ASCII letters
|
||||
with some mnemonic value. Jean-Loup Gailly
|
||||
<gzip@prep.ai.mit.edu> is maintaining a registry of subfield
|
||||
IDs; please send him any subfield ID you wish to use. Subfield
|
||||
IDs with SI2 = 0 are reserved for future use. The following
|
||||
IDs are currently defined:
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 8]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
SI1 SI2 Data
|
||||
---------- ---------- ----
|
||||
0x41 ('A') 0x70 ('P') Apollo file type information
|
||||
|
||||
LEN gives the length of the subfield data, excluding the 4
|
||||
initial bytes.
|
||||
|
||||
2.3.1.2. Compliance
|
||||
|
||||
A compliant compressor must produce files with correct ID1,
|
||||
ID2, CM, CRC32, and ISIZE, but may set all the other fields in
|
||||
the fixed-length part of the header to default values (255 for
|
||||
OS, 0 for all others). The compressor must set all reserved
|
||||
bits to zero.
|
||||
|
||||
A compliant decompressor must check ID1, ID2, and CM, and
|
||||
provide an error indication if any of these have incorrect
|
||||
values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC
|
||||
at least so it can skip over the optional fields if they are
|
||||
present. It need not examine any other part of the header or
|
||||
trailer; in particular, a decompressor may ignore FTEXT and OS
|
||||
and always produce binary output, and still be compliant. A
|
||||
compliant decompressor must give an error indication if any
|
||||
reserved bit is non-zero, since such a bit could indicate the
|
||||
presence of a new field that would cause subsequent data to be
|
||||
interpreted incorrectly.
|
||||
|
||||
3. References
|
||||
|
||||
[1] "Information Processing - 8-bit single-byte coded graphic
|
||||
character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987).
|
||||
The ISO 8859-1 (Latin-1) character set is a superset of 7-bit
|
||||
ASCII. Files defining this character set are available as
|
||||
iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/
|
||||
|
||||
[2] ISO 3309
|
||||
|
||||
[3] ITU-T recommendation V.42
|
||||
|
||||
[4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in
|
||||
ftp://prep.ai.mit.edu/pub/gnu/
|
||||
|
||||
[6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table
|
||||
Look-Up", Communications of the ACM, 31(8), pp.1008-1013.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 9]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
[7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal,
|
||||
pp.118-133.
|
||||
|
||||
[8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt,
|
||||
describing the CRC concept.
|
||||
|
||||
4. Security Considerations
|
||||
|
||||
Any data compression method involves the reduction of redundancy in
|
||||
the data. Consequently, any corruption of the data is likely to have
|
||||
severe effects and be difficult to correct. Uncompressed text, on
|
||||
the other hand, will probably still be readable despite the presence
|
||||
of some corrupted bytes.
|
||||
|
||||
It is recommended that systems using this data format provide some
|
||||
means of validating the integrity of the compressed data, such as by
|
||||
setting and checking the CRC-32 check value.
|
||||
|
||||
5. Acknowledgements
|
||||
|
||||
Trademarks cited in this document are the property of their
|
||||
respective owners.
|
||||
|
||||
Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler,
|
||||
the related software described in this specification. Glenn
|
||||
Randers-Pehrson converted this document to RFC and HTML format.
|
||||
|
||||
6. Author's Address
|
||||
|
||||
L. Peter Deutsch
|
||||
Aladdin Enterprises
|
||||
203 Santa Margarita Ave.
|
||||
Menlo Park, CA 94025
|
||||
|
||||
Phone: (415) 322-0103 (AM only)
|
||||
FAX: (415) 322-1734
|
||||
EMail: <ghost@aladdin.com>
|
||||
|
||||
Questions about the technical content of this specification can be
|
||||
sent by email to:
|
||||
|
||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
||||
Mark Adler <madler@alumni.caltech.edu>
|
||||
|
||||
Editorial comments on this specification can be sent by email to:
|
||||
|
||||
L. Peter Deutsch <ghost@aladdin.com> and
|
||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 10]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
7. Appendix: Jean-Loup Gailly's gzip utility
|
||||
|
||||
The most widely used implementation of gzip compression, and the
|
||||
original documentation on which this specification is based, were
|
||||
created by Jean-Loup Gailly <gzip@prep.ai.mit.edu>. Since this
|
||||
implementation is a de facto standard, we mention some more of its
|
||||
features here. Again, the material in this section is not part of
|
||||
the specification per se, and implementations need not follow it to
|
||||
be compliant.
|
||||
|
||||
When compressing or decompressing a file, gzip preserves the
|
||||
protection, ownership, and modification time attributes on the local
|
||||
file system, since there is no provision for representing protection
|
||||
attributes in the gzip file format itself. Since the file format
|
||||
includes a modification time, the gzip decompressor provides a
|
||||
command line switch that assigns the modification time from the file,
|
||||
rather than the local modification time of the compressed input, to
|
||||
the decompressed output.
|
||||
|
||||
8. Appendix: Sample CRC Code
|
||||
|
||||
The following sample code represents a practical implementation of
|
||||
the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42
|
||||
for a formal specification.)
|
||||
|
||||
The sample code is in the ANSI C programming language. Non C users
|
||||
may find it easier to read with these hints:
|
||||
|
||||
& Bitwise AND operator.
|
||||
^ Bitwise exclusive-OR operator.
|
||||
>> Bitwise right shift operator. When applied to an
|
||||
unsigned quantity, as here, right shift inserts zero
|
||||
bit(s) at the left.
|
||||
! Logical NOT operator.
|
||||
++ "n++" increments the variable n.
|
||||
0xNNN 0x introduces a hexadecimal (base 16) constant.
|
||||
Suffix L indicates a long value (at least 32 bits).
|
||||
|
||||
/* Table of CRCs of all 8-bit messages. */
|
||||
unsigned long crc_table[256];
|
||||
|
||||
/* Flag: has the table been computed? Initially false. */
|
||||
int crc_table_computed = 0;
|
||||
|
||||
/* Make the table for a fast CRC. */
|
||||
void make_crc_table(void)
|
||||
{
|
||||
unsigned long c;
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 11]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
int n, k;
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long) n;
|
||||
for (k = 0; k < 8; k++) {
|
||||
if (c & 1) {
|
||||
c = 0xedb88320L ^ (c >> 1);
|
||||
} else {
|
||||
c = c >> 1;
|
||||
}
|
||||
}
|
||||
crc_table[n] = c;
|
||||
}
|
||||
crc_table_computed = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Update a running crc with the bytes buf[0..len-1] and return
|
||||
the updated crc. The crc should be initialized to zero. Pre- and
|
||||
post-conditioning (one's complement) is performed within this
|
||||
function so it shouldn't be done by the caller. Usage example:
|
||||
|
||||
unsigned long crc = 0L;
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
crc = update_crc(crc, buffer, length);
|
||||
}
|
||||
if (crc != original_crc) error();
|
||||
*/
|
||||
unsigned long update_crc(unsigned long crc,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
unsigned long c = crc ^ 0xffffffffL;
|
||||
int n;
|
||||
|
||||
if (!crc_table_computed)
|
||||
make_crc_table();
|
||||
for (n = 0; n < len; n++) {
|
||||
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
return c ^ 0xffffffffL;
|
||||
}
|
||||
|
||||
/* Return the CRC of the bytes buf[0..len-1]. */
|
||||
unsigned long crc(unsigned char *buf, int len)
|
||||
{
|
||||
return update_crc(0L, buf, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 12]
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
A Fast Method for Identifying Plain Text Files
|
||||
==============================================
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Given a file coming from an unknown source, it is sometimes desirable
|
||||
to find out whether the format of that file is plain text. Although
|
||||
this may appear like a simple task, a fully accurate detection of the
|
||||
file type requires heavy-duty semantic analysis on the file contents.
|
||||
It is, however, possible to obtain satisfactory results by employing
|
||||
various heuristics.
|
||||
|
||||
Previous versions of PKZip and other zip-compatible compression tools
|
||||
were using a crude detection scheme: if more than 80% (4/5) of the bytes
|
||||
found in a certain buffer are within the range [7..127], the file is
|
||||
labeled as plain text, otherwise it is labeled as binary. A prominent
|
||||
limitation of this scheme is the restriction to Latin-based alphabets.
|
||||
Other alphabets, like Greek, Cyrillic or Asian, make extensive use of
|
||||
the bytes within the range [128..255], and texts using these alphabets
|
||||
are most often misidentified by this scheme; in other words, the rate
|
||||
of false negatives is sometimes too high, which means that the recall
|
||||
is low. Another weakness of this scheme is a reduced precision, due to
|
||||
the false positives that may occur when binary files containing large
|
||||
amounts of textual characters are misidentified as plain text.
|
||||
|
||||
In this article we propose a new, simple detection scheme that features
|
||||
a much increased precision and a near-100% recall. This scheme is
|
||||
designed to work on ASCII, Unicode and other ASCII-derived alphabets,
|
||||
and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.)
|
||||
and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings
|
||||
(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however.
|
||||
|
||||
|
||||
The Algorithm
|
||||
-------------
|
||||
|
||||
The algorithm works by dividing the set of bytecodes [0..255] into three
|
||||
categories:
|
||||
- The white list of textual bytecodes:
|
||||
9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255.
|
||||
- The gray list of tolerated bytecodes:
|
||||
7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC).
|
||||
- The black list of undesired, non-textual bytecodes:
|
||||
0 (NUL) to 6, 14 to 31.
|
||||
|
||||
If a file contains at least one byte that belongs to the white list and
|
||||
no byte that belongs to the black list, then the file is categorized as
|
||||
plain text; otherwise, it is categorized as binary. (The boundary case,
|
||||
when the file is empty, automatically falls into the latter category.)
|
||||
|
||||
|
||||
Rationale
|
||||
---------
|
||||
|
||||
The idea behind this algorithm relies on two observations.
|
||||
|
||||
The first observation is that, although the full range of 7-bit codes
|
||||
[0..127] is properly specified by the ASCII standard, most control
|
||||
characters in the range [0..31] are not used in practice. The only
|
||||
widely-used, almost universally-portable control codes are 9 (TAB),
|
||||
10 (LF) and 13 (CR). There are a few more control codes that are
|
||||
recognized on a reduced range of platforms and text viewers/editors:
|
||||
7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these
|
||||
codes are rarely (if ever) used alone, without being accompanied by
|
||||
some printable text. Even the newer, portable text formats such as
|
||||
XML avoid using control characters outside the list mentioned here.
|
||||
|
||||
The second observation is that most of the binary files tend to contain
|
||||
control characters, especially 0 (NUL). Even though the older text
|
||||
detection schemes observe the presence of non-ASCII codes from the range
|
||||
[128..255], the precision rarely has to suffer if this upper range is
|
||||
labeled as textual, because the files that are genuinely binary tend to
|
||||
contain both control characters and codes from the upper range. On the
|
||||
other hand, the upper range needs to be labeled as textual, because it
|
||||
is used by virtually all ASCII extensions. In particular, this range is
|
||||
used for encoding non-Latin scripts.
|
||||
|
||||
Since there is no counting involved, other than simply observing the
|
||||
presence or the absence of some byte values, the algorithm produces
|
||||
consistent results, regardless what alphabet encoding is being used.
|
||||
(If counting were involved, it could be possible to obtain different
|
||||
results on a text encoded, say, using ISO-8859-16 versus UTF-8.)
|
||||
|
||||
There is an extra category of plain text files that are "polluted" with
|
||||
one or more black-listed codes, either by mistake or by peculiar design
|
||||
considerations. In such cases, a scheme that tolerates a small fraction
|
||||
of black-listed codes would provide an increased recall (i.e. more true
|
||||
positives). This, however, incurs a reduced precision overall, since
|
||||
false positives are more likely to appear in binary files that contain
|
||||
large chunks of textual data. Furthermore, "polluted" plain text should
|
||||
be regarded as binary by general-purpose text detection schemes, because
|
||||
general-purpose text processing algorithms might not be applicable.
|
||||
Under this premise, it is safe to say that our detection method provides
|
||||
a near-100% recall.
|
||||
|
||||
Experiments have been run on many files coming from various platforms
|
||||
and applications. We tried plain text files, system logs, source code,
|
||||
formatted office documents, compiled object code, etc. The results
|
||||
confirm the optimistic assumptions about the capabilities of this
|
||||
algorithm.
|
||||
|
||||
|
||||
--
|
||||
Cosmin Truta
|
||||
Last updated: 2006-May-28
|
||||
Executable → Regular
Executable → Regular
+1
-1
@@ -205,7 +205,7 @@ and sets \fIinterp\fR's result to an error message indicating that
|
||||
the \fBreturn\fR, \fBbreak\fR, or \fBcontinue\fR command was
|
||||
invoked in an inappropriate place.
|
||||
This means that top-level applications should never see a return code
|
||||
from \fBTcl_EvalObjEx\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR.
|
||||
from \fBTcl_EvalObjEx\fR other than \fBTCL_OK\fR or \fBTCL_ERROR\fR.
|
||||
|
||||
.SH KEYWORDS
|
||||
execute, file, global, result, script, value
|
||||
|
||||
Regular → Executable
+5
-2
@@ -57,6 +57,9 @@ after the optional white space and sign are
|
||||
.QW \fB0x\fR
|
||||
then \fIsrc\fR is expected to be in hexadecimal form; otherwise,
|
||||
if the first such characters are
|
||||
.QW \fB0d\fR
|
||||
then \fIsrc\fR is expected to be in decimal form; otherwise,
|
||||
if the first such characters are
|
||||
.QW \fB0o\fR
|
||||
then \fIsrc\fR is expected to be in octal form; otherwise,
|
||||
if the first such characters are
|
||||
@@ -65,8 +68,8 @@ then \fIsrc\fR is expected to be in binary form; otherwise,
|
||||
if the first such character is
|
||||
.QW \fB0\fR
|
||||
then \fIsrc\fR
|
||||
is expected to be in octal form; otherwise, \fIsrc\fR is
|
||||
expected to be in decimal form.
|
||||
is expected to be in octal form; otherwise, \fIsrc\fR
|
||||
is expected to be in decimal form.
|
||||
.PP
|
||||
\fBTcl_GetDouble\fR expects \fIsrc\fR to consist of a floating-point
|
||||
number, which is: white space; a sign; a sequence of digits; a
|
||||
|
||||
Regular → Executable
+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, \fBint64\fR, or something else.
|
||||
\fBlong int\fR, \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
|
||||
|
||||
@@ -32,8 +32,6 @@ the command at global level instead of the current stack level.
|
||||
.PP
|
||||
\fBTcl_RecordAndEvalObj\fR is invoked to record a command as an event
|
||||
on the history list and then execute it using \fBTcl_EvalObjEx\fR
|
||||
(or \fBTcl_GlobalEvalObj\fR if the \fBTCL_EVAL_GLOBAL\fR bit is set
|
||||
in \fIflags\fR).
|
||||
It returns a completion code such as \fBTCL_OK\fR just like \fBTcl_EvalObjEx\fR,
|
||||
as well as a result value containing additional information
|
||||
(a result value or error message)
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ Tcl_UniChar *
|
||||
Tcl_UniChar *
|
||||
\fBTcl_GetUnicode\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
Tcl_UniChar
|
||||
int
|
||||
\fBTcl_GetUniChar\fR(\fIobjPtr, index\fR)
|
||||
.sp
|
||||
int
|
||||
|
||||
+3
-3
@@ -13,13 +13,13 @@ Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
.sp
|
||||
Tcl_UniChar
|
||||
int
|
||||
\fBTcl_UniCharToUpper\fR(\fIch\fR)
|
||||
.sp
|
||||
Tcl_UniChar
|
||||
int
|
||||
\fBTcl_UniCharToLower\fR(\fIch\fR)
|
||||
.sp
|
||||
Tcl_UniChar
|
||||
int
|
||||
\fBTcl_UniCharToTitle\fR(\fIch\fR)
|
||||
.sp
|
||||
int
|
||||
|
||||
@@ -63,7 +63,7 @@ const char *
|
||||
const char *
|
||||
\fBTcl_UtfPrev\fR(\fIsrc, start\fR)
|
||||
.sp
|
||||
Tcl_UniChar
|
||||
int
|
||||
\fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR)
|
||||
.sp
|
||||
const char *
|
||||
@@ -232,7 +232,7 @@ the start of the UTF-8 string. If \fIsrc\fR was already at \fIstart\fR, the
|
||||
return value will be \fIstart\fR.
|
||||
.PP
|
||||
\fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the
|
||||
Pascal Ord() function. It returns the Tcl_UniChar represented at the
|
||||
Pascal Ord() function. It returns the Unicode character represented at the
|
||||
specified character (not byte) \fIindex\fR in the UTF-8 string
|
||||
\fIsrc\fR. The source string must contain at least \fIindex\fR
|
||||
characters. Behavior is undefined if a negative \fIindex\fR is given.
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ exception to occur.
|
||||
The exception causes the current script to be aborted
|
||||
out to the innermost containing loop command, which then
|
||||
continues with the next iteration of the loop.
|
||||
Catch exceptions are also handled in a few other situations, such
|
||||
Continue exceptions are also handled in a few other situations, such
|
||||
as the \fBcatch\fR command and the outermost scripts of procedure
|
||||
bodies.
|
||||
.SH EXAMPLE
|
||||
|
||||
+16
-6
@@ -14,7 +14,7 @@ oo::copy \- create copies of objects and classes
|
||||
.nf
|
||||
package require TclOO
|
||||
|
||||
\fBoo::copy\fI sourceObject \fR?\fItargetObject\fR?
|
||||
\fBoo::copy\fI sourceObject \fR?\fItargetObject\fR? ?\fItargetNamespace\fR?
|
||||
.fi
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
@@ -22,11 +22,21 @@ package require TclOO
|
||||
The \fBoo::copy\fR command creates a copy of an object or class. It takes the
|
||||
name of the object or class to be copied, \fIsourceObject\fR, and optionally
|
||||
the name of the object or class to create, \fItargetObject\fR, which will be
|
||||
resolved relative to the current namespace if not an absolute qualified name.
|
||||
If \fItargetObject\fR is omitted, a new name is chosen. The copied object will
|
||||
be of the same class as the source object, and will have all its per-object
|
||||
methods copied. If it is a class, it will also have all the class methods in
|
||||
the class copied, but it will not have any of its instances copied.
|
||||
resolved relative to the current namespace if not an absolute qualified name
|
||||
and
|
||||
.VS TIP473
|
||||
\fItargetNamespace\fR which is the name of the namespace that will hold the
|
||||
internal state of the object (\fBmy\fR command, etc.); it \fImust not\fR
|
||||
refer to an existing namespace.
|
||||
If either \fItargetObject\fR or \fItargetNamespace\fR is omitted or is given
|
||||
as the empty string, a new name is chosen. Names, unless specified, are
|
||||
chosen with the same algorithm used by the \fBnew\fR method of
|
||||
\fBoo::class\fR.
|
||||
.VE TIP473
|
||||
The copied object will be of the same class as the source object, and will have
|
||||
all its per-object methods copied. If it is a class, it will also have all the
|
||||
class methods in the class copied, but it will not have any of its instances
|
||||
copied.
|
||||
.PP
|
||||
.VS
|
||||
After the \fItargetObject\fR has been created and all definitions of its
|
||||
|
||||
@@ -142,6 +142,8 @@ be afterwards.
|
||||
\fBself\fI subcommand arg ...\fR
|
||||
.TP
|
||||
\fBself\fI script\fR
|
||||
.TP
|
||||
\fBself\fR
|
||||
.
|
||||
This command is equivalent to calling \fBoo::objdefine\fR on the class being
|
||||
defined (see \fBCONFIGURING OBJECTS\fR below for a description of the
|
||||
@@ -151,6 +153,13 @@ and
|
||||
.QW "\fBoo::define \fIcls \fBself \fIsubcommand ...\fR"
|
||||
operates identically to
|
||||
.QW "\fBoo::objdefine \fIcls subcommand ...\fR" .
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP470
|
||||
If no arguments at all are used, this gives the name of the class currently
|
||||
being configured.
|
||||
.VE TIP470
|
||||
.RE
|
||||
.TP
|
||||
\fBsuperclass\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
|
||||
.VS
|
||||
@@ -265,6 +274,12 @@ not previously refer to a method in that object. Does not affect the classes
|
||||
that the object is an instance of. Does not change the export status of the
|
||||
method; if it was exported before, it will be afterwards.
|
||||
.TP
|
||||
\fBself \fR
|
||||
.
|
||||
.VS TIP470
|
||||
This gives the name of the object currently being configured.
|
||||
.VE TIP470
|
||||
.TP
|
||||
\fBunexport\fI name \fR?\fIname ...\fR?
|
||||
.
|
||||
This arranges for each of the named methods, \fIname\fR, to be not exported
|
||||
|
||||
+1
-1
@@ -437,7 +437,7 @@ puts $foo
|
||||
# prints: \fIa b foo {a b} bar 2 baz 3\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
append(n), array(n), foreach(n), mapeach(n), incr(n), list(n), lappend(n), set(n)
|
||||
append(n), array(n), foreach(n), incr(n), list(n), lappend(n), lmap(n), set(n)
|
||||
.SH KEYWORDS
|
||||
dictionary, create, update, lookup, iterate, filter, map
|
||||
'\" Local Variables:
|
||||
|
||||
+2
-1
@@ -46,7 +46,8 @@ value is the form produced by the \fB%g\fR format specifier of Tcl's
|
||||
An expression consists of a combination of operands, operators, parentheses and
|
||||
commas, possibly with whitespace between any of these elements, which is
|
||||
ignored.
|
||||
An integer operand may be specified in decimal, binary
|
||||
An integer operand may be specified in decimal (the normal case, the optional
|
||||
first two characters are \fB0d\fR), binary
|
||||
(the first two characters are \fB0b\fR), octal
|
||||
(the first two characters are \fB0o\fR), or hexadecimal
|
||||
(the first two characters are \fB0x\fR) form. For
|
||||
|
||||
@@ -89,6 +89,8 @@ For \fBx\fR or \fBX\fR conversions, \fB0x\fR or \fB0X\fR (respectively)
|
||||
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 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.
|
||||
|
||||
+1
-1
@@ -297,7 +297,7 @@ scripts are stored.
|
||||
This is actually the value of the \fBtcl_library\fR
|
||||
variable and may be changed by setting \fBtcl_library\fR.
|
||||
.TP
|
||||
\fBinfo loaded \fR?\fIinterp\fR? \fR?\fIpackage\fR?
|
||||
\fBinfo loaded \fR?\fIinterp\fR? ?\fIpackage\fR?
|
||||
.
|
||||
Returns the filename loaded as part of \fIpackage\fR. If \fIpackage\fR
|
||||
is not specified, returns a list describing all of the packages
|
||||
|
||||
Regular → Executable
+3
-3
@@ -293,12 +293,12 @@ treatment is as if the enclosing delimiters were
|
||||
.QW \fB[.\fR \&
|
||||
and
|
||||
.QW \fB.]\fR .)
|
||||
For example, if \fBo\fR and \fB\*(qo\fR are the members of an
|
||||
For example, if \fBo\fR and \fB\[^o]\fR are the members of an
|
||||
equivalence class, then
|
||||
.QW \fB[[=o=]]\fR ,
|
||||
.QW \fB[[=\*(qo=]]\fR ,
|
||||
.QW \fB[[=\[^o]=]]\fR ,
|
||||
and
|
||||
.QW \fB[o\*(qo]\fR \&
|
||||
.QW \fB[o\[^o]]\fR \&
|
||||
are all synonymous. An equivalence class may not be an endpoint of a range.
|
||||
.RS
|
||||
.PP
|
||||
|
||||
@@ -68,6 +68,33 @@ and
|
||||
sequences are handled for each substitution using the information
|
||||
from the corresponding match.
|
||||
.TP
|
||||
\fB\-command\fR
|
||||
.VS 8.7
|
||||
Changes the handling of \fIsubSpec\fR so that it is not treated
|
||||
as a template for a substitution string and the substrings
|
||||
.QW &
|
||||
and
|
||||
.QW \e\fIn\fR
|
||||
no longer have special meaning. Instead \fIsubSpec\fR must be a
|
||||
command prefix, that is, a non-empty list. The substring of \fIstring\fR
|
||||
that matches \fIexp\fR, and then each substring that matches each
|
||||
capturing sub-RE within \fIexp\fR are appended as additional elements
|
||||
to that list. (The items appended to the list are much like what
|
||||
\fBregexp\fR \fB-inline\fR would return). The completed list is then
|
||||
evaluated as a Tcl command, and the result of that command is the
|
||||
substitution string. Any error or exception from command evaluation
|
||||
becomes an error or exception from the \fBregsub\fR command.
|
||||
.RS
|
||||
.PP
|
||||
If \fB\-all\fR is not also given, the command callback will be invoked at most
|
||||
once (exactly when the regular expression matches). If \fB\-all\fR is given,
|
||||
the command callback will be invoked for each matched location, in sequence.
|
||||
The exact location indices that matched are not made available to the script.
|
||||
.PP
|
||||
See \fBEXAMPLES\fR below for illustrative cases.
|
||||
.RE
|
||||
.VE 8.7
|
||||
.TP
|
||||
\fB\-expanded\fR
|
||||
.
|
||||
Enables use of the expanded regular expression syntax where
|
||||
@@ -183,6 +210,53 @@ set substitution {[format \e\e\e\eu%04x [scan "\e\e&" %c]]}
|
||||
set quoted [subst [string map {\en {\e\eu000a}} \e
|
||||
[\fBregsub\fR -all $RE $string $substitution]]]
|
||||
.CE
|
||||
.PP
|
||||
.VS 8.7
|
||||
The above operation can be done using \fBregsub \-command\fR instead, which is
|
||||
often faster. (A full pre-computed \fBstring map\fR would be faster still, but
|
||||
the cost of computing the map for a transformation as complex as this can be
|
||||
quite large.)
|
||||
.PP
|
||||
.CS
|
||||
# This RE is just a character class for everything "bad"
|
||||
set RE {[][{};#\e\e\e$\es\eu0080-\euffff]}
|
||||
|
||||
# This encodes what the RE described above matches
|
||||
proc encodeChar {ch} {
|
||||
# newline is handled specially since backslash-newline is a
|
||||
# special sequence.
|
||||
if {$ch eq "\en"} {
|
||||
return "\e\eu000a"
|
||||
}
|
||||
# No point in writing this as a one-liner
|
||||
scan $ch %c charNumber
|
||||
format "\e\eu%04x" $charNumber
|
||||
}
|
||||
|
||||
set quoted [\fBregsub\fR -all -command $RE $string encodeChar]
|
||||
.CE
|
||||
.PP
|
||||
Decoding a URL-encoded string using \fBregsub \-command\fR, a lambda term and
|
||||
the \fBapply\fR command.
|
||||
.PP
|
||||
.CS
|
||||
# Match one of the sequences in a URL-encoded string that needs
|
||||
# fixing, converting + to space and %XX to the right character
|
||||
# (e.g., %7e becomes ~)
|
||||
set RE {(\e+)|%([0-9A-Fa-f]{2})}
|
||||
|
||||
# Note that -command uses a command prefix, not a command name
|
||||
set decoded [\fBregsub\fR -all -command $RE $string {apply {{- p h} {
|
||||
# + is a special case; handle directly
|
||||
if {$p eq "+"} {
|
||||
return " "
|
||||
}
|
||||
# convert hex to a char
|
||||
scan $h %x charNumber
|
||||
format %c $charNumber
|
||||
}}}]
|
||||
.CE
|
||||
.VE 8.7
|
||||
.SH "SEE ALSO"
|
||||
regexp(n), re_syntax(n), subst(n), string(n)
|
||||
.SH KEYWORDS
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
'\"
|
||||
'\" Copyright (c) 2005 Sergey Brester aka sebres.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH timerate n "" Tcl "Tcl Built-In Commands"
|
||||
.so man.macros
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
timerate \- Time-related execution resp. performance measurement of a script
|
||||
.SH SYNOPSIS
|
||||
\fBtimerate \fIscript\fR \fI?time?\fR
|
||||
.sp
|
||||
\fBtimerate \fI?-direct?\fR \fI?-overhead double?\fR \fIscript\fR \fI?time?\fR
|
||||
.sp
|
||||
\fBtimerate \fI?-calibrate?\fR \fI?-direct?\fR \fIscript\fR \fI?time?\fR
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The first and second form will evaluate \fIscript\fR until the interval
|
||||
\fItime\fR given in milliseconds elapses, or for 1000 milliseconds (1 second)
|
||||
if \fItime\fR is not specified.
|
||||
.sp
|
||||
It will then return a canonical tcl-list of the form
|
||||
.PP
|
||||
.CS
|
||||
\f0.095977 µs/# 52095836 # 10419167 #/sec 5000.000 nett-ms\fR
|
||||
.CE
|
||||
.PP
|
||||
which indicates:
|
||||
.IP \(bu
|
||||
the average amount of time required per iteration, in microseconds (lindex $result 0)
|
||||
.IP \(bu
|
||||
the count how many times it was executed (lindex $result 2)
|
||||
.IP \(bu
|
||||
the estimated rate per second (lindex $result 4)
|
||||
.IP \(bu
|
||||
the estimated real execution time without measurement overhead (lindex $result 6)
|
||||
.PP
|
||||
Time is measured in elapsed time using heighest timer resolution as possible, not CPU time.
|
||||
This command may be used to provide information as to how well the script or a tcl-command
|
||||
is performing and can help determine bottlenecks and fine-tune application performance.
|
||||
.PP
|
||||
\fI-calibrate\fR
|
||||
.
|
||||
To measure very fast scripts as exact as posible the calibration process
|
||||
may be required.
|
||||
|
||||
This parameter used to calibrate \fBtimerate\fR calculating the estimated overhead
|
||||
of given \fIscript\fR as default overhead for further execution of \fBtimerate\fR.
|
||||
It can take up to 10 seconds if parameter \fItime\fR is not specified.
|
||||
.PP
|
||||
\fI-overhead double\fR
|
||||
.
|
||||
This parameter used to supply the measurement overhead of single iteration
|
||||
(in microseconds) that should be ignored during whole evaluation process.
|
||||
.PP
|
||||
\fI-direct\fR
|
||||
.
|
||||
Causes direct execution per iteration (not compiled variant of evaluation used).
|
||||
.PP
|
||||
In opposition to \fBtime\fR the execution limited here by fixed time instead of
|
||||
repetition count.
|
||||
Additionally the compiled variant of the script will be used during whole evaluation
|
||||
(as if it were part of a compiled \fBproc\fR), if parameter \fI-direct\fR is not specified.
|
||||
Therefore it provides more precise results and prevents very long execution time
|
||||
by slow scripts resp. scripts with unknown speed.
|
||||
|
||||
.SH EXAMPLE
|
||||
Estimate how fast it takes for a simple Tcl \fBfor\fR loop (including
|
||||
operations on variable \fIi\fR) to count to a ten:
|
||||
.PP
|
||||
.CS
|
||||
# calibrate:
|
||||
timerate -calibrate {}
|
||||
# measure:
|
||||
timerate { for {set i 0} {$i<10} {incr i} {} } 5000
|
||||
.CE
|
||||
.PP
|
||||
Estimate how fast it takes for a simple Tcl \fBfor\fR loop only (ignoring the
|
||||
overhead for operations on variable \fIi\fR) to count to a ten:
|
||||
.PP
|
||||
.CS
|
||||
# calibrate for overhead of variable operations:
|
||||
set i 0; timerate -calibrate {expr {$i<10}; incr i} 1000
|
||||
# measure:
|
||||
timerate { for {set i 0} {$i<10} {incr i} {} } 5000
|
||||
.CE
|
||||
.PP
|
||||
Estimate the rate of calculating the hour using \fBclock format\fR only, ignoring
|
||||
overhead of the rest, without measurement how fast it takes for a whole script:
|
||||
.PP
|
||||
.CS
|
||||
# calibrate:
|
||||
timerate -calibrate {}
|
||||
# estimate overhead:
|
||||
set tm 0
|
||||
set ovh [lindex [timerate { incr tm [expr {24*60*60}] }] 0]
|
||||
# measure using esimated overhead:
|
||||
set tm 0
|
||||
timerate -overhead $ovh {
|
||||
clock format $tm -format %H
|
||||
incr tm [expr {24*60*60}]; # overhead for this is ignored
|
||||
} 5000
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
time(n)
|
||||
.SH KEYWORDS
|
||||
script, timerate, time
|
||||
.\" Local Variables:
|
||||
.\" mode: nroff
|
||||
.\" End:
|
||||
+209
-202
@@ -140,73 +140,73 @@ static const crange alphaRangeTable[] = {
|
||||
{0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x561, 0x587},
|
||||
{0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3},
|
||||
{0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea},
|
||||
{0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b4}, {0x8b6, 0x8bd},
|
||||
{0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c},
|
||||
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1},
|
||||
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c},
|
||||
{0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8},
|
||||
{0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28},
|
||||
{0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a},
|
||||
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
|
||||
{0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39},
|
||||
{0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8},
|
||||
{0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
|
||||
{0xd12, 0xd3a}, {0xd54, 0xd56}, {0xd5f, 0xd61}, {0xd7a, 0xd7f},
|
||||
{0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6},
|
||||
{0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97}, {0xe99, 0xe9f},
|
||||
{0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4}, {0xedc, 0xedf},
|
||||
{0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c}, {0x1000, 0x102a},
|
||||
{0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070}, {0x1075, 0x1081},
|
||||
{0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248}, {0x124a, 0x124d},
|
||||
{0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d},
|
||||
{0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5},
|
||||
{0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a},
|
||||
{0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1401, 0x166c},
|
||||
{0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x16f1, 0x16f8},
|
||||
{0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751},
|
||||
{0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3}, {0x1820, 0x1877},
|
||||
{0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5}, {0x1900, 0x191e},
|
||||
{0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9},
|
||||
{0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33}, {0x1b45, 0x1b4b},
|
||||
{0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23}, {0x1c4d, 0x1c4f},
|
||||
{0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1},
|
||||
{0x1d00, 0x1dbf}, {0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45},
|
||||
{0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4},
|
||||
{0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3},
|
||||
{0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc},
|
||||
{0x2090, 0x209c}, {0x210a, 0x2113}, {0x2119, 0x211d}, {0x212a, 0x212d},
|
||||
{0x212f, 0x2139}, {0x213c, 0x213f}, {0x2145, 0x2149}, {0x2c00, 0x2c2e},
|
||||
{0x2c30, 0x2c5e}, {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee}, {0x2d00, 0x2d25},
|
||||
{0x2d30, 0x2d67}, {0x2d80, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae},
|
||||
{0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce},
|
||||
{0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x3031, 0x3035}, {0x3041, 0x3096},
|
||||
{0x309d, 0x309f}, {0x30a1, 0x30fa}, {0x30fc, 0x30ff}, {0x3105, 0x312d},
|
||||
{0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5},
|
||||
{0x4e00, 0x9fd5}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c},
|
||||
{0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5},
|
||||
{0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ae}, {0xa7b0, 0xa7b7},
|
||||
{0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a}, {0xa80c, 0xa822},
|
||||
{0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7}, {0xa90a, 0xa925},
|
||||
{0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2}, {0xa9e0, 0xa9e4},
|
||||
{0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe}, {0xaa00, 0xaa28}, {0xaa40, 0xaa42},
|
||||
{0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, {0xaa7e, 0xaaaf}, {0xaab9, 0xaabd},
|
||||
{0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4}, {0xab01, 0xab06},
|
||||
{0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
|
||||
{0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2}, {0xac00, 0xd7a3},
|
||||
{0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e},
|
||||
{0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e}, {0xdd40, 0xdd7e},
|
||||
{0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e}, {0xde40, 0xde7e},
|
||||
{0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e},
|
||||
{0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9},
|
||||
{0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36},
|
||||
{0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f},
|
||||
{0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc},
|
||||
{0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe}, {0xffc2, 0xffc7},
|
||||
{0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}
|
||||
{0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86a}, {0x8a0, 0x8b4},
|
||||
{0x8b6, 0x8bd}, {0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980},
|
||||
{0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9},
|
||||
{0x9df, 0x9e1}, {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30},
|
||||
{0xa59, 0xa5c}, {0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91},
|
||||
{0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c},
|
||||
{0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61},
|
||||
{0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa},
|
||||
{0xbae, 0xbb9}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
|
||||
{0xc2a, 0xc39}, {0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90},
|
||||
{0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c},
|
||||
{0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd54, 0xd56}, {0xd5f, 0xd61},
|
||||
{0xd7a, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb},
|
||||
{0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97},
|
||||
{0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4},
|
||||
{0xedc, 0xedf}, {0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c},
|
||||
{0x1000, 0x102a}, {0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070},
|
||||
{0x1075, 0x1081}, {0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248},
|
||||
{0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288},
|
||||
{0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be},
|
||||
{0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315},
|
||||
{0x1318, 0x135a}, {0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd},
|
||||
{0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea},
|
||||
{0x16f1, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731},
|
||||
{0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3},
|
||||
{0x1820, 0x1877}, {0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5},
|
||||
{0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},
|
||||
{0x19b0, 0x19c9}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33},
|
||||
{0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23},
|
||||
{0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1ce9, 0x1cec},
|
||||
{0x1cee, 0x1cf1}, {0x1d00, 0x1dbf}, {0x1e00, 0x1f15}, {0x1f18, 0x1f1d},
|
||||
{0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d},
|
||||
{0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc},
|
||||
{0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4},
|
||||
{0x1ff6, 0x1ffc}, {0x2090, 0x209c}, {0x210a, 0x2113}, {0x2119, 0x211d},
|
||||
{0x212a, 0x212d}, {0x212f, 0x2139}, {0x213c, 0x213f}, {0x2145, 0x2149},
|
||||
{0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee},
|
||||
{0x2d00, 0x2d25}, {0x2d30, 0x2d67}, {0x2d80, 0x2d96}, {0x2da0, 0x2da6},
|
||||
{0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6},
|
||||
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x3031, 0x3035},
|
||||
{0x3041, 0x3096}, {0x309d, 0x309f}, {0x30a1, 0x30fa}, {0x30fc, 0x30ff},
|
||||
{0x3105, 0x312e}, {0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff},
|
||||
{0x3400, 0x4db5}, {0x4e00, 0x9fea}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd},
|
||||
{0xa500, 0xa60c}, {0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d},
|
||||
{0xa6a0, 0xa6e5}, {0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ae},
|
||||
{0xa7b0, 0xa7b7}, {0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a},
|
||||
{0xa80c, 0xa822}, {0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7},
|
||||
{0xa90a, 0xa925}, {0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2},
|
||||
{0xa9e0, 0xa9e4}, {0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe}, {0xaa00, 0xaa28},
|
||||
{0xaa40, 0xaa42}, {0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, {0xaa7e, 0xaaaf},
|
||||
{0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4},
|
||||
{0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26},
|
||||
{0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2},
|
||||
{0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e},
|
||||
{0xdc40, 0xdc7e}, {0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e},
|
||||
{0xdd40, 0xdd7e}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e},
|
||||
{0xde40, 0xde7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e},
|
||||
{0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d},
|
||||
{0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28},
|
||||
{0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d},
|
||||
{0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74},
|
||||
{0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe},
|
||||
{0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}
|
||||
#if TCL_UTF_MAX > 4
|
||||
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
|
||||
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0},
|
||||
{0x10300, 0x1031f}, {0x10330, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
|
||||
{0x10300, 0x1031f}, {0x1032d, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
|
||||
{0x10380, 0x1039d}, {0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d},
|
||||
{0x104b0, 0x104d3}, {0x104d8, 0x104fb}, {0x10500, 0x10527}, {0x10530, 0x10563},
|
||||
{0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
|
||||
@@ -222,24 +222,26 @@ static const crange alphaRangeTable[] = {
|
||||
{0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339},
|
||||
{0x1135d, 0x11361}, {0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af},
|
||||
{0x11580, 0x115ae}, {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa},
|
||||
{0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08},
|
||||
{0x11c0a, 0x11c2e}, {0x11c72, 0x11c8f}, {0x12000, 0x12399}, {0x12480, 0x12543},
|
||||
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
|
||||
{0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77},
|
||||
{0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f}, {0x17000, 0x187ec},
|
||||
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
|
||||
{0x1bc90, 0x1bc99}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
|
||||
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
|
||||
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
|
||||
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0},
|
||||
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734},
|
||||
{0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8},
|
||||
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943},
|
||||
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
|
||||
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
|
||||
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
|
||||
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
|
||||
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}
|
||||
{0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11a0b, 0x11a32}, {0x11a5c, 0x11a83},
|
||||
{0x11a86, 0x11a89}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c2e},
|
||||
{0x11c72, 0x11c8f}, {0x11d00, 0x11d06}, {0x11d0b, 0x11d30}, {0x12000, 0x12399},
|
||||
{0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38},
|
||||
{0x16a40, 0x16a5e}, {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43},
|
||||
{0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f},
|
||||
{0x17000, 0x187ec}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb},
|
||||
{0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
|
||||
{0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9},
|
||||
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
|
||||
{0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
|
||||
{0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0}, {0x1d6c2, 0x1d6da},
|
||||
{0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, {0x1d736, 0x1d74e},
|
||||
{0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8}, {0x1d7aa, 0x1d7c2},
|
||||
{0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943}, {0x1ee00, 0x1ee03},
|
||||
{0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f},
|
||||
{0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c},
|
||||
{0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9},
|
||||
{0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
|
||||
{0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -250,28 +252,29 @@ static const chr alphaCharTable[] = {
|
||||
0x38c, 0x559, 0x66e, 0x66f, 0x6d5, 0x6e5, 0x6e6, 0x6ee, 0x6ef,
|
||||
0x6ff, 0x710, 0x7b1, 0x7f4, 0x7f5, 0x7fa, 0x81a, 0x824, 0x828,
|
||||
0x93d, 0x950, 0x98f, 0x990, 0x9b2, 0x9bd, 0x9ce, 0x9dc, 0x9dd,
|
||||
0x9f0, 0x9f1, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38,
|
||||
0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1, 0xaf9,
|
||||
0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71, 0xb83,
|
||||
0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0, 0xc3d,
|
||||
0xc60, 0xc61, 0xc80, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2,
|
||||
0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84, 0xe87,
|
||||
0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2, 0xeb3,
|
||||
0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e, 0x10c7,
|
||||
0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae, 0x1baf,
|
||||
0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102,
|
||||
0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2,
|
||||
0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c,
|
||||
0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6,
|
||||
0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
|
||||
0x9f0, 0x9f1, 0x9fc, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36,
|
||||
0xa38, 0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1,
|
||||
0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71,
|
||||
0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0,
|
||||
0xc3d, 0xc60, 0xc61, 0xc80, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1,
|
||||
0xcf2, 0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84,
|
||||
0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2,
|
||||
0xeb3, 0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e,
|
||||
0x10c7, 0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae,
|
||||
0x1baf, 0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f,
|
||||
0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184,
|
||||
0x2cf2, 0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b,
|
||||
0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5,
|
||||
0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
|
||||
#if TCL_UTF_MAX > 4
|
||||
,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be,
|
||||
0x109bf, 0x10a00, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, 0x11310, 0x11332,
|
||||
0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x11c40,
|
||||
0x16f50, 0x16fe0, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6,
|
||||
0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42,
|
||||
0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b,
|
||||
0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
|
||||
0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x11a00,
|
||||
0x11a3a, 0x11a50, 0x11c40, 0x11d08, 0x11d09, 0x11d46, 0x16f50, 0x16fe0, 0x16fe1,
|
||||
0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22,
|
||||
0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51,
|
||||
0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62,
|
||||
0x1ee64, 0x1ee7e
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -321,8 +324,8 @@ static const crange digitRangeTable[] = {
|
||||
,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f},
|
||||
{0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459}, {0x114d0, 0x114d9},
|
||||
{0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9},
|
||||
{0x11c50, 0x11c59}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff},
|
||||
{0x1e950, 0x1e959}
|
||||
{0x11c50, 0x11c59}, {0x11d50, 0x11d59}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59},
|
||||
{0x1d7ce, 0x1d7ff}, {0x1e950, 0x1e959}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -345,7 +348,7 @@ static const crange punctRangeTable[] = {
|
||||
{0x1b5a, 0x1b60}, {0x1bfc, 0x1bff}, {0x1c3b, 0x1c3f}, {0x1cc0, 0x1cc7},
|
||||
{0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205e},
|
||||
{0x2308, 0x230b}, {0x2768, 0x2775}, {0x27e6, 0x27ef}, {0x2983, 0x2998},
|
||||
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e44},
|
||||
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e49},
|
||||
{0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f},
|
||||
{0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd},
|
||||
{0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61},
|
||||
@@ -356,7 +359,8 @@ static const crange punctRangeTable[] = {
|
||||
{0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143},
|
||||
{0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x1144b, 0x1144f},
|
||||
{0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c}, {0x1173c, 0x1173e},
|
||||
{0x11c41, 0x11c45}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x1da87, 0x1da8b}
|
||||
{0x11a3f, 0x11a46}, {0x11a9a, 0x11a9c}, {0x11a9e, 0x11aa2}, {0x11c41, 0x11c45},
|
||||
{0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x1da87, 0x1da8b}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -367,14 +371,14 @@ static const chr punctCharTable[] = {
|
||||
0xab, 0xb6, 0xb7, 0xbb, 0xbf, 0x37e, 0x387, 0x589, 0x58a,
|
||||
0x5be, 0x5c0, 0x5c3, 0x5c6, 0x5f3, 0x5f4, 0x609, 0x60a, 0x60c,
|
||||
0x60d, 0x61b, 0x61e, 0x61f, 0x6d4, 0x85e, 0x964, 0x965, 0x970,
|
||||
0xaf0, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14, 0xf85, 0xfd9, 0xfda,
|
||||
0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x1735, 0x1736, 0x1944,
|
||||
0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3, 0x207d, 0x207e, 0x208d,
|
||||
0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc, 0x29fd, 0x2cfe, 0x2cff,
|
||||
0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, 0xa4ff, 0xa673, 0xa67e,
|
||||
0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9de, 0xa9df, 0xaade,
|
||||
0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, 0xfe63, 0xfe68, 0xfe6a,
|
||||
0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d
|
||||
0x9fd, 0xaf0, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14, 0xf85, 0xfd9,
|
||||
0xfda, 0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x1735, 0x1736,
|
||||
0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3, 0x207d, 0x207e,
|
||||
0x208d, 0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc, 0x29fd, 0x2cfe,
|
||||
0x2cff, 0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, 0xa4ff, 0xa673,
|
||||
0xa67e, 0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9de, 0xa9df,
|
||||
0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, 0xfe63, 0xfe68,
|
||||
0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d
|
||||
#if TCL_UTF_MAX > 4
|
||||
,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc,
|
||||
0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x11c70,
|
||||
@@ -615,63 +619,63 @@ static const crange graphRangeTable[] = {
|
||||
{0x559, 0x55f}, {0x561, 0x587}, {0x58d, 0x58f}, {0x591, 0x5c7},
|
||||
{0x5d0, 0x5ea}, {0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc},
|
||||
{0x6de, 0x70d}, {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa},
|
||||
{0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x8a0, 0x8b4},
|
||||
{0x8b6, 0x8bd}, {0x8d4, 0x8e1}, {0x8e3, 0x983}, {0x985, 0x98c},
|
||||
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4},
|
||||
{0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fb}, {0xa01, 0xa03},
|
||||
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42},
|
||||
{0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75}, {0xa81, 0xa83},
|
||||
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
|
||||
{0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd},
|
||||
{0xae0, 0xae3}, {0xae6, 0xaf1}, {0xb01, 0xb03}, {0xb05, 0xb0c},
|
||||
{0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb3c, 0xb44},
|
||||
{0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77}, {0xb85, 0xb8a},
|
||||
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
|
||||
{0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, {0xbe6, 0xbfa},
|
||||
{0xc00, 0xc03}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
|
||||
{0xc2a, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48}, {0xc4a, 0xc4d},
|
||||
{0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc83},
|
||||
{0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3},
|
||||
{0xcb5, 0xcb9}, {0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd},
|
||||
{0xce0, 0xce3}, {0xce6, 0xcef}, {0xd01, 0xd03}, {0xd05, 0xd0c},
|
||||
{0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd3d, 0xd44}, {0xd46, 0xd48},
|
||||
{0xd4a, 0xd4f}, {0xd54, 0xd63}, {0xd66, 0xd7f}, {0xd85, 0xd96},
|
||||
{0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xdcf, 0xdd4},
|
||||
{0xdd8, 0xddf}, {0xde6, 0xdef}, {0xdf2, 0xdf4}, {0xe01, 0xe3a},
|
||||
{0xe3f, 0xe5b}, {0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3},
|
||||
{0xead, 0xeb9}, {0xebb, 0xebd}, {0xec0, 0xec4}, {0xec8, 0xecd},
|
||||
{0xed0, 0xed9}, {0xedc, 0xedf}, {0xf00, 0xf47}, {0xf49, 0xf6c},
|
||||
{0xf71, 0xf97}, {0xf99, 0xfbc}, {0xfbe, 0xfcc}, {0xfce, 0xfda},
|
||||
{0x1000, 0x10c5}, {0x10d0, 0x1248}, {0x124a, 0x124d}, {0x1250, 0x1256},
|
||||
{0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0},
|
||||
{0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6},
|
||||
{0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a}, {0x135d, 0x137c},
|
||||
{0x1380, 0x1399}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1400, 0x167f},
|
||||
{0x1681, 0x169c}, {0x16a0, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1714},
|
||||
{0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176c}, {0x176e, 0x1770},
|
||||
{0x1780, 0x17dd}, {0x17e0, 0x17e9}, {0x17f0, 0x17f9}, {0x1800, 0x180d},
|
||||
{0x1810, 0x1819}, {0x1820, 0x1877}, {0x1880, 0x18aa}, {0x18b0, 0x18f5},
|
||||
{0x1900, 0x191e}, {0x1920, 0x192b}, {0x1930, 0x193b}, {0x1944, 0x196d},
|
||||
{0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9}, {0x19d0, 0x19da},
|
||||
{0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, {0x1a60, 0x1a7c}, {0x1a7f, 0x1a89},
|
||||
{0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, {0x1ab0, 0x1abe}, {0x1b00, 0x1b4b},
|
||||
{0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37}, {0x1c3b, 0x1c49},
|
||||
{0x1c4d, 0x1c88}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6}, {0x1d00, 0x1df5},
|
||||
{0x1dfb, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
|
||||
{0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4},
|
||||
{0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4},
|
||||
{0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e},
|
||||
{0x2090, 0x209c}, {0x20a0, 0x20be}, {0x20d0, 0x20f0}, {0x2100, 0x218b},
|
||||
{0x2190, 0x23fe}, {0x2400, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73},
|
||||
{0x2b76, 0x2b95}, {0x2b98, 0x2bb9}, {0x2bbd, 0x2bc8}, {0x2bca, 0x2bd1},
|
||||
{0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x860, 0x86a},
|
||||
{0x8a0, 0x8b4}, {0x8b6, 0x8bd}, {0x8d4, 0x8e1}, {0x8e3, 0x983},
|
||||
{0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9},
|
||||
{0x9bc, 0x9c4}, {0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fd},
|
||||
{0xa01, 0xa03}, {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30},
|
||||
{0xa3e, 0xa42}, {0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75},
|
||||
{0xa81, 0xa83}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8},
|
||||
{0xaaa, 0xab0}, {0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9},
|
||||
{0xacb, 0xacd}, {0xae0, 0xae3}, {0xae6, 0xaf1}, {0xaf9, 0xaff},
|
||||
{0xb01, 0xb03}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30},
|
||||
{0xb35, 0xb39}, {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63},
|
||||
{0xb66, 0xb77}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95},
|
||||
{0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8},
|
||||
{0xbca, 0xbcd}, {0xbe6, 0xbfa}, {0xc00, 0xc03}, {0xc05, 0xc0c},
|
||||
{0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc3d, 0xc44},
|
||||
{0xc46, 0xc48}, {0xc4a, 0xc4d}, {0xc58, 0xc5a}, {0xc60, 0xc63},
|
||||
{0xc66, 0xc6f}, {0xc78, 0xc83}, {0xc85, 0xc8c}, {0xc8e, 0xc90},
|
||||
{0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xcbc, 0xcc4},
|
||||
{0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3}, {0xce6, 0xcef},
|
||||
{0xd00, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd44},
|
||||
{0xd46, 0xd48}, {0xd4a, 0xd4f}, {0xd54, 0xd63}, {0xd66, 0xd7f},
|
||||
{0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6},
|
||||
{0xdcf, 0xdd4}, {0xdd8, 0xddf}, {0xde6, 0xdef}, {0xdf2, 0xdf4},
|
||||
{0xe01, 0xe3a}, {0xe3f, 0xe5b}, {0xe94, 0xe97}, {0xe99, 0xe9f},
|
||||
{0xea1, 0xea3}, {0xead, 0xeb9}, {0xebb, 0xebd}, {0xec0, 0xec4},
|
||||
{0xec8, 0xecd}, {0xed0, 0xed9}, {0xedc, 0xedf}, {0xf00, 0xf47},
|
||||
{0xf49, 0xf6c}, {0xf71, 0xf97}, {0xf99, 0xfbc}, {0xfbe, 0xfcc},
|
||||
{0xfce, 0xfda}, {0x1000, 0x10c5}, {0x10d0, 0x1248}, {0x124a, 0x124d},
|
||||
{0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d},
|
||||
{0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5},
|
||||
{0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a},
|
||||
{0x135d, 0x137c}, {0x1380, 0x1399}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd},
|
||||
{0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f8}, {0x1700, 0x170c},
|
||||
{0x170e, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176c},
|
||||
{0x176e, 0x1770}, {0x1780, 0x17dd}, {0x17e0, 0x17e9}, {0x17f0, 0x17f9},
|
||||
{0x1800, 0x180d}, {0x1810, 0x1819}, {0x1820, 0x1877}, {0x1880, 0x18aa},
|
||||
{0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1920, 0x192b}, {0x1930, 0x193b},
|
||||
{0x1944, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9},
|
||||
{0x19d0, 0x19da}, {0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, {0x1a60, 0x1a7c},
|
||||
{0x1a7f, 0x1a89}, {0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, {0x1ab0, 0x1abe},
|
||||
{0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37},
|
||||
{0x1c3b, 0x1c49}, {0x1c4d, 0x1c88}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf9},
|
||||
{0x1d00, 0x1df9}, {0x1dfb, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45},
|
||||
{0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4},
|
||||
{0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef},
|
||||
{0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e},
|
||||
{0x2074, 0x208e}, {0x2090, 0x209c}, {0x20a0, 0x20bf}, {0x20d0, 0x20f0},
|
||||
{0x2100, 0x218b}, {0x2190, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73},
|
||||
{0x2b76, 0x2b95}, {0x2b98, 0x2bb9}, {0x2bbd, 0x2bc8}, {0x2bca, 0x2bd2},
|
||||
{0x2bec, 0x2bef}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3},
|
||||
{0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96}, {0x2da0, 0x2da6},
|
||||
{0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6},
|
||||
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e44},
|
||||
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e49},
|
||||
{0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb},
|
||||
{0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312d},
|
||||
{0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312e},
|
||||
{0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3}, {0x31f0, 0x321e},
|
||||
{0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fd5}, {0xa000, 0xa48c},
|
||||
{0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fea}, {0xa000, 0xa48c},
|
||||
{0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ae},
|
||||
{0xa7b0, 0xa7b7}, {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877},
|
||||
{0xa880, 0xa8c5}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953},
|
||||
@@ -694,7 +698,7 @@ static const crange graphRangeTable[] = {
|
||||
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
|
||||
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133},
|
||||
{0x10137, 0x1018e}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
|
||||
{0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x10330, 0x1034a},
|
||||
{0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x1032d, 0x1034a},
|
||||
{0x10350, 0x1037a}, {0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5},
|
||||
{0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x104b0, 0x104d3}, {0x104d8, 0x104fb},
|
||||
{0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
|
||||
@@ -717,35 +721,38 @@ static const crange graphRangeTable[] = {
|
||||
{0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644},
|
||||
{0x11650, 0x11659}, {0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9},
|
||||
{0x11700, 0x11719}, {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x118a0, 0x118f2},
|
||||
{0x11a00, 0x11a47}, {0x11a50, 0x11a83}, {0x11a86, 0x11a9c}, {0x11a9e, 0x11aa2},
|
||||
{0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45},
|
||||
{0x11c50, 0x11c6c}, {0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6},
|
||||
{0x11d00, 0x11d06}, {0x11d0b, 0x11d36}, {0x11d3f, 0x11d47}, {0x11d50, 0x11d59},
|
||||
{0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474}, {0x12480, 0x12543},
|
||||
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
|
||||
{0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45},
|
||||
{0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f},
|
||||
{0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x17000, 0x187ec},
|
||||
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
|
||||
{0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126},
|
||||
{0x1d129, 0x1d172}, {0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356},
|
||||
{0x1d360, 0x1d371}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
|
||||
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
|
||||
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
|
||||
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb},
|
||||
{0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006},
|
||||
{0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, {0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4},
|
||||
{0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, {0x1e950, 0x1e959}, {0x1ee00, 0x1ee03},
|
||||
{0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f},
|
||||
{0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c},
|
||||
{0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9},
|
||||
{0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae},
|
||||
{0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f10c},
|
||||
{0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202},
|
||||
{0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f300, 0x1f6d2}, {0x1f6e0, 0x1f6ec},
|
||||
{0x1f6f0, 0x1f6f6}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b},
|
||||
{0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad},
|
||||
{0x1f910, 0x1f91e}, {0x1f920, 0x1f927}, {0x1f933, 0x1f93e}, {0x1f940, 0x1f94b},
|
||||
{0x1f950, 0x1f95e}, {0x1f980, 0x1f991}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
|
||||
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
|
||||
{0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb}, {0x1bc00, 0x1bc6a},
|
||||
{0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f},
|
||||
{0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172}, {0x1d17b, 0x1d1e8},
|
||||
{0x1d200, 0x1d245}, {0x1d300, 0x1d356}, {0x1d360, 0x1d371}, {0x1d400, 0x1d454},
|
||||
{0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3},
|
||||
{0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c},
|
||||
{0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550},
|
||||
{0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb}, {0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f},
|
||||
{0x1daa1, 0x1daaf}, {0x1e000, 0x1e006}, {0x1e008, 0x1e018}, {0x1e01b, 0x1e021},
|
||||
{0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4}, {0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a},
|
||||
{0x1e950, 0x1e959}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32},
|
||||
{0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72},
|
||||
{0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b},
|
||||
{0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b},
|
||||
{0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf},
|
||||
{0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f10c}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b},
|
||||
{0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202}, {0x1f210, 0x1f23b}, {0x1f240, 0x1f248},
|
||||
{0x1f260, 0x1f265}, {0x1f300, 0x1f6d4}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f8},
|
||||
{0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847},
|
||||
{0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x1f900, 0x1f90b},
|
||||
{0x1f910, 0x1f93e}, {0x1f940, 0x1f94c}, {0x1f950, 0x1f96b}, {0x1f980, 0x1f997},
|
||||
{0x1f9d0, 0x1f9e6}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
|
||||
{0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -755,23 +762,23 @@ static const chr graphCharTable[] = {
|
||||
0x38c, 0x589, 0x58a, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8,
|
||||
0x9d7, 0x9dc, 0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36,
|
||||
0xa38, 0xa39, 0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3,
|
||||
0xad0, 0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56,
|
||||
0xb57, 0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e,
|
||||
0xb9f, 0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6,
|
||||
0xcde, 0xcf1, 0xcf2, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81,
|
||||
0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa,
|
||||
0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940,
|
||||
0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d,
|
||||
0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd
|
||||
0xad0, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56, 0xb57,
|
||||
0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f,
|
||||
0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6, 0xcde,
|
||||
0xcf1, 0xcf2, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81, 0xe82,
|
||||
0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab,
|
||||
0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1f59,
|
||||
0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xfb3e,
|
||||
0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd
|
||||
#if TCL_UTF_MAX > 4
|
||||
,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4,
|
||||
0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333,
|
||||
0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x118ff, 0x16a6e, 0x16a6f,
|
||||
0x16fe0, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb,
|
||||
0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27,
|
||||
0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54,
|
||||
0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e,
|
||||
0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f930, 0x1f9c0
|
||||
0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x118ff, 0x11d08, 0x11d09,
|
||||
0x11d3a, 0x11d3c, 0x11d3d, 0x16a6e, 0x16a6f, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f,
|
||||
0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f,
|
||||
0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49,
|
||||
0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f,
|
||||
0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f9c0
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
+6
-6
@@ -1059,7 +1059,7 @@ declare 293 {
|
||||
int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
|
||||
}
|
||||
declare 294 {
|
||||
void Tcl_ExitThread(int status)
|
||||
TCL_NORETURN void Tcl_ExitThread(int status)
|
||||
}
|
||||
declare 295 {
|
||||
int Tcl_ExternalToUtf(Tcl_Interp *interp, Tcl_Encoding encoding,
|
||||
@@ -1148,16 +1148,16 @@ declare 319 {
|
||||
Tcl_QueuePosition position)
|
||||
}
|
||||
declare 320 {
|
||||
Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index)
|
||||
int Tcl_UniCharAtIndex(const char *src, int index)
|
||||
}
|
||||
declare 321 {
|
||||
Tcl_UniChar Tcl_UniCharToLower(int ch)
|
||||
int Tcl_UniCharToLower(int ch)
|
||||
}
|
||||
declare 322 {
|
||||
Tcl_UniChar Tcl_UniCharToTitle(int ch)
|
||||
int Tcl_UniCharToTitle(int ch)
|
||||
}
|
||||
declare 323 {
|
||||
Tcl_UniChar Tcl_UniCharToUpper(int ch)
|
||||
int Tcl_UniCharToUpper(int ch)
|
||||
}
|
||||
declare 324 {
|
||||
int Tcl_UniCharToUtf(int ch, char *buf)
|
||||
@@ -1351,7 +1351,7 @@ declare 380 {
|
||||
int Tcl_GetCharLength(Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 381 {
|
||||
Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index)
|
||||
int Tcl_GetUniChar(Tcl_Obj *objPtr, int index)
|
||||
}
|
||||
declare 382 {
|
||||
Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr)
|
||||
|
||||
+30
-26
@@ -41,7 +41,6 @@ extern "C" {
|
||||
* unix/configure.ac (2 LOC Major, 2 LOC minor, 1 LOC patch)
|
||||
* win/configure.ac (as above)
|
||||
* win/tcl.m4 (not patchlevel)
|
||||
* win/makefile.bc (not patchlevel) 2 LOC
|
||||
* README (sections 0 and 2, with and without separator)
|
||||
* macosx/Tcl.pbproj/project.pbxproj (not patchlevel) 1 LOC
|
||||
* macosx/Tcl.pbproj/default.pbxuser (not patchlevel) 1 LOC
|
||||
@@ -56,11 +55,12 @@ extern "C" {
|
||||
#define TCL_MAJOR_VERSION 8
|
||||
#define TCL_MINOR_VERSION 7
|
||||
#define TCL_RELEASE_LEVEL TCL_ALPHA_RELEASE
|
||||
#define TCL_RELEASE_SERIAL 0
|
||||
#define TCL_RELEASE_SERIAL 2
|
||||
|
||||
#define TCL_VERSION "8.7"
|
||||
#define TCL_PATCH_LEVEL "8.7a0"
|
||||
#define TCL_PATCH_LEVEL "8.7a2"
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) || defined(RC_INVOKED)
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* The following definitions set up the proper options for Windows compilers.
|
||||
@@ -89,6 +89,7 @@ extern "C" {
|
||||
# define JOIN(a,b) JOIN1(a,b)
|
||||
# define JOIN1(a,b) a##b
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* A special definition used to allow this header file to be included from
|
||||
@@ -140,7 +141,7 @@ extern "C" {
|
||||
# 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)
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
# define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))
|
||||
# define TCL_NORETURN __attribute__ ((noreturn))
|
||||
@@ -256,7 +257,7 @@ extern "C" {
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# undef _ANSI_ARGS_
|
||||
# define _ANSI_ARGS_(x) x
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Definitions that allow this header file to be used either with or without
|
||||
@@ -376,8 +377,8 @@ typedef long LONG;
|
||||
* we have one, we can have the other.)
|
||||
*
|
||||
* Also defines the following macros:
|
||||
* TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a real
|
||||
* 64-bit system.)
|
||||
* TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a
|
||||
* LP64 system such as modern Solaris or Linux ... not including Win64)
|
||||
* Tcl_WideAsLong - forgetful converter from wideInt to long.
|
||||
* Tcl_LongAsWide - sign-extending converter from long to wideInt.
|
||||
* Tcl_WideAsDouble - converter from wideInt to double.
|
||||
@@ -394,11 +395,7 @@ typedef long LONG;
|
||||
#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
|
||||
# if defined(_WIN32)
|
||||
# define TCL_WIDE_INT_TYPE __int64
|
||||
# ifdef __BORLANDC__
|
||||
# define TCL_LL_MODIFIER "L"
|
||||
# else /* __BORLANDC__ */
|
||||
# define TCL_LL_MODIFIER "I64"
|
||||
# endif /* __BORLANDC__ */
|
||||
# define TCL_LL_MODIFIER "I64"
|
||||
# elif defined(__GNUC__)
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
@@ -424,10 +421,6 @@ typedef TCL_WIDE_INT_TYPE Tcl_WideInt;
|
||||
typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
# define Tcl_WideAsLong(val) ((long)(val))
|
||||
# define Tcl_LongAsWide(val) ((long)(val))
|
||||
# define Tcl_WideAsDouble(val) ((double)((long)(val)))
|
||||
# define Tcl_DoubleAsWide(val) ((long)((double)(val)))
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "l"
|
||||
# endif /* !TCL_LL_MODIFIER */
|
||||
@@ -439,12 +432,13 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
# endif /* !TCL_LL_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)))
|
||||
# define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val)))
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#define Tcl_WideAsLong(val) ((long)((Tcl_WideInt)(val)))
|
||||
#define Tcl_LongAsWide(val) ((Tcl_WideInt)((long)(val)))
|
||||
#define Tcl_WideAsDouble(val) ((double)((Tcl_WideInt)(val)))
|
||||
#define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val)))
|
||||
|
||||
#if defined(_WIN32)
|
||||
# ifdef __BORLANDC__
|
||||
typedef struct stati64 Tcl_StatBuf;
|
||||
@@ -529,7 +523,7 @@ typedef struct Tcl_Interp
|
||||
int errorLineDontUse; /* Don't use in extensions! */
|
||||
#endif
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
Tcl_Interp;
|
||||
|
||||
typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler;
|
||||
@@ -1003,7 +997,9 @@ typedef struct Tcl_DString {
|
||||
|
||||
#define Tcl_DStringLength(dsPtr) ((dsPtr)->length)
|
||||
#define Tcl_DStringValue(dsPtr) ((dsPtr)->string)
|
||||
#define Tcl_DStringTrunc Tcl_DStringSetLength
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# define Tcl_DStringTrunc Tcl_DStringSetLength
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Definitions for the maximum number of digits of precision that may be
|
||||
@@ -1131,7 +1127,7 @@ typedef struct Tcl_DString {
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# define TCL_PARSE_PART1 0x400
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Types for linked variables:
|
||||
@@ -1147,8 +1143,13 @@ typedef struct Tcl_DString {
|
||||
#define TCL_LINK_SHORT 8
|
||||
#define TCL_LINK_USHORT 9
|
||||
#define TCL_LINK_UINT 10
|
||||
#if defined(TCL_WIDE_INT_IS_LONG) || defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define TCL_LINK_LONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_INT : TCL_LINK_INT)
|
||||
#define TCL_LINK_ULONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_UINT : TCL_LINK_UINT)
|
||||
#else
|
||||
#define TCL_LINK_LONG 11
|
||||
#define TCL_LINK_ULONG 12
|
||||
#endif
|
||||
#define TCL_LINK_FLOAT 13
|
||||
#define TCL_LINK_WIDE_UINT 14
|
||||
#define TCL_LINK_READ_ONLY 0x80
|
||||
@@ -2200,7 +2201,7 @@ typedef struct Tcl_EncodingType {
|
||||
*/
|
||||
|
||||
#ifndef TCL_UTF_MAX
|
||||
#define TCL_UTF_MAX 3
|
||||
#define TCL_UTF_MAX 4
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2262,6 +2263,8 @@ typedef struct mp_int mp_int;
|
||||
#define MP_INT_DECLARED
|
||||
typedef unsigned int mp_digit;
|
||||
#define MP_DIGIT_DECLARED
|
||||
typedef unsigned TCL_WIDE_INT_TYPE mp_word;
|
||||
#define MP_WORD_DECLARED
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -2534,7 +2537,7 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
Tcl_DbNewBignumObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewBooleanObj
|
||||
# define Tcl_NewBooleanObj(val) \
|
||||
Tcl_DbNewBooleanObj(val, __FILE__, __LINE__)
|
||||
Tcl_DbNewLongObj((val)!=0, __FILE__, __LINE__)
|
||||
# undef Tcl_NewByteArrayObj
|
||||
# define Tcl_NewByteArrayObj(bytes, len) \
|
||||
Tcl_DbNewByteArrayObj(bytes, len, __FILE__, __LINE__)
|
||||
@@ -2627,7 +2630,6 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
# define panic Tcl_Panic
|
||||
#endif
|
||||
# define panicVA Tcl_PanicVA
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -2638,6 +2640,8 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
|
||||
extern Tcl_AppInitProc Tcl_AppInit;
|
||||
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
#endif /* RC_INVOKED */
|
||||
|
||||
/*
|
||||
|
||||
+21
-1
@@ -137,6 +137,8 @@ typedef enum TalInstType {
|
||||
* ranges */
|
||||
ASSEM_BOOL, /* One Boolean operand */
|
||||
ASSEM_BOOL_LVT4, /* One Boolean, one 4-byte LVT ref. */
|
||||
ASSEM_CLOCK_READ, /* 1-byte unsigned-integer case number, in the
|
||||
* range 0-3 */
|
||||
ASSEM_CONCAT1, /* 1-byte unsigned-integer operand count, must
|
||||
* be strictly positive, consumes N, produces
|
||||
* 1 */
|
||||
@@ -350,6 +352,7 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
{"bitnot", ASSEM_1BYTE, INST_BITNOT, 1, 1},
|
||||
{"bitor", ASSEM_1BYTE, INST_BITOR, 2, 1},
|
||||
{"bitxor", ASSEM_1BYTE, INST_BITXOR, 2, 1},
|
||||
{"clockRead", ASSEM_CLOCK_READ, INST_CLOCK_READ, 0, 1},
|
||||
{"concat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1},
|
||||
{"concatStk", ASSEM_LIST, INST_CONCAT_STK, INT_MIN,1},
|
||||
{"coroName", ASSEM_1BYTE, INST_COROUTINE_NAME, 0, 1},
|
||||
@@ -1361,6 +1364,23 @@ AssembleOneLine(
|
||||
TclEmitInt4(localVar, envPtr);
|
||||
break;
|
||||
|
||||
case ASSEM_CLOCK_READ:
|
||||
if (parsePtr->numWords != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, &instNameObj, "imm8");
|
||||
goto cleanup;
|
||||
}
|
||||
if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (opnd < 0 || opnd > 3) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("operand must be [0..3]", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND<0,>3", NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, opnd);
|
||||
break;
|
||||
|
||||
case ASSEM_CONCAT1:
|
||||
if (parsePtr->numWords != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, &instNameObj, "imm8");
|
||||
@@ -4246,7 +4266,7 @@ AddBasicBlockRangeToErrorInfo(
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
Tcl_AddErrorInfo(interp, " and ");
|
||||
if (bbPtr->successor1 != NULL) {
|
||||
Tcl_SetIntObj(lineNo, bbPtr->successor1->startLine);
|
||||
TclSetLongObj(lineNo, bbPtr->successor1->startLine);
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
} else {
|
||||
Tcl_AddErrorInfo(interp, "end of assembly code");
|
||||
|
||||
+166
-77
@@ -265,7 +265,6 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"cd", Tcl_CdObjCmd, NULL, NULL, 0},
|
||||
{"close", Tcl_CloseObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"eof", Tcl_EofObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"encoding", Tcl_EncodingObjCmd, NULL, NULL, 0},
|
||||
{"exec", Tcl_ExecObjCmd, NULL, NULL, 0},
|
||||
{"exit", Tcl_ExitObjCmd, NULL, NULL, 0},
|
||||
{"fblocked", Tcl_FblockedObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
@@ -511,7 +510,11 @@ Tcl_CreateInterp(void)
|
||||
iPtr = ckalloc(sizeof(Interp));
|
||||
interp = (Tcl_Interp *) iPtr;
|
||||
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
iPtr->result = &tclEmptyString;
|
||||
#else
|
||||
iPtr->result = iPtr->resultSpace;
|
||||
#endif
|
||||
iPtr->freeProc = NULL;
|
||||
iPtr->errorLine = 0;
|
||||
iPtr->objResultPtr = Tcl_NewObj();
|
||||
@@ -571,9 +574,11 @@ Tcl_CreateInterp(void)
|
||||
iPtr->rootFramePtr = NULL; /* Initialise as soon as :: is available */
|
||||
iPtr->lookupNsPtr = NULL;
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
iPtr->appendResult = NULL;
|
||||
iPtr->appendAvl = 0;
|
||||
iPtr->appendUsed = 0;
|
||||
#endif
|
||||
|
||||
Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
|
||||
iPtr->packageUnknown = NULL;
|
||||
@@ -603,7 +608,9 @@ Tcl_CreateInterp(void)
|
||||
iPtr->emptyObjPtr = Tcl_NewObj();
|
||||
/* Another empty object. */
|
||||
Tcl_IncrRefCount(iPtr->emptyObjPtr);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
iPtr->resultSpace[0] = 0;
|
||||
#endif
|
||||
iPtr->threadId = Tcl_GetCurrentThread();
|
||||
|
||||
/* TIP #378 */
|
||||
@@ -790,16 +797,17 @@ Tcl_CreateInterp(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the "array", "binary", "chan", "dict", "file", "info",
|
||||
* "namespace" and "string" ensembles. Note that all these commands (and
|
||||
* their subcommands that are not present in the global namespace) are
|
||||
* wholly safe *except* for "file".
|
||||
* Create the "array", "binary", "chan", "clock", "dict", "encoding",
|
||||
* "file", "info", "namespace" and "string" ensembles. Note that all these
|
||||
* commands (and their subcommands that are not present in the global
|
||||
* namespace) are wholly safe *except* for "clock", "encoding" and "file".
|
||||
*/
|
||||
|
||||
TclInitArrayCmd(interp);
|
||||
TclInitBinaryCmd(interp);
|
||||
TclInitChanCmd(interp);
|
||||
TclInitDictCmd(interp);
|
||||
TclInitEncodingCmd(interp);
|
||||
TclInitFileCmd(interp);
|
||||
TclInitInfoCmd(interp);
|
||||
TclInitNamespaceCmd(interp);
|
||||
@@ -1027,6 +1035,7 @@ TclHideUnsafeCommands(
|
||||
Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
|
||||
}
|
||||
}
|
||||
TclMakeEncodingCommandSafe(interp); /* Ugh! */
|
||||
TclMakeFileCommandSafe(interp); /* Ugh! */
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1062,7 +1071,7 @@ Tcl_CallWhenDeleted(
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
static Tcl_ThreadDataKey assocDataCounterKey;
|
||||
int *assocDataCounterPtr =
|
||||
Tcl_GetThreadData(&assocDataCounterKey, (int)sizeof(int));
|
||||
Tcl_GetThreadData(&assocDataCounterKey, sizeof(int));
|
||||
int isNew;
|
||||
char buffer[32 + TCL_INTEGER_SPACE];
|
||||
AssocData *dPtr = ckalloc(sizeof(AssocData));
|
||||
@@ -1534,10 +1543,12 @@ DeleteInterpProc(
|
||||
if (iPtr->returnOpts) {
|
||||
Tcl_DecrRefCount(iPtr->returnOpts);
|
||||
}
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
if (iPtr->appendResult != NULL) {
|
||||
ckfree(iPtr->appendResult);
|
||||
iPtr->appendResult = NULL;
|
||||
}
|
||||
#endif
|
||||
TclFreePackageInfo(iPtr);
|
||||
while (iPtr->tracePtr != NULL) {
|
||||
Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr);
|
||||
@@ -2042,11 +2053,11 @@ Tcl_CreateCommand(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
ImportRef *oldRefPtr = NULL;
|
||||
Namespace *nsPtr, *dummy1, *dummy2;
|
||||
Command *cmdPtr, *refCmdPtr;
|
||||
Namespace *nsPtr;
|
||||
Command *cmdPtr;
|
||||
Tcl_HashEntry *hPtr;
|
||||
const char *tail;
|
||||
int isNew;
|
||||
int isNew = 0, deleted = 0;
|
||||
ImportedCmdData *dataPtr;
|
||||
|
||||
if (iPtr->flags & DELETED) {
|
||||
@@ -2059,32 +2070,52 @@ Tcl_CreateCommand(
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine where the command should reside. If its name contains
|
||||
* namespace qualifiers, we put it in the specified namespace; otherwise,
|
||||
* we always put it in the global namespace.
|
||||
* If the command name we seek to create already exists, we need to
|
||||
* delete that first. That can be tricky in the presence of traces.
|
||||
* Loop until we no longer find an existing command in the way, or
|
||||
* until we've deleted one command and that didn't finish the job.
|
||||
*/
|
||||
|
||||
if (strstr(cmdName, "::") != NULL) {
|
||||
TclGetNamespaceForQualName(interp, cmdName, NULL,
|
||||
TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
|
||||
if ((nsPtr == NULL) || (tail == NULL)) {
|
||||
return (Tcl_Command) NULL;
|
||||
}
|
||||
} else {
|
||||
nsPtr = iPtr->globalNsPtr;
|
||||
tail = cmdName;
|
||||
}
|
||||
while (1) {
|
||||
/*
|
||||
* Determine where the command should reside. If its name contains
|
||||
* namespace qualifiers, we put it in the specified namespace;
|
||||
* otherwise, we always put it in the global namespace.
|
||||
*/
|
||||
|
||||
if (strstr(cmdName, "::") != NULL) {
|
||||
Namespace *dummy1, *dummy2;
|
||||
|
||||
TclGetNamespaceForQualName(interp, cmdName, NULL,
|
||||
TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
|
||||
if ((nsPtr == NULL) || (tail == NULL)) {
|
||||
return (Tcl_Command) NULL;
|
||||
}
|
||||
} else {
|
||||
nsPtr = iPtr->globalNsPtr;
|
||||
tail = cmdName;
|
||||
}
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
|
||||
if (isNew || deleted) {
|
||||
/*
|
||||
* isNew - No conflict with existing command.
|
||||
* deleted - We've already deleted a conflicting command
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* An existing command conflicts. Try to delete it.. */
|
||||
cmdPtr = Tcl_GetHashValue(hPtr);
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
if (!isNew) {
|
||||
/*
|
||||
* Command already exists. Delete the old one. Be careful to preserve
|
||||
* Be careful to preserve
|
||||
* any existing import links so we can restore them down below. That
|
||||
* way, you can redefine a command and its import status will remain
|
||||
* intact.
|
||||
*/
|
||||
|
||||
cmdPtr = Tcl_GetHashValue(hPtr);
|
||||
cmdPtr->refCount++;
|
||||
if (cmdPtr->importRefPtr) {
|
||||
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
|
||||
@@ -2097,18 +2128,21 @@ Tcl_CreateCommand(
|
||||
cmdPtr->importRefPtr = NULL;
|
||||
}
|
||||
TclCleanupCommandMacro(cmdPtr);
|
||||
deleted = 1;
|
||||
}
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
if (!isNew) {
|
||||
/*
|
||||
* If the deletion callback recreated the command, just throw away
|
||||
* the new command (if we try to delete it again, we could get
|
||||
* stuck in an infinite loop).
|
||||
*/
|
||||
if (!isNew) {
|
||||
/*
|
||||
* If the deletion callback recreated the command, just throw away
|
||||
* the new command (if we try to delete it again, we could get
|
||||
* stuck in an infinite loop).
|
||||
*/
|
||||
|
||||
ckfree(Tcl_GetHashValue(hPtr));
|
||||
}
|
||||
|
||||
if (!deleted) {
|
||||
|
||||
ckfree(Tcl_GetHashValue(hPtr));
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Command resolvers (per-interp, per-namespace) might have resolved
|
||||
* to a command for the given namespace scope with this command not
|
||||
@@ -2156,7 +2190,7 @@ Tcl_CreateCommand(
|
||||
if (oldRefPtr != NULL) {
|
||||
cmdPtr->importRefPtr = oldRefPtr;
|
||||
while (oldRefPtr != NULL) {
|
||||
refCmdPtr = oldRefPtr->importedCmdPtr;
|
||||
Command *refCmdPtr = oldRefPtr->importedCmdPtr;
|
||||
dataPtr = refCmdPtr->objClientData;
|
||||
dataPtr->realCmdPtr = cmdPtr;
|
||||
oldRefPtr = oldRefPtr->nextPtr;
|
||||
@@ -2217,11 +2251,11 @@ Tcl_CreateObjCommand(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
ImportRef *oldRefPtr = NULL;
|
||||
Namespace *nsPtr, *dummy1, *dummy2;
|
||||
Command *cmdPtr, *refCmdPtr;
|
||||
Namespace *nsPtr;
|
||||
Command *cmdPtr;
|
||||
Tcl_HashEntry *hPtr;
|
||||
const char *tail;
|
||||
int isNew;
|
||||
int isNew = 0, deleted = 0;
|
||||
ImportedCmdData *dataPtr;
|
||||
|
||||
if (iPtr->flags & DELETED) {
|
||||
@@ -2234,29 +2268,45 @@ Tcl_CreateObjCommand(
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine where the command should reside. If its name contains
|
||||
* namespace qualifiers, we put it in the specified namespace; otherwise,
|
||||
* we always put it in the global namespace.
|
||||
* If the command name we seek to create already exists, we need to
|
||||
* delete that first. That can be tricky in the presence of traces.
|
||||
* Loop until we no longer find an existing command in the way, or
|
||||
* until we've deleted one command and that didn't finish the job.
|
||||
*/
|
||||
|
||||
if (strstr(cmdName, "::") != NULL) {
|
||||
TclGetNamespaceForQualName(interp, cmdName, NULL,
|
||||
while (1) {
|
||||
/*
|
||||
* Determine where the command should reside. If its name contains
|
||||
* namespace qualifiers, we put it in the specified namespace;
|
||||
* otherwise, we always put it in the global namespace.
|
||||
*/
|
||||
|
||||
if (strstr(cmdName, "::") != NULL) {
|
||||
Namespace *dummy1, *dummy2;
|
||||
|
||||
TclGetNamespaceForQualName(interp, cmdName, NULL,
|
||||
TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
|
||||
if ((nsPtr == NULL) || (tail == NULL)) {
|
||||
return (Tcl_Command) NULL;
|
||||
}
|
||||
} else {
|
||||
nsPtr = iPtr->globalNsPtr;
|
||||
tail = cmdName;
|
||||
}
|
||||
if ((nsPtr == NULL) || (tail == NULL)) {
|
||||
return (Tcl_Command) NULL;
|
||||
}
|
||||
} else {
|
||||
nsPtr = iPtr->globalNsPtr;
|
||||
tail = cmdName;
|
||||
}
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
TclInvalidateNsPath(nsPtr);
|
||||
if (!isNew) {
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
|
||||
if (isNew || deleted) {
|
||||
/*
|
||||
* isNew - No conflict with existing command.
|
||||
* deleted - We've already deleted a conflicting command
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* An existing command conflicts. Try to delete it.. */
|
||||
cmdPtr = Tcl_GetHashValue(hPtr);
|
||||
|
||||
/* Command already exists. */
|
||||
|
||||
/*
|
||||
* [***] This is wrong. See Tcl Bug a16752c252.
|
||||
* However, this buggy behavior is kept under particular
|
||||
@@ -2293,18 +2343,20 @@ Tcl_CreateObjCommand(
|
||||
cmdPtr->importRefPtr = NULL;
|
||||
}
|
||||
TclCleanupCommandMacro(cmdPtr);
|
||||
deleted = 1;
|
||||
}
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
if (!isNew) {
|
||||
/*
|
||||
* If the deletion callback recreated the command, just throw away
|
||||
* the new command (if we try to delete it again, we could get
|
||||
* stuck in an infinite loop).
|
||||
*/
|
||||
if (!isNew) {
|
||||
/*
|
||||
* If the deletion callback recreated the command, just throw away
|
||||
* the new command (if we try to delete it again, we could get
|
||||
* stuck in an infinite loop).
|
||||
*/
|
||||
|
||||
ckfree(Tcl_GetHashValue(hPtr));
|
||||
}
|
||||
} else {
|
||||
ckfree(Tcl_GetHashValue(hPtr));
|
||||
}
|
||||
|
||||
if (!deleted) {
|
||||
/*
|
||||
* Command resolvers (per-interp, per-namespace) might have resolved
|
||||
* to a command for the given namespace scope with this command not
|
||||
@@ -2324,6 +2376,7 @@ Tcl_CreateObjCommand(
|
||||
*/
|
||||
|
||||
TclInvalidateNsCmdLookup(nsPtr);
|
||||
TclInvalidateNsPath(nsPtr);
|
||||
}
|
||||
cmdPtr = ckalloc(sizeof(Command));
|
||||
Tcl_SetHashValue(hPtr, cmdPtr);
|
||||
@@ -2351,7 +2404,7 @@ Tcl_CreateObjCommand(
|
||||
if (oldRefPtr != NULL) {
|
||||
cmdPtr->importRefPtr = oldRefPtr;
|
||||
while (oldRefPtr != NULL) {
|
||||
refCmdPtr = oldRefPtr->importedCmdPtr;
|
||||
Command *refCmdPtr = oldRefPtr->importedCmdPtr;
|
||||
dataPtr = refCmdPtr->objClientData;
|
||||
dataPtr->realCmdPtr = cmdPtr;
|
||||
oldRefPtr = oldRefPtr->nextPtr;
|
||||
@@ -3550,7 +3603,7 @@ OldMathFuncProc(
|
||||
args[k].type = TCL_INT;
|
||||
break;
|
||||
}
|
||||
if (Tcl_GetWideIntFromObj(interp, valuePtr, &args[k].wideValue)
|
||||
if (TclGetWideIntFromObj(interp, valuePtr, &args[k].wideValue)
|
||||
== TCL_OK) {
|
||||
args[k].type = TCL_WIDE_INT;
|
||||
break;
|
||||
@@ -3576,7 +3629,7 @@ OldMathFuncProc(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
valuePtr = Tcl_GetObjResult(interp);
|
||||
Tcl_GetWideIntFromObj(NULL, valuePtr, &args[k].wideValue);
|
||||
TclGetWideIntFromObj(NULL, valuePtr, &args[k].wideValue);
|
||||
Tcl_ResetResult(interp);
|
||||
break;
|
||||
}
|
||||
@@ -4705,7 +4758,7 @@ TEOV_RunEnterTraces(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Command *cmdPtr = *cmdPtrPtr;
|
||||
int newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
|
||||
size_t newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
|
||||
int length, traceCode = TCL_OK;
|
||||
const char *command = TclGetStringFromObj(commandPtr, &length);
|
||||
|
||||
@@ -5850,6 +5903,7 @@ TclArgumentGet(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_Eval
|
||||
int
|
||||
Tcl_Eval(
|
||||
@@ -5902,6 +5956,7 @@ Tcl_GlobalEvalObj(
|
||||
{
|
||||
return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -6728,6 +6783,7 @@ Tcl_AppendObjToErrorInfo(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_AddErrorInfo
|
||||
void
|
||||
Tcl_AddErrorInfo(
|
||||
@@ -6737,6 +6793,7 @@ Tcl_AddErrorInfo(
|
||||
{
|
||||
Tcl_AddObjErrorInfo(interp, message, -1);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -6909,6 +6966,7 @@ Tcl_VarEval(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_GlobalEval
|
||||
int
|
||||
Tcl_GlobalEval(
|
||||
@@ -6926,6 +6984,7 @@ Tcl_GlobalEval(
|
||||
iPtr->varFramePtr = savedVarFramePtr;
|
||||
return result;
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -7179,7 +7238,7 @@ ExprIsqrtFunc(
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
|
||||
if (TclGetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (w < 0) {
|
||||
@@ -7401,7 +7460,7 @@ ExprAbsFunc(
|
||||
}
|
||||
goto unChanged;
|
||||
} else if (l == LONG_MIN) {
|
||||
TclBNInitBignumFromLong(&big, l);
|
||||
TclInitBignumFromLong(&big, l);
|
||||
goto tooLarge;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewLongObj(-l));
|
||||
@@ -7436,7 +7495,7 @@ ExprAbsFunc(
|
||||
goto unChanged;
|
||||
}
|
||||
if (w == LLONG_MIN) {
|
||||
TclBNInitBignumFromWideInt(&big, w);
|
||||
TclInitBignumFromWideInt(&big, w);
|
||||
goto tooLarge;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
|
||||
@@ -7622,7 +7681,7 @@ ExprWideFunc(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objPtr = Tcl_GetObjResult(interp);
|
||||
if (Tcl_GetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) {
|
||||
if (TclGetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) {
|
||||
/*
|
||||
* Truncate the bignum; keep only bits in wide int range.
|
||||
*/
|
||||
@@ -7633,7 +7692,7 @@ ExprWideFunc(
|
||||
mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big);
|
||||
objPtr = Tcl_NewBignumObj(&big);
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
|
||||
TclGetWideIntFromObj(NULL, objPtr, &wResult);
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
|
||||
@@ -8750,6 +8809,35 @@ TclNRCoroutineActivateCallback(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclNREvalList --
|
||||
*
|
||||
* Callback to invoke command as list, used in order to delayed
|
||||
* processing of canonical list command in sane environment.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
TclNREvalList(
|
||||
ClientData data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
int objc;
|
||||
Tcl_Obj **objv;
|
||||
Tcl_Obj *listPtr = data[0];
|
||||
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
|
||||
TclMarkTailcall(interp);
|
||||
TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
|
||||
TclListObjGetElements(NULL, listPtr, &objc, &objv);
|
||||
return TclNREvalObjv(interp, objc, objv, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -8804,7 +8892,8 @@ NRCoroInjectObjCmd(
|
||||
*/
|
||||
|
||||
iPtr->execEnvPtr = corPtr->eePtr;
|
||||
TclNREvalObjEx(interp, Tcl_NewListObj(objc-2, objv+2), 0, NULL, INT_MIN);
|
||||
TclNRAddCallback(interp, TclNREvalList, Tcl_NewListObj(objc-2, objv+2),
|
||||
NULL, NULL, NULL);
|
||||
iPtr->execEnvPtr = savedEEPtr;
|
||||
|
||||
return TCL_OK;
|
||||
|
||||
+16
-8
@@ -536,7 +536,7 @@ SetByteArrayFromAny(
|
||||
const char *src, *srcEnd;
|
||||
unsigned char *dst;
|
||||
ByteArray *byteArrayPtr;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
|
||||
if (objPtr->typePtr == &properByteArrayType) {
|
||||
return TCL_OK;
|
||||
@@ -551,7 +551,7 @@ SetByteArrayFromAny(
|
||||
|
||||
byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length));
|
||||
for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
|
||||
src += Tcl_UtfToUniChar(src, &ch);
|
||||
src += TclUtfToUniChar(src, &ch);
|
||||
improper = improper || (ch > 255);
|
||||
*dst++ = UCHAR(ch);
|
||||
}
|
||||
@@ -1300,10 +1300,10 @@ BinaryFormatCmd(
|
||||
|
||||
badField:
|
||||
{
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
char buf[TCL_UTF_MAX + 1];
|
||||
|
||||
Tcl_UtfToUniChar(errorString, &ch);
|
||||
TclUtfToUniChar(errorString, &ch);
|
||||
buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad field specifier \"%s\"", buf));
|
||||
@@ -1670,10 +1670,10 @@ BinaryScanCmd(
|
||||
|
||||
badField:
|
||||
{
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
char buf[TCL_UTF_MAX + 1];
|
||||
|
||||
Tcl_UtfToUniChar(errorString, &ch);
|
||||
TclUtfToUniChar(errorString, &ch);
|
||||
buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad field specifier \"%s\"", buf));
|
||||
@@ -1743,7 +1743,15 @@ GetFormatSpec(
|
||||
(*formatPtr)++;
|
||||
*countPtr = BINARY_ALL;
|
||||
} else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
|
||||
*countPtr = strtoul(*formatPtr, (char **) formatPtr, 10);
|
||||
unsigned long int count;
|
||||
|
||||
errno = 0;
|
||||
count = strtoul(*formatPtr, (char **) formatPtr, 10);
|
||||
if (errno || (count > (unsigned long) INT_MAX)) {
|
||||
*countPtr = INT_MAX;
|
||||
} else {
|
||||
*countPtr = (int) count;
|
||||
}
|
||||
} else {
|
||||
*countPtr = BINARY_NOCOUNT;
|
||||
}
|
||||
@@ -2276,7 +2284,7 @@ ScanNumber(
|
||||
Tcl_Obj *bigObj = NULL;
|
||||
mp_int big;
|
||||
|
||||
TclBNInitBignumFromWideUInt(&big, uwvalue);
|
||||
TclInitBignumFromWideUInt(&big, uwvalue);
|
||||
bigObj = Tcl_NewBignumObj(&big);
|
||||
return bigObj;
|
||||
}
|
||||
|
||||
+27
-24
@@ -89,14 +89,14 @@ static struct mem_header *allocHead = NULL; /* List of allocated structures */
|
||||
#define BODY_OFFSET \
|
||||
((size_t) (&((struct mem_header *) 0)->body))
|
||||
|
||||
static int total_mallocs = 0;
|
||||
static int total_frees = 0;
|
||||
static unsigned int total_mallocs = 0;
|
||||
static unsigned int total_frees = 0;
|
||||
static size_t current_bytes_malloced = 0;
|
||||
static size_t maximum_bytes_malloced = 0;
|
||||
static int current_malloc_packets = 0;
|
||||
static int maximum_malloc_packets = 0;
|
||||
static int break_on_malloc = 0;
|
||||
static int trace_on_at_malloc = 0;
|
||||
static unsigned int current_malloc_packets = 0;
|
||||
static unsigned int maximum_malloc_packets = 0;
|
||||
static unsigned int break_on_malloc = 0;
|
||||
static unsigned int trace_on_at_malloc = 0;
|
||||
static int alloc_tracing = FALSE;
|
||||
static int init_malloced_bodies = TRUE;
|
||||
#ifdef MEM_VALIDATE
|
||||
@@ -184,18 +184,18 @@ TclDumpMemoryInfo(
|
||||
return 0;
|
||||
}
|
||||
sprintf(buf,
|
||||
"total mallocs %10d\n"
|
||||
"total frees %10d\n"
|
||||
"current packets allocated %10d\n"
|
||||
"current bytes allocated %10lu\n"
|
||||
"maximum packets allocated %10d\n"
|
||||
"maximum bytes allocated %10lu\n",
|
||||
"total mallocs %10u\n"
|
||||
"total frees %10u\n"
|
||||
"current packets allocated %10u\n"
|
||||
"current bytes allocated %10" TCL_LL_MODIFIER "u\n"
|
||||
"maximum packets allocated %10u\n"
|
||||
"maximum bytes allocated %10" TCL_LL_MODIFIER "u\n",
|
||||
total_mallocs,
|
||||
total_frees,
|
||||
current_malloc_packets,
|
||||
(unsigned long)current_bytes_malloced,
|
||||
(Tcl_WideInt)current_bytes_malloced,
|
||||
maximum_malloc_packets,
|
||||
(unsigned long)maximum_bytes_malloced);
|
||||
(Tcl_WideInt)maximum_bytes_malloced);
|
||||
if (flags == 0) {
|
||||
fprintf((FILE *)clientData, "%s", buf);
|
||||
} else {
|
||||
@@ -359,9 +359,8 @@ Tcl_DumpActiveMemory(
|
||||
Tcl_MutexLock(ckallocMutexPtr);
|
||||
for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
|
||||
address = &memScanP->body[0];
|
||||
fprintf(fileP, "%8" TCL_LL_MODIFIER "x - %8" TCL_LL_MODIFIER "x %7" TCL_LL_MODIFIER "d @ %s %d %s",
|
||||
(Tcl_WideInt)(size_t)address,
|
||||
(Tcl_WideInt)((size_t)address + memScanP->length - 1),
|
||||
fprintf(fileP, "%p - %p %" TCL_LL_MODIFIER "d @ %s %d %s",
|
||||
address, address + memScanP->length - 1,
|
||||
(Tcl_WideInt)memScanP->length, memScanP->file, memScanP->line,
|
||||
(memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
|
||||
(void) fputc('\n', fileP);
|
||||
@@ -450,7 +449,7 @@ Tcl_DbCkalloc(
|
||||
total_mallocs++;
|
||||
if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
|
||||
(void) fflush(stdout);
|
||||
fprintf(stderr, "reached malloc trace enable point (%d)\n",
|
||||
fprintf(stderr, "reached malloc trace enable point (%u)\n",
|
||||
total_mallocs);
|
||||
fflush(stderr);
|
||||
alloc_tracing = TRUE;
|
||||
@@ -465,7 +464,7 @@ Tcl_DbCkalloc(
|
||||
if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
|
||||
break_on_malloc = 0;
|
||||
(void) fflush(stdout);
|
||||
Tcl_Panic("reached malloc break limit (%d)", total_mallocs);
|
||||
Tcl_Panic("reached malloc break limit (%u)", total_mallocs);
|
||||
}
|
||||
|
||||
current_malloc_packets++;
|
||||
@@ -848,22 +847,24 @@ MemoryCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1],"break_on_malloc") == 0) {
|
||||
int value;
|
||||
if (argc != 3) {
|
||||
goto argError;
|
||||
}
|
||||
if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK) {
|
||||
if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break_on_malloc = (unsigned int) value;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1],"info") == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10lu\n%-25s %10d\n%-25s %10lu\n",
|
||||
"%-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",
|
||||
"total mallocs", total_mallocs, "total frees", total_frees,
|
||||
"current packets allocated", current_malloc_packets,
|
||||
"current bytes allocated", (unsigned long)current_bytes_malloced,
|
||||
"current bytes allocated", (Tcl_WideInt)current_bytes_malloced,
|
||||
"maximum packets allocated", maximum_malloc_packets,
|
||||
"maximum bytes allocated", (unsigned long)maximum_bytes_malloced));
|
||||
"maximum bytes allocated", (Tcl_WideInt)maximum_bytes_malloced));
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1], "init") == 0) {
|
||||
@@ -934,12 +935,14 @@ MemoryCmd(
|
||||
}
|
||||
|
||||
if (strcmp(argv[1],"trace_on_at_malloc") == 0) {
|
||||
int value;
|
||||
if (argc != 3) {
|
||||
goto argError;
|
||||
}
|
||||
if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK) {
|
||||
if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
trace_on_at_malloc = value;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1],"validate") == 0) {
|
||||
|
||||
+29
-17
@@ -91,7 +91,7 @@ static const char *const literals[] = {
|
||||
* Structure containing the client data for [clock]
|
||||
*/
|
||||
|
||||
typedef struct ClockClientData {
|
||||
typedef struct {
|
||||
size_t refCount; /* Number of live references. */
|
||||
Tcl_Obj **literals; /* Pool of object literals. */
|
||||
} ClockClientData;
|
||||
@@ -208,11 +208,7 @@ struct ClockCommand {
|
||||
};
|
||||
|
||||
static const struct ClockCommand clockCommands[] = {
|
||||
{ "clicks", ClockClicksObjCmd },
|
||||
{ "getenv", ClockGetenvObjCmd },
|
||||
{ "microseconds", ClockMicrosecondsObjCmd },
|
||||
{ "milliseconds", ClockMillisecondsObjCmd },
|
||||
{ "seconds", ClockSecondsObjCmd },
|
||||
{ "Oldscan", TclClockOldscanObjCmd },
|
||||
{ "ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd },
|
||||
{ "GetDateFields", ClockGetdatefieldsObjCmd },
|
||||
@@ -253,6 +249,19 @@ TclClockInit(
|
||||
ClockClientData *data;
|
||||
int i;
|
||||
|
||||
/* Structure of the 'clock' ensemble */
|
||||
|
||||
static const EnsembleImplMap clockImplMap[] = {
|
||||
{"add", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"clicks", ClockClicksObjCmd, TclCompileClockClicksCmd, NULL, NULL, 0},
|
||||
{"format", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"microseconds", ClockMicrosecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(1), 0},
|
||||
{"milliseconds", ClockMillisecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(2), 0},
|
||||
{"scan", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL , 0},
|
||||
{"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(3), 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Safe interps get [::clock] as alias to a master, so do not need their
|
||||
* own copies of the support routines.
|
||||
@@ -276,6 +285,7 @@ TclClockInit(
|
||||
|
||||
/*
|
||||
* Install the commands.
|
||||
* TODO - Let Tcl_MakeEnsemble do this?
|
||||
*/
|
||||
|
||||
#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
|
||||
@@ -286,6 +296,10 @@ TclClockInit(
|
||||
Tcl_CreateObjCommand(interp, cmdName, clockCmdPtr->objCmdProc, data,
|
||||
ClockDeleteCmdProc);
|
||||
}
|
||||
|
||||
/* Make the clock ensemble */
|
||||
|
||||
TclMakeEnsemble(interp, "clock", clockImplMap);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -349,7 +363,7 @@ ClockConvertlocaltoutcObjCmd(
|
||||
"found in dictionary", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if ((Tcl_GetWideIntFromObj(interp, secondsObj,
|
||||
if ((TclGetWideIntFromObj(interp, secondsObj,
|
||||
&fields.localSeconds) != TCL_OK)
|
||||
|| (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK)
|
||||
|| ConvertLocalToUTC(interp, &fields, objv[2], changeover)) {
|
||||
@@ -428,7 +442,7 @@ ClockGetdatefieldsObjCmd(
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "seconds tzdata changeover");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetWideIntFromObj(interp, objv[1], &fields.seconds) != TCL_OK
|
||||
if (TclGetWideIntFromObj(interp, objv[1], &fields.seconds) != TCL_OK
|
||||
|| TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1134,7 +1148,7 @@ LookupLastTransition(
|
||||
*/
|
||||
|
||||
if (Tcl_ListObjIndex(interp, rowv[0], 0, &compObj) != TCL_OK
|
||||
|| Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
|
||||
|| TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1157,7 +1171,7 @@ LookupLastTransition(
|
||||
int m = (l + u + 1) / 2;
|
||||
|
||||
if (Tcl_ListObjIndex(interp, rowv[m], 0, &compObj) != TCL_OK ||
|
||||
Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
|
||||
TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
if (tick >= compVal) {
|
||||
@@ -1507,9 +1521,9 @@ GetJulianDayFromEraYearMonthDay(
|
||||
* See above bug for details. The casts are necessary.
|
||||
*/
|
||||
if (ym1 >= 0)
|
||||
ym1o4 = ym1 / 4;
|
||||
ym1o4 = ym1 / 4;
|
||||
else {
|
||||
ym1o4 = - (int) (((unsigned int) -ym1) / 4);
|
||||
ym1o4 = - (int) (((unsigned int) -ym1) / 4);
|
||||
}
|
||||
#endif
|
||||
if (ym1 % 4 < 0) {
|
||||
@@ -1564,12 +1578,10 @@ static int
|
||||
IsGregorianLeapYear(
|
||||
TclDateFields *fields) /* Date to test */
|
||||
{
|
||||
int year;
|
||||
int year = fields->year;
|
||||
|
||||
if (fields->era == BCE) {
|
||||
year = 1 - fields->year;
|
||||
} else {
|
||||
year = fields->year;
|
||||
year = 1 - year;
|
||||
}
|
||||
if (year%4 != 0) {
|
||||
return 0;
|
||||
@@ -1680,7 +1692,7 @@ ThreadSafeLocalTime(
|
||||
* Get a thread-local buffer to hold the returned time.
|
||||
*/
|
||||
|
||||
struct tm *tmPtr = Tcl_GetThreadData(&tmKey, (int) sizeof(struct tm));
|
||||
struct tm *tmPtr = Tcl_GetThreadData(&tmKey, sizeof(struct tm));
|
||||
#ifdef HAVE_LOCALTIME_R
|
||||
localtime_r(timePtr, tmPtr);
|
||||
#else
|
||||
@@ -1936,7 +1948,7 @@ ClockParseformatargsObjCmd(
|
||||
* Check options.
|
||||
*/
|
||||
|
||||
if (Tcl_GetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) {
|
||||
if (TclGetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if ((saw & (1 << CLOCK_FORMAT_GMT))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+349
-71
@@ -46,9 +46,24 @@ struct ForeachState {
|
||||
|
||||
static int CheckAccess(Tcl_Interp *interp, Tcl_Obj *pathPtr,
|
||||
int mode);
|
||||
static int BadEncodingSubcommand(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingConvertfromObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingConverttoObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingDirsObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingNamesObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingSystemObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static inline int ForeachAssignments(Tcl_Interp *interp,
|
||||
struct ForeachState *statePtr);
|
||||
static inline void ForeachCleanup(Tcl_Interp *interp,
|
||||
@@ -542,81 +557,282 @@ Tcl_EncodingObjCmd(
|
||||
|
||||
switch ((enum options) index) {
|
||||
case ENC_CONVERTTO:
|
||||
case ENC_CONVERTFROM: {
|
||||
Tcl_Obj *data;
|
||||
Tcl_DString ds;
|
||||
Tcl_Encoding encoding;
|
||||
int length;
|
||||
const char *stringPtr;
|
||||
|
||||
if (objc == 3) {
|
||||
encoding = Tcl_GetEncoding(interp, NULL);
|
||||
data = objv[2];
|
||||
} else if (objc == 4) {
|
||||
if (Tcl_GetEncodingFromObj(interp, objv[2], &encoding) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
data = objv[3];
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?encoding? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if ((enum options) index == ENC_CONVERTFROM) {
|
||||
/*
|
||||
* Treat the string as binary data.
|
||||
*/
|
||||
|
||||
stringPtr = (char *) Tcl_GetByteArrayFromObj(data, &length);
|
||||
Tcl_ExternalToUtfDString(encoding, stringPtr, length, &ds);
|
||||
|
||||
/*
|
||||
* Note that we cannot use Tcl_DStringResult here because it will
|
||||
* truncate the string at the first null byte.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, TclDStringToObj(&ds));
|
||||
} else {
|
||||
/*
|
||||
* Store the result as binary data.
|
||||
*/
|
||||
|
||||
stringPtr = TclGetStringFromObj(data, &length);
|
||||
Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds);
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
|
||||
(unsigned char *) Tcl_DStringValue(&ds),
|
||||
Tcl_DStringLength(&ds)));
|
||||
Tcl_DStringFree(&ds);
|
||||
}
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
break;
|
||||
}
|
||||
return EncodingConverttoObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_CONVERTFROM:
|
||||
return EncodingConvertfromObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_DIRS:
|
||||
return EncodingDirsObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_NAMES:
|
||||
if (objc > 2) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_GetEncodingNames(interp);
|
||||
break;
|
||||
return EncodingNamesObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_SYSTEM:
|
||||
if (objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?encoding?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 2) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
Tcl_GetEncodingName(NULL), -1));
|
||||
} else {
|
||||
return Tcl_SetSystemEncoding(interp, TclGetString(objv[2]));
|
||||
}
|
||||
break;
|
||||
return EncodingSystemObjCmd(dummy, interp, objc, objv);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* TclInitEncodingCmd --
|
||||
*
|
||||
* This function creates the 'encoding' ensemble.
|
||||
*
|
||||
* Results:
|
||||
* Returns the Tcl_Command so created.
|
||||
*
|
||||
* Side effects:
|
||||
* The ensemble is initialized.
|
||||
*
|
||||
* This command is hidden in a safe interpreter.
|
||||
*/
|
||||
|
||||
Tcl_Command
|
||||
TclInitEncodingCmd(
|
||||
Tcl_Interp* interp) /* Tcl interpreter */
|
||||
{
|
||||
static const EnsembleImplMap encodingImplMap[] = {
|
||||
{"convertfrom", EncodingConvertfromObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"convertto", EncodingConverttoObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"dirs", EncodingDirsObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"names", EncodingNamesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"system", EncodingSystemObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
return TclMakeEnsemble(interp, "encoding", encodingImplMap);
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* TclMakeEncodingCommandSafe --
|
||||
*
|
||||
* This function hides the unsafe 'dirs' and 'system' subcommands of
|
||||
* the "encoding" Tcl command ensemble. It must be called only from
|
||||
* TclHideUnsafeCommands.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result
|
||||
*
|
||||
* Side effects:
|
||||
* Adds commands to the table of hidden commands.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclMakeEncodingCommandSafe(
|
||||
Tcl_Interp* interp) /* Tcl interpreter */
|
||||
{
|
||||
static const struct {
|
||||
const char *cmdName;
|
||||
int unsafe;
|
||||
} unsafeInfo[] = {
|
||||
{"convertfrom", 0},
|
||||
{"convertto", 0},
|
||||
{"dirs", 1},
|
||||
{"names", 0},
|
||||
{"system", 0},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
int i;
|
||||
Tcl_DString oldBuf, newBuf;
|
||||
|
||||
Tcl_DStringInit(&oldBuf);
|
||||
TclDStringAppendLiteral(&oldBuf, "::tcl::encoding::");
|
||||
Tcl_DStringInit(&newBuf);
|
||||
TclDStringAppendLiteral(&newBuf, "tcl:encoding:");
|
||||
for (i=0 ; unsafeInfo[i].cmdName != NULL ; i++) {
|
||||
if (unsafeInfo[i].unsafe) {
|
||||
const char *oldName, *newName;
|
||||
|
||||
Tcl_DStringSetLength(&oldBuf, 17);
|
||||
oldName = Tcl_DStringAppend(&oldBuf, unsafeInfo[i].cmdName, -1);
|
||||
Tcl_DStringSetLength(&newBuf, 13);
|
||||
newName = Tcl_DStringAppend(&newBuf, unsafeInfo[i].cmdName, -1);
|
||||
if (TclRenameCommand(interp, oldName, "___tmp") != TCL_OK
|
||||
|| Tcl_HideCommand(interp, "___tmp", newName) != TCL_OK) {
|
||||
Tcl_Panic("problem making 'encoding %s' safe: %s",
|
||||
unsafeInfo[i].cmdName,
|
||||
Tcl_GetString(Tcl_GetObjResult(interp)));
|
||||
}
|
||||
Tcl_CreateObjCommand(interp, oldName, BadEncodingSubcommand,
|
||||
(ClientData) unsafeInfo[i].cmdName, NULL);
|
||||
}
|
||||
}
|
||||
Tcl_DStringFree(&oldBuf);
|
||||
Tcl_DStringFree(&newBuf);
|
||||
|
||||
/*
|
||||
* Ugh. The [encoding] command is now actually safe, but it is assumed by
|
||||
* scripts that it is not, which messes up security policies.
|
||||
*/
|
||||
|
||||
if (Tcl_HideCommand(interp, "encoding", "encoding") != TCL_OK) {
|
||||
Tcl_Panic("problem making 'encoding' safe: %s",
|
||||
Tcl_GetString(Tcl_GetObjResult(interp)));
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* BadEncodingSubcommand --
|
||||
*
|
||||
* Command used to act as a backstop implementation when subcommands of
|
||||
* "encoding" are unsafe (the real implementations of the subcommands are
|
||||
* hidden). The clientData is always the full official subcommand name.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result (always a TCL_ERROR).
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
BadEncodingSubcommand(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
const char *subcommandName = (const char *) clientData;
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"not allowed to invoke subcommand %s of encoding", subcommandName));
|
||||
Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* EncodingConvertfromObjCmd --
|
||||
*
|
||||
* This command converts a byte array in an external encoding into a
|
||||
* Tcl string
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingConvertfromObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Obj *data; /* Byte array to convert */
|
||||
Tcl_DString ds; /* Buffer to hold the string */
|
||||
Tcl_Encoding encoding; /* Encoding to use */
|
||||
int length; /* Length of the byte array being converted */
|
||||
const char *bytesPtr; /* Pointer to the first byte of the array */
|
||||
|
||||
if (objc == 2) {
|
||||
encoding = Tcl_GetEncoding(interp, NULL);
|
||||
data = objv[1];
|
||||
} else if (objc == 3) {
|
||||
if (Tcl_GetEncodingFromObj(interp, objv[1], &encoding) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
data = objv[2];
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?encoding? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the string into a byte array in 'ds'
|
||||
*/
|
||||
bytesPtr = (char *) Tcl_GetByteArrayFromObj(data, &length);
|
||||
Tcl_ExternalToUtfDString(encoding, bytesPtr, length, &ds);
|
||||
|
||||
/*
|
||||
* Note that we cannot use Tcl_DStringResult here because it will
|
||||
* truncate the string at the first null byte.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, TclDStringToObj(&ds));
|
||||
|
||||
/*
|
||||
* We're done with the encoding
|
||||
*/
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return TCL_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* EncodingConverttoObjCmd --
|
||||
*
|
||||
* This command converts a Tcl string into a byte array that
|
||||
* encodes the string according to some encoding.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingConverttoObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Obj *data; /* String to convert */
|
||||
Tcl_DString ds; /* Buffer to hold the byte array */
|
||||
Tcl_Encoding encoding; /* Encoding to use */
|
||||
int length; /* Length of the string being converted */
|
||||
const char *stringPtr; /* Pointer to the first byte of the string */
|
||||
|
||||
/* TODO - ADJUST OBJ INDICES WHEN ENSEMBLIFYING THIS */
|
||||
|
||||
if (objc == 2) {
|
||||
encoding = Tcl_GetEncoding(interp, NULL);
|
||||
data = objv[1];
|
||||
} else if (objc == 3) {
|
||||
if (Tcl_GetEncodingFromObj(interp, objv[1], &encoding) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
data = objv[2];
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?encoding? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the string to a byte array in 'ds'
|
||||
*/
|
||||
|
||||
stringPtr = TclGetStringFromObj(data, &length);
|
||||
Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds);
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewByteArrayObj((unsigned char*) Tcl_DStringValue(&ds),
|
||||
Tcl_DStringLength(&ds)));
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
/*
|
||||
* We're done with the encoding
|
||||
*/
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return TCL_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -642,16 +858,16 @@ EncodingDirsObjCmd(
|
||||
{
|
||||
Tcl_Obj *dirListObj;
|
||||
|
||||
if (objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?dirList?");
|
||||
if (objc > 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?dirList?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 2) {
|
||||
if (objc == 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
dirListObj = objv[2];
|
||||
dirListObj = objv[1];
|
||||
if (Tcl_SetEncodingSearchPath(dirListObj) == TCL_ERROR) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected directory list but got \"%s\"",
|
||||
@@ -664,6 +880,68 @@ EncodingDirsObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* EncodingNamesObjCmd --
|
||||
*
|
||||
* This command returns a list of the available encoding names
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingNamesObjCmd(ClientData dummy, /* Unused */
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
int objc, /* Number of command line args */
|
||||
Tcl_Obj* const objv[]) /* Vector of command line args */
|
||||
{
|
||||
if (objc > 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_GetEncodingNames(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* EncodingSystemObjCmd --
|
||||
*
|
||||
* This command retrieves or changes the system encoding
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result
|
||||
*
|
||||
* Side effects:
|
||||
* May change the system encoding.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingSystemObjCmd(ClientData dummy, /* Unused */
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
int objc, /* Number of command line args */
|
||||
Tcl_Obj* const objv[]) /* Vector of command line args */
|
||||
{
|
||||
if (objc > 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?encoding?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 1) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj(Tcl_GetEncodingName(NULL), -1));
|
||||
} else {
|
||||
return Tcl_SetSystemEncoding(interp, TclGetString(objv[1]));
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+21
-22
@@ -3682,7 +3682,7 @@ Tcl_LsortObjCmd(
|
||||
int sortMode = SORTMODE_ASCII;
|
||||
int group, groupSize, groupOffset, idx, allocatedIndexVector = 0;
|
||||
Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
|
||||
SortElement *elementArray, *elementPtr;
|
||||
SortElement *elementArray = NULL, *elementPtr;
|
||||
SortInfo sortInfo; /* Information about this sort that needs to
|
||||
* be passed to the comparison function. */
|
||||
# define NUM_LISTS 30
|
||||
@@ -3728,7 +3728,7 @@ Tcl_LsortObjCmd(
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0,
|
||||
&index) != TCL_OK) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
switch ((enum Lsort_Switches) index) {
|
||||
case LSORT_ASCII:
|
||||
@@ -3741,7 +3741,7 @@ Tcl_LsortObjCmd(
|
||||
"by comparison command", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
sortInfo.sortMode = SORTMODE_COMMAND;
|
||||
cmdPtr = objv[i+1];
|
||||
@@ -3766,12 +3766,12 @@ Tcl_LsortObjCmd(
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
if (TclListObjGetElements(interp, objv[i+1], &indexc,
|
||||
&indexv) != TCL_OK) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3788,7 +3788,7 @@ Tcl_LsortObjCmd(
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (-index option item number %d)", j));
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
indexPtr = objv[i+1];
|
||||
@@ -3817,11 +3817,11 @@ Tcl_LsortObjCmd(
|
||||
"followed by stride length", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
if (Tcl_GetIntFromObj(interp, objv[i+1], &groupSize) != TCL_OK) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
if (groupSize < 2) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
@@ -3829,7 +3829,7 @@ Tcl_LsortObjCmd(
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT",
|
||||
"BADSTRIDE", NULL);
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
group = 1;
|
||||
i++;
|
||||
@@ -3884,7 +3884,7 @@ Tcl_LsortObjCmd(
|
||||
listObj = TclListObjCopy(interp, listObj);
|
||||
if (listObj == NULL) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3902,7 +3902,7 @@ Tcl_LsortObjCmd(
|
||||
Tcl_IncrRefCount(newObjPtr);
|
||||
TclDecrRefCount(newObjPtr);
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, newCommandPtr, Tcl_NewObj());
|
||||
sortInfo.compareCmdPtr = newCommandPtr;
|
||||
@@ -3995,7 +3995,7 @@ Tcl_LsortObjCmd(
|
||||
* begins sorting it into the sublists as it appears.
|
||||
*/
|
||||
|
||||
elementArray = TclStackAlloc(interp, length * sizeof(SortElement));
|
||||
elementArray = ckalloc(length * sizeof(SortElement));
|
||||
|
||||
for (i=0; i < length; i++){
|
||||
idx = groupSize * i + groupOffset;
|
||||
@@ -4005,7 +4005,7 @@ Tcl_LsortObjCmd(
|
||||
*/
|
||||
indexPtr = SelectObjFromSublist(listObjPtrs[idx], &sortInfo);
|
||||
if (sortInfo.resultCode != TCL_OK) {
|
||||
goto done1;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
indexPtr = listObjPtrs[idx];
|
||||
@@ -4022,7 +4022,7 @@ Tcl_LsortObjCmd(
|
||||
|
||||
if (TclGetWideIntFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done1;
|
||||
goto done;
|
||||
}
|
||||
elementArray[i].collationKey.wideValue = a;
|
||||
} else if (sortMode == SORTMODE_REAL) {
|
||||
@@ -4031,7 +4031,7 @@ Tcl_LsortObjCmd(
|
||||
if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr,
|
||||
&a) != TCL_OK) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done1;
|
||||
goto done;
|
||||
}
|
||||
elementArray[i].collationKey.doubleValue = a;
|
||||
} else {
|
||||
@@ -4118,19 +4118,18 @@ Tcl_LsortObjCmd(
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
}
|
||||
|
||||
done1:
|
||||
TclStackFree(interp, elementArray);
|
||||
|
||||
done:
|
||||
if (sortMode == SORTMODE_COMMAND) {
|
||||
TclDecrRefCount(sortInfo.compareCmdPtr);
|
||||
TclDecrRefCount(listObj);
|
||||
sortInfo.compareCmdPtr = NULL;
|
||||
}
|
||||
done2:
|
||||
if (allocatedIndexVector) {
|
||||
TclStackFree(interp, sortInfo.indexv);
|
||||
}
|
||||
if (elementArray) {
|
||||
ckfree(elementArray);
|
||||
}
|
||||
return sortInfo.resultCode;
|
||||
}
|
||||
|
||||
@@ -4371,7 +4370,7 @@ static int
|
||||
DictionaryCompare(
|
||||
const char *left, const char *right) /* The strings to compare. */
|
||||
{
|
||||
Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
|
||||
Tcl_UniChar uniLeft = 0, uniRight = 0, uniLeftLower, uniRightLower;
|
||||
int diff, zeros;
|
||||
int secondaryDiff = 0;
|
||||
|
||||
@@ -4440,8 +4439,8 @@ DictionaryCompare(
|
||||
*/
|
||||
|
||||
if ((*left != '\0') && (*right != '\0')) {
|
||||
left += Tcl_UtfToUniChar(left, &uniLeft);
|
||||
right += Tcl_UtfToUniChar(right, &uniRight);
|
||||
left += TclUtfToUniChar(left, &uniLeft);
|
||||
right += TclUtfToUniChar(right, &uniRight);
|
||||
|
||||
/*
|
||||
* Convert both chars to lower for the comparison, because
|
||||
|
||||
+138
-16
@@ -309,7 +309,7 @@ Tcl_RegexpObjCmd(
|
||||
eflags = 0;
|
||||
} else if (offset > stringLength) {
|
||||
eflags = TCL_REG_NOTBOL;
|
||||
} else if (Tcl_GetUniChar(objPtr, offset-1) == (Tcl_UniChar)'\n') {
|
||||
} else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') {
|
||||
eflags = 0;
|
||||
} else {
|
||||
eflags = TCL_REG_NOTBOL;
|
||||
@@ -487,26 +487,27 @@ Tcl_RegsubObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int idx, result, cflags, all, wlen, wsublen, numMatches, offset;
|
||||
int start, end, subStart, subEnd, match;
|
||||
int start, end, subStart, subEnd, match, command, numParts;
|
||||
Tcl_RegExp regExpr;
|
||||
Tcl_RegExpInfo info;
|
||||
Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL;
|
||||
Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend;
|
||||
Tcl_UniChar ch = 0, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend;
|
||||
|
||||
static const char *const options[] = {
|
||||
"-all", "-nocase", "-expanded",
|
||||
"-line", "-linestop", "-lineanchor", "-start",
|
||||
"-all", "-command", "-expanded", "-line",
|
||||
"-linestop", "-lineanchor", "-nocase", "-start",
|
||||
"--", NULL
|
||||
};
|
||||
enum options {
|
||||
REGSUB_ALL, REGSUB_NOCASE, REGSUB_EXPANDED,
|
||||
REGSUB_LINE, REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_START,
|
||||
REGSUB_ALL, REGSUB_COMMAND, REGSUB_EXPANDED, REGSUB_LINE,
|
||||
REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_NOCASE, REGSUB_START,
|
||||
REGSUB_LAST
|
||||
};
|
||||
|
||||
cflags = TCL_REG_ADVANCED;
|
||||
all = 0;
|
||||
offset = 0;
|
||||
command = 0;
|
||||
resultPtr = NULL;
|
||||
|
||||
for (idx = 1; idx < objc; idx++) {
|
||||
@@ -528,6 +529,9 @@ Tcl_RegsubObjCmd(
|
||||
case REGSUB_NOCASE:
|
||||
cflags |= TCL_REG_NOCASE;
|
||||
break;
|
||||
case REGSUB_COMMAND:
|
||||
command = 1;
|
||||
break;
|
||||
case REGSUB_EXPANDED:
|
||||
cflags |= TCL_REG_EXPANDED;
|
||||
break;
|
||||
@@ -585,7 +589,7 @@ Tcl_RegsubObjCmd(
|
||||
}
|
||||
}
|
||||
|
||||
if (all && (offset == 0)
|
||||
if (all && (offset == 0) && (command == 0)
|
||||
&& (strpbrk(TclGetString(objv[2]), "&\\") == NULL)
|
||||
&& (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
|
||||
/*
|
||||
@@ -661,6 +665,28 @@ Tcl_RegsubObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (command) {
|
||||
/*
|
||||
* In command-prefix mode, we require that the third non-option
|
||||
* argument be a list, so we enforce that here. Afterwards, we fetch
|
||||
* the RE compilation again in case objv[0] and objv[2] are the same
|
||||
* object. (If they aren't, that's cheap to do.)
|
||||
*/
|
||||
|
||||
if (Tcl_ListObjLength(interp, objv[2], &numParts) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (numParts < 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"command prefix must be a list of at least one element",
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGSUB",
|
||||
"CMDEMPTY", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure to avoid problems where the objects are shared. This can
|
||||
* cause RegExpObj <> UnicodeObj shimmering that causes data corruption.
|
||||
@@ -678,7 +704,9 @@ Tcl_RegsubObjCmd(
|
||||
} else {
|
||||
subPtr = objv[2];
|
||||
}
|
||||
wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen);
|
||||
if (!command) {
|
||||
wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen);
|
||||
}
|
||||
|
||||
result = TCL_OK;
|
||||
|
||||
@@ -736,6 +764,90 @@ Tcl_RegsubObjCmd(
|
||||
end = info.matches[0].end;
|
||||
Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start);
|
||||
|
||||
/*
|
||||
* In command-prefix mode, the substitutions are added as quoted
|
||||
* arguments to the subSpec to form a command, that is then executed
|
||||
* and the result used as the string to substitute in. Actually,
|
||||
* everything is passed through Tcl_EvalObjv, as that's much faster.
|
||||
*/
|
||||
|
||||
if (command) {
|
||||
Tcl_Obj **args = NULL, **parts;
|
||||
int numArgs;
|
||||
|
||||
Tcl_ListObjGetElements(interp, subPtr, &numParts, &parts);
|
||||
numArgs = numParts + info.nsubs + 1;
|
||||
args = ckalloc(sizeof(Tcl_Obj*) * numArgs);
|
||||
memcpy(args, parts, sizeof(Tcl_Obj*) * numParts);
|
||||
|
||||
for (idx = 0 ; idx <= info.nsubs ; idx++) {
|
||||
subStart = info.matches[idx].start;
|
||||
subEnd = info.matches[idx].end;
|
||||
if ((subStart >= 0) && (subEnd >= 0)) {
|
||||
args[idx + numParts] = Tcl_NewUnicodeObj(
|
||||
wstring + offset + subStart, subEnd - subStart);
|
||||
} else {
|
||||
args[idx + numParts] = Tcl_NewObj();
|
||||
}
|
||||
Tcl_IncrRefCount(args[idx + numParts]);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we're locally holding the references to the
|
||||
* argument words we added for this time round the loop, and the
|
||||
* subPtr is holding the references to the words that the user
|
||||
* supplied directly. None are zero-refcount, which is important
|
||||
* because Tcl_EvalObjv is "hairy monster" in terms of refcount
|
||||
* handling, being able to optionally add references to any of its
|
||||
* argument words. We'll drop the local refs immediately
|
||||
* afterwards; subPtr is handled in the main exit stanza.
|
||||
*/
|
||||
|
||||
result = Tcl_EvalObjv(interp, numArgs, args, 0);
|
||||
for (idx = 0 ; idx <= info.nsubs ; idx++) {
|
||||
TclDecrRefCount(args[idx + numParts]);
|
||||
}
|
||||
ckfree(args);
|
||||
if (result != TCL_OK) {
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (%s substitution computation script)",
|
||||
options[REGSUB_COMMAND]));
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
Tcl_AppendObjToObj(resultPtr, Tcl_GetObjResult(interp));
|
||||
Tcl_ResetResult(interp);
|
||||
|
||||
/*
|
||||
* Refetch the unicode, in case the representation was smashed by
|
||||
* the user code.
|
||||
*/
|
||||
|
||||
wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen);
|
||||
|
||||
offset += end;
|
||||
if (end == 0 || start == end) {
|
||||
/*
|
||||
* Always consume at least one character of the input string
|
||||
* in order to prevent infinite loops, even when we
|
||||
* technically matched the empty string; we must not match
|
||||
* again at the same spot.
|
||||
*/
|
||||
|
||||
if (offset < wlen) {
|
||||
Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1);
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
if (all) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Append the subSpec argument to the variable, making appropriate
|
||||
* substitutions. This code is a bit hairy because of the backslash
|
||||
@@ -1061,7 +1173,7 @@ Tcl_SplitObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
int len;
|
||||
const char *splitChars;
|
||||
const char *stringPtr;
|
||||
@@ -1106,6 +1218,10 @@ Tcl_SplitObjCmd(
|
||||
for ( ; stringPtr < end; stringPtr += len) {
|
||||
len = TclUtfToUniChar(stringPtr, &ch);
|
||||
|
||||
if (!len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume Tcl_UniChar is an integral type...
|
||||
*/
|
||||
@@ -1146,7 +1262,7 @@ Tcl_SplitObjCmd(
|
||||
} else {
|
||||
const char *element, *p, *splitEnd;
|
||||
int splitLen;
|
||||
Tcl_UniChar splitChar;
|
||||
Tcl_UniChar splitChar = 0;
|
||||
|
||||
/*
|
||||
* Normal case: split on any of a given set of characters. Discard
|
||||
@@ -1370,7 +1486,7 @@ StringIsCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
const char *string1, *end, *stop;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
int (*chcomp)(int) = NULL; /* The UniChar comparison function. */
|
||||
int i, failat = 0, result = 1, strict = 0, index, length1, length2;
|
||||
Tcl_Obj *objPtr, *failVarObj = NULL;
|
||||
@@ -1565,7 +1681,7 @@ StringIsCmd(
|
||||
}
|
||||
break;
|
||||
case STR_IS_WIDE:
|
||||
if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) {
|
||||
if (TCL_OK == TclGetWideIntFromObj(NULL, objPtr, &w)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1702,8 +1818,14 @@ StringIsCmd(
|
||||
}
|
||||
end = string1 + length1;
|
||||
for (; string1 < end; string1 += length2, failat++) {
|
||||
int fullchar;
|
||||
length2 = TclUtfToUniChar(string1, &ch);
|
||||
if (!chcomp(ch)) {
|
||||
fullchar = ch;
|
||||
if (!length2) {
|
||||
length2 = TclUtfToUniChar(string1, &ch);
|
||||
fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000;
|
||||
}
|
||||
if (!chcomp(fullchar)) {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
@@ -2298,7 +2420,7 @@ StringStartCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
const char *p, *string;
|
||||
int cur, index, length, numChars;
|
||||
|
||||
@@ -2359,7 +2481,7 @@ StringEndCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
const char *p, *end, *string;
|
||||
int cur, index, length, numChars;
|
||||
|
||||
|
||||
@@ -734,6 +734,105 @@ TclCompileCatchCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCompileClockClicksCmd --
|
||||
*
|
||||
* Procedure called to compile the "tcl::clock::clicks" command.
|
||||
*
|
||||
* Results:
|
||||
* Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
|
||||
* evaluation to run time.
|
||||
*
|
||||
* Side effects:
|
||||
* Instructions are added to envPtr to execute the "clock clicks"
|
||||
* command at runtime.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclCompileClockClicksCmd(
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
Tcl_Token* tokenPtr;
|
||||
|
||||
switch (parsePtr->numWords) {
|
||||
case 1:
|
||||
/*
|
||||
* No args
|
||||
*/
|
||||
TclEmitInstInt1(INST_CLOCK_READ, 0, envPtr);
|
||||
break;
|
||||
case 2:
|
||||
/*
|
||||
* -milliseconds or -microseconds
|
||||
*/
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD
|
||||
|| tokenPtr[1].size < 4
|
||||
|| tokenPtr[1].size > 13) {
|
||||
return TCL_ERROR;
|
||||
} else if (!strncmp(tokenPtr[1].start, "-microseconds",
|
||||
tokenPtr[1].size)) {
|
||||
TclEmitInstInt1(INST_CLOCK_READ, 1, envPtr);
|
||||
break;
|
||||
} else if (!strncmp(tokenPtr[1].start, "-milliseconds",
|
||||
tokenPtr[1].size)) {
|
||||
TclEmitInstInt1(INST_CLOCK_READ, 2, envPtr);
|
||||
break;
|
||||
} else {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
default:
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCompileClockReadingCmd --
|
||||
*
|
||||
* Procedure called to compile the "tcl::clock::microseconds",
|
||||
* "tcl::clock::milliseconds" and "tcl::clock::seconds" commands.
|
||||
*
|
||||
* Results:
|
||||
* Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
|
||||
* evaluation to run time.
|
||||
*
|
||||
* Side effects:
|
||||
* Instructions are added to envPtr to execute the "clock clicks"
|
||||
* command at runtime.
|
||||
*
|
||||
* Client data is 1 for microseconds, 2 for milliseconds, 3 for seconds.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclCompileClockReadingCmd(
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
if (parsePtr->numWords != 1) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclEmitInstInt1(INST_CLOCK_READ, PTR2INT(cmdPtr->objClientData), envPtr);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
@@ -1885,7 +1885,7 @@ ParseLexeme(
|
||||
{
|
||||
const char *end;
|
||||
int scanned;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_Obj *literal = NULL;
|
||||
unsigned char byte;
|
||||
|
||||
@@ -2064,13 +2064,13 @@ ParseLexeme(
|
||||
|
||||
if (!TclIsBareword(*start) || *start == '_') {
|
||||
if (Tcl_UtfCharComplete(start, numBytes)) {
|
||||
scanned = Tcl_UtfToUniChar(start, &ch);
|
||||
scanned = TclUtfToUniChar(start, &ch);
|
||||
} else {
|
||||
char utfBytes[TCL_UTF_MAX];
|
||||
|
||||
memcpy(utfBytes, start, (size_t) numBytes);
|
||||
utfBytes[numBytes] = '\0';
|
||||
scanned = Tcl_UtfToUniChar(utfBytes, &ch);
|
||||
scanned = TclUtfToUniChar(utfBytes, &ch);
|
||||
}
|
||||
*lexemePtr = INVALID;
|
||||
Tcl_DecrRefCount(literal);
|
||||
|
||||
@@ -654,6 +654,11 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
/* Lappend list to general variable.
|
||||
* Stack: ... varName list => ... listVarContents */
|
||||
|
||||
{"clockRead", 2, +1, 1, {OPERAND_UINT1}},
|
||||
/* Read clock out to the stack. Operand is which clock to read
|
||||
* 0=clicks, 1=microseconds, 2=milliseconds, 3=seconds.
|
||||
* Stack: ... => ... time */
|
||||
|
||||
{NULL, 0, 0, 0, {OPERAND_NONE}}
|
||||
};
|
||||
|
||||
|
||||
+16
-14
@@ -425,7 +425,7 @@ typedef struct ByteCode {
|
||||
* compiled. If the code is executed if a
|
||||
* different namespace, it must be
|
||||
* recompiled. */
|
||||
int nsEpoch; /* Value of nsPtr->resolverEpoch when this
|
||||
size_t nsEpoch; /* Value of nsPtr->resolverEpoch when this
|
||||
* ByteCode was compiled. Used to invalidate
|
||||
* code when new namespace resolution rules
|
||||
* are put into effect. */
|
||||
@@ -821,8 +821,10 @@ typedef struct ByteCode {
|
||||
#define INST_LAPPEND_LIST_ARRAY_STK 187
|
||||
#define INST_LAPPEND_LIST_STK 188
|
||||
|
||||
#define INST_CLOCK_READ 189
|
||||
|
||||
/* The last opcode */
|
||||
#define LAST_INST_OPCODE 188
|
||||
#define LAST_INST_OPCODE 189
|
||||
|
||||
/*
|
||||
* Table describing the Tcl bytecode instructions: their name (for displaying
|
||||
@@ -1238,10 +1240,10 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
|
||||
|
||||
#define TclCheckStackDepth(depth, envPtr) \
|
||||
do { \
|
||||
int dd = (depth); \
|
||||
if (dd != (envPtr)->currStackDepth) { \
|
||||
int _dd = (depth); \
|
||||
if (_dd != (envPtr)->currStackDepth) { \
|
||||
Tcl_Panic("bad stack depth computations: is %i, should be %i", \
|
||||
(envPtr)->currStackDepth, dd); \
|
||||
(envPtr)->currStackDepth, _dd); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -1257,12 +1259,12 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
|
||||
|
||||
#define TclUpdateStackReqs(op, i, envPtr) \
|
||||
do { \
|
||||
int delta = tclInstructionTable[(op)].stackEffect; \
|
||||
if (delta) { \
|
||||
if (delta == INT_MIN) { \
|
||||
delta = 1 - (i); \
|
||||
int _delta = tclInstructionTable[(op)].stackEffect; \
|
||||
if (_delta) { \
|
||||
if (_delta == INT_MIN) { \
|
||||
_delta = 1 - (i); \
|
||||
} \
|
||||
TclAdjustStackDepth(delta, envPtr); \
|
||||
TclAdjustStackDepth(_delta, envPtr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -1376,11 +1378,11 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
|
||||
|
||||
#define TclEmitPush(objIndex, envPtr) \
|
||||
do { \
|
||||
register int objIndexCopy = (objIndex); \
|
||||
if (objIndexCopy <= 255) { \
|
||||
TclEmitInstInt1(INST_PUSH1, objIndexCopy, (envPtr)); \
|
||||
register int _objIndexCopy = (objIndex); \
|
||||
if (_objIndexCopy <= 255) { \
|
||||
TclEmitInstInt1(INST_PUSH1, _objIndexCopy, (envPtr)); \
|
||||
} else { \
|
||||
TclEmitInstInt4(INST_PUSH4, objIndexCopy, (envPtr)); \
|
||||
TclEmitInstInt4(INST_PUSH4, _objIndexCopy, (envPtr)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* tclDate.h --
|
||||
*
|
||||
* This header file handles common usage of clock primitives
|
||||
* between tclDate.c (yacc), tclClock.c and tclClockFmt.c.
|
||||
*
|
||||
* Copyright (c) 2014 Serg G. Brester (aka sebres)
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifndef _TCLCLOCK_H
|
||||
#define _TCLCLOCK_H
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
#define JULIAN_DAY_POSIX_EPOCH 2440588
|
||||
#define GREGORIAN_CHANGE_DATE 2361222
|
||||
#define SECONDS_PER_DAY 86400
|
||||
#define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
|
||||
* SECONDS_PER_DAY)
|
||||
#define FOUR_CENTURIES 146097 /* days */
|
||||
#define JDAY_1_JAN_1_CE_JULIAN 1721424
|
||||
#define JDAY_1_JAN_1_CE_GREGORIAN 1721426
|
||||
#define ONE_CENTURY_GREGORIAN 36524 /* days */
|
||||
#define FOUR_YEARS 1461 /* days */
|
||||
#define ONE_YEAR 365 /* days */
|
||||
|
||||
#define RODDENBERRY 1946 /* Another epoch (Hi, Jeff!) */
|
||||
|
||||
|
||||
#define CLF_OPTIONAL (1 << 0) /* token is non mandatory */
|
||||
#define CLF_POSIXSEC (1 << 1)
|
||||
#define CLF_LOCALSEC (1 << 2)
|
||||
#define CLF_JULIANDAY (1 << 3)
|
||||
#define CLF_TIME (1 << 4)
|
||||
#define CLF_CENTURY (1 << 6)
|
||||
#define CLF_DAYOFMONTH (1 << 7)
|
||||
#define CLF_DAYOFYEAR (1 << 8)
|
||||
#define CLF_MONTH (1 << 9)
|
||||
#define CLF_YEAR (1 << 10)
|
||||
#define CLF_ISO8601YEAR (1 << 12)
|
||||
#define CLF_ISO8601 (1 << 13)
|
||||
#define CLF_ISO8601CENTURY (1 << 14)
|
||||
#define CLF_SIGNED (1 << 15)
|
||||
/* On demand (lazy) assemble flags */
|
||||
#define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */
|
||||
#define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */
|
||||
#define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */
|
||||
|
||||
#define CLF_DATE (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | \
|
||||
CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | CLF_ISO8601)
|
||||
|
||||
/*
|
||||
* Enumeration of the string literals used in [clock]
|
||||
*/
|
||||
|
||||
typedef enum ClockLiteral {
|
||||
LIT__NIL,
|
||||
LIT__DEFAULT_FORMAT,
|
||||
LIT_SYSTEM, LIT_CURRENT, LIT_C,
|
||||
LIT_BCE, LIT_CE,
|
||||
LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR,
|
||||
LIT_ERA, LIT_GMT, LIT_GREGORIAN,
|
||||
LIT_INTEGER_VALUE_TOO_LARGE,
|
||||
LIT_ISO8601WEEK, LIT_ISO8601YEAR,
|
||||
LIT_JULIANDAY, LIT_LOCALSECONDS,
|
||||
LIT_MONTH,
|
||||
LIT_SECONDS, LIT_TZNAME, LIT_TZOFFSET,
|
||||
LIT_YEAR,
|
||||
LIT_TZDATA,
|
||||
LIT_GETSYSTEMTIMEZONE,
|
||||
LIT_SETUPTIMEZONE,
|
||||
LIT_MCGET,
|
||||
LIT_GETSYSTEMLOCALE, LIT_GETCURRENTLOCALE,
|
||||
LIT_LOCALIZE_FORMAT,
|
||||
LIT__END
|
||||
} ClockLiteral;
|
||||
|
||||
#define CLOCK_LITERAL_ARRAY(litarr) static const char *const litarr[] = { \
|
||||
"", \
|
||||
"%a %b %d %H:%M:%S %Z %Y", \
|
||||
"system", "current", "C", \
|
||||
"BCE", "CE", \
|
||||
"dayOfMonth", "dayOfWeek", "dayOfYear", \
|
||||
"era", ":GMT", "gregorian", \
|
||||
"integer value too large to represent", \
|
||||
"iso8601Week", "iso8601Year", \
|
||||
"julianDay", "localSeconds", \
|
||||
"month", \
|
||||
"seconds", "tzName", "tzOffset", \
|
||||
"year", \
|
||||
"::tcl::clock::TZData", \
|
||||
"::tcl::clock::GetSystemTimeZone", \
|
||||
"::tcl::clock::SetupTimeZone", \
|
||||
"::tcl::clock::mcget", \
|
||||
"::tcl::clock::GetSystemLocale", "::tcl::clock::mclocale", \
|
||||
"::tcl::clock::LocalizeFormat" \
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumeration of the msgcat literals used in [clock]
|
||||
*/
|
||||
|
||||
typedef enum ClockMsgCtLiteral {
|
||||
MCLIT__NIL, /* placeholder */
|
||||
MCLIT_MONTHS_FULL, MCLIT_MONTHS_ABBREV, MCLIT_MONTHS_COMB,
|
||||
MCLIT_DAYS_OF_WEEK_FULL, MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_COMB,
|
||||
MCLIT_AM, MCLIT_PM,
|
||||
MCLIT_LOCALE_ERAS,
|
||||
MCLIT_BCE, MCLIT_CE,
|
||||
MCLIT_BCE2, MCLIT_CE2,
|
||||
MCLIT_BCE3, MCLIT_CE3,
|
||||
MCLIT_LOCALE_NUMERALS,
|
||||
MCLIT__END
|
||||
} ClockMsgCtLiteral;
|
||||
|
||||
#define CLOCK_LOCALE_LITERAL_ARRAY(litarr, pref) static const char *const litarr[] = { \
|
||||
pref "", \
|
||||
pref "MONTHS_FULL", pref "MONTHS_ABBREV", pref "MONTHS_COMB", \
|
||||
pref "DAYS_OF_WEEK_FULL", pref "DAYS_OF_WEEK_ABBREV", pref "DAYS_OF_WEEK_COMB", \
|
||||
pref "AM", pref "PM", \
|
||||
pref "LOCALE_ERAS", \
|
||||
pref "BCE", pref "CE", \
|
||||
pref "b.c.e.", pref "c.e.", \
|
||||
pref "b.c.", pref "a.d.", \
|
||||
pref "LOCALE_NUMERALS", \
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure containing the fields used in [clock format] and [clock scan]
|
||||
*/
|
||||
|
||||
typedef struct TclDateFields {
|
||||
|
||||
/* Cacheable fields: */
|
||||
|
||||
Tcl_WideInt seconds; /* Time expressed in seconds from the Posix
|
||||
* epoch */
|
||||
Tcl_WideInt localSeconds; /* Local time expressed in nominal seconds
|
||||
* from the Posix epoch */
|
||||
int tzOffset; /* Time zone offset in seconds east of
|
||||
* Greenwich */
|
||||
int julianDay; /* Julian Day Number in local time zone */
|
||||
enum {BCE=1, CE=0} era; /* Era */
|
||||
int gregorian; /* Flag == 1 if the date is Gregorian */
|
||||
int year; /* Year of the era */
|
||||
int dayOfYear; /* Day of the year (1 January == 1) */
|
||||
int month; /* Month number */
|
||||
int dayOfMonth; /* Day of the month */
|
||||
int iso8601Year; /* ISO8601 week-based year */
|
||||
int iso8601Week; /* ISO8601 week number */
|
||||
int dayOfWeek; /* Day of the week */
|
||||
int hour; /* Hours of day (in-between time only calculation) */
|
||||
int minutes; /* Minutes of day (in-between time only calculation) */
|
||||
int secondOfDay; /* Seconds of day (in-between time only calculation) */
|
||||
|
||||
/* Non cacheable fields: */
|
||||
|
||||
Tcl_Obj *tzName; /* Name (or corresponding DST-abbreviation) of the
|
||||
* time zone, if set the refCount is incremented */
|
||||
} TclDateFields;
|
||||
|
||||
#define ClockCacheableDateFieldsSize \
|
||||
TclOffset(TclDateFields, tzName)
|
||||
|
||||
/*
|
||||
* Structure contains return parsed fields.
|
||||
*/
|
||||
|
||||
typedef struct DateInfo {
|
||||
const char *dateStart;
|
||||
const char *dateInput;
|
||||
const char *dateEnd;
|
||||
|
||||
TclDateFields date;
|
||||
|
||||
int flags;
|
||||
|
||||
int dateHaveDate;
|
||||
|
||||
int dateMeridian;
|
||||
int dateHaveTime;
|
||||
|
||||
int dateTimezone;
|
||||
int dateDSTmode;
|
||||
int dateHaveZone;
|
||||
|
||||
int dateRelMonth;
|
||||
int dateRelDay;
|
||||
int dateRelSeconds;
|
||||
int dateHaveRel;
|
||||
|
||||
int dateMonthOrdinalIncr;
|
||||
int dateMonthOrdinal;
|
||||
int dateHaveOrdinalMonth;
|
||||
|
||||
int dateDayOrdinal;
|
||||
int dateDayNumber;
|
||||
int dateHaveDay;
|
||||
|
||||
int *dateRelPointer;
|
||||
|
||||
int dateSpaceCount;
|
||||
int dateDigitCount;
|
||||
|
||||
int dateCentury;
|
||||
|
||||
Tcl_Obj* messages; /* Error messages */
|
||||
const char* separatrix; /* String separating messages */
|
||||
} DateInfo;
|
||||
|
||||
#define yydate (info->date) /* Date fields used for converting */
|
||||
|
||||
#define yyDay (info->date.dayOfMonth)
|
||||
#define yyMonth (info->date.month)
|
||||
#define yyYear (info->date.year)
|
||||
|
||||
#define yyHour (info->date.hour)
|
||||
#define yyMinutes (info->date.minutes)
|
||||
#define yySeconds (info->date.secondOfDay)
|
||||
|
||||
#define yyDSTmode (info->dateDSTmode)
|
||||
#define yyDayOrdinal (info->dateDayOrdinal)
|
||||
#define yyDayNumber (info->dateDayNumber)
|
||||
#define yyMonthOrdinalIncr (info->dateMonthOrdinalIncr)
|
||||
#define yyMonthOrdinal (info->dateMonthOrdinal)
|
||||
#define yyHaveDate (info->dateHaveDate)
|
||||
#define yyHaveDay (info->dateHaveDay)
|
||||
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
|
||||
#define yyHaveRel (info->dateHaveRel)
|
||||
#define yyHaveTime (info->dateHaveTime)
|
||||
#define yyHaveZone (info->dateHaveZone)
|
||||
#define yyTimezone (info->dateTimezone)
|
||||
#define yyMeridian (info->dateMeridian)
|
||||
#define yyRelMonth (info->dateRelMonth)
|
||||
#define yyRelDay (info->dateRelDay)
|
||||
#define yyRelSeconds (info->dateRelSeconds)
|
||||
#define yyRelPointer (info->dateRelPointer)
|
||||
#define yyInput (info->dateInput)
|
||||
#define yyDigitCount (info->dateDigitCount)
|
||||
#define yySpaceCount (info->dateSpaceCount)
|
||||
|
||||
static inline void
|
||||
ClockInitDateInfo(DateInfo *info) {
|
||||
memset(info, 0, sizeof(DateInfo));
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure containing the command arguments supplied to [clock format] and [clock scan]
|
||||
*/
|
||||
|
||||
#define CLF_EXTENDED (1 << 4)
|
||||
#define CLF_STRICT (1 << 8)
|
||||
#define CLF_LOCALE_USED (1 << 15)
|
||||
|
||||
typedef struct ClockFmtScnCmdArgs {
|
||||
ClientData clientData; /* Opaque pointer to literal pool, etc. */
|
||||
Tcl_Interp *interp; /* Tcl interpreter */
|
||||
|
||||
Tcl_Obj *formatObj; /* Format */
|
||||
Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */
|
||||
Tcl_Obj *timezoneObj; /* Default time zone in which the time will be expressed */
|
||||
Tcl_Obj *baseObj; /* Base (scan and add) or clockValue (format) */
|
||||
int flags; /* Flags control scanning */
|
||||
|
||||
Tcl_Obj *mcDictObj; /* Current dictionary of tcl::clock package for given localeObj*/
|
||||
} ClockFmtScnCmdArgs;
|
||||
|
||||
/*
|
||||
* Structure containing the client data for [clock]
|
||||
*/
|
||||
|
||||
typedef struct ClockClientData {
|
||||
size_t refCount; /* Number of live references. */
|
||||
Tcl_Obj **literals; /* Pool of object literals (common, locale independent). */
|
||||
Tcl_Obj **mcLiterals; /* Msgcat object literals with mc-keys for search with locale. */
|
||||
Tcl_Obj **mcLitIdxs; /* Msgcat object indices prefixed with _IDX_,
|
||||
* used for quick dictionary search */
|
||||
|
||||
/* Cache for current clock parameters, imparted via "configure" */
|
||||
unsigned long LastTZEpoch;
|
||||
int currentYearCentury;
|
||||
int yearOfCenturySwitch;
|
||||
Tcl_Obj *SystemTimeZone;
|
||||
Tcl_Obj *SystemSetupTZData;
|
||||
Tcl_Obj *GMTSetupTimeZone;
|
||||
Tcl_Obj *GMTSetupTZData;
|
||||
Tcl_Obj *AnySetupTimeZone;
|
||||
Tcl_Obj *AnySetupTZData;
|
||||
Tcl_Obj *LastUnnormSetupTimeZone;
|
||||
Tcl_Obj *LastSetupTimeZone;
|
||||
Tcl_Obj *LastSetupTZData;
|
||||
|
||||
Tcl_Obj *CurrentLocale;
|
||||
Tcl_Obj *CurrentLocaleDict;
|
||||
Tcl_Obj *LastUnnormUsedLocale;
|
||||
Tcl_Obj *LastUsedLocale;
|
||||
Tcl_Obj *LastUsedLocaleDict;
|
||||
|
||||
/* Cache for last base (last-second fast convert if base/tz not changed) */
|
||||
struct {
|
||||
Tcl_Obj *timezoneObj;
|
||||
TclDateFields Date;
|
||||
} lastBase;
|
||||
/* Las-period cache for fast UTC2Local conversion */
|
||||
struct {
|
||||
/* keys */
|
||||
Tcl_Obj *timezoneObj;
|
||||
int changeover;
|
||||
Tcl_WideInt seconds;
|
||||
Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */
|
||||
/* values */
|
||||
int tzOffset;
|
||||
Tcl_Obj *tzName;
|
||||
} UTC2Local;
|
||||
/* Las-period cache for fast Local2UTC conversion */
|
||||
struct {
|
||||
/* keys */
|
||||
Tcl_Obj *timezoneObj;
|
||||
int changeover;
|
||||
Tcl_WideInt localSeconds;
|
||||
Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */
|
||||
/* values */
|
||||
int tzOffset;
|
||||
} Local2UTC;
|
||||
} ClockClientData;
|
||||
|
||||
#define ClockDefaultYearCentury 2000
|
||||
#define ClockDefaultCenturySwitch 38
|
||||
|
||||
/*
|
||||
* Meridian: am, pm, or 24-hour style.
|
||||
*/
|
||||
|
||||
typedef enum _MERIDIAN {
|
||||
MERam, MERpm, MER24
|
||||
} MERIDIAN;
|
||||
|
||||
/*
|
||||
* Clock scan and format facilities.
|
||||
*/
|
||||
|
||||
#define CLOCK_FMT_SCN_STORAGE_GC_SIZE 32
|
||||
|
||||
#define CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE 2
|
||||
|
||||
typedef struct ClockScanToken ClockScanToken;
|
||||
|
||||
|
||||
typedef int ClockScanTokenProc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok);
|
||||
|
||||
|
||||
typedef enum _CLCKTOK_TYPE {
|
||||
CTOKT_DIGIT = 1, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
|
||||
CFMTT_INT, CFMTT_WIDE, CFMTT_PROC
|
||||
} CLCKTOK_TYPE;
|
||||
|
||||
typedef struct ClockScanTokenMap {
|
||||
unsigned short int type;
|
||||
unsigned short int flags;
|
||||
unsigned short int clearFlags;
|
||||
unsigned short int minSize;
|
||||
unsigned short int maxSize;
|
||||
unsigned short int offs;
|
||||
ClockScanTokenProc *parser;
|
||||
const void *data;
|
||||
} ClockScanTokenMap;
|
||||
|
||||
typedef struct ClockScanToken {
|
||||
ClockScanTokenMap *map;
|
||||
struct {
|
||||
const char *start;
|
||||
const char *end;
|
||||
} tokWord;
|
||||
unsigned short int endDistance;
|
||||
unsigned short int lookAhMin;
|
||||
unsigned short int lookAhMax;
|
||||
unsigned short int lookAhTok;
|
||||
} ClockScanToken;
|
||||
|
||||
|
||||
#define MIN_FMT_RESULT_BLOCK_ALLOC 200
|
||||
|
||||
typedef struct DateFormat {
|
||||
char *resMem;
|
||||
char *resEnd;
|
||||
char *output;
|
||||
|
||||
TclDateFields date;
|
||||
|
||||
Tcl_Obj *localeEra;
|
||||
} DateFormat;
|
||||
|
||||
#define CLFMT_INCR (1 << 3)
|
||||
#define CLFMT_DECR (1 << 4)
|
||||
#define CLFMT_CALC (1 << 5)
|
||||
#define CLFMT_LOCALE_INDX (1 << 8)
|
||||
|
||||
typedef struct ClockFormatToken ClockFormatToken;
|
||||
|
||||
typedef int ClockFormatTokenProc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateFormat *dateFmt,
|
||||
ClockFormatToken *tok,
|
||||
int *val);
|
||||
|
||||
typedef struct ClockFormatTokenMap {
|
||||
unsigned short int type;
|
||||
const char *tostr;
|
||||
unsigned short int width;
|
||||
unsigned short int flags;
|
||||
unsigned short int divider;
|
||||
unsigned short int divmod;
|
||||
unsigned short int offs;
|
||||
ClockFormatTokenProc *fmtproc;
|
||||
void *data;
|
||||
} ClockFormatTokenMap;
|
||||
typedef struct ClockFormatToken {
|
||||
ClockFormatTokenMap *map;
|
||||
struct {
|
||||
const char *start;
|
||||
const char *end;
|
||||
} tokWord;
|
||||
} ClockFormatToken;
|
||||
|
||||
|
||||
typedef struct ClockFmtScnStorage ClockFmtScnStorage;
|
||||
|
||||
typedef struct ClockFmtScnStorage {
|
||||
int objRefCount; /* Reference count shared across threads */
|
||||
ClockScanToken *scnTok;
|
||||
unsigned int scnTokC;
|
||||
unsigned int scnSpaceCount; /* Count of mandatory spaces used in format */
|
||||
ClockFormatToken *fmtTok;
|
||||
unsigned int fmtTokC;
|
||||
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
|
||||
ClockFmtScnStorage *nextPtr;
|
||||
ClockFmtScnStorage *prevPtr;
|
||||
#endif
|
||||
#if 0
|
||||
+Tcl_HashEntry hashEntry /* ClockFmtScnStorage is a derivate of Tcl_HashEntry,
|
||||
* stored by offset +sizeof(self) */
|
||||
#endif
|
||||
} ClockFmtScnStorage;
|
||||
|
||||
/*
|
||||
* Prototypes of module functions.
|
||||
*/
|
||||
|
||||
MODULE_SCOPE int ToSeconds(int Hours, int Minutes,
|
||||
int Seconds, MERIDIAN Meridian);
|
||||
MODULE_SCOPE int IsGregorianLeapYear(TclDateFields *);
|
||||
MODULE_SCOPE void
|
||||
GetJulianDayFromEraYearWeekDay(
|
||||
TclDateFields *fields, int changeover);
|
||||
MODULE_SCOPE void
|
||||
GetJulianDayFromEraYearMonthDay(
|
||||
TclDateFields *fields, int changeover);
|
||||
MODULE_SCOPE void
|
||||
GetJulianDayFromEraYearDay(
|
||||
TclDateFields *fields, int changeover);
|
||||
MODULE_SCOPE int ConvertUTCToLocal(ClientData clientData, Tcl_Interp *,
|
||||
TclDateFields *, Tcl_Obj *timezoneObj, int);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
|
||||
int, Tcl_Obj *const *, Tcl_WideInt rangesVal[2]);
|
||||
|
||||
MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info);
|
||||
|
||||
/* tclClock.c module declarations */
|
||||
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockSetupTimeZone(ClientData clientData,
|
||||
Tcl_Interp *interp, Tcl_Obj *timezoneObj);
|
||||
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockMCDict(ClockFmtScnCmdArgs *opts);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockMCGetIdx(ClockFmtScnCmdArgs *opts, int mcKey);
|
||||
MODULE_SCOPE int ClockMCSetIdx(ClockFmtScnCmdArgs *opts, int mcKey,
|
||||
Tcl_Obj *valObj);
|
||||
|
||||
/* tclClockFmt.c module declarations */
|
||||
|
||||
MODULE_SCOPE Tcl_Obj*
|
||||
ClockFrmObjGetLocFmtKey(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
|
||||
MODULE_SCOPE ClockFmtScnStorage *
|
||||
Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
|
||||
|
||||
MODULE_SCOPE int ClockScan(register DateInfo *info,
|
||||
Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts);
|
||||
|
||||
MODULE_SCOPE int ClockFormat(register DateFormat *dateFmt,
|
||||
ClockFmtScnCmdArgs *opts);
|
||||
|
||||
MODULE_SCOPE void ClockFrmScnClearCaches(void);
|
||||
|
||||
#endif /* _TCLCLOCK_H */
|
||||
+50
-18
@@ -23,6 +23,15 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_tcl)
|
||||
# define TCL_DEPRECATED(msg) EXTERN TCL_DEPRECATED_API(msg)
|
||||
#elif defined(TCL_NO_DEPRECATED)
|
||||
# define TCL_DEPRECATED(msg) MODULE_SCOPE
|
||||
#else
|
||||
# define TCL_DEPRECATED(msg) EXTERN
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* WARNING: This file is automatically generated by the tools/genStubs.tcl
|
||||
* script. Any modifications to the function declarations below should be made
|
||||
@@ -878,7 +887,7 @@ EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, int objc,
|
||||
EXTERN int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int flags);
|
||||
/* 294 */
|
||||
EXTERN void Tcl_ExitThread(int status);
|
||||
EXTERN TCL_NORETURN void Tcl_ExitThread(int status);
|
||||
/* 295 */
|
||||
EXTERN int Tcl_ExternalToUtf(Tcl_Interp *interp,
|
||||
Tcl_Encoding encoding, const char *src,
|
||||
@@ -950,13 +959,13 @@ EXTERN void Tcl_ThreadAlert(Tcl_ThreadId threadId);
|
||||
EXTERN void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId,
|
||||
Tcl_Event *evPtr, Tcl_QueuePosition position);
|
||||
/* 320 */
|
||||
EXTERN Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index);
|
||||
EXTERN int Tcl_UniCharAtIndex(const char *src, int index);
|
||||
/* 321 */
|
||||
EXTERN Tcl_UniChar Tcl_UniCharToLower(int ch);
|
||||
EXTERN int Tcl_UniCharToLower(int ch);
|
||||
/* 322 */
|
||||
EXTERN Tcl_UniChar Tcl_UniCharToTitle(int ch);
|
||||
EXTERN int Tcl_UniCharToTitle(int ch);
|
||||
/* 323 */
|
||||
EXTERN Tcl_UniChar Tcl_UniCharToUpper(int ch);
|
||||
EXTERN int Tcl_UniCharToUpper(int ch);
|
||||
/* 324 */
|
||||
EXTERN int Tcl_UniCharToUtf(int ch, char *buf);
|
||||
/* 325 */
|
||||
@@ -1108,7 +1117,7 @@ EXTERN void Tcl_SetUnicodeObj(Tcl_Obj *objPtr,
|
||||
/* 380 */
|
||||
EXTERN int Tcl_GetCharLength(Tcl_Obj *objPtr);
|
||||
/* 381 */
|
||||
EXTERN Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index);
|
||||
EXTERN int Tcl_GetUniChar(Tcl_Obj *objPtr, int index);
|
||||
/* 382 */
|
||||
EXTERN Tcl_UniChar * Tcl_GetUnicode(Tcl_Obj *objPtr);
|
||||
/* 383 */
|
||||
@@ -2151,7 +2160,7 @@ typedef struct TclStubs {
|
||||
int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, int numBytes, int flags); /* 291 */
|
||||
int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 292 */
|
||||
int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */
|
||||
void (*tcl_ExitThread) (int status); /* 294 */
|
||||
TCL_NORETURN1 void (*tcl_ExitThread) (int status); /* 294 */
|
||||
int (*tcl_ExternalToUtf) (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); /* 295 */
|
||||
char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 296 */
|
||||
void (*tcl_FinalizeThread) (void); /* 297 */
|
||||
@@ -2177,10 +2186,10 @@ typedef struct TclStubs {
|
||||
Tcl_Obj * (*tcl_SetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags); /* 317 */
|
||||
void (*tcl_ThreadAlert) (Tcl_ThreadId threadId); /* 318 */
|
||||
void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 319 */
|
||||
Tcl_UniChar (*tcl_UniCharAtIndex) (const char *src, int index); /* 320 */
|
||||
Tcl_UniChar (*tcl_UniCharToLower) (int ch); /* 321 */
|
||||
Tcl_UniChar (*tcl_UniCharToTitle) (int ch); /* 322 */
|
||||
Tcl_UniChar (*tcl_UniCharToUpper) (int ch); /* 323 */
|
||||
int (*tcl_UniCharAtIndex) (const char *src, int index); /* 320 */
|
||||
int (*tcl_UniCharToLower) (int ch); /* 321 */
|
||||
int (*tcl_UniCharToTitle) (int ch); /* 322 */
|
||||
int (*tcl_UniCharToUpper) (int ch); /* 323 */
|
||||
int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */
|
||||
CONST84_RETURN char * (*tcl_UtfAtIndex) (const char *src, int index); /* 325 */
|
||||
int (*tcl_UtfCharComplete) (const char *src, int length); /* 326 */
|
||||
@@ -2238,7 +2247,7 @@ typedef struct TclStubs {
|
||||
Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, int numChars); /* 378 */
|
||||
void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); /* 379 */
|
||||
int (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 380 */
|
||||
Tcl_UniChar (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */
|
||||
int (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */
|
||||
Tcl_UniChar * (*tcl_GetUnicode) (Tcl_Obj *objPtr); /* 382 */
|
||||
Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, int first, int last); /* 383 */
|
||||
void (*tcl_AppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int length); /* 384 */
|
||||
@@ -3835,13 +3844,13 @@ extern const TclStubs *tclStubsPtr;
|
||||
sizeof(char *), msg, flags, indexPtr)
|
||||
#undef Tcl_NewBooleanObj
|
||||
#define Tcl_NewBooleanObj(boolValue) \
|
||||
Tcl_NewIntObj((boolValue)!=0)
|
||||
Tcl_NewLongObj((boolValue)!=0)
|
||||
#undef Tcl_DbNewBooleanObj
|
||||
#define Tcl_DbNewBooleanObj(boolValue, file, line) \
|
||||
Tcl_DbNewLongObj((boolValue)!=0, file, line)
|
||||
#undef Tcl_SetBooleanObj
|
||||
#define Tcl_SetBooleanObj(objPtr, boolValue) \
|
||||
Tcl_SetIntObj((objPtr), (boolValue)!=0)
|
||||
Tcl_SetLongObj(objPtr, (boolValue)!=0)
|
||||
#undef Tcl_SetVar
|
||||
#define Tcl_SetVar(interp, varName, newValue, flags) \
|
||||
Tcl_SetVar2(interp, varName, NULL, newValue, flags)
|
||||
@@ -3870,6 +3879,29 @@ extern const TclStubs *tclStubsPtr;
|
||||
#define Tcl_AddObjErrorInfo(interp, message, length) \
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, length))
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
#undef Tcl_Eval
|
||||
#define Tcl_Eval(interp, objPtr) \
|
||||
Tcl_EvalEx(interp, objPtr, -1, 0)
|
||||
#undef Tcl_GlobalEval
|
||||
#define Tcl_GlobalEval(interp, objPtr) \
|
||||
Tcl_EvalEx(interp, objPtr, -1, TCL_EVAL_GLOBAL)
|
||||
#undef Tcl_SaveResult
|
||||
#define Tcl_SaveResult(interp, statePtr) \
|
||||
do { \
|
||||
(statePtr)->objResultPtr = Tcl_GetObjResult(interp); \
|
||||
Tcl_IncrRefCount((statePtr)->objResultPtr); \
|
||||
Tcl_SetObjResult(interp, Tcl_NewObj()); \
|
||||
} while(0)
|
||||
#undef Tcl_RestoreResult
|
||||
#define Tcl_RestoreResult(interp, statePtr) \
|
||||
do { \
|
||||
Tcl_ResetResult(interp); \
|
||||
Tcl_SetObjResult(interp, (statePtr)->objResultPtr); \
|
||||
Tcl_DecrRefCount((statePtr)->objResultPtr); \
|
||||
} while(0)
|
||||
#undef Tcl_DiscardResult
|
||||
#define Tcl_DiscardResult(statePtr) \
|
||||
Tcl_DecrRefCount((statePtr)->objResultPtr)
|
||||
#undef Tcl_SetResult
|
||||
#define Tcl_SetResult(interp, result, freeProc) \
|
||||
do { \
|
||||
@@ -3939,10 +3971,10 @@ extern const TclStubs *tclStubsPtr;
|
||||
*/
|
||||
|
||||
#undef Tcl_EvalObj
|
||||
#define Tcl_EvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),0)
|
||||
#define Tcl_EvalObj(interp, objPtr) \
|
||||
Tcl_EvalObjEx(interp, objPtr, 0)
|
||||
#undef Tcl_GlobalEvalObj
|
||||
#define Tcl_GlobalEvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL)
|
||||
#define Tcl_GlobalEvalObj(interp, objPtr) \
|
||||
Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL)
|
||||
|
||||
#endif /* _TCLDECLS */
|
||||
|
||||
@@ -3562,7 +3562,7 @@ TclDictWithFinish(
|
||||
* If the dictionary variable doesn't exist, drop everything silently.
|
||||
*/
|
||||
|
||||
dictPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
dictPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
TCL_LEAVE_ERR_MSG, index);
|
||||
if (dictPtr == NULL) {
|
||||
return TCL_OK;
|
||||
@@ -3645,8 +3645,8 @@ TclDictWithFinish(
|
||||
* Write back the outermost dictionary to the variable.
|
||||
*/
|
||||
|
||||
if (TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, dictPtr,
|
||||
TCL_LEAVE_ERR_MSG, index) == NULL) {
|
||||
if (TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
dictPtr, TCL_LEAVE_ERR_MSG, index) == NULL) {
|
||||
if (allocdict) {
|
||||
TclDecrRefCount(dictPtr);
|
||||
}
|
||||
|
||||
+20
-26
@@ -27,9 +27,8 @@ static Tcl_Obj * DisassembleByteCodeObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
static int FormatInstruction(ByteCode *codePtr,
|
||||
const unsigned char *pc, Tcl_Obj *bufferObj);
|
||||
static void GetLocationInformation(Tcl_Interp *interp,
|
||||
Proc *procPtr, Tcl_Obj **fileObjPtr,
|
||||
int *linePtr);
|
||||
static void GetLocationInformation(Proc *procPtr,
|
||||
Tcl_Obj **fileObjPtr, int *linePtr);
|
||||
static void PrintSourceToObj(Tcl_Obj *appendObj,
|
||||
const char *stringPtr, int maxChars);
|
||||
static void UpdateStringOfInstName(Tcl_Obj *objPtr);
|
||||
@@ -73,8 +72,6 @@ static const Tcl_ObjType tclInstNameType = {
|
||||
|
||||
static void
|
||||
GetLocationInformation(
|
||||
Tcl_Interp *interp, /* Where to look up the location
|
||||
* information. */
|
||||
Proc *procPtr, /* What to look up the information for. */
|
||||
Tcl_Obj **fileObjPtr, /* Where to write the information about what
|
||||
* file the code came from. Will be written
|
||||
@@ -88,20 +85,21 @@ GetLocationInformation(
|
||||
* either with the line number or with -1 if
|
||||
* the information is not available. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_HashEntry *hePtr;
|
||||
CmdFrame *cfPtr;
|
||||
CmdFrame *cfPtr = TclGetCmdFrameForProcedure(procPtr);
|
||||
|
||||
*fileObjPtr = NULL;
|
||||
*linePtr = -1;
|
||||
if (iPtr != NULL && procPtr != NULL) {
|
||||
hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, procPtr);
|
||||
if (hePtr != NULL && (cfPtr = Tcl_GetHashValue(hePtr)) != NULL) {
|
||||
*linePtr = cfPtr->line[0];
|
||||
if (cfPtr->type == TCL_LOCATION_SOURCE) {
|
||||
*fileObjPtr = cfPtr->data.eval.path;
|
||||
}
|
||||
}
|
||||
if (cfPtr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the source location data out of the CmdFrame.
|
||||
*/
|
||||
|
||||
*linePtr = cfPtr->line[0];
|
||||
if (cfPtr->type == TCL_LOCATION_SOURCE) {
|
||||
*fileObjPtr = cfPtr->data.eval.path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +252,6 @@ DisassembleByteCodeObj(
|
||||
int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i, line;
|
||||
Interp *iPtr = (Interp *) *codePtr->interpHandle;
|
||||
Tcl_Obj *bufferObj, *fileObj;
|
||||
char ptrBuf1[20], ptrBuf2[20];
|
||||
|
||||
TclNewObj(bufferObj);
|
||||
if (codePtr->refCount <= 0) {
|
||||
@@ -269,16 +266,14 @@ DisassembleByteCodeObj(
|
||||
* Print header lines describing the ByteCode.
|
||||
*/
|
||||
|
||||
sprintf(ptrBuf1, "%p", codePtr);
|
||||
sprintf(ptrBuf2, "%p", iPtr);
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"ByteCode 0x%s, refCt %u, epoch %u, interp 0x%s (epoch %u)\n",
|
||||
ptrBuf1, codePtr->refCount, codePtr->compileEpoch, ptrBuf2,
|
||||
"ByteCode %p, refCt %u, epoch %u, interp %p (epoch %u)\n",
|
||||
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
|
||||
iPtr->compileEpoch);
|
||||
Tcl_AppendToObj(bufferObj, " Source ", -1);
|
||||
PrintSourceToObj(bufferObj, codePtr->source,
|
||||
TclMin(codePtr->numSrcBytes, 55));
|
||||
GetLocationInformation(interp, codePtr->procPtr, &fileObj, &line);
|
||||
GetLocationInformation(codePtr->procPtr, &fileObj, &line);
|
||||
if (line > -1 && fileObj != NULL) {
|
||||
Tcl_AppendPrintfToObj(bufferObj, "\n File \"%s\" Line %d",
|
||||
Tcl_GetString(fileObj), line);
|
||||
@@ -316,10 +311,9 @@ DisassembleByteCodeObj(
|
||||
Proc *procPtr = codePtr->procPtr;
|
||||
int numCompiledLocals = procPtr->numCompiledLocals;
|
||||
|
||||
sprintf(ptrBuf1, "%p", procPtr);
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" Proc 0x%s, refCt %d, args %d, compiled locals %d\n",
|
||||
ptrBuf1, procPtr->refCount, procPtr->numArgs,
|
||||
" Proc %p, refCt %d, args %d, compiled locals %d\n",
|
||||
procPtr, procPtr->refCount, procPtr->numArgs,
|
||||
numCompiledLocals);
|
||||
if (numCompiledLocals > 0) {
|
||||
CompiledLocal *localPtr = procPtr->firstLocalPtr;
|
||||
@@ -1221,7 +1215,7 @@ DisassembleByteCodeAsDicts(
|
||||
* system if it is available.
|
||||
*/
|
||||
|
||||
GetLocationInformation(interp, codePtr->procPtr, &file, &line);
|
||||
GetLocationInformation(codePtr->procPtr, &file, &line);
|
||||
|
||||
/*
|
||||
* Build the overall result.
|
||||
|
||||
+47
-34
@@ -2293,8 +2293,11 @@ UtfToUtfProc(
|
||||
const char *srcStart, *srcEnd, *srcClose;
|
||||
const char *dstStart, *dstEnd;
|
||||
int result, numChars, charLimit = INT_MAX;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
|
||||
|
||||
if (flags & TCL_ENCODING_START) {
|
||||
*statePtr = 0;
|
||||
}
|
||||
result = TCL_OK;
|
||||
|
||||
srcStart = src;
|
||||
@@ -2326,7 +2329,7 @@ UtfToUtfProc(
|
||||
}
|
||||
if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && pureNullMode == 0)) {
|
||||
/*
|
||||
* Copy 7bit chatacters, but skip null-bytes when we are in input
|
||||
* Copy 7bit characters, but skip null-bytes when we are in input
|
||||
* mode, so that they get converted to 0xc080.
|
||||
*/
|
||||
|
||||
@@ -2341,17 +2344,19 @@ UtfToUtfProc(
|
||||
src += 2;
|
||||
} else if (!Tcl_UtfCharComplete(src, srcEnd - src)) {
|
||||
/*
|
||||
* Always check before using Tcl_UtfToUniChar. Not doing can so
|
||||
* cause it run beyond the endof the buffer! If we happen such an
|
||||
* incomplete char its byts are made to represent themselves.
|
||||
* Always check before using TclUtfToUniChar. Not doing can so
|
||||
* cause it run beyond the end of the buffer! If we happen such an
|
||||
* incomplete char its bytes are made to represent themselves.
|
||||
*/
|
||||
|
||||
ch = (unsigned char) *src;
|
||||
*chPtr = (unsigned char) *src;
|
||||
src += 1;
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
dst += Tcl_UniCharToUtf(*chPtr, dst);
|
||||
} else {
|
||||
src += Tcl_UtfToUniChar(src, &ch);
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
int n = TclUtfToUniChar(src, chPtr);
|
||||
src += n;
|
||||
if (!n) numChars--;
|
||||
dst += Tcl_UniCharToUtf(*chPtr, dst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2407,8 +2412,11 @@ UnicodeToUtfProc(
|
||||
const char *srcStart, *srcEnd;
|
||||
const char *dstEnd, *dstStart;
|
||||
int result, numChars, charLimit = INT_MAX;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
|
||||
|
||||
if (flags & TCL_ENCODING_START) {
|
||||
*statePtr = 0;
|
||||
}
|
||||
if (flags & TCL_ENCODING_CHAR_LIMIT) {
|
||||
charLimit = *dstCharsPtr;
|
||||
}
|
||||
@@ -2436,11 +2444,13 @@ UnicodeToUtfProc(
|
||||
* Tcl_UniChar-size data.
|
||||
*/
|
||||
|
||||
ch = *(Tcl_UniChar *)src;
|
||||
if (ch && ch < 0x80) {
|
||||
*dst++ = (ch & 0xFF);
|
||||
*chPtr = *(Tcl_UniChar *)src;
|
||||
if (*chPtr && *chPtr < 0x80) {
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
} else {
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
int n = Tcl_UniCharToUtf(*chPtr, dst);
|
||||
dst += n;
|
||||
if (!n) --numChars;/* Don't count high surrogates */
|
||||
}
|
||||
src += sizeof(Tcl_UniChar);
|
||||
}
|
||||
@@ -2497,8 +2507,11 @@ UtfToUnicodeProc(
|
||||
{
|
||||
const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
|
||||
int result, numChars;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
|
||||
|
||||
if (flags & TCL_ENCODING_START) {
|
||||
*statePtr = 0;
|
||||
}
|
||||
srcStart = src;
|
||||
srcEnd = src + srcLen;
|
||||
srcClose = srcEnd;
|
||||
@@ -2524,7 +2537,7 @@ UtfToUnicodeProc(
|
||||
result = TCL_CONVERT_NOSPACE;
|
||||
break;
|
||||
}
|
||||
src += TclUtfToUniChar(src, &ch);
|
||||
src += TclUtfToUniChar(src, chPtr);
|
||||
|
||||
/*
|
||||
* Need to handle this in a way that won't cause misalignment by
|
||||
@@ -2533,23 +2546,23 @@ UtfToUnicodeProc(
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#if TCL_UTF_MAX > 4
|
||||
*dst++ = (ch >> 24);
|
||||
*dst++ = ((ch >> 16) & 0xFF);
|
||||
*dst++ = ((ch >> 8) & 0xFF);
|
||||
*dst++ = (ch & 0xFF);
|
||||
*dst++ = (*chPtr >> 24);
|
||||
*dst++ = ((*chPtr >> 16) & 0xFF);
|
||||
*dst++ = ((*chPtr >> 8) & 0xFF);
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
#else
|
||||
*dst++ = (ch >> 8);
|
||||
*dst++ = (ch & 0xFF);
|
||||
*dst++ = (*chPtr >> 8);
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
#endif
|
||||
#else
|
||||
#if TCL_UTF_MAX > 4
|
||||
*dst++ = (ch & 0xFF);
|
||||
*dst++ = ((ch >> 8) & 0xFF);
|
||||
*dst++ = ((ch >> 16) & 0xFF);
|
||||
*dst++ = (ch >> 24);
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
*dst++ = ((*chPtr >> 8) & 0xFF);
|
||||
*dst++ = ((*chPtr >> 16) & 0xFF);
|
||||
*dst++ = (*chPtr >> 24);
|
||||
#else
|
||||
*dst++ = (ch & 0xFF);
|
||||
*dst++ = (ch >> 8);
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
*dst++ = (*chPtr >> 8);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -2607,7 +2620,7 @@ TableToUtfProc(
|
||||
const char *srcStart, *srcEnd;
|
||||
const char *dstEnd, *dstStart, *prefixBytes;
|
||||
int result, byte, numChars, charLimit = INT_MAX;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
const unsigned short *const *toUnicode;
|
||||
const unsigned short *pageZero;
|
||||
TableEncodingData *dataPtr = clientData;
|
||||
@@ -2719,7 +2732,7 @@ TableFromUtfProc(
|
||||
{
|
||||
const char *srcStart, *srcEnd, *srcClose;
|
||||
const char *dstStart, *dstEnd, *prefixBytes;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
int result, len, word, numChars;
|
||||
TableEncodingData *dataPtr = clientData;
|
||||
const unsigned short *const *fromUnicode;
|
||||
@@ -2853,7 +2866,7 @@ Iso88591ToUtfProc(
|
||||
|
||||
result = TCL_OK;
|
||||
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
|
||||
if (dst > dstEnd) {
|
||||
result = TCL_CONVERT_NOSPACE;
|
||||
@@ -2939,7 +2952,7 @@ Iso88591FromUtfProc(
|
||||
dstEnd = dst + dstLen - 1;
|
||||
|
||||
for (numChars = 0; src < srcEnd; numChars++) {
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
int len;
|
||||
|
||||
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
|
||||
@@ -3326,7 +3339,7 @@ EscapeFromUtfProc(
|
||||
for (numChars = 0; src < srcEnd; numChars++) {
|
||||
unsigned len;
|
||||
int word;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
|
||||
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
|
||||
/*
|
||||
@@ -3371,7 +3384,7 @@ EscapeFromUtfProc(
|
||||
|
||||
/*
|
||||
* The state variable has the value of oldState when word is 0.
|
||||
* In this case, the escape sequense should not be copied to dst
|
||||
* In this case, the escape sequence should not be copied to dst
|
||||
* because the current character set is not changed.
|
||||
*/
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ static const Tcl_ObjType ensembleCmdType = {
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int epoch; /* Used to confirm when the data in this
|
||||
size_t 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
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ typedef struct BgError {
|
||||
* pending background errors for the interpreter.
|
||||
*/
|
||||
|
||||
typedef struct ErrAssocData {
|
||||
typedef struct {
|
||||
Tcl_Interp *interp; /* Interpreter in which error occurred. */
|
||||
Tcl_Obj *cmdPrefix; /* First word(s) of the handler command */
|
||||
BgError *firstBgPtr; /* First in list of all background errors
|
||||
|
||||
+66
-32
@@ -510,8 +510,7 @@ VarHashCreateVar(
|
||||
: (*(tPtr) = TCL_NUMBER_DOUBLE)), \
|
||||
*(ptrPtr) = (ClientData) \
|
||||
(&((objPtr)->internalRep.doubleValue)), TCL_OK) : \
|
||||
((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \
|
||||
? TCL_ERROR : \
|
||||
TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))
|
||||
#else /* !TCL_WIDE_INT_IS_LONG */
|
||||
@@ -530,8 +529,7 @@ VarHashCreateVar(
|
||||
: (*(tPtr) = TCL_NUMBER_DOUBLE)), \
|
||||
*(ptrPtr) = (ClientData) \
|
||||
(&((objPtr)->internalRep.doubleValue)), TCL_OK) : \
|
||||
((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \
|
||||
? TCL_ERROR : \
|
||||
TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
@@ -910,9 +908,9 @@ TclCreateExecEnv(
|
||||
+ (size_t) (size-1) * sizeof(Tcl_Obj *));
|
||||
|
||||
eePtr->execStackPtr = esPtr;
|
||||
TclNewBooleanObj(eePtr->constants[0], 0);
|
||||
TclNewLongObj(eePtr->constants[0], 0);
|
||||
Tcl_IncrRefCount(eePtr->constants[0]);
|
||||
TclNewBooleanObj(eePtr->constants[1], 1);
|
||||
TclNewLongObj(eePtr->constants[1], 1);
|
||||
Tcl_IncrRefCount(eePtr->constants[1]);
|
||||
eePtr->interp = interp;
|
||||
eePtr->callbackPtr = NULL;
|
||||
@@ -3186,7 +3184,7 @@ TEBCresume(
|
||||
*/
|
||||
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr,
|
||||
objResultPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr,
|
||||
part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
if (!objResultPtr) {
|
||||
@@ -3433,7 +3431,7 @@ TEBCresume(
|
||||
|
||||
doCallPtrSetVar:
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr,
|
||||
objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr,
|
||||
part1Ptr, part2Ptr, valuePtr, storeFlags, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
if (!objResultPtr) {
|
||||
@@ -3569,7 +3567,7 @@ TEBCresume(
|
||||
VarHashRefCount(arrayPtr)++;
|
||||
}
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr,
|
||||
objResultPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr,
|
||||
part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
if (TclIsVarInHash(varPtr)) {
|
||||
@@ -3598,7 +3596,7 @@ TEBCresume(
|
||||
}
|
||||
}
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr,
|
||||
objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr,
|
||||
part2Ptr, objResultPtr, TCL_LEAVE_ERR_MSG, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
if (!objResultPtr) {
|
||||
@@ -3862,7 +3860,7 @@ TEBCresume(
|
||||
Tcl_DecrRefCount(incrPtr);
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrIncrObjVar(interp, varPtr, arrayPtr,
|
||||
objResultPtr = TclPtrIncrObjVarIdx(interp, varPtr, arrayPtr,
|
||||
part1Ptr, part2Ptr, incrPtr, TCL_LEAVE_ERR_MSG, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
Tcl_DecrRefCount(incrPtr);
|
||||
@@ -4017,7 +4015,7 @@ TEBCresume(
|
||||
|
||||
slowUnsetScalar:
|
||||
DECACHE_STACK_INFO();
|
||||
if (TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, flags,
|
||||
if (TclPtrUnsetVarIdx(interp, varPtr, NULL, NULL, NULL, flags,
|
||||
opnd) != TCL_OK && flags) {
|
||||
goto errorInUnset;
|
||||
}
|
||||
@@ -4069,7 +4067,7 @@ TEBCresume(
|
||||
if (flags & TCL_LEAVE_ERR_MSG) {
|
||||
goto errorInUnset;
|
||||
}
|
||||
} else if (TclPtrUnsetVar(interp, varPtr, arrayPtr, NULL, part2Ptr,
|
||||
} else if (TclPtrUnsetVarIdx(interp, varPtr, arrayPtr, NULL, part2Ptr,
|
||||
flags, opnd) != TCL_OK && (flags & TCL_LEAVE_ERR_MSG)) {
|
||||
goto errorInUnset;
|
||||
}
|
||||
@@ -4126,7 +4124,7 @@ TEBCresume(
|
||||
varPtr->value.objPtr = NULL;
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
|
||||
TclPtrUnsetVarIdx(interp, varPtr, NULL, NULL, NULL, 0, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
}
|
||||
NEXT_INST_F(5, 0, 0);
|
||||
@@ -4342,7 +4340,7 @@ TEBCresume(
|
||||
if (TclIsVarInHash(otherPtr)) {
|
||||
VarHashRefCount(otherPtr)++;
|
||||
}
|
||||
} else if (TclPtrObjMakeUpvar(interp, otherPtr, NULL, 0,
|
||||
} else if (TclPtrObjMakeUpvarIdx(interp, otherPtr, NULL, 0,
|
||||
opnd) != TCL_OK) {
|
||||
TRACE_ERROR(interp);
|
||||
goto gotError;
|
||||
@@ -5449,7 +5447,7 @@ TEBCresume(
|
||||
valuePtr->bytes+index, 1);
|
||||
} else {
|
||||
char buf[TCL_UTF_MAX];
|
||||
Tcl_UniChar ch = Tcl_GetUniChar(valuePtr, index);
|
||||
int ch = Tcl_GetUniChar(valuePtr, index);
|
||||
|
||||
/*
|
||||
* This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch, 1)
|
||||
@@ -6764,7 +6762,7 @@ TEBCresume(
|
||||
}
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
|
||||
if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
|
||||
CACHE_STACK_INFO();
|
||||
TRACE_APPEND((
|
||||
@@ -6935,7 +6933,7 @@ TEBCresume(
|
||||
}
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
|
||||
if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
|
||||
CACHE_STACK_INFO();
|
||||
TRACE_APPEND(("ERROR init. index temp %d: %.30s",
|
||||
@@ -7158,7 +7156,8 @@ TEBCresume(
|
||||
dictPtr = varPtr->value.objPtr;
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2);
|
||||
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL, 0,
|
||||
opnd2);
|
||||
CACHE_STACK_INFO();
|
||||
}
|
||||
if (dictPtr == NULL) {
|
||||
@@ -7232,7 +7231,7 @@ TEBCresume(
|
||||
} else {
|
||||
Tcl_IncrRefCount(dictPtr);
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
|
||||
objResultPtr = TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
dictPtr, TCL_LEAVE_ERR_MSG, opnd2);
|
||||
CACHE_STACK_INFO();
|
||||
TclDecrRefCount(dictPtr);
|
||||
@@ -7261,7 +7260,8 @@ TEBCresume(
|
||||
dictPtr = varPtr->value.objPtr;
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
|
||||
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL, 0,
|
||||
opnd);
|
||||
CACHE_STACK_INFO();
|
||||
}
|
||||
if (dictPtr == NULL) {
|
||||
@@ -7370,7 +7370,7 @@ TEBCresume(
|
||||
} else {
|
||||
Tcl_IncrRefCount(dictPtr);
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
|
||||
objResultPtr = TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
dictPtr, TCL_LEAVE_ERR_MSG, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
TclDecrRefCount(dictPtr);
|
||||
@@ -7464,7 +7464,7 @@ TEBCresume(
|
||||
dictPtr = varPtr->value.objPtr;
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL,
|
||||
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
TCL_LEAVE_ERR_MSG, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
if (dictPtr == NULL) {
|
||||
@@ -7497,7 +7497,7 @@ TEBCresume(
|
||||
TclObjUnsetVar2(interp,
|
||||
localName(iPtr->varFramePtr, duiPtr->varIndices[i]),
|
||||
NULL, 0);
|
||||
} else if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
|
||||
} else if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
valuePtr, TCL_LEAVE_ERR_MSG,
|
||||
duiPtr->varIndices[i]) == NULL) {
|
||||
CACHE_STACK_INFO();
|
||||
@@ -7524,7 +7524,8 @@ TEBCresume(
|
||||
dictPtr = varPtr->value.objPtr;
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
|
||||
dictPtr = TclPtrGetVarIdx(interp, varPtr, NULL, NULL, NULL, 0,
|
||||
opnd);
|
||||
CACHE_STACK_INFO();
|
||||
}
|
||||
if (dictPtr == NULL) {
|
||||
@@ -7554,8 +7555,8 @@ TEBCresume(
|
||||
valuePtr = var2Ptr->value.objPtr;
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
valuePtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0,
|
||||
duiPtr->varIndices[i]);
|
||||
valuePtr = TclPtrGetVarIdx(interp, var2Ptr, NULL, NULL, NULL,
|
||||
0, duiPtr->varIndices[i]);
|
||||
CACHE_STACK_INFO();
|
||||
}
|
||||
if (valuePtr == NULL) {
|
||||
@@ -7573,7 +7574,7 @@ TEBCresume(
|
||||
varPtr->value.objPtr = dictPtr;
|
||||
} else {
|
||||
DECACHE_STACK_INFO();
|
||||
objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
|
||||
objResultPtr = TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
|
||||
dictPtr, TCL_LEAVE_ERR_MSG, opnd);
|
||||
CACHE_STACK_INFO();
|
||||
if (objResultPtr == NULL) {
|
||||
@@ -7664,6 +7665,39 @@ TEBCresume(
|
||||
* -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
case INST_CLOCK_READ:
|
||||
{ /* Read the wall clock */
|
||||
Tcl_WideInt wval;
|
||||
Tcl_Time now;
|
||||
switch(TclGetUInt1AtPtr(pc+1)) {
|
||||
case 0: /* clicks */
|
||||
#ifdef TCL_WIDE_CLICKS
|
||||
wval = TclpGetWideClicks();
|
||||
#else
|
||||
wval = (Tcl_WideInt) TclpGetClicks();
|
||||
#endif
|
||||
break;
|
||||
case 1: /* microseconds */
|
||||
Tcl_GetTime(&now);
|
||||
wval = (Tcl_WideInt) now.sec * 1000000 + now.usec;
|
||||
break;
|
||||
case 2: /* milliseconds */
|
||||
Tcl_GetTime(&now);
|
||||
wval = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000;
|
||||
break;
|
||||
case 3: /* seconds */
|
||||
Tcl_GetTime(&now);
|
||||
wval = (Tcl_WideInt) now.sec;
|
||||
break;
|
||||
default:
|
||||
Tcl_Panic("clockRead instruction with unknown clock#");
|
||||
}
|
||||
/* TclNewWideObj(objResultPtr, wval); doesn't exist */
|
||||
objResultPtr = Tcl_NewWideIntObj(wval);
|
||||
TRACE_WITH_OBJ(("=> "), objResultPtr);
|
||||
NEXT_INST_F(2, 0, 1);
|
||||
}
|
||||
|
||||
default:
|
||||
Tcl_Panic("TclNRExecuteByteCode: unrecognized opCode %u", *pc);
|
||||
} /* end of switch on opCode */
|
||||
@@ -8184,7 +8218,7 @@ ExecuteExtendedBinaryMathOp(
|
||||
* Arguments are opposite sign; remainder is sum.
|
||||
*/
|
||||
|
||||
TclBNInitBignumFromWideInt(&big1, w1);
|
||||
TclInitBignumFromWideInt(&big1, w1);
|
||||
mp_add(&big2, &big1, &big2);
|
||||
mp_clear(&big1);
|
||||
BIG_RESULT(&big2);
|
||||
@@ -9150,7 +9184,7 @@ ExecuteExtendedUnaryMathOp(
|
||||
if (w != LLONG_MIN) {
|
||||
WIDE_RESULT(-w);
|
||||
}
|
||||
TclBNInitBignumFromLong(&big, *(const long *) ptr);
|
||||
TclInitBignumFromLong(&big, *(const long *) ptr);
|
||||
break;
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
case TCL_NUMBER_WIDE:
|
||||
@@ -9158,7 +9192,7 @@ ExecuteExtendedUnaryMathOp(
|
||||
if (w != LLONG_MIN) {
|
||||
WIDE_RESULT(-w);
|
||||
}
|
||||
TclBNInitBignumFromWideInt(&big, w);
|
||||
TclInitBignumFromWideInt(&big, w);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -9199,7 +9233,7 @@ TclCompareTwoNumbers(
|
||||
Tcl_Obj *valuePtr,
|
||||
Tcl_Obj *value2Ptr)
|
||||
{
|
||||
int type1, type2, compare;
|
||||
int type1 = TCL_NUMBER_NAN, type2 = TCL_NUMBER_NAN, compare;
|
||||
ClientData ptr1, ptr2;
|
||||
mp_int big1, big2;
|
||||
double d1, d2, tmp;
|
||||
|
||||
@@ -45,19 +45,6 @@ static Tcl_HashEntry * AllocArrayEntry(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
static int CompareArrayKeys(void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
static TCL_HASH_TYPE HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
|
||||
/*
|
||||
* Prototypes for the one word hash key methods. Not actually declared because
|
||||
* this is a critical path that is implemented in the core hash table access
|
||||
* function.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static Tcl_HashEntry * AllocOneWordEntry(Tcl_HashTable *tablePtr,
|
||||
void *keyPtr);
|
||||
static int CompareOneWordKeys(void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
static unsigned int HashOneWordKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prototypes for the string hash key methods.
|
||||
*/
|
||||
|
||||
@@ -62,15 +62,14 @@ Tcl_RecordAndEval(
|
||||
* instead of Tcl_Eval. */
|
||||
{
|
||||
register Tcl_Obj *cmdPtr;
|
||||
int length = strlen(cmd);
|
||||
int result;
|
||||
|
||||
if (length > 0) {
|
||||
if (cmd[0]) {
|
||||
/*
|
||||
* Call Tcl_RecordAndEvalObj to do the actual work.
|
||||
*/
|
||||
|
||||
cmdPtr = Tcl_NewStringObj(cmd, length);
|
||||
cmdPtr = Tcl_NewStringObj(cmd, -1);
|
||||
Tcl_IncrRefCount(cmdPtr);
|
||||
result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags);
|
||||
|
||||
|
||||
+401
-332
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -214,7 +214,7 @@ typedef struct ChannelState {
|
||||
* because it happened in the background. The
|
||||
* value is the chanMg, if any. #219's
|
||||
* companion to 'unreportedError'. */
|
||||
int epoch; /* Used to test validity of stored channelname
|
||||
size_t epoch; /* Used to test validity of stored channelname
|
||||
* lookup results. */
|
||||
} ChannelState;
|
||||
|
||||
|
||||
+29
-16
@@ -25,7 +25,7 @@ typedef struct AcceptCallback {
|
||||
* It must be per-thread because of std channel limitations.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
int initialized; /* Set to 1 when the module is initialized. */
|
||||
Tcl_Obj *stdoutObjPtr; /* Cached stdout channel Tcl_Obj */
|
||||
} ThreadSpecificData;
|
||||
@@ -113,7 +113,6 @@ Tcl_PutsObjCmd(
|
||||
int newline; /* Add a newline at end? */
|
||||
int result; /* Result of puts operation. */
|
||||
int mode; /* Mode in which channel is opened. */
|
||||
ThreadSpecificData *tsdPtr;
|
||||
|
||||
switch (objc) {
|
||||
case 2: /* [puts $x] */
|
||||
@@ -160,7 +159,7 @@ Tcl_PutsObjCmd(
|
||||
}
|
||||
|
||||
if (chanObjPtr == NULL) {
|
||||
tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
if (!tsdPtr->initialized) {
|
||||
tsdPtr->initialized = 1;
|
||||
@@ -1618,19 +1617,34 @@ Tcl_SocketObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// Set the options to their default value if the user didn't override their
|
||||
// value.
|
||||
if (reusep == -1) reusep = 0;
|
||||
if (reusea == -1) reusea = 1;
|
||||
/*
|
||||
* Set the options to their default value if the user didn't override
|
||||
* their value.
|
||||
*/
|
||||
|
||||
// Build the bitset with the flags values.
|
||||
if (reusea)
|
||||
if (reusep == -1) {
|
||||
reusep = 0;
|
||||
}
|
||||
if (reusea == -1) {
|
||||
reusea = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the bitset with the flags values.
|
||||
*/
|
||||
|
||||
if (reusea) {
|
||||
flags |= TCL_TCPSERVER_REUSEADDR;
|
||||
if (reusep)
|
||||
}
|
||||
if (reusep) {
|
||||
flags |= TCL_TCPSERVER_REUSEPORT;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the arguments should have been parsed by now, 'a' points to the
|
||||
* last one, the port number.
|
||||
*/
|
||||
|
||||
// All the arguments should have been parsed by now, 'a' points to the last
|
||||
// one, the port number.
|
||||
if (a != objc-1) {
|
||||
goto wrongNumArgs;
|
||||
}
|
||||
@@ -1638,15 +1652,14 @@ Tcl_SocketObjCmd(
|
||||
port = TclGetString(objv[a]);
|
||||
|
||||
if (server) {
|
||||
AcceptCallback *acceptCallbackPtr =
|
||||
ckalloc(sizeof(AcceptCallback));
|
||||
AcceptCallback *acceptCallbackPtr = ckalloc(sizeof(AcceptCallback));
|
||||
|
||||
Tcl_IncrRefCount(script);
|
||||
acceptCallbackPtr->script = script;
|
||||
acceptCallbackPtr->interp = interp;
|
||||
|
||||
chan = Tcl_OpenTcpServerEx(interp, port, host, flags, AcceptCallbackProc,
|
||||
acceptCallbackPtr);
|
||||
chan = Tcl_OpenTcpServerEx(interp, port, host, flags,
|
||||
AcceptCallbackProc, acceptCallbackPtr);
|
||||
if (chan == NULL) {
|
||||
Tcl_DecrRefCount(script);
|
||||
ckfree(acceptCallbackPtr);
|
||||
|
||||
+46
-25
@@ -41,6 +41,8 @@ static void ReflectWatch(ClientData clientData, int mask);
|
||||
static int ReflectBlock(ClientData clientData, int mode);
|
||||
#ifdef TCL_THREADS
|
||||
static void ReflectThread(ClientData clientData, int action);
|
||||
static int ReflectEventRun(Tcl_Event *ev, int flags);
|
||||
static int ReflectEventDelete(Tcl_Event *ev, ClientData cd);
|
||||
#endif
|
||||
static Tcl_WideInt ReflectSeekWide(ClientData clientData,
|
||||
Tcl_WideInt offset, int mode, int *errorCodePtr);
|
||||
@@ -234,7 +236,7 @@ typedef enum {
|
||||
* sharing problems.
|
||||
*/
|
||||
|
||||
typedef struct ForwardParamBase {
|
||||
typedef struct {
|
||||
int code; /* O: Ok/Fail of the cmd handler */
|
||||
char *msgStr; /* O: Error message for handler failure */
|
||||
int mustFree; /* O: True if msgStr is allocated, false if
|
||||
@@ -309,7 +311,7 @@ typedef struct ForwardingResult ForwardingResult;
|
||||
* General event structure, with reference to operation specific data.
|
||||
*/
|
||||
|
||||
typedef struct ForwardingEvent {
|
||||
typedef struct {
|
||||
Tcl_Event event; /* Basic event data, has to be first item */
|
||||
ForwardingResult *resultPtr;
|
||||
ForwardedOperation op; /* Forwarded driver operation */
|
||||
@@ -346,7 +348,7 @@ struct ForwardingResult {
|
||||
* results. */
|
||||
};
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
/*
|
||||
* Table of all reflected channels owned by this thread. This is the
|
||||
* per-thread version of the per-interpreter map.
|
||||
@@ -723,7 +725,7 @@ TclChanCreateObjCmd(
|
||||
Tcl_DecrRefCount(rcPtr->name);
|
||||
Tcl_DecrRefCount(rcPtr->methods);
|
||||
Tcl_DecrRefCount(rcPtr->cmd);
|
||||
ckfree((char*) rcPtr);
|
||||
ckfree(rcPtr);
|
||||
return TCL_ERROR;
|
||||
|
||||
#undef MODE
|
||||
@@ -748,7 +750,8 @@ TclChanCreateObjCmd(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef struct ReflectEvent {
|
||||
#ifdef TCL_THREADS
|
||||
typedef struct {
|
||||
Tcl_Event header;
|
||||
ReflectedChannel *rcPtr;
|
||||
int events;
|
||||
@@ -791,6 +794,7 @@ ReflectEventDelete(
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
TclChanPostEventObjCmd(
|
||||
@@ -851,11 +855,12 @@ TclChanPostEventObjCmd(
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the search above subsumes several of the older checks, namely:
|
||||
* Note that the search above subsumes several of the older checks,
|
||||
* namely:
|
||||
*
|
||||
* (1) Does the channel handle refer to a reflected channel ?
|
||||
* (1) Does the channel handle refer to a reflected channel?
|
||||
* (2) Is the post event issued from the interpreter holding the handler
|
||||
* of the reflected channel ?
|
||||
* of the reflected channel?
|
||||
*
|
||||
* A successful search answers yes to both. Because the map holds only
|
||||
* handles of reflected channels, and only of such whose handler is
|
||||
@@ -939,7 +944,8 @@ TclChanPostEventObjCmd(
|
||||
|
||||
(void) GetThreadReflectedChannelMap();
|
||||
|
||||
/* XXX Race condition !!
|
||||
/*
|
||||
* XXX Race condition !!
|
||||
* XXX The destination thread may not exist anymore already.
|
||||
* XXX (Delayed postevent executed after channel got removed).
|
||||
* XXX Can we detect this ? (check the validity of the owner threadid ?)
|
||||
@@ -1221,8 +1227,8 @@ ReflectClose(
|
||||
#endif
|
||||
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
|
||||
if (tctPtr && tctPtr != &tclRChannelType) {
|
||||
ckfree(tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
ckfree(tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
}
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
return (result == TCL_OK) ? EOK : EINVAL;
|
||||
@@ -1272,7 +1278,10 @@ ReflectInput(
|
||||
|
||||
if (p.base.code != TCL_OK) {
|
||||
if (p.base.code < 0) {
|
||||
/* No error message, this is an errno signal. */
|
||||
/*
|
||||
* No error message, this is an errno signal.
|
||||
*/
|
||||
|
||||
*errorCodePtr = -p.base.code;
|
||||
} else {
|
||||
PassReceivedError(rcPtr->chan, &p);
|
||||
@@ -1375,7 +1384,10 @@ ReflectOutput(
|
||||
|
||||
if (p.base.code != TCL_OK) {
|
||||
if (p.base.code < 0) {
|
||||
/* No error message, this is an errno signal. */
|
||||
/*
|
||||
* No error message, this is an errno signal.
|
||||
*/
|
||||
|
||||
*errorCodePtr = -p.base.code;
|
||||
} else {
|
||||
PassReceivedError(rcPtr->chan, &p);
|
||||
@@ -1426,8 +1438,8 @@ ReflectOutput(
|
||||
|
||||
if ((written == 0) && (toWrite > 0)) {
|
||||
/*
|
||||
* The handler claims to have written nothing of what it was
|
||||
* given. That is bad.
|
||||
* The handler claims to have written nothing of what it was given.
|
||||
* That is bad.
|
||||
*/
|
||||
|
||||
SetChannelErrorStr(rcPtr->chan, msg_write_nothing);
|
||||
@@ -2373,8 +2385,8 @@ InvokeTclMethod(
|
||||
* None.
|
||||
*
|
||||
* Users:
|
||||
* ReflectInput/Output(), to enable the signaling of EAGAIN
|
||||
* on 0-sized short reads/writes.
|
||||
* ReflectInput/Output(), to enable the signaling of EAGAIN on 0-sized
|
||||
* short reads/writes.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2560,7 +2572,10 @@ DeleteReflectedChannelMap(
|
||||
|
||||
evPtr = resultPtr->evPtr;
|
||||
|
||||
/* Basic crash safety until this routine can get revised [3411310] */
|
||||
/*
|
||||
* Basic crash safety until this routine can get revised [3411310]
|
||||
*/
|
||||
|
||||
if (evPtr == NULL) {
|
||||
continue;
|
||||
}
|
||||
@@ -2675,8 +2690,8 @@ DeleteThreadReflectedChannelMap(
|
||||
|
||||
/*
|
||||
* Go through the list of pending results and cancel all whose events were
|
||||
* destined for this thread. While this is in progress we block any
|
||||
* other access to the list of pending results.
|
||||
* destined for this thread. While this is in progress we block any other
|
||||
* access to the list of pending results.
|
||||
*/
|
||||
|
||||
Tcl_MutexLock(&rcForwardMutex);
|
||||
@@ -2707,7 +2722,10 @@ DeleteThreadReflectedChannelMap(
|
||||
|
||||
evPtr = resultPtr->evPtr;
|
||||
|
||||
/* Basic crash safety until this routine can get revised [3411310] */
|
||||
/*
|
||||
* Basic crash safety until this routine can get revised [3411310]
|
||||
*/
|
||||
|
||||
if (evPtr == NULL ) {
|
||||
continue;
|
||||
}
|
||||
@@ -2761,8 +2779,8 @@ ForwardOpToHandlerThread(
|
||||
const void *param) /* Arguments */
|
||||
{
|
||||
/*
|
||||
* Core of the communication from OWNER to HANDLER thread.
|
||||
* The receiver is ForwardProc() below.
|
||||
* Core of the communication from OWNER to HANDLER thread. The receiver is
|
||||
* ForwardProc() below.
|
||||
*/
|
||||
|
||||
Tcl_ThreadId dst = rcPtr->thread;
|
||||
@@ -2812,7 +2830,10 @@ ForwardOpToHandlerThread(
|
||||
*/
|
||||
|
||||
TclSpliceIn(resultPtr, forwardList);
|
||||
/* Do not unlock here. That is done by the ConditionWait */
|
||||
|
||||
/*
|
||||
* Do not unlock here. That is done by the ConditionWait.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ensure cleanup of the event if the origin thread exits while this event
|
||||
@@ -2888,7 +2909,7 @@ ForwardProc(
|
||||
* Notes regarding access to the referenced data.
|
||||
*
|
||||
* In principle the data belongs to the originating thread (see
|
||||
* evPtr->src), however this thread is currently blocked at (*), i.e.
|
||||
* evPtr->src), however this thread is currently blocked at (*), i.e.,
|
||||
* quiescent. Because of this we can treat the data as belonging to us,
|
||||
* without fear of race conditions. I.e. we can read and write as we like.
|
||||
*
|
||||
|
||||
@@ -329,7 +329,7 @@ struct ForwardingResult {
|
||||
* results. */
|
||||
};
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
/*
|
||||
* Table of all reflected transformations owned by this thread.
|
||||
*/
|
||||
|
||||
+19
-10
@@ -12,16 +12,21 @@
|
||||
#include "tclInt.h"
|
||||
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
/* On Windows, we need to do proper Unicode->UTF-8 conversion. */
|
||||
/*
|
||||
* On Windows, we need to do proper Unicode->UTF-8 conversion.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
int initialized;
|
||||
Tcl_DString errorMsg; /* UTF-8 encoded error-message */
|
||||
} ThreadSpecificData;
|
||||
static Tcl_ThreadDataKey dataKey;
|
||||
|
||||
#undef gai_strerror
|
||||
static const char *gai_strerror(int code) {
|
||||
static const char *
|
||||
gai_strerror(
|
||||
int code)
|
||||
{
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
if (tsdPtr->initialized) {
|
||||
@@ -126,7 +131,7 @@ TclSockMinimumBuffers(
|
||||
}
|
||||
len = sizeof(int);
|
||||
getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *) ¤t, &len);
|
||||
(char *) ¤t, &len);
|
||||
if (current < size) {
|
||||
len = sizeof(int);
|
||||
setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
|
||||
@@ -215,7 +220,7 @@ TclCreateSocketAddress(
|
||||
* We found some problems when using AI_ADDRCONFIG, e.g. on systems that
|
||||
* have no networking besides the loopback interface and want to resolve
|
||||
* localhost. See [Bugs 3385024, 3382419, 3382431]. As the advantage of
|
||||
* using AI_ADDRCONFIG in situations where it works, is probably low,
|
||||
* using AI_ADDRCONFIG is probably low even in situations where it works,
|
||||
* we'll leave it out for now. After all, it is just an optimisation.
|
||||
*
|
||||
* Missing on: OpenBSD, NetBSD.
|
||||
@@ -300,16 +305,20 @@ TclCreateSocketAddress(
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
|
||||
const char *host, Tcl_TcpAcceptProc *acceptProc,
|
||||
ClientData callbackData)
|
||||
|
||||
Tcl_Channel
|
||||
Tcl_OpenTcpServer(
|
||||
Tcl_Interp *interp,
|
||||
int port,
|
||||
const char *host,
|
||||
Tcl_TcpAcceptProc *acceptProc,
|
||||
ClientData callbackData)
|
||||
{
|
||||
char portbuf[TCL_INTEGER_SPACE];
|
||||
|
||||
TclFormatInt(portbuf, port);
|
||||
|
||||
return Tcl_OpenTcpServerEx(interp, portbuf, host, TCL_TCPSERVER_REUSEADDR,
|
||||
acceptProc, callbackData);
|
||||
acceptProc, callbackData);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+32
-25
@@ -57,7 +57,7 @@ typedef struct FilesystemRecord {
|
||||
* this information each time the corresponding epoch counter changes.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
int initialized;
|
||||
size_t cwdPathEpoch;
|
||||
size_t filesystemEpoch;
|
||||
@@ -611,6 +611,7 @@ FsRecacheFilesystemList(void)
|
||||
|
||||
while (toFree) {
|
||||
FilesystemRecord *next = toFree->nextPtr;
|
||||
|
||||
toFree->fsPtr = NULL;
|
||||
ckfree(toFree);
|
||||
toFree = next;
|
||||
@@ -672,7 +673,6 @@ TclFSEpoch(void)
|
||||
|
||||
return tsdPtr->filesystemEpoch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If non-NULL, clientData is owned by us and must be freed later.
|
||||
@@ -784,7 +784,9 @@ TclFinalizeFilesystem(void)
|
||||
while (fsRecPtr != NULL) {
|
||||
FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr;
|
||||
|
||||
/* The native filesystem is static, so we don't free it. */
|
||||
/*
|
||||
* The native filesystem is static, so we don't free it.
|
||||
*/
|
||||
|
||||
if (fsRecPtr != &nativeFilesystemRecord) {
|
||||
ckfree(fsRecPtr);
|
||||
@@ -947,7 +949,7 @@ Tcl_FSRegister(
|
||||
|
||||
int
|
||||
Tcl_FSUnregister(
|
||||
const Tcl_Filesystem *fsPtr) /* The filesystem record to remove. */
|
||||
const Tcl_Filesystem *fsPtr)/* The filesystem record to remove. */
|
||||
{
|
||||
int retVal = TCL_ERROR;
|
||||
FilesystemRecord *fsRecPtr;
|
||||
@@ -1233,7 +1235,7 @@ FsAddMountsToGlobResult(
|
||||
|
||||
len--;
|
||||
}
|
||||
len++; /* account for '/' in the mElt [Bug 1602539] */
|
||||
len++; /* account for '/' in the mElt [Bug 1602539] */
|
||||
mElt = TclNewFSPathObj(pathPtr, mount + len, mlen - len);
|
||||
Tcl_ListObjAppendElement(NULL, resultPtr, mElt);
|
||||
}
|
||||
@@ -1403,7 +1405,7 @@ TclFSNormalizeToUniquePath(
|
||||
* Call each of the "normalise path" functions in succession. This is a
|
||||
* special case, in which if we have a native filesystem handler, we call
|
||||
* it first. This is because the root of Tcl's filesystem is always a
|
||||
* native filesystem (i.e. '/' on unix is native).
|
||||
* native filesystem (i.e., '/' on unix is native).
|
||||
*/
|
||||
|
||||
firstFsRecPtr = FsGetFirstFilesystem();
|
||||
@@ -1525,7 +1527,7 @@ TclGetOpenModeEx(
|
||||
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)
|
||||
|
||||
/*
|
||||
* Check for the simpler fopen-like access modes (e.g. "r"). They are
|
||||
* Check for the simpler fopen-like access modes (e.g., "r"). They are
|
||||
* distinguished from the POSIX access modes by the presence of a
|
||||
* lower-case first letter.
|
||||
*/
|
||||
@@ -1762,7 +1764,7 @@ Tcl_FSEvalFileEx(
|
||||
* this cross-platform to allow for scripted documents. [Bug: 2040]
|
||||
*/
|
||||
|
||||
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32");
|
||||
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
|
||||
|
||||
/*
|
||||
* If the encoding is specified, set it for the channel. Else don't touch
|
||||
@@ -1897,7 +1899,7 @@ TclNREvalFile(
|
||||
* this cross-platform to allow for scripted documents. [Bug: 2040]
|
||||
*/
|
||||
|
||||
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32");
|
||||
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
|
||||
|
||||
/*
|
||||
* If the encoding is specified, set it for the channel. Else don't touch
|
||||
@@ -2671,6 +2673,7 @@ Tcl_FSGetCwd(
|
||||
fsRecPtr = fsRecPtr->nextPtr) {
|
||||
ClientData retCd;
|
||||
TclFSGetCwdProc2 *proc2;
|
||||
|
||||
if (fsRecPtr->fsPtr->getCwdProc == NULL) {
|
||||
continue;
|
||||
}
|
||||
@@ -3143,8 +3146,8 @@ Tcl_FSLoadFile(
|
||||
* Workaround for issue with modern HPUX which do allow the unlink (no ETXTBSY
|
||||
* error) yet somehow trash some internal data structures which prevents the
|
||||
* second and further shared libraries from getting properly loaded. Only the
|
||||
* first is ok. We try to get around the issue by not unlinking,
|
||||
* i.e. emulating the behaviour of the older HPUX which denied removal.
|
||||
* first is ok. We try to get around the issue by not unlinking, i.e.,
|
||||
* emulating the behaviour of the older HPUX which denied removal.
|
||||
*
|
||||
* Doing the unlink is also an issue within docker containers, whose AUFS
|
||||
* bungles this as well, see
|
||||
@@ -3162,28 +3165,30 @@ Tcl_FSLoadFile(
|
||||
*/
|
||||
|
||||
int
|
||||
TclSkipUnlink (Tcl_Obj* shlibFile)
|
||||
TclSkipUnlink(
|
||||
Tcl_Obj *shlibFile)
|
||||
{
|
||||
/* Order of testing:
|
||||
/*
|
||||
* Order of testing:
|
||||
* 1. On hpux we generally want to skip unlink in general
|
||||
*
|
||||
* Outside of hpux then:
|
||||
* 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present, non-empty, => int)
|
||||
* 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present,
|
||||
* non-empty, => int)
|
||||
* 3. For general AUFS environment (statfs, if available).
|
||||
*
|
||||
* Ad 2: This variable can disable/override the AUFS detection, i.e. for
|
||||
* testing if a newer AUFS does not have the bug any more.
|
||||
* testing if a newer AUFS does not have the bug any more.
|
||||
*
|
||||
* Ad 3: This is conditionally compiled in. Condition currently must be set manually.
|
||||
* This part needs proper tests in the configure(.in).
|
||||
* Ad 3: This is conditionally compiled in. Condition currently must be
|
||||
* set manually. This part needs proper tests in the configure(.in).
|
||||
*/
|
||||
|
||||
#ifdef hpux
|
||||
return 1;
|
||||
#else
|
||||
char* skipstr;
|
||||
char *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK");
|
||||
|
||||
skipstr = getenv ("TCL_TEMPLOAD_NO_UNLINK");
|
||||
if (skipstr && (skipstr[0] != '\0')) {
|
||||
return atoi(skipstr);
|
||||
}
|
||||
@@ -3192,7 +3197,8 @@ TclSkipUnlink (Tcl_Obj* shlibFile)
|
||||
#ifndef NO_FSTATFS
|
||||
{
|
||||
struct statfs fs;
|
||||
/* Have fstatfs. May not have the AUFS super magic ... Indeed our build
|
||||
/*
|
||||
* Have fstatfs. May not have the AUFS super magic ... Indeed our build
|
||||
* box is too old to have it directly in the headers. Define taken from
|
||||
* http://mooon.googlecode.com/svn/trunk/linux_include/linux/aufs_type.h
|
||||
* http://aufs.sourceforge.net/
|
||||
@@ -3209,8 +3215,10 @@ TclSkipUnlink (Tcl_Obj* shlibFile)
|
||||
#endif /* ... NO_FSTATFS */
|
||||
#endif /* ... TCL_TEMPLOAD_NO_UNLINK */
|
||||
|
||||
/* Fallback: !hpux, no EV override, no AUFS (detection, nor detected):
|
||||
* Don't skip */
|
||||
/*
|
||||
* Fallback: !hpux, no EV override, no AUFS (detection, nor detected):
|
||||
* Don't skip
|
||||
*/
|
||||
return 0;
|
||||
#endif /* hpux */
|
||||
}
|
||||
@@ -3415,9 +3423,8 @@ Tcl_LoadFile(
|
||||
* avoids any worries about leaving the copy laying around on exit.
|
||||
*/
|
||||
|
||||
if (
|
||||
!TclSkipUnlink (copyToPtr) &&
|
||||
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
|
||||
if (!TclSkipUnlink(copyToPtr) &&
|
||||
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
|
||||
Tcl_DecrRefCount(copyToPtr);
|
||||
|
||||
/*
|
||||
|
||||
@@ -101,6 +101,7 @@ typedef struct {
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_GetIndexFromObj
|
||||
int
|
||||
Tcl_GetIndexFromObj(
|
||||
@@ -137,6 +138,7 @@ Tcl_GetIndexFromObj(
|
||||
return Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, sizeof(char *),
|
||||
msg, flags, indexPtr);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
|
||||
@@ -1011,6 +1011,32 @@ declare 251 {
|
||||
int TclRegisterLiteral(void *envPtr,
|
||||
const char *bytes, int length, int flags)
|
||||
}
|
||||
|
||||
# Exporting of the internal API to variables.
|
||||
|
||||
declare 252 {
|
||||
Tcl_Obj *TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr,
|
||||
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
const int flags)
|
||||
}
|
||||
declare 253 {
|
||||
Tcl_Obj *TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr,
|
||||
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
Tcl_Obj *newValuePtr, const int flags)
|
||||
}
|
||||
declare 254 {
|
||||
Tcl_Obj *TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr,
|
||||
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
Tcl_Obj *incrPtr, const int flags)
|
||||
}
|
||||
declare 255 {
|
||||
int TclPtrObjMakeUpvar(Tcl_Interp *interp, Tcl_Var otherPtr,
|
||||
Tcl_Obj *myNamePtr, int myFlags)
|
||||
}
|
||||
declare 256 {
|
||||
int TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr,
|
||||
Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags)
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
|
||||
|
||||
+73
-80
@@ -265,7 +265,7 @@ typedef struct Namespace {
|
||||
* strings; values have type (Namespace *). If
|
||||
* NULL, there are no children. */
|
||||
#endif
|
||||
long nsId; /* Unique id for the namespace. */
|
||||
size_t nsId; /* Unique id for the namespace. */
|
||||
Tcl_Interp *interp; /* The interpreter containing this
|
||||
* namespace. */
|
||||
int flags; /* OR-ed combination of the namespace status
|
||||
@@ -299,12 +299,12 @@ typedef struct Namespace {
|
||||
* registered using "namespace export". */
|
||||
int maxExportPatterns; /* Mumber of export patterns for which space
|
||||
* is currently allocated. */
|
||||
int cmdRefEpoch; /* Incremented if a newly added command
|
||||
size_t 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. */
|
||||
int resolverEpoch; /* Incremented whenever (a) the name
|
||||
size_t 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. */
|
||||
int exportLookupEpoch; /* Incremented whenever a command is added to
|
||||
size_t 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
|
||||
@@ -432,7 +432,7 @@ typedef struct EnsembleConfig {
|
||||
* if the command has been deleted (or never
|
||||
* existed; the global namespace never has an
|
||||
* ensemble command.) */
|
||||
int epoch; /* The epoch at which this ensemble's table of
|
||||
size_t 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
|
||||
@@ -1357,7 +1357,7 @@ MODULE_SCOPE void TclThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
|
||||
*/
|
||||
|
||||
#define TCL_TSD_INIT(keyPtr) \
|
||||
(ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
|
||||
Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -1639,7 +1639,7 @@ typedef struct Command {
|
||||
* representing a command's name in a ByteCode
|
||||
* instruction sequence. This structure can be
|
||||
* freed when refCount becomes zero. */
|
||||
int cmdEpoch; /* Incremented to invalidate any references
|
||||
size_t 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
|
||||
@@ -1862,6 +1862,7 @@ typedef struct Interp {
|
||||
* See Tcl_AppendResult code for details.
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
char *appendResult; /* Storage space for results generated by
|
||||
* Tcl_AppendResult. Ckalloc-ed. NULL means
|
||||
* not yet allocated. */
|
||||
@@ -1869,6 +1870,11 @@ typedef struct Interp {
|
||||
* partialResult. */
|
||||
int appendUsed; /* Number of non-null bytes currently stored
|
||||
* at partialResult. */
|
||||
#else
|
||||
char *appendResultDontUse;
|
||||
int appendAvlDontUse;
|
||||
int appendUsedDontUse;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Information about packages. Used only in tclPkg.c.
|
||||
@@ -1930,8 +1936,12 @@ 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];
|
||||
/* Static space holding small results. */
|
||||
#else
|
||||
char resultSpaceDontUse[TCL_RESULT_SIZE+1];
|
||||
#endif
|
||||
Tcl_Obj *objResultPtr; /* If the last command returned an object
|
||||
* result, this points to it. Should not be
|
||||
* accessed directly; see comment above. */
|
||||
@@ -2620,7 +2630,7 @@ typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, size_t *lengthPtr,
|
||||
*/
|
||||
|
||||
typedef struct ProcessGlobalValue {
|
||||
size_t epoch; /* Epoch counter to detect changes in the
|
||||
size_t epoch; /* Epoch counter to detect changes in the
|
||||
* master value. */
|
||||
size_t numBytes; /* Length of the master string. */
|
||||
char *value; /* The master string value. */
|
||||
@@ -2961,7 +2971,8 @@ MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, Tcl_Channel *chanPtr,
|
||||
int *modePtr, int flags);
|
||||
MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp,
|
||||
MODULE_SCOPE CmdFrame * TclGetCmdFrameForProcedure(Proc *procPtr);
|
||||
MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *value, int *code);
|
||||
MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, ClientData *clientDataPtr,
|
||||
@@ -2996,6 +3007,9 @@ MODULE_SCOPE int TclInfoLocalsCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclInfoVarsCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE void TclInitAlloc(void);
|
||||
MODULE_SCOPE void TclInitBignumFromLong(mp_int *, long);
|
||||
MODULE_SCOPE void TclInitBignumFromWideInt(mp_int *, Tcl_WideInt);
|
||||
MODULE_SCOPE void TclInitBignumFromWideUInt(mp_int *, Tcl_WideUInt);
|
||||
MODULE_SCOPE void TclInitDbCkalloc(void);
|
||||
MODULE_SCOPE void TclInitDoubleConversion(void);
|
||||
MODULE_SCOPE void TclInitEmbeddedConfigurationInformation(
|
||||
@@ -3114,7 +3128,7 @@ MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp);
|
||||
MODULE_SCOPE void * TclThreadStorageKeyGet(Tcl_ThreadDataKey *keyPtr);
|
||||
MODULE_SCOPE void TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr,
|
||||
void *data);
|
||||
MODULE_SCOPE void TclpThreadExit(int status);
|
||||
MODULE_SCOPE TCL_NORETURN void TclpThreadExit(int status);
|
||||
MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex);
|
||||
MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id);
|
||||
MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex);
|
||||
@@ -3277,10 +3291,8 @@ MODULE_SCOPE int Tcl_AssembleObjCmd(ClientData clientData,
|
||||
MODULE_SCOPE int TclNRAssembleObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
|
||||
MODULE_SCOPE int Tcl_EncodingObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE Tcl_Command TclInitEncodingCmd(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int TclMakeEncodingCommandSafe(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int Tcl_EofObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -3518,6 +3530,12 @@ MODULE_SCOPE int TclCompileBreakCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileCatchCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileClockClicksCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileClockReadingCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileConcatCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3954,7 +3972,7 @@ MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp,
|
||||
struct CompileEnv *envPtr);
|
||||
|
||||
/*
|
||||
* Functions defined in generic/tclVar.c and currenttly exported only for use
|
||||
* 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
|
||||
* the public interface.
|
||||
*/
|
||||
@@ -3968,20 +3986,21 @@ MODULE_SCOPE Var * TclLookupArrayElement(Tcl_Interp *interp,
|
||||
const int flags, const char *msg,
|
||||
const int createPart1, const int createPart2,
|
||||
Var *arrayPtr, int index);
|
||||
MODULE_SCOPE Tcl_Obj * TclPtrGetVar(Tcl_Interp *interp,
|
||||
MODULE_SCOPE Tcl_Obj * TclPtrGetVarIdx(Tcl_Interp *interp,
|
||||
Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, const int flags, int index);
|
||||
MODULE_SCOPE Tcl_Obj * TclPtrSetVar(Tcl_Interp *interp,
|
||||
MODULE_SCOPE Tcl_Obj * TclPtrSetVarIdx(Tcl_Interp *interp,
|
||||
Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
|
||||
const int flags, int index);
|
||||
MODULE_SCOPE Tcl_Obj * TclPtrIncrObjVar(Tcl_Interp *interp,
|
||||
MODULE_SCOPE Tcl_Obj * TclPtrIncrObjVarIdx(Tcl_Interp *interp,
|
||||
Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr,
|
||||
const int flags, int index);
|
||||
MODULE_SCOPE int TclPtrObjMakeUpvar(Tcl_Interp *interp, Var *otherPtr,
|
||||
Tcl_Obj *myNamePtr, int myFlags, int index);
|
||||
MODULE_SCOPE int TclPtrUnsetVar(Tcl_Interp *interp, Var *varPtr,
|
||||
MODULE_SCOPE int TclPtrObjMakeUpvarIdx(Tcl_Interp *interp,
|
||||
Var *otherPtr, Tcl_Obj *myNamePtr, int myFlags,
|
||||
int index);
|
||||
MODULE_SCOPE int TclPtrUnsetVarIdx(Tcl_Interp *interp, Var *varPtr,
|
||||
Var *arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, const int flags,
|
||||
int index);
|
||||
@@ -4339,13 +4358,13 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
#define TCL_MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token))
|
||||
#define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr) \
|
||||
do { \
|
||||
int needed = (used) + (append); \
|
||||
if (needed > TCL_MAX_TOKENS) { \
|
||||
int _needed = (used) + (append); \
|
||||
if (_needed > TCL_MAX_TOKENS) { \
|
||||
Tcl_Panic("max # of tokens for a Tcl parse (%d) exceeded", \
|
||||
TCL_MAX_TOKENS); \
|
||||
} \
|
||||
if (needed > (available)) { \
|
||||
int allocated = 2 * needed; \
|
||||
if (_needed > (available)) { \
|
||||
int allocated = 2 * _needed; \
|
||||
Tcl_Token *oldPtr = (tokenPtr); \
|
||||
Tcl_Token *newPtr; \
|
||||
if (oldPtr == (staticPtr)) { \
|
||||
@@ -4357,7 +4376,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
newPtr = (Tcl_Token *) attemptckrealloc((char *) oldPtr, \
|
||||
(unsigned int) (allocated * sizeof(Tcl_Token))); \
|
||||
if (newPtr == NULL) { \
|
||||
allocated = needed + (append) + TCL_MIN_TOKEN_GROWTH; \
|
||||
allocated = _needed + (append) + TCL_MIN_TOKEN_GROWTH; \
|
||||
if (allocated > TCL_MAX_TOKENS) { \
|
||||
allocated = TCL_MAX_TOKENS; \
|
||||
} \
|
||||
@@ -4392,7 +4411,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
|
||||
#define TclUtfToUniChar(str, chPtr) \
|
||||
((((unsigned char) *(str)) < 0xC0) ? \
|
||||
((*(chPtr) = (Tcl_UniChar) *(str)), 1) \
|
||||
((*(chPtr) = (unsigned char) *(str)), 1) \
|
||||
: Tcl_UtfToUniChar(str, chPtr))
|
||||
|
||||
/*
|
||||
@@ -4409,14 +4428,14 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
|
||||
#define TclNumUtfChars(numChars, bytes, numBytes) \
|
||||
do { \
|
||||
int count, i = (numBytes); \
|
||||
unsigned char *str = (unsigned char *) (bytes); \
|
||||
while (i && (*str < 0xC0)) { i--; str++; } \
|
||||
count = (numBytes) - i; \
|
||||
if (i) { \
|
||||
count += Tcl_NumUtfChars((bytes) + count, i); \
|
||||
int _count, _i = (numBytes); \
|
||||
unsigned char *_str = (unsigned char *) (bytes); \
|
||||
while (_i && (*_str < 0xC0)) { _i--; _str++; } \
|
||||
_count = (numBytes) - _i; \
|
||||
if (_i) { \
|
||||
_count += Tcl_NumUtfChars((bytes) + _count, _i); \
|
||||
} \
|
||||
(numChars) = count; \
|
||||
(numChars) = _count; \
|
||||
} while (0);
|
||||
|
||||
/*
|
||||
@@ -4516,9 +4535,7 @@ 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 TclSetIntObj(Tcl_Obj *objPtr, int intValue);
|
||||
* MODULE_SCOPE void TclSetLongObj(Tcl_Obj *objPtr, long longValue);
|
||||
* MODULE_SCOPE void TclSetBooleanObj(Tcl_Obj *objPtr, long boolValue);
|
||||
* MODULE_SCOPE void TclSetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d);
|
||||
*----------------------------------------------------------------
|
||||
@@ -4532,19 +4549,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
(objPtr)->typePtr = &tclIntType; \
|
||||
} while (0)
|
||||
|
||||
#define TclSetIntObj(objPtr, l) \
|
||||
TclSetLongObj(objPtr, l)
|
||||
|
||||
/*
|
||||
* NOTE: There is to be no such thing as a "pure" boolean. Boolean values set
|
||||
* programmatically go straight to being "int" Tcl_Obj's, with value 0 or 1.
|
||||
* The only "boolean" Tcl_Obj's shall be those holding the cached boolean
|
||||
* value of strings like: "yes", "no", "true", "false", "on", "off".
|
||||
*/
|
||||
|
||||
#define TclSetBooleanObj(objPtr, b) \
|
||||
TclSetLongObj(objPtr, (b)!=0);
|
||||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
#define TclSetWideIntObj(objPtr, w) \
|
||||
do { \
|
||||
@@ -4570,7 +4574,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
* the core. The ANSI C "prototypes" for these macros are:
|
||||
*
|
||||
* MODULE_SCOPE void TclNewLongObj(Tcl_Obj *objPtr, long l);
|
||||
* MODULE_SCOPE void TclNewBooleanObj(Tcl_Obj *objPtr, int b);
|
||||
* MODULE_SCOPE void TclNewWideObj(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);
|
||||
@@ -4591,13 +4594,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
TCL_DTRACE_OBJ_CREATE(objPtr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* NOTE: There is to be no such thing as a "pure" boolean.
|
||||
* See comment above TclSetBooleanObj macro above.
|
||||
*/
|
||||
#define TclNewBooleanObj(objPtr, b) \
|
||||
TclNewLongObj((objPtr), (b)!=0)
|
||||
|
||||
#define TclNewDoubleObj(objPtr, d) \
|
||||
do { \
|
||||
TclIncrObjsAllocated(); \
|
||||
@@ -4623,9 +4619,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
#define TclNewLongObj(objPtr, l) \
|
||||
(objPtr) = Tcl_NewLongObj(l)
|
||||
|
||||
#define TclNewBooleanObj(objPtr, b) \
|
||||
(objPtr) = Tcl_NewBooleanObj(b)
|
||||
|
||||
#define TclNewDoubleObj(objPtr, d) \
|
||||
(objPtr) = Tcl_NewDoubleObj(d)
|
||||
|
||||
@@ -4767,11 +4760,11 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
#ifndef TCL_MEM_DEBUG
|
||||
#define TclSmallAllocEx(interp, nbytes, memPtr) \
|
||||
do { \
|
||||
Tcl_Obj *objPtr; \
|
||||
Tcl_Obj *_objPtr; \
|
||||
TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \
|
||||
TclIncrObjsAllocated(); \
|
||||
TclAllocObjStorageEx((interp), (objPtr)); \
|
||||
memPtr = (ClientData) (objPtr); \
|
||||
TclAllocObjStorageEx((interp), (_objPtr)); \
|
||||
memPtr = (ClientData) (_objPtr); \
|
||||
} while (0)
|
||||
|
||||
#define TclSmallFreeEx(interp, memPtr) \
|
||||
@@ -4783,19 +4776,19 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
#else /* TCL_MEM_DEBUG */
|
||||
#define TclSmallAllocEx(interp, nbytes, memPtr) \
|
||||
do { \
|
||||
Tcl_Obj *objPtr; \
|
||||
Tcl_Obj *_objPtr; \
|
||||
TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \
|
||||
TclNewObj(objPtr); \
|
||||
memPtr = (ClientData) objPtr; \
|
||||
TclNewObj(_objPtr); \
|
||||
memPtr = (ClientData) _objPtr; \
|
||||
} while (0)
|
||||
|
||||
#define TclSmallFreeEx(interp, memPtr) \
|
||||
do { \
|
||||
Tcl_Obj *objPtr = (Tcl_Obj *) memPtr; \
|
||||
objPtr->bytes = NULL; \
|
||||
objPtr->typePtr = NULL; \
|
||||
objPtr->refCount = 1; \
|
||||
TclDecrRefCount(objPtr); \
|
||||
Tcl_Obj *_objPtr = (Tcl_Obj *) memPtr; \
|
||||
_objPtr->bytes = NULL; \
|
||||
_objPtr->typePtr = NULL; \
|
||||
_objPtr->refCount = 1; \
|
||||
TclDecrRefCount(_objPtr); \
|
||||
} while (0)
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
|
||||
@@ -4847,15 +4840,15 @@ typedef struct NRE_callback {
|
||||
|
||||
#define TclNRAddCallback(interp,postProcPtr,data0,data1,data2,data3) \
|
||||
do { \
|
||||
NRE_callback *callbackPtr; \
|
||||
TCLNR_ALLOC((interp), (callbackPtr)); \
|
||||
callbackPtr->procPtr = (postProcPtr); \
|
||||
callbackPtr->data[0] = (ClientData)(data0); \
|
||||
callbackPtr->data[1] = (ClientData)(data1); \
|
||||
callbackPtr->data[2] = (ClientData)(data2); \
|
||||
callbackPtr->data[3] = (ClientData)(data3); \
|
||||
callbackPtr->nextPtr = TOP_CB(interp); \
|
||||
TOP_CB(interp) = callbackPtr; \
|
||||
NRE_callback *_callbackPtr; \
|
||||
TCLNR_ALLOC((interp), (_callbackPtr)); \
|
||||
_callbackPtr->procPtr = (postProcPtr); \
|
||||
_callbackPtr->data[0] = (ClientData)(data0); \
|
||||
_callbackPtr->data[1] = (ClientData)(data1); \
|
||||
_callbackPtr->data[2] = (ClientData)(data2); \
|
||||
_callbackPtr->data[3] = (ClientData)(data3); \
|
||||
_callbackPtr->nextPtr = TOP_CB(interp); \
|
||||
TOP_CB(interp) = _callbackPtr; \
|
||||
} while (0)
|
||||
|
||||
#if NRE_USE_SMALL_ALLOC
|
||||
|
||||
@@ -617,6 +617,28 @@ EXTERN void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags,
|
||||
/* 251 */
|
||||
EXTERN int TclRegisterLiteral(void *envPtr, const char *bytes,
|
||||
int length, int flags);
|
||||
/* 252 */
|
||||
EXTERN Tcl_Obj * TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr,
|
||||
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, const int flags);
|
||||
/* 253 */
|
||||
EXTERN Tcl_Obj * TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr,
|
||||
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
|
||||
const int flags);
|
||||
/* 254 */
|
||||
EXTERN Tcl_Obj * TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr,
|
||||
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr,
|
||||
const int flags);
|
||||
/* 255 */
|
||||
EXTERN int TclPtrObjMakeUpvar(Tcl_Interp *interp,
|
||||
Tcl_Var otherPtr, Tcl_Obj *myNamePtr,
|
||||
int myFlags);
|
||||
/* 256 */
|
||||
EXTERN int TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr,
|
||||
Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, const int flags);
|
||||
|
||||
typedef struct TclIntStubs {
|
||||
int magic;
|
||||
@@ -874,6 +896,11 @@ typedef struct TclIntStubs {
|
||||
char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */
|
||||
void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */
|
||||
int (*tclRegisterLiteral) (void *envPtr, const char *bytes, int length, int flags); /* 251 */
|
||||
Tcl_Obj * (*tclPtrGetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 252 */
|
||||
Tcl_Obj * (*tclPtrSetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, const int flags); /* 253 */
|
||||
Tcl_Obj * (*tclPtrIncrObjVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, const int flags); /* 254 */
|
||||
int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */
|
||||
int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 256 */
|
||||
} TclIntStubs;
|
||||
|
||||
extern const TclIntStubs *tclIntStubsPtr;
|
||||
@@ -1305,6 +1332,16 @@ extern const TclIntStubs *tclIntStubsPtr;
|
||||
(tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */
|
||||
#define TclRegisterLiteral \
|
||||
(tclIntStubsPtr->tclRegisterLiteral) /* 251 */
|
||||
#define TclPtrGetVar \
|
||||
(tclIntStubsPtr->tclPtrGetVar) /* 252 */
|
||||
#define TclPtrSetVar \
|
||||
(tclIntStubsPtr->tclPtrSetVar) /* 253 */
|
||||
#define TclPtrIncrObjVar \
|
||||
(tclIntStubsPtr->tclPtrIncrObjVar) /* 254 */
|
||||
#define TclPtrObjMakeUpvar \
|
||||
(tclIntStubsPtr->tclPtrObjMakeUpvar) /* 255 */
|
||||
#define TclPtrUnsetVar \
|
||||
(tclIntStubsPtr->tclPtrUnsetVar) /* 256 */
|
||||
|
||||
#endif /* defined(USE_TCL_STUBS) */
|
||||
|
||||
|
||||
@@ -3533,9 +3533,6 @@ Tcl_LimitAddHandler(
|
||||
if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_DYNAMIC) {
|
||||
deleteProc = (Tcl_LimitHandlerDeleteProc *) Tcl_Free;
|
||||
}
|
||||
if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_STATIC) {
|
||||
deleteProc = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a handler record.
|
||||
|
||||
+97
-104
@@ -36,8 +36,10 @@ typedef struct Link {
|
||||
unsigned int ui;
|
||||
short s;
|
||||
unsigned short us;
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
long l;
|
||||
unsigned long ul;
|
||||
#endif
|
||||
Tcl_WideInt w;
|
||||
Tcl_WideUInt uw;
|
||||
float f;
|
||||
@@ -68,6 +70,7 @@ static char * LinkTraceProc(ClientData clientData,Tcl_Interp *interp,
|
||||
const char *name1, const char *name2, int flags);
|
||||
static Tcl_Obj * ObjValue(Link *linkPtr);
|
||||
static int GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr);
|
||||
static int GetInvalidWideFromObj(Tcl_Obj *objPtr, Tcl_WideInt *widePtr);
|
||||
static int GetInvalidDoubleFromObj(Tcl_Obj *objPtr, double *doublePtr);
|
||||
|
||||
/*
|
||||
@@ -128,6 +131,14 @@ Tcl_LinkVar(
|
||||
Tcl_IncrRefCount(linkPtr->varName);
|
||||
linkPtr->addr = addr;
|
||||
linkPtr->type = type & ~TCL_LINK_READ_ONLY;
|
||||
#if !defined(TCL_NO_DEPRECATED) && (defined(TCL_WIDE_INT_IS_LONG) \
|
||||
|| defined(_WIN32) || defined(__CYGWIN__))
|
||||
if (linkPtr->type == 11 /* legacy TCL_LINK_LONG */) {
|
||||
linkPtr->type = TCL_LINK_LONG;
|
||||
} else if (linkPtr->type == 12 /* legacy TCL_LINK_ULONG */) {
|
||||
linkPtr->type = TCL_LINK_ULONG;
|
||||
}
|
||||
#endif
|
||||
if (type & TCL_LINK_READ_ONLY) {
|
||||
linkPtr->flags = LINK_READ_ONLY;
|
||||
} else {
|
||||
@@ -334,12 +345,14 @@ LinkTraceProc(
|
||||
case TCL_LINK_UINT:
|
||||
changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui);
|
||||
break;
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
case TCL_LINK_LONG:
|
||||
changed = (LinkedVar(long) != linkPtr->lastValue.l);
|
||||
break;
|
||||
case TCL_LINK_ULONG:
|
||||
changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul);
|
||||
break;
|
||||
#endif
|
||||
case TCL_LINK_FLOAT:
|
||||
changed = (LinkedVar(float) != linkPtr->lastValue.f);
|
||||
break;
|
||||
@@ -381,38 +394,31 @@ LinkTraceProc(
|
||||
|
||||
switch (linkPtr->type) {
|
||||
case TCL_LINK_INT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i)
|
||||
!= TCL_OK) {
|
||||
if (GetInvalidIntFromObj(valueObj, &linkPtr->lastValue.i) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &linkPtr->lastValue.i) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
LinkedVar(int) = linkPtr->lastValue.i;
|
||||
break;
|
||||
|
||||
case TCL_LINK_WIDE_INT:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w)
|
||||
!= TCL_OK) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &linkPtr->lastValue.w) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
linkPtr->lastValue.w = (Tcl_WideInt) valueInt;
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w;
|
||||
break;
|
||||
|
||||
case TCL_LINK_DOUBLE:
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d) != TCL_OK) {
|
||||
#ifdef ACCEPT_NAN
|
||||
if (valueObj->typePtr != &tclDoubleType) {
|
||||
#endif
|
||||
if (GetInvalidDoubleFromObj(valueObj, &linkPtr->lastValue.d)
|
||||
!= TCL_OK) {
|
||||
if (GetInvalidDoubleFromObj(valueObj, &linkPtr->lastValue.d) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have real value";
|
||||
@@ -426,8 +432,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_BOOLEAN:
|
||||
if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have boolean value";
|
||||
@@ -436,131 +441,106 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_CHAR:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have char value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have char value";
|
||||
}
|
||||
linkPtr->lastValue.c = (char)valueInt;
|
||||
LinkedVar(char) = linkPtr->lastValue.c;
|
||||
LinkedVar(char) = linkPtr->lastValue.c = (char)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_UCHAR:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < 0 || valueInt > UCHAR_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned char value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned char value";
|
||||
}
|
||||
linkPtr->lastValue.uc = (unsigned char) valueInt;
|
||||
LinkedVar(unsigned char) = linkPtr->lastValue.uc;
|
||||
LinkedVar(unsigned char) = linkPtr->lastValue.uc = (unsigned char) valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_SHORT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < SHRT_MIN || valueInt > SHRT_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have short value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have short value";
|
||||
}
|
||||
linkPtr->lastValue.s = (short)valueInt;
|
||||
LinkedVar(short) = linkPtr->lastValue.s;
|
||||
LinkedVar(short) = linkPtr->lastValue.s = (short)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_USHORT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < 0 || valueInt > USHRT_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned short value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned short value";
|
||||
}
|
||||
linkPtr->lastValue.us = (unsigned short)valueInt;
|
||||
LinkedVar(unsigned short) = linkPtr->lastValue.us;
|
||||
LinkedVar(unsigned short) = linkPtr->lastValue.us = (unsigned short)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_UINT:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < 0 || valueWide > UINT_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned int value";
|
||||
}
|
||||
linkPtr->lastValue.ui = (unsigned int)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned int value";
|
||||
}
|
||||
LinkedVar(unsigned int) = linkPtr->lastValue.ui;
|
||||
LinkedVar(unsigned int) = linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
break;
|
||||
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
case TCL_LINK_LONG:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < LONG_MIN || valueWide > LONG_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have long value";
|
||||
}
|
||||
linkPtr->lastValue.l = (long)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.l = (long)valueWide;
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have long value";
|
||||
}
|
||||
LinkedVar(long) = linkPtr->lastValue.l;
|
||||
LinkedVar(long) = linkPtr->lastValue.l = (long)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_ULONG:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < 0 || (Tcl_WideUInt) valueWide > ULONG_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned long value";
|
||||
}
|
||||
linkPtr->lastValue.ul = (unsigned long)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned long value";
|
||||
}
|
||||
LinkedVar(unsigned long) = linkPtr->lastValue.ul;
|
||||
LinkedVar(unsigned long) = linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TCL_LINK_WIDE_UINT:
|
||||
/*
|
||||
* FIXME: represent as a bignum.
|
||||
*/
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned wide int value";
|
||||
}
|
||||
linkPtr->lastValue.uw = (Tcl_WideUInt)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned wide int value";
|
||||
}
|
||||
LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw;
|
||||
LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_FLOAT:
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &valueDouble) != TCL_OK
|
||||
if ((Tcl_GetDoubleFromObj(NULL, valueObj, &valueDouble) != TCL_OK
|
||||
&& GetInvalidDoubleFromObj(valueObj, &valueDouble) != TCL_OK)
|
||||
|| valueDouble < -FLT_MAX || valueDouble > FLT_MAX) {
|
||||
if (GetInvalidDoubleFromObj(valueObj, &valueDouble)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have float value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have float value";
|
||||
}
|
||||
linkPtr->lastValue.f = (float)valueDouble;
|
||||
LinkedVar(float) = linkPtr->lastValue.f;
|
||||
LinkedVar(float) = linkPtr->lastValue.f = (float)valueDouble;
|
||||
break;
|
||||
|
||||
case TCL_LINK_STRING:
|
||||
@@ -631,12 +611,14 @@ ObjValue(
|
||||
case TCL_LINK_UINT:
|
||||
linkPtr->lastValue.ui = LinkedVar(unsigned int);
|
||||
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ui);
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
case TCL_LINK_LONG:
|
||||
linkPtr->lastValue.l = LinkedVar(long);
|
||||
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.l);
|
||||
case TCL_LINK_ULONG:
|
||||
linkPtr->lastValue.ul = LinkedVar(unsigned long);
|
||||
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ul);
|
||||
#endif
|
||||
case TCL_LINK_FLOAT:
|
||||
linkPtr->lastValue.f = LinkedVar(float);
|
||||
return Tcl_NewDoubleObj(linkPtr->lastValue.f);
|
||||
@@ -710,7 +692,7 @@ SetInvalidRealFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) {
|
||||
/*
|
||||
* This function checks for integer representations, which are valid
|
||||
* when linking with C variables, but which are invalid in other
|
||||
* contexts in Tcl. Handled are "+", "-", "", "0x", "0b" and "0o"
|
||||
* contexts in Tcl. Handled are "+", "-", "", "0x", "0b", "0d" and "0o"
|
||||
* (upperand lowercase). See bug [39f6304c2e].
|
||||
*/
|
||||
int
|
||||
@@ -719,7 +701,7 @@ GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr)
|
||||
const char *str = TclGetString(objPtr);
|
||||
|
||||
if ((objPtr->length == 0) ||
|
||||
((objPtr->length == 2) && (str[0] == '0') && strchr("xXbBoO", str[1]))) {
|
||||
((objPtr->length == 2) && (str[0] == '0') && strchr("xXbBoOdD", str[1]))) {
|
||||
*intPtr = 0;
|
||||
return TCL_OK;
|
||||
} else if ((objPtr->length == 1) && strchr("+-", str[0])) {
|
||||
@@ -729,6 +711,18 @@ GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr)
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
GetInvalidWideFromObj(Tcl_Obj *objPtr, Tcl_WideInt *widePtr)
|
||||
{
|
||||
int intValue;
|
||||
|
||||
if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*widePtr = intValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks for double representations, which are valid
|
||||
* when linking with C variables, but which are invalid in other
|
||||
@@ -736,8 +730,7 @@ GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr)
|
||||
* (upper- and lowercase) and sequences like "1e-". See bug [39f6304c2e].
|
||||
*/
|
||||
int
|
||||
GetInvalidDoubleFromObj(Tcl_Obj *objPtr,
|
||||
double *doublePtr)
|
||||
GetInvalidDoubleFromObj(Tcl_Obj *objPtr, double *doublePtr)
|
||||
{
|
||||
int intValue;
|
||||
|
||||
|
||||
+2
-2
@@ -130,7 +130,7 @@ Tcl_LoadObjCmd(
|
||||
Tcl_PackageInitProc *initProc;
|
||||
const char *p, *fullFileName, *packageName;
|
||||
Tcl_LoadHandle loadHandle;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
unsigned len;
|
||||
int index, flags = 0;
|
||||
Tcl_Obj *const *savedobjv = objv;
|
||||
@@ -336,7 +336,7 @@ Tcl_LoadObjCmd(
|
||||
}
|
||||
#endif /* __CYGWIN__ */
|
||||
for (p = pkgGuess; *p != 0; p += offset) {
|
||||
offset = Tcl_UtfToUniChar(p, &ch);
|
||||
offset = TclUtfToUniChar(p, &ch);
|
||||
if ((ch > 0x100)
|
||||
|| !(isalpha(UCHAR(ch)) /* INTL: ISO only */
|
||||
|| (UCHAR(ch) == '_'))) {
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
* limited to a single interpreter.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
size_t numNsCreated; /* Count of the number of namespaces created
|
||||
* within the thread. This value is used as a
|
||||
* unique id for each namespace. Cannot be
|
||||
|
||||
@@ -41,6 +41,7 @@ static const struct {
|
||||
{"forward", TclOODefineForwardObjCmd, 1},
|
||||
{"method", TclOODefineMethodObjCmd, 1},
|
||||
{"renamemethod", TclOODefineRenameMethodObjCmd, 1},
|
||||
{"self", TclOODefineObjSelfObjCmd, 0},
|
||||
{"unexport", TclOODefineUnexportObjCmd, 1},
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
* win/tclooConfig.sh
|
||||
*/
|
||||
|
||||
#define TCLOO_VERSION "1.0.4"
|
||||
#define TCLOO_VERSION "1.2.0"
|
||||
#define TCLOO_PATCHLEVEL TCLOO_VERSION
|
||||
|
||||
#include "tcl.h"
|
||||
|
||||
+27
-5
@@ -1183,8 +1183,9 @@ TclOOCopyObjectCmd(
|
||||
{
|
||||
Tcl_Object oPtr, o2Ptr;
|
||||
|
||||
if (objc < 2 || objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "sourceName ?targetName?");
|
||||
if (objc < 2 || objc > 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"sourceName ?targetName? ?targetNamespace?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1204,12 +1205,14 @@ TclOOCopyObjectCmd(
|
||||
if (objc == 2) {
|
||||
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, NULL, NULL);
|
||||
} else {
|
||||
const char *name;
|
||||
const char *name, *namespaceName;
|
||||
Tcl_DString buffer;
|
||||
|
||||
name = TclGetString(objv[2]);
|
||||
Tcl_DStringInit(&buffer);
|
||||
if (name[0]!=':' || name[1]!=':') {
|
||||
if (name[0] == '\0') {
|
||||
name = NULL;
|
||||
} else if (name[0]!=':' || name[1]!=':') {
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
if (iPtr->varFramePtr != NULL) {
|
||||
@@ -1220,7 +1223,26 @@ TclOOCopyObjectCmd(
|
||||
Tcl_DStringAppend(&buffer, name, -1);
|
||||
name = Tcl_DStringValue(&buffer);
|
||||
}
|
||||
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, name, NULL);
|
||||
|
||||
/*
|
||||
* Choose a unique namespace name if the user didn't supply one.
|
||||
*/
|
||||
|
||||
namespaceName = NULL;
|
||||
if (objc == 4) {
|
||||
namespaceName = TclGetString(objv[3]);
|
||||
|
||||
if (namespaceName[0] == '\0') {
|
||||
namespaceName = NULL;
|
||||
} else if (Tcl_FindNamespace(interp, namespaceName, NULL,
|
||||
0) != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%s refers to an existing namespace", namespaceName));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, name, namespaceName);
|
||||
Tcl_DStringFree(&buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -619,6 +619,7 @@ AddClassMethodNames(
|
||||
int isWanted = (!(flags & PUBLIC_METHOD)
|
||||
|| (mPtr->flags & PUBLIC_METHOD)) ? IN_LIST : 0;
|
||||
|
||||
isWanted |= (mPtr->typePtr == NULL ? NO_IMPLEMENTATION : 0);
|
||||
Tcl_SetHashValue(hPtr, INT2PTR(isWanted));
|
||||
} else if ((PTR2INT(Tcl_GetHashValue(hPtr)) & NO_IMPLEMENTATION)
|
||||
&& mPtr->typePtr != NULL) {
|
||||
|
||||
+112
-131
@@ -47,8 +47,11 @@ struct DeclaredSlot {
|
||||
static inline void BumpGlobalEpoch(Tcl_Interp *interp, Class *classPtr);
|
||||
static Tcl_Command FindCommand(Tcl_Interp *interp, Tcl_Obj *stringObj,
|
||||
Tcl_Namespace *const namespacePtr);
|
||||
static void GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr,
|
||||
static inline void GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr,
|
||||
Tcl_Obj *savedNameObj, const char *typeOfSubject);
|
||||
static inline int MagicDefinitionInvoke(Tcl_Interp *interp,
|
||||
Tcl_Namespace *nsPtr, int cmdIndex,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static inline Class * GetClassInOuterContext(Tcl_Interp *interp,
|
||||
Tcl_Obj *className, const char *errMsg);
|
||||
static inline int InitDefineContext(Tcl_Interp *interp,
|
||||
@@ -755,7 +758,7 @@ GetClassInOuterContext(
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
static inline void
|
||||
GenerateErrorInfo(
|
||||
Tcl_Interp *interp, /* Where to store the error info trace. */
|
||||
Object *oPtr, /* What object (or class) was being configured
|
||||
@@ -784,6 +787,69 @@ GenerateErrorInfo(
|
||||
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* 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
|
||||
* clearer. Doesn't handle the management of the stack frame.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline int
|
||||
MagicDefinitionInvoke(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Namespace *nsPtr,
|
||||
int cmdIndex,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Tcl_Obj *objPtr, *obj2Ptr, **objs;
|
||||
Tcl_Command cmd;
|
||||
int isRoot, dummy, result, offset = cmdIndex + 1;
|
||||
|
||||
/*
|
||||
* More than one argument: fire them through the ensemble processing
|
||||
* engine so that everything appears to be good and proper in error
|
||||
* messages. Note that we cannot just concatenate and send through
|
||||
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we cannot go
|
||||
* through Tcl_EvalObjv without the extra work to pre-find the command, as
|
||||
* that finds command names in the wrong namespace at the moment. Ugly!
|
||||
*/
|
||||
|
||||
isRoot = TclInitRewriteEnsemble(interp, offset, 1, objv);
|
||||
|
||||
/*
|
||||
* Build the list of arguments using a Tcl_Obj as a workspace. See
|
||||
* comments above for why these contortions are necessary.
|
||||
*/
|
||||
|
||||
objPtr = Tcl_NewObj();
|
||||
obj2Ptr = Tcl_NewObj();
|
||||
cmd = FindCommand(interp, objv[cmdIndex], nsPtr);
|
||||
if (cmd == NULL) {
|
||||
/* punt this case! */
|
||||
Tcl_AppendObjToObj(obj2Ptr, objv[cmdIndex]);
|
||||
} else {
|
||||
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
|
||||
/* TODO: overflow? */
|
||||
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-offset, objv+offset);
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
|
||||
|
||||
result = Tcl_EvalObjv(interp, objc-cmdIndex, objs, TCL_EVAL_INVOKE);
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -805,8 +871,8 @@ TclOODefineObjCmd(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Foundation *fPtr = TclOOGetFoundation(interp);
|
||||
int result;
|
||||
Object *oPtr;
|
||||
int result;
|
||||
|
||||
if (objc < 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "className arg ?arg ...?");
|
||||
@@ -846,46 +912,7 @@ TclOODefineObjCmd(
|
||||
}
|
||||
TclDecrRefCount(objNameObj);
|
||||
} else {
|
||||
Tcl_Obj *objPtr, *obj2Ptr, **objs;
|
||||
Tcl_Command cmd;
|
||||
int isRoot, dummy;
|
||||
|
||||
/*
|
||||
* More than one argument: fire them through the ensemble processing
|
||||
* engine so that everything appears to be good and proper in error
|
||||
* messages. Note that we cannot just concatenate and send through
|
||||
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we
|
||||
* cannot go through Tcl_EvalObjv without the extra work to pre-find
|
||||
* the command, as that finds command names in the wrong namespace at
|
||||
* the moment. Ugly!
|
||||
*/
|
||||
|
||||
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
|
||||
|
||||
/*
|
||||
* Build the list of arguments using a Tcl_Obj as a workspace. See
|
||||
* comments above for why these contortions are necessary.
|
||||
*/
|
||||
|
||||
objPtr = Tcl_NewObj();
|
||||
obj2Ptr = Tcl_NewObj();
|
||||
cmd = FindCommand(interp, objv[2], fPtr->defineNs);
|
||||
if (cmd == NULL) {
|
||||
/* punt this case! */
|
||||
Tcl_AppendObjToObj(obj2Ptr, objv[2]);
|
||||
} else {
|
||||
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
|
||||
/* TODO: overflow? */
|
||||
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-3, objv+3);
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
|
||||
|
||||
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
result = MagicDefinitionInvoke(interp, fPtr->defineNs, 2, objc, objv);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
|
||||
@@ -918,8 +945,8 @@ TclOOObjDefObjCmd(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Foundation *fPtr = TclOOGetFoundation(interp);
|
||||
int isRoot, result;
|
||||
Object *oPtr;
|
||||
int result;
|
||||
|
||||
if (objc < 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "objectName arg ?arg ...?");
|
||||
@@ -952,47 +979,7 @@ TclOOObjDefObjCmd(
|
||||
}
|
||||
TclDecrRefCount(objNameObj);
|
||||
} else {
|
||||
Tcl_Obj *objPtr, *obj2Ptr, **objs;
|
||||
Tcl_Command cmd;
|
||||
int dummy;
|
||||
|
||||
/*
|
||||
* More than one argument: fire them through the ensemble processing
|
||||
* engine so that everything appears to be good and proper in error
|
||||
* messages. Note that we cannot just concatenate and send through
|
||||
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we
|
||||
* cannot go through Tcl_EvalObjv without the extra work to pre-find
|
||||
* the command, as that finds command names in the wrong namespace at
|
||||
* the moment. Ugly!
|
||||
*/
|
||||
|
||||
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
|
||||
|
||||
/*
|
||||
* Build the list of arguments using a Tcl_Obj as a workspace. See
|
||||
* comments above for why these contortions are necessary.
|
||||
*/
|
||||
|
||||
objPtr = Tcl_NewObj();
|
||||
obj2Ptr = Tcl_NewObj();
|
||||
cmd = FindCommand(interp, objv[2], fPtr->objdefNs);
|
||||
if (cmd == NULL) {
|
||||
/* punt this case! */
|
||||
Tcl_AppendObjToObj(obj2Ptr, objv[2]);
|
||||
} else {
|
||||
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
|
||||
/* TODO: overflow? */
|
||||
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-3, objv+3);
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
|
||||
|
||||
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
|
||||
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 2, objc, objv);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
|
||||
@@ -1025,19 +1012,19 @@ TclOODefineSelfObjCmd(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Foundation *fPtr = TclOOGetFoundation(interp);
|
||||
int result;
|
||||
Object *oPtr;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
int result;
|
||||
|
||||
oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the oo::objdefine namespace the current namespace and evaluate the
|
||||
* command(s).
|
||||
@@ -1059,46 +1046,7 @@ TclOODefineSelfObjCmd(
|
||||
}
|
||||
TclDecrRefCount(objNameObj);
|
||||
} else {
|
||||
Tcl_Obj *objPtr, *obj2Ptr, **objs;
|
||||
Tcl_Command cmd;
|
||||
int isRoot, dummy;
|
||||
|
||||
/*
|
||||
* More than one argument: fire them through the ensemble processing
|
||||
* engine so that everything appears to be good and proper in error
|
||||
* messages. Note that we cannot just concatenate and send through
|
||||
* Tcl_EvalObjEx, as that doesn't do ensemble processing, and we
|
||||
* cannot go through Tcl_EvalObjv without the extra work to pre-find
|
||||
* the command, as that finds command names in the wrong namespace at
|
||||
* the moment. Ugly!
|
||||
*/
|
||||
|
||||
isRoot = TclInitRewriteEnsemble(interp, 2, 1, objv);
|
||||
|
||||
/*
|
||||
* Build the list of arguments using a Tcl_Obj as a workspace. See
|
||||
* comments above for why these contortions are necessary.
|
||||
*/
|
||||
|
||||
objPtr = Tcl_NewObj();
|
||||
obj2Ptr = Tcl_NewObj();
|
||||
cmd = FindCommand(interp, objv[1], fPtr->objdefNs);
|
||||
if (cmd == NULL) {
|
||||
/* punt this case! */
|
||||
Tcl_AppendObjToObj(obj2Ptr, objv[1]);
|
||||
} else {
|
||||
Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
|
||||
/* TODO: overflow? */
|
||||
Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-2, objv+2);
|
||||
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
|
||||
|
||||
result = Tcl_EvalObjv(interp, objc-1, objs, TCL_EVAL_INVOKE);
|
||||
if (isRoot) {
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
}
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 1, objc, objv);
|
||||
}
|
||||
DelRef(oPtr);
|
||||
|
||||
@@ -1110,6 +1058,39 @@ TclOODefineSelfObjCmd(
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefineObjSelfObjCmd --
|
||||
* Implementation of the "self" subcommand of the "oo::objdefine"
|
||||
* command.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclOODefineObjSelfObjCmd(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr;
|
||||
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
@@ -431,6 +431,9 @@ MODULE_SCOPE int TclOODefineClassObjCmd(ClientData clientData,
|
||||
MODULE_SCOPE int TclOODefineSelfObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
MODULE_SCOPE int TclOODefineObjSelfObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
MODULE_SCOPE int TclOOUnknownDefinition(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
|
||||
+25
-22
@@ -75,7 +75,7 @@ typedef struct ObjData {
|
||||
* The structure defined below is used in this file only.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
Tcl_HashTable *lineCLPtr; /* This table remembers for each Tcl_Obj
|
||||
* generated by a call to the function
|
||||
* TclSubstTokens() from a literal text
|
||||
@@ -344,17 +344,17 @@ typedef struct ResolvedCmdName {
|
||||
* reference (not the namespace that contains
|
||||
* the referenced command). NULL if the name
|
||||
* is fully qualified.*/
|
||||
long refNsId; /* refNsPtr's unique namespace id. Used to
|
||||
size_t 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). */
|
||||
int refNsCmdEpoch; /* Value of the referencing namespace's
|
||||
size_t 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. */
|
||||
int cmdEpoch; /* Value of the command's cmdEpoch when this
|
||||
size_t 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,
|
||||
@@ -1732,7 +1732,7 @@ Tcl_InvalidateStringRep(
|
||||
* is coerced to 1.
|
||||
*
|
||||
* When TCL_MEM_DEBUG is defined, this function just returns the result
|
||||
* of calling the debugging version Tcl_DbNewBooleanObj.
|
||||
* of calling the debugging version Tcl_DbNewLongObj.
|
||||
*
|
||||
* Results:
|
||||
* The newly created object is returned. This object will have an invalid
|
||||
@@ -1751,7 +1751,7 @@ Tcl_Obj *
|
||||
Tcl_NewBooleanObj(
|
||||
register int boolValue) /* Boolean used to initialize new object. */
|
||||
{
|
||||
return Tcl_DbNewBooleanObj(boolValue, "unknown", 0);
|
||||
return Tcl_DbNewLongObj(boolValue!=0, "unknown", 0);
|
||||
}
|
||||
|
||||
#else /* if not TCL_MEM_DEBUG */
|
||||
@@ -1762,7 +1762,7 @@ Tcl_NewBooleanObj(
|
||||
{
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclNewBooleanObj(objPtr, boolValue);
|
||||
TclNewLongObj(objPtr, boolValue!=0);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
@@ -1793,6 +1793,7 @@ Tcl_NewBooleanObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_DbNewBooleanObj
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
@@ -1856,8 +1857,9 @@ Tcl_SetBooleanObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj");
|
||||
}
|
||||
|
||||
TclSetBooleanObj(objPtr, boolValue);
|
||||
TclSetLongObj(objPtr, boolValue!=0);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2458,7 +2460,7 @@ Tcl_SetIntObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetIntObj");
|
||||
}
|
||||
|
||||
TclSetIntObj(objPtr, intValue);
|
||||
TclSetLongObj(objPtr, intValue);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3036,7 +3038,7 @@ Tcl_SetWideIntObj(
|
||||
#else
|
||||
mp_int big;
|
||||
|
||||
TclBNInitBignumFromWideInt(&big, wideValue);
|
||||
TclInitBignumFromWideInt(&big, wideValue);
|
||||
Tcl_SetBignumObj(objPtr, &big);
|
||||
#endif
|
||||
}
|
||||
@@ -3400,12 +3402,12 @@ GetBignumFromObj(
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objPtr->typePtr == &tclIntType) {
|
||||
TclBNInitBignumFromLong(bignumValue, objPtr->internalRep.longValue);
|
||||
TclInitBignumFromLong(bignumValue, objPtr->internalRep.longValue);
|
||||
return TCL_OK;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (objPtr->typePtr == &tclWideIntType) {
|
||||
TclBNInitBignumFromWideInt(bignumValue,
|
||||
TclInitBignumFromWideInt(bignumValue,
|
||||
objPtr->internalRep.wideValue);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -4453,7 +4455,6 @@ Tcl_RepresentationCmd(
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
char ptrBuffer[2*TCL_INTEGER_SPACE+6];
|
||||
Tcl_Obj *descObj;
|
||||
|
||||
if (objc != 2) {
|
||||
@@ -4467,18 +4468,20 @@ Tcl_RepresentationCmd(
|
||||
* "1872361827361287"
|
||||
*/
|
||||
|
||||
sprintf(ptrBuffer, "%p", (void *) objv[1]);
|
||||
descObj = Tcl_ObjPrintf("value is a %s with a refcount of %d,"
|
||||
" object pointer at %s",
|
||||
objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
|
||||
objv[1]->refCount, ptrBuffer);
|
||||
" object pointer at %p",
|
||||
objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
|
||||
objv[1]->refCount, objv[1]);
|
||||
|
||||
if (objv[1]->typePtr) {
|
||||
sprintf(ptrBuffer, "%p:%p",
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr1,
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr2);
|
||||
Tcl_AppendPrintfToObj(descObj, ", internal representation %s",
|
||||
ptrBuffer);
|
||||
if (objv[1]->typePtr == &tclDoubleType) {
|
||||
Tcl_AppendPrintfToObj(descObj, ", internal representation %g",
|
||||
objv[1]->internalRep.doubleValue);
|
||||
} else {
|
||||
Tcl_AppendPrintfToObj(descObj, ", internal representation %p:%p",
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr1,
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr2);
|
||||
}
|
||||
}
|
||||
|
||||
if (objv[1]->bytes) {
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ Tcl_PanicVA(
|
||||
__builtin_trap();
|
||||
# elif defined(_WIN64)
|
||||
__debugbreak();
|
||||
# elif defined(_MSC_VER)
|
||||
# elif defined(_MSC_VER) && defined (_M_IX86)
|
||||
_asm {int 3}
|
||||
# else
|
||||
DebugBreak();
|
||||
|
||||
+16
-4
@@ -829,7 +829,7 @@ TclParseBackslash(
|
||||
* written there. */
|
||||
{
|
||||
register const char *p = src+1;
|
||||
Tcl_UniChar unichar;
|
||||
Tcl_UniChar unichar = 0;
|
||||
int result;
|
||||
int count;
|
||||
char buf[TCL_UTF_MAX];
|
||||
@@ -963,13 +963,13 @@ TclParseBackslash(
|
||||
*/
|
||||
|
||||
if (Tcl_UtfCharComplete(p, numBytes - 1)) {
|
||||
count = Tcl_UtfToUniChar(p, &unichar) + 1; /* +1 for '\' */
|
||||
count = TclUtfToUniChar(p, &unichar) + 1; /* +1 for '\' */
|
||||
} else {
|
||||
char utfBytes[TCL_UTF_MAX];
|
||||
|
||||
memcpy(utfBytes, p, (size_t) (numBytes - 1));
|
||||
utfBytes[numBytes - 1] = '\0';
|
||||
count = Tcl_UtfToUniChar(utfBytes, &unichar) + 1;
|
||||
count = TclUtfToUniChar(utfBytes, &unichar) + 1;
|
||||
}
|
||||
result = unichar;
|
||||
break;
|
||||
@@ -979,6 +979,15 @@ TclParseBackslash(
|
||||
if (readPtr != NULL) {
|
||||
*readPtr = count;
|
||||
}
|
||||
if ((result & 0xF800) == 0xD800) {
|
||||
/* If result is a surrogate, Tcl_UniCharToUtf will try to
|
||||
* handle that especially, but we don't want that here.
|
||||
*/
|
||||
dst[2] = (char) ((result | 0x80) & 0xBF);
|
||||
dst[1] = (char) (((result >> 6) | 0x80) & 0xBF);
|
||||
dst[0] = (char) ((result >> 12) | 0xE0);
|
||||
return 3;
|
||||
}
|
||||
return Tcl_UniCharToUtf(result, dst);
|
||||
}
|
||||
|
||||
@@ -1169,6 +1178,8 @@ ParseTokens(
|
||||
numBytes--;
|
||||
nestedPtr = TclStackAlloc(parsePtr->interp, sizeof(Tcl_Parse));
|
||||
while (1) {
|
||||
const char *curEnd;
|
||||
|
||||
if (Tcl_ParseCommand(parsePtr->interp, src, numBytes, 1,
|
||||
nestedPtr) != TCL_OK) {
|
||||
parsePtr->errorType = nestedPtr->errorType;
|
||||
@@ -1177,8 +1188,9 @@ ParseTokens(
|
||||
TclStackFree(parsePtr->interp, nestedPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
curEnd = src + numBytes;
|
||||
src = nestedPtr->commandStart + nestedPtr->commandSize;
|
||||
numBytes = parsePtr->end - src;
|
||||
numBytes = curEnd - src;
|
||||
Tcl_FreeParse(nestedPtr);
|
||||
|
||||
/*
|
||||
|
||||
+48
-33
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclFileSystem.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Prototypes for functions defined later in this file.
|
||||
@@ -849,18 +850,20 @@ TclJoinPath(
|
||||
int elements,
|
||||
Tcl_Obj * const objv[])
|
||||
{
|
||||
Tcl_Obj *res;
|
||||
Tcl_Obj *res = NULL;
|
||||
int i;
|
||||
const Tcl_Filesystem *fsPtr = NULL;
|
||||
|
||||
res = NULL;
|
||||
assert ( elements >= 0 );
|
||||
|
||||
for (i = 0; i < elements; i++) {
|
||||
int driveNameLength, strEltLen, length;
|
||||
Tcl_PathType type;
|
||||
char *strElt, *ptr;
|
||||
Tcl_Obj *driveName = NULL;
|
||||
Tcl_Obj *elt = objv[i];
|
||||
if (elements == 0) {
|
||||
return Tcl_NewObj();
|
||||
}
|
||||
|
||||
assert ( elements > 0 );
|
||||
|
||||
if (elements == 2) {
|
||||
Tcl_Obj *elt = objv[0];
|
||||
|
||||
/*
|
||||
* This is a special case where we can be much more efficient, where
|
||||
@@ -869,18 +872,17 @@ TclJoinPath(
|
||||
* object which can be normalized more efficiently. Currently we only
|
||||
* use the special case when we have exactly two elements, but we
|
||||
* could expand that in the future.
|
||||
*
|
||||
* Bugfix [a47641a0]. TclNewFSPathObj requires first argument
|
||||
* to be an absolute path. Added a check for that elt is absolute.
|
||||
*
|
||||
* Bugfix [a47641a0]. TclNewFSPathObj requires first argument
|
||||
* to be an absolute path. Added a check for that elt is absolute.
|
||||
*/
|
||||
|
||||
if ((i == (elements-2)) && (i == 0)
|
||||
&& (elt->typePtr == &tclFsPathType)
|
||||
if ((elt->typePtr == &tclFsPathType)
|
||||
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
|
||||
&& TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
|
||||
Tcl_Obj *tailObj = objv[i+1];
|
||||
Tcl_Obj *tailObj = objv[1];
|
||||
Tcl_PathType type = TclGetPathType(tailObj, NULL, NULL, NULL);
|
||||
|
||||
type = TclGetPathType(tailObj, NULL, NULL, NULL);
|
||||
if (type == TCL_PATH_RELATIVE) {
|
||||
const char *str;
|
||||
int len;
|
||||
@@ -893,9 +895,6 @@ TclJoinPath(
|
||||
* the base itself is just fine!
|
||||
*/
|
||||
|
||||
if (res != NULL) {
|
||||
TclDecrRefCount(res);
|
||||
}
|
||||
return elt;
|
||||
}
|
||||
|
||||
@@ -918,10 +917,17 @@ TclJoinPath(
|
||||
|
||||
if ((tclPlatform != TCL_PLATFORM_WINDOWS)
|
||||
|| (strchr(Tcl_GetString(elt), '\\') == NULL)) {
|
||||
if (res != NULL) {
|
||||
TclDecrRefCount(res);
|
||||
|
||||
if (PATHFLAGS(elt)) {
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
}
|
||||
if (TCL_PATH_ABSOLUTE != Tcl_FSGetPathType(elt)) {
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
}
|
||||
(void) Tcl_FSGetNormalizedPath(NULL, elt);
|
||||
if (elt == PATHOBJ(elt)->normPathPtr) {
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
}
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,24 +936,30 @@ TclJoinPath(
|
||||
* more general code below handle things.
|
||||
*/
|
||||
} else if (tclPlatform == TCL_PLATFORM_UNIX) {
|
||||
if (res != NULL) {
|
||||
TclDecrRefCount(res);
|
||||
}
|
||||
return tailObj;
|
||||
} else {
|
||||
const char *str = TclGetString(tailObj);
|
||||
|
||||
if (tclPlatform == TCL_PLATFORM_WINDOWS) {
|
||||
if (strchr(str, '\\') == NULL) {
|
||||
if (res != NULL) {
|
||||
TclDecrRefCount(res);
|
||||
}
|
||||
return tailObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert ( res == NULL );
|
||||
|
||||
for (i = 0; i < elements; i++) {
|
||||
int driveNameLength, strEltLen, length;
|
||||
Tcl_PathType type;
|
||||
char *strElt, *ptr;
|
||||
Tcl_Obj *driveName = NULL;
|
||||
Tcl_Obj *elt = objv[i];
|
||||
|
||||
strElt = TclGetStringFromObj(elt, &strEltLen);
|
||||
driveNameLength = 0;
|
||||
type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
|
||||
if (type != TCL_PATH_RELATIVE) {
|
||||
/*
|
||||
@@ -1003,6 +1015,12 @@ TclJoinPath(
|
||||
}
|
||||
}
|
||||
ptr = strElt;
|
||||
/* [Bug f34cf83dd0] */
|
||||
if (driveNameLength > 0) {
|
||||
if (ptr[0] == '/' && ptr[-1] == '/') {
|
||||
goto noQuickReturn;
|
||||
}
|
||||
}
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr == '/' && (ptr[1] == '/' || ptr[1] == '\0')) {
|
||||
/*
|
||||
@@ -1034,10 +1052,8 @@ TclJoinPath(
|
||||
noQuickReturn:
|
||||
if (res == NULL) {
|
||||
res = Tcl_NewObj();
|
||||
ptr = TclGetStringFromObj(res, &length);
|
||||
} else {
|
||||
ptr = TclGetStringFromObj(res, &length);
|
||||
}
|
||||
ptr = TclGetStringFromObj(res, &length);
|
||||
|
||||
/*
|
||||
* Strip off any './' before a tilde, unless this is the beginning of
|
||||
@@ -1070,6 +1086,7 @@ TclJoinPath(
|
||||
|
||||
if (sep != NULL) {
|
||||
separator = TclGetString(sep)[0];
|
||||
TclDecrRefCount(sep);
|
||||
}
|
||||
/* Safety check in case the VFS driver caused sharing */
|
||||
if (Tcl_IsShared(res)) {
|
||||
@@ -1105,9 +1122,7 @@ TclJoinPath(
|
||||
Tcl_SetObjLength(res, length);
|
||||
}
|
||||
}
|
||||
if (res == NULL) {
|
||||
res = Tcl_NewObj();
|
||||
}
|
||||
assert ( res != NULL );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -668,7 +668,13 @@ TclCreatePipeline(
|
||||
if (*p == '>') {
|
||||
p++;
|
||||
atOK = 0;
|
||||
flags = O_WRONLY | O_CREAT;
|
||||
|
||||
/*
|
||||
* Note that the O_APPEND flag only has an effect on POSIX
|
||||
* platforms. On Windows, we just have to carry on regardless.
|
||||
*/
|
||||
|
||||
flags = O_WRONLY | O_CREAT | O_APPEND;
|
||||
}
|
||||
if (errorClose != 0) {
|
||||
errorClose = 0;
|
||||
|
||||
+24
-12
@@ -32,6 +32,7 @@ typedef struct PkgAvail {
|
||||
char *script; /* Script to invoke to provide this version of
|
||||
* the package. Malloc'ed and protected by
|
||||
* Tcl_Preserve and Tcl_Release. */
|
||||
char *pkgIndex; /* Full file name of pkgIndex file */
|
||||
struct PkgAvail *nextPtr; /* Next in list of available versions of the
|
||||
* same package. */
|
||||
} PkgAvail;
|
||||
@@ -223,6 +224,7 @@ static void PkgFilesCleanupProc(ClientData clientData,
|
||||
entry = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
Tcl_DeleteHashTable(&pkgFiles->table);
|
||||
ckfree(pkgFiles);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -329,8 +331,8 @@ Tcl_PkgRequireEx(
|
||||
*
|
||||
* Second, how does this work? If we reach this point, then the global
|
||||
* variable tclEmptyStringRep has the value NULL. Compare that with
|
||||
* the definition of tclEmptyStringRep near the top of the file
|
||||
* generic/tclObj.c. It clearly should not have the value NULL; it
|
||||
* the definition of tclEmptyStringRep near the top of this file.
|
||||
* It clearly should not have the value NULL; it
|
||||
* should point to the char tclEmptyString. If we see it having the
|
||||
* value NULL, then somehow we are seeing a Tcl library that isn't
|
||||
* completely initialized, and that's an indicator for the error
|
||||
@@ -346,18 +348,11 @@ Tcl_PkgRequireEx(
|
||||
* After all, two Tcl libraries can't be a good thing!)
|
||||
*
|
||||
* Trouble is that's going to be tricky. We're now using a Tcl library
|
||||
* that's not fully initialized. In particular, it doesn't have a
|
||||
* proper value for tclEmptyStringRep. The Tcl_Obj system heavily
|
||||
* depends on the value of tclEmptyStringRep and all of Tcl depends
|
||||
* (increasingly) on the Tcl_Obj system, we need to correct that flaw
|
||||
* before making the calls to set the interpreter result to the error
|
||||
* message. That's the only flaw corrected; other problems with
|
||||
* initialization of the Tcl library are not remedied, so be very
|
||||
* careful about adding any other calls here without checking how they
|
||||
* behave when initialization is incomplete.
|
||||
* that's not fully initialized. Functions in it may not work
|
||||
* reliably, so be very careful about adding any other calls here
|
||||
* without checking how they behave when initialization is incomplete.
|
||||
*/
|
||||
|
||||
tclEmptyStringRep = &tclEmptyString;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"Cannot load package \"%s\" in standalone executable:"
|
||||
" This package is not compiled with stub support", name));
|
||||
@@ -573,6 +568,9 @@ PkgRequireCore(
|
||||
pkgName->nextPtr = pkgFiles->names;
|
||||
strcpy(pkgName->name, name);
|
||||
pkgFiles->names = pkgName;
|
||||
if (bestPtr->pkgIndex) {
|
||||
TclPkgFileSeen(interp, bestPtr->pkgIndex);
|
||||
}
|
||||
code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);
|
||||
/* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/
|
||||
pkgFiles->names = pkgName->nextPtr;
|
||||
@@ -921,6 +919,9 @@ Tcl_PackageObjCmd(
|
||||
pkgPtr->availPtr = availPtr->nextPtr;
|
||||
Tcl_EventuallyFree(availPtr->version, TCL_DYNAMIC);
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
}
|
||||
ckfree(availPtr);
|
||||
}
|
||||
ckfree(pkgPtr);
|
||||
@@ -971,6 +972,9 @@ Tcl_PackageObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -981,6 +985,7 @@ Tcl_PackageObjCmd(
|
||||
}
|
||||
if (availPtr == NULL) {
|
||||
availPtr = ckalloc(sizeof(PkgAvail));
|
||||
availPtr->pkgIndex = 0;
|
||||
DupBlock(availPtr->version, argv3, (unsigned) length + 1);
|
||||
|
||||
if (prevPtr == NULL) {
|
||||
@@ -991,6 +996,10 @@ Tcl_PackageObjCmd(
|
||||
prevPtr->nextPtr = availPtr;
|
||||
}
|
||||
}
|
||||
if (iPtr->scriptFile) {
|
||||
argv4 = TclGetStringFromObj(iPtr->scriptFile, &length);
|
||||
DupBlock(availPtr->pkgIndex, argv4, (unsigned) length + 1);
|
||||
}
|
||||
argv4 = TclGetStringFromObj(objv[4], &length);
|
||||
DupBlock(availPtr->script, argv4, (unsigned) length + 1);
|
||||
break;
|
||||
@@ -1346,6 +1355,9 @@ TclFreePackageInfo(
|
||||
pkgPtr->availPtr = availPtr->nextPtr;
|
||||
Tcl_EventuallyFree(availPtr->version, TCL_DYNAMIC);
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
}
|
||||
ckfree(availPtr);
|
||||
}
|
||||
ckfree(pkgPtr);
|
||||
|
||||
@@ -155,7 +155,7 @@ Tcl_Preserve(
|
||||
refPtr->clientData = clientData;
|
||||
refPtr->refCount = 1;
|
||||
refPtr->mustFree = 0;
|
||||
refPtr->freeProc = TCL_STATIC;
|
||||
refPtr->freeProc = 0;
|
||||
inUse += 1;
|
||||
Tcl_MutexUnlock(&preserveMutex);
|
||||
}
|
||||
|
||||
@@ -2749,6 +2749,41 @@ MakeLambdaError(
|
||||
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclGetCmdFrameForProcedure --
|
||||
*
|
||||
* How to get the CmdFrame information for a procedure.
|
||||
*
|
||||
* Results:
|
||||
* A pointer to the CmdFrame (only guaranteed to be valid until the next
|
||||
* Tcl command is processed or the interpreter's state is otherwise
|
||||
* modified) or a NULL if the information is not available.
|
||||
*
|
||||
* Side effects:
|
||||
* none.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
CmdFrame *
|
||||
TclGetCmdFrameForProcedure(
|
||||
Proc *procPtr) /* The procedure whose cmd-frame is to be
|
||||
* looked up. */
|
||||
{
|
||||
Tcl_HashEntry *hePtr;
|
||||
|
||||
if (procPtr == NULL || procPtr->iPtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
hePtr = Tcl_FindHashEntry(procPtr->iPtr->linePBodyPtr, procPtr);
|
||||
if (hePtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return (CmdFrame *) Tcl_GetHashValue(hePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@
|
||||
|
||||
#define NUM_REGEXPS 30
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
int initialized; /* Set to 1 when the module is initialized. */
|
||||
char *patterns[NUM_REGEXPS];/* Strings corresponding to compiled regular
|
||||
* expression patterns. NULL means that this
|
||||
@@ -679,7 +679,7 @@ TclRegAbout(
|
||||
|
||||
resultObj = Tcl_NewObj();
|
||||
Tcl_ListObjAppendElement(NULL, resultObj,
|
||||
Tcl_NewIntObj((int) regexpPtr->re.re_nsub));
|
||||
Tcl_NewWideIntObj((Tcl_WideInt) regexpPtr->re.re_nsub));
|
||||
|
||||
/*
|
||||
* Now append a list of all the bit-flags set for the RE.
|
||||
|
||||
+1
-1
@@ -232,6 +232,7 @@ Tcl_DiscardInterpState(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_SaveResult
|
||||
void
|
||||
Tcl_SaveResult(
|
||||
@@ -409,7 +410,6 @@ Tcl_DiscardResult(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
void
|
||||
Tcl_SetResult(
|
||||
Tcl_Interp *interp, /* Interpreter with which to associate the
|
||||
|
||||
+43
-37
@@ -72,17 +72,17 @@ BuildCharSet(
|
||||
CharSet *cset,
|
||||
const char *format) /* Points to first char of set. */
|
||||
{
|
||||
Tcl_UniChar ch, start;
|
||||
Tcl_UniChar ch = 0, start;
|
||||
int offset, nranges;
|
||||
const char *end;
|
||||
|
||||
memset(cset, 0, sizeof(CharSet));
|
||||
|
||||
offset = Tcl_UtfToUniChar(format, &ch);
|
||||
offset = TclUtfToUniChar(format, &ch);
|
||||
if (ch == '^') {
|
||||
cset->exclude = 1;
|
||||
format += offset;
|
||||
offset = Tcl_UtfToUniChar(format, &ch);
|
||||
offset = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
end = format + offset;
|
||||
|
||||
@@ -91,14 +91,14 @@ BuildCharSet(
|
||||
*/
|
||||
|
||||
if (ch == ']') {
|
||||
end += Tcl_UtfToUniChar(end, &ch);
|
||||
end += TclUtfToUniChar(end, &ch);
|
||||
}
|
||||
nranges = 0;
|
||||
while (ch != ']') {
|
||||
if (ch == '-') {
|
||||
nranges++;
|
||||
}
|
||||
end += Tcl_UtfToUniChar(end, &ch);
|
||||
end += TclUtfToUniChar(end, &ch);
|
||||
}
|
||||
|
||||
cset->chars = ckalloc(sizeof(Tcl_UniChar) * (end - format - 1));
|
||||
@@ -113,11 +113,11 @@ BuildCharSet(
|
||||
*/
|
||||
|
||||
cset->nchars = cset->nranges = 0;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
start = ch;
|
||||
if (ch == ']' || ch == '-') {
|
||||
cset->chars[cset->nchars++] = ch;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
while (ch != ']') {
|
||||
if (*format == '-') {
|
||||
@@ -138,7 +138,7 @@ BuildCharSet(
|
||||
cset->chars[cset->nchars++] = start;
|
||||
cset->chars[cset->nchars++] = ch;
|
||||
} else {
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
|
||||
/*
|
||||
* Check to see if the range is in reverse order.
|
||||
@@ -156,7 +156,7 @@ BuildCharSet(
|
||||
} else {
|
||||
cset->chars[cset->nchars++] = ch;
|
||||
}
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
@@ -257,7 +257,7 @@ ValidateFormat(
|
||||
{
|
||||
int gotXpg, gotSequential, value, i, flags;
|
||||
char *end;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
int objIndex, xpgSize, nspace = numVars;
|
||||
int *nassign = TclStackAlloc(interp, nspace * sizeof(int));
|
||||
char buf[TCL_UTF_MAX+1];
|
||||
@@ -279,20 +279,20 @@ ValidateFormat(
|
||||
xpgSize = objIndex = gotXpg = gotSequential = 0;
|
||||
|
||||
while (*format != '\0') {
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
|
||||
flags = 0;
|
||||
|
||||
if (ch != '%') {
|
||||
continue;
|
||||
}
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
if (ch == '%') {
|
||||
continue;
|
||||
}
|
||||
if (ch == '*') {
|
||||
flags |= SCAN_SUPPRESS;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
goto xpgCheckDone;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ ValidateFormat(
|
||||
goto notXpg;
|
||||
}
|
||||
format = end+1;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
gotXpg = 1;
|
||||
if (gotSequential) {
|
||||
goto mixedXPG;
|
||||
@@ -347,7 +347,7 @@ ValidateFormat(
|
||||
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
|
||||
value = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */
|
||||
flags |= SCAN_WIDTH;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -359,13 +359,13 @@ ValidateFormat(
|
||||
if (*format == 'l') {
|
||||
flags |= SCAN_BIG;
|
||||
format += 1;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
break;
|
||||
}
|
||||
case 'L':
|
||||
flags |= SCAN_LONGER;
|
||||
case 'h':
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
|
||||
if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) {
|
||||
@@ -434,24 +434,24 @@ ValidateFormat(
|
||||
if (*format == '\0') {
|
||||
goto badSet;
|
||||
}
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
if (ch == '^') {
|
||||
if (*format == '\0') {
|
||||
goto badSet;
|
||||
}
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
if (ch == ']') {
|
||||
if (*format == '\0') {
|
||||
goto badSet;
|
||||
}
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
while (ch != ']') {
|
||||
if (*format == '\0') {
|
||||
goto badSet;
|
||||
}
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
break;
|
||||
badSet:
|
||||
@@ -582,7 +582,7 @@ Tcl_ScanObjCmd(
|
||||
char op = 0;
|
||||
int width, underflow = 0;
|
||||
Tcl_WideInt wideValue;
|
||||
Tcl_UniChar ch, sch;
|
||||
Tcl_UniChar ch = 0, sch = 0;
|
||||
Tcl_Obj **objs = NULL, *objPtr = NULL;
|
||||
int flags;
|
||||
char buf[513]; /* Temporary buffer to hold scanned number
|
||||
@@ -630,7 +630,7 @@ Tcl_ScanObjCmd(
|
||||
nconversions = 0;
|
||||
while (*format != '\0') {
|
||||
int parseFlag = TCL_PARSE_NO_WHITESPACE;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
|
||||
flags = 0;
|
||||
|
||||
@@ -639,13 +639,13 @@ Tcl_ScanObjCmd(
|
||||
*/
|
||||
|
||||
if (Tcl_UniCharIsSpace(ch)) {
|
||||
offset = Tcl_UtfToUniChar(string, &sch);
|
||||
offset = TclUtfToUniChar(string, &sch);
|
||||
while (Tcl_UniCharIsSpace(sch)) {
|
||||
if (*string == '\0') {
|
||||
goto done;
|
||||
}
|
||||
string += offset;
|
||||
offset = Tcl_UtfToUniChar(string, &sch);
|
||||
offset = TclUtfToUniChar(string, &sch);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -656,14 +656,14 @@ Tcl_ScanObjCmd(
|
||||
underflow = 1;
|
||||
goto done;
|
||||
}
|
||||
string += Tcl_UtfToUniChar(string, &sch);
|
||||
string += TclUtfToUniChar(string, &sch);
|
||||
if (ch != sch) {
|
||||
goto done;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
if (ch == '%') {
|
||||
goto literal;
|
||||
}
|
||||
@@ -675,13 +675,13 @@ Tcl_ScanObjCmd(
|
||||
|
||||
if (ch == '*') {
|
||||
flags |= SCAN_SUPPRESS;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
} else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
|
||||
char *formatEnd;
|
||||
value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */
|
||||
if (*formatEnd == '$') {
|
||||
format = formatEnd+1;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
objIndex = (int) value - 1;
|
||||
}
|
||||
}
|
||||
@@ -692,7 +692,7 @@ Tcl_ScanObjCmd(
|
||||
|
||||
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
|
||||
width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
} else {
|
||||
width = 0;
|
||||
}
|
||||
@@ -706,7 +706,7 @@ Tcl_ScanObjCmd(
|
||||
if (*format == 'l') {
|
||||
flags |= SCAN_BIG;
|
||||
format += 1;
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
break;
|
||||
}
|
||||
case 'L':
|
||||
@@ -715,7 +715,7 @@ Tcl_ScanObjCmd(
|
||||
* Fall through so we skip to the next character.
|
||||
*/
|
||||
case 'h':
|
||||
format += Tcl_UtfToUniChar(format, &ch);
|
||||
format += TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -799,7 +799,7 @@ Tcl_ScanObjCmd(
|
||||
|
||||
if (!(flags & SCAN_NOSKIP)) {
|
||||
while (*string != '\0') {
|
||||
offset = Tcl_UtfToUniChar(string, &sch);
|
||||
offset = TclUtfToUniChar(string, &sch);
|
||||
if (!Tcl_UniCharIsSpace(sch)) {
|
||||
break;
|
||||
}
|
||||
@@ -826,7 +826,7 @@ Tcl_ScanObjCmd(
|
||||
}
|
||||
end = string;
|
||||
while (*end != '\0') {
|
||||
offset = Tcl_UtfToUniChar(end, &sch);
|
||||
offset = TclUtfToUniChar(end, &sch);
|
||||
if (Tcl_UniCharIsSpace(sch)) {
|
||||
break;
|
||||
}
|
||||
@@ -854,7 +854,7 @@ Tcl_ScanObjCmd(
|
||||
|
||||
format = BuildCharSet(&cset, format);
|
||||
while (*end != '\0') {
|
||||
offset = Tcl_UtfToUniChar(end, &sch);
|
||||
offset = TclUtfToUniChar(end, &sch);
|
||||
if (!CharInSet(&cset, (int)sch)) {
|
||||
break;
|
||||
}
|
||||
@@ -885,9 +885,15 @@ Tcl_ScanObjCmd(
|
||||
* Scan a single Unicode character.
|
||||
*/
|
||||
|
||||
string += Tcl_UtfToUniChar(string, &sch);
|
||||
offset = TclUtfToUniChar(string, &sch);
|
||||
i = (int)sch;
|
||||
if (!offset) {
|
||||
offset = Tcl_UtfToUniChar(string, &sch);
|
||||
i = (((i<<10) & 0x0FFC00) + 0x10000) + (sch & 0x3FF);
|
||||
}
|
||||
string += offset;
|
||||
if (!(flags & SCAN_SUPPRESS)) {
|
||||
objPtr = Tcl_NewIntObj((int)sch);
|
||||
objPtr = Tcl_NewIntObj(i);
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
CLANG_ASSERT(objs);
|
||||
objs[objIndex++] = objPtr;
|
||||
|
||||
@@ -0,0 +1,527 @@
|
||||
/*
|
||||
* tclStrIdxTree.c --
|
||||
*
|
||||
* Contains the routines for managing string index tries in Tcl.
|
||||
*
|
||||
* This code is back-ported from the tclSE engine, by Serg G. Brester.
|
||||
*
|
||||
* Copyright (c) 2016 by Sergey G. Brester aka sebres. All rights reserved.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* String index tries are prepaired structures used for fast greedy search of the string
|
||||
* (index) by unique string prefix as key.
|
||||
*
|
||||
* Index tree build for two lists together can be explained in the following datagram
|
||||
*
|
||||
* Lists:
|
||||
*
|
||||
* {Januar Februar Maerz April Mai Juni Juli August September Oktober November Dezember}
|
||||
* {Jnr Fbr Mrz Apr Mai Jni Jli Agt Spt Okt Nvb Dzb}
|
||||
*
|
||||
* Index-Tree:
|
||||
*
|
||||
* j 0 * ...
|
||||
* anuar 1 *
|
||||
* u 0 * a 0
|
||||
* ni 6 * pril 4
|
||||
* li 7 * ugust 8
|
||||
* n 0 * gt 8
|
||||
* r 1 * s 9
|
||||
* i 6 * eptember 9
|
||||
* li 7 * pt 9
|
||||
* f 2 * oktober 10
|
||||
* ebruar 2 * n 11
|
||||
* br 2 * ovember 11
|
||||
* m 0 * vb 11
|
||||
* a 0 * d 12
|
||||
* erz 3 * ezember 12
|
||||
* i 5 * zb 12
|
||||
* rz 3 *
|
||||
* ...
|
||||
*
|
||||
* Thereby value 0 shows pure group items (corresponding ambigous matches).
|
||||
* But the group may have a value if it contains only same values
|
||||
* (see for example group "f" above).
|
||||
*
|
||||
* StrIdxTree's are very fast, so:
|
||||
* build of above-mentioned tree takes about 10 microseconds.
|
||||
* search of string index in this tree takes fewer as 0.1 microseconds.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclStrIdxTree.h"
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclStrIdxTreeSearch --
|
||||
*
|
||||
* Find largest part of string "start" in indexed tree (case sensitive).
|
||||
*
|
||||
* Also used for building of string index tree.
|
||||
*
|
||||
* Results:
|
||||
* Return position of UTF character in start after last equal character
|
||||
* and found item (with parent).
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE const char*
|
||||
TclStrIdxTreeSearch(
|
||||
TclStrIdxTree **foundParent, /* Return value of found sub tree (used for tree build) */
|
||||
TclStrIdx **foundItem, /* Return value of found item */
|
||||
TclStrIdxTree *tree, /* Index tree will be browsed */
|
||||
const char *start, /* UTF string to find in tree */
|
||||
const char *end) /* End of string */
|
||||
{
|
||||
TclStrIdxTree *parent = tree, *prevParent = tree;
|
||||
TclStrIdx *item = tree->firstPtr, *prevItem = NULL;
|
||||
const char *s = start, *f, *cin, *cinf, *prevf;
|
||||
int offs = 0;
|
||||
|
||||
if (item == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* search in tree */
|
||||
do {
|
||||
cinf = cin = TclGetString(item->key) + offs;
|
||||
f = TclUtfFindEqualNCInLwr(s, end, cin, cin + item->length, &cinf);
|
||||
/* if something was found */
|
||||
if (f > s) {
|
||||
/* if whole string was found */
|
||||
if (f >= end) {
|
||||
start = f;
|
||||
goto done;
|
||||
};
|
||||
/* set new offset and shift start string */
|
||||
offs += cinf - cin;
|
||||
s = f;
|
||||
/* if match item, go deeper as long as possible */
|
||||
if (offs >= item->length && item->childTree.firstPtr) {
|
||||
/* save previuosly found item (if not ambigous) for
|
||||
* possible fallback (few greedy match) */
|
||||
if (item->value != NULL) {
|
||||
prevf = f;
|
||||
prevItem = item;
|
||||
prevParent = parent;
|
||||
}
|
||||
parent = &item->childTree;
|
||||
item = item->childTree.firstPtr;
|
||||
continue;
|
||||
}
|
||||
/* no children - return this item and current chars found */
|
||||
start = f;
|
||||
goto done;
|
||||
}
|
||||
|
||||
item = item->nextPtr;
|
||||
|
||||
} while (item != NULL);
|
||||
|
||||
/* fallback (few greedy match) not ambigous (has a value) */
|
||||
if (prevItem != NULL) {
|
||||
item = prevItem;
|
||||
parent = prevParent;
|
||||
start = prevf;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (foundParent)
|
||||
*foundParent = parent;
|
||||
if (foundItem)
|
||||
*foundItem = item;
|
||||
return start;
|
||||
}
|
||||
|
||||
MODULE_SCOPE void
|
||||
TclStrIdxTreeFree(
|
||||
TclStrIdx *tree)
|
||||
{
|
||||
while (tree != NULL) {
|
||||
TclStrIdx *t;
|
||||
Tcl_DecrRefCount(tree->key);
|
||||
if (tree->childTree.firstPtr != NULL) {
|
||||
TclStrIdxTreeFree(tree->childTree.firstPtr);
|
||||
}
|
||||
t = tree, tree = tree->nextPtr;
|
||||
ckfree(t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Several bidirectional list primitives
|
||||
*/
|
||||
inline void
|
||||
TclStrIdxTreeInsertBranch(
|
||||
TclStrIdxTree *parent,
|
||||
register TclStrIdx *item,
|
||||
register TclStrIdx *child)
|
||||
{
|
||||
if (parent->firstPtr == child)
|
||||
parent->firstPtr = item;
|
||||
if (parent->lastPtr == child)
|
||||
parent->lastPtr = item;
|
||||
if ( (item->nextPtr = child->nextPtr) ) {
|
||||
item->nextPtr->prevPtr = item;
|
||||
child->nextPtr = NULL;
|
||||
}
|
||||
if ( (item->prevPtr = child->prevPtr) ) {
|
||||
item->prevPtr->nextPtr = item;
|
||||
child->prevPtr = NULL;
|
||||
}
|
||||
item->childTree.firstPtr = child;
|
||||
item->childTree.lastPtr = child;
|
||||
}
|
||||
|
||||
inline void
|
||||
TclStrIdxTreeAppend(
|
||||
register TclStrIdxTree *parent,
|
||||
register TclStrIdx *item)
|
||||
{
|
||||
if (parent->lastPtr != NULL) {
|
||||
parent->lastPtr->nextPtr = item;
|
||||
}
|
||||
item->prevPtr = parent->lastPtr;
|
||||
item->nextPtr = NULL;
|
||||
parent->lastPtr = item;
|
||||
if (parent->firstPtr == NULL) {
|
||||
parent->firstPtr = item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclStrIdxTreeBuildFromList --
|
||||
*
|
||||
* Build or extend string indexed tree from tcl list.
|
||||
* If the values not given the values of built list are indices starts with 1.
|
||||
* Value of 0 is thereby reserved to the ambigous values.
|
||||
*
|
||||
* Important: by multiple lists, optimal tree can be created only if list with
|
||||
* larger strings used firstly.
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE int
|
||||
TclStrIdxTreeBuildFromList(
|
||||
TclStrIdxTree *idxTree,
|
||||
int lstc,
|
||||
Tcl_Obj **lstv,
|
||||
ClientData *values)
|
||||
{
|
||||
Tcl_Obj **lwrv;
|
||||
int i, ret = TCL_ERROR;
|
||||
ClientData val;
|
||||
const char *s, *e, *f;
|
||||
TclStrIdx *item;
|
||||
|
||||
/* create lowercase reflection of the list keys */
|
||||
|
||||
lwrv = ckalloc(sizeof(Tcl_Obj*) * lstc);
|
||||
if (lwrv == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 0; i < lstc; i++) {
|
||||
lwrv[i] = Tcl_DuplicateObj(lstv[i]);
|
||||
if (lwrv[i] == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_IncrRefCount(lwrv[i]);
|
||||
lwrv[i]->length = Tcl_UtfToLower(TclGetString(lwrv[i]));
|
||||
}
|
||||
|
||||
/* build index tree of the list keys */
|
||||
for (i = 0; i < lstc; i++) {
|
||||
TclStrIdxTree *foundParent = idxTree;
|
||||
e = s = TclGetString(lwrv[i]);
|
||||
e += lwrv[i]->length;
|
||||
val = values ? values[i] : INT2PTR(i+1);
|
||||
|
||||
/* ignore empty keys (impossible to index it) */
|
||||
if (lwrv[i]->length == 0) continue;
|
||||
|
||||
item = NULL;
|
||||
if (idxTree->firstPtr != NULL) {
|
||||
TclStrIdx *foundItem;
|
||||
f = TclStrIdxTreeSearch(&foundParent, &foundItem,
|
||||
idxTree, s, e);
|
||||
/* if common prefix was found */
|
||||
if (f > s) {
|
||||
/* ignore element if fulfilled or ambigous */
|
||||
if (f == e) {
|
||||
continue;
|
||||
}
|
||||
/* if shortest key was found with the same value,
|
||||
* just replace its current key with longest key */
|
||||
if ( foundItem->value == val
|
||||
&& foundItem->length < lwrv[i]->length
|
||||
&& foundItem->childTree.firstPtr == NULL
|
||||
) {
|
||||
Tcl_SetObjRef(foundItem->key, lwrv[i]);
|
||||
foundItem->length = lwrv[i]->length;
|
||||
continue;
|
||||
}
|
||||
/* split tree (e. g. j->(jan,jun) + jul == j->(jan,ju->(jun,jul)) )
|
||||
* but don't split by fulfilled child of found item ( ii->iii->iiii ) */
|
||||
if (foundItem->length != (f - s)) {
|
||||
/* first split found item (insert one between parent and found + new one) */
|
||||
item = ckalloc(sizeof(*item));
|
||||
if (item == NULL) {
|
||||
goto done;
|
||||
}
|
||||
Tcl_InitObjRef(item->key, foundItem->key);
|
||||
item->length = f - s;
|
||||
/* set value or mark as ambigous if not the same value of both */
|
||||
item->value = (foundItem->value == val) ? val : NULL;
|
||||
/* insert group item between foundParent and foundItem */
|
||||
TclStrIdxTreeInsertBranch(foundParent, item, foundItem);
|
||||
foundParent = &item->childTree;
|
||||
} else {
|
||||
/* the new item should be added as child of found item */
|
||||
foundParent = &foundItem->childTree;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* append item at end of found parent */
|
||||
item = ckalloc(sizeof(*item));
|
||||
if (item == NULL) {
|
||||
goto done;
|
||||
}
|
||||
item->childTree.lastPtr = item->childTree.firstPtr = NULL;
|
||||
Tcl_InitObjRef(item->key, lwrv[i]);
|
||||
item->length = lwrv[i]->length;
|
||||
item->value = val;
|
||||
TclStrIdxTreeAppend(foundParent, item);
|
||||
};
|
||||
|
||||
ret = TCL_OK;
|
||||
|
||||
done:
|
||||
|
||||
if (lwrv != NULL) {
|
||||
for (i = 0; i < lstc; i++) {
|
||||
Tcl_DecrRefCount(lwrv[i]);
|
||||
}
|
||||
ckfree(lwrv);
|
||||
}
|
||||
|
||||
if (ret != TCL_OK) {
|
||||
if (idxTree->firstPtr != NULL) {
|
||||
TclStrIdxTreeFree(idxTree->firstPtr);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
|
||||
static void
|
||||
StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr);
|
||||
static void
|
||||
StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr);
|
||||
|
||||
Tcl_ObjType StrIdxTreeObjType = {
|
||||
"str-idx-tree", /* name */
|
||||
StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */
|
||||
StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */
|
||||
StrIdxTreeObj_UpdateStringProc, /* updateStringProc */
|
||||
NULL /* setFromAnyProc */
|
||||
};
|
||||
|
||||
MODULE_SCOPE Tcl_Obj*
|
||||
TclStrIdxTreeNewObj()
|
||||
{
|
||||
Tcl_Obj *objPtr = Tcl_NewObj();
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = &StrIdxTreeObjType;
|
||||
/* return tree root in internal representation */
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
static void
|
||||
StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
|
||||
{
|
||||
/* follow links (smart pointers) */
|
||||
if ( srcPtr->internalRep.twoPtrValue.ptr1 != NULL
|
||||
&& srcPtr->internalRep.twoPtrValue.ptr2 == NULL
|
||||
) {
|
||||
srcPtr = (Tcl_Obj*)srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
/* create smart pointer to it (ptr1 != NULL, ptr2 = NULL) */
|
||||
Tcl_InitObjRef(*((Tcl_Obj **)©Ptr->internalRep.twoPtrValue.ptr1),
|
||||
srcPtr);
|
||||
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
copyPtr->typePtr = &StrIdxTreeObjType;
|
||||
}
|
||||
|
||||
static void
|
||||
StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr)
|
||||
{
|
||||
/* follow links (smart pointers) */
|
||||
if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL
|
||||
&& objPtr->internalRep.twoPtrValue.ptr2 == NULL
|
||||
) {
|
||||
/* is a link */
|
||||
Tcl_UnsetObjRef(*((Tcl_Obj **)&objPtr->internalRep.twoPtrValue.ptr1));
|
||||
} else {
|
||||
/* is a tree */
|
||||
TclStrIdxTree *tree = (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1;
|
||||
if (tree->firstPtr != NULL) {
|
||||
TclStrIdxTreeFree(tree->firstPtr);
|
||||
}
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
}
|
||||
objPtr->typePtr = NULL;
|
||||
};
|
||||
|
||||
static void
|
||||
StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr)
|
||||
{
|
||||
/* currently only dummy empty string possible */
|
||||
objPtr->length = 0;
|
||||
objPtr->bytes = &tclEmptyString;
|
||||
};
|
||||
|
||||
MODULE_SCOPE TclStrIdxTree *
|
||||
TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr) {
|
||||
/* follow links (smart pointers) */
|
||||
if (objPtr->typePtr != &StrIdxTreeObjType) {
|
||||
return NULL;
|
||||
}
|
||||
if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL
|
||||
&& objPtr->internalRep.twoPtrValue.ptr2 == NULL
|
||||
) {
|
||||
objPtr = (Tcl_Obj*)objPtr->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
/* return tree root in internal representation */
|
||||
return (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Several debug primitives
|
||||
*/
|
||||
#if 0
|
||||
/* currently unused, debug resp. test purposes only */
|
||||
|
||||
void
|
||||
TclStrIdxTreePrint(
|
||||
Tcl_Interp *interp,
|
||||
TclStrIdx *tree,
|
||||
int offs)
|
||||
{
|
||||
Tcl_Obj *obj[2];
|
||||
const char *s;
|
||||
Tcl_InitObjRef(obj[0], Tcl_NewStringObj("::puts", -1));
|
||||
while (tree != NULL) {
|
||||
s = TclGetString(tree->key) + offs;
|
||||
Tcl_InitObjRef(obj[1], Tcl_ObjPrintf("%*s%.*s\t:%d",
|
||||
offs, "", tree->length - offs, s, tree->value));
|
||||
Tcl_PutsObjCmd(NULL, interp, 2, obj);
|
||||
Tcl_UnsetObjRef(obj[1]);
|
||||
if (tree->childTree.firstPtr != NULL) {
|
||||
TclStrIdxTreePrint(interp, tree->childTree.firstPtr, tree->length);
|
||||
}
|
||||
tree = tree->nextPtr;
|
||||
}
|
||||
Tcl_UnsetObjRef(obj[0]);
|
||||
}
|
||||
|
||||
|
||||
MODULE_SCOPE int
|
||||
TclStrIdxTreeTestObjCmd(
|
||||
ClientData clientData, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
const char *cs, *cin, *ret;
|
||||
|
||||
static const char *const options[] = {
|
||||
"index", "puts-index", "findequal",
|
||||
NULL
|
||||
};
|
||||
enum optionInd {
|
||||
O_INDEX, O_PUTS_INDEX, O_FINDEQUAL
|
||||
};
|
||||
int optionIndex;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], options,
|
||||
"option", 0, &optionIndex) != TCL_OK) {
|
||||
Tcl_SetErrorCode(interp, "CLOCK", "badOption",
|
||||
Tcl_GetString(objv[1]), NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (optionIndex) {
|
||||
case O_FINDEQUAL:
|
||||
if (objc < 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
cs = TclGetString(objv[2]);
|
||||
cin = TclGetString(objv[3]);
|
||||
ret = TclUtfFindEqual(
|
||||
cs, cs + objv[1]->length, cin, cin + objv[2]->length);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(ret - cs));
|
||||
break;
|
||||
case O_INDEX:
|
||||
case O_PUTS_INDEX:
|
||||
|
||||
if (1) {
|
||||
Tcl_Obj **lstv;
|
||||
int i, lstc;
|
||||
TclStrIdxTree idxTree = {NULL, NULL};
|
||||
i = 1;
|
||||
while (++i < objc) {
|
||||
if (TclListObjGetElements(interp, objv[i],
|
||||
&lstc, &lstv) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
};
|
||||
TclStrIdxTreeBuildFromList(&idxTree, lstc, lstv, NULL);
|
||||
}
|
||||
if (optionIndex == O_PUTS_INDEX) {
|
||||
TclStrIdxTreePrint(interp, idxTree.firstPtr, 0);
|
||||
}
|
||||
TclStrIdxTreeFree(idxTree.firstPtr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* tclStrIdxTree.h --
|
||||
*
|
||||
* Declarations of string index tries and other primitives currently
|
||||
* back-ported from tclSE.
|
||||
*
|
||||
* Copyright (c) 2016 Serg G. Brester (aka sebres)
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifndef _TCLSTRIDXTREE_H
|
||||
#define _TCLSTRIDXTREE_H
|
||||
|
||||
|
||||
/*
|
||||
* Main structures declarations of index tree and entry
|
||||
*/
|
||||
|
||||
typedef struct TclStrIdxTree {
|
||||
struct TclStrIdx *firstPtr;
|
||||
struct TclStrIdx *lastPtr;
|
||||
} TclStrIdxTree;
|
||||
|
||||
typedef struct TclStrIdx {
|
||||
struct TclStrIdxTree childTree;
|
||||
struct TclStrIdx *nextPtr;
|
||||
struct TclStrIdx *prevPtr;
|
||||
Tcl_Obj *key;
|
||||
int length;
|
||||
ClientData value;
|
||||
} TclStrIdx;
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclUtfFindEqual, TclUtfFindEqualNC --
|
||||
*
|
||||
* Find largest part of string cs in string cin (case sensitive and not).
|
||||
*
|
||||
* Results:
|
||||
* Return position of UTF character in cs after last equal character.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline const char *
|
||||
TclUtfFindEqual(
|
||||
register const char *cs, /* UTF string to find in cin. */
|
||||
register const char *cse, /* End of cs */
|
||||
register const char *cin, /* UTF string will be browsed. */
|
||||
register const char *cine) /* End of cin */
|
||||
{
|
||||
register const char *ret = cs;
|
||||
Tcl_UniChar ch1, ch2;
|
||||
do {
|
||||
cs += TclUtfToUniChar(cs, &ch1);
|
||||
cin += TclUtfToUniChar(cin, &ch2);
|
||||
if (ch1 != ch2) break;
|
||||
} while ((ret = cs) < cse && cin < cine);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
TclUtfFindEqualNC(
|
||||
register const char *cs, /* UTF string to find in cin. */
|
||||
register const char *cse, /* End of cs */
|
||||
register const char *cin, /* UTF string will be browsed. */
|
||||
register const char *cine, /* End of cin */
|
||||
const char **cinfnd) /* Return position in cin */
|
||||
{
|
||||
register const char *ret = cs;
|
||||
Tcl_UniChar ch1, ch2;
|
||||
do {
|
||||
cs += TclUtfToUniChar(cs, &ch1);
|
||||
cin += TclUtfToUniChar(cin, &ch2);
|
||||
if (ch1 != ch2) {
|
||||
ch1 = Tcl_UniCharToLower(ch1);
|
||||
ch2 = Tcl_UniCharToLower(ch2);
|
||||
if (ch1 != ch2) break;
|
||||
}
|
||||
*cinfnd = cin;
|
||||
} while ((ret = cs) < cse && cin < cine);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
TclUtfFindEqualNCInLwr(
|
||||
register const char *cs, /* UTF string (in anycase) to find in cin. */
|
||||
register const char *cse, /* End of cs */
|
||||
register const char *cin, /* UTF string (in lowercase) will be browsed. */
|
||||
register const char *cine, /* End of cin */
|
||||
const char **cinfnd) /* Return position in cin */
|
||||
{
|
||||
register const char *ret = cs;
|
||||
Tcl_UniChar ch1, ch2;
|
||||
do {
|
||||
cs += TclUtfToUniChar(cs, &ch1);
|
||||
cin += TclUtfToUniChar(cin, &ch2);
|
||||
if (ch1 != ch2) {
|
||||
ch1 = Tcl_UniCharToLower(ch1);
|
||||
if (ch1 != ch2) break;
|
||||
}
|
||||
*cinfnd = cin;
|
||||
} while ((ret = cs) < cse && cin < cine);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
TclUtfNext(
|
||||
register const char *src) /* The current location in the string. */
|
||||
{
|
||||
if (((unsigned char) *(src)) < 0xC0) {
|
||||
return ++src;
|
||||
} else {
|
||||
Tcl_UniChar ch;
|
||||
return src + TclUtfToUniChar(src, &ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Primitives to safe set, reset and free references.
|
||||
*/
|
||||
|
||||
#define Tcl_UnsetObjRef(obj) \
|
||||
if (obj != NULL) { Tcl_DecrRefCount(obj); obj = NULL; }
|
||||
#define Tcl_InitObjRef(obj, val) \
|
||||
obj = val; if (obj) { Tcl_IncrRefCount(obj); }
|
||||
#define Tcl_SetObjRef(obj, val) \
|
||||
if (1) { \
|
||||
Tcl_Obj *nval = val; \
|
||||
if (obj != nval) { \
|
||||
Tcl_Obj *prev = obj; \
|
||||
Tcl_InitObjRef(obj, nval); \
|
||||
if (prev != NULL) { Tcl_DecrRefCount(prev); }; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototypes of module functions.
|
||||
*/
|
||||
|
||||
MODULE_SCOPE const char*
|
||||
TclStrIdxTreeSearch(TclStrIdxTree **foundParent,
|
||||
TclStrIdx **foundItem, TclStrIdxTree *tree,
|
||||
const char *start, const char *end);
|
||||
|
||||
MODULE_SCOPE int TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree,
|
||||
int lstc, Tcl_Obj **lstv, ClientData *values);
|
||||
|
||||
MODULE_SCOPE Tcl_Obj*
|
||||
TclStrIdxTreeNewObj();
|
||||
|
||||
MODULE_SCOPE TclStrIdxTree*
|
||||
TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr);
|
||||
|
||||
#if 1
|
||||
|
||||
MODULE_SCOPE int TclStrIdxTreeTestObjCmd(ClientData, Tcl_Interp *,
|
||||
int, Tcl_Obj *const objv[]);
|
||||
#endif
|
||||
|
||||
#endif /* _TCLSTRIDXTREE_H */
|
||||
Regular → Executable
+78
-56
@@ -17,13 +17,6 @@
|
||||
#include "tommath.h"
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
* Define KILL_OCTAL to suppress interpretation of numbers with leading zero
|
||||
* as octal. (Ceterum censeo: numeros octonarios delendos esse.)
|
||||
*/
|
||||
|
||||
#undef KILL_OCTAL
|
||||
|
||||
/*
|
||||
* This code supports (at least hypothetically), IBM, Cray, VAX and IEEE-754
|
||||
* floating point; of these, only IEEE-754 can represent NaN. IEEE-754 can be
|
||||
@@ -489,7 +482,7 @@ TclParseNumber(
|
||||
{
|
||||
enum State {
|
||||
INITIAL, SIGNUM, ZERO, ZERO_X,
|
||||
ZERO_O, ZERO_B, BINARY,
|
||||
ZERO_O, ZERO_B, ZERO_D, BINARY,
|
||||
HEXADECIMAL, OCTAL, BAD_OCTAL, DECIMAL,
|
||||
LEADING_RADIX_POINT, FRACTION,
|
||||
EXPONENT_START, EXPONENT_SIGNUM, EXPONENT,
|
||||
@@ -546,6 +539,20 @@ TclParseNumber(
|
||||
*/
|
||||
|
||||
if (bytes == NULL) {
|
||||
if (interp == NULL && endPtrPtr == NULL) {
|
||||
if (objPtr->typePtr == &tclDictType) {
|
||||
/* A dict can never be a (single) number */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objPtr->typePtr == &tclListType) {
|
||||
int length;
|
||||
/* A list can only be a (single) number if its length == 1 */
|
||||
TclListObjLength(NULL, objPtr, &length);
|
||||
if (length != 1) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
bytes = TclGetString(objPtr);
|
||||
}
|
||||
|
||||
@@ -657,7 +664,11 @@ TclParseNumber(
|
||||
state = ZERO_O;
|
||||
break;
|
||||
}
|
||||
#ifdef KILL_OCTAL
|
||||
if (c == 'd' || c == 'D') {
|
||||
state = ZERO_D;
|
||||
break;
|
||||
}
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
goto decimal;
|
||||
#endif
|
||||
/* FALLTHROUGH */
|
||||
@@ -700,7 +711,7 @@ TclParseNumber(
|
||||
|| (octalSignificandWide >
|
||||
(~(Tcl_WideUInt)0 >> shift)))) {
|
||||
octalSignificandOverflow = 1;
|
||||
TclBNInitBignumFromWideUInt(&octalSignificandBig,
|
||||
TclInitBignumFromWideUInt(&octalSignificandBig,
|
||||
octalSignificandWide);
|
||||
}
|
||||
}
|
||||
@@ -740,7 +751,7 @@ TclParseNumber(
|
||||
|
||||
goto endgame;
|
||||
}
|
||||
#ifndef KILL_OCTAL
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
|
||||
/*
|
||||
* Scanned a number with a leading zero that contains an 8, 9,
|
||||
@@ -817,7 +828,7 @@ TclParseNumber(
|
||||
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
|
||||
significandWide > (~(Tcl_WideUInt)0 >> shift))) {
|
||||
significandOverflow = 1;
|
||||
TclBNInitBignumFromWideUInt(&significandBig,
|
||||
TclInitBignumFromWideUInt(&significandBig,
|
||||
significandWide);
|
||||
}
|
||||
}
|
||||
@@ -858,7 +869,7 @@ TclParseNumber(
|
||||
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
|
||||
significandWide > (~(Tcl_WideUInt)0 >> shift))) {
|
||||
significandOverflow = 1;
|
||||
TclBNInitBignumFromWideUInt(&significandBig,
|
||||
TclInitBignumFromWideUInt(&significandBig,
|
||||
significandWide);
|
||||
}
|
||||
}
|
||||
@@ -873,13 +884,23 @@ TclParseNumber(
|
||||
state = BINARY;
|
||||
break;
|
||||
|
||||
case ZERO_D:
|
||||
if (c == '0') {
|
||||
numTrailZeros++;
|
||||
} else if ( ! isdigit(UCHAR(c))) {
|
||||
goto endgame;
|
||||
}
|
||||
state = DECIMAL;
|
||||
flags |= TCL_PARSE_INTEGER_ONLY;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case DECIMAL:
|
||||
/*
|
||||
* Scanned an optional + or - followed by a string of decimal
|
||||
* digits.
|
||||
*/
|
||||
|
||||
#ifdef KILL_OCTAL
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
decimal:
|
||||
#endif
|
||||
acceptState = state;
|
||||
@@ -1169,6 +1190,7 @@ TclParseNumber(
|
||||
case ZERO_X:
|
||||
case ZERO_O:
|
||||
case ZERO_B:
|
||||
case ZERO_D:
|
||||
case LEADING_RADIX_POINT:
|
||||
case EXPONENT_START:
|
||||
case EXPONENT_SIGNUM:
|
||||
@@ -1183,16 +1205,16 @@ TclParseNumber(
|
||||
case sNA:
|
||||
case sNANPAREN:
|
||||
case sNANHEX:
|
||||
#endif
|
||||
Tcl_Panic("TclParseNumber: bad acceptState %d parsing '%s'",
|
||||
acceptState, bytes);
|
||||
#endif
|
||||
case BINARY:
|
||||
shift = numTrailZeros;
|
||||
if (!significandOverflow && significandWide != 0 &&
|
||||
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
|
||||
significandWide > (MOST_BITS + signum) >> shift)) {
|
||||
significandOverflow = 1;
|
||||
TclBNInitBignumFromWideUInt(&significandBig, significandWide);
|
||||
TclInitBignumFromWideUInt(&significandBig, significandWide);
|
||||
}
|
||||
if (shift) {
|
||||
if (!significandOverflow) {
|
||||
@@ -1213,7 +1235,7 @@ TclParseNumber(
|
||||
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
|
||||
significandWide > (MOST_BITS + signum) >> shift)) {
|
||||
significandOverflow = 1;
|
||||
TclBNInitBignumFromWideUInt(&significandBig, significandWide);
|
||||
TclInitBignumFromWideUInt(&significandBig, significandWide);
|
||||
}
|
||||
if (shift) {
|
||||
if (!significandOverflow) {
|
||||
@@ -1234,7 +1256,7 @@ TclParseNumber(
|
||||
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
|
||||
octalSignificandWide > (MOST_BITS + signum) >> shift)) {
|
||||
octalSignificandOverflow = 1;
|
||||
TclBNInitBignumFromWideUInt(&octalSignificandBig,
|
||||
TclInitBignumFromWideUInt(&octalSignificandBig,
|
||||
octalSignificandWide);
|
||||
}
|
||||
if (shift) {
|
||||
@@ -1261,7 +1283,7 @@ TclParseNumber(
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
TclBNInitBignumFromWideUInt(&octalSignificandBig,
|
||||
TclInitBignumFromWideUInt(&octalSignificandBig,
|
||||
octalSignificandWide);
|
||||
octalSignificandOverflow = 1;
|
||||
} else {
|
||||
@@ -1289,7 +1311,7 @@ TclParseNumber(
|
||||
&significandWide, &significandBig, significandOverflow);
|
||||
if (!significandOverflow && (significandWide > MOST_BITS+signum)){
|
||||
significandOverflow = 1;
|
||||
TclBNInitBignumFromWideUInt(&significandBig, significandWide);
|
||||
TclInitBignumFromWideUInt(&significandBig, significandWide);
|
||||
}
|
||||
returnInteger:
|
||||
if (!significandOverflow) {
|
||||
@@ -1308,7 +1330,7 @@ TclParseNumber(
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
TclBNInitBignumFromWideUInt(&significandBig,
|
||||
TclInitBignumFromWideUInt(&significandBig,
|
||||
significandWide);
|
||||
significandOverflow = 1;
|
||||
} else {
|
||||
@@ -1463,7 +1485,7 @@ AccumulateDecimalDigit(
|
||||
* bignum and fall through into the bignum case.
|
||||
*/
|
||||
|
||||
TclBNInitBignumFromWideUInt(bignumRepPtr, w);
|
||||
TclInitBignumFromWideUInt(bignumRepPtr, w);
|
||||
} else {
|
||||
/*
|
||||
* Wide multiplication.
|
||||
@@ -1606,7 +1628,7 @@ MakeLowPrecisionDouble(
|
||||
* call MakeHighPrecisionDouble to do it the hard way.
|
||||
*/
|
||||
|
||||
TclBNInitBignumFromWideUInt(&significandBig, significand);
|
||||
TclInitBignumFromWideUInt(&significandBig, significand);
|
||||
retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs,
|
||||
exponent);
|
||||
mp_clear(&significandBig);
|
||||
@@ -1973,7 +1995,7 @@ RefineApproximation(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static void
|
||||
static inline void
|
||||
MulPow5(
|
||||
mp_int *base, /* Number to multiply. */
|
||||
unsigned n, /* Power of 5 to multiply by. */
|
||||
@@ -2018,7 +2040,7 @@ MulPow5(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
NormalizeRightward(
|
||||
Tcl_WideUInt *wPtr) /* INOUT: Number to shift. */
|
||||
{
|
||||
@@ -2109,7 +2131,7 @@ RequiredPrecision(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static void
|
||||
static inline void
|
||||
DoubleToExpAndSig(
|
||||
double dv, /* Number to convert. */
|
||||
Tcl_WideUInt *significand, /* OUTPUT: Significand of the number. */
|
||||
@@ -2157,7 +2179,7 @@ DoubleToExpAndSig(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static void
|
||||
static inline void
|
||||
TakeAbsoluteValue(
|
||||
Double *d, /* Number to replace with absolute value. */
|
||||
int *sign) /* Place to put the signum. */
|
||||
@@ -2188,7 +2210,7 @@ TakeAbsoluteValue(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
FormatInfAndNaN(
|
||||
Double *d, /* Exceptional number to format. */
|
||||
int *decpt, /* Decimal point to set to a bogus value. */
|
||||
@@ -2230,7 +2252,7 @@ FormatInfAndNaN(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
FormatZero(
|
||||
int *decpt, /* Location of the decimal point. */
|
||||
char **endPtr) /* Pointer to the end of the formatted data */
|
||||
@@ -2260,7 +2282,7 @@ FormatZero(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
ApproximateLog10(
|
||||
Tcl_WideUInt bw, /* Integer significand of the number. */
|
||||
int be, /* Power of two to scale bw. */
|
||||
@@ -2308,7 +2330,7 @@ ApproximateLog10(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
BetterLog10(
|
||||
double d, /* Original number to format. */
|
||||
int k, /* Characteristic(Log base 10) of the
|
||||
@@ -2351,7 +2373,7 @@ BetterLog10(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static void
|
||||
static inline void
|
||||
ComputeScale(
|
||||
int be, /* Exponent part of number: d = bw * 2**be. */
|
||||
int k, /* Characteristic of log10(number). */
|
||||
@@ -2414,7 +2436,7 @@ ComputeScale(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static void
|
||||
static inline void
|
||||
SetPrecisionLimits(
|
||||
int convType, /* Type of conversion: TCL_DD_SHORTEST,
|
||||
* TCL_DD_STEELE0, TCL_DD_E_FMT,
|
||||
@@ -2475,7 +2497,7 @@ SetPrecisionLimits(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
BumpUp(
|
||||
char *s, /* Cursor pointing one past the end of the
|
||||
* string. */
|
||||
@@ -2509,7 +2531,7 @@ BumpUp(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
AdjustRange(
|
||||
double *dPtr, /* INOUT: Number to adjust. */
|
||||
int k) /* IN: floor(log10(d)) */
|
||||
@@ -2582,7 +2604,7 @@ AdjustRange(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
ShorteningQuickFormat(
|
||||
double d, /* Number to convert. */
|
||||
int k, /* floor(log10(d)) */
|
||||
@@ -2657,7 +2679,7 @@ ShorteningQuickFormat(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
StrictQuickFormat(
|
||||
double d, /* Number to convert. */
|
||||
int k, /* floor(log10(d)) */
|
||||
@@ -2731,7 +2753,7 @@ StrictQuickFormat(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
QuickConversion(
|
||||
double e, /* Number to format. */
|
||||
int k, /* floor(log10(d)), approximately. */
|
||||
@@ -2836,7 +2858,7 @@ QuickConversion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static void
|
||||
static inline void
|
||||
CastOutPowersOf2(
|
||||
int *b2, /* Power of 2 to multiply the significand. */
|
||||
int *m2, /* Power of 2 to multiply 1/2 ulp. */
|
||||
@@ -2880,7 +2902,7 @@ CastOutPowersOf2(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
ShorteningInt64Conversion(
|
||||
Double *dPtr, /* Original number to convert. */
|
||||
int convType, /* Type of conversion (shortest, Steele,
|
||||
@@ -3049,7 +3071,7 @@ ShorteningInt64Conversion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
StrictInt64Conversion(
|
||||
Double *dPtr, /* Original number to convert. */
|
||||
int convType, /* Type of conversion (shortest, Steele,
|
||||
@@ -3155,7 +3177,7 @@ StrictInt64Conversion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
ShouldBankerRoundUpPowD(
|
||||
mp_int *b, /* Numerator of the fraction. */
|
||||
int sd, /* Denominator is 2**(sd*DIGIT_BIT). */
|
||||
@@ -3193,7 +3215,7 @@ ShouldBankerRoundUpPowD(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
ShouldBankerRoundUpToNextPowD(
|
||||
mp_int *b, /* Numerator of the fraction. */
|
||||
mp_int *m, /* Numerator of the rounding tolerance. */
|
||||
@@ -3256,7 +3278,7 @@ ShouldBankerRoundUpToNextPowD(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
ShorteningBignumConversionPowD(
|
||||
Double *dPtr, /* Original number to convert. */
|
||||
int convType, /* Type of conversion (shortest, Steele,
|
||||
@@ -3293,7 +3315,7 @@ ShorteningBignumConversionPowD(
|
||||
* mminus = 5**m5
|
||||
*/
|
||||
|
||||
TclBNInitBignumFromWideUInt(&b, bw);
|
||||
TclInitBignumFromWideUInt(&b, bw);
|
||||
mp_init_set_int(&mminus, 1);
|
||||
MulPow5(&b, b5, &b);
|
||||
mp_mul_2d(&b, b2, &b);
|
||||
@@ -3449,7 +3471,7 @@ ShorteningBignumConversionPowD(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
StrictBignumConversionPowD(
|
||||
Double *dPtr, /* Original number to convert. */
|
||||
int convType, /* Type of conversion (shortest, Steele,
|
||||
@@ -3480,7 +3502,7 @@ StrictBignumConversionPowD(
|
||||
* b = bw * 2**b2 * 5**b5
|
||||
*/
|
||||
|
||||
TclBNInitBignumFromWideUInt(&b, bw);
|
||||
TclInitBignumFromWideUInt(&b, bw);
|
||||
MulPow5(&b, b5, &b);
|
||||
mp_mul_2d(&b, b2, &b);
|
||||
|
||||
@@ -3565,7 +3587,7 @@ StrictBignumConversionPowD(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
ShouldBankerRoundUp(
|
||||
mp_int *twor, /* 2x the remainder from thd division that
|
||||
* produced the last digit. */
|
||||
@@ -3600,7 +3622,7 @@ ShouldBankerRoundUp(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static int
|
||||
static inline int
|
||||
ShouldBankerRoundUpToNext(
|
||||
mp_int *b, /* Remainder from the division that produced
|
||||
* the last digit. */
|
||||
@@ -3654,7 +3676,7 @@ ShouldBankerRoundUpToNext(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
ShorteningBignumConversion(
|
||||
Double *dPtr, /* Original number being converted. */
|
||||
int convType, /* Conversion type. */
|
||||
@@ -3688,7 +3710,7 @@ ShorteningBignumConversion(
|
||||
* S = 2**s2 * 5*s5
|
||||
*/
|
||||
|
||||
TclBNInitBignumFromWideUInt(&b, bw);
|
||||
TclInitBignumFromWideUInt(&b, bw);
|
||||
mp_mul_2d(&b, b2, &b);
|
||||
mp_init_set_int(&S, 1);
|
||||
MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);
|
||||
@@ -3798,7 +3820,7 @@ ShorteningBignumConversion(
|
||||
--s5;
|
||||
|
||||
/*
|
||||
* IDEA: It might possibly be a win to fall back to int64
|
||||
* IDEA: It might possibly be a win to fall back to int64_t
|
||||
* arithmetic here if S < 2**64/10. But it's a win only for
|
||||
* a fairly narrow range of magnitudes so perhaps not worth
|
||||
* bothering. We already know that we shorten the
|
||||
@@ -3870,7 +3892,7 @@ ShorteningBignumConversion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline static char *
|
||||
static inline char *
|
||||
StrictBignumConversion(
|
||||
Double *dPtr, /* Original number being converted. */
|
||||
int convType, /* Conversion type. */
|
||||
@@ -3901,7 +3923,7 @@ StrictBignumConversion(
|
||||
*/
|
||||
|
||||
mp_init_multi(&temp, &dig, NULL);
|
||||
TclBNInitBignumFromWideUInt(&b, bw);
|
||||
TclInitBignumFromWideUInt(&b, bw);
|
||||
mp_mul_2d(&b, b2, &b);
|
||||
mp_init_set_int(&S, 1);
|
||||
MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);
|
||||
@@ -3963,7 +3985,7 @@ StrictBignumConversion(
|
||||
* As with the shortening bignum conversion, it's possible at this
|
||||
* point that we will have reduced the denominator to less than
|
||||
* 2**64/10, at which point it would be possible to fall back to
|
||||
* to int64 arithmetic. But the potential payoff is tremendously
|
||||
* to int64_t arithmetic. But the potential payoff is tremendously
|
||||
* less - unless we're working in F format - because we know that
|
||||
* three groups of digits will always suffice for %#.17e, the
|
||||
* longest format that doesn't introduce empty precision.
|
||||
@@ -4557,7 +4579,7 @@ Tcl_InitBignumFromDouble(
|
||||
Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits);
|
||||
int shift = expt - mantBits;
|
||||
|
||||
TclBNInitBignumFromWideInt(b, w);
|
||||
TclInitBignumFromWideInt(b, w);
|
||||
if (shift < 0) {
|
||||
mp_div_2d(b, -shift, b, NULL);
|
||||
} else if (shift > 0) {
|
||||
|
||||
+274
-115
@@ -466,7 +466,7 @@ Tcl_GetCharLength(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_UniChar
|
||||
int
|
||||
Tcl_GetUniChar(
|
||||
Tcl_Obj *objPtr, /* The object to get the Unicode charater
|
||||
* from. */
|
||||
@@ -483,7 +483,7 @@ Tcl_GetUniChar(
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, NULL);
|
||||
|
||||
return (Tcl_UniChar) bytes[index];
|
||||
return (int) bytes[index];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -493,7 +493,7 @@ Tcl_GetUniChar(
|
||||
SetStringFromAny(NULL, objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
|
||||
if (stringPtr->hasUnicode == 0) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE) == 0) {
|
||||
/*
|
||||
* If numChars is unknown, compute it.
|
||||
*/
|
||||
@@ -507,7 +507,7 @@ Tcl_GetUniChar(
|
||||
FillUnicodeRep(objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
}
|
||||
return stringPtr->unicode[index];
|
||||
return (int) stringPtr->unicode[index];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -569,7 +569,7 @@ Tcl_GetUnicodeFromObj(
|
||||
SetStringFromAny(NULL, objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
|
||||
if (stringPtr->hasUnicode == 0) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE) == 0) {
|
||||
FillUnicodeRep(objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
}
|
||||
@@ -607,6 +607,7 @@ Tcl_GetRange(
|
||||
{
|
||||
Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */
|
||||
String *stringPtr;
|
||||
int i, firstoffset = 0, lastoffset = 0;
|
||||
|
||||
/*
|
||||
* Optimize the case where we're really dealing with a bytearray object
|
||||
@@ -627,7 +628,7 @@ Tcl_GetRange(
|
||||
SetStringFromAny(NULL, objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
|
||||
if (stringPtr->hasUnicode == 0) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE) == 0) {
|
||||
/*
|
||||
* If numChars is unknown, compute it.
|
||||
*/
|
||||
@@ -651,7 +652,17 @@ Tcl_GetRange(
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
}
|
||||
|
||||
return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1);
|
||||
for (i = 0; i <= last + lastoffset + firstoffset; i++) {
|
||||
if ((stringPtr->unicode[i] & 0xfc00) == 0xd800) {
|
||||
if (i < first + firstoffset) {
|
||||
firstoffset++;
|
||||
} else {
|
||||
lastoffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Tcl_NewUnicodeObj(stringPtr->unicode + first + firstoffset, last-first+1 + lastoffset + firstoffset);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -783,7 +794,7 @@ Tcl_SetObjLength(
|
||||
*/
|
||||
|
||||
stringPtr->numChars = -1;
|
||||
stringPtr->hasUnicode = 0;
|
||||
stringPtr->flags = 0;
|
||||
} else {
|
||||
/*
|
||||
* Changing length of pure unicode string.
|
||||
@@ -802,7 +813,7 @@ Tcl_SetObjLength(
|
||||
|
||||
stringPtr->numChars = length;
|
||||
stringPtr->unicode[length] = 0;
|
||||
stringPtr->hasUnicode = 1;
|
||||
stringPtr->flags |= TCL_HAS_UNICODE;
|
||||
|
||||
/*
|
||||
* Can only get here when objPtr->bytes == NULL. No need to invalidate
|
||||
@@ -893,7 +904,7 @@ Tcl_AttemptSetObjLength(
|
||||
*/
|
||||
|
||||
stringPtr->numChars = -1;
|
||||
stringPtr->hasUnicode = 0;
|
||||
stringPtr->flags = 0;
|
||||
} else {
|
||||
/*
|
||||
* Changing length of pure unicode string.
|
||||
@@ -917,7 +928,7 @@ Tcl_AttemptSetObjLength(
|
||||
|
||||
stringPtr->unicode[length] = 0;
|
||||
stringPtr->numChars = length;
|
||||
stringPtr->hasUnicode = 1;
|
||||
stringPtr->flags |= TCL_HAS_UNICODE;
|
||||
|
||||
/*
|
||||
* Can only get here when objPtr->bytes == NULL. No need to invalidate
|
||||
@@ -1000,7 +1011,7 @@ SetUnicodeObj(
|
||||
memcpy(stringPtr->unicode, unicode, numChars * sizeof(Tcl_UniChar));
|
||||
stringPtr->unicode[numChars] = 0;
|
||||
stringPtr->numChars = numChars;
|
||||
stringPtr->hasUnicode = 1;
|
||||
stringPtr->flags |= TCL_HAS_UNICODE;
|
||||
|
||||
TclInvalidateStringRep(objPtr);
|
||||
stringPtr->allocated = 0;
|
||||
@@ -1071,7 +1082,7 @@ Tcl_AppendLimitedToObj(
|
||||
SetStringFromAny(NULL, objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
|
||||
if (stringPtr->hasUnicode && stringPtr->numChars > 0) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE) && stringPtr->numChars > 0) {
|
||||
AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
|
||||
} else {
|
||||
AppendUtfToUtfRep(objPtr, bytes, toCopy);
|
||||
@@ -1082,7 +1093,7 @@ Tcl_AppendLimitedToObj(
|
||||
}
|
||||
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
if (stringPtr->hasUnicode && stringPtr->numChars > 0) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE) && stringPtr->numChars > 0) {
|
||||
AppendUtfToUnicodeRep(objPtr, ellipsis, strlen(ellipsis));
|
||||
} else {
|
||||
AppendUtfToUtfRep(objPtr, ellipsis, strlen(ellipsis));
|
||||
@@ -1161,7 +1172,7 @@ Tcl_AppendUnicodeToObj(
|
||||
* objPtr's string rep.
|
||||
*/
|
||||
|
||||
if (stringPtr->hasUnicode) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE)) {
|
||||
AppendUnicodeToUnicodeRep(objPtr, unicode, length);
|
||||
} else {
|
||||
AppendUnicodeToUtfRep(objPtr, unicode, length);
|
||||
@@ -1267,7 +1278,7 @@ Tcl_AppendObjToObj(
|
||||
* appendObjPtr and append it.
|
||||
*/
|
||||
|
||||
if (stringPtr->hasUnicode) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE)) {
|
||||
/*
|
||||
* If appendObjPtr is not of the "String" type, don't convert it.
|
||||
*/
|
||||
@@ -1543,7 +1554,7 @@ AppendUtfToUtfRep(
|
||||
*/
|
||||
|
||||
stringPtr->numChars = -1;
|
||||
stringPtr->hasUnicode = 0;
|
||||
stringPtr->flags = 0;
|
||||
|
||||
if (bytes) {
|
||||
memmove(objPtr->bytes + oldLength, bytes, numBytes);
|
||||
@@ -1650,6 +1661,7 @@ Tcl_AppendFormatToObj(
|
||||
const char *span = format, *msg, *errCode;
|
||||
int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
|
||||
int originalLength, limit;
|
||||
Tcl_UniChar ch = 0;
|
||||
static const char *mixedXPG =
|
||||
"cannot mix \"%\" and \"%n$\" conversion specifiers";
|
||||
static const char *const badIndex[2] = {
|
||||
@@ -1670,12 +1682,14 @@ Tcl_AppendFormatToObj(
|
||||
|
||||
while (*format != '\0') {
|
||||
char *end;
|
||||
int gotMinus, gotHash, gotZero, gotSpace, gotPlus, sawFlag;
|
||||
int width, gotPrecision, precision, useShort, useWide, useBig;
|
||||
int gotMinus = 0, gotHash = 0, gotZero = 0, gotSpace = 0, gotPlus = 0;
|
||||
int width, gotPrecision, precision, sawFlag, useShort = 0, useBig = 0;
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
int useWide = 0;
|
||||
#endif
|
||||
int newXpg, numChars, allocSegment = 0, segmentLimit, segmentNumBytes;
|
||||
Tcl_Obj *segment;
|
||||
Tcl_UniChar ch;
|
||||
int step = Tcl_UtfToUniChar(format, &ch);
|
||||
int step = TclUtfToUniChar(format, &ch);
|
||||
|
||||
format += step;
|
||||
if (ch != '%') {
|
||||
@@ -1699,7 +1713,7 @@ Tcl_AppendFormatToObj(
|
||||
* Step 0. Handle special case of escaped format marker (i.e., %%).
|
||||
*/
|
||||
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
if (ch == '%') {
|
||||
span = format;
|
||||
numBytes = step;
|
||||
@@ -1719,7 +1733,7 @@ Tcl_AppendFormatToObj(
|
||||
newXpg = 1;
|
||||
objIndex = position - 1;
|
||||
format = end + 1;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
}
|
||||
if (newXpg) {
|
||||
@@ -1747,7 +1761,6 @@ Tcl_AppendFormatToObj(
|
||||
* Step 2. Set of flags.
|
||||
*/
|
||||
|
||||
gotMinus = gotHash = gotZero = gotSpace = gotPlus = 0;
|
||||
sawFlag = 1;
|
||||
do {
|
||||
switch (ch) {
|
||||
@@ -1771,7 +1784,7 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
if (sawFlag) {
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
} while (sawFlag);
|
||||
|
||||
@@ -1783,7 +1796,7 @@ Tcl_AppendFormatToObj(
|
||||
if (isdigit(UCHAR(ch))) {
|
||||
width = strtoul(format, &end, 10);
|
||||
format = end;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
} else if (ch == '*') {
|
||||
if (objIndex >= objc - 1) {
|
||||
msg = badIndex[gotXpg];
|
||||
@@ -1799,7 +1812,7 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
objIndex++;
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
if (width > limit) {
|
||||
msg = overflow;
|
||||
@@ -1815,12 +1828,12 @@ Tcl_AppendFormatToObj(
|
||||
if (ch == '.') {
|
||||
gotPrecision = 1;
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
if (isdigit(UCHAR(ch))) {
|
||||
precision = strtoul(format, &end, 10);
|
||||
format = end;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
} else if (ch == '*') {
|
||||
if (objIndex >= objc - 1) {
|
||||
msg = badIndex[gotXpg];
|
||||
@@ -1841,38 +1854,57 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
objIndex++;
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step 5. Length modifier.
|
||||
*/
|
||||
|
||||
useShort = useWide = useBig = 0;
|
||||
if (ch == 'h') {
|
||||
useShort = 1;
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
} else if (ch == 'l') {
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
if (ch == 'l') {
|
||||
useBig = 1;
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
} else {
|
||||
useWide = 1;
|
||||
#endif
|
||||
}
|
||||
} else if ((ch == 'I') && (format[1] == '6') && (format[2] == '4')) {
|
||||
format += (step + 2);
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
useBig = 1;
|
||||
} else if (ch == 'L') {
|
||||
} else if (ch == 'I') {
|
||||
if ((format[1] == '6') && (format[2] == '4')) {
|
||||
format += (step + 2);
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
useWide = 1;
|
||||
#endif
|
||||
} else if ((format[1] == '3') && (format[2] == '2')) {
|
||||
format += (step + 2);
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
} else {
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
}
|
||||
} else if ((ch == 't') || (ch == 'z')) {
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
useBig = 1;
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (sizeof(size_t) > sizeof(int)) {
|
||||
useWide = 1;
|
||||
}
|
||||
#endif
|
||||
} else if ((ch == 'q') ||(ch == 'j')) {
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
useWide = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
format += step;
|
||||
@@ -1925,6 +1957,7 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
case 'd':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'b': {
|
||||
@@ -1935,11 +1968,17 @@ Tcl_AppendFormatToObj(
|
||||
mp_int big;
|
||||
int toAppend, isNegative = 0;
|
||||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
if (ch == 'p') {
|
||||
useWide = 1;
|
||||
}
|
||||
#endif
|
||||
if (useBig) {
|
||||
if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) {
|
||||
goto error;
|
||||
}
|
||||
isNegative = (mp_cmp_d(&big, 0) == MP_LT);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
} else if (useWide) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
|
||||
Tcl_Obj *objPtr;
|
||||
@@ -1954,6 +1993,7 @@ Tcl_AppendFormatToObj(
|
||||
Tcl_DecrRefCount(objPtr);
|
||||
}
|
||||
isNegative = (w < (Tcl_WideInt) 0);
|
||||
#endif
|
||||
} else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
|
||||
Tcl_Obj *objPtr;
|
||||
@@ -1993,15 +2033,19 @@ Tcl_AppendFormatToObj(
|
||||
segmentLimit -= 1;
|
||||
}
|
||||
|
||||
if (gotHash) {
|
||||
if (gotHash || (ch == 'p')) {
|
||||
switch (ch) {
|
||||
case 'o':
|
||||
Tcl_AppendToObj(segment, "0", 1);
|
||||
segmentLimit -= 1;
|
||||
precision--;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
Tcl_AppendToObj(segment, "0X", 2);
|
||||
segmentLimit -= 2;
|
||||
break;
|
||||
case 'p':
|
||||
case 'x':
|
||||
Tcl_AppendToObj(segment, "0x", 2);
|
||||
segmentLimit -= 2;
|
||||
break;
|
||||
@@ -2009,6 +2053,10 @@ Tcl_AppendFormatToObj(
|
||||
Tcl_AppendToObj(segment, "0b", 2);
|
||||
segmentLimit -= 2;
|
||||
break;
|
||||
case 'd':
|
||||
Tcl_AppendToObj(segment, "0d", 2);
|
||||
segmentLimit -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2020,8 +2068,10 @@ Tcl_AppendFormatToObj(
|
||||
|
||||
if (useShort) {
|
||||
pure = Tcl_NewIntObj((int) s);
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
} else if (useWide) {
|
||||
pure = Tcl_NewWideIntObj(w);
|
||||
#endif
|
||||
} else if (useBig) {
|
||||
pure = Tcl_NewBignumObj(&big);
|
||||
} else {
|
||||
@@ -2078,6 +2128,7 @@ Tcl_AppendFormatToObj(
|
||||
|
||||
case 'u':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'b': {
|
||||
@@ -2104,6 +2155,7 @@ Tcl_AppendFormatToObj(
|
||||
numDigits++;
|
||||
us /= base;
|
||||
}
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
} else if (useWide) {
|
||||
Tcl_WideUInt uw = (Tcl_WideUInt) w;
|
||||
|
||||
@@ -2112,6 +2164,7 @@ Tcl_AppendFormatToObj(
|
||||
numDigits++;
|
||||
uw /= base;
|
||||
}
|
||||
#endif
|
||||
} else if (useBig && big.used) {
|
||||
int leftover = (big.used * DIGIT_BIT) % numBits;
|
||||
mp_digit mask = (~(mp_digit)0) << (DIGIT_BIT-leftover);
|
||||
@@ -2161,7 +2214,11 @@ Tcl_AppendFormatToObj(
|
||||
}
|
||||
digitOffset = (int) (bits % base);
|
||||
if (digitOffset > 9) {
|
||||
bytes[numDigits] = 'a' + digitOffset - 10;
|
||||
if (ch == 'X') {
|
||||
bytes[numDigits] = 'A' + digitOffset - 10;
|
||||
} else {
|
||||
bytes[numDigits] = 'a' + digitOffset - 10;
|
||||
}
|
||||
} else {
|
||||
bytes[numDigits] = '0' + digitOffset;
|
||||
}
|
||||
@@ -2283,14 +2340,6 @@ Tcl_AppendFormatToObj(
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case 'E':
|
||||
case 'G':
|
||||
case 'X': {
|
||||
Tcl_SetObjLength(segment, Tcl_UtfToUpper(TclGetString(segment)));
|
||||
}
|
||||
}
|
||||
|
||||
if (width>0 && numChars<0) {
|
||||
numChars = Tcl_GetCharLength(segment);
|
||||
}
|
||||
@@ -2467,6 +2516,7 @@ AppendPrintfToObjVA(
|
||||
case 'u':
|
||||
case 'd':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'x':
|
||||
case 'X':
|
||||
seekingConversion = 0;
|
||||
@@ -2517,7 +2567,15 @@ AppendPrintfToObjVA(
|
||||
++size;
|
||||
p++;
|
||||
break;
|
||||
case 'L':
|
||||
case 't':
|
||||
case 'z':
|
||||
if (sizeof(size_t) == sizeof(Tcl_WideInt)) {
|
||||
size = 2;
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
case 'j':
|
||||
case 'q':
|
||||
size = 2;
|
||||
p++;
|
||||
break;
|
||||
@@ -2525,6 +2583,10 @@ AppendPrintfToObjVA(
|
||||
if (p[1]=='6' && p[2]=='4') {
|
||||
p += 2;
|
||||
size = 2;
|
||||
} else if (p[1]=='3' && p[2]=='2') {
|
||||
p += 2;
|
||||
} else if (sizeof(size_t) == sizeof(Tcl_WideInt)) {
|
||||
size = 2;
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
@@ -2673,7 +2735,7 @@ TclStringRepeat(
|
||||
if (!binary) {
|
||||
if (objPtr->typePtr == &tclStringType) {
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
if (stringPtr->hasUnicode) {
|
||||
if (stringPtr->flags & TCL_HAS_UNICODE) {
|
||||
unichar = 1;
|
||||
}
|
||||
}
|
||||
@@ -2732,7 +2794,7 @@ TclStringRepeat(
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"string size overflow: unable to alloc %"
|
||||
TCL_LL_MODIFIER "u bytes",
|
||||
TCL_LL_MODIFIER "d bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(count*length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
@@ -2799,11 +2861,21 @@ TclStringCatObjv(
|
||||
Tcl_Obj * const objv[],
|
||||
Tcl_Obj **objPtrPtr)
|
||||
{
|
||||
Tcl_Obj *objPtr, *objResultPtr, * const *ov;
|
||||
int oc, length = 0, binary = 1, first = 0;
|
||||
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 */
|
||||
|
||||
/* assert (objc >= 2) */
|
||||
/* assert ( objc >= 0 ) */
|
||||
|
||||
if (objc <= 1) {
|
||||
/* Only one or no objects; return first or empty */
|
||||
*objPtrPtr = objc ? objv[0] : Tcl_NewObj();
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* assert ( objc >= 2 ) */
|
||||
|
||||
/*
|
||||
* Analyze to determine what representation result should be.
|
||||
@@ -2813,8 +2885,8 @@ TclStringCatObjv(
|
||||
*/
|
||||
|
||||
ov = objv, oc = objc;
|
||||
while (oc-- && (binary || allowUniChar)) {
|
||||
objPtr = *ov++;
|
||||
do {
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
if (objPtr->bytes) {
|
||||
/* Value has a string rep. */
|
||||
@@ -2844,72 +2916,144 @@ TclStringCatObjv(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (--oc && (binary || allowUniChar));
|
||||
|
||||
if (binary) {
|
||||
/* Result will be pure byte array. Pre-size it */
|
||||
ov = objv; oc = objc;
|
||||
while (oc-- && (length >= 0)) {
|
||||
objPtr = *ov++;
|
||||
do {
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
if (objPtr->bytes == NULL) {
|
||||
int numBytes;
|
||||
|
||||
Tcl_GetByteArrayFromObj(objPtr, &numBytes); /* PANIC? */
|
||||
if (length == 0) {
|
||||
first = objc - oc - 1;
|
||||
if (numBytes) {
|
||||
last = objc - oc;
|
||||
if (length == 0) {
|
||||
first = last;
|
||||
} else if (numBytes > INT_MAX - length) {
|
||||
goto overflow;
|
||||
}
|
||||
length += numBytes;
|
||||
}
|
||||
length += numBytes;
|
||||
}
|
||||
}
|
||||
} while (--oc);
|
||||
} else if (allowUniChar && requestUniChar) {
|
||||
/* Result will be pure Tcl_UniChar array. Pre-size it. */
|
||||
ov = objv; oc = objc;
|
||||
while (oc-- && (length >= 0)) {
|
||||
objPtr = *ov++;
|
||||
do {
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
if ((objPtr->bytes == NULL) || (objPtr->length)) {
|
||||
int numChars;
|
||||
|
||||
Tcl_GetUnicodeFromObj(objPtr, &numChars); /* PANIC? */
|
||||
if (length == 0) {
|
||||
first = objc - oc - 1;
|
||||
if (numChars) {
|
||||
last = objc - oc;
|
||||
if (length == 0) {
|
||||
first = last;
|
||||
} else if (numChars > INT_MAX - length) {
|
||||
goto overflow;
|
||||
}
|
||||
length += numChars;
|
||||
}
|
||||
length += numChars;
|
||||
}
|
||||
}
|
||||
} while (--oc);
|
||||
} else {
|
||||
/* Result will be concat of string reps. Pre-size it. */
|
||||
ov = objv; oc = objc;
|
||||
while (oc-- && (length >= 0)) {
|
||||
int numBytes;
|
||||
do {
|
||||
Tcl_Obj *pendingPtr = NULL;
|
||||
|
||||
objPtr = *ov++;
|
||||
/*
|
||||
* Loop until a possibly non-empty value is reached.
|
||||
* Keep string rep generation pending when possible.
|
||||
*/
|
||||
|
||||
Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */
|
||||
if ((length == 0) && numBytes) {
|
||||
first = objc - oc - 1;
|
||||
do {
|
||||
/* assert ( pendingPtr == NULL ) */
|
||||
/* assert ( length == 0 ) */
|
||||
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
if (objPtr->bytes == NULL) {
|
||||
/* No string rep; Take the chance we can avoid making it */
|
||||
pendingPtr = objPtr;
|
||||
} else {
|
||||
Tcl_GetStringFromObj(objPtr, &length); /* PANIC? */
|
||||
}
|
||||
} while (--oc && (length == 0) && (pendingPtr == NULL));
|
||||
|
||||
/*
|
||||
* Either we found a possibly non-empty value, and we
|
||||
* remember this index as the first and last such value so
|
||||
* far seen, or (oc == 0) and all values are known empty,
|
||||
* so first = last = objc - 1 signals the right quick return.
|
||||
*/
|
||||
|
||||
first = last = objc - oc - 1;
|
||||
|
||||
if (oc && (length == 0)) {
|
||||
int numBytes;
|
||||
|
||||
/* assert ( pendingPtr != NULL ) */
|
||||
|
||||
/*
|
||||
* There's a pending value followed by more values.
|
||||
* Loop over remaining values generating strings until
|
||||
* a non-empty value is found, or the pending value gets
|
||||
* its string generated.
|
||||
*/
|
||||
|
||||
do {
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */
|
||||
} while (--oc && numBytes == 0 && pendingPtr->bytes == NULL);
|
||||
|
||||
if (numBytes) {
|
||||
last = objc -oc -1;
|
||||
}
|
||||
if (oc || numBytes) {
|
||||
Tcl_GetStringFromObj(pendingPtr, &length);
|
||||
}
|
||||
if (length == 0) {
|
||||
if (numBytes) {
|
||||
first = last;
|
||||
}
|
||||
} else if (numBytes > INT_MAX - length) {
|
||||
goto overflow;
|
||||
}
|
||||
length += numBytes;
|
||||
}
|
||||
length += numBytes;
|
||||
} while (oc && (length == 0));
|
||||
|
||||
while (oc) {
|
||||
int numBytes;
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
/* assert ( length > 0 && pendingPtr == NULL ) */
|
||||
|
||||
Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */
|
||||
if (numBytes) {
|
||||
last = objc - oc;
|
||||
if (numBytes > INT_MAX - length) {
|
||||
goto overflow;
|
||||
}
|
||||
length += numBytes;
|
||||
}
|
||||
--oc;
|
||||
}
|
||||
}
|
||||
|
||||
if (length < 0) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max size for a Tcl value (%d bytes) exceeded", INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
/* Total length of zero means every value has length zero */
|
||||
*objPtrPtr = objv[0];
|
||||
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;
|
||||
}
|
||||
|
||||
objv += first; objc -= first;
|
||||
objv += first; objc = (last - first + 1);
|
||||
|
||||
if (binary) {
|
||||
/* Efficiently produce a pure byte array result */
|
||||
@@ -2956,7 +3100,7 @@ TclStringCatObjv(
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %"
|
||||
TCL_LL_MODIFIER "u bytes",
|
||||
TCL_LL_MODIFIER "d bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
@@ -2972,7 +3116,7 @@ TclStringCatObjv(
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"concatenation failed: unable to alloc %"
|
||||
TCL_LL_MODIFIER "u bytes",
|
||||
TCL_LL_MODIFIER "d bytes",
|
||||
(Tcl_WideUInt)STRING_SIZE(length)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
@@ -3010,9 +3154,9 @@ TclStringCatObjv(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
dst = Tcl_GetString(objResultPtr) + start;
|
||||
if (length > start) {
|
||||
TclFreeIntRep(objResultPtr);
|
||||
}
|
||||
|
||||
/* assert ( length > start ) */
|
||||
TclFreeIntRep(objResultPtr);
|
||||
} else {
|
||||
objResultPtr = Tcl_NewObj(); /* PANIC? */
|
||||
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
|
||||
@@ -3039,6 +3183,14 @@ TclStringCatObjv(
|
||||
}
|
||||
*objPtrPtr = objResultPtr;
|
||||
return TCL_OK;
|
||||
|
||||
overflow:
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"max size for a Tcl value (%d bytes) exceeded", INT_MAX));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3287,7 +3439,7 @@ TclStringObjReverse(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
String *stringPtr;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_UniChar ch = 0;
|
||||
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
int numBytes;
|
||||
@@ -3303,7 +3455,7 @@ TclStringObjReverse(
|
||||
SetStringFromAny(NULL, objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
|
||||
if (stringPtr->hasUnicode) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE)) {
|
||||
Tcl_UniChar *from = Tcl_GetUnicode(objPtr);
|
||||
Tcl_UniChar *src = from + stringPtr->numChars;
|
||||
|
||||
@@ -3315,7 +3467,6 @@ TclStringObjReverse(
|
||||
* Tcl_SetObjLength into growing the unicode rep buffer.
|
||||
*/
|
||||
|
||||
ch = 0;
|
||||
objPtr = Tcl_NewUnicodeObj(&ch, 1);
|
||||
Tcl_SetObjLength(objPtr, stringPtr->numChars);
|
||||
to = Tcl_GetUnicode(objPtr);
|
||||
@@ -3361,7 +3512,7 @@ TclStringObjReverse(
|
||||
* It's part of the contract for objPtr->bytes values.
|
||||
* Thus, we can skip calling Tcl_UtfCharComplete() here.
|
||||
*/
|
||||
int bytesInChar = Tcl_UtfToUniChar(from, &ch);
|
||||
int bytesInChar = TclUtfToUniChar(from, &ch);
|
||||
|
||||
ReverseBytes((unsigned char *)to, (unsigned char *)from,
|
||||
bytesInChar);
|
||||
@@ -3417,10 +3568,10 @@ ExtendUnicodeRepWithString(
|
||||
int numAppendChars)
|
||||
{
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
int needed, numOrigChars = 0;
|
||||
Tcl_UniChar *dst;
|
||||
int incr, needed, numOrigChars = 0;
|
||||
Tcl_UniChar *dst, unichar = 0;
|
||||
|
||||
if (stringPtr->hasUnicode) {
|
||||
if ((stringPtr->flags & TCL_HAS_UNICODE)) {
|
||||
numOrigChars = stringPtr->numChars;
|
||||
}
|
||||
if (numAppendChars == -1) {
|
||||
@@ -3434,14 +3585,19 @@ ExtendUnicodeRepWithString(
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
}
|
||||
|
||||
stringPtr->hasUnicode = 1;
|
||||
stringPtr->flags |= TCL_HAS_UNICODE;
|
||||
if (bytes) {
|
||||
stringPtr->numChars = needed;
|
||||
} else {
|
||||
numAppendChars = 0;
|
||||
}
|
||||
for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) {
|
||||
bytes += TclUtfToUniChar(bytes, dst);
|
||||
bytes += (incr = TclUtfToUniChar(bytes, &unichar));
|
||||
*dst = unichar;
|
||||
if (!incr) {
|
||||
bytes += TclUtfToUniChar(bytes, &unichar);
|
||||
*++dst = unichar;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
}
|
||||
@@ -3484,7 +3640,7 @@ DupStringInternalRep(
|
||||
return;
|
||||
}
|
||||
|
||||
if (srcStringPtr->hasUnicode) {
|
||||
if (srcStringPtr->flags & TCL_HAS_UNICODE) {
|
||||
int copyMaxChars;
|
||||
|
||||
if (srcStringPtr->maxChars / 2 >= srcStringPtr->numChars) {
|
||||
@@ -3506,7 +3662,7 @@ DupStringInternalRep(
|
||||
copyStringPtr->maxChars = 0;
|
||||
copyStringPtr->unicode[0] = 0;
|
||||
}
|
||||
copyStringPtr->hasUnicode = srcStringPtr->hasUnicode;
|
||||
copyStringPtr->flags = srcStringPtr->flags;
|
||||
copyStringPtr->numChars = srcStringPtr->numChars;
|
||||
|
||||
/*
|
||||
@@ -3561,7 +3717,7 @@ SetStringFromAny(
|
||||
stringPtr->numChars = -1;
|
||||
stringPtr->allocated = objPtr->length;
|
||||
stringPtr->maxChars = 0;
|
||||
stringPtr->hasUnicode = 0;
|
||||
stringPtr->flags = 0;
|
||||
SET_STRING(objPtr, stringPtr);
|
||||
objPtr->typePtr = &tclStringType;
|
||||
}
|
||||
@@ -3620,8 +3776,8 @@ ExtendStringRepWithUnicode(
|
||||
* Pre-condition: this is the "string" Tcl_ObjType.
|
||||
*/
|
||||
|
||||
int i, origLength, size = 0;
|
||||
char *dst;
|
||||
int incr, i, origLength, size = 0, offset = 0;
|
||||
char *dst, buf[TCL_UTF_MAX];
|
||||
String *stringPtr = GET_STRING(objPtr);
|
||||
|
||||
if (numChars < 0) {
|
||||
@@ -3646,9 +3802,11 @@ ExtendStringRepWithUnicode(
|
||||
goto copyBytes;
|
||||
}
|
||||
|
||||
for (i = 0; i < numChars && size >= 0; i++) {
|
||||
size += TclUtfCount(unicode[i]);
|
||||
for (i = 0; i < numChars + offset && size >= 0; i++) {
|
||||
size += (incr = Tcl_UniCharToUtf((int) unicode[i], buf));
|
||||
if (!incr) offset++;
|
||||
}
|
||||
offset = 0;
|
||||
if (size < 0) {
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
|
||||
}
|
||||
@@ -3663,8 +3821,9 @@ ExtendStringRepWithUnicode(
|
||||
|
||||
copyBytes:
|
||||
dst = objPtr->bytes + origLength;
|
||||
for (i = 0; i < numChars; i++) {
|
||||
dst += Tcl_UniCharToUtf((int) unicode[i], dst);
|
||||
for (i = 0; i < numChars + offset; i++) {
|
||||
dst += (incr = Tcl_UniCharToUtf((int) unicode[i], dst));
|
||||
if (!incr) offset++;
|
||||
}
|
||||
*dst = '\0';
|
||||
objPtr->length = dst - objPtr->bytes;
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
* can be officially modified by altering the definition of Tcl_UniChar in
|
||||
* tcl.h, but do not do that unless you are sure what you're doing!
|
||||
*/
|
||||
#define TCL_HAS_UNICODE 1 /* This string has Unicode representation */
|
||||
#define TCL_HAS_BIGUNICODE 2 /* This string contains characters > \uffff */
|
||||
|
||||
typedef struct {
|
||||
int numChars; /* The number of chars in the string. -1 means
|
||||
@@ -57,8 +59,7 @@ typedef struct {
|
||||
* termination char). */
|
||||
int maxChars; /* Max number of chars that can fit in the
|
||||
* space allocated for the unicode array. */
|
||||
int hasUnicode; /* Boolean determining whether the string has
|
||||
* a Unicode representation. */
|
||||
int flags; /* Combination of TCL_HAS_UNICODE and TCL_HAS_BIGUNICODE */
|
||||
Tcl_UniChar unicode[1]; /* The array of Unicode chars. The actual size
|
||||
* of this field depends on the 'maxChars'
|
||||
* field above. */
|
||||
|
||||
+94
-12
@@ -41,15 +41,15 @@
|
||||
#undef Tcl_FindExecutable
|
||||
#undef TclpGetPid
|
||||
#undef TclSockMinimumBuffers
|
||||
#define TclBackgroundException Tcl_BackgroundException
|
||||
#undef Tcl_SetIntObj
|
||||
#undef TclpInetNtoa
|
||||
#undef TclWinGetServByName
|
||||
#undef TclWinGetSockOpt
|
||||
#undef TclWinSetSockOpt
|
||||
#undef TclWinNToHS
|
||||
|
||||
/* See bug 510001: TclSockMinimumBuffers needs plat imp */
|
||||
#ifdef _WIN64
|
||||
#if defined(_WIN64) || defined(TCL_NO_DEPRECATED)
|
||||
# define TclSockMinimumBuffersOld 0
|
||||
#else
|
||||
#define TclSockMinimumBuffersOld sockMinimumBuffersOld
|
||||
@@ -59,6 +59,20 @@ static int TclSockMinimumBuffersOld(int sock, int size)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TCL_NO_DEPRECATED)
|
||||
# define TclSetStartupScriptPath 0
|
||||
# define TclGetStartupScriptPath 0
|
||||
# define TclSetStartupScriptFileName 0
|
||||
# define TclGetStartupScriptFileName 0
|
||||
# define TclpInetNtoa 0
|
||||
# define TclWinGetServByName 0
|
||||
# define TclWinGetSockOpt 0
|
||||
# define TclWinSetSockOpt 0
|
||||
# define TclWinNToHS 0
|
||||
# define TclBNInitBignumFromWideUInt 0
|
||||
# define TclBNInitBignumFromWideInt 0
|
||||
# define TclBNInitBignumFromLong 0
|
||||
#else
|
||||
#define TclSetStartupScriptPath setStartupScriptPath
|
||||
static void TclSetStartupScriptPath(Tcl_Obj *path)
|
||||
{
|
||||
@@ -92,6 +106,10 @@ static unsigned short TclWinNToHS(unsigned short ns) {
|
||||
return ntohs(ns);
|
||||
}
|
||||
#endif
|
||||
# define TclBNInitBignumFromWideUInt TclInitBignumFromWideUInt
|
||||
# define TclBNInitBignumFromWideInt TclInitBignumFromWideInt
|
||||
# define TclBNInitBignumFromLong TclInitBignumFromLong
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
#ifdef _WIN32
|
||||
# define TclUnixWaitForFile 0
|
||||
@@ -131,6 +149,7 @@ void *TclWinGetTclInstance()
|
||||
return hInstance;
|
||||
}
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#define TclWinSetSockOpt winSetSockOpt
|
||||
static int
|
||||
TclWinSetSockOpt(SOCKET s, int level, int optname,
|
||||
@@ -153,6 +172,7 @@ TclWinGetServByName(const char *name, const char *proto)
|
||||
{
|
||||
return getservbyname(name, proto);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
#define TclWinNoBackslash winNoBackslash
|
||||
static char *
|
||||
@@ -287,26 +307,79 @@ static int formatInt(char *buffer, int n){
|
||||
}
|
||||
#define TclFormatInt (int(*)(char *, long))formatInt
|
||||
|
||||
#endif
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#else /* UNIX and MAC */
|
||||
# ifdef TCL_NO_DEPRECATED
|
||||
# define TclpLocaltime_unix 0
|
||||
# define TclpGmtime_unix 0
|
||||
# else
|
||||
# define TclpLocaltime_unix TclpLocaltime
|
||||
# define TclpGmtime_unix TclpGmtime
|
||||
# endif
|
||||
#endif
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
# define Tcl_SeekOld 0
|
||||
# define Tcl_TellOld 0
|
||||
# undef Tcl_SetBooleanObj
|
||||
# define Tcl_SetBooleanObj 0
|
||||
# undef Tcl_PkgPresent
|
||||
# define Tcl_PkgPresent 0
|
||||
# undef Tcl_PkgProvide
|
||||
# define Tcl_PkgProvide 0
|
||||
# undef Tcl_PkgRequire
|
||||
# define Tcl_PkgRequire 0
|
||||
# undef Tcl_GetIndexFromObj
|
||||
# define Tcl_GetIndexFromObj 0
|
||||
# define Tcl_NewBooleanObj 0
|
||||
# undef Tcl_DbNewBooleanObj
|
||||
# define Tcl_DbNewBooleanObj 0
|
||||
# undef Tcl_SetBooleanObj
|
||||
# define Tcl_SetBooleanObj 0
|
||||
# undef Tcl_SetVar
|
||||
# define Tcl_SetVar 0
|
||||
# undef Tcl_UnsetVar
|
||||
# define Tcl_UnsetVar 0
|
||||
# undef Tcl_GetVar
|
||||
# define Tcl_GetVar 0
|
||||
# undef Tcl_TraceVar
|
||||
# define Tcl_TraceVar 0
|
||||
# undef Tcl_UntraceVar
|
||||
# define Tcl_UntraceVar 0
|
||||
# undef Tcl_VarTraceInfo
|
||||
# define Tcl_VarTraceInfo 0
|
||||
# undef Tcl_UpVar
|
||||
# define Tcl_UpVar 0
|
||||
# undef Tcl_AddErrorInfo
|
||||
# define Tcl_AddErrorInfo 0
|
||||
# undef Tcl_AddObjErrorInfo
|
||||
# define Tcl_AddObjErrorInfo 0
|
||||
# undef Tcl_Eval
|
||||
# define Tcl_Eval 0
|
||||
# undef Tcl_GlobalEval
|
||||
# define Tcl_GlobalEval 0
|
||||
# undef Tcl_SaveResult
|
||||
# define Tcl_SaveResult 0
|
||||
# undef Tcl_RestoreResult
|
||||
# define Tcl_RestoreResult 0
|
||||
# undef Tcl_DiscardResult
|
||||
# define Tcl_DiscardResult 0
|
||||
# undef Tcl_SetResult
|
||||
# define Tcl_SetResult 0
|
||||
# undef Tcl_EvalObj
|
||||
# define Tcl_EvalObj 0
|
||||
# undef Tcl_GlobalEvalObj
|
||||
# define Tcl_GlobalEvalObj 0
|
||||
# define TclBackgroundException 0
|
||||
# undef TclpReaddir
|
||||
# define TclpReaddir 0
|
||||
# undef TclpGetDate
|
||||
# define TclpGetDate 0
|
||||
# undef TclpLocaltime
|
||||
# define TclpLocaltime 0
|
||||
# undef TclpGmtime
|
||||
# define TclpGmtime 0
|
||||
# define TclpLocaltime_unix 0
|
||||
# define TclpGmtime_unix 0
|
||||
#else /* TCL_NO_DEPRECATED */
|
||||
# define Tcl_SeekOld seekOld
|
||||
# define Tcl_TellOld tellOld
|
||||
# define TclBackgroundException Tcl_BackgroundException
|
||||
# define TclpLocaltime_unix TclpLocaltime
|
||||
# define TclpGmtime_unix TclpGmtime
|
||||
|
||||
static int
|
||||
seekOld(
|
||||
@@ -597,6 +670,11 @@ static const TclIntStubs tclIntStubs = {
|
||||
TclDoubleDigits, /* 249 */
|
||||
TclSetSlaveCancelFlags, /* 250 */
|
||||
TclRegisterLiteral, /* 251 */
|
||||
TclPtrGetVar, /* 252 */
|
||||
TclPtrSetVar, /* 253 */
|
||||
TclPtrIncrObjVar, /* 254 */
|
||||
TclPtrObjMakeUpvar, /* 255 */
|
||||
TclPtrUnsetVar, /* 256 */
|
||||
};
|
||||
|
||||
static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
@@ -787,6 +865,10 @@ const TclTomMathStubs tclTomMathStubs = {
|
||||
TclBNInitBignumFromWideInt, /* 65 */
|
||||
TclBNInitBignumFromWideUInt, /* 66 */
|
||||
TclBN_mp_expt_d_ex, /* 67 */
|
||||
TclBN_mp_set_long_long, /* 68 */
|
||||
TclBN_mp_get_long_long, /* 69 */
|
||||
TclBN_mp_set_long, /* 70 */
|
||||
TclBN_mp_get_long, /* 71 */
|
||||
};
|
||||
|
||||
static const TclStubHooks tclStubHooks = {
|
||||
|
||||
@@ -67,7 +67,7 @@ Tcl_InitStubs(
|
||||
|
||||
if (!stubsPtr || (stubsPtr->magic != (((exact&0xff00) >= 0x900) ? magic : TCL_STUB_MAGIC))) {
|
||||
iPtr->result = (char *)"interpreter uses an incompatible stubs mechanism";
|
||||
iPtr->freeProc = TCL_STATIC;
|
||||
iPtr->freeProc = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* tclStubLibTbl.c --
|
||||
*
|
||||
* Stub object that will be statically linked into extensions that want
|
||||
* to access Tcl.
|
||||
*
|
||||
* Copyright (c) 1998-1999 by Scriptics Corporation.
|
||||
* Copyright (c) 1998 Paul Duffin.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclInitStubTable --
|
||||
*
|
||||
* Initialize the stub table, using the structure pointed at
|
||||
* by the "version" argument.
|
||||
*
|
||||
* Results:
|
||||
* Outputs the value of the "version" argument.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets the stub table pointers.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
MODULE_SCOPE const char *
|
||||
TclInitStubTable(
|
||||
const char *version) /* points to the version field of a
|
||||
TclStubInfoType structure variable. */
|
||||
{
|
||||
tclStubsPtr = ((const TclStubInfoType *) version)->stubs;
|
||||
|
||||
if (tclStubsPtr->hooks) {
|
||||
tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs;
|
||||
tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs;
|
||||
tclIntPlatStubsPtr = tclStubsPtr->hooks->tclIntPlatStubs;
|
||||
} else {
|
||||
tclPlatStubsPtr = NULL;
|
||||
tclIntStubsPtr = NULL;
|
||||
tclIntPlatStubsPtr = NULL;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
||||
+93
-6
@@ -67,6 +67,18 @@ typedef struct TestAsyncHandler {
|
||||
/* Next is list of handlers. */
|
||||
} TestAsyncHandler;
|
||||
|
||||
/*
|
||||
* Start of the socket driver state structure to acces field testFlags
|
||||
*/
|
||||
|
||||
typedef struct TcpState TcpState;
|
||||
|
||||
struct TcpState {
|
||||
Tcl_Channel channel; /* Channel associated with this socket. */
|
||||
int testFlags; /* bit field for tests. Is set by testsocket
|
||||
* test procedure */
|
||||
};
|
||||
|
||||
TCL_DECLARE_MUTEX(asyncTestMutex)
|
||||
|
||||
static TestAsyncHandler *firstHandler = NULL;
|
||||
@@ -364,6 +376,8 @@ static int TestChannelCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int argc, const char **argv);
|
||||
static int TestChannelEventCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int argc, const char **argv);
|
||||
static int TestSocketCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int argc, const char **argv);
|
||||
static int TestFilesystemObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -676,6 +690,8 @@ Tcltest_Init(
|
||||
TestNumUtfCharsCmd, NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testsocket", TestSocketCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testtranslatefilename",
|
||||
@@ -3405,7 +3421,7 @@ TestMathFunc2(
|
||||
resultPtr->type = TCL_WIDE_INT;
|
||||
resultPtr->wideValue = ((w0 > w1)? w0 : w1);
|
||||
} else {
|
||||
Tcl_SetResult(interp, (char *)"T3: wrong type for arg 2", TCL_STATIC);
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 2", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else if (args[0].type == TCL_DOUBLE) {
|
||||
@@ -3427,7 +3443,7 @@ TestMathFunc2(
|
||||
resultPtr->type = TCL_DOUBLE;
|
||||
resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
|
||||
} else {
|
||||
Tcl_SetResult(interp, (char *)"T3: wrong type for arg 2", TCL_STATIC);
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 2", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else if (args[0].type == TCL_WIDE_INT) {
|
||||
@@ -3450,11 +3466,11 @@ TestMathFunc2(
|
||||
resultPtr->type = TCL_WIDE_INT;
|
||||
resultPtr->wideValue = ((w0 > w1)? w0 : w1);
|
||||
} else {
|
||||
Tcl_SetResult(interp, (char *)"T3: wrong type for arg 2", TCL_STATIC);
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 2", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
Tcl_SetResult(interp, (char *)"T3: wrong type for arg 1", TCL_STATIC);
|
||||
Tcl_AppendResult(interp, "T3: wrong type for arg 1", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
return result;
|
||||
@@ -3847,6 +3863,7 @@ TestprintObjCmd(
|
||||
Tcl_Obj *const objv[]) /* The argument objects. */
|
||||
{
|
||||
Tcl_WideInt argv1 = 0;
|
||||
size_t argv2;
|
||||
|
||||
if (objc < 2 || objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "format wideint");
|
||||
@@ -3855,7 +3872,8 @@ TestprintObjCmd(
|
||||
if (objc > 1) {
|
||||
Tcl_GetWideIntFromObj(interp, objv[2], &argv1);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(Tcl_GetString(objv[1]), argv1));
|
||||
argv2 = (size_t)argv1;
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(Tcl_GetString(objv[1]), argv1, argv2, argv2));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -6076,6 +6094,75 @@ TestChannelEventCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TestSocketCmd --
|
||||
*
|
||||
* Implements the Tcl "testsocket" debugging command and its
|
||||
* subcommands. This is part of the testing environment.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
TestSocketCmd(
|
||||
ClientData clientData, /* Not used. */
|
||||
Tcl_Interp *interp, /* Interpreter for result. */
|
||||
int argc, /* Count of additional args. */
|
||||
const char **argv) /* Additional arg strings. */
|
||||
{
|
||||
const char *cmdName; /* Sub command. */
|
||||
size_t len; /* Length of subcommand string. */
|
||||
|
||||
if (argc < 2) {
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" subcommand ?additional args..?\"", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
cmdName = argv[1];
|
||||
len = strlen(cmdName);
|
||||
|
||||
if ((cmdName[0] == 't') && (strncmp(cmdName, "testflags", len) == 0)) {
|
||||
Tcl_Channel hChannel;
|
||||
int modePtr;
|
||||
TcpState *statePtr;
|
||||
/* Set test value in the socket driver
|
||||
*/
|
||||
/* Check for argument "channel name"
|
||||
*/
|
||||
if (argc < 4) {
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" testflags channel flags\"", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
hChannel = Tcl_GetChannel(interp, argv[2], &modePtr);
|
||||
if ( NULL == hChannel ) {
|
||||
Tcl_AppendResult(interp, "unknown channel:", argv[2], NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
statePtr = (TcpState *)Tcl_GetChannelInstanceData(hChannel);
|
||||
if ( NULL == statePtr) {
|
||||
Tcl_AppendResult(interp, "No channel instance data:", argv[2],
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
statePtr->testFlags = atoi(argv[3]);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be "
|
||||
"testflags", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -6749,7 +6836,7 @@ TestNumUtfCharsCmd(
|
||||
int len = -1;
|
||||
|
||||
if (objc > 2) {
|
||||
(void) Tcl_GetStringFromObj(objv[1], &len);
|
||||
(void) Tcl_GetIntFromObj(interp, objv[2], &len);
|
||||
}
|
||||
len = Tcl_NumUtfChars(Tcl_GetString(objv[1]), len);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(len));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user