Compare commits
467
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c7e545b80 | ||
|
|
004361c91d | ||
|
|
744e7bfe51 | ||
|
|
9b701fdae7 | ||
|
|
1f197f004a | ||
|
|
3dcb02dc07 | ||
|
|
329c85106b | ||
|
|
334ffdfa50 | ||
|
|
4b98569f89 | ||
|
|
0fe50b37a2 | ||
|
|
c08a9df4d6 | ||
|
|
a60da763ba | ||
|
|
88ab76b3b8 | ||
|
|
5f8f27387d | ||
|
|
ceae73bd28 | ||
|
|
a74fb9ea31 | ||
|
|
cc63d97f54 | ||
|
|
461b9f3322 | ||
|
|
47089ed2b3 | ||
|
|
ff04f434c4 | ||
|
|
e55620ed06 | ||
|
|
052f13167e | ||
|
|
6fb8bfc715 | ||
|
|
f19d7ab302 | ||
|
|
3eb4868d33 | ||
|
|
090475cc9c | ||
|
|
7f2205461c | ||
|
|
b1576079b7 | ||
|
|
125a9f8a25 | ||
|
|
5b5dffa386 | ||
|
|
48b8a3755c | ||
|
|
94d4975fa2 | ||
|
|
604007076c | ||
|
|
3afefe3d81 | ||
|
|
5db8831fb0 | ||
|
|
28721acb58 | ||
|
|
6a8b9ef2d6 | ||
|
|
4715d60689 | ||
|
|
539adc9f7f | ||
|
|
5e1812e37c | ||
|
|
158ab27221 | ||
|
|
edb5d20cbf | ||
|
|
47912a0cab | ||
|
|
d32b2d8171 | ||
|
|
61f362f9a4 | ||
|
|
b4ca74a562 | ||
|
|
8eb9237e4a | ||
|
|
c6cd29b3f9 | ||
|
|
3bb92ad005 | ||
|
|
eccb17258f | ||
|
|
f57343eb42 | ||
|
|
e55ee4d6cc | ||
|
|
2e71d669fe | ||
|
|
07f07faf4b | ||
|
|
63543e9ad0 | ||
|
|
73ccc4ba86 | ||
|
|
9265507b2c | ||
|
|
7974460313 | ||
|
|
5fedb4d01b | ||
|
|
29055898b0 | ||
|
|
7156085860 | ||
|
|
5d76c6e6c0 | ||
|
|
a4eef46453 | ||
|
|
73f53667ed | ||
|
|
fbb32b908c | ||
|
|
1b7b5e839c | ||
|
|
643d4e096b | ||
|
|
8b4cb6f5d9 | ||
|
|
54a7fb1431 | ||
|
|
d7461d07ad | ||
|
|
f4401162e8 | ||
|
|
a84b51c1b4 | ||
|
|
e538095963 | ||
|
|
99a5afc6e0 | ||
|
|
61c463f55f | ||
|
|
2ff193dc57 | ||
|
|
7d850a310d | ||
|
|
95eec569fd | ||
|
|
fa53de3d90 | ||
|
|
f1ace09e64 | ||
|
|
f54edc88cf | ||
|
|
04fbce15ca | ||
|
|
e083b8e9bb | ||
|
|
65baa666b5 | ||
|
|
22c5cd91eb | ||
|
|
48ecb1a2ee | ||
|
|
75e37a235a | ||
|
|
e29e8eee24 | ||
|
|
84a26717ef | ||
|
|
643b20e2b2 | ||
|
|
68f4187dd1 | ||
|
|
01ccb9ccaa | ||
|
|
3fd76e6ba7 | ||
|
|
7218e5967c | ||
|
|
cc1b3e8ddc | ||
|
|
c4669a8b0c | ||
|
|
a0d540327f | ||
|
|
2d6278c829 | ||
|
|
ba89a15d53 | ||
|
|
d8b36a0216 | ||
|
|
b8c001575a | ||
|
|
681e50da88 | ||
|
|
b04c31eecb | ||
|
|
acdf0e593a | ||
|
|
3c51a58c1e | ||
|
|
acce1f902b | ||
|
|
9888275261 | ||
|
|
01f9f84db5 | ||
|
|
9bed70dea4 | ||
|
|
3ab2f65ec6 | ||
|
|
322ea4d71d | ||
|
|
fd83709b45 | ||
|
|
c09e2ded08 | ||
|
|
8e5e88f4db | ||
|
|
d3c1978e07 | ||
|
|
fb36ca1b18 | ||
|
|
27ce96cd71 | ||
|
|
abd9269a04 | ||
|
|
aacc275d30 | ||
|
|
0b7940e00e | ||
|
|
183a28c109 | ||
|
|
c4f8c1063c | ||
|
|
438b6b5009 | ||
|
|
a95f198d2e | ||
|
|
87d82b22e7 | ||
|
|
e0c1d41f5e | ||
|
|
1a41595e06 | ||
|
|
2d4cef6d56 | ||
|
|
f8ff5f9f13 | ||
|
|
210aa9605a | ||
|
|
19292d74bf | ||
|
|
ab5b2feda0 | ||
|
|
35a41cd0d6 | ||
|
|
9873314d0d | ||
|
|
f3f494358f | ||
|
|
0c9e9be9e5 | ||
|
|
e024894c53 | ||
|
|
e3220aa631 | ||
|
|
47d1451282 | ||
|
|
5f636c9b81 | ||
|
|
45659eebd2 | ||
|
|
3ec273770b | ||
|
|
c69e73e183 | ||
|
|
fa12c3782d | ||
|
|
af15fe284a | ||
|
|
d7f092d1cf | ||
|
|
fea67060de | ||
|
|
ea20dfbaae | ||
|
|
da22d54b77 | ||
|
|
e4bf3a0afd | ||
|
|
473f2fb8dd | ||
|
|
29d26aa2c1 | ||
|
|
fecf0d5e64 | ||
|
|
b70fbe851c | ||
|
|
747725c1fc | ||
|
|
f60122dc91 | ||
|
|
dfb3ea8358 | ||
|
|
da5348ec0f | ||
|
|
322bd5dd1f | ||
|
|
9f8bc994a9 | ||
|
|
a7101c49af | ||
|
|
ea3c325aa5 | ||
|
|
9915e77374 | ||
|
|
9db9d4ff84 | ||
|
|
335591836a | ||
|
|
e9e54156fa | ||
|
|
f91d3dd584 | ||
|
|
88d357a99c | ||
|
|
c97d829e0c | ||
|
|
be0324597a | ||
|
|
fcca5df8d6 | ||
|
|
7284ed46fb | ||
|
|
5b2fb22633 | ||
|
|
16c608178f | ||
|
|
924739ac23 | ||
|
|
fdcd434e12 | ||
|
|
5d9aef7a4e | ||
|
|
b497ad4e53 | ||
|
|
a95a8e4a9c | ||
|
|
d10806530d | ||
|
|
c867dfd034 | ||
|
|
601ecb35c8 | ||
|
|
87fc10a8da | ||
|
|
32d3c7b2a1 | ||
|
|
42143bf4e9 | ||
|
|
a7350e3489 | ||
|
|
8a33c02a15 | ||
|
|
1abf8e4ad8 | ||
|
|
e92b34ab12 | ||
|
|
59e40535f5 | ||
|
|
3d4fa09102 | ||
|
|
5e96fb5ee1 | ||
|
|
d0e001a334 | ||
|
|
8bf9869083 | ||
|
|
269a88ebaf | ||
|
|
9757dd7eba | ||
|
|
9365e418f3 | ||
|
|
ebb15ded42 | ||
|
|
2f51a2e128 | ||
|
|
a5f9898e34 | ||
|
|
e2c7cfecc1 | ||
|
|
c736ad3e88 | ||
|
|
3d1b611f4c | ||
|
|
6cfae752ff | ||
|
|
253440c377 | ||
|
|
61e5f733e5 | ||
|
|
77a33cf2ff | ||
|
|
3756d27b06 | ||
|
|
551a220b1f | ||
|
|
a529e32955 | ||
|
|
2e6d32b5a8 | ||
|
|
9bc964b5bb | ||
|
|
daa585d846 | ||
|
|
bc5c5261e5 | ||
|
|
a2e8fa6c52 | ||
|
|
4fa18eaa12 | ||
|
|
f9c41b4bcc | ||
|
|
8655555eb4 | ||
|
|
2a5a3323cb | ||
|
|
2d315899eb | ||
|
|
6ac66b5476 | ||
|
|
2b096d89a3 | ||
|
|
4252a9c191 | ||
|
|
52fe1455a7 | ||
|
|
4c46afc6f5 | ||
|
|
1673f7d67a | ||
|
|
c6eeda71be | ||
|
|
15df01c93d | ||
|
|
1408478f56 | ||
|
|
021c7456ff | ||
|
|
6eb3a60712 | ||
|
|
8837ed8935 | ||
|
|
e5b53212a8 | ||
|
|
97ef11cb6e | ||
|
|
71680aec07 | ||
|
|
4d2bb24e84 | ||
|
|
56214ea49a | ||
|
|
88cddf0b80 | ||
|
|
183b5fd257 | ||
|
|
ff8fef8c8d | ||
|
|
2a7cf86d30 | ||
|
|
0530d01b63 | ||
|
|
e9bb48106a | ||
|
|
c6fabad70e | ||
|
|
88abf586de | ||
|
|
16dcfe4b5f | ||
|
|
bce5a2ae75 | ||
|
|
cb2a1e4c13 | ||
|
|
a62fd8466e | ||
|
|
c7a7120587 | ||
|
|
02d7d5af4c | ||
|
|
3e8c032e35 | ||
|
|
b9409ecdff | ||
|
|
912913c340 | ||
|
|
ac3233bf36 | ||
|
|
934c12d4a4 | ||
|
|
d1f0a7b5f7 | ||
|
|
ee1a8aed63 | ||
|
|
2a00313c29 | ||
|
|
b896860fbf | ||
|
|
6c5d496711 | ||
|
|
66cf21eaaf | ||
|
|
47b0512591 | ||
|
|
080aa64c3d | ||
|
|
f8cfd0ecd0 | ||
|
|
ee4aa52d42 | ||
|
|
ca31b05c9d | ||
|
|
baf55bba6a | ||
|
|
75cae59053 | ||
|
|
10a9e13e5d | ||
|
|
3bb727a3c7 | ||
|
|
e02a90c10d | ||
|
|
5de4bf8981 | ||
|
|
12a4d297b9 | ||
|
|
bef17eed6a | ||
|
|
6bcc85f28e | ||
|
|
61e8875498 | ||
|
|
5350ed1efe | ||
|
|
d08f5c564c | ||
|
|
f5cb50339f | ||
|
|
f3343892a7 | ||
|
|
886199711d | ||
|
|
57182d5ef3 | ||
|
|
5fe3c1fbee | ||
|
|
bfa93a894c | ||
|
|
6ddf4c01d5 | ||
|
|
e5f7fb59c4 | ||
|
|
fa81506a01 | ||
|
|
74ed570183 | ||
|
|
3183209237 | ||
|
|
5bef69e253 | ||
|
|
3f6201e538 | ||
|
|
596cd02dba | ||
|
|
ecec9dacef | ||
|
|
ece5f1377f | ||
|
|
c98d055207 | ||
|
|
45f1f60132 | ||
|
|
ff27c27a27 | ||
|
|
3e6fc11b81 | ||
|
|
e622e61b3a | ||
|
|
2f73d6810c | ||
|
|
378008089c | ||
|
|
8f2742b2f5 | ||
|
|
4a58d3c00a | ||
|
|
4840e7dbb4 | ||
|
|
e31901dcd5 | ||
|
|
2207a65968 | ||
|
|
282de06cab | ||
|
|
8f14151916 | ||
|
|
e8e909f1cd | ||
|
|
6733e57835 | ||
|
|
6978c989d7 | ||
|
|
d888a526f4 | ||
|
|
ada7d66e9f | ||
|
|
1a8dc819d6 | ||
|
|
b3bfa3ee1d | ||
|
|
b6212a88b3 | ||
|
|
01eab1e2cd | ||
|
|
90725c211b | ||
|
|
90d3294572 | ||
|
|
6e09fe5ab9 | ||
|
|
fa1ab4f740 | ||
|
|
3ac01c586f | ||
|
|
c65342141a | ||
|
|
0e8e132aca | ||
|
|
d4cb991846 | ||
|
|
e51a0bd096 | ||
|
|
521821debf | ||
|
|
06a0036a49 | ||
|
|
c91f173c8b | ||
|
|
ec145024fd | ||
|
|
47f1107ebc | ||
|
|
78bbf020ea | ||
|
|
342aec6684 | ||
|
|
f0882154a8 | ||
|
|
89583a6623 | ||
|
|
0258413bde | ||
|
|
e175773277 | ||
|
|
b6ae0212a1 | ||
|
|
5ff110b484 | ||
|
|
438b687249 | ||
|
|
8c3bcfe950 | ||
|
|
cacb796441 | ||
|
|
cad363e97d | ||
|
|
f54081e9e5 | ||
|
|
40094302e0 | ||
|
|
c7569e1c35 | ||
|
|
ae659fdb12 | ||
|
|
fc5e6debde | ||
|
|
876dd3ac96 | ||
|
|
8c665116c9 | ||
|
|
1eb2dfe0fc | ||
|
|
f53e4a7a0e | ||
|
|
5be047220d | ||
|
|
510244810f | ||
|
|
9f92115d2d | ||
|
|
ad8e3dcb0a | ||
|
|
f77ffeb9b2 | ||
|
|
c574af192d | ||
|
|
fd4bc0f106 | ||
|
|
cca7f018e0 | ||
|
|
e12cc95f12 | ||
|
|
beb8c62dff | ||
|
|
684c2c9051 | ||
|
|
767efbf478 | ||
|
|
b4b95b976a | ||
|
|
2c59046c95 | ||
|
|
f11f5780e0 | ||
|
|
c00d7aa9b9 | ||
|
|
050c8a639f | ||
|
|
248247d828 | ||
|
|
42f972d403 | ||
|
|
a92cc7b340 | ||
|
|
b6ac569a5d | ||
|
|
2c00f457ae | ||
|
|
4a8456e406 | ||
|
|
63d77c0046 | ||
|
|
cc6eaf6308 | ||
|
|
6597355ad8 | ||
|
|
c53002fe3b | ||
|
|
2c2a7d737a | ||
|
|
d250eba26d | ||
|
|
2585021472 | ||
|
|
518e457db3 | ||
|
|
7afa150e2f | ||
|
|
490384e3e7 | ||
|
|
4e83fe1049 | ||
|
|
5d9939831c | ||
|
|
f4549b8fc4 | ||
|
|
d7803bcb41 | ||
|
|
c25181bd7d | ||
|
|
2ceb7a6077 | ||
|
|
e3bde55a0f | ||
|
|
834d5da992 | ||
|
|
2be298f89d | ||
|
|
c9ae8d64d3 | ||
|
|
477af49f88 | ||
|
|
7716fd3e46 | ||
|
|
e99699b008 | ||
|
|
72fa9a96c8 | ||
|
|
8fc4750efc | ||
|
|
78b4196767 | ||
|
|
1e9a5591d9 | ||
|
|
128e4211ae | ||
|
|
88b2f7f06e | ||
|
|
a994cc42f5 | ||
|
|
12945e9a16 | ||
|
|
2803a8a055 | ||
|
|
29ae06c2d3 | ||
|
|
48459b2357 | ||
|
|
8f95efa4cf | ||
|
|
c8e62b1cfa | ||
|
|
cbc312324e | ||
|
|
03ecb591a6 | ||
|
|
6bb7b1e15d | ||
|
|
a2e12b4377 | ||
|
|
6d9846f8c9 | ||
|
|
666deab1ea | ||
|
|
bb9e19e6eb | ||
|
|
ea8a9ba071 | ||
|
|
430c9bc178 | ||
|
|
e7e7bafe96 | ||
|
|
9c349ce2e2 | ||
|
|
e7f9c9c822 | ||
|
|
83fcae9bbe | ||
|
|
d5961a83e0 | ||
|
|
9c6b83d5b1 | ||
|
|
8a115927af | ||
|
|
68cab10668 | ||
|
|
c28c2d5b9a | ||
|
|
78f85049ff | ||
|
|
a30f092ea3 | ||
|
|
4f13f826e4 | ||
|
|
1c54736c0d | ||
|
|
f9dd75e79c | ||
|
|
d423ce0c06 | ||
|
|
76b954ec41 | ||
|
|
c45f1130d1 | ||
|
|
0891bbbcbb | ||
|
|
05feb2c73f | ||
|
|
0e49a49b8f | ||
|
|
57dc79f34e | ||
|
|
413a0c2501 | ||
|
|
76007824cc | ||
|
|
db5995b2b8 | ||
|
|
9083b5bf61 | ||
|
|
4ad593f2bf | ||
|
|
cdacc33cbb | ||
|
|
f7157671ce | ||
|
|
b004b21242 | ||
|
|
2a15c7082e | ||
|
|
9901b732cc | ||
|
|
ffb2a3d9b4 | ||
|
|
0eb33efc7a | ||
|
|
53baa9e5c4 | ||
|
|
af735a0ba9 | ||
|
|
a7b60b26f1 | ||
|
|
d6bd07fecc | ||
|
|
f497ce9a95 | ||
|
|
414163addc | ||
|
|
71fd534215 | ||
|
|
b8bcc352ea | ||
|
|
f04eef80d7 | ||
|
|
2de2d8678f | ||
|
|
d5e04d6200 | ||
|
|
6d14b815b2 | ||
|
|
ed18777278 |
Regular → Executable
Regular → Executable
Executable → Regular
Executable → Regular
+3
-2
@@ -637,8 +637,9 @@ On output, produces a locale-dependent time of day representation on a
|
||||
12-hour clock. On input, accepts whatever \fB%r\fR produces.
|
||||
.TP
|
||||
\fB%R\fR
|
||||
On output, produces a locale-dependent time of day representation on a
|
||||
24-hour clock. On input, accepts whatever \fB%R\fR produces.
|
||||
On output, the time in 24-hour notation (%H:%M). For a version
|
||||
including the seconds, see \fB%T\fR below. On input, accepts whatever
|
||||
\fB%R\fR produces.
|
||||
.TP
|
||||
\fB%s\fR
|
||||
On output, simply formats the \fItimeVal\fR argument as a decimal
|
||||
|
||||
+10
-6
@@ -25,11 +25,12 @@ below for a description), depending on \fIoption\fR. The legal
|
||||
This appends the given string (or strings) to the value that the given
|
||||
key maps to in the dictionary value contained in the given variable,
|
||||
writing the resulting dictionary value back to that variable.
|
||||
Non-existent keys are treated as if they map to an empty string.
|
||||
Non-existent keys are treated as if they map to an empty string. The
|
||||
updated dictionary value is returned.
|
||||
.TP
|
||||
\fBdict create \fR?\fIkey value ...\fR?
|
||||
.
|
||||
Create a new dictionary that contains each of the key/value mappings
|
||||
Return a new dictionary that contains each of the key/value mappings
|
||||
listed as arguments (keys and values alternating, with each key being
|
||||
followed by its associated value.)
|
||||
.TP
|
||||
@@ -121,7 +122,8 @@ not specified) to the value that the given key maps to in the
|
||||
dictionary value contained in the given variable, writing the
|
||||
resulting dictionary value back to that variable. Non-existent keys
|
||||
are treated as if they map to 0. It is an error to increment a value
|
||||
for an existing key if that value is not an integer.
|
||||
for an existing key if that value is not an integer. The updated
|
||||
dictionary value is returned.
|
||||
.TP
|
||||
\fBdict info \fIdictionaryValue\fR
|
||||
.
|
||||
@@ -145,7 +147,8 @@ to in the dictionary value contained in the given variable, writing
|
||||
the resulting dictionary value back to that variable. Non-existent
|
||||
keys are treated as if they map to an empty list, and it is legal for
|
||||
there to be no items to append to the list. It is an error for the
|
||||
value that the key maps to to not be representable as a list.
|
||||
value that the key maps to to not be representable as a list. The
|
||||
updated dictionary value is returned.
|
||||
.TP
|
||||
\fBdict map \fR{\fIkeyVar valueVar\fR} \fIdictionaryValue body\fR
|
||||
.
|
||||
@@ -202,7 +205,7 @@ This operation takes the name of a variable containing a dictionary
|
||||
value and places an updated dictionary value in that variable
|
||||
containing a mapping from the given key to the given value. When
|
||||
multiple keys are present, this operation creates or updates a chain
|
||||
of nested dictionaries.
|
||||
of nested dictionaries. The updated dictionary value is returned.
|
||||
.TP
|
||||
\fBdict size \fIdictionaryValue\fR
|
||||
.
|
||||
@@ -216,7 +219,8 @@ dictionary value in that variable that does not contain a mapping for
|
||||
the given key. Where multiple keys are present, this describes a path
|
||||
through nested dictionaries to the mapping to remove. At least one key
|
||||
must be specified, but the last key on the key-path need not exist.
|
||||
All other components on the path must exist.
|
||||
All other components on the path must exist. The updated dictionary
|
||||
value is returned.
|
||||
.TP
|
||||
\fBdict update \fIdictionaryVariable key varName \fR?\fIkey varName ...\fR? \fIbody\fR
|
||||
.
|
||||
|
||||
+27
-7
@@ -14,10 +14,21 @@ encoding \- Manipulate encodings
|
||||
.BE
|
||||
.SH INTRODUCTION
|
||||
.PP
|
||||
Strings in Tcl are encoded using 16-bit Unicode characters. Different
|
||||
operating system interfaces or applications may generate strings in
|
||||
other encodings such as Shift-JIS. The \fBencoding\fR command helps
|
||||
to bridge the gap between Unicode and these other formats.
|
||||
Strings in Tcl are logically a sequence of 16-bit Unicode characters.
|
||||
These strings are represented in memory as a sequence of bytes that
|
||||
may be in one of several encodings: modified UTF\-8 (which uses 1 to 3
|
||||
bytes per character), 16-bit
|
||||
.QW Unicode
|
||||
(which uses 2 bytes per character, with an endianness that is
|
||||
dependent on the host architecture), and binary (which uses a single
|
||||
byte per character but only handles a restricted range of characters).
|
||||
Tcl does not guarantee to always use the same encoding for the same
|
||||
string.
|
||||
.PP
|
||||
Different operating system interfaces or applications may generate
|
||||
strings in other encodings such as Shift\-JIS. The \fBencoding\fR
|
||||
command helps to bridge the gap between Unicode and these other
|
||||
formats.
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Performs one of several encoding related operations, depending on
|
||||
@@ -37,8 +48,9 @@ system encoding is used.
|
||||
Convert \fIstring\fR from Unicode to the specified \fIencoding\fR.
|
||||
The result is a sequence of bytes that represents the converted
|
||||
string. Each byte is stored in the lower 8-bits of a Unicode
|
||||
character. If \fIencoding\fR is not specified, the current
|
||||
system encoding is used.
|
||||
character (indeed, the resulting string is a binary string as far as
|
||||
Tcl is concerned, at least initially). If \fIencoding\fR is not
|
||||
specified, the current system encoding is used.
|
||||
.TP
|
||||
\fBencoding dirs\fR ?\fIdirectoryList\fR?
|
||||
.
|
||||
@@ -56,6 +68,11 @@ searchable directory, that element is ignored.
|
||||
.
|
||||
Returns a list containing the names of all of the encodings that are
|
||||
currently available.
|
||||
The encodings
|
||||
.QW utf-8
|
||||
and
|
||||
.QW iso8859-1
|
||||
are guaranteed to be present in the list.
|
||||
.TP
|
||||
\fBencoding system\fR ?\fIencoding\fR?
|
||||
.
|
||||
@@ -73,7 +90,7 @@ However, because the \fBsource\fR command always reads files using the
|
||||
current system encoding, Tcl will only source such files correctly
|
||||
when the encoding used to write the file is the same. This tends not
|
||||
to be true in an internationalized setting. For example, if such a
|
||||
file was sourced in North America (where the ISO8859-1 is normally
|
||||
file was sourced in North America (where the ISO8859\-1 is normally
|
||||
used), each byte in the file would be treated as a separate character
|
||||
that maps to the 00 page in Unicode. The resulting Tcl strings will
|
||||
not contain the expected Japanese characters. Instead, they will
|
||||
@@ -93,3 +110,6 @@ which is the Hiragana letter HA.
|
||||
Tcl_GetEncoding(3)
|
||||
.SH KEYWORDS
|
||||
encoding, unicode
|
||||
.\" Local Variables:
|
||||
.\" mode: nroff
|
||||
.\" End:
|
||||
|
||||
+24
-3
@@ -46,8 +46,11 @@ non-blocking mode; the \fBfcopy\fR command takes care of that automatically.
|
||||
However, it is necessary to enter the event loop by using
|
||||
the \fBvwait\fR command or by using Tk.
|
||||
.PP
|
||||
You are not allowed to do other I/O operations with
|
||||
\fIinchan\fR or \fIoutchan\fR during a background \fBfcopy\fR.
|
||||
You are not allowed to do other input operations with \fIinchan\fR, or
|
||||
output operations with \fIoutchan\fR, during a background
|
||||
\fBfcopy\fR. The converse is entirely legitimate, as exhibited by the
|
||||
bidirectional fcopy example below.
|
||||
.PP
|
||||
If either \fIinchan\fR or \fIoutchan\fR get closed
|
||||
while the copy is in progress, the current copy is stopped
|
||||
and the command callback is \fInot\fR made.
|
||||
@@ -57,7 +60,7 @@ then all data already queued for \fIoutchan\fR is written out.
|
||||
Note that \fIinchan\fR can become readable during a background copy.
|
||||
You should turn off any \fBfileevent\fR handlers during a background
|
||||
copy so those handlers do not interfere with the copy.
|
||||
Any I/O attempted by a \fBfileevent\fR handler will get a
|
||||
Any wrong-sided I/O attempted (by a \fBfileevent\fR handler or otherwise) will get a
|
||||
.QW "channel busy"
|
||||
error.
|
||||
.PP
|
||||
@@ -149,6 +152,24 @@ set total 0
|
||||
-command [list CopyMore $in $out $chunk]
|
||||
vwait done
|
||||
.CE
|
||||
.PP
|
||||
The fourth example starts an asynchronous, bidirectional fcopy between
|
||||
two sockets. Those could also be pipes from two [open "|hal 9000" r+]
|
||||
(though their conversation would remain secret to the script, since
|
||||
all four fileevent slots are busy).
|
||||
.PP
|
||||
.CS
|
||||
set flows 2
|
||||
proc Done {dir args} {
|
||||
global flows done
|
||||
puts "$dir is over."
|
||||
incr flows -1
|
||||
if {$flows<=0} {set done 1}
|
||||
}
|
||||
\fBfcopy\fR $sok1 $sok2 -command [list Done UP]
|
||||
\fBfcopy\fR $sok2 $sok1 -command [list Done DOWN]
|
||||
vwait done
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
eof(n), fblocked(n), fconfigure(n), file(n)
|
||||
.SH KEYWORDS
|
||||
|
||||
Executable → Regular
+24
-4
@@ -343,10 +343,13 @@ misleading.
|
||||
\fBstring bytelength \fIstring\fR
|
||||
.
|
||||
Returns a decimal string giving the number of bytes used to represent
|
||||
\fIstring\fR in memory. Because UTF\-8 uses one to three bytes to
|
||||
represent Unicode characters, the byte length will not be the same as
|
||||
the character length in general. The cases where a script cares about
|
||||
the byte length are rare.
|
||||
\fIstring\fR in memory when encoded as Tcl's internal modified UTF\-8;
|
||||
Tcl may use other encodings for \fIstring\fR as well, and does not
|
||||
guarantee to only use a single encoding for a particular \fIstring\fR.
|
||||
Because UTF\-8 uses a variable number of bytes to represent Unicode
|
||||
characters, the byte length will not be the same as the character
|
||||
length in general. The cases where a script cares about the byte
|
||||
length are rare.
|
||||
.RS
|
||||
.PP
|
||||
In almost all cases, you should use the
|
||||
@@ -354,10 +357,27 @@ In almost all cases, you should use the
|
||||
Tcl byte array value). Refer to the \fBTcl_NumUtfChars\fR manual
|
||||
entry for more details on the UTF\-8 representation.
|
||||
.PP
|
||||
Formally, the \fBstring bytelength\fR operation returns the content of
|
||||
the \fIlength\fR field of the \fBTcl_Obj\fR structure, after calling
|
||||
\fBTcl_GetString\fR to ensure that the \fIbytes\fR field is populated.
|
||||
This is highly unlikely to be useful to Tcl scripts, as Tcl's internal
|
||||
encoding is not strict UTF\-8, but rather a modified CESU\-8 with a
|
||||
denormalized NUL (identical to that used in a number of places by
|
||||
Java's serialization mechanism) to enable basic processing with
|
||||
non-Unicode-aware C functions. As this representation should only
|
||||
ever be used by Tcl's implementation, the number of bytes used to
|
||||
store the representation is of very low value (except to C extension
|
||||
code, which has direct access for the purpose of memory management,
|
||||
etc.)
|
||||
.PP
|
||||
\fICompatibility note:\fR it is likely that this subcommand will be
|
||||
withdrawn in a future version of Tcl. It is better to use the
|
||||
\fBencoding convertto\fR command to convert a string to a known
|
||||
encoding and then apply \fBstring length\fR to that.
|
||||
.PP
|
||||
.CS
|
||||
\fBstring length\fR [encoding convertto utf-8 $theString]
|
||||
.CE
|
||||
.RE
|
||||
.TP
|
||||
\fBstring wordend \fIstring charIndex\fR
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_precision, tcl_rcFileName, tcl_traceCompile, tcl_traceEval, tcl_wordchars, tcl_version \- Variables used by Tcl
|
||||
argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_precision, tcl_rcFileName, tcl_traceCompile, tcl_traceExec, tcl_wordchars, tcl_version \- Variables used by Tcl
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@@ -347,8 +347,8 @@ was compiled with threads enabled.
|
||||
.
|
||||
This identifies the
|
||||
current user based on the login information available on the platform.
|
||||
This comes from the USER or LOGNAME environment variable on Unix,
|
||||
and the value from GetUserName on Windows.
|
||||
This value comes from the getuid() and getpwuid() system calls on Unix,
|
||||
and the value from the GetUserName() system call on Windows.
|
||||
.TP
|
||||
\fBwordSize\fR
|
||||
.
|
||||
|
||||
+23
-20
@@ -67,15 +67,12 @@ extern "C" {
|
||||
* We use this method because there is no autoconf equivalent.
|
||||
*/
|
||||
|
||||
#ifndef __WIN32__
|
||||
# if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || defined(__BORLANDC__) || (defined(__WATCOMC__) && defined(__WINDOWS_386__))
|
||||
#ifdef _WIN32
|
||||
# ifndef __WIN32__
|
||||
# define __WIN32__
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
# ifndef _WIN32
|
||||
# define _WIN32
|
||||
# endif
|
||||
# endif
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -83,11 +80,11 @@ extern "C" {
|
||||
* STRICT: See MSDN Article Q83456
|
||||
*/
|
||||
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
# ifndef STRICT
|
||||
# define STRICT
|
||||
# endif
|
||||
#endif /* __WIN32__ */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
* Utility macros: STRINGIFY takes an argument and wraps it in "" (double
|
||||
@@ -191,7 +188,7 @@ extern "C" {
|
||||
* MSVCRT.
|
||||
*/
|
||||
|
||||
#if (defined(__WIN32__) && (defined(_MSC_VER) || (__BORLANDC__ >= 0x0550) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
|
||||
#if (defined(_WIN32) && (defined(_MSC_VER) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0550)) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
|
||||
# define HAVE_DECLSPEC 1
|
||||
# ifdef STATIC_BUILD
|
||||
# define DLLIMPORT
|
||||
@@ -315,14 +312,14 @@ extern "C" {
|
||||
* VOID. This block is skipped under Cygwin and Mingw.
|
||||
*/
|
||||
|
||||
#if defined(__WIN32__) && !defined(HAVE_WINNT_IGNORE_VOID)
|
||||
#if defined(_WIN32) && !defined(HAVE_WINNT_IGNORE_VOID)
|
||||
#ifndef VOID
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef short SHORT;
|
||||
typedef long LONG;
|
||||
#endif
|
||||
#endif /* __WIN32__ && !HAVE_WINNT_IGNORE_VOID */
|
||||
#endif /* _WIN32 && !HAVE_WINNT_IGNORE_VOID */
|
||||
|
||||
/*
|
||||
* Macro to use instead of "void" for arguments that must have type "void *"
|
||||
@@ -390,7 +387,7 @@ typedef long LONG;
|
||||
*/
|
||||
|
||||
#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
|
||||
# if defined(__WIN32__)
|
||||
# if defined(_WIN32)
|
||||
# define TCL_WIDE_INT_TYPE __int64
|
||||
# ifdef __BORLANDC__
|
||||
# define TCL_LL_MODIFIER "L"
|
||||
@@ -400,7 +397,7 @@ typedef long LONG;
|
||||
# elif defined(__GNUC__)
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
# else /* ! __WIN32__ && ! __GNUC__ */
|
||||
# else /* ! _WIN32 && ! __GNUC__ */
|
||||
/*
|
||||
* Don't know what platform it is and configure hasn't discovered what is
|
||||
* going on for us. Try to guess...
|
||||
@@ -415,7 +412,7 @@ typedef long LONG;
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# endif
|
||||
# endif /* NO_LIMITS_H */
|
||||
# endif /* __WIN32__ */
|
||||
# endif /* _WIN32 */
|
||||
#endif /* !TCL_WIDE_INT_TYPE & !TCL_WIDE_INT_IS_LONG */
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
# undef TCL_WIDE_INT_TYPE
|
||||
@@ -447,7 +444,7 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
# define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val)))
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#if defined(_WIN32)
|
||||
# ifdef __BORLANDC__
|
||||
typedef struct stati64 Tcl_StatBuf;
|
||||
# elif defined(_WIN64)
|
||||
@@ -562,7 +559,7 @@ typedef struct Tcl_ZLibStream_ *Tcl_ZlibStream;
|
||||
* will be called as the main fuction of the new thread created by that call.
|
||||
*/
|
||||
|
||||
#if defined __WIN32__
|
||||
#if defined _WIN32
|
||||
typedef unsigned (__stdcall Tcl_ThreadCreateProc) (ClientData clientData);
|
||||
#else
|
||||
typedef void (Tcl_ThreadCreateProc) (ClientData clientData);
|
||||
@@ -574,7 +571,7 @@ typedef void (Tcl_ThreadCreateProc) (ClientData clientData);
|
||||
* in generic/tclThreadTest.c for it's usage.
|
||||
*/
|
||||
|
||||
#if defined __WIN32__
|
||||
#if defined _WIN32
|
||||
# define Tcl_ThreadCreateType unsigned __stdcall
|
||||
# define TCL_THREAD_CREATE_RETURN return 0
|
||||
#else
|
||||
@@ -2436,9 +2433,15 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
|
||||
/*
|
||||
* Include platform specific public function declarations that are accessible
|
||||
* via the stubs table.
|
||||
* via the stubs table. Make all TclOO symbols MODULE_SCOPE (which only
|
||||
* has effect on building it as a shared library). See ticket [3010352].
|
||||
*/
|
||||
|
||||
#if defined(BUILD_tcl)
|
||||
# undef TCLAPI
|
||||
# define TCLAPI MODULE_SCOPE
|
||||
#endif
|
||||
|
||||
#include "tclPlatDecls.h"
|
||||
|
||||
/*
|
||||
|
||||
+13
-7
@@ -26,6 +26,7 @@
|
||||
*- jumpTable testing
|
||||
*- syntax (?)
|
||||
*- returnCodeBranch
|
||||
*- tclooNext, tclooNextClass
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
@@ -49,7 +50,7 @@ typedef enum BasicBlockCatchState {
|
||||
BBCS_UNKNOWN = 0, /* Catch context has not yet been identified */
|
||||
BBCS_NONE, /* Block is outside of any catch */
|
||||
BBCS_INCATCH, /* Block is within a catch context */
|
||||
BBCS_CAUGHT, /* Block is within a catch context and
|
||||
BBCS_CAUGHT /* Block is within a catch context and
|
||||
* may be executed after an exception fires */
|
||||
} BasicBlockCatchState;
|
||||
|
||||
@@ -120,7 +121,7 @@ enum BasicBlockFlags {
|
||||
* marking it as the start of a 'catch'
|
||||
* sequence. The 'jumpTarget' is the exception
|
||||
* exit from the catch block. */
|
||||
BB_ENDCATCH = (1 << 5), /* Block ends with an 'endCatch' instruction,
|
||||
BB_ENDCATCH = (1 << 5) /* Block ends with an 'endCatch' instruction,
|
||||
* unwinding the catch from the exception
|
||||
* stack. */
|
||||
};
|
||||
@@ -183,7 +184,7 @@ typedef enum TalInstType {
|
||||
* produces N */
|
||||
ASSEM_SINT1, /* One 1-byte signed-integer operand
|
||||
* (INCR_STK_IMM) */
|
||||
ASSEM_SINT4_LVT4, /* Signed 4-byte integer operand followed by
|
||||
ASSEM_SINT4_LVT4 /* Signed 4-byte integer operand followed by
|
||||
* LVT entry. Fixed arity */
|
||||
} TalInstType;
|
||||
|
||||
@@ -437,6 +438,8 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
{"nop", ASSEM_1BYTE, INST_NOP, 0, 0},
|
||||
{"not", ASSEM_1BYTE, INST_LNOT, 1, 1},
|
||||
{"nsupvar", ASSEM_LVT4, INST_NSUPVAR, 2, 1},
|
||||
{"numericType", ASSEM_1BYTE, INST_NUM_TYPE, 1, 1},
|
||||
{"originCmd", ASSEM_1BYTE, INST_ORIGIN_COMMAND, 1, 1},
|
||||
{"over", ASSEM_OVER, INST_OVER, INT_MIN,-1-1},
|
||||
{"pop", ASSEM_1BYTE, INST_POP, 1, 0},
|
||||
{"pushReturnCode", ASSEM_1BYTE, INST_PUSH_RETURN_CODE, 0, 1},
|
||||
@@ -453,9 +456,9 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
| INST_STORE_ARRAY4), 2, 1},
|
||||
{"storeArrayStk", ASSEM_1BYTE, INST_STORE_ARRAY_STK, 3, 1},
|
||||
{"storeStk", ASSEM_1BYTE, INST_STORE_STK, 2, 1},
|
||||
{"strLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1},
|
||||
{"strTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1},
|
||||
{"strUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1},
|
||||
{"strcaseLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1},
|
||||
{"strcaseTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1},
|
||||
{"strcaseUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1},
|
||||
{"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1},
|
||||
{"strcat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1},
|
||||
{"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1},
|
||||
@@ -466,6 +469,7 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
{"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1},
|
||||
{"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1},
|
||||
{"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1},
|
||||
{"strreplace", ASSEM_1BYTE, INST_STR_REPLACE, 4, 1},
|
||||
{"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1},
|
||||
{"strtrim", ASSEM_1BYTE, INST_STR_TRIM, 2, 1},
|
||||
{"strtrimLeft", ASSEM_1BYTE, INST_STR_TRIM_LEFT, 2, 1},
|
||||
@@ -475,6 +479,7 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
{"tclooIsObject", ASSEM_1BYTE, INST_TCLOO_IS_OBJECT, 1, 1},
|
||||
{"tclooNamespace", ASSEM_1BYTE, INST_TCLOO_NS, 1, 1},
|
||||
{"tclooSelf", ASSEM_1BYTE, INST_TCLOO_SELF, 0, 1},
|
||||
{"tryCvtToBoolean", ASSEM_1BYTE, INST_TRY_CVT_TO_BOOLEAN,1, 2},
|
||||
{"tryCvtToNumeric", ASSEM_1BYTE, INST_TRY_CVT_TO_NUMERIC,1, 1},
|
||||
{"uminus", ASSEM_1BYTE, INST_UMINUS, 1, 1},
|
||||
{"unset", ASSEM_BOOL_LVT4,INST_UNSET_SCALAR, 0, 0},
|
||||
@@ -514,7 +519,8 @@ static const unsigned char NonThrowingByteCodes[] = {
|
||||
INST_RESOLVE_COMMAND, /* 154 */
|
||||
INST_STR_TRIM, INST_STR_TRIM_LEFT, INST_STR_TRIM_RIGHT, /* 166-168 */
|
||||
INST_CONCAT_STK, /* 169 */
|
||||
INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE /* 170-172 */
|
||||
INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE, /* 170-172 */
|
||||
INST_NUM_TYPE /* 180 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+38
-24
@@ -259,7 +259,7 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"variable", Tcl_VariableObjCmd, TclCompileVariableCmd, NULL, CMD_IS_SAFE},
|
||||
{"while", Tcl_WhileObjCmd, TclCompileWhileCmd, TclNRWhileObjCmd, CMD_IS_SAFE},
|
||||
{"yield", NULL, TclCompileYieldCmd, TclNRYieldObjCmd, CMD_IS_SAFE},
|
||||
{"yieldto", NULL, NULL, TclNRYieldToObjCmd, CMD_IS_SAFE},
|
||||
{"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE},
|
||||
|
||||
/*
|
||||
* Commands in the OS-interface. Note that many of these are unsafe.
|
||||
@@ -2085,10 +2085,19 @@ Tcl_CreateCommand(
|
||||
*/
|
||||
|
||||
cmdPtr = Tcl_GetHashValue(hPtr);
|
||||
oldRefPtr = cmdPtr->importRefPtr;
|
||||
cmdPtr->importRefPtr = NULL;
|
||||
cmdPtr->refCount++;
|
||||
if (cmdPtr->importRefPtr) {
|
||||
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
|
||||
}
|
||||
|
||||
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
|
||||
|
||||
if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) {
|
||||
oldRefPtr = cmdPtr->importRefPtr;
|
||||
cmdPtr->importRefPtr = NULL;
|
||||
}
|
||||
TclCleanupCommandMacro(cmdPtr);
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
if (!isNew) {
|
||||
/*
|
||||
@@ -2272,10 +2281,19 @@ Tcl_CreateObjCommand(
|
||||
* intact.
|
||||
*/
|
||||
|
||||
oldRefPtr = cmdPtr->importRefPtr;
|
||||
cmdPtr->importRefPtr = NULL;
|
||||
cmdPtr->refCount++;
|
||||
if (cmdPtr->importRefPtr) {
|
||||
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
|
||||
}
|
||||
|
||||
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
|
||||
|
||||
if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) {
|
||||
oldRefPtr = cmdPtr->importRefPtr;
|
||||
cmdPtr->importRefPtr = NULL;
|
||||
}
|
||||
TclCleanupCommandMacro(cmdPtr);
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
|
||||
if (!isNew) {
|
||||
/*
|
||||
@@ -3117,12 +3135,13 @@ Tcl_DeleteCommandFromToken(
|
||||
* commands were created that refer back to this command. Delete these
|
||||
* imported commands now.
|
||||
*/
|
||||
|
||||
for (refPtr = cmdPtr->importRefPtr; refPtr != NULL;
|
||||
refPtr = nextRefPtr) {
|
||||
nextRefPtr = refPtr->nextPtr;
|
||||
importCmd = (Tcl_Command) refPtr->importedCmdPtr;
|
||||
Tcl_DeleteCommandFromToken(interp, importCmd);
|
||||
if (!(cmdPtr->flags & CMD_REDEF_IN_PROGRESS)) {
|
||||
for (refPtr = cmdPtr->importRefPtr; refPtr != NULL;
|
||||
refPtr = nextRefPtr) {
|
||||
nextRefPtr = refPtr->nextPtr;
|
||||
importCmd = (Tcl_Command) refPtr->importedCmdPtr;
|
||||
Tcl_DeleteCommandFromToken(interp, importCmd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -8416,8 +8435,7 @@ TclNRYieldToObjCmd(
|
||||
{
|
||||
CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
|
||||
Tcl_Obj *listPtr, *nsObjPtr;
|
||||
Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
|
||||
Tcl_Namespace *ns1Ptr;
|
||||
Tcl_Namespace *nsPtr = TclGetCurrentNamespace(interp);
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?");
|
||||
@@ -8431,11 +8449,13 @@ TclNRYieldToObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the tailcall in the caller env, then just yield.
|
||||
*
|
||||
* This is essentially code from TclNRTailcallObjCmd
|
||||
*/
|
||||
if (((Namespace *) nsPtr)->flags & NS_DYING) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"yieldto called in deleted namespace", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the tailcall in the caller env, then just yield.
|
||||
@@ -8444,15 +8464,9 @@ TclNRYieldToObjCmd(
|
||||
*/
|
||||
|
||||
listPtr = Tcl_NewListObj(objc, objv);
|
||||
|
||||
nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
|
||||
if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr))
|
||||
|| (nsPtr != ns1Ptr)) {
|
||||
Tcl_Panic("yieldto failed to find the proper namespace");
|
||||
}
|
||||
TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
|
||||
|
||||
|
||||
/*
|
||||
* Add the callback in the caller's env, then instruct TEBC to yield.
|
||||
*/
|
||||
|
||||
+33
-41
@@ -610,9 +610,7 @@ UpdateStringOfByteArray(
|
||||
*
|
||||
* This function appends an array of bytes to a byte array object. Note
|
||||
* that the object *must* be unshared, and the array of bytes *must not*
|
||||
* refer to the object being appended to. Also the caller must have
|
||||
* already checked that the final length of the bytearray after the
|
||||
* append operations is complete will not overflow the int range.
|
||||
* refer to the object being appended to.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -631,6 +629,7 @@ TclAppendBytesToByteArray(
|
||||
int len)
|
||||
{
|
||||
ByteArray *byteArrayPtr;
|
||||
int needed;
|
||||
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
|
||||
@@ -639,64 +638,57 @@ TclAppendBytesToByteArray(
|
||||
Tcl_Panic("%s must be called with definite number of bytes to append",
|
||||
"TclAppendBytesToByteArray");
|
||||
}
|
||||
if (len == 0) {
|
||||
/* Append zero bytes is a no-op. */
|
||||
return;
|
||||
}
|
||||
if (objPtr->typePtr != &tclByteArrayType) {
|
||||
SetByteArrayFromAny(NULL, objPtr);
|
||||
}
|
||||
byteArrayPtr = GET_BYTEARRAY(objPtr);
|
||||
|
||||
if (len > INT_MAX - byteArrayPtr->used) {
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
|
||||
}
|
||||
|
||||
needed = byteArrayPtr->used + len;
|
||||
/*
|
||||
* If we need to, resize the allocated space in the byte array.
|
||||
*/
|
||||
|
||||
if (byteArrayPtr->used + len > byteArrayPtr->allocated) {
|
||||
unsigned int attempt, used = byteArrayPtr->used;
|
||||
ByteArray *tmpByteArrayPtr = NULL;
|
||||
if (needed > byteArrayPtr->allocated) {
|
||||
ByteArray *ptr = NULL;
|
||||
int attempt;
|
||||
|
||||
attempt = byteArrayPtr->allocated;
|
||||
if (attempt < 1) {
|
||||
/*
|
||||
* No allocated bytes, so must be none used too. We use this
|
||||
* method to calculate how many bytes to allocate because we can
|
||||
* end up with a zero-length buffer otherwise, when doubling can
|
||||
* cause trouble. [Bug 3067036]
|
||||
*/
|
||||
|
||||
attempt = len + 1;
|
||||
} else {
|
||||
do {
|
||||
attempt *= 2;
|
||||
} while (attempt < used+len);
|
||||
if (needed <= INT_MAX/2) {
|
||||
/* Try to allocate double the total space that is needed. */
|
||||
attempt = 2 * needed;
|
||||
ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
/* Try to allocate double the increment that is needed (plus). */
|
||||
unsigned int limit = INT_MAX - needed;
|
||||
unsigned int extra = len + TCL_MIN_GROWTH;
|
||||
int growth = (int) ((extra > limit) ? limit : extra);
|
||||
|
||||
if (BYTEARRAY_SIZE(attempt) > BYTEARRAY_SIZE(used)) {
|
||||
tmpByteArrayPtr = attemptckrealloc(byteArrayPtr,
|
||||
BYTEARRAY_SIZE(attempt));
|
||||
attempt = needed + growth;
|
||||
ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
|
||||
}
|
||||
|
||||
if (tmpByteArrayPtr == NULL) {
|
||||
attempt = used + len;
|
||||
if (BYTEARRAY_SIZE(attempt) < BYTEARRAY_SIZE(used)) {
|
||||
Tcl_Panic("attempt to allocate a bigger buffer than we can handle");
|
||||
}
|
||||
tmpByteArrayPtr = ckrealloc(byteArrayPtr,
|
||||
BYTEARRAY_SIZE(attempt));
|
||||
if (ptr == NULL) {
|
||||
/* Last chance: Try to allocate exactly what is needed. */
|
||||
attempt = needed;
|
||||
ptr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
|
||||
}
|
||||
|
||||
byteArrayPtr = tmpByteArrayPtr;
|
||||
byteArrayPtr = ptr;
|
||||
byteArrayPtr->allocated = attempt;
|
||||
byteArrayPtr->used = used;
|
||||
SET_BYTEARRAY(objPtr, byteArrayPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the append if there's any point.
|
||||
*/
|
||||
|
||||
if (len > 0) {
|
||||
if (bytes) {
|
||||
memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
|
||||
byteArrayPtr->used += len;
|
||||
TclInvalidateStringRep(objPtr);
|
||||
}
|
||||
byteArrayPtr->used += len;
|
||||
TclInvalidateStringRep(objPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+22
-16
@@ -19,7 +19,7 @@
|
||||
* Windows has mktime. The configurators do not check.
|
||||
*/
|
||||
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
#define HAVE_MKTIME 1
|
||||
#endif
|
||||
|
||||
@@ -548,18 +548,21 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
|
||||
}
|
||||
dict = objv[1];
|
||||
if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
|
||||
&era) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_YEAR],
|
||||
&fieldPtr) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_YEAR], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &fields.year) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_MONTH],
|
||||
&fieldPtr) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_MONTH], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &fields.month) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFMONTH],
|
||||
&fieldPtr) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFMONTH], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &fields.dayOfMonth)!=TCL_OK
|
||||
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
|
||||
if (fieldPtr == NULL)
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("expected key(s) not found in dictionary", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
fields.era = era;
|
||||
@@ -638,18 +641,21 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
|
||||
}
|
||||
dict = objv[1];
|
||||
if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
|
||||
&era) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601YEAR],
|
||||
&fieldPtr) != TCL_OK
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &fields.iso8601Year)!=TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601WEEK],
|
||||
&fieldPtr) != TCL_OK
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &fields.iso8601Week)!=TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFWEEK],
|
||||
&fieldPtr) != TCL_OK
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &fields.dayOfWeek) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601YEAR], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &(fields.iso8601Year)) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601WEEK], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &(fields.iso8601Week)) != TCL_OK
|
||||
|| Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFWEEK], &fieldPtr) != TCL_OK
|
||||
|| fieldPtr == NULL
|
||||
|| TclGetIntFromObj(interp, fieldPtr, &(fields.dayOfWeek)) != TCL_OK
|
||||
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
|
||||
if (fieldPtr == NULL)
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("expected key(s) not found in dictionary", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
fields.era = era;
|
||||
|
||||
+1
-1
@@ -1590,7 +1590,7 @@ FileAttrIsOwnedCmd(
|
||||
* test for equivalence to the current user.
|
||||
*/
|
||||
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__)
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
value = 1;
|
||||
#else
|
||||
value = (geteuid() == buf.st_uid);
|
||||
|
||||
+15
-14
@@ -29,7 +29,7 @@
|
||||
typedef struct SortElement {
|
||||
union { /* The value that we sorting by. */
|
||||
const char *strValuePtr;
|
||||
long intValue;
|
||||
Tcl_WideInt wideValue;
|
||||
double doubleValue;
|
||||
Tcl_Obj *objValuePtr;
|
||||
} collationKey;
|
||||
@@ -2893,7 +2893,8 @@ Tcl_LsearchObjCmd(
|
||||
{
|
||||
const char *bytes, *patternBytes;
|
||||
int i, match, index, result, listc, length, elemLen, bisect;
|
||||
int dataType, isIncreasing, lower, upper, patInt, objInt, offset;
|
||||
int dataType, isIncreasing, lower, upper, offset;
|
||||
Tcl_WideInt patWide, objWide;
|
||||
int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
|
||||
double patDouble, objDouble;
|
||||
SortInfo sortInfo;
|
||||
@@ -3212,7 +3213,7 @@ Tcl_LsearchObjCmd(
|
||||
patternBytes = TclGetStringFromObj(patObj, &length);
|
||||
break;
|
||||
case INTEGER:
|
||||
result = TclGetIntFromObj(interp, patObj, &patInt);
|
||||
result = TclGetWideIntFromObj(interp, patObj, &patWide);
|
||||
if (result != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
@@ -3281,13 +3282,13 @@ Tcl_LsearchObjCmd(
|
||||
match = DictionaryCompare(patternBytes, bytes);
|
||||
break;
|
||||
case INTEGER:
|
||||
result = TclGetIntFromObj(interp, itemPtr, &objInt);
|
||||
result = TclGetWideIntFromObj(interp, itemPtr, &objWide);
|
||||
if (result != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
if (patInt == objInt) {
|
||||
if (patWide == objWide) {
|
||||
match = 0;
|
||||
} else if (patInt < objInt) {
|
||||
} else if (patWide < objWide) {
|
||||
match = -1;
|
||||
} else {
|
||||
match = 1;
|
||||
@@ -3400,14 +3401,14 @@ Tcl_LsearchObjCmd(
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
result = TclGetIntFromObj(interp, itemPtr, &objInt);
|
||||
result = TclGetWideIntFromObj(interp, itemPtr, &objWide);
|
||||
if (result != TCL_OK) {
|
||||
if (listPtr != NULL) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
match = (objInt == patInt);
|
||||
match = (objWide == patWide);
|
||||
break;
|
||||
|
||||
case REAL:
|
||||
@@ -3971,13 +3972,13 @@ Tcl_LsortObjCmd(
|
||||
if (sortMode == SORTMODE_ASCII) {
|
||||
elementArray[i].collationKey.strValuePtr = TclGetString(indexPtr);
|
||||
} else if (sortMode == SORTMODE_INTEGER) {
|
||||
long a;
|
||||
Tcl_WideInt a;
|
||||
|
||||
if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
|
||||
if (TclGetWideIntFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
goto done1;
|
||||
}
|
||||
elementArray[i].collationKey.intValue = a;
|
||||
elementArray[i].collationKey.wideValue = a;
|
||||
} else if (sortMode == SORTMODE_REAL) {
|
||||
double a;
|
||||
|
||||
@@ -4226,10 +4227,10 @@ SortCompare(
|
||||
order = DictionaryCompare(elemPtr1->collationKey.strValuePtr,
|
||||
elemPtr2->collationKey.strValuePtr);
|
||||
} else if (infoPtr->sortMode == SORTMODE_INTEGER) {
|
||||
long a, b;
|
||||
Tcl_WideInt a, b;
|
||||
|
||||
a = elemPtr1->collationKey.intValue;
|
||||
b = elemPtr2->collationKey.intValue;
|
||||
a = elemPtr1->collationKey.wideValue;
|
||||
b = elemPtr2->collationKey.wideValue;
|
||||
order = ((a >= b) - (a <= b));
|
||||
} else if (infoPtr->sortMode == SORTMODE_REAL) {
|
||||
double a, b;
|
||||
|
||||
+34
-34
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclRegexp.h"
|
||||
#include "tclStringTrim.h"
|
||||
|
||||
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
|
||||
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
|
||||
@@ -35,36 +36,35 @@ static int UniCharIsHexDigit(int character);
|
||||
/*
|
||||
* Default set of characters to trim in [string trim] and friends. This is a
|
||||
* UTF-8 literal string containing all Unicode space characters [TIP #413]
|
||||
*
|
||||
* Synch with tclCompCmdsSZ.c
|
||||
*/
|
||||
|
||||
#define DEFAULT_TRIM_SET \
|
||||
"\x09\x0a\x0b\x0c\x0d " /* ASCII */\
|
||||
"\xc0\x80" /* nul (U+0000) */\
|
||||
"\xc2\x85" /* next line (U+0085) */\
|
||||
"\xc2\xa0" /* non-breaking space (U+00a0) */\
|
||||
"\xe1\x9a\x80" /* ogham space mark (U+1680) */ \
|
||||
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */\
|
||||
"\xe2\x80\x80" /* en quad (U+2000) */\
|
||||
"\xe2\x80\x81" /* em quad (U+2001) */\
|
||||
"\xe2\x80\x82" /* en space (U+2002) */\
|
||||
"\xe2\x80\x83" /* em space (U+2003) */\
|
||||
"\xe2\x80\x84" /* three-per-em space (U+2004) */\
|
||||
"\xe2\x80\x85" /* four-per-em space (U+2005) */\
|
||||
"\xe2\x80\x86" /* six-per-em space (U+2006) */\
|
||||
"\xe2\x80\x87" /* figure space (U+2007) */\
|
||||
"\xe2\x80\x88" /* punctuation space (U+2008) */\
|
||||
"\xe2\x80\x89" /* thin space (U+2009) */\
|
||||
"\xe2\x80\x8a" /* hair space (U+200a) */\
|
||||
"\xe2\x80\x8b" /* zero width space (U+200b) */\
|
||||
"\xe2\x80\xa8" /* line separator (U+2028) */\
|
||||
"\xe2\x80\xa9" /* paragraph separator (U+2029) */\
|
||||
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */\
|
||||
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */\
|
||||
"\xe2\x81\xa0" /* word joiner (U+2060) */\
|
||||
"\xe3\x80\x80" /* ideographic space (U+3000) */\
|
||||
const char tclDefaultTrimSet[] =
|
||||
"\x09\x0a\x0b\x0c\x0d " /* ASCII */
|
||||
"\xc0\x80" /* nul (U+0000) */
|
||||
"\xc2\x85" /* next line (U+0085) */
|
||||
"\xc2\xa0" /* non-breaking space (U+00a0) */
|
||||
"\xe1\x9a\x80" /* ogham space mark (U+1680) */
|
||||
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */
|
||||
"\xe2\x80\x80" /* en quad (U+2000) */
|
||||
"\xe2\x80\x81" /* em quad (U+2001) */
|
||||
"\xe2\x80\x82" /* en space (U+2002) */
|
||||
"\xe2\x80\x83" /* em space (U+2003) */
|
||||
"\xe2\x80\x84" /* three-per-em space (U+2004) */
|
||||
"\xe2\x80\x85" /* four-per-em space (U+2005) */
|
||||
"\xe2\x80\x86" /* six-per-em space (U+2006) */
|
||||
"\xe2\x80\x87" /* figure space (U+2007) */
|
||||
"\xe2\x80\x88" /* punctuation space (U+2008) */
|
||||
"\xe2\x80\x89" /* thin space (U+2009) */
|
||||
"\xe2\x80\x8a" /* hair space (U+200a) */
|
||||
"\xe2\x80\x8b" /* zero width space (U+200b) */
|
||||
"\xe2\x80\xa8" /* line separator (U+2028) */
|
||||
"\xe2\x80\xa9" /* paragraph separator (U+2029) */
|
||||
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */
|
||||
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */
|
||||
"\xe2\x81\xa0" /* word joiner (U+2060) */
|
||||
"\xe3\x80\x80" /* ideographic space (U+3000) */
|
||||
"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
|
||||
;
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -3191,8 +3191,8 @@ StringTrimCmd(
|
||||
if (objc == 3) {
|
||||
string2 = TclGetStringFromObj(objv[2], &length2);
|
||||
} else if (objc == 2) {
|
||||
string2 = DEFAULT_TRIM_SET;
|
||||
length2 = strlen(DEFAULT_TRIM_SET);
|
||||
string2 = tclDefaultTrimSet;
|
||||
length2 = strlen(tclDefaultTrimSet);
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
|
||||
return TCL_ERROR;
|
||||
@@ -3239,8 +3239,8 @@ StringTrimLCmd(
|
||||
if (objc == 3) {
|
||||
string2 = TclGetStringFromObj(objv[2], &length2);
|
||||
} else if (objc == 2) {
|
||||
string2 = DEFAULT_TRIM_SET;
|
||||
length2 = strlen(DEFAULT_TRIM_SET);
|
||||
string2 = tclDefaultTrimSet;
|
||||
length2 = strlen(tclDefaultTrimSet);
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
|
||||
return TCL_ERROR;
|
||||
@@ -3285,8 +3285,8 @@ StringTrimRCmd(
|
||||
if (objc == 3) {
|
||||
string2 = TclGetStringFromObj(objv[2], &length2);
|
||||
} else if (objc == 2) {
|
||||
string2 = DEFAULT_TRIM_SET;
|
||||
length2 = strlen(DEFAULT_TRIM_SET);
|
||||
string2 = tclDefaultTrimSet;
|
||||
length2 = strlen(tclDefaultTrimSet);
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
|
||||
return TCL_ERROR;
|
||||
@@ -3332,7 +3332,7 @@ TclInitStringCmd(
|
||||
{"equal", StringEqualCmd, TclCompileStringEqualCmd, NULL, NULL, 0},
|
||||
{"first", StringFirstCmd, TclCompileStringFirstCmd, NULL, NULL, 0},
|
||||
{"index", StringIndexCmd, TclCompileStringIndexCmd, NULL, NULL, 0},
|
||||
{"is", StringIsCmd, NULL, NULL, NULL, 0},
|
||||
{"is", StringIsCmd, TclCompileStringIsCmd, NULL, NULL, 0},
|
||||
{"last", StringLastCmd, TclCompileStringLastCmd, NULL, NULL, 0},
|
||||
{"length", StringLenCmd, TclCompileStringLenCmd, NULL, NULL, 0},
|
||||
{"map", StringMapCmd, TclCompileStringMapCmd, NULL, NULL, 0},
|
||||
|
||||
@@ -65,13 +65,6 @@ const AuxDataType tclDictUpdateInfoType = {
|
||||
FreeDictUpdateInfo, /* freeProc */
|
||||
PrintDictUpdateInfo /* printProc */
|
||||
};
|
||||
|
||||
/*
|
||||
* The definition of what whitespace is stripped when [concat]enating. Must be
|
||||
* kept in synch with tclUtil.c
|
||||
*/
|
||||
|
||||
#define CONCAT_WS " \f\v\r\t\n"
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -285,7 +278,7 @@ TclCompileArraySetCmd(
|
||||
|
||||
if (isDataValid && !isDataEven) {
|
||||
PushStringLiteral(envPtr, "list must have an even number of elements");
|
||||
PushStringLiteral(envPtr, "-errorCode {TCL ARGUMENT FORMAT}");
|
||||
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
|
||||
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
|
||||
TclEmitInt4( 0, envPtr);
|
||||
goto done;
|
||||
@@ -380,7 +373,7 @@ TclCompileArraySetCmd(
|
||||
offsetFwd = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1(INST_JUMP_FALSE1, 0, envPtr);
|
||||
PushStringLiteral(envPtr, "list must have an even number of elements");
|
||||
PushStringLiteral(envPtr, "-errorCode {TCL ARGUMENT FORMAT}");
|
||||
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
|
||||
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
|
||||
TclEmitInt4( 0, envPtr);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
|
||||
@@ -1955,6 +1955,28 @@ TclCompileNamespaceCodeCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileNamespaceOriginCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
Tcl_Token *tokenPtr;
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
|
||||
if (parsePtr->numWords != 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
|
||||
CompileWord(envPtr, tokenPtr, interp, 1);
|
||||
TclEmitOpcode( INST_ORIGIN_COMMAND, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileNamespaceQualifiersCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
@@ -3017,6 +3039,66 @@ IndexTailVarIfKnown(
|
||||
return localIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclCompileObjectNextCmd, TclCompileObjectSelfCmd --
|
||||
*
|
||||
* Compilations of the TclOO utility commands [next] and [self].
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclCompileObjectNextCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
|
||||
int i;
|
||||
|
||||
if (parsePtr->numWords > 255) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
for (i=0 ; i<parsePtr->numWords ; i++) {
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
TclEmitInstInt1( INST_TCLOO_NEXT, i, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileObjectNextToCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
|
||||
int i;
|
||||
|
||||
if (parsePtr->numWords < 2 || parsePtr->numWords > 255) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
for (i=0 ; i<parsePtr->numWords ; i++) {
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
TclEmitInstInt1( INST_TCLOO_NEXT_CLASS, i, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileObjectSelfCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
|
||||
+364
-36
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclCompile.h"
|
||||
#include "tclStringTrim.h"
|
||||
|
||||
/*
|
||||
* Prototypes for procedures defined later in this file:
|
||||
@@ -423,6 +424,284 @@ TclCompileStringIndexCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileStringIsCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
static const char *const isClasses[] = {
|
||||
"alnum", "alpha", "ascii", "control",
|
||||
"boolean", "digit", "double", "entier",
|
||||
"false", "graph", "integer", "list",
|
||||
"lower", "print", "punct", "space",
|
||||
"true", "upper", "wideinteger", "wordchar",
|
||||
"xdigit", NULL
|
||||
};
|
||||
enum isClasses {
|
||||
STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL,
|
||||
STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER,
|
||||
STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST,
|
||||
STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE,
|
||||
STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD,
|
||||
STR_IS_XDIGIT
|
||||
};
|
||||
int t, range, allowEmpty = 0, end;
|
||||
InstStringClassType strClassType;
|
||||
Tcl_Obj *isClass;
|
||||
|
||||
if (parsePtr->numWords < 3 || parsePtr->numWords > 6) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
isClass = Tcl_NewObj();
|
||||
if (!TclWordKnownAtCompileTime(tokenPtr, isClass)) {
|
||||
Tcl_DecrRefCount(isClass);
|
||||
return TCL_ERROR;
|
||||
} else if (Tcl_GetIndexFromObj(interp, isClass, isClasses, "class", 0,
|
||||
&t) != TCL_OK) {
|
||||
Tcl_DecrRefCount(isClass);
|
||||
TclCompileSyntaxError(interp, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
Tcl_DecrRefCount(isClass);
|
||||
|
||||
#define GotLiteral(tokenPtr, word) \
|
||||
((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD && \
|
||||
(tokenPtr)[1].size > 1 && \
|
||||
(tokenPtr)[1].start[0] == word[0] && \
|
||||
strncmp((tokenPtr)[1].start, (word), (tokenPtr)[1].size) == 0)
|
||||
|
||||
/*
|
||||
* Cannot handle the -failindex option at all, and that's the only legal
|
||||
* way to have more than 4 arguments.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 3 && parsePtr->numWords != 4) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (parsePtr->numWords == 3) {
|
||||
allowEmpty = 1;
|
||||
} else {
|
||||
if (!GotLiteral(tokenPtr, "-strict")) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
#undef GotLiteral
|
||||
|
||||
/*
|
||||
* Compile the code. There are several main classes of check here.
|
||||
* 1. Character classes
|
||||
* 2. Booleans
|
||||
* 3. Integers
|
||||
* 4. Floats
|
||||
* 5. Lists
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, tokenPtr, interp, parsePtr->numWords-1);
|
||||
|
||||
switch ((enum isClasses) t) {
|
||||
case STR_IS_ALNUM:
|
||||
strClassType = STR_CLASS_ALNUM;
|
||||
goto compileStrClass;
|
||||
case STR_IS_ALPHA:
|
||||
strClassType = STR_CLASS_ALPHA;
|
||||
goto compileStrClass;
|
||||
case STR_IS_ASCII:
|
||||
strClassType = STR_CLASS_ASCII;
|
||||
goto compileStrClass;
|
||||
case STR_IS_CONTROL:
|
||||
strClassType = STR_CLASS_CONTROL;
|
||||
goto compileStrClass;
|
||||
case STR_IS_DIGIT:
|
||||
strClassType = STR_CLASS_DIGIT;
|
||||
goto compileStrClass;
|
||||
case STR_IS_GRAPH:
|
||||
strClassType = STR_CLASS_GRAPH;
|
||||
goto compileStrClass;
|
||||
case STR_IS_LOWER:
|
||||
strClassType = STR_CLASS_LOWER;
|
||||
goto compileStrClass;
|
||||
case STR_IS_PRINT:
|
||||
strClassType = STR_CLASS_PRINT;
|
||||
goto compileStrClass;
|
||||
case STR_IS_PUNCT:
|
||||
strClassType = STR_CLASS_PUNCT;
|
||||
goto compileStrClass;
|
||||
case STR_IS_SPACE:
|
||||
strClassType = STR_CLASS_SPACE;
|
||||
goto compileStrClass;
|
||||
case STR_IS_UPPER:
|
||||
strClassType = STR_CLASS_UPPER;
|
||||
goto compileStrClass;
|
||||
case STR_IS_WORD:
|
||||
strClassType = STR_CLASS_WORD;
|
||||
goto compileStrClass;
|
||||
case STR_IS_XDIGIT:
|
||||
strClassType = STR_CLASS_XDIGIT;
|
||||
compileStrClass:
|
||||
if (allowEmpty) {
|
||||
OP1( STR_CLASS, strClassType);
|
||||
} else {
|
||||
int over, over2;
|
||||
|
||||
OP( DUP);
|
||||
OP1( STR_CLASS, strClassType);
|
||||
JUMP1( JUMP_TRUE, over);
|
||||
OP( POP);
|
||||
PUSH( "0");
|
||||
JUMP1( JUMP, over2);
|
||||
FIXJUMP1(over);
|
||||
PUSH( "");
|
||||
OP( STR_NEQ);
|
||||
FIXJUMP1(over2);
|
||||
}
|
||||
return TCL_OK;
|
||||
|
||||
case STR_IS_BOOL:
|
||||
case STR_IS_FALSE:
|
||||
case STR_IS_TRUE:
|
||||
OP( TRY_CVT_TO_BOOLEAN);
|
||||
switch (t) {
|
||||
int over, over2;
|
||||
|
||||
case STR_IS_BOOL:
|
||||
if (allowEmpty) {
|
||||
JUMP1( JUMP_TRUE, over);
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
JUMP1( JUMP, over2);
|
||||
FIXJUMP1(over);
|
||||
OP( POP);
|
||||
PUSH( "1");
|
||||
FIXJUMP1(over2);
|
||||
} else {
|
||||
OP4( REVERSE, 2);
|
||||
OP( POP);
|
||||
}
|
||||
return TCL_OK;
|
||||
case STR_IS_TRUE:
|
||||
JUMP1( JUMP_TRUE, over);
|
||||
if (allowEmpty) {
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
} else {
|
||||
OP( POP);
|
||||
PUSH( "0");
|
||||
}
|
||||
FIXJUMP1( over);
|
||||
OP( LNOT);
|
||||
OP( LNOT);
|
||||
return TCL_OK;
|
||||
case STR_IS_FALSE:
|
||||
JUMP1( JUMP_TRUE, over);
|
||||
if (allowEmpty) {
|
||||
PUSH( "");
|
||||
OP( STR_NEQ);
|
||||
} else {
|
||||
OP( POP);
|
||||
PUSH( "1");
|
||||
}
|
||||
FIXJUMP1( over);
|
||||
OP( LNOT);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
case STR_IS_DOUBLE: {
|
||||
int satisfied, isEmpty;
|
||||
|
||||
if (allowEmpty) {
|
||||
OP( DUP);
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
JUMP1( JUMP_TRUE, isEmpty);
|
||||
OP( NUM_TYPE);
|
||||
JUMP1( JUMP_TRUE, satisfied);
|
||||
PUSH( "0");
|
||||
JUMP1( JUMP, end);
|
||||
FIXJUMP1( isEmpty);
|
||||
OP( POP);
|
||||
FIXJUMP1( satisfied);
|
||||
} else {
|
||||
OP( NUM_TYPE);
|
||||
JUMP1( JUMP_TRUE, satisfied);
|
||||
PUSH( "0");
|
||||
JUMP1( JUMP, end);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
FIXJUMP1( satisfied);
|
||||
}
|
||||
PUSH( "1");
|
||||
FIXJUMP1( end);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
case STR_IS_INT:
|
||||
case STR_IS_WIDE:
|
||||
case STR_IS_ENTIER:
|
||||
if (allowEmpty) {
|
||||
int testNumType;
|
||||
|
||||
OP( DUP);
|
||||
OP( NUM_TYPE);
|
||||
OP( DUP);
|
||||
JUMP1( JUMP_TRUE, testNumType);
|
||||
OP( POP);
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
JUMP1( JUMP, end);
|
||||
TclAdjustStackDepth(1, envPtr);
|
||||
FIXJUMP1( testNumType);
|
||||
OP4( REVERSE, 2);
|
||||
OP( POP);
|
||||
} else {
|
||||
OP( NUM_TYPE);
|
||||
OP( DUP);
|
||||
JUMP1( JUMP_FALSE, end);
|
||||
}
|
||||
|
||||
switch (t) {
|
||||
case STR_IS_INT:
|
||||
PUSH( "1");
|
||||
OP( EQ);
|
||||
break;
|
||||
case STR_IS_WIDE:
|
||||
PUSH( "2");
|
||||
OP( LE);
|
||||
break;
|
||||
case STR_IS_ENTIER:
|
||||
PUSH( "3");
|
||||
OP( LE);
|
||||
break;
|
||||
}
|
||||
FIXJUMP1( end);
|
||||
return TCL_OK;
|
||||
|
||||
case STR_IS_LIST:
|
||||
range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
|
||||
OP4( BEGIN_CATCH4, range);
|
||||
ExceptionRangeStarts(envPtr, range);
|
||||
OP( DUP);
|
||||
OP( LIST_LENGTH);
|
||||
OP( POP);
|
||||
ExceptionRangeEnds(envPtr, range);
|
||||
ExceptionRangeTarget(envPtr, range, catchOffset);
|
||||
OP( POP);
|
||||
OP( PUSH_RETURN_CODE);
|
||||
OP( END_CATCH);
|
||||
OP( LNOT);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileStringMatchCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
@@ -700,8 +979,8 @@ TclCompileStringReplaceCmd(
|
||||
|
||||
/*
|
||||
* We handle these replacements specially: first character (where
|
||||
* idx1=idx2=0) and suffixes (where idx1=idx2=INDEX_END). Anything else
|
||||
* and the semantics get rather screwy.
|
||||
* idx1=idx2=0) and last character (where idx1=idx2=INDEX_END). Anything
|
||||
* else and the semantics get rather screwy.
|
||||
*/
|
||||
|
||||
if (idx1 == 0 && idx2 == 0) {
|
||||
@@ -787,37 +1066,6 @@ TclCompileStringReplaceCmd(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Synch with tclCmdMZ.c
|
||||
*/
|
||||
|
||||
#define DEFAULT_TRIM_SET \
|
||||
"\x09\x0a\x0b\x0c\x0d " /* ASCII */\
|
||||
"\xc0\x80" /* nul (U+0000) */\
|
||||
"\xc2\x85" /* next line (U+0085) */\
|
||||
"\xc2\xa0" /* non-breaking space (U+00a0) */\
|
||||
"\xe1\x9a\x80" /* ogham space mark (U+1680) */ \
|
||||
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */\
|
||||
"\xe2\x80\x80" /* en quad (U+2000) */\
|
||||
"\xe2\x80\x81" /* em quad (U+2001) */\
|
||||
"\xe2\x80\x82" /* en space (U+2002) */\
|
||||
"\xe2\x80\x83" /* em space (U+2003) */\
|
||||
"\xe2\x80\x84" /* three-per-em space (U+2004) */\
|
||||
"\xe2\x80\x85" /* four-per-em space (U+2005) */\
|
||||
"\xe2\x80\x86" /* six-per-em space (U+2006) */\
|
||||
"\xe2\x80\x87" /* figure space (U+2007) */\
|
||||
"\xe2\x80\x88" /* punctuation space (U+2008) */\
|
||||
"\xe2\x80\x89" /* thin space (U+2009) */\
|
||||
"\xe2\x80\x8a" /* hair space (U+200a) */\
|
||||
"\xe2\x80\x8b" /* zero width space (U+200b) */\
|
||||
"\xe2\x80\xa8" /* line separator (U+2028) */\
|
||||
"\xe2\x80\xa9" /* paragraph separator (U+2029) */\
|
||||
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */\
|
||||
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */\
|
||||
"\xe2\x81\xa0" /* word joiner (U+2060) */\
|
||||
"\xe3\x80\x80" /* ideographic space (U+3000) */\
|
||||
"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
|
||||
|
||||
int
|
||||
TclCompileStringTrimLCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
@@ -840,7 +1088,7 @@ TclCompileStringTrimLCmd(
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 2);
|
||||
} else {
|
||||
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
|
||||
PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet));
|
||||
}
|
||||
OP( STR_TRIM_LEFT);
|
||||
return TCL_OK;
|
||||
@@ -868,7 +1116,7 @@ TclCompileStringTrimRCmd(
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 2);
|
||||
} else {
|
||||
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
|
||||
PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet));
|
||||
}
|
||||
OP( STR_TRIM_RIGHT);
|
||||
return TCL_OK;
|
||||
@@ -896,7 +1144,7 @@ TclCompileStringTrimCmd(
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 2);
|
||||
} else {
|
||||
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
|
||||
PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet));
|
||||
}
|
||||
OP( STR_TRIM);
|
||||
return TCL_OK;
|
||||
@@ -968,6 +1216,41 @@ TclCompileStringToTitleCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support definitions for the [string is] compilation.
|
||||
*/
|
||||
|
||||
static int
|
||||
UniCharIsAscii(
|
||||
int character)
|
||||
{
|
||||
return (character >= 0) && (character < 0x80);
|
||||
}
|
||||
|
||||
static int
|
||||
UniCharIsHexDigit(
|
||||
int character)
|
||||
{
|
||||
return (character >= 0) && (character < 0x80) && isxdigit(character);
|
||||
}
|
||||
|
||||
StringClassDesc const tclStringClassTable[] = {
|
||||
{"alnum", Tcl_UniCharIsAlnum},
|
||||
{"alpha", Tcl_UniCharIsAlpha},
|
||||
{"ascii", UniCharIsAscii},
|
||||
{"control", Tcl_UniCharIsControl},
|
||||
{"digit", Tcl_UniCharIsDigit},
|
||||
{"graph", Tcl_UniCharIsGraph},
|
||||
{"lower", Tcl_UniCharIsLower},
|
||||
{"print", Tcl_UniCharIsPrint},
|
||||
{"punct", Tcl_UniCharIsPunct},
|
||||
{"space", Tcl_UniCharIsSpace},
|
||||
{"upper", Tcl_UniCharIsUpper},
|
||||
{"word", Tcl_UniCharIsWordChar},
|
||||
{"xdigit", UniCharIsHexDigit},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -3474,6 +3757,51 @@ TclCompileYieldCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCompileYieldToCmd --
|
||||
*
|
||||
* Procedure called to compile the "yieldto" command.
|
||||
*
|
||||
* Results:
|
||||
* Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
|
||||
* evaluation to runtime.
|
||||
*
|
||||
* Side effects:
|
||||
* Instructions are added to envPtr to execute the "yieldto" command at
|
||||
* runtime.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclCompileYieldToCmd(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
int i;
|
||||
|
||||
if (parsePtr->numWords < 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
OP( NS_CURRENT);
|
||||
for (i = 1 ; i < parsePtr->numWords ; i++) {
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
OP4( LIST, i);
|
||||
OP( YIELD_TO_INVOKE);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+70
-8
@@ -493,6 +493,7 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
* qualified version, or produces the empty string if no such command
|
||||
* exists. Never generates errors.
|
||||
* Stack: ... cmdName => ... fullCmdName */
|
||||
|
||||
{"tclooSelf", 1, +1, 0, {OPERAND_NONE}},
|
||||
/* Push the identity of the current TclOO object (i.e., the name of
|
||||
* its current public access command) on the stack. */
|
||||
@@ -594,23 +595,61 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
* is number of values to concatenate.
|
||||
* Operation: push concat(stk1 stk2 ... stktop) */
|
||||
|
||||
{"strUpper", 1, 0, 0, {OPERAND_NONE}},
|
||||
{"strcaseUpper", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* [string toupper] core: converts whole string to upper case using
|
||||
* the default (extended "C" locale) rules.
|
||||
* Stack: ... string => ... newString */
|
||||
{"strLower", 1, 0, 0, {OPERAND_NONE}},
|
||||
{"strcaseLower", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* [string tolower] core: converts whole string to upper case using
|
||||
* the default (extended "C" locale) rules.
|
||||
* Stack: ... string => ... newString */
|
||||
{"strTitle", 1, 0, 0, {OPERAND_NONE}},
|
||||
{"strcaseTitle", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* [string totitle] core: converts whole string to upper case using
|
||||
* the default (extended "C" locale) rules.
|
||||
* Stack: ... string => ... newString */
|
||||
{"strReplace", 1, -3, 0, {OPERAND_NONE}},
|
||||
{"strreplace", 1, -3, 0, {OPERAND_NONE}},
|
||||
/* [string replace] core: replaces a non-empty range of one string
|
||||
* with the contents of another.
|
||||
* Stack: ... string fromIdx toIdx replacement => ... newString */
|
||||
|
||||
{"originCmd", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* Reports which command was the origin (via namespace import chain)
|
||||
* of the command named on the top of the stack.
|
||||
* Stack: ... cmdName => ... fullOriginalCmdName */
|
||||
|
||||
{"tclooNext", 2, INT_MIN, 1, {OPERAND_UINT1}},
|
||||
/* Call the next item on the TclOO call chain, passing opnd arguments
|
||||
* (min 1, max 255, *includes* "next"). The result of the invoked
|
||||
* method implementation will be pushed on the stack in place of the
|
||||
* arguments (similar to invokeStk).
|
||||
* Stack: ... "next" arg2 arg3 -- argN => ... result */
|
||||
{"tclooNextClass", 2, INT_MIN, 1, {OPERAND_UINT1}},
|
||||
/* Call the following item on the TclOO call chain defined by class
|
||||
* className, passing opnd arguments (min 2, max 255, *includes*
|
||||
* "nextto" and the class name). The result of the invoked method
|
||||
* implementation will be pushed on the stack in place of the
|
||||
* arguments (similar to invokeStk).
|
||||
* Stack: ... "nextto" className arg3 arg4 -- argN => ... result */
|
||||
|
||||
{"yieldToInvoke", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* Makes the current coroutine yield the value at the top of the
|
||||
* stack, invoking the given command/args with resolution in the given
|
||||
* namespace (all packed into a list), and places the list of values
|
||||
* that are the response back on top of the stack when it resumes.
|
||||
* Stack: ... [list ns cmd arg1 ... argN] => ... resumeList */
|
||||
|
||||
{"numericType", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* Pushes the numeric type code of the word at the top of the stack.
|
||||
* Stack: ... value => ... typeCode */
|
||||
{"tryCvtToBoolean", 1, +1, 0, {OPERAND_NONE}},
|
||||
/* Try converting stktop to boolean if possible. No errors.
|
||||
* Stack: ... value => ... value isStrictBool */
|
||||
{"strclass", 2, 0, 1, {OPERAND_SCLS1}},
|
||||
/* See if all the characters of the given string are a member of the
|
||||
* specified (by opnd) character class. Note that an empty string will
|
||||
* satisfy the class check (standard definition of "all").
|
||||
* Stack: ... stringValue => ... boolean */
|
||||
|
||||
{NULL, 0, 0, 0, {OPERAND_NONE}}
|
||||
};
|
||||
|
||||
@@ -5058,6 +5097,11 @@ FormatInstruction(
|
||||
}
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", (unsigned) opnd);
|
||||
break;
|
||||
case OPERAND_SCLS1:
|
||||
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
|
||||
Tcl_AppendPrintfToObj(bufferObj, "%s ",
|
||||
tclStringClassTable[opnd].name);
|
||||
break;
|
||||
case OPERAND_NONE:
|
||||
default:
|
||||
break;
|
||||
@@ -5274,7 +5318,7 @@ PrintSourceToObj(
|
||||
int maxChars) /* Maximum number of chars to print. */
|
||||
{
|
||||
register const char *p;
|
||||
register int i = 0;
|
||||
register int i = 0, len;
|
||||
|
||||
if (stringPtr == NULL) {
|
||||
Tcl_AppendToObj(appendObj, "\"\"", -1);
|
||||
@@ -5283,32 +5327,50 @@ PrintSourceToObj(
|
||||
|
||||
Tcl_AppendToObj(appendObj, "\"", -1);
|
||||
p = stringPtr;
|
||||
for (; (*p != '\0') && (i < maxChars); p++, i++) {
|
||||
switch (*p) {
|
||||
for (; (*p != '\0') && (i < maxChars); p+=len) {
|
||||
Tcl_UniChar ch;
|
||||
|
||||
len = TclUtfToUniChar(p, &ch);
|
||||
switch (ch) {
|
||||
case '"':
|
||||
Tcl_AppendToObj(appendObj, "\\\"", -1);
|
||||
i += 2;
|
||||
continue;
|
||||
case '\f':
|
||||
Tcl_AppendToObj(appendObj, "\\f", -1);
|
||||
i += 2;
|
||||
continue;
|
||||
case '\n':
|
||||
Tcl_AppendToObj(appendObj, "\\n", -1);
|
||||
i += 2;
|
||||
continue;
|
||||
case '\r':
|
||||
Tcl_AppendToObj(appendObj, "\\r", -1);
|
||||
i += 2;
|
||||
continue;
|
||||
case '\t':
|
||||
Tcl_AppendToObj(appendObj, "\\t", -1);
|
||||
i += 2;
|
||||
continue;
|
||||
case '\v':
|
||||
Tcl_AppendToObj(appendObj, "\\v", -1);
|
||||
i += 2;
|
||||
continue;
|
||||
default:
|
||||
Tcl_AppendPrintfToObj(appendObj, "%c", *p);
|
||||
if (ch < 0x20 || ch >= 0x7f) {
|
||||
Tcl_AppendPrintfToObj(appendObj, "\\u%04x", ch);
|
||||
i += 6;
|
||||
} else {
|
||||
Tcl_AppendPrintfToObj(appendObj, "%c", ch);
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Tcl_AppendToObj(appendObj, "\"", -1);
|
||||
if (*p != '\0') {
|
||||
Tcl_AppendToObj(appendObj, "...", -1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TCL_COMPILE_STATS
|
||||
|
||||
+50
-2
@@ -751,6 +751,8 @@ typedef struct ByteCode {
|
||||
#define INST_INFO_LEVEL_NUM 152
|
||||
#define INST_INFO_LEVEL_ARGS 153
|
||||
#define INST_RESOLVE_COMMAND 154
|
||||
|
||||
/* For compilation relating to TclOO */
|
||||
#define INST_TCLOO_SELF 155
|
||||
#define INST_TCLOO_CLASS 156
|
||||
#define INST_TCLOO_NS 157
|
||||
@@ -786,8 +788,19 @@ typedef struct ByteCode {
|
||||
#define INST_STR_TITLE 176
|
||||
#define INST_STR_REPLACE 177
|
||||
|
||||
#define INST_ORIGIN_COMMAND 178
|
||||
|
||||
#define INST_TCLOO_NEXT 179
|
||||
#define INST_TCLOO_NEXT_CLASS 180
|
||||
|
||||
#define INST_YIELD_TO_INVOKE 181
|
||||
|
||||
#define INST_NUM_TYPE 182
|
||||
#define INST_TRY_CVT_TO_BOOLEAN 183
|
||||
#define INST_STR_CLASS 184
|
||||
|
||||
/* The last opcode */
|
||||
#define LAST_INST_OPCODE 177
|
||||
#define LAST_INST_OPCODE 184
|
||||
|
||||
/*
|
||||
* Table describing the Tcl bytecode instructions: their name (for displaying
|
||||
@@ -812,8 +825,9 @@ typedef enum InstOperandType {
|
||||
* variable table. */
|
||||
OPERAND_LVT4, /* Four byte unsigned index into the local
|
||||
* variable table. */
|
||||
OPERAND_AUX4 /* Four byte unsigned index into the aux data
|
||||
OPERAND_AUX4, /* Four byte unsigned index into the aux data
|
||||
* table. */
|
||||
OPERAND_SCLS1 /* Index into tclStringClassTable. */
|
||||
} InstOperandType;
|
||||
|
||||
typedef struct InstructionDesc {
|
||||
@@ -831,6 +845,40 @@ typedef struct InstructionDesc {
|
||||
|
||||
MODULE_SCOPE InstructionDesc const tclInstructionTable[];
|
||||
|
||||
/*
|
||||
* Constants used by INST_STRING_CLASS to indicate character classes. These
|
||||
* correspond closely by name with what [string is] can support, but there is
|
||||
* no requirement to keep the values the same.
|
||||
*/
|
||||
|
||||
typedef enum InstStringClassType {
|
||||
STR_CLASS_ALNUM, /* Unicode alphabet or digit characters. */
|
||||
STR_CLASS_ALPHA, /* Unicode alphabet characters. */
|
||||
STR_CLASS_ASCII, /* Characters in range U+000000..U+00007F. */
|
||||
STR_CLASS_CONTROL, /* Unicode control characters. */
|
||||
STR_CLASS_DIGIT, /* Unicode digit characters. */
|
||||
STR_CLASS_GRAPH, /* Unicode printing characters, excluding
|
||||
* space. */
|
||||
STR_CLASS_LOWER, /* Unicode lower-case alphabet characters. */
|
||||
STR_CLASS_PRINT, /* Unicode printing characters, including
|
||||
* spaces. */
|
||||
STR_CLASS_PUNCT, /* Unicode punctuation characters. */
|
||||
STR_CLASS_SPACE, /* Unicode space characters. */
|
||||
STR_CLASS_UPPER, /* Unicode upper-case alphabet characters. */
|
||||
STR_CLASS_WORD, /* Unicode word (alphabetic, digit, connector
|
||||
* punctuation) characters. */
|
||||
STR_CLASS_XDIGIT /* Characters that can be used as digits in
|
||||
* hexadecimal numbers ([0-9A-Fa-f]). */
|
||||
} InstStringClassType;
|
||||
|
||||
typedef struct StringClassDesc {
|
||||
const char *name; /* Name of the class. */
|
||||
int (*comparator)(int); /* Function to test if a single unicode
|
||||
* character is a member of the class. */
|
||||
} StringClassDesc;
|
||||
|
||||
MODULE_SCOPE StringClassDesc const tclStringClassTable[];
|
||||
|
||||
/*
|
||||
* Compilation of some Tcl constructs such as if commands and the logical or
|
||||
* (||) and logical and (&&) operators in expressions requires the generation
|
||||
|
||||
+12
-12
@@ -63,7 +63,7 @@ EXTERN void Tcl_DbCkfree(char *ptr, const char *file, int line);
|
||||
/* 8 */
|
||||
EXTERN char * Tcl_DbCkrealloc(char *ptr, unsigned int size,
|
||||
const char *file, int line);
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
/* 9 */
|
||||
EXTERN void Tcl_CreateFileHandler(int fd, int mask,
|
||||
Tcl_FileProc *proc, ClientData clientData);
|
||||
@@ -73,7 +73,7 @@ EXTERN void Tcl_CreateFileHandler(int fd, int mask,
|
||||
EXTERN void Tcl_CreateFileHandler(int fd, int mask,
|
||||
Tcl_FileProc *proc, ClientData clientData);
|
||||
#endif /* MACOSX */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
/* 10 */
|
||||
EXTERN void Tcl_DeleteFileHandler(int fd);
|
||||
#endif /* UNIX */
|
||||
@@ -511,7 +511,7 @@ EXTERN Tcl_Interp * Tcl_GetMaster(Tcl_Interp *interp);
|
||||
EXTERN const char * Tcl_GetNameOfExecutable(void);
|
||||
/* 166 */
|
||||
EXTERN Tcl_Obj * Tcl_GetObjResult(Tcl_Interp *interp);
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
/* 167 */
|
||||
EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp,
|
||||
const char *chanID, int forWriting,
|
||||
@@ -1835,19 +1835,19 @@ typedef struct TclStubs {
|
||||
char * (*tcl_DbCkalloc) (unsigned int size, const char *file, int line); /* 6 */
|
||||
void (*tcl_DbCkfree) (char *ptr, const char *file, int line); /* 7 */
|
||||
char * (*tcl_DbCkrealloc) (char *ptr, unsigned int size, const char *file, int line); /* 8 */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) /* WIN */
|
||||
#if defined(_WIN32) /* WIN */
|
||||
void (*reserved9)(void);
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */
|
||||
#endif /* MACOSX */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
void (*tcl_DeleteFileHandler) (int fd); /* 10 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) /* WIN */
|
||||
#if defined(_WIN32) /* WIN */
|
||||
void (*reserved10)(void);
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
@@ -2009,10 +2009,10 @@ typedef struct TclStubs {
|
||||
Tcl_Interp * (*tcl_GetMaster) (Tcl_Interp *interp); /* 164 */
|
||||
const char * (*tcl_GetNameOfExecutable) (void); /* 165 */
|
||||
Tcl_Obj * (*tcl_GetObjResult) (Tcl_Interp *interp); /* 166 */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
int (*tcl_GetOpenFile) (Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) /* WIN */
|
||||
#if defined(_WIN32) /* WIN */
|
||||
void (*reserved167)(void);
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
@@ -2513,7 +2513,7 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_DbCkfree) /* 7 */
|
||||
#define Tcl_DbCkrealloc \
|
||||
(tclStubsPtr->tcl_DbCkrealloc) /* 8 */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#define Tcl_CreateFileHandler \
|
||||
(tclStubsPtr->tcl_CreateFileHandler) /* 9 */
|
||||
#endif /* UNIX */
|
||||
@@ -2521,7 +2521,7 @@ extern const TclStubs *tclStubsPtr;
|
||||
#define Tcl_CreateFileHandler \
|
||||
(tclStubsPtr->tcl_CreateFileHandler) /* 9 */
|
||||
#endif /* MACOSX */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#define Tcl_DeleteFileHandler \
|
||||
(tclStubsPtr->tcl_DeleteFileHandler) /* 10 */
|
||||
#endif /* UNIX */
|
||||
@@ -2841,7 +2841,7 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_GetNameOfExecutable) /* 165 */
|
||||
#define Tcl_GetObjResult \
|
||||
(tclStubsPtr->tcl_GetObjResult) /* 166 */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#define Tcl_GetOpenFile \
|
||||
(tclStubsPtr->tcl_GetOpenFile) /* 167 */
|
||||
#endif /* UNIX */
|
||||
|
||||
@@ -182,6 +182,7 @@ TCL_DECLARE_MUTEX(encodingMutex)
|
||||
|
||||
static Tcl_Encoding defaultEncoding;
|
||||
static Tcl_Encoding systemEncoding;
|
||||
Tcl_Encoding tclIdentityEncoding;
|
||||
|
||||
/*
|
||||
* The following variable is used in the sparse matrix code for a
|
||||
@@ -567,7 +568,7 @@ TclInitEncodingSubsystem(void)
|
||||
type.freeProc = NULL;
|
||||
type.nullSize = 1;
|
||||
type.clientData = NULL;
|
||||
Tcl_CreateEncoding(&type);
|
||||
tclIdentityEncoding = Tcl_CreateEncoding(&type);
|
||||
|
||||
type.encodingName = "utf-8";
|
||||
type.toUtfProc = UtfExtToUtfIntProc;
|
||||
@@ -651,6 +652,7 @@ TclFinalizeEncodingSubsystem(void)
|
||||
Tcl_MutexLock(&encodingMutex);
|
||||
encodingsInitialized = 0;
|
||||
FreeEncoding(systemEncoding);
|
||||
FreeEncoding(tclIdentityEncoding);
|
||||
|
||||
hPtr = Tcl_FirstHashEntry(&encodingTable, &search);
|
||||
while (hPtr != NULL) {
|
||||
|
||||
+17
-7
@@ -2751,13 +2751,6 @@ TclCompileEnsemble(
|
||||
const char *word;
|
||||
|
||||
Tcl_IncrRefCount(replaced);
|
||||
|
||||
/*
|
||||
* This is where we return to if we are parsing multiple nested compiled
|
||||
* ensembles. [info object] is such a beast.
|
||||
*/
|
||||
|
||||
checkNextWord:
|
||||
if (parsePtr->numWords < depth + 1) {
|
||||
goto failed;
|
||||
}
|
||||
@@ -2769,6 +2762,12 @@ TclCompileEnsemble(
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is where we return to if we are parsing multiple nested compiled
|
||||
* ensembles. [info object] is such a beast.
|
||||
*/
|
||||
|
||||
checkNextWord:
|
||||
word = tokenPtr[1].start;
|
||||
numBytes = tokenPtr[1].size;
|
||||
|
||||
@@ -2979,6 +2978,17 @@ TclCompileEnsemble(
|
||||
|
||||
if (cmdPtr->compileProc == TclCompileEnsemble) {
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (parsePtr->numWords < depth + 1
|
||||
|| tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
/*
|
||||
* Too hard because the user has done something unpleasant like
|
||||
* omitting the sub-ensemble's command name or used a non-constant
|
||||
* name for a sub-ensemble's command name; we respond by bailing
|
||||
* out completely (this is a rare case). [Bug 6d2f249a01]
|
||||
*/
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
ensemble = (Tcl_Command) cmdPtr;
|
||||
goto checkNextWord;
|
||||
}
|
||||
|
||||
+2
-2
@@ -444,7 +444,7 @@ TclUnsetEnv(
|
||||
* that no = should be included, and Windows requires it.
|
||||
*/
|
||||
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__)
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
string = ckalloc(length + 2);
|
||||
memcpy(string, name, (size_t) length);
|
||||
string[length] = '=';
|
||||
@@ -453,7 +453,7 @@ TclUnsetEnv(
|
||||
string = ckalloc(length + 1);
|
||||
memcpy(string, name, (size_t) length);
|
||||
string[length] = '\0';
|
||||
#endif /* WIN32 */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
Tcl_UtfToExternalDString(NULL, string, -1, &envString);
|
||||
string = ckrealloc(string, Tcl_DStringLength(&envString) + 1);
|
||||
|
||||
+956
-488
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -517,7 +517,7 @@ CopyRenameOneFile(
|
||||
* 16 bits and we get collisions. See bug #2015723.
|
||||
*/
|
||||
|
||||
#if !defined(WIN32) && !defined(__CYGWIN__)
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
if ((sourceStatBuf.st_ino != 0) && (targetStatBuf.st_ino != 0)) {
|
||||
if ((sourceStatBuf.st_ino == targetStatBuf.st_ino) &&
|
||||
(sourceStatBuf.st_dev == targetStatBuf.st_dev)) {
|
||||
|
||||
+1144
-1877
File diff suppressed because it is too large
Load Diff
+1
-31
@@ -36,6 +36,7 @@
|
||||
*/
|
||||
|
||||
typedef struct ChannelBuffer {
|
||||
int refCount; /* Current uses count */
|
||||
int nextAdded; /* The next position into which a character
|
||||
* will be put in the buffer. */
|
||||
int nextRemoved; /* Position of next byte to be removed from
|
||||
@@ -226,11 +227,6 @@ typedef struct ChannelState {
|
||||
* flushed after every newline. */
|
||||
#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always
|
||||
* be flushed immediately. */
|
||||
#define BUFFER_READY (1<<6) /* Current output buffer (the
|
||||
* curOutPtr field in the channel
|
||||
* structure) should be output as soon
|
||||
* as possible even though it may not
|
||||
* be full. */
|
||||
#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued
|
||||
* output buffers has been
|
||||
* scheduled. */
|
||||
@@ -252,9 +248,6 @@ typedef struct ChannelState {
|
||||
#define INPUT_SAW_CR (1<<12) /* Channel is in CRLF eol input
|
||||
* translation mode and the last byte
|
||||
* seen was a "\r". */
|
||||
#define INPUT_NEED_NL (1<<15) /* Saw a '\r' at end of last buffer,
|
||||
* and there should be a '\n' at
|
||||
* beginning of next buffer. */
|
||||
#define CHANNEL_DEAD (1<<13) /* The channel has been closed by the
|
||||
* exit handler (on exit) but not
|
||||
* deallocated. When any IO operation
|
||||
@@ -274,29 +267,6 @@ typedef struct ChannelState {
|
||||
* changes. */
|
||||
#define CHANNEL_RAW_MODE (1<<16) /* When set, notes that the Raw API is
|
||||
* being used. */
|
||||
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
|
||||
#define CHANNEL_TIMER_FEV (1<<17) /* When set the event we are notified
|
||||
* by is a fileevent generated by a
|
||||
* timer. We don't know if the driver
|
||||
* has more data and should not try to
|
||||
* read from it. If the system needs
|
||||
* more than is in the buffers out
|
||||
* read routines will simulate a short
|
||||
* read (0 characters read) */
|
||||
#define CHANNEL_HAS_MORE_DATA (1<<18) /* Set by NotifyChannel for a channel
|
||||
* if and only if the channel is
|
||||
* configured non-blocking, the driver
|
||||
* for said channel has no
|
||||
* blockmodeproc, and data has arrived
|
||||
* for reading at the OS level). A
|
||||
* GetInput will pass reading from the
|
||||
* driver if the channel is
|
||||
* non-blocking, without blockmode
|
||||
* proc and the flag has not been set.
|
||||
* A read will be performed if the
|
||||
* flag is set. This will reset the
|
||||
* flag as well. */
|
||||
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
|
||||
|
||||
#define CHANNEL_INCLOSE (1<<19) /* Channel is currently being closed.
|
||||
* Its structures are still live and
|
||||
|
||||
+27
-4
@@ -181,6 +181,7 @@ Tcl_PutsObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_Preserve(chan);
|
||||
result = Tcl_WriteObj(chan, string);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
@@ -191,6 +192,7 @@ Tcl_PutsObjCmd(
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
Tcl_Release(chan);
|
||||
return TCL_OK;
|
||||
|
||||
/*
|
||||
@@ -205,6 +207,7 @@ Tcl_PutsObjCmd(
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf("error writing \"%s\": %s",
|
||||
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
|
||||
}
|
||||
Tcl_Release(chan);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -252,6 +255,7 @@ Tcl_FlushObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_Preserve(chan);
|
||||
if (Tcl_Flush(chan) != TCL_OK) {
|
||||
/*
|
||||
* TIP #219.
|
||||
@@ -265,8 +269,10 @@ Tcl_FlushObjCmd(
|
||||
"error flushing \"%s\": %s",
|
||||
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
|
||||
}
|
||||
Tcl_Release(chan);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Release(chan);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -299,6 +305,7 @@ Tcl_GetsObjCmd(
|
||||
int lineLen; /* Length of line just read. */
|
||||
int mode; /* Mode in which channel is opened. */
|
||||
Tcl_Obj *linePtr, *chanObjPtr;
|
||||
int code = TCL_OK;
|
||||
|
||||
if ((objc != 2) && (objc != 3)) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "channelId ?varName?");
|
||||
@@ -315,6 +322,7 @@ Tcl_GetsObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_Preserve(chan);
|
||||
linePtr = Tcl_NewObj();
|
||||
lineLen = Tcl_GetsObj(chan, linePtr);
|
||||
if (lineLen < 0) {
|
||||
@@ -333,20 +341,24 @@ Tcl_GetsObjCmd(
|
||||
"error reading \"%s\": %s",
|
||||
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
|
||||
}
|
||||
return TCL_ERROR;
|
||||
code = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
lineLen = -1;
|
||||
}
|
||||
if (objc == 3) {
|
||||
if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr,
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
return TCL_ERROR;
|
||||
code = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(lineLen));
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, linePtr);
|
||||
}
|
||||
return TCL_OK;
|
||||
done:
|
||||
Tcl_Release(chan);
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -453,6 +465,7 @@ Tcl_ReadObjCmd(
|
||||
|
||||
resultPtr = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(resultPtr);
|
||||
Tcl_Preserve(chan);
|
||||
charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0);
|
||||
if (charactersRead < 0) {
|
||||
/*
|
||||
@@ -467,6 +480,7 @@ Tcl_ReadObjCmd(
|
||||
"error reading \"%s\": %s",
|
||||
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
|
||||
}
|
||||
Tcl_Release(chan);
|
||||
Tcl_DecrRefCount(resultPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -485,6 +499,7 @@ Tcl_ReadObjCmd(
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
Tcl_Release(chan);
|
||||
Tcl_DecrRefCount(resultPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -544,6 +559,7 @@ Tcl_SeekObjCmd(
|
||||
mode = modeArray[optionIndex];
|
||||
}
|
||||
|
||||
Tcl_Preserve(chan);
|
||||
result = Tcl_Seek(chan, offset, mode);
|
||||
if (result == Tcl_LongAsWide(-1)) {
|
||||
/*
|
||||
@@ -558,8 +574,10 @@ Tcl_SeekObjCmd(
|
||||
"error during seek on \"%s\": %s",
|
||||
TclGetString(objv[1]), Tcl_PosixError(interp)));
|
||||
}
|
||||
Tcl_Release(chan);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Release(chan);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -590,6 +608,7 @@ Tcl_TellObjCmd(
|
||||
{
|
||||
Tcl_Channel chan; /* The channel to tell on. */
|
||||
Tcl_WideInt newLoc;
|
||||
int code;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
|
||||
@@ -605,6 +624,7 @@ Tcl_TellObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_Preserve(chan);
|
||||
newLoc = Tcl_Tell(chan);
|
||||
|
||||
/*
|
||||
@@ -613,7 +633,10 @@ Tcl_TellObjCmd(
|
||||
* them into the regular interpreter result.
|
||||
*/
|
||||
|
||||
if (TclChanCaughtErrorBypass(interp, chan)) {
|
||||
|
||||
code = TclChanCaughtErrorBypass(interp, chan);
|
||||
Tcl_Release(chan);
|
||||
if (code) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+105
-71
@@ -210,7 +210,27 @@ struct TransformChannelData {
|
||||
* a transformation of incoming data. Also
|
||||
* serves as buffer of all data not yet
|
||||
* consumed by the reader. */
|
||||
int refCount;
|
||||
};
|
||||
|
||||
static void
|
||||
PreserveData(
|
||||
TransformChannelData *dataPtr)
|
||||
{
|
||||
dataPtr->refCount++;
|
||||
}
|
||||
|
||||
static void
|
||||
ReleaseData(
|
||||
TransformChannelData *dataPtr)
|
||||
{
|
||||
if (--dataPtr->refCount) {
|
||||
return;
|
||||
}
|
||||
ResultClear(&dataPtr->result);
|
||||
Tcl_DecrRefCount(dataPtr->command);
|
||||
ckfree(dataPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -240,6 +260,7 @@ TclChannelTransform(
|
||||
Channel *chanPtr; /* The actual channel. */
|
||||
ChannelState *statePtr; /* State info for channel. */
|
||||
int mode; /* Read/write mode of the channel. */
|
||||
int objc;
|
||||
TransformChannelData *dataPtr;
|
||||
Tcl_DString ds;
|
||||
|
||||
@@ -247,6 +268,12 @@ TclChannelTransform(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (TCL_OK != Tcl_ListObjLength(interp, cmdObjPtr, &objc)) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("-command value is not a list", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
chanPtr = (Channel *) chan;
|
||||
statePtr = chanPtr->state;
|
||||
chanPtr = statePtr->topChanPtr;
|
||||
@@ -261,6 +288,7 @@ TclChannelTransform(
|
||||
|
||||
dataPtr = ckalloc(sizeof(TransformChannelData));
|
||||
|
||||
dataPtr->refCount = 1;
|
||||
Tcl_DStringInit(&ds);
|
||||
Tcl_GetChannelOption(interp, chan, "-blocking", &ds);
|
||||
dataPtr->readIsFlushed = 0;
|
||||
@@ -270,7 +298,6 @@ TclChannelTransform(
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
dataPtr->self = chan;
|
||||
dataPtr->watchMask = 0;
|
||||
dataPtr->mode = mode;
|
||||
dataPtr->timer = NULL;
|
||||
@@ -286,19 +313,20 @@ TclChannelTransform(
|
||||
if (dataPtr->self == NULL) {
|
||||
Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp),
|
||||
"\nfailed to stack channel \"%s\"", Tcl_GetChannelName(chan));
|
||||
Tcl_DecrRefCount(dataPtr->command);
|
||||
ResultClear(&dataPtr->result);
|
||||
ckfree(dataPtr);
|
||||
ReleaseData(dataPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_Preserve(dataPtr->self);
|
||||
|
||||
/*
|
||||
* At last initialize the transformation at the script level.
|
||||
*/
|
||||
|
||||
PreserveData(dataPtr);
|
||||
if ((dataPtr->mode & TCL_WRITABLE) && ExecuteCallback(dataPtr, NULL,
|
||||
A_CREATE_WRITE, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK){
|
||||
Tcl_UnstackChannel(interp, chan);
|
||||
ReleaseData(dataPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -307,9 +335,11 @@ TclChannelTransform(
|
||||
ExecuteCallback(dataPtr, NULL, A_DELETE_WRITE, NULL, 0, TRANSMIT_DONT,
|
||||
P_NO_PRESERVE);
|
||||
Tcl_UnstackChannel(interp, chan);
|
||||
ReleaseData(dataPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
ReleaseData(dataPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -350,7 +380,10 @@ ExecuteCallback(
|
||||
unsigned char *resBuf;
|
||||
Tcl_InterpState state = NULL;
|
||||
int res = TCL_OK;
|
||||
Tcl_Obj *command = Tcl_DuplicateObj(dataPtr->command);
|
||||
Tcl_Obj *command = TclListObjCopy(NULL, dataPtr->command);
|
||||
Tcl_Interp *eval = dataPtr->interp;
|
||||
|
||||
Tcl_Preserve(eval);
|
||||
|
||||
/*
|
||||
* Step 1, create the complete command to execute. Do this by appending
|
||||
@@ -361,26 +394,18 @@ ExecuteCallback(
|
||||
*/
|
||||
|
||||
if (preserve == P_PRESERVE) {
|
||||
state = Tcl_SaveInterpState(dataPtr->interp, res);
|
||||
state = Tcl_SaveInterpState(eval, res);
|
||||
}
|
||||
|
||||
Tcl_IncrRefCount(command);
|
||||
res = Tcl_ListObjAppendElement(dataPtr->interp, command,
|
||||
Tcl_NewStringObj((char *) op, -1));
|
||||
if (res != TCL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1));
|
||||
|
||||
/*
|
||||
* Use a byte-array to prevent the misinterpretation of binary data coming
|
||||
* through as UTF while at the tcl level.
|
||||
*/
|
||||
|
||||
res = Tcl_ListObjAppendElement(dataPtr->interp, command,
|
||||
Tcl_NewByteArrayObj(buf, bufLen));
|
||||
if (res != TCL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, command, Tcl_NewByteArrayObj(buf, bufLen));
|
||||
|
||||
/*
|
||||
* Step 2, execute the command at the global level of the interpreter used
|
||||
@@ -390,13 +415,14 @@ ExecuteCallback(
|
||||
* current interpreter. Don't copy if in preservation mode.
|
||||
*/
|
||||
|
||||
res = Tcl_EvalObjEx(dataPtr->interp, command, TCL_EVAL_GLOBAL);
|
||||
res = Tcl_EvalObjEx(eval, command, TCL_EVAL_GLOBAL);
|
||||
Tcl_DecrRefCount(command);
|
||||
command = NULL;
|
||||
|
||||
if ((res != TCL_OK) && (interp != NULL) && (dataPtr->interp != interp)
|
||||
if ((res != TCL_OK) && (interp != NULL) && (eval != interp)
|
||||
&& (preserve == P_NO_PRESERVE)) {
|
||||
Tcl_SetObjResult(interp, Tcl_GetObjResult(dataPtr->interp));
|
||||
Tcl_SetObjResult(interp, Tcl_GetObjResult(eval));
|
||||
Tcl_Release(eval);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -411,20 +437,26 @@ ExecuteCallback(
|
||||
break;
|
||||
|
||||
case TRANSMIT_DOWN:
|
||||
resObj = Tcl_GetObjResult(dataPtr->interp);
|
||||
if (dataPtr->self == NULL) {
|
||||
break;
|
||||
}
|
||||
resObj = Tcl_GetObjResult(eval);
|
||||
resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
|
||||
Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf,
|
||||
resLen);
|
||||
break;
|
||||
|
||||
case TRANSMIT_SELF:
|
||||
resObj = Tcl_GetObjResult(dataPtr->interp);
|
||||
if (dataPtr->self == NULL) {
|
||||
break;
|
||||
}
|
||||
resObj = Tcl_GetObjResult(eval);
|
||||
resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
|
||||
Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen);
|
||||
break;
|
||||
|
||||
case TRANSMIT_IBUF:
|
||||
resObj = Tcl_GetObjResult(dataPtr->interp);
|
||||
resObj = Tcl_GetObjResult(eval);
|
||||
resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
|
||||
ResultAdd(&dataPtr->result, resBuf, resLen);
|
||||
break;
|
||||
@@ -434,24 +466,16 @@ ExecuteCallback(
|
||||
* Interpret result as integer number.
|
||||
*/
|
||||
|
||||
resObj = Tcl_GetObjResult(dataPtr->interp);
|
||||
TclGetIntFromObj(dataPtr->interp, resObj, &dataPtr->maxRead);
|
||||
resObj = Tcl_GetObjResult(eval);
|
||||
TclGetIntFromObj(eval, resObj, &dataPtr->maxRead);
|
||||
break;
|
||||
}
|
||||
|
||||
Tcl_ResetResult(dataPtr->interp);
|
||||
Tcl_ResetResult(eval);
|
||||
if (preserve == P_PRESERVE) {
|
||||
(void) Tcl_RestoreInterpState(dataPtr->interp, state);
|
||||
}
|
||||
return res;
|
||||
|
||||
cleanup:
|
||||
if (preserve == P_PRESERVE) {
|
||||
(void) Tcl_RestoreInterpState(dataPtr->interp, state);
|
||||
}
|
||||
if (command != NULL) {
|
||||
Tcl_DecrRefCount(command);
|
||||
(void) Tcl_RestoreInterpState(eval, state);
|
||||
}
|
||||
Tcl_Release(eval);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -535,6 +559,7 @@ TransformCloseProc(
|
||||
* system rely on (f.e. signaling the close to interested parties).
|
||||
*/
|
||||
|
||||
PreserveData(dataPtr);
|
||||
if (dataPtr->mode & TCL_WRITABLE) {
|
||||
ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0,
|
||||
TRANSMIT_DOWN, P_PRESERVE);
|
||||
@@ -554,14 +579,15 @@ TransformCloseProc(
|
||||
ExecuteCallback(dataPtr, interp, A_DELETE_READ, NULL, 0,
|
||||
TRANSMIT_DONT, P_PRESERVE);
|
||||
}
|
||||
ReleaseData(dataPtr);
|
||||
|
||||
/*
|
||||
* General cleanup.
|
||||
*/
|
||||
|
||||
ResultClear(&dataPtr->result);
|
||||
Tcl_DecrRefCount(dataPtr->command);
|
||||
ckfree(dataPtr);
|
||||
Tcl_Release(dataPtr->self);
|
||||
dataPtr->self = NULL;
|
||||
ReleaseData(dataPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -596,7 +622,7 @@ TransformInputProc(
|
||||
* Should assert(dataPtr->mode & TCL_READABLE);
|
||||
*/
|
||||
|
||||
if (toRead == 0) {
|
||||
if (toRead == 0 || dataPtr->self == NULL) {
|
||||
/*
|
||||
* Catch a no-op.
|
||||
*/
|
||||
@@ -606,6 +632,7 @@ TransformInputProc(
|
||||
gotBytes = 0;
|
||||
downChan = Tcl_GetStackedChannel(dataPtr->self);
|
||||
|
||||
PreserveData(dataPtr);
|
||||
while (toRead > 0) {
|
||||
/*
|
||||
* Loop until the request is satisfied (or no data is available from
|
||||
@@ -623,7 +650,7 @@ TransformInputProc(
|
||||
* break out of the loop and return to the caller.
|
||||
*/
|
||||
|
||||
return gotBytes;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -647,7 +674,7 @@ TransformInputProc(
|
||||
}
|
||||
} /* else: 'maxRead < 0' == Accept the current value of toRead. */
|
||||
if (toRead <= 0) {
|
||||
return gotBytes;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -656,44 +683,40 @@ TransformInputProc(
|
||||
|
||||
read = Tcl_ReadRaw(downChan, buf, toRead);
|
||||
if (read < 0) {
|
||||
/*
|
||||
* Report errors to caller. EAGAIN is a special situation. If we
|
||||
* had some data before we report that instead of the request to
|
||||
* re-try.
|
||||
*/
|
||||
int error = Tcl_GetErrno();
|
||||
if (Tcl_InputBlocked(downChan) && (gotBytes > 0)) {
|
||||
/*
|
||||
* Zero bytes available from downChan because blocked.
|
||||
* But nonzero bytes already copied, so total is a
|
||||
* valid blocked short read. Return to caller.
|
||||
*/
|
||||
|
||||
if ((error == EAGAIN) && (gotBytes > 0)) {
|
||||
return gotBytes;
|
||||
break;
|
||||
}
|
||||
|
||||
*errorCodePtr = error;
|
||||
return -1;
|
||||
/*
|
||||
* Either downChan is not blocked (there's a real error).
|
||||
* or it is and there are no bytes copied yet. In either
|
||||
* case we want to pass the "error" along to the caller,
|
||||
* either to report an error, or to signal to the caller
|
||||
* that zero bytes are available because blocked.
|
||||
*/
|
||||
|
||||
*errorCodePtr = Tcl_GetErrno();
|
||||
gotBytes = -1;
|
||||
break;
|
||||
} else if (read == 0) {
|
||||
/*
|
||||
* Check wether we hit on EOF in the underlying channel or not. If
|
||||
* not differentiate between blocking and non-blocking modes. In
|
||||
* non-blocking mode we ran temporarily out of data. Signal this
|
||||
* to the caller via EWOULDBLOCK and error return (-1). In the
|
||||
* other cases we simply return what we got and let the caller
|
||||
* wait for more. On the other hand, if we got an EOF we have to
|
||||
* convert and flush all waiting partial data.
|
||||
*/
|
||||
|
||||
if (!Tcl_Eof(downChan)) {
|
||||
if ((gotBytes == 0) && (dataPtr->flags & CHANNEL_ASYNC)) {
|
||||
*errorCodePtr = EWOULDBLOCK;
|
||||
return -1;
|
||||
}
|
||||
return gotBytes;
|
||||
}
|
||||
/*
|
||||
* Zero returned from Tcl_ReadRaw() always indicates EOF
|
||||
* on the down channel.
|
||||
*/
|
||||
|
||||
if (dataPtr->readIsFlushed) {
|
||||
/*
|
||||
* Already flushed, nothing to do anymore.
|
||||
*/
|
||||
|
||||
return gotBytes;
|
||||
break;
|
||||
}
|
||||
|
||||
dataPtr->readIsFlushed = 1;
|
||||
@@ -705,7 +728,7 @@ TransformInputProc(
|
||||
* We had nothing to flush.
|
||||
*/
|
||||
|
||||
return gotBytes;
|
||||
break;
|
||||
}
|
||||
|
||||
continue; /* at: while (toRead > 0) */
|
||||
@@ -719,9 +742,11 @@ TransformInputProc(
|
||||
if (ExecuteCallback(dataPtr, NULL, A_READ, UCHARP(buf), read,
|
||||
TRANSMIT_IBUF, P_PRESERVE) != TCL_OK) {
|
||||
*errorCodePtr = EINVAL;
|
||||
return -1;
|
||||
gotBytes = -1;
|
||||
break;
|
||||
}
|
||||
} /* while toRead > 0 */
|
||||
ReleaseData(dataPtr);
|
||||
|
||||
return gotBytes;
|
||||
}
|
||||
@@ -763,11 +788,13 @@ TransformOutputProc(
|
||||
return 0;
|
||||
}
|
||||
|
||||
PreserveData(dataPtr);
|
||||
if (ExecuteCallback(dataPtr, NULL, A_WRITE, UCHARP(buf), toWrite,
|
||||
TRANSMIT_DOWN, P_NO_PRESERVE) != TCL_OK) {
|
||||
*errorCodePtr = EINVAL;
|
||||
return -1;
|
||||
toWrite = -1;
|
||||
}
|
||||
ReleaseData(dataPtr);
|
||||
|
||||
return toWrite;
|
||||
}
|
||||
@@ -820,6 +847,7 @@ TransformSeekProc(
|
||||
* request down, unchanged.
|
||||
*/
|
||||
|
||||
PreserveData(dataPtr);
|
||||
if (dataPtr->mode & TCL_WRITABLE) {
|
||||
ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN,
|
||||
P_NO_PRESERVE);
|
||||
@@ -831,6 +859,7 @@ TransformSeekProc(
|
||||
ResultClear(&dataPtr->result);
|
||||
dataPtr->readIsFlushed = 0;
|
||||
}
|
||||
ReleaseData(dataPtr);
|
||||
|
||||
return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode,
|
||||
errorCodePtr);
|
||||
@@ -891,6 +920,7 @@ TransformWideSeekProc(
|
||||
* request down, unchanged.
|
||||
*/
|
||||
|
||||
PreserveData(dataPtr);
|
||||
if (dataPtr->mode & TCL_WRITABLE) {
|
||||
ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN,
|
||||
P_NO_PRESERVE);
|
||||
@@ -902,6 +932,7 @@ TransformWideSeekProc(
|
||||
ResultClear(&dataPtr->result);
|
||||
dataPtr->readIsFlushed = 0;
|
||||
}
|
||||
ReleaseData(dataPtr);
|
||||
|
||||
/*
|
||||
* If we have a wide seek capability, we should stick with that.
|
||||
@@ -1056,6 +1087,9 @@ TransformWatchProc(
|
||||
* unchanged.
|
||||
*/
|
||||
|
||||
if (dataPtr->self == NULL) {
|
||||
return;
|
||||
}
|
||||
downChan = Tcl_GetStackedChannel(dataPtr->self);
|
||||
|
||||
Tcl_GetChannelType(downChan)->watchProc(
|
||||
|
||||
+96
-220
@@ -99,31 +99,9 @@ typedef struct {
|
||||
Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */
|
||||
Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */
|
||||
#endif
|
||||
|
||||
/* See [==] as well.
|
||||
* Storage for the command prefix and the additional words required for
|
||||
* the invocation of methods in the command handler.
|
||||
*
|
||||
* argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2]
|
||||
* cmd ... pfx | method chan | detail1 detail2
|
||||
* ~~~~ CT ~~~ ~~ CT ~~
|
||||
*
|
||||
* CT = Belongs to the 'Command handler Thread'.
|
||||
*/
|
||||
|
||||
int argc; /* Number of preallocated words - 2 */
|
||||
Tcl_Obj **argv; /* Preallocated array for calling the handler.
|
||||
* args[0] is placeholder for cmd word.
|
||||
* Followed by the arguments in the prefix,
|
||||
* plus 4 placeholders for method, channel,
|
||||
* and at most two varying (method specific)
|
||||
* words. */
|
||||
int methods; /* Bitmask of supported methods */
|
||||
|
||||
/*
|
||||
* NOTE (9): Should we have predefined shared literals for the method
|
||||
* names?
|
||||
*/
|
||||
Tcl_Obj *cmd; /* Callback command prefix */
|
||||
Tcl_Obj *methods; /* Methods to append to command prefix */
|
||||
Tcl_Obj *name; /* Name of the channel as created */
|
||||
|
||||
int mode; /* Mask of R/W mode */
|
||||
int interest; /* Mask of events the channel is interested
|
||||
@@ -450,9 +428,8 @@ static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp,
|
||||
Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj);
|
||||
static Tcl_Obj * NextHandle(void);
|
||||
static void FreeReflectedChannel(ReflectedChannel *rcPtr);
|
||||
static void FreeReflectedChannelArgs(ReflectedChannel *rcPtr);
|
||||
static int InvokeTclMethod(ReflectedChannel *rcPtr,
|
||||
const char *method, Tcl_Obj *argOneObj,
|
||||
MethodName method, Tcl_Obj *argOneObj,
|
||||
Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr);
|
||||
|
||||
static ReflectedChannelMap * GetReflectedChannelMap(Tcl_Interp *interp);
|
||||
@@ -467,16 +444,14 @@ static int ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj *resObj);
|
||||
* list-quoting to keep the words of the message together. See also [x].
|
||||
*/
|
||||
|
||||
static const char *msg_read_unsup = "{read not supported by Tcl driver}";
|
||||
static const char *msg_read_toomuch = "{read delivered more than requested}";
|
||||
static const char *msg_write_unsup = "{write not supported by Tcl driver}";
|
||||
static const char *msg_write_toomuch = "{write wrote more than requested}";
|
||||
static const char *msg_write_nothing = "{write wrote nothing}";
|
||||
static const char *msg_seek_beforestart = "{Tried to seek before origin}";
|
||||
#ifdef TCL_THREADS
|
||||
static const char *msg_send_originlost = "{Channel thread lost}";
|
||||
static const char *msg_send_dstlost = "{Owner lost}";
|
||||
#endif /* TCL_THREADS */
|
||||
static const char *msg_send_dstlost = "{Owner lost}";
|
||||
static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}";
|
||||
|
||||
/*
|
||||
@@ -583,10 +558,6 @@ TclChanCreateObjCmd(
|
||||
|
||||
rcId = NextHandle();
|
||||
rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);
|
||||
chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
|
||||
mode);
|
||||
rcPtr->chan = chan;
|
||||
chanPtr = (Channel *) chan;
|
||||
|
||||
/*
|
||||
* Invoke 'initialize' and validate that the handler is present and ok.
|
||||
@@ -600,7 +571,7 @@ TclChanCreateObjCmd(
|
||||
|
||||
modeObj = DecodeEventMask(mode);
|
||||
/* assert modeObj.refCount == 1 */
|
||||
result = InvokeTclMethod(rcPtr, "initialize", modeObj, NULL, &resObj);
|
||||
result = InvokeTclMethod(rcPtr, METH_INIT, modeObj, NULL, &resObj);
|
||||
Tcl_DecrRefCount(modeObj);
|
||||
|
||||
if (result != TCL_OK) {
|
||||
@@ -683,7 +654,11 @@ TclChanCreateObjCmd(
|
||||
* Everything is fine now.
|
||||
*/
|
||||
|
||||
rcPtr->methods = methods;
|
||||
chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
|
||||
mode);
|
||||
rcPtr->chan = chan;
|
||||
Tcl_Preserve(chan);
|
||||
chanPtr = (Channel *) chan;
|
||||
|
||||
if ((methods & NULLABLE_METHODS) != NULLABLE_METHODS) {
|
||||
/*
|
||||
@@ -744,12 +719,10 @@ TclChanCreateObjCmd(
|
||||
return TCL_OK;
|
||||
|
||||
error:
|
||||
/*
|
||||
* Signal to ReflectClose to not call 'finalize'.
|
||||
*/
|
||||
|
||||
rcPtr->methods = 0;
|
||||
Tcl_Close(interp, chan);
|
||||
Tcl_DecrRefCount(rcPtr->name);
|
||||
Tcl_DecrRefCount(rcPtr->methods);
|
||||
Tcl_DecrRefCount(rcPtr->cmd);
|
||||
ckfree((char*) rcPtr);
|
||||
return TCL_ERROR;
|
||||
|
||||
#undef MODE
|
||||
@@ -1138,6 +1111,7 @@ ReflectClose(
|
||||
ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in
|
||||
* this interp */
|
||||
Tcl_HashEntry *hPtr; /* Entry in the above map */
|
||||
const Tcl_ChannelType *tctPtr;
|
||||
|
||||
if (TclInThreadExit()) {
|
||||
/*
|
||||
@@ -1172,21 +1146,15 @@ ReflectClose(
|
||||
if (result != TCL_OK) {
|
||||
FreeReceivedError(&p);
|
||||
}
|
||||
return EOK;
|
||||
}
|
||||
#endif
|
||||
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
return EOK;
|
||||
}
|
||||
|
||||
/*
|
||||
* -- No -- ASSERT rcPtr->methods & FLAG(METH_FINAL)
|
||||
*
|
||||
* A cleaned method mask here implies that the channel creation was
|
||||
* aborted, and "finalize" must not be called.
|
||||
*/
|
||||
|
||||
if (rcPtr->methods == 0) {
|
||||
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
|
||||
if (tctPtr && tctPtr != &tclRChannelType) {
|
||||
ckfree((char *)tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
}
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
return EOK;
|
||||
}
|
||||
@@ -1208,14 +1176,12 @@ ReflectClose(
|
||||
|
||||
Tcl_DeleteEvents(ReflectEventDelete, rcPtr);
|
||||
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
|
||||
if (result != TCL_OK) {
|
||||
PassReceivedErrorInterp(interp, &p);
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
result = InvokeTclMethod(rcPtr, "finalize", NULL, NULL, &resObj);
|
||||
result = InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj);
|
||||
if ((result != TCL_OK) && (interp != NULL)) {
|
||||
Tcl_SetChannelErrorInterp(interp, resObj);
|
||||
}
|
||||
@@ -1253,6 +1219,11 @@ ReflectClose(
|
||||
}
|
||||
#endif
|
||||
|
||||
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
|
||||
if (tctPtr && tctPtr != &tclRChannelType) {
|
||||
ckfree((char *)tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
}
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
#ifdef TCL_THREADS
|
||||
}
|
||||
@@ -1289,18 +1260,6 @@ ReflectInput(
|
||||
unsigned char *bytev; /* Array of returned bytes */
|
||||
Tcl_Obj *resObj; /* Result data for 'read' */
|
||||
|
||||
/*
|
||||
* The following check can be done before thread redirection, because we
|
||||
* are reading from an item which is readonly, i.e. will never change
|
||||
* during the lifetime of the channel.
|
||||
*/
|
||||
|
||||
if (!(rcPtr->methods & FLAG(METH_READ))) {
|
||||
SetChannelErrorStr(rcPtr->chan, msg_read_unsup);
|
||||
*errorCodePtr = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
@@ -1339,7 +1298,7 @@ ReflectInput(
|
||||
toReadObj = Tcl_NewIntObj(toRead);
|
||||
Tcl_IncrRefCount(toReadObj);
|
||||
|
||||
if (InvokeTclMethod(rcPtr, "read", toReadObj, NULL, &resObj)!=TCL_OK) {
|
||||
if (InvokeTclMethod(rcPtr, METH_READ, toReadObj, NULL, &resObj)!=TCL_OK) {
|
||||
int code = ErrnoReturn(rcPtr, resObj);
|
||||
|
||||
if (code < 0) {
|
||||
@@ -1404,18 +1363,6 @@ ReflectOutput(
|
||||
Tcl_Obj *resObj; /* Result data for 'write' */
|
||||
int written;
|
||||
|
||||
/*
|
||||
* The following check can be done before thread redirection, because we
|
||||
* are reading from an item which is readonly, i.e. will never change
|
||||
* during the lifetime of the channel.
|
||||
*/
|
||||
|
||||
if (!(rcPtr->methods & FLAG(METH_WRITE))) {
|
||||
SetChannelErrorStr(rcPtr->chan, msg_write_unsup);
|
||||
*errorCodePtr = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
@@ -1450,11 +1397,12 @@ ReflectOutput(
|
||||
/* ASSERT: rcPtr->mode & TCL_WRITABLE */
|
||||
|
||||
Tcl_Preserve(rcPtr);
|
||||
Tcl_Preserve(rcPtr->interp);
|
||||
|
||||
bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toWrite);
|
||||
Tcl_IncrRefCount(bufObj);
|
||||
|
||||
if (InvokeTclMethod(rcPtr, "write", bufObj, NULL, &resObj) != TCL_OK) {
|
||||
if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) {
|
||||
int code = ErrnoReturn(rcPtr, resObj);
|
||||
|
||||
if (code < 0) {
|
||||
@@ -1466,6 +1414,14 @@ ReflectOutput(
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (Tcl_InterpDeleted(rcPtr->interp)) {
|
||||
/*
|
||||
* The interp was destroyed during InvokeTclMethod().
|
||||
*/
|
||||
|
||||
SetChannelErrorStr(rcPtr->chan, msg_send_dstlost);
|
||||
goto invalid;
|
||||
}
|
||||
if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) {
|
||||
Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
|
||||
goto invalid;
|
||||
@@ -1495,6 +1451,7 @@ ReflectOutput(
|
||||
stop:
|
||||
Tcl_DecrRefCount(bufObj);
|
||||
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
|
||||
Tcl_Release(rcPtr->interp);
|
||||
Tcl_Release(rcPtr);
|
||||
return written;
|
||||
invalid:
|
||||
@@ -1568,7 +1525,7 @@ ReflectSeekWide(
|
||||
Tcl_IncrRefCount(offObj);
|
||||
Tcl_IncrRefCount(baseObj);
|
||||
|
||||
if (InvokeTclMethod(rcPtr, "seek", offObj, baseObj, &resObj) != TCL_OK) {
|
||||
if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) {
|
||||
Tcl_SetChannelError(rcPtr->chan, resObj);
|
||||
goto invalid;
|
||||
}
|
||||
@@ -1639,8 +1596,6 @@ ReflectWatch(
|
||||
ReflectedChannel *rcPtr = clientData;
|
||||
Tcl_Obj *maskObj;
|
||||
|
||||
/* ASSERT rcPtr->methods & FLAG(METH_WATCH) */
|
||||
|
||||
/*
|
||||
* We restrict the interest to what the channel can support. IOW there
|
||||
* will never be write events for a channel which is not writable.
|
||||
@@ -1683,7 +1638,7 @@ ReflectWatch(
|
||||
|
||||
maskObj = DecodeEventMask(mask);
|
||||
/* assert maskObj.refCount == 1 */
|
||||
(void) InvokeTclMethod(rcPtr, "watch", maskObj, NULL, NULL);
|
||||
(void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL);
|
||||
Tcl_DecrRefCount(maskObj);
|
||||
|
||||
Tcl_Release(rcPtr);
|
||||
@@ -1742,7 +1697,7 @@ ReflectBlock(
|
||||
|
||||
Tcl_Preserve(rcPtr);
|
||||
|
||||
if (InvokeTclMethod(rcPtr, "blocking", blockObj, NULL, &resObj)!=TCL_OK) {
|
||||
if (InvokeTclMethod(rcPtr,METH_BLOCKING,blockObj,NULL,&resObj)!=TCL_OK) {
|
||||
Tcl_SetChannelError(rcPtr->chan, resObj);
|
||||
errorNum = EINVAL;
|
||||
} else {
|
||||
@@ -1854,7 +1809,7 @@ ReflectSetOption(
|
||||
Tcl_IncrRefCount(optionObj);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
|
||||
result = InvokeTclMethod(rcPtr, "configure",optionObj,valueObj, &resObj);
|
||||
result = InvokeTclMethod(rcPtr, METH_CONFIGURE,optionObj,valueObj, &resObj);
|
||||
if (result != TCL_OK) {
|
||||
UnmarshallErrorResult(interp, resObj);
|
||||
}
|
||||
@@ -1899,7 +1854,7 @@ ReflectGetOption(
|
||||
Tcl_Obj *resObj; /* Result data for 'configure' */
|
||||
int listc, result = TCL_OK;
|
||||
Tcl_Obj **listv;
|
||||
const char *method;
|
||||
MethodName method;
|
||||
|
||||
/*
|
||||
* Are we in the correct thread?
|
||||
@@ -1938,14 +1893,14 @@ ReflectGetOption(
|
||||
* Retrieve all options.
|
||||
*/
|
||||
|
||||
method = "cgetall";
|
||||
method = METH_CGETALL;
|
||||
optionObj = NULL;
|
||||
} else {
|
||||
/*
|
||||
* Retrieve the value of one option.
|
||||
*/
|
||||
|
||||
method = "cget";
|
||||
method = METH_CGET;
|
||||
optionObj = Tcl_NewStringObj(optionName, -1);
|
||||
Tcl_IncrRefCount(optionObj);
|
||||
}
|
||||
@@ -2159,16 +2114,13 @@ NewReflectedChannel(
|
||||
Tcl_Obj *handleObj)
|
||||
{
|
||||
ReflectedChannel *rcPtr;
|
||||
int i, listc;
|
||||
Tcl_Obj **listv;
|
||||
MethodName mn = METH_BLOCKING;
|
||||
|
||||
rcPtr = ckalloc(sizeof(ReflectedChannel));
|
||||
|
||||
/* rcPtr->chan: Assigned by caller. Dummy data here. */
|
||||
/* rcPtr->methods: Assigned by caller. Dummy data here. */
|
||||
|
||||
rcPtr->chan = NULL;
|
||||
rcPtr->methods = 0;
|
||||
rcPtr->interp = interp;
|
||||
rcPtr->dead = 0;
|
||||
#ifdef TCL_THREADS
|
||||
@@ -2177,54 +2129,17 @@ NewReflectedChannel(
|
||||
rcPtr->mode = mode;
|
||||
rcPtr->interest = 0; /* Initially no interest registered */
|
||||
|
||||
/*
|
||||
* Method placeholder.
|
||||
*/
|
||||
|
||||
/* ASSERT: cmdpfxObj is a Tcl List */
|
||||
|
||||
Tcl_ListObjGetElements(interp, cmdpfxObj, &listc, &listv);
|
||||
|
||||
/*
|
||||
* See [==] as well.
|
||||
* Storage for the command prefix and the additional words required for
|
||||
* the invocation of methods in the command handler.
|
||||
*
|
||||
* listv [0] [listc-1] | [listc] [listc+1] |
|
||||
* argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2]
|
||||
* cmd ... pfx | method chan | detail1 detail2
|
||||
*/
|
||||
|
||||
rcPtr->argc = listc + 2;
|
||||
rcPtr->argv = ckalloc(sizeof(Tcl_Obj *) * (listc+4));
|
||||
|
||||
/*
|
||||
* Duplicate object references.
|
||||
*/
|
||||
|
||||
for (i=0; i<listc ; i++) {
|
||||
Tcl_Obj *word = rcPtr->argv[i] = listv[i];
|
||||
|
||||
Tcl_IncrRefCount(word);
|
||||
rcPtr->cmd = TclListObjCopy(NULL, cmdpfxObj);
|
||||
Tcl_IncrRefCount(rcPtr->cmd);
|
||||
rcPtr->methods = Tcl_NewListObj(METH_WRITE + 1, NULL);
|
||||
while (mn <= METH_WRITE) {
|
||||
Tcl_ListObjAppendElement(NULL, rcPtr->methods,
|
||||
Tcl_NewStringObj(methodNames[mn++], -1));
|
||||
}
|
||||
|
||||
i++; /* Skip placeholder for method */
|
||||
|
||||
/*
|
||||
* [Bug 1667990]: See [x] in FreeReflectedChannel for release
|
||||
*/
|
||||
|
||||
rcPtr->argv[i] = handleObj;
|
||||
Tcl_IncrRefCount(handleObj);
|
||||
|
||||
/*
|
||||
* The next two objects are kept empty, varying arguments.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialization complete.
|
||||
*/
|
||||
|
||||
Tcl_IncrRefCount(rcPtr->methods);
|
||||
rcPtr->name = handleObj;
|
||||
Tcl_IncrRefCount(rcPtr->name);
|
||||
return rcPtr;
|
||||
}
|
||||
|
||||
@@ -2271,45 +2186,15 @@ NextHandle(void)
|
||||
}
|
||||
|
||||
static void
|
||||
FreeReflectedChannelArgs(
|
||||
ReflectedChannel *rcPtr)
|
||||
{
|
||||
int i, n = rcPtr->argc - 2;
|
||||
|
||||
if (n < 0) {
|
||||
return;
|
||||
}
|
||||
for (i=0; i<n; i++) {
|
||||
Tcl_DecrRefCount(rcPtr->argv[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* [Bug 1667990]: See [x] in NewReflectedChannel for lock. n+1 = argc-1.
|
||||
*/
|
||||
|
||||
Tcl_DecrRefCount(rcPtr->argv[n+1]);
|
||||
|
||||
rcPtr->argc = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
FreeReflectedChannel(
|
||||
ReflectedChannel *rcPtr)
|
||||
{
|
||||
Channel *chanPtr = (Channel *) rcPtr->chan;
|
||||
|
||||
if (chanPtr->typePtr != &tclRChannelType) {
|
||||
/*
|
||||
* Delete a cloned ChannelType structure.
|
||||
*/
|
||||
|
||||
ckfree(chanPtr->typePtr);
|
||||
chanPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
FreeReflectedChannelArgs(rcPtr);
|
||||
|
||||
ckfree(rcPtr->argv);
|
||||
Tcl_Release(chanPtr);
|
||||
Tcl_DecrRefCount(rcPtr->name);
|
||||
Tcl_DecrRefCount(rcPtr->methods);
|
||||
Tcl_DecrRefCount(rcPtr->cmd);
|
||||
ckfree(rcPtr);
|
||||
}
|
||||
|
||||
@@ -2340,16 +2225,16 @@ FreeReflectedChannel(
|
||||
static int
|
||||
InvokeTclMethod(
|
||||
ReflectedChannel *rcPtr,
|
||||
const char *method,
|
||||
MethodName method,
|
||||
Tcl_Obj *argOneObj, /* NULL'able */
|
||||
Tcl_Obj *argTwoObj, /* NULL'able */
|
||||
Tcl_Obj **resultObjPtr) /* NULL'able */
|
||||
{
|
||||
int cmdc; /* #words in constructed command */
|
||||
Tcl_Obj *methObj = NULL; /* Method name in object form */
|
||||
Tcl_InterpState sr; /* State of handler interp */
|
||||
int result; /* Result code of method invokation */
|
||||
Tcl_Obj *resObj = NULL; /* Result of method invokation. */
|
||||
Tcl_Obj *cmd;
|
||||
|
||||
if (rcPtr->dead) {
|
||||
/*
|
||||
@@ -2372,19 +2257,15 @@ InvokeTclMethod(
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE (5): Decide impl. issue: Cache objects with method names? Needs
|
||||
* TSD data as reflections can be created in many different threads.
|
||||
* NO: Caching of command resolutions means storage per channel.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Insert method into the pre-allocated area, after the command prefix,
|
||||
* Insert method into the callback command, after the command prefix,
|
||||
* before the channel id.
|
||||
*/
|
||||
|
||||
methObj = Tcl_NewStringObj(method, -1);
|
||||
Tcl_IncrRefCount(methObj);
|
||||
rcPtr->argv[rcPtr->argc - 2] = methObj;
|
||||
cmd = TclListObjCopy(NULL, rcPtr->cmd);
|
||||
|
||||
Tcl_ListObjIndex(NULL, rcPtr->methods, method, &methObj);
|
||||
Tcl_ListObjAppendElement(NULL, cmd, methObj);
|
||||
Tcl_ListObjAppendElement(NULL, cmd, rcPtr->name);
|
||||
|
||||
/*
|
||||
* Append the additional argument containing method specific details
|
||||
@@ -2394,13 +2275,10 @@ InvokeTclMethod(
|
||||
* The objects will survive the Tcl_EvalObjv without change.
|
||||
*/
|
||||
|
||||
cmdc = rcPtr->argc;
|
||||
if (argOneObj) {
|
||||
rcPtr->argv[cmdc] = argOneObj;
|
||||
cmdc++;
|
||||
Tcl_ListObjAppendElement(NULL, cmd, argOneObj);
|
||||
if (argTwoObj) {
|
||||
rcPtr->argv[cmdc] = argTwoObj;
|
||||
cmdc++;
|
||||
Tcl_ListObjAppendElement(NULL, cmd, argTwoObj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2409,9 +2287,10 @@ InvokeTclMethod(
|
||||
* existing state intact.
|
||||
*/
|
||||
|
||||
Tcl_IncrRefCount(cmd);
|
||||
sr = Tcl_SaveInterpState(rcPtr->interp, 0 /* Dummy */);
|
||||
Tcl_Preserve(rcPtr->interp);
|
||||
result = Tcl_EvalObjv(rcPtr->interp, cmdc, rcPtr->argv, TCL_EVAL_GLOBAL);
|
||||
result = Tcl_EvalObjEx(rcPtr->interp, cmd, TCL_EVAL_GLOBAL);
|
||||
|
||||
/*
|
||||
* We do not try to extract the result information if the caller has no
|
||||
@@ -2437,7 +2316,6 @@ InvokeTclMethod(
|
||||
*/
|
||||
|
||||
if (result != TCL_ERROR) {
|
||||
Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rcPtr->argv);
|
||||
int cmdLen;
|
||||
const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen);
|
||||
|
||||
@@ -2451,24 +2329,16 @@ InvokeTclMethod(
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
Tcl_AppendObjToErrorInfo(rcPtr->interp, Tcl_ObjPrintf(
|
||||
"\n (chan handler subcommand \"%s\")", method));
|
||||
"\n (chan handler subcommand \"%s\")",
|
||||
methodNames[method]));
|
||||
resObj = MarshallError(rcPtr->interp);
|
||||
}
|
||||
Tcl_IncrRefCount(resObj);
|
||||
}
|
||||
Tcl_DecrRefCount(cmd);
|
||||
Tcl_RestoreInterpState(rcPtr->interp, sr);
|
||||
Tcl_Release(rcPtr->interp);
|
||||
|
||||
/*
|
||||
* Cleanup of the dynamic parts of the command.
|
||||
*
|
||||
* The detail objects survived the Tcl_EvalObjv without change because of
|
||||
* the contract. Therefore there is no need to decrement the refcounts. Only
|
||||
* the internal method object has to be disposed of.
|
||||
*/
|
||||
|
||||
Tcl_DecrRefCount(methObj);
|
||||
|
||||
/*
|
||||
* The resObj has a ref count of 1 at this location. This means that the
|
||||
* caller of InvokeTclMethod has to dispose of it (but only if it was
|
||||
@@ -2700,7 +2570,6 @@ DeleteReflectedChannelMap(
|
||||
}
|
||||
|
||||
rcPtr->dead = 1;
|
||||
FreeReflectedChannelArgs(rcPtr);
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
}
|
||||
#endif
|
||||
@@ -2840,7 +2709,6 @@ DeleteThreadReflectedChannelMap(
|
||||
ReflectedChannel *rcPtr = Tcl_GetChannelInstanceData(chan);
|
||||
|
||||
rcPtr->dead = 1;
|
||||
FreeReflectedChannelArgs(rcPtr);
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
}
|
||||
ckfree(rcmPtr);
|
||||
@@ -3018,17 +2886,19 @@ ForwardProc(
|
||||
* call upon for the driver.
|
||||
*/
|
||||
|
||||
case ForwardedClose:
|
||||
case ForwardedClose: {
|
||||
/*
|
||||
* No parameters/results.
|
||||
*/
|
||||
|
||||
if (InvokeTclMethod(rcPtr, "finalize", NULL, NULL, &resObj)!=TCL_OK) {
|
||||
const Tcl_ChannelType *tctPtr;
|
||||
|
||||
if (InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj)!=TCL_OK) {
|
||||
ForwardSetObjError(paramPtr, resObj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Freeing is done here, in the origin thread, because the argv[]
|
||||
* Freeing is done here, in the origin thread, callback command
|
||||
* objects belong to this thread. Deallocating them in a different
|
||||
* thread is not allowed
|
||||
*
|
||||
@@ -3047,15 +2917,21 @@ ForwardProc(
|
||||
Tcl_GetChannelName(rcPtr->chan));
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
|
||||
FreeReflectedChannelArgs(rcPtr);
|
||||
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
|
||||
if (tctPtr && tctPtr != &tclRChannelType) {
|
||||
ckfree((char *)tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
}
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
break;
|
||||
}
|
||||
|
||||
case ForwardedInput: {
|
||||
Tcl_Obj *toReadObj = Tcl_NewIntObj(paramPtr->input.toRead);
|
||||
Tcl_IncrRefCount(toReadObj);
|
||||
|
||||
Tcl_Preserve(rcPtr);
|
||||
if (InvokeTclMethod(rcPtr, "read", toReadObj, NULL, &resObj)!=TCL_OK){
|
||||
if (InvokeTclMethod(rcPtr, METH_READ, toReadObj, NULL, &resObj)!=TCL_OK){
|
||||
int code = ErrnoReturn(rcPtr, resObj);
|
||||
|
||||
if (code < 0) {
|
||||
@@ -3095,7 +2971,7 @@ ForwardProc(
|
||||
Tcl_IncrRefCount(bufObj);
|
||||
|
||||
Tcl_Preserve(rcPtr);
|
||||
if (InvokeTclMethod(rcPtr, "write", bufObj, NULL, &resObj) != TCL_OK) {
|
||||
if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) {
|
||||
int code = ErrnoReturn(rcPtr, resObj);
|
||||
|
||||
if (code < 0) {
|
||||
@@ -3138,7 +3014,7 @@ ForwardProc(
|
||||
Tcl_IncrRefCount(baseObj);
|
||||
|
||||
Tcl_Preserve(rcPtr);
|
||||
if (InvokeTclMethod(rcPtr, "seek", offObj, baseObj, &resObj)!=TCL_OK){
|
||||
if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK){
|
||||
ForwardSetObjError(paramPtr, resObj);
|
||||
paramPtr->seek.offset = -1;
|
||||
} else {
|
||||
@@ -3174,7 +3050,7 @@ ForwardProc(
|
||||
/* assert maskObj.refCount == 1 */
|
||||
|
||||
Tcl_Preserve(rcPtr);
|
||||
(void) InvokeTclMethod(rcPtr, "watch", maskObj, NULL, NULL);
|
||||
(void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL);
|
||||
Tcl_DecrRefCount(maskObj);
|
||||
Tcl_Release(rcPtr);
|
||||
break;
|
||||
@@ -3185,7 +3061,7 @@ ForwardProc(
|
||||
|
||||
Tcl_IncrRefCount(blockObj);
|
||||
Tcl_Preserve(rcPtr);
|
||||
if (InvokeTclMethod(rcPtr, "blocking", blockObj, NULL,
|
||||
if (InvokeTclMethod(rcPtr, METH_BLOCKING, blockObj, NULL,
|
||||
&resObj) != TCL_OK) {
|
||||
ForwardSetObjError(paramPtr, resObj);
|
||||
}
|
||||
@@ -3201,7 +3077,7 @@ ForwardProc(
|
||||
Tcl_IncrRefCount(optionObj);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
Tcl_Preserve(rcPtr);
|
||||
if (InvokeTclMethod(rcPtr, "configure", optionObj, valueObj,
|
||||
if (InvokeTclMethod(rcPtr, METH_CONFIGURE, optionObj, valueObj,
|
||||
&resObj) != TCL_OK) {
|
||||
ForwardSetObjError(paramPtr, resObj);
|
||||
}
|
||||
@@ -3220,7 +3096,7 @@ ForwardProc(
|
||||
|
||||
Tcl_IncrRefCount(optionObj);
|
||||
Tcl_Preserve(rcPtr);
|
||||
if (InvokeTclMethod(rcPtr, "cget", optionObj, NULL, &resObj)!=TCL_OK){
|
||||
if (InvokeTclMethod(rcPtr, METH_CGET, optionObj, NULL, &resObj)!=TCL_OK){
|
||||
ForwardSetObjError(paramPtr, resObj);
|
||||
} else {
|
||||
TclDStringAppendObj(paramPtr->getOpt.value, resObj);
|
||||
@@ -3236,7 +3112,7 @@ ForwardProc(
|
||||
*/
|
||||
|
||||
Tcl_Preserve(rcPtr);
|
||||
if (InvokeTclMethod(rcPtr, "cgetall", NULL, NULL, &resObj) != TCL_OK){
|
||||
if (InvokeTclMethod(rcPtr, METH_CGETALL, NULL, NULL, &resObj) != TCL_OK){
|
||||
ForwardSetObjError(paramPtr, resObj);
|
||||
} else {
|
||||
/*
|
||||
|
||||
+39
-51
@@ -457,8 +457,7 @@ static void TimerKill(ReflectedTransform *rtPtr);
|
||||
static void TimerSetup(ReflectedTransform *rtPtr);
|
||||
static void TimerRun(ClientData clientData);
|
||||
static int TransformRead(ReflectedTransform *rtPtr,
|
||||
int *errorCodePtr, unsigned char *buf,
|
||||
int toRead);
|
||||
int *errorCodePtr, Tcl_Obj *bufObj);
|
||||
static int TransformWrite(ReflectedTransform *rtPtr,
|
||||
int *errorCodePtr, unsigned char *buf,
|
||||
int toWrite);
|
||||
@@ -1063,6 +1062,7 @@ ReflectInput(
|
||||
{
|
||||
ReflectedTransform *rtPtr = clientData;
|
||||
int gotBytes, copied, readBytes;
|
||||
Tcl_Obj *bufObj;
|
||||
|
||||
/*
|
||||
* The following check can be done before thread redirection, because we
|
||||
@@ -1078,6 +1078,9 @@ ReflectInput(
|
||||
|
||||
Tcl_Preserve(rtPtr);
|
||||
|
||||
/* TODO: Consider a more appropriate buffer size. */
|
||||
bufObj = Tcl_NewByteArrayObj(NULL, toRead);
|
||||
Tcl_IncrRefCount(bufObj);
|
||||
gotBytes = 0;
|
||||
while (toRead > 0) {
|
||||
/*
|
||||
@@ -1129,52 +1132,40 @@ ReflectInput(
|
||||
goto stop;
|
||||
}
|
||||
|
||||
readBytes = Tcl_ReadRaw(rtPtr->parent, buf, toRead);
|
||||
if (readBytes < 0) {
|
||||
/*
|
||||
* Report errors to caller. The state of the seek system is
|
||||
* unchanged!
|
||||
*/
|
||||
|
||||
if ((Tcl_GetErrno() == EAGAIN) && (gotBytes > 0)) {
|
||||
readBytes = Tcl_ReadRaw(rtPtr->parent,
|
||||
(char *) Tcl_SetByteArrayLength(bufObj, toRead), toRead);
|
||||
if (readBytes < 0) {
|
||||
if (Tcl_InputBlocked(rtPtr->parent) && (gotBytes > 0)) {
|
||||
|
||||
/*
|
||||
* EAGAIN is a special situation. If we had some data before
|
||||
* we report that instead of the request to re-try.
|
||||
* Down channel is blocked and offers zero additional bytes.
|
||||
* The nonzero gotBytes already returned makes the total
|
||||
* operation a valid short read. Return to caller.
|
||||
*/
|
||||
|
||||
goto stop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Either the down channel is not blocked (a real error)
|
||||
* or it is and there are gotBytes==0 byte copied so far.
|
||||
* In either case, pass up the error, so we either report
|
||||
* any real error, or do not mistakenly signal EOF by
|
||||
* returning 0 to the caller.
|
||||
*/
|
||||
|
||||
*errorCodePtr = Tcl_GetErrno();
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (readBytes == 0) {
|
||||
|
||||
/*
|
||||
* Check wether we hit on EOF in 'parent' or not. If not
|
||||
* differentiate between blocking and non-blocking modes. In
|
||||
* non-blocking mode we ran temporarily out of data. Signal this
|
||||
* to the caller via EWOULDBLOCK and error return (-1). In the
|
||||
* other cases we simply return what we got and let the caller
|
||||
* wait for more. On the other hand, if we got an EOF we have to
|
||||
* convert and flush all waiting partial data.
|
||||
* Zero returned from Tcl_ReadRaw() always indicates EOF
|
||||
* on the down channel.
|
||||
*/
|
||||
|
||||
if (!Tcl_Eof(rtPtr->parent)) {
|
||||
/*
|
||||
* The state of the seek system is unchanged!
|
||||
*/
|
||||
|
||||
if ((gotBytes == 0) && rtPtr->nonblocking) {
|
||||
*errorCodePtr = EWOULDBLOCK;
|
||||
goto error;
|
||||
}
|
||||
goto stop;
|
||||
} else {
|
||||
/*
|
||||
* Eof in parent.
|
||||
*/
|
||||
|
||||
|
||||
if (rtPtr->readIsDrained) {
|
||||
goto stop;
|
||||
}
|
||||
@@ -1198,13 +1189,7 @@ ReflectInput(
|
||||
goto stop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset eof, force caller to drain result buffer.
|
||||
*/
|
||||
|
||||
((Channel *) rtPtr->parent)->state->flags &= ~CHANNEL_EOF;
|
||||
continue; /* at: while (toRead > 0) */
|
||||
}
|
||||
} /* readBytes == 0 */
|
||||
|
||||
/*
|
||||
@@ -1213,12 +1198,20 @@ ReflectInput(
|
||||
* iteration will put it into the result.
|
||||
*/
|
||||
|
||||
if (!TransformRead(rtPtr, errorCodePtr, UCHARP(buf), readBytes)) {
|
||||
Tcl_SetByteArrayLength(bufObj, readBytes);
|
||||
if (!TransformRead(rtPtr, errorCodePtr, bufObj)) {
|
||||
goto error;
|
||||
}
|
||||
if (Tcl_IsShared(bufObj)) {
|
||||
Tcl_DecrRefCount(bufObj);
|
||||
bufObj = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(bufObj);
|
||||
}
|
||||
Tcl_SetByteArrayLength(bufObj, 0);
|
||||
} /* while toRead > 0 */
|
||||
|
||||
stop:
|
||||
Tcl_DecrRefCount(bufObj);
|
||||
Tcl_Release(rtPtr);
|
||||
return gotBytes;
|
||||
|
||||
@@ -2010,6 +2003,7 @@ InvokeTclMethod(
|
||||
|
||||
sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */);
|
||||
Tcl_Preserve(rtPtr);
|
||||
Tcl_Preserve(rtPtr->interp);
|
||||
result = Tcl_EvalObjv(rtPtr->interp, cmdc, rtPtr->argv, TCL_EVAL_GLOBAL);
|
||||
|
||||
/*
|
||||
@@ -2054,6 +2048,7 @@ InvokeTclMethod(
|
||||
Tcl_IncrRefCount(resObj);
|
||||
}
|
||||
Tcl_RestoreInterpState(rtPtr->interp, sr);
|
||||
Tcl_Release(rtPtr->interp);
|
||||
Tcl_Release(rtPtr);
|
||||
|
||||
/*
|
||||
@@ -3065,10 +3060,8 @@ static int
|
||||
TransformRead(
|
||||
ReflectedTransform *rtPtr,
|
||||
int *errorCodePtr,
|
||||
unsigned char *buf,
|
||||
int toRead)
|
||||
Tcl_Obj *bufObj)
|
||||
{
|
||||
Tcl_Obj *bufObj;
|
||||
Tcl_Obj *resObj;
|
||||
int bytec; /* Number of returned bytes */
|
||||
unsigned char *bytev; /* Array of returned bytes */
|
||||
@@ -3081,8 +3074,8 @@ TransformRead(
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
p.transform.buf = (char *) buf;
|
||||
p.transform.size = toRead;
|
||||
p.transform.buf = (char *) Tcl_GetByteArrayFromObj(bufObj,
|
||||
&(p.transform.size));
|
||||
|
||||
ForwardOpToOwnerThread(rtPtr, ForwardedInput, &p);
|
||||
|
||||
@@ -3102,12 +3095,8 @@ TransformRead(
|
||||
/* ASSERT: rtPtr->method & FLAG(METH_READ) */
|
||||
/* ASSERT: rtPtr->mode & TCL_READABLE */
|
||||
|
||||
bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toRead);
|
||||
Tcl_IncrRefCount(bufObj);
|
||||
|
||||
if (InvokeTclMethod(rtPtr, "read", bufObj, NULL, &resObj) != TCL_OK) {
|
||||
Tcl_SetChannelError(rtPtr->chan, resObj);
|
||||
Tcl_DecrRefCount(bufObj);
|
||||
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
|
||||
*errorCodePtr = EINVAL;
|
||||
return 0;
|
||||
@@ -3116,7 +3105,6 @@ TransformRead(
|
||||
bytev = Tcl_GetByteArrayFromObj(resObj, &bytec);
|
||||
ResultAdd(&rtPtr->result, bytev, bytec);
|
||||
|
||||
Tcl_DecrRefCount(bufObj);
|
||||
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
|
||||
return 1;
|
||||
}
|
||||
|
||||
+89
-5
@@ -19,11 +19,17 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
# include "tclWinInt.h"
|
||||
#endif
|
||||
#include "tclFileSystem.h"
|
||||
|
||||
#ifdef TCL_TEMPLOAD_NO_UNLINK
|
||||
#ifndef NO_FSTATFS
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* struct FilesystemRecord --
|
||||
*
|
||||
@@ -792,7 +798,7 @@ TclFinalizeFilesystem(void)
|
||||
* filesystem is likely to fail.
|
||||
*/
|
||||
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
TclWinEncodingsCleanup();
|
||||
#endif
|
||||
}
|
||||
@@ -819,7 +825,7 @@ TclResetFilesystem(void)
|
||||
filesystemList = &nativeFilesystemRecord;
|
||||
theFilesystemEpoch++;
|
||||
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Cleans up the win32 API filesystem proc lookup table. This must happen
|
||||
* very late in finalization so that deleting of copied dlls can occur.
|
||||
@@ -3110,6 +3116,82 @@ 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.
|
||||
*
|
||||
* Doing the unlink is also an issue within docker containers, whose AUFS
|
||||
* bungles this as well, see
|
||||
* https://github.com/dotcloud/docker/issues/1911
|
||||
*
|
||||
* For these situations the change below makes the execution of the unlink
|
||||
* semi-controllable at runtime.
|
||||
*
|
||||
* An AUFS filesystem (if it can be detected) will force avoidance of
|
||||
* unlink. The env variable TCL_TEMPLOAD_NO_UNLINK allows detection of a
|
||||
* users general request (unlink and not.
|
||||
*
|
||||
* By default the unlink is done (if not in AUFS). However if the variable is
|
||||
* present and set to true (any integer > 0) then the unlink is skipped.
|
||||
*/
|
||||
|
||||
int
|
||||
TclSkipUnlink (Tcl_Obj* shlibFile)
|
||||
{
|
||||
/* 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)
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
|
||||
skipstr = getenv ("TCL_TEMPLOAD_NO_UNLINK");
|
||||
if (skipstr && (skipstr[0] != '\0')) {
|
||||
return atoi(skipstr);
|
||||
}
|
||||
|
||||
#ifdef TCL_TEMPLOAD_NO_UNLINK
|
||||
#ifndef NO_FSTATFS
|
||||
{
|
||||
struct statfs fs;
|
||||
/* 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/
|
||||
* Better reference will be gladly taken.
|
||||
*/
|
||||
#ifndef AUFS_SUPER_MAGIC
|
||||
#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
|
||||
#endif /* AUFS_SUPER_MAGIC */
|
||||
if ((statfs(Tcl_GetString (shlibFile), &fs) == 0) &&
|
||||
(fs.f_type == AUFS_SUPER_MAGIC)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif /* ... NO_FSTATFS */
|
||||
#endif /* ... TCL_TEMPLOAD_NO_UNLINK */
|
||||
|
||||
/* Fallback: !hpux, no EV override, no AUFS (detection, nor detected):
|
||||
* Don't skip */
|
||||
return 0;
|
||||
#endif /* hpux */
|
||||
}
|
||||
|
||||
int
|
||||
Tcl_LoadFile(
|
||||
Tcl_Interp *interp, /* Used for error reporting. */
|
||||
@@ -3255,7 +3337,7 @@ Tcl_LoadFile(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
#ifndef __WIN32__
|
||||
#ifndef _WIN32
|
||||
/*
|
||||
* Do we need to set appropriate permissions on the file? This may be
|
||||
* required on some systems. On Unix we could loop over the file
|
||||
@@ -3300,7 +3382,9 @@ Tcl_LoadFile(
|
||||
* avoids any worries about leaving the copy laying around on exit.
|
||||
*/
|
||||
|
||||
if (Tcl_FSDeleteFile(copyToPtr) == TCL_OK) {
|
||||
if (
|
||||
!TclSkipUnlink (copyToPtr) &&
|
||||
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
|
||||
Tcl_DecrRefCount(copyToPtr);
|
||||
|
||||
/*
|
||||
|
||||
@@ -1686,6 +1686,7 @@ typedef struct Command {
|
||||
#define CMD_TRACE_ACTIVE 0x2
|
||||
#define CMD_HAS_EXEC_TRACES 0x4
|
||||
#define CMD_COMPILES_EXPANDED 0x8
|
||||
#define CMD_REDEF_IN_PROGRESS 0x10
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -2451,6 +2452,30 @@ typedef struct List {
|
||||
TclGetIntForIndex(interp, objPtr, ignore, idxPtr)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro used to save a function call for common uses of
|
||||
* Tcl_GetWideIntFromObj(). The ANSI C "prototype" is:
|
||||
*
|
||||
* MODULE_SCOPE int TclGetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
* Tcl_WideInt *wideIntPtr);
|
||||
*/
|
||||
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
|
||||
(((objPtr)->typePtr == &tclIntType) \
|
||||
? (*(wideIntPtr) = (Tcl_WideInt) \
|
||||
((objPtr)->internalRep.longValue), TCL_OK) : \
|
||||
Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
|
||||
#else /* !TCL_WIDE_INT_IS_LONG */
|
||||
#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
|
||||
(((objPtr)->typePtr == &tclWideIntType) \
|
||||
? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \
|
||||
((objPtr)->typePtr == &tclIntType) \
|
||||
? (*(wideIntPtr) = (Tcl_WideInt) \
|
||||
((objPtr)->internalRep.longValue), TCL_OK) : \
|
||||
Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
/*
|
||||
* Flag values for TclTraceDictPath().
|
||||
*
|
||||
@@ -2639,6 +2664,8 @@ MODULE_SCOPE char *tclMemDumpFileName;
|
||||
MODULE_SCOPE TclPlatformType tclPlatform;
|
||||
MODULE_SCOPE Tcl_NotifierProcs tclNotifierHooks;
|
||||
|
||||
MODULE_SCOPE Tcl_Encoding tclIdentityEncoding;
|
||||
|
||||
/*
|
||||
* TIP #233 (Virtualized Time)
|
||||
* Data for the time hooks, if any.
|
||||
@@ -2893,6 +2920,7 @@ MODULE_SCOPE void TclFinalizeObjects(void);
|
||||
MODULE_SCOPE void TclFinalizePreserve(void);
|
||||
MODULE_SCOPE void TclFinalizeSynchronization(void);
|
||||
MODULE_SCOPE void TclFinalizeThreadAlloc(void);
|
||||
MODULE_SCOPE void TclFinalizeThreadAllocThread(void);
|
||||
MODULE_SCOPE void TclFinalizeThreadData(void);
|
||||
MODULE_SCOPE void TclFinalizeThreadObjects(void);
|
||||
MODULE_SCOPE double TclFloor(const mp_int *a);
|
||||
@@ -2918,6 +2946,8 @@ MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp,
|
||||
MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclGetSourceFromFrame(CmdFrame *cfPtr, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE char * TclGetStringStorage(Tcl_Obj *objPtr,
|
||||
unsigned int *sizePtr);
|
||||
MODULE_SCOPE int TclGlob(Tcl_Interp *interp, char *pattern,
|
||||
Tcl_Obj *unquotedPrefix, int globFlags,
|
||||
Tcl_GlobTypeData *types);
|
||||
@@ -3571,6 +3601,9 @@ MODULE_SCOPE int TclCompileNamespaceCodeCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileNamespaceCurrentCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileNamespaceOriginCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileNamespaceQualifiersCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3586,6 +3619,12 @@ MODULE_SCOPE int TclCompileNamespaceWhichCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileNoOp(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileObjectNextCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileObjectNextToCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileObjectSelfCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3613,6 +3652,9 @@ MODULE_SCOPE int TclCompileStringFirstCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileStringIndexCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileStringIsCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileStringLastCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3679,6 +3721,9 @@ MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileYieldCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileYieldToCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileBasic0ArgCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#ifndef _TCLINTPLATDECLS
|
||||
#define _TCLINTPLATDECLS
|
||||
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
# define Tcl_DirEntry void
|
||||
# define DIR void
|
||||
#endif
|
||||
@@ -45,7 +45,7 @@ extern "C" {
|
||||
* Exported function declarations:
|
||||
*/
|
||||
|
||||
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
/* 0 */
|
||||
EXTERN void TclGetAndDetachPids(Tcl_Interp *interp,
|
||||
Tcl_Channel chan);
|
||||
@@ -104,7 +104,7 @@ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
|
||||
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
|
||||
Tcl_Obj *resultingNameObj);
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
/* 0 */
|
||||
EXTERN void TclWinConvertError(DWORD errCode);
|
||||
/* 1 */
|
||||
@@ -258,7 +258,7 @@ typedef struct TclIntPlatStubs {
|
||||
int magic;
|
||||
void *hooks;
|
||||
|
||||
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */
|
||||
int (*tclpCloseFile) (TclFile file); /* 1 */
|
||||
Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */
|
||||
@@ -291,7 +291,7 @@ typedef struct TclIntPlatStubs {
|
||||
int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */
|
||||
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
void (*tclWinConvertError) (DWORD errCode); /* 0 */
|
||||
void (*tclWinConvertWSAError) (DWORD errCode); /* 1 */
|
||||
struct servent * (*tclWinGetServByName) (const char *nm, const char *proto); /* 2 */
|
||||
@@ -371,7 +371,7 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
* Inline function declarations:
|
||||
*/
|
||||
|
||||
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#define TclGetAndDetachPids \
|
||||
(tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */
|
||||
#define TclpCloseFile \
|
||||
@@ -420,7 +420,7 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
#define TclUnixOpenTemporaryFile \
|
||||
(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
#define TclWinConvertError \
|
||||
(tclIntPlatStubsPtr->tclWinConvertError) /* 0 */
|
||||
#define TclWinConvertWSAError \
|
||||
@@ -550,9 +550,15 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
|
||||
#undef TclpInetNtoa
|
||||
#define TclpInetNtoa inet_ntoa
|
||||
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__)
|
||||
#if defined(_WIN32)
|
||||
# undef TclWinNToHS
|
||||
# undef TclWinGetServByName
|
||||
# undef TclWinGetSockOpt
|
||||
# undef TclWinSetSockOpt
|
||||
# define TclWinNToHS ntohs
|
||||
# define TclWinGetServByName getservbyname
|
||||
# define TclWinGetSockOpt getsockopt
|
||||
# define TclWinSetSockOpt setsockopt
|
||||
#else
|
||||
# undef TclpGetPid
|
||||
# define TclpGetPid(pid) ((unsigned long) (pid))
|
||||
|
||||
+2
-2
@@ -830,7 +830,7 @@ Tcl_UnloadObjCmd(
|
||||
* Unload the shared library from the application memory...
|
||||
*/
|
||||
|
||||
#if defined(TCL_UNLOAD_DLLS) || defined(__WIN32__)
|
||||
#if defined(TCL_UNLOAD_DLLS) || defined(_WIN32)
|
||||
/*
|
||||
* Some Unix dlls are poorly behaved - registering things like atexit
|
||||
* calls that can't be unregistered. If you unload such dlls, you get
|
||||
@@ -1151,7 +1151,7 @@ TclFinalizeLoad(void)
|
||||
pkgPtr = firstPackagePtr;
|
||||
firstPackagePtr = pkgPtr->nextPtr;
|
||||
|
||||
#if defined(TCL_UNLOAD_DLLS) || defined(__WIN32__)
|
||||
#if defined(TCL_UNLOAD_DLLS) || defined(_WIN32)
|
||||
/*
|
||||
* Some Unix dlls are poorly behaved - registering things like atexit
|
||||
* calls that can't be unregistered. If you unload such dlls, you get
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@
|
||||
* we have to translate that to strcmp here.
|
||||
*/
|
||||
|
||||
#ifndef __WIN32__
|
||||
#ifndef _WIN32
|
||||
# define TCHAR char
|
||||
# define TEXT(arg) arg
|
||||
# define _tcscmp strcmp
|
||||
|
||||
+1
-1
@@ -171,7 +171,7 @@ static const EnsembleImplMap defaultNamespaceMap[] = {
|
||||
{"forget", NamespaceForgetCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"import", NamespaceImportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
|
||||
{"inscope", NamespaceInscopeCmd, NULL, NRNamespaceInscopeCmd, NULL, 0},
|
||||
{"origin", NamespaceOriginCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"origin", NamespaceOriginCmd, TclCompileNamespaceOriginCmd, NULL, NULL, 0},
|
||||
{"parent", NamespaceParentCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"path", NamespacePathCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"qualifiers", NamespaceQualifiersCmd, TclCompileNamespaceQualifiersCmd, NULL, NULL, 0},
|
||||
|
||||
+6
-4
@@ -437,10 +437,12 @@ InitFoundation(
|
||||
* ensemble.
|
||||
*/
|
||||
|
||||
Tcl_CreateObjCommand(interp, "::oo::Helpers::next", TclOONextObjCmd, NULL,
|
||||
NULL);
|
||||
Tcl_CreateObjCommand(interp, "::oo::Helpers::nextto", TclOONextToObjCmd,
|
||||
NULL, NULL);
|
||||
cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::next",
|
||||
NULL, TclOONextObjCmd, NULL, NULL);
|
||||
cmdPtr->compileProc = TclCompileObjectNextCmd;
|
||||
cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::nextto",
|
||||
NULL, TclOONextToObjCmd, NULL, NULL);
|
||||
cmdPtr->compileProc = TclCompileObjectNextToCmd;
|
||||
cmdPtr = (Command *) Tcl_CreateObjCommand(interp, "::oo::Helpers::self",
|
||||
TclOOSelfObjCmd, NULL, NULL);
|
||||
cmdPtr->compileProc = TclCompileObjectSelfCmd;
|
||||
|
||||
@@ -18,6 +18,7 @@ library tclOO
|
||||
|
||||
interface tclOO
|
||||
hooks tclOOInt
|
||||
scspec TCLAPI
|
||||
|
||||
declare 0 {
|
||||
Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp,
|
||||
|
||||
+25
-18
@@ -17,16 +17,11 @@
|
||||
#include "tclOOInt.h"
|
||||
|
||||
static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp);
|
||||
static int AfterNRDestructor(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int DecrRefsPostClassConstructor(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int FinalizeConstruction(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int FinalizeEval(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static int RestoreFrame(ClientData data[],
|
||||
Tcl_Interp *interp, int result);
|
||||
static Tcl_NRPostProc AfterNRDestructor;
|
||||
static Tcl_NRPostProc DecrRefsPostClassConstructor;
|
||||
static Tcl_NRPostProc FinalizeConstruction;
|
||||
static Tcl_NRPostProc FinalizeEval;
|
||||
static Tcl_NRPostProc NextRestoreFrame;
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -808,7 +803,7 @@ TclOONextObjCmd(
|
||||
* that this is like [uplevel 1] and not [eval].
|
||||
*/
|
||||
|
||||
TclNRAddCallback(interp, RestoreFrame, framePtr, NULL, NULL, NULL);
|
||||
TclNRAddCallback(interp, NextRestoreFrame, framePtr, NULL,NULL,NULL);
|
||||
iPtr->varFramePtr = framePtr->callerVarPtr;
|
||||
return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1);
|
||||
}
|
||||
@@ -826,6 +821,7 @@ TclOONextToObjCmd(
|
||||
CallContext *contextPtr;
|
||||
int i;
|
||||
Tcl_Object object;
|
||||
const char *methodType;
|
||||
|
||||
/*
|
||||
* Start with sanity checks on the calling context to make sure that we
|
||||
@@ -877,8 +873,8 @@ TclOONextToObjCmd(
|
||||
* context. Note that this is like [uplevel 1] and not [eval].
|
||||
*/
|
||||
|
||||
TclNRAddCallback(interp, RestoreFrame, framePtr, contextPtr,
|
||||
INT2PTR(contextPtr->index), NULL);
|
||||
TclNRAddCallback(interp, NextRestoreFrame, framePtr,
|
||||
contextPtr, INT2PTR(contextPtr->index), NULL);
|
||||
contextPtr->index = i-1;
|
||||
iPtr->varFramePtr = framePtr->callerVarPtr;
|
||||
return TclNRObjectContextInvokeNext(interp,
|
||||
@@ -891,24 +887,35 @@ TclOONextToObjCmd(
|
||||
* is on the chain but unreachable, or not on the chain at all.
|
||||
*/
|
||||
|
||||
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
|
||||
methodType = "constructor";
|
||||
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
|
||||
methodType = "destructor";
|
||||
} else {
|
||||
methodType = "method";
|
||||
}
|
||||
|
||||
for (i=contextPtr->index ; i>=0 ; i--) {
|
||||
struct MInvoke *miPtr = contextPtr->callPtr->chain + i;
|
||||
|
||||
if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"method implementation by \"%s\" not reachable from here",
|
||||
TclGetString(objv[1])));
|
||||
"%s implementation by \"%s\" not reachable from here",
|
||||
methodType, TclGetString(objv[1])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_REACHABLE",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"method has no non-filter implementation by \"%s\"",
|
||||
TclGetString(objv[1])));
|
||||
"%s has no non-filter implementation by \"%s\"",
|
||||
methodType, TclGetString(objv[1])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
static int
|
||||
RestoreFrame(
|
||||
NextRestoreFrame(
|
||||
ClientData data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
|
||||
+38
-40
@@ -5,19 +5,19 @@
|
||||
#ifndef _TCLOODECLS
|
||||
#define _TCLOODECLS
|
||||
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#ifdef BUILD_tcl
|
||||
# define TCL_STORAGE_CLASS DLLEXPORT
|
||||
#else
|
||||
# ifdef USE_TCL_STUBS
|
||||
# undef USE_TCLOO_STUBS
|
||||
# define USE_TCLOO_STUBS
|
||||
# define TCL_STORAGE_CLASS
|
||||
#ifndef TCLAPI
|
||||
# ifdef BUILD_tcl
|
||||
# define TCLAPI extern DLLEXPORT
|
||||
# else
|
||||
# define TCL_STORAGE_CLASS DLLIMPORT
|
||||
# define TCLAPI extern DLLIMPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_TCL_STUBS
|
||||
# undef USE_TCLOO_STUBS
|
||||
# define USE_TCLOO_STUBS
|
||||
#endif
|
||||
|
||||
/* !BEGIN!: Do not edit below this line. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -29,92 +29,92 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/* 0 */
|
||||
EXTERN Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp,
|
||||
Tcl_Object sourceObject,
|
||||
const char *targetName,
|
||||
const char *targetNamespaceName);
|
||||
/* 1 */
|
||||
EXTERN Tcl_Object Tcl_GetClassAsObject(Tcl_Class clazz);
|
||||
TCLAPI Tcl_Object Tcl_GetClassAsObject(Tcl_Class clazz);
|
||||
/* 2 */
|
||||
EXTERN Tcl_Class Tcl_GetObjectAsClass(Tcl_Object object);
|
||||
TCLAPI Tcl_Class Tcl_GetObjectAsClass(Tcl_Object object);
|
||||
/* 3 */
|
||||
EXTERN Tcl_Command Tcl_GetObjectCommand(Tcl_Object object);
|
||||
TCLAPI Tcl_Command Tcl_GetObjectCommand(Tcl_Object object);
|
||||
/* 4 */
|
||||
EXTERN Tcl_Object Tcl_GetObjectFromObj(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Object Tcl_GetObjectFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
/* 5 */
|
||||
EXTERN Tcl_Namespace * Tcl_GetObjectNamespace(Tcl_Object object);
|
||||
TCLAPI Tcl_Namespace * Tcl_GetObjectNamespace(Tcl_Object object);
|
||||
/* 6 */
|
||||
EXTERN Tcl_Class Tcl_MethodDeclarerClass(Tcl_Method method);
|
||||
TCLAPI Tcl_Class Tcl_MethodDeclarerClass(Tcl_Method method);
|
||||
/* 7 */
|
||||
EXTERN Tcl_Object Tcl_MethodDeclarerObject(Tcl_Method method);
|
||||
TCLAPI Tcl_Object Tcl_MethodDeclarerObject(Tcl_Method method);
|
||||
/* 8 */
|
||||
EXTERN int Tcl_MethodIsPublic(Tcl_Method method);
|
||||
TCLAPI int Tcl_MethodIsPublic(Tcl_Method method);
|
||||
/* 9 */
|
||||
EXTERN int Tcl_MethodIsType(Tcl_Method method,
|
||||
TCLAPI int Tcl_MethodIsType(Tcl_Method method,
|
||||
const Tcl_MethodType *typePtr,
|
||||
ClientData *clientDataPtr);
|
||||
/* 10 */
|
||||
EXTERN Tcl_Obj * Tcl_MethodName(Tcl_Method method);
|
||||
TCLAPI Tcl_Obj * Tcl_MethodName(Tcl_Method method);
|
||||
/* 11 */
|
||||
EXTERN Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp,
|
||||
Tcl_Object object, Tcl_Obj *nameObj,
|
||||
int isPublic, const Tcl_MethodType *typePtr,
|
||||
ClientData clientData);
|
||||
/* 12 */
|
||||
EXTERN Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
|
||||
TCLAPI Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
|
||||
Tcl_Obj *nameObj, int isPublic,
|
||||
const Tcl_MethodType *typePtr,
|
||||
ClientData clientData);
|
||||
/* 13 */
|
||||
EXTERN Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp,
|
||||
Tcl_Class cls, const char *nameStr,
|
||||
const char *nsNameStr, int objc,
|
||||
Tcl_Obj *const *objv, int skip);
|
||||
/* 14 */
|
||||
EXTERN int Tcl_ObjectDeleted(Tcl_Object object);
|
||||
TCLAPI int Tcl_ObjectDeleted(Tcl_Object object);
|
||||
/* 15 */
|
||||
EXTERN int Tcl_ObjectContextIsFiltering(
|
||||
TCLAPI int Tcl_ObjectContextIsFiltering(
|
||||
Tcl_ObjectContext context);
|
||||
/* 16 */
|
||||
EXTERN Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context);
|
||||
TCLAPI Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context);
|
||||
/* 17 */
|
||||
EXTERN Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context);
|
||||
TCLAPI Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context);
|
||||
/* 18 */
|
||||
EXTERN int Tcl_ObjectContextSkippedArgs(
|
||||
TCLAPI int Tcl_ObjectContextSkippedArgs(
|
||||
Tcl_ObjectContext context);
|
||||
/* 19 */
|
||||
EXTERN ClientData Tcl_ClassGetMetadata(Tcl_Class clazz,
|
||||
TCLAPI ClientData Tcl_ClassGetMetadata(Tcl_Class clazz,
|
||||
const Tcl_ObjectMetadataType *typePtr);
|
||||
/* 20 */
|
||||
EXTERN void Tcl_ClassSetMetadata(Tcl_Class clazz,
|
||||
TCLAPI void Tcl_ClassSetMetadata(Tcl_Class clazz,
|
||||
const Tcl_ObjectMetadataType *typePtr,
|
||||
ClientData metadata);
|
||||
/* 21 */
|
||||
EXTERN ClientData Tcl_ObjectGetMetadata(Tcl_Object object,
|
||||
TCLAPI ClientData Tcl_ObjectGetMetadata(Tcl_Object object,
|
||||
const Tcl_ObjectMetadataType *typePtr);
|
||||
/* 22 */
|
||||
EXTERN void Tcl_ObjectSetMetadata(Tcl_Object object,
|
||||
TCLAPI void Tcl_ObjectSetMetadata(Tcl_Object object,
|
||||
const Tcl_ObjectMetadataType *typePtr,
|
||||
ClientData metadata);
|
||||
/* 23 */
|
||||
EXTERN int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp,
|
||||
TCLAPI int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp,
|
||||
Tcl_ObjectContext context, int objc,
|
||||
Tcl_Obj *const *objv, int skip);
|
||||
/* 24 */
|
||||
EXTERN Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper(
|
||||
TCLAPI Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper(
|
||||
Tcl_Object object);
|
||||
/* 25 */
|
||||
EXTERN void Tcl_ObjectSetMethodNameMapper(Tcl_Object object,
|
||||
TCLAPI void Tcl_ObjectSetMethodNameMapper(Tcl_Object object,
|
||||
Tcl_ObjectMapMethodNameProc *mapMethodNameProc);
|
||||
/* 26 */
|
||||
EXTERN void Tcl_ClassSetConstructor(Tcl_Interp *interp,
|
||||
TCLAPI void Tcl_ClassSetConstructor(Tcl_Interp *interp,
|
||||
Tcl_Class clazz, Tcl_Method method);
|
||||
/* 27 */
|
||||
EXTERN void Tcl_ClassSetDestructor(Tcl_Interp *interp,
|
||||
TCLAPI void Tcl_ClassSetDestructor(Tcl_Interp *interp,
|
||||
Tcl_Class clazz, Tcl_Method method);
|
||||
/* 28 */
|
||||
EXTERN Tcl_Obj * Tcl_GetObjectName(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Obj * Tcl_GetObjectName(Tcl_Interp *interp,
|
||||
Tcl_Object object);
|
||||
|
||||
typedef struct {
|
||||
@@ -231,6 +231,4 @@ extern const TclOOStubs *tclOOStubsPtr;
|
||||
|
||||
/* !END!: Do not edit above this line. */
|
||||
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#define TCL_STORAGE_CLASS DLLIMPORT
|
||||
#endif /* _TCLOODECLS */
|
||||
|
||||
+16
-29
@@ -5,17 +5,6 @@
|
||||
#ifndef _TCLOOINTDECLS
|
||||
#define _TCLOOINTDECLS
|
||||
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#ifdef BUILD_tcl
|
||||
# define TCL_STORAGE_CLASS DLLEXPORT
|
||||
#else
|
||||
# ifdef USE_TCL_STUBS
|
||||
# define TCL_STORAGE_CLASS
|
||||
# else
|
||||
# define TCL_STORAGE_CLASS DLLIMPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* !BEGIN!: Do not edit below this line. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -27,46 +16,46 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/* 0 */
|
||||
EXTERN Tcl_Object TclOOGetDefineCmdContext(Tcl_Interp *interp);
|
||||
TCLAPI Tcl_Object TclOOGetDefineCmdContext(Tcl_Interp *interp);
|
||||
/* 1 */
|
||||
EXTERN Tcl_Method TclOOMakeProcInstanceMethod(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Method TclOOMakeProcInstanceMethod(Tcl_Interp *interp,
|
||||
Object *oPtr, int flags, Tcl_Obj *nameObj,
|
||||
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
|
||||
const Tcl_MethodType *typePtr,
|
||||
ClientData clientData, Proc **procPtrPtr);
|
||||
/* 2 */
|
||||
EXTERN Tcl_Method TclOOMakeProcMethod(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Method TclOOMakeProcMethod(Tcl_Interp *interp,
|
||||
Class *clsPtr, int flags, Tcl_Obj *nameObj,
|
||||
const char *namePtr, Tcl_Obj *argsObj,
|
||||
Tcl_Obj *bodyObj,
|
||||
const Tcl_MethodType *typePtr,
|
||||
ClientData clientData, Proc **procPtrPtr);
|
||||
/* 3 */
|
||||
EXTERN Method * TclOONewProcInstanceMethod(Tcl_Interp *interp,
|
||||
TCLAPI Method * TclOONewProcInstanceMethod(Tcl_Interp *interp,
|
||||
Object *oPtr, int flags, Tcl_Obj *nameObj,
|
||||
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
|
||||
ProcedureMethod **pmPtrPtr);
|
||||
/* 4 */
|
||||
EXTERN Method * TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr,
|
||||
TCLAPI Method * TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr,
|
||||
int flags, Tcl_Obj *nameObj,
|
||||
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
|
||||
ProcedureMethod **pmPtrPtr);
|
||||
/* 5 */
|
||||
EXTERN int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp,
|
||||
TCLAPI int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv,
|
||||
int publicOnly, Class *startCls);
|
||||
/* 6 */
|
||||
EXTERN int TclOOIsReachable(Class *targetPtr, Class *startPtr);
|
||||
TCLAPI int TclOOIsReachable(Class *targetPtr, Class *startPtr);
|
||||
/* 7 */
|
||||
EXTERN Method * TclOONewForwardMethod(Tcl_Interp *interp,
|
||||
TCLAPI Method * TclOONewForwardMethod(Tcl_Interp *interp,
|
||||
Class *clsPtr, int isPublic,
|
||||
Tcl_Obj *nameObj, Tcl_Obj *prefixObj);
|
||||
/* 8 */
|
||||
EXTERN Method * TclOONewForwardInstanceMethod(Tcl_Interp *interp,
|
||||
TCLAPI Method * TclOONewForwardInstanceMethod(Tcl_Interp *interp,
|
||||
Object *oPtr, int isPublic, Tcl_Obj *nameObj,
|
||||
Tcl_Obj *prefixObj);
|
||||
/* 9 */
|
||||
EXTERN Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp,
|
||||
Tcl_Object oPtr,
|
||||
TclOO_PreCallProc *preCallPtr,
|
||||
TclOO_PostCallProc *postCallPtr,
|
||||
@@ -75,7 +64,7 @@ EXTERN Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp,
|
||||
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
|
||||
int flags, void **internalTokenPtr);
|
||||
/* 10 */
|
||||
EXTERN Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp,
|
||||
TCLAPI Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp,
|
||||
Tcl_Class clsPtr,
|
||||
TclOO_PreCallProc *preCallPtr,
|
||||
TclOO_PostCallProc *postCallPtr,
|
||||
@@ -84,22 +73,22 @@ EXTERN Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp,
|
||||
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
|
||||
int flags, void **internalTokenPtr);
|
||||
/* 11 */
|
||||
EXTERN int TclOOInvokeObject(Tcl_Interp *interp,
|
||||
TCLAPI int TclOOInvokeObject(Tcl_Interp *interp,
|
||||
Tcl_Object object, Tcl_Class startCls,
|
||||
int publicPrivate, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
/* 12 */
|
||||
EXTERN void TclOOObjectSetFilters(Object *oPtr, int numFilters,
|
||||
TCLAPI void TclOOObjectSetFilters(Object *oPtr, int numFilters,
|
||||
Tcl_Obj *const *filters);
|
||||
/* 13 */
|
||||
EXTERN void TclOOClassSetFilters(Tcl_Interp *interp,
|
||||
TCLAPI void TclOOClassSetFilters(Tcl_Interp *interp,
|
||||
Class *classPtr, int numFilters,
|
||||
Tcl_Obj *const *filters);
|
||||
/* 14 */
|
||||
EXTERN void TclOOObjectSetMixins(Object *oPtr, int numMixins,
|
||||
TCLAPI void TclOOObjectSetMixins(Object *oPtr, int numMixins,
|
||||
Class *const *mixins);
|
||||
/* 15 */
|
||||
EXTERN void TclOOClassSetMixins(Tcl_Interp *interp,
|
||||
TCLAPI void TclOOClassSetMixins(Tcl_Interp *interp,
|
||||
Class *classPtr, int numMixins,
|
||||
Class *const *mixins);
|
||||
|
||||
@@ -174,6 +163,4 @@ extern const TclOOIntStubs *tclOOIntStubsPtr;
|
||||
|
||||
/* !END!: Do not edit above this line. */
|
||||
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#define TCL_STORAGE_CLASS DLLIMPORT
|
||||
#endif /* _TCLOOINTDECLS */
|
||||
|
||||
@@ -512,7 +512,7 @@ TclFSGetPathType(
|
||||
|
||||
if (PATHFLAGS(pathPtr) == 0) {
|
||||
/* The path is not absolute... */
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
/* ... on Windows we must make another call to determine whether
|
||||
* it's relative or volumerelative [Bug 2571597]. */
|
||||
return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr,
|
||||
@@ -1956,7 +1956,7 @@ Tcl_FSGetNormalizedPath(
|
||||
/*
|
||||
* We have a refCount on the cwd.
|
||||
*/
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
} else if (type == TCL_PATH_VOLUME_RELATIVE) {
|
||||
/*
|
||||
* Only Windows has volume-relative paths.
|
||||
@@ -1969,7 +1969,7 @@ Tcl_FSGetNormalizedPath(
|
||||
return NULL;
|
||||
}
|
||||
pureNormalized = 0;
|
||||
#endif /* __WIN32__ */
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ extern "C" {
|
||||
* Exported function declarations:
|
||||
*/
|
||||
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
/* 0 */
|
||||
EXTERN TCHAR * Tcl_WinUtfToTChar(const char *str, int len,
|
||||
Tcl_DString *dsPtr);
|
||||
@@ -75,7 +75,7 @@ typedef struct TclPlatStubs {
|
||||
int magic;
|
||||
void *hooks;
|
||||
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
TCHAR * (*tcl_WinUtfToTChar) (const char *str, int len, Tcl_DString *dsPtr); /* 0 */
|
||||
char * (*tcl_WinTCharToUtf) (const TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
|
||||
#endif /* WIN */
|
||||
@@ -97,7 +97,7 @@ extern const TclPlatStubs *tclPlatStubsPtr;
|
||||
* Inline function declarations:
|
||||
*/
|
||||
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
#define Tcl_WinUtfToTChar \
|
||||
(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
|
||||
#define Tcl_WinTCharToUtf \
|
||||
|
||||
+32
-40
@@ -1855,9 +1855,39 @@ InterpProcNR2(
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the result code.
|
||||
* Free the stack-allocated compiled locals and CallFrame. It is important
|
||||
* to pop the call frame without freeing it first: the compiledLocals
|
||||
* cannot be freed before the frame is popped, as the local variables must
|
||||
* be deleted. But the compiledLocals must be freed first, as they were
|
||||
* allocated later on the stack.
|
||||
*/
|
||||
|
||||
if (result != TCL_OK) {
|
||||
goto process;
|
||||
}
|
||||
|
||||
done:
|
||||
if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
|
||||
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
|
||||
Tcl_Obj *r = Tcl_GetObjResult(interp);
|
||||
|
||||
TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ?
|
||||
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result,
|
||||
TclGetString(r), r);
|
||||
}
|
||||
|
||||
freePtr = iPtr->framePtr;
|
||||
Tcl_PopCallFrame(interp); /* Pop but do not free. */
|
||||
TclStackFree(interp, freePtr->compiledLocals);
|
||||
/* Free compiledLocals. */
|
||||
TclStackFree(interp, freePtr); /* Free CallFrame. */
|
||||
return result;
|
||||
|
||||
/*
|
||||
* Process any non-TCL_OK result code.
|
||||
*/
|
||||
|
||||
process:
|
||||
switch (result) {
|
||||
case TCL_RETURN:
|
||||
/*
|
||||
@@ -1892,46 +1922,8 @@ InterpProcNR2(
|
||||
*/
|
||||
|
||||
errorProc(interp, procNameObj);
|
||||
|
||||
default:
|
||||
/*
|
||||
* Process other results (OK and non-standard) by doing nothing
|
||||
* special, skipping directly to the code afterwards that cleans up
|
||||
* associated memory.
|
||||
*
|
||||
* Non-standard results are processed by passing them through quickly.
|
||||
* This means they all work as exceptions, unwinding the stack quickly
|
||||
* and neatly. Who knows how well they are handled by third-party code
|
||||
* though...
|
||||
*/
|
||||
|
||||
(void) 0; /* do nothing */
|
||||
}
|
||||
|
||||
if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
|
||||
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
|
||||
Tcl_Obj *r = Tcl_GetObjResult(interp);
|
||||
|
||||
TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ?
|
||||
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result,
|
||||
TclGetString(r), r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the stack-allocated compiled locals and CallFrame. It is important
|
||||
* to pop the call frame without freeing it first: the compiledLocals
|
||||
* cannot be freed before the frame is popped, as the local variables must
|
||||
* be deleted. But the compiledLocals must be freed first, as they were
|
||||
* allocated later on the stack.
|
||||
*/
|
||||
|
||||
freePtr = iPtr->framePtr;
|
||||
Tcl_PopCallFrame(interp); /* Pop but do not free. */
|
||||
TclStackFree(interp, freePtr->compiledLocals);
|
||||
/* Free compiledLocals. */
|
||||
TclStackFree(interp, freePtr); /* Free CallFrame. */
|
||||
|
||||
return result;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Executable → Regular
+79
-18
@@ -1123,7 +1123,8 @@ Tcl_AppendLimitedToObj(
|
||||
if (ellipsis == NULL) {
|
||||
ellipsis = "...";
|
||||
}
|
||||
toCopy = Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes;
|
||||
toCopy = (bytes == NULL) ? limit
|
||||
: Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1281,23 +1282,43 @@ Tcl_AppendObjToObj(
|
||||
|
||||
if ((TclIsPureByteArray(objPtr) || objPtr->bytes == tclEmptyStringRep)
|
||||
&& TclIsPureByteArray(appendObjPtr)) {
|
||||
unsigned char *bytesSrc;
|
||||
int lengthSrc, lengthTotal;
|
||||
|
||||
/*
|
||||
* We do not assume that objPtr and appendObjPtr must be distinct!
|
||||
* This makes this code a bit more complex than it otherwise would be,
|
||||
* but in turn makes it much safer.
|
||||
* You might expect the code here to be
|
||||
*
|
||||
* bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length);
|
||||
* TclAppendBytesToByteArray(objPtr, bytes, length);
|
||||
*
|
||||
* and essentially all of the time that would be fine. However,
|
||||
* it would run into trouble in the case where objPtr and
|
||||
* appendObjPtr point to the same thing. That may never be a
|
||||
* good idea. It seems to violate Copy On Write, and we don't
|
||||
* have any tests for the situation, since making any Tcl commands
|
||||
* that call Tcl_AppendObjToObj() do that appears impossible
|
||||
* (They honor Copy On Write!). For the sake of extensions that
|
||||
* go off into that realm, though, here's a more complex approach
|
||||
* that can handle all the cases.
|
||||
*/
|
||||
|
||||
/* Get lengths */
|
||||
int lengthSrc;
|
||||
|
||||
(void) Tcl_GetByteArrayFromObj(objPtr, &length);
|
||||
(void) Tcl_GetByteArrayFromObj(appendObjPtr, &lengthSrc);
|
||||
lengthTotal = length + lengthSrc;
|
||||
if (((length > lengthSrc) ? length : lengthSrc) > lengthTotal) {
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
|
||||
}
|
||||
bytesSrc = Tcl_GetByteArrayFromObj(appendObjPtr, NULL);
|
||||
TclAppendBytesToByteArray(objPtr, bytesSrc, lengthSrc);
|
||||
|
||||
/* Grow buffer enough for the append */
|
||||
TclAppendBytesToByteArray(objPtr, NULL, lengthSrc);
|
||||
|
||||
/* Reset objPtr back to the original value */
|
||||
Tcl_SetByteArrayLength(objPtr, length);
|
||||
|
||||
/*
|
||||
* Now do the append knowing that buffer growth cannot cause
|
||||
* any trouble.
|
||||
*/
|
||||
|
||||
TclAppendBytesToByteArray(objPtr,
|
||||
Tcl_GetByteArrayFromObj(appendObjPtr, NULL), lengthSrc);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1415,7 +1436,7 @@ AppendUnicodeToUnicodeRep(
|
||||
* the reallocs below.
|
||||
*/
|
||||
|
||||
if (unicode >= stringPtr->unicode
|
||||
if (unicode && unicode >= stringPtr->unicode
|
||||
&& unicode <= stringPtr->unicode + stringPtr->maxChars) {
|
||||
offset = unicode - stringPtr->unicode;
|
||||
}
|
||||
@@ -1437,8 +1458,10 @@ AppendUnicodeToUnicodeRep(
|
||||
* trailing null.
|
||||
*/
|
||||
|
||||
memmove(stringPtr->unicode + stringPtr->numChars, unicode,
|
||||
appendNumChars * sizeof(Tcl_UniChar));
|
||||
if (unicode) {
|
||||
memmove(stringPtr->unicode + stringPtr->numChars, unicode,
|
||||
appendNumChars * sizeof(Tcl_UniChar));
|
||||
}
|
||||
stringPtr->unicode[numChars] = 0;
|
||||
stringPtr->numChars = numChars;
|
||||
stringPtr->allocated = 0;
|
||||
@@ -1577,7 +1600,7 @@ AppendUtfToUtfRep(
|
||||
* the reallocs below.
|
||||
*/
|
||||
|
||||
if (bytes >= objPtr->bytes
|
||||
if (bytes && bytes >= objPtr->bytes
|
||||
&& bytes <= objPtr->bytes + objPtr->length) {
|
||||
offset = bytes - objPtr->bytes;
|
||||
}
|
||||
@@ -1605,7 +1628,9 @@ AppendUtfToUtfRep(
|
||||
stringPtr->numChars = -1;
|
||||
stringPtr->hasUnicode = 0;
|
||||
|
||||
memmove(objPtr->bytes + oldLength, bytes, numBytes);
|
||||
if (bytes) {
|
||||
memmove(objPtr->bytes + oldLength, bytes, numBytes);
|
||||
}
|
||||
objPtr->bytes[newLength] = 0;
|
||||
objPtr->length = newLength;
|
||||
}
|
||||
@@ -2635,6 +2660,38 @@ Tcl_ObjPrintf(
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclGetStringStorage --
|
||||
*
|
||||
* Returns the string storage space of a Tcl_Obj.
|
||||
*
|
||||
* Results:
|
||||
* The pointer value objPtr->bytes is returned and the number of bytes
|
||||
* allocated there is written to *sizePtr (if known).
|
||||
*
|
||||
* Side effects:
|
||||
* May set objPtr->bytes.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
TclGetStringStorage(
|
||||
Tcl_Obj *objPtr,
|
||||
unsigned int *sizePtr)
|
||||
{
|
||||
String *stringPtr;
|
||||
|
||||
if (objPtr->typePtr != &tclStringType || objPtr->bytes == NULL) {
|
||||
return TclGetStringFromObj(objPtr, (int *)sizePtr);
|
||||
}
|
||||
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
*sizePtr = stringPtr->allocated;
|
||||
return objPtr->bytes;
|
||||
}
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
@@ -2828,7 +2885,11 @@ ExtendUnicodeRepWithString(
|
||||
}
|
||||
|
||||
stringPtr->hasUnicode = 1;
|
||||
stringPtr->numChars = needed;
|
||||
if (bytes) {
|
||||
stringPtr->numChars = needed;
|
||||
} else {
|
||||
numAppendChars = 0;
|
||||
}
|
||||
for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) {
|
||||
bytes += TclUtfToUniChar(bytes, dst);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* tclStringTrim.h --
|
||||
*
|
||||
* This file contains the definition of what characters are to be trimmed
|
||||
* from a string by [string trim] by default. It's only needed by Tcl's
|
||||
* implementation; it does not form a public or private API at all.
|
||||
*
|
||||
* Copyright (c) 1987-1993 The Regents of the University of California.
|
||||
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
|
||||
* Copyright (c) 1998-2000 Scriptics Corporation.
|
||||
* Copyright (c) 2002 ActiveState Corporation.
|
||||
* Copyright (c) 2003-2013 Donal K. Fellows.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifndef TCL_STRING_TRIM_H
|
||||
#define TCL_STRING_TRIM_H
|
||||
|
||||
/*
|
||||
* Default set of characters to trim in [string trim] and friends. This is a
|
||||
* UTF-8 literal string containing all Unicode space characters. [TIP #413]
|
||||
*/
|
||||
|
||||
MODULE_SCOPE const char tclDefaultTrimSet[];
|
||||
|
||||
/*
|
||||
* The whitespace trimming set used when [concat]enating. This is a subset of
|
||||
* the above, and deliberately so.
|
||||
*/
|
||||
|
||||
#define CONCAT_TRIM_SET " \f\v\r\t\n"
|
||||
|
||||
#endif /* TCL_STRING_TRIM_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
||||
+23
-15
@@ -44,6 +44,9 @@
|
||||
#define TclBackgroundException Tcl_BackgroundException
|
||||
#undef Tcl_SetIntObj
|
||||
#undef TclpInetNtoa
|
||||
#undef TclWinGetServByName
|
||||
#undef TclWinGetSockOpt
|
||||
#undef TclWinSetSockOpt
|
||||
|
||||
/* See bug 510001: TclSockMinimumBuffers needs plat imp */
|
||||
#ifdef _WIN64
|
||||
@@ -90,7 +93,7 @@ static unsigned short TclWinNToHS(unsigned short ns) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
# define TclUnixWaitForFile 0
|
||||
# define TclUnixCopyFile 0
|
||||
# define TclUnixOpenTemporaryFile 0
|
||||
@@ -111,7 +114,8 @@ TclpIsAtty(int fd)
|
||||
return isatty(fd);
|
||||
}
|
||||
|
||||
int
|
||||
#define TclWinGetPlatformId winGetPlatformId
|
||||
static int
|
||||
TclWinGetPlatformId()
|
||||
{
|
||||
/* Don't bother to determine the real platform on cygwin,
|
||||
@@ -127,27 +131,31 @@ void *TclWinGetTclInstance()
|
||||
return hInstance;
|
||||
}
|
||||
|
||||
int
|
||||
#define TclWinSetSockOpt winSetSockOpt
|
||||
static int
|
||||
TclWinSetSockOpt(SOCKET s, int level, int optname,
|
||||
const char *optval, int optlen)
|
||||
{
|
||||
return setsockopt((int) s, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int
|
||||
#define TclWinGetSockOpt winGetSockOpt
|
||||
static int
|
||||
TclWinGetSockOpt(SOCKET s, int level, int optname,
|
||||
char *optval, int *optlen)
|
||||
{
|
||||
return getsockopt((int) s, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
struct servent *
|
||||
#define TclWinGetServByName winGetServByName
|
||||
static struct servent *
|
||||
TclWinGetServByName(const char *name, const char *proto)
|
||||
{
|
||||
return getservbyname(name, proto);
|
||||
}
|
||||
|
||||
char *
|
||||
#define TclWinNoBackslash winNoBackslash
|
||||
static char *
|
||||
TclWinNoBackslash(char *path)
|
||||
{
|
||||
char *p;
|
||||
@@ -557,7 +565,7 @@ static const TclIntStubs tclIntStubs = {
|
||||
static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
TCL_STUB_MAGIC,
|
||||
0,
|
||||
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
TclGetAndDetachPids, /* 0 */
|
||||
TclpCloseFile, /* 1 */
|
||||
TclpCreateCommandChannel, /* 2 */
|
||||
@@ -590,7 +598,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
TclWinCPUID, /* 29 */
|
||||
TclUnixOpenTemporaryFile, /* 30 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
TclWinConvertError, /* 0 */
|
||||
TclWinConvertWSAError, /* 1 */
|
||||
TclWinGetServByName, /* 2 */
|
||||
@@ -661,7 +669,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
|
||||
static const TclPlatStubs tclPlatStubs = {
|
||||
TCL_STUB_MAGIC,
|
||||
0,
|
||||
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
|
||||
Tcl_WinUtfToTChar, /* 0 */
|
||||
Tcl_WinTCharToUtf, /* 1 */
|
||||
#endif /* WIN */
|
||||
@@ -758,19 +766,19 @@ const TclStubs tclStubs = {
|
||||
Tcl_DbCkalloc, /* 6 */
|
||||
Tcl_DbCkfree, /* 7 */
|
||||
Tcl_DbCkrealloc, /* 8 */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
Tcl_CreateFileHandler, /* 9 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) /* WIN */
|
||||
#if defined(_WIN32) /* WIN */
|
||||
0, /* 9 */
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
Tcl_CreateFileHandler, /* 9 */
|
||||
#endif /* MACOSX */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
Tcl_DeleteFileHandler, /* 10 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) /* WIN */
|
||||
#if defined(_WIN32) /* WIN */
|
||||
0, /* 10 */
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
@@ -932,10 +940,10 @@ const TclStubs tclStubs = {
|
||||
Tcl_GetMaster, /* 164 */
|
||||
Tcl_GetNameOfExecutable, /* 165 */
|
||||
Tcl_GetObjResult, /* 166 */
|
||||
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
|
||||
Tcl_GetOpenFile, /* 167 */
|
||||
#endif /* UNIX */
|
||||
#if defined(__WIN32__) /* WIN */
|
||||
#if defined(_WIN32) /* WIN */
|
||||
0, /* 167 */
|
||||
#endif /* WIN */
|
||||
#ifdef MAC_OSX_TCL /* MACOSX */
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
+3
-3
@@ -414,7 +414,7 @@ static int TestNRELevels(ClientData clientData,
|
||||
static int TestInterpResolverCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
#if defined(HAVE_CPUID) || defined(__WIN32__)
|
||||
#if defined(HAVE_CPUID) || defined(_WIN32)
|
||||
static int TestcpuidCmd(ClientData dummy,
|
||||
Tcl_Interp* interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -681,7 +681,7 @@ Tcltest_Init(
|
||||
NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
|
||||
NULL, NULL);
|
||||
#if defined(HAVE_CPUID) || defined(__WIN32__)
|
||||
#if defined(HAVE_CPUID) || defined(_WIN32)
|
||||
Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd,
|
||||
(ClientData) 0, NULL);
|
||||
#endif
|
||||
@@ -6648,7 +6648,7 @@ TestNumUtfCharsCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#if defined(HAVE_CPUID) || defined(__WIN32__)
|
||||
#if defined(HAVE_CPUID) || defined(_WIN32)
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+6
-2
@@ -339,8 +339,9 @@ Tcl_ConditionFinalize(
|
||||
*
|
||||
* TclFinalizeThreadData --
|
||||
*
|
||||
* This function cleans up the thread-local storage. This is called once
|
||||
* for each thread.
|
||||
* This function cleans up the thread-local storage. Secondary, it cleans
|
||||
* thread alloc cache.
|
||||
* This is called once for each thread before thread exits.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -355,6 +356,9 @@ void
|
||||
TclFinalizeThreadData(void)
|
||||
{
|
||||
TclFinalizeThreadDataThread();
|
||||
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
TclFinalizeThreadAllocThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1023,6 +1023,33 @@ TclFinalizeThreadAlloc(void)
|
||||
TclpFreeAllocCache(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclFinalizeThreadAllocThread --
|
||||
*
|
||||
* This procedure is used to destroy single thread private resources used
|
||||
* in this file.
|
||||
* Called in TclpFinalizeThreadData when a thread exits (Tcl_FinalizeThread).
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TclFinalizeThreadAllocThread(void)
|
||||
{
|
||||
Cache *cachePtr = TclpGetAllocCache();
|
||||
if (cachePtr != NULL) {
|
||||
TclpFreeAllocCache(cachePtr);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !(TCL_THREADS && USE_THREAD_ALLOC) */
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
|
||||
/*
|
||||
* The information about each joinable thread is remembered in a structure as
|
||||
@@ -305,7 +305,7 @@ TclSignalExitThread(
|
||||
|
||||
Tcl_MutexUnlock(&threadPtr->threadMutex);
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
+10
-6
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclParse.h"
|
||||
#include "tclStringTrim.h"
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
@@ -1768,8 +1769,7 @@ TclTrimLeft(
|
||||
*/
|
||||
|
||||
/* The whitespace characters trimmed during [concat] operations */
|
||||
#define CONCAT_WS " \f\v\r\t\n"
|
||||
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_WS "") - 1)
|
||||
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_TRIM_SET "") - 1)
|
||||
|
||||
char *
|
||||
Tcl_Concat(
|
||||
@@ -1825,7 +1825,8 @@ Tcl_Concat(
|
||||
* Trim away the leading whitespace.
|
||||
*/
|
||||
|
||||
trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
|
||||
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
element += trim;
|
||||
elemLength -= trim;
|
||||
|
||||
@@ -1834,7 +1835,8 @@ Tcl_Concat(
|
||||
* a final backslash character.
|
||||
*/
|
||||
|
||||
trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
|
||||
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
trim -= trim && (element[elemLength - trim - 1] == '\\');
|
||||
elemLength -= trim;
|
||||
|
||||
@@ -1959,7 +1961,8 @@ Tcl_ConcatObj(
|
||||
* Trim away the leading whitespace.
|
||||
*/
|
||||
|
||||
trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
|
||||
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
element += trim;
|
||||
elemLength -= trim;
|
||||
|
||||
@@ -1968,7 +1971,8 @@ Tcl_ConcatObj(
|
||||
* a final backslash character.
|
||||
*/
|
||||
|
||||
trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
|
||||
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
|
||||
CONCAT_WS_SIZE);
|
||||
trim -= trim && (element[elemLength - trim - 1] == '\\');
|
||||
elemLength -= trim;
|
||||
|
||||
|
||||
+5
-40
@@ -2994,47 +2994,18 @@ ZlibTransformInput(
|
||||
*/
|
||||
|
||||
if (readBytes < 0) {
|
||||
/*
|
||||
* Report errors to caller. The state of the seek system is
|
||||
* unchanged!
|
||||
*/
|
||||
|
||||
if ((Tcl_GetErrno() == EAGAIN) && (gotBytes > 0)) {
|
||||
/*
|
||||
* EAGAIN is a special situation. If we had some data before
|
||||
* we report that instead of the request to re-try.
|
||||
*/
|
||||
|
||||
/* See ReflectInput() in tclIORTrans.c */
|
||||
if (Tcl_InputBlocked(cd->parent) && (gotBytes > 0)) {
|
||||
return gotBytes;
|
||||
}
|
||||
|
||||
*errorCodePtr = Tcl_GetErrno();
|
||||
return -1;
|
||||
} else if (readBytes == 0) {
|
||||
}
|
||||
if (readBytes == 0) {
|
||||
/*
|
||||
* Check wether we hit on EOF in 'parent' or not. If not,
|
||||
* differentiate between blocking and non-blocking modes. In
|
||||
* non-blocking mode we ran temporarily out of data. Signal this
|
||||
* to the caller via EWOULDBLOCK and error return (-1). In the
|
||||
* other cases we simply return what we got and let the caller
|
||||
* wait for more. On the other hand, if we got an EOF we have to
|
||||
* convert and flush all waiting partial data.
|
||||
*/
|
||||
|
||||
if (!Tcl_Eof(cd->parent)) {
|
||||
/*
|
||||
* The state of the seek system is unchanged!
|
||||
*/
|
||||
|
||||
if ((gotBytes == 0) && (cd->flags & ASYNC)) {
|
||||
*errorCodePtr = EWOULDBLOCK;
|
||||
return -1;
|
||||
}
|
||||
return gotBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* (Semi-)Eof in parent.
|
||||
* Eof in parent.
|
||||
*
|
||||
* Now this is a bit different. The partial data waiting is
|
||||
* converted and returned.
|
||||
@@ -3052,12 +3023,6 @@ ZlibTransformInput(
|
||||
|
||||
return gotBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset eof, force caller to drain result buffer.
|
||||
*/
|
||||
|
||||
((Channel *) cd->parent)->state->flags &= ~CHANNEL_EOF;
|
||||
} else /* readBytes > 0 */ {
|
||||
/*
|
||||
* Transform the read chunk, which was not empty. Anything we get
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user