Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge unchained branch [22400aa71b] and resolve conflicts. |
|---|---|
| Timelines: | family | ancestors | descendants | both | pyk-objinterface |
| Files: | files | file ages | folders |
| SHA3-256: |
961f58e1488c12f27d23e06d13d68532 |
| User & Date: | pooryorick 2023-06-26 07:24:26.737 |
Context
|
2024-06-27
| ||
| 07:46 | Merge unchained [16c46aa0ac5d85f0]. check-in: 7751515578 user: pooryorick tags: pyk-objinterface | |
|
2023-06-26
| ||
| 07:24 | Merge unchained branch [22400aa71b] and resolve conflicts. check-in: 961f58e148 user: pooryorick tags: pyk-objinterface | |
|
2023-06-18
| ||
| 21:30 | Merge trunk-encoding-defaultstrict [c499122331]. check-in: 22400aa71b user: pooryorick tags: unchained | |
|
2023-05-20
| ||
| 20:11 | Merge "unchained branch [a03cbbdf63] and resolve conflicts. check-in: 6803cae7fa user: pooryorick tags: pyk-objinterface | |
Changes
Changes to doc/OpenFileChnl.3.
| ︙ | ︙ | |||
402 403 404 405 406 407 408 | .SH "TCL_READCHARS AND TCL_READ" .PP \fBTcl_ReadChars\fR consumes bytes from \fIchannel\fR, converting the bytes to UTF-8 based on the channel's encoding and storing the produced data in \fIreadObjPtr\fR's string representation. The return value of \fBTcl_ReadChars\fR is the number of characters, up to \fIcharsToRead\fR, that were stored in \fIreadObjPtr\fR. If an error occurs while reading, the | | | > > > | | < | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | .SH "TCL_READCHARS AND TCL_READ" .PP \fBTcl_ReadChars\fR consumes bytes from \fIchannel\fR, converting the bytes to UTF-8 based on the channel's encoding and storing the produced data in \fIreadObjPtr\fR's string representation. The return value of \fBTcl_ReadChars\fR is the number of characters, up to \fIcharsToRead\fR, that were stored in \fIreadObjPtr\fR. If an error occurs while reading, the return value is -1 and \fBTcl_ReadChars\fR records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. If an encoding error happens while the channel is in blocking mode with -profile strict, the characters retrieved until the encoding error happened will be stored in \fIreadObjPtr\fR. .PP Setting \fIcharsToRead\fR to -1 will cause the command to read all characters currently available (non-blocking) or everything until eof (blocking mode). .PP The return value may be smaller than the value to read, indicating that less data than requested was available. This is called a \fIshort read\fR. In blocking mode, this can only happen on an end-of-file. In nonblocking mode, a short read can also occur if an encoding error is encountered (with -profile strict) or if there is not enough input currently available: \fBTcl_ReadChars\fR returns a short count rather than waiting for more data. .PP If the channel is in blocking mode, a return value of zero indicates an end-of-file condition. If the channel is in nonblocking mode, a return value of zero indicates either that no input is currently available or an end-of-file condition. Use \fBTcl_Eof\fR and \fBTcl_InputBlocked\fR to tell which of these conditions actually occurred. .PP |
| ︙ | ︙ |
Changes to doc/TclZlib.3.
| ︙ | ︙ | |||
184 185 186 187 188 189 190 | \fBTcl_ZlibStreamSetCompressionDictionary\fR is used to control the compression dictionary used with the stream, a compression dictionary being an array of bytes (such as might be created with \fBTcl_NewByteArrayObj\fR) that is used to initialize the compression engine rather than leaving it to create it on the fly from the data being compressed. Setting a compression dictionary allows for more efficient compression in the case where the start of the data is highly regular, but it does require both the compressor and the | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | \fBTcl_ZlibStreamSetCompressionDictionary\fR is used to control the compression dictionary used with the stream, a compression dictionary being an array of bytes (such as might be created with \fBTcl_NewByteArrayObj\fR) that is used to initialize the compression engine rather than leaving it to create it on the fly from the data being compressed. Setting a compression dictionary allows for more efficient compression in the case where the start of the data is highly regular, but it does require both the compressor and the decompressor to agree on the value to use. Compression dictionaries are only fully supported for zlib-format data; on compression, they must be set before any data is sent in with \fBTcl_ZlibStreamPut\fR, and on decompression they should be set when \fBTcl_ZlibStreamGet\fR produces an \fBerror\fR with its \fB\-errorcode\fR set to .QW "\fBZLIB NEED_DICT\fI code\fR" ; the \fIcode\fR will be the Adler-32 checksum (see \fBTcl_ZlibAdler32\fR) of the compression dictionary sought. (Note that this is only true for |
| ︙ | ︙ |
Changes to doc/Thread.3.
| ︙ | ︙ | |||
65 66 67 68 69 70 71 | .AP Tcl_ThreadId id in Id of the thread waited upon. .AP Tcl_ThreadCreateProc *proc in This procedure will act as the \fBmain()\fR of the newly created thread. The specified \fIclientData\fR will be its sole argument. .AP void *clientData in Arbitrary information. Passed as sole argument to the \fIproc\fR. | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | .AP Tcl_ThreadId id in Id of the thread waited upon. .AP Tcl_ThreadCreateProc *proc in This procedure will act as the \fBmain()\fR of the newly created thread. The specified \fIclientData\fR will be its sole argument. .AP void *clientData in Arbitrary information. Passed as sole argument to the \fIproc\fR. .AP size_t stackSize in The size of the stack given to the new thread. .AP int flags in Bitmask containing flags allowing the caller to modify behavior of the new thread. .AP int *result out The referred storage is used to place the exit code of the thread waited upon into it. |
| ︙ | ︙ |
Changes to doc/chan.n.
| ︙ | ︙ | |||
51 52 53 54 55 56 57 | .PP \fBchan close\fR fully flushes any output before closing the write side of a channel unless it is non-blocking mode, where it returns immediately and the channel is flushed in the background before finally being closed. .PP \fBchan close\fR may return an error if an error occurs while flushing output. If a process in a command pipeline created by \fBopen\fR returns an | > | > > > > > > > > > > > > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | .PP \fBchan close\fR fully flushes any output before closing the write side of a channel unless it is non-blocking mode, where it returns immediately and the channel is flushed in the background before finally being closed. .PP \fBchan close\fR may return an error if an error occurs while flushing output. If a process in a command pipeline created by \fBopen\fR returns an error (either by returning a non-zero exit code or writing to its standard error file descriptor), \fBchan close\fR generates an error in the same manner as \fBexec\fR. .PP Closing one side of a socket or command pipeline may lead to the shutdown() or close() of the underlying system resource, leading to a reaction from whatever is on the other side of the pipeline or socket. .PP If the channel for a command pipeline is in blocking mode, \fBchan close\fR waits for the connected processes to complete. .PP \fBchan close\fR only affects the current interpreter. If the channel is open in any other interpreter, its state is unchanged there. See \fBinterp\fR for a description of channel sharing. .PP When the last interpreter sharing a channel is destroyed, the channel is switched to blocking mode and fully flushed and then closed. .PP Channels are automatically closed when an interpreter is destroyed and when the process exits. From 8.6 on (TIP#398), nonblocking channels are no longer switched to blocking mode when exiting; this guarantees a timely exit even when the peer or a communication channel is stalled. To ensure proper flushing of stalled nonblocking channels on exit, one must now either (a) actively switch them back to blocking or (b) use the environment variable \fBTCL_FLUSH_NONBLOCKING_ON_EXIT\fR, which when set and not equal to .QW \fB0\fR restores the previous behavior. .RE .TP \fBchan configure \fIchannelName\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... . Configures or reports the configuration of \fIchannelName\fR. .RS .PP |
| ︙ | ︙ | |||
344 345 346 347 348 349 350 | as its handler, and returns the name of the channel. \fBcmdPrefix\fR is the first words of a command that provides the interface for a \fBrefchan\fR. .RS .PP \fBImode\fR is a list of one or more of the strings .QW \fBread\fR or | | | | 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | as its handler, and returns the name of the channel. \fBcmdPrefix\fR is the first words of a command that provides the interface for a \fBrefchan\fR. .RS .PP \fBImode\fR is a list of one or more of the strings .QW \fBread\fR or .QW \fBwrite\fR , indicating whether the channel is a read channel, a write channel, or both. It is an error if the handler does not support the chosen mode. .PP The handler is called as needed from the global namespace at the top level, and command resolution happens there at the time of the call. If the handler is renamed or deleted any subsequent attempt to call it is an error, which may not be able to describe the failure. .PP |
| ︙ | ︙ |
Changes to doc/close.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH close n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME close \- Close an open channel .SH SYNOPSIS | | | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | .TH close n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME close \- Close an open channel .SH SYNOPSIS \fBclose \fIchannelId\fR ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)? .BE .SH DESCRIPTION .PP Closes or half-closes the channel given by \fIchannelId\fR. \fBchan close\fR is another name for this command. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .PP The single-argument form is a simple |
| ︙ | ︙ | |||
45 46 47 48 49 50 51 | channel. When the last interpreter in which the channel is registered invokes \fBclose\fR, the cleanup actions described above occur. See the \fBinterp\fR command for a description of channel sharing. .PP Channels are automatically closed when an interpreter is destroyed and when the process exits. | | > > > > > > > | > | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | channel. When the last interpreter in which the channel is registered invokes \fBclose\fR, the cleanup actions described above occur. See the \fBinterp\fR command for a description of channel sharing. .PP Channels are automatically closed when an interpreter is destroyed and when the process exits. From 8.6 on (TIP#398), nonblocking channels are no longer switched to blocking mode when exiting; this guarantees a timely exit even when the peer or a communication channel is stalled. To ensure proper flushing of stalled nonblocking channels on exit, one must now either (a) actively switch them back to blocking or (b) use the environment variable \fBTCL_FLUSH_NONBLOCKING_ON_EXIT\fR, which when set and not equal to .QW \fB0\fR restores the previous behavior. .PP The command returns an empty string, and may generate an error if an error occurs while flushing output. If a command in a command pipeline created with \fBopen\fR returns an error (either by returning a non-zero exit code or writing to its standard error file descriptor), \fBclose\fR generates an error (similar to the \fBexec\fR command.) .PP The two-argument form is a .QW "half-close" : given a bidirectional channel like a socket or command pipeline and a (possibly abbreviated) direction, it closes only the sub-stream going in that direction. This means a shutdown() on a socket, and a close() of one end of a pipe for a command pipeline. Then, the |
| ︙ | ︙ | |||
91 92 93 94 95 96 97 |
uplevel 1 $script
} result options
\fBclose\fR $chan
return -options $options $result
}
.CE
.SH "SEE ALSO"
| | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
uplevel 1 $script
} result options
\fBclose\fR $chan
return -options $options $result
}
.CE
.SH "SEE ALSO"
chan(n), file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, channel, close, nonblocking, half-close
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:
|
Changes to doc/configurable.n.
1 2 3 4 5 6 | '\" '\" Copyright © 2019 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
'\"
'\" Copyright © 2019 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH configurable n 0.4 TclOO "TclOO Commands"
.so man.macros
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
oo::configurable, configure, property \- class that makes configurable classes and objects, and supports making configurable properties
.SH SYNOPSIS
.nf
package require TclOO
\fBoo::configurable create \fIclass\fR ?\fIdefinitionScript\fR?
\fBoo::define \fIclass\fB {\fR
\fBproperty \fIpropName\fR ?\fIoptions...\fR? ?\fIpropName\fR ?\fIoptions...\fR?...?
\fB}\fR
\fBoo::objdefine \fIobject\fB {\fR
\fBproperty \fIpropName\fR ?\fIoptions...\fR? ?\fIpropName\fR ?\fIoptions...\fR?...?
\fB}\fR
\fIobjectName \fBconfigure\fR
\fIobjectName \fBconfigure\fR \fI\-prop\fR
\fIobjectName \fBconfigure\fR \fI\-prop value\fR ?\fI\-prop value\fR...
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
\(-> \fBoo::class\fR
\(-> \fBoo::configurable\fR
|
| ︙ | ︙ | |||
142 143 144 145 146 147 148 | \fBoo::configurable\fR metaclass works by mixing in a class and setting definition namespaces during object creation that provide the other bits and pieces of machinery. The key pieces of the implementation are enumerated here so that they can be used by other code: .TP \fBoo::configuresupport::configurable\fR . | | < | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | \fBoo::configurable\fR metaclass works by mixing in a class and setting definition namespaces during object creation that provide the other bits and pieces of machinery. The key pieces of the implementation are enumerated here so that they can be used by other code: .TP \fBoo::configuresupport::configurable\fR . This is a class that provides the implementation of the \fBconfigure\fR method (described above in \fBCONFIGURE METHOD\fR). .TP \fBoo::configuresupport::configurableclass\fR . This is a namespace that contains the definition dialect that provides the \fBproperty\fR declaration for use in classes (i.e., via \fBoo::define\fR, and class constructors under normal circumstances), as described above in \fBPROPERTY DEFINITIONS\fR. It \fBnamespace export\fRs its \fBproperty\fR command so that it may be used easily in user definition dialects. .TP \fBoo::configuresupport::configurableobject\fR . This is a namespace that contains the definition dialect that provides the \fBproperty\fR declaration for use in instance objects (i.e., via \fBoo::objdefine\fR, and the \fBself\fR declaration in \fBoo::define\fR), as described above in \fBPROPERTY DEFINITIONS\fR. It \fBnamespace export\fRs its \fBproperty\fR command so that it may be used easily in user definition dialects. .PP The underlying property discovery mechanism relies on four slots (see \fBoo::define\fR for what that implies) that list the properties that can be configured. These slots do not themselves impose any semantics on what the |
| ︙ | ︙ |
Changes to doc/ledit.n.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 | with the \fIvalue\fR arguments. The resulting list is then stored back in \fIlistVar\fR and returned as the result of the command. .PP Arguments \fIfirst\fR and \fIlast\fR are index values specifying the first and last elements of the range to replace. They are interpreted the same as index values for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | with the \fIvalue\fR arguments. The resulting list is then stored back in \fIlistVar\fR and returned as the result of the command. .PP Arguments \fIfirst\fR and \fIlast\fR are index values specifying the first and last elements of the range to replace. They are interpreted the same as index values for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. The index \fB0\fR refers to the first element of the list, and \fBend\fR refers to the last element of the list. .PP If either \fIfirst\fR or \fIlast\fR is less than zero, it is considered to refer to the position before the first element of the list. This allows elements to be prepended. .PP If either \fIfirst\fR or \fIlast\fR indicates a position greater than the |
| ︙ | ︙ | |||
45 46 47 48 49 50 51 | the list. If no \fIvalue\fR arguments are specified, then the elements between \fIfirst\fR and \fIlast\fR are simply deleted. .SH EXAMPLES .PP Prepend to a list. .PP .CS | | | | | | | | | | | | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
the list. If no \fIvalue\fR arguments are specified, then the elements
between \fIfirst\fR and \fIlast\fR are simply deleted.
.SH EXAMPLES
.PP
Prepend to a list.
.PP
.CS
set lst {c d e f g}
\fI\(-> c d e f g\fR
\fBledit\fR lst -1 -1 a b
\fI\(-> a b c d e f g\fR
.CE
.PP
Append to the list.
.PP
.CS
\fBledit\fR lst end+1 end+1 h i
\fI\(-> a b c d e f g h i\fR
.CE
.PP
Delete third and fourth elements.
.PP
.CS
\fBledit\fR lst 2 3
\fI\(-> a b e f g h i\fR
.CE
.PP
Replace two elements with three.
.PP
.CS
\fBledit\fR lst 2 3 x y z
\fI\(-> a b x y z g h i\fR
set lst
\fI\(-> a b x y z g h i\fR
.CE
.PP
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, list, replace
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:
|
Changes to doc/library.n.
| ︙ | ︙ | |||
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | and arrange for the other procedures to be loaded on-demand using the auto-load mechanism defined below. .SH "COMMAND PROCEDURES" .PP The following procedures are provided in the Tcl library: .TP \fBauto_execok \fIcmd\fR Determines whether there is an executable file or shell builtin by the name \fIcmd\fR. If so, it returns a list of arguments to be passed to \fBexec\fR to execute the executable file or shell builtin named by \fIcmd\fR. If not, it returns an empty string. This command examines the directories in the current search path (given by the PATH environment variable) in its search for an executable file named \fIcmd\fR. On Windows platforms, the search is expanded with the same directories and file extensions as used by \fBexec\fR. \fBAuto_execok\fR remembers information about previous searches in an array named \fBauto_execs\fR; this avoids the path search in future calls for the same \fIcmd\fR. The command \fBauto_reset\fR may be used to force \fBauto_execok\fR to forget its cached information. .TP \fBauto_import \fIpattern\fR \fBAuto_import\fR is invoked during \fBnamespace import\fR to see if the imported commands specified by \fIpattern\fR reside in an autoloaded library. If so, the commands are loaded so that they will be available to the interpreter for creating the import links. If the commands do not reside in an autoloaded library, \fBauto_import\fR does nothing. The pattern matching is performed according to the matching rules of \fBnamespace import\fR. .TP \fBauto_load \fIcmd\fR This command attempts to load the definition for a Tcl command named \fIcmd\fR. To do this, it searches an \fIauto-load path\fR, which is a list of one or more directories. The auto-load path is given by the global variable \fBauto_path\fR if it exists. If there is no | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
and arrange for the other procedures to be loaded on-demand using
the auto-load mechanism defined below.
.SH "COMMAND PROCEDURES"
.PP
The following procedures are provided in the Tcl library:
.TP
\fBauto_execok \fIcmd\fR
.
Determines whether there is an executable file or shell builtin
by the name \fIcmd\fR. If so, it returns a list of arguments to be
passed to \fBexec\fR to execute the executable file or shell builtin
named by \fIcmd\fR. If not, it returns an empty string. This command
examines the directories in the current search path (given by the PATH
environment variable) in its search for an executable file named
\fIcmd\fR. On Windows platforms, the search is expanded with the same
directories and file extensions as used by \fBexec\fR. \fBAuto_execok\fR
remembers information about previous searches in an array named
\fBauto_execs\fR; this avoids the path search in future calls for the
same \fIcmd\fR. The command \fBauto_reset\fR may be used to force
\fBauto_execok\fR to forget its cached information.
.RS
.PP
For example, to run the \fIumask\fR shell builtin on Linux, you would do:
.PP
.CS
exec {*}[\fBauto_execok\fR umask]
.CE
.PP
To run the \fIDIR\fR shell builtin on Windows, you would do:
.PP
.CS
exec {*}[\fBauto_execok\fR dir]
.CE
.PP
To discover if there is a \fIfrobnicate\fR binary on the user's PATH,
you would do:
.PP
.CS
set mayFrob [expr {[llength [\fBauto_execok\fR frobnicate]] > 0}]
.CE
.RE
.TP
\fBauto_import \fIpattern\fR
.
\fBAuto_import\fR is invoked during \fBnamespace import\fR to see if
the imported commands specified by \fIpattern\fR reside in an
autoloaded library. If so, the commands are loaded so that they will
be available to the interpreter for creating the import links. If the
commands do not reside in an autoloaded library, \fBauto_import\fR
does nothing. The pattern matching is performed according to the
matching rules of \fBnamespace import\fR.
.RS
.PP
It is not normally necessary to call this command directly.
.RE
.TP
\fBauto_load \fIcmd\fR
.
This command attempts to load the definition for a Tcl command named
\fIcmd\fR. To do this, it searches an \fIauto-load path\fR, which is
a list of one or more directories. The auto-load path is given by the
global variable \fBauto_path\fR if it exists. If there is no
\fBauto_path\fR variable, then the \fBTCLLIBPATH\fR environment variable is
used, if it exists. Otherwise the auto-load path consists of just the
Tcl library directory. Within each directory in the auto-load path
there must be a file \fBtclIndex\fR that describes one or more
commands defined in that directory and a script to evaluate to load
each of the commands. The \fBtclIndex\fR file should be generated
with the \fBauto_mkindex\fR command. If \fIcmd\fR is found in an
index file, then the appropriate script is evaluated to create the
command. The \fBauto_load\fR command returns 1 if \fIcmd\fR was
successfully created. The command returns 0 if there was no index
entry for \fIcmd\fR or if the script did not actually define \fIcmd\fR
(e.g. because index information is out of date). If an error occurs
while processing the script, then that error is returned.
\fBAuto_load\fR only reads the index information once and saves it in
the array \fBauto_index\fR; future calls to \fBauto_load\fR check for
\fIcmd\fR in the array rather than re-reading the index files. The
cached index information may be deleted with the command
\fBauto_reset\fR. This will force the next \fBauto_load\fR command to
reload the index database from disk.
.RS
.PP
It is not normally necessary to call this command directly; the
default \fBunknown\fR handler will do so.
.RE
.TP
\fBauto_mkindex \fIdir pattern pattern ...\fR
.
Generates an index suitable for use by \fBauto_load\fR. The command
searches \fIdir\fR for all files whose names match any of the
\fIpattern\fR arguments (matching is done with the \fBglob\fR
command), generates an index of all the Tcl command procedures defined
|
| ︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | Destroys all the information cached by \fBauto_execok\fR and \fBauto_load\fR. This information will be re-read from disk the next time it is needed. \fBAuto_reset\fR also deletes any procedures listed in the auto-load index, so that fresh copies of them will be loaded the next time that they are used. .TP \fBauto_qualify \fIcommand namespace\fR Computes a list of fully qualified names for \fIcommand\fR. This list mirrors the path a standard Tcl interpreter follows for command lookups: first it looks for the command in the current namespace, and then in the global namespace. Accordingly, if \fIcommand\fR is relative and \fInamespace\fR is not \fB::\fR, the list returned has two elements: \fIcommand\fR scoped by \fInamespace\fR, as if it were a command in the \fInamespace\fR namespace; and \fIcommand\fR as if it were a command in the global namespace. Otherwise, if either \fIcommand\fR is absolute (it begins with \fB::\fR), or \fInamespace\fR is \fB::\fR, the list contains only \fIcommand\fR as if it were a command in the global namespace. .RS .PP \fBAuto_qualify\fR is used by the auto-loading facilities in Tcl, both for producing auto-loading indexes such as \fIpkgIndex.tcl\fR, and for performing the actual auto-loading of functions at runtime. .RE .TP \fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR This is a standard search procedure for use by extensions during their initialization. They call this procedure to look for their script library in several standard directories. The last component of the name of the library directory is normally \fIbasenameversion\fR (e.g., tk8.0), but it might be .QW library | > > | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | Destroys all the information cached by \fBauto_execok\fR and \fBauto_load\fR. This information will be re-read from disk the next time it is needed. \fBAuto_reset\fR also deletes any procedures listed in the auto-load index, so that fresh copies of them will be loaded the next time that they are used. .TP \fBauto_qualify \fIcommand namespace\fR . Computes a list of fully qualified names for \fIcommand\fR. This list mirrors the path a standard Tcl interpreter follows for command lookups: first it looks for the command in the current namespace, and then in the global namespace. Accordingly, if \fIcommand\fR is relative and \fInamespace\fR is not \fB::\fR, the list returned has two elements: \fIcommand\fR scoped by \fInamespace\fR, as if it were a command in the \fInamespace\fR namespace; and \fIcommand\fR as if it were a command in the global namespace. Otherwise, if either \fIcommand\fR is absolute (it begins with \fB::\fR), or \fInamespace\fR is \fB::\fR, the list contains only \fIcommand\fR as if it were a command in the global namespace. .RS .PP \fBAuto_qualify\fR is used by the auto-loading facilities in Tcl, both for producing auto-loading indexes such as \fIpkgIndex.tcl\fR, and for performing the actual auto-loading of functions at runtime. .RE .TP \fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR . This is a standard search procedure for use by extensions during their initialization. They call this procedure to look for their script library in several standard directories. The last component of the name of the library directory is normally \fIbasenameversion\fR (e.g., tk8.0), but it might be .QW library |
| ︙ | ︙ | |||
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | relative to the Tcl library directory; relative to the executable file in the standard installation bin or bin/\fIarch\fR directory; relative to the executable file in the current build tree; relative to the executable file in a parallel build tree. .TP \fBparray \fIarrayName\fR ?\fIpattern\fR? Prints on standard output the names and values of all the elements in the array \fIarrayName\fR, or just the names that match \fIpattern\fR (using the matching rules of \fBstring match\fR) and their values if \fIpattern\fR is given. \fIArrayName\fR must be an array accessible to the caller of \fBparray\fR. It may be either local or global. .TP \fBtcl_endOfWord \fIstr start\fR Returns the index of the first end-of-word location that occurs after a starting index \fIstart\fR in the string \fIstr\fR. An end-of-word location is defined to be the first non-word character following the first word character after the starting point. Returns -1 if there are no more end-of-word locations after the starting point. See the description of \fBtcl_wordchars\fR and \fBtcl_nonwordchars\fR below for more details on how Tcl determines which characters are word characters. .TP \fBtcl_startOfNextWord \fIstr start\fR Returns the index of the first start-of-word location that occurs after a starting index \fIstart\fR in the string \fIstr\fR. A start-of-word location is defined to be the first word character following a non-word character. Returns \-1 if there are no more start-of-word locations after the starting point. .TP \fBtcl_startOfPreviousWord \fIstr start\fR Returns the index of the first start-of-word location that occurs before a starting index \fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more start-of-word locations before the starting point. .TP \fBtcl_wordBreakAfter \fIstr start\fR Returns the index of the first word boundary after the starting index \fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more boundaries after the starting point in the given string. The index returned refers to the second character of the pair that comprises a boundary. .TP \fBtcl_wordBreakBefore \fIstr start\fR Returns the index of the first word boundary before the starting index \fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more boundaries before the starting point in the given string. The index returned refers to the second character of the pair that comprises a boundary. .SH "VARIABLES" .PP The following global variables are defined or used by the procedures in the Tcl library. They fall into two broad classes, handling unknown commands and packages, and determining what are words. .SS "AUTOLOADING AND PACKAGE MANAGEMENT VARIABLES" .TP \fBauto_execs\fR Used by \fBauto_execok\fR to record information about whether particular commands exist as executable files. .TP \fBauto_index\fR Used by \fBauto_load\fR to save the index information read from disk. .TP \fBauto_noexec\fR If set to any value, then \fBunknown\fR will not attempt to auto-exec any commands. .TP \fBauto_noload\fR If set to any value, then \fBunknown\fR will not attempt to auto-load any commands. .TP \fBauto_path\fR . If set, then it must contain a valid Tcl list giving directories to search during auto-load operations (including for package index files when using the default \fBpackage unknown\fR handler). This variable is initialized during startup to contain, in order: the directories listed in the \fBTCLLIBPATH\fR environment variable, the directory named by the \fBtcl_library\fR global variable, the parent directory of \fBtcl_library\fR, the directories listed in the \fBtcl_pkgPath\fR variable. Additional locations to look for files and package indices should normally be added to this variable using \fBlappend\fR. .TP \fBenv(TCL_LIBRARY)\fR If set, then it specifies the location of the directory containing library scripts (the value of this variable will be assigned to the \fBtcl_library\fR variable and therefore returned by the command \fBinfo library\fR). If this variable is not set then a default value is used. .TP \fBenv(TCLLIBPATH)\fR If set, then it must contain a valid Tcl list giving directories to search during auto-load operations. Directories must be specified in Tcl format, using .QW / as the path separator, regardless of platform. This variable is only used when initializing the \fBauto_path\fR variable. .SS "WORD BOUNDARY DETERMINATION VARIABLES" These variables are only used in the \fBtcl_endOfWord\fR, \fBtcl_startOfNextWord\fR, \fBtcl_startOfPreviousWord\fR, \fBtcl_wordBreakAfter\fR, and \fBtcl_wordBreakBefore\fR commands. .TP \fBtcl_nonwordchars\fR This variable contains a regular expression that is used by routines like \fBtcl_endOfWord\fR to identify whether a character is part of a word or not. If the pattern matches a character, the character is | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
relative to the Tcl library directory;
relative to the executable file in the standard installation
bin or bin/\fIarch\fR directory;
relative to the executable file in the current build tree;
relative to the executable file in a parallel build tree.
.TP
\fBparray \fIarrayName\fR ?\fIpattern\fR?
.
Prints on standard output the names and values of all the elements in the
array \fIarrayName\fR, or just the names that match \fIpattern\fR (using the
matching rules of \fBstring match\fR) and their values if \fIpattern\fR is
given.
\fIArrayName\fR must be an array accessible to the caller of \fBparray\fR.
It may be either local or global.
The result of this command is the empty string.
.RS
.PP
For example, to print the contents of the \fBtcl_platform\fR array, do:
.PP
.CS
\fBparray\fR tcl_platform
.CE
.RE
.TP
\fBtcl_endOfWord \fIstr start\fR
.
Returns the index of the first end-of-word location that occurs after
a starting index \fIstart\fR in the string \fIstr\fR. An end-of-word
location is defined to be the first non-word character following the
first word character after the starting point. Returns -1 if there
are no more end-of-word locations after the starting point. See the
description of \fBtcl_wordchars\fR and \fBtcl_nonwordchars\fR below
for more details on how Tcl determines which characters are word
characters.
.TP
\fBtcl_startOfNextWord \fIstr start\fR
.
Returns the index of the first start-of-word location that occurs
after a starting index \fIstart\fR in the string \fIstr\fR. A
start-of-word location is defined to be the first word character
following a non-word character. Returns \-1 if there are no more
start-of-word locations after the starting point.
.RS
.PP
For example, to print the indices of the starts of each word in a
string according to platform rules:
.PP
.CS
set theString "The quick brown fox"
for {set idx 0} {$idx >= 0} {
set idx [\fBtcl_startOfNextWord\fR $theString $idx]} {
puts "Word start index: $idx"
}
.CE
.RE
.TP
\fBtcl_startOfPreviousWord \fIstr start\fR
.
Returns the index of the first start-of-word location that occurs
before a starting index \fIstart\fR in the string \fIstr\fR. Returns
\-1 if there are no more start-of-word locations before the starting
point.
.TP
\fBtcl_wordBreakAfter \fIstr start\fR
.
Returns the index of the first word boundary after the starting index
\fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more
boundaries after the starting point in the given string. The index
returned refers to the second character of the pair that comprises a
boundary.
.TP
\fBtcl_wordBreakBefore \fIstr start\fR
.
Returns the index of the first word boundary before the starting index
\fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more
boundaries before the starting point in the given string. The index
returned refers to the second character of the pair that comprises a
boundary.
.SH "VARIABLES"
.PP
The following global variables are defined or used by the procedures in
the Tcl library. They fall into two broad classes, handling unknown
commands and packages, and determining what are words.
.SS "AUTOLOADING AND PACKAGE MANAGEMENT VARIABLES"
.TP
\fBauto_execs\fR
.
Used by \fBauto_execok\fR to record information about whether
particular commands exist as executable files.
.RS
.PP
Not normally usefully accessed directly by user code.
.RE
.TP
\fBauto_index\fR
.
Used by \fBauto_load\fR to save the index information read from
disk.
.RS
.PP
Not normally usefully accessed directly by user code.
.RE
.TP
\fBauto_noexec\fR
.
If set to any value, then \fBunknown\fR will not attempt to auto-exec
any commands.
.TP
\fBauto_noload\fR
.
If set to any value, then \fBunknown\fR will not attempt to auto-load
any commands.
.TP
\fBauto_path\fR
.
If set, then it must contain a valid Tcl list giving directories to
search during auto-load operations (including for package index
files when using the default \fBpackage unknown\fR handler).
This variable is initialized during startup to contain, in order:
the directories listed in the \fBTCLLIBPATH\fR environment variable,
the directory named by the \fBtcl_library\fR global variable,
the parent directory of \fBtcl_library\fR,
the directories listed in the \fBtcl_pkgPath\fR variable.
Additional locations to look for files and package indices should
normally be added to this variable using \fBlappend\fR.
.RS
.PP
For example, to add the \fIlib\fR directory next to the running
script, you would do:
.PP
.CS
lappend \fBauto_path\fR [file dirname [info script]]/lib
.CE
.PP
Note that if the script uses \fBcd\fR, it is advisable to ensure that
entries on the \fBauto_path\fR are \fBfile normalize\fRd.
.RE
.TP
\fBenv(TCL_LIBRARY)\fR
.
If set, then it specifies the location of the directory containing
library scripts (the value of this variable will be
assigned to the \fBtcl_library\fR variable and therefore returned by
the command \fBinfo library\fR). If this variable is not set then
a default value is used.
.RS
.PP
Use of this environment variable is not recommended outside of testing.
Tcl installations should already know where to find their own script
files, as the value is baked in during the build or installation.
.RE
.TP
\fBenv(TCLLIBPATH)\fR
.
If set, then it must contain a valid Tcl list giving directories to
search during auto-load operations. Directories must be specified in
Tcl format, using
.QW /
as the path separator, regardless of platform.
This variable is only used when initializing the \fBauto_path\fR variable.
.RS
.PP
A key consequence of this variable is that it gives a way to let the user
of a script specify the list of places where that script may use
\fBpackage require\fR to read packages from. It is not normally usefully
settable within a Tcl script itself \fIexcept\fR to influence where other
interpreters load from (whether made with \fBinterp create\fR or launched
as their own threads or subprocesses).
.RE
.SS "WORD BOUNDARY DETERMINATION VARIABLES"
These variables are only used in the \fBtcl_endOfWord\fR,
\fBtcl_startOfNextWord\fR, \fBtcl_startOfPreviousWord\fR,
\fBtcl_wordBreakAfter\fR, and \fBtcl_wordBreakBefore\fR commands.
.TP
\fBtcl_nonwordchars\fR
.
This variable contains a regular expression that is used by routines
like \fBtcl_endOfWord\fR to identify whether a character is part of a
word or not. If the pattern matches a character, the character is
considered to be a non-word character. The default value is
.QW "\\W" .
.TP
\fBtcl_wordchars\fR
.
This variable contains a regular expression that is used by routines
like \fBtcl_endOfWord\fR to identify whether a character is part of a
word or not. If the pattern matches a character, the character is
considered to be a word character. The default value is
.QW "\\w" .
.SH "SEE ALSO"
env(n), info(n), re_syntax(n)
.SH KEYWORDS
auto-exec, auto-load, library, unknown, word, whitespace
'\"Local Variables:
'\"mode: nroff
'\"End:
|
Changes to doc/link.n.
| ︙ | ︙ | |||
48 49 50 51 52 53 54 |
oo::class create ABC {
method Foo {} {
puts "This is Foo in [self]"
}
constructor {} {
\fBlink\fR Foo
| | | | | | | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
oo::class create ABC {
method Foo {} {
puts "This is Foo in [self]"
}
constructor {} {
\fBlink\fR Foo
# The method Foo is now directly accessible as Foo here
\fBlink\fR {bar Foo}
# The method Foo is now directly accessible as bar
\fBlink\fR {::ExternalCall Foo}
# The method Foo is now directly accessible in the global
# namespace as ExternalCall
}
method grill {} {
puts "Step 1:"
Foo
puts "Step 2:"
bar
}
}
ABC create abc
abc grill
\fI\(-> Step 1:\fR
\fI\(-> This is Foo in ::abc\fR
\fI\(-> Step 2:\fR
\fI\(-> This is Foo in ::abc\fR
# Direct access via the linked command
puts "Step 3:"; ExternalCall
\fI\(-> Step 3:\fR
\fI\(-> This is Foo in ::abc\fR
.CE
.PP
This example shows that multiple linked commands can be made in a call to
\fBlink\fR, and that they can handle arguments.
.PP
.CS
oo::class create Ex {
constructor {} {
\fBlink\fR a b c
# The methods a, b, and c (defined below) are all now
# directly accessible within methods under their own names.
}
method a {} {
puts "This is a"
}
method b {x} {
puts "This is b($x)"
|
| ︙ | ︙ |
Changes to doc/lremove.n.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | lremove \- Remove elements from a list by index .SH SYNOPSIS \fBlremove \fIlist\fR ?\fIindex ...\fR? .BE .SH DESCRIPTION .PP \fBlremove\fR returns a new list formed by simultaneously removing zero or | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | lremove \- Remove elements from a list by index .SH SYNOPSIS \fBlremove \fIlist\fR ?\fIindex ...\fR? .BE .SH DESCRIPTION .PP \fBlremove\fR returns a new list formed by simultaneously removing zero or more elements of \fIlist\fR at each of the indices given by an arbitrary number of \fIindex\fR arguments. The indices may be in any order and may be repeated; the element at index will only be removed once. The index values are interpreted the same as index values for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. 0 refers to the first element of the list, and \fBend\fR refers to the last element of the list. .SH EXAMPLES |
| ︙ | ︙ |
Changes to doc/lseq.n.
1 2 3 4 5 6 7 8 9 10 11 12 13 | '\" '\" Copyright (c) 2022 Eric Taylor. All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lseq n 8.7 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lseq \- Build a numeric sequence returned as a list .SH SYNOPSIS | | | | > | > > > | | > > > | | > | | > < | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
'\"
'\" Copyright (c) 2022 Eric Taylor. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lseq n 8.7 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
lseq \- Build a numeric sequence returned as a list
.SH SYNOPSIS
\fBlseq \fIstart \fR?(\fB..\fR|\fBto\fR)? \fIend\fR ??\fBby\fR? \fIstep\fR?
\fBlseq \fIstart \fBcount\fR \fIcount\fR ??\fBby\fR? \fIstep\fR?
\fBlseq \fIcount\fR ?\fBby \fIstep\fR?
.BE
.SH DESCRIPTION
.PP
The \fBlseq\fR command creates a sequence of numeric values using the given
parameters \fIstart\fR, \fIend\fR, and \fIstep\fR.
The \fIoperation\fR argument
.QW \fB..\fR
or
.QW \fBto\fR
defines an inclusive range; if it is omitted, the range is exclusive.
The \fBcount\fR option is used to define a count of the number of elements in
the list.
The \fIstep\fR (which may be preceded by \fBby\fR) is 1 if not provided.
The short form with a
single \fIcount\fR value will create a range from 0 to \fIcount\fR-1 (i.e.,
\fIcount\fR values).
.PP
The numeric arguments, \fIstart\fR, \fIend\fR, \fIstep\fR, and \fIcount\fR,
can also be a valid expression. the \fBlseq\fR command will evaluate the
expression (as if with \fBexpr\fR)
and use the numeric result, or return an error as with any invalid argument
value; a non-numeric expression result will result in an error.
.SH EXAMPLES
.CS
.\"
\fBlseq\fR 3
\fI\(-> 0 1 2\fR
\fBlseq\fR 3 0
\fI\(-> 3 2 1 0\fR
\fBlseq\fR 10 .. 1 by -2
\fI\(-> 10 8 6 4 2\fR
set l [\fBlseq\fR 0 -5]
\fI\(-> 0 -1 -2 -3 -4 -5\fR
foreach i [\fBlseq\fR [llength $l]] {
puts l($i)=[lindex $l $i]
}
\fI\(-> l(0)=0\fR
\fI\(-> l(1)=-1\fR
\fI\(-> l(2)=-2\fR
\fI\(-> l(3)=-3\fR
\fI\(-> l(4)=-4\fR
\fI\(-> l(5)=-5\fR
foreach i [\fBlseq\fR {[llength $l]-1} 0] {
puts l($i)=[lindex $l $i]
}
\fI\(-> l(5)=-5\fR
\fI\(-> l(4)=-4\fR
\fI\(-> l(3)=-3\fR
\fI\(-> l(2)=-2\fR
\fI\(-> l(1)=-1\fR
\fI\(-> l(0)=0\fR
set i 17
\fI\(-> 17\fR
if {$i in [\fBlseq\fR 0 50]} { # equivalent to: (0 <= $i && $i < 50)
puts "Ok"
} else {
puts "outside :("
}
\fI\(-> Ok\fR
set sqrs [lmap i [\fBlseq\fR 1 10] { expr {$i*$i} }]
\fI\(-> 1 4 9 16 25 36 49 64 81 100\fR
.\"
.CE
.SH "SEE ALSO"
foreach(n), list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n),
llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
|
| ︙ | ︙ |
Changes to doc/open.n.
| ︙ | ︙ | |||
124 125 126 127 128 129 130 131 132 133 134 135 136 137 | . If the file exists it is truncated to zero length. .PP If a new file is created as part of opening it, \fIpermissions\fR (an integer) is used to set the permissions for the new file in conjunction with the process's file mode creation mask. \fIPermissions\fR defaults to 0666. .SH "COMMAND PIPELINES" .PP If the first character of \fIfileName\fR is .QW \fB|\fR then the remaining characters of \fIfileName\fR are treated as a list of arguments that describe a command pipeline to invoke, in the same style as the | > > > > > > > > > > > > > > > > > > > > > > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | . If the file exists it is truncated to zero length. .PP If a new file is created as part of opening it, \fIpermissions\fR (an integer) is used to set the permissions for the new file in conjunction with the process's file mode creation mask. \fIPermissions\fR defaults to 0666. .PP .VS "8.7, TIP 603" When the file opened is an ordinary disk file, the \fBchan configure\fR and \fBfconfigure\fR commands can be used to query this additional configuration option: .TP \fB\-stat\fR . This option, when read, returns a dictionary of values much as is obtained from the \fBfile stat\fR command, where that stat information relates to the real opened file. Keys in the dictionary may include \fBatime\fR, \fBctime\fR, \fBdev\fR, \fBgid\fR, \fBino\fR, \fBmode\fR, \fBmtime\fR, \fBnlink\fR, \fBsize\fR, \fBtype\fR, and \fBuid\fR among others; the \fBmtime\fR, \fBsize\fR and \fBtype\fR fields are guaranteed to be present and meaningful on all platforms; other keys may be present too. .RS .PP \fIImplementation note:\fR This option maps to a call to \fBfstat()\fR on POSIX platforms, and to a call to \fBGetFileInformationByHandle()\fR on Windows; the information reported is what those system calls produce. .RE .VE "8.7, TIP 603" .SH "COMMAND PIPELINES" .PP If the first character of \fIfileName\fR is .QW \fB|\fR then the remaining characters of \fIfileName\fR are treated as a list of arguments that describe a command pipeline to invoke, in the same style as the |
| ︙ | ︙ |
Changes to doc/timerate.n.
| ︙ | ︙ | |||
31 32 33 34 35 36 37 | .PP The first and second form will evaluate \fIscript\fR until the interval \fItime\fR given in milliseconds elapses, or for 1000 milliseconds (1 second) if \fItime\fR is not specified. .sp The parameter \fImax-count\fR could additionally impose a further restriction by the maximal number of iterations to evaluate the script. | | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | .PP The first and second form will evaluate \fIscript\fR until the interval \fItime\fR given in milliseconds elapses, or for 1000 milliseconds (1 second) if \fItime\fR is not specified. .sp The parameter \fImax-count\fR could additionally impose a further restriction by the maximal number of iterations to evaluate the script. If \fImax-count\fR is specified, the evaluation will stop either this count of iterations is reached or the time is exceeded. .sp It will then return a canonical Tcl-list of the form: .PP .CS \fB0.095977 \(mcs/# 52095836 # 10419167 #/sec 5000.000 net-ms\fR .CE .PP which indicates: .IP \(bu 3 |
| ︙ | ︙ | |||
81 82 83 84 85 86 87 | . The \fB-direct\fR option causes direct execution of the supplied script, without compilation, in a manner similar to the \fBtime\fR command. It can be used to measure the cost of \fBTcl_EvalObjEx\fR, of the invocation of canonical lists, and of the uncompiled versions of bytecoded commands. .PP As opposed to the \fBtime\fR commmand, which runs the tested script for a fixed | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | . The \fB-direct\fR option causes direct execution of the supplied script, without compilation, in a manner similar to the \fBtime\fR command. It can be used to measure the cost of \fBTcl_EvalObjEx\fR, of the invocation of canonical lists, and of the uncompiled versions of bytecoded commands. .PP As opposed to the \fBtime\fR commmand, which runs the tested script for a fixed number of iterations, the \fBtimerate\fR command runs it for a fixed time. Additionally, the compiled variant of the script will be used during the entire measurement, as if the script were part of a compiled procedure, if the \fB\-direct\fR option is not specified. The fixed time period and possibility of compilation allow for more precise results and prevent very long execution times by slow scripts, making it practical for measuring scripts with highly uncertain execution times. .SH EXAMPLES Estimate how fast it takes for a simple Tcl \fBfor\fR loop (including |
| ︙ | ︙ |
Changes to generic/tcl.decls.
| ︙ | ︙ | |||
1438 1439 1440 1441 1442 1443 1444 |
void Tcl_ConditionFinalize(Tcl_Condition *condPtr)
}
declare 392 {
void Tcl_MutexFinalize(Tcl_Mutex *mutex)
}
declare 393 {
int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc,
| | | 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 |
void Tcl_ConditionFinalize(Tcl_Condition *condPtr)
}
declare 392 {
void Tcl_MutexFinalize(Tcl_Mutex *mutex)
}
declare 393 {
int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc,
void *clientData, TCL_HASH_TYPE stackSize, int flags)
}
# Introduced in 8.3.2
declare 394 {
Tcl_Size Tcl_ReadRaw(Tcl_Channel chan, char *dst, Tcl_Size bytesToRead)
}
declare 395 {
|
| ︙ | ︙ |
Changes to generic/tcl.h.
| ︙ | ︙ | |||
783 784 785 786 787 788 789 |
* macros Tcl_DStringValue and Tcl_DStringLength.
*/
#define TCL_DSTRING_STATIC_SIZE 200
typedef struct Tcl_DString {
char *string; /* Points to beginning of string: either
* staticSpace below or a malloced array. */
| | | | 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 |
* macros Tcl_DStringValue and Tcl_DStringLength.
*/
#define TCL_DSTRING_STATIC_SIZE 200
typedef struct Tcl_DString {
char *string; /* Points to beginning of string: either
* staticSpace below or a malloced array. */
Tcl_Size length; /* Number of bytes in string excluding
* terminating nul */
Tcl_Size spaceAvl; /* Total number of bytes available for the
* string and its terminating NULL char. */
char staticSpace[TCL_DSTRING_STATIC_SIZE];
/* Space to use in common case where string is
* small. */
} Tcl_DString;
|
| ︙ | ︙ | |||
1923 1924 1925 1926 1927 1928 1929 | * Reserve top byte for profile values (disjoint, not a mask). In case of * changes, ensure ENCODING_PROFILE_* macros in tclInt.h are modified if * necessary. */ #define TCL_ENCODING_PROFILE_TCL8 0x01000000 #define TCL_ENCODING_PROFILE_STRICT 0x02000000 #define TCL_ENCODING_PROFILE_REPLACE 0x03000000 | | | 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 | * Reserve top byte for profile values (disjoint, not a mask). In case of * changes, ensure ENCODING_PROFILE_* macros in tclInt.h are modified if * necessary. */ #define TCL_ENCODING_PROFILE_TCL8 0x01000000 #define TCL_ENCODING_PROFILE_STRICT 0x02000000 #define TCL_ENCODING_PROFILE_REPLACE 0x03000000 #define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_STRICT /* * The following definitions are the error codes returned by the conversion * routines: * * TCL_OK - All characters were converted. * TCL_CONVERT_NOSPACE - The output buffer would not have been large |
| ︙ | ︙ |
Changes to generic/tclArithSeries.c.
| ︙ | ︙ | |||
154 155 156 157 158 159 160 |
NULL,
ArithSeriesObjReverse,
NULL,
NULL,
},
};
const ObjectType tclArithSeriesObjType = {
| | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
NULL,
ArithSeriesObjReverse,
NULL,
NULL,
},
};
const ObjectType tclArithSeriesObjType = {
"arithseries",
FreeArithSeriesInternalRep, /* freeIntRepProc */
DupArithSeriesInternalRep, /* dupIntRepProc */
UpdateStringOfArithSeries, /* updateStringProc */
SetArithSeriesFromAny, /* setFromAnyProc */
2,
(Tcl_ObjInterface *)&tclArithSeriesInterface
};
|
| ︙ | ︙ | |||
418 419 420 421 422 423 424 |
assignNumber(useDoubles, &step, &dstep, stepObj);
if (useDoubles) {
step = dstep;
} else {
dstep = step;
}
if (dstep == 0) {
| | | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
assignNumber(useDoubles, &step, &dstep, stepObj);
if (useDoubles) {
step = dstep;
} else {
dstep = step;
}
if (dstep == 0) {
TclNewObj(*arithSeriesObj);
return TCL_OK;
}
}
if (endObj) {
assignNumber(useDoubles, &end, &dend, endObj);
}
if (lenObj) {
|
| ︙ | ︙ |
Changes to generic/tclBasic.c.
| ︙ | ︙ | |||
801 802 803 804 805 806 807 |
iPtr->legacyResult = NULL;
/* Special invalid value: Any attempt to free the legacy result
* will cause a crash. */
iPtr->legacyFreeProc = (void (*) (void))-1;
iPtr->errorLine = 0;
iPtr->stubTable = &tclStubs;
| | | 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 |
iPtr->legacyResult = NULL;
/* Special invalid value: Any attempt to free the legacy result
* will cause a crash. */
iPtr->legacyFreeProc = (void (*) (void))-1;
iPtr->errorLine = 0;
iPtr->stubTable = &tclStubs;
TclNewObj(iPtr->objResultPtr);
Tcl_IncrRefCount(iPtr->objResultPtr);
iPtr->handle = TclHandleCreate(iPtr);
iPtr->globalNsPtr = NULL;
iPtr->hiddenCmdTablePtr = NULL;
iPtr->interpInfo = NULL;
iPtr->optimizer = TclOptimizeBytecode;
|
| ︙ | ︙ | |||
886 887 888 889 890 891 892 |
iPtr->flags = 0;
iPtr->tracePtr = NULL;
iPtr->tracesForbiddingInline = 0;
iPtr->activeCmdTracePtr = NULL;
iPtr->activeInterpTracePtr = NULL;
iPtr->assocData = NULL;
iPtr->execEnvPtr = NULL; /* Set after namespaces initialized. */
| | | 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 |
iPtr->flags = 0;
iPtr->tracePtr = NULL;
iPtr->tracesForbiddingInline = 0;
iPtr->activeCmdTracePtr = NULL;
iPtr->activeInterpTracePtr = NULL;
iPtr->assocData = NULL;
iPtr->execEnvPtr = NULL; /* Set after namespaces initialized. */
TclNewObj(iPtr->emptyObjPtr);
/* Another empty object. */
Tcl_IncrRefCount(iPtr->emptyObjPtr);
iPtr->threadId = Tcl_GetCurrentThread();
/* TIP #378 */
#ifdef TCL_INTERP_DEBUG_FRAME
iPtr->flags |= INTERP_DEBUG_FRAME;
|
| ︙ | ︙ | |||
950 951 952 953 954 955 956 |
iPtr->chanMsg = NULL;
/*
* TIP #285, Script cancellation support.
*/
| | | 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 |
iPtr->chanMsg = NULL;
/*
* TIP #285, Script cancellation support.
*/
TclNewObj(iPtr->asyncCancelMsg);
cancelInfo = (CancelInfo *)Tcl_Alloc(sizeof(CancelInfo));
cancelInfo->interp = interp;
iPtr->asyncCancel = Tcl_AsyncCreate(CancelEvalProc, cancelInfo);
cancelInfo->async = iPtr->asyncCancel;
cancelInfo->result = NULL;
|
| ︙ | ︙ |
Changes to generic/tclBinary.c.
| ︙ | ︙ | |||
734 735 736 737 738 739 740 |
if ((BYTEARRAY_MAX_LEN - byteArrayPtr->used) < len) {
/* Will wrap around !! */
Tcl_Panic("max size of a byte array exceeded");
}
needed = byteArrayPtr->used + len;
if (needed > byteArrayPtr->allocated) {
| < < < < < < | < < < < | < < | < < < < < < < | < < < < < < < < | < < < | > | | 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 |
if ((BYTEARRAY_MAX_LEN - byteArrayPtr->used) < len) {
/* Will wrap around !! */
Tcl_Panic("max size of a byte array exceeded");
}
needed = byteArrayPtr->used + len;
if (needed > byteArrayPtr->allocated) {
Tcl_Size newCapacity;
byteArrayPtr =
(ByteArray *)TclReallocElemsEx(byteArrayPtr,
needed,
1,
offsetof(ByteArray, bytes),
&newCapacity);
byteArrayPtr->allocated = newCapacity;
SET_BYTEARRAY(irPtr, byteArrayPtr);
}
if (bytes) {
memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
}
byteArrayPtr->used += len;
|
| ︙ | ︙ |
Changes to generic/tclCkalloc.c.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This code contributed by Karl Lehenbauer and Mark Diekhans */ #include "tclInt.h" #define FALSE 0 #define TRUE 1 #undef Tcl_Alloc #undef Tcl_Free #undef Tcl_Realloc | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This code contributed by Karl Lehenbauer and Mark Diekhans */ #include "tclInt.h" #include <assert.h> #define FALSE 0 #define TRUE 1 #undef Tcl_Alloc #undef Tcl_Free #undef Tcl_Realloc |
| ︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
TCL_UNUSED(void *),
TCL_UNUSED(int) /*flags*/)
{
return 1;
}
#endif /* TCL_MEM_DEBUG */
/*
*---------------------------------------------------------------------------
*
* TclFinalizeMemorySubsystem --
*
* This procedure is called to finalize all the structures that are used
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 |
TCL_UNUSED(void *),
TCL_UNUSED(int) /*flags*/)
{
return 1;
}
#endif /* TCL_MEM_DEBUG */
/*
*------------------------------------------------------------------------
*
* TclAllocElemsEx --
*
* See TclAttemptAllocElemsEx. This function differs in that it panics
* on failure.
*
* Results:
* Non-NULL pointer to allocated memory block.
*
* Side effects:
* Panics if memory of at least the requested size could not be
* allocated.
*
*------------------------------------------------------------------------
*/
void *
TclAllocElemsEx(
Tcl_Size elemCount, /* Allocation will store at least these many... */
Tcl_Size elemSize, /* ...elements of this size */
Tcl_Size leadSize, /* Additional leading space in bytes */
Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
here if non-NULL. Only modified on success */
{
void *ptr = TclAttemptReallocElemsEx(
NULL, elemCount, elemSize, leadSize, capacityPtr);
if (ptr == NULL) {
Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
elemCount,
elemSize);
}
return ptr;
}
/*
*------------------------------------------------------------------------
*
* TclAttemptReallocElemsEx --
*
* Attempts to allocate (oldPtr == NULL) or reallocate memory of the
* requested size plus some more for future growth. The amount of
* reallocation is adjusted depending on on failure.
*
*
* Results:
* Pointer to allocated memory block which is at least as large
* as the requested size or NULL if allocation failed.
*
*------------------------------------------------------------------------
*/
void *
TclAttemptReallocElemsEx(
void *oldPtr, /* Pointer to memory block to reallocate or
* NULL to indicate this is a new allocation */
Tcl_Size elemCount, /* Allocation will store at least these many... */
Tcl_Size elemSize, /* ...elements of this size */
Tcl_Size leadSize, /* Additional leading space in bytes */
Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
here if non-NULL. Only modified on success */
{
void *ptr;
Tcl_Size limit;
Tcl_Size attempt;
assert(elemCount > 0);
assert(elemSize > 0);
assert(elemSize < TCL_SIZE_MAX);
assert(leadSize >= 0);
assert(leadSize < TCL_SIZE_MAX);
limit = (TCL_SIZE_MAX - leadSize) / elemSize;
if (elemCount > limit) {
return NULL;
}
/* Loop trying for extra space, reducing request each time */
attempt = TclUpsizeAlloc(0, elemCount, limit);
ptr = NULL;
while (attempt > elemCount) {
if (oldPtr) {
ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt * elemSize);
} else {
ptr = Tcl_AttemptAlloc(leadSize + attempt * elemSize);
}
if (ptr) {
break;
}
attempt = TclUpsizeRetry(elemCount, attempt);
}
/* Try exact size as a last resort */
if (ptr == NULL) {
attempt = elemCount;
if (oldPtr) {
ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt * elemSize);
} else {
ptr = Tcl_AttemptAlloc(leadSize + attempt * elemSize);
}
}
if (ptr && capacityPtr) {
*capacityPtr = attempt;
}
return ptr;
}
/*
*------------------------------------------------------------------------
*
* TclReallocElemsEx --
*
* See TclAttemptReallocElemsEx. This function differs in that it panics
* on failure.
*
* Results:
* Non-NULL pointer to allocated memory block.
*
* Side effects:
* Panics if memory of at least the requested size could not be
* allocated.
*
*------------------------------------------------------------------------
*/
void *
TclReallocElemsEx(
void *oldPtr, /* Pointer to memory block to reallocate */
Tcl_Size elemCount, /* Allocation will store at least these many... */
Tcl_Size elemSize, /* ...elements of this size */
Tcl_Size leadSize, /* Additional leading space in bytes */
Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
here if non-NULL. Only modified on success */
{
void *ptr = TclAttemptReallocElemsEx(
oldPtr, elemCount, elemSize, leadSize, capacityPtr);
if (ptr == NULL) {
Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
elemCount,
elemSize);
}
return ptr;
}
/*
*---------------------------------------------------------------------------
*
* TclFinalizeMemorySubsystem --
*
* This procedure is called to finalize all the structures that are used
|
| ︙ | ︙ |
Changes to generic/tclCmdAH.c.
| ︙ | ︙ | |||
2320 2321 2322 2323 2324 2325 2326 |
Tcl_StatBuf *statPtr) /* Pointer to buffer containing stat data to
* store in varName. */
{
Tcl_Obj *field, *value, *result;
unsigned short mode;
if (varName == NULL) {
| | | 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 |
Tcl_StatBuf *statPtr) /* Pointer to buffer containing stat data to
* store in varName. */
{
Tcl_Obj *field, *value, *result;
unsigned short mode;
if (varName == NULL) {
TclNewObj(result);
Tcl_IncrRefCount(result);
#define DOBJPUT(key, objValue) \
Tcl_DictObjPut(NULL, result, \
Tcl_NewStringObj((key), -1), \
(objValue));
DOBJPUT("dev", Tcl_NewWideIntObj((long)statPtr->st_dev));
DOBJPUT("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
|
| ︙ | ︙ | |||
2382 2383 2384 2385 2386 2387 2388 2389 2390 |
STORE_ARY("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
STORE_ARY("size", Tcl_NewWideIntObj(statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
STORE_ARY("blocks", Tcl_NewWideIntObj(statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
#endif
STORE_ARY("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
| > > > > > | > | 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 |
STORE_ARY("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
STORE_ARY("size", Tcl_NewWideIntObj(statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
STORE_ARY("blocks", Tcl_NewWideIntObj(statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
if (S_ISCHR(statPtr->st_mode) || S_ISBLK(statPtr->st_mode)) {
STORE_ARY("rdev", Tcl_NewWideIntObj((long) statPtr->st_rdev));
}
#endif
STORE_ARY("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
STORE_ARY("mtime", Tcl_NewWideIntObj(
Tcl_GetModificationTimeFromStat(statPtr)));
STORE_ARY("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
mode = (unsigned short) statPtr->st_mode;
STORE_ARY("mode", Tcl_NewWideIntObj(mode));
STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef STORE_ARY
return TCL_OK;
|
| ︙ | ︙ |
Changes to generic/tclCmdIL.c.
| ︙ | ︙ | |||
708 709 710 711 712 713 714 |
* special characters. This lets us avoid scans of any hash tables.
*/
entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
if (entryPtr != NULL) {
if (specificNsInPattern) {
cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
| | | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 |
* special characters. This lets us avoid scans of any hash tables.
*/
entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
if (entryPtr != NULL) {
if (specificNsInPattern) {
cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
TclNewObj(elemObjPtr);
Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
} else {
cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
Tcl_SetObjResult(interp, listPtr);
|
| ︙ | ︙ | |||
759 760 761 762 763 764 765 |
entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
while (entryPtr != NULL) {
cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
if ((simplePattern == NULL)
|| Tcl_StringMatch(cmdName, simplePattern)) {
if (specificNsInPattern) {
cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
| | | 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 |
entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
while (entryPtr != NULL) {
cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
if ((simplePattern == NULL)
|| Tcl_StringMatch(cmdName, simplePattern)) {
if (specificNsInPattern) {
cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
TclNewObj(elemObjPtr);
Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
} else {
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
}
entryPtr = Tcl_NextHashEntry(&search);
|
| ︙ | ︙ | |||
986 987 988 989 990 991 992 |
valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
localPtr->defValuePtr, TCL_LEAVE_ERR_MSG);
if (valueObjPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
} else {
| | > | 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 |
valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
localPtr->defValuePtr, TCL_LEAVE_ERR_MSG);
if (valueObjPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
} else {
Tcl_Obj *nullObjPtr;
TclNewObj(nullObjPtr);
valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
nullObjPtr, TCL_LEAVE_ERR_MSG);
if (valueObjPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
|
| ︙ | ︙ | |||
1902 1903 1904 1905 1906 1907 1908 |
TclGetOriginalCommand((Tcl_Command) cmdPtr);
if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
goto simpleProcOK;
}
} else {
simpleProcOK:
if (specificNsInPattern) {
| | | 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 |
TclGetOriginalCommand((Tcl_Command) cmdPtr);
if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
goto simpleProcOK;
}
} else {
simpleProcOK:
if (specificNsInPattern) {
TclNewObj(elemObjPtr);
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
elemObjPtr);
} else {
elemObjPtr = Tcl_NewStringObj(simplePattern, -1);
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
}
|
| ︙ | ︙ | |||
1930 1931 1932 1933 1934 1935 1936 |
TclGetOriginalCommand((Tcl_Command) cmdPtr);
if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
goto procOK;
}
} else {
procOK:
if (specificNsInPattern) {
| | | 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 |
TclGetOriginalCommand((Tcl_Command) cmdPtr);
if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
goto procOK;
}
} else {
procOK:
if (specificNsInPattern) {
TclNewObj(elemObjPtr);
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
elemObjPtr);
} else {
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
}
|
| ︙ | ︙ | |||
2263 2264 2265 2266 2267 2268 2269 |
&elemPtrs) != TCL_OK) {
return TCL_ERROR;
}
resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
} else {
Tcl_Size i;
| | | 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 |
&elemPtrs) != TCL_OK) {
return TCL_ERROR;
}
resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
} else {
Tcl_Size i;
TclNewObj(resObjPtr);
if (TclObjectHasInterface(objv[1], list, index)) {
Tcl_Obj *valueObj;
for (i = 0; i < listLen; i++) {
if (i > 0) {
/*
* NOTE: This code is relying on Tcl_AppendObjToObj() **NOT**
|
| ︙ | ︙ |
Changes to generic/tclCmdMZ.c.
| ︙ | ︙ | |||
354 355 356 357 358 359 360 |
/*
* It's the number of substitutions, plus one for the matchVar at
* index 0
*/
objc = info.nsubs + 1;
if (all <= 1) {
| | | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
/*
* It's the number of substitutions, plus one for the matchVar at
* index 0
*/
objc = info.nsubs + 1;
if (all <= 1) {
TclNewObj(resultPtr);
}
}
for (i = 0; i < objc; i++) {
Tcl_Obj *newPtr;
if (indices) {
Tcl_Size start, end;
|
| ︙ | ︙ | |||
396 397 398 399 400 401 402 |
newPtr = Tcl_NewListObj(2, objs);
} else {
if ((i <= (int)info.nsubs) && (info.matches[i].end > 0)) {
newPtr = Tcl_GetRange(objPtr,
offset + info.matches[i].start,
offset + info.matches[i].end - 1);
} else {
| | | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
newPtr = Tcl_NewListObj(2, objs);
} else {
if ((i <= (int)info.nsubs) && (info.matches[i].end > 0)) {
newPtr = Tcl_GetRange(objPtr,
offset + info.matches[i].start,
offset + info.matches[i].end - 1);
} else {
TclNewObj(newPtr);
}
}
if (doinline) {
if (Tcl_ListObjAppendElement(interp, resultPtr, newPtr)
!= TCL_OK) {
Tcl_DecrRefCount(newPtr);
Tcl_DecrRefCount(resultPtr);
|
| ︙ | ︙ | |||
1191 1192 1193 1194 1195 1196 1197 |
} else {
Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?");
return TCL_ERROR;
}
stringPtr = Tcl_GetStringFromObj(objv[1], &stringLen);
end = stringPtr + stringLen;
| | | 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 |
} else {
Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?");
return TCL_ERROR;
}
stringPtr = Tcl_GetStringFromObj(objv[1], &stringLen);
end = stringPtr + stringLen;
TclNewObj(listPtr);
if (stringLen == 0) {
/*
* Do nothing.
*/
} else if (splitCharLen == 0) {
Tcl_HashTable charReuseTable;
|
| ︙ | ︙ | |||
4706 4707 4708 4709 4710 4711 4712 |
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv,
"body ?handler ...? ?finally script?");
return TCL_ERROR;
}
bodyObj = objv[1];
| | | 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 |
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv,
"body ?handler ...? ?finally script?");
return TCL_ERROR;
}
bodyObj = objv[1];
TclNewObj(handlersObj);
bodyShared = 0;
haveHandlers = 0;
for (i=2 ; i<objc ; i++) {
enum Handlers type;
Tcl_Obj *info[5];
if (Tcl_GetIndexFromObj(interp, objv[i], handlerNames, "handler type",
|
| ︙ | ︙ |
Changes to generic/tclDecls.h.
| ︙ | ︙ | |||
1030 1031 1032 1033 1034 1035 1036 | /* 391 */ EXTERN void Tcl_ConditionFinalize(Tcl_Condition *condPtr); /* 392 */ EXTERN void Tcl_MutexFinalize(Tcl_Mutex *mutex); /* 393 */ EXTERN int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, | | | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 | /* 391 */ EXTERN void Tcl_ConditionFinalize(Tcl_Condition *condPtr); /* 392 */ EXTERN void Tcl_MutexFinalize(Tcl_Mutex *mutex); /* 393 */ EXTERN int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); /* 394 */ EXTERN Tcl_Size Tcl_ReadRaw(Tcl_Channel chan, char *dst, Tcl_Size bytesToRead); /* 395 */ EXTERN Tcl_Size Tcl_WriteRaw(Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 396 */ |
| ︙ | ︙ | |||
2266 2267 2268 2269 2270 2271 2272 |
void (*tcl_SetNotifier) (const Tcl_NotifierProcs *notifierProcPtr); /* 386 */
Tcl_Mutex * (*tcl_GetAllocMutex) (void); /* 387 */
int (*tcl_GetChannelNames) (Tcl_Interp *interp); /* 388 */
int (*tcl_GetChannelNamesEx) (Tcl_Interp *interp, const char *pattern); /* 389 */
int (*tcl_ProcObjCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); /* 390 */
void (*tcl_ConditionFinalize) (Tcl_Condition *condPtr); /* 391 */
void (*tcl_MutexFinalize) (Tcl_Mutex *mutex); /* 392 */
| | | 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 |
void (*tcl_SetNotifier) (const Tcl_NotifierProcs *notifierProcPtr); /* 386 */
Tcl_Mutex * (*tcl_GetAllocMutex) (void); /* 387 */
int (*tcl_GetChannelNames) (Tcl_Interp *interp); /* 388 */
int (*tcl_GetChannelNamesEx) (Tcl_Interp *interp, const char *pattern); /* 389 */
int (*tcl_ProcObjCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); /* 390 */
void (*tcl_ConditionFinalize) (Tcl_Condition *condPtr); /* 391 */
void (*tcl_MutexFinalize) (Tcl_Mutex *mutex); /* 392 */
int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); /* 393 */
Tcl_Size (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, Tcl_Size bytesToRead); /* 394 */
Tcl_Size (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 395 */
Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */
int (*tcl_ChannelBuffered) (Tcl_Channel chan); /* 397 */
const char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */
Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (const Tcl_ChannelType *chanTypePtr); /* 399 */
Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (const Tcl_ChannelType *chanTypePtr); /* 400 */
|
| ︙ | ︙ |
Changes to generic/tclDictObj.c.
| ︙ | ︙ | |||
154 155 156 157 158 159 160 |
do { \
Tcl_ObjInternalRep ir; \
ir.twoPtrValue.ptr1 = (dictRepPtr); \
ir.twoPtrValue.ptr2 = NULL; \
Tcl_StoreInternalRep((objPtr), &tclDictType, &ir); \
} while (0)
| | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
do { \
Tcl_ObjInternalRep ir; \
ir.twoPtrValue.ptr1 = (dictRepPtr); \
ir.twoPtrValue.ptr2 = NULL; \
Tcl_StoreInternalRep((objPtr), &tclDictType, &ir); \
} while (0)
#define DictGetInternalRep(objPtr, dictRepPtr) \
do { \
const Tcl_ObjInternalRep *irPtr; \
irPtr = TclFetchInternalRep((objPtr), &tclDictType); \
(dictRepPtr) = irPtr ? (Dict *)irPtr->twoPtrValue.ptr1 : NULL; \
} while (0)
/*
|
| ︙ | ︙ | |||
359 360 361 362 363 364 365 |
DupDictInternalRep(
Tcl_Obj *srcPtr,
Tcl_Obj *copyPtr)
{
Dict *oldDict, *newDict = (Dict *)Tcl_Alloc(sizeof(Dict));
ChainEntry *cPtr;
| | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
DupDictInternalRep(
Tcl_Obj *srcPtr,
Tcl_Obj *copyPtr)
{
Dict *oldDict, *newDict = (Dict *)Tcl_Alloc(sizeof(Dict));
ChainEntry *cPtr;
DictGetInternalRep(srcPtr, oldDict);
/*
* Copy values across from the old hash table.
*/
InitChainTable(newDict);
for (cPtr=oldDict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) {
|
| ︙ | ︙ | |||
419 420 421 422 423 424 425 |
static void
FreeDictInternalRep(
Tcl_Obj *dictPtr)
{
Dict *dict;
| | | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
static void
FreeDictInternalRep(
Tcl_Obj *dictPtr)
{
Dict *dict;
DictGetInternalRep(dictPtr, dict);
if (dict->refCount-- <= 1) {
DeleteDict(dict);
}
}
/*
|
| ︙ | ︙ | |||
497 498 499 500 501 502 503 |
/*
* This field is the most useful one in the whole hash structure, and it
* is not exposed by any API function...
*/
Tcl_Size numElems;
| | | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 |
/*
* This field is the most useful one in the whole hash structure, and it
* is not exposed by any API function...
*/
Tcl_Size numElems;
DictGetInternalRep(dictPtr, dict);
assert (dict != NULL);
numElems = dict->table.numEntries * 2;
/* Handle empty list case first, simplifies what follows */
if (numElems == 0) {
|
| ︙ | ︙ | |||
729 730 731 732 733 734 735 |
static Dict *
GetDictFromObj(
Tcl_Interp *interp,
Tcl_Obj *dictPtr)
{
Dict *dict;
| | | | 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 |
static Dict *
GetDictFromObj(
Tcl_Interp *interp,
Tcl_Obj *dictPtr)
{
Dict *dict;
DictGetInternalRep(dictPtr, dict);
if (dict == NULL) {
if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
return NULL;
}
DictGetInternalRep(dictPtr, dict);
}
return dict;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
782 783 784 785 786 787 788 |
Tcl_Size keyc,
Tcl_Obj *const keyv[],
int flags)
{
Dict *dict, *newDict;
Tcl_Size i;
| | | | 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 |
Tcl_Size keyc,
Tcl_Obj *const keyv[],
int flags)
{
Dict *dict, *newDict;
Tcl_Size i;
DictGetInternalRep(dictPtr, dict);
if (dict == NULL) {
if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
return NULL;
}
DictGetInternalRep(dictPtr, dict);
}
if (flags & DICT_PATH_UPDATE) {
dict->chain = NULL;
}
for (i=0 ; i<keyc ; i++) {
Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&dict->table, keyv[i]);
|
| ︙ | ︙ | |||
825 826 827 828 829 830 831 |
hPtr = CreateChainEntry(dict, keyv[i], &isNew);
tmpObj = Tcl_NewDictObj();
Tcl_IncrRefCount(tmpObj);
Tcl_SetHashValue(hPtr, tmpObj);
} else {
tmpObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
| | | | | 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 |
hPtr = CreateChainEntry(dict, keyv[i], &isNew);
tmpObj = Tcl_NewDictObj();
Tcl_IncrRefCount(tmpObj);
Tcl_SetHashValue(hPtr, tmpObj);
} else {
tmpObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
DictGetInternalRep(tmpObj, newDict);
if (newDict == NULL) {
if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
return NULL;
}
}
}
DictGetInternalRep(tmpObj, newDict);
if (flags & DICT_PATH_UPDATE) {
if (Tcl_IsShared(tmpObj)) {
TclDecrRefCount(tmpObj);
tmpObj = Tcl_DuplicateObj(tmpObj);
Tcl_IncrRefCount(tmpObj);
Tcl_SetHashValue(hPtr, tmpObj);
dict->epoch++;
DictGetInternalRep(tmpObj, newDict);
}
newDict->chain = dictPtr;
}
dict = newDict;
dictPtr = tmpObj;
}
|
| ︙ | ︙ | |||
879 880 881 882 883 884 885 |
static void
InvalidateDictChain(
Tcl_Obj *dictObj)
{
Dict *dict;
| | | | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 |
static void
InvalidateDictChain(
Tcl_Obj *dictObj)
{
Dict *dict;
DictGetInternalRep(dictObj, dict);
assert( dict != NULL);
do {
dict->refCount++;
TclInvalidateStringRep(dictObj);
TclFreeInternalRep(dictObj);
DictSetIntRep(dictObj, dict);
dict->epoch++;
dictObj = dict->chain;
if (dictObj == NULL) {
break;
}
dict->chain = NULL;
DictGetInternalRep(dictObj, dict);
} while (dict != NULL);
}
/*
*----------------------------------------------------------------------
*
* Tcl_DictObjPut --
|
| ︙ | ︙ | |||
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 |
if (DeleteChainEntry(dict, keyPtr)) {
TclInvalidateStringRep(dictPtr);
dict->epoch++;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_DictObjSize --
*
* How many key,value pairs are there in the dictionary?
| > > > > > > > > > > > > > > > > > > > > | 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 |
if (DeleteChainEntry(dict, keyPtr)) {
TclInvalidateStringRep(dictPtr);
dict->epoch++;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_DictGetSize
*
* Returns the size of dictPtr. Caller must ensure that dictPtr has type
* 'tclDicttype'.
*
*
*----------------------------------------------------------------------
*/
Tcl_Size
TclDictGetSize(Tcl_Obj *dictPtr)
{
Dict *dict;
DictGetInternalRep(dictPtr, dict);
return dict->table.numEntries;
}
/*
*----------------------------------------------------------------------
*
* Tcl_DictObjSize --
*
* How many key,value pairs are there in the dictionary?
|
| ︙ | ︙ | |||
1297 1298 1299 1300 1301 1302 1303 |
}
dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_CREATE);
if (dictPtr == NULL) {
return TCL_ERROR;
}
| | | 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 |
}
dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_CREATE);
if (dictPtr == NULL) {
return TCL_ERROR;
}
DictGetInternalRep(dictPtr, dict);
assert(dict != NULL);
hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew);
Tcl_IncrRefCount(valuePtr);
if (!isNew) {
Tcl_Obj *oldValuePtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
TclDecrRefCount(oldValuePtr);
|
| ︙ | ︙ | |||
1355 1356 1357 1358 1359 1360 1361 |
}
dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_UPDATE);
if (dictPtr == NULL) {
return TCL_ERROR;
}
| | | 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 |
}
dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_UPDATE);
if (dictPtr == NULL) {
return TCL_ERROR;
}
DictGetInternalRep(dictPtr, dict);
assert(dict != NULL);
DeleteChainEntry(dict, keyv[keyc-1]);
InvalidateDictChain(dictPtr);
return TCL_OK;
}
/*
|
| ︙ | ︙ |
Changes to generic/tclEvent.c.
| ︙ | ︙ | |||
2042 2043 2044 2045 2046 2047 2048 |
*/
int
Tcl_CreateThread(
Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
Tcl_ThreadCreateProc *proc, /* Main() function of the thread */
void *clientData, /* The one argument to Main() */
| | | 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 |
*/
int
Tcl_CreateThread(
Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
Tcl_ThreadCreateProc *proc, /* Main() function of the thread */
void *clientData, /* The one argument to Main() */
TCL_HASH_TYPE stackSize, /* Size of stack for the new thread */
int flags) /* Flags controlling behaviour of the new
* thread. */
{
#if TCL_THREADS
ThreadClientData *cdPtr = (ThreadClientData *)Tcl_Alloc(sizeof(ThreadClientData));
int result;
|
| ︙ | ︙ |
Changes to generic/tclExecute.c.
| ︙ | ︙ | |||
362 363 364 365 366 367 368 | #define OBJ_AT_TOS *tosPtr #define OBJ_UNDER_TOS *(tosPtr-1) #define OBJ_AT_DEPTH(n) *(tosPtr-(n)) | | | | | | | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
#define OBJ_AT_TOS *tosPtr
#define OBJ_UNDER_TOS *(tosPtr-1)
#define OBJ_AT_DEPTH(n) *(tosPtr-(n))
#define CURR_DEPTH (tosPtr - initTosPtr)
#define STACK_BASE(esPtr) ((esPtr)->stackWords - 1)
/*
* Macros used to trace instruction execution. The macros TRACE,
* TRACE_WITH_OBJ, and O2S are only used inside TclNRExecuteByteCode. O2S is
* only used in TRACE* calls to get a string from an object.
*/
#ifdef TCL_COMPILE_DEBUG
# define TRACE(a) \
while (traceInstructions) { \
fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels, \
CURR_DEPTH, \
(pc - codePtr->codeStart), \
GetOpcodeName(pc)); \
printf a; \
break; \
}
# define TRACE_APPEND(a) \
while (traceInstructions) { \
printf a; \
break; \
}
# define TRACE_ERROR(interp) \
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
# define TRACE_WITH_OBJ(a, objPtr) \
while (traceInstructions) { \
fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels, \
CURR_DEPTH, \
(pc - codePtr->codeStart), \
GetOpcodeName(pc)); \
printf a; \
TclPrintObject(stdout, objPtr, 30); \
fprintf(stdout, "\n"); \
break; \
}
# define O2S(objPtr) \
|
| ︙ | ︙ | |||
632 633 634 635 636 637 638 | Tcl_Obj *valuePtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, int searchMode, ByteCode *codePtr); static const char * GetSrcInfoForPc(const unsigned char *pc, ByteCode *codePtr, Tcl_Size *lengthPtr, const unsigned char **pcBeg, int *cmdIdxPtr); | | | | | 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 | Tcl_Obj *valuePtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, int searchMode, ByteCode *codePtr); static const char * GetSrcInfoForPc(const unsigned char *pc, ByteCode *codePtr, Tcl_Size *lengthPtr, const unsigned char **pcBeg, int *cmdIdxPtr); static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, TCL_HASH_TYPE growth, int move); static void IllegalExprOperandType(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj *opndPtr); static void InitByteCodeExecution(Tcl_Interp *interp); static inline int wordSkip(void *ptr); static void ReleaseDictIterator(Tcl_Obj *objPtr); /* Useful elsewhere, make available in tclInt.h or stubs? */ static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, TCL_HASH_TYPE numWords); static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, TCL_HASH_TYPE numWords); static Tcl_NRPostProc CopyCallback; static Tcl_NRPostProc ExprObjCallback; static Tcl_NRPostProc FinalizeOONext; static Tcl_NRPostProc FinalizeOONextFilter; static Tcl_NRPostProc TEBCresume; /* |
| ︙ | ︙ | |||
788 789 790 791 792 793 794 |
*----------------------------------------------------------------------
*/
ExecEnv *
TclCreateExecEnv(
Tcl_Interp *interp, /* Interpreter for which the execution
* environment is being created. */
| | | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 |
*----------------------------------------------------------------------
*/
ExecEnv *
TclCreateExecEnv(
Tcl_Interp *interp, /* Interpreter for which the execution
* environment is being created. */
TCL_HASH_TYPE size) /* The initial stack size, in number of words
* [sizeof(Tcl_Obj*)] */
{
ExecEnv *eePtr = (ExecEnv *)Tcl_Alloc(sizeof(ExecEnv));
ExecStack *esPtr = (ExecStack *)Tcl_Alloc(offsetof(ExecStack, stackWords)
+ size * sizeof(Tcl_Obj *));
eePtr->execStackPtr = esPtr;
|
| ︙ | ︙ | |||
970 971 972 973 974 975 976 |
*----------------------------------------------------------------------
*/
static Tcl_Obj **
GrowEvaluationStack(
ExecEnv *eePtr, /* Points to the ExecEnv with an evaluation
* stack to enlarge. */
| | | | 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 |
*----------------------------------------------------------------------
*/
static Tcl_Obj **
GrowEvaluationStack(
ExecEnv *eePtr, /* Points to the ExecEnv with an evaluation
* stack to enlarge. */
TCL_HASH_TYPE growth1, /* How much larger than the current used
* size. */
int move) /* 1 if move words since last marker. */
{
ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL;
TCL_HASH_TYPE newBytes;
Tcl_Size growth = growth1;
Tcl_Size newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart;
Tcl_Size moveWords = 0;
if (move) {
if (!markerPtr) {
|
| ︙ | ︙ | |||
1122 1123 1124 1125 1126 1127 1128 |
*
*--------------------------------------------------------------
*/
static Tcl_Obj **
StackAllocWords(
Tcl_Interp *interp,
| | | | 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 |
*
*--------------------------------------------------------------
*/
static Tcl_Obj **
StackAllocWords(
Tcl_Interp *interp,
TCL_HASH_TYPE numWords)
{
/*
* Note that GrowEvaluationStack sets a marker in the stack. This marker
* is read when rewinding, e.g., by TclStackFree.
*/
Interp *iPtr = (Interp *) interp;
ExecEnv *eePtr = iPtr->execEnvPtr;
Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 0);
eePtr->execStackPtr->tosPtr += numWords;
return resPtr;
}
static Tcl_Obj **
StackReallocWords(
Tcl_Interp *interp,
TCL_HASH_TYPE numWords)
{
Interp *iPtr = (Interp *) interp;
ExecEnv *eePtr = iPtr->execEnvPtr;
Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 1);
eePtr->execStackPtr->tosPtr += numWords;
return resPtr;
|
| ︙ | ︙ | |||
1219 1220 1221 1222 1223 1224 1225 |
eePtr->execStackPtr = esPtr;
}
}
void *
TclStackAlloc(
Tcl_Interp *interp,
| | | | | | | 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 |
eePtr->execStackPtr = esPtr;
}
}
void *
TclStackAlloc(
Tcl_Interp *interp,
TCL_HASH_TYPE numBytes)
{
Interp *iPtr = (Interp *) interp;
TCL_HASH_TYPE numWords;
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
return Tcl_Alloc(numBytes);
}
numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
return StackAllocWords(interp, numWords);
}
void *
TclStackRealloc(
Tcl_Interp *interp,
void *ptr,
TCL_HASH_TYPE numBytes)
{
Interp *iPtr = (Interp *) interp;
ExecEnv *eePtr;
ExecStack *esPtr;
Tcl_Obj **markerPtr;
TCL_HASH_TYPE numWords;
if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
return Tcl_Realloc(ptr, numBytes);
}
eePtr = iPtr->execEnvPtr;
esPtr = eePtr->execStackPtr;
|
| ︙ | ︙ | |||
1884 1885 1886 1887 1888 1889 1890 |
int
TclNRExecuteByteCode(
Tcl_Interp *interp, /* Token for command interpreter. */
ByteCode *codePtr) /* The bytecode sequence to interpret. */
{
Interp *iPtr = (Interp *) interp;
TEBCdata *TD;
| | | | 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 |
int
TclNRExecuteByteCode(
Tcl_Interp *interp, /* Token for command interpreter. */
ByteCode *codePtr) /* The bytecode sequence to interpret. */
{
Interp *iPtr = (Interp *) interp;
TEBCdata *TD;
TCL_HASH_TYPE size = sizeof(TEBCdata) - 1
+ (codePtr->maxStackDepth + codePtr->maxExceptDepth)
* sizeof(void *);
TCL_HASH_TYPE numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *);
TclPreserveByteCode(codePtr);
/*
* Reserve the stack, setup the TEBCdataPtr (TD) and CallFrame
*
* The execution uses a unified stack: first a TEBCdata, immediately
|
| ︙ | ︙ | |||
2061 2062 2063 2064 2065 2066 2067 |
#endif
TEBC_DATA_DIG();
#ifdef TCL_COMPILE_DEBUG
if (!pc && (tclTraceExec >= 2)) {
PrintByteCodeInfo(codePtr);
| | | 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 |
#endif
TEBC_DATA_DIG();
#ifdef TCL_COMPILE_DEBUG
if (!pc && (tclTraceExec >= 2)) {
PrintByteCodeInfo(codePtr);
fprintf(stdout, " Starting stack top=%" TCL_T_MODIFIER "d\n", CURR_DEPTH);
fflush(stdout);
}
#endif
if (!pc) {
/* bytecode is starting from scratch */
pc = codePtr->codeStart;
|
| ︙ | ︙ | |||
2120 2121 2122 2123 2124 2125 2126 | } /* * Push the call's object result and continue execution with the next * instruction. */ | | | 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 |
}
/*
* Push the call's object result and continue execution with the next
* instruction.
*/
TRACE_WITH_OBJ(("%" TCL_SIZE_MODIFIER "d => ... after \"%.20s\": TCL_OK, result=",
objc, cmdNameBuf), Tcl_GetObjResult(interp));
/*
* Obtain and reset interp's result to avoid possible duplications of
* objects [Bug 781585]. We do not call Tcl_ResetResult to avoid any
* side effects caused by the resetting of errorInfo and errorCode
* [Bug 804681], which are not needed here. We chose instead to
|
| ︙ | ︙ | |||
2265 2266 2267 2268 2269 2270 2271 |
#ifdef TCL_COMPILE_DEBUG
/*
* Skip the stack depth check if an expansion is in progress.
*/
CHECK_STACK();
if (traceInstructions) {
| | | 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 |
#ifdef TCL_COMPILE_DEBUG
/*
* Skip the stack depth check if an expansion is in progress.
*/
CHECK_STACK();
if (traceInstructions) {
fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d ", iPtr->numLevels, CURR_DEPTH);
TclPrintInstruction(codePtr, pc);
fflush(stdout);
}
#endif /* TCL_COMPILE_DEBUG */
TCL_DTRACE_INST_NEXT();
|
| ︙ | ︙ | |||
2385 2386 2387 2388 2389 2390 2391 |
}
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
if (traceInstructions) {
TRACE_APPEND(("YIELD...\n"));
} else {
| | | 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 |
}
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
if (traceInstructions) {
TRACE_APPEND(("YIELD...\n"));
} else {
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding value \"%.30s\"\n",
iPtr->numLevels, (pc - codePtr->codeStart),
Tcl_GetString(OBJ_AT_TOS));
}
fflush(stdout);
}
#endif
yieldParameter = NULL; /*==CORO_ACTIVATE_YIELD*/
|
| ︙ | ︙ | |||
2428 2429 2430 2431 2432 2433 2434 |
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
if (traceInstructions) {
TRACE(("[%.30s] => YIELD...\n", O2S(valuePtr)));
} else {
/* FIXME: What is the right thing to trace? */
| | | 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 |
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
if (traceInstructions) {
TRACE(("[%.30s] => YIELD...\n", O2S(valuePtr)));
} else {
/* FIXME: What is the right thing to trace? */
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding to [%.30s]\n",
iPtr->numLevels, (pc - codePtr->codeStart),
TclGetString(valuePtr));
}
fflush(stdout);
}
#endif
|
| ︙ | ︙ | |||
2632 2633 2634 2635 2636 2637 2638 | * we do not define a special tclObjType for it. It is not dangerous * as the obj is never passed anywhere, so that all manipulations are * performed here and in INST_INVOKE_EXPANDED (in case of an expansion * error, also in INST_EXPAND_STKTOP). */ TclNewObj(objPtr); | | | | | | 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 |
* we do not define a special tclObjType for it. It is not dangerous
* as the obj is never passed anywhere, so that all manipulations are
* performed here and in INST_INVOKE_EXPANDED (in case of an expansion
* error, also in INST_EXPAND_STKTOP).
*/
TclNewObj(objPtr);
objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(CURR_DEPTH);
objPtr->length = 0;
PUSH_TAUX_OBJ(objPtr);
TRACE(("=> mark depth as %" TCL_T_MODIFIER "d\n", CURR_DEPTH));
NEXT_INST_F(1, 0, 0);
break;
case INST_EXPAND_DROP:
/*
* Drops an element of the auxObjList, popping stack elements to
* restore the stack to the state before the point where the aux
* element was created.
*/
CLANG_ASSERT(auxObjList);
objc = CURR_DEPTH - PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2);
POP_TAUX_OBJ();
#ifdef TCL_COMPILE_DEBUG
/* Ugly abuse! */
starting = 1;
#endif
TRACE(("=> drop %" TCL_SIZE_MODIFIER "d items\n", objc));
NEXT_INST_V(1, objc, 0);
case INST_EXPAND_STKTOP: {
Tcl_Size i;
TEBCdata *newTD;
ptrdiff_t oldCatchTopOff, oldTosPtrOff;
|
| ︙ | ︙ | |||
2754 2755 2756 2757 2758 2759 2760 |
TEBC_YIELD();
/* add TEBCResume for object at top of stack */
return TclNRExecuteByteCode(interp,
TclCompileObj(interp, OBJ_AT_TOS, NULL, 0));
case INST_INVOKE_EXPANDED:
CLANG_ASSERT(auxObjList);
| | | 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 |
TEBC_YIELD();
/* add TEBCResume for object at top of stack */
return TclNRExecuteByteCode(interp,
TclCompileObj(interp, OBJ_AT_TOS, NULL, 0));
case INST_INVOKE_EXPANDED:
CLANG_ASSERT(auxObjList);
objc = CURR_DEPTH - PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2);
POP_TAUX_OBJ();
if (objc) {
pcAdjustment = 1;
goto doInvocation;
}
/*
|
| ︙ | ︙ | |||
2788 2789 2790 2791 2792 2793 2794 |
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
Tcl_Size i;
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
| | | | 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 |
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
Tcl_Size i;
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
TRACE(("%" TCL_SIZE_MODIFIER "d => call ", objc));
} else {
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ", iPtr->numLevels,
(pc - codePtr->codeStart));
}
for (i = 0; i < objc; i++) {
TclPrintObject(stdout, objv[i], 15);
fprintf(stdout, " ");
}
fprintf(stdout, "\n");
|
| ︙ | ︙ | |||
4435 4436 4437 4438 4439 4440 4441 |
miPtr->mPtr->declaringClassPtr == classPtr) {
newDepth = i;
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
} else {
| | | 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 |
miPtr->mPtr->declaringClassPtr == classPtr) {
newDepth = i;
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
} else {
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ",
iPtr->numLevels,
(size_t)(pc - codePtr->codeStart));
}
for (i = 0; i < opnd; i++) {
TclPrintObject(stdout, objv[i], 15);
fprintf(stdout, " ");
}
|
| ︙ | ︙ | |||
4537 4538 4539 4540 4541 4542 4543 |
#ifdef TCL_COMPILE_DEBUG
} else if (tclTraceExec >= 2) {
int i;
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
} else {
| | | | 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 |
#ifdef TCL_COMPILE_DEBUG
} else if (tclTraceExec >= 2) {
int i;
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
} else {
fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_Z_MODIFIER "u) invoking ",
iPtr->numLevels, (pc - codePtr->codeStart));
}
for (i = 0; i < opnd; i++) {
TclPrintObject(stdout, objv[i], 15);
fprintf(stdout, " ");
}
fprintf(stdout, "\n");
fflush(stdout);
|
| ︙ | ︙ | |||
4656 4657 4658 4659 4660 4661 4662 |
case INST_LIST_LENGTH:
TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS)));
if (TclListObjLengthM(interp, OBJ_AT_TOS, &length) != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
}
| | | | 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 |
case INST_LIST_LENGTH:
TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS)));
if (TclListObjLengthM(interp, OBJ_AT_TOS, &length) != TCL_OK) {
TRACE_ERROR(interp);
goto gotError;
}
TclNewIntObj(objResultPtr, length);
TRACE_APPEND(("%" TCL_SIZE_MODIFIER "d\n", length));
NEXT_INST_F(1, 1, 1);
case INST_LIST_INDEX: /* lindex with objc == 3 */
value2Ptr = OBJ_AT_TOS;
valuePtr = OBJ_UNDER_TOS;
TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr)));
if (
|
| ︙ | ︙ | |||
5131 5132 5133 5134 5135 5136 5137 |
}
TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
NEXT_INST_F(1, 1, 0);
}
case INST_LREPLACE4:
{
| | | 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 |
}
TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
NEXT_INST_F(1, 1, 0);
}
case INST_LREPLACE4:
{
TCL_HASH_TYPE numToDelete, numNewElems;
int end_indicator;
int haveSecondIndex, flags;
Tcl_Obj *fromIdxObj, *toIdxObj;
opnd = TclGetInt4AtPtr(pc + 1);
flags = TclGetInt1AtPtr(pc + 5);
/* Stack: ... listobj index1 ?index2? new1 ... newN */
|
| ︙ | ︙ | |||
6670 6671 6672 6673 6674 6675 6676 |
Tcl_IncrRefCount(valuePtr);
}
} else {
DECACHE_STACK_INFO();
if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
CACHE_STACK_INFO();
| | | 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 |
Tcl_IncrRefCount(valuePtr);
}
} else {
DECACHE_STACK_INFO();
if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
CACHE_STACK_INFO();
TRACE_APPEND(("ERROR init. index temp %" TCL_SIZE_MODIFIER "d: %.30s",
varIndex, O2S(Tcl_GetObjResult(interp))));
goto gotError;
}
CACHE_STACK_INFO();
}
valIndex++;
}
|
| ︙ | ︙ | |||
6717 6718 6719 6720 6721 6722 6723 | * - collecting obj (unshared) * The instruction lappends the result to the collecting obj. */ tmpPtr = OBJ_AT_DEPTH(1); infoPtr = (ForeachInfo *)tmpPtr->internalRep.twoPtrValue.ptr1; numLists = infoPtr->numLists; | | | | | | 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 |
* - collecting obj (unshared)
* The instruction lappends the result to the collecting obj.
*/
tmpPtr = OBJ_AT_DEPTH(1);
infoPtr = (ForeachInfo *)tmpPtr->internalRep.twoPtrValue.ptr1;
numLists = infoPtr->numLists;
TRACE_APPEND(("=> appending to list at depth %" TCL_SIZE_MODIFIER "d\n", 3 + numLists));
objPtr = OBJ_AT_DEPTH(3 + numLists);
Tcl_ListObjAppendElement(NULL, objPtr, OBJ_AT_TOS);
NEXT_INST_F(1, 1, 0);
}
break;
case INST_BEGIN_CATCH4:
/*
* Record start of the catch command with exception range index equal
* to the operand. Push the current stack depth onto the special catch
* stack.
*/
*(++catchTop) = (Tcl_Obj *)INT2PTR(CURR_DEPTH);
TRACE(("%u => catchTop=%" TCL_T_MODIFIER "d, stackTop=%" TCL_T_MODIFIER "d\n",
TclGetUInt4AtPtr(pc+1), (catchTop - initCatchTop - 1),
CURR_DEPTH));
NEXT_INST_F(5, 0, 0);
break;
case INST_END_CATCH:
catchTop--;
DECACHE_STACK_INFO();
|
| ︙ | ︙ | |||
7545 7546 7547 7548 7549 7550 7551 |
while (cleanup--) {
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
}
if (result == TCL_BREAK) {
result = TCL_OK;
pc = (codePtr->codeStart + rangePtr->breakOffset);
| | | | 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 |
while (cleanup--) {
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
}
if (result == TCL_BREAK) {
result = TCL_OK;
pc = (codePtr->codeStart + rangePtr->breakOffset);
TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
StringForResultCode(result),
rangePtr->codeOffset, rangePtr->breakOffset));
NEXT_INST_F(0, 0, 0);
}
if (rangePtr->continueOffset == TCL_INDEX_NONE) {
TRACE_APPEND(("%s, loop w/o continue, checking for catch\n",
StringForResultCode(result)));
goto checkForCatch;
}
result = TCL_OK;
pc = (codePtr->codeStart + rangePtr->continueOffset);
TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
StringForResultCode(result),
rangePtr->codeOffset, rangePtr->continueOffset));
NEXT_INST_F(0, 0, 0);
}
#ifdef TCL_COMPILE_DEBUG
if (traceInstructions) {
objPtr = Tcl_GetObjResult(interp);
|
| ︙ | ︙ | |||
7647 7648 7649 7650 7651 7652 7653 |
/*
* Clear all expansions that may have started after the last
* INST_BEGIN_CATCH.
*/
while (auxObjList) {
if ((catchTop != initCatchTop)
| | | | 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 |
/*
* Clear all expansions that may have started after the last
* INST_BEGIN_CATCH.
*/
while (auxObjList) {
if ((catchTop != initCatchTop)
&& (PTR2INT(*catchTop) >
PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2))) {
break;
}
POP_TAUX_OBJ();
}
/*
* We must not catch if the script in progress has been canceled with
|
| ︙ | ︙ | |||
7723 7724 7725 7726 7727 7728 7729 |
* "exception". It was found either by checkForCatch just above or by
* an instruction during break, continue, or error processing. Jump to
* its catchOffset after unwinding the operand stack to the depth it
* had when starting to execute the range's catch command.
*/
processCatch:
| | | | | | | 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 |
* "exception". It was found either by checkForCatch just above or by
* an instruction during break, continue, or error processing. Jump to
* its catchOffset after unwinding the operand stack to the depth it
* had when starting to execute the range's catch command.
*/
processCatch:
while (CURR_DEPTH > PTR2INT(*catchTop)) {
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
}
#ifdef TCL_COMPILE_DEBUG
if (traceInstructions) {
fprintf(stdout, " ... found catch at %" TCL_SIZE_MODIFIER "d, catchTop=%" TCL_T_MODIFIER "d, "
"unwound to %" TCL_T_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
rangePtr->codeOffset, (catchTop - initCatchTop - 1),
PTR2INT(*catchTop), rangePtr->catchOffset);
}
#endif
pc = (codePtr->codeStart + rangePtr->catchOffset);
NEXT_INST_F(0, 0, 0); /* Restart the execution loop at pc. */
/*
* end of infinite loop dispatching on instructions.
|
| ︙ | ︙ | |||
7768 7769 7770 7771 7772 7773 7774 |
while (tosPtr > initTosPtr) {
objPtr = POP_OBJECT();
Tcl_DecrRefCount(objPtr);
}
if (tosPtr < initTosPtr) {
fprintf(stderr,
| | | | | 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 |
while (tosPtr > initTosPtr) {
objPtr = POP_OBJECT();
Tcl_DecrRefCount(objPtr);
}
if (tosPtr < initTosPtr) {
fprintf(stderr,
"\nTclNRExecuteByteCode: abnormal return at pc %" TCL_T_MODIFIER "d: "
"stack top %" TCL_T_MODIFIER "d < entry stack top %d\n",
(pc - codePtr->codeStart),
CURR_DEPTH, 0);
Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top");
}
CLANG_ASSERT(bcFramePtr);
}
iPtr->cmdFramePtr = bcFramePtr->nextPtr;
|
| ︙ | ︙ | |||
9296 9297 9298 9299 9300 9301 9302 |
Tcl_Size codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
int bestDist = INT_MAX; /* Distance of pc to best cmd's start pc. */
int bestSrcOffset = -1; /* Initialized to avoid compiler warning. */
int bestSrcLength = -1; /* Initialized to avoid compiler warning. */
int bestCmdIdx = -1;
/* The pc must point within the bytecode */
| | | 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 |
Tcl_Size codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
int bestDist = INT_MAX; /* Distance of pc to best cmd's start pc. */
int bestSrcOffset = -1; /* Initialized to avoid compiler warning. */
int bestSrcLength = -1; /* Initialized to avoid compiler warning. */
int bestCmdIdx = -1;
/* The pc must point within the bytecode */
assert ((pcOffset >= 0) && (pcOffset < codePtr->numCodeBytes));
/*
* Decode the code and source offset and length for each command. The
* closest enclosing command is the last one whose code started before
* pcOffset.
*/
|
| ︙ | ︙ | |||
9784 9785 9786 9787 9788 9789 9790 |
Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps)\t%" TCL_Z_MODIFIER "u\n",
tclObjsAlloced);
Tcl_AppendPrintfToObj(objPtr, "Current objects\t\t\t%" TCL_Z_MODIFIER "u\n",
(tclObjsAlloced - tclObjsFreed));
Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%" TCL_Z_MODIFIER "u\n",
statsPtr->numLiteralsCreated);
| | | 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798 |
Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps)\t%" TCL_Z_MODIFIER "u\n",
tclObjsAlloced);
Tcl_AppendPrintfToObj(objPtr, "Current objects\t\t\t%" TCL_Z_MODIFIER "u\n",
(tclObjsAlloced - tclObjsFreed));
Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%" TCL_Z_MODIFIER "u\n",
statsPtr->numLiteralsCreated);
Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%" TCL_SIZE_MODIFIER "d (%0.1f%% of current objects)\n",
globalTablePtr->numEntries,
Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed));
Tcl_AppendPrintfToObj(objPtr, " ByteCode literals\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current literals)\n",
numByteCodeLits,
Percent(numByteCodeLits, globalTablePtr->numEntries));
Tcl_AppendPrintfToObj(objPtr, " Literals reused > 1x\t\t%" TCL_Z_MODIFIER "u\n",
numSharedMultX);
|
| ︙ | ︙ | |||
9876 9877 9878 9879 9880 9881 9882 |
break;
}
}
sum = 0;
for (i = 0; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->literalCount[i];
| | | 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 |
break;
}
}
sum = 0;
for (i = 0; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->literalCount[i];
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
decadeHigh, Percent(sum, statsPtr->numLiteralsCreated));
}
litTableStats = TclLiteralStats(globalTablePtr);
Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal table statistics:\n%s\n",
litTableStats);
Tcl_Free(litTableStats);
|
| ︙ | ︙ | |||
9909 9910 9911 9912 9913 9914 9915 |
}
}
maxSizeDecade = i;
sum = 0;
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->srcCount[i];
| | | 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 |
}
}
maxSizeDecade = i;
sum = 0;
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->srcCount[i];
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
decadeHigh, Percent(sum, statsPtr->numCompilations));
}
Tcl_AppendPrintfToObj(objPtr, "\nByteCode sizes:\n");
Tcl_AppendPrintfToObj(objPtr, "\t Up to size\t\tPercentage\n");
minSizeDecade = maxSizeDecade = 0;
for (i = 0; i < 31; i++) {
|
| ︙ | ︙ | |||
9933 9934 9935 9936 9937 9938 9939 |
}
}
maxSizeDecade = i;
sum = 0;
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->byteCodeCount[i];
| | | 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 |
}
}
maxSizeDecade = i;
sum = 0;
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->byteCodeCount[i];
Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
decadeHigh, Percent(sum, statsPtr->numCompilations));
}
Tcl_AppendPrintfToObj(objPtr, "\nByteCode longevity (excludes Current ByteCodes):\n");
Tcl_AppendPrintfToObj(objPtr, "\t Up to ms\t\tPercentage\n");
minSizeDecade = maxSizeDecade = 0;
for (i = 0; i < 31; i++) {
|
| ︙ | ︙ |
Changes to generic/tclIO.c.
| ︙ | ︙ | |||
655 656 657 658 659 660 661 | * Decrement the refcount which was earlier artificially * bumped up to keep the channel from being closed. */ statePtr->refCount--; } | | | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
* Decrement the refcount which was earlier artificially
* bumped up to keep the channel from being closed.
*/
statePtr->refCount--;
}
if (statePtr->refCount <= 0) {
/*
* Close it only if the refcount indicates that the channel is
* not referenced from any interpreter. If it is, that
* interpreter will close the channel when it gets destroyed.
*/
(void) Tcl_CloseEx(NULL, (Tcl_Channel) chanPtr, 0);
|
| ︙ | ︙ | |||
1074 1075 1076 1077 1078 1079 1080 |
{
ChannelState *statePtr = ((Channel *) chan)->state;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->stdinInitialized == 1
&& tsdPtr->stdinChannel != NULL
&& statePtr == ((Channel *)tsdPtr->stdinChannel)->state) {
| | | | | 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 |
{
ChannelState *statePtr = ((Channel *) chan)->state;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->stdinInitialized == 1
&& tsdPtr->stdinChannel != NULL
&& statePtr == ((Channel *)tsdPtr->stdinChannel)->state) {
if (statePtr->refCount < 2) {
statePtr->refCount = 0;
tsdPtr->stdinChannel = NULL;
return;
}
} else if (tsdPtr->stdoutInitialized == 1
&& tsdPtr->stdoutChannel != NULL
&& statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) {
if (statePtr->refCount < 2) {
statePtr->refCount = 0;
tsdPtr->stdoutChannel = NULL;
return;
}
} else if (tsdPtr->stderrInitialized == 1
&& tsdPtr->stderrChannel != NULL
&& statePtr == ((Channel *)tsdPtr->stderrChannel)->state) {
if (statePtr->refCount < 2) {
statePtr->refCount = 0;
tsdPtr->stderrChannel = NULL;
return;
}
}
}
|
| ︙ | ︙ | |||
1252 1253 1254 1255 1256 1257 1258 |
CheckForStdChannelsBeingClosed(chan);
/*
* If the refCount reached zero, close the actual channel.
*/
| | | 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 |
CheckForStdChannelsBeingClosed(chan);
/*
* If the refCount reached zero, close the actual channel.
*/
if (statePtr->refCount <= 0) {
Tcl_Preserve(statePtr);
if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
/*
* We don't want to re-enter Tcl_CloseEx().
*/
if (!GotFlag(statePtr, CHANNEL_CLOSED)) {
|
| ︙ | ︙ | |||
2004 2005 2006 2007 2008 2009 2010 |
}
}
static void
ChannelFree(
Channel *chanPtr)
{
| | | 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 |
}
}
static void
ChannelFree(
Channel *chanPtr)
{
if (chanPtr->refCount == 0) {
Tcl_Free(chanPtr);
return;
}
chanPtr->typePtr = NULL;
}
/*
|
| ︙ | ︙ | |||
2179 2180 2181 2182 2183 2184 2185 |
}
} else {
/*
* This channel does not cover another one. Simply do a close, if
* necessary.
*/
| | | 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 |
}
} else {
/*
* This channel does not cover another one. Simply do a close, if
* necessary.
*/
if (statePtr->refCount <= 0) {
if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) {
/*
* TIP #219, Tcl Channel Reflection API.
* "TclChanCaughtErrorBypass" is not required here, it was
* done already by "Tcl_Close".
*/
|
| ︙ | ︙ | |||
2547 2548 2549 2550 2551 2552 2553 |
Tcl_Free(bufPtr);
}
static int
IsShared(
ChannelBuffer *bufPtr)
{
| | | 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 |
Tcl_Free(bufPtr);
}
static int
IsShared(
ChannelBuffer *bufPtr)
{
return bufPtr->refCount > 1;
}
/*
*----------------------------------------------------------------------
*
* RecycleBuffer --
*
|
| ︙ | ︙ | |||
2996 2997 2998 2999 3000 3001 3002 |
/*
* If the channel is flagged as closed, delete it when the refCount drops
* to zero, the output queue is empty and there is no output in the
* current output buffer.
*/
| | | 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 |
/*
* If the channel is flagged as closed, delete it when the refCount drops
* to zero, the output queue is empty and there is no output in the
* current output buffer.
*/
if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount <= 0) &&
(statePtr->outQueueHead == NULL) &&
((statePtr->curOutPtr == NULL) ||
IsBufferEmpty(statePtr->curOutPtr))) {
errorCode = CloseChannel(interp, chanPtr, errorCode);
goto done;
}
|
| ︙ | ︙ | |||
3457 3458 3459 3460 3461 3462 3463 |
* This operation should occur at the top of a channel stack.
*/
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
chanPtr = statePtr->topChanPtr;
| | | 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 |
* This operation should occur at the top of a channel stack.
*/
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
chanPtr = statePtr->topChanPtr;
if (statePtr->refCount > 0) {
Tcl_Panic("called Tcl_Close on channel with refCount > 0");
}
if (GotFlag(statePtr, CHANNEL_INCLOSE)) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"illegal recursive call to close through close-handler"
|
| ︙ | ︙ | |||
4192 4193 4194 4195 4196 4197 4198 |
*/
if ((len == 1) && (UCHAR(*src) < 0xC0)) {
return WriteBytes(chanPtr, src, len);
}
objPtr = Tcl_NewStringObj(src, len);
| < | 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 |
*/
if ((len == 1) && (UCHAR(*src) < 0xC0)) {
return WriteBytes(chanPtr, src, len);
}
objPtr = Tcl_NewStringObj(src, len);
src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len);
if (src == NULL) {
Tcl_SetErrno(EILSEQ);
result = TCL_INDEX_NONE;
} else {
result = WriteBytes(chanPtr, src, len);
}
|
| ︙ | ︙ | |||
4366 4367 4368 4369 4370 4371 4372 |
|| (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
nextNewLine = (char *)memchr(src, '\n', srcLen);
}
while (srcLen + saved + endEncoding > 0 && !encodingError) {
ChannelBuffer *bufPtr;
char *dst;
| | | | 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 |
|| (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
nextNewLine = (char *)memchr(src, '\n', srcLen);
}
while (srcLen + saved + endEncoding > 0 && !encodingError) {
ChannelBuffer *bufPtr;
char *dst;
int result, srcRead, dstLen, dstWrote;
Tcl_Size srcLimit = srcLen;
if (nextNewLine) {
srcLimit = nextNewLine - src;
}
/* Get space to write into */
bufPtr = statePtr->curOutPtr;
|
| ︙ | ︙ | |||
4557 4558 4559 4560 4561 4562 4563 |
* for managing the storage. */
{
Tcl_Obj *objPtr;
Tcl_Size charsStored;
TclNewObj(objPtr);
charsStored = Tcl_GetsObj(chan, objPtr);
| | | 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 |
* for managing the storage. */
{
Tcl_Obj *objPtr;
Tcl_Size charsStored;
TclNewObj(objPtr);
charsStored = Tcl_GetsObj(chan, objPtr);
if (charsStored > 0) {
TclDStringAppendObj(lineRead, objPtr);
}
TclDecrRefCount(objPtr);
return charsStored;
}
/*
|
| ︙ | ︙ | |||
5999 6000 6001 6002 6003 6004 6005 |
*/
if (GotFlag(statePtr, CHANNEL_EOF)) {
statePtr->inputEncodingFlags |= TCL_ENCODING_START;
}
ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF);
statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
| | | 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 |
*/
if (GotFlag(statePtr, CHANNEL_EOF)) {
statePtr->inputEncodingFlags |= TCL_ENCODING_START;
}
ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF);
statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
for (copied = 0; toRead != 0 ; ) {
int copiedNow = -1;
if (statePtr->inQueueHead != NULL) {
if (binaryMode) {
copiedNow = ReadBytes(statePtr, objPtr, toRead);
} else {
copiedNow = ReadChars(statePtr, objPtr, toRead, &factor);
}
|
| ︙ | ︙ | |||
8220 8221 8222 8223 8224 8225 8226 |
if (GotFlag(statePtr, TCL_READABLE)) {
statePtr->inEofChar = newValue[0];
}
} else {
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"bad value for -eofchar: must be non-NUL ASCII"
| | | 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 |
if (GotFlag(statePtr, TCL_READABLE)) {
statePtr->inEofChar = newValue[0];
}
} else {
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"bad value for -eofchar: must be non-NUL ASCII"
" character", TCL_INDEX_NONE));
}
Tcl_Free((void *)argv);
return TCL_ERROR;
}
if (argv != NULL) {
Tcl_Free((void *)argv);
}
|
| ︙ | ︙ | |||
10645 10646 10647 10648 10649 10650 10651 |
int
Tcl_IsChannelShared(
Tcl_Channel chan) /* The channel to query */
{
ChannelState *statePtr = ((Channel *) chan)->state;
/* State of real channel structure. */
| | | 10644 10645 10646 10647 10648 10649 10650 10651 10652 10653 10654 10655 10656 10657 10658 |
int
Tcl_IsChannelShared(
Tcl_Channel chan) /* The channel to query */
{
ChannelState *statePtr = ((Channel *) chan)->state;
/* State of real channel structure. */
return ((statePtr->refCount > 1) ? 1 : 0);
}
/*
*----------------------------------------------------------------------
*
* Tcl_IsChannelExisting --
*
|
| ︙ | ︙ |
Changes to generic/tclIOCmd.c.
| ︙ | ︙ | |||
1796 1797 1798 1799 1800 1801 1802 |
ChanPendingObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
| < > | 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 |
ChanPendingObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
static const char *const options[] = {"input", "output", NULL};
enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT} index;
int mode;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "mode channelId");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], options, "mode", 0,
|
| ︙ | ︙ |
Changes to generic/tclInt.decls.
| ︙ | ︙ | |||
533 534 535 536 537 538 539 |
declare 213 {
Tcl_Obj *TclGetObjNameOfExecutable(void)
}
declare 214 {
void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding)
}
declare 215 {
| | | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 |
declare 213 {
Tcl_Obj *TclGetObjNameOfExecutable(void)
}
declare 214 {
void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding)
}
declare 215 {
void *TclStackAlloc(Tcl_Interp *interp, TCL_HASH_TYPE numBytes)
}
declare 216 {
void TclStackFree(Tcl_Interp *interp, void *freePtr)
}
declare 217 {
int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr,
Tcl_Namespace *namespacePtr, int isProcCallFrame)
|
| ︙ | ︙ |
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
104 105 106 107 108 109 110 | # ifdef LITTLE_ENDIAN # if BYTE_ORDER == LITTLE_ENDIAN # undef WORDS_BIGENDIAN # endif # endif #endif | < < < < < < | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | # ifdef LITTLE_ENDIAN # if BYTE_ORDER == LITTLE_ENDIAN # undef WORDS_BIGENDIAN # endif # endif #endif /* * Macros used to cast between pointers and integers (e.g. when storing an int * in ClientData), on 64-bit architectures they avoid gcc warning about "cast * to/from pointer from/to integer of different size". */ #if !defined(INT2PTR) |
| ︙ | ︙ | |||
3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 |
#define ENCODING_PROFILE_MASK 0xFF000000
#define ENCODING_PROFILE_GET(flags_) ((flags_) & ENCODING_PROFILE_MASK)
#define ENCODING_PROFILE_SET(flags_, profile_) \
do { \
(flags_) &= ~ENCODING_PROFILE_MASK; \
(flags_) |= profile_; \
} while (0)
/*
*----------------------------------------------------------------
* Variables shared among Tcl modules but not used by the outside world.
*----------------------------------------------------------------
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 |
#define ENCODING_PROFILE_MASK 0xFF000000
#define ENCODING_PROFILE_GET(flags_) ((flags_) & ENCODING_PROFILE_MASK)
#define ENCODING_PROFILE_SET(flags_, profile_) \
do { \
(flags_) &= ~ENCODING_PROFILE_MASK; \
(flags_) |= profile_; \
} while (0)
/*
*----------------------------------------------------------------------
* Common functions for calculating overallocation. Trivial but allows for
* experimenting with growth factors without having to change code in
* multiple places. See TclAttemptAllocElemsEx and similar for usage
* examples. Best to use those functions. Direct use of TclUpsizeAlloc /
* TclResizeAlloc is needed in special cases such as when total size of
* memory block is limited to less than TCL_SIZE_MAX.
*
*----------------------------------------------------------------------
*/
static inline Tcl_Size
TclUpsizeAlloc(TCL_UNUSED(Tcl_Size) /* oldSize. For future experiments with
* some growth algorithms that use this
* information. */,
Tcl_Size needed,
Tcl_Size limit)
{
/* assert (oldCapacity < needed <= limit) */
if (needed < (limit - needed/2)) {
return needed + needed / 2;
}
else {
return limit;
}
}
static inline Tcl_Size TclUpsizeRetry(Tcl_Size needed, Tcl_Size lastAttempt) {
/* assert (needed < lastAttempt) */
if (needed < lastAttempt - 1) {
/* (needed+lastAttempt)/2 but that formula may overflow Tcl_Size */
return needed + (lastAttempt - needed) / 2;
} else {
return needed;
}
}
MODULE_SCOPE void *TclAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize,
Tcl_Size leadSize, Tcl_Size *capacityPtr);
MODULE_SCOPE void *TclReallocElemsEx(void *oldPtr, Tcl_Size elemCount,
Tcl_Size elemSize, Tcl_Size leadSize,
Tcl_Size *capacityPtr);
MODULE_SCOPE void *TclAttemptReallocElemsEx(void *oldPtr,
Tcl_Size elemCount, Tcl_Size elemSize,
Tcl_Size leadSize, Tcl_Size *capacityPtr);
/* Alloc elemCount elements of size elemSize with leadSize header
* returning actual capacity (in elements) in *capacityPtr. */
static inline void *TclAttemptAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize,
Tcl_Size leadSize, Tcl_Size *capacityPtr) {
return TclAttemptReallocElemsEx(
NULL, elemCount, elemSize, leadSize, capacityPtr);
}
/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *TclAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr) {
return TclAllocElemsEx(numBytes, 1, 0, capacityPtr);
}
/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *
TclAttemptAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr)
{
return TclAttemptAllocElemsEx(numBytes, 1, 0, capacityPtr);
}
/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *TclReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) {
return TclReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
}
/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *TclAttemptReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) {
return TclAttemptReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
}
/*
*----------------------------------------------------------------
* Variables shared among Tcl modules but not used by the outside world.
*----------------------------------------------------------------
*/
|
| ︙ | ︙ | |||
3488 3489 3490 3491 3492 3493 3494 | #endif MODULE_SCOPE int TclCreateSocketAddress(Tcl_Interp *interp, struct addrinfo **addrlist, const char *host, int port, int willBind, const char **errorMsgPtr); MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, | | | 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 | #endif MODULE_SCOPE int TclCreateSocketAddress(Tcl_Interp *interp, struct addrinfo **addrlist, const char *host, int port, int willBind, const char **errorMsgPtr); MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); MODULE_SCOPE Tcl_Size TclpFindVariable(const char *name, Tcl_Size *lengthPtr); MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr, TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); MODULE_SCOPE void *TclpInitNotifier(void); MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); |
| ︙ | ︙ | |||
3558 3559 3560 3561 3562 3563 3564 | MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue, Tcl_Encoding encoding); MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result); MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp, Tcl_Obj *const *objv, Tcl_Size objc, Tcl_Size subIdx, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, | | | 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 | MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue, Tcl_Encoding encoding); MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result); MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp, Tcl_Obj *const *objv, Tcl_Size objc, Tcl_Size subIdx, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, TCL_HASH_TYPE numBytes); typedef int (*memCmpFn_t)(const void*, const void*, size_t); MODULE_SCOPE int TclStringCmp(Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, int checkEq, int nocase, Tcl_Size reqlength); MODULE_SCOPE int TclStringCmpOpts(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int *nocase, Tcl_Size *reqlength); MODULE_SCOPE int TclStringIndexInterface(Tcl_Interp *interp, Tcl_Obj *objPtr, |
| ︙ | ︙ | |||
4638 4639 4640 4641 4642 4643 4644 |
Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------
| | | > > > > > > | < > > > > > > > > > > | 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 |
Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------
* Macros used by the Tcl core to set a Tcl_Obj's string representation to a
* copy of the "len" bytes starting at "bytePtr". The value of "len" must
* not be negative. When "len" is 0, then it is acceptable to pass
* "bytePtr" = NULL. When "len" > 0, "bytePtr" must not be NULL, and it
* must point to a location from which "len" bytes may be read. These
* constraints are not checked here. The validity of the bytes copied
* as a value string representation is also not verififed. This macro
* must not be called while "objPtr" is being freed or when "objPtr"
* already has a string representation. The caller must use
* this macro properly. Improper use can lead to dangerous results.
* Because "len" is referenced multiple times, take care that it is an
* expression with the same value each use.
*
* The ANSI C "prototypes" for these macros are:
*
* MODULE_SCOPE void TclInitEmptyStringRep(Tcl_Obj *objPtr);
* MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
* MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
*
*----------------------------------------------------------------
*/
#define TclInitEmptyStringRep(objPtr) \
((objPtr)->length = (((objPtr)->bytes = &tclEmptyString), 0))
#define TclInitStringRep(objPtr, bytePtr, len) \
if ((len) == 0) { \
TclInitEmptyStringRep(objPtr); \
} else { \
(objPtr)->bytes = (char *)Tcl_Alloc((len) + 1U); \
memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)); \
(objPtr)->bytes[len] = '\0'; \
(objPtr)->length = (len); \
}
#define TclAttemptInitStringRep(objPtr, bytePtr, len) \
((((len) == 0) ? ( \
TclInitEmptyStringRep(objPtr) \
) : ( \
(objPtr)->bytes = (char *)Tcl_AttemptAlloc((len) + 1U), \
(objPtr)->length = ((objPtr)->bytes) ? \
(memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)), \
(objPtr)->bytes[len] = '\0', (len)) : (-1) \
)), (objPtr)->bytes)
/*
*----------------------------------------------------------------
* Macro used by the Tcl core to get the string representation's byte array
* pointer from a Tcl_Obj. This is an inline version of Tcl_GetString(). The
* macro's expression result is the string rep's byte pointer which might be
* NULL. The bytes referenced by this pointer must not be modified by the
|
| ︙ | ︙ |
Changes to generic/tclIntDecls.h.
| ︙ | ︙ | |||
447 448 449 450 451 452 453 | EXTERN void TclpFindExecutable(const char *argv0); /* 213 */ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void); /* 214 */ EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding); /* 215 */ | | > | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 | EXTERN void TclpFindExecutable(const char *argv0); /* 213 */ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void); /* 214 */ EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding); /* 215 */ EXTERN void * TclStackAlloc(Tcl_Interp *interp, TCL_HASH_TYPE numBytes); /* 216 */ EXTERN void TclStackFree(Tcl_Interp *interp, void *freePtr); /* 217 */ EXTERN int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); |
| ︙ | ︙ | |||
799 800 801 802 803 804 805 |
Tcl_Channel (*tclpOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* 208 */
void (*reserved209)(void);
void (*reserved210)(void);
void (*reserved211)(void);
void (*tclpFindExecutable) (const char *argv0); /* 212 */
Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */
void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */
| | | 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 |
Tcl_Channel (*tclpOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* 208 */
void (*reserved209)(void);
void (*reserved210)(void);
void (*reserved211)(void);
void (*tclpFindExecutable) (const char *argv0); /* 212 */
Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */
void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */
void * (*tclStackAlloc) (Tcl_Interp *interp, TCL_HASH_TYPE numBytes); /* 215 */
void (*tclStackFree) (Tcl_Interp *interp, void *freePtr); /* 216 */
int (*tclPushStackFrame) (Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 217 */
void (*tclPopStackFrame) (Tcl_Interp *interp); /* 218 */
void (*reserved219)(void);
void (*reserved220)(void);
void (*reserved221)(void);
void (*reserved222)(void);
|
| ︙ | ︙ |
Changes to generic/tclListObj.c.
| ︙ | ︙ | |||
381 382 383 384 385 386 387 |
return 1;
}
/*
*------------------------------------------------------------------------
*
| < < < < < < < < < < < < < < < < < < < < < < < < | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
return 1;
}
/*
*------------------------------------------------------------------------
*
* ListRepFreeUnreferenced --
*
* Inline wrapper for ListRepUnsharedFreeUnreferenced that does quick checks
* before calling it.
*
* IMPORTANT: this function must not be called on an internal
* representation of a Tcl_Obj that is itself shared.
|
| ︙ | ︙ | |||
822 823 824 825 826 827 828 829 830 |
if (objc > LIST_MAX) {
if (flags & LISTREP_PANIC_ON_FAIL) {
Tcl_Panic("max length of a Tcl list exceeded");
}
return NULL;
}
if (flags & LISTREP_SPACE_FLAGS) {
/* Caller requests extra space front, back or both */
| > | > < < | < < < | | > | | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
if (objc > LIST_MAX) {
if (flags & LISTREP_PANIC_ON_FAIL) {
Tcl_Panic("max length of a Tcl list exceeded");
}
return NULL;
}
storePtr = NULL;
if (flags & LISTREP_SPACE_FLAGS) {
/* Caller requests extra space front, back or both */
storePtr = (ListStore *)TclAttemptAllocElemsEx(
objc, sizeof(Tcl_Obj *), offsetof(ListStore, slots), &capacity);
} else {
/* Exact allocation */
capacity = objc;
storePtr = (ListStore *)Tcl_AttemptAlloc(LIST_SIZE(capacity));
}
if (storePtr == NULL) {
if (flags & LISTREP_PANIC_ON_FAIL) {
Tcl_Panic("list creation failed: unable to alloc %" TCL_Z_MODIFIER
"u bytes",
LIST_SIZE(objc));
}
return NULL;
}
storePtr->refCount = 0;
storePtr->flags = 0;
storePtr->numAllocated = capacity;
|
| ︙ | ︙ | |||
897 898 899 900 901 902 903 | * The memory pointed to by storePtr is freed if it a new block has to * be returned. * * *------------------------------------------------------------------------ */ ListStore * | | | < < < < | < < < < < < < | < | < | > | | < < < > | > | | | 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 |
* The memory pointed to by storePtr is freed if it a new block has to
* be returned.
*
*
*------------------------------------------------------------------------
*/
ListStore *
ListStoreReallocate (ListStore *storePtr, Tcl_Size needed)
{
Tcl_Size capacity;
if (needed > LIST_MAX) {
return NULL;
}
storePtr = (ListStore *)TclAttemptReallocElemsEx(storePtr,
needed,
sizeof(Tcl_Obj *),
offsetof(ListStore, slots),
&capacity);
/* Only the capacity has changed, fix it in the header */
if (storePtr) {
storePtr->numAllocated = capacity;
}
return storePtr;
}
/*
*----------------------------------------------------------------------
*
* ListRepInit --
*
* Initializes a ListRep to hold a list internal representation
* with space for objc elements.
|
| ︙ | ︙ |
Changes to generic/tclOOCall.c.
| ︙ | ︙ | |||
2251 2252 2253 2254 2255 2256 2257 |
/*
* Gather the information. Unsorted! (Caller will sort.)
*/
*allocated = 1;
Tcl_InitObjHashTable(&hashTable);
FindClassProps(clsPtr, writable, &hashTable);
| | | 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 |
/*
* Gather the information. Unsorted! (Caller will sort.)
*/
*allocated = 1;
Tcl_InitObjHashTable(&hashTable);
FindClassProps(clsPtr, writable, &hashTable);
TclNewObj(result);
FOREACH_HASH(propName, dummy, &hashTable) {
Tcl_ListObjAppendElement(NULL, result, propName);
}
Tcl_DeleteHashTable(&hashTable);
/*
* Cache the information. Also purges the cache.
|
| ︙ | ︙ | |||
2333 2334 2335 2336 2337 2338 2339 |
/*
* Gather the information. Unsorted! (Caller will sort.)
*/
*allocated = 1;
Tcl_InitObjHashTable(&hashTable);
FindObjectProps(oPtr, writable, &hashTable);
| | | 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 |
/*
* Gather the information. Unsorted! (Caller will sort.)
*/
*allocated = 1;
Tcl_InitObjHashTable(&hashTable);
FindObjectProps(oPtr, writable, &hashTable);
TclNewObj(result);
FOREACH_HASH(propName, dummy, &hashTable) {
Tcl_ListObjAppendElement(NULL, result, propName);
}
Tcl_DeleteHashTable(&hashTable);
/*
* Cache the information.
|
| ︙ | ︙ |
Changes to generic/tclOODefineCmds.c.
| ︙ | ︙ | |||
3225 3226 3227 3228 3229 3230 3231 |
} else if (!oPtr->classPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
| | | 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 |
} else if (!oPtr->classPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
TclNewObj(resultObj);
FOREACH(propNameObj, oPtr->classPtr->properties.readable) {
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
|
| ︙ | ︙ | |||
3290 3291 3292 3293 3294 3295 3296 |
NULL);
return TCL_ERROR;
}
if (oPtr == NULL) {
return TCL_ERROR;
}
| | | 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 |
NULL);
return TCL_ERROR;
}
if (oPtr == NULL) {
return TCL_ERROR;
}
TclNewObj(resultObj);
FOREACH(propNameObj, oPtr->properties.readable) {
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
|
| ︙ | ︙ | |||
3422 3423 3424 3425 3426 3427 3428 |
} else if (!oPtr->classPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
| | | 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 |
} else if (!oPtr->classPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
TclNewObj(resultObj);
FOREACH(propNameObj, oPtr->classPtr->properties.writable) {
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
|
| ︙ | ︙ | |||
3487 3488 3489 3490 3491 3492 3493 |
NULL);
return TCL_ERROR;
}
if (oPtr == NULL) {
return TCL_ERROR;
}
| | | 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 |
NULL);
return TCL_ERROR;
}
if (oPtr == NULL) {
return TCL_ERROR;
}
TclNewObj(resultObj);
FOREACH(propNameObj, oPtr->properties.writable) {
Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
|
| ︙ | ︙ |
Changes to generic/tclOOInfo.c.
| ︙ | ︙ | |||
1783 1784 1785 1786 1787 1788 1789 |
if (all) {
result = TclOOGetAllClassProperties(clsPtr, writable, &allocated);
if (allocated) {
SortPropList(result);
}
} else {
| | | 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 |
if (all) {
result = TclOOGetAllClassProperties(clsPtr, writable, &allocated);
if (allocated) {
SortPropList(result);
}
} else {
TclNewObj(result);
if (writable) {
FOREACH(propObj, clsPtr->properties.writable) {
Tcl_ListObjAppendElement(NULL, result, propObj);
}
} else {
FOREACH(propObj, clsPtr->properties.readable) {
Tcl_ListObjAppendElement(NULL, result, propObj);
|
| ︙ | ︙ | |||
1846 1847 1848 1849 1850 1851 1852 |
if (all) {
result = TclOOGetAllObjectProperties(oPtr, writable, &allocated);
if (allocated) {
SortPropList(result);
}
} else {
| | | 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 |
if (all) {
result = TclOOGetAllObjectProperties(oPtr, writable, &allocated);
if (allocated) {
SortPropList(result);
}
} else {
TclNewObj(result);
if (writable) {
FOREACH(propObj, oPtr->properties.writable) {
Tcl_ListObjAppendElement(NULL, result, propObj);
}
} else {
FOREACH(propObj, oPtr->properties.readable) {
Tcl_ListObjAppendElement(NULL, result, propObj);
|
| ︙ | ︙ |
Changes to generic/tclOOScript.h.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | #ifndef TCL_OO_SCRIPT_H #define TCL_OO_SCRIPT_H /* * The scripted part of the definitions of TclOO. * | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#ifndef TCL_OO_SCRIPT_H
#define TCL_OO_SCRIPT_H
/*
* The scripted part of the definitions of TclOO.
*
* Compiled from tools/tclOOScript.tcl by tools/makeHeader.tcl, which
* contains the commented version of everything; *this* file is automatically
* generated.
*/
static const char *tclOOSetupScript =
/* !BEGIN!: Do not edit below this line. */
"::namespace eval ::oo {\n"
|
| ︙ | ︙ |
Changes to generic/tclObj.c.
| ︙ | ︙ | |||
1055 1056 1057 1058 1059 1060 1061 |
Tcl_HashEntry *hPtr;
Tcl_HashTable *tablePtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
tablePtr = tsdPtr->objThreadMap;
if (tablePtr != NULL) {
| | | 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 |
Tcl_HashEntry *hPtr;
Tcl_HashTable *tablePtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
tablePtr = tsdPtr->objThreadMap;
if (tablePtr != NULL) {
fprintf(outFile, "total objects: %" TCL_SIZE_MODIFIER "d\n", tablePtr->numEntries);
for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);
if (objData != NULL) {
fprintf(outFile,
"key = 0x%p, objPtr = 0x%p, file = %s, line = %d\n",
|
| ︙ | ︙ | |||
1109 1110 1111 1112 1113 1114 1115 |
const char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
objPtr->refCount = 0;
objPtr->typePtr = NULL;
| | | 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 |
const char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
objPtr->refCount = 0;
objPtr->typePtr = NULL;
TclInitEmptyStringRep(objPtr);
#if TCL_THREADS
/*
* Add entry to a thread local map used to check if a Tcl_Obj was
* allocated by the currently executing thread.
*/
|
| ︙ | ︙ | |||
1251 1252 1253 1254 1255 1256 1257 |
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_DbNewObj(
TCL_UNUSED(const char *) /*file*/,
TCL_UNUSED(int) /*line*/)
{
| > > | | 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 |
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_DbNewObj(
TCL_UNUSED(const char *) /*file*/,
TCL_UNUSED(int) /*line*/)
{
Tcl_Obj *objPtr;
TclNewObj(objPtr);
return objPtr;
}
#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------------
*
* TclAllocateFreeObjects --
|
| ︙ | ︙ | |||
1645 1646 1647 1648 1649 1650 1651 |
return dupPtr;
}
/*
*----------------------------------------------------------------------
*
| | | 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 |
return dupPtr;
}
/*
*----------------------------------------------------------------------
*
* TclDuplicatePureObj --
*
* Duplicates a Tcl_Obj and converts the internal representation of the
* duplicate to the given type, changing neither the 'bytes' field
* nor the internal representation of the original object, and without
* duplicating the bytes field unless necessary, i.e. unless the
* duplicate provides no updateStringProc after conversion. This can
* avoid an expensive memory allocation since the data in the 'bytes'
|
| ︙ | ︙ | |||
1712 1713 1714 1715 1716 1717 1718 |
if (bytes && (dupPtr->typePtr == NULL
|| dupPtr->typePtr->updateStringProc == NULL
|| typePtr == &tclStringType
)
) {
| | > > > > > > > | 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 |
if (bytes && (dupPtr->typePtr == NULL
|| dupPtr->typePtr->updateStringProc == NULL
|| typePtr == &tclStringType
)
) {
if (!TclAttemptInitStringRep(dupPtr, bytes, objPtr->length)) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"insufficient memory to initialize string", -1));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
}
status = TCL_ERROR;
}
}
return status;
}
Tcl_Obj *
TclDuplicatePureObj(
Tcl_Interp *interp,
|
| ︙ | ︙ | |||
1926 1927 1928 1929 1930 1931 1932 |
size_t numBytes)
{
assert(objPtr->bytes == NULL || bytes == NULL);
if (objPtr->bytes == NULL) {
/* Start with no string rep */
if (numBytes == 0) {
| | | 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 |
size_t numBytes)
{
assert(objPtr->bytes == NULL || bytes == NULL);
if (objPtr->bytes == NULL) {
/* Start with no string rep */
if (numBytes == 0) {
TclInitEmptyStringRep(objPtr);
return objPtr->bytes;
} else {
objPtr->bytes = (char *)Tcl_AttemptAlloc(numBytes + 1);
if (objPtr->bytes) {
objPtr->length = numBytes;
if (bytes) {
memcpy(objPtr->bytes, bytes, numBytes);
|
| ︙ | ︙ | |||
1953 1954 1955 1956 1957 1958 1959 |
objPtr->bytes[objPtr->length] = '\0';
}
}
} else {
/* Start with non-empty string rep (allocated) */
if (numBytes == 0) {
Tcl_Free(objPtr->bytes);
| | | 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 |
objPtr->bytes[objPtr->length] = '\0';
}
}
} else {
/* Start with non-empty string rep (allocated) */
if (numBytes == 0) {
Tcl_Free(objPtr->bytes);
TclInitEmptyStringRep(objPtr);
return objPtr->bytes;
} else {
objPtr->bytes = (char *)Tcl_AttemptRealloc(objPtr->bytes,
numBytes + 1);
if (objPtr->bytes) {
objPtr->length = numBytes;
objPtr->bytes[objPtr->length] = '\0';
|
| ︙ | ︙ | |||
2021 2022 2023 2024 2025 2026 2027 | *---------------------------------------------------------------------- * * Tcl_StoreInternalRep -- * * Called to set the object's internal representation to match a * particular type. * | | > | | | < < | | | 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 |
*----------------------------------------------------------------------
*
* Tcl_StoreInternalRep --
*
* Called to set the object's internal representation to match a
* particular type.
*
* It is the caller's responsibility to guarantee that
* the value of the submitted internalrep is in agreement with
* the value of any existing string rep.
*
* Results:
* None.
*
* Side effects:
* Calls the freeIntRepProc of the current Tcl_ObjType, if any.
* Sets the internalRep and typePtr fields to the submitted values.
*
*----------------------------------------------------------------------
*/
void
Tcl_StoreInternalRep(
Tcl_Obj *objPtr, /* Object whose internal rep should be set. */
const Tcl_ObjType *typePtr, /* New type for the object */
const Tcl_ObjInternalRep *irPtr) /* New internalrep for the object */
{
/* Clear out any existing internalrep ( "shimmer" ) */
TclFreeInternalRep(objPtr);
/* When irPtr == NULL, just leave objPtr with no internalrep for typePtr */
if (irPtr) {
/* Copy the new internalrep into place */
objPtr->internalRep = *irPtr;
/* Set the type to match */
objPtr->typePtr = typePtr;
}
}
|
| ︙ | ︙ | |||
2281 2282 2283 2284 2285 2286 2287 |
int newBool;
char lowerCase[6];
Tcl_Size i, length;
const char *str = Tcl_GetStringFromObj(objPtr, &length);
if ((length == 0) || (length > 5)) {
/*
| | | | 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 |
int newBool;
char lowerCase[6];
Tcl_Size i, length;
const char *str = Tcl_GetStringFromObj(objPtr, &length);
if ((length == 0) || (length > 5)) {
/*
* Longest valid boolean string rep. is "false".
*/
return TCL_ERROR;
}
switch (str[0]) {
case '0':
if (length == 1) {
|
| ︙ | ︙ | |||
3527 3528 3529 3530 3531 3532 3533 |
objPtr->typePtr = NULL;
/*
* TODO: If objPtr has a string rep, this leaves
* it undisturbed. Not clear that's proper. Pure
* bignum values are converted to empty string.
*/
if (objPtr->bytes == NULL) {
| | | 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 |
objPtr->typePtr = NULL;
/*
* TODO: If objPtr has a string rep, this leaves
* it undisturbed. Not clear that's proper. Pure
* bignum values are converted to empty string.
*/
if (objPtr->bytes == NULL) {
TclInitEmptyStringRep(objPtr);
}
}
return TCL_OK;
}
if (objPtr->typePtr == tclIntType) {
if (mp_init_i64(bignumValue,
objPtr->internalRep.wideValue) != MP_OKAY) {
|
| ︙ | ︙ | |||
3913 3914 3915 3916 3917 3918 3919 |
*/
#undef Tcl_IsShared
int
Tcl_IsShared(
Tcl_Obj *objPtr) /* The object to test for being shared. */
{
| | | 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 |
*/
#undef Tcl_IsShared
int
Tcl_IsShared(
Tcl_Obj *objPtr) /* The object to test for being shared. */
{
return ((objPtr)->refCount > 1);
}
/*
*----------------------------------------------------------------------
*
* Tcl_DbIncrRefCount --
*
|
| ︙ | ︙ | |||
4356 4357 4358 4359 4360 4361 4362 |
*
* See also HashStringKey in tclHash.c.
* See also HashString in tclLiteral.c.
*
* See [tcl-Feature Request #2958832]
*/
| | | 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 |
*
* See also HashStringKey in tclHash.c.
* See also HashString in tclLiteral.c.
*
* See [tcl-Feature Request #2958832]
*/
if (length > 0) {
result = UCHAR(*string);
while (--length) {
result += (result << 3) + UCHAR(*++string);
}
}
return result;
}
|
| ︙ | ︙ |
Changes to generic/tclPathObj.c.
| ︙ | ︙ | |||
2343 2344 2345 2346 2347 2348 2349 |
copy = Tcl_DuplicateObj(copy);
}
Tcl_IncrRefCount(copy);
/* Steal copy's string rep */
pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
pathPtr->length = cwdLen;
| | | 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 |
copy = Tcl_DuplicateObj(copy);
}
Tcl_IncrRefCount(copy);
/* Steal copy's string rep */
pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
pathPtr->length = cwdLen;
TclInitEmptyStringRep(copy);
TclDecrRefCount(copy);
}
/*
*---------------------------------------------------------------------------
*
* TclNativePathInFilesystem --
|
| ︙ | ︙ |
Changes to generic/tclResult.c.
| ︙ | ︙ | |||
491 492 493 494 495 496 497 |
/*
* Scan through the arguments one at a time, appending them to the
* errorCode field as list elements.
*/
va_start(argList, interp);
| | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
/*
* Scan through the arguments one at a time, appending them to the
* errorCode field as list elements.
*/
va_start(argList, interp);
TclNewObj(errorObj);
/*
* Scan through the arguments one at a time, appending them to the
* errorCode field as list elements.
*/
while (1) {
|
| ︙ | ︙ |
Changes to generic/tclScan.c.
| ︙ | ︙ | |||
1093 1094 1095 1096 1097 1098 1099 |
}
} else {
/*
* Here no vars were specified, we want a list returned (inline scan)
* We create an empty Tcl_Obj to fill missing values rather than
* allocating a new Tcl_Obj every time. See test scan-bigdata-XX.
*/
| | > | 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 |
}
} else {
/*
* Here no vars were specified, we want a list returned (inline scan)
* We create an empty Tcl_Obj to fill missing values rather than
* allocating a new Tcl_Obj every time. See test scan-bigdata-XX.
*/
Tcl_Obj *emptyObj;
TclNewObj(emptyObj);
Tcl_IncrRefCount(emptyObj);
TclNewObj(objPtr);
for (i = 0; code == TCL_OK && i < totalVars; i++) {
if (objs[i] != NULL) {
code = Tcl_ListObjAppendElement(interp, objPtr, objs[i]);
Tcl_DecrRefCount(objs[i]);
} else {
|
| ︙ | ︙ |
Changes to generic/tclStringObj.c.
| ︙ | ︙ | |||
57 58 59 60 61 62 63 | static void ExtendUnicodeRepWithString(Tcl_Obj *objPtr, const char *bytes, Tcl_Size numBytes, Tcl_Size numAppendChars); static void FillUnicodeRep(Tcl_Obj *objPtr); static void FreeStringInternalRep(Tcl_Obj *objPtr); static Tcl_Size GetCharLength(Tcl_Obj *objPtr); static Tcl_Obj* GetRange(tclObjTypeInterfaceArgsStringRange); | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | static void ExtendUnicodeRepWithString(Tcl_Obj *objPtr, const char *bytes, Tcl_Size numBytes, Tcl_Size numAppendChars); static void FillUnicodeRep(Tcl_Obj *objPtr); static void FreeStringInternalRep(Tcl_Obj *objPtr); static Tcl_Size GetCharLength(Tcl_Obj *objPtr); static Tcl_Obj* GetRange(tclObjTypeInterfaceArgsStringRange); static void GrowStringBuffer(Tcl_Obj *objPtr, Tcl_Size needed, int flag); static void GrowUnicodeBuffer(Tcl_Obj *objPtr, Tcl_Size needed); static int SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, Tcl_Size numChars); static Tcl_Size UnicodeLength(const Tcl_UniChar *unicode); static void UpdateStringOfString(Tcl_Obj *objPtr); /* |
| ︙ | ︙ | |||
119 120 121 122 123 124 125 |
#ifndef TCL_MIN_UNICHAR_GROWTH
#define TCL_MIN_UNICHAR_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_UniChar)
#endif
static void
GrowStringBuffer(
Tcl_Obj *objPtr,
| | | | > | > > < < < < | < < > > | | | < < | < > | < < | < < < | < < | | | | > | > > > > | < < < | < | < | | < < | | < | < < | < < > | > | | < < | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
#ifndef TCL_MIN_UNICHAR_GROWTH
#define TCL_MIN_UNICHAR_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_UniChar)
#endif
static void
GrowStringBuffer(
Tcl_Obj *objPtr,
Tcl_Size needed, /* Not including terminating nul */
int flag) /* If 0, try to overallocate */
{
/*
* Preconditions:
* objPtr->typePtr == &tclStringType
* needed > stringPtr->allocated
* flag || objPtr->bytes != NULL
*/
String *stringPtr = GET_STRING(objPtr);
char *ptr;
Tcl_Size capacity;
assert(needed <= TCL_SIZE_MAX - 1);
needed += 1; /* Include terminating nul */
if (objPtr->bytes == &tclEmptyString) {
objPtr->bytes = NULL;
}
/*
* In code below, note 'capacity' and 'needed' include terminating nul,
* while stringPtr->allocated does not.
*/
if (flag == 0 || stringPtr->allocated > 0) {
ptr = (char *)TclReallocEx(objPtr->bytes, needed, &capacity);
} else {
/* Allocate exact size */
ptr = (char *)Tcl_Realloc(objPtr->bytes, needed);
capacity = needed;
}
objPtr->bytes = ptr;
stringPtr->allocated = capacity - 1; /* Does not include slot for end nul */
}
static void
GrowUnicodeBuffer(
Tcl_Obj *objPtr,
Tcl_Size needed)
{
/*
* Preconditions:
* objPtr->typePtr == &tclStringType
* needed > stringPtr->maxChars
*/
String *stringPtr = GET_STRING(objPtr);
Tcl_Size maxChars;
/* Note STRING_MAXCHARS already takes into account space for nul */
if (needed > STRING_MAXCHARS) {
Tcl_Panic("max size for a Tcl unicode rep (%" TCL_Z_MODIFIER "d bytes) exceeded",
STRING_MAXCHARS);
}
if (stringPtr->maxChars > 0) {
/* Expansion - try allocating extra space */
stringPtr = (String *)TclReallocElemsEx(stringPtr,
needed + 1, /* +1 for nul */
sizeof(Tcl_UniChar),
offsetof(String, unicode),
&maxChars);
maxChars -= 1; /* End nul not included */
}
else {
/*
* First allocation - just big enough. Note needed does
* not include terminating nul but STRING_SIZE does
*/
stringPtr = (String *)Tcl_Realloc(stringPtr, STRING_SIZE(needed));
maxChars = needed;
}
stringPtr->maxChars = maxChars;
SET_STRING(objPtr, stringPtr);
}
/*
*----------------------------------------------------------------------
*
* Tcl_NewStringObj --
|
| ︙ | ︙ | |||
606 607 608 609 610 611 612 |
}
ch = stringPtr->unicode[index];
return ch;
}
int
TclGetUniChar(
| | | 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 |
}
ch = stringPtr->unicode[index];
return ch;
}
int
TclGetUniChar(
Tcl_Obj *objPtr, /* The object to get the Unicode character
* from. */
Tcl_Size index) /* Get the index'th Unicode character. */
{
int ch = 0;
if (index < 0) {
return -1;
|
| ︙ | ︙ | |||
721 722 723 724 725 726 727 |
Tcl_Obj *
GetRange(tclObjTypeInterfaceArgsStringRange) {
Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */
String *stringPtr;
Tcl_Size length = 0;
if (first < 0) {
| | | 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 |
Tcl_Obj *
GetRange(tclObjTypeInterfaceArgsStringRange) {
Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */
String *stringPtr;
Tcl_Size length = 0;
if (first < 0) {
first = 0;
}
/*
* Optimize the case where we're really dealing with a bytearray object
* we don't need to convert to a string to perform the substring operation.
*/
|
| ︙ | ︙ | |||
1040 1041 1042 1043 1044 1045 1046 |
/*
* Need to enlarge the buffer.
*/
char *newBytes;
if (objPtr->bytes == &tclEmptyString) {
| | | | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 |
/*
* Need to enlarge the buffer.
*/
char *newBytes;
if (objPtr->bytes == &tclEmptyString) {
newBytes = (char *)Tcl_AttemptAlloc(length + 1U);
} else {
newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1U);
}
if (newBytes == NULL) {
return 0;
}
objPtr->bytes = newBytes;
stringPtr->allocated = length;
}
|
| ︙ | ︙ | |||
1241 1242 1243 1244 1245 1246 1247 |
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj");
}
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
| | | | 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 |
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj");
}
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
if (stringPtr->hasUnicode && (stringPtr->numChars) > 0) {
AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
} else {
AppendUtfToUtfRep(objPtr, bytes, toCopy);
}
if (length <= limit) {
return;
}
stringPtr = GET_STRING(objPtr);
if (stringPtr->hasUnicode && (stringPtr->numChars) > 0) {
AppendUtfToUnicodeRep(objPtr, ellipsis, eLen);
} else {
AppendUtfToUtfRep(objPtr, ellipsis, eLen);
}
}
/*
|
| ︙ | ︙ | |||
1894 1895 1896 1897 1898 1899 1900 |
if (gotXpg) {
msg = mixedXPG;
errCode = "MIXEDSPECTYPES";
goto errorMsg;
}
gotSequential = 1;
}
| | | 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 |
if (gotXpg) {
msg = mixedXPG;
errCode = "MIXEDSPECTYPES";
goto errorMsg;
}
gotSequential = 1;
}
if ((objIndex < 0) || (objIndex >= objc)) {
msg = badIndex[gotXpg];
errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH";
goto errorMsg;
}
/*
* Step 2. Set of flags.
|
| ︙ | ︙ | |||
2477 2478 2479 2480 2481 2482 2483 |
allocSegment = 1;
if (!Tcl_AttemptSetObjLength(segment, length)) {
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
bytes = TclGetString(segment);
| | | 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 |
allocSegment = 1;
if (!Tcl_AttemptSetObjLength(segment, length)) {
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
bytes = TclGetString(segment);
if (!Tcl_AttemptSetObjLength(segment, snprintf(bytes, segment->length, spec, d))) {
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
if (ch == 'A') {
char *q = TclGetString(segment) + 1;
*q = 'x';
|
| ︙ | ︙ | |||
3034 3035 3036 3037 3038 3039 3040 |
Tcl_AppendObjToObj(objResultPtr, objResultPtr);
done *= 2;
}
Tcl_AppendToObj(objResultPtr, TclGetString(objResultPtr),
(count - done) * length);
}
return objResultPtr;
| < | 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 |
Tcl_AppendObjToObj(objResultPtr, objResultPtr);
done *= 2;
}
Tcl_AppendToObj(objResultPtr, TclGetString(objResultPtr),
(count - done) * length);
}
return objResultPtr;
}
/*
*---------------------------------------------------------------------------
*
* TclStringCat --
*
|
| ︙ | ︙ | |||
3072 3073 3074 3075 3076 3077 3078 |
Tcl_Size first = objc - 1; /* Index of first value possibly not empty */
Tcl_Size last = 0; /* Index of last value possibly not empty */
int inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);
/* assert ( objc >= 0 ) */
if (objc <= 1) {
| > | > > | > > > | 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 |
Tcl_Size first = objc - 1; /* Index of first value possibly not empty */
Tcl_Size last = 0; /* Index of last value possibly not empty */
int inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);
/* assert ( objc >= 0 ) */
if (objc <= 1) {
if (objc != 1) {
/* Negative (shouldn't be) no objects; return empty */
Tcl_Obj *obj;
TclNewObj(obj);
return obj;
}
/* One object; return first */
return objv[0];
}
/* assert ( objc >= 2 ) */
/*
* Analyze to determine what representation result should be.
* GOALS: Avoid shimmering & string rep generation.
|
| ︙ | ︙ | |||
3371 3372 3373 3374 3375 3376 3377 |
objResultPtr = *objv++; objc--;
(void)Tcl_GetStringFromObj(objResultPtr, &start);
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
| | | | 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 |
objResultPtr = *objv++; objc--;
(void)Tcl_GetStringFromObj(objResultPtr, &start);
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
length));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
}
return NULL;
}
dst = TclGetString(objResultPtr) + start;
/* assert ( length > start ) */
TclFreeInternalRep(objResultPtr);
} else {
TclNewObj(objResultPtr); /* PANIC? */
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
Tcl_DecrRefCount(objResultPtr);
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
length));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
}
return NULL;
}
dst = TclGetString(objResultPtr);
}
|
| ︙ | ︙ | |||
3512 3513 3514 3515 3516 3517 3518 |
memCmpFn = memcmp;
s1len *= sizeof(Tcl_UniChar);
s2len *= sizeof(Tcl_UniChar);
if (reqlength > 0) {
reqlength *= sizeof(Tcl_UniChar);
}
} else {
| | | 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 |
memCmpFn = memcmp;
s1len *= sizeof(Tcl_UniChar);
s2len *= sizeof(Tcl_UniChar);
if (reqlength > 0) {
reqlength *= sizeof(Tcl_UniChar);
}
} else {
memCmpFn = (memCmpFn_t)(void *)TclUniCharNcmp;
}
}
}
} else {
empty = TclCheckEmptyString(value1Ptr);
if (empty > 0) {
switch (TclCheckEmptyString(value2Ptr)) {
|
| ︙ | ︙ | |||
3570 3571 3572 3573 3574 3575 3576 |
* memcmp() as that is unsafe with any string containing NUL
* (\xC0\x80 in Tcl's utf rep). We can use the more efficient
* TclpUtfNcmp2 if we are case-sensitive and no specific
* length was requested.
*/
if ((reqlength < 0) && !nocase) {
| | | | 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 |
* memcmp() as that is unsafe with any string containing NUL
* (\xC0\x80 in Tcl's utf rep). We can use the more efficient
* TclpUtfNcmp2 if we are case-sensitive and no specific
* length was requested.
*/
if ((reqlength < 0) && !nocase) {
memCmpFn = (memCmpFn_t)(void *)TclpUtfNcmp2;
} else {
s1len = Tcl_NumUtfChars(s1, s1len);
s2len = Tcl_NumUtfChars(s2, s2len);
memCmpFn = (memCmpFn_t)(void *)
(nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
}
}
}
/* At this point s1len, s2len, and reqlength should by now have been
* adjusted so that they are all in the units expected by the selected
|
| ︙ | ︙ | |||
4351 4352 4353 4354 4355 4356 4357 |
* memory pointed to by that NULL pointer is clearly bogus, and
* needs a reset.
*/
stringPtr->allocated = 0;
if (stringPtr->numChars == 0) {
| | | 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 |
* memory pointed to by that NULL pointer is clearly bogus, and
* needs a reset.
*/
stringPtr->allocated = 0;
if (stringPtr->numChars == 0) {
TclInitEmptyStringRep(objPtr);
} else {
(void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode,
stringPtr->numChars);
}
}
static Tcl_Size
|
| ︙ | ︙ |
Changes to generic/tclStringRep.h.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 |
typedef struct {
Tcl_Size numChars; /* The number of chars in the string.
* TCL_INDEX_NONE means this value has not been
* calculated. Any other means that there is a valid
* Unicode rep, or that the number of UTF bytes ==
* the number of chars. */
| | | | > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
typedef struct {
Tcl_Size numChars; /* The number of chars in the string.
* TCL_INDEX_NONE means this value has not been
* calculated. Any other means that there is a valid
* Unicode rep, or that the number of UTF bytes ==
* the number of chars. */
Tcl_Size allocated; /* The amount of space allocated for
* the UTF-8 string. Does not include nul
* terminator so actual allocation is
* (allocated+1). */
Tcl_Size maxChars; /* Max number of chars that can fit in the
* space allocated for the Unicode array. */
int hasUnicode; /* Boolean determining whether the string has
* a Tcl_UniChar representation. */
Tcl_UniChar unicode[TCLFLEXARRAY]; /* The array of Tcl_UniChar units.
* The actual size of this field depends on
* the maxChars field above. */
|
| ︙ | ︙ |
Changes to generic/tclTest.c.
| ︙ | ︙ | |||
5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 |
return TCL_ERROR;
}
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n);
if (p == NULL) {
return TCL_ERROR;
}
if (x.m != 1) {
Tcl_AppendResult(interp, "Tcl_GetBytesFromObj() overwrites variable", NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, x.n));
return TCL_OK;
}
| > > > > | 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 |
return TCL_ERROR;
}
p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n);
if (p == NULL) {
return TCL_ERROR;
}
#if !defined(TCL_NO_DEPRECATED) && defined(__clang__)
# pragma clang diagnostic pop
#endif
if (x.m != 1) {
Tcl_AppendResult(interp, "Tcl_GetBytesFromObj() overwrites variable", NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, x.n));
return TCL_OK;
}
|
| ︙ | ︙ |
Changes to generic/tclTestObj.c.
| ︙ | ︙ | |||
115 116 117 118 119 120 121 |
Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd,
NULL, NULL);
Tcl_CreateObjCommand(interp, "testlistobj", TestlistobjCmd,
NULL, NULL);
Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd,
NULL, NULL);
| > | | > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd,
NULL, NULL);
Tcl_CreateObjCommand(interp, "testlistobj", TestlistobjCmd,
NULL, NULL);
Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd,
NULL, NULL);
if (sizeof(Tcl_Size) == sizeof(Tcl_WideInt)) {
Tcl_CreateObjCommand(interp, "testbigdata", TestbigdataCmd,
NULL, NULL);
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestbignumobjCmd --
|
| ︙ | ︙ |
Changes to generic/tclTestObjInterfaceInteger.c.
| ︙ | ︙ | |||
306 307 308 309 310 311 312 |
TCL_UNUSEDVAR(Tcl_Obj *listPtr), /* List object for which an element array
* is to be returned. */
TCL_UNUSEDVAR(Tcl_Size *objcPtr), /* Where to store the count of objects
* referenced by objv. */
TCL_UNUSEDVAR(Tcl_Obj ***objvPtr) /* Where to store the pointer to an
* array of */
) {
| > > > > | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
TCL_UNUSEDVAR(Tcl_Obj *listPtr), /* List object for which an element array
* is to be returned. */
TCL_UNUSEDVAR(Tcl_Size *objcPtr), /* Where to store the count of objects
* referenced by objv. */
TCL_UNUSEDVAR(Tcl_Obj ***objvPtr) /* Where to store the pointer to an
* array of */
) {
ListInteger *listRepPtr;
listRepPtr = ListGetInternalRep(listPtr);
*objcPtr = listRepPtr->used;
*objvPtr = listRepPtr->values;
return TCL_OK;
}
static int ListIntegerListObjAppendElement(tclObjTypeInterfaceArgsListAppend) {
int status;
Tcl_Size length;
status = Tcl_ListObjLength(interp, listPtr, &length);
if (status != TCL_OK) {
|
| ︙ | ︙ |
Changes to generic/tclUtil.c.
| ︙ | ︙ | |||
1023 1024 1025 1026 1027 1028 1029 |
{
const char *p = src;
Tcl_Size nestingLevel = 0; /* Brace nesting count */
int forbidNone = 0; /* Do not permit CONVERT_NONE mode. Something
* needs protection or escape. */
int requireEscape = 0; /* Force use of CONVERT_ESCAPE mode. For some
* reason bare or brace-quoted form fails. */
| | | | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
{
const char *p = src;
Tcl_Size nestingLevel = 0; /* Brace nesting count */
int forbidNone = 0; /* Do not permit CONVERT_NONE mode. Something
* needs protection or escape. */
int requireEscape = 0; /* Force use of CONVERT_ESCAPE mode. For some
* reason bare or brace-quoted form fails. */
Tcl_Size extra = 0; /* Count of number of extra bytes needed for
* formatted element, assuming we use escape
* sequences in formatting. */
Tcl_Size bytesNeeded; /* Buffer length computed to complete the
* element formatting in the selected mode. */
#if COMPAT
int preferEscape = 0; /* Use preferences to track whether to use */
int preferBrace = 0; /* CONVERT_MASK mode. */
int braceCount = 0; /* Count of all braces '{' '}' seen. */
#endif /* COMPAT */
|
| ︙ | ︙ | |||
2594 2595 2596 2597 2598 2599 2600 |
* at end. */
{
Tcl_Size newSize;
if (length < 0) {
length = strlen(bytes);
}
| > > > > > > > | < < < < < | < | | | > | < | | | | | 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 |
* at end. */
{
Tcl_Size newSize;
if (length < 0) {
length = strlen(bytes);
}
if (length > (TCL_SIZE_MAX - dsPtr->length - 1)) {
Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER
"d bytes) exceeded",
TCL_SIZE_MAX);
return NULL; /* NOTREACHED */
}
newSize = length + dsPtr->length + 1;
if (newSize > dsPtr->spaceAvl) {
if (dsPtr->string == dsPtr->staticSpace) {
char *newString;
newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
memcpy(newString, dsPtr->string, dsPtr->length);
dsPtr->string = newString;
} else {
Tcl_Size offset = -1;
/* See [16896d49fd] */
if (bytes >= dsPtr->string
&& bytes <= dsPtr->string + dsPtr->length) {
/* Source string is within this DString. Note offset */
offset = bytes - dsPtr->string;
}
dsPtr->string =
(char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
if (offset >= 0) {
bytes = dsPtr->string + offset;
}
}
}
/*
* Copy the new string into the buffer at the end of the old one.
*/
|
| ︙ | ︙ | |||
2733 2734 2735 2736 2737 2738 2739 |
/*
* Allocate a larger buffer for the string if the current one isn't large
* enough. Allocate extra space in the new buffer so that there will be
* room to grow before we have to allocate again. SPECIAL NOTE: must use
* memcpy, not strcpy, to copy the string to a larger buffer, since there
* may be embedded NULLs in the string in some cases.
*/
| | | < | | > < | | | 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 |
/*
* Allocate a larger buffer for the string if the current one isn't large
* enough. Allocate extra space in the new buffer so that there will be
* room to grow before we have to allocate again. SPECIAL NOTE: must use
* memcpy, not strcpy, to copy the string to a larger buffer, since there
* may be embedded NULLs in the string in some cases.
*/
newSize += 1; /* For terminating nul */
if (newSize > dsPtr->spaceAvl) {
if (dsPtr->string == dsPtr->staticSpace) {
char *newString;
newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
memcpy(newString, dsPtr->string, dsPtr->length);
dsPtr->string = newString;
} else {
int offset = -1;
/* See [16896d49fd] */
if (element >= dsPtr->string
&& element <= dsPtr->string + dsPtr->length) {
/* Source string is within this DString. Note offset */
offset = element - dsPtr->string;
}
dsPtr->string =
(char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
if (offset >= 0) {
element = dsPtr->string + offset;
}
}
}
dst = dsPtr->string + dsPtr->length;
|
| ︙ | ︙ | |||
2810 2811 2812 2813 2814 2815 2816 |
if (length >= dsPtr->spaceAvl) {
/*
* There are two interesting cases here. In the first case, the user
* may be trying to allocate a large buffer of a specific size. It
* would be wasteful to overallocate that buffer, so we just allocate
* enough for the requested size plus the trailing null byte. In the
* second case, we are growing the buffer incrementally, so we need
| | | | | > > > | | 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 |
if (length >= dsPtr->spaceAvl) {
/*
* There are two interesting cases here. In the first case, the user
* may be trying to allocate a large buffer of a specific size. It
* would be wasteful to overallocate that buffer, so we just allocate
* enough for the requested size plus the trailing null byte. In the
* second case, we are growing the buffer incrementally, so we need
* behavior similar to Tcl_DStringAppend.
* TODO - the above makes no sense to me. How does the code below
* translate into distinguishing the two cases above? IMO, if caller
* specifically sets the length, there is no cause for overallocation.
*/
if (length >= TCL_SIZE_MAX) {
Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
}
newsize = TclUpsizeAlloc(dsPtr->spaceAvl, length + 1, TCL_SIZE_MAX);
if (length < newsize) {
dsPtr->spaceAvl = newsize;
} else {
dsPtr->spaceAvl = length + 1;
}
if (dsPtr->string == dsPtr->staticSpace) {
char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);
|
| ︙ | ︙ |
Changes to generic/tclZipfs.c.
| ︙ | ︙ | |||
1898 1899 1900 1901 1902 1903 1904 |
* Are there any entries in the zipHash? Don't need to enumerate them
* all to know.
*/
return (ZipFS.zipHash.numEntries ? TCL_OK : TCL_BREAK);
}
| | | 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 |
* Are there any entries in the zipHash? Don't need to enumerate them
* all to know.
*/
return (ZipFS.zipHash.numEntries ? TCL_OK : TCL_BREAK);
}
TclNewObj(resultList);
for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
hPtr = Tcl_NextHashEntry(&search)) {
zf = (ZipFile *) Tcl_GetHashValue(hPtr);
Tcl_ListObjAppendElement(NULL, resultList, Tcl_NewStringObj(
zf->mountPoint, -1));
Tcl_ListObjAppendElement(NULL, resultList, Tcl_NewStringObj(
zf->name, -1));
|
| ︙ | ︙ |
Changes to library/clock.tcl.
| ︙ | ︙ | |||
306 307 308 309 310 311 312 |
# make a reasonable guess, but this table needs to be taken with a grain
# of salt.
variable WinZoneInfo [dict create {*}{
{-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Kwajalein
{-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Midway
{-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Honolulu
| | | | | | | | | | | | | | | | | | | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
# make a reasonable guess, but this table needs to be taken with a grain
# of salt.
variable WinZoneInfo [dict create {*}{
{-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Kwajalein
{-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Midway
{-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Honolulu
{-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage
{-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles
{-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana
{-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver
{-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua
{-25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Phoenix
{-21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Regina
{-21600 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Chicago
{-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City
{-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/New_York
{-18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Indianapolis
{-14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Caracas
{-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999}
:America/Santiago
{-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus
{-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax
{-12600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/St_Johns
{-10800 0 3600 0 2 0 2 2 0 0 0 0 10 0 3 2 0 0 0} :America/Sao_Paulo
{-10800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Godthab
{-10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Buenos_Aires
{-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia
{-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo
{-7200 0 3600 0 9 0 5 2 0 0 0 0 3 0 5 2 0 0 0} :America/Noronha
{-3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Atlantic/Azores
{-3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Atlantic/Cape_Verde
{0 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :UTC
{0 0 3600 0 10 0 5 2 0 0 0 0 3 0 5 1 0 0 0} :Europe/London
{3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Kinshasa
{3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :CET
{7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Harare
{7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0}
:Africa/Cairo
{7200 0 3600 0 10 0 5 4 0 0 0 0 3 0 5 3 0 0 0} :Europe/Helsinki
{7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0} :Asia/Jerusalem
{7200 0 3600 0 9 0 5 1 0 0 0 0 3 0 5 0 0 0 0} :Europe/Bucharest
{7200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Athens
{7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0} :Asia/Amman
{7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0}
:Asia/Beirut
{7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0} :Africa/Windhoek
{10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Riyadh
{10800 0 3600 0 10 0 1 4 0 0 0 0 4 0 1 3 0 0 0} :Asia/Baghdad
{10800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Moscow
{12600 0 3600 0 9 2 4 2 0 0 0 0 3 0 1 2 0 0 0} :Asia/Tehran
{14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0} :Asia/Baku
{14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Muscat
{14400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Tbilisi
{16200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Kabul
{18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Karachi
{18000 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Yekaterinburg
{19800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Calcutta
{20700 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Katmandu
|
| ︙ | ︙ | |||
580 581 582 583 584 585 586 | wast +0700 \ wadt +0800 \ jt +0730 \ cct +0800 \ jst +0900 \ kst +0900 \ cast +0930 \ | | | | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 | wast +0700 \ wadt +0800 \ jt +0730 \ cct +0800 \ jst +0900 \ kst +0900 \ cast +0930 \ jdt +1000 \ kdt +1000 \ cadt +1030 \ east +1000 \ eadt +1030 \ gst +1000 \ nzt +1200 \ nzst +1200 \ nzdt +1300 \ |
| ︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 |
}
percentO {
append retval %%O
}
}
proc $procName {clockval timezone} "
| | | | | | | | < > > > > | | 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
}
percentO {
append retval %%O
}
}
proc $procName {clockval timezone} "
$preFormatCode
return \[::format [list $formatString] $substituents\]
"
# puts [list $procName [info args $procName] [info body $procName]]
return $procName
}
#----------------------------------------------------------------------
#
# clock scan --
#
# Inputs a count of seconds since the Posix Epoch as a time of day.
#
# The 'clock scan' command scans times of day on input. Refer to the user
# documentation to see what it does.
#
#----------------------------------------------------------------------
proc ::tcl::clock::scan { args } {
set format {}
# Check the count of args
if { [llength $args] < 1 || [llength $args] % 2 != 1 } {
set cmdName "clock scan"
return -code error \
-errorcode [list CLOCK wrongNumArgs] \
"wrong \# args: should be\
\"$cmdName string\
?-base seconds?\
?-format string? ?-gmt boolean?\
?-locale LOCALE? ?-timezone ZONE?\""
}
# Set defaults
set base [clock seconds]
set string [lindex $args 0]
set format {}
set gmt 0
set locale c
set timezone [GetSystemTimeZone]
# Pick up command line options.
foreach { flag value } [lreplace $args 0 0] {
switch -exact -- $flag {
-b - -ba - -bas - -base {
set base $value
}
-f - -fo - -for - -form - -forma - -format {
set saw(-format) {}
set format $value
}
-g - -gm - -gmt {
set saw(-gmt) {}
set gmt $value
}
-l - -lo - -loc - -loca - -local - -locale {
set saw(-locale) {}
set locale [string tolower $value]
}
-t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone {
set saw(-timezone) {}
set timezone $value
}
default {
return -code error \
-errorcode [list CLOCK badOption $flag] \
"bad option \"$flag\",\
must be -base, -format, -gmt, -locale or -timezone"
}
}
}
# Check options for validity
if { [info exists saw(-gmt)] && [info exists saw(-timezone)] } {
|
| ︙ | ︙ | |||
1971 1972 1973 1974 1975 1976 1977 |
append procBody [MakeParseCodeFromFields $fieldSet $TimeParseActions]
# Assemble seconds from the Julian day and second of the day.
# Convert to local time unless epoch seconds or stardate are
# being processed - they're always absolute
if { ![dict exists $fieldSet seconds]
| | | 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 |
append procBody [MakeParseCodeFromFields $fieldSet $TimeParseActions]
# Assemble seconds from the Julian day and second of the day.
# Convert to local time unless epoch seconds or stardate are
# being processed - they're always absolute
if { ![dict exists $fieldSet seconds]
&& ![dict exists $fieldSet starDate] } {
append procBody {
if { [dict get $date julianDay] > 5373484 } {
return -code error -errorcode [list CLOCK dateTooLarge] \
"requested date too large to represent"
}
dict set date localSeconds [expr {
-210866803200
|
| ︙ | ︙ | |||
2375 2376 2377 2378 2379 2380 2381 | d %e MMMM %B MMM %b MM %m M %N yyyy %Y yy %y | | | | 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 |
d %e
MMMM %B
MMM %b
MM %m
M %N
yyyy %Y
yy %y
y %y
gg {}
} $unquoted]
if { $quoted eq {} } {
set quote '
} else {
set quote $quoted
}
}
|
| ︙ | ︙ | |||
2405 2406 2407 2408 2409 2410 2411 | d %e MMMM %B MMM %b MM %m M %N yyyy %Y yy %y | | | | 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 |
d %e
MMMM %B
MMM %b
MM %m
M %N
yyyy %Y
yy %y
y %y
gg {}
} $unquoted]
if { $quoted eq {} } {
set quote '
} else {
set quote $quoted
}
}
|
| ︙ | ︙ | |||
2985 2986 2987 2988 2989 2990 2991 |
variable TimeZoneBad
if {[set result [getenv TCL_TZ]] ne {}} {
set timezone $result
} elseif {[set result [getenv TZ]] ne {}} {
set timezone $result
} else {
| | | | | | | | | | | | | | | 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 |
variable TimeZoneBad
if {[set result [getenv TCL_TZ]] ne {}} {
set timezone $result
} elseif {[set result [getenv TZ]] ne {}} {
set timezone $result
} else {
# Cache the time zone only if it was detected by one of the
# expensive methods.
if { [info exists CachedSystemTimeZone] } {
set timezone $CachedSystemTimeZone
} elseif { $::tcl_platform(platform) eq {windows} } {
set timezone [GuessWindowsTimeZone]
} elseif { [file exists /etc/localtime]
&& ![catch {ReadZoneinfoFile \
Tcl/Localtime /etc/localtime}] } {
set timezone :Tcl/Localtime
} else {
set timezone :localtime
}
set CachedSystemTimeZone $timezone
}
if { ![dict exists $TimeZoneBad $timezone] } {
dict set TimeZoneBad $timezone [catch {SetupTimeZone $timezone}]
}
if { [dict get $TimeZoneBad $timezone] } {
return :localtime
|
| ︙ | ︙ | |||
3604 3605 3606 3607 3608 3609 3610 |
([-+]?)
# 3 - Standard time zone offset, hours
([[:digit:]]{1,2})
(?:
# 4 - Standard time zone offset, minutes
: ([[:digit:]]{1,2})
(?:
| | | | | | | | | | | | | | 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 |
([-+]?)
# 3 - Standard time zone offset, hours
([[:digit:]]{1,2})
(?:
# 4 - Standard time zone offset, minutes
: ([[:digit:]]{1,2})
(?:
# 5 - Standard time zone offset, seconds
: ([[:digit:]]{1,2} )
)?
)?
(?:
# 6 - DST time zone name
([[:alpha:]]+ | <[-+[:alnum:]]+>)
(?:
(?:
# 7 - DST time zone offset, signum
([-+]?)
# 8 - DST time zone offset, hours
([[:digit:]]{1,2})
(?:
# 9 - DST time zone offset, minutes
: ([[:digit:]]{1,2})
(?:
# 10 - DST time zone offset, seconds
: ([[:digit:]]{1,2})
)?
)?
)?
(?:
,
(?:
# 11 - Optional J in n and Jn form 12 - Day of year
( J ? ) ( [[:digit:]]+ )
| M
# 13 - Month number 14 - Week of month 15 - Day of week
( [[:digit:]] + )
[.] ( [[:digit:]] + )
[.] ( [[:digit:]] + )
)
(?:
# 16 - Start time of DST - hours
/ ( [[:digit:]]{1,2} )
(?:
# 17 - Start time of DST - minutes
: ( [[:digit:]]{1,2} )
(?:
# 18 - Start time of DST - seconds
: ( [[:digit:]]{1,2} )
)?
)?
)?
,
(?:
# 19 - Optional J in n and Jn form 20 - Day of year
( J ? ) ( [[:digit:]]+ )
| M
# 21 - Month number 22 - Week of month 23 - Day of week
( [[:digit:]] + )
[.] ( [[:digit:]] + )
[.] ( [[:digit:]] + )
)
(?:
# 24 - End time of DST - hours
/ ( [[:digit:]]{1,2} )
(?:
# 25 - End time of DST - minutes
: ( [[:digit:]]{1,2} )
(?:
# 26 - End time of DST - seconds
: ( [[:digit:]]{1,2} )
)?
)?
)?
)?
)?
)?
$
} $tz -> x(stdName) x(stdSignum) x(stdHours) x(stdMinutes) x(stdSeconds) \
x(dstName) x(dstSignum) x(dstHours) x(dstMinutes) x(dstSeconds) \
x(startJ) x(startDayOfYear) \
x(startMonth) x(startWeekOfMonth) x(startDayOfWeek) \
x(startHours) x(startMinutes) x(startSeconds) \
x(endJ) x(endDayOfYear) \
|
| ︙ | ︙ | |||
4239 4240 4241 4242 4243 4244 4245 |
proc ::tcl::clock::add { clockval args } {
if { [llength $args] % 2 != 0 } {
set cmdName "clock add"
return -code error \
-errorcode [list CLOCK wrongNumArgs] \
"wrong \# args: should be\
| | | > > | | 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 |
proc ::tcl::clock::add { clockval args } {
if { [llength $args] % 2 != 0 } {
set cmdName "clock add"
return -code error \
-errorcode [list CLOCK wrongNumArgs] \
"wrong \# args: should be\
\"$cmdName clockval ?number units?...\
?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?\""
}
if { [catch { expr {wide($clockval)} } result] } {
return -code error $result
}
set offsets {}
set gmt 0
set locale c
set timezone [GetSystemTimeZone]
foreach { a b } $args {
if { [string is integer -strict $a] } {
lappend offsets $a $b
} else {
switch -exact -- $a {
-g - -gm - -gmt {
set saw(-gmt) {}
set gmt $b
}
-l - -lo - -loc - -loca - -local - -locale {
set locale [string tolower $b]
}
-t - -ti - -tim - -time - -timez - -timezo - -timezon -
-timezone {
set saw(-timezone) {}
set timezone $b
}
default {
throw [list CLOCK badOption $a] \
"bad option \"$a\",\
must be -gmt, -locale or -timezone"
}
}
}
}
# Check options for validity
|
| ︙ | ︙ | |||
4334 4335 4336 4337 4338 4339 4340 |
seconds - second {
set clockval [expr { $quantity + $clockval }]
}
default {
throw [list CLOCK badUnit $unit] \
"unknown unit \"$unit\", must be \
| | | 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 |
seconds - second {
set clockval [expr { $quantity + $clockval }]
}
default {
throw [list CLOCK badUnit $unit] \
"unknown unit \"$unit\", must be \
years, months, weeks, days, hours, minutes or seconds"
}
}
}
return $clockval
} trap CLOCK {result opts} {
# Conceal the innards of [clock] when it's an expected error
dict unset opts -errorinfo
|
| ︙ | ︙ | |||
4494 4495 4496 4497 4498 4499 4500 |
proc ::tcl::clock::ChangeCurrentLocale {args} {
variable FormatProc
variable LocaleNumeralCache
variable CachedSystemTimeZone
variable TimeZoneBad
foreach p [info procs [namespace current]::scanproc'*'current] {
| | | | 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 |
proc ::tcl::clock::ChangeCurrentLocale {args} {
variable FormatProc
variable LocaleNumeralCache
variable CachedSystemTimeZone
variable TimeZoneBad
foreach p [info procs [namespace current]::scanproc'*'current] {
rename $p {}
}
foreach p [info procs [namespace current]::formatproc'*'current] {
rename $p {}
}
catch {array unset FormatProc *'current}
set LocaleNumeralCache {}
}
#----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to tests/clock.test.
| ︙ | ︙ | |||
36763 36764 36765 36766 36767 36768 36769 36770 36771 36772 36773 36774 36775 36776 |
}
-result {Sun Jan 08 22:30:06 WAST 2012}
}
test clock-57.1 {clock scan - abbreviated options} {
clock scan 1970-01-01 -f %Y-%m-%d -g true
} 0
test clock-58.1 {clock l10n - Japanese localisation} {*}{
-setup {
proc backslashify { string } {
set retval {}
foreach char [split $string {}] {
| > > > > > > > > | 36763 36764 36765 36766 36767 36768 36769 36770 36771 36772 36773 36774 36775 36776 36777 36778 36779 36780 36781 36782 36783 36784 |
}
-result {Sun Jan 08 22:30:06 WAST 2012}
}
test clock-57.1 {clock scan - abbreviated options} {
clock scan 1970-01-01 -f %Y-%m-%d -g true
} 0
test clock-57.2 {clock scan - not -gmt and -timezone in the same call} {
catch {clock scan 1970-01-01 -format %Y-%m-%d -gmt true -timezone :Europe/Berlin}
} 1
test clock-57.3 {clock scan - not -g and -timezone in the same call} {
catch {clock scan 1970-01-01 -format %Y-%m-%d -g true -timezone :Europe/Berlin}
} 1
test clock-58.1 {clock l10n - Japanese localisation} {*}{
-setup {
proc backslashify { string } {
set retval {}
foreach char [split $string {}] {
|
| ︙ | ︙ | |||
36975 36976 36977 36978 36979 36980 36981 36982 36983 36984 36985 36986 36987 36988 |
-body {
clock add 0 1 year -foo bar
}
-match glob
-returnCodes error
-result {bad option "-foo"*}
}
test clock-66.1 {clock scan, no date, never-before-seen timezone} {*}{
-setup {
::tcl::clock::ClearCaches
}
-body {
clock scan 1200 \
| > > > > > > > > > | 36983 36984 36985 36986 36987 36988 36989 36990 36991 36992 36993 36994 36995 36996 36997 36998 36999 37000 37001 37002 37003 37004 37005 |
-body {
clock add 0 1 year -foo bar
}
-match glob
-returnCodes error
-result {bad option "-foo"*}
}
test clock-65.2 {clock add with both -timezone and -gmt} {*}{
-body {
clock add 0 1 year -timezone :CET -gmt true
}
-match glob
-returnCodes error
-result {cannot use -gmt and -timezone in same call}
}
test clock-66.1 {clock scan, no date, never-before-seen timezone} {*}{
-setup {
::tcl::clock::ClearCaches
}
-body {
clock scan 1200 \
|
| ︙ | ︙ |
Changes to tests/env.test.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
source [file join [file dirname [info script]] tcltests.tcl]
# [exec] is required here to see the actual environment received by child
# processes.
proc getenv {} {
global printenvScript
catch {exec [interpreter] $printenvScript} out
if {$out eq "child process exited abnormally"} {
| > > > > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
source [file join [file dirname [info script]] tcltests.tcl]
testConstraint utf8system [string equal [encoding system] utf-8]
if {[llength [auto_execok bash]]} {
testConstraint haveBash 1
}
# [exec] is required here to see the actual environment received by child
# processes.
proc getenv {} {
global printenvScript
catch {exec [interpreter] $printenvScript} out
if {$out eq "child process exited abnormally"} {
|
| ︙ | ︙ | |||
503 504 505 506 507 508 509 510 511 512 513 514 515 516 |
flush $pipe
set result [gets $pipe]
close $pipe
if {$result ne $::env(USERPROFILE)} {
list ERROR $result ne $::env(USERPROFILE)
}
} -result {}
# cleanup
rename getenv {}
rename envrestore {}
rename envprep {}
| > > > > > > > > > > > > > > > > | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 |
flush $pipe
set result [gets $pipe]
close $pipe
if {$result ne $::env(USERPROFILE)} {
list ERROR $result ne $::env(USERPROFILE)
}
} -result {}
test env-10.0 {
Unequal environment strings test should test unequal
} -constraints {unix haveBash utf8system knownBug} -setup {
set tclScript [makeFile {
puts [string equal $env(XX) $env(YY)]
} tclScript]
set shellCode {
export XX=$'\351'
export YY=$'\303\251'
}
append shellCode "[info nameofexecutable] $tclScript\n"
set shScript [makeFile $shellCode shScript]
} -body {
exec {*}[auto_execok bash] $shScript
} -result 0
# cleanup
rename getenv {}
rename envrestore {}
rename envprep {}
|
| ︙ | ︙ |
Changes to tests/fileName.test.
| ︙ | ︙ | |||
1606 1607 1608 1609 1610 1611 1612 |
glob -nocomplain -directory [file home] -join * fileName-20.10
} -cleanup {
cd $savewd
removeDirectory isolate
removeFile fileName-20.10 $s
removeDirectory sub [file home]
} -result [file home]/sub/fileName-20.10
| | > > > > > > > > > > > > > > > > > > > > | 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 |
glob -nocomplain -directory [file home] -join * fileName-20.10
} -cleanup {
cd $savewd
removeDirectory isolate
removeFile fileName-20.10 $s
removeDirectory sub [file home]
} -result [file home]/sub/fileName-20.10
test fileName-20.11 {glob dir with undecodable file names} -setup {
# Specifically use /tmp as on WSL [temporaryDirectory]
# on NTFS prevents creation of arbitrary byte sequences in names.
set prevDir [pwd]
set testDir /tmp/tcltest/fileName-20.11
file delete -force $testDir; # Clear it
file mkdir $testDir
cd $testDir
set prevEnc [encoding system]
# Create a file name that is invalid if interpreted as utf-8
encoding system iso8859-1
close [open \xe9 w]
} -cleanup {
encoding system $prevEnc
cd $prevDir
file delete -force $testDir
} -constraints {unix knownBug} -body {
set result [file exists [lindex [glob *] 0]]
encoding system utf-8
lappend result [file exists [lindex [glob *] 0]]
} -result {1 1}
apply [list {} {
test fileName-6d4e9d1af5bf5b7d {
memory leak in SetFsPathFromAny
Runs under both a TCL_DEBUG_MEM build and a -DPURIFY build for
valgrind, which is useful since Valgrind provides information about the
|
| ︙ | ︙ |
Changes to tests/io.test.
| ︙ | ︙ | |||
1664 1665 1666 1667 1668 1669 1670 |
set in [read $f]
read $f
scan [string index $in end] %c
} -cleanup {
catch {close $f}
} -result 194
| < | | 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 |
set in [read $f]
read $f
scan [string index $in end] %c
} -cleanup {
catch {close $f}
} -result 194
test {io-12.10 strict} {ReadChars: multibyte chars split} -body {
set f [open $path(test1) w]
fconfigure $f -translation binary
puts -nonewline $f [string repeat a 9]\xC2
close $f
set f [open $path(test1)]
fconfigure $f -encoding utf-8 -profile strict -buffersize 10
set in [read $f]
|
| ︙ | ︙ | |||
5917 5918 5919 5920 5921 5922 5923 |
set l [list]
set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
lappend l [fconfigure $sock -eofchar] [fconfigure $sock -translation]
close $sock
set l
} {{} auto}
test io-39.24 {Tcl_SetChannelOption, server socket is not readable or
| | | 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 |
set l [list]
set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
lappend l [fconfigure $sock -eofchar] [fconfigure $sock -translation]
close $sock
set l
} {{} auto}
test io-39.24 {Tcl_SetChannelOption, server socket is not readable or
writable so we can't change -eofchar or -translation } {
set l [list]
set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
fconfigure $sock -eofchar D -translation lf
lappend l [fconfigure $sock -eofchar] [fconfigure $sock -translation]
close $sock
set l
} {{} auto}
|
| ︙ | ︙ | |||
6486 6487 6488 6489 6490 6491 6492 |
set f4 [open $path(foo) r]
testfevent create
testfevent share $f3
testfevent share $f4
fileevent $f readable {script 1}
fileevent $f2 readable {script 2}
testfevent cmd "fileevent $f3 readable {script 3}
| | | 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 |
set f4 [open $path(foo) r]
testfevent create
testfevent share $f3
testfevent share $f4
fileevent $f readable {script 1}
fileevent $f2 readable {script 2}
testfevent cmd "fileevent $f3 readable {script 3}
fileevent $f4 readable {script 4}"
testfevent delete
set x [list [fileevent $f readable] [fileevent $f2 readable] \
[fileevent $f3 readable] [fileevent $f4 readable]]
close $f
close $f2
close $f3
close $f4
|
| ︙ | ︙ | |||
7794 7795 7796 7797 7798 7799 7800 |
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means reading the "Á" gives an error
fconfigure $in -encoding ascii -profile strict
fconfigure $out -encoding koi8-r -translation lf
proc ::xxx args {
| | | 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 |
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means reading the "Á" gives an error
fconfigure $in -encoding ascii -profile strict
fconfigure $out -encoding koi8-r -translation lf
proc ::xxx args {
set ::s0 $args
}
fcopy $in $out -command ::xxx
vwait ::s0
set ::s0
} -cleanup {
close $in
|
| ︙ | ︙ | |||
7821 7822 7823 7824 7825 7826 7827 |
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means writing the "Á" gives an error
fconfigure $in -encoding utf-8
fconfigure $out -encoding ascii -translation lf -profile strict
proc ::xxx args {
| | | 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 |
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means writing the "Á" gives an error
fconfigure $in -encoding utf-8
fconfigure $out -encoding ascii -translation lf -profile strict
proc ::xxx args {
set ::s0 $args
}
fcopy $in $out -command ::xxx
vwait ::s0
set ::s0
} -cleanup {
close $in
|
| ︙ | ︙ | |||
9349 9350 9351 9352 9353 9354 9355 |
set f [open $fn w+]
fconfigure $f -encoding binary
# \x81 is an incomplete byte sequence in utf-8
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar {} \
| | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > | 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 |
set f [open $fn w+]
fconfigure $f -encoding binary
# \x81 is an incomplete byte sequence in utf-8
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar {} \
-translation lf -profile strict
} -body {
gets $f
} -cleanup {
close $f
removeFile io-75.6
} -match glob -returnCodes 1 -result {error reading "file*":\
invalid or incomplete multibyte or wide character}
test io-75.7.gets {
invalid utf-8 encoding gets is not ignored (-profile strict)
} -setup {
set fn [makeFile {} io-75.7]
set f [open $fn w+]
fconfigure $f -encoding binary
# \x81 is invalid in utf-8
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar {} -translation lf \
-profile strict
} -body {
list [catch {read $f} msg] $msg
} -cleanup {
close $f
removeFile io-75.7
} -match glob -result {1 {error reading "file*":\
invalid or incomplete multibyte or wide character}}
test io-75.7.read {invalid utf-8 encoding eof handling (-profile strict)} -setup {
set fn [makeFile {} io-75.7]
set f [open $fn w+]
fconfigure $f -encoding binary
# \xA1 is invalid in utf-8. -eofchar is not detected, because it comes later.
puts -nonewline $f A\xA1\x1A
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar \x1A \
-translation lf -profile strict
} -body {
set status [catch {read $f} cres copts]
set d [dict get $copts -result read]
binary scan $d H* hd
lappend hd [eof $f]
lappend hd $status
lappend hd $cres
fconfigure $f -encoding iso8859-1
lappend hd [read $f];# We changed encoding, so now we can read the \xA1
close $f
set hd
} -cleanup {
removeFile io-75.7
} -match glob -result {41 0 1 {error reading "file*":\
invalid or incomplete multibyte or wide character} ¡}
test io-75.7.read {invalid utf-8 encoding eof handling (-profile strict)} -setup {
set fn [makeFile {} io-75.7]
set f [open $fn w+]
fconfigure $f -encoding binary
# \xA1 is invalid in utf-8. -eofchar is not detected, because it comes later.
puts -nonewline $f A\xA1\x1A
|
| ︙ | ︙ | |||
9463 9464 9465 9466 9467 9468 9469 |
removeFile io-75.8
} -result {41 1 {}}
test {io-75.8 {invalid before eof}} {
invalid utf-8 encoding eof handling (-profile strict)
} -setup {
| < | < < | 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 |
removeFile io-75.8
} -result {41 1 {}}
test {io-75.8 {invalid before eof}} {
invalid utf-8 encoding eof handling (-profile strict)
} -setup {
set fn [makeFile {} io-75.8]
set f [open $fn w+]
# This also configures the channel encoding profile as strict.
fconfigure $f -encoding binary
# \x81 is invalid in utf-8. -eofchar is not detected, because it comes later.
puts -nonewline $f A\x81\x81\x1A
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar \x1A \
-translation lf -profile strict
} -body {
set res [list [catch {read $f} cres] [eof $f]]
chan configure $f -encoding iso8859-1
lappend res [read $f 1]
chan configure $f -encoding utf-8
catch {read $f 1} cres
lappend res $cres
close $f
set res
|
| ︙ | ︙ | |||
9504 9505 9506 9507 9508 9509 9510 |
set chan [file tempfile];
fconfigure $chan -encoding binary
puts -nonewline $chan \x81\x1A
flush $chan
seek $chan 0
chan configure $chan -encoding utf-8 -profile strict
} -body {
| | < | 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 |
set chan [file tempfile];
fconfigure $chan -encoding binary
puts -nonewline $chan \x81\x1A
flush $chan
seek $chan 0
chan configure $chan -encoding utf-8 -profile strict
} -body {
list [catch {read $chan 1} cres] $cres
} -cleanup {
close $chan
unset res
} -match glob -result {1 {error reading "*":\
invalid or incomplete multibyte or wide character}}
|
| ︙ | ︙ | |||
9610 9611 9612 9613 9614 9615 9616 |
flush $f
seek $f 0
fconfigure $f -encoding shiftjis -blocking 0 -eofchar {} -translation lf \
-profile strict
} -body {
set d [read $f]
binary scan $d H* hd
| | < | 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 |
flush $f
seek $f 0
fconfigure $f -encoding shiftjis -blocking 0 -eofchar {} -translation lf \
-profile strict
} -body {
set d [read $f]
binary scan $d H* hd
lappend hd [catch {set d [read $f]} msg] $msg
} -cleanup {
close $f
removeFile io-75.11
} -match glob -result {41 1 {error reading "file*":\
invalid or incomplete multibyte or wide character}}
|
| ︙ | ︙ | |||
9722 9723 9724 9725 9726 9727 9728 |
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -blocking 0 -eofchar {} -translation lf \
-profile strict
} -body {
set d [read $f]
binary scan $d H* hd
| | < | | | < | | | < | < | 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 |
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -blocking 0 -eofchar {} -translation lf \
-profile strict
} -body {
set d [read $f]
binary scan $d H* hd
lappend hd [catch {read $f} msg] $msg
} -cleanup {
close $f
removeFile io-75.13
} -match glob -result {41 1 {error reading "file*":\
invalid or incomplete multibyte or wide character}}
test io-75.14 {
[gets] succesfully returns lines prior to error
invalid utf-8 encoding [gets] continues in non-strict mode after error
} -setup {
set chan [file tempfile]
fconfigure $chan -encoding binary
# \xC0\n is an invalid utf-8 sequence
puts -nonewline $chan a\nb\nc\xC0\nd\n
flush $chan
seek $chan 0
fconfigure $chan -encoding utf-8 -buffering none -eofchar {} \
-translation auto -profile strict
} -body {
lappend res [gets $chan]
lappend res [gets $chan]
lappend res [catch {gets $chan} cres] $cres
chan configure $chan -profile tcl8
lappend res [gets $chan]
lappend res [gets $chan]
close $chan
return $res
} -match glob -result {a b 1 {error reading "*":\
invalid or incomplete multibyte or wide character} cÀ d}
test io-75.15 {
invalid utf-8 encoding strict
gets does not hang
gets succeeds for the first two lines
} -setup {
set res {}
set chan [file tempfile]
fconfigure $chan -encoding binary
# \xC0\x40 is an invalid utf-8 sequence
puts $chan hello\nAB\nCD\xC0\x40EF\nGHI
seek $chan 0
} -body {
#Now try to read it with [gets]
fconfigure $chan -encoding utf-8 -profile strict
lappend res [gets $chan]
lappend res [gets $chan]
lappend res [catch {gets $chan} cres] $cres
lappend res [catch {gets $chan} cres] $cres
chan configure $chan -translation binary
set data [read $chan 4]
foreach char [split $data {}] {
scan $char %c ord
lappend res [format %x $ord]
}
fconfigure $chan -encoding utf-8 -profile strict -translation auto
|
| ︙ | ︙ |
Changes to tests/ioCmd.test.
| ︙ | ︙ | |||
225 226 227 228 229 230 231 |
test iocmd-8.4 {fconfigure command} -setup {
file delete $path(test1)
set f1 [open $path(test1) w]
} -body {
fconfigure $f1 froboz
} -returnCodes error -cleanup {
close $f1
| | | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
test iocmd-8.4 {fconfigure command} -setup {
file delete $path(test1)
set f1 [open $path(test1) w]
} -body {
fconfigure $f1 froboz
} -returnCodes error -cleanup {
close $f1
} -result [expectedOpts "froboz" -stat]
test iocmd-8.5 {fconfigure command} -returnCodes error -body {
fconfigure stdin -buffering froboz
} -result {bad value for -buffering: must be one of full, line, or none}
test iocmd-8.6 {fconfigure command} -returnCodes error -body {
fconfigure stdin -translation froboz
} -result {bad value for -translation: must be one of auto, binary, cr, lf, crlf, or platform}
test iocmd-8.7 {fconfigure command} -setup {
|
| ︙ | ︙ | |||
588 589 590 591 592 593 594 |
set fid [open $f rb]
append d [read $fid]
close $fid
return $d
} -cleanup {
removeFile $f
} -result 341234x6
| | > > > > > > > > > > > > > > > > > > > > > | 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
set fid [open $f rb]
append d [read $fid]
close $fid
return $d
} -cleanup {
removeFile $f
} -result 341234x6
test ioCmd-13.12 {open file produces something that has fconfigure -stat} -setup {
set f [makeFile {} iocmd13_12]
set result {}
} -body {
set fd [open $f wb]
set result [dict get [fconfigure $fd -stat] type]
fconfigure $fd -buffering none
puts -nonewline $fd abc
# Three ways of getting the size; all should agree!
lappend result [tell $fd] [file size $f] \
[dict get [fconfigure $fd -stat] size]
puts -nonewline $fd def
lappend result [tell $fd] [file size $f] \
[dict get [fconfigure $fd -stat] size]
puts -nonewline $fd ghi
lappend result [tell $fd] [file size $f] \
[dict get [fconfigure $fd -stat] size]
close $fd
return $result
} -cleanup {
removeFile $f
} -result {file 3 3 3 6 6 6 9 9 9}
test iocmd-14.1 {file id parsing errors} {
list [catch {eof gorp} msg] $msg $::errorCode
} {1 {can not find channel named "gorp"} {TCL LOOKUP CHANNEL gorp}}
test iocmd-14.2 {file id parsing errors} {
list [catch {eof filex} msg] $msg
} {1 {can not find channel named "filex"}}
|
| ︙ | ︙ |
Changes to tests/linsert.test.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 |
catch {unset lis}
catch {rename p ""}
test linsert-1.1-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 0 a
} {a 1 2 3 4 5}
test linsert-1.2-@mode@ {linsert command} {
| | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
catch {unset lis}
catch {rename p ""}
test linsert-1.1-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 0 a
} {a 1 2 3 4 5}
test linsert-1.2-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 1 a
} {1 a 2 3 4 5}
test linsert-1.3-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 2 a
} {1 2 a 3 4 5}
test linsert-1.4-@mode@ {linsert command} {
@linsert@ [newlist {1 2 3 4 5}] 3 a
} {1 2 3 a 4 5}
|
| ︙ | ︙ | |||
122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
@linsert@ [newlist $list] 1 "x y"
return "a b c"
}
p
} "a b c"
test linsert-3.2-@mode@ {linsert won't modify shared argument objects} {
catch {unset lis}
set lis [format "a \"%s\" c" "b"]
@linsert@ [newlist $lis] 0 [string length $lis]
} "7 a b c"
# cleanup
catch {unset lis}
catch {rename p ""}
| > | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
@linsert@ [newlist $list] 1 "x y"
return "a b c"
}
p
} "a b c"
test linsert-3.2-@mode@ {linsert won't modify shared argument objects} {
catch {unset lis}
puts boom
set lis [format "a \"%s\" c" "b"]
@linsert@ [newlist $lis] 0 [string length $lis]
} "7 a b c"
# cleanup
catch {unset lis}
catch {rename p ""}
|
| ︙ | ︙ |
Changes to tests/listRep.test.
| ︙ | ︙ | |||
217 218 219 220 221 222 223 |
test listrep-1.2 {
Inserts at back of unshared list with no free space should allocate all
space at back -- linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceNone] $end 99]
validate $l
list $l [leadSpace $l] [tailSpace $l]
| | | | | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
test listrep-1.2 {
Inserts at back of unshared list with no free space should allocate all
space at back -- linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceNone] $end 99]
validate $l
list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 7 99} 0 4]
test listrep-1.2.1 {
Inserts at back of unshared list with no free space should allocate all
space at back -- lset version
} -constraints testlistrep -body {
set l [freeSpaceNone]
lset l $end+1 99
validate $l
list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 7 99} 0 4]
test listrep-1.2.2 {
Inserts at back of unshared list with no free space should allocate all
space at back -- lappend version
} -constraints testlistrep -body {
set l [freeSpaceNone]
lappend l 99
validate $l
list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 7 99} 0 4]
test listrep-1.3 {
Inserts in middle of unshared list with no free space should reallocate with
equal free space at front and back - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceNone] $four 99]
validate $l
|
| ︙ | ︙ | |||
1156 1157 1158 1159 1160 1161 1162 |
test listrep-3.3 {
Inserts in front of unshared spanned list with insufficient total freespace
should reallocate with equal free space - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $zero -3 -2 -1]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
| | | | 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 |
test listrep-3.3 {
Inserts in front of unshared spanned list with insufficient total freespace
should reallocate with equal free space - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $zero -3 -2 -1]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -3 7] 3 2 1]
test listrep-3.3.1 {
Inserts in front of unshared spanned list with insufficient total freespace
should reallocate with equal free space - lreplace version
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $zero -1 -3 -2 -1]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -3 7] 3 2 1]
test listrep-3.4 {
Inserts at back of unshared spanned list with room at back should not
reallocate - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth] $end 8]
validate $l
|
| ︙ | ︙ | |||
1251 1252 1253 1254 1255 1256 1257 |
Inserts in back of unshared spanned list with insufficient total freespace
should reallocate with all *additional* space at back. Note this differs
from the insert in front case because here we realloc(). - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $end 8 9 10]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
| | | | | | 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 |
Inserts in back of unshared spanned list with insufficient total freespace
should reallocate with all *additional* space at back. Note this differs
from the insert in front case because here we realloc(). - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $end 8 9 10]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 10] 1 4 1]
test listrep-3.6.1 {
Inserts in back of unshared spanned list with insufficient total freespace
should reallocate with all *additional* space at back. Note this differs
from the insert in front case because here we realloc() - lreplace version
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $end+1 $end+1 8 9 10]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 10] 1 4 1]
test listrep-3.6.2 {
Inserts in back of unshared spanned list with insufficient total freespace
should reallocate with all *additional* space at back. Note this differs
from the insert in front case because here we realloc() - lappend version
} -constraints testlistrep -body {
set l [freeSpaceBoth 8 1 1]
lappend l 8 9 10
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 10] 1 4 1]
test listrep-3.6.3 {
Inserts in back of unshared spanned list with insufficient total freespace
should reallocate with all *additional* space at back. Note this differs
from the insert in front case because here we realloc() - lset version
} -constraints testlistrep -body {
set l [freeSpaceNone]
lset l $end+1 8
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 8] 0 4 1]
test listrep-3.7 {
Inserts in front half of unshared spanned list with room in front should not
reallocate and should move front segment
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth] $one -2 -1]
validate $l
|
| ︙ | ︙ | |||
1337 1338 1339 1340 1341 1342 1343 |
test listrep-3.10 {
Inserts in front half of unshared spanned list with insufficient total space.
Note use of realloc() means new space will be at the back - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $one -3 -2 -1]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
| | | | 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 |
test listrep-3.10 {
Inserts in front half of unshared spanned list with insufficient total space.
Note use of realloc() means new space will be at the back - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $one -3 -2 -1]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 1 4 1]
test listrep-3.10.1 {
Inserts in front half of unshared spanned list with insufficient total space.
Note use of realloc() means new space will be at the back - lreplace version
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $one -1 -3 -2 -1]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 1 4 1]
test listrep-3.11 {
Inserts in back half of unshared spanned list with room in back should not
reallocate and should move back segment - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth] $end-$one 8 9]
validate $l
|
| ︙ | ︙ | |||
1410 1411 1412 1413 1414 1415 1416 |
Inserts in back half of unshared spanned list with insufficient
total space. Note use of realloc() means new space will be at the
back - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $end-$one 8 9 10]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
| | | | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 |
Inserts in back half of unshared spanned list with insufficient
total space. Note use of realloc() means new space will be at the
back - linsert version
} -constraints testlistrep -body {
set l [linsert [freeSpaceBoth 8 1 1] $end-$one 8 9 10]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 10 7} 1 4 1]
test listrep-3.14.1 {
Inserts in back half of unshared spanned list with insufficient
total space. Note use of realloc() means new space will be at the
back - lrepalce version
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $end -1 8 9 10]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 10 7} 1 4 1]
test listrep-3.15 {
Deletes from front of small unshared span list results in elements
moved up front and span removal - lreplace version
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth] $zero $zero]
validate $l
|
| ︙ | ︙ | |||
1710 1711 1712 1713 1714 1715 1716 |
test listrep-3.27 {
Replacement of elements at front in unshared spanned list with insufficient
total freespace should reallocate with equal free space
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $zero $one 10 11 12 13 14]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
| | | 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 |
test listrep-3.27 {
Replacement of elements at front in unshared spanned list with insufficient
total freespace should reallocate with equal free space
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $zero $one 10 11 12 13 14]
validate $l
list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {10 11 12 13 14 2 3 4 5 6 7} 3 2 1]
test listrep-3.28 {
Replacement of elements at back with same number of elements in unshared
spanned list is in-place - lreplace version
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth] $end-1 $end 10 11]
validate $l
|
| ︙ | ︙ | |||
1766 1767 1768 1769 1770 1771 1772 |
Replacement of elements at back with more elements in unshared spanned list
with insufficient total space reallocates with more room in the tail because
of realloc()
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $end-1 $end 10 11 12 13 14]
validate $l
list $l [leadSpace $l] [tailSpace $l]
| | | 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 |
Replacement of elements at back with more elements in unshared spanned list
with insufficient total space reallocates with more room in the tail because
of realloc()
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $end-1 $end 10 11 12 13 14]
validate $l
list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 10 11 12 13 14} 1 4]
test listrep-3.33 {
Replacement of elements in the middle in an unshared spanned list with
the same number of elements - lreplace version
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth] $two $four 10 11 12]
validate $l
|
| ︙ | ︙ | |||
1860 1861 1862 1863 1864 1865 1866 |
Replacement of elements in an unshared spanned list with more elements
when there is not enough free space results in new allocation. The back
end has more space because of realloc()
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $one $one 8 9 10 11 12]
validate $l
list $l [leadSpace $l] [tailSpace $l]
| | | 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 |
Replacement of elements in an unshared spanned list with more elements
when there is not enough free space results in new allocation. The back
end has more space because of realloc()
} -constraints testlistrep -body {
set l [lreplace [freeSpaceBoth 8 1 1] $one $one 8 9 10 11 12]
validate $l
list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 8 9 10 11 12 2 3 4 5 6 7} 1 5]
#
# 4.* - tests on shared spanned lists
test listrep-4.1 {
Inserts in front of shared spanned list with used elements in lead space
creates new list rep with more lead than tail space - linsert version
|
| ︙ | ︙ |
Changes to tests/lseq.test.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
-result {wrong # args: should be "lseq n ??op? n ??by? n??"}
test lseq-1.2 {step magnitude} {
lseq 10 .. 1 by -2 ;# or this could be an error - or not
} {10 8 6 4 2}
| | > > | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
-result {wrong # args: should be "lseq n ??op? n ??by? n??"}
test lseq-1.2 {step magnitude} {
lseq 10 .. 1 by -2 ;# or this could be an error - or not
} {10 8 6 4 2}
test lseq-1.3 {synergy between int and double} -body {
set rl [lseq 25. to 5. by -5]
set il [lseq 25 to 5 by -5]
lmap r $rl i $il { if {$r ne "" && $i ne ""} {expr {int($r) == $i}} else {list $r $i} }
} -cleanup {
unset rl il
} -result {1 1 1 1 1}
test lseq-1.4 {integer decreasing} {
lseq 10 .. 1
} {10 9 8 7 6 5 4 3 2 1}
test lseq-1.5 {integer increasing} {
lseq 1 .. 10
|
| ︙ | ︙ | |||
203 204 205 206 207 208 209 |
[lseq -10 1 -3] \
[lseq 10 -1 -4] \
[lseq -10 -1 3] \
[lseq 10 1 -5]
} {{-10 -8 -6 -4 -2} {} {} {10 6 2} {-10 -7 -4 -1} {10 5}}
| | < < > > | | > > | | | | > > | | | | | | | | | > > | | > > | | > > | | > > | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
[lseq -10 1 -3] \
[lseq 10 -1 -4] \
[lseq -10 -1 3] \
[lseq 10 1 -5]
} {{-10 -8 -6 -4 -2} {} {} {10 6 2} {-10 -7 -4 -1} {10 5}}
test lseq-3.1 {experiement} -body {
set ans {}
foreach factor [lseq 2.0 10.0] {
set start 1
set end 10
for {set step 1} {$step < 1e8} {} {
set l [lseq $start to $end by $step]
if {[llength $l] != 10} {
lappend ans $factor $step [llength $l] $l
}
set step [expr {$step * $factor}]
set end [expr {$end * $factor}]
}
}
if {$ans eq {}} {
set ans OK
}
set ans
} -cleanup {
unset ans step end start factor l
} -result {OK}
test lseq-3.2 {error case} -body {
lseq foo
} -returnCodes 1 -result {bad operation "foo": must be .., to, count, or by}
test lseq-3.3 {error case} -body {
lseq 10 foo
} -returnCodes 1 -result {bad operation "foo": must be .., to, count, or by}
test lseq-3.4 {error case} -body {
lseq 25 or 6
} -returnCodes 1 -result {bad operation "or": must be .., to, count, or by}
test lseq-3.5 {simple count and step arguments} -body {
set s [lseq 25 by 6]
list $s length=[llength $s]
} -cleanup {
unset s
} -result {{0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108 114 120 126 132 138 144} length=25}
test lseq-3.6 {error case} -body {
lseq 1 7 or 3
} -returnCodes 1 -result {bad operation "or": must be .., to, count, or by}
test lseq-3.7 {lmap lseq} -body {
lmap x [lseq 5] { expr {$x * $x} }
} -cleanup {unset x} -result {0 1 4 9 16}
test lseq-3.8 {lrange lseq} -body {
set r [lrange [lseq 1 100] 10 20]
set empty [lrange [lseq 1 100] 20 10]
list $r $empty [lindex [tcl::unsupported::representation $r] 3]
} -cleanup {
unset r empty
} -result {{11 12 13 14 15 16 17 18 19 20 21} {} arithseries}
test lseq-3.9 {lassign lseq} -constraints arithSeriesShimmer -body {
set r [lseq 15]
set r2 [lassign $r a b]
list [lindex [tcl::unsupported::representation $r] 3] $a $b \
[lindex [tcl::unsupported::representation $r2] 3]
} -cleanup {unset r r2 a b} -result {arithseries 0 1 arithseries}
test lseq-3.10 {lsearch lseq must shimmer?} -constraints arithSeriesShimmer -body {
set r [lseq 15 0]
set a [lsearch $r 9]
list [lindex [tcl::unsupported::representation $r] 3] $a
} -cleanup {unset r a} -result {arithseries 6}
test lseq-3.11 {lreverse lseq} -body {
set r [lseq 15 0]
set a [lreverse $r]
join [list \
[lindex [tcl::unsupported::representation $r] 3] \
$r \
[lindex [tcl::unsupported::representation $a] 3] \
$a] \n
} -cleanup {unset r a} -result {arithseries
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
arithseries
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15}
test lseq-3.12 {in operator} -body {
set r [lseq 9]
set i [expr {7 in $r}]
set j [expr {10 ni $r}]
set k [expr {-1 in $r}]
set l [expr {4 ni $r}]
list $i $j $k $l [lindex [tcl::unsupported::representation $r] 3]
} -cleanup {
unset r i j k l
} -result {1 1 0 0 arithseries}
test lseq-3.13 {lmap lseq shimmer} -constraints arithSeriesShimmer -body {
set r [lseq 15]
set rep-before [lindex [tcl::unsupported::representation $r] 3]
set m [lmap i $r { expr {$i * 7} }]
set rep-after [lindex [tcl::unsupported::representation $r] 3]
set rep-m [lindex [tcl::unsupported::representation $m] 3]
list $r ${rep-before} ${rep-after} ${rep-m} $m
} -cleanup {
unset r rep-before m rep-after rep-m
} -result {{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14} arithseries arithseries list {0 7 14 21 28 35 42 49 56 63 70 77 84 91 98}}
test lseq-3.14 {array for shimmer} -constraints arithSeriesShimmerOk -body {
array set testarray {a Test for This great Function}
set vars [lseq 2]
set vars-rep [lindex [tcl::unsupported::representation $vars] 3]
after 1
array for $vars testarray {
lappend keys $0
lappend vals $1
}
# Since hash order is not guaranteed, have to validate content ignoring order
set valk [lmap k $keys {expr {$k in {a for great}}}]
set valv [lmap v $vals {expr {$v in {Test This Function}}}]
set vars-after [lindex [tcl::unsupported::representation $vars] 3]
list ${vars-rep} $valk $valv ${vars-after}
} -cleanup {
unset testarray vars vars-rep 0 valk k valv v vars-after
} -result {arithseries {1 1 1} {1 1 1} arithseries}
test lseq-3.15 {join for shimmer} -constraints arithSeriesShimmer -body {
set r [lseq 3]
set rep-before [lindex [tcl::unsupported::representation $r] 3]
set str [join $r :]
set rep-after [lindex [tcl::unsupported::representation $r] 3]
list ${rep-before} $str ${rep-after}
} -cleanup {
unset r rep-before str rep-after
} -result {arithseries 0:1:2 arithseries}
test lseq-3.16 {error case} -body {
lseq 16 to
} -returnCodes 1 -result {missing "to" value.}
test lseq-3.17 {error case} -body {
lseq 17 to 13 by
|
| ︙ | ︙ | |||
369 370 371 372 373 374 375 |
llength [lseq 1 to 1 1]
} {1}
test lseq-3.25 {edge case} {
llength [lseq 1 to 1 by 1]
} {1}
| | > > | | | > > | | > > | | > > > > > > > > > > > > > > > > | | | | | | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
llength [lseq 1 to 1 1]
} {1}
test lseq-3.25 {edge case} {
llength [lseq 1 to 1 by 1]
} {1}
test lseq-3.26 {lsort shimmer} -constraints arithSeriesShimmer -body {
set r [lseq 15 0]
set rep-before [lindex [tcl::unsupported::representation $r] 3]
set lexical_sort [lsort $r]
set rep-after [lindex [tcl::unsupported::representation $r] 3]
list ${rep-before} $lexical_sort ${rep-after}
} -cleanup {
unset r rep-before lexical_sort rep-after
} -result {arithseries {0 1 10 11 12 13 14 15 2 3 4 5 6 7 8 9} arithseries}
test lseq-3.27 {lreplace shimmer} -constraints arithSeriesShimmer -body {
set r [lseq 15 0]
set rep-before [lindex [tcl::unsupported::representation $r] 3]
set lexical_sort [lreplace $r 3 5 A B C]
set rep-after [lindex [tcl::unsupported::representation $r] 3]
list ${rep-before} $lexical_sort ${rep-after}
} -cleanup {
unset r
unset rep-before
unset lexical_sort
unset rep-after
} -result {arithseries {15 14 13 A B C 9 8 7 6 5 4 3 2 1 0} arithseries}
test lseq-3.28 {lreverse bug in ArithSeries} -body {
set r [lseq -5 17 3]
set rr [lreverse $r]
list $r $rr [string equal $r [lreverse $rr]]
} -cleanup {
unset r rr
} -result {{-5 -2 1 4 7 10 13 16} {16 13 10 7 4 1 -2 -5} 1}
test lseq-3.29 {edge case: negative count} {
lseq -15
} {}
test lseq-3.30 {lreverse with double values} -constraints arithSeriesDouble -body {
set r [lseq 3.5 18.5 1.5]
set a [lreverse $r]
join [list \
[lindex [tcl::unsupported::representation $r] 3] \
$r \
[lindex [tcl::unsupported::representation $a] 3] \
$a] \n
} -cleanup {
unset r a
} -result {arithseries
3.5 5.0 6.5 8.0 9.5 11.0 12.5 14.0 15.5 17.0 18.5
arithseries
18.5 17.0 15.5 14.0 12.5 11.0 9.5 8.0 6.5 5.0 3.5}
test lseq-3.31 {lreverse inplace with doubles} {arithSeriesDouble has64BitLengths} {
lreverse [lseq 1.1 29.9 0.3]
} {29.9 29.6 29.3 29.0 28.7 28.4 28.1 27.8 27.5 27.2 26.9 26.6 26.3 26.0 25.7 25.4 25.1 24.8 24.5 24.2 23.9 23.6 23.3 23.0 22.7 22.4 22.1 21.8 21.5 21.2 20.9 20.6 20.3 20.0 19.7 19.4 19.1 18.8 18.5 18.2 17.9 17.6 17.3 17.0 16.7 16.4 16.1 15.8 15.5 15.2 14.9 14.6 14.3 14.0 13.7 13.4 13.1 12.8 12.5 12.2 11.9 11.6 11.3 11.0 10.7 10.4 10.1 9.8 9.5 9.2 8.9 8.6 8.3 8.0 7.7 7.4 7.1 6.8 6.5 6.2 5.9 5.6 5.3 5.0 4.7 4.4 4.1 3.8 3.5 3.2 2.9 2.6 2.3 2.0 1.7 1.4 1.1}
# lsearch -
# -- should not shimmer lseq list
# -- should not leak lseq elements
test lseq-3.32 {lsearch nested lists of lseq} -constraints arithSeriesShimmer -body {
set srchlist {}
for {set i 5} {$i < 25} {incr i} {
lappend srchlist [lseq $i count 7 by 3]
}
set a [lsearch -all -inline -index 1 $srchlist 23]
set b [lmap i $a {lindex [tcl::unsupported::representation $i] 3}]
list [lindex [tcl::unsupported::representation $a] 3] $a $b \
[lindex [tcl::unsupported::representation [lindex $srchlist 15]] 3]
} -cleanup {
unset srchlist i a b
} -result {list {{20 23 26 29 32 35 38}} arithseries arithseries}
test lseq-4.1 {end expressions} -body {
set start 7
lseq $start $start+11
} -cleanup {unset start} -result {7 8 9 10 11 12 13 14 15 16 17 18}
test lseq-4.2 {start expressions} -body {
set base [clock seconds]
set tl [lseq $base-60 $base 10]
lmap t $tl {expr {$t - $base + 60}}
} -cleanup {unset base tl t} -result {0 10 20 30 40 50 60}
## lseq 1 to 10 by -2
## # -> lseq: invalid step = -2 with a = 1 and b = 10
test lseq-4.3 {TIP examples} -body {
set examples {# Examples from TIP-629
# --- Begin ---
lseq 10 .. 1
# -> 10 9 8 7 6 5 4 3 2 1
lseq 1 .. 10
# -> 1 2 3 4 5 6 7 8 9 10
lseq 10 .. 1 by 2
|
| ︙ | ︙ | |||
461 462 463 464 465 466 467 |
lseq 5 5
# -> 5
lseq 5 5 2
# -> 5
lseq 5 5 -2
# -> 5
}
| | > > | | | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
lseq 5 5
# -> 5
lseq 5 5 2
# -> 5
lseq 5 5 -2
# -> 5
}
set res {}
foreach {cmd expect} [split $examples \n] {
if {[string trim $cmd] ne ""} {
set cmd [string trimleft $cmd]
if {[string match {\#*} $cmd]} continue
set status [catch $cmd ans]
lappend res $ans
if {[regexp {\# -> (.*)$} $expect -> expected]} {
if {$expected ne $ans} {
lappend res [list Mismatch: $cmd -> $ans ne $expected]
}
}
}
}
set res
} -cleanup {
unset res cmd status ans expect expected examples
} -result {{10 9 8 7 6 5 4 3 2 1} {1 2 3 4 5 6 7 8 9 10} {} {10 8 6 4 2} {5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0} {5.0 10.0 15.0 20.0 25.0} {} {25.0 20.0 15.0 10.0 5.0} {1 3 5 7 9} {25.0 20.0 15.0 10.0 5.0 0.0 -5.0 -10.0 -15.0 -20.0 -25.0} 5 5 5}
#
# Ticket 9933cc4d88697f05976accebd31c1e3ba6efe9c6 - lseq corner case
test lseq-4.4 {lseq corner case} -constraints has64BitLengths -body {
set tcmd {
set res {}
set s [catch {lindex [lseq 10 100] 0} e]
lappend res $s $e
set s [catch {lindex [lseq 10 9223372036854775000] 0} e]
lappend res $s $e
set s [catch {llength [lseq 10 9223372036854775000]} e]
lappend res $s $e
set s [catch {lindex [lseq 10 2147483647] 0} e]
lappend res $s $e
set s [catch {llength [lseq 10 2147483647]} e]
lappend res $s $e
}
eval $tcmd
} -cleanup {
unset res s e tcmd
} -result {0 10 0 10 0 9223372036854774991 0 10 0 2147483638}
# Ticket 99e834bf33 - lseq, lindex end off by one
test lseq-4.5 {lindex off by one} -body {
lappend res [eval {lindex [lseq 1 4] end}]
lappend res [eval {lindex [lseq 1 4] end-1}]
|
| ︙ | ︙ | |||
522 523 524 525 526 527 528 |
set i 4
set c [lindex $l $i]
set d [$cmd $l $i]
set e [lindex [lseq 2 10] $i]
set f [$cmd [lseq 2 10] $i]
list $c $d $e $f
} -cleanup {
| | < | > | > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 |
set i 4
set c [lindex $l $i]
set d [$cmd $l $i]
set e [lindex [lseq 2 10] $i]
set f [$cmd [lseq 2 10] $i]
list $c $d $e $f
} -cleanup {
unset l cmd i c d e f
} -result [lrepeat 4 6]
test lseq-4.7 {empty list} {
list [lseq 0] [join [lseq 0] {}] [join [lseq 1] {}]
} {{} {} 0}
test lseq-4.8 {error case lrange} -body {
lrange [lseq 1 5] fred ginger
} -cleanup {
unset -nocomplain fred ginger
} -returnCodes 1 -result {bad index "fred": must be integer?[+-]integer? or end?[+-]integer?}
test lseq-4.9 {lrange empty/partial sets} -body {
set res {}
foreach {fred ginger} {7 8 4 9 0 15 9 9 4 2} {
lappend res [lrange [lseq 1 5] $fred $ginger]
}
set res
} -cleanup {unset res fred ginger} -result {{} 5 {1 2 3 4 5} {} {}}
# Panic when using variable value?
test lseq-4.10 {panic using variable index} -body {
set i 0
lindex [lseq 10] $i
} -cleanup {unset i} -result {0}
test lseq-4.11 {bug lseq / lindex discrepancies} -constraints has64BitLengths -body {
lindex [lseq 0x7fffffff] 0x80000000
} -result {}
test lseq-4.12 {bug lseq} -constraints has64BitLengths -body {
llength [lseq 0x100000000]
} -result {4294967296}
test lseq-4.13 {bug lseq} -constraints has64BitLengths -body {
set l [lseq 0x7fffffffffffffff]
list \
[llength $l] \
[lindex $l end] \
[lindex $l 9223372036854775800]
} -cleanup {unset l} -result {9223372036854775807 9223372036854775806 9223372036854775800}
test lseq-4.14 {bug lseq - inconsistent rounding} has64BitLengths {
# using a non-integer increment, [lseq] rounding seems to be not consistent:
lseq 4 40 0.1
} {4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}
test lseq-4.15 {bug lseq - inconsistent rounding} has64BitLengths {
# using a non-integer increment, [lseq] rounding seems to be not consistent:
lseq 6 40 0.1
} {6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}
test lseq-4.16 {bug lseq - inconsistent rounding} {
# using a non-integer increment, [lseq] rounding seems to be not consistent:
set res {}
lappend res [lseq 4.07 6 0.1]
lappend res [lseq 4.03 4.208 0.013]
} {{4.07 4.17 4.27 4.37 4.47 4.57 4.67 4.77 4.87 4.97 5.07 5.17 5.27 5.37 5.47 5.57 5.67 5.77 5.87 5.97} {4.03 4.043 4.056 4.069 4.082 4.095 4.108 4.121 4.134 4.147 4.16 4.173 4.186 4.199}}
# Test abstract list in a concat
# -- lseq list should not shimmer
# -- lseq elements should not leak
test lseq-4.17 {concat shimmer} -body {
set rng [lseq 8 15 2]
set pre [list A b C]
set pst [list x Y z]
list [concat $pre $rng $pst] \
[lindex [tcl::unsupported::representation $pre] 3] \
[lindex [tcl::unsupported::representation $rng] 3] \
[lindex [tcl::unsupported::representation $pst] 3]
} -cleanup {unset rng pre pst} -result {{A b C 8 10 12 14 x Y z} list arithseries list}
test lseq-4.18 {concat shimmer} -body {
set rng [lseq 8 15 2]
set pre [list A b C]
set pst [list x Y z]
list [concat $rng $pre $pst] \
[lindex [tcl::unsupported::representation $rng] 3] \
[lindex [tcl::unsupported::representation $pre] 3] \
[lindex [tcl::unsupported::representation $pst] 3]
} -cleanup {unset rng pre pst} -result {{8 10 12 14 A b C x Y z} arithseries list list}
# Test lseq elements as var names
test lseq-4.19 {varnames} -body {
set plist {}
foreach v {auto_execok auto_load auto_qualify} {
lappend plist proc $v [info args $v] [info body $v]
}
set res {}
set varlist [lseq 1 to 4]
foreach $varlist $plist {
lappend res $2 [llength $3]
}
lappend res [lindex [tcl::unsupported::representation $varlist] 3]
} -cleanup {
unset {*}$varlist res varlist v plist
} -result {auto_execok 1 auto_load 2 auto_qualify 2 arithseries}
test lseq-convertToList {does not result in a memory error} -body {
trace add variable var1 write [list ::apply [list args {
error {this is an error}
} [namespace current]]]
list [catch {set var1 [lindex [lreplace [lseq 1 2] 1 1 hello] 0]} cres] $cres
} -cleanup {unset var1 cres} -result {1 {can't set "var1": this is an error}}
# cleanup
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End:
|
Changes to tests/stringObj.test.
| ︙ | ︙ | |||
74 75 76 77 78 79 80 |
} 10
test stringObj-4.3 {Tcl_SetObjLength procedure, string gets longer} testobj {
testobj freeallvars
teststringobj set 1 abcdef
teststringobj append 1 xyzq -1
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
| | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
} 10
test stringObj-4.3 {Tcl_SetObjLength procedure, string gets longer} testobj {
testobj freeallvars
teststringobj set 1 abcdef
teststringobj append 1 xyzq -1
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {10 15 abcdefxyzq}
test stringObj-4.4 {Tcl_SetObjLength procedure, "empty string", length 0} testobj {
testobj freeallvars
testobj newobj 1
teststringobj setlength 1 0
list [teststringobj length2 1] [teststringobj get 1]
} {0 {}}
|
| ︙ | ︙ | |||
107 108 109 110 111 112 113 |
set result {}
teststringobj append 1 1234567890123 -1
lappend result [teststringobj length 1] [teststringobj length2 1]
teststringobj setlength 1 10
teststringobj append 1 abcdef -1
lappend result [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
| | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
set result {}
teststringobj append 1 1234567890123 -1
lappend result [teststringobj length 1] [teststringobj length2 1]
teststringobj setlength 1 10
teststringobj append 1 abcdef -1
lappend result [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {15 15 16 24 xy12345678abcdef}
test stringObj-6.1 {Tcl_AppendStringsToObj procedure, type conversion} testobj {
testobj freeallvars
teststringobj set2 1 [list a b]
teststringobj appendstrings 1 xyz { 1234 } foo
teststringobj get 1
} {a bxyz 1234 foo}
|
| ︙ | ︙ | |||
138 139 140 141 142 143 144 |
list [teststringobj length 1] [teststringobj get 1]
} {15 {abc 123 abcdefg}}
test stringObj-6.5 {Tcl_AppendStringsToObj procedure, don't double space if initial string empty} testobj {
testobj freeallvars
testobj newobj 1
teststringobj appendstrings 1 123 abcdefg
list [teststringobj length 1] [teststringobj length2 1] [teststringobj get 1]
| | | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
list [teststringobj length 1] [teststringobj get 1]
} {15 {abc 123 abcdefg}}
test stringObj-6.5 {Tcl_AppendStringsToObj procedure, don't double space if initial string empty} testobj {
testobj freeallvars
testobj newobj 1
teststringobj appendstrings 1 123 abcdefg
list [teststringobj length 1] [teststringobj length2 1] [teststringobj get 1]
} {10 15 123abcdefg}
test stringObj-6.6 {Tcl_AppendStringsToObj procedure, space reallocation} testobj {
testobj freeallvars
teststringobj set 1 abc
teststringobj setlength 1 10
teststringobj setlength 1 2
teststringobj appendstrings 1 34567890
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {10 10 ab34567890}
test stringObj-6.7 {Tcl_AppendStringsToObj procedure, space reallocation} testobj {
testobj freeallvars
teststringobj set 1 abc
teststringobj setlength 1 10
teststringobj setlength 1 2
teststringobj appendstrings 1 34567890x
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {11 17 ab34567890x}
test stringObj-6.8 {Tcl_AppendStringsToObj procedure, object totally empty} testobj {
testobj freeallvars
testobj newobj 1
teststringobj appendstrings 1 {}
list [teststringobj length2 1] [teststringobj get 1]
} {0 {}}
test stringObj-6.9 {Tcl_AppendStringToObj, pure unicode} testobj {
testobj freeallvars
teststringobj set2 1 [string replace abc 1 1 d]
teststringobj appendstrings 1 foo bar soom
teststringobj get 1
} adcfoobarsoom
test stringObj-7.1 {SetStringFromAny procedure} testobj {
testobj freeallvars
teststringobj set2 1 [list a b]
teststringobj append 1 x -1
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {4 6 {a bx}}
test stringObj-7.2 {SetStringFromAny procedure, null object} testobj {
testobj freeallvars
testobj newobj 1
teststringobj appendstrings 1 {}
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {0 0 {}}
|
| ︙ | ︙ | |||
204 205 206 207 208 209 210 |
teststringobj set 1 {}
teststringobj append 1 abcde -1
testobj duplicate 1 2
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj maxchars 1] [teststringobj get 1] \
[teststringobj length 2] [teststringobj length2 2] \
[teststringobj maxchars 2] [teststringobj get 2]
| | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
teststringobj set 1 {}
teststringobj append 1 abcde -1
testobj duplicate 1 2
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj maxchars 1] [teststringobj get 1] \
[teststringobj length 2] [teststringobj length2 2] \
[teststringobj maxchars 2] [teststringobj get 2]
} {5 8 0 abcde 5 5 0 abcde}
test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj {
set x abc\xEF\xBF\xAEghi
string length $x
set y $x
list [testobj objtype $x] [testobj objtype $y] [append x "\xAE\xBF\xEF"] \
[set y] [testobj objtype $x] [testobj objtype $y]
} "string string abc\xEF\xBF\xAEghi\xAE\xBF\xEF abc\xEF\xBF\xAEghi string string"
|
| ︙ | ︙ |
Changes to tools/tcltk-man2html-utils.tcl.
| ︙ | ︙ | |||
1267 1268 1269 1270 1271 1272 1273 |
}
##
## merge copyright listings
##
proc merge-copyrights {l1 l2} {
set merge {}
| | | 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 |
}
##
## merge copyright listings
##
proc merge-copyrights {l1 l2} {
set merge {}
set re1 {^Copyright +(?:\(c\)|\\\(co|©|©) +(\w.*?)(?:all rights reserved)?(?:\. )*$}
set re2 {^(\d+) +(?:by +)?(\w.*)$} ;# date who
set re3 {^(\d+)-(\d+) +(?:by +)?(\w.*)$} ;# from to who
set re4 {^(\d+), *(\d+) +(?:by +)?(\w.*)$} ;# date1 date2 who
foreach copyright [concat $l1 $l2] {
if {[regexp -nocase -- $re1 $copyright -> info]} {
set info [string trimright $info ". "] ; # remove extra period
if {[regexp -- $re2 $info -> date who]} {
|
| ︙ | ︙ |
Changes to tools/tcltk-man2html.tcl.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 | set ::Version "50/9.0" set ::CSSFILE "docs.css" ## ## Source the utility functions that provide most of the ## implementation of the transformation from nroff to html. ## | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
set ::Version "50/9.0"
set ::CSSFILE "docs.css"
##
## Source the utility functions that provide most of the
## implementation of the transformation from nroff to html.
##
source -encoding utf-8 [file join [file dirname [info script]] tcltk-man2html-utils.tcl]
proc getversion {tclh {name {}}} {
if {[file exists $tclh]} {
set chan [open $tclh]
set data [read $chan]
close $chan
if {$name eq ""} {
|
| ︙ | ︙ |
Changes to unix/Makefile.in.
| ︙ | ︙ | |||
2448 2449 2450 2451 2452 2453 2454 |
@EXTRA_BUILD_HTML@
html-tk: ${NATIVE_TCLSH}
$(BUILD_HTML) --tk
@EXTRA_BUILD_HTML@
BUILD_HTML = \
| | | 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 |
@EXTRA_BUILD_HTML@
html-tk: ${NATIVE_TCLSH}
$(BUILD_HTML) --tk
@EXTRA_BUILD_HTML@
BUILD_HTML = \
@${NATIVE_TCLSH} -encoding utf-8 $(TOOL_DIR)/tcltk-man2html.tcl \
--useversion=$(MAJOR_VERSION).$(MINOR_VERSION) \
--htmldir="$(HTML_INSTALL_DIR)" \
--srcdir=$(TOP_DIR) $(BUILD_HTML_FLAGS)
#--------------------------------------------------------------------------
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
|
| ︙ | ︙ |
Changes to unix/configure.
| ︙ | ︙ | |||
9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 | fi ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_blksize" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STAT_ST_BLKSIZE 1" >>confdefs.h fi fi ac_fn_c_check_type "$LINENO" "blkcnt_t" "ac_cv_type_blkcnt_t" "$ac_includes_default" if test "x$ac_cv_type_blkcnt_t" = xyes then : | > > > > > > > > | 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 | fi ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_blksize" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STAT_ST_BLKSIZE 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct stat" "st_rdev" "ac_cv_member_struct_stat_st_rdev" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_rdev" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STAT_ST_RDEV 1" >>confdefs.h fi fi ac_fn_c_check_type "$LINENO" "blkcnt_t" "ac_cv_type_blkcnt_t" "$ac_includes_default" if test "x$ac_cv_type_blkcnt_t" = xyes then : |
| ︙ | ︙ |
Changes to unix/configure.ac.
| ︙ | ︙ | |||
367 368 369 370 371 372 373 | #-------------------------------------------------------------------- # Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But # we might be able to use fstatfs instead. Some systems (OpenBSD?) also # lack blkcnt_t. #-------------------------------------------------------------------- if test "$ac_cv_cygwin" != "yes"; then | | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
#--------------------------------------------------------------------
# Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
# we might be able to use fstatfs instead. Some systems (OpenBSD?) also
# lack blkcnt_t.
#--------------------------------------------------------------------
if test "$ac_cv_cygwin" != "yes"; then
AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_blksize, struct stat.st_rdev])
fi
AC_CHECK_TYPES([blkcnt_t])
AC_CHECK_FUNC(fstatfs, , [AC_DEFINE(NO_FSTATFS, 1, [Do we have fstatfs()?])])
#--------------------------------------------------------------------
# Some system have no memcmp or it does not work with 8 bit data, this
# checks it and add memcmp.o to LIBOBJS if needed
|
| ︙ | ︙ |
Changes to unix/tclUnixChan.c.
| ︙ | ︙ | |||
120 121 122 123 124 125 126 127 128 129 130 131 132 133 | */ static int FileBlockModeProc(void *instanceData, int mode); static int FileCloseProc(void *instanceData, Tcl_Interp *interp, int flags); static int FileGetHandleProc(void *instanceData, int direction, void **handlePtr); static int FileInputProc(void *instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(void *instanceData, const char *buf, int toWrite, int *errorCode); static int FileTruncateProc(void *instanceData, long long length); static long long FileWideSeekProc(void *instanceData, | > > > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | */ static int FileBlockModeProc(void *instanceData, int mode); static int FileCloseProc(void *instanceData, Tcl_Interp *interp, int flags); static int FileGetHandleProc(void *instanceData, int direction, void **handlePtr); static int FileGetOptionProc(void *instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int FileInputProc(void *instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(void *instanceData, const char *buf, int toWrite, int *errorCode); static int FileTruncateProc(void *instanceData, long long length); static long long FileWideSeekProc(void *instanceData, |
| ︙ | ︙ | |||
160 161 162 163 164 165 166 |
"file", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
NULL, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
NULL,
NULL, /* Set option proc. */
| | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
"file", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
NULL, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
NULL,
NULL, /* Set option proc. */
FileGetOptionProc, /* Get option proc. */
FileWatchProc, /* Initialize notifier. */
FileGetHandleProc, /* Get OS handles out of channel. */
FileCloseProc, /* close2proc. */
FileBlockModeProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
FileWideSeekProc, /* wide seek proc. */
|
| ︙ | ︙ | |||
271 272 273 274 275 276 277 |
* Assume there is always enough input available. This will block
* appropriately, and read will unblock as soon as a short read is
* possible, if the channel is in blocking mode. If the channel is
* nonblocking, the read will never block.
*/
do {
| | | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
* Assume there is always enough input available. This will block
* appropriately, and read will unblock as soon as a short read is
* possible, if the channel is in blocking mode. If the channel is
* nonblocking, the read will never block.
*/
do {
bytesRead = read(fsPtr->fd, buf, (size_t)toRead);
} while ((bytesRead < 0) && (errno == EINTR));
if (bytesRead < 0) {
*errorCodePtr = errno;
return -1;
}
return bytesRead;
|
| ︙ | ︙ | |||
320 321 322 323 324 325 326 |
* SF Tcl Bug 465765. Do not try to write nothing into a file. STREAM
* based implementations will considers this as EOF (if there is a
* pipe behind the file).
*/
return 0;
}
| | | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
* SF Tcl Bug 465765. Do not try to write nothing into a file. STREAM
* based implementations will considers this as EOF (if there is a
* pipe behind the file).
*/
return 0;
}
written = write(fsPtr->fd, buf, (size_t)toWrite);
if (written >= 0) {
return written;
}
*errorCodePtr = errno;
return -1;
}
|
| ︙ | ︙ | |||
529 530 531 532 533 534 535 536 537 538 539 540 541 542 |
if (direction & fsPtr->validMask) {
*handlePtr = INT2PTR(fsPtr->fd);
return TCL_OK;
}
return TCL_ERROR;
}
#ifdef SUPPORTS_TTY
/*
*----------------------------------------------------------------------
*
* TtyModemStatusStr --
*
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 |
if (direction & fsPtr->validMask) {
*handlePtr = INT2PTR(fsPtr->fd);
return TCL_OK;
}
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* FileGetOptionProc --
*
* Gets an option associated with an open file. If the optionName arg is
* non-NULL, retrieves the value of that option. If the optionName arg is
* NULL, retrieves a list of alternating option names and values for the
* given channel.
*
* Results:
* A standard Tcl result. Also sets the supplied DString to the string
* value of the option(s) returned. Sets error message if needed
* (by calling Tcl_BadChannelOption).
*
*----------------------------------------------------------------------
*/
static inline void
StoreElementInDict(
Tcl_Obj *dictObj,
const char *name,
Tcl_Obj *valueObj)
{
/*
* We assume that the dict is being built fresh and that there's never any
* duplicate keys.
*/
Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1);
Tcl_DictObjPut(NULL, dictObj, nameObj, valueObj);
}
static inline const char *
GetTypeFromMode(
int mode)
{
/*
* TODO: deduplicate with tclCmdAH.c
*/
if (S_ISREG(mode)) {
return "file";
} else if (S_ISDIR(mode)) {
return "directory";
} else if (S_ISCHR(mode)) {
return "characterSpecial";
} else if (S_ISBLK(mode)) {
return "blockSpecial";
} else if (S_ISFIFO(mode)) {
return "fifo";
#ifdef S_ISLNK
} else if (S_ISLNK(mode)) {
return "link";
#endif
#ifdef S_ISSOCK
} else if (S_ISSOCK(mode)) {
return "socket";
#endif
}
return "unknown";
}
static Tcl_Obj *
StatOpenFile(
FileState *fsPtr)
{
Tcl_StatBuf statBuf; /* Not allocated on heap; we're definitely
* API-synchronized with how Tcl is built! */
Tcl_Obj *dictObj;
unsigned short mode;
if (TclOSfstat(fsPtr->fd, &statBuf) < 0) {
return NULL;
}
/*
* TODO: merge with TIP 594 implementation (it's silly to have a
* duplicate!)
*/
TclNewObj(dictObj);
#define STORE_ELEM(name, value) StoreElementInDict(dictObj, name, value)
STORE_ELEM("dev", Tcl_NewWideIntObj((long) statBuf.st_dev));
STORE_ELEM("ino", Tcl_NewWideIntObj((Tcl_WideInt) statBuf.st_ino));
STORE_ELEM("nlink", Tcl_NewWideIntObj((long) statBuf.st_nlink));
STORE_ELEM("uid", Tcl_NewWideIntObj((long) statBuf.st_uid));
STORE_ELEM("gid", Tcl_NewWideIntObj((long) statBuf.st_gid));
STORE_ELEM("size", Tcl_NewWideIntObj((Tcl_WideInt) statBuf.st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
STORE_ELEM("blocks", Tcl_NewWideIntObj((Tcl_WideInt) statBuf.st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
STORE_ELEM("blksize", Tcl_NewWideIntObj((long) statBuf.st_blksize));
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
if (S_ISCHR(statBuf.st_mode) || S_ISBLK(statBuf.st_mode)) {
STORE_ELEM("rdev", Tcl_NewWideIntObj((long) statBuf.st_rdev));
}
#endif
STORE_ELEM("atime", Tcl_NewWideIntObj(
Tcl_GetAccessTimeFromStat(&statBuf)));
STORE_ELEM("mtime", Tcl_NewWideIntObj(
Tcl_GetModificationTimeFromStat(&statBuf)));
STORE_ELEM("ctime", Tcl_NewWideIntObj(
Tcl_GetChangeTimeFromStat(&statBuf)));
mode = (unsigned short) statBuf.st_mode;
STORE_ELEM("mode", Tcl_NewWideIntObj(mode));
STORE_ELEM("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef STORE_ELEM
return dictObj;
}
static int
FileGetOptionProc(
void *instanceData,
Tcl_Interp *interp,
const char *optionName,
Tcl_DString *dsPtr)
{
FileState *fsPtr = (FileState *)instanceData;
int valid = 0; /* Flag if valid option parsed. */
int len;
if (optionName == NULL) {
len = 0;
valid = 1;
} else {
len = strlen(optionName);
}
/*
* Get option -stat
* Option is readonly and returned by [fconfigure chan -stat] but not
* returned by [fconfigure chan] without explicit option name.
*/
if ((len > 1) && (strncmp(optionName, "-stat", len) == 0)) {
Tcl_Obj *dictObj = StatOpenFile(fsPtr);
const char *dictContents;
Tcl_Size dictLength;
if (dictObj == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file channel status: %s",
Tcl_PosixError(interp)));
return TCL_ERROR;
}
/*
* Transfer dictionary to the DString. Note that we don't do this as
* an element as this is an option that can't be retrieved with a
* general probe.
*/
dictContents = Tcl_GetStringFromObj(dictObj, &dictLength);
Tcl_DStringAppend(dsPtr, dictContents, dictLength);
Tcl_DecrRefCount(dictObj);
return TCL_OK;
}
if (valid) {
return TCL_OK;
}
return Tcl_BadChannelOption(interp, optionName,
"stat");
}
#ifdef SUPPORTS_TTY
/*
*----------------------------------------------------------------------
*
* TtyModemStatusStr --
*
|
| ︙ | ︙ |
Changes to unix/tclUnixFile.c.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
const char *argv0) /* The value of the application's argv[0]
* (native). */
{
Tcl_Encoding encoding;
const char *name, *p;
Tcl_StatBuf statBuf;
Tcl_DString buffer, nameString, cwd, utfName;
if (argv0 == NULL) {
return;
}
Tcl_DStringInit(&buffer);
name = argv0;
| > | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
const char *argv0) /* The value of the application's argv[0]
* (native). */
{
Tcl_Encoding encoding;
const char *name, *p;
Tcl_StatBuf statBuf;
Tcl_DString buffer, nameString, cwd, utfName;
Tcl_Obj *obj;
if (argv0 == NULL) {
return;
}
Tcl_DStringInit(&buffer);
name = argv0;
|
| ︙ | ︙ | |||
134 135 136 137 138 139 140 |
break;
} else if (*(p+1) == 0) {
p = "./";
} else {
p++;
}
}
| > | | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
break;
} else if (*(p+1) == 0) {
p = "./";
} else {
p++;
}
}
TclNewObj(obj);
TclSetObjNameOfExecutable(obj, NULL);
goto done;
/*
* If the name starts with "/" then just store it
*/
gotName:
|
| ︙ | ︙ | |||
157 158 159 160 161 162 163 |
TclSetObjNameOfExecutable(
Tcl_NewStringObj(Tcl_DStringValue(&utfName), TCL_INDEX_NONE), encoding);
Tcl_DStringFree(&utfName);
goto done;
}
if (TclpGetCwd(NULL, &cwd) == NULL) {
| > | | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
TclSetObjNameOfExecutable(
Tcl_NewStringObj(Tcl_DStringValue(&utfName), TCL_INDEX_NONE), encoding);
Tcl_DStringFree(&utfName);
goto done;
}
if (TclpGetCwd(NULL, &cwd) == NULL) {
TclNewObj(obj);
TclSetObjNameOfExecutable(obj, NULL);
goto done;
}
/*
* The name is relative to the current working directory. First strip off
* a leading "./", if any, then add the full path name of the current
* working directory.
|
| ︙ | ︙ |
Changes to unix/tclUnixThrd.c.
| ︙ | ︙ | |||
210 211 212 213 214 215 216 |
*/
int
TclpThreadCreate(
Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
Tcl_ThreadCreateProc *proc, /* Main() function of the thread */
void *clientData, /* The one argument to Main() */
| | | | | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
*/
int
TclpThreadCreate(
Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
Tcl_ThreadCreateProc *proc, /* Main() function of the thread */
void *clientData, /* The one argument to Main() */
TCL_HASH_TYPE stackSize, /* Size of stack for the new thread */
int flags) /* Flags controlling behaviour of the new
* thread. */
{
#if TCL_THREADS
pthread_attr_t attr;
pthread_t theThread;
int result;
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
if (stackSize != TCL_THREAD_STACK_DEFAULT) {
pthread_attr_setstacksize(&attr, (size_t)stackSize);
#ifdef TCL_THREAD_STACK_MIN
} else {
/*
* Certain systems define a thread stack size that by default is too
* small for many operations. The user has the option of defining
* TCL_THREAD_STACK_MIN to a value large enough to work for their
* needs. This would look like (for 128K min stack):
* make MEM_DEBUG_FLAGS=-DTCL_THREAD_STACK_MIN=131072L
*
* This solution is not optimal, as we should allow the user to
* specify a size at runtime, but we don't want to slow this function
* down, and that would still leave the main thread at the default.
*/
size_t size;
result = pthread_attr_getstacksize(&attr, &size);
if (!result && (size < TCL_THREAD_STACK_MIN)) {
pthread_attr_setstacksize(&attr, (size_t)TCL_THREAD_STACK_MIN);
}
#endif /* TCL_THREAD_STACK_MIN */
}
#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
if (!(flags & TCL_THREAD_JOINABLE)) {
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
| ︙ | ︙ |
Changes to win/Makefile.in.
| ︙ | ︙ | |||
977 978 979 980 981 982 983 | @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ $(WINE) ./$(TCLSH) $(TESTFLAGS) -load "$(TEST_LOAD_FACILITIES)" $(SCRIPT) # This target can be used to run tclsh from the build directory via # `make shell SCRIPT=foo.tcl` shell: binaries @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ | | | 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 | @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ $(WINE) ./$(TCLSH) $(TESTFLAGS) -load "$(TEST_LOAD_FACILITIES)" $(SCRIPT) # This target can be used to run tclsh from the build directory via # `make shell SCRIPT=foo.tcl` shell: binaries @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ $(WINE) ./$(TCLSH) -encoding utf-8 $(SCRIPT) # This target can be used to run tclsh inside either gdb or insight gdb: binaries @echo "set env TCL_LIBRARY=$(LIBRARY_DIR)" > gdb.run gdb ./$(TCLSH) --command=gdb.run rm gdb.run |
| ︙ | ︙ |
Changes to win/makefile.vc.
| ︙ | ︙ | |||
673 674 675 676 677 678 679 | HTMLBASE=TclTk$(VERSION) HHPFILE=$(HTMLDIR)\$(HTMLBASE).hhp CHMFILE=$(HTMLDIR)\$(HTMLBASE).chm htmlhelp: chmsetup $(CHMFILE) $(CHMFILE): $(DOCDIR)\* | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | HTMLBASE=TclTk$(VERSION) HHPFILE=$(HTMLDIR)\$(HTMLBASE).hhp CHMFILE=$(HTMLDIR)\$(HTMLBASE).chm htmlhelp: chmsetup $(CHMFILE) $(CHMFILE): $(DOCDIR)\* @$(TCLSH) -encoding utf-8 $(TOOLSDIR)\tcltk-man2html.tcl "--htmldir=$(HTMLDIR)" @echo Compiling HTML help project -"$(HHC)" <<$(HHPFILE) >NUL [OPTIONS] Compatibility=1.1 or later Compiled file=$(HTMLBASE).chm Default topic=contents.htm Display compile progress=no |
| ︙ | ︙ |
Changes to win/tclWinChan.c.
| ︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | static void FileChannelExitHandler(void *clientData); static void FileCheckProc(void *clientData, int flags); static int FileCloseProc(void *instanceData, Tcl_Interp *interp, int flags); static int FileEventProc(Tcl_Event *evPtr, int flags); static int FileGetHandleProc(void *instanceData, int direction, void **handlePtr); static ThreadSpecificData *FileInit(void); static int FileInputProc(void *instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(void *instanceData, const char *buf, int toWrite, int *errorCode); static long long FileWideSeekProc(void *instanceData, long long offset, int mode, int *errorCode); | > > > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | static void FileChannelExitHandler(void *clientData); static void FileCheckProc(void *clientData, int flags); static int FileCloseProc(void *instanceData, Tcl_Interp *interp, int flags); static int FileEventProc(Tcl_Event *evPtr, int flags); static int FileGetHandleProc(void *instanceData, int direction, void **handlePtr); static int FileGetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static ThreadSpecificData *FileInit(void); static int FileInputProc(void *instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(void *instanceData, const char *buf, int toWrite, int *errorCode); static long long FileWideSeekProc(void *instanceData, long long offset, int mode, int *errorCode); |
| ︙ | ︙ | |||
106 107 108 109 110 111 112 |
"file", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
NULL, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
NULL,
NULL, /* Set option proc. */
| | > > > > > > > > > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
"file", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
NULL, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
NULL,
NULL, /* Set option proc. */
FileGetOptionProc, /* Get option proc. */
FileWatchProc, /* Set up the notifier to watch the channel. */
FileGetHandleProc, /* Get an OS handle from channel. */
FileCloseProc, /* close2proc. */
FileBlockProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
FileWideSeekProc, /* Wide seek proc. */
FileThreadActionProc, /* Thread action proc. */
FileTruncateProc /* Truncate proc. */
};
/*
* General useful clarification macros.
*/
#define SET_FLAG(var, flag) ((var) |= (flag))
#define CLEAR_FLAG(var, flag) ((var) &= ~(flag))
#define TEST_FLAG(value, flag) (((value) & (flag)) != 0)
/*
* The number of 100-ns intervals between the Windows system epoch (1601-01-01
* on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01).
*/
#define POSIX_EPOCH_AS_FILETIME \
((long long) 116444736 * (long long) 1000000000)
/*
*----------------------------------------------------------------------
*
* FileInit --
*
* This function creates the window used to simulate file events.
|
| ︙ | ︙ | |||
741 742 743 744 745 746 747 748 749 750 751 752 753 754 |
if (!TEST_FLAG(direction, infoPtr->validMask)) {
return TCL_ERROR;
}
*handlePtr = (void *) infoPtr->handle;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclpOpenFileChannel --
*
* Open an File based channel on Unix systems.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
if (!TEST_FLAG(direction, infoPtr->validMask)) {
return TCL_ERROR;
}
*handlePtr = (void *) infoPtr->handle;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* FileGetOptionProc --
*
* Gets an option associated with an open file. If the optionName arg is
* non-NULL, retrieves the value of that option. If the optionName arg is
* NULL, retrieves a list of alternating option names and values for the
* given channel.
*
* Results:
* A standard Tcl result. Also sets the supplied DString to the string
* value of the option(s) returned. Sets error message if needed
* (by calling Tcl_BadChannelOption).
*
*----------------------------------------------------------------------
*/
static inline ULONGLONG
CombineDwords(
DWORD hi,
DWORD lo)
{
ULARGE_INTEGER converter;
converter.LowPart = lo;
converter.HighPart = hi;
return converter.QuadPart;
}
static inline void
StoreElementInDict(
Tcl_Obj *dictObj,
const char *name,
Tcl_Obj *valueObj)
{
/*
* We assume that the dict is being built fresh and that there's never any
* duplicate keys.
*/
Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1);
Tcl_DictObjPut(NULL, dictObj, nameObj, valueObj);
}
static inline time_t
ToCTime(
FILETIME fileTime) /* UTC time */
{
LARGE_INTEGER convertedTime;
convertedTime.LowPart = fileTime.dwLowDateTime;
convertedTime.HighPart = (LONG) fileTime.dwHighDateTime;
return (time_t) ((convertedTime.QuadPart -
(long long) POSIX_EPOCH_AS_FILETIME) / (long long) 10000000);
}
static Tcl_Obj *
StatOpenFile(
FileInfo *infoPtr)
{
DWORD attr;
int dev, nlink = 1;
unsigned short mode;
unsigned long long size, inode;
long long atime, ctime, mtime;
BY_HANDLE_FILE_INFORMATION data;
Tcl_Obj *dictObj;
if (GetFileInformationByHandle(infoPtr->handle, &data) != TRUE) {
Tcl_SetErrno(ENOENT);
return NULL;
}
atime = ToCTime(data.ftLastAccessTime);
mtime = ToCTime(data.ftLastWriteTime);
ctime = ToCTime(data.ftCreationTime);
attr = data.dwFileAttributes;
size = CombineDwords(data.nFileSizeHigh, data.nFileSizeLow);
nlink = data.nNumberOfLinks;
/*
* Unfortunately our stat definition's inode field (unsigned short) will
* throw away most of the precision we have here, which means we can't
* rely on inode as a unique identifier of a file. We'd really like to do
* something like how we handle 'st_size'.
*/
inode = CombineDwords(data.nFileIndexHigh, data.nFileIndexLow);
dev = data.dwVolumeSerialNumber;
/*
* Note that this code has no idea whether the file can be executed.
*/
mode = (attr & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR|S_IEXEC : S_IFREG;
mode |= (attr & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD|S_IWRITE;
mode |= (mode & (S_IREAD|S_IWRITE|S_IEXEC)) >> 3;
mode |= (mode & (S_IREAD|S_IWRITE|S_IEXEC)) >> 6;
/*
* We don't construct a Tcl_StatBuf; we're using the info immediately.
*/
TclNewObj(dictObj);
#define STORE_ELEM(name, value) StoreElementInDict(dictObj, name, value)
STORE_ELEM("dev", Tcl_NewWideIntObj((long) dev));
STORE_ELEM("ino", Tcl_NewWideIntObj((long long) inode));
STORE_ELEM("nlink", Tcl_NewIntObj(nlink));
STORE_ELEM("uid", Tcl_NewIntObj(0));
STORE_ELEM("gid", Tcl_NewIntObj(0));
STORE_ELEM("size", Tcl_NewWideIntObj((long long) size));
STORE_ELEM("atime", Tcl_NewWideIntObj(atime));
STORE_ELEM("mtime", Tcl_NewWideIntObj(mtime));
STORE_ELEM("ctime", Tcl_NewWideIntObj(ctime));
STORE_ELEM("mode", Tcl_NewWideIntObj(mode));
/*
* Windows only has files and directories, as far as we're concerned.
* Anything else and we definitely couldn't have got here anyway.
*/
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
STORE_ELEM("type", Tcl_NewStringObj("directory", -1));
} else {
STORE_ELEM("type", Tcl_NewStringObj("file", -1));
}
#undef STORE_ELEM
return dictObj;
}
static int
FileGetOptionProc(
ClientData instanceData, /* The file state. */
Tcl_Interp *interp, /* For error reporting. */
const char *optionName, /* What option to read, or NULL for all. */
Tcl_DString *dsPtr) /* Where to write the value read. */
{
FileInfo *infoPtr = (FileInfo *)instanceData;
int valid = 0; /* Flag if valid option parsed. */
int len;
if (optionName == NULL) {
len = 0;
valid = 1;
} else {
len = strlen(optionName);
}
/*
* Get option -stat
* Option is readonly and returned by [fconfigure chan -stat] but not
* returned by [fconfigure chan] without explicit option name.
*/
if ((len > 1) && (strncmp(optionName, "-stat", len) == 0)) {
Tcl_Obj *dictObj = StatOpenFile(infoPtr);
const char *dictContents;
Tcl_Size dictLength;
if (dictObj == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file channel status: %s",
Tcl_PosixError(interp)));
return TCL_ERROR;
}
/*
* Transfer dictionary to the DString. Note that we don't do this as
* an element as this is an option that can't be retrieved with a
* general probe.
*/
dictContents = Tcl_GetStringFromObj(dictObj, &dictLength);
Tcl_DStringAppend(dsPtr, dictContents, dictLength);
Tcl_DecrRefCount(dictObj);
return TCL_OK;
}
if (valid) {
return TCL_OK;
}
return Tcl_BadChannelOption(interp, optionName,
"stat");
}
/*
*----------------------------------------------------------------------
*
* TclpOpenFileChannel --
*
* Open an File based channel on Unix systems.
|
| ︙ | ︙ |
Changes to win/tclWinDde.c.
| ︙ | ︙ | |||
276 277 278 279 280 281 282 |
const WCHAR *name, /* The name that will be used to refer to the
* interpreter in later "send" commands. Must
* be globally unique. */
int flags, /* DDE_FLAG_FORCE or 0 */
Tcl_Obj *handlerPtr) /* Name of the optional proc/command to handle
* incoming Dde eval's */
{
| | | | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
const WCHAR *name, /* The name that will be used to refer to the
* interpreter in later "send" commands. Must
* be globally unique. */
int flags, /* DDE_FLAG_FORCE or 0 */
Tcl_Obj *handlerPtr) /* Name of the optional proc/command to handle
* incoming Dde eval's */
{
int suffix;
RegisteredInterp *riPtr, *prevPtr;
Tcl_DString dString;
const WCHAR *actualName;
Tcl_Obj *srvListPtr = NULL, **srvPtrPtr = NULL;
Tcl_Size n, srvCount = 0, offset;
int lastSuffix, r = TCL_OK;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
* See if the application is already registered; if so, remove its current
* name from the registry. The deletion of the command will take care of
* disposing of this entry.
|
| ︙ | ︙ | |||
905 906 907 908 909 910 911 |
case XTYP_WILDCONNECT: {
/*
* Dde wants a list of services and topics that we support.
*/
HSZPAIR *returnPtr;
| | | > > > | | | | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 |
case XTYP_WILDCONNECT: {
/*
* Dde wants a list of services and topics that we support.
*/
HSZPAIR *returnPtr;
Tcl_Size i;
DWORD numItems;
for (i = 0, riPtr = tsdPtr->interpListPtr; riPtr != NULL;
i++, riPtr = riPtr->nextPtr) {
/*
* Empty loop body.
*/
}
if ((size_t)i >= UINT_MAX/sizeof(HSZPAIR)) {
return NULL;
}
numItems = (DWORD)i;
ddeReturn = DdeCreateDataHandle(ddeInstance, NULL,
(numItems + 1) * (DWORD)sizeof(HSZPAIR), 0, 0, 0, 0);
returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &dlen);
len = dlen;
for (i = 0, riPtr = tsdPtr->interpListPtr; i < (Tcl_Size)numItems;
i++, riPtr = riPtr->nextPtr) {
returnPtr[i].hszSvc = DdeCreateStringHandleW(ddeInstance,
TCL_DDE_SERVICE_NAME, CP_WINUNICODE);
returnPtr[i].hszTopic = DdeCreateStringHandleW(ddeInstance,
riPtr->name, CP_WINUNICODE);
}
returnPtr[i].hszSvc = NULL;
|
| ︙ | ︙ | |||
1608 1609 1610 1611 1612 1613 1614 |
returnObjPtr =
Tcl_NewByteArrayObj((BYTE *) dataString, tmp);
} else {
Tcl_DString dsBuf;
if ((tmp >= sizeof(WCHAR))
&& !dataString[tmp / sizeof(WCHAR) - 1]) {
| | | 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 |
returnObjPtr =
Tcl_NewByteArrayObj((BYTE *) dataString, tmp);
} else {
Tcl_DString dsBuf;
if ((tmp >= sizeof(WCHAR))
&& !dataString[tmp / sizeof(WCHAR) - 1]) {
tmp -= (DWORD)sizeof(WCHAR);
}
Tcl_DStringInit(&dsBuf);
Tcl_WCharToUtfDString(dataString, tmp>>1, &dsBuf);
returnObjPtr =
Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
Tcl_DStringLength(&dsBuf));
Tcl_DStringFree(&dsBuf);
|
| ︙ | ︙ |
Changes to win/tclWinThrd.c.
| ︙ | ︙ | |||
200 201 202 203 204 205 206 |
*/
int
TclpThreadCreate(
Tcl_ThreadId *idPtr, /* Return, the ID of the thread. */
Tcl_ThreadCreateProc *proc, /* Main() function of the thread. */
void *clientData, /* The one argument to Main(). */
| | | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
*/
int
TclpThreadCreate(
Tcl_ThreadId *idPtr, /* Return, the ID of the thread. */
Tcl_ThreadCreateProc *proc, /* Main() function of the thread. */
void *clientData, /* The one argument to Main(). */
TCL_HASH_TYPE stackSize, /* Size of stack for the new thread. */
int flags) /* Flags controlling behaviour of the new
* thread. */
{
WinThread *winThreadPtr; /* Per-thread startup info */
HANDLE tHandle;
winThreadPtr = (WinThread *)Tcl_Alloc(sizeof(WinThread));
winThreadPtr->lpStartAddress = (LPTHREAD_START_ROUTINE) proc;
winThreadPtr->lpParameter = clientData;
winThreadPtr->fpControl = _controlfp(0, 0);
EnterCriticalSection(&joinLock);
*idPtr = 0; /* must initialize as Tcl_Thread is a pointer and
* on WIN64 sizeof void* != sizeof unsigned
*/
#if defined(_MSC_VER) || defined(__MSVCRT__)
tHandle = (HANDLE) _beginthreadex(NULL, (unsigned)stackSize,
(Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr,
0, (unsigned *)idPtr);
#else
tHandle = CreateThread(NULL, (DWORD)stackSize,
TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr);
#endif
if (tHandle == NULL) {
LeaveCriticalSection(&joinLock);
return TCL_ERROR;
} else {
|
| ︙ | ︙ | |||
721 722 723 724 725 726 727 |
TclpGlobalUnlock();
}
csPtr = *((CRITICAL_SECTION **)mutexPtr);
winCondPtr = *((WinCondition **)condPtr);
if (timePtr == NULL) {
wtime = INFINITE;
} else {
| | | 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 |
TclpGlobalUnlock();
}
csPtr = *((CRITICAL_SECTION **)mutexPtr);
winCondPtr = *((WinCondition **)condPtr);
if (timePtr == NULL) {
wtime = INFINITE;
} else {
wtime = (DWORD)timePtr->sec * 1000 + (DWORD)timePtr->usec / 1000;
}
/*
* Queue the thread on the condition, using the per-condition lock for
* serialization.
*/
|
| ︙ | ︙ |